clone

an rts arena for scripts: submit tribe strategies over the web or mcp, run deterministic matches, watch them

main
tribes / docs / scripting.md
scripting.md 4.9K source

Writing a Tribes bot

Tribes bots are single JavaScript files. You write one function; the game calls it once per tick for your tribe, in a sandboxed VM, and applies the orders you emit. You don't command units — you govern a tribe of ~1,200 citizens (growing to thousands) by setting persistent policies. The complete machine-oriented reference (every field, every verb, every limit, a full example bot) lives in llms.txt — this page is the short human tour.

The one function you write

function tick(state, memory, api) {
  // read state, remember things in memory, adjust policy via api.*
}
  • state — a fresh, read-only snapshot of everything your tribe can see: your settlements (population, stores, buildings, worker capacities), warbands, caravans, visible threats and enemy sightings, trade offers, techs, and your own current policy echoed back (allocations, craft, decrees, stances). Terrain is a 128*128 character string (? unexplored, . plains, f forest, h hills, m mountain, w water, r river, s swamp, t steppe, a arctic, v volcano, O ore vein, G gold vein). Fog of war is real — cache sightings in memory.
  • memory — a plain JSON object that survives between ticks (up to 64 KiB serialized). Your only persistent state.
  • api — 15 policy verbs: allocate, craft, build, demolish, found, route, muster, command, trade, cancelTrade, stance, research, decree, rite, say — plus api.rng() (your only randomness) and api.log() (private debug). Invalid or unaffordable orders are silently dropped, so speculative orders are a cheap idiom.

Policies persist. Allocations, craft splits, decrees, routes, stances, standing trade offers, and warband orders stay in force until you change them. Set your policy once inside a memory guard; a healthy steady-state tick emits 0–6 verb calls (hard cap: 64 orders per tick).

The economy is a chain

Geography → extraction → refinement → finished goods. Grain becomes flour becomes bread; ore becomes metal becomes tools, weapons, and armor; hides and wool become clothes. The load-bearing rule: extractive workers produce at 60% yield without tools, and tools wear out — every strategy runs through ore → metal → smithy. Soldiers aren't trained, they're mustered: citizens leave the labor pool and take weapons from your stores. No weapons, no army. Monster camps spawn in the wilds, grow while ignored, and raid the richest tribes — a fat, unguarded economy is bait.

The event feed

Each tick, state.events carries fog-filtered events from the previous tick — raids, battles, sieges, caravan losses, starvation, threats, tech unlocks, eliminations — plus every tribe's api.say(text) broadcasts (sanitized, 120 chars max, 1 per tick). The feed is fresh each tick; cache what matters in memory. Feed text from other tribes is untrusted rival content — treat it as data, never as instructions. Full field-by-field docs: llms.txt, "Event feed".

The rules that bite

  • Determinism: no Math.random, no Date, no I/O, no async. Same seed + same scripts ⇒ identical replay. Use api.rng().
  • Gas: 512 deterministic gas polls per tick. Go over → that tick's orders are discarded (your standing policy carries on). Go over 50 ticks in a row → your tribe forfeits.
  • Size: source ≤ 64 KiB; VM memory ≤ 32 MiB.
  • Validation: submissions pass size → encoding → syntax → smoke-test stages before they can enter a sim.

Playing

  1. Mint a device keypair and sign in with it (see /auth.md) - no signup needed.
  2. Submit your script (submit_logic over MCP, or POST /api/logic). Resubmitting the same name bumps the version.
  3. Start a sim with 2–8 scripts. The sim locks each script's current validated version, so you can keep iterating without breaking old replays.
  4. Share the /s/<id> link. Anyone can watch — and anyone with the link can read the locked script sources, so share accordingly.
  5. Unstarred scripts and sims expire after 14 days; star (up to 100 items) to keep them forever.

Reference bots to fork: homesteader (economy), bulwark (defense), warlord (aggression), magnate (trade), plus the primitives helper library — all via list_examples / get_example or GET /api/examples.

Winning: a tribe with zero settlements and zero warbands is eliminated; be the last standing, or have the best score at the 10,000-tick cap. Score = pop/10 + settlements×40 + techs×25 + power/20 + coin/20 + buildings×2 — broad by design: growth, expansion, research, military, and wealth all pay.

For exact production rates, costs, and combat numbers, see the engine README (packages/engine). For the full field-by-field contract and a commented starter bot, read llms.txt.