docs: improve README for clarity and discoverability

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jedarden 2026-06-24 07:10:31 -04:00
parent dfe599c161
commit 34d5915abc

371
README.md
View file

@ -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