Phaser AE

Grid dungeon crawler

Pro packv3.0.0-0ArcadeNew

The rules of a real-time, first-person dungeon crawler in the grid tradition, with the mechanics found in games like Legend of Grimrock and Dungeon Master. You draw the dungeon; the pack moves the party, runs the monsters and works every lever, plate and pit.

This is a Pro pack. Upgrade to Phaser Pro to use it in your games.See Phaser Pro →

Released October 25, 2026

Grid dungeon crawler: a screenshot of its demo
A note about these graphics

Expansion packs don't come with graphics. This screenshot is one way of drawing what the pack does, made for its demo: none of the sprites, tiles or backgrounds in it are in the pack.

That's by design. A pack is a game's logic, mechanics and effects, and it works with whatever art you give it. Some packs draw effects, backdrops or 3D scenes of their own, but none carries a game's sprites.

So the look is yours. Make the art on phaser.io, bring your own, or let your agent draw it in code: the same pack can look like anything.

The pack

gridCrawler

function gridCrawler(): Pack<{ gridCrawler: typeof kit; }>

Compose the grid crawler's rules, its two dungeons and its autopilot under game.gridCrawler.

Helpers

checkDungeon

function checkDungeon(d: CrawlerDungeon): string[]

Check a dungeon without playing it: every problem found, as sentences an editor can show, empty when it is sound. Each floor's map goes through sector-map's checkMap; then the kinds, the party, the rules, the goal and every feature: cells on the grid and open, wall props on a wall, stairs and pits that lead somewhere, actions that name what exists. createCrawlerRun throws on the first few.

crawlerAutopilot

function crawlerAutopilot(run: CrawlerRun, pilot: CrawlerPilot, dt: number): string

Play the run for a frame, as a simple player would, before run.step(dt): fight what is ahead with every hand, missile and spell that is ready, turn to face what attacks from the side, heal and eat when low, keep a torch lit (fetching a light first when it has none, and one water cannot put out before wading), pick up what lies about, use levers, buttons, locks it has the key for, alcoves (putting in what they need) and sconces, weigh down plates that hold doors open with a spare item, explore every cell it can reach, hunt the goal's monsters, and take the stairs down (or, with nothing else left, an open pit). It plans from the whole dungeon's state, so it is for attract modes, demos and tests that prove a dungeon can be finished, not for an opponent. Returns what it is doing.

crawlerRunes

const crawlerRunes: readonly string[]

The rune grid the crypt casts from, three by three.

createCrawlerPilot

function createCrawlerPilot(): CrawlerPilot

A fresh autopilot memory.

createCrawlerRun

function createCrawlerRun(dungeon: CrawlerDungeon): CrawlerRun

Start a run through a dungeon. Throws, naming the problems, on a dungeon checkDungeon finds fault with.

cryptSpells

function cryptSpells(): SpellDef[]

The crypt's spells, cast from crawlerRunes.

dirOf

const dirOf = (f: Facing): number=> …

A direction's index, 0 (north) to 3 (west).

facingBetween

function facingBetween(a: Cell, b: Cell): Facing | null

The direction from one cell to a neighbour, or null when they are not side by side.

facingOfDegrees

const facingOfDegrees = (deg: number): Facing=> …

The facing nearest compass degrees (clockwise from north).

FACINGS

const FACINGS: readonly Facing[]

The four directions, clockwise from north.

facingYaw

const facingYaw = (f: Facing): number=> …

The engine's yaw for a facing: forward is (−sin yaw, cos yaw), so north (−z) is π and east (+x) is −π/2.

floodedVault

function floodedVault(options: FloodedVaultOptions = {}): CrawlerDungeon

The Flooded Vault: one explorer alone, in the dark (no light without a flame), over two floors of a sunken cistern. Water slows every step and puts out a torch, so the oil lantern on a pedestal is the light to keep; a vault crab guards a bronze key for the grate before the stairs; a current in the pool carries the explorer off; a sinkhole drops to the floor below; a whirlpool spins; a scale holds the idol chamber's door while weighed with a rock; and lifting the idol stirs the drowned. No spells, a bigger pack, a one-by-one formation, other armour slots, faster hunger and slower steps. The goal: carry the idol back up to the square the explorer started on.

floorData

function floorData(def: CrawlerFloor): { data: SectorMapData; cell: number; origin: [number, number]; columns: number; rows: number; pitBase: Map<number, number>; charCells: (chars: string) => number[] }

The map data a floor plays: a grid painted into sectors (pits and secret walls given sectors of their own) or the map as given, with the hidden triggers that carry its features' map actions. Throws nothing: checkMap judges it.

runeCrypt

function runeCrypt(options: RuneCryptOptions = {}): CrawlerDungeon

The Rune Crypt: a party of four (a fighter and a barbarian in front, a rogue with a bow and a mage behind) down three floors of a dark crypt. Levers raise gates, a plate holds a gate open while weighed down, a loose brick opens a secret nook, pits drop to the floor below until a lever closes them, a spinner turns the party, a teleporter shortcuts the ossuary, an iron key opens a lock, a barricade has to be broken and a nest breeds crawlers. A crystal heals before the last hall, a carved skull in an alcove opens it, and the Bone King, a guarding boss who throws green fire, waits with his wisps. Skeletons, archers, crawlers and wisps walk the grid; the mage casts from a three by three rune grid. The goal: kill the Bone King.

stepCell

const stepCell = (cell: Cell, f: Facing): Cell=> …

The cell one step from cell toward f.

turnFacing

const turnFacing = (f: Facing, turns: number): Facing=> …

The direction turns quarter turns clockwise of f (negative turns go anticlockwise).

Classes

CompiledFloor

class CompiledFloor

A floor ready to play.

  • readonly id: string — Its id.
  • readonly index: number — Its place in the dungeon.
  • readonly def: CrawlerFloor — The authored floor.
  • readonly data: SectorMapData — The map data it plays, with the crawler's sectors and hidden triggers.
  • map: SectorMap — The live map.
  • readonly cell: number — Cell size, world units.
  • readonly origin: [number, number] — Cell [0, 0]'s north-west corner.
  • readonly columns: number — Columns.
  • readonly rows: number — Rows.
  • readonly sectorOf: Int32Array — The sector each cell is, or −1 for rock and solid sectors.
  • readonly atCell: Map<number, CrawlerFeature[]> — Features standing in cells.
  • readonly onWall: Map<number, WallFeature> — Wall features by cell and face.
  • readonly zones: Map<number, ZoneFeature[]> — Zones by cell.
  • readonly features: CrawlerFeature[] — Every feature on the floor.
  • readonly pitBase: Map<number, number> — A pit cell's floor height when shut, by cell index.
  • readonly exits: number[] — Cells where a map trigger ends the level.
  • constructor(def: CrawlerFloor, index: number)
  • key(cell: Cell): number — A cell's index.
  • cellOf(k: number): Cell — The cell of an index.
  • inside(cell: Cell): boolean — Whether a cell is on the grid.
  • open(cell: Cell): boolean — Whether a cell is open floor (a sector that is not solid).
  • centre(cell: Cell): [number, number] — A cell's centre, [x, z] in world units.
  • cellAt(x: number, z: number): Cell — The cell a world point is in (it may be off the grid).
  • floorOf(cell: Cell): number — A cell's floor height now; a pit cell's shut height.
  • drawnFloor(cell: Cell): number — A cell's drawn floor height now (an open pit's bottom).
  • ceilingOf(cell: Cell): number — A cell's ceiling height now.
  • isDoor(cell: Cell): boolean — Whether a cell is a door sector.
  • sectorId(cell: Cell): string | null — The sector id of a cell, or null.
  • edge(cell: Cell, f: Facing): number — What lies between a cell and its neighbour toward f: −2 rock, −1 open (one sector), else the line between them.
  • wallAt(cell: Cell, f: Facing): boolean — Whether the face of a cell toward f is rock (a wall to hang things on).
  • passage(cell: Cell, f: Facing, body: { height: number; step: number; drop: number }): 'ok' | 'wall' | 'door' | 'height' — Whether a body can go from a cell to its neighbour toward f now: 'ok', or what stops it — 'wall' (rock, a blocking edge), 'door' (a door not open enough) or 'height' (too high a step up or down, or no headroom).
  • flies(cell: Cell, f: Facing, y: number): boolean — Whether something flying at height y crosses from a cell toward f (walls and shut doors stop it).
  • things(): FloorThing[] — The map's things on the grid.
  • reset(): void — Rebuild the live map from its data (a fresh start).

