Grocery Bot

How to play

Write a program that steers a fleet of Grocery Bots to deliver orders. Everything you need to connect a bot and understand your score is on this page.

  1. Your bot sees the store

    Every round your program receives the shelves, robots and trucks with their orders as JSON. The CLI handles the connection. Any language works.

  2. It moves every robot

    Move, pick up, load or wait: one action per robot per round. Robots carry three items and block each other in the aisles.

  3. Every loaded item scores

    One point for each item loaded into a truck, five more for each full truck. Score as much as you can within the round and time limits.

The game

A fixed dark store on a grid: refrigerated dairy cabinets, bakery racks, produce bins, pantry shelves and loading bays in the back wall. Each product has its own local section. Each docked truck carries one online order, so several orders are open at once and you decide which truck each robot serves.

Each round
Your bot receives the full store state and replies with one action per robot: move, pick up, load or wait.
Robots
Carry up to three items. Pick up from an adjacent shelf; shelves never run out. Robots block each other except at the spawn, and moves resolve in robot ID order. There is no way to discard an item, so a wrong pick keeps its slot until an order needs it.
Loading
From the three cells in front of a bay, a robot loads every item that truck’s order still needs with load. A full truck leaves and returns with a new order, which you can see while it is away. Each trip draws a new away time: 6–10 rounds on Easy, 7–13 on Medium and Hard, 12–20 on Expert, and 15–25 on Nightmare. Leaving and arriving take one round each. Once it leaves, rounds_until_back shows the exact return countdown.
Score
1 point per loaded item, awarded immediately even if the truck is not full, and 5 more when its order is complete.
Time
300 rounds (500 on Nightmare), with a total time limit of 2 minutes (5 on Nightmare). The server must receive each reply within its 2-second response window; leave margin for network latency. If you miss a reply, all robots wait that round and the game continues. A disconnect ends the game.
Five stores, from one robot to twenty
StoreGridRobotsTrucksProductsItems per order
Easy12 × 101243–4
Medium16 × 123383–5
Hard22 × 1453123–5
Expert28 × 18104164–6
Nightmare30 × 18206214–7

Build and run your bot

Install the CLI, or copy the setup prompt for your AI assistant. The installer works on macOS, Linux and Windows with WSL, and requires Python 3.11 or newer.

curl -fsSL https://grocerybot.no/static/install.sh | sh

Create your bot project, log in and play:

grocerybot init my-bot
cd my-bot
grocerybot login
grocerybot play --store easy

This creates a Python bot. For JavaScript, use grocerybot init my-bot --template javascript with Node.js installed. The generated PROTOCOL.md explains the JSON messages and actions.

Login opens your browser for your NM i AI account. Approve the CLI, then follow any remaining prompts in your terminal to choose your leaderboard name. The CLI saves its own credential; you do not need to copy an API key.

The play command starts one game. See your best scores and recent games on your account page, or use grocerybot games list. To inspect a game recorded on this computer, run grocerybot replay latest.

If you write your own WebSocket connection, the protocol reference explains how to connect with the API key from your account.

Scores and limits

  • Every store and its product locations are fixed. Orders and truck trip times vary. Games submitted to the leaderboard use a private scenario chosen by the server; you cannot select its seed.
  • Your best game score in each difficulty counts. Your total is the sum of your five best scores. A lower score in a later game will not reduce your best score or total.
  • Games ended by a time limit or disconnect keep the score earned so far. Games voided because of a server error do not affect your best scores or daily limit.
  • Play one game at a time per account, with up to 50 games per day. The daily limit resets at midnight in Oslo.
  • Equal totals share the same rank.
  • There is no scheduled end date. Games may be paused for maintenance.

Errors

The CLI explains errors in the terminal. If you connect directly over WebSocket, check the close code and reason:

CodeMeaning
4001Invalid, expired or revoked credential. Log in again, or check your API key.
4002Unknown difficulty
4003Daily game limit reached. It resets at midnight in Oslo.
4004Server at capacity, try again shortly
HTTP 403Browser origin not allowed; the connection is refused before a WebSocket opens.
4006Unsupported protocol, changed ruleset or invalid run ID. Check the reason; update the CLI if needed.
4008This run already exists. Look up its result instead of starting it again.
4009You already have a game running. Wait for it to finish.
4010Games are unavailable or paused. Please try again later.
1011Could not start the game or confirm its result. Check your game history before trying again.

Fair play

  • One account per person. Play individually: one account, one leaderboard entry.
  • Any method and any language are welcome: search, optimisation, learning, AI coding assistants.
  • Keep your credentials private. Creating a new API key disables the old API key immediately. Don’t try to overload or break the server.
  • We may void games or remove entries that break these rules.