SCRAPLINE — full game design
Why the game is shaped the way it is: rules, economy, units, resolution,
spectator presentation, bot experience, league fit, and the playtest plan
that validates it. This document explains; it does not bind. Where it and
GAME-SPEC.md disagree, the spec wins and the disagreement is a bug.
Where it comes from. A modular-fleet RTS — mirrored grid, energy economy, chassis plus modules, HQ kill, simultaneous ticks — shaped by three research tracks (competition history, spectator and broadcast design, RTS mechanics evidence; findings in the appendix), by the measured pathologies of a predecessor league (three weeks of instrumented scars), and by four standing league decisions: divisions with promotion/relegation · an original game · one participant class on equal terms · bot vs bot, always. The name is the salvage endgame, which is the game’s signature.
1. The five pillars
- The score is the screen. Every quantity that decides the game is drawn as physical material: HQ integrity as blocks that shatter, cargo as visible load, energy fields that dim as they drain, wrecks that accumulate where battles happened. A stranger reads the match in 5 seconds; no overlay is load-bearing. (Splatoon/Clash Royale/BattleBots evidence: destruction and material read better than bars and numbers.)
- Damage ratchets. The HQ can never be repaired. Every point of progress toward the win is permanent, so games structurally end. (A predecessor’s 4.7:1 heal edge and 96-round stalemates, inverted.)
- The ground runs dry. Energy is finite. Home fields deplete around mid-game, and from then on the richest energy on the map is the scrap of earlier battles — the endgame is fought over the wreckage of the midgame. (StarCraft LotV’s depletion-as-clock, Total Annihilation’s reclaim economy.)
- The lead is the exposure. No rubber-banding, no income handicaps. Comebacks come from the leader’s own mass: expensive rigs drop expensive wrecks, heavy haulers are heavy targets (carried cargo drops at 100%). (Dota’s bounty-scales-with-net-worth; rubber-banding research: handicaps read as rigged and punish skill.)
- Deterministic, simultaneous, fully visible. The engine is a pure function of (bot A, bot B, map). No randomness anywhere, including conflict resolution. Full information — no fog. Both bots act simultaneously each tick; there is no first-mover.
2. The game at a glance
| Players | 2 bots, one program each, same act(observation) → orders contract |
| Board | 24×24 grid, 180°-rotationally symmetric, impassable asteroid chokes |
| Match length | 300 ticks hard cap (~2–4 min broadcast at 2–4 ticks/sec; faster headless) |
| Win | Destroy the enemy HQ (500 HP, never repairable) |
| At tick 300 | Tiebreak chain: HQ damage dealt → energy collected → draw (draws are legal; soccer scoring 3/1/0 in the league) |
| Economy | Finite energy nodes + battlefield scrap (60% of a dead rig’s cost) + a +1/tick trickle |
| Units | 3 chassis × 5 modules, max 16 rigs, all designs legal from day one |
| Actions | One order per rig per tick: MOVE / FIRE / MINE / TRANSFER / RESTORE / IDLE; HQ: BUILD |
| Crash | Missed tick = all rigs IDLE, loudly marked; never a forfeit |
3. The arena
- Grid: 24×24. Maps are generated, not hand-made, by a parameterized generator that enforces 180° rotational symmetry — both bots get identical geometry by construction. The generator’s parameters (node richness, node split between home and center, choke density, HQ separation) are the map variety axis, and map class is a first-order variable: the league’s census set must span it deliberately, exactly as the predecessor’s gap-band law required.
- HQ: a 2×2 structure per side at mirrored positions. All distances in the spec are measured from the nearest tile of the footprint (the predecessor’s anchor-corner error, legislated away). Displayed as 25 blocks of 20 HP; blocks shatter permanently and visibly — the two part-ruined HQs are the match’s health bars and its story.
- Asteroids: impassable terrain forming 2–4 corridors. They block movement only — weapons fire over everything (one rule, no line-of-sight subsystem; a predecessor’s never-blocked hitscan ray was fine).
- Energy nodes: glowing fields that visibly dim as they drain. Per
side: two home nodes (600 energy each) near the HQ; on the center
line: contested nodes totalling 2,100 energy (600 / a 450-pair
straddling the exact center, since 180° symmetry on an even grid has
no single center tile / 600 — normative layout in
GAME-SPEC.md). Total map energy is finite and known. - Scrap piles: created where rigs die (60% of build cost, plus 100% of any carried cargo). Persistent, never decay, minable by anyone — the board accumulates the match’s history, and battlefields become mining sites.
4. Economy
- Starting bank: 150 energy (two opening rigs’ worth — enough to open double-miner, miner + fighter, or a rush; the opening build order is a real decision from tick 0).
- Trickle: HQ produces +1 energy/tick unconditionally. This is crash insurance and comeback floor — deliberately below one drill’s yield (5/tick), so it funds nothing on its own. (AoE2’s relic trickle ≈ one worker is the precedent; the user’s draft had +2 — halved so a turtle cannot live on it. Playtest knob.)
- Mining: a rig with Drill modules, orthogonally adjacent to a node or a scrap pile, MINEs +5 energy per drill per tick into its own cargo hold (+30 hold per drill).
- Depositing: automatic and free whenever a cargo-carrying rig is adjacent to its own HQ footprint. Deposited energy = banked.
- Transfers: TRANSFER moves up to 30 energy to one adjacent friendly rig. Bucket-brigade relays are therefore possible but cost a rig’s action every tick — expected to be a niche tool, not a dominant structure. (A predecessor’s conveyor pathologies argue against privileging static chains; if playtests show relays are strictly dead, that is acceptable dead space.)
- The depletion clock: two home nodes = 1,200 energy; a standard double-drill miner extracts 10/tick. A one-base bot mines out around tick 120–150 of 300 — after which it must contest the center, mine scrap, or starve. This is the anti-turtle clock and it needs no timer rule. (LotV’s halved patches, built to force expansion, are the direct precedent.)
- Salvage (cut and restored by user decision, both 2026-08-25): a destroyed rig leaves a scrap pile worth 60% of its build cost, plus 100% of its carried cargo, where it died. Scrap is mined like a node. Sized honestly: at 15–30 rig deaths a game this is ~600–1,300 energy — 15–30% of the whole map economy, nearly ALL income after the nodes dry (~tick 150), and a recycling ceiling of ~2.5× military throughput if every wreck is swept. It is the dominant endgame economy, not a garnish. Two recorded risks: the field-holder collects (so wreck value is a comeback mostly in defensive battles), and graveyard churn can extend the grind. The red-team sweep is therefore 60 → 30 → 0, gated on endgame health: median length ≤260 and tiebreak share ≤40% at the shipped value. (FAF wrecks return 81%, TA made reclaim central; keeping it under 100% keeps war lossy so the world still winds down.)
5. Rigs — chassis, modules, and the counter matrix
Design goal: a modular system whose combinatorics create real fleet identity, without converging on one Pareto-optimal build. Research verdict on free-form modularity (Warzone 2100, Gladiabots): it collapses to one meta build unless counters live on a defender-side class the attacker cannot change mid-fight. So: the chassis is the counter class, Brood War style, in exactly six numbers.
Chassis (the defender-side class)
| Chassis | Cost | HP | Speed | Slots | Silhouette |
|---|---|---|---|---|---|
| Light | 20 | 60 | 2 | 1 | small, darting |
| Medium | 30 | 100 | 1 | 2 | the standard rig |
| Heavy | 60 | 200 | 1 | 3 | broad, slow |
Three chassis = three instantly readable silhouettes on screen (the Clash Royale shape-language rule) and three collision weights (§6).
Modules (20 energy each)
| Module | Function |
|---|---|
| Blaster | Range 2 (Chebyshev), 24 damage/tick — ×1.0 vs Light, ×0.5 vs Medium, ×0.25 vs Heavy/HQ |
| Lance | Range 3, 16 damage/tick — ×1.0 vs Heavy/HQ, ×0.75 vs Medium, ×0.5 vs Light |
| Drill | +5 mining/tick, +30 cargo hold |
| Booster | +1 speed (speed cap 3) |
| Repair | RESTOREs one adjacent friendly rig 10 HP/tick at 1 energy per 2 HP, only if the target took no damage in the last 5 ticks |
That multiplier table is the whole balance core: six numbers (Brood War’s damage-type × size matrix — 100/75/50 and 100/50/25 — stolen directly). Blasters shred swarms and barely scratch armor; Lances crack armor and whiff at swarms; the HQ counts as Heavy, so the Lance is also the siege weapon. No loadout wins every matchup, because the matchup is decided by the enemy’s chassis mix.
Repair, made safe by construction (the predecessor’s stalemate, priced out): repair is slower than any weapon (10 HP/tick vs 16–24), costs energy, costs the medic’s action, cannot happen under fire (the 5-tick rule deletes combat healing), and can never touch the HQ. It is a between-fights recovery tool that rewards winning engagements.
The standard rigs (caster vocabulary, starter-kit gallery)
| Name | Build | Cost | Role |
|---|---|---|---|
| Wasp | Light + Blaster | 40 | cheap swarm attacker |
| Courier | Light + Drill | 40 | fast expedition miner |
| Ghost | Light + Booster | 40 | speed-3 scout / blocker |
| Miner | Medium + 2 Drills | 70 | workhorse harvester (10/tick, 60 hold) |
| Trooper | Medium + 2 Blasters | 70 | anti-swarm line fighter |
| Pikeman | Medium + 2 Lances | 70 | anti-heavy / siege line |
| Skirmisher | Medium + Blaster + Booster | 70 | raider, hauler-hunter |
| Medic | Medium + Repair + Booster | 70 | mobile between-fights repair |
| Barge | Heavy + 3 Drills | 120 | 15/tick, 90-hold super-miner — and the juiciest piracy target in the game |
| Juggernaut | Heavy + 3 Lances | 120 | siege platform (48/tick vs HQ) |
| Bastion | Heavy + 2 Blasters + Repair | 120 | escort anchor |
Fleet cap: 16 rigs, shown on screen as pips. A visible hard cap, not a hidden cost-scaling multiplier — a predecessor’s covert +20% per-unit price scale is exactly the kind of invisible rule this design bans.
Building: the HQ issues one BUILD per tick; the rig assembles visibly as a ghost on a chosen free tile adjacent to the HQ and activates after cost/10 ticks (a Wasp in 4, a Juggernaut in 12). The ghost is visible to both bots and the audience — production telegraphs, which is both fair (full information) and dramatic (the siege platform taking shape IS the tension beat).
6. Tick structure and resolution
Each tick, in strict phase order, everything simultaneous within a phase:
- Broadcast: both bots receive the full state (all positions, HP, cargo, banks, node remainders, build ghosts — no fog, no hidden information except the opponent’s code).
- Orders: each bot submits one order per rig + optionally one BUILD. A missed/crashed tick = all rigs IDLE, marked loudly in the replay. Never a forfeit. (Battlesnake’s graceful-degradation rule.)
- Movement + collisions: all MOVEs resolve at once. Conflicts are
settled by the mass rule — deterministic, order-free, no dice:
- Two rigs end on the same tile (or swap through each other, which counts as the same thing): the heavier chassis survives and takes 40 damage; the lighter is destroyed (drops scrap + cargo on the spot). Equal class: both are destroyed. Applies to allies too — your traffic jam is your bug, and it is loud.
- Moving into a stationary rig or asteroid: the mover stays put (a visible bounce). (Screeps’ soft random collisions created a notorious traffic- management tax; Halite III’s all-die rule and Battlesnake’s longer-snake-wins are the clean precedents — this is Battlesnake’s rule with chassis weight as the public stat. It also creates the ram: a 40-energy Wasp trades itself into a wounded Juggernaut, and a Heavy can plow through a light screen. Attacking pays even with no gun.)
- Combat: all FIREs resolve simultaneously; damage from this tick’s shots is computed against positions after movement, then applied at once. A target that moved out of range produces a visible whiff. Rigs at ≤0 HP die together (mutual kills are possible and legal) and drop scrap + cargo where they stood.
- Economy: MINE, TRANSFER, RESTORE resolve; adjacent cargo auto-deposits; trickle ticks.
- Production: build ghosts advance; finished rigs activate.
One order per rig per tick means acting and moving are mutually exclusive — the rule that quietly taxes kiting (a Skirmisher that repositions every tick deals zero damage) and makes speed a positioning tool rather than an untouchable-DPS exploit.
7. Winning
- HQ destroyed → instant win. If both HQs die on the same tick, the tiebreak chain below decides.
- Tick 300, in order: more HQ damage dealt → more total energy collected → draw.
Draws are legal and league-scored soccer-style (3 / 1 / 0). A
deterministic engine playing two perfectly mirrored bots on a symmetric
map should draw — pretending otherwise means a coin flip, and the
A predecessor’s seven-value win_condition taught us to enumerate every outcome
honestly. Damage-dealt comes first in the chain so that a bot that
never attacks can never win a close game — the tiebreak itself is an
anti-turtle rule. (The user’s draft broke ties on net worth; that
rewards mutual mining races — the gardeners’ pathology at the meta level
— so collected energy is demoted to second.)
The anti-turtle stack (all structural, no patches)
- Home nodes deplete by ~tick 150 — staying home means starving.
- HQ damage is permanent — every probe is progress that keeps.
- Damage-dealt-first tiebreak — passivity cannot win close games.
- Salvage sits where battles happened — post-depletion income is at the front, never at home.
- The trickle (+1) funds nothing.
No shrinking zone, no sudden-death timer — the BR-zone research shows forcing clocks work but breed edge-riding degeneracy; depletion does the same job inside the economy itself.
The comeback stack (all earned, no handicaps)
- Wreck bounty — killing the leader’s Juggernaut leaves a 72-energy scrap pile (Dota’s bounty logic), with the honest caveat that the field-holder collects, so this pays mostly in defensive battles.
- Cargo piracy — the leader hauls more, and carried cargo drops at 100% where the hauler dies: the lead is visible mass in transit.
- Counter-matrix exchanges — a smaller fleet with the right chassis mix wins trades against a bigger wrong one.
- The depletion clock drags the leader out of their half to keep earning — exposure rises with appetite.
- Nothing else. No income boosts, no position-indexed powers — in a skill league, manufactured comebacks read as rigged (rubber-banding research) and punish the better bot.
8. Spectator and broadcast design
The 12-item broadcast checklist from the research, applied:
- One static screen. 24×24 fits whole; no camera, no auto-director.
- Four material reads, no overlay needed: HQ blocks (shattered blocks never heal), cargo drawn as stacked cubes on rigs (risk-in-transit is visible mass), nodes dimming as they drain, scrap piles accumulating where the fighting was. Three chassis silhouettes in two team colors.
- Persistent score strip (the Fox Box / eval-bar rule): paired HQ integrity + energy collected, derived only from visible material — it lags the action slightly, which preserves suspense (the documented eval-bar failure mode is a search-driven bar that spoils the game).
- Lead-history sparkline under the strip: comebacks become legible as a shape, and the absence of rubber-banding is verifiable by the audience.
- Intent layer, audience-only: every order is renderable (FIRE draws the beam, BUILD shows the ghost), and each bot may attach one ≤40-char intent string per tick (“massing lances”, “raiding their barge”) shown to viewers and casters, never to the opponent. Optionally each bot reports a self-estimated win probability — the OpenAI Five “2.9% and the crowd went wild” dial.
- Pace: 300 ticks at 2–4 ticks/sec = a 75–150 second core match, 3–5 minutes cast with intro — BattleBots bout length, deliberately. Census matches run headless at full speed.
- Identity: team names, colors, cosmetic hull skins, career records, and the humans behind the bots as the storyline — Battlesnake’s proven lesson that the developers are the characters.
- Replay viewer (first-class, not an afterthought — Halite’s organizers rated it their most important feature): JSON event stream, timeline scrub, speed control, round-snapping, spoiler-free mode, and jump-to-swing (auto-highlight = the ticks of maximum score-strip movement).
9. The bot experience
- Contract: one function —
act(observation) → orders— called every tick for both bots simultaneously. Python only in the pilot (league decision #3), one starter kit. - Ten minutes to first match (Halite’s explicit, measured target): the starter kit ships a working default bot (build two Miners, mine the nearest node, add Troopers, attack when the bank allows), a local runner, and the replay viewer. A newcomer edits one function and watches their change play the same evening.
- All rules published day one (CodinGame’s lesson: progressive presentation, never progressive information): the starter guide teaches four standard rigs and ignores the matrix; the full reference is one page away. Nothing is unlockable knowledge.
- Observations, not interpretations (a predecessor’s API scar, nine instances of it): the observation carries raw facts — positions, HP, cargo, ownership — never derived judgements. Any predicate a bot needs, it computes itself. No query in the API can throw for asking about something visible; everything visible is in the snapshot.
- Compute: a fixed per-tick budget, generous enough that forward simulation is a real strategy (the engine is deterministic and the rules are cheap — rollouts are the intended top-division skill), tight enough to bound match time. Budget enforcement must be deterministic and hardware-fair: official matches replay-verified on reference hardware, and a bot’s timeout behaviour is IDLE-that-tick, never forfeit. Matches with infrastructure faults above a threshold are excluded from standings as measurement error — Halite’s 24–59% server timeout pollution is the cautionary precedent.
- Determinism guarantee: same bots + same map = same game, bit for bit. Any protest is resolved by replaying the match.
10. League integration
From the league plan (now LEAGUE-RULES.md), bound to a concrete game:
- Census format: divisions of 10 play full double-round-robins over a stratified map set spanning the generator’s parameter space (node richness, HQ separation, choke density) — the map-class law. Both “sides” are played per pairing despite rotational symmetry (defense in depth against any asymmetry bug — the predecessor’s side-bias lesson).
- Scoring: 3/1/0 with draws legal. Tiebreak on head-to-head, then aggregate HQ-damage differential — never a coin flip.
- Season spec freeze (Battlecode’s most-repeated complaint, legislated): the rules and all numbers freeze at season start. Balance changes happen between seasons, with a published changelog and a red-team report justifying each number.
- Entry: to join the bottom division, beat the Doorman — a public boss bot slightly stronger than the starter kit (CodinGame’s beatable- boss gate). It filters broken bots, not people.
- Promotion/relegation: as per the league plan (2 auto + 1 playoff), decided only on census results, never on a ladder snapshot — the documented CodinGame/Russian-AI-Cup noise lesson.
- Engine open-source from day one. Every dead competition in the research died of sponsor economics, not player loss (Halite, Terminal, Russian AI Cup); Battlesnake survived its own company’s exit only because the engine was open and cheap. Open engine + community-runnable matches is the league’s survival insurance.
11. Balance validation — the red-team plan
The method, applied from day one: every degenerate strategy the design fears gets an archetype bot built to embody it, and every knob gets a gate. No number above ships on argument alone.
| Archetype | Embodies | Gate it must pass |
|---|---|---|
arch_turtle |
max defense, never leaves home | loses ≥90% vs the balanced reference; its games still end ≤300 ticks |
arch_rush |
all fighters from the opening bank | ≤55% vs balanced reference on every map class (esp. short-HQ-distance maps) |
arch_greed |
pure economy, minimal military | beats arch_turtle; loses to balanced — economy alone must not free-win |
arch_pirate |
all Skirmishers, hunts haulers | strong vs arch_greed, weak vs escorted play — escorts must be the counter |
arch_deathball |
one composition, massed | a mixed counter-composition of equal cost beats it — the matrix gate |
arch_swarm |
maximum Wasps | Troopers counter at ≥2:1 cost efficiency; Lance-only fleets lose to it |
arch_relay |
bucket-brigade logistics | measured, not gated — establishes whether relays are niche or dead |
Tuning targets (measured on the archetype tournament + reference bots, per map class, never pooled):
- Median game length 180–260 ticks; ≥60% of decisive games end by HQ kill, not tiebreak.
- First combat contact: median ≤ tick 60.
- Comeback rate: winner was behind on energy collected at tick 150 in 15–30% of decisive games (below = snowball problem, above = leads are meaningless).
- The ghost test, formalized: every reference bot replayed against a non-interacting ghost must change outcome or ≥30% of its collected energy — interaction is measured, not assumed.
- No archetype above 60% against the balanced reference anywhere.
The knob table (every open parameter, its owner-question, its gate): the salvage rate (60 — sweep 60/30/0, gated on median length ≤260 and tiebreak share ≤40%), trickle (+1 — comeback floor vs turtle fuel), collision damage to the survivor (40), the six matrix multipliers, node sizes and split, spawn delay divisor (10), fleet cap (16), repair rate (10) and its 5-tick combat lockout, starting bank (150). Each gets a sweep in the red-team tournament before Season 0, and the sweep must show an interior optimum — a knob that is best at the end of its range is a design smell (the parameter law).
12. Two defaults that were argued, and the gates that would change them
Neither is a proof. Both are recorded here so that if the meta argues with them, the argument is against a written position rather than a habit.
HQ repair: OFF. The population-scale evidence is from one predecessor league (its whole top-16 converged on heal-don’t-fight under a repairable objective), which is suggestive, not conclusive; the independent evidence (MOBA towers, Clash Royale towers, BattleBots’ persistent-damage finding) supports the ratchet, while StarCraft and AoE show repair can coexist with health when other clocks carry the game. If it is ever wanted, it goes in behind a flag as either the scar rule (repair permanently lowers max HP) or the opportunity rule (repairing blocks that tick’s BUILD), and the archetype gates decide: turtle still loses ≥90%, ≥60% of decisive games still end by HQ kill, median length ≤260. Starting OFF is also the reversible direction — adding repair later is additive, removing it later breaks metas.
Match length: 300 ticks. Sized to where a predecessor’s games naturally resolved (median decisive game ~200–250 rounds; the 1000-cap games were the stalemates, at 5× the compute). The gate that would change it: if >40% of decisive games end on tiebreak, or games regularly hit the cap mid-arc (armies fielded, energy still in the ground), raise to 400 — and scale total map energy proportionally, so it lengthens the contest and not the grind. HQ HP is not the length knob: a predecessor’s grind measurement (60 rounds of decided-outcome siege against a 22-round ceiling) shows extra HP extends the worst phase. HQ HP’s real job is rush pricing.
Appendix — research findings behind the decisions
Competition history (Battlecode, Halite, Screeps, Battlesnake, CodinGame, Lux, Terminal, Russian AI Cup, Gladiabots, Bot Bowl, aiarena.net): under-10-minute setup is the participation dial (Halite, whose organizers’ paper names starter kits >80% of users and the replay viewer as the most important feature); crashes must degrade gracefully and infrastructure faults are measurement error (Battlesnake; Halite’s 24–59% timeout pollution); mid-season balance patches are the longest-running event’s most-repeated complaint (Battlecode); ladders are noisy — decide standings on round-robins or paired games, never snapshots (CodinGame, Russian AI Cup, Lux S3); persistent worlds with purchasable compute generate permanent grievance (Screeps); dice-heavy games kill both search and learning entries (Bot Bowl); competitions die of sponsor economics, so the engine must be open source (Halite, Terminal, Russian AI Cup, Battlesnake).
Spectator design: the always-on score strip is broadcasting’s most copied invention (Fox Box 1994; chess eval bar), but must derive from visible material or it spoils outcomes; the score should BE the screen (Splatoon turf, Clash Royale towers); physical persistent destruction out-reads any health bar (BattleBots, where damage is legible enough to be the scoring system); swarms need either a director or a board that fits one screen (StarCraft observer research vs Clash Royale); bot introspection is a drama engine (OpenAI Five’s win-probability moment); identity and developer storylines carry machine competitions (Battlesnake’s 50k+ non-programmer viewers); replay viewers need scrub, speed, spoiler-free, and jump-to-event (generals.io, Halite/Chlorine).
Mechanics evidence: counter systems stay cyclic only with hard, defender-side multipliers — Brood War’s six numbers, AoE2’s bonus ≈ 5× base, ≥2:1 in-matchup cost efficiency (Game Developer, “In Defense of Hard Counters”); free-form modularity converges to one build without a class axis (Warzone 2100, Gladiabots’ own developer); depletion forces expansion (LotV’s halved patches, by stated design intent); salvage economies pull fleets to the front and worked (TA, FAF’s 81% wrecks); clean simultaneous resolution is deterministic and order-free — Halite III’s all-die-with-cargo-drop and Battlesnake’s public-stat head-to-head versus Screeps’ random-winner traffic tax; comebacks should route through the leader’s exposure, not handicaps (Dota bounty; Mario Kart’s position-indexed items as the opposite pole; rubber-banding literature on perceived fairness).