CrawlerRun

class CrawlerRun

A run through a dungeon crawler: a party moving a whole cell at a time over sector-map floors, turning a quarter at a time, with moves queued and timed so a presenter can glide the camera; characters with hit points, energy, food, levels and two hands that attack on their own cooldowns (melee from the front rows, missiles and spells from any); rune spells; torches that burn down; real-time monsters that walk the grid, see, hear, chase, guard and attack; and the floor's pressure plates, levers, buttons, pits, stairs, teleporters, spinners, alcoves, secret walls, sconces, locks, writing, spawners, crystals, obstacles and zones, wired to the map's doors and triggers. Headless and seeded. Get one from createCrawlerRun.

  • readonly floors: CompiledFloor[] — The floors, compiled: each one's live map is a sector-map for the renderer.
  • constructor(dungeon: CrawlerDungeon)
  • get status(): CrawlerSave['status'] — 'playing', 'won' or 'over'.
  • get time(): number — Seconds played.
  • get floor(): CompiledFloor — The party's floor, compiled; its map is the live sector map.
  • get cell(): Cell — The party's cell (where it is going, while it moves).
  • get facing(): Facing — The party's facing.
  • get action(): PartyAction | null — What the party is doing, or null.
  • get queued(): CrawlerMove[] — Moves waiting.
  • get idle(): boolean — Whether the party is standing still with nothing queued.
  • get characters(): CrawlerCharacter[] — The characters (copies).
  • get held(): ItemInstance | null — The item in the party's hand, or null.
  • get resting(): boolean — Resting.
  • monsters(floor?: string): CrawlerMonster[] — Monsters on a floor (default the party's), alive.
  • items(floor?: string): FloorItem[] — Items lying on a floor (default the party's).
  • projectiles(): CrawlerProjectile[] — What is flying.
  • feature(id: string): FeatureState | undefined — A feature's state, or undefined.
  • featureDef(id: string): { def: CrawlerFeature; floor: string } | undefined — A feature's definition and floor id, or undefined.
  • item(kind: string): ItemDef | undefined — An item kind.
  • monster(kind: string): MonsterDef | undefined — A monster kind.
  • get spells(): SpellDef[] — The spells.
  • get runes(): string[] — The rune grid.
  • floorById(id: string): CompiledFloor — A floor by id. Throws on one that does not exist.
  • visited(floor?: string): Cell[] — Cells the party has stood in on a floor (default its own), for an automap.
  • get stats(): CrawlerStats — The run's numbers so far.
  • get goalSpec(): { kill: string[]; carry: string[]; reach: { floor: string; at: Cell }[]; needsReach: boolean } — What wins, resolved from the dungeon's goal or its default.
  • get body(): { height: number; step: number; drop: number } — The body the party moves with: headroom, highest step up and deepest step down, in units.
  • get formation(): { columns: number; rows: number; meleeRows: number } — The formation: columns, rows, and how many rows from the front fight hand to hand.
  • get settings(): CrawlerSettings — The rules' numbers, resolved.
  • get light(): CrawlerView['light'] — The party's light now: radius in cells, the flame's share (0 to 1) and where it comes from.
  • move(m: CrawlerMove): boolean — Queue a move: a step forward, back or sideways, or a quarter turn. It starts at once when the party is standing, else waits for the moves before it. Returns false when the queue is full (the rules' queue) or the party cannot move. Throws on an unknown move.
  • stairsTarget(fl: CompiledFloor, f: StairsFeature): { floor: CompiledFloor; stairs: StairsFeature } | null — Where a stairs leads: the floor and the stairs there.
  • pitTarget(fl: CompiledFloor, f: PitFeature): { floor: CompiledFloor; cell: Cell } | null — Where a pit drops to.
  • rest(on: boolean): boolean — Rest: regenerate faster while nothing hunts the party; any move or attack ends it.
  • arrange(order: number[]): void — Put the characters in new formation slots: order[i] is the slot for character i. Throws unless it gives each a different slot inside the formation.
  • attack(character: number, hand: 0 | 1): boolean — Use what a character holds in a hand: a weapon attacks (melee the cell ahead, from the front rows unless it has reach; ranged shoots the ammunition in the other hand; a throwable flies), food is eaten, a potion drunk, a scroll read; an empty hand punches. Each hand waits its own cooldown. Returns whether it acted. Throws on a character or hand that does not exist.
  • cast(character: number, runes: string[]): boolean — Cast from the rune grid: the runes, in any order, name a spell; the character must be a caster of its level with the energy. A projectile flies from the party down the grid; a heal, light or shield takes effect at once. An unknown combination fizzles. Returns whether a spell was cast. Throws on a character that does not exist.
  • interact(): CrawlerFeature['kind'] | 'door' | 'lift' | 'switch' | 'locked' | 'map' | 'nothing' — Use what is in front of the party: a lever, button, lock (with its key from the hand, the hands or the packs), writing, an alcove or a sconce on the wall of its own cell ahead (taking from or putting the held item in), a crystal in the cell ahead, or else the map's door, lift or switch ahead. Returns the feature's kind, 'door', 'lift', 'switch' (a map use trigger), 'locked', 'map' (anything else the map did) or 'nothing'.
  • carries(kind: string): boolean — Whether the party holds an item of a kind anywhere.
  • keys(): string[] — The key names the party holds, for the map's locked doors.
  • take(place: ItemPlace): boolean — Take an item into the party's hand (it must be empty): from the floor here or ahead (index in the cell's list, default the last), the alcove or sconce ahead, or a character's hand, pack or worn slot. Returns whether it did.
  • put(place: ItemPlace): boolean — Put the item in the party's hand somewhere: on the floor here or ahead, in the alcove or sconce ahead, or in a character's hand, pack or worn slot (swapping with what is there; armour only in its own slot; a stack of the same kind tops up). Returns whether it did.
  • pickUp(where: 'here' | 'ahead' = 'here'): string | null — Pick up the top item here (or ahead) and stow it: a stack of its kind first, then an empty hand for a weapon or a torch, then the first free pack slot, front characters first. Returns the item's id, or null.
  • stow(): boolean — Stow the item in the party's hand: into a stack, a free hand (weapons and torches), or a pack. Returns whether it found room.
  • feed(character: number, from: 'held' | ItemPlace): boolean — A character eats or drinks food or a potion from the party's hand ('held') or from any character's hand, pack or worn slot. Returns whether it did. Throws on a character that does not exist.
  • drop(): boolean — Drop the item in the party's hand on the floor here.
  • throwHeld(character?: number): boolean — Throw the item in the party's hand down the grid, by a character (default the first alive). Returns whether it flew.
  • goalState(): { kill: boolean; carry: boolean; reach: boolean } — Whether each part of the goal holds now.
  • step(dt: number): CrawlerEvent[] — Run the dungeon on by dt seconds (0 to 0.25): the party's move and the next queued one, the characters' food, regeneration, cooldowns and torches, the monsters on the party's floor, what flies, plates, spawners, crystals, zones and the floor's map (doors, lifts, triggers). Floors the party is not on wait. Returns what happened since the last step, actions taken between steps included. Throws on a dt out of range.
  • camera(): CrawlerCamera — Where the camera is now, gliding through the party's move.
  • view(): CrawlerView — Everything the presenter draws this frame on the party's floor.
  • get state(): CrawlerSave — A copy of everything that changes: what a save needs.
  • restore(save: CrawlerSave): void — Put back a saved state of this dungeon. Throws on one that does not fit.

Types

AlcoveFeature

interface AlcoveFeature

An alcove in a cell's wall face that holds items: placing what it needs does do, taking it away undo.

  • kind: 'alcove' — 'alcove'.
  • id: string — Unique id across the dungeon.
  • at: Cell — The cell it is used from.
  • face: Facing — The wall of that cell it is in.
  • items?: ItemStack[] — Items in it at the start.
  • capacity?: number — Most items it holds, 1 to 64; default 4.
  • need?: string — The item kind that sets it off; default any item.
  • do?: CrawlerAction[] — Actions when it comes to hold what it needs.
  • undo?: CrawlerAction[] — Actions when it stops holding it.

ButtonFeature

interface ButtonFeature

A button on a cell's wall face: each press does do. A hidden one is a loose brick that opens a secret.

  • kind: 'button' — 'button'.
  • id: string — Unique id across the dungeon.
  • at: Cell — The cell it is used from.
  • face: Facing — The wall of that cell it is on.
  • do?: CrawlerAction[] — Actions on a press.
  • once?: boolean — Works once; default false.
  • hidden?: boolean — Hard to see; default false.

Cell

type Cell = [number, number]

A cell of a floor's grid, [column, row]: column 0 is the west edge, row 0 the north edge.

CharacterDef

interface CharacterDef

One character of the party.

  • name: string — A name to show.
  • role?: string — A class to show (fighter, mage…); the rules ignore it.
  • hp: number — Most hit points, 1 to 1000000.
  • energy: number — Most energy (mana), 0 to 1000000.
  • food?: number — Most food, 1 to 1000000; default 100.
  • level?: number — Starting level, 1 to 1000; default 1.
  • caster?: boolean — Casts spells; default false.
  • power?: number — Multiplies the damage it deals, 0 to 100; default 1.
  • accuracy?: number — Added to its weapons' accuracy, −1 to 1; default 0.
  • evasion?: number — Chance to dodge, 0 to 0.95; default 0.05.
  • protection?: number — Protection of its own, 0 to 100000; default 0.
  • slot?: number — Its place in the formation, 0 to columns × rows − 1; default its place in the list.
  • perLevel?: { hp?: number; energy?: number; power?: number } — What each level up adds; default the rules' perLevel.
  • hands?: [ItemStack | null, ItemStack | null] — Items in its hands at the start, [left, right].
  • worn?: Record<string, string> — Item kinds worn at the start, by slot.
  • pack?: ItemStack[] — Items in its pack at the start.

CrawlerAction

type CrawlerAction = | TriggerAction | { pit: string; open: boolean | 'toggle' } | { feature: string; on: boolean | 'toggle' } | { spawner: string } | { give: string; count?: number } | { place: string; at: Cell; floor?: string; count?: number } | { win: true }

Something a feature does: any sector-map trigger action (open a door, move a floor, switch lamps, a message, a spawn, a teleport, the exit…), run on the feature's own floor, or one of the crawler's own:

  • { pit, open }: open or close a pit ('toggle' flips it).
  • { feature, on }: switch a plate, teleporter, spinner or spawner on or off ('toggle' flips it).
  • { spawner }: that spawner brings out a monster now.
  • { give, count }: an item into the party's hand (or onto its cell when the hand is full).
  • { place, at, floor, count }: an item onto a cell.
  • { win: true }: the dungeon is won.

CrawlerCamera

interface CrawlerCamera

Where the camera is and how it glides, for the presenter.

  • x: number — Eye position, world units.
  • y: number — Eye height, world units.
  • z: number — Eye position, world units.
  • yaw: number — The engine's yaw, gliding through turns the short way round.
  • from: Cell — The cell the move started in.
  • to: Cell — The cell it ends in.
  • facing: Facing — The facing now (the new one, during a turn).
  • progress: number — How far through the move, 0 to 1 (1 when standing).
  • moving: PartyAction['kind'] | null — What is moving it: 'step', 'turn', 'bump', 'fall' or null when standing.

CrawlerCharacter

interface CrawlerCharacter

What a character is now.

  • id: string — Its id, c0, c1… by its place in the party list.
  • name: string — Its name.
  • role: string — Its role.
  • slot: number — Its formation slot.
  • row: number — Its row, 0 the front.
  • column: number — Its column, 0 the left.
  • hp: number — Hit points.
  • maxHp: number — Most hit points.
  • energy: number — Energy.
  • maxEnergy: number — Most energy.
  • food: number — Food.
  • maxFood: number — Most food.
  • level: number — Level.
  • xp: number — Experience.
  • power: number — Damage multiplier.
  • alive: boolean — Alive.
  • caster: boolean — Casts spells.
  • hands: [ItemInstance | null, ItemInstance | null] — Its hands, left and right.
  • worn: Record<string, ItemInstance | null> — What it wears, by slot.
  • pack: (ItemInstance | null)[] — Its pack.
  • cooldown: [number, number] — Seconds until each hand is ready.
  • castCooldown: number — Seconds until it can cast again.

CrawlerDungeon

interface CrawlerDungeon

A whole dungeon: floors, kinds, the party and the rules.

  • name?: string — A name to show.
  • floors: CrawlerFloor[] — The floors, top first: stairs down and pits lead to the next.
  • items: ItemDef[] — Item kinds.
  • monsters: MonsterDef[] — Monster kinds.
  • runes?: string[] — The rune grid, by name, in the order the presenter lays it out (Grimrock-style grids are 3 by 3); default none.
  • spells?: SpellDef[] — Spells.
  • party: PartyDef — The party.
  • rules?: CrawlerRules — The rules' numbers.
  • goal?: CrawlerGoal — What wins; default kill every boss kind placed, or else use a map exit.
  • sounds?: Partial<Record<CrawlerEvent['type'], string>> — Sounds by event type: a sound event comes with each event of that type, where it happened.
  • seed?: number — The seed for every roll; default 1.
  • meta?: Record<string, unknown> — Anything else the game keeps with the dungeon.

CrawlerEvent

type CrawlerEvent = | { type: 'step'; from: Cell; to: Cell; dir: Facing } | { type: 'bump'; dir: Facing; what: 'wall' | 'door' | 'monster' | 'obstacle' | 'height' } | { type: 'turn'; facing: Facing; by: 1 | -1 } | { type: 'attack'; by: string; hand: 0 | 1 | null; with: string; at: Cell } | { type: 'hit'; by: string; target: string; damage: number; at: Cell } | { type: 'miss'; by: string; target: string | null; at: Cell } | { type: 'damage'; target: string; amount: number; x: number; y: number; z: number; to: 'monster' | 'character' | 'obstacle' } | { type: 'spell'; character: string; spell: string } | { type: 'fizzle'; character: string; runes: string[] } | { type: 'refused'; character: string; reason: 'dead' | 'cooldown' | 'energy' | 'level' | 'reach' | 'ammo' | 'caster' | 'nothing' } | { type: 'projectile'; id: string; phase: 'launch' | 'burst' | 'stop'; what: string; x: number; y: number; z: number; splash: number } | { type: 'plate'; id: string; down: boolean } | { type: 'lever'; id: string; down: boolean } | { type: 'button'; id: string } | { type: 'pit'; id: string; open: boolean } | { type: 'fall'; who: string; from: string; to: string; at: Cell } | { type: 'door'; sector: string; phase: string } | { type: 'teleport'; who: string; floor: string; at: Cell } | { type: 'spin'; facing: Facing } | { type: 'stairs'; dir: 'up' | 'down'; floor: string; at: Cell } | { type: 'floor'; floor: string } | { type: 'pickup'; item: string; kind: string } | { type: 'put'; item: string; kind: string; where: string } | { type: 'eat'; character: string; item: string } | { type: 'drink'; character: string; item: string } | { type: 'read'; text: string; spell: string | null } | { type: 'unlock'; id: string } | { type: 'locked'; id: string; key: string } | { type: 'alcove'; id: string; filled: boolean } | { type: 'sconce'; id: string; lit: boolean } | { type: 'heal'; character: string; amount: number } | { type: 'crystal'; id: string } | { type: 'torch'; item: string; lit: boolean } | { type: 'level-up'; character: string; level: number } | { type: 'death'; who: string; kind: 'character' | 'monster' | 'obstacle' } | { type: 'notice'; monster: string } | { type: 'spawn'; monster: string; kind: string; at: Cell } | { type: 'secret'; id: string } | { type: 'message'; text: string } | { type: 'event'; name: string; data?: unknown } | { type: 'map'; event: MapEvent } | { type: 'win' } | { type: 'over' } | { type: 'sound'; sound: string; x: number; y: number; z: number }

What happened.

CrawlerFeature

type CrawlerFeature = | PlateFeature | LeverFeature | ButtonFeature | PitFeature | StairsFeature | TeleporterFeature | SpinnerFeature | AlcoveFeature | SecretFeature | SconceFeature | LockFeature | InscriptionFeature | SpawnerFeature | CrystalFeature | ObstacleFeature | ZoneFeature

Anything the crawler lays over a floor, keyed by cell.

CrawlerFloor

interface CrawlerFloor

One floor of the dungeon: a sector map on a grid of square cells, and the features on it. Things in the map place the start ('start'), monsters (by kind id) and items (by item id); other things are scenery for the presenter.

  • id: string — Unique id.
  • name?: string — A name to show.
  • grid?: GridMap — The floor painted as characters (sector-map's gridMap): the usual way.
  • map?: SectorMapData — Or a map made another way, laid out on the grid.
  • cell?: number — With map: the cell size in units, 0.5 to 64; default 2 (a grid uses its own cell).
  • origin?: [number, number] — With map: where cell [0, 0]'s north-west corner is, [x, z]; default [0, 0].
  • features?: CrawlerFeature[] — The crawler's features.
  • items?: { item: string; at: Cell; count?: number }[] — Items lying on cells at the start, as well as the map's item things (which are one each).
  • ambient?: number — The darkness: the light the party has with no torch or spell, in cells, 0 to 32; default the rules' ambient.
  • meta?: Record<string, unknown> — Anything else the game keeps with the floor (music, a tint).

CrawlerGoal

interface CrawlerGoal

What wins the dungeon. Every part given must hold at once; a map exit action counts as reaching.

  • kill?: string[] — Kill every monster of these kinds or tags, wherever it is.
  • carry?: string[] — Carry an item of each of these kinds.
  • reach?: { floor: string; at: Cell }[] — Stand on one of these cells (or use a map exit).

CrawlerMonster

interface CrawlerMonster

A monster now.

  • id: string — Unique id, <kind>-<n>.
  • kind: string — Its kind.
  • floor: string — The floor it is on, by id.
  • cell: Cell — Its cell (where it is going, while it moves).
  • facing: Facing — Its facing.
  • hp: number — Hit points.
  • mode: 'idle' | 'wander' | 'hunt' | 'return' | 'dead' — 'idle', 'wander', 'hunt', 'return' or 'dead'.
  • action: { kind: 'step' | 'turn' | 'attack'; t: number; time: number; from: Cell; fromFacing: Facing; dir: Facing } | null — What it is doing, or null between actions.
  • cooldown: number — Seconds until it may attack again.
  • wait: number — Seconds it waits before thinking again.
  • alert: { cell: Cell; time: number } | null — Where it last saw or heard the party, and seconds left before it gives up.
  • home: { cell: Cell; facing: Facing } — Its post and facing, for guards going back.
  • walked: number — Cells walked, for the presenter's walk cycle.
  • tag: string | null — A tag, for kill triggers.
  • spawner: string | null — The spawner it came from, or null.
  • hurt: number — Seconds since it was last hurt, for a flinch.

CrawlerMove

type CrawlerMove = 'forward' | 'back' | 'left' | 'right' | 'turn-left' | 'turn-right'

A move the party can make: a step four ways, or a quarter turn.

CrawlerPilot

interface CrawlerPilot

An autopilot's memory between frames.

  • goal: string — What it is doing: 'fight', 'heal', 'rest', 'loot', 'use', 'explore', 'plate', 'hunt', 'goal', 'stairs', 'pit', 'wait' or ''.
  • target: Cell | null — The cell it is heading for, or null.
  • used: Record<string, number> — Times it has used each feature, by id.
  • pressed: string[] — Plates it has pressed, by id.
  • wait: number — Seconds before it decides again.
  • stuck: number — Seconds without moving to a new cell.
  • last: string — Where it was last frame, as floor:column,row.
  • skip: Record<string, number> — Targets it gave up on for now, by key, with seconds left.

CrawlerProjectile

interface CrawlerProjectile

Something flying down the grid.

  • id: string — Unique id.
  • from: string — Who sent it: a character id or a monster id.
  • side: 'party' | 'monster' — 'party' or 'monster': who it is against.
  • what: string — What it is: a spell id, an item kind or a monster kind.
  • floor: string — The floor it is on.
  • cell: Cell — The cell it is leaving.
  • dir: Facing — Its heading.
  • t: number — How far toward the next cell, 0 to 1.
  • def: ProjectileDef — Its flight.
  • left: number — Cells it may still fly.
  • y: number — Its height above the floor where it started, in world units.
  • item: ItemInstance | null — The item it is (a thrown dagger, an arrow), left where it stops.
  • power: number — Multiplies its damage (the thrower's power).

CrawlerProp

interface CrawlerProp

A wall prop or cell prop as the presenter draws it.

  • id: string — The feature's id.
  • kind: CrawlerFeature['kind'] — Its kind.
  • cell: Cell — Its cell (for a wall prop, the cell it is used from).
  • face: Facing | null — A wall prop's wall, or null.
  • x: number — Where to draw it: a wall prop on the middle of its wall face, a cell prop at the cell's centre on its floor.
  • y: number — Floor height at the prop, world units.
  • z: number — Where to draw it.
  • yaw: number — The engine's yaw it faces: a wall prop faces out of its wall into the cell.
  • active: boolean — Plates and levers down, pits open, locks unlocked, buttons pressed.
  • on: boolean — Plates, teleporters, spinners and spawners working.
  • items: string[] — What an alcove holds, or a sconce's torch, by item kind.
  • hidden: boolean — Hidden plates and buttons.
  • text: string | null — Text of an inscription.
  • dir: 'up' | 'down' | null — A stairs' way, or null.
  • prop: string | null — An obstacle's prop name, or null.
  • lit: boolean — A crystal that works now; a sconce holding a lit torch.

CrawlerRules

interface CrawlerRules

The rules' numbers. Every one has a default.

  • moveTime?: number — Seconds a step from one cell to the next takes, 0.02 to 10; default 0.4.
  • turnTime?: number — Seconds a quarter turn takes, 0 to 10; default 0.25.
  • bumpTime?: number — Seconds a bump into a wall holds the party, 0 to 10; default 0.25.
  • fallTime?: number — Seconds a fall from a pit takes to land, 0 to 10; default 0.5.
  • queue?: number — Most moves queued while one is under way, 0 to 16; default 2.
  • hunger?: number — Food each character eats a second, 0 to 1000; default 0.04.
  • starve?: number — Hit points a starving character loses a second, 0 to 1000; default 0.5.
  • regen?: { hp?: number; energy?: number } — Hit points and energy regained a second, as a share of the most, 0 to 1; default 0.004 and 0.02.
  • rest?: number — Multiplies regeneration and hunger while resting, 1 to 100; default 6.
  • pitDamage?: [number, number] — Damage to each character from a fall, [min, max]; default [2, 6].
  • levels?: number[] — Experience needed for each level after the first, in order (cumulative), each 1 to 1e12; default a gentle curve to level 10.
  • perLevel?: { hp?: number; energy?: number; power?: number } — What a level up adds, unless a character says; default 6 hit points, 4 energy.
  • xpShare?: 'each' | 'split' — 'each' (every living character gets a kill's whole experience, the default) or 'split' (shared among them).
  • unarmed?: ItemAttack — A bare hand's attack; default [1, 3] damage every 1 second at 0.8 accuracy.
  • noise?: { step?: number; attack?: number; spell?: number; bump?: number } — How far the party's noise carries, in cells, 0 to 64; default step 2, attack 4, spell 5, bump 3.
  • ambient?: number — The light the party has with no torch or spell, in cells, 0 to 32; default 1.
  • friendlyFire?: boolean — The party's own blasts hurt it; default true.
  • reachAhead?: boolean — Items can be taken from and put on the cell ahead as well as the party's own; default true.

CrawlerSave

interface CrawlerSave

Everything that changes in a run; a save holds exactly this.

  • time: number — Seconds played.
  • status: 'playing' | 'won' | 'over' — 'playing', 'won' or 'over' (the whole party dead).
  • floor: string — The party's floor, by id.
  • cell: Cell — The party's cell (where it is going, while it moves).
  • facing: Facing — The party's facing (the new one, while it turns).
  • action: PartyAction | null — What the party is doing, or null.
  • queue: CrawlerMove[] — Moves waiting.
  • held: ItemInstance | null — The item in the party's hand (the pointer's), or null.
  • characters: CrawlerCharacter[] — The characters.
  • light: { radius: number; time: number } — A light spell: radius in cells and seconds left.
  • shield: { protection: number; time: number } — A shield spell: protection and seconds left.
  • resting: boolean — Resting.
  • monsters: CrawlerMonster[] — The monsters, on every floor.
  • items: FloorItem[] — Items lying on floors.
  • projectiles: CrawlerProjectile[] — What is flying.
  • features: Record<string, FeatureState> — Every feature's state, by id.
  • maps: Record<string, SectorMapState> — Each floor's map state, by floor id.
  • visited: Record<string, number[]> — Cells the party has stood in, by floor id (cell indices, row × columns + column).
  • secrets: string[] — Secrets found, by feature or sector id.
  • kills: number — Monsters killed.
  • steps: number — Steps taken.
  • serial: number — The id counter.
  • drain: Record<string, number> — Damage over time not yet a whole point, by character or monster id.
  • rng: number[] — The random stream.

CrawlerSettings

interface CrawlerSettings

The rules' numbers with every default filled in (see CrawlerRules for what each means).

  • moveTime: number — Seconds a step takes.
  • turnTime: number — Seconds a quarter turn takes.
  • bumpTime: number — Seconds a bump holds the party.
  • fallTime: number — Seconds a fall takes to land.
  • queue: number — Most moves queued.
  • hunger: number — Food eaten a second.
  • starve: number — Hit points a starving character loses a second.
  • regenHp: number — Hit points regained a second, as a share of the most.
  • regenEnergy: number — Energy regained a second, as a share of the most.
  • rest: number — Resting's multiplier.
  • pitDamage: [number, number] — A fall's damage, [min, max].
  • levels: number[] — Experience for each level after the first.
  • perLevel: { hp: number; energy: number; power: number } — What a level adds.
  • xpShare: 'each' | 'split' — How a kill's experience is shared.
  • unarmed: ItemAttack — A bare hand's attack.
  • noise: { step: number; attack: number; spell: number; bump: number } — How far noise carries, in cells.
  • ambient: number — Light with no flame or spell, in cells.
  • friendlyFire: boolean — The party's blasts hurt it.
  • reachAhead: boolean — Items reach to the cell ahead.

CrawlerSkill

type CrawlerSkill = 'easy' | 'normal' | 'hard'

How hard a preset is: multiplies monsters' hit points and damage.

CrawlerStats

interface CrawlerStats

The run's numbers so far.

  • time: number — Seconds played.
  • kills: number — Monsters killed.
  • steps: number — Steps taken.
  • secrets: number — Secrets found.
  • secretsTotal: number — Secrets in the dungeon (secret walls and secret sectors).
  • floors: number — Floors the party has been on.

CrawlerView

interface CrawlerView

A frame's worth of what to draw.

  • floor: string — The party's floor, by id.
  • camera: CrawlerCamera — The camera and its glide.
  • light: { radius: number; level: number; source: 'ambient' | 'torch' | 'spell' } — The party's light: radius in cells, the share of a full torch's flame (0 to 1), and where it comes from.
  • monsters: { id: string; kind: string; x: number; y: number; z: number; yaw: number; cell: Cell; facing: Facing; action: 'idle' | 'step' | 'turn' | 'attack'; progress: number; walk: number; hp: number; maxHp: number; boss: boolean; hurt: number; mode: CrawlerMonster['mode'] }[] — Monsters on the floor: where they are, gliding, which way they face, and a walk phase.
  • items: { id: string; kind: string; count: number; x: number; y: number; z: number; cell: Cell }[] — Items on the floor: spread over the cell's quarters.
  • projectiles: { id: string; what: string; x: number; y: number; z: number; yaw: number; light: number; color: string | null }[] — What is flying.
  • props: CrawlerProp[] — The crawler's props: levers, buttons, alcoves, sconces, locks, writing, plates, pits, stairs, teleporters, spinners, spawners, crystals, obstacles.
  • scenery: { type: string; x: number; y: number; z: number; yaw: number }[] — The map's other things (scenery), by type.

CrystalFeature

interface CrystalFeature

A healing crystal standing in a cell: using it from the next cell heals and revives the party, then it dims a while.

  • kind: 'crystal' — 'crystal'.
  • id: string — Unique id across the dungeon.
  • at: Cell — Its cell; nothing walks into it.
  • cooldown?: number — Seconds before it works again, 0 to 100000; default 120.

Facing

type Facing = 'n' | 'e' | 's' | 'w'

A compass direction on the grid: north is up the rows (−z), east along them (+x).

FeatureState

interface FeatureState

A feature's state now.

  • on: boolean — Working (plates, teleporters, spinners, spawners).
  • active: boolean — A plate or lever down; a pit open; a lock unlocked; a button pressed at least once.
  • spent: boolean — Spent: a once lever or button used, a lock opened, a latched plate pressed.
  • items: ItemInstance[] — What an alcove holds, or a sconce's torch.
  • timer: number — A crystal's seconds before it works again; a spawner's seconds to its next spawn.
  • spawned: number — A spawner: how many it has brought out.
  • hp: number — A breakable obstacle's hit points left; 0 for every other feature.
  • broken: boolean — An obstacle broken: no longer in the way.
  • used: boolean — Used by the party at least once (read, pulled, pressed, taken from).

FloodedVaultOptions

interface FloodedVaultOptions

Options for floodedVault.

  • skill?: CrawlerSkill — Monsters' toughness; default 'normal'.
  • seed?: number — The seed; default 1.

FloorItem

interface FloorItem

An item lying on a floor.

  • item: ItemInstance — The item.
  • floor: string — The floor, by id.
  • cell: Cell — Its cell.

FloorThing

interface FloorThing

A thing the map placed, on the grid.

  • type: string — Its type.
  • cell: Cell — Its cell.
  • facing: Facing — Its facing.
  • tag: string | null — Its tag, or null.
  • ambush: boolean — Placed in ambush (waits for sight).
  • patrol: boolean — Placed to walk about.
  • x: number — World position.
  • z: number — World position.
  • yaw: number — The engine's yaw.

InscriptionFeature

interface InscriptionFeature

Writing on a cell's wall face, read by using it.

  • kind: 'inscription' — 'inscription'.
  • id: string — Unique id across the dungeon.
  • at: Cell — The cell it is read from.
  • face: Facing — The wall of that cell it is on.
  • text: string — The text.

ItemAttack

interface ItemAttack

An attack an item makes from a character's hand.

  • kind: 'melee' | 'ranged' | 'throw' — 'melee' (the cell ahead, from the front rows), 'ranged' (a projectile, needing ammo in the other hand when it says) or 'throw' (the item itself flies).
  • damage: [number, number] — Damage, [min, max] whole numbers from 0 to 100000 (a ranged weapon's projectile has its own).
  • cooldown: number — Seconds before this hand is ready again, 0.05 to 60.
  • accuracy?: number — Chance to hit before the target's evasion, 0 to 1; default 0.85.
  • reach?: boolean — Melee from any row (a spear); default false.
  • ammo?: string — Ranged: the item kind it shoots, held in the other hand.
  • projectile?: ProjectileDef — Ranged and throw: how the shot flies; default 6 cells a second, range 12.
  • energy?: number — Energy it costs, 0 to 100000; default 0.

ItemDef

interface ItemDef

A kind of item.

  • id: string — Unique id; maps and features place it by this.
  • name?: string — A name to show.
  • kind: 'weapon' | 'armour' | 'shield' | 'food' | 'torch' | 'key' | 'scroll' | 'potion' | 'throwable' | 'ammo' | 'misc' — What it is: decides what using it does and where it can go.
  • weight?: number — Weight on a plate, per item, 0 to 1000; default 1.
  • stack?: number — Most in one stack, 1 to 999; default 1.
  • attack?: ItemAttack — A weapon's or throwable's attack.
  • slot?: string — Armour: the slot it is worn in (one of the party's slots).
  • protection?: number — Armour and shields: protection taken off each hit, 0 to 10000.
  • evasion?: number — Armour and shields: added to the wearer's evasion, −1 to 1.
  • food?: number — Food: how much it restores.
  • effect?: ItemEffect — Potions (and food, besides food): what drinking it does.
  • fuel?: number — Torch: seconds it burns in a hand, 1 to 1000000; default 300.
  • light?: number — Torch: the light it gives at full flame, in cells, 0 to 32; default 4. It dims to half as it burns down.
  • waterproof?: boolean — Torch: water does not put it out (a lantern); default false.
  • opens?: string — Key: the key name a sector-map door's key asks for; default the item's id.
  • text?: string — Scroll: its text.
  • spell?: string — Scroll: the spell whose runes it shows.

ItemEffect

interface ItemEffect

What an item does when drunk, eaten or used.

  • hp?: number — Hit points restored (negative hurts).
  • energy?: number — Energy restored.
  • food?: number — Food restored.
  • revive?: number — Brings a dead character back with this many hit points.

ItemInstance

interface ItemInstance

One item, or a stack of one kind.

  • id: string — Unique id, <kind>-<n>.
  • kind: string — Its item kind.
  • count: number — How many, 1 or more.
  • fuel?: number — A torch's seconds of flame left.

ItemPlace

type ItemPlace = | { floor: 'here' | 'ahead'; index?: number } | { wall: true } | { character: number; hand: 0 | 1 } | { character: number; pack: number } | { character: number; worn: string }

Where an item is taken from or put.

ItemStack

type ItemStack = string | { item: string; count?: number }

An item kind, or a stack of one: 'arrow' or { item: 'arrow', count: 12 }.

LeverFeature

interface LeverFeature

A lever on a cell's wall face: pulled down and pushed back up, doing do and undo.

  • kind: 'lever' — 'lever'.
  • id: string — Unique id across the dungeon.
  • at: Cell — The cell it is used from.
  • face: Facing — The wall of that cell it is on.
  • down?: boolean — Down at the start; default false.
  • do?: CrawlerAction[] — Actions as it goes down.
  • undo?: CrawlerAction[] — Actions as it goes up.
  • once?: boolean — Pulled once, it stays; default false.

LockFeature

interface LockFeature

A lock on a cell's wall face: using it with its key does do.

  • kind: 'lock' — 'lock'.
  • id: string — Unique id across the dungeon.
  • at: Cell — The cell it is used from.
  • face: Facing — The wall of that cell it is on.
  • key: string — The key's item kind.
  • consume?: boolean — The key is used up; default true.
  • do?: CrawlerAction[] — Actions on unlocking.

MonsterAttack

interface MonsterAttack

How a monster attacks.

  • kind: 'melee' | 'ranged' — 'melee' (the next cell, through an open edge) or 'ranged' (a projectile along a row or column in sight).
  • damage: [number, number] — Damage, [min, max] whole numbers from 0 to 100000 (a ranged attack's projectile has its own).
  • cooldown: [number, number] — Seconds between attacks, [min, max] from 0.1 to 60.
  • windup?: number — Seconds from starting the attack to its landing, 0 to 10; default 0.4. A party that steps away in time is missed.
  • accuracy?: number — Chance to hit before the target's evasion, 0 to 1; default 0.8.
  • range?: number — Ranged: most cells away it shoots, 1 to 64; default 5.
  • projectile?: ProjectileDef — Ranged: the projectile; default 5 cells a second with the attack's damage.

MonsterDef

interface MonsterDef

A kind of monster.

  • id: string — Unique id; maps and spawners place it by this.
  • name?: string — A name to show.
  • hp: number — Hit points, 1 to 1000000.
  • moveTime: number — Seconds a step from one cell to the next takes, 0.05 to 60.
  • turnTime?: number — Seconds a quarter turn takes, 0 to 60; default half its moveTime.
  • attack: MonsterAttack — Its attack.
  • sight?: number — How many cells it sees, 0 to 64; default 6.
  • view?: 'front' | 'all' — 'front' (the default: its front half, sides included) or 'all' (eyes all round).
  • hearing?: number — Multiplies how far it hears the party's noise, 0 (deaf) to 10; default 1.
  • memory?: number — Seconds it keeps hunting where it last saw or heard the party, 0 to 600; default 8.
  • float?: boolean — Floats: crosses open pits and does not press plates; default false.
  • guard?: boolean — Holds its post: waits until it sees the party, and goes back when it loses them; default false.
  • wander?: boolean — Roams when it has nothing to hunt; default true (false for guards).
  • strafe?: boolean — Moves sideways and back without turning first; default false.
  • step?: number — Highest step between cells it climbs, in units, 0 to 64; default the party's step.
  • weight?: number — Weight on a plate, 0 to 1000; default 5 (0 when it floats).
  • protection?: number — Protection taken off each hit, 0 to 100000; default 0.
  • evasion?: number — Chance to dodge a hit, 0 to 0.95; default 0.1.
  • xp?: number — Experience for killing it, shared as the rules' xpShare says, 0 to 1e9; default 10.
  • drops?: { item: string; chance?: number; count?: number }[] — What it may leave where it dies: an item kind, the chance (default 1) and how many (default 1).
  • resist?: Record<string, number> — Damage multipliers by element ({ fire: 0.5, cold: 2 }), 0 to 10.
  • boss?: boolean — A boss: the presenter shows its health, and the default goal is to kill every boss. Default false.
  • sounds?: MonsterSounds — Its sounds.

MonsterSounds

interface MonsterSounds

Sounds a monster makes, by name, as sound events where it is.

  • see?: string — When it notices the party.
  • attack?: string — As it starts an attack.
  • pain?: string — When it is hurt and lives.
  • death?: string — When it dies.
  • step?: string — Each cell it walks.

ObstacleFeature

interface ObstacleFeature

Something solid in a cell (a statue, a barricade): nothing walks into it; with hit points it can be broken.

  • kind: 'obstacle' — 'obstacle'.
  • id: string — Unique id across the dungeon.
  • at: Cell — Its cell.
  • hp?: number — Hit points, above 0; default none: it cannot be broken.
  • prop?: string — What the presenter draws, by name.
  • drops?: string[] — Item kinds it leaves when broken.

PartyAction

interface PartyAction

What the party is doing: moving, turning, bumping, falling or arriving from stairs.

  • kind: 'step' | 'turn' | 'bump' | 'fall' — 'step', 'turn', 'bump' or 'fall' (landing on a floor below).
  • t: number — Seconds it has taken so far.
  • time: number — Seconds it takes.
  • from: Cell — The cell it started from.
  • to: Cell — The cell it ends in (the same for a turn or a bump).
  • fromFacing: Facing — The facing it started with.
  • dir: Facing — The direction of a step or bump.

PartyDef

interface PartyDef

The party: who is in it and how it stands and moves.

  • characters: CharacterDef[] — The characters, 1 to columns × rows.
  • formation?: { columns: number; rows: number } — The formation's columns (across) and rows (front to back), 1 to 8 each; default 2 by 2.
  • meleeRows?: number — How many rows from the front can fight hand to hand, 1 to 8; default 1.
  • packSize?: number — Pack slots per character, 0 to 256; default 12.
  • slots?: string[] — Armour slots; default ['head', 'body', 'legs', 'feet'].
  • weight?: number — The party's weight on plates, 0 to 1000; default 10.
  • eye?: number — Eye height above the floor, in units, 0.1 to 64; default 1.3.
  • height?: number — Headroom it needs, in units, 0.1 to 64; default 1.6.
  • step?: number — Highest step up between cells, in units, 0 to 64; default 0.6.
  • drop?: number — Deepest step down between cells, in units, 0 to 64; default 1.5.

PitFeature

interface PitFeature

A pit in a cell's floor, open or shut by actions: what walks onto it open falls to the floor below.

  • kind: 'pit' — 'pit'.
  • id: string — Unique id across the dungeon.
  • at: Cell — Its cell.
  • open?: boolean — Open at the start; default true.
  • to?: { floor?: string; at?: Cell } — Where a fall lands: a floor (default the next in the list) and a cell (default the same).
  • damage?: [number, number] — Damage to each character on a fall, [min, max] whole numbers; default the rules' pitDamage.
  • depth?: number — How far its floor drops when open, in units, above 0; default 3. On a grid floor the cell becomes its own sector, named by the pit's id, so the map draws the hole.
  • sector?: string — A floor made from map data: the sector (id or tag) to lower and raise; default none (the presenter draws the hole).

PlateBy

type PlateBy = 'party' | 'monster' | 'item'

Who weighs on a pressure plate.

PlateFeature

interface PlateFeature

A pressure plate on a cell's floor: down while the weight on it is at least its weight.

  • kind: 'plate' — 'plate'.
  • id: string — Unique id across the dungeon.
  • at: Cell — Its cell.
  • weight?: number — The weight that presses it, above 0; default 1. The party weighs PartyDef.weight, a monster its kind's weight, an item its weight times its count.
  • by?: PlateBy[] — What presses it; default all three.
  • do?: CrawlerAction[] — Actions as it goes down.
  • undo?: CrawlerAction[] — Actions as it comes back up.
  • latch?: boolean — Stays down once pressed; default false.
  • hidden?: boolean — Hard to see: the presenter draws it faintly or not at all; default false.
  • on?: boolean — Working at the start; default true. A { feature, on } action switches it.

ProjectileDef

interface ProjectileDef

A projectile a weapon, a throw, a spell or a monster sends down the grid.

  • speed: number — Cells per second, 0.5 to 100.
  • damage: [number, number] — Damage on a hit, [min, max] whole numbers from 0 to 100000.
  • splash?: number — Burst reach in cells, 0 to 8: 0 hurts everything in the cell it bursts in, more spreads through open edges; default none (only what it hits).
  • range?: number — Most cells it flies, 1 to 256; default 16.
  • motion?: 'smooth' | 'cell' — 'smooth' (the default) glides between cells; 'cell' jumps a whole cell at a time.
  • element?: string — Its element ('fire', 'cold'…), matched against a monster's resist.
  • light?: number — Light it gives off for the presenter, in cells, 0 to 32; default 0.
  • color?: string — Colour for the presenter, CSS.

RuneCryptOptions

interface RuneCryptOptions

Options for runeCrypt.

  • floors?: 2 | 3 — 3 floors (the default), or 2: the gate and the throne, with the ossuary left out.
  • skill?: CrawlerSkill — Monsters' toughness; default 'normal'.
  • seed?: number — The seed; default 1.

SconceFeature

interface SconceFeature

A torch sconce on a cell's wall face: holds one torch, lit, that the party can take and put back.

  • kind: 'sconce' — 'sconce'.
  • id: string — Unique id across the dungeon.
  • at: Cell — The cell it is used from.
  • face: Facing — The wall of that cell it is on.
  • torch?: boolean | string — Holding a torch at the start: true for the first torch kind, or a torch kind by id; default false.
  • lamp?: string — A map light tag switched on while it holds a torch and off while it is empty.
  • do?: CrawlerAction[] — Actions when a torch is put in.
  • undo?: CrawlerAction[] — Actions when the torch is taken.

SecretFeature

interface SecretFeature

A secret wall: a cell that looks like rock until an action opens it ({ open: id }, from a hidden button).

  • kind: 'secret' — 'secret'.
  • id: string — Unique id across the dungeon; on a grid floor also the id of the door sector it becomes.
  • at: Cell — Its cell (rock in the grid, or anything: it becomes a shut door).
  • floor?: number — Floor height when open; default the map's.
  • ceiling?: number — Ceiling height when open; default the map's.
  • texture?: string — The wall texture its shut face shows; default the map's wall.
  • sector?: string — A floor made from map data: the door sector it is (id); default the feature's id.

SpawnerFeature

interface SpawnerFeature

A monster spawner on a cell: brings out monsters on a timer or when an action says.

  • kind: 'spawner' — 'spawner'.
  • id: string — Unique id across the dungeon.
  • at: Cell — Its cell.
  • monster: string — The monster kind.
  • every?: number — Seconds between spawns, above 0; default 0: only on a { spawner } action.
  • count?: number — Most it ever brings out, 1 to 10000; default 1.
  • max?: number — Most of its monsters alive at once, 1 to 100; default 1.
  • on?: boolean — Working at the start; default true.
  • facing?: Facing — Which way its monsters face; default south.
  • tag?: string — A tag its monsters carry, for kill triggers.

SpellDef

interface SpellDef

A spell cast from the rune grid.

  • id: string — Unique id.
  • name?: string — A name to show.
  • runes: string[] — The runes that cast it, by name from the dungeon's runes, in any order.
  • energy: number — Energy it costs, 0 to 100000.
  • level?: number — The caster's level it needs, 1 to 1000; default 1.
  • cooldown?: number — Seconds before the caster casts again, 0 to 600; default 1.5.
  • projectile?: ProjectileDef — A missile down the grid (a fireball, a frost bolt).
  • heal?: [number, number] — Hit points restored, [min, max].
  • target?: 'self' | 'party' | 'weakest' — Who a heal reaches: 'self', 'party' or 'weakest' (the default: the living character lowest by share).
  • light?: { radius: number; time: number } — Light around the party: a radius in cells and seconds it lasts.
  • shield?: { protection: number; time: number } — Protection for every character: how much and seconds it lasts.

SpinnerFeature

interface SpinnerFeature

A spinner on a cell: the party arriving on it is turned.

  • kind: 'spinner' — 'spinner'.
  • id: string — Unique id across the dungeon.
  • at: Cell — Its cell.
  • turn?: 1 | 2 | 3 | 'random' — Quarter turns clockwise, 1 to 3, or 'random' (1 to 3, from the run's seed); default 'random'.
  • on?: boolean — On at the start; default true.

StairsFeature

interface StairsFeature

Stairs between floors: walking into the cell goes up or down.

  • kind: 'stairs' — 'stairs'.
  • id: string — Unique id across the dungeon.
  • at: Cell — Its cell.
  • dir: 'up' | 'down' — Up a floor (the one before in the list) or down (the one after).
  • exit: Facing — The side it is entered from and left by: the party walks out of it this way.
  • to?: { floor?: string; stairs?: string } — Where it leads: a floor (default by dir) and the stairs there (default the ones going the other way, nearest this cell).

TeleportBy

type TeleportBy = 'party' | 'monster' | 'item' | 'projectile'

Who a teleporter moves.

TeleporterFeature

interface TeleporterFeature

A teleporter on a cell: what enters it while it is on is moved to to.

  • kind: 'teleporter' — 'teleporter'.
  • id: string — Unique id across the dungeon.
  • at: Cell — Its cell.
  • to: { floor?: string; at: Cell; facing?: Facing } — Where to: a cell, on a floor (default this one), and the party's new facing (default unchanged).
  • on?: boolean — On at the start; default true.
  • by?: TeleportBy[] — What it moves; default all four.

WallFeature

type WallFeature = LeverFeature | ButtonFeature | AlcoveFeature | SconceFeature | LockFeature | InscriptionFeature

The features drawn on a wall face rather than standing in a cell.

ZoneFeature

interface ZoneFeature

A stretch of cells with its own rules: water that slows, puts out torches and hurts.

  • kind: 'zone' — 'zone'.
  • id: string — Unique id across the dungeon.
  • cells?: Cell[] — Its cells.
  • chars?: string — On a grid floor: every cell painted with one of these characters.
  • slow?: number — Multiplies the time a step into or out of it takes, 0.1 to 10; default 1.
  • douse?: boolean — Puts out torches that are not waterproof as the party enters; default false.
  • damage?: number — Damage per second to each character standing in it, 0 to 1000; default 0.
  • quiet?: boolean — Steps in it make no noise; default false.