Papersseum

Docs › Competition

2. The game

Five bots start in a circular arena (11,304 playable cells on a 120×120 grid) and play for 180 seconds.

  • Moving. Your bot decides 10 times per second (1,800 decisions per match) and returns one of three actions: 0 straight, 1 turn left, 2 turn right. The world runs at 30 ticks per second, so you move between decisions.
  • Speed. You start at 10 cells per second and gain +1 cell per second for every 5% of the map you own. After a kill you get a 1.5× speed boost for 5 seconds. Speed is capped at 29 cells per second.
  • Starting land. Every bot starts with a disc of land worth about 1% of the map (radius 6, 109 cells).
  • Trail. While you are outside your own land you draw a trail behind you.
  • Your trail needs its home. The land cell you stepped off from is your trail's anchor. If another bot takes that cell (for example by closing a loop around it) while you are out, you die: the bot that took it gets your remaining land and the speed boost. Get back to any of your own land first and your trail closes as usual.
  • Capturing. Re-enter your own land and everything enclosed by your loop becomes yours, including other players' land. A bot whose head is inside the loop when it closes is trapped and dies: the capturer takes its land and gets the speed boost, as with any kill.
  • One bot per cell. Two bots never end a tick on the same cell. Running into a bot whose head is on its own trail cuts that trail (the cell the head stands on counts as trail): that bot dies and you step in, so a bot standing on its own land kills an intruder it runs into. Two bots that swap cells pass through each other (two trail-drawers fighting head-on are settled by the head-on rule below). If two bots want the same empty cell, the bot with more land moves in (equal land: the lower seat) and the other waits one tick. A bot also waits rather than step onto a bot standing still on its own land.
  • One connected mass. A bot's land is always a single piece (cells touching along an edge); it never splits into islands. When land changes hands and a piece would be left apart from the rest (a kill's spoils, or a rival's loop cutting your land in two), a one-cell-wide strip of land is laid over empty ground, the shortest way, to join the pieces. The strip never takes another bot's land, trail or the wall. If there is no way through empty ground, the cut-off piece becomes neutral instead.
  • Crossing your own trail is harmless. You can loop back over it, cross it, or run along it. Nothing happens.
  • Dying. You die if a rival's head touches your trail, or if you lose a head-on collision. A head-on is when two bots that are both drawing a trail (that is, both outside their own land) move into the same cell or swap cells: the bot with less land dies and the other takes its land; if they have equal land both die and the land becomes neutral. The bot that killed you takes all your land (and your trail cells on empty ground) and gets the speed boost.
  • Respawning. After 3 seconds you come back with a fresh 1% patch on empty ground at least 20 cells from any live head. If the arena has no room, you try again a little later.
  • The wall is solid but safe. Steering into it just slides you along the edge.
  • Winning a match. The largest share of the map when the 180 seconds end. Ties break on time-averaged coverage (the share you held over the whole match), then on fewer deaths.

Every match is deterministic from its seed and the action log, so any game can be replayed exactly.

What your bot sees

Every decision, act(obs) receives a dict:

  • obs["local"]: shape (16, 31, 31). A crop centred on your head, rotated so you always face "up". This is the view for quick reactions.
  • obs["global"]: shape (16, 120, 120). The whole arena, north up. Use it for planning (it costs more to process).
  • obs["scalars"]: your coverage, rank, speed, heading, boost left, respawn countdown, deaths, time remaining, and each opponent's coverage, speed and alive flag.

The 16 channels are: your territory, trail and head; the same three for each of the four opponents; and the arena mask. Use the named indices in papersseum.channels (ch.OWN_TERRITORY, ch.OWN_TRAIL, ch.OWN_HEAD, ch.opponent(i), ch.ARENA_MASK) instead of magic numbers. To print what your bot sees:

print(papersseum.ascii_obs(obs, "local"))