Phaser AE

Segmented shooter

Pro packv3.0.0-32DArcade

The rules of a field shooter where a long chain of segments snakes down through a field of obstacles towards the player, and every hit splits it in two. The chains, the field, the hazards, the gun, the scoring and the wave cycle are all here, as one definition your game plays and draws.

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

Released October 14, 2026 · updated October 20, 2026

Segmented shooter: 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

segmentedShooter

function segmentedShooter(): Pack<{ segmentedShooter: typeof api }>

Install the renderer-independent segmented shooter API.

Helpers

CellType

const CellType: { readonly empty: 0; readonly mushroom: 1; readonly poisoned: 2; readonly flower: 3; readonly bomb: 4; }

Cell contents. Mushrooms, poisoned mushrooms and flowers are obstacles; bombs are DDT canisters.

centipedePreset

function centipedePreset(o: CentipedePresetOptions = {}): SegmentedConfig

Centipede (Atari, 1981; Ed Logg and Dona Bailey) as data. From the original design document (Ed Logg, May 1981) and the rev 4 ROM disassembly: a 30-column field of 8-pixel cells; 12 segment slots; wave 1 a single slow 12-segment chain, then each shorter chain with one more separate fast head, slow then fast, until 12 heads, then the cycle repeats; no slow centipedes from 40,000 points. Slow chains move 1 px per frame, fast chains and separate heads 2. A chain turns down a row and reverses at a mushroom, edge or other segment; a poisoned mushroom sends it straight to the bottom; at the bottom it bounces inside the player area (turning back down 6 rows up), releasing its tail as a new head, and replacement heads enter from the sides every 192 frames (8 fewer per head, at least 96, 2 fewer per 10,000 points). A shot segment leaves a mushroom and splits the chain, the segment behind becoming a head. One 7 px/frame shot; holding fire is autofire. Mushrooms take 4 shots (1 point). Flea (200, two hits, the first speeds it from 2 to 4 px/frame, 3 from 60,000) drops in waves shorter than 12 while few mushrooms remain near the bottom (at most 5, 8 from 20,000, 6 + score/20,000 from 120,000), seeding mushrooms with a 25% chance per row. Spider (300/600/900 at 64+/22+/under 22 px from the gun) zig-zags through the player area, re-planning every 48 frames, eats mushrooms, 1 px/frame until 1,000 points on hard (5,000 on easy) then 2, its ceiling falling from 12 rows to 7 between 60,000 and 180,000, 128 frames between spiders. Scorpion (1000) crosses the upper field in waves of 10 segments or fewer, poisoning mushrooms, 1 px per frame, with a 75% chance of 2 from 20,000; it shares the flea's slot. Dying restores damaged and poisoned mushrooms for 5 points each. Three lives, at most six; an extra life every 12,000.

createSegmentedShooter

function createSegmentedShooter(config: SegmentedConfig)

Create an independent segmented-shooter game. No renderer or kernel clock is required.

millipedePreset

function millipedePreset(o: MillipedePresetOptions = {}): SegmentedConfig

Millipede (Atari, 1982) as data, a faithful core of the sequel's rules: the same field and gun with a taller player area; 12-segment chains cycling one more head per formation, each formation flown slow then fast until 20,000 points; the field scrolls down a row after every cleared wave and evolves by Game-of-Life rules after the fourth formation (DDT poisons neighbours, poison kills plain neighbours, flowers never die); the ninth formation creeps the field down a row every 2 seconds. Shooting a diving head destroys its chain. Four DDT bombs (800) whose cloud kills everything inside for triple points (a spider 1,800), one more appearing at the top whenever the field scrolls down. Spider 300/600/900/1200 by distance; earwig 1,000 (poisons, chains of 10 or fewer); inchworm 100 (slows all enemies for 3.5 s); dragonfly 500 (zig-zags down planting mushrooms, chains of 9 or fewer); mosquito 400 (bounces down, its death scrolls the field up, chains of 8 or fewer); beetle 300 (walks the bottom, climbs, turns mushrooms into flowers, its death scrolls the field down; from wave 2); bee 200 (two hits, plants mushrooms when few remain). Raids after formations 2, 6, 8, 10 and 12 (bees, dragonflies, mosquitoes, bees and dragonflies, all three): the first kill scores normally, each next 100 more up to 1,000. Dying restores damaged, poisoned and flowered mushrooms for 5 each. An extra life every 15,000. Spawn rates, raid sizes, speeds and the player-area height are tuned approximations: no disassembly of Millipede was available.

