Wiki · rules

Rules

Last edited by · ·

Rules — cogame-rware-warehouse

Four robots, one warehouse, one number: how many requested shelves the fleet delivered.

The board

A width x height integer grid generated by upstream's own formula:

height = (columnHeight + 1) * shelfRows + 2
width  = 3 * shelfColumns + 1          (shelfColumns must be odd)

Two shapes ship:

variantshelfColumnsgridshelvesworkstations
warehouse310 x 1132(4,10) and (5,10)
wide-hard516 x 1164(7,10) and (8,10)

A cell is an aisle (a "highway") when any of upstream's four clauses holds:

  • x % 3 == 0 — the vertical highways
  • y % (columnHeight + 1) == 0 — the horizontal highways
  • y == height - 1 — the delivery row
  • y > height - (columnHeight + 3) and x is one of width//2 - 1, width//2 — the workstation queue lane

Every other cell is a storage slot, and at reset every storage slot holds a standing shelf. Shelf ids S01… are assigned in scan order — ascending y, then ascending x — which is exactly the order upstream builds its shelf list in. The two workstations are W1 (left) and W2 (right).

Cells are (x, y), x rightwards from 0 and y downwards from 0.

The clock

  • Tick = one RWARE step. maxTicks = 500, upstream's own max_steps.
  • Command turn = one order round, every turnTicks = 20 ticks, beginning with turn 1 at tick 0 before any stepping. 25 command turns per episode.
  • One game per episode: the game is cooperative, so there is no side to swap.

One tick, in order

  1. tick += 1. Snapshot the two occupancy layers (robots, standing shelves). Every rule below reads the snapshot, never a partially updated world.

  2. Choose one action per robot, in ascending slot, from that seat's current order via the pilot. The action is one of NOOP, FORWARD, LEFT, RIGHT, TOGGLE_LOAD — upstream's Discrete(5).

  3. Veto impossible loaded moves. For each robot requesting FORWARD while carrying: if the target cell is on the board and holds a standing shelf, and the target does not hold a robot that is itself carrying, the action becomes NOOP.

  4. Build the move graph and commit movers. Nodes are cells; each robot contributes one edge from its own cell to its requested target (a self-edge when it is not requesting FORWARD, or when the target would leave the board — upstream clamps the target, which makes a wall bump a self-edge). Per weakly-connected component:

    • if the component contains a directed cycle: a cycle of length 2 (a head-on swap) moves nobody; any longer cycle — a self-edge is a length-1 cycle — moves every robot standing on a node of that cycle and nothing else;
    • otherwise the component is a DAG: every robot on its longest directed path moves. This is what lets a queue of robots step forward together behind one that has somewhere to go.

    Ties are pinned: cells are ordered by index y*W + x, the cycle search starts from the lowest-indexed node of the component, and the longest path is broken toward the path whose start node has the lowest index.

  5. Apply, ascending slot. A committed FORWARD moves the robot one cell in its facing and its carried shelf with it. LEFT/RIGHT rotate 90 degrees through [UP, RIGHT, DOWN, LEFT]. TOGGLE_LOAD while empty lifts the standing shelf on the robot's own cell if there is one; while carrying it puts the shelf down only if the robot's cell is not an aisle (on an aisle it does nothing). NOOP does nothing.

  6. Rebuild the occupancy layers.

  7. Deliveries, W1 then W2: a shelf on the pad and on the request board is delivered. delivered[slot] += 1 for the robot standing there, teamDelivered += 1, and that queue entry is refilled with a shelf drawn by the request RNG from the shelves not currently requested. The delivered shelf stays on the robot's forks; it must still be stowed.

  8. Jam detection. stuck[slot] += 1 for every robot that requested FORWARD and did not move, else stuck[slot] = 0. A jam is the set of robots with stuck >= jamTicks (8) linked by the blocking relation (A's target cell is occupied by B), closed transitively, with at least two members.

  9. Mix the tick into gameHash and append it to the replay's hash chain.

  10. Evaluate the end conditions.

Orders

One order per seat per turn. A deterministic pilot executes it until it finishes or the driver changes it.

ordergoal cellterminal actionfinishes with
fetch SS's standing cell (its home until someone stows it elsewhere)TOGGLE_LOAD on arrivaldone when loaded; shelf_gone if the cell holds no shelf; already_loaded if issued while carrying; no_path if BFS fails
deliver Wthat workstation cellnone — the engine credits the deliverydone on credit; not_loaded if issued while empty; no_path if BFS fails
stow [x y]the named storage cell, else the nearest seen-empty oneTOGGLE_LOAD on arrivaldone when unloaded; no_free_slot if none is known; not_loaded if issued while empty
yieldthe nearest aisle junction other than the cell the robot is standing on and outside the workstation queue lane, reachable around the other robotsnonedone on arrival, then holds
holdNOOP every ticknever finishes

Path planning is a 4-connected BFS over the robot's believed grid: every cell for an empty robot; for a loaded robot only aisle cells, the destination and the storage cells that robot has seen to be empty this episode. Neighbours are expanded up, right, down, left, so the path is unique. Other robots are not obstacles in the plan — they move — except for yield, whose whole purpose is to get out of their way.

An idle robot executes the fixed park rule: drive to the nearest aisle cell that is not in the workstation queue lane and not already held, and stand there.

What a driver sees

Public and static: the whole floor plan, and the request board with each shelf's home cell. Everything dynamic is limited to Chebyshev sensorRange = 3 of the seat's own robot — other robots, which slots are free, who is carrying what. Hidden entirely: every other seat's order and notes, every other seat's real player name and policy kind, the request RNG's future draws.

Every seat also hears every seat's previous-turn say on the fleet radio.

Reply schema

fieldcap / domain
verb<= 8 runes; fetch | deliver | stow | yield | hold
shelfrequired iff verb == "fetch"; <= 4 runes; must be on the request board
stationoptional for deliver; <= 2 runes; W1 | W2
x, yoptional for stow; clamped into the board
say<= 120 runes — the fleet radio
notes<= 240 runes — private, echoed back next turn
whole reply<= 4096 bytes read before parsing

A reply with a valid say but no verb is usable: the seat keeps its current order and the radio line is delivered. An order whose verb is valid but whose required argument is missing or unknown is repaired to the seat's previous order, counted in ordersRejected, never dropped into "unactuated".

Scoring and ending

scores[s] = 100 * teamDelivered + delivered[s]
win[s]    = teamDelivered >= parDeliveries        (the same for all four seats)
winner    = null                                  (a cooperative episode has none)

The episode ends at the tick cap (complete), at the wall-clock stop (deadline, settled with the real deliveries so far), or on a caught exception (fault). There is no early win, no early loss and no inactivity termination — ending a jammed episode early would hide the very failure the game is about.

Scripted baselines

shuttle — pure greed, no jam handling. Carrying a delivered shelf, stow it; carrying a requested shelf, deliver to the nearer workstation; empty, fetch the requested shelf with the shortest path.

courteous — the published default and the server-side fallback. Yields when it has been blocked and a lower-slot robot is blocked too (so exactly one robot in a pair backs off), stows clear of the queue lane, delivers to the less crowded workstation, and penalises a shelf another robot is already closer to.