The pack
gridBombs
function gridBombs(): Pack<{ gridBombs: GridBombsApi }>
Install the renderer-independent grid bombs API. Movement comes from grid-walker's continuous walker.
Helpers
BATTLE_ARENAS
const BATTLE_ARENAS: Readonly<Record<string, readonly string[]>>
Battle arena layouts shipped with the pack (authored maps; ? cells are soft at the match density).
battleItems
function battleItems(): ItemDef[]
Super Bomberman-style battle power-ups (ids are what the arena hides).
battlePreset
function battlePreset(o: BattleOptions = {}): BomberGameConfig
A Super Bomberman-style battle as a configuration.
bombermanPreset
function bombermanPreset(o: BombermanOptions = {}): BomberGameConfig
The 1985 NES Bomberman stage game as a configuration (any field can then be replaced).
botProfile
function botProfile(level: BotLevel): BotProfile
A named bot profile.
createBomberBot
function createBomberBot(profile: BotProfile | BotLevel = "normal", seed = 1): BomberBot
Create a bot with a named level or a custom profile. seed drives its few random choices.
createBomberGame
function createBomberGame(config: BomberGameConfig): BomberGame
Create a rules owner from a configuration (see bombermanPreset and battlePreset).
createBombField
function createBombField(arena: Arena, rules: Partial<BombRules> = {}, traits: Record<string, ItemTrait> = {}): BombField
Create the bomb mechanic for an arena (from resolveArena). traits say how flames treat each item kind.
dangerMap
function dangerMap(field: BombField, o: DangerOptions = {}): DangerMap
Build the danger map of a field now, resolving chain reactions in fuse order.
enemyDecide
function enemyDecide(brain: EnemyBrain, sense: EnemySense, rng: Rng): Dir
Pick a monster's direction at a tile centre. Uses rng in a fixed order, so it is deterministic.
firstStep
function firstStep(from: Cell, to: Cell, blocked: (x: number, y: number) => boolean, limit = 4096): Dir | null
First step of a shortest path (breadth first, up/left/down/right order) or null when unreachable within limit tiles.
nesBomberRules
function nesBomberRules(): BomberRules
NES bomber rules.
nesBombRules
function nesBombRules(): BombRules
NES bomb timings.
nesEnemies
function nesEnemies(): EnemyKind[]
The eight NES monsters. Scores, the slow/normal/fast classes, soft-block passing and intelligence come from the sources in the docs; tile speeds are estimates on a 16-pixel tile at 60 frames per second.
nesItems
function nesItems(): ItemDef[]
The eight NES power-ups and the monster each releases when it (or the exit, while it is the stage's item) is bombed.
nesStages
function nesStages(bonus = true): StageDef[]
The NES stage list: fifty stages from the table, with the ten bonus stages in their places when bonus.
pillarArena
function pillarArena(options: PillarArenaOptions = {}): string[]
The classic Bomberman arena as a map template: a hard border, a hard pillar on every cell with both
coordinates even, ? on every other floor cell (resolve it with a density) and digit starts.
pressureSpiral
function pressureSpiral(cols: number, rows: number): Cell[]
Clockwise spiral of the arena interior from the top-left, the order pressure blocks fall in.
resolveArena
function resolveArena(map: readonly string[], options: ResolveOptions = {}): Arena
Parse an authored string map into an Arena. Rows must all be the same width.
? cells become soft blocks with probability density (seeded); keepClear cells and
cells next to a bomber start (an L of three) are forced clear so nobody starts boxed in.
safeDuring
function safeDuring(map: DangerMap, x: number, y: number, from: number, to: number, margin = 0): boolean
Is a tile free of lethal flame for the whole interval [from, to] seconds from now (with a safety margin)?
stageDifficulty
function stageDifficulty(level: DifficultyLevel): StageDifficulty
Campaign difficulty scaling for a level.
stageIndex
function stageIndex(stages: readonly StageDef[], n: number): number
Index in a stage list of the stage labelled n (bonus stages are skipped).
steer
function steer( walker: GridWalker, held: Dir | null, speed: number, dt: number, walls: (x: number, y: number) => boolean, reach = 0.7, ): boolean
Move a walker for dt seconds while held is pressed. walls(x, y) is true for tiles this actor may
not enter. reach is how far (in tiles, 0.5..1) past the midpoint between two lanes the actor still
slides onto the far lane when the near one is blocked. Returns true when it moved.
untouched
function untouched(map: DangerMap, x: number, y: number): boolean
Is a tile under no known threat at all?
validateBomberGame
function validateBomberGame(c: BomberGameConfig): BomberGameConfig
Validate a configuration; throws with the reason for anything unsupported.
Functions
validateBombRules
function validateBombRules(r: BombRules): BombRules
Validate a full rule set (throws with the field name).
validateBotProfile
function validateBotProfile(p: BotProfile): BotProfile
Validate a profile (throws with the field name).
validateEnemyKind
function validateEnemyKind(k: EnemyKind): EnemyKind
Validate a monster kind.
Classes
BomberBot
class BomberBot
A Bomberman bot. Create with createBomberBot; call BomberBot.think once per frame.
readonly profile: BotProfile— The skill profile in use.constructor(profile: BotProfile | BotLevel = "normal", seed = 1)get state(): BotState— The bot's memory, for debugging or display.think(view: BotView, dt: number): BomberIntent— Decide this frame's intent.dtis the frame length in seconds.snapshot(): BotState— Snapshot of the bot's memory.restore(s: BotState)— Return to a snapshot.
BomberGame
class BomberGame
The rules owner. Create with createBomberGame.
readonly config: BomberGameConfig— The validated configuration.constructor(config: BomberGameConfig)reset(stage = 0)— Start again from the first stage (or round).stagepicks a campaign start stage (0-based).get state(): BomberGameState— A copy of the state.get field(): BombField— The bomb field (read it; do not change it from outside a step).get arena(): Arena— The resolved arena of the current stage or round.botState(id: string): BotState | null— A bot's memory (null for players).enemyKind(id: string): EnemyKind— Monster kind definition.item(id: string): ItemDef | undefined— Item definition.get stageDef(): StageDef | null— The campaign stage definition in play (null in a match).speedOf(id: string): number— A bomber's current speed in tiles per second (with speed-ups and disease).control(id: string, intent: Partial<BomberIntent>)— Set a player bomber's intent for the next frames.bombandactionare presses (consumed once).tick(dt: number)— Advance bydtseconds in whole 60 Hz frames (at most eight per call; the rest is dropped).drain(): BomberEvent[]— Events since the last drain.snapshot(): BomberGameSnapshot— Everything needed to return to this moment.restore(snap: BomberGameSnapshot)— Return to a snapshot.scaledCounts(counts: Record<string, number>): Record<string, number>— Monster counts after difficulty scaling: the total is scaled and rounded, then shared out over the kinds by largest remainder (ties go to the kind listed first), and at least one monster stays.
BombField
class BombField
The bomb mechanic on one arena. Create with createBombField.
readonly rules: BombRules— The rules in force.constructor(arena: Arena, rules: Partial<BombRules> = {}, traits: Record<string, ItemTrait> = {})get state(): BombFieldState— A copy of the whole state.get cols()— Width in tiles.get rows()— Height in tiles.get bombs(): readonly Bomb[]— Live bombs (read-only view; do not mutate).get flames(): readonly Flame[]— Live flames (read-only view).get items(): readonly FieldItem[]— Exposed items (read-only view).get burning(): readonly Burning[]— Burning soft blocks (read-only view).inside(x: number, y: number)— Is the cell inside the arena?tile(x: number, y: number): Tile— The tile at a cell (hardoutside the arena).setTile(x: number, y: number, t: Tile)— Replace a tile (for authored edits, pressure blocks or rebuilt walls).hide(x: number, y: number, kind: string | null)— Hide an item kind under a soft block (revealed when the block burns away).hiddenAt(x: number, y: number): string | null— What a soft block hides, or null.bombAt(x: number, y: number): Bomb | undefined— The bomb resting or sliding on a cell (airborne bombs are on no cell).flameAt(x: number, y: number): Flame | undefined— The flame on a cell, if any.itemAt(x: number, y: number): FieldItem | undefined— The exposed item on a cell, if any.isBurning(x: number, y: number)— Is the cell a soft block that is burning away?countOwned(owner: string)— Bombs an owner has on the board (including airborne ones).blocked(x: number, y: number, mover: Mover = {}): boolean— Can a mover enter this cell? Hard blocks and the outside always block; soft blocks (including burning ones) unlesswallpass; bombs unlessbombpassor the mover is still standing on that bomb.place( owner: string, x: number, y: number, o: { range: number; remote?: boolean; pierce?: boolean; fuse?: number; passers?: readonly string[] }, ): Bomb | null— Place a bomb on a floor tile. Returns null (and changes nothing) when the tile is not floor or already holds a bomb.passersare the actors overlapping the tile now; they may walk off it.detonate(owner: string, mode: "oldest" | "all" = "oldest"): number[]— Trigger remote bombs of an owner:oldestsets off only the oldest one (the NES Detonator),allsets off every one. They explode on the next tick. Returns the ids triggered.defuseRemote(owner: string)— Turn an owner's waiting remote bombs back into fused bombs (e.g. when the owner loses the remote).kick(x: number, y: number, dir: Dir, by: string): boolean— Kick the bomb on a cell: it slidesdiruntil something blocks it. Returns false when it cannot move at all.stop(bombId: number)— Stop a sliding bomb on its nearest tile centre (a "kick stop").punch(x: number, y: number, dir: Dir, by: string, distance = this.rules.punchDistance): boolean— Punch (or throw) the bomb on a celldistancetiles indir; it flies over everything and bounces on one tile at a time while its landing tile is blocked. Its fuse waits while it flies.dropItem(kind: string, x: number, y: number): number | null— Put an exposed item on a floor tile (a dropped or scattered power-up). Returns its id, or null if the tile is taken.takeItem(x: number, y: number): FieldItem | null— Remove and return the exposed item on a cell (a pickup).removeBomb(id: number)— Remove a bomb without exploding it (an owner leaving the game).crush(x: number, y: number)— A falling block lands on a cell: the tile becomes hard, and the bomb, item, flame and hidden item there are removed (Super Bomberman's sudden-death pressure block). Actors on it are the caller's to crush.blastFrom(x: number, y: number, range: number, pierce = false): { cells: Cell[]; bombs: number[] }— The tiles a blast from (x, y) would reach now, without changing anything: the centre, then each arm in up/left/down/right order.stopslists the bombs (by id) the arms would set off.tick(dt: number, ctx: FieldActors = {})— Advance the field bydtseconds (call once per fixed frame).drain(): BombEvent[]— Events since the last drain, oldest first.snapshot(): BombFieldState— Copy of the state for laterrestore.restore(state: BombFieldState)— Return to a snapshot.
Constants
DEFAULT_BOMB_RULES
const DEFAULT_BOMB_RULES: Readonly<BombRules>
Default bomb rules (the NES timings, see the docs for their sources).
DIRS
const DIRS: readonly Dir[]
The four directions in the fixed order every scan uses (deterministic tie-breaking).
FRAME
const FRAME: number
The simulation runs in whole 60 Hz frames.
MAX_ARENA_CELLS
const MAX_ARENA_CELLS: 16384
Largest arena accepted: a resource bound for the per-step flood fills, not a game limit.
OPPOSITE
const OPPOSITE: Readonly<Record<Dir, Dir>>
The direction that undoes each direction.
STEP
const STEP: Readonly<Record<Dir, Readonly<Cell>>>
Unit step for each direction.
Types
Arena
interface Arena
A parsed arena. Legend for string maps:
# hard (indestructible) block, % soft (destructible) block, . or space floor,
? soft with the resolver's probability (floor otherwise), x floor that is always kept clear,
1..9 bomber start N (floor, kept clear), e an enemy start hint (floor),
D a soft block hiding the exit door, P a soft block hiding the stage power-up.
cols: number— Width in tiles.rows: number— Height in tiles.tiles: Tile[]— Row-major tiles,rows * colslong.starts: Cell[]— Bomber starts by index (map digits 1..9 are indexes 0..8).enemyStarts: Cell[]— Authored enemy start hints (e).door: Cell | null— Soft blocks that must hide the exit door (D), if authored.powerUp: Cell | null— Soft block that must hide the stage power-up (P), if authored.
BattleOptions
interface BattleOptions
Options for battlePreset.
players?: number— Bombers, 2..4 on the shipped arenas (more with an authored map that has more starts). Default 4.humans?: number— How many of them are humans (the rest are bots). Default 1.difficulty?: BotLevel— Bot skill: a level for all bots. Defaultnormal.bots?: (BotLevel | BotProfile)[]— Per-bot skill overrides (index 0 is the first bot).arena?: keyof typeof BATTLE_ARENAS | string[]— A shipped arena name or an authored map. Defaultclassic.density?: number— Soft block density. Default 0.7.wins?: number— Round wins needed. Default 3.time?: number— Seconds per round. Default 180.suddenDeathAt?: number | null— Sudden death from this many seconds remaining (null = off). Default 60.items?: Record<string, number>— Item counts hidden per round (merged over the defaults; 0 removes one).startKick?: boolean— Everyone starts with kick. Default false.startRemote?: boolean— Everyone starts with remote bombs. Default false.chainDelay?: number— Seconds between a flame reaching a bomb and that bomb going off. Default 0.1 (a visible ripple).seed?: number— Seed. Default 1993.teams?: "ffa" | "pairs"— Teams (ffafree-for-all, orpairs: 1+3 against 2+4). Defaultffa.
Bomb
interface Bomb
A bomb on the board.
id: number— Stable id (stable rendering key).owner: string— Owner id (whatever the caller uses for actors).x: number— Centre x in tiles (continuous while it slides or flies).y: number— Centre y in tiles.fuse: number— Seconds to go; Infinity for a remote bomb waiting for its trigger.age: number— Seconds the bomb has existed (for pulsing art).remote: boolean— Remote-controlled: no fuse until detonated.range: number— Blast arm length in tiles.pierce: boolean— Blast arms burn through soft blocks instead of stopping at the first.seq: number— Placement order (oldest first); the remote trigger and same-frame explosions use it.passers: string[]— Actors still overlapping the bomb since it was placed: they may walk off it, nobody may walk on.motion: BombMotion | null— Movement, or null when resting on a tile centre.group: number— Blast group this bomb will explode in (set when a flame chains it), 0 for its own new group.
BomberDef
interface BomberDef
A bomber taking part.
id: string— Id (also bomb owner id).team?: string— Team; bombers on a team never hurt each other unlessteamHarm. Default: its own id (free-for-all).control: "player" | "bot"—playerreadsBomberGame.control;botis driven by a BomberBot.bot?: BotLevel | BotProfile— Bot skill (a level or a profile). Defaultnormal.start?: number— Arena start index. Default: its position in the list.
BomberEvent
type BomberEvent = | BombEvent | { /** A stage or round began. */ kind: "begin"; label: string; bonus: boolean } | { /** Play started after the banner. */ kind: "go" } | { /** A bomber died. */ kind: "bomber-died"; id: string; by: string | null; cause: "flame" | "enemy" | "crushed"; x: number; y: number } | { /** A monster died. */ kind: "enemy-died"; id: string; enemy: string; by: string | null; points: number; x: number; y: number } | { /** A bomber took an item. */ kind: "picked"; id: string; item: string; effect: ItemEffect; disease?: Disease } | { /** Monsters were released. */ kind: "released"; enemy: string; count: number; from: "door" | "item" | "timeout" } | { /** The exit door opened (every monster gone). */ kind: "door-open" } | { /** A bomber reached the open exit. */ kind: "stage-clear"; id: string; stage: number } | { /** Lives were added. */ kind: "extra-life"; lives: number } | { /** A campaign ran out of lives. */ kind: "game-over" } | { /** Sudden death began. */ kind: "hurry" } | { /** A pressure block fell. */ kind: "pressure"; x: number; y: number } | { /** A round was decided. */ kind: "round-over"; winner: string | null } | { /** The match was won. */ kind: "match-over"; winner: string } | { /** A disease passed between bombers. */ kind: "infected"; from: string; to: string; disease: Disease }
Things that happened (drain them with BomberGame.drain).
BomberGameConfig
interface BomberGameConfig
A whole game definition: rules, bombers, items, monster kinds, and a campaign or a match.
seed: number— Seed for maps, item placement, monsters and bots.bombs: Partial<BombRules>— Bomb timings and options.rules: BomberRules— Bomber rules.bombers: BomberDef[]— The bombers.items: ItemDef[]— Power-up kinds.enemies: EnemyKind[]— Monster kinds.campaign?: Campaign— Stage structure (exactly one ofcampaignandmatch).match?: Match— Battle structure (exactly one ofcampaignandmatch).
BomberGameSnapshot
interface BomberGameSnapshot
A snapshot of a whole game.
state: BomberGameState— Game state.field: BombFieldState— Bomb field state.arena: Arena— Resolved arena.bots: Record<string, BotState>— Bot memories by bomber id.inputs: Record<string, BomberIntent>— Pending inputs.acc: number— Frame accumulator.
BomberGameState
interface BomberGameState
The game's whole state; plain data.
mode: "campaign" | "match"—campaignormatch.status: "intro" | "playing" | "dying" | "clear" | "round-over" | "match-over" | "game-over"— Phase of play.statusTime: number— Seconds in this status.stage: number— Campaign: stage index (0-based) in the table.loop: number— Campaign: completed loops of the table.bonus: boolean— Campaign: this stage is a bonus stage.label: string— Banner label for the stage or round.round: number— Match: round number (1-based).roundWinner: string | null— Match: winning team of the last round,draw, or null.matchWinner: string | null— Match: winning team of the match, or null.clock: number— Seconds left on the clock (Infinity with no clock).lives: number— Campaign lives left.bombers: BomberState[]— Bombers.enemies: EnemyState[]— Monsters (dying ones stay a moment for their animation).door: Cell | null— The exit door tile (campaign), or null.doorShown: boolean— The door has been uncovered.doorOpen: boolean— The door works (uncovered and no monsters left).powerUp: string | null— The stage's power-up id, or null.flooded: boolean— The time-out flood has happened.hurry: boolean— Sudden death has begun.pressure: number— Pressure blocks dropped so far.pressureWait: number— Seconds to the next pressure block.decide: number— Seconds left before a decided round is scored (match), or -1.nextEnemy: number— Next monster id number.pending: { x: number; y: number; kind: string; count: number; wait: number }[]— Monster releases waiting for a door's flames to die down.groupKills: Record<string, number>— Kills per blast group (for multi-kill scores).released: number[]— Blast groups that have already released monsters from a door or item.rng: number[]— The seeded random stream's state (four words, from the kernel'srng.snapshot()); it advances in place, so a snapshot saves it.frame: number— Frames simulated.
BomberIntent
interface BomberIntent
What a bomber (player or bot) asks for this frame.
move: Dir | null— Direction held, or null to stand still.bomb: boolean— Bomb button pressed this frame.action: boolean— Action button pressed this frame (remote detonate, or punch).
BombermanOptions
interface BombermanOptions
Options for bombermanPreset.
stage?: number— First stage (1-based, counting stages only, not bonus stages). Default 1.lives?: number— Lives. Default 3.seed?: number— Seed. Default 1985.difficulty?: DifficultyLevel | StageDifficulty— Difficulty level or explicit scaling. Defaultarcade.cols?: number— Arena width including the border. Default 31 (the NES stage).rows?: number— Arena height including the border. Default 13.density?: number— Soft block density. Default 0.3.bonus?: boolean— Include the bonus stages. Default true.time?: number— Seconds per stage. Default 200.coop?: number— Extra bots playing co-op alongside the player (0 = classic single player).coopBot?: BotLevel | BotProfile— Skill of co-op bots. Defaultnormal.
BomberRules
interface BomberRules
Rules for bombers.
speed: number— Base speed, tiles per second.speedStep: number— Speed added per speed-up.maxSpeedSteps: number— Most speed-ups that count.maxBombs: number— Most bombs at once.maxRange: number— Longest blast range.start: Loadout— Starting loadout (and what a campaign bomber returns to after a death, plus its kept items).remoteMode: "oldest" | "all"— The remote trigger sets off theoldestbomb (NES) orallof them.touch: number— Contact distance (tiles, per axis) at which a monster kills a bomber.selfHarm: boolean— Do a bomber's own flames hurt it?teamHarm: boolean— Do teammates' flames hurt?cornerReach: number— Corner sliding reach in tiles (0.5..1), seesteer.deathSeconds: number— Seconds a death takes to play out.diseaseSeconds: number— Seconds a skull disease lasts.diseases: Disease[]— Diseases a skull can give.spreadDisease: boolean— A diseased bomber passes the disease to bombers it touches.scatterOnDeath: boolean— A dead bomber's collected power-ups scatter over the arena (battle).
BomberState
interface BomberState extends Loadout
A bomber now.
id: string— Id.team: string— Team.control: "player" | "bot"— Who drives it.alive: boolean— Alive.deadTime: number— Seconds since it died (for the death animation).cause: "flame" | "enemy" | "crushed" | null— How it died.x: number— Centre x in tiles.y: number— Centre y in tiles.facing: Dir— Facing.moving: boolean— Moved this frame.invincible: number— Seconds of invincibility left.disease: { kind: Disease; time: number } | null— Current disease and seconds left, or null.score: number— Score.wins: number— Round wins (match).kills: number— Opponents and monsters killed.picked: string[]— Items picked up this life (scattered on death in a match).walk: GridWalkerState— Walker state (position, heading).
BombEvent
type BombEvent = | { /** A bomb was placed. */ kind: "placed"; bomb: number; owner: string; x: number; y: number } | { /** A bomb exploded: its centre and every tile its arms reached, in order. */ kind: "exploded"; bomb: number; owner: string; x: number; y: number; group: number; cells: Cell[]; /** True when another blast set it off. */ chained: boolean; } | { /** A soft block was hit and starts burning. */ kind: "soft-hit"; x: number; y: number; group: number; owner: string; hidden: string | null } | { /** A burnt soft block disappeared; `item` is what it revealed. */ kind: "revealed"; x: number; y: number; item: string | null } | { /** A blast arm reached an exposed item. */ kind: "item-hit"; item: string; id: number; x: number; y: number; group: number; owner: string; destroyed: boolean } | { /** A bomb started sliding. */ kind: "kicked"; bomb: number; by: string; dir: Dir } | { /** A sliding bomb stopped. */ kind: "stopped"; bomb: number; x: number; y: number } | { /** A bomb was punched into the air. */ kind: "punched"; bomb: number; by: string; dir: Dir } | { /** A flying bomb left one side and re-entered at the other (a discontinuity: snap art). */ kind: "wrapped"; bomb: number } | { /** A flying bomb landed on a blocked tile and bounces on. */ kind: "bounced"; bomb: number; x: number; y: number } | { /** A flying bomb landed. */ kind: "landed"; bomb: number; x: number; y: number } | { /** A tile was crushed by a falling block. */ kind: "crushed"; x: number; y: number; bomb: number | null; item: string | null }
What happened during a tick (drain them with BombField.drain).
BombFieldState
interface BombFieldState
Everything the field owns; plain data.
cols: number— Width in tiles.rows: number— Height in tiles.tiles: Tile[]— Row-major tiles.hidden: (string | null)[]— Row-major: what each soft block hides (an item kind) or null.items: FieldItem[]— Exposed items.bombs: Bomb[]— Bombs, in placement order.flames: Flame[]— Lethal flames.burning: Burning[]— Soft blocks burning away.nextId: number— Next id for bombs and items.seq: number— Placement counter.group: number— Last blast group number.time: number— Seconds simulated.
BombMotion
type BombMotion = | { /** Sliding after a kick, one tile at a time, until something blocks it. */ kind: "slide"; /** Slide direction. */ dir: Dir; /** Tiles per second. */ speed: number; /** Who kicked it. */ by: string; } | { /** Flying after a punch or throw; it cannot explode or be hit while airborne. */ kind: "flight"; /** Flight direction. */ dir: Dir; /** Launch position. */ from: Cell; /** Landing cell. */ to: Cell; /** Seconds flown on this leg. */ t: number; /** Seconds this leg takes. */ duration: number; /** Who punched it. */ by: string; }
How a bomb is moving, if it is.
BombRules
interface BombRules
Timings and options for bombs and blasts.
fuse: number— Seconds from placing to exploding.flameSeconds: number— Seconds a flame stays lethal on its cell.burnSeconds?: number— Seconds a soft block burns before it disappears and reveals what it hid. DefaultflameSeconds.chainDelay: number— Seconds between a flame reaching a bomb and that bomb exploding; 0 chains in the same frame.flameStopsAtItems: boolean— Do flames stop at the first exposed item they destroy? (Super Bomberman: yes.)slideSpeed: number— Kicked bombs slide at this many tiles per second.punchDistance: number— Tiles a punched (or thrown) bomb flies before it tries to land.punchSeconds: number— Seconds a punched bomb spends in the air overpunchDistancetiles (bounces take a share of it per tile).wrapPunch: boolean— Do punched bombs that leave the arena come back in on the opposite side? Otherwise they bounce back.itemsStopSlides: boolean— Do sliding bombs stop in front of exposed items (true) or slide over them (false)?
BotActor
interface BotActor
Another actor as a bot sees it.
id: string— Actor id.x: number— Continuous centre x in tiles.y: number— Continuous centre y in tiles.kind: "bomber" | "enemy"—bomber(another player or bot) orenemy(a monster that kills by touch).team: string— Team id; bombers on the bot's team are allies. Monsters are always hostile.speed: number— Tiles per second.wallpass?: boolean— Can it cross soft blocks (for judging its escape routes).bombpass?: boolean— Can it cross bombs.
BotLevel
type BotLevel = "easy" | "normal" | "arcade"
Named bot levels. arcade is the strongest.
BotProfile
interface BotProfile
Bot difficulty: one profile per skill level, or your own.
think: number— Seconds between full re-plans (reaction time). The flame guard still runs every frame.margin: number— Safety margin in seconds when judging whether a tile will be clear.aggression: number— Chance of bombing when an opponent stands in the blast it would make.trap: boolean— Looks for bombs that leave an opponent no escape and always takes them.hunt: boolean— Walks towards opponents when nothing better is on.items: boolean— Collects power-ups.mistakes: number— Chance per plan of misjudging danger (an imperfect bot); 0 never errs.enemyClearance: number— Tiles to keep between itself and monsters.dig: number— Weight on blowing up soft blocks.commit: number— Seconds a planned target is kept before looking for a better one (stops dithering).refuges: number— Safe tiles that must stay reachable after placing a bomb (more = harder to trap).
BotSelf
interface BotSelf
The bot itself.
id: string— Its id (also the owner id of its bombs).x: number— Continuous centre x in tiles.y: number— Continuous centre y in tiles.team: string— Its team.speed: number— Tiles per second.bombsLeft: number— Bombs it may still place now.range: number— Its blast range.pierce: boolean— Its bombs pierce soft blocks.remote: boolean— Its bombs are remote-controlled.wallpass: boolean— Walks through soft blocks.bombpass: boolean— Walks through bombs.flamepass: boolean— Immune to flames.invincible: number— Seconds of invincibility left.fuse: number— Fuse its new bombs will have (seconds).reversed?: boolean— Its controls are reversed (a skull disease); the bot steers through it.
BotState
interface BotState
A bot's own memory (snapshot-able).
rng: number[]— The seeded random stream's state (four words, from the kernel'srng.snapshot()); it advances in place.wait: number— Seconds until the next full plan.target: Cell | null— Current target tile, if any.reason: "escape" | "item" | "goal" | "hunt" | "dig" | "idle"— Why it is going there.held: number— Seconds the target has been held.move: Dir | null— The intent being repeated between plans.path: Cell[]— The planned path (tiles from the bot's tile to the target) followed between plans.
BotView
interface BotView
Everything a bot reads. A game builds one per frame; a different grid game can build its own.
field: BombField— The bomb field.self: BotSelf— The bot.actors: readonly BotActor[]— Every other live actor.goal?: Cell | null— A tile to walk to when there is nothing better to do (an open exit door), or null.itemValue?: (kind: string) => number— How much the bot wants an exposed item kind (0 ignore, negative avoid and never bomb). Default: 1 for everything butexit.hazards?: readonly { x: number; y: number; at: number }[]— Tiles that become deadly for good at a known time (falling pressure blocks): seconds from now.
Burning
interface Burning
A soft block in the middle of burning away.
x: number— Tile x.y: number— Tile y.time: number— Seconds left.group: number— Blast group that burned it.owner: string— Owner of the bomb that burned it.
Campaign
interface Campaign
The single-player (or co-op) stage structure.
stages: StageDef[]— The stages in order; the campaign loops back to the first after the last whenloop.map: string[]— Map template for stages without their own (?cells become soft blocks atdensity).density: number— Soft block density for?cells.time: number— Seconds on the clock per stage (0 = no clock).bonusTime: number— Seconds a bonus stage lasts.bonusPopulation: number— Monsters kept on the board during a bonus stage.timeout: { kind: string; count: number } | null— When the clock runs out: every monster is removed andcountofkindreleased (null: nothing happens).release: number— Monsters released when the exposed exit door or the stage item is bombed.releaseKind: string— Monster kind released when no item names one.exit: string— Item id used for the exit door.lives: number— Lives at the start.extraLifePerStage: number— Lives added on clearing a stage.loop: boolean— Loop back to stage 1 after the last, keeping power-ups.enemyDistance: number— Monsters start at least this far (Manhattan tiles) from every bomber start.introSeconds: number— Seconds a stage's banner shows before play.clearSeconds: number— Seconds between reaching the exit and the next stage.chainScore: "double" | "none"— Multi-kill scoring in one blast group:doubledoubles each further monster,nonescores each at face value.difficulty: StageDifficulty— Difficulty scaling.
Cell
interface Cell
A tile coordinate; tile centres are integers and one tile is one model unit.
x: number— Column, 0 at the left.y: number— Row, 0 at the top.
DangerMap
interface DangerMap
Seconds-until-lethal and seconds-until-safe for every tile.
cols: number— Width in tiles.rows: number— Height in tiles.start: Float64Array— Row-major seconds until the tile is next lethal (0 = burning now, Infinity = no known threat).end: Float64Array— Row-major seconds until that threat has passed (0 when there is none).
DangerOptions
interface DangerOptions
Options for dangerMap.
self?: string— Seconds to assume before a remote bomb (no fuse) goes off. Default: Infinity forself's own remote bombs (it decides when) andremoteGuessfor everyone else's.remoteGuess?: number— Seconds to assume for other owners' remote bombs. Default 0.6.selfRemoteGuess?: number— Seconds to assume forself's own remote bombs. Default Infinity (it decides when they go off).extra?: readonly HypotheticalBomb[]— Extra bombs to imagine on the board.
DifficultyLevel
type DifficultyLevel = "easy" | "normal" | "arcade"
Named campaign difficulty. arcade is the original tables.
Dir
type Dir = GridDirection
One of the four grid directions (the same names grid-walker uses).
Disease
type Disease = "slow" | "fast" | "reverse" | "diarrhea" | "constipation" | "short-fuse" | "low-power"
A Super Bomberman skull disease.
EnemyBrain
interface EnemyBrain
How a monster decides where to go at each tile centre.
turn: number— Chance per tile centre of taking a random open turn even though the way ahead is open.chase: number— Chance per tile centre of heading for a bomber that is withinrange.range: number— How near (Manhattan tiles) a bomber must be to be chased.path: boolean— Chase along the shortest path (true) or just towards the bomber (false; it gets stuck behind walls).evade: boolean— Never steps onto a tile a bomb is about to burn.axis?: "x" | "y"— Prefers this axis when it picks a direction at random (the NES Dahl drifts left and right).
EnemyKind
interface EnemyKind
A monster kind: plain data, so a game can add its own.
id: string— Kind id (ballom,onil...).score: number— Points for killing one.speed: number— Tiles per second.wallpass: boolean— Walks through soft blocks (and dies if one it is inside is blasted).bombpass?: boolean— Walks through bombs. Default false.brain: EnemyBrain— Its decision making.
EnemySense
interface EnemySense
What a monster's brain can see at a decision point.
at: Cell— The tile centre it has reached.dir: Dir— Its heading.blocked: (x: number, y: number) => boolean— Tiles this monster may not enter.targets: readonly Cell[]— Bombers it can chase (nearest is used).danger: DangerMap | null— The danger map, needed whenbrain.evadeis set.speed: number— Its speed in tiles per second (for danger timing).chaseScale: number— Scale onchase(difficulty).rangeScale: number— Scale onrange(difficulty).
EnemyState
interface EnemyState
A monster now.
id: string— Stable id.kind: string— Kind id.x: number— Centre x in tiles.y: number— Centre y in tiles.dir: Dir— Heading.alive: boolean— Alive (dying monsters are not).dying: number— Seconds since it died, or -1 while alive.points: number— Points it scored when it died (0 alive).shield: number— Seconds of immunity to flames left (fresh from a door).walk: GridWalkerState— Walker state.
FieldActors
interface FieldActors
Where actors stand, so bombs know who overlaps them and where slides must stop.
actors?: readonly { id: string; x: number; y: number }[]— Live actors' continuous centres.
FieldItem
interface FieldItem
An exposed item lying on a floor tile (a power-up panel, an exit door, a skull ...).
id: number— Stable id.kind: string— Item kind (the caller's vocabulary;exitis not special here).x: number— Tile x.y: number— Tile y.
Flame
interface Flame
A lethal flame on one tile.
x: number— Tile x.y: number— Tile y.time: number— Seconds left.total: number— Seconds it lasts in total.group: number— Blast group: one bomb plus every bomb it chained. Used for kill attribution and multi-kill scores.owner: string— Owner of the bomb whose arm laid this flame.shape: "centre" | "arm" | "end"— For art: the bomb's tile, a middle piece of an arm, or the tip of an arm.dir: Dir | null— Arm direction (null for the centre).
GridBombsApi
type GridBombsApi = typeof api
game.gridBombs: the bomb field, bots, monsters, the rules owner and the Bomberman presets.
HypotheticalBomb
interface HypotheticalBomb
A bomb that does not exist yet, for "what if I place one here?" questions.
x: number— Tile x.y: number— Tile y.range: number— Blast arm length.pierce?: boolean— Burns through soft blocks.fuse: number— Seconds until it explodes.
ItemDef
interface ItemDef
A power-up kind.
id: string— Item id (also the kind the bomb field reports).effect: ItemEffect— Its effect.amount?: number— Steps added bybomb,fireandspeed. Default 1.seconds?: number— Seconds for timed effects (invincible). Default 30.keepOnDeath?: boolean— Campaign: kept when the bomber loses a life. Default true for bomb/fire/speed/life, false otherwise.burnable?: boolean— Destroyed by blasts. Default true.spawns?: string— Campaign: the monster kind released when this item, or the exit while this is the stage's item, is bombed.
ItemEffect
type ItemEffect = | "bomb" | "fire" | "full-fire" | "speed" | "wallpass" | "remote" | "bombpass" | "flamepass" | "invincible" | "kick" | "punch" | "pierce" | "skull" | "life"
What a power-up does when picked up.
ItemTrait
interface ItemTrait
Per-kind behaviour of exposed items under flames.
burnable?: boolean— Destroyed by a blast arm. Default true.blocksFlame?: boolean— Stops a blast arm (in addition toflameStopsAtItems). Default:flameStopsAtItemsfor burnable items, false otherwise.
Loadout
interface Loadout
A bomber's abilities (also used as the starting loadout).
bombs: number— Bombs at once.range: number— Blast range in tiles.speedSteps: number— Speed-up steps collected.wallpass: boolean— Walks through soft blocks.bombpass: boolean— Walks through bombs.flamepass: boolean— Immune to flames.remote: boolean— Bombs wait for the action button.kick: boolean— Walking into a bomb kicks it.punch: boolean— The action button punches the bomb in front.pierce: boolean— Blasts burn through soft blocks.
Match
interface Match
The battle structure.
map: string[]— Map template (?cells become soft blocks atdensity); digits are bomber starts.density: number— Soft block density.items: Record<string, number>— Items hidden under soft blocks each round, by item id.time: number— Seconds per round (0 = no clock).suddenDeath: { at: number; interval: number } | null— Pressure blocks spiral in from the edge fromatseconds remaining, one everyintervalseconds; null = off.wins: number— Round wins needed to take the match.drawWindow: number— Seconds to wait after a round is decided before scoring it (both last bombers dying = a draw).resultSeconds: number— Seconds the round result shows.introSeconds: number— Seconds the round banner shows before play.enemies?: Record<string, number>— Optional monsters in battle too, by kind id.
Mover
interface Mover
Who is asking whether a tile is blocked.
id?: string— Actor id (for the bomb-passer rule).wallpass?: boolean— Walks through soft blocks.bombpass?: boolean— Walks through bombs.
PillarArenaOptions
interface PillarArenaOptions
Options for pillarArena.
cols?: number— Width in tiles including the border; odd keeps the pillar grid symmetric. Default 15.rows?: number— Height in tiles including the border. Default 13.starts?: readonly Cell[] | "corners" | "top-left"— Bomber starts, orcornersfor up to four corner starts,top-leftfor the stage-mode start. Defaultcorners.players?: number— How many corner starts whenstartsiscorners(1..4). Default 4.pillars?: boolean— Indestructible pillar every second cell (the classic grid). Default true.
ResolveOptions
interface ResolveOptions
Options for resolveArena: how ? cells are decided.
density?: number— Probability that a?cell becomes a soft block. Default 0.6.seed?: number— Seed for the decisions. Default 1.keepClear?: readonly Cell[]— Extra cells to force to floor (e.g. bomber starts and the cells beside them).
StageDef
interface StageDef
One stage of a campaign.
label?: string— Label shown in the stage banner. Default: its number.enemies: Record<string, number>— Monster counts by kind id.powerUp?: string | null— Item id hidden under one soft block, or null.bonus?: boolean— A bonus stage: invincible, open arena, monsters ofbonusKindkeep coming until the clock runs out.bonusKind?: string— Monster kind of a bonus stage.map?: string[]— An authored map for this stage (else the campaign's).
StageDifficulty
interface StageDifficulty
Difficulty scaling of a campaign. arcadeDifficulty (all 1s) plays the stage table as authored.
population: number— Multiplies every monster count (rounded; at least one monster stays).enemySpeed: number— Multiplies monster speeds.chase: number— Multiplies the monsters' chase chance and range.flood: number— Multiplies the time-out flood and the exit/item release counts (rounded, at least 1).time: number— Multiplies the clock.
Tile
type Tile = "floor" | "hard" | "soft"
What occupies a tile before any bombs or actors.