rampAt

function rampAt(ramp: ScoreRamp, score: number): number

The value of a ScoreRamp at a score.

segmentWaves

function segmentWaves(segments: number, first: ("slow" | "fast")[] = ["slow"]): Formation[]

Centipede's wave cycle for a chain of segments: one full slow chain, then each shorter chain with one more separate head twice (a slow pass, then a fast one), ending with a 1-segment chain and segments - 1 heads, after which the cycle repeats. Once all waves are fast (40,000 points) each formation is one pass.

validateSegmented

function validateSegmented(c: SegmentedConfig)

Throws a descriptive error for an unsupported definition.

Classes

SegmentedShooter

class SegmentedShooter

Owns a segmented-shooter game: the mushroom field, segment chains (movement, turning, poison dives, splitting with head promotion, bottom bounce and replacement heads), hazards, bombs, raids, the gun and its single shot, scoring, lives, deaths with mushroom restoration, and wave progression. Renderer-free, deterministic for a seed and an input sequence, and serializable.

  • readonly config: SegmentedConfig — The validated definition (a private copy).
  • constructor(config: SegmentedConfig)
  • get zoneTop() — First row of the player area.
  • get size() — Field width and height in pixels.
  • cellAt(col: number, row: number): { type: CellCode; hp: number } — The cell at a column and row (empty outside the field).
  • countMushrooms(top: number, bottom: number) — Mushrooms (including poisoned ones and flowers) in the inclusive row range.
  • liveSegments() — Live segments in all chains.
  • segmentBox(seg: Segment): Box — A segment's hit box (one cell centred on it).
  • hazardBox(h: Hazard): Box — A hazard's hit box.
  • playerBox(x = this.s.player.x, y = this.s.player.y): Box — The player's hit box.
  • hazardValue(h: Hazard) — What a hazard would score if shot now (bands use its vertical distance from the player).
  • get formation(): Formation — The formation in play.
  • passes(f: Formation = this.formation) — The passes a formation has at the current score (slow passes collapse once all waves are fast).
  • get state(): SegmentedState — A read-only copy of the whole state.
  • drain() — Take the events since the last drain.
  • snapshot() — Serializable snapshot of the whole game.
  • restore(snap: ReturnType<SegmentedShooter["snapshot"]>) — Restore a snapshot taken from the same configuration.
  • reset(startWave = 1, seed = this.config.seed) — Start a new game with the same configuration, optionally at a later (1-based) wave and with a new seed (a fresh field).
  • tick(seconds: number, input: SegmentedInput = {}) — Advance by real seconds (fixed frames inside); returns the live state (do not mutate it).
  • step(input: SegmentedInput = {}) — Advance exactly one simulation frame.
  • scroll(rows: number) — Scroll the whole field rows rows: positive moves it down (a new row grows at the top), negative up.
  • evolve() — Evolve the field once by mushrooms.life (no-op when the rules are null).
  • spawnHazard(def: HazardDef | string, raid = false) — Spawn a hazard of a type now, by the type's own entry rule. Returns its id.

Types

BombRules

interface BombRules

DDT bombs.

  • max: number — Most on the field.
  • initial: number — Placed with the starting field.
  • rows: RowRange — Rows they may be placed in at the start.
  • radius: { x: number; y: number } — Cloud half-extent in cells (an ellipse).
  • frames: number — Frames the cloud kills for.
  • score: number — Points for detonating one.
  • multiplier: number — Points multiplier for enemies killed in a cloud.
  • spawnOnScroll: boolean — A new bomb appears in the top row when the field scrolls down (while fewer than max).
  • killsPlayer: boolean — The cloud kills the player.
  • leavesMushrooms: boolean — Segments killed by a cloud leave mushrooms.

CellCode

type CellCode = (typeof CellType)[keyof typeof CellType]

One of the CellType codes.

CentipedeHazard

type CentipedeHazard = "flea" | "spider" | "scorpion"

Hazard ids of the Centipede preset.

CentipedePresetOptions

interface CentipedePresetOptions extends SegmentedPresetOptions

Options for centipedePreset.

  • hazards?: CentipedeHazard[] — Which hazards appear (default all three).

Chain

interface Chain

A chain of segments; segments[0] is its head.

  • id: number — Stable id (a split keeps the front chain's id; the rear gets a new one).
  • segments: Segment[] — Head first.
  • speed: number — Pixels per frame.
  • progress: number — Pixels travelled towards the next cell.
  • poisoned: boolean — Diving after touching a poisoned mushroom.
  • releaseTail: boolean — Its tail will break off when it reaches the bottom row.

Cloud

interface Cloud

A bomb cloud.

  • id: number — Stable id.
  • col: number — Centre cell.
  • row: number — Row of the centre cell.
  • frames: number — Frames left.

Formation

interface Formation

One centipede formation. Each of its passes is one wave.

  • length: number — Segments in the main chain (head included); 0 for none.
  • heads: number — Separate single-segment heads that enter with it at random columns of the top row.
  • passes: ("slow" | "fast")[] — Speed of each pass, in order. Every pass is a wave. slow passes collapse to one fast pass once the score reaches waves.allFastAtScore.
  • raid?: string — Raid (an id in raids) flown after this formation's last pass.
  • creep?: number — During this formation's waves the field creeps down one row every creep frames, until the chain is cleared, a bomb is shot or a life is lost.
  • evolve?: boolean — Evolve the mushroom field by mushrooms.life after this formation's last pass.

Hazard

interface Hazard

One live hazard.

  • id: number — Stable id.
  • kind: string — Its HazardDef id.
  • x: number — Centre, pixels.
  • y: number — Vertical centre, pixels.
  • vx: number — Velocity, pixels per frame.
  • vy: number — Vertical velocity, pixels per frame; positive is down.
  • speed: number — Speed chosen at spawn (or after a hit).
  • dir: number — Side it entered from / heads to: +1 rightwards, -1 leftwards.
  • hp: number — Hits left.
  • timer: number — Frames alive.
  • climbing: boolean — A crawler climbing.
  • raid: boolean — Spawned by a raid.
  • lastRow: number — Last cell row / column its centre was in (for drops and climbing).
  • lastCol: number — Last cell column its centre was in; -2 until it has been placed.

HazardDef

interface HazardDef

One hazard type: movement, contact effects, scoring and spawn rules.

  • id: string — Unique id; it is also the kind of spawned hazards.
  • motion: HazardMotion — Movement policy.
  • width: number — Hit-box width, pixels.
  • height: number — Hit-box height, pixels.
  • speed: ScoreRamp — Speed in pixels per frame.
  • fast?: { chance: ScoreRamp; speed: number } — A chance, decided at spawn, of moving at speed instead (the scorpion's fast crossings).
  • hp: number — Shots needed.
  • hitSpeed?: number — Speed after a hit that does not kill (the flea and bee speed up).
  • score: number | { atLeast: number; score: number }[] — Points: a constant, or bands by vertical distance from the player (first band whose atLeast the distance reaches).
  • bombScore?: number — Base points when killed by a bomb (before the bomb multiplier), when it differs (Millipede's spider: 600).
  • lethal: boolean — Touching the player kills the player.
  • onCell?: "poison" | "eat" | "flower" | "drop" — What it does to the cell under its centre: poison mushrooms, eat them, turn them into flowers, or drop new ones.
  • dropChance?: number — For drop: chance per row crossed of leaving a mushroom in an empty cell above the bottom row.
  • onKill?: "slow" | "scroll-down" | "scroll-up" — What killing it does to the game.
  • band?: RowRange — For cross: rows it may cross along.
  • reach?: ScoreRamp — For spider: rows above the bottom it may climb to.
  • turnFrames?: number — For spider/zigzag: frames between re-plans or swings.
  • turnChance?: number — For spider: chance a re-plan changes course; for crawl: chance per column of starting to climb.
  • spawn: HazardSpawn — Regular spawn schedule.

HazardMotion

type HazardMotion = /** Falls straight down from a random column (Centipede flea, Millipede bee). */ | "drop" /** Enters from a side within the player area and zig-zags across, re-planning every `turnFrames` (spider). */ | "spider" /** Crosses horizontally along a random row of `band` (scorpion, earwig, inchworm). */ | "cross" /** Falls while swinging left and right every `turnFrames` (dragonfly). */ | "zigzag" /** Enters at a top corner and descends diagonally, bouncing off the side walls (mosquito). */ | "bounce" /** Walks along the bottom row from a side, may climb straight up a column and leave at the top (beetle). */ | "crawl"

How a hazard moves.

HazardSpawn

interface HazardSpawn

When a hazard type is spawned by the regular schedule (raids spawn their own).

  • every: number — Frames between spawn attempts (an attempt happens when frame % every === 0).
  • chance: ScoreRamp — Chance that an attempt whose conditions hold spawns one.
  • cooldown: number — Frames after one of this type dies or leaves (and at each life's start) before the next attempt.
  • maxActive: ScoreRamp — Most of this type alive at once.
  • minWave?: number — Only from this wave (1-based count of waves started).
  • maxMainLength?: number — Only in waves whose formation's main chain has at most this many segments.
  • lowMushrooms?: { above: number; rows: number; atMost: ScoreRamp } — Only while few mushrooms remain near the bottom: rows [bottom - above - rows + 1, bottom - above] hold at most atMost.
  • slot?: string — Hazards with the same slot never coexist (Centipede's flea and scorpion share one object slot).
  • raidOnly?: boolean — Never spawned by the schedule, only by raids.

MillipedeHazard

type MillipedeHazard = "spider" | "bee" | "earwig" | "inchworm" | "dragonfly" | "mosquito" | "beetle"

Hazard ids of the Millipede preset.

MillipedePresetOptions

interface MillipedePresetOptions extends SegmentedPresetOptions

Options for millipedePreset.

  • hazards?: MillipedeHazard[] — Which hazards appear (default all).
  • bombs?: number — DDT bombs on the field (4 = arcade; 0 for none).
  • raids?: boolean — Insect raids between waves (default true).

RaidDef

interface RaidDef

A raid (Millipede's insect swarm): a burst of hazards with escalating points, between waves.

  • hazards: string[] — Hazard ids flown, in rotation.
  • count: number — Hazards flown in all.
  • interval: number — Frames between launches.
  • scoreStep: number — Each kill after the first scores this much more than the last (the first scores its normal value).
  • scoreCap: number — Most a raid kill can score; a bomb kill scores this at once.

RowRange

interface RowRange

Inclusive row range, counted from the top row (0).

  • top: number — First row.
  • bottom: number — Last row (inclusive).

ScoreRamp

type ScoreRamp = number | ReadonlyArray<readonly [number, number]>

A number that changes with score: a constant, or [fromScore, value] pairs sorted by score whose first entry starts at 0. The value of the last pair whose score has been reached applies.

Segment

interface Segment

One segment. Its id is stable for life, whatever chain it ends up in.

  • id: number — Stable id.
  • col: number — Cell it is moving into.
  • row: number — Row of the cell it is moving into, 0 at the top of the field.
  • pcol: number — Cell it is moving from (row -1 is above the field).
  • prow: number — Row of the cell it is moving from; -1 is above the field.
  • dir: number — Horizontal heading, +1 right / -1 left.
  • vdir: number — Vertical heading for its next turn, +1 down / -1 up.
  • x: number — Centre, pixels (interpolated between the two cells).
  • y: number — Vertical centre, pixels (interpolated between the two cells).

SegmentedConfig

interface SegmentedConfig

Complete definition. Every original value is in centipedePreset / millipedePreset.

  • name: string — Preset name, for presenters.
  • hz: number — Simulation frames per second.
  • seed: number — Seed for the field, spawns and choices.
  • cols: number — Field columns.
  • rows: number — Field rows (row 0 at the top).
  • cell: number — Cell size in pixels.
  • zoneRows: number — Player area height in rows from the bottom. The player stays in it; chains that reach the bottom bounce inside it.
  • mushrooms: { /** Shots to destroy one. */ hp: number; /** Starting field: for each row of each range, \perRow` random columns get a mushroom (a repeat column places none). / initial: Array<RowRange & { perRow: number }>; /* Points for destroying a mushroom. / destroyScore: number; /* Points for destroying a poisoned mushroom. / poisonedDestroyScore: number; /* After a death, damaged and poisoned mushrooms (and flowers, if set) are restored one at a time. / restore: { score: number; frames: number; flowers: boolean }; /* Shots stop at flowers (which they cannot destroy). / flowersBlockShots: boolean; /* Chance per column of a mushroom in the row that scrolls in at the top. / scrollFill: number; /* Field evolution rules (Millipede's Game-of-Life step), or null. Counts are 8-neighbour mushrooms/flowers. */ life: { survive: number[]; birth: number[]; bombPoisons: boolean; poisonKills: boolean } | null; }` — The mushroom field.
  • chain: { /** Segment slots: live segments never exceed it (replacement heads only fill empty slots). */ maxSegments: number; /** Pixels per frame of a slow and a fast main chain. */ slowSpeed: number; fastSpeed: number; /** Pixels per frame of separate heads (wave heads, replacement heads, released tails). */ headSpeed: number; /** Points for a head and a body segment. */ headScore: number; bodyScore: number; /** A shot segment leaves a mushroom where it was. */ mushroomOnKill: boolean; /** A head turns when another chain's segment is ahead. */ turnOnSegments: boolean; /** A head that runs into a poisoned mushroom dives straight to the bottom. */ poisonDive: boolean; /** Shooting a diving head destroys its whole chain (Millipede). */ poisonedHeadKillsChain: boolean; /** When a chain turns back up from the bottom, its tail breaks off as a new head on reaching the bottom row. */ releaseTailAtBottom: boolean; /** Entry column of the main chain (default the middle). */ entryCol?: number; /** Replacement heads from the sides of the player area once a segment has reached the bottom, or null. Delay frames start at \delay`, fall by `step` per head down to `min`, and by `scoreStep` per `scoreEvery` points. */ newHeads: { delay: number; step: number; min: number; scoreEvery: number; scoreStep: number } | null; }` — The segmented enemy.
  • waves: { /** Formations in order; the cycle repeats. */ cycle: Formation[]; /** From this score every formation is a single fast pass. */ allFastAtScore: number; /** Frames between a cleared wave and the next. */ clearDelay: number; /** Rows the field scrolls down after each cleared wave. */ scrollOnClear: number; /** Colour schemes cycled per wave (\state.palette`). */ palettes: number; }` — Wave progression.
  • player: { /** Hit-box size, pixels. */ width: number; height: number; /** Pixels per frame at full stick (keyboard / joystick). */ speed: number; /** Largest trackball (pointer) movement per frame, pixels. */ trackballMax: number; /** Starting lives, including the one in play. */ lives: number; /** No extra life is awarded beyond this many. */ maxLives: number; /** An extra life every this many points (0 = none). */ extraEvery: number; /** Frames of the death explosion before mushrooms are restored. */ deathFrames: number; /** Frames after the restoration before play resumes. */ respawnFrames: number; /** Mushrooms, flowers and bombs block the gun. */ blockedByField: boolean; } — The player's gun.
  • shot: { /** Pixels per frame. */ speed: number; /** Length, pixels. */ height: number; } — The single player shot.
  • hazards: HazardDef[] — Hazard types.
  • raids: Record<string, RaidDef> — Raids by id.
  • bombs: BombRules | null — DDT bombs, or null.
  • effects: { slowFactor: number; slowFrames: number } — The slow-down a slow kill causes: enemies move at slowFactor for slowFrames.

SegmentedEvent

type SegmentedEvent = | { kind: "wave-start"; wave: number; formation: number; pass: number; speed: "slow" | "fast"; length: number; heads: number } | { kind: "wave-clear"; wave: number } | { kind: "segment-killed"; id: number; chain: number; head: boolean; score: number; x: number; y: number; by: "shot" | "bomb" } | { kind: "chain-split"; from: number; rear: number } | { kind: "tail-released"; from: number; chain: number } | { kind: "head-spawned"; chain: number; col: number; row: number } | { kind: "poison-dive"; chain: number } | { kind: "mushroom-hit"; col: number; row: number; hp: number } | { kind: "mushroom-destroyed"; col: number; row: number; score: number; by: string } | { kind: "mushroom-poisoned"; col: number; row: number } | { kind: "mushroom-flowered"; col: number; row: number } | { kind: "mushroom-grown"; col: number; row: number; by: string } | { kind: "mushroom-restored"; col: number; row: number; score: number } | { kind: "hazard-spawn"; id: number; hazard: string; raid: boolean } | { kind: "hazard-hit"; id: number; hazard: string; hp: number } | { kind: "hazard-killed"; id: number; hazard: string; score: number; x: number; y: number; by: "shot" | "bomb" } | { kind: "hazard-gone"; id: number; hazard: string } | { kind: "player-fire"; x: number; y: number } | { kind: "shot-blocked"; x: number; y: number } | { kind: "player-hit"; x: number; y: number; by: string } | { kind: "extra-life"; lives: number } | { kind: "bomb-exploded"; col: number; row: number; score: number } | { kind: "field-scrolled"; rows: number } | { kind: "field-evolved"; born: number; died: number } | { kind: "slowdown"; frames: number } | { kind: "raid-start"; raid: string } | { kind: "raid-end"; raid: string } | { kind: "respawn" } | { kind: "game-over"; score: number }

Ordered notifications for presentation: drain() them each frame.

SegmentedInput

interface SegmentedInput

One frame of player input.

  • move?: { x: number; y: number } — Stick/keys: each axis -1..1, scaled by player.speed.
  • nudge?: { x: number; y: number } — Trackball/pointer movement this frame in pixels, clamped to player.trackballMax per axis.
  • fire?: boolean — Fire held (a new shot leaves whenever none is in flight: holding it is autofire).

SegmentedPresetOptions

interface SegmentedPresetOptions

Options shared by both presets: the arcade values unless overridden.

  • cols?: number — Field columns (30 = arcade).
  • rows?: number — Field rows below the score line (31 = arcade).
  • zoneRows?: number — Player area rows.
  • segments?: number — Segment slots and the full chain length (12 = arcade).
  • lives?: number — Starting lives (3 = arcade default; the operator could set 2-5).
  • extraEvery?: number — Points per extra life.
  • mushroomHp?: number — Shots per mushroom (4 = arcade).
  • density?: number — Multiplies the starting mushroom count (1 = arcade).
  • difficulty?: "easy" | "hard" — Operator difficulty switch (hard was the factory default).
  • seed?: number — Seed for the field and every random choice.

SegmentedState

interface SegmentedState

Serializable game state; read it through state.

  • frame: number — Frames since the game began.
  • wave: number — Waves started, 1-based.
  • formation: number — Index into waves.cycle, and pass within it.
  • pass: number — Index into the current formation's passes, 0-based.
  • mainLength: number — This wave's main chain length (spawn conditions use it).
  • speed: "slow" | "fast" — This wave's speed.
  • status: SegmentedStatus — Status and frames left in it.
  • statusFrames: number — Frames left in the current status.
  • score: number — Score.
  • lives: number — Lives, including the one in play.
  • nextExtra: number — Score of the next extra life.
  • palette: number — Colour scheme index.
  • cells: number[] — Cell types (CellType), row-major, cols * rows.
  • hp: number[] — Cell hit points, row-major.
  • chains: Chain[] — Live chains.
  • hazards: Hazard[] — Live hazards.
  • clouds: Cloud[] — Bomb clouds.
  • player: { x: number; y: number; alive: boolean } — The gun: centre and alive.
  • shot: { x: number; y: number } | null — The shot in flight: centre x and top y.
  • bottomReached: boolean — A segment has reached the bottom this wave (replacement heads run).
  • headTimer: number — Frames counted towards the next replacement head, and heads made this wave.
  • headsSpawned: number — Replacement heads made so far this wave; each shortens the next head's delay by newHeads.step frames.
  • cooldowns: Record<string, number> — Frames before each hazard type may next spawn.
  • raid: { id: string; spawned: number; timer: number; value: number } | null — The raid in progress.
  • raidDone: boolean — This wave's raid has run (or was cut short by a death).
  • afterDone: boolean — Between-wave field changes done.
  • slowFrames: number — Frames of slow-down left.
  • creep: { active: boolean; timer: number } — Field creep this wave.
  • restoreQueue: number[] — Cells still to restore after a death.
  • respawnWait: boolean — Restoration finished; waiting to respawn.
  • nextId: number — Next id.
  • random: number[] — The kernel generator's state (four words from createRng), advanced in place, so a snapshot carries the stream.

SegmentedStatus

type SegmentedStatus = "playing" | "wave-clear" | "raid" | "dying" | "restoring" | "game-over"

Game status.