Play built-insArena+ New botLeaderboardRules
| # | Player | Rating | Matches |
|---|---|---|---|
| 1 | @house | 1095 | 23 |
| 2 | @arena-test | 989 | 1 |
| 3 | @mdashti | 980 | 3 |
| 4 | @credits-test | 937 | 11 |
Grid Royale is a resource-economy battle royale on a square grid. Each player commands units that harvest ore from cells, carry it home, and bank it. Banked ore is your score. Carried ore is at risk: a unit that dies drops its cargo and scores nothing. A border closes inward over the match, forcing players together until contact decides it. Highest bank at the end wins.
Everything is integer arithmetic over a seeded state, so a match is fully deterministic: the same seed and the same actions always produce the same result, and any replay re-runs identically.
cargo (0 to cargo_cap). Each player starts with one unit on its base, cargo 0.Turns are simultaneous. Every player submits an action batch: at most one order per unit it owns, plus an optional base spawn. All batches are collected, then resolved together. No player sees another's order for that turn before submitting.
A unit order is one of: MOVE_N, MOVE_E, MOVE_S, MOVE_W, or STAY. A unit with no order defaults to STAY.
One turn resolves in fixed phases. Within a phase, every effect reads the state from before that phase, so the result never depends on unit order.
MOVE_* order, the move costs floor(source_cell_ore / move_cost_divisor) from cargo. If the unit can afford it, the cost is deducted and the unit moves one cell. If it cannot afford it, the unit stays put and does not harvest this turn (it spent the turn trying to move). Moving off a rich cell is expensive on purpose.STAY unit that is not on its own base harvests floor(cell_ore / harvest_divisor) from its cell into cargo, capped by remaining cargo space.spawn_cost, are under the units_cap, and have no own unit sitting on your base, a new unit appears on your base with 0 cargo and spawn_cost is deducted from your bank.shrink_interval turns) the safe zone contracts inward by one ring, down to the min_zone floor. Any unit then outside the safe zone is destroyed and its cargo is lost (not spilled).There is no attack order. You kill an enemy by colliding with it, which kills your unit too. The cargo spills onto the cell, so ramming a loaded enemy hands the ore to whoever harvests the wreck next. Defending a laden unit on its way home, and judging when a trade is worth a unit, is most of the mid-game.
The border is the only place ore leaves the game. Cargo lost to it does not spill. That is what makes the late game tighten rather than spiral.
The match ends when the turn count reaches max_turns, or when at most one player is not eliminated. A player is eliminated when it has zero units and a bank below spawn_cost (it can never act again); a player with zero units but enough bank to spawn is still in.
Placement is a strict order: higher final bank first, then more units alive, then banked-earlier, then lower seat index.
The ore map is generated from the match seed with rotational symmetry matching the player count, so every player begins in a position identical to every other up to rotation. No seat is luckier; outcomes come from play, not the draw.
Each turn your bot receives the full observation as JSON (no hidden information at this version):
{
"turn": 41,
"max_turns": 400,
"you": 0,
"width": 32,
"height": 32,
"safe_zone": { "x0": 4, "y0": 4, "x1": 27, "y1": 27 },
"ore": [[0, 12, 0, "..."], "..."],
"bases": [{ "owner": 0, "x": 8, "y": 8 }, "..."],
"banks": [10240, 9980, "..."],
"units": [{ "id": 12, "owner": 0, "x": 9, "y": 8, "cargo": 740 }, "..."],
"params": { "cargo_cap": 1000, "spawn_cost": 500, "move_cost_divisor": 10, "harvest_divisor": 4, "units_cap": 50 }
}
ore is row-major: ore[y][x].
{
"orders": [
{ "unit": 12, "do": "MOVE_N" },
{ "unit": 15, "do": "STAY" }
],
"spawn": true
}
spawn is optional. A unit you do not mention defaults to STAY, so a minimal bot still harvests.
Three independent limits decide how much a unit can do per turn:
| Limit | Setting | Notes |
|---|---|---|
| Action | one order per owned unit, one optional spawn | enforced by the engine |
| Fuel per turn | 5,000,000 instructions, bank up to 20,000,000 | the competitive compute budget for bots |
| Wall-clock | 2,000 ms per turn | liveness backstop; a breach is an operational forfeit |
Fuel is metered, hardware-independent instruction counting: a search-everything bot hits the ceiling mid-search and must act on what it found. Exhausting fuel, timing out, or returning an illegal action is a no-action turn (your units default to STAY).
| Parameter | Value |
|---|---|
| grid side (2p / 4p) | 24 / 32 |
| players | 2 or 4 |
| cargo_cap | 1000 |
| harvest_divisor | 4 |
| move_cost_divisor | 10 |
| spawn_cost | 500 |
| units_cap | 50 per player |
| max_turns | 400 |
| shrink_interval | 25 turns |
| min_zone | 8×8 (always contains all bases) |