# Flagstead > Flagstead is a free browser game in the style of the 1993 Settlers: lay roads between flags, run production chains, train knights and take the rival castles. The page exposes a JavaScript API, `window.flagstead.agent`, so AI agents can play through calls instead of clicking on the canvas map, and so different AI models can be compared on the same games. The map is drawn on canvases, so screenshots and clicks are a slow way to play. Use the API from the page's JavaScript context (for example a browser tool that runs JavaScript in the page). Every call is synchronous and returns plain JSON, and one script may make many calls. `flagstead.agent.help()` returns the reference generated from the code, with every building's cost, inputs and outputs. ## How to play as an agent 1. `flagstead.agent.start({ size: 64, rivals: 1, diff: 0, assist: 1 })` starts a game and returns the first observation. The game stays paused for you. 2. Each turn: read `observe()`, act (`spots`, `look`, `map`, `build`, `link`, `attack`, `set` and so on), then call `advance(seconds)`. Game time passes only inside `advance`, and the rivals play while it runs; the page's own clock and speed buttons do nothing in a game started this way. Calls other than `help()` are refused until `start()`. 3. `over` becomes `"won"` or `"lost"` at the end. `score()` returns the result card. Every action returns `{ ok: true, ... }` or `{ ok: false, reason, hint }`. Positions are nodes, `n = y * width + x`; buildings, flags and roads are ids. Starting a game through the API counts as one anonymous `agent` play in the site's daily totals; nothing about you or the agent is stored. ## Agents that cannot run JavaScript Open https://flagstead.centminmod.com/?agent instead. A box labelled "Agent command" appears at the top of the page. Type commands into it and press Enter (or the Run button); the results replace the text under the box, one line per command, starting with `> ` and the command. - A command is the call's name followed by its arguments separated by spaces: `start {"size": 64, "rivals": 1, "diff": 1, "seed": 1, "assist": 0}`, `spots lumberjack 3`, `build lumberjack 3376`, `set 512 {"knights": 2}`, `advance 30`. - Arguments are read as JSON when they parse (numbers, `{objects}`, `[lists]`, `"quoted text"`), otherwise as plain words. An argument starting with `{` or `[` must be valid JSON with double-quoted keys, or the command is refused with `bad-json`. - Join up to 20 commands with `;` to save round trips: `observe; spots hut 2; enemies`. - `help` prints the full reference and rules. ## Assist levels The level is set at `start()` and reported by `observe()` and `score()`. - `0` rules only: no starter goal or `goals()`, `spots()` unranked (nearest your roads first), no attack odds, no advice; the page also hides its goal card, tips, attack odds, At risk marks, the Problems panel's tip lines and the field guide's opening steps. Use `look()` and `map()` to judge sites and targets yourself. This is the level for comparing models. - `1` player parity (default): what a human player sees: the starter goal card, ranked building sites and attack odds. - `2` coached: level 1 plus `advice` in each observation and an opening plan in `help()`. ## API - `start({size, rivals, diff, stock, seed, assist, noAttacks, map, adapt, goal})`: new game (size 64, 96 or 128; rivals 1 to 3; diff 0 easy, 1 normal, 2 hard; stock "lean", "normal" or "rich"; assist 0, 1 or 2; `noAttacks: true` for rivals that never attack; `map: "islands"` for neutral islands across the sea, reached by ship, see Seafaring; `adapt: true` for catch-up, see Goals and catch-up (refused with `bad-arguments` unless `true` or `false`); `goal: "hold"`, `"champions"` or `"gold"` for a way to win besides conquest, refused with `bad-arguments` when it is anything else); returns `observe()`. `observe()` and `score()` report `noAttacks` and `adapt`; `score()` reports `map` and `goal`. - `observe()`: about 1k tokens: time, `peaceLeft`, land, stock, people, knights, built and sites by type, `problems` (id, type, issue), jammed flags, enemies in reach, new messages; `goal` (the next starter goal) from assist 1, `advice` at assist 2. `victory` shows progress toward the game's goal (see Goals and catch-up) at every assist level: `goal`, `have` and `need` (for `hold`, the seconds held in a row of 300, and `share`, the part of all land you hold now). From assist 1, once the ten starter goals are done, `advisor` lists up to 3 tips, the same the page's Advisor card shows a player at that moment (fill border garrisons before the peace ends, archers on coasts rivals can land on, a gold foundry for morale, then the coaching hints); at assist 2 `advice` leaves out the ones `advisor` already gives. `incoming` lists rival parties on their way to your buildings, as the page tells a player when they set out: `by` (the realm's name), the target's `id` and `type`, `knights` and `sea` (a landing party: the knights aboard while its ship sails, then those still marching on or fighting at the target while it waits off the coast; knights walking back aboard are no longer incoming); 3 at most, the largest first. From assist 1, `atRisk` lists your manned military buildings a rival could attack now by its own rule (see Rival levels; on easy, until 10 minutes after the peace, only those held by one knight or none), as the page's At risk marks: `id`, `by`, `send` (knights it can send, by land or one landing), `defenders` and `sea` (the landing is the larger threat); 3 at most, the most exposed first. At assist 0 attack odds are hidden, so `atRisk` is left out. In `knights`, `home` and `ranks` are knights in storehouses, `garrisoned` knights inside military buildings, `field` knights outside them (attacking, defending, walking), `archers` every archer, `archersHome` the stored ones and `aboard` (only while any sail) the knights and archers on your ships. Once you have a dock, a harbour or a ship, `ships` lists each ship's id, `size` (`small` cog or `large` carrack), `home` dock, `state` (building, idle, loading, sailing, landed, unloading), `task` (expedition, shuttle, landing, return), `reason` in plain words and `cargo` (goods, people, knights, archers, the goods by kind in `store` and the people by job in `crew`). - `buildings(type?)`: your buildings with id, node, flag id, state, site progress, issue, level, `paused` and `train` (gatherers' level training, and garrisons' training with gold). `status` is what the building's panel shows: `working`, `idle`, `resting` (60 of its product stored), `no-worker`, `exhausted`, `paused`, `no-road`, `unmanned` or `operational`, and `site` (or `no-road`) while it is built; it differs from `issue`, which lists only problems. Workers' buildings give `prod` (productivity, 0 to 1), finished mines `left` (the ore still within reach), storehouses `store` (the goods they hold) and sites `need` (the planks and stone still to arrive, those on the way included). These are what the page's resource panels, opened from the stock counts in the top bar, list for each good. Garrisons give `knights` and `archers` now inside, and the settings `want`, `wantArchers`, `prio` and `manual` (set by hand with `set(id, {knights|archers})`, so `autoGarrison` leaves it alone); construction sites give `prio`; docks and harbours give `keep`. The castle and harbours give `archers`, the archers kept there that defend it. The castle also gives what the Knights panel's castle guard note shows: `knights` stored there, `reserve` and `archerReserve` (see `settings()`) and `onWay`, its knights walking back to it or out defending it (see Castle guard). - `spots(type, k)`: legal sites for a building type that a road can reach (up to 50). Empty means no room. From assist 1, mine sites need geologist signs; at assist 0 every legal mine site is listed, so check `look()` for signs. - `look(n, r)`: terrain, grown trees and saplings, boulders, fish, land owners, geologist signs (marked rich where the geologist says so), animals (deer, rabbits, partridges and ducks, all of which hunters take) and buildings within r steps (1 to 8) of node n. Hidden ore is never shown. - `map(cell?)`: the whole island as rows of characters, one per cell of nodes: terrain (`~` water, `s` shore, `.` meadow, `T` forest, `o` boulders, `,` steppe, `^` mountain, `*` snow) and owners (`0` you, `1`-`3` rivals, `-` nobody, `C` a castle). Cell (cx, cy) starts at node (cx * cell, cy * cell). - `build(type, n)`: places a building and connects it by road. If no road can reach it, nothing is built and `reason` is `no-road-route`. `warn` lists missing materials or tools, and `roads` the ids of the roads it laid. - `flag(n)`, `road(flagId, n)`, `link(id)`, `flagsAlong(roadId)`, `demolish(id)`: roads and flags by hand. `build` and `link` join the nearest road network with a storehouse, which need not be the castle's; `link` also returns `roads`, so `flagsAlong` works on roads laid for you. - `geologist(flagId?)`: surveys mountains within 6 steps of a flag; a flag with none that near is refused (`no-mountain`). With no id it picks or places a flag near your mountains. - `enemies()`: manned enemy military buildings with defender ranks, how many of your knights are in reach and their ranks; odds from assist 1, rating the first defenders + 2 knights in reach; on islands maps `landing` names a dock or harbour a landing on it can leave from now. `attack(id, count?)` sends knights. - `set(id, {knights, archers, prio, paused, train, role})`: building settings. `prio: true` stars a garrison (knights come there first) or a construction site ("build this first": all sites share one queue, oldest first, and a starred site gets its planks, stone and builder before the others; the star ends when the site is finished). `settings({reserve, archerReserve, tools, dist, transport, garrisons, autoGarrison})`: realm settings (`reserve` the knights and `archerReserve` the archers the castle keeps, 3 and 2 by default, see the castle guard rule); an unknown name or a value that is not a number refuses the whole call (`bad-settings`) and changes nothing. `autoGarrison: true` applies the rivals' garrison rule to yours every 7 seconds: a garrison with rival land within its radius + 6 wants a full garrison (from 60% of the peace, towers keep 1 archer and fortresses 2), any other wants one knight, so knights leave the interior for the front. Turning it on hands every garrison to it; a garrison you later give `knights` or `archers` with `set()` keeps your setting. While it is on, `garrisons: "min"|"max"` is refused (`bad-settings`), as the page greys out those buttons. It is off by default, when each new military building wants a full garrison. - `ship(dockId, size?)`, `coasts(dockId, k?)`, `expedition(dockId, n)`, `landing(dockId, targetId, count?)`, `keep(dockId, {good: n})`: seafaring, see below. - `advance(seconds)`: run time forward in 0.05-second ticks (the nearest whole number of them), at most 600 seconds per call; returns `observe()`. In a browser, a long advance on a large map can freeze the page for a few seconds. - `goals()`: the ten starter goals a new player is shown, and which are done (refused at assist 0). `score()`: the result card, including the `gen` (map generator) and `rules` versions, how the game was played (`via`: page, console or mcp), this game's start number and how many games were started, `adapt` with `eased` (per rival in seat order, 60 for each once-a-minute catch-up check that found it eased: whole minutes, not exact seconds), and `goal` with `goalAt` (the second it was reached, else null), and `timeline`, your turning points so far as the page's game-over card lists them, oldest first: each has `t` (seconds) and `event` (`peace` the peace ended, `peak` your largest land with `land`, `attacked` the first attack and `lost` the first building lost, each with the building `type` and `by`, `castleAttacked`, `castleFell`, `fell` a rival's castle fell, each with `by`, and `goal` with the `goal` reached); `by` is a realm's name (null for nobody). `help()`: the full reference. ## Goals and catch-up Two start options, both off by default. - `goal`: a way to win besides conquest. Reaching it ends the game as a win at once (`over` becomes `"won"`); taking every rival castle still wins too, and rivals ignore goals. `"hold"`: own half of all land (every node that is not water) for 5 minutes in a row. `"champions"`: have 5 Champions (rank 4 knights) at once, in garrisons, storehouses, ships or the field. `"gold"`: make 50 gold bars in your foundries (the starting gold does not count). `observe().victory` shows the progress at every assist level, as the page's goal chip does. - `adapt` (catch-up): once a minute, from the land statistics, while your land is under 0.6 times the leading rival's, that rival thinks 1.5 times slower and checks for attacks half as often; it recovers once your land is back above 0.7 times its own. `score().eased` adds 60 per check that found a rival eased, so it counts whole minutes rather than exact seconds. No randomness is involved, so games still replay. ## Seafaring On an islands map (`start({map: "islands"})`) your castle shares the main island with the rivals, and neutral islands lie across the sea, at least one of them with iron or gold ore. Ships reach them; there are no ferries in the road network. - `build("dock", n)`: a dock is a storehouse on the coast of the open sea (not a lake), with its flag on land. `spots("dock")` lists sites. It claims no land. - `ship(dockId, size?)`: builds a ship at your finished dock or harbour from a builder (or a serf and a hammer) of that dock's own store. `size` is `"small"` (default), a cog from 10 planks, ready after 120 seconds, or `"large"`, a carrack from 16 planks and 2 steel, ready after 240 seconds. `observe().ships` names each ship's `size`. Goods reach a dock like any storehouse: produced nearby, or sent there with `set(castleId, {role: "nostore"})`; `set(dockId, {role: "collect"})` gathers spare knights there. - `coasts(dockId, k?)`: harbour sites an expedition from that dock can reach, on other islands of the same sea, nearest by sea first (12 by default, at most 50), each with `n`, `x`, `y` and an `island` id. - `expedition(dockId, n)`: an idle ship at that dock loads a builder, a knight, 6 planks and 4 stone from its store and sails to site `n`. Refused with `no-kit` and `missing` when the store lacks part of the kit; a harbour keeps its last knight as its guard, so an expedition from a harbour needs 2 knights there. - `landing(dockId, targetId, count?)`: an idle ship at that dock or harbour takes up to `count` (1 to 8; by default all it holds, 4 on a cog and 8 on a carrack, the largest idle ship going first) of its knights, highest rank first, to a beach near enemy military building `targetId` on another island of its sea, and they attack it. Refused with `no-knights` when the port has none above its guard or the castle reserve, and `no-landing` when no beach lies within 10 steps of the target on that sea or the target is on the port's own island. - `keep(dockId, {good: n})`: keep n (0 to 99; 0 clears) of a good at a dock or harbour, or of crew: `knight`, `archer`, `serf`, `builder` or another job (not `carrier`). Any bad entry refuses the whole call and changes nothing; `keep(dockId)` reads the settings back. A harbour you found starts with `knight: 3`, so ships bring it 2 knights beyond its guard; normal and hard rivals land 4 to 8 knights, so keep at least 3 there. `keep(harbourId, {knight: 0})` clears it. Refusals: `no-dock` (not your dock or harbour; `ship`, `coasts`, `expedition` and `landing` also need it finished), `no-planks`, `no-steel`, `bad-size`, `no-builder`, `no-ship` (no idle ship at that dock), `bad-target`, `no-kit`, `no-knights`, `no-landing`, `bad-good`, `bad-amount`; each comes with a `hint`. Issues in `problems`: `no-road`, `no-worker` (needs a serf and a tool), `resting` (60 of its product stored), `exhausted` (mine is empty), `unmanned` (no knight yet), `under-attack`, `paused`. ## Rules - You are player 0 (blue). You win when every rival castle is taken, or when you reach the game's goal if it has one (see Goals and catch-up), and lose when your castle falls. - A building's flag is the node below-right of it. Sites are small, medium, large or mine (mountain); a building needs a site at least its size. - Every building needs a road from its flag to a storehouse. Goods and workers travel the roads; one carrier works each road segment and a flag holds 8 goods. Flags need a free node between them. Removing a road sends its carriers home and the goods they carry are lost. - Construction uses the planks and stone in its cost, carried to the site by road. Planks come from logs at a sawmill, logs from woodcutters felling grown trees; foresters plant trees; stonecutters split boulders. - A worker is a serf plus the tool for the job. The toolmaker turns planks and steel into missing tools; with no hammer in reach, a stored builder becomes the toolmaker. Serfs grow in storehouses up to 300, plus 60 for each storehouse beyond the castle. - Fishermen catch fish in the first two rows of water off the shore, where fish breed back; hunters take deer, rabbits, partridges and ducks (shot from the shore). - Mines dig what lies within 2 steps on mountains and eat one food (fish, meat or bread) per load. Ore is hidden until a geologist leaves signs. - Food chains: a fisherman or hunter brings one food a trip. A farm's wheat feeds two loads: the mill makes 1 flour from each wheat and the bakery 2 bread from each flour; the pig farm raises 1 pig on each wheat and the butcher cuts 2 meat from each pig. - Steel comes from a smelter (coal and iron ore), gold bars from a foundry (coal and gold ore). A weaponsmith (coal and steel) makes swords and shields; a serf with both becomes a squire. - A building rests while 60 of its product is stored in the storehouses its roads reach, and restarts by itself as stock falls. - Guard huts (radius 6, 2 places), watchtowers (8, 5) and fortresses (11, 9) extend your borders once a knight mans them. Land an enemy takes destroys your buildings, flags and roads on it. - Knights have ranks 0 Squire to 4 Champion and health 10 + 4 x rank. In a duel a blow comes every 0.75 seconds from a random side and lands with chance 0.55 + 0.08 x (rank difference) + 0.15 x (morale difference), for 2 to 5 + 0.6 x rank damage. - Morale (0 to 1) is the gold your realm holds, full at half a bar per knight or archer (stored ones included). Gold delivered to a garrison trains one knight a rank every 40 seconds. Knights heal in garrisons. - Each manned garrison asks for gold (2 for a guard hut, 4 for a watchtower, 6 for a fortress); starred garrisons (`set(id, {prio: true})`) get theirs before the others. `set(id, {train: false})` on a garrison stops it asking for gold and training; gold already there waits until training resumes. - You may attack any manned enemy military building within 16 steps of your garrisons. Each military building sends all but one knight, the castle all but its guard (`settings({reserve})`) and a harbour all but its guard; knights in other storehouses do not attack. On islands maps only knights on the target's own island count; across the sea, send them with `landing()`. Defenders come out one at a time; a building is captured only when no defender is left inside, duelling, or walking back in from a duel it won. - Seafaring: a dock (medium, 6 planks and 4 stone) stands on the open sea's coast and claims no land. A ship costs 10 planks and a builder from that dock's store and takes 120 seconds to build. It holds 8 goods or 4 people, sails 1.5 nodes a second and takes 3 seconds to load or unload. - An expedition carries a builder, a knight, 6 planks and 4 stone to a free coast site on another island of the same sea. The builder builds a harbour from the landed goods (no road needed); when it is done the knight moves in and the harbour claims land within radius 6. A site taken before the ship arrives sends it home with the kit. An expedition never takes a harbour's last knight, its guard: from a harbour it needs 2 knights there, or it is refused with `no-kit`. - Larger hulls: a carrack (`ship(dockId, "large")`) costs 16 planks, 2 steel and a builder and takes 240 seconds to build. It holds 16 goods or 8 people (a cog 8 or 4), sails at 1.125 nodes a second (a cog 1.5) and takes 5 seconds to load or unload (a cog 3). Rivals build one carrack once their harbour stands and their castle has steel to spare. - Idle ships shuttle goods between your docks and harbours on one sea: up to 8 of one good per trip (16 on a carrack), from the port with the largest surplus over its keep to the port furthest below its keep, unloaded into its store. - Troop transport: crew kept with `keep(dockId, {knight: n})` travel the same way, up to 4 a trip (8 on a carrack): knights (highest rank first), archers and stored people by job. A port never gives up knights below its own keep, a harbour its guard or the castle its reserve. When no port has them to spare, they walk to the ship's port from a storehouse on its roads (never another port) and the ship waits for them. Knights a harbour holds beyond its guard man the military buildings on its island. - Hostile landings: `landing(dockId, targetId, count)` sends up to 4 knights (8 on a carrack) from that dock or harbour (highest rank first, never its guard or the castle reserve) on an idle ship to a beach within 10 steps of an enemy military building on another island of its sea. They go ashore, attack by the usual duel rules and hold what they capture (the extras walk back aboard); if the target is lost, gone or out of reach, the survivors walk back aboard. The ship waits offshore until none is ashore, then brings them home. Rivals at normal and hard difficulty land too, never with `noAttacks` (see Rival levels). - Docks and harbours fall like storehouses: land an enemy takes destroys a dock, and a harbour (defended by its knights) is destroyed when captured. A ship lying at a lost port is lost with its cargo; a ship at sea makes another port on its sea its home, or is lost when none is left. - Archers (serf + bow) share garrison places and shoot every 2 seconds at enemy knights within 5, 7 or 9 steps, or wound (never kill) defenders of enemy garrisons in range. Rivals neither attack nor shoot before `peaceLeft` reaches 0. In a game started with `noAttacks` they never attack, and their archers shoot only at knights attacking them or crossing their land; you may still conquer them. - Archers kept in the castle or a harbour (stored ones: sent home when a garrison wants fewer archers, or shipped with `keep`) defend it only. Every 2 seconds up to 3 of them shoot at enemy knights within 8 (castle) or 7 (harbour) steps that attack or cross your land, landing parties included. Unlike garrison archers they never wound the defenders of enemy garrisons. Rivals' castles and harbours shoot the same way. - Castle guard: the castle keeps a reserve of knights (`settings({reserve})`, 3 by default) and of archers (`settings({archerReserve})`, 2 by default) and sends out only those above it. While it holds fewer knights than its reserve, counting those on their way (its own attackers walking back included) and its own defenders out in a duel or walking back from one, knights in your other storehouses on its roads (not one set to Collect, and above a dock's knight keep) walk there before any garrison gets one, so new recruits refill it first, and every 10 seconds garrisons holding more than one knight send one back each, interior before front, nearest first, starred ones last, until the reserve is met. Its archers are recruited in the castle from bows in its store, always leaving one bow there for a new hunter; the toolmaker makes the bows it lacks once workers have their tools. Rivals' castles refill the same way. - Defence: when a building is attacked, garrisons within 10 steps each send one knight if they hold 2 or more, and storehouses within 10 steps (the castle and harbours too) send every knight above their floor (the castle its reserve, a harbour its guard of 1, other storehouses none), highest rank first, up to the room left. At most 3 buildings send, or 5 when the castle or a harbour is attacked. Rivals are defended the same way. A harbour's knight keep (3 by default for one you found) is what idle ships' shuttles and the castle refill leave there; a landing from it, its help to a building under attack and the knights it gives to man its island's garrisons may still take it down to its guard of 1. - Rival levels (`diff`): the peace lasts 45 minutes on easy, 25 on normal and 12 on hard. Rivals think every 4.5, 2.6 or 1.4 seconds and start with 0.8, 1 or 1.35 times your normal stock. A rival attacks the enemy building where its knights in reach, less the defenders times 3 (easy), 1.6 (normal) or 1.4 (hard), come out highest, when that is above 4, 1.5 or 0.9; it sends at most the defenders plus 2 (easy) or twice the defenders plus 3. Easy rivals look for a target about every 2 minutes (normal every 16 seconds, hard every 8), and in their first 10 minutes after the peace attack only buildings held by one knight. Only normal and hard rivals land by sea. Easy rivals know only ore within 2 steps of their own land, as you do through geologists and mines; normal and hard rivals know every deposit. ## Benchmark protocol To compare models fairly, run each model on the same settings and seeds, for example `start({ size: 64, rivals: 1, diff: 1, seed, assist: 0 })` for seeds 1 to 5, with the same limit on game time and calls, and record `score()` at the end of each game. - Play each game once: one `start()` per game. `score()` reports `start` and `starts`, so restarts show. - The same seed and the same calls replay the same game, rivals included, on the same JavaScript engine. - Agents that can only type into the `?agent` console cannot reach hidden state, so it is the fair browser route. - Use only `flagstead.agent`. Reading `flagstead.S`, importing the game's modules or reading its source reveals hidden ore and rival plans, so a run that does any of these does not count. - `score()` counts every call except `help()` and `score()`, and every refused call. - Compare benchmark results only within the same `gen` and `rules` (both in `score()`): a new map generator or new rules make older results incomparable. - Compare results only between games with the same `adapt` and `goal` (both in `score()`): catch-up changes how hard the rivals play, so results with `adapt` are not comparable with those without, and a goal ends games early. - Through the MCP server, an `advance` whose tool call timed out in the client was still applied; call `observe()` before retrying. ## Optional - [Play Flagstead](https://flagstead.centminmod.com/): the game itself - [Trailer](https://flagstead.centminmod.com/demo/): 30 seconds of real gameplay