The pack
digCombat
function digCombat(): Pack<{ digCombat: DigCombatApi }>
Install the renderer-independent dig-combat rules. The terrain is an excavation field, so that pack is composed first.
Helpers
createDigCombat
function createDigCombat(config: DigCombatConfig): DigCombat
Build an underground-combat game. Throws a readable error for an unsupported configuration.
deepMinePreset
function deepMinePreset(o: DeepMineOptions = {}): DigCombatConfig
A materially different configuration of the same rules: a bigger seeded mine with more strata and a steeper depth table, three-pump harpoon, more rocks, both-side escape, faster speed-ups and generated rounds.
DIG_DIFFICULTY
const DIG_DIFFICULTY: Readonly<Record<DigDifficulty, Readonly<DifficultyScale>>>
The Easy / Normal / Arcade scaling tables. Arcade is the original game.
DIG_DUG_VEGETABLES
const DIG_DUG_VEGETABLES: ReadonlyArray<{ kind: string; score: number }>
Vegetables by round (the source's FRUITAB: the last entry repeats).
digDifficulty
function digDifficulty(d: DigDifficulty | DifficultyScale = "arcade"): DifficultyScale
Resolve a difficulty name or explicit scale into a scale.
digDugEnemies
function digDugEnemies(playerSpeed = 3.25): Record<string, EnemyKindDef>
Dig Dug's enemy kinds. Speeds are from the source's SPEEDTAB duty cycles against the player's pace.
digDugPreset
function digDugPreset(o: DigDugOptions = {}): DigCombatConfig
Dig Dug (Namco 1982): the arcade's rounds, enemies, harpoon and pump, rocks, vegetables, escape and scoring.
digDugRounds
function digDugRounds(): DigRound[]
The fifteen Dig Dug rounds decoded from the rack tables (rounds 16+ repeat 12-15).
generateDigRound
function generateDigRound(g: DigGeneration, seed = 1): DigRound
A seeded round in Dig Dug's style for any field size: one short tunnel per enemy (or shared), buried rocks that start supported, a central start tunnel and an optional surface row. Deterministic from the seed.
mrDoEnemies
function mrDoEnemies(): Record<string, EnemyKindDef>
Mr. Do!'s monsters: creeps that turn into diggers, Alphamonsters and the blue apple-eaters.
mrDoPreset
function mrDoPreset(o: MrDoOptions = {}): DigCombatConfig
Mr. Do! (Universal 1982): cherries, apples, the power ball, the nest and its food, EXTRA, the diamond.
mrDoScene
function mrDoScene(scene: number, o: MrDoSceneOptions = {}): DigRound
One Mr. Do! scene (1-based): number-shaped tunnels, cherry clusters, apples that start supported, the nest.
roundMarkers
function roundMarkers(round: number): { big: number; small: number }
Round markers as the arcade shows them: one big flower per ten rounds, one small flower per remaining round.
Classes
DigCombat
class DigCombat
A complete underground-combat game. Create one with createDigCombat. Deterministic: the same config and
inputs give the same game; snapshot/restore round-trip it.
readonly config: DigCombatConfig— The configuration (a private copy).readonly scale: DifficultyScale— The resolved difficulty scale.readonly timings: DigTimings— Resolved lifecycle timings.constructor(config: DigCombatConfig)reset(): void— Start a new game from the configured start round.get state(): DigState— A deep copy of the game state.get field(): Excavation— The excavation field of the current round (read it to draw the earth; do not drive it directly).get roundDef(): DigRound— The authored round being played.roundIndex(round: number): number— The round index used for a round number (rounds after the last loop fromloopFrom).get remaining(): number— Enemies still in play (not killed, crushed or escaped).drain(): DigEvent[]— Take the events since the last drain.snapshot(): DigSnapshot— A complete serializable snapshot.restore(snap: DigSnapshot): void— Restore a snapshot taken from a game with the same config.tick(dt: number, input: DigInput): void— Advance the game bydtseconds with the player's input.
Constants
DIG_DUG_COLS
const DIG_DUG_COLS: 14
Dig Dug's field: 14 columns; row 0 is the surface, rows 1-14 are earth.
DIG_DUG_ROWS
const DIG_DUG_ROWS: 15
Dig Dug's field rows (surface plus fourteen rows of earth).
MR_DO_COLS
const MR_DO_COLS: 12
Mr. Do!'s field: 12 columns by 13 rows (no surface row).
MR_DO_ROWS
const MR_DO_ROWS: 13
Mr. Do!'s field rows.
Types
BallDef
interface BallDef
The bouncing power ball (Mr. Do!): bounces through tunnels until it kills or is caught.
kind: "ball"— Discriminator.speed: number— Speed in cells per second.recharge: number[]— Seconds before the ball reforms after a kill, per use (the last entry repeats).hitRadius: number— Kill distance in cells.catchRadius: number— Catch distance in cells (picking a missed ball back up).score?: number— Points per kill (overrides the enemy's score).
BallState
interface BallState
The power ball.
phase: "held" | "flying" | "recharging"— What it is doing.x: number— Position.y: number— Position.vx: number— Velocity.vy: number— Velocity.timer: number— Seconds in flight, or seconds left recharging.uses: number— Kills this round (the recharge grows with them).
CherryDef
interface CherryDef
Cherries (Mr. Do!): score per cherry and a bonus for a cluster eaten without a pause.
kind?: string— Item kind treated as a cherry. Default "cherry".score: number— Points per cherry.streak: number— Cherries in a row for the bonus.streakBonus: number— Bonus points.gapSeconds: number— Longest pause (seconds) that keeps a streak going.
DeepMineOptions
interface DeepMineOptions
Options for the generated deep-mine variant.
cols?: number— Columns. Default 20.rows?: number— Rows including the surface. Default 20.strata?: number— Strata count (evenly spaced). Default 6.pookas?: number— Pookas in round 1 (one more every other round, to a cap). Default 3.fygars?: number— Fygars in round 1. Default 2.maxEnemies?: number— Most enemies a round may have. Default 12.rocks?: number— Rocks per round. Default 6.pumps?: number— Pumps to pop. Default 3.difficulty?: DigDifficulty | DifficultyScale— Difficulty. Default "normal".lives?: number— Lives. Default 4.seed?: number— Seed. Default 7.roundCount?: number— Rounds to generate before looping. Default 12.
DiamondDef
interface DiamondDef
The diamond (Mr. Do!): a broken apple sometimes reveals one.
chance: number— Chance per broken object.fromRound: number— First round it can appear.score: number— Points.
DifficultyScale
interface DifficultyScale
Difficulty and population scaling, applied on top of the authored tables.
enemySpeed: number— Multiplier on every enemy speed.ghostRate: number— Multiplier on the ghost meter's fill rate (how often enemies ghost through the earth).fireRate: number— Multiplier on fire-breathing frequency.maxEnemies: number— Most enemies a round starts with (the first N authored); 0 means no cap.transformRate: number— Multiplier on how often monsters turn into diggers.spawnInterval: number— Multiplier on the nest's spawn interval (larger is slower).maxGhosts: number— Most ghosts at once.aggression: number— Multiplier on the chance an enemy takes the tunnel route to the player.
DigAI
interface DigAI
Enemy movement intelligence.
chase: number— Chance per decision of taking the tunnel route to the player when there is one.ghostMeter: number— Ghost meter threshold: when the shared meter is full, the next enemy that cannot reach the player along tunnels turns into eyes (and the meter empties).ghostBase: number— Meter filled per second.ghostPerRound: number— Extra meter per second per round.restBonus: number— Extra meter per second while the player stands still.ghostMinSeconds: number— Minimum seconds as a ghost.ghostMaxSeconds: number— After this long a ghost lands in any open cell.ghostDelay: number— Seconds after the round starts before anyone may ghost.ghostKeepAway?: number— Ghosts never land closer than this to the player. Default 1.5 cells.
DigCombatApi
type DigCombatApi = typeof api
game.digCombat: underground combat rules (createDigCombat), the Dig Dug and Mr. Do! presets and the round generator.
DigCombatConfig
interface DigCombatConfig
A complete underground-combat game. Every count, table and timing is data.
field: { subdivisions?: number; tunnelWidth?: number; strata?: number[]; legend?: Record<string, Terrain> }— Field resolution and strata (shared by every round).rounds: DigRound[]— Rounds in order.loopFrom?: number— After the last round, continue from this index (0-based). Default the last round.player: { start: Cell; speed: number; digFactor?: number; pushes?: boolean; direction?: Direction; /** * Cornering window in cells (0..0.49) either side of a turn line: a perpendicular turn pressed this close to * a cell centre is taken at that centre at once (sliding onto it) instead of after the next whole cell. * Reversal is always immediate. Default 0 (centre-only turns). */ turnWindow?: number; }— The player.enemies: Record<string, EnemyKindDef>— Enemy kinds by name.objectKinds?: Record<string, DigObjectKind>— Loose object kinds by name.weapon: HarpoonDef | BallDef | null— The weapon, or null for none (a pure digging game).ai: DigAI— Enemy AI.vegetable?: VegetableDef— The bonus vegetable.nest?: NestDef— The monster nest.cherries?: CherryDef— Cherries.extra?: ExtraDef— EXTRA letters.escape?: EscapeDef— Last-enemy escape.speedUp?: { fromRound: number; remaining: number }[]— Speed-up thresholds: fromfromRound, enemies go fast when no more thanremainingare left.diamond?: DiamondDef— The diamond.digScore?: { points: number; per: number }— Points for digging fresh earth:pointsperpercells dug.clearWhen: ("enemies" | "cherries" | "extra" | "diamond")[]— Ways to clear a round.lives: number— Lives including the one in play.extraLives?: { at: number[]; every: number } | null— Extra lives at each score inat(ascending), then everyeverypoints after the last (0: no more). Null for none.difficulty?: DigDifficulty | DifficultyScale— Difficulty preset or explicit scaling. Default "arcade".startRound?: number— Starting round (1-based). Default 1.seed?: number— Seed. Default 1.timings?: Partial<DigTimings>— Lifecycle timings.touchRadius?: number— Player/enemy contact distance in cells. Default 0.6.resetOnDeath?: boolean— Enemies return to their start positions after the player dies. Default true.
DigDifficulty
type DigDifficulty = "easy" | "normal" | "arcade"
Named difficulty presets. arcade is the original tables; normal (the gallery default) and easy thin and slow the opposition.
DigDugOptions
interface DigDugOptions
Options for the Dig Dug preset.
difficulty?: DigDifficulty | DifficultyScale— Difficulty preset or scale. Default "normal".lives?: number— Lives. Default 3.startRound?: number— Starting round. Default 1.seed?: number— Seed. Default 1.playerSpeed?: number— Player speed (cells per second). Default 3.25.pumps?: number— Pumps to pop (including the hit). Default 4.harpoonRange?: number— Harpoon reach in cells. Default 2.75.intro?: boolean— Walk in from the surface at the start of each round. Default true.turnWindow?: number— The player's cornering window in cells (seeDigCombatConfig.player.turnWindow). Default 0.4.
DigEvent
type DigEvent = | { kind: "round-start"; round: number } | { kind: "playing" } | { kind: "dig"; score: number } | { kind: "harpoon"; direction: Direction } | { kind: "hit"; enemy: string } | { kind: "pump"; enemy: string; stage: number } | { kind: "pop"; enemy: string; score: number; x: number; y: number } | { kind: "deflate"; enemy: string; stage: number } | { kind: "ghost"; enemy: string } | { kind: "materialise"; enemy: string } | { kind: "fire"; enemy: string } | { kind: "fall"; object: string } | { kind: "crush"; object: string; enemies: string[]; player: boolean; score: number; x: number; y: number } | { kind: "vegetable"; item: string; vegetable: string } | { kind: "bonus"; what: string; score: number; x: number; y: number } | { kind: "speed-up" } | { kind: "escape"; enemy: string } | { kind: "escaped"; enemy: string } | { kind: "throw" } | { kind: "ball-kill"; enemy: string; score: number; x: number; y: number } | { kind: "catch-ball" } | { kind: "cherry"; score: number; streak: number } | { kind: "spawn"; enemy: string; enemyKind: string } | { kind: "transform"; enemy: string; into: string } | { kind: "eat"; enemy: string; object: string } | { kind: "food"; score: number } | { kind: "alpha"; enemy: string; letter: string } | { kind: "letter"; letter: string; index: number } | { kind: "diamond"; item: string } | { kind: "death"; cause: "enemy" | "fire" | "crush" } | { kind: "extra-life"; lives: number } | { kind: "clear"; by: "enemies" | "cherries" | "extra" | "diamond" } | { kind: "game-over"; score: number }
Something that happened. Drain them with drain().
DigGeneration
interface DigGeneration
Parameters for a generated digging round.
cols: number— Columns (5..64).rows: number— Rows including the surface row (5..64).enemies: Record<string, number>— Enemies by kind.objects: number— Rocks (or apples) to bury.objectKind?: string— Object kind. Default "rock".tunnelLength?: number— Tunnel length in cells. Default 3.player?: Cell— Player start. Default the centre.intro?: boolean— Walk in from the surface. Default false.clusters?: number— Collectible clusters (2 x 4 cherries) to bury. Default 0.
DigInput
interface DigInput
Player input for one tick.
move: Direction | null— Held direction, or null.fire: boolean— Fire/pump button held.
DigObjectKind
interface DigObjectKind extends LooseObjectKind
A loose object kind with crush scoring.
crushScores: number[]— Points for crushing 1, 2, 3 ... enemies with one fall (the last entry repeats).
DigRound
interface DigRound
One round (or level, scene, rack).
map: string[]— Terrain map for the excavation field (its legend).tunnels?: TunnelSpec[]— Straight tunnels carved at start.enemies: { kind: string; at: Cell; direction?: Direction }[]— Enemies present at the start.objects?: { kind: string; at: Cell }[]— Loose objects.items?: { kind: string; at: Cell; group?: string }[]— Collectibles (cherries).player?: Cell— Player start. Default:player.start.intro?: Cell[]— Walk-in waypoints from the first to the start (the player digs its way in).nest?: { at: Cell; count: number }— The nest cell and how many monsters it releases.palette?: number— Presentation hint (palette index).
DigSnapshot
interface DigSnapshot
A complete snapshot of a dig-combat game.
state: DigState— Rules state.field: ExcavationSnapshot— The field.random: RngState— The kernel generator's state (four words, fromrng.snapshot()), so the replay draws the same numbers.
DigState
interface DigState
Complete serializable game state (the field's own state is in the snapshot).
status: DigStatus— Lifecycle.statusTime: number— Seconds in the current status.round: number— Round number (1-based).roundIndex: number— Index intorounds.score: number— Score.lives: number— Lives including the one in play.nextLife: number— Next extra-life score, or 0 for none.player: { x: number; y: number; direction: Direction; moving: boolean; digging: boolean; pumping: boolean; alive: boolean; still: number; introStep: number }— The player.enemies: EnemyState[]— Enemies, including ones just killed (shown briefly).flames: FlameState[]— Flames.harpoon: HarpoonState | null— The harpoon (when the weapon is one).ball: BallState | null— The ball (when the weapon is one).dropped: number— Objects dropped this round.vegetable: { phase: "waiting" | "pending" | "showing" | "done"; kind: string; score: number; timer: number }— The vegetable: pending (timeruntil it shows), showing, or done.fast: boolean— Enemies are in the sped-up state.ghostMeter: number— Ghost meter.nest: { at: Cell; left: number; timer: number; food: "none" | "out" | "eaten" } | null— The nest: monsters left to release, release timer, whether the food is out or eaten.frozen: boolean— Creeps frozen by the food.summons: { alpha: string; others: string[] } | null— Monsters summoned by the food: the Alphamonster's id ("" if none) and the others.queue: { kind: string; letter: string; role: "alpha" | "summon"; at: Cell; delay: number }[]— Monsters waiting to appear (one at a time, never on top of the player).extra: { got: boolean[]; current: number; timer: number; nextScore: number } | null— EXTRA progress.streak: { count: number; group: string; since: number }— Cherry streak.diamond: string— The diamond is out (its item id) or "".clearedBy: "" | "enemies" | "cherries" | "extra" | "diamond"— How the last round was cleared ("" while playing).popups: Popup[]— Scores shown in the field.digCredit: number— Fresh digging accumulated towards the next dig score.serial: number— Id counter.roundTime: number— Seconds played this round.deathCause: "" | "enemy" | "fire" | "crush"— What killed the player last ("" while alive).
DigStatus
type DigStatus = "intro" | "ready" | "playing" | "dying" | "clear" | "game-over"
Lifecycle of the game.
DigTimings
interface DigTimings
Seconds of the round lifecycle.
readySeconds: number— READY before play (after a walk-in, or a lost life).deathSeconds: number— From a death to the next READY.clearSeconds: number— From a clear to the next round.
EnemyKindDef
interface EnemyKindDef
An enemy kind.
speed: number— Speed in tunnels.fastSpeed?: number— Speed once the round speeds up (default speed x 1.25).ghostSpeed?: number— Speed as ghost eyes through the earth (default speed x 0.4).digSpeed?: number— Speed while digging as a digger (default speed x 0.7).ghosts?: boolean— May ghost through earth to reach the player. Default true.fire?: FireDef— Fire breath.score: number | number[]— Points for a weapon kill: one value, or one per stratum (deeper strata later in the list).horizontalMultiplier?: number— Score multiplier when killed by a horizontal harpoon (Fygar x2). Default 1.eatsObjects?: boolean— Eats loose objects it walks into (Mr. Do!'s Alphamonsters and blue monsters eat apples).pushes?: boolean— Pushes pushable objects.transform?: { into: string; every: [number, number]; seconds: number }— Periodically becomes another kind for a while (a creep turning into a digger).digs?: boolean— Digs through earth towards the player instead of following tunnels (a digger).eatsItems?: boolean— Eats collectibles it passes (a digger eating cherries).speedPerRound?: number— Fraction of speed added per round after the first. Default 0.maxSpeedScale?: number— Cap on the per-round speed scale. Default 1.5.freezable?: boolean— Frozen by the nest's bonus food. Default false.
EnemyPhase
type EnemyPhase = "walk" | "ghost" | "inflated" | "stunned" | "windup" | "fire" | "digger" | "frozen" | "escaping" | "popped" | "crushed" | "killed" | "escaped"
What an enemy is doing.
EnemyState
interface EnemyState
Serializable enemy state.
id: string— Unique id (also the excavation body id).kind: string— Current kind (changes while transformed).baseKind: string— Authored kind.x: number— Position.y: number— Position.direction: Direction— Facing.phase: EnemyPhase— What it is doing.inflate: number— Inflation stage (0 = normal).timer: number— Phase timer (windup, flame, stun, pop, transform).fireIn: number— Seconds to the next fire breath.transformIn: number— Seconds to the next transformation.sincePump: number— Seconds since the last pump.home: Cell— Spawn cell (reset target).letter: string— Letter carried by an Alphamonster, or "".escapeLeg: number— Escape leg: 0 rising, 1 walking to the edge, 2 leaving.pendingGhost: boolean— Ghost decision pending (applied after the field step).
EscapeDef
interface EscapeDef
The last enemy's escape (Dig Dug).
remaining: number— Escape starts when this many enemies remain.row: number— The surface row it escapes along.side: "left" | "right" | "nearest"— Which edge it leaves by.
ExtraDef
interface ExtraDef
EXTRA letters (Mr. Do!): Alphamonsters carry letters; collect them all for an extra life.
letters: string— The word.everyScore: number— An Alphamonster appears each time the score passes a multiple of this.cycleSeconds: number— Seconds per highlighted letter as the display cycles.kind: string— Enemy kind of the Alphamonster.spawn: Cell— Where Alphamonsters appear.extraLife?: boolean— Completing the word awards a life. Default true.
FireDef
interface FireDef
A fire breath: the breather stops, flashes, then breathes a flame that passes through earth.
range: number— Flame reach in cells from the breather's centre.windup: number— Seconds standing still (flashing) before the flame.seconds: number— Seconds the flame lasts (it grows to full length over the first third).interval: [number, number]— Seeded seconds between breaths [min, max] (divided by the difficulty's fireRate).horizontalOnly?: boolean— Breathe only while moving horizontally (Dig Dug's Fygar). Default true.
FlameState
interface FlameState
A flame in the field.
owner: string— Breather id.x: number— Origin (the breather's centre).y: number— Row.direction: Direction— Direction.length: number— Current reach in cells.timer: number— Seconds left.
HarpoonDef
interface HarpoonDef
The harpoon and air pump (Dig Dug): attaches, inflates over several pumps, deflates when released.
kind: "harpoon"— Discriminator.range: number— Reach in cells.speed: number— Extension speed in cells per second.pumps: number— Pumps to pop, counting the hit.pumpInterval: number— Shortest time between counted presses.holdInterval: number— Pump repeat while the button is held.deflateSeconds: number— Seconds without a pump before one stage deflates.releaseSeconds: number— Seconds without a pump before the harpoon lets go.recoverSeconds: number— Seconds a fully deflated enemy stays stunned.popSeconds: number— Seconds the popped enemy stays on screen.
HarpoonState
interface HarpoonState
The harpoon.
phase: "idle" | "extending" | "attached"— What it is doing.direction: Direction— Direction thrown.length: number— Current length in cells.target: string— Attached enemy id.sincePump: number— Seconds since the last pump.held: number— Seconds the button has been held while attached.
MrDoOptions
interface MrDoOptions extends MrDoSceneOptions
Options for the Mr. Do! preset.
difficulty?: DigDifficulty | DifficultyScale— Difficulty preset or scale. Default "normal".lives?: number— Lives. Default 3.startRound?: number— Starting scene. Default 1.seed?: number— Seed. Default 1.recharge?: number[]— Seconds before the ball reforms after each kill (the last repeats).turnWindow?: number— The player's cornering window in cells (seeDigCombatConfig.player.turnWindow). Default 0.4.
MrDoSceneOptions
interface MrDoSceneOptions
Options for a Mr. Do! scene.
clusters?: number— Cherry clusters (2 x 4). Default 4.apples?: number— Apples. Default 5.creeps?: number— Monsters the nest releases. Default 6 + one every two scenes, to 10.
NestDef
interface NestDef
The monster nest (Mr. Do!): releases monsters one by one, then turns into a bonus food.
interval: number— Seconds between releases.kind: string— Kind released.foodScores: number[]— Points for the food, per round (the last entry repeats).summons: { kind: string; count: number }[]— Monsters summoned by eating the food (besides the Alphamonster whenextrais set).
Popup
interface Popup
A score shown where it was earned.
id: number— Stable id.score: number— Points.x: number— Where.y: number— Where.timer: number— Seconds left.
VegetableDef
interface VegetableDef
The bonus vegetable: appears after N objects have been dropped in a round.
afterObjects: number— Objects dropped before it appears.at: Cell— Where it appears.delay: number— Delay after the triggering drop.seconds: number— Seconds it stays.table: { kind: string; score: number }[]— Kind and points per round (round N uses entry N-1; the last repeats).


