The pack
roadPursuit
function roadPursuit(): Pack<{ roadPursuit: typeof api }>
Install the road pursuit API.
Helpers
CHASE_HQ_CARS
const CHASE_HQ_CARS: Readonly<Record<string, TargetCarDef>>
Getaway cars by the ROUND list of Taito's manual (white, yellow, silver, blue, unknown) and the attract specs.
CHASE_HQ_KINDS
const CHASE_HQ_KINDS: Record<string, SceneryKind>
Kinds the race and the pursuit spawn: tyre smoke, dust, sparks, the target's smoke and fire, debris.
CHASE_HQ_MISSIONS
const CHASE_HQ_MISSIONS: readonly MissionDef[]
The five rounds. Briefings follow Nancy's pattern on the arcade's radio monitor (StrategyWiki, the frames).
CHASE_HQ_SCALE
const CHASE_HQ_SCALE: 1.2
Chase H.Q. draws traffic and the getaway cars a little larger than the player's scale. Measured at equal depth on
the arcade frames (REFERENCES.md: width / (base row - horizon row)): the Porsche 0.87, a traffic sports car 1.08
(x1.24), the Lotus 0.98 (x1.13). Drawn widths vw are 1.2 x true; collision boxes stay inside them.
CHASE_HQ_TRAFFIC
const CHASE_HQ_TRAFFIC: TrafficKind[]
Civilian traffic seen on the arcade frames: sports cars, saloons, a pickup, a truck and a bus. Speeds are estimates.
chaseHQPreset
function chaseHQPreset(o: ChaseHQOptions = {}): PursuitConfig
Chase H.Q. as a pursuit configuration.
chaseHQRace
function chaseHQRace(o: ChaseHQOptions = {}): RoadRaceConfig
The race underneath Chase H.Q. (road-racer configuration).
createPursuit
function createPursuit(config: PursuitConfig): Pursuit
Create a pursuit.
leadFromRoad
function leadFromRoad(doc: RoadDocument, entry: string, fallback: number): number
The road file's boss marker carries each round's starting DISTANCE (data.lead): the file is the source of truth.
PURSUIT_ROADS
const PURSUIT_ROADS: Record<string, RoadDocument>
The road files of this folder, by name.
SCI_CARS
const SCI_CARS: Readonly<Record<string, TargetCarDef>>
The getaway vehicles (cars 1 to 3 are not identified by any source: shapes from the frames, names generic).
SCI_MISSIONS
const SCI_MISSIONS: readonly MissionDef[]
Six stages: five arrests and the run to the hideout.
SCI_TRAFFIC
const SCI_TRAFFIC: TrafficKind[]
Civilian traffic.
sciPreset
function sciPreset(o: SciOptions = {}): PursuitConfig
S.C.I. as a pursuit configuration: the gun, the bazooka, the biker gang, a flying target and a reach stage.
sciRace
function sciRace(o: SciOptions = {}): RoadRaceConfig
The race underneath S.C.I.
stepTarget
function stepTarget(t: TargetState, d: TargetDrive, w: TargetWorld): void
Move the target one step.
Classes
Pursuit
class Pursuit
A pursuit. Create with createPursuit(config).
readonly config: PursuitConfig— The configuration the pursuit was created with.race: RoadRace— The road-racer race under the pursuit: the car, road, traffic and field. It is replaced by a new race at the start of each mission.state: PursuitState— The pursuit state the presenter reads; replaced on a restore, so read it afresh each frame.riders: RiderState[]— The gang riders on the road now.constructor(config: PursuitConfig)get mission(): MissionDef— The mission being played.start(): void— Start from attract: the first mission's briefing.tick(dt: number, input: PursuitInput = {}): void— Advance bydtseconds of wall time (fixed steps inside, at most 0.25 s per call). Presses are latched.drain(): PursuitEvent[]— Events since the last drain.get speedDisplay(): number— Speed in the vehicle's display units.scene(base?: { back: number; fov: number }): PursuitScene— What to draw: the race's scene, plus the turbo camera over the view's camera (base: the view'sbackandfov; road-view-pseudo3d'sRoadScene.camera).step(input: PursuitInput = {}): void— One fixed step.snapshot(): PursuitSnapshot— A plain copy of the whole pursuit.restore(s: PursuitSnapshot): void— Restore a snapshot taken from a pursuit with the same config.
Types
ChaseHQOptions
interface ChaseHQOptions
Options for chaseHQPreset.
difficulty?: Difficulty—"easy","normal"or"arcade". Default"normal".seed?: number— Seed for the pursuit's random choices. Default 1988.road?: RoadDocument— Another road file with the same entries (stage-1..stage-5).timer?: number— The timer DIP: 55, 60 (factory), 65 or 70 s. Default by difficulty (easy 70, normal 65, arcade 60).turbos?: number— The turbo DIP: 3 (factory) or 5. Default by difficulty (easy 5, normal and arcade 3).startStage?: number— Start at this round (1-based).
ContinueDef
interface ContinueDef
The continue: after the clock runs out, a count during which a credit carries on from the same spot.
countdown: number— Seconds of the CONTINUE count.clearDamage: boolean— Damage on the target is cleared on a continue (the factory DIP) or carried over.max: number— Continues per game (-1 unlimited).
ForkWay
type ForkWay = "left" | "right" | "random"
Which branch at a mission's fork is the way the target went.
GangDef
interface GangDef
A gang that rides out to stop you before the target (S.C.I.'s motorcyclists): bump them off the road.
kind: string— Sprite kind and collision box.w: number— Collision box width (metres).h: number— Collision box height (metres).d: number— Collision box depth along the road (metres).count: ByDifficulty<number>— Riders per mission (by difficulty).at: number— They appear when the DISTANCE counter is below this (metres).match: number— Their speed relative to yours (m/s, they hang around you), lateral speed (m/s) and how often they lunge (s).lateral: number— Lateral speed (m/s) when a rider moves across the road.lunge: [number, number]— A rider lunges at you every so many seconds, picked between these two (min, max).knock: number— A rider hitting you knocks your speed down by this (m/s).points: number— Points for each rider bumped off (times the stage number).
GunDef
interface GunDef
The partner's gun (S.C.I.: Gibson fires from the roof).
rounds: number— Rounds per credit (-1 unlimited: the S.C.I. pistol).every: number— Seconds between rounds while the button is held.speed: number— Round speed relative to your car (m/s).range: number— Range (metres).damage: ByDifficulty<number>— Damage of a round on the target.lock: { range: number; window: number }— The gunsight locks onto the target within this range (metres) and this lateral window (metres): rounds fly at it.points: number— Points for a round on the target (times the stage number).
HeavyDef
interface HeavyDef
A heavy weapon dropped by the helicopter (S.C.I.'s bazooka): limited rounds, far stronger than the gun.
rounds: number— Rounds in each drop.damage: ByDifficulty<number>— Damage per round (by difficulty).every: number— Seconds between rounds.dropAt: number— The drop comes once you are within this distance of the target, landingaheadmetres in front of you.ahead: number— Metres in front of you where the drop lands.
MissionDef
interface MissionDef
One mission: a criminal, a getaway vehicle, a road, a fork.
id: string— Unique name of the mission (such as"courier"); error messages quote it.stage?: number— Stage number shown and used for scoring (1-based). Default its place inmissions.kind?: "arrest" | "reach"—arrest(catch and immobilise the target) orreach(S.C.I.'s last stage: reach the end against the clock).criminal: string— The criminal ("RALPH, THE IDAHO SLASHER").charge: string— "OK! You're under arrest on suspicion of ...".briefing: string[]— The dispatcher's radio briefing, line by line.frequency?: number— The radio frequency on the briefing monitor (MHz).car?: TargetCarDef— The getaway vehicle (arrest missions).entry: string— A road-data entry of the road file to start from.lead: number— DISTANCE at the start (metres).approach: ByDifficulty<number>— How far ahead of you the target notionally travels while out of sight (m/s): DISTANCE closes at your speed minus this.fork?: { way: ForkWay; detour: number; helicopter?: boolean } | null— The fork: which way the target went (the arrow), the extra DISTANCE for the other way, and a helicopter showing the way.time?: ByDifficulty<number>— Override the chase clock (S.C.I.'s last stage: 30 s).turbos?: number— Override the turbos for this mission (S.C.I.'s last stage: 1).noContinue?: boolean— No continue in this mission.drive?: Partial<TargetDrive>— Override the drive.gang?: boolean— A gang rides out in this mission.heavy?: boolean— A heavy weapon is dropped in this mission.
PursuitClock
interface PursuitClock
The clocks.
chase: ByDifficulty<number>— Seconds to catch up (DIP: 55 / 60 / 65 / 70; 60 factory).extend: ByDifficulty<number>— Seconds added (or set) when the target is sighted (the DIP value again).extendMode: "add" | "reset"—addthe extension to the time left (the US manual) orresetthe clock to it.sight: number— The target counts as sighted within this distance (metres).warning: number— The dispatcher warns that time is running out at this many seconds.max?: number— Cap on the clock.
PursuitConfig
interface PursuitConfig
A whole pursuit game.
name: string— Display name of the game ("Chase H.Q.").difficulty: Difficulty—"easy","normal"or"arcade": picks the value of every by-difficulty setting.seed: number— Seed for the pursuit's own random choices (the target's weave, the gang's lunges, a random fork); the same seed and inputs replay the same pursuit.race: RoadRaceConfig— The race underneath (road-racer): the road file (one entry per mission), the vehicle (its turbo is a timedboostwithcharges), traffic, crashes and the race's distance score. The pursuit replaces its clock start and entry per mission, and scores overtakes itself.missions: MissionDef[]— The missions in order; at least one. An arrest mission needs acar, and every mission aleadabove 0.clock: PursuitClock— The chase clock.drive: TargetDrive— How the getaway vehicle drives (a mission may override parts).ram: RamDef— Ramming and the arrest.turbos: ByDifficulty<number>— Turbos per mission and after a continue (the vehicle'sboost.chargesis replaced).gun?: GunDef | null— The partner's gun. null or left out: no gun.heavy?: HeavyDef | null— The heavy weapon a helicopter drops (in missions that setheavy). null or left out: none.gang?: GangDef | null— The gang of riders (in missions that setgang). null or left out: none.scoring: PursuitScoring— Points for overtaking, hits, clears and bonuses.continue: ContinueDef— The continue after the clock runs out.smash?: { slow: number; points: number } | null— Field kinds that smash out of the way when driven through (barriers, garbage cans), slowing you byslow(0..1).scrape?: number— Tunnel walls: scraping one costs this fraction of your speed per second and throws sparks.briefingTime: number— Seconds of the radio briefing (any button skips it). The arrest scene lasts at mostram.arrestTime.clearTime: number— Seconds the clear tally is shown after an arrest, before the next mission starts (or the all-clear bonus is awarded).turboCamera?: { back: number; fov: number; ease: number } | null— Turbo camera: while a turbo burns the camera drops backbackmetres and widens byfovdegrees, easing in and out overeases.
PursuitEvent
type PursuitEvent = | { type: "briefing"; mission: number; criminal: string } | { type: "mission"; mission: number; stage: number } | { type: "go" } | { type: "sighted"; time: number } | { type: "warning" } | { type: "turbo"; left: number } | { type: "turbo-end" } | { type: "hit"; damage: number; side: boolean; points: number; spin: boolean } | { type: "shot"; damage: number; points: number; heavy: boolean } | { type: "fire"; heavy: boolean } | { type: "fork"; right: boolean; detour: number } | { type: "smash"; kind: string } | { type: "scrape" } | { type: "overtake"; points: number } | { type: "rider-down"; points: number } | { type: "drop" } | { type: "pickup"; rounds: number } | { type: "arrest"; criminal: string; charge: string } | { type: "clear"; time: number; timeBonus: number; clear: number } | { type: "time-up" } | { type: "continue"; countdown: number } | { type: "continued" } | { type: "escaped" } | { type: "game-over" } | { type: "complete"; bonus: number } | { type: "race"; event: RaceEvent }
Events for the presenter and sound.
PursuitInput
interface PursuitInput extends RaceInput
What the player does this step.
turbo?: boolean— Turbo button (a press fires one turbo).fire?: boolean— The partner's gun (held).start?: boolean— Start / continue / skip the briefing (a press).
PursuitPhase
type PursuitPhase = "attract" | "briefing" | "chase" | "arrest" | "clear" | "continue" | "over" | "complete"
Phases of a pursuit.
PursuitScene
type PursuitScene = RaceScene & { camera?: { back?: number; fov?: number } }
What scene() adds to the race's scene: the turbo camera over the view's camera.
PursuitScoring
interface PursuitScoring
Scoring of a pursuit (the race scores distance; this is the rest). Points marked "x stage" multiply by the stage.
overtake: { start: number; step: number; max: number }— Overtaking traffic:startpoints,stepmore each car passed without a crash, up tomax(Chase H.Q.: 200, 200, 8,000).hit: number— Each hit on the target (x stage).clear: number— Clear bonus at the arrest (x stage).perSecond: number— Time bonus per whole second left at the arrest.allClear: number— Bonus for clearing every mission.continued: number— Points scored in a stage after a continue are divided by this (Chase H.Q.: 10).
PursuitSnapshot
interface PursuitSnapshot
A saved pursuit: plain data.
state: PursuitState— The pursuit state.internal: Internal— Counters and flags the pursuit keeps besides the state: timers, spawned-object ids and what has happened this mission.riders: RiderState[]— The gang riders on the road.race: RaceSnapshot— The race underneath, as road-racer saves it.events: PursuitEvent[]— Events not yet drained.acc: number— Seconds ofticktime not yet spent in fixed steps; less than one step (1/60 s).
PursuitState
interface PursuitState
The pursuit state the presenter reads.
phase: PursuitPhase— Where the pursuit is: briefing, chase, arrest and so on.phaseTime: number— Seconds spent in the current phase.mission: number— Mission index (0-based) and stage number (1-based).stage: number— Stage number shown and used for scoring (1-based).time: number— Seconds on the clock.score: number— Points scored so far: the race's distance score plus the pursuit's awards, carried across missions.topScore: number— The best score reached so far.distance: number— DISTANCE to the target (metres; never below 1 once sighted) and the mission's starting lead.lead: number— The mission's starting DISTANCE (metres).sighted: boolean— The target has been sighted this mission (dome light on, siren, damage meter).damage: number— Damage on the target 0..1.turbos: number— Turbos left; seconds left of the turbo burning; 0..1 of the turbo camera.turbo: number— Seconds left of the turbo burning; 0 when none is.zoom: number— How far the turbo camera has pulled back, 0..1, easing in and out overturboCamera.ease.rounds: number— Rounds left (-1 unlimited, 0 none) and heavy rounds left.heavy: number— Heavy-weapon rounds left; 0 until one is picked up.locked: boolean— The gunsight is on the target.continues: number— Continues used, and whether this stage was continued (its points are divided).continued: boolean— Whether this stage was continued, so its points are divided byscoring.continued.countdown: number— Seconds left of the CONTINUE count.chain: number— The overtake chain's next award.award: number— The last award (shown under the score) and seconds since.sinceAward: number— Seconds since the last award was made; Infinity before the first.typed: number— The briefing: characters of the text shown so far.arrow: number— The fork arrow being shown (-1 left, 1 right, 0 none) and the way the target went (-1, 1).way: number— The way the target went at this mission's fork: -1 left, 1 right, 0 when there is no fork.detoured: boolean— Took the wrong branch at this mission's fork.bonus: { time: number; timeBonus: number; clear: number } | null— Bonuses of the last clear (for the tally).target: TargetState | null— The getaway vehicle once it has been sighted this mission; null before that, and in a mission with no car.
RamDef
interface RamDef
Ramming and the arrest. Damage is a fraction of the meter (1 = immobilised).
damage: ByDifficulty<{ rear: number; side: number }>— Damage of a hit to the rear and to the side (Chase H.Q.'s manual: side hits do more), by difficulty.sideOverlap: number— A hit counts as a side hit when the cars overlap sideways by less than this fraction of their mean width.closingBonus: number— Extra damage per m/s of closing speed aboveminClosing, as a fraction of the base damage.minClosing: number— Closing speed (m/s) below which a touch does no damage (a nudge).cooldown: number— Seconds after a hit before another counts.rebound: { drop: number; push: number; time: number }— Your car after a hit: speed to the target's speed minusdrop(m/s), pushedpushm/s away, skiddingtimes.shove: { x: number; z: number }— The target is shoved sideways (m/s) and forward (m/s) by a hit.outsideSpin: { kappa: number; time: number } | null— Hitting it from the outside of a bend spins you out (Chase H.Q.'s manual): on a bend of at least this curvature (1/m), when you are on the outside of the target. null = never.arrestTime: number— Seconds of the arrest: the target pulls over and stops, then the clear.segments: number— Segments of the damage meter (Chase H.Q.: 20), for the presenter.
RiderState
interface RiderState
A gang rider.
id: string— The id of the field object that stands for the rider in the race's scene.z: number— Course position (metres along the course, the race's z).x: number— Lateral position across the road (metres, positive right).speed: number— Forward speed (m/s).hold: number— Its offset from you it holds (metres ahead) and its lateral line.line: number— The lateral position (metres, positive right) it is moving to.lungeIn: number— Seconds until it next lunges at you.down: boolean— Knocked off: tumbling away.
SciOptions
interface SciOptions
Options for sciPreset.
difficulty?: Difficulty—"easy","normal"or"arcade". Default"normal".seed?: number— Seed for the pursuit's random choices. Default 1989.road?: RoadDocument— Another road file with the same entries (stage-1..stage-6).timer?: number— The timer DIP: 55, 60 (factory), 65 or 70 s. Default by difficulty.turbos?: number— The turbo DIP: 3 (factory) or 5.startStage?: number— Start at this stage (1-based).
TargetCarDef
interface TargetCarDef
The getaway vehicle: what it is.
kind: string— Sprite kind in the field (the presenter's art key).name: string— Display name ("WHITE SPORTS CAR").w: number— Collision box (metres).h: number— Collision box height (metres).d: number— Collision box depth along the road (metres).vw?: number— Drawn width (metres) when the art is drawn larger than the box. Defaultw.top: number— Top speed (m/s): it sprints up to this when you are on its tail (Chase H.Q.'s attract specs).cruise: number— Speed while it cruises ahead of you (m/s).flying?: number— It flies (S.C.I.'s stage 5 helicopter): it cannot be rammed, only shot, and it ignores traffic. Height (m).data?: Record<string, number | string | boolean>— Plain values handed to the presenter (colour, art hints).
TargetDrive
interface TargetDrive
How a getaway vehicle drives once it is on the road with you.
pace: ByDifficulty<number>— Multiplier on its cruise and top speeds by difficulty (arcade 1).sprintRange: number— Within this distance behind it (metres) it puts its foot down to its top speed.accel: number— Acceleration and braking (m/s^2).brake: number— Braking deceleration (m/s^2), a positive number.lateral: number— Lateral speed (m/s) when it swerves, weaves and blocks.weave: [number, number]— It picks a new line across the road everyweaveseconds (min, max).blockRange: number— Within this distance behind it it moves across in front of you to block. 0 = never.block: number— 0..1 of the way toward your line it moves when it blocks.lookAhead: number— It swerves around traffic this far ahead (metres).shaken: number— Seconds it swerves away and sprints after a hit.match: number | null— Level with you or behind you it goes this much faster than you (m/s), whatever its top speed: Chase H.Q.'s target cannot simply be overtaken (Japanese Wikipedia). null = it keeps its own top speed.
TargetState
interface TargetState
The getaway vehicle's live state.
id: string— The id of the field object that stands for the vehicle in the race's scene.z: number— Course z and lateral x (the race's frame).x: number— Lateral position across the road (metres, positive right).speed: number— Its own forward speed (m/s), before the shove of a hit is added.line: number— Lateral line it is moving to.weaveIn: number— Seconds until it picks a new line.shaken: number— Seconds left of a hit's swerve and sprint.vx: number— Lateral and forward shove from the last hit (decaying).vz: number— Forward shove from the last hit (m/s), decaying.stopping: boolean— Pulling over for the arrest.
TargetWorld
interface TargetWorld
What the target sees this step.
dt: number— Seconds the step advances.playerZ: number— Your car: course z, lateral x, speed.playerX: number— Your car's lateral position across the road (metres, positive right).playerSpeed: number— Your car's speed (m/s).road(z: number): { left: number; right: number }— Tarmac edges of the road it is on (the strips the race drives).traffic: readonly { z: number; x: number; speed: number }[]— Traffic (course z, lateral x, speed). A flying target passes over it.rng: () => number— Seeded uniform [0, 1).cruise: number— Cruise and top speeds for the difficulty (m/s).top: number— Top speed for the difficulty (m/s).flying?: boolean— It flies (no traffic to avoid).


