Teams write Python bots that fight for territory, four at a timehead to head. The server plays games nonstop and ranks every bot. Below is the latest ranked game.
- Territory: step into a cell and wait a turn to take it. Stay connected to your home or you're out.
- Cutline: draw a trail and close loops to claim land. Step on a rival's trail to cut it. Nobody gets knocked out.
- Conquest: armies, gold, buildings and capitals. Attack from next door; lose your capital or get cut off from it and you're out.
- Treadline: two players draw edges between grid points. Enclosed area pays every turn; touch an enemy edge to break it.
- Zone Rush: take cells by standing on them, upgrade your own, raid rivals. A well-timed SHIELD freezes raiders. Nobody gets knocked out.
Switch games with the buttons at the top. One account works for every game; each game has its own bots and rankings.
- Rules: how the game works and how to write a bot.
- Rankings: every bot, ordered by rating.
- Replays: every game played, step through any of them.
- Test match: pick any four botstwo bots and watch. Ratings don't change.
- Play yourself: steer one bot with the keyboard against threeplay a bot yourself, click by click.
- My bots: sign up and upload your bots.
- Make an account. Sign up with the invite code you were given.
- Grab the starter bot. starter_bot.py, one Python function.
- Upload it. It plays a test game, 12 placement games, then the ladder.
Rankings
Every bot, ordered by rating. Every few seconds the server picks four botstwo bots and plays a ranked game. Finishing above a bot raises your rating, finishing below it lowers it, so second place beats third and fourth and loses to first.
| # | Bot | Rating trend | Rating | Last 5 | Finishes 1st → 4th | Games | Win % |
|---|
| Opponent | Games | Finished above |
|---|
Replays
Every game the server has played. Ranked games count for the rankings. Placement games are a new bot's first 12, which set its starting rating. Test matches are ones people ran by hand and don't count.
Replay
Test match
Put any four botstwo bots on the board and watch. Fights don't change ratings.
Play yourself
Take a seat against a bot. You get Blue or Red at random. Click one of your nodes, then one of the ringed points it can reach. The bot's moves come back straight after yours.
Take a seat against three bots. Arrows or WASD move, Space stays, R retreats from a capture, E raises a SHIELD. Stand still to take or upgrade the cell you're on. A frozen bot can only wait. Walk into an enemy cell to attack it. M, B, P build a mine, barracks or defense post. G parks 100 reserve soldiers on your cell. F bomb, X missile, V MIRV, H H-bomb (the game picks the best enemy cells in sight). R moves your capital to where you stand. On your capital, 1, 2, 3 re-split your army (attack-heavy, balanced, defend-heavy). Dark cells are ones you can't see right now.
Click your node, then a ringed point. Esc or a click elsewhere drops the pick. Thick edges with a light centre line are protected this turn.
Arrow keys or WASD move. Space stays, R retreats, E shields. Walk into enemy land = attack. M mine · B barracks · P post · G garrison · F bomb · X missile · V MIRV · H H-bomb · R move capital · 1/2/3 re-split (capital only). Hold a key to keep going.
My bots
Upload bots here. A new bot plays one 60-turn check game, then 12 placement games, then joins the rankings.
| Bot | Status | Rating | Games | Wins | Uploaded |
|---|
How it works
Write one Python function. It gets the whole board every turn and returns a move.
The game
- Four bots start on the four corners. Your corner is your home. Every other cell starts neutral.
- Each turn all four bots pick NORTH, EAST, SOUTH, WEST, STAY or RETREAT at the same time.
- Moving through your own cells is free. Stepping into a neutral or enemy cell starts a capture: stay one more turn and it's yours. An enemy home takes two.
- While capturing you can only STAY (keep going) or RETREAT (back to the cell you came from).
- Stay connected to your home through your own cells. Land cut off from home turns neutral. If you get cut off, you're out. Lose your home and you're out. Out means all your land turns neutral.
- You can hold 35 cells. A 36th releases one of your outer cells.
- A cell with a bot on it is closed for that turn. Two bots stepping into one empty cell: the owner wins it, otherwise whoever holds the priority token. The token moves one seat per turn.
- Last bot standing wins. After 300 turns, the living bot with the most cells wins; a tie is a draw.
Your code
One file with act(state) returning the move as a string. 2 s for the first turn, 200 ms after. Late, missing or illegal = STAY. Standard library only; print() goes to your log.
def act(state):
me = state["self"]
if me["capture_target"]:
return "STAY" # finish the capture
return "EAST" if "EAST" in state["legal_actions"] else "STAY"
What you get each turn
turn, turns_remaining, width, height, cell_cap
owner[y][x] -1 neutral, else the owner's id
self id, position [x, y], home, capture_target,
dwell_remaining, owned_count
bots[4] the same for everyone, plus alive
priority_seat who wins a tie this turn
legal_actions what you may do right now
Download starter_bot.py
The game
- Four bots start on protected 2×2 pads in the corners. Nobody can enter or capture a rival's pad. Some boards have walls in the middle.
- Each turn all four bots pick NORTH, EAST, SOUTH, WEST or STAY at the same time.
- Leave your land and you draw a trail behind you. Walking back over your own trail shortens it to that point.
- Get back onto your land and the loop closes: your trail and everything it encloses become yours, rival land included (not pads).
- Step on a rival's open trail (anywhere except where the rival is standing) and you cut it. Their trail disappears and the server drives them home. Until they're back they can't draw, claim or cut. Land they already own stays theirs.
- Cuts happen before loops close. If two loops claim the same cell on the same turn, it keeps its old owner.
- A bot that stays put keeps its cell, and bots can't swap places. Two bots stepping into one empty cell: whoever holds the priority token gets it. The token moves one seat per turn.
- Nobody is ever knocked out. Every turn you score one point for each cell you own. Most points at the end wins (72 turns on 9×7, 100 on 12×8).
Your code
One file with act(state) returning the move as a string. 2 s for the first turn, 200 ms after. Late, missing or illegal = STAY. Standard library only; print() goes to your log.
def act(state):
me = state["self"]
if me["returning"]:
return "STAY" # cut: the server drives you home
return "EAST" if "EAST" in state["legal_actions"] else "STAY"
What you get each turn
turn, turns_remaining, turns, width, height
owner[y][x] -1 neutral, else the owner's id
walls, pads blocked cells; each bot's 2x2 start
self id, position [x, y], trail (oldest first),
returning, area, score, blocked
bots[4] the same for everyone
priority_seat who wins a tie this turn
legal_actions what you may do right now
Download starter_bot.py
The game
Rules version 3: get cut off from your capital and you're out straight away, and every weapon is in play. Radar, scans and interceptors are off.
- Four teams on a 12×12 board with mirrored walls. Each has one robot on its capital (the thick square), 1,000 soldiers (500 attack, 350 defense, 150 reserve) and 100 gold.
- Where capitals start: one random spot mirrored into all four quarters, so every team gets the same position (the default). Other options: the four corners, or choose: on a setup turn 0 each team sends
CAPITAL x yfor a cell in its own quarter, at least one cell in from the edge and the centre lines. No pick, or a bad one, keeps the corner. The setup turn doesn't count toward the 5-turn timeout. - Each turn your robot does one thing. Step into your own land: a move. Step into neutral land: it's yours after one more turn. Step into enemy land: a battle on that cell.
- Your attack soldiers travel with the robot. The defender sends 65% of its free defense, split over every new attack it faces that turn, plus any soldiers parked on that cell. Its reserve joins a turn later. The battle ends after 2 turns. Capitals defend ×1.6, cells next to a defense post ×1.4.
- Lose a battle and your robot walks back to where it came from. If it can't, it's out.
- Take a capital and its team is out; you get +300 points. If a robot is sitting on its own capital you lay siege from next door instead of walking in.
- Your robot must stay joined to its capital through your own land. The moment a captured cell breaks that path, your robot is out, that same turn: no grace turn, no reconnecting. While claiming or fighting, the cell you stepped from must be joined. Keep your land thick: a one-cell snake dies with you on it.
- New soldiers go to reserve: +3 +0.4 per cell each turn (+12 per barracks). Gold: +1 +0.12 per cell (+3 per mine). Own a whole quarter of the map: +4 soldiers +1 gold.
- To move soldiers between attack, defense and reserve you must stand on your capital and ALLOCATE (uses your turn). GARRISON parks reserve soldiers on the cell you stand on; WITHDRAW takes them back.
- Buildings, on your own joined-up cell, one per cell: mine 60 gold, barracks 70 (3 turns), defense post 45 (2 turns). You're locked while building.
- Weapons (virtual, one per turn, each with its own cooldown). Aim at enemy cells you can see right now, within range of your robot:
Every enemy cell in the blast takes the damage (overlapping blasts add up): soldiers parked there die first, that team loses damage ÷ its cell count from its defense, an idle robot standing there loses attack soldiers, and a building falls half the time. Weapons never take land and never touch a capital cell, not even one that used to be a capital. The H-bomb numbers may still change.gold range blast damage cooldown Bomb 35 3 1 100 5 Missile 120 10 1 220 12 MIRV (3 targets) 300 14 1 each 180 25 H-bomb 500 12 2 250 30 - Move your capital (RELOCATE, a new rule whose numbers may still change): stand on your own joined cell that isn't the capital and has no building; 150 gold, locked 3 turns, once per 60 turns. Then that cell is your capital: ×1.6 defense, ALLOCATE works there, supply is counted from it, and losing it puts you out. The old cell is ordinary land that weapons still can't touch. A strike on the cell while you're locked, or being cut off, cancels it (no refund). Others only learn where it went when they see it.
- You only see your own land and the cells next to it. Everything else is what you last saw.
- Two robots stepping into one cell, swapping, or stepping onto a robot: blocked. A bot that sends nothing 5 turns running is out.
- +1 point per cell you own, every turn. Last team alive wins. Otherwise, after 300 turns or 30 turns with nothing happening, the surviving team with the most points.
Your code
One file with act(state) returning one action string. 2 s for the first turn, 200 ms after. Illegal = WAIT; nothing at all counts toward the 5-turn timeout. The JSON form {"kind": "move", "direction": "E"} works too.
def act(state):
if state["self"]["busy"]:
return "WAIT" # claiming, fighting or building
for a in ("EAST", "SOUTH", "BUILD MINE"):
if a in state["legal_actions"]:
return a
return "WAIT"
Actions
NORTH / EAST / SOUTH / WEST move, claim, or attack BUILD MINE / BARRACKS / POST ALLOCATE 0.5 0.35 0.15 attack/defense/reserve, capital only GARRISON 100 / WITHDRAW 100 BOMB x y / MISSILE x y / HBOMB x y MIRV x1 y1 x2 y2 x3 y3 up to 3 different cells BOMB / MISSILE / MIRV / HBOMB bare: the game aims RELOCATE move your capital here CAPITAL x y setup turn (choose mode) WAIT
What you get each turn
turn, turns_remaining, width, height
phase "setup" (choose mode, turn 0) or "play"
capital_choices setup: cells you may pick
owner[y][x] -1 neutral, a team, None = never seen
seen[y][x] tick you last saw it (== turn: in view)
walls, region blocked cells; quarter of each cell
capitals the ones you've found
buildings, garrisons what you know of them
self position, capital, army, gold, income,
busy, supplied, score, weapons
{ready_in, cost, ...}, relocate_ready_in
robots enemy robots in view
battles the ones you're in
rules, legal_actions
Download starter_bot.py
The game
- Two players, Blue (0) and Red (1), on a 17×11 grid of points (or 19×13). Each starts with one edge of length 3 on the middle row, touching its side of the board: Blue on the left, Red on the right.
- Blue opens with 1 move. After that turns alternate with 2 moves each, until the very last turn, which has 1 again. 60 moves each, 120 in all.
- A move: pick one of your nodes (the dots at the ends of your edges) and draw a straight edge to any point at most 3 columns and 3 rows away. The end point becomes your node.
- You can't end in the middle of your own edge or pass through your own node, and you can't draw an edge you already have. You may cross your own edges.
- A region completely surrounded by your own edges is enclosed. The board's border is not a wall, and a point where two of your edges cross counts as a corner. Area is exact, in grid squares.
- At the end of every turn (yours and your opponent's) both players add their enclosed area to their score. An enclosure keeps paying until it's broken.
- If your new edge crosses or even touches an opponent edge, that whole edge breaks and anything it enclosed is gone. Opponent nodes left with no edges disappear. Starting edges break like any other.
- A move may touch at most one opponent edge. Touching an opponent node touches every edge at it, so it's only allowed when exactly one unprotected edge is attached.
- Edges the opponent placed in their latest turn are protected (drawn thick with a light centre line) and can't be touched. You can't run along an opponent edge lengthwise.
- After move 120 the higher score wins; equal scores are a draw. A player with no legal move on their turn loses.
Your code
One file with act(state). It's called once per move for both players; only the player to move acts, so return "WAIT" when your_turn is false. On your move return "MOVE x1 y1 x2 y2". 2 s for the first call, 200 ms after. A late, missing or illegal move is passed: that move is used up and nothing is drawn.
def act(state):
if not state["your_turn"]:
return "WAIT"
for x1, y1, x2, y2, breaks, closes in state["legal_moves"]:
if closes: # comes back to your own lines
return f"MOVE {x1} {y1} {x2} {y2}"
return state["legal_actions"][0]
What you get each move
turn, turns moves played, moves in the game (120)
round, rounds the rules' turn number (61 turns)
your_turn, to_move, moves_left (in this turn)
width, height, reach (3)
self, opponent id, color, score, area, nodes
edges id, a, b, owner, turn, protected
regions owner, area, outline, edges
legal_moves [x1, y1, x2, y2, breaks, closes]
breaks: enemy edge id or -1
legal_actions "MOVE x1 y1 x2 y2" strings
Download starter_bot.py
The game
- Board. 8×8 cells. Each cell shows a value 1, 2 or 3, higher toward the middle; the layout is mirrored, so every corner is equivalent. Each bot starts in a corner. That corner is its home: it is always yours and can never be taken.
- Moves. Every turn all four bots choose N, E, S, W, STAY or SHIELD at the same time. A cell with a bot on it is closed for that turn, so there are no swaps and no following. If two bots step into the same empty cell, the cell's owner gets it. Otherwise the priority token decides. The token moves one seat every turn.
- Take. Stay 1 turn on a cell that isn't yours and it becomes yours, at level 1. An upgraded rival cell takes 3 turns. Taking a rival's cell also pays a one-off raid bonus of 8 × its value × its level.
- Upgrade. Stay 3 turns on your own cell and it is upgraded: it counts double.
- Shield. Instead of moving you may SHIELD. You can't SHIELD again for the next 4 turns. For that one turn none of your cells can be taken: every rival who stays on one of your cells this turn, your home included, loses its progress and is frozen (forced to STAY) for the next 2 turns. A rival that is already frozen isn't caught again. A SHIELD turn does not count as staying. A SHIELD that catches nobody backfires: you are frozen for 2 turns.
- Score. At the end of every turn you score the value of each cell you own, ×2 if it is upgraded.
- End. After 80 turns, the most points wins. Nobody is ever knocked out.
A blocked move counts as a stay. Leaving a cell resets your progress on it. A taken cell drops to level 1.
Reading the board
- The small number in each cell's corner is its value. Brighter cells with an inner line are upgraded.
- An arc round a bot shows how far it is through taking or upgrading its cell.
- A dashed ring over a bot's cells means it shielded that turn. A faded bot with a dashed ring is frozen.
- The white diamond marks the bot holding the priority token.
Your code
One file with act(state) returning NORTH, EAST, SOUTH, WEST, STAY or SHIELD. 2 s for the first turn, 200 ms after. Late, illegal or crashing = STAY. Standard library only; print() goes to your log.
def act(state):
me = state["self"]
if me["need"]:
return "STAY" # finish taking or upgrading this cell
return "EAST" if "EAST" in state["legal_actions"] else "STAY"
What you get each turn
Coordinates are [x, y], with [0, 0] top-left.
| turn, turns_remaining, turns | the game clock (80 turns) |
| width, height, walls | board size; walls is empty on the standard board |
| owner[y][x] | -1 for neutral, otherwise the owner's id |
| value[y][x] | points per turn for owning the cell |
| level[y][x] | 2 means upgraded (counts double), 0 for neutral |
| priority_seat | who wins a tie for an empty cell this turn |
| legal_actions | the actions you may take right now (just STAY while frozen) |
| rules | the rule numbers: capture, upgrade, steal, cooldown, stun, backfire, raid_bonus |
| self, bots[4] | you, and every bot by id, each with: |
| id, position, home | seat, where it stands, its corner |
| progress, need | stays made on its cell, and stays needed (0 = nothing to do there) |
| score, income, cells | points so far, points per turn now, cells owned |
| cooldown | {"SHIELD": k}: turns until it can SHIELD again |
| shield, frozen | shield is null between turns (a SHIELD lasts only its own turn); frozen = turns it must still STAY |