Game guide

The HADR game is a deterministic, lockstep, fire-only dispatch simulation. Contacts report fires around a city; you run intake, reconcile the reports into beliefs, and dispatch fire trucks to save lives and buildings. The engine owns hidden truth, emits imperfect evidence, accepts typed vehicle commands, and scores outcomes. It never owns your reports, incidents, reconciliation policy, prompts, or model calls. The typed control surface is documented separately in the API guide.

Objective and measures

Protect people and buildings from fire within the tick limit. The engine reports three measures at the end of an episode:

  • casualties: the fixed occupants of every building that collapsed.
  • buildings_lost: the number of collapsed buildings.
  • tokens: always reported as null. Runtime token cost is participant self-reported and never measured by the engine.

There is no composite score.

Four layers

The engine keeps four values strictly separate; the boundary is enforced in code, not by convention:

  1. Hidden true state: real building, fire, and occupant state that you never see directly during play.
  2. Imperfect contacts: the public evidence delivered to you. A report’s location or claim may be stale, exaggerated, wrong, or a false alarm.
  3. Filed agent beliefs: incidents your code derives from contacts. These live entirely in participant code; the simulator hosts none of them.
  4. Typed actions: dispatch and next_tick, the only ways you change the world.

Hidden truth, imperfect contacts, filed beliefs, and typed actions kept in separate layers

dispatch requires an opaque incident_id, logs and echoes it, and never validates it against any store: filed incidents are your beliefs, and the simulator never sees them. Deterministic reconciliation sits between stateless intake and model-driven dispatch so that reruns are reproducible and auditable.

World mechanics

  • Buildings have fixed occupants and a status of normal, burning, or collapsed. Collapse is irreversible and adds the building’s occupants to casualties exactly once. Extinguishing restores a building to normal with no casualties.
  • Fires grow by a per-tick rate. A stationary truck within the scenario’s suppression radius of a burning building fights the nearest one (ties broken by building ID) and reduces its intensity; multiple trucks stack. A fire that reaches full intensity collapses its building; one driven to zero is extinguished.
  • Fire spread between adjacent buildings is an isolated extension flag, disabled by default for the first release.
  • Trucks have a vehicle_id, a public position, and a status of idle, moving, or firefighting. They have no home station and roam freely; repositioning is just a dispatch to a point.

What you can see

  • A public map with a road graph and building display geometry. Building coordinates come only from converting IDs you learned from contacts; there is no building enumeration or search.
  • Truck vision: each truck truthfully reports the buildings within its radius as a typed observation contact each tick, carrying a per-fire tick countdown for each burning one.
  • Human contacts as evidence, which may be imperfect. Partial observability is the point: uncertainty comes from the contacts, not from sensor noise on truck vision.

Play is lockstep. You reason about a frozen observation for the current tick, queue commands, then call next_tick to advance exactly one tick. An episode ends when it is resolved (no active fires and none scheduled) or hits its tick_limit. Scenarios use published seeds, and you may restart at any time; the same scenario and seed reproduce the same episode.

Difficulty stages

Scenarios share one engine; difficulty stages do not fork simulation code. They change what evidence looks like:

  • Stage 1 delivers perfect structured_report contacts directly.
  • Stage 2+ delivers rendered human_text plus the exact reported location, withholding the canonical claim so intake must extract it.
  • Typed sensor contacts (truck observations) always bypass language rendering.

Every stage runs on the same trap: there are always fewer trucks than fires, suppression is slow so a truck committed to a fire stays on it, and the most crowded building is under-claimed as only medium severity. The fire you lose is the one you never dispatched to, so difficulty is a prioritization-and-reconciliation problem, not a geometry one. Each stage keeps that trap and layers on one new demand:

Stage What makes it hard
1 Nothing is hidden and the reports are perfect. This is as easy as it gets.
2 Reports arrive as panicked human-language calls.
3 Separate calls describe the same fire; they are not always accurate. Merge before you dispatch.
4 Reports contradict each other, and you have to react to changing situations. Revise the plan and redirect a truck if you need to.
5 The ultimate challenge. High call volume, duplicates, false alarms, a wrong address, and callers who misremember when the fire started. Triage signal from noise and trust neither the loudest report nor the stated time.

Display and scoring

An ordinary browser display polls a read-only snapshot. Each scenario sets an immutable display policy: full_state scenarios expose current truth and live metrics for teaching or spectating, while public_only scenarios (including assessment scenarios) show only public facts, so the room display reveals no truth either.

A deterministic greedy baseline, using only public evidence, sits on the scoreboard as the bar to beat. Scoring is honor-system: extraction is graded offline in your own tests against published labeled datasets, the engine has no grading operation and never sees your report schema, and self-reported tokens and model IDs remain visibly unverified and cannot affect the simulation.

The API guide documents the typed control surface, connection rules, every tool, and the error catalogue.

Maps

The @map half of a scenario ID picks one of three cities; the map guide describes each one in full.

Londone Feeladelphia Stockhome
Map of Londone: crooked lanes around a green, a river across the north-east, and a canal through the middle Map of Feeladelphia: a vast street grid along a south-east waterfront, crossed by a canal Map of Stockhome: a radial old-town core ringed by grid districts, wrapped around a bay