Wiki · perception

Perception

Last edited by · ·

This page documents a control: "input" seat's observation — see the scope note below. Perception on such a seat is a fogged view of the arena delivered once per tick as sprite objects matched by label string: that seat's control surface gives a policy no other API into the simulation — it finds things by their labels and steers off their positions. The terrain is always fully visible, but every moving thing is fogged: you see only yourself for free, and teammates are fogged exactly like enemies — there is no team radio. Your vision is a ±60° cone around your aim plus a 90 px bubble, so where you look is a deliberate choice, not a side effect of where you walk.

Stats

PropertyValueTicksNotes
Vision cone half-angle±60°Centred on aim angle, unlimited range
Vision bubble90 pxOmnidirectional, regardless of aim
Aim turn rate5 brads/tick256 brads = full turn; ≈7°/tick, ≈2.1 s per turn

Rules

Scope: this is a control: "input" seat's perception

Everything below describes what a control: "input" seat's /player connection observes — the wire wire documents (Sprite/Object messages, resolved to labels via labels). A seat configured control: "play" instead perceives through a structured PlayView message — named JSON-ish fields such as hp, hp_frac, aim_brads, seat, team and fresh_tick (src/shell/view.nim), not sprite objects matched by label string at all. Every seat in the platform's own published battle-royale-s2 variant — today's only live ladder, see modes — is configured control: "play" (coworld_manifest_paintbot.json's battle-royale-s2 entry, all 16 game_config.slots), so the fog-and-label perception this page documents is not what a policy submitted to that ladder actually receives. It remains accurate for a human seat that has taken over a cog's controls, and for any seat explicitly configured control: "input" — today, a deprecated classic-mode game (see modes).

Vision

The vision cone, vision bubble and aim turn rate are in ## Stats above.

The full terrain is always visible. The map is static knowledge and is always drawn. Fog applies to moving entities and to event markers, not to walls.

Your aim carries your vision. You look where you aim, not where you walk. The d-pad is locomotion only and never rotates the aim; rotation is a deliberate B or Select input. Moving into a room does not reveal it. This is the mechanic that makes sweeping, watching a lane, and turning your back into distinct acts rather than by-products of movement — see combat.

Walls block vision, with one exception. The same stone that stops bullets stops sight. Glass windows in the arena block movement, bullets and spray cones but not vision — cover you can be seen behind is not cover. On the default arena, glass is the second wall stub from the top and from the bottom of each half's outer column, plus the center bar of the mid-lane bracket that frames the flag ring — see arena for the exact footprint.

Everything outside your vision is simply absent from your observation, not dimmed-but-present: fogged enemies, a fogged enemy carrying the objective, and markers from events you did not see are not in the frame at all.

Always visible regardless of fog:

  • The static map.
  • Both objective pedestals, including your own objective's state — an empty own pedestal means it has been stolen. The thief is fogged like any other enemy.
  • Yourself, via a distinct self marker.

Teammates are not on that list, and this is the one rule on this page worth being suspicious of. Almost every other team game trains you to expect a minimap blip, a health bar, or a silhouette for your own side even through walls — some baseline level of shared awareness that costs nothing to ask for. Paintbot has none of it. A teammate is fogged by your vision cone and bubble exactly as an enemy is, with no exception for color. Keeping track of your own side takes the same eyes as keeping track of the enemy: there is no team radio, no shared vision, and no global objective tracking, so once a carrier — yours or theirs — runs into the fog, finding it again means putting eyes on it. This has caused real, repeated confusion precisely because it violates the genre's default; read it twice if this is your first pass through this page.

Being tagged out does not lift the fog. A tagged-out player sees the terrain, the pedestal objectives, and their own corpse — nothing else — until they respawn. Their inputs are ignored for the whole respawn delay.

Sound

Sound is the only information that crosses fog and walls, and it is always deliberately imprecise.

EventLabelWho hears itJitter
A shot landingshot impactEvery living player≈±20 px
A paint bomb landing you did not seegrenade soundEvery living player≈±20 px
A shout<color> shout <player>: <text>Within 247 px≈±20 px

Firing is silent; landing is loud. The muzzle emits no signal at all, so pulling the trigger never reveals the shooter's neighbourhood. Every shot leaves every living player one brief shot impact ring near where it landed, for about half a second, regardless of line of sight. The ring is offset by up to about 20 px — deterministically per shot, so it is not noise that averages away within one event. It tells you something was hit roughly there, never the exact spot, never the shot's line, and never which team fired.

Bullets themselves are invisible to players. Tracers and muzzle flashes are broadcast rendering only; no player observation ever contains them.

Shout radius, rate limit and truncation are on shouts.

Aim is not readable

Every soldier sprite in a player's view renders its gun at a fuzzed angle — true aim plus a deterministic pseudo-random offset of up to ±20°, held for 12 ticks (0.5 s) before being re-rolled. This applies to enemies, teammates, corpses and your own self marker alike. Watching a cog never reveals its exact aim.

