Skip to main content

UNSW Battlecode

unswbc is the toolkit for UNSW CPMSoc's Battlecode competition. It creates a bot project, builds it with the compiler already on your machine, and plays two bots against each other on a map, writing a replay you can watch.

Install

unswbc is a Python package. Install uv first.

macOS and Linux

curl -LsSf https://astral.sh/uv/install.sh | sh

Windows, in PowerShell

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Open a new shell so uv is on your PATH. Then install the toolkit:

uv tool install unswbc

That puts unswbc on your PATH. Upgrade with uv tool upgrade unswbc, and pin a version with uv tool install unswbc==0.3.0.

Without uv

Possible, but not recommended. You need Python 3.11 or newer already installed, and you manage the environment yourself:

python3 -m venv ~/.unswbc && ~/.unswbc/bin/pip install unswbc

unswbc then lives at ~/.unswbc/bin/unswbc. Put that directory on your PATH to run it by name. Plain pip install --user unswbc is not an option: most Linux distributions and Homebrew refuse it.

The same wheel runs on macOS, Linux and Windows. It carries the game engine, every contest map and the VS Code replay viewer, so there is nothing else to download. It runs your bots with the tools already on your machine, so for C or C++ bots you still need a compiler.

Your first bot

unswbc init python mybot
unswbc run maps/arena.map mybot mybot

init writes a working bot and a helper library into mybot/, and adds missing contest maps to a shared maps/ folder beside it. Existing maps are never overwritten, even with init --force. run takes a map and exactly two bots, builds both and plays them, then writes a .replay file. Name the same project twice to play it against itself.

Leave the language out and init asks for it, so unswbc init mybot works too.

After upgrading the toolkit, run unswbc maps to add newly bundled maps to maps/ without creating a bot. You can choose another folder with unswbc maps path/to/maps. When initializing a bot in the current directory, the shared map folder is ../maps/; use unswbc maps ../maps to update it.

unswbc                 # the commands, and what this machine is missing
unswbc --build         # the same, but compile a test program too
unswbc run <map> a b   # two different bots
unswbc run <map> a b --no-replay
unswbc init python     # writes into the current directory
unswbc log             # the errors this machine has hit
unswbc help <command>

Submitting

Make an API key on your team page, give it to unswbc once, then upload from the command line. The zip holds bot.toml and the files project.include names, laid out the way the judge wants:

unswbc auth set bc_...            # keeps it in ~/.unswbc/keys.json, one key per server
unswbc auth status                # which server, which key, which team
unswbc submit mybot               # upload the project in mybot/
unswbc submit mybot -n v12 -d "wider search"
unswbc auth clear                 # forget the key for this server

The version is named after the folder and the date unless -n says otherwise. UNSWBC_KEY overrides the stored key, for CI.

When something breaks

Every error unswbc prints is also appended to ~/.unswbc/log. unswbc log shows it. Quote it when you ask for help.

A bot is an ordinary process: unswbc writes the board to its stdin each turn and reads the move back from stdout. Anything that can read and write text can play.

variable effect
UNSWBC_PYTHON the interpreter to run .py bots with
CC, CXX the compilers to build .c and .cpp bots with
UNSWBC_TURN_MS per-turn deadline, default 10
UNSWBC_WARMUP_MS first-turn allowance, measured from spawn, default 200
UNSWBC_SERVER the contest server, default https://game.battlecode.au
UNSWBC_KEY the API key to submit with; beats the stored one
UNSWBC_NO_VSCODE do not set up the replay viewer
NO_COLOR plain output; colour is off anyway when the output is piped

In the judge

The judge runs bots inside a WebAssembly sandbox, so the same code behaves the same on every machine, and it measures work in CPU points rather than seconds: each WebAssembly instruction has a fixed price, so a slow judge day cannot cost you a turn.

limit value
points per dragon per turn 100 million
memory per dragon 48 MB
time per turn 2 s of CPU, 20 s wall; a backstop that only ever catches a bot that found a way around the meter

