osrlib.crawl.dungeon
The multi-level dungeon grid: cells, edges, doors, areas, traps, and state.
Authored content is frozen; play mutates a state overlay — the template/instance
split applied to space. DungeonSpec and its
levels, areas, features, and traps are game content, never mutated;
DungeonState carries everything play changes
(explored cells, door state, sprung traps, dropped piles, the party's location) and
serializes into saves.
Geometry, as API convention: cells are 10' squares addressed (x, y) with
x increasing east and y increasing south from the level's northwest corner.
Edges are the single spatial truth for walls and doors: an edges map keyed by the
canonical edge key (a cell plus north or west, so each physical edge has exactly
one entry). An edge absent from the map is a wall — authored content declares its
passages (open) and doors explicitly — and the level boundary is implicitly wall.
Position
module-attribute
A cell address: (x, y), x increasing east, y increasing south, from (0, 0).
AreaSpec
Bases: BaseModel
A keyed area (a room or cave): a named region over cells with content bindings.
Areas annotate the grid; cells not in any area are corridor. Content prose lives here — events carry ids and front ends resolve prose against the adventure.
AreaTreasureSpec
Bases: BaseModel
An area's generated-treasure declaration: explicit type letters, or unguarded.
Generates on first entry into the area — how content places generated treasure
in an area with no monsters. letters names one or more treasure type letters
(see the treasure type index); unguarded=True instead
rolls the dungeon level's unguarded-treasure band. Exactly one of the two
applies.
Direction
Bases: StrEnum
The four grid directions.
The wire values are lowercase — they serialize into commands, events, and
saves; changing them is a schema_version bump.
DoorSpec
Bases: BaseModel
A door on an edge, exactly as authored.
kind="secret" doors are invisible until discovered (a successful secret-door
search marks them in the state overlay). stuck and locked are the authored
starting conditions; play mutates the overlay, never this spec.
DoorState
Bases: BaseModel
One door's mutable overlay: open, wedged, discovered, unlocked.
opened_by_party is the swing-shut rule's memory: only doors the party
opened (by whatever means) swing shut behind it; authored-open doors stay.
DropPile
Bases: BaseModel
Dropped items and coins on a cell — droppable, recoverable, distraction bait.
Drops and loot round-trip: battle-end loot, death-save survivors, and player
drops all land here and TakeTreasure recovers them.
DroppedItem
DungeonSpec
Bases: BaseModel
A dungeon: one or more levels joined by transitions.
level
Return the level with number.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
number
|
int
|
The 1-based level number. |
required |
Returns:
| Type | Description |
|---|---|
LevelSpec
|
The level spec. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no level has that number. |
DungeonState
Bases: BaseModel
The mutable overlay play writes over the frozen adventure content.
References are strings so the overlay serializes flat: explored and seen
cells key by "{dungeon}:{level}", doors by
edge_ref, traps and caches by
"{dungeon}:{level}:{area_or_feature_id}", piles by
cell_ref. explored is the party's
footprint — the cells it has physically entered — while seen is its map
memory: the cells its own light has shown it, read by the player projection
only. Attempt memory (listen once per character per door, search once per
character per cell per kind, the pick-lock lockout with the thief's level at
failure) lives here too — it is game state, not procedure-local bookkeeping.
generated_caches
class-attribute
instance-attribute
generated_caches: dict[str, GeneratedCache] = {}
generated_treasure_areas
class-attribute
instance-attribute
is_explored
mark_explored
mark_seen
Mark cells seen (idempotent): map memory, what the party has glimpsed by light.
Seen cells are read by the player projection only, so a front end's
automap remembers a room the party's light showed it after the party
walks on. They never affect movement cost — that reads the explored
footprint via is_explored
— or drop-pile visibility, which stays on explored cells (piles only ever
form where the party has stood). New positions append in sorted (x, y)
order so serialization is deterministic across runs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dungeon_id
|
str
|
The dungeon id. |
required |
level_number
|
int
|
The 1-based level number. |
required |
positions
|
Iterable[Position]
|
The cells to remember; already-seen cells are skipped. |
required |
Edge
EdgeKind
Bases: StrEnum
What occupies an edge between two cells.
FeatureSpec
Bases: BaseModel
A keyed feature: a treasure cache, a construction trick, or custom content.
Stairs are TransitionSpec's alone — no
second home. Caches carry hand-placed contents — item_ids (any id from
load_equipment, see
the equipment id index), magic_item_ids (any id from
load_magic_items, see
the magic item id index), and coins — plus an optional
treasure trap, so a cache's contents can be dropped, found, and recovered like
any other treasure. Hand-placed magic items instantiate when the cache is
emptied: the author names the item, and its creation details (charges,
quantities, sword sentience) roll on the treasure stream via
instantiate_magic_item.
cell binds the feature to a cell; a feature listed on an area with
cell=None binds to the whole area.
GeneratedCache
Bases: BaseModel
An engine-created treasure cache in the state overlay.
Authored FeatureSpecs are frozen content;
the state overlay owns play-created treasure — the template/instance split
applied to loot. Generated hoards are always untrapped: traps are authored
content only, never a generation outcome (see the adaptations register).
KeyedEncounter
Bases: BaseModel
An area's keyed encounter: monsters with counts and optional pins.
aware=True means the monsters expect intruders (they never roll surprise);
stance pins the reaction outright (no reaction roll); alignment fixes the
spawn alignment for multi-option templates. hoard=True (the default) means
the engine generates the keyed monsters' lair hoard the first time the
encounter spawns; hoard=False is the treasure-absent keyed room — a monster
room the stocking roll gave no treasure — expressible because SRD stocking
puts treasure on only some monster rooms, while an encounter would otherwise
always bring its lair letters.
monsters
class-attribute
instance-attribute
monsters: tuple[KeyedMonster, ...] = Field(min_length=1)
KeyedMonster
Bases: BaseModel
One monster line of a keyed encounter: the template and its count.
template_id is any id in the session's effective catalog — a shipped id from
load_monsters (see
the monster id index) or one bundled by the adventure's
monsters.
LevelSpec
Bases: BaseModel
One dungeon level: a grid of 10' cells with edges, areas, and transitions.
number is 1-based and rules-visible — it keys the encounter-table band.
entrance is where EnterDungeon and town travel land (required on some level
per adventure validation).
in_bounds
edge
Return the authored edge on one side of a cell.
An edge absent from the map is a wall (authored content declares its passages), and the level boundary is implicitly wall.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
position
|
Position
|
The cell. |
required |
direction
|
Direction
|
Which of the cell's four edges. |
required |
Returns:
| Type | Description |
|---|---|
Edge
|
The edge entry. |
area_at
transition_at
transition_at(position: Position) -> TransitionSpec | None
Return the transition on a cell, or None.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
position
|
Position
|
The cell. |
required |
Returns:
| Type | Description |
|---|---|
TransitionSpec | None
|
The transition, if one is authored there. |
PartyLocation
TransitionSpec
Bases: BaseModel
A level transition on a cell: stairs, trapdoor, or chute.
The destination is (dungeon_id, level_number, position, facing). Chutes are
one-way — UseStairs rejects on arrival cells that have no transition back.
TrapEffect
Bases: BaseModel
What a sprung trap does: damage, a save, a condition, a fall, or a transition.
damage_dice rolls once; volley_dice is the darts form (1d6 projectiles,
each rolling damage_dice — a count-times-damage form the dice grammar alone
can't say). save gates the whole effect (negates or half damage).
kills marks save-or-die forms (poison gas). condition with its duration is
the blindness form; fall_feet is the pit's falling damage; transition
drops the victim elsewhere (slides). manual keeps prose for the rest.
condition_duration_dice
class-attribute
instance-attribute
condition_duration_dice: str | None = None
condition_duration_amount
class-attribute
instance-attribute
condition_duration_amount: int | None = None
condition_duration_unit
class-attribute
instance-attribute
condition_duration_unit: TimeUnit | None = None
TrapSpec
Bases: BaseModel
A trap: room (over an area) or treasure (on a feature).
trigger names the springing action (enter a cell of the trapped area,
open a trapped cache). affects defaults to the triggerer; party covers
forms like poison gas filling the room.
TreasureBundle
ValuableSpec
Bases: BaseModel
An authored named valuable in a cache — instantiated on take.
The authoring surface for named treasure: a unique gem or piece of jewellery
with its own display name, rather than a generic generated one. name is the
display name; the instance id comes from the session allocator when the cache
is emptied.
WanderingSpec
Bases: BaseModel
A level's wandering-monster parameters.
The defaults are RAW: a 1-in-6 check every two turns. table overrides the
compiled level-band table with an inline custom list (same row model).
cell_ref
Return the structured cell reference used by location-bound effects.
The format is cell:{dungeon}:{level}:{x},{y} — an
ActiveEffect.target_ref in this form
anchors the effect to a dungeon cell.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dungeon_id
|
str
|
The dungeon id. |
required |
level_number
|
int
|
The 1-based level number. |
required |
position
|
Position
|
The cell. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The cell reference string. |
edge_key
Return the canonical key for the edge on direction's side of position.
Each physical edge has exactly one entry: the key is a cell plus north or
west, so a cell's south edge is its southern neighbour's north edge and its
east edge the eastern neighbour's west. The format is "{x},{y}:{side}".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
position
|
Position
|
The cell. |
required |
direction
|
Direction
|
Which of the cell's four edges. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The canonical edge key. |
edge_ref
Return the state-overlay reference for one physical edge (door bookkeeping).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dungeon_id
|
str
|
The dungeon id. |
required |
level_number
|
int
|
The 1-based level number. |
required |
position
|
Position
|
The cell. |
required |
direction
|
Direction
|
Which of the cell's four edges. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The edge reference string, canonicalized like |
str
|