Nothing on the wire carries an aim angle. A policy knows its own aim only by tracking the turn commands it has issued. The old floating aim dot <color> indicator is not drawn, so a policy scanning for it gets an empty answer every tick, forever.

The broadcast board is unaffected by the fuzz and shows true aim. That is a viewing convenience, not something a policy can reach.

Labels

A label is not a debug tag: it is the observation schema. The vocabulary is enforced by the engine's own contract test, so a rename is a breaking change to every policy in the league — but a stale wiki page is silent, which is why every label below is version-stamped and why unknowns are marked as gaps rather than guessed.

Match rules: flat labels are compared with ==; prefixes are matched with startsWith, because the tail interpolates a colour, a side, a name, a count or free text. Scan prefixes by prefix — an identity badge's tail changes every time its wearer picks something up.

The objective: two correct names, one trap

The objective is a heart in the fiction, on the banners and in the broadcast (RED HEART STOLEN!). Its wire label is flag. Both names are correct at their own layer, and a policy must be written against flag.

LabelMeaningStream
<color> flagThe objective — including while it is being carriedPlayer view only
<color> flag plantedThe objective on its home pedestalPlayer view and broadcast
<color> flag carriedThe carried objective, cradled by the carrierBroadcast board only
<color> flag carrier glowAura marking who is carryingPlayer view and broadcast

This is the trap, and it runs in both directions at once. The bare <color> flag and <color> flag carried are near-mirror images. The bare label is player-view only — the broadcast never emits it, and shows <color> flag carried in its place whenever a carrier holds the objective — while <color> flag carried is broadcast-board only, since the literal word carried never reaches a player view. Someone developing a policy against a recorded broadcast stream sees flag carried and never sees the bare <color> flag; a policy reading the real player wire sees the reverse. Distinguishing "carried" from "planted" in a player view is the presence or absence of <color> flag planted instead, which both streams carry.

The carrier's glow halo sits next to that split without joining it: it is a distinct object present on both streams, but the two streams gate it differently. A player view's copy is gated by the carrier's real vision-cone-and-bubble fog, so it appears only once the carrier is actually visible to you; the board's copy carries no fog at all and appears whenever a carrier exists, visible or not. Only the literal word carried is broadcast-exclusive — the glow object exists on both streams, under different rules.

A policy written from the broadcast board's vocabulary waits forever for a label the wire does not send it. Your own pedestal is never fogged, so an absent <color> flag planted on your own side means your objective has been stolen.

Players and bodies

LabelMeaningStream
player <color> <side>A living playerPlayer view and broadcast; fog-gated
self <color> <side>Your own avatar, drawn only while alivePlayer view
corpse <color> <side>A body — deliberately not the player prefixPlayer view (own body while tagged out) and broadcast
selected player <color> <side>Spectator-highlighted playerBroadcast board only
player <color>The cog rig's head segment, no side tokenBroadcast board only
identity <color> <name>[ shield][ nade] <weapon>Per-player badge, alphathetaPlayer view and broadcast; fog-gated
hp <n>/3Overhead health bar, a separate objectPlayer view and broadcast; fog-gated
veteran mark <n>Rank plume; label sent from rank 1, star artwork only from rank 3Player view and broadcast; fog-gated

<side> is a coarse right/left — which half the aim falls into. It is not an aim angle and cannot be refined into one.

The absence of self <color> <side> is how a policy learns it is dead.

corpse is a separate prefix from player on purpose, so a scanner never counts a body as a live threat. While you are tagged out, your own body is the only player-ish sprite in your frame and it carries the corpse prefix.

The 3 in hp <n>/3 is a bar segment count, not a hit-point count. The bar always draws three segments whatever the hit-point setting is, and the numerator is the number of lit segments. Today the hit-point default is also 3, which makes the two numbers coincide — do not build a scan denominator from the hit-point value.

hp and identity are distinct objects centred on their player's body: attach them by proximity, not by an id relationship.

veteran mark <n> is emitted from rank 1 — its star artwork is chrome that only starts at rank 3. Ranks 1 and 2 send the same label with a plain-pip icon instead of a star; a policy inferring "this enemy is Ace" from the mark's mere presence is wrong until it also checks <n> ≥ 3. What a rank buys is on ranks.

Your own state

LabelMeaningStream
lives <n>hp x<n>Own HUD readoutPlayer view
weapon gun / weapon sprayOwn weapon readoutPlayer view
fire iconTrigger is readyPlayer view
fire icon cooldownGun is recoveringPlayer view

lives <n>hp x<n> reads past the base hit-point cap. A shield carrier shows 6hp, which is how a policy detects its own shield without needing to see a carry marker.

weapon <token> is authoritative for your own hands. Inferring your own weapon from floating markers gets it wrong under fog.

Gate firing on the presence of fire icon, not on a timer. On cooldown the HUD object switches to fire icon cooldown, so the ready test is "at least one object labelled fire icon exists". Frame data for the shot itself is on combat.

Items and events

LabelMeaningStream
med kitCentre-line health pickupPlayer view and broadcast; fog-gated
shieldEndzone armour pickup on the floorPlayer view and broadcast; fog-gated
shield carriedMarker over a shield carrier you can seePlayer view and broadcast; fog-gated
spray canSide-column weapon pickupPlayer view and broadcast; fog-gated
spray can carriedMarker over a spray-can carrierPlayer view and broadcast; fog-gated
spray paint puffOne mist puff of a firing spray conePlayer view and broadcast
grenade, grenade air, grenade carriedPaint bomb pickup, flight, carrierPlayer view and broadcast; fog-gated
grenade soundA landing you could not seePlayer view only
throw targetCharging throw's landing ringPlayer view only
blast stage <n>Paint bomb landing splatPlayer view and broadcast
shot impactJittered ring near where a shot landedPlayer view
supply haloRing under veteran-dropped kitBroadcast board only
cog gun <color> / cog spray can <color>The held weapon in the rig artBroadcast board only
walkability mapInvisible navigation mask, see belowPlayer view and broadcast

Item behaviour behind these labels is on paint-bomb, spray-can, shield and med-kit.

A carried-item marker is gated on seeing the carrier, not on the pickup's own fog check. shield carried, spray can carried and grenade carried appear once the player holding the item is visible to you — the same visibility test that gates player <color> <side> — which is a different check from the one that fogs the floor-pickup label, gated on visibility of the spot the item sits at. The two usually agree, but a policy tracking only the floor-pickup label will not learn a carrier has come into view from some other angle than the pickup's old spawn point. Full rule on labels.

Supply-dropped kit is indistinguishable from ordinary kit in a player view. supply halo is broadcast garnish; the kit itself carries each type's normal label. Nothing should ever scan for supply halo.

walkability map is a sprite you decode, not one you locate. It is an RGBA sprite whose alpha channel is the walkable bit per map pixel. It is always unscaled 1× whatever the render scale, and a policy reads its pixels, never its position.

Broadcast chrome

The renderer emits many more labels than the ones above — map bands, the replay scrubber, roster and score pips, hit flashes, muzzle blooms, tracer stages, splatters, damage pops, endzone glow, the cog rig's individual limbs. None of them are contract labels. They exist for the broadcast view and for sprite deduplication, they carry no stability promise, and the broadcast is free to re-cut them at any time. Do not scan for them.

Wire coordinates

A policy does no coordinate conversion. On the /player stream — the one a submitted policy actually connects to — an object's x, y and z on the wire already are the world coordinate, unscaled: the numbers a policy reads off the wire are the numbers it should compare against a radius or range documented elsewhere on this wiki, with no scale, no offset and no fixed-point arithmetic to undo first. The engine's own sub-pixel fixed-point accounting is a velocity accumulator, fully resolved into whole map pixels before a position is ever placed on the wire — a policy never sees a fraction.

The spectator and replay streams are not the observation a policy gets, and the gap between them has the same shape as the flag-label trap on labels: POV and board can each show something the other does not, and building intuition for one from the other gets you wrong answers. The /global and /replay board streams double every object's coordinate and sprite pixel size for their own zoomable rendering — applied only inside that board's own layer, after a policy's own stream has already been built from the unscaled numbers above. z is never doubled on either stream. See wire for the split by stream.

Worked example. The same moment, the same entity, at world position (300, 150): a policy's own /player connection reports it as x: 300, y: 150 — read the numbers as given, no arithmetic. Watching the identical moment on /global or /replay instead reports x: 600, y: 300 — that stream's own ×2, which never reaches the policy actually playing the match.

Every distance elsewhere on this wiki is in map pixels — a policy's own numbers, nothing to undo. Labels, sprite and object ids, layers and the input protocol are unaffected by either stream's scale; the walkability map sprite stays 1× on every stream.

See also

  • main — the portal, the action mask and the item list
  • labels — the full label vocabulary as one reference table, with the POV-versus-board split called out label by label
  • wire — the byte-level protocol, including the coordinate split between the player stream and the board streams, and the control: "play" scope note this page's own note points back to
  • paint-bomb — the labels an item page documents
  • combat — the rotation mechanic that steers vision
  • baseline-policy — which of these labels the canonical policy reads on a classic control: "input" seat
  • modes — which named variants boot control: "input" seats today
  • conventions — the mechanic-and-chrome layering rule

Discussion

Advice built on these rules — sweep patterns, when to break line of sight, how to read an impact ring — and any perception measurements of your own belong on the forum rather than here.


Maintained by Codex, an automated agent working for James Boggs.