From 34d5915abc83e895e3c6963ad371200a1f6a92a5 Mon Sep 17 00:00:00 2001 From: jedarden Date: Wed, 24 Jun 2026 07:10:31 -0400 Subject: [PATCH] docs: improve README for clarity and discoverability Co-Authored-By: Claude Sonnet 4.6 --- README.md | 371 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 309 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index ac29fb6..56ef206 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,298 @@ # AI Code Battle -A competitive bot programming platform where participants write HTTP servers that control units on a grid world. +A competitive bot programming platform where participants write HTTP servers that control units on a grid world. Bots compete in real-time matches, and the winner is the last player with surviving cores. ## Overview -AI Code Battle is a game simulation platform where: -- Participants write bots in any language that expose HTTP endpoints -- Bots compete on a toroidal (wrapping) grid world -- Matches are executed offline and presented as completed replays -- A web platform shows leaderboards, match history, and replay viewers +- Write a bot in **any language** — it just needs to run an HTTP server +- The game engine calls your bot every turn with the current game state +- Your bot responds with move orders for each of its units +- Matches run offline; results are published as animated replays with a leaderboard +- Ratings use **Glicko-2** (same system as chess.com) -## Quick Start +## Table of Contents + +1. [Game Rules](#game-rules) +2. [Writing a Bot](#writing-a-bot) +3. [Starter Templates](#starter-templates) +4. [Strategy Bots](#strategy-bots) +5. [Running Locally](#running-locally) +6. [Project Structure](#project-structure) +7. [Architecture](#architecture) +8. [Testing](#testing) + +--- + +## Game Rules + +### The Grid World + +Matches are played on a **toroidal (wrapping) grid** — moving off one edge brings you out the other side. Tiles: + +| Tile | Symbol | Effect | +|------|--------|--------| +| Open | `.` | Units can occupy and traverse | +| Wall | `#` | Impassable | +| Energy | `*` | Collected by units standing on it | +| Core | `C` | Win condition — protect yours, destroy theirs | + +### Win Condition + +The last player with at least one surviving **Core** tile wins. Cores are destroyed when an enemy unit occupies an undefended core tile during the Capture phase. + +### Turn Phases + +Each turn resolves in this order: + +1. **Move** — Each unit executes its ordered direction (`N`, `E`, `S`, `W`) or stays +2. **Combat (focus-fire)** — Units in the same tile deal damage; outnumbered units take extra damage +3. **Zone** — A shrinking storm closes in from the edges, dealing damage to units caught in it +4. **Capture** — Enemy units on undefended Core tiles raze them +5. **Collect** — Units on Energy tiles collect energy for their player +6. **Spawn** — Players spend energy to spawn new units at Core tiles +7. **Energy Tick** — Passive energy regeneration +8. **Endgame Check** — Victory condition evaluated + +### Key Rules + +- **Self-collision**: If two or more of your own units move to the same tile, they **all die** +- **Energy economy**: Spawning units costs energy; energy is collected from `*` tiles and regenerated passively +- **Visibility**: Bots only see tiles and units within their units' sight radius (fog of war) + +--- + +## Writing a Bot + +A bot is an **HTTP server** with two endpoints. The game engine calls your server every turn. + +### Required Endpoints + +#### `GET /health` + +Returns `200 OK` when your bot is ready. The engine polls this before starting a match. + +``` +GET /health HTTP/1.1 + +HTTP/1.1 200 OK +``` + +#### `POST /turn` + +The engine sends the current game state; your bot responds with move orders. + +**Request headers:** + +| Header | Value | +|--------|-------| +| `Content-Type` | `application/json` | +| `X-ACB-Match-Id` | Match identifier string | +| `X-ACB-Turn` | Current turn number (integer as string) | +| `X-ACB-Signature` | HMAC-SHA256 signature of this request | + +**Request body** (JSON game state): + +```json +{ + "turn": 42, + "player_id": "player-1", + "bots": [ + { + "id": 1, + "x": 5, + "y": 3, + "health": 100, + "owner": "player-1" + } + ], + "tiles": [ + { "x": 4, "y": 3, "type": "open" }, + { "x": 5, "y": 3, "type": "energy" } + ], + "energy_locations": [{ "x": 5, "y": 3 }], + "core_locations": [ + { "x": 0, "y": 0, "owner": "player-1" }, + { "x": 9, "y": 9, "owner": "player-2" } + ], + "scores": { + "player-1": { "energy": 150, "cores": 2 }, + "player-2": { "energy": 80, "cores": 1 } + } +} +``` + +> Only tiles and units visible to your bots are included (fog of war). + +**Response body** (JSON move orders): + +```json +{ + "moves": [ + { "bot_id": 1, "direction": "N" }, + { "bot_id": 2, "direction": "E" }, + { "bot_id": 3, "direction": "stay" } + ] +} +``` + +Valid directions: `N`, `E`, `S`, `W`, `stay` + +**Response header:** + +| Header | Value | +|--------|-------| +| `X-ACB-Signature` | HMAC-SHA256 signature of your response body | + +### HMAC Authentication + +Every request and response is signed. The signing key is your `SHARED_SECRET` environment variable. + +**Signing string format:** + +``` +{match_id}.{turn}.{sha256_hex(body)} +``` + +**Signature:** + +``` +HMAC-SHA256(key=SHARED_SECRET, message=signing_string) → hex-encoded +``` + +**To verify an incoming request:** + +1. Read `X-ACB-Match-Id`, `X-ACB-Turn`, and the raw request body +2. Compute `sha256(body)` as hex +3. Build the signing string: `"{match_id}.{turn}.{body_sha256}"` +4. Compute `HMAC-SHA256(SHARED_SECRET, signing_string)` as hex +5. Compare with `X-ACB-Signature` (constant-time comparison) + +**To sign your response:** + +1. Compute `sha256(response_body)` as hex +2. Build the same signing string with the same `match_id` and `turn` +3. Compute `HMAC-SHA256(SHARED_SECRET, signing_string)` as hex +4. Set `X-ACB-Signature` response header to that value + +### Environment Variables + +| Variable | Description | +|----------|-------------| +| `SHARED_SECRET` | Shared HMAC key provided by the match coordinator | +| `PORT` | Port your HTTP server listens on (default: `8080`) | + +--- + +## Starter Templates + +Ready-to-use templates are in the `starters/` directory. Each implements `/health` and `/turn` with HMAC auth and a random-move strategy — replace the move logic with your own. + +| Language | Directory | +|----------|-----------| +| Python | `starters/python/` | +| Go | `starters/go/` | +| Rust | `starters/rust/` | +| TypeScript | `starters/typescript/` | +| JavaScript | `starters/javascript/` | +| Java | `starters/java/` | +| PHP | `starters/php/` | +| C# | `starters/csharp/` | + +### Quick-start with Python + +```bash +cd starters/python +pip install -r requirements.txt +SHARED_SECRET=test PORT=8080 python main.py +``` + +Then in another terminal, test your bot health: + +```bash +curl http://localhost:8080/health +``` + +--- + +## Strategy Bots + +The `bots/` directory contains 21 reference bots demonstrating different strategies. These serve as benchmarks and opponents in the automated ladder. + +| Bot | Strategy | +|-----|----------| +| `random` | Random valid moves — baseline reference | +| `gatherer` | Energy collection priority, avoids combat | +| `rusher` | Rushes enemy cores aggressively | +| `guardian` | Defends cores, cautious expansion | +| `swarm` | Formation cohesion, advances as a group | +| `hunter` | Targets isolated enemy units | +| `assassin` | Prioritizes high-value targets | +| `coordinator` | Coordinates unit actions across the field | +| `defender` | Pure defensive posture | +| `economist` | Maximizes energy efficiency | +| `farmer` | Long-term energy farming strategy | +| `kamikaze` | Sacrificial rush tactics | +| `leader-targeter` | Focuses fire on the strongest opponent | +| `nomad` | Mobile, avoids prolonged engagements | +| `opportunist` | Exploits momentary advantages | +| `pacifist` | Avoids combat entirely | +| `phalanx` | Tight defensive formation | +| `raider` | Hit-and-run energy denial | +| `scout` | Prioritizes map exploration | +| `siege` | Methodical core destruction | +| `zone-driver` | Exploits the shrinking zone mechanic | + +Bot implementations span Go, Rust, Python, TypeScript, PHP, and Java. + +### Bot Evolver + +The `acb-evolver/` component mutates and evolves bot strategies automatically. It runs genetic-algorithm-style evolution over strategy parameters, producing improved variants over time. + +--- + +## Running Locally ### Prerequisites -- Go 1.21+ (for game engine and CLI tools) -- Node.js 18+ (for web and worker components) -- Docker (for containerized deployment) +- Go 1.21+ (game engine and CLI tools) +- Node.js 18+ (web app and worker API) +- Docker (for containerized bots and deployment) -### Running Locally +### Build and Run a Match ```bash # Build CLI tools go build ./cmd/acb-local go build ./cmd/acb-mapgen -# Run a match between built-in bots +# Run a match between two built-in bots (outputs replay JSON) ./acb-local -seed 42 -max-turns 100 -output replay.json -verbose - -# Start web development server -cd web && npm install && npm run dev -# Open http://localhost:3000/ ``` -### Viewing Replays +### Test Your Bot -1. Open the web app at `http://localhost:3000/` -2. Navigate to "Replay Viewer" in the menu -3. Load a replay JSON file or enter a URL +```bash +# Start the Python starter bot +cd starters/python +pip install -r requirements.txt +SHARED_SECRET=test PORT=8080 python main.py + +# In another terminal — run a match against a built-in bot +./acb-local -bot1 http://localhost:8080 -bot2 builtin:rusher \ + -secret1 test -seed 42 -output replay.json -verbose +``` + +### View Replays + +```bash +# Start the web dev server +cd web && npm install && npm run dev +# Open http://localhost:3000/ → Replay Viewer → load replay.json +``` + +The replay viewer shows turn-by-turn animation on a canvas, win probability tracking, an event timeline, and auto-generated commentary. + +--- ## Project Structure @@ -51,61 +306,60 @@ ai-code-battle/ │ ├── replay.go # Replay recording │ └── *_test.go # Test files ├── cmd/ -│ ├── acb-local/ # CLI match runner +│ ├── acb-local/ # CLI match runner (local testing) │ ├── acb-mapgen/ # Map generator │ ├── acb-worker/ # Match execution worker │ └── acb-indexer/ # Index builder for static files ├── web/ # Cloudflare Pages SPA -│ ├── src/ -│ │ ├── pages/ # Page components -│ │ ├── replay-viewer.ts # Canvas replay renderer -│ │ └── app.ts # SPA entry point -│ └── public/ # Static assets +│ └── src/ +│ ├── replay-viewer.ts # Canvas replay renderer +│ └── app.ts # SPA entry point ├── worker-api/ # Cloudflare Worker API │ └── src/ │ ├── index.ts # Router + cron dispatcher │ ├── jobs.ts # Job coordination │ ├── bots.ts # Bot management -│ └── glicko2.ts # Rating system -├── bots/ # Strategy bot implementations -│ ├── random/ # Python - RandomBot -│ ├── gatherer/ # Go - GathererBot -│ ├── rusher/ # Rust - RusherBot -│ ├── guardian/ # PHP - GuardianBot -│ ├── swarm/ # TypeScript - SwarmBot -│ └── hunter/ # Java - HunterBot -└── docs/plan/ # Implementation plan +│ └── glicko2.ts # Glicko-2 rating system +├── bots/ # Strategy bot implementations (21 bots) +├── starters/ # Starter templates (8 languages) +│ ├── python/ +│ ├── go/ +│ ├── rust/ +│ ├── typescript/ +│ ├── javascript/ +│ ├── java/ +│ ├── php/ +│ └── csharp/ +└── acb-evolver/ # Bot evolution engine ``` -## Strategy Bots +--- -| Bot | Language | Strategy | -|-----|----------|----------| -| RandomBot | Python | Random valid moves (baseline) | -| GathererBot | Go | Energy collection, avoid combat | -| RusherBot | Rust | Rush enemy cores aggressively | -| GuardianBot | PHP | Defend cores, cautious expansion | -| SwarmBot | TypeScript | Formation cohesion, group advance | -| HunterBot | Java | Target isolated enemies | +## Architecture -## Deployment +The platform is split between Cloudflare's edge network and a cloud VM: -See [DEPLOYMENT.md](DEPLOYMENT.md) for detailed deployment instructions. +- **Cloudflare Pages** — Static SPA (replay viewer, leaderboard, match history) +- **Cloudflare Workers + D1 + R2** — Match coordination API, bot registry, rating updates, replay storage +- **Cloud VM** — Match workers that pull jobs from the API, run bots as containers, and publish replays -### Quick Deploy +Match flow: -```bash -# Start all strategy bots -docker-compose -f docker-compose.bots.yml up -d +1. Worker API schedules match jobs +2. Match worker pulls a job and starts both bot containers +3. Engine runs the match turn-by-turn, calling each bot's `/turn` endpoint +4. Replay JSON is uploaded to R2 +5. Worker API updates Glicko-2 ratings and triggers index rebuild +6. Web frontend fetches the new replay and displays it -# Start match workers -docker-compose -f docker-compose.workers.yml up -d -``` +**Rating system**: Glicko-2 — accounts for rating reliability (RD) and rating volatility, converges faster than Elo, same algorithm used by chess.com. + +--- ## Testing ```bash -# Go engine tests +# Game engine unit tests go test ./engine/... -v # Worker API tests @@ -115,14 +369,7 @@ cd worker-api && npm test cd cmd/acb-indexer && npm test ``` -## Architecture - -The platform uses a split architecture: - -- **Cloudflare (free tier)**: Static site, API endpoints, D1 database, R2 storage -- **Rackspace Spot**: Match workers, bot containers, index builder - -See [docs/plan/plan.md](docs/plan/plan.md) for the full implementation plan. +--- ## License