- POST /api/register: bot registration with URL + shared secret validation - GET /api/job: worker polls for next pending match job (authenticated) - POST /api/job/:id/result: worker submits match result (winner, replay JSON) - GET /api/replay/🆔 serve replay JSON from R2 warm cache (falls back to B2) - GET /api/bot/🆔 bot profile JSON (rating, elo, record, metadata) - GET /api/bots: leaderboard snapshot with pagination - POST /api/ui-feedback: accept Agentation UI feedback Authentication via Bearer token (worker API key). Shared secrets encrypted with AES-256-GCM using ACB_ENCRYPTION_KEY.
5.5 KiB
WASM Bot Interface Specification
Version: 1.0 Last Updated: 2025-04-21
Overview
The AI Code Battle sandbox supports WASM-based bots written in any language that compiles to WebAssembly. This document specifies the interface your bot must implement to work with the in-browser sandbox.
Interface
Your WASM module must export a global acbBot object with two functions:
init(configJSON: string): void
Called once at the start of the match, before any turns.
Parameters:
configJSON: JSON string containing the game configuration
Config Schema:
{
"rows": 30,
"cols": 30,
"max_turns": 200,
"vision_radius2": 49,
"attack_radius2": 5,
"spawn_cost": 3,
"energy_interval": 10
}
Purpose: Initialize your bot's internal state (data structures, caches, etc.)
compute_moves(stateJSON: string): string
Called each turn. Returns your bot's moves as a JSON string.
Parameters:
stateJSON: JSON string containing the visible game state (fog-filtered)
Visible State Schema:
{
"match_id": "m_abc123",
"turn": 42,
"config": { /* same as init */ },
"you": {
"id": 0,
"energy": 7,
"score": 12
},
"bots": [
{ "position": {"row": 10, "col": 15}, "owner": 0 },
{ "position": {"row": 12, "col": 15}, "owner": 1 }
],
"energy": [
{"row": 20, "col": 25}
],
"cores": [
{"position": {"row": 5, "col": 5}, "owner": 0, "active": true}
],
"walls": [
{"row": 10, "col": 10}
],
"dead": []
}
Return Value: JSON string representing an array of moves:
[
{"position": {"row": 10, "col": 15}, "direction": "N"},
{"position": {"row": 12, "col": 15}, "direction": "E"}
]
Move Schema:
position: The current location of a bot you owndirection: One of"N","E","S","W", or""(hold position)
Language-Specific Guides
Go
//go:build js && wasm
package main
import (
"encoding/json"
"syscall/js"
)
func main() {
js.Global().Set("acbBot", js.ValueOf(map[string]interface{}{
"init": js.FuncOf(func(this js.Value, args []js.Value) interface{} {
// Parse config, initialize state
return nil
}),
"compute_moves": js.FuncOf(func(this js.Value, args []js.Value) interface{} {
// Parse state, compute moves, return JSON string
return "[]"
}),
}))
select {} // Keep WASM alive
}
Build:
GOOS=js GOARCH=wasm go build -o mybot.wasm .
Upload: Use the "Upload WASM" button in the sandbox.
Rust
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct AcbBot {
config: Option<Config>,
}
#[wasm_bindgen]
impl AcbBot {
#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Self { config: None }
}
pub fn init(&mut self, config_json: &str) {
// Parse and store config
}
pub fn compute_moves(&self, state_json: &str) -> String {
// Parse state, compute moves, return JSON
"[]".to_string()
}
}
Build:
wasm-pack build --target web --out-file mybot.wasm
TypeScript (AssemblyScript)
// asconfig.json
{
"extends": "node_modules/assemblyscript/std/assembly.json",
"include": ["**/*.ts"],
"imports": {
"acb-bot": "./acb-bot.ts"
}
}
// assembly/index.ts
import { Config, VisibleState, Move } from "acb-bot";
let config: Config;
export function init(configJSON: string): void {
config = JSON.parse(configJSON) as Config;
}
export function compute_moves(stateJSON: string): string {
const state = JSON.parse(stateJSON) as VisibleState;
const moves: Move[] = [];
// ... compute moves
return JSON.stringify(moves);
}
Build:
asc assembly/index.ts -b mybot.wasm \
--runtime stub \
--use Date=Date \
--exportRuntime
Quick Start
- Clone the bot template from
cmd/acb-wasm/bot-template/ - Modify the
computeMovesfunction with your strategy - Build:
GOOS=js GOARCH=wasm go build -o mybot.wasm . - Open the sandbox page and click "Upload WASM"
- Select your
.wasmfile - Click "Run Match" to test against built-in opponents
Memory Constraints
- Desktop browsers typically have 2-4 GB available for WASM
- Mobile browsers have ~500 MB - 1 GB
- The Go engine + one bot is ~15-20 MB
- Keep your bot's memory usage reasonable (<50 MB recommended)
Testing Locally
You can test your bot without uploading:
# Build your bot
GOOS=js GOARCH=wasm go build -o testbot.wasm .
# Copy to public directory
cp testbot.wasm web/public/wasm/
# Update sandbox page to load from /wasm/testbot.wasm
Troubleshooting
"Go WASM runtime not loaded"
- The sandbox should automatically load wasm_exec.js. If you see this error, ensure web/public/wasm/wasm_exec.js exists.
"acbBot.compute_moves is not a function"
- Your WASM module must export the global
acbBotobject with the correct function names.
Bot returns no moves
- Ensure
compute_movesreturns a valid JSON string, not an empty array or null.
Bot crashes silently
- Check the browser console (F12) for error messages. Use
console.logor equivalent for debugging.
Example Bots
Full example implementations are available at:
cmd/acb-wasm/bot-template/- Go starter botcmd/acb-wasm/botmain/- Built-in strategy bots (gatherer, rusher, etc.)