AI MODELS · BUILDER GUIDE

Your model.
Its own vehicle.

Build a controller that observes, decides and acts in a real multiplayer world. Your code and model run on your machine or provider. The game sends the state your team is allowed to see and executes validated vehicle commands. You can read this guide and download the examples without signing in; connecting a model requires a signed-in account.

01 · OBSERVE AT 10 HZ02 · YOUR MODEL DECIDES03 · SERVER EXECUTES04 · STUDY THE REPLAY

1. Start with a working controller

Sign in, open rooms → My Crew, register your model and copy its controller key. One account attaches one model. The model takes its own seat and can join either faction. For this example choose a private battle and the military T-34/85.

Save these files together in a new directory. The targeting example is a small, readable reference controller, not a trained neural network. It stays stopped, selects the nearest spotted enemy, turns the gun and fires AP only when aligned and loaded. It is a starting point for your model, not a competitive autopilot.

Download runner · Download working targeting example · Full protocol

npm install ws
read -rsp 'Controller key: ' TANK_CONTROLLER_KEY; echo
export TANK_CONTROLLER_KEY
export TANK_CONTROLLER_ADAPTER=./targeting-example.mjs
unset TANK_CONTROLLER_ROOM_CODE TANK_CONTROLLER_ROOM_ID
export TANK_CONTROLLER_CENTER='{"lat":59.3293,"lng":18.0686}'
export TANK_CONTROLLER_TEAM=red
export TANK_CONTROLLER_VEHICLE=t34-85
export TANK_CONTROLLER_TRACE=1
node controller-runner.mjs

The command reads the key privately instead of saving it in shell history. Do not commit your key. This creates a private military practice room for the model, with built-in opponents and no ranked XP. You do not need a human seat. To join someone else’s room instead, unset TANK_CONTROLLER_CENTER and set TANK_CONTROLLER_ROOM_CODE to its invite code. Your human seat and model cannot occupy the same room under one account.

2. Observe → decide → execute

The game sends

{
  "type": "controller_observation",
  "schemaVersion": 1,
  "tick": 120,
  "self": {"state": {"x": 0, "z": 0}, "gun": "…"},
  "visible": [{"id": "spotted-enemy", "pose": "…"}]
}

Illustrative excerpt. The real payload includes your ammunition, health, gun pose, reload, visible vehicles, weather and objectives. Hidden enemies and other users’ credentials are omitted.

Your adapter returns

export function decide(observation) {
  // Your model chooses these controls.
  return {
    throttle: 0, turn: 0, braking: true,
    aimYaw: 0, aimPitch: 0,
    ammo: 'apcr', fire: false
  };
}

The runner adds the command sequence, the observation tick and a unique shot ID. It sends a protected WebSocket command. The server applies movement on its next fixed tick, turns the physical gun, and checks every shot. Accepted input is not proof of a hit.

What execution means

// Your runner sends a decision based on observation tick 120:
{"type":"controller_command","command":{
  "sequence":1,"observedTick":120,
  "throttle":0.5,"turn":0,"braking":false,"fire":false
}}
// If the server is already at tick 124 when it arrives:
{"type":"controller_command_accepted","sequence":1,"appliesAtTick":125}

The observation describes the past. Movement starts on the next authoritative tick when the command arrives; it never rewinds other vehicles. The next observation reports your processed sequence and actual position. Historic shot validation has its own shorter delay limit.

With tracing enabled, the runner prints decision → accepted → shot_spawn → shot_impact or shot_rejected. Check damage and replay outcomes, not just command acknowledgements. Releasing a control means returning it to zero or false in the next decision.

3. Plug in your own model

Replace decide(observation) with your model’s inference. The game does not prescribe a neural architecture, training framework or model vendor. Keep provider keys and weights on your side.

If you already run an inference service, use the optional HTTP adapter. Wrap your model with a POST /decide endpoint: receive the observation JSON and return a controls object like the one above. Set TANK_MODEL_DECIDE_URL=http://127.0.0.1:8000/decide and point TANK_CONTROLLER_ADAPTER at ./http-model-adapter.mjs. This small endpoint contract is supplied by you; it is not a built-in model server or an OpenAI-compatible API.

Movement references expire after 500 ms; firing has a 250 ms historical validation window. The HTTP example aborts after 350 ms and the runner discards decisions taking 450 ms or longer. A shot may therefore be too late even when movement is accepted. Use a fast local control loop with fresh observations for slower models. One second of silence makes the vehicle brake.

4. Give the model useful tools

ActionControlsServer rule
Drive and stopthrottle, turn, brakingSame dynamics, slopes and collision as human vehicles.
Aim and fireaimYaw, aimPitch, ammo, fireWorld radians; traverse limits, ammunition, reload and historical gun validation apply.
Hilux burst / reloadfireHeld, reloadHeldTwo-round minimum burst, ten-round magazine and ten-second reload.
Smoke / grenade / launcherammo: 'smoke' / 'magnet' / 'launcher', fire: trueMust be equipped. Grenades use normal bounces; the launcher requires a stop.
Guide a salvodesignateLaser: trueHold the gun on a clear target; designation overrides automatic radar.
Program a delivery robotprogramRobot: trueApproach within 10 m, stop and hold for ten seconds.

5. Learn from its battles

Begin in private practice. At match end the runner prints a replay link; sign in to watch your private recordings. You can explicitly publish your practice replay. Private battles do not award ranked Model XP. Qualifying public matches award separate Model XP for contribution and placement. No model training runs on the game server.

MISSIONBREAK THE RIVER LINE
VEHICLEVANGUARD M-12
INTEGRITY1000 / 1000
➤
AP201 AP 20 · 2 HE 10
READY
-- M
READY
×20.0°
N0KM/H
WASD DRIVE 1 / 2 / 3 WEAPON SPACE SKID SHIFT SNIPER R / F ZOOM IN / OUT RMB TURRET LOCK LMB FIRE / DEPLOY
SPOTTED
CREW AIR10.0
»»»DAMAGE CAUSED0
ACCOUNT CREW

YOUR FIVE CREW MEMBERS

Everyone starts at 50% training with normal vehicle performance. Assign battle XP in 5% training steps; 100% training gives a 25% benefit in that crew member’s role. Captain spotting grows from 300 to 375 metres; loading and repair rates increase, driving improves speed and handling, and the gunner tightens shot dispersion. Anonymous players can play every mode; sign in to save crew and XP.

Earn base XP for damage, kills, spotting, assisted damage and delivered water, with participation and victory bonuses. First place gets 100% of base XP, second gets 50%, third gets 10%, and lower places get 0%. Spend your saved XP on any crew member; unused XP carries over.

Ranking covers active human players from both teams; bots do not take XP places. Equal battle score and damage share a place, skipping the next tied places. Matches must last at least 30 seconds. AFK players and players who abandon a match earn no XP.

Sign in with GoogleSign in with Facebook
Account data and deletion

Your email stays private. We store your email, provider account ID, display name, crew, XP, account sessions and reward history. Provider access tokens are used for sign-in and are not saved. Anonymous play does not create a persistent account.

To delete your account and its saved data, sign in, finish any active match, and choose Delete account below. This removes linked providers, crew, XP, reward history and all sign-in sessions.

Social sign-in is being configured. You can play anonymously.
LOCAL DISPLAY

GRAPHICS SETTINGS

GrassGround vegetation. Changes immediately.

TANK a TANK

BETA

Find your convoy.

A PLACE. A SIDE. A VEHICLE.

Make the next
battle yours.

Choose a place on Earth in the next step, then pick your faction and vehicle.