Paintbot
Last edited by · ·
Verified against paintbot-v0.7.397 (GV63 / GLORYVERSION 18), 2026-09-11 — see docs/wiki/_era.md.
Paintbot is a paintball game played by AI policies rather than by hand: you
submit a policy — a linux/amd64 Docker image — that drives a Cog, a small
three-wheeled robot, reading the world off a sprite wire as labelled objects
and writing back an 8-bit action mask 24 times a second. This wiki documents
the game's rules, exact numbers and wire schemas; what people learn, ask and
argue about lives on the forum.
The chapters below follow the order a new reader actually asks them in,
one short paragraph and one link each — go read the linked page for the
depth, this page only routes you there. The ## Reference section further
down is the older, deeper digest this wiki used to lead with; it documents
the classic capture-the-flag ruleset specifically and is not yet re-traced
against the live game (see the note at its top).
What is this
Paintbot is a sixteen-seat paintball battle royale played by policies that people write. Nobody is killed — a hit removes hit points, a Cog at zero is tagged out (the broadcast's chrome for the moment is splatted), and the last Cog standing wins the episode. See glossary for every term this page uses.
Why would I care
"My brain fights other people's brains, and that produces a legible testbed for agent behavior." Put your own brain in the field and watch it fight the others; every move it makes is on the record.
→ glory
How it works
The loop, one line: write a policy → it plays episodes against the field around the clock → every deed it pulls off mints Glory → your standing is a decaying average of your recent episodes → watch any episode to see why.
→ episode
What happens in a round
Today's live ladder runs exactly one variant, battle-royale-s2: sixteen
solo seats drop onto one map, a closing zone forces the fight, there are no
respawns, and the round ends the instant one seat is left standing. This
replaced an eight-duo-team version of the same ladder on 2026-09-05 — if you
read anything describing Battle Royale as duo teams, it is describing a
retired build.
How scoring works
An episode runs two ledgers that never read each other: match reward (the
win/loss/draw signal) and Glory (the team spectacle
scoreboard, minted by deeds and stacked by
multipliers). Jackpots are rare and earned, not routine.
Standing is a decaying average of your recent episodes' Glory,
never a single best round or a running max — see docs/wiki/_era.md for
today's exact aggregation setting.
How to build
Download the coworld package, run an episode locally against the bundled
baseline, then package your own policy as a Docker image — the same
artifact shape the platform runs. Nothing about the process is
language-specific.
How to submit
Submitting needs a GitHub account — sign-in is GitHub OAuth only. Once you've built and locally verified a policy, upload it and submit it to a league; the response names what was accepted, what happens next, and where to check on it.
How to read the ladder
Entrants compete in leagues, not single episodes: a round is a scheduled batch of episodes for one division, and your standing rolls up your recent rounds rather than crowning one of them. A champion is not a winner — see glossary for every standings label this wiki can currently define, and which ones it can't yet.
→ round
Reference
Everything from here down documents the classic two-team
capture-the-flag ruleset specifically — it is not a description
of the live battle-royale-s2 ladder, which has its own numbers (for
example 4 hit points per life, not 3 — see damage-and-health) and its
own item/loot economy (see battle-royale-s2). This section used to be
introduced as the wiki's assumed default; it no longer is one. Its own
Quick Facts and Items tables below were re-checked against current source
for this page's 2026-09-11 pass (two stale numbers corrected — see
## Version history); the deeper pages they link out to each carry their
own independent verification status — see docs/wiki/AUDIT.md for which
are still due a full re-trace.
In classic two-team play, two 8-player teams, Red and Blue, spawn on
opposite edges of a symmetric arena (1235×659 px by default) and race to
steal the enemy objective (wire label flag, a heart on screen and in
the broadcast) and carry it into their own capture zone. Winning an episode
pays +1, losing −1, and running out the clock −1 to both sides.
Paintbot also runs other rulesets elsewhere in its engine history; see
modes for what each is called and which ones this wiki documents.
Start here
| Page | What it answers |
|---|---|
| policies | What a policy is as an artifact — a linux/amd64 Docker image plus a run argv, seated by one environment variable |
| baseline-policy | What the shipped, open-source reference policy actually does: its lanes, its roles, and the conditions it branches on |
| submitting-a-policy | The engine's shared wire protocol (see wire) and packaging the image; the platform push itself is build-and-submit |
The policy contract
A policy has no API into the simulation. It receives sprite objects once per tick, matches them by their label string, steers off their positions, and writes back one byte. Four pages define that entire surface.
| Page | The surface it defines |
|---|---|
| perception | What a Cog can see — the fog, the ±60° vision cone around aim, the 90 px omnidirectional bubble, and sound |
| labels | The observation contract — every label string, and which of the two streams (a policy's POV, or the broadcast board) carries it |
| action-mask | The control surface — the eight bits, sent once per tick |
| wire | The literal bytes underneath all three — transport, message framing, and the field names a policy's socket actually carries |
You see only yourself for free. Teammates are fogged exactly like enemies, and there is no team radio; the only channel between Cogs is a 10-character shout, heard by both teams alike.
The eight bits, in full:
| Bit | Value | Button | Action |
|---|---|---|---|
| 0 | 1 | Up | Move up |
| 1 | 2 | Down | Move down |
| 2 | 4 | Left | Move left |
| 3 | 8 | Right | Move right |
| 4 | 16 | Select | Rotate aim clockwise |
| 5 | 32 | A | Fire the gun, or the cone while carrying a spray can |
| 6 | 64 | B | Rotate aim counter-clockwise |
| 7 | 128 | C | Hold to charge a throw, release to throw |
The d-pad is locomotion only and never changes where you aim or look. The browser key bindings are chrome for a human at a seat; the bitmask is what a policy sends.
Traps
Two things here cost people days, and neither announces itself.
There is no engine version handshake at connect. The wire protocol (see
wire for its message shape) carries no version field: GameVersion is a
compile-time constant baked into each
binary, the server never asks a connecting container what it was built against,
and the container never says. An image built against a stale engine connects
cleanly, plays, and produces a match that looks entirely normal and means
nothing — no error, no warning, no signal of any kind. Compatibility is a
provenance question to settle before the container starts, not something either
side can discover once it is running. See policies.
flag is the mechanic; heart is the chrome. The objective's wire label is
flag, and that is the string a policy matches on; the art, the banners and the
broadcast call it a heart (RED HEART STOLEN!). Both are correct, at different
layers, and a policy scanning its observation for heart finds nothing at all.
labels documents a second edge on the same object: the bare <color> flag
is POV-only and never reaches the board, while <color> flag carried never
reaches a POV.
Quick facts (classic ruleset)
| Property | Value | Ticks | Notes |
|---|---|---|---|
| Tick rate | 24 / s | — | Every duration on this wiki converts at this rate |
| Players per team | 8 | — | Red and Blue; Red spawns left, Blue right |
| Lives per player | 3 | — | Out of lives = out for the rest of the episode |
| Hit points per life | 3 | — | 1 removed per bullet; no passive regeneration; battle-royale-s2 runs 4, see damage-and-health |
| Respawn delay | 3.0 s | 72 | Refills hit points to full; no grace period on return |
| Arena size | 1235×659 px | — | Default arena; the arena-large variant is 1606×858 px |
| Fire windup | 0.21 s | 5 | Aim locks at the trigger pull |
| Fire cooldown | 0.5 s | 12 | 1.5 s (36 ticks) while carrying a shield; gun only, spray can untouched |
| Gun range | 1050 px | — | The one fixed range every map ships (map-wide only on the smallest field — bigger maps make closing distance matter); a released shot's aim carries a small Gaussian jitter, so hit resolution is not perfectly deterministic |
| Vision cone | ±60° | — | Centred on aim, unlimited range, plus a 90 px bubble |
| Episode score | +1 / −1 / −1 | — | Win / loss / timeout draw, the draw paid to both sides — classic ruleset only, see round for battle-royale-s2 |
Game mechanics
| Page | What it covers |
|---|---|
| episode | One full match, start to finish — spawn, lives, the two ways it ends, and the score it produces |
| capture-the-flag | The core win condition: stealing the enemy flag off its pedestal and carrying it to your own capture zone |
| arena | Map size, cover layout, the glass panes that block everything but sight, pedestals and capture zones |
| movement | Acceleration, friction, top speed, wall behaviour, and why the d-pad never changes where you aim |
| combat | Windup, release, cooldown, the bullet corridor, and line of sight |
| damage-and-health | Hit points, lives, what refills them, and how shield armor layers on top |
| shouts | 10-character messages, a 247 px radius, one per player per second |
What a Cog can see, the labels it sees things by, and the bits it sends back are grouped under The policy contract above.
Items (classic ruleset)
Every item is taken by touch. Three are carried; a med kit is consumed on the
spot instead. battle-royale-s2 runs its own loot economy on top of this —
see battle-royale-s2.
| Item | Wire label | Effect | Pickup respawn |
|---|---|---|---|
| paint-bomb | grenade | Thrown blast: 2 hit points inside 52 px, teammates and the thrower included | 5 s |
| spray-can | spray can | Forward cone: 3 hit points out to 5 squares (170 px) | 30 s |
| shield | shield | 3 armor hit points, absorbed before the base pool; gun's fire cooldown 3× slower, spray can untouched | 30 s |
| med-kit | med kit | Refills a hurt player to their full hit point ceiling on touch | 30 s |
Scoring and progression, in depth
| Page | What it covers |
|---|---|
| scoring | Match reward — the +1 / −1 / −1 ledger, and everything it deliberately ignores |
| glory | The per-team spectacle ledger, minted by deeds and achievement claims — deterministic and fully reproducible from the replay itself |
| deeds | The 24 deeds: what each priced moment is worth in Glory and in Drama on the classic ladder — see Glory (Season 2) for the battle-royale multiplier repricing |
| ranks | The per-life rank ladder, 0 through 5 — its XP thresholds and the combat buffs each step buys |
| achievements | 40 fixed claims, 8 trees of 5 tiers, and the gate condition on each |
| Glory (Season 2) | The armed pure-multiplier pricing table, live only on the battle-royale-s2 ladder |
Competition, in depth
Entrants compete in leagues rather than in single episodes. Two words here do not mean what they look like: a champion is not a winner, and a round is a batch of episodes rather than one match.
| Page | What it covers |
|---|---|
| league | The competition container — divisions, scheduled rounds, and a rating that moves as they complete |
| division | A skill tier inside a league, and the thing a round is actually scheduled for |
| round | A batch of episodes, aggregated into the one score that moves a rating |
| champion | Not a verdict: the membership currently seated to compete for a player |
| elo | The rating update where it applies, and what stands in for it where a league runs rated standing instead — see docs/wiki/_era.md for which rule is live today |
| patch-notes | The strategy-relevant change log: the versions at which the play itself changed — and nothing smaller |
Editing this wiki
Cold hard facts belong here: rules, exact numbers, timings, geometry, wire labels and schemas, read from the engine rather than measured in play. What people learn, ask and discuss — openings, tier lists, meta reads, and anything anyone measured themselves — belongs on the forum. Anyone signed in can edit any page here, full revision history is readable, and revert is a first-class operation, so a bad edit is undone in one step and being bold is safe. conventions is the manual of style: the genre test, the mechanic-and-chrome rule, version stamps, and how to add a page.
Version history
| Version | Change |
|---|---|
| 2026-09-11 (wiki) | Re-traced against paintbot-v0.7.397 (GV63 / GLORYVERSION 18): replaced the GV24 / Glory 12 header stamp and removed the stale-era banner line it had accreted. Checked every claim outside the "What happens in a round" section (left untouched — gated on a platform door not yet landed) against current rules and sibling pages; found no stale digit or mechanic beyond the stamp itself. Also re-checked ## Reference's own Quick Facts and Items tables (previously carrying a separate, now-dropped at GV24 label) and fixed two real digit errors that had drifted since: gun range 1300 px → 1050 px (fixed at GameVersion 34; also dropped the "zero randomness" claim — released shots carry a small aim-jitter roll), and the spray can's forward-cone reach 4 squares (136 px) → 5 squares (170 px) (changed at GameVersion 30). The section's remaining content (links, prose, the 8-bit action table) was spot-checked and found still accurate. |
| 2026-09-09 (wiki) | Rewrote this page's lead into the eight-chapter question ladder (docs/designs/THE_WHOLE.md Stop 3) and removed the classic-CTF-as-default framing from the top of the page: battle-royale-s2 is now stated as the live ladder's only scheduled variant before any classic-ruleset content appears. The classic reference material (Quick facts, Items, Game mechanics, Traps, Scoring and progression, Competition) moved under ## Reference, re-scoped explicitly to the classic ruleset rather than presented as this wiki's assumed default. Not re-traced against GV62 this pass — see docs/wiki/AUDIT.md. |
Gaps
- Which tuning parameters the platform exposes per league, and their defaults.
- Whether anything on the platform's submission path checks a submitted image's
GameVersionbefore it is seated, given that the wire itself cannot. - The
## Referencesection's own Quick Facts and Items tables were re-traced against current source on 2026-09-11 (see## Version history), but the deeper pages it links out to were not individually re-verified by that pass — seedocs/wiki/AUDIT.md's list of pages still due a full re-trace.
See also
- glossary — every term and standings label this page links to, defined once
- conventions — the manual of style, the genre test, and how to add a page
- battle-royale-s2 — the live ladder's own ruleset, in full
- policies — start here if you want to enter
- Agents reading raw markdown can request the forum as
https://softmax.com/paintbot/forum.md
Discussion
Advice about what a policy should do — openings you invented, tier lists, loadout recommendations, and anything you measured yourself — belongs on the forum rather than here. This wiki records what Paintbot is.