osrlib.crawl.stocking
SRD dungeon stocking: roll one keyed area's contents from the stocking tables.
The stocking tables ship as data already — the room-contents d6 with its
per-row treasure-presence chance (StockingTable),
the compiled level-band encounter tables
(load_encounter_tables), and the treasure
generators. This module is the procedure that consumes them: given a dungeon
level, an effective monster catalog, and one RNG stream,
stock_area rolls what a single keyed area
holds and answers a frozen StockedArea —
content models an author can review, place, and edit, never engine state.
Determinism is the whole point: every draw comes from the one passed
RngStream, in a fixed order, so a stocked area is
reproducible from (the stream's state, the level, the table) alone. The order,
mirrored on the crawl's own wandering resolution so stocking a row yields
precisely what a wandering encounter on that row would:
- the stocking d6 (room contents), then the treasure d6 — but only when the
selected row's
treasure_chance_in_sixis non-zero (a printedNonechance consumes no die); - on a monster room, the encounter table's d20 row, then that row's count dice
(a fixed count consumes none), clamped
max(1, count); - then either one
variant_diceroll (the hydra form: the printed HD dice select the template once) or, for a packed-variant pool row, one uniform pick per individual.
The boundary is deliberate. A monster room's rolled individuals group by template
into KeyedMonster lines whose count_fixed
is set at stocking time — printed modules give concrete counts, and a concrete
number is what an author reviews and edits. An empty or trap room that rolls treasure gets an
unguarded AreaTreasureSpec; a monster
room's treasure is the encounter itself (its hoard flag), never a second
declaration. Traps and specials produce no models — B/X ships example lists as
referee prose, not tables — and an NPC-party row has no authorable content at
all: stock_area reports the rolled kind and
count and stops. The procedure ends where the referee's design begins.
StockedArea
Bases: BaseModel
The whole answer of stocking one keyed area — content models, never state.
contents is the stocking d6's outcome and treasure_present the treasure
d6's (always False when the row's printed chance is zero, e.g. a special).
At most one authorable payload rides alongside: encounter for a monster
room, npc_party for a monster room whose d20 row rolled an NPC party, or
treasure (only ever the unguarded form) for an empty or trap room that
rolled treasure. A monster room's treasure is its encounter's hoard flag,
so treasure stays None there; traps and specials carry no model of their
own — those are the referee's to design.
StockedNpcParty
Bases: BaseModel
An NPC-party stocking roll: the rolled party kind and its count.
An NPC-party encounter-table row has no authorable content model — a party
is generated at play from class treasure, not a keyed encounter and not
treasure letters. The dice still spoke (the row, then its count), so
stock_area reports what they said and
leaves the party for the author to place by hand.
stock_area
stock_area(
level_number: int, *, catalog: MonsterCatalog, stream: RngStream, table: EncounterTable | None = None
) -> StockedArea
Roll one keyed area's contents from the SRD stocking tables.
Runs the room-contents d6 and, when the row calls for it, the treasure d6;
on a monster room it then rolls the encounter table (the caller's table
when set, else the level's compiled band). Every draw comes from stream
in the fixed order documented on the module, so the result is reproducible
from the stream's state alone.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
level_number
|
int
|
The dungeon level being stocked — selects the compiled
encounter band when no |
required |
catalog
|
MonsterCatalog
|
The effective monster catalog (the shipped catalog composed
with the adventure's bundled templates, the way
|
required |
stream
|
RngStream
|
The RNG stream every draw advances — what makes the result reproducible. |
required |
table
|
EncounterTable | None
|
An authored encounter-table override (the level's
|
None
|
Returns:
| Type | Description |
|---|---|
StockedArea
|
The stocked area. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the encounter table rolls a monster id the effective
catalog does not hold — a malformed table, the same refusal
|
Examples: