Phaser AE

Road combat

Pro packv3.0.0-32DArcade

The rules of top-down road-combat driving games: a car, and a boat on the river, driven up a road that forks, narrows and widens while enemy vehicles try to stop you, civilians must be spared and a weapons van keeps you armed. One session from a config runs it all; your game supplies input and draws the state.

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

Road combat: 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

roadCombat

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

Install the road combat API.

Helpers

COMBAT_ROADS

const COMBAT_ROADS: Record<string, RoadDocument>

The road files of this folder, by name.

createRoadCombat

function createRoadCombat(config: RoadCombatConfig, seed = 1): RoadCombat

Create a session.

desertPatrolPreset

function desertPatrolPreset(o: DesertPatrolOptions = {}): RoadCombatConfig

Desert Patrol: an original road-combat game showing the same API with different rules.

desertPatrolRoad

function desertPatrolRoad()

Desert Patrol's road file (roads/desert-patrol.road.json in this pack).

DIFFICULTY

const DIFFICULTY: Readonly<Record<Difficulty, { population: number; aggression: number }>>

Population, aggression and handling assist per difficulty. Arcade is the original tables.

SPY_AWARD

const SPY_AWARD: Readonly<Record<Difficulty, ReadonlyArray<{ score: number; cars: number }>>>

Spare cars awarded when the opening timer runs out, by score. Arcade: two cars at 18,000 (players' reports); none below a lower threshold, estimated at 9,000 (players report that zero is possible but not where). Normal and Easy are gentler so a human keeps playing past the timer.

spyHunterKinds

function spyHunterKinds(): Record<string, VehicleKindDef>

Spy Hunter's vehicles, sized from the arcade sprites at half resolution (the screen is 240 units across).

spyHunterPreset

function spyHunterPreset(o: SpyHunterOptions = {}): RoadCombatConfig

Spy Hunter (Bally Midway 1983) as a road-combat config.

spyHunterRoad

function spyHunterRoad()

Spy Hunter's road file (roads/spy-hunter.road.json in this pack): territories, forks, bridge out, boathouses.

spyHunterWeapons

function spyHunterWeapons(): Record<string, WeaponDef>

Spy Hunter's weapons: unlimited twin machine guns, and the van's oil slick, smoke screen and missiles.

Functions

validate

function validate(c: RoadCombatConfig): void

Reject configurations the session cannot run, with the reason.

Classes

CombatRoad

class CombatRoad

The road a road-combat session drives.

  • readonly doc: RoadDocument — The road document the course was loaded from (metres), before the game seed was mixed in.
  • readonly data: RoadData — The loaded road data (road-data), in the document's own units: metres.
  • constructor(doc: RoadDocument, o: CombatRoadOptions)
  • reset(): void — Back to the start of the road.
  • get revision(): number — Bumped whenever ground changes or more road is laid (a road-view revision).
  • get entered(): readonly TerritoryVisit[] — Territories entered so far.
  • sample(s: number): RoadSample | null — A sample at a world distance (null beyond the laid road).
  • update(s: number, x: number, ahead: number): RoadUpdate — Advance the car to (s, x): lay road ahead, decide forks by the car's side (never into a dead end), and report territories entered, the fork taken, a boathouse crossed, and banners, vans and checkpoints ahead.
  • territoryAt(s: number): TerritoryVisit — The territory covering s.
  • spansAt(s: number): CombatSpan[] — The cross-section at s (world units, paint order).
  • lookAt(s: number): string | null — The region look at s (the palette a renderer should use).
  • featuresIn(v0: number, v1: number): CombatFeature[] — Features to draw between two distances (world units).
  • markingsIn(v0: number, v1: number): CombatMarking[] — Lane lines to draw (world units).
  • surfaceAt(s: number, x: number): string — The surface id under (s, x).
  • drivable(surface: string, medium: "road" | "river"): boolean — True when a medium may drive on a surface.
  • pathAt(s: number, preferX?: number): PathPoint — The carriageway that continues the road at s, nearest preferX.
  • respawnAt(s: number, preferX?: number, clear = 160): PathPoint — Where to put a car back down at s: on the continuing carriageway, clear of a median or island opening within clear ahead (the half nearest preferX is chosen when one opens).
  • laneAt(s: number, x: number, medium: "road" | "river"): { from: number; to: number } | null — The drivable run of the cross-section containing x (for AI steering), or null when off it.
  • snapshot(): CombatRoadState — Plain-data snapshot.
  • restore(s: CombatRoadState): void — Restore a snapshot from a road of the same document and seed.

RoadCombat

class RoadCombat

One game of road combat.

  • readonly config: RoadCombatConfig — The rule set the game was created with; it is not changed.
  • readonly road: CombatRoad — The road being driven (road-data in world units; also a road-view-topdown source).
  • readonly specs: { car: VehicleSpec; boat: VehicleSpec; top: number } — World-unit handling specs.
  • constructor(config: RoadCombatConfig, seed = 1)
  • get state(): Readonly<RoadCombatState> — The live state (read it; do not write it).
  • get handling() — The player's handling state (gear, revs, skid) from vehicle-handling.
  • drain(): RoadCombatEvent[] — Events since the last drain.
  • get shots(): Shot[] — Shots in flight, in the course frame.
  • get night(): number — Night amount 0..1 at the player's position (0 with no daylight cycle).
  • weaponFor(id: string): WeaponDef | undefined — The weapon a button fires in the player's current medium.
  • reset(): void — Back to the attract state at the start of the road.
  • start(): void — Start a game: the van puts the car down at the start.
  • tick(dt: number, input: RoadCombatInput = {}): void — Advance by dt seconds in fixed 1/60 s steps.
  • step(input: RoadCombatInput = {}): void — One fixed step.
  • spawnKind(kind: string, where?: "ahead" | "behind"): Actor | null — Spawn a kind ahead of or behind the player on its medium. Returns the actor or null when it cannot fit.
  • get timerDisplay(): number | null — The number the timer display shows (Spy Hunter counts 999 down to 0), or null.
  • snapshot(): Snapshot — Plain-data snapshot of everything.
  • restore(snap: Snapshot): void — Restore a snapshot taken from a session with the same config.

Types

Actor

interface Actor

A vehicle in play (enemy, civilian or the van). Plain data.

  • id: number — Unique id, handed out from RoadCombatState.nextId.
  • kind: string — Id of the vehicle kind in RoadCombatConfig.kinds; the van is van.
  • role: "enemy" | "civilian" | "van" — Whether it scores when destroyed (enemy), costs the player (civilian) or is the weapons van (van).
  • medium: Medium — Where it is: on the road, on the river or in the air.
  • s: number — Distance along.
  • x: number — Lateral.
  • speed: number — Speed along.
  • vx: number — Lateral speed.
  • width: number — Body width across the road in world units.
  • length: number — Body length along the road in world units.
  • cruise: number — Cruise target speed (world units/s).
  • lane: number — Lane fraction across its carriageway, -1..1.
  • mode: string — Behaviour state.
  • modeTime: number — Seconds in the mode.
  • timer: number — Next attack timer.
  • ammo: number — Shots or bombs left.
  • hits: number — Bullet hits left.
  • blades: boolean — Blades extended (slasher).
  • blind: number — Seconds left blinded by smoke.
  • credit: number — Seconds left since the player last touched it or hit it with a weapon (credit window).
  • altitude: number — Air height 0..1 (bomber entering and leaving).
  • cargo: string — Van: the weapon it carries.
  • dead: boolean — Dead (exploding) and removed next step.
  • yaw: number — Visual heading relative to the road (radians, + right).
  • spinning: boolean — Spinning (oil).

AiDef

type AiDef = TrafficAi | RammerAi | SlasherAi | ShooterAi | BomberAi | DumperAi | TorpedoAi

Any behaviour.

Armour

interface Armour

Immunities: true means that weapon or attack does nothing to this kind.

  • bullets?: boolean — Machine guns and cannon shells (Road Lord: bullet-proof).
  • ram?: boolean — Being pushed off the road.
  • oil?: boolean — Oil slicks.
  • smoke?: boolean — Smoke screens.
  • missiles?: boolean — Missiles.
  • flame?: boolean — The boat's flame.
  • mines?: boolean — Mines.

BomberAi

interface BomberAi

A bomber (Mad Bomber): flies ahead of the player and drops bombs that blast and leave craters.

  • kind: "bomber" — Selects the bomber behaviour in VehicleKindDef.ai.
  • hold: number — Distance ahead of the player it holds, world units.
  • bombEvery: readonly [number, number] — Seconds between bombs (range).
  • bombs: number — Bombs before it leaves.
  • fall: number — Seconds a bomb falls.
  • blast: number — Blast radius, world units (kills the player inside it as the bomb lands).
  • crater: { width: number; length: number } | null — Crater size left on the ground (null: none); driving into it is a crash.
  • track?: number — Lateral tracking rate toward the player, 1/s. Default 1.5.

CombatFeature

interface CombatFeature

A road feature for drawing (world units).

  • id: string — Stable id: the same feature keeps the same id while it is on screen.
  • kind: string — What to draw, as the road document names it (boathouse, sign, gantry ...).
  • u: number — Centre across the road, world units.
  • v: number — Centre along the road, world units.
  • width: number — Size across the road, world units.
  • length: number — Size along the road, world units.
  • z?: number — Draw order relative to the view's base z; boathouses are 30 and other features 2.

CombatMarking

interface CombatMarking

A painted marking (world units).

  • id: string — Stable id: dashes are keyed by it.
  • u: number — Centre of the line across the road, world units.
  • from: number — Start along the road, world units.
  • to: number — End along the road, world units.
  • width: number — Line width, world units, at least 1.
  • dash?: number — Dash length, world units; omitted or 0 draws a solid line.
  • gap?: number — Gap between dashes, world units; default the dash length.
  • colour?: string — Line colour; default white.

CombatRoadOptions

interface CombatRoadOptions

Options for a CombatRoad.

  • unitsPerMetre: number — World units per metre (road files are in metres).
  • seed?: number — Mixed into the document seed, so every game seed generates different territories. Default 0.
  • ahead?: number — Lay road at least this far ahead of the car, world units. Default 600.
  • drivable: { road: readonly string[]; river: readonly string[] } — Surfaces each medium may drive on (anything else is off the road, or aground).

CombatRoadState

interface CombatRoadState

Plain-data state.

  • path: PathSnapshot — The road-data path's own snapshot: the road laid so far and the car's place on it.
  • visits: TerritoryVisit[] — Every territory entered so far, in order.
  • ahead: number — How far ahead markers have been reported, in road-data units (metres).
  • rev: number — The revision counter, bumped whenever ground changes or road is laid.
  • end: number — The end of the road laid so far, in road-data units (metres).

CombatSpan

interface CombatSpan

A span of surface across the road (world units).

  • from: number — Left edge across the road, world units.
  • to: number — Right edge across the road, world units.
  • surface: string — Id of the surface in this span, looked up in the road's surfaces.

DaylightDef

interface DaylightDef

Day and night along the road (presentation reads light; the rules can shorten sight).

  • period: number — One full day-night cycle, world units travelled.
  • night: number — Fraction of the cycle that is night.
  • start?: number — Phase at the start, 0..1 (0 = noon).

DesertPatrolOptions

interface DesertPatrolOptions

Options for desertPatrolPreset.

  • difficulty?: Difficulty — Default normal.
  • time?: number — Starting time, seconds. Default 75.
  • extend?: number — Seconds added at each checkpoint. Default 40.
  • lives?: number — Spare cars. Default 2.

Difficulty

type Difficulty = "easy" | "normal" | "arcade"

Difficulty: arcade is the original tables, normal the gallery default, easy a gentler game.

DistanceScore

interface DistanceScore

Distance scoring for one medium.

  • points: number — Points per every world units travelled on a scoring surface.
  • every: number — Distance per award.
  • surfaces?: readonly string[] — Surfaces that score (kinds). Default: the carriageway kinds of that medium.

DumperAi

interface DumperAi

A dumper (Barrel Dumper): drives ahead and drops floating explosives behind it.

  • kind: "dumper" — Selects the dumper behaviour in VehicleKindDef.ai.
  • dropEvery: readonly [number, number] — Seconds between drops (range).
  • size: number — Barrel size, world units.
  • life?: number — Seconds a barrel lasts. Default 20.
  • weave?: number — Lane changes per second. Default 0.3.

EncounterTable

interface EncounterTable

What appears in a territory.

  • civilians?: { kinds: Readonly<Record<string, number>>; every: readonly [number, number]; max?: number } — Civilian kinds by weight, and the distance between them (range).
  • enemies?: readonly EnemyEncounter[] — Enemy rows.
  • ramp?: number — Population multiplier added per territory entered (difficulty ramp). Default 0.08.
  • rampCap?: number — Cap on the ramp's multiplier. Default 2.

EnemyEncounter

interface EnemyEncounter

One enemy row of an encounter table.

  • kind: string — Kind id.
  • every: readonly [number, number] — Distance between appearances (range), world units, at the table's base rate.
  • after?: number — First appears this far into the territory. Default 0.
  • fromVisit?: number — Only from this territory visit of this medium onward (0 = the first). Default 0.
  • fromTerritory?: number — Only from this overall territory index onward. Default 0.
  • max?: number — At most this many of the kind at once. Default 1.

Hazard

interface Hazard

A patch on the ground or water: oil, smoke, a crater, a barrel, a mine, a flame burst.

  • id: number — Unique id, handed out from RoadCombatState.nextId.
  • kind: "oil" | "smoke" | "crater" | "barrel" | "mine" | "flame" | "bomb" — What it is: an oil slick, smoke screen, crater, floating barrel, mine, flame burst or a bomb in the air.
  • s: number — Centre distance along the road, world units.
  • x: number — Centre across the road, world units, 0 on the road's centre line.
  • width: number — Size across the road in world units.
  • length: number — Size along the road in world units.
  • life: number — Seconds left.
  • age: number — Seconds since it appeared.
  • owner: "player" | "enemy" — Laid by the player (credit for kills) or an enemy.
  • medium: Medium — Medium it lies on.
  • fall: number — Bomb: seconds until it lands.
  • blast: number — Bomb: blast radius; crater size it leaves.
  • crater: { width: number; length: number } | null — Crater a bomb leaves where it lands (null: none).

LivesDef

interface LivesDef

Lives.

  • start: number — Spare cars at the start (after a lead-in timer, the award replaces this).
  • extra: readonly number[] — Scores that award an extra car.
  • every?: number — After the last listed score, one more every this many points. Default none.
  • max?: number — At most this many spare cars. Default 9.

LoiterDef

interface LoiterDef

Dawdling: staying slow or on the shoulder brings these kinds after you (Spy Hunter's limo and helicopter).

  • slow: number — Below this fraction of top speed counts as dawdling.
  • seconds: number — Shoulder or slow for this long dispatches the next kind.
  • kinds: readonly string[] — Kinds dispatched in order (one per trigger).

Medium

type Medium = "road" | "river" | "air"

Where a vehicle lives: on the road, on the river, or in the air (above both).

PathPoint

interface PathPoint

The carriageway that continues the road at a distance.

  • x: number — Centre across, world units.
  • half: number — Half-width, world units.
  • medium: "road" | "river" — Road or river.

PlayerState

interface PlayerState

The player.

  • medium: "road" | "river" — Car or boat.
  • phase: "drop" | "drive" | "van" | "wreck" — drop: being put down; drive; van: riding inside; wreck: crashed.
  • phaseTime: number — Seconds in the phase.
  • s: number — Distance along the road, world units.
  • x: number — Position across the road, world units, 0 on the road's centre line.
  • speed: number — Speed along the road in world units per second.
  • vx: number — Lateral speed in world units per second.
  • gear: number — Index of the gear engaged (the lever position of a two-gear shifter).
  • gearName: string — Name of the gear engaged, as the handling spec names it.
  • yaw: number — Visual heading relative to the road.
  • skid: number — Skid intensity 0..1.
  • spinning: boolean — Whether an oil slick has spun the car.
  • weapons: Record<string, number | null> — Supplies by weapon id (null = unlimited).
  • invulnerable: number — Seconds of invulnerability left after a drop.
  • cause: string — Cause of the last crash.
  • surface: string — The surface under the car (road surface id).
  • width: number — Body width across the road in world units.
  • length: number — Body length along the road in world units.

RammerAi

interface RammerAi

A rammer (Road Lord): matches the player's speed alongside, then swerves into it to push it off the road.

  • kind: "rammer" — Selects the rammer behaviour in VehicleKindDef.ai.
  • ramEvery: readonly [number, number] — Seconds between rams (range).
  • ramTime?: number — Seconds a ram lasts. Default 0.6.
  • gap?: number — Gap kept alongside before ramming, world units. Default 6.

RoadCombatConfig

interface RoadCombatConfig

The whole rule set. Presets build these; anything can be changed.

  • name: string — A name for the HUD and panel.
  • road: RoadDocument — The road file (road-data): territories as sections, forks, boathouse links, regions, surfaces, van, banner and checkpoint markers. Road files are metres; unitsPerMetre converts.
  • unitsPerMetre: number — World units per metre for the handling specs (the car's sprite scale).
  • car: VehicleSpec — The player's car and boat handling, in metres (scaled by unitsPerMetre).
  • boat: VehicleSpec — The player's boat handling, in metres (scaled by unitsPerMetre).
  • aiCar: VehicleSpec — A handling spec for AI road vehicles and AI boats, in metres (its gear tops are replaced per kind).
  • aiBoat: VehicleSpec — A handling spec for AI boats, in metres (its gear tops are replaced per kind).
  • surfaces: SurfaceMap — Surface mapping.
  • player: { width: number; length: number; boatWidth?: number; boatLength?: number } — Player body size, world units.
  • window: { ahead: number; behind: number } — The visible window around the player: how far ahead and behind things spawn and despawn.
  • kinds: Readonly<Record<string, VehicleKindDef>> — Vehicle kinds by id.
  • weapons: Readonly<Record<string, WeaponDef>> — Weapons by id.
  • base: readonly string[] — Weapons always fitted (unlimited guns).
  • riverSwap?: Readonly<Record<string, string>> — Weapon substitutions on the river (Spy Hunter: the oil slick button fires a flame from the boat).
  • encounters: Readonly<Record<string, EncounterTable>> — Encounter tables by territory id, falling back to default.<kind> (default.road, default.river).
  • van: VanDef | null — The van, or null for none.
  • timer: TimerDef | null — Timer, or null.
  • lives: LivesDef — Lives.
  • scoring: ScoringDef — Scoring.
  • loiter: LoiterDef | null — Dawdling rule, or null.
  • daylight: DaylightDef | null — Day and night, or null for always day.
  • crash: { wreck: number; drop: number; invulnerable?: number } — Crash timing: the wreck shows for wreck s, then the car is put back down over drop s.
  • population?: number — Population scale (multiplies encounter rates). Default 1.
  • aggression?: number — Aggression scale (divides attack intervals). Default 1.
  • difficulty: Difficulty — Difficulty passed to the handling assist.
  • shifter?: "toggle" | "sequential" — Gears the shifter offers (indices into the car's gearbox). Default all.

RoadCombatEvent

type RoadCombatEvent = | { kind: "start" } | { kind: "banner"; text: string } | { kind: "territory"; id: string; index: number; medium: "road" | "river" } | { kind: "fork"; branch: "left" | "right" } | { kind: "kill"; actor: number; what: string; by: string; score: number; s: number; x: number; medium: Medium } | { kind: "civilian"; actor: number; what: string; s: number; x: number } | { kind: "crash"; cause: string; s: number; x: number; medium: "road" | "river" } | { kind: "respawn"; medium: "road" | "river" } | { kind: "car-lost"; spares: number } | { kind: "extra-car"; spares: number } | { kind: "timer-end"; awarded: number } | { kind: "time-up" } | { kind: "checkpoint"; bonus: number; added: number } | { kind: "van-parked"; actor: number; weapon: string } | { kind: "van-called"; actor: number; weapon: string } | { kind: "van-enter"; weapon: string } | { kind: "van-exit"; weapon: string } | { kind: "weapon"; weapon: string; supply: number | null } | { kind: "fire"; weapon: string } | { kind: "boathouse"; to: "road" | "river"; score: number } | { kind: "bomb"; s: number; x: number } | { kind: "blast"; s: number; x: number; radius: number } | { kind: "torpedo"; s: number; x: number } | { kind: "no-points"; seconds: number } | { kind: "game-over"; score: number }

Things that happened this step, for sound, effects and banners.

RoadCombatInput

interface RoadCombatInput

The controls for one step.

  • steer?: number — -1 full left .. 1 full right.
  • throttle?: number — 0..1 pedal.
  • brake?: number — 0..1 brake (only if the car has one worth using; Spy Hunter has none).
  • gear?: number — Gear lever position (Spy Hunter: 0 LOW, 1 HIGH).
  • fire?: Readonly<Record<string, boolean | undefined>> — Held weapon buttons by weapon id (guns, oil, smoke, missiles ...).
  • callVan?: boolean — The van button (press).
  • boost?: boolean — Boost (if the car has one).

RoadCombatState

interface RoadCombatState

The whole session state (snapshot).

  • status: "ready" | "playing" | "over" — ready before start, playing during play, over after the last car is lost or time runs out.
  • time: number — Seconds of play since the game started.
  • score: number — Points scored.
  • spares: number — Spare cars (not counting the one in play).
  • extrasAwarded: number — Extra-car thresholds already awarded.
  • timer: number | null — Timer seconds left (null: no timer or it has expired).
  • unlimited: boolean — Lead-in timer still running: unlimited cars.
  • noPoints: number — Seconds of NO POINTS left.
  • distanceAcc: number — Distance accumulated toward the next distance award.
  • player: PlayerState — The player's car or boat.
  • actors: Actor[] — Every vehicle in play: enemies, civilians and the van.
  • hazards: Hazard[] — Every patch on the ground or water: slicks, smoke, craters, barrels, mines, flames and bombs.
  • shots: Shot[] — Every projectile in flight.
  • nextId: number — The id the next actor or hazard receives.
  • rng: number[] — The seeded stream's four 32-bit words (a kernel Rng snapshot); drawing advances them in place, so a snapshot carries the stream.
  • road: CombatRoadState — The road's own state: the path, territories entered and how far road is laid.
  • territory: number — The territory index the player is in.
  • vansThisTerritory: number — Vans issued in this territory, and whether the van button may call one.
  • vanCallable: boolean — Whether the van button may call another van: set after leaving a van while the territory has vans left; cleared on entering a territory, on a call, or when a civilian is destroyed (if the van defines that).
  • vanCycle: number — The van's weapon cycle position.
  • vanWeapon: string — Weapon carried by this territory's vans.
  • encounterNext: Record<string, number> — Encounter cursors (next distance per encounter row) for the current territory.
  • loiter: number — Seconds dawdling, and the next loiter kind index.
  • loiterNext: number — Index of the next kind of LoiterDef.kinds to dispatch; it wraps round.
  • banner: { text: string; time: number } | null — Banner text and seconds left.
  • cooldown: Record<string, number> — Weapon cooldowns (seconds until the next shot) by weapon id.
  • held: Record<string, boolean> — Weapons held last step (for edge-triggered uses).
  • acc: number — Accumulator for the fixed step.
  • visitsByMedium: { road: number; river: number } — Visit counts by medium entered so far.
  • projectiles: { player: unknown; enemy: unknown } — Projectile system snapshots.
  • vehicles: Record<string, unknown> — Vehicle-handling snapshots by actor id ("player" for the player).
  • fired: number — Hazard and shot ids already resolved.

RoadUpdate

interface RoadUpdate

What the road reports as the car advances.

  • entered: TerritoryVisit[] — Territories entered (in order).
  • forked?: "left" | "right" — The branch taken at a fork.
  • boathouse?: "road" | "river" — A boathouse crossed: the medium the car is now in.
  • banners: string[] — Banner texts whose markers came into view.
  • vans: number[] — Van parking spots that came into view (world s).
  • checkpoints: number — Checkpoint markers passed.

ScoringDef

interface ScoringDef

Scoring rules.

  • distance: { road?: DistanceScore; river?: DistanceScore } — Distance points by medium.
  • boathouse?: { river?: number; road?: number } — Points for passing a boathouse into each medium.
  • noPoints?: number — Seconds the score is frozen after a civilian is destroyed (NO POINTS). Default 0.
  • civilianPenalty?: number — Points deducted for a civilian. Default 0.
  • checkpoint?: { points: number; perSecond?: number } — Points for passing a checkpoint marker, plus per second of time left.

ShooterAi

interface ShooterAi

A shooter (Enforcer): runs alongside and fires a spread of pellets at the player.

  • kind: "shooter" — Selects the shooter behaviour in VehicleKindDef.ai.
  • gap: number — Lateral gap kept alongside, world units.
  • fireEvery: readonly [number, number] — Seconds between volleys (range).
  • pellets: number — Pellets per volley.
  • spread: number — Spread of a volley, radians.
  • shotSpeed: number — Pellet speed relative to the shooter, world units per second.
  • shotLife: number — Pellet life, seconds (its range).
  • alongside?: number — Fire only within this distance along of the player. Default the shooter's length.
  • windup?: number — Seconds the gunman leans out before the volley (the warning; mode aim). Default 0.5.

Shot

interface Shot

A projectile, in the road frame (x lateral, s along).

  • id: number — Unique id, handed out per projectile system, so a player missile or an enemy shot never shares an id with a bullet.
  • kind: "bullet" | "shell" | "missile" | "pellet" | "torpedo" — What it is: a bullet, cannon shell, missile, shotgun pellet or torpedo.
  • owner: "player" | "enemy" — Who fired it; the player gets the credit for kills.
  • x: number — Position across the road, world units.
  • s: number — Position along the road, world units.
  • rot: number — Heading in the (x, s) plane, radians (PI/2 = straight ahead).

SlasherAi

interface SlasherAi

A slasher (Switch Blade): closes from behind, extends tyre blades alongside and swerves into the player.

  • kind: "slasher" — Selects the slasher behaviour in VehicleKindDef.ai.
  • reach: number — Blade reach beyond the body, world units: touching the player inside it is a crash.
  • bladesTime: number — Seconds the blades stay out.
  • every: readonly [number, number] — Seconds between blade attacks (range).

SpyHunterOptions

interface SpyHunterOptions

Options for spyHunterPreset.

  • difficulty?: Difficulty — Easy, Normal (gallery default) or Arcade (the original tables). Default normal.
  • timer?: number — The operator's game timer: 60 or 90 seconds (DIP switch; 90 is the factory setting). Default 90.
  • extra?: readonly number[] — Extra-car scores. Default 30,000, 60,000, 90,000 and 120,000 (the attract screen).
  • vans?: number — Vans per territory. Default 2.
  • noPoints?: number — Seconds of NO POINTS after a civilian. Default 3 (an estimate: "a second or two" to "a short time").

SurfaceMap

interface SurfaceMap

How the session reads the road's surfaces, per medium.

  • road: Readonly<Record<string, string>> — Road surface id to a vehicle-handling surface id, for road vehicles (* is the fallback).
  • river: Readonly<Record<string, string>> — For boats.
  • drivable: { road: readonly string[]; river: readonly string[] } — Surfaces each medium may drive on; anything else is off the road (a crash) or aground.
  • shoulder?: readonly string[] — Shoulder surfaces: drivable, but they score nothing and count as dawdling.
  • specs?: Readonly<Record<string, SurfaceSpec>> — Extra handling surfaces (puddle, bridge, shoulder ...) by id.

TerritoryVisit

interface TerritoryVisit

A territory (section visit) as entered.

  • index: number — Order of entry, from 0.
  • id: string — Section id.
  • s0: number — Start along, world units.
  • s1: number — End along (the next territory's start), 1e12 until known (plain JSON).
  • length: number — Length, world units.
  • kind: "road" | "river" — Road or river.
  • ofKind: number — How many territories of this medium were entered before it.
  • via: string | null — The link it was entered through (boathouse), or null.

TimerDef

interface TimerDef

The opening timer (Spy Hunter: unlimited cars while it runs) or a checkpoint timer (time runs out = game over; every checkpoint marker on the road adds time).

  • mode: "lead-in" | "checkpoint" — lead-in: unlimited cars until it expires, then cars are awarded by score. checkpoint: the game ends when it reaches 0; each checkpoint marker passed adds extend seconds.
  • seconds: number — Seconds.
  • display?: number — The number the display counts down from (Spy Hunter: 999). Default: seconds.
  • award?: ReadonlyArray<{ score: number; cars: number }> — Lead-in: spare cars awarded when it expires, by score reached (the highest row met).
  • extend?: number — Checkpoint: seconds added at each checkpoint marker.
  • cap?: number — Checkpoint: the most time that can be banked.
  • pauseInVan?: boolean — Pause while the car rides in the van. Default true.

TorpedoAi

interface TorpedoAi

A torpedo boat (Doctor Torpedo): from behind it fires forward, from ahead it fires back.

  • kind: "torpedo" — Selects the torpedo-boat behaviour in VehicleKindDef.ai.
  • fireEvery: readonly [number, number] — Seconds between torpedoes (range).
  • speed: number — Torpedo speed relative to the boat, world units per second.
  • life: number — Torpedo life, seconds.

TrafficAi

interface TrafficAi

Traffic: holds a lane at its cruise speed, changes lane now and then, slows behind slower traffic.

  • kind: "traffic" — Selects the traffic behaviour in VehicleKindDef.ai.
  • laneChange?: number — Lane changes per second (chance). Default 0.08.

VanDef

interface VanDef

The weapons van (Spy Hunter) or any supply vehicle the player drives into.

  • weapons: readonly string[] — Weapons it can carry, in order.
  • pick: "cycle" | "random" — Which one each van carries: in order, by the stream, or the same one.
  • perTerritory: number — Vans per territory: the first parks on the shoulder (at the road's van markers), the rest are called with the van button.
  • width: number — Body size.
  • length: number — Body length along the road in world units.
  • speed: number — Speed while overtaking and leading, as a fraction of the player's top speed.
  • wait: number — Seconds it waits ahead with the ramp down before leaving.
  • inside: number — Seconds the car rides inside.
  • tolerance: number — Lateral alignment tolerance for driving in, world units.
  • civilianCancels?: boolean — Killing a civilian cancels the called van (Spy Hunter's lamp goes out). Default true.
  • medium?: "road" — Vans only on these media. Default road.

VehicleKindDef

interface VehicleKindDef

A kind of vehicle the session can spawn.

  • role: "enemy" | "civilian" — Enemies score when destroyed; civilians cost NO POINTS.
  • medium: Medium — Road, river or air.
  • width: number — Body size, world units.
  • length: number — Body length along the road in world units.
  • mass?: number — Relative mass for ramming. Default 1.
  • score?: number — Points when destroyed. Default 0.
  • speed: readonly [number, number] — Cruise speed range as a fraction of the player's top speed.
  • top?: number — Top speed as a fraction of the player's top speed. Default 1.1 x the cruise maximum.
  • armour?: Armour — Immunities.
  • ai: AiDef — Behaviour.
  • enter?: "ahead" | "behind" | "either" — Where it enters: ahead (overtaken by the player), behind (catches up) or either. Default ahead.
  • hits?: number — Hit points against bullets. Default 1.

WeaponDef

interface WeaponDef

A player weapon.

  • kind: "gun" | "cannon" | "slick" | "smoke" | "missile" | "flame" | "mine" — What it does: forward guns, a forward cannon, a rear oil slick, rear smoke, anti-air missiles, a rear flame, rear mines.
  • label: string — HUD lamp label.
  • supply: number | null — Supply when issued: shots, uses or seconds of spray (see unit); null is unlimited.
  • unit: "uses" | "seconds" — What supply counts.
  • rate?: number — Shots per second while held (guns, cannon, flame ticks). Default 8.
  • speed?: number — Projectile speed relative to the car (guns, cannon, missiles).
  • life?: number — Projectile life, seconds (its range).
  • radius?: number — Projectile radius. Default 1.5.
  • hits?: readonly Medium[] — Targets it can hit. Guns: road and river; missiles: air.
  • pierce?: number — Hits beyond the first (cannon). Default 0.
  • homing?: number — Homing turn rate, rad/s (missiles). Default 0.
  • width?: number — Patch size for slick, smoke, mines and flame (world units).
  • length?: number — Patch length along the road in world units.
  • patchLife?: number — Patch life, seconds.
  • blind?: number — Seconds a vehicle is blinded by smoke. Default 1.5.
  • damage?: number — Damage per hit. Default 1.