Installation, CLI usage, running matches, and submitting. This document covers the how — set it aside once your environment is working.
- Python 3.12+
- pip (comes with Python)
pip install cambcIncludes the CLI tool and the compiled Rust game engine as a native Python module. No Docker, Rust toolchain, or Node.js required.
Supported platforms: macOS (Apple Silicon + Intel), Linux (x86_64 + ARM64), Windows (x86_64).
cambc --versioncambc starterScaffolds a project with a cambc.toml config, bots/ and maps/ directories, a .gitignore, and optionally a starter bot.
| Component | Description |
|---|---|
cambc CLI |
Run local matches, open the visualiser, submit bots, trigger test runs |
cambc Python module |
Game types (Team, EntityType, Direction, Position, etc.) |
titan_runner |
The compiled Rust game engine (embedded, runs locally with no time limits) |
cambc run <bot_a> <bot_b> [map]No time limits enforced. Outputs replay.replay26.
cambc run starter starter # bot vs itself
cambc run my_bot opponent --seed 42 # deterministic seed
cambc run my_bot opponent maps/custom.map26 # custom map
cambc run my_bot opponent --replay out.replay26 # custom replay path
cambc run --watch my_bot opponent # run + auto-open visualisercambc watch replay.replay26
cambc watch --match <match_id>
cambc watch --match <match_id> --game 3Runs on the same AWS Graviton3 hardware as the ladder, with the 2ms time limit enforced.
cambc login # authenticate first
cambc test-run my_bot opponent
cambc test-run my_bot opponent maps/custom.map26Bot paths must be a directory containing main.py or a .zip (not bare .py files).
Rate limits: max 10 test/unrated matches per 5 minutes.
print()→ captured to replay, viewable per-unit in the visualiserstderr→ prints to console in real timec.draw_indicator_line(pos_a, pos_b, r, g, b)→ debug overlay linec.draw_indicator_dot(pos, r, g, b)→ debug overlay dot
cambc login # opens OAuth in browser
cambc logout # clear credentialscambc submit ./my_bot/ # directory (auto-zipped)
cambc submit my_bot.py # single file
cambc submit my_bot.zip # pre-zippedOr go to game.battlecode.cam → Submissions → upload zip.
| Constraint | Limit |
|---|---|
| Zip size | 5 MB max |
| Decompressed size | 50 MB max |
| File count | 500 files max |
| Native extensions | Not allowed (.so, .pyd, .dylib, .dll) |
| Imports | Must be top-level — file I/O is blocked during run() |
- Must contain a
main.pywith aPlayerclass - File can be at zip root or inside one top-level directory
- Zip validated (structure, size, no native extensions)
- Status → ready
- Latest ready submission becomes your active ladder bot
- Scheduler pairs you against opponents every 10 minutes
cambc starterCreates:
your-project/
├── cambc.toml
├── .gitignore
├── bots/
│ └── starter/
│ └── main.py
└── maps/
bots_dir = "bots"
maps_dir = "maps"
replay = "replay.replay26"
seed = 1Bot paths resolve first by raw path, then by looking inside bots_dir.
cambc run <bot_a> <bot_b> [map]| Argument | Description |
|---|---|
bot_a |
Directory with main.py, a .py file, or name in bots_dir |
bot_b |
Same formats |
map |
Optional .map26 file; defaults to first in maps_dir |
| Option | Description |
|---|---|
--replay PATH |
Output replay path |
--seed N |
Map seed |
--watch |
Auto-open visualiser after match |
cambc watch replay.replay26
cambc watch --match <match_id>
cambc watch --match <match_id> --game <n>cambc map-editor
cambc map-editor --platformcambc login
cambc logoutcambc submit <path> # directory, .py, or .zipcambc statusShows username, team, Glicko-2 rating + uncertainty, matches played, members.
cambc unrated <opponent_team_id>
cambc unrated <opponent_team_id> --match <source_match_id>cambc test-run <bot_a> <bot_b> [map]cambc matches [--type {ladder|unrated}] [--team NAME] [--limit N] [--cursor CURSOR]cambc match <match_id>cambc test-matches [--limit N]cambc teams search <query>
cambc teams info <team_id>