A turn over its budget gives no reply, and a dragon that gives no reply dies that turn, so leave yourself a margin. A dragon's first turn is no exception: the interpreter and NumPy are already loaded, but your own imports and setup count, so spread heavy precomputation over turns or do it lazily. Prices, in points: most instructions 1, loads and stores 2, division 3, calls 4 to 6, memory growth 50, bulk copies and fills 10 plus 1 per 8 bytes, and 2 for everything else, which includes 128-bit SIMD. Writing output costs 2.5 million per write plus 4,000 per byte, so keep logging light. The full table is opcode_cost in judge/sandbox/src/limits/cpu.rs.

Rough costs to plan around: parsing a round in the Python helper is ~10 million points, a full-map flood fill on 32x32 is ~19 million in Python and ~0.3 million in C++. C and C++ are compiled with -O2 -msimd128 against the C standard library and libc++, with the zip's own directory on the include path; there are no other libraries, so vendor any you need as source. Vector code is priced like scalar code and runs as real SIMD, so it is worth writing. Python runs on CPython 3.13 with the standard library and NumPy 2.5, nothing else, so vendor any pure-Python code you need.

Output is sent when you flush, and a flush is one write. The helpers flush once, at the end of the turn, and reading your next turn flushes too, so leave it that way: a bot that flushes after every line pays 2.5 million points a line. In C++ that means no std::unitbuf, no cin.tie(nullptr) unless you flush at ENDTURN yourself, and std::clog rather than std::cerr for debug output. To C and C++ the judge's stdout looks like a terminal (isatty is true), so C stdio is line buffered: with sync_with_stdio(false) every line that ends in \n goes out as its own write, at 2.5 million points each. Python is unaffected, since the helper's stdout is fully buffered. A wait that nothing can end, such as taking a lock twice on your only thread, ends the turn over budget at once.

Matches are reproducible: randomness comes from a generator seeded per dragon and match, and the clock advances with the points you spend, so time.sleep costs no real time and timing your own search measures points.

Watching replays

The VS Code extension opens any .replay file as an interactive board with a game log, per-team statistics and charts. unswbc ships it and installs it when unswbc init creates a project, so there is nothing to download. To redo that at any point:

unswbc vscode

Replays also open at game.battlecode.au, which uses the same renderer.

Building from source

Only needed if you want to change the toolkit itself. unswbc is a pure Python package, so there is nothing to compile:

pip install -e pythoncli

pythoncli/unswbc/unswbc_engine.wasm and replay-viewer.vsix are committed prebuilt, so a checkout needs no toolchain. Rebuild them with pythoncli/build-wasm.sh (needs wasi-sdk) and pythoncli/build-vsix.sh (needs node and pnpm).

unswbc run --sandbox is the exception: it runs on the judge's own metered interpreter, which is not in this repository, so a source checkout cannot use it. Install the released package for that.

Layout

directory what it is
pythoncli/ the unswbc command, and the init project templates
engine/ the game rules, the replay format and the bot protocol
packages/visualiser/ the board renderer, shared by the web app and VS Code
vscode-extension/ the replay viewer
examples/ bots to play against
maps/ boards

Release files for unswbc 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for unswbc 0.3.0
File Interpreter ABI Platform
unswbc-0.3.0-py3-none-any.whl Python 3 none any Details

Release files / unswbc-0.3.0-py3-none-any.whl

Download URL unswbc-0.3.0-py3-none-any.whl
Size 19.1 MB
Tags Python 3
SHA-256 checksum
How to use checksums
56a1ba1dc2fd88f2136b21e592090d2f3ac2a7f1deb47441724f15ef70cd76c5
BLAKE2b-256 checksum
How to use checksums
1857a42f11c3f2f1bd54ac3245f3c97c4598763a62db0a40bed5e07b42ea59b7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release history Release notifications | RSS feed

1.1.0

1 release file

1.0.2

1 release file

1.0.1

1 release file

1.0.0

1 release file

0.3.13

1 release file

0.3.12

1 release file

0.3.11

1 release file

0.3.10

1 release file

0.3.9

1 release file

0.3.7

1 release file

0.3.6

1 release file

0.3.5

2 release files

0.3.4

1 release file

0.3.3

1 release file

0.3.2

1 release file

0.3.1

1 release file

This release

0.3.0 This release

1 release file

0.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page