Skip to main content
Glama
ty-meador

civ-v-llm-harness

by ty-meador

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault

No arguments

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
how_to_playA

How to play through these tools, from the playbook shipped with this server; needs no game and works at any time. With no topic: the index of topics and the introduction (what you are, what you see, gate, seats, loading a game). Playbook topics: start, turn_loop (every turn in order; two agents or two clients on one game), quiet_turns (skip_quiet_turns and what wakes a run), batches (do and action_id), verify, blockers (the end-turn blocker table and what clears each), diplomacy (leader screens, discussions, the trade table), rules (what the harness refuses on purpose), first_turn; "all" is the whole playbook. A tool name -- finish_turn, briefing, turn_status, overview, compare, propose_deal, give_order -- is that reply's full key-by-key reference, the part its own description leaves out. Read a topic once, when you first need it; the answer is Markdown.

referenceA

The rule book, as Markdown: what every unit, building, wonder, project, process, promotion, social policy and ideology tenet, technology, belief, resource, terrain, feature, improvement, specialist and unit action does, read once from this game's own database (mods and DLC included) and cached. No other answer repeats this text (since runtime v216): chooser rows carry the enum, the name and live numbers, and a resource tile carries its resource name. Sections, one per call with section: terrain, resources, improvements, units, buildings, projects, processes, promotions, policies, techs, beliefs, specialists, actions. The whole book is long (tens of thousands of tokens): read it once at the start of a game if you can hold it, otherwise the section a choice needs. Also served as the MCP resources civ5://reference and civ5://reference/{section}. Usable while it is not my turn.

turn_statusA

Whose turn it is, current turn number, whether it is my turn, what blocks ending it, and whether a greeting / discussion / tech / great-person screen is up (those are not in pending_popups). gate is the one thing to read first: null means act freely; otherwise it names what must happen before any action works and clear_with the tool that does it (every refusal carries the same object). seat is the player this server plays. todo lists the decisions the turn still needs: units (need orders), cities (empty production), promotions, steal_tech (a pending spy chooser, even when blocking_name says something else: the engine reports one blocker at a time), and todo.ongoing -- units the game is already moving (automated or on a multi-turn move; attention names a camp, hostile or lost destination beside one), which never block the turn. blocking_name / blocking_hint say what stops end_turn and which tool clears it. alerts are facts about my own empire that block nothing: low happiness or an unhappy tier, a strategic resource in deficit; happiness rides on every status. expiring_deals (within 3 turns) and expiring_friendships (within 5) list what is about to lapse. While a leader screen is up (leader_greeting_pending / discussion_pending) the engine freezes blocking_name and todo: discussion() reads it, dismiss_discussion() closes a plain greeting. From the main menu it reports {"ingame": false, "screen": ...}: load_latest / load_save get back into a game. Every key in detail: how_to_play("turn_status").

briefingA

My turn in one compact read, for deciding and for recovering after a context reset: what I must do, what changed, and what the board looks like. decisions is every mandatory item, never cut -- units needing orders, promotions, cities with nothing to build, research unset, an incoming deal, a stolen tech, decision popups, or the blocker -- each with the tool that clears it. warnings are facts that do not block (alerts, expiring deals / friendships / allies); opportunities idle caravans and spies, free route slots. changes since the baseline (my previous briefing of this game and seat, kept beside my notebook): empire totals {was, now}, cities and units new / gone, events from the game's log (its own cursor: turn_digest keeps its own). empire; cities (only those worth a look, with why); units (totals, ongoing, attention, damaged); threats (visible hostiles within 4 plots of a city or 2 of a unit, nearest first; distance only, no odds; ones already briefed are marked seen); camps; civ_rules (my leader's trait text, on a first briefing or since="turn"); notes (new since my last briefing or finish_turn; notes="all" the latest limit); assignments and orders when I have any. While a gate is up only gate comes back (withheld). Every list but decisions stops at limit (default 8, max 50) with omitted and more naming the tool that shows the rest. since="turn" lists every event after my previous turn ended: use it after a context reset. detail="full" gives every field of every row. Five game reads; nothing another seat can see is read. Every key in detail: how_to_play("briefing").

set_seatA

Change which player this server plays, or re-detect it (player_id omitted). Needed when every tool answers "this seat is not active" although the game is waiting for a human: the server was started with --seat auto before the game was up, or a hotseat save was loaded and auto's default (seat 1) is not the seat on screen. Only a seat the engine considers human can be chosen; the answer lists human_seats. With no player_id: solo and network games re-run detection; hotseat takes the seat on screen when it is human. The notebook follows the seat (one notebook per game and seat). Usable while it is not my turn.

wait_for_my_turnA

Block until it is my turn (hotseat: dismisses the hand-off screen; LAN/solo: waits for the AIs to finish), then return turn_status. On timeout it returns the current status with my_turn=false -- call it again. A progress notification goes out every few seconds while waiting, so with a client that honours progress timeout_seconds can be as long as an AI round needs (600-1800); otherwise keep it under the client's tool-call limit. Also sweeps informational popups. finish_turn does end_turn + this + turn_digest in one call.

Returns early with discussion_pending=true when an AI leader wants an answer mid-turn: discussion() shows what they said and the buttons, respond_discussion(button_id) answers; for a trade offer on the table incoming_deal() reads the terms and accept_deal()/refuse_deal() resolve it; dismiss_discussion() leaves without agreeing. Then call this again. Returns early with tech_popup_pending=true when a technology must be chosen (research still unset). Every answer carries gate (as turn_status): null when you may act, else what still stands in the way and the tool that clears it. A timeout answer carries seat (the player this server waits for) and active_player; in hotseat a different active_player is the other player's turn -- call again.

playersA

HUMAN seats only (network/hotseat games): whether each is connected, has an active turn, and has ended their turn. Like the in-game player list, a seat I have not met shows its name but not its civ. In a solo game this is just me. For the AI civs and city-states I have met -- their ids, scores, war state -- use diplomacy; that is where player_ids for trade/diplomacy tools come from.

overviewB

My empire at a glance: gold, science, culture, happiness, research, era, counts, turn/year. strategic_resources (revealed only) with available spare copies -- negative is a deficit: units and buildings fight and produce at a penalty. luxuries with owned / imported / exported copies (last_copy when selling one would drop the happiness bonus); bonus_resources the resource list's bonus stack. The top-bar tooltips ride along: happiness_breakdown (with the Happiness screen's rows: by_luxury, cities, unhappiness tooltips, the unhappy tier, penalties), gold_breakdown (income vs expenses, unit maintenance), science_breakdown, culture_breakdown, tourism_breakdown, faith_breakdown; unit_supply (Military Overview cap and deficit), score_breakdown, golden_age_progress / golden_age_threshold. idle_trade_units lists caravans and cargo ships without a route (with in_city and the nearest city to walk to: only one standing in my city can be given a route) and idle_spies unassigned spies. Every key in detail: how_to_play("overview").

notification_logA

The Notification Log: every notification the game still holds for me, newest first, including ones already dismissed -- which is what the screen is for. turn_digest carries only what the panel is currently showing, so something read once and dismissed is otherwise gone. Each row has the turn it arrived on. limit is the newest N (default 40); include_dismissed=false keeps only the ones still showing.

turn_digestA

Everything recorded since my last call: combats, cities founded/lost, wars, chat, notifications, alerts. Notes: a caravan / cargo ship shows up as unit_destroyed the turn its trade route starts -- the route IS the unit now (it comes back as a new unit when the route ends); unit_graphics_reset means the engine only rebuilt a model (era change, upgrade), the unit is fine. unit_captured is a civilian taken, not killed: the row carries the unit, its tile, the captor when in sight and (barbarians) the nearest revealed camp. Leader lines you provoked yourself via negotiate_deal/propose_deal are not included; unsolicited AI approaches are.

quick_saveA

Save the game right now (same as the in-game Quick Save / F5). Cheap -- call it after anything costly (founding a city, a policy/research choice, before combat), not just periodically, since a crash loses everything back to the engine's last autosave otherwise.

end_turnA

End my turn. If something blocks it (unit needs orders, research/production choice), turn_status shows it. Auto-quicksaves first by default (single-player only) -- cheap insurance against this game's frequent ambient crashes; pass autosave=False to skip. Refused with turn_claim when another client of this seat gave this turn's first order and is still at it (its pid and timings are in the answer): that client owns the turn until 180 s pass without an order from it or its process exits; force=true takes it over.

finish_turnA

The turn boundary as one call: end my turn, wait until it is my turn again, and return the new turn -- status (as turn_status), digest (as turn_digest: what happened while I was away), turn and notes (notebook entries since my last finish_turn or briefing; notes="all" brings the latest eight). briefing=true returns briefing (see the briefing tool) in place of status and digest. If the turn will not end, ok=false and end_turn carries the refusal with the todo that blocks it: nothing is waited on. Safe to repeat: when it is already not my turn it only waits, never ends a second turn. Returns early with discussion_pending=true (an AI wants an answer: discussion() then respond_discussion / accept_deal / refuse_deal / dismiss_discussion, then call again) or tech_popup_pending=true (set_research). timed_out=true means the AIs are still moving after timeout_seconds: call again (the default 600 is safe in Claude Code, which moves a long call to a background task; under a client with a hard per-call limit stay below it). Progress notifications go out every few seconds. skip_quiet_turns=N keeps ending turns, up to N more, while nothing needs me (no unit awaiting orders, empty city, promotion, popup, blocker, expiring ally, worsening alert, paused order or eventful digest); wake_on adds my own words (event kinds or notification text, e.g. ["Machinery"]). The skipped turns' digests are merged and turns_skipped / woke_because say what happened; the harness never issues an order for me. One client owns the turn: another client of this seat gets ok=false with turn_claim instead of ending a turn under it; force=true takes it over. autosave=false skips the quick-save before ending. Every key of the reply, what wakes a quiet run, and the claim rules: how_to_play("finish_turn").

doA

Carry out a list of orders in one call, in order: [{"tool": "unit_mission", "args": {"unit_id": 7, "mission": "MISSION_FORTIFY"}}, {"tool": "set_production", "args": {...}}, ...]. Each order is the named tool with its own arguments and comes back with its own result under results (index, tool, result). The first refusal (ok=false) stops the batch by default: the orders after it are listed under skipped, since the state they were reasoned about is no longer certain; stop_on_refusal=false runs them all. Not allowed inside: wait_for_my_turn, finish_turn, end_turn, load_*, lua, do. At most 40 orders. An order may carry "action_id": a retried batch after a transport timeout then replays the results of orders already carried out instead of repeating them (see the server instructions on action_id). force=true takes the turn over from another client of this seat that still holds it (see end_turn).

rememberA

Write a note to my notebook for this game: the plan, a promise, a threat, why I did something ("Tradition then Rationalism", "Askia denounced me t140: expect a DoW", "keep 2 archers in Moson Kahni"). Notes survive session restarts and context loss: they live beside the game (one notebook per game and seat, keyed by leader/civ/map/capital), and the latest ones ride along in every finish_turn result. tag groups notes (plan, threat, diplomacy, todo...). replace_id rewrites an existing note in place, so a living plan stays one note instead of a trail of superseded ones; the result carries previous (the text, tag and turn it overwrote). A replace whose tag differs from the stored tag is refused with stored_tag and writes nothing (the id was probably wrong); an empty tag keeps the stored tag, and retag=true allows the change. Usable while it is not my turn.

recallA

Read my notebook for this game (see remember): every note with its id, the turn it was written on and its tag; tag filters, limit is the newest N (default 50). The last few also arrive with each finish_turn result. Usable while it is not my turn.

forgetB

Delete one note from my notebook by id (recall lists them).

assignA

Give units or cities a structured assignment in my notebook: what they are for, where, when it is done and when to look again. A prose note (remember) says why; an assignment lets a later me -- after a context reset, in a new session -- see at once what each unit is doing and whether that still holds. role: a short word (escort, settle, improve, defend, explore, diplomacy...). purpose: one sentence. unit_ids / city_ids: mine, now; each is fingerprinted (type and creation turn; name and founding turn), so if an id later names a different unit the assignment says the assigned one is gone instead of following it. target: {x, y} a plot (a city site, a tile to improve, a city to take or hold), {unit_id, owner} a foreign unit, or {player} a civ or city-state. done_when (checked on every read; default "manual"): {kind: "unit_at"|"city_at"|"improvement", x, y} (x, y default to the target plot; unit_at takes unit_id, improvement takes improvement e.g. "FARM"), {kind: "building", city_id, building}, {kind: "tech", tech}. review (optional): {turn: N, hostile_within: plots, hp_below: percent} -- look again at turn N, when a visible hostile comes that close to an assigned unit or city, when an assigned unit's hp drops below. replace_id: this replaces that assignment, which is closed as replaced (the two never compete). The answer is the stored assignment reconciled right away (see assignments). One game read.

assignmentsA

My assignments (see assign), each reconciled against what I can see now, in one game read. An active row: id, role, purpose, since_turn, state -- condition_met (its done_when holds: evidence says how; close_assignment it), needs_review (reasons lists each observation: an assigned unit missing or gone -- an upgrade on its last plot is named --, a city no longer mine, the target plot's owner changed or a city now too close to a site, a target unit not where last seen, a war or elimination, the review turn, a hostile within range, low hp) or on_track --, units / cities as they are now, target as observed (a fogged plot or an out-of-sight unit is known: stale / unknown with when it was last seen; never assumed gone or still there), done_when and review. Nothing is closed, re-targeted or ordered for me. status: "active" (default), "closed" (completed, cancelled, replaced), or "all". briefing() carries the active ones compactly, needing-a-look first.

amend_assignmentA

Change an active assignment in place: only the fields given change (role, purpose, done_when and review as in assign; unit_ids / city_ids replace the list; target={} clears the target; review={} clears the triggers). Use it when a unit was upgraded (new id), a site moved, or the review turn passed and the plan still holds. note is kept in the assignment's history. The answer is the amended assignment reconciled now, with previous values. One game read.

close_assignmentA

Close an active assignment: outcome "completed" or "cancelled", with an optional note (why). Closed ones leave the briefing and stay readable with assignments(status="closed"). Usable while it is not my turn.

give_orderA

Give one of my units a short sequence of steps the harness carries out over the coming turns, so a plan already chosen does not cost a call every turn. steps (at most 6, in order): {kind: "move", x, y} walk there (multi-turn); {kind: "build", build: "FARM"} build it where the previous move ends (x, y name another plot); {kind: "heal", hp: 80} heal to at least that percent (default 100); {kind: "hold", mission: "fortify"|"sleep"|"alert"} as the last step. Example: move to (12,8) then build FARM; or heal to 80, move to (30,14), hold. purpose is a free-text label for the order. It runs now (start=true) as far as it can, then at the start of each of my turns (finish_turn / wait_for_my_turn carry orders), one step per turn at most, through move_unit / unit_mission. It pauses and hands the unit back with pause.reason and hint when a hostile comes into sight within interrupt.hostile_within plots (default 2; 0 off), the unit was damaged (interrupt.damaged, default true) or is below interrupt.hp_below, an enemy stands on the destination (an order never attacks), a step is refused or makes no progress, a save was loaded, or I give the unit a direct order. An order never declares war, attacks, ends the turn or touches another unit; a unit on automation leaves it as soon as the order is stored. One open order per unit (replace_id replaces it); a first step that cannot run now refuses the order. Stored in my notebook: orders survive a restart, briefing() lists them, resume_order / cancel_order finish a paused one. Every interrupt and state: how_to_play("give_order").

ordersA

My conditional orders (see give_order) as stored, without reading the game: id, unit, status (active / paused; completed, cancelled, replaced, failed once closed), step N of M and now (the current step), steps, state (moving, building, healing, no_moves...), pause (kind, reason, hint, turn) when it waits for me, last (the last step issued: turn, what, ok, err / note), issued_count (calls it made for me), purpose. status: "open" (default), "closed" or "all". Usable while it is not my turn.

resume_orderA

Hand a paused order its unit back and run it now (an active one just runs now). What paused it -- the hostiles in sight, the hp now -- is taken as seen, so only something new pauses it again. Every step is re-checked against the board first: a step completed meanwhile is not issued again. To change the plan instead, give_order with replace_id.

cancel_orderB

Close an open order as cancelled (note: why). The standing move it had issued is dropped, so the unit stops where it is; a build or fortify already under way is left alone. Usable while it is not my turn.

unit_home_optionsA

Where a trade unit or a Great Admiral could re-home (the Change Home City / Change Port chooser). Both need the unit to be standing in one of my cities; outside one there is no button, and the answer says so. cities is the engine's own candidate list -- apply one with unit_mission(unit_id, mission, x, y) using the mission in the reply. Re-homing a caravan nearer a richer partner is how a 6-gold route becomes a 12-gold one; see available_trade_routes after.

unitsB

My units with position, moves left, hp, strength, current promotions, XP toward the next promotion (xp / xp_needed), and whether they still need orders. garrisoned is the Military Overview status. upgrade_to / upgrade_gold / can_upgrade are the unit-panel upgrade preview when a path exists; upgrade_blocked (when can_upgrade is false) is the panel's red lines: reason territory / city / gold / resources (each short one) / stacking, unavailable (the target cannot be trained yet: prereq_tech) or moved. A religious unit carries religion (the faith it spreads, which is the one of the city it was bought in -- not necessarily yours) and spreads_left, as the unit panel names it. A Worker mid-job carries build (BUILD_*) and build_turns_left as the unit panel's "Trading Post (6)" line; mission_name names a standing MISSION_* (e.g. ROUTE_TO). territory {player_id, owner, city_state} is whose land the unit stands on when it is not mine (a unit in a city-state's land costs influence each turn); absent on my own or unowned land.

maya_optionsB

Pending Maya Long Count rewards, including unavailable types and the baktun when chosen.

choose_maya_bonusC

Choose an available UNIT_* from maya_options (unit="UNIT_PROPHET", ...) and verify the reward was consumed.

archaeology_optionsC

Completed dig: artifact origins/era, available art/writing slots, artifact vs landmark or writing vs culture choices. Unmet artifact origins are masked.

choose_archaeologyC

Confirm a choice ID at the completed dig's x,y from archaeology_options. Verifies resolution.

unit_mission_targetsA

Legal visible targets for an air strike/sweep, nuke, paradrop, rebase or airlift mission listed in available_unit_actions. Paginated: offset / limit (at most 100 per page; total says how many exist); use unit_mission to issue the order. Air strikes include target details and a combat preview with retaliation, strength and visible interceptors. Expected damage taken excludes interception; unseen interceptors may still exist. Fogged destinations are excluded because legality could expose hidden occupants.

map_windowA

Revealed plots within radius of (x, y). vis=true is in sight now and includes yields (food/production/gold/science/culture/faith), fresh_water, worked, under_construction, trade_route (the plot hover's "Trade Route": a city connection to the capital, not a caravan line; those are trade_routes().path), and live units/cities (units have strength/promotions; a city banner has strength, garrison, puppet/razing, religion). A resource tile carries resource (and resource_qty); what a resource gives when improved, its happiness and its blurb are in reference("resources"), once, not on every tile. A revealed Oil/Aluminum/Coal tile that we cannot yet hook has resource_requires_tech. A barbarian camp with a city-state kill-camp quest has cs_quest. vis=false is discovered but fogged (no live units/owners/features/yields). Prefer known_world for the full discovered map.

explore_frontierA

Where the known map ends for this unit: revealed, passable plots of its domain (sea for a ship, land otherwise) that border unrevealed plots, nearest first. Each has unrevealed_neighbors (how much stepping there reveals), distance (hex distance, not path length), reachable (true when a route exists through the already-revealed map; false = behind land or an unknown strait, listed last), terrain t (a Trireme cannot enter OCEAN), and map_edge=true on the polar rows (mostly ice beyond). move_unit refuses unrevealed targets, so an explorer picks its next stop from here. frontier_total / unrevealed_plots say how much is left; note explains an empty list. limit is how many plots to list (default 12).

tactical_viewA

One unit's surroundings in one read, for choosing its move or attack. neighbors are the six adjacent plots by coordinate and direction (NE, E, SE, SW, W, NW; the engine's own adjacency, so map wrap and the edge rows need no hex arithmetic), each with terrain, river_crossing, owner, visible units and move: attack (a melee attack; its preview is in targets), open (move_unit would send the order), refused (move_unit would refuse it, why says why) or enemy (a visible enemy this unit cannot melee). open is not a path cost: turns-to-reach and movement cost are not available. targets are the unit's melee and ranged targets with the combat previews available_unit_actions gives. occupants (visible units, hostile first) and cities (a fogged one is last_seen) cover radius (1-5; by default as far as this unit itself sees or shoots, at least 2); fog counts visible, fogged and unrevealed plots there, and unseen_within_2 is how many plots within two cannot be seen: fog can hide units, so nothing is called safe. unit.sight is this unit's own line of sight from the engine (range, on_hills, plots, reach: high ground adds a plot, hills and forest in between block); a ranged unit's unit.fire_los is the same test with its attack range, the one a ranged attack must pass (a Crossbowman on a hill reaches 3); occupant and city rows say in_sight / in_fire_los. grid is a lettered picture of the same area with its legend; players names every owner id in the reply. detail="full" adds plots (every revealed plot in radius, as map_window reads it) and the previews' modifier rows.

known_worldA

Everything this seat knows: empire, own units/cities, met civs and city-states, notifications, and every revealed plot. Fogged plots have vis=false and omit live occupants; unrevealed tiles are absent.

map_indexA

Compact map scan: revealed luxuries/strategics, barb camps, ruins, met foreign cities, visible natural wonders, and in-sight world wonders. A camp with a city-state kill-camp quest carries cs_quest (met CS only). Prefer this over known_world unless you need every plot.

revealed_mapA

The whole revealed map at a glance, as character grids: one string per row (north first), one character per plot, one grid per layer. Layers: vis ('#' in sight now, '~' revealed but fogged: what you see there is what was last seen and may be stale until a unit gets eyes back on it, ' ' unrevealed), terrain, elevation (hills/mountain), river, owner (borders), feature, improvement, resource, route. Each reply carries its own legend (letters are assigned per reply). Fog rules are the human's: a fogged plot shows remembered feature/improvement/route/owner, never live units or pillage. Pass layers to fetch a subset and x0/y0/x1/y1 to window a large map (a Huge map after Satellites is about 10 KB per layer). map_window(x, y, r) reads one area in full; map_index lists cities, camps and resources with coordinates.

generic_popupA

Read the open yes/no confirmation (the game's generic popup): its text and numbered buttons. These are BUTTONPOPUP_RETURN_CIVILIAN (keep a captured civilian or return it: returning to a city-state gives +30 influence, to an AI a diplomatic bonus), ANNEX_CITY / PUPPET_CITY after a conquest, BARBARIAN_RANSOM, MINOR_CIV_ENTER_TERRITORY, CONFIRM_COMMAND and the like. Nothing else moves while one is open ("popup needs a decision"). Answer with answer_popup(button).

answer_popupA

Press one button (1-based id from generic_popup) of the open generic confirmation. Runs the button's real handler (e.g. Network.SendReturnCivilian) and closes the window. Returns discussion_pending because some answers make an AI leader speak next (dismiss_discussion).

goody_hut_optionsA

When turn_status.pending_popups shows BUTTONPOPUP_CHOOSE_GOODY_HUT_REWARD (a Shoshone Pathfinder entered ancient ruins): the rewards on offer, each with the popup's own description.

choose_goody_hutB

Take one ruins reward from goody_hut_options, e.g. goody="GOODY_CULTURE".

available_unit_actionsA

Legal unit-panel actions for this unit right now (missions, tile builds on ITS plot, commands, promotions). Call this before unit_mission. Move-to is a separate tool (move_unit). Does not select the unit or pan the camera. For Workers/Work Boats also returns nearby_builds: plots within 2 tiles that still need work (unimproved, or pillaged) with the builds legal there -- move_unit onto one, then unit_mission(MISSION_BUILD, build=...). build_info adds the unit-panel turns and yield_delta for each build. A build issued with 0 moves left starts next turn. ranged_targets includes combat strength and expected damage; air previews include retaliation and a warning about interception. Melee previews include fire_support_damage in damage taken and its effect on damage dealt. promotions are the chooser's own rows -- promotion (pass this to choose_promotion) and name; what each does is in reference("promotions"). An action row's help is only the line the panel computes for this unit (upgrade target and price, scrap gold, golden age length, paradrop range); the standing sentence for every action is in reference("actions").

todo_actionsA

Legal actions for many units in one call. With no unit_ids: every unit in turn_status.todo.units (still needs an order) plus every unit with a promotion waiting; with unit_ids: exactly those. Each row is what available_unit_actions returns for that unit (actions, promotions, nearby_builds, attack_targets, ranged_targets, moves, x, y) plus id, type and promotion_ready. Action rows drop the computed help line (upgrade price, scrap gold) unless full=true; the standing text for every action and promotion is in reference("actions") / reference("promotions"). One query instead of one per unit: the read for a whole turn's units in one call. Refused while it is not our turn unless unit_ids is given. detail: "normal" (default, the rows above), "full" (same as full=true) or "summary": per unit only id, type, x, y, moves, promotion_ready, actions as bare type strings minus the everyday ones (move, route, swap, skip, sleep, fortify, alert, wake, cancel, delete, automate/stop, remove route -- listed once in routine_actions, counted per unit in routine), promotions (enums for choose_promotion), attack / ranged targets (x, y, unit or city, owner, hp; no preview) and build_plots (x, y, builds, resource). drill_down gives the exact todo_actions arguments for the normal rows. Same single read at every level; a summary of 38 units is a fraction of the normal size. limit returns the first N units in todo order and lists the rest in omitted (count, ids, the args that fetch them). Every reply has detail, n (total units) and returned.

choose_promotionC

Choose an earned promotion, using its PROMOTION_ name.

upgrade_unitA

Upgrade a unit for gold along its upgrade path (e.g. Warrior -> Swordsman). Needs full moves, own/allied territory, the gold and any strategic resource. The engine replaces the unit: use the returned unit_id (new) from now on, not the one passed in. available_unit_actions lists COMMAND_UPGRADE when possible.

disband_unitA

Disband (delete) one of my units -- the unit panel's Disband button. Irreversible. Frees its gold maintenance and any strategic resource it consumes (e.g. an obsolete Swordsman holding Iron). Returns effects.before/after with unit count and strategic_resources so the freed resource is measured.

move_unitA

Order one of my units to move to plot (x, y) (multi-turn paths allowed, like a right-click). Selects the unit like the unit panel does (orders go through the game's network path). A unit on a conditional order (give_order) is taken back: the order pauses (order_paused).

unit_missionA

Give a unit a mission: MISSION_FOUND (settle here), MISSION_FORTIFY, MISSION_SLEEP, MISSION_SKIP, MISSION_HEAL, MISSION_ALERT, MISSION_RANGE_ATTACK (x,y), MISSION_PILLAGE (result includes gold_gained), MISSION_EMBARK/DISEMBARK... An air strike is MISSION_MOVE_TO onto the target plot (that is how the game issues it); like a melee move onto an enemy, the result then carries attack with both sides' hp before/after and who died. An intercepted strike says so: attack.intercepted, interceptor, shot_down (from the game's own banner). MISSION_BUILD: pass the improvement in build, e.g. build="BUILD_FARM" (do NOT put it in x/y -- those are for movement-shaped missions). Builds on the unit's own tile. MISSION_SPREAD_RELIGION / MISSION_REMOVE_HERESY: the unit must be inside or adjacent to the target city; the result's effects reports that city's followers/majority before and after, spreads_left, and (for a city-state) influence before/after, so no follow-up read is needed to know whether the spread worked. MISSION_CREATE_GREAT_WORK: the reply's great_work names the work and the city/building slot it filled. AUTOMATE_EXPLORE / AUTOMATE_BUILD (the unit panel's automation buttons, when available_unit_actions lists them) hand the unit to the game's own automation; it then never blocks end_turn. The reply has automated=true, and the unit is listed under turn_status.todo.ongoing until a new move_unit / unit_mission takes it back. Selects the unit like the unit panel does (orders go through the game's network path). A unit on a conditional order (give_order) is taken back: the order pauses (order_paused).

citiesA

My cities: population, yields, current production and turns left, growth, happiness. growth is "growing" (then growth_turns is present), "stagnant" (food_surplus 0 -- typical while empire happiness is negative, which throttles growth) or "starving" (negative surplus, will lose pop). building_maintenance / connection_gold are the Economic Overview per-city expense/income rows (omit when 0). blockaded / wltkd_turns are the city-banner blockade and We Love the King timer. Open one city with city_screen(city_id) for buildings, specialists, worked tiles, queue, and focus.

city_screenA

The city screen for one of my cities: buildings, specialists and their Great Person meters, which tiles are being worked, the full production queue, citizen focus, avoid-growth, and plots that can be bought (buyable + buy_gold). A tile the screen still prices in red (not enough gold) has buy_gold and can_afford: false instead of buyable. meters is the corner of the city screen: food stored/needed and the growth label (a settler counts as stagnant), production stored/needed/per-turn, culture stored/needed and turns until the next border tile, and the fractional gold/science plus faith and tourism per turn; meters.breakdown is the hover behind each of those (sources, food eaten, modifier lines, total). Specialist rows and slots carry yields; built buildings carry their enum and name (what each does: reference("buildings")). An owned tile another of our cities is working names that city (worked_by); a blockaded water tile or a visible enemy unit is marked. Buildings a human can click-to-sell carry can_sell / sell_gold / gold_maintenance. Writes from the same screen: set_city_focus, set_avoid_growth, change_working_plot, buy_city_plot, city_task (annex / raze / unraze), sell_building.

great_person_progressA

Great Person overview: each city's specialist progress, class-specific threshold and rate; national General/Admiral XP meters and next Prophet faith threshold.

culture_worksB

Culture Overview works tab: own buildings' occupied/empty Great Work slots, work tooltips, theming rules/bonuses, city tourism breakdowns and tourism modifiers toward met rivals. swap is the swap tab: ours per class (the work we put up and the pull-down's candidates) and theirs (every met civ's offered writing/art/artifact). Writes: set_swappable_great_work, swap_great_works.

set_swappable_great_workB

Swap tab pull-down: put one of our works of work_class (writing / art / artifact) up for swapping, or pass -1 to clear that spot. Candidates are culture_works().swap.ours[class].candidates.

swap_great_worksA

Swap tab's Swap button: exchange the work we have put up for one another civ offers (their_work_id from culture_works().swap.theirs, same class). Refused unless we have a work of that class put up.

change_specialistA

Add (add=true) or remove (false) one specialist in a BUILDING_* from city_screen. Disables automatic specialist assignment, like clicking a slot. Verifies the resulting count.

set_auto_specialistsB

Enable or disable automatic specialist assignment in an owned, non-puppet city.

set_city_focusA

Set citizen focus on one of my (non-puppet) cities. focus is one of: balanced, food, production, gold, science, culture, great_people, faith. Same as the city-screen focus buttons.

set_avoid_growthB

Toggle avoid-growth on one of my (non-puppet) cities (the city-screen checkbox).

change_working_plotA

Toggle whether this city works plot (x, y). Same as clicking the tile in the city screen. Forced-worked tiles stay locked until clicked again. Puppets refuse.

buy_city_plotB

Buy plot (x, y) for this city for gold. city_screen lists buyable plots with buy_gold.

city_taskB

City-screen tasks: annex (a puppet), raze, or unraze. Annexed cities get resistance; raze burns one population per turn. cities()/city_screen already flag puppet/razing state.

sell_buildingA

Sell one building in one of my non-puppet cities (the city-screen click-to-sell). city_screen lists can_sell / sell_gold / gold_maintenance. Usually one sell per city per turn.

compareA

Your candidates side by side in one read, for a decision you are weighing; the facts, never a pick. kind="production": city_id + candidates (up to 8 UNIT_/BUILDING_/PROJECT_/PROCESS_ types): can_produce or why not, cost, stored, turns, gold / faith price with *can_buy, effects, conditional per-tile yields with how many of this city's tiles qualify, estimated_change (formula in assumptions), maintenance, unique_replaces. kind="research": up to 8 TECH types: status, cost, progress, turns, missing_prereqs, path_beakers and path_turns_estimate for a locked one, unlocks. kind="improvements": unit_id (a worker) + optional plots ([[x, y], ...]; default: plots within 2 that are owned or hold a resource) + optional candidates (BUILD_ types): per plot yields_now, worked, city; per build legal (or why), turns (work only), tile_change, empire_change when a city works the tile, removes / chop_production, connects, maintenance. Fogged plots are not read. sort= a yield or "turns". kind="trade": unit_id (a caravan or cargo ship in a city): every destination with what each end receives, distance and hazard (visible hostiles and camps near it; never "safe"). sort= gold, science, food, production, *_them or distance. Every answer has context, sources, assumptions, n / returned and omitted with the arguments that fetch the rest (limit, 1-20). detail="full" adds help text and the chooser's hover breakdown. Field by field: how_to_play("compare").

city_ranged_attackA

Ranged attack from a city onto plot (x, y). See available_city_strikes first. Does not select the city or pan/flip the camera.

available_city_strikesA

Plots this city can bombard right now. Empty if it has no ranged strike this turn.

available_productionA

What this city can produce right now: units, buildings, projects, processes, with turns at the current production rate, and for units/buildings the gold rush-buy price (gold; absent when the item can never be bought, e.g. national wonders) plus can_buy (affordable AND purchasable right now -> purchase_production). Use set_production(city_id, item) to queue one. Each row carries gold (rush-buy cost, can_buy) and, when the faith tab offers it, faith + faith_can_buy; faith_only rows (Missionaries, Great People, belief buildings) cannot be produced, only bought with purchase_production(yield_type="FAITH"). A priced row with can_buy false carries buy_blocked {reason, text}: gold (balance of cost), stacking (one per tile, with blocking_units), unbuyable, engine (the greyed button's own sentence) or refused. Each row carries the enum in item and, when it differs, the name the chooser button shows: BNW renamed several (BUILDING_THEATRE is "Zoo"), and cities() prints that name, not the enum. A puppet is refused (its AI picks production; producing says what) -- except for Venice, whose puppets answer purchase_only: true with just the gold/faith rows the purchase screen offers.

set_productionA

Set a city's production. item like UNIT_WARRIOR, UNIT_SETTLER, BUILDING_MONUMENT, PROJECT_..., PROCESS_WEALTH. append=true queues it behind the current build (the production screen's shift-click) instead of replacing it; the reply lists the whole queue.

remove_from_queueA

Drop one item from a city's production queue (the city screen's click on a queued item). position is 1-based as set_production's queue and city_screen list it: 1 is what the city is building now, 2 the item behind it. The reply names removed and the queue left; when nothing is left the city needs set_production before the turn can end. Re-setting an item already queued is refused ("already in this city's production queue (position N)"): remove it here first, or set_production another item.

purchase_costA

Read-only: cost to rush-buy item (UNIT_.../BUILDING_...) with gold or faith right now, and whether it's actually purchasable. yield_type is "GOLD" (default) or "FAITH". Wonders (built via a BUILDING_* item too) are never purchasable in vanilla BNW -- can_purchase will read false. Check this before purchase_production. A refusal carries reason and, when the engine has one, engine_reason: the same sentence the production popup puts under a greyed-out purchase button.

purchase_productionA

Rush-buy a unit or building (item like UNIT_WARRIOR, BUILDING_MARKET) with gold or faith (yield_type "GOLD", the default, or "FAITH"). See purchase_cost for price/affordability first. Wonders can never be purchased this way.

available_policiesA

Social policies: what is adopted, what can be adopted right now (enum + name; the effect text is in reference("policies")), which branches are unlocked / unlockable, culture vs next cost. Use before choose_policy / unlock_policy_branch.

choose_policyB

Adopt a social policy, e.g. POLICY_TRADITION, within an already-unlocked branch.

unlock_policy_branchA

Unlock a policy branch/tree, e.g. POLICY_BRANCH_TRADITION, spending a culture policy slot.

choose_ideologyA

Choose the empire's ideology when ENDTURN_BLOCKING_CHOOSE_IDEOLOGY is up (3 Factories or the Modern era): branch is POLICY_BRANCH_FREEDOM, POLICY_BRANCH_ORDER or POLICY_BRANCH_AUTOCRACY. Irreversible short of a revolution. Other civs' ideologies are public (their choice matters for ideological pressure/unhappiness). Returns ideology (confirmed) and free_tenets to spend via choose_policy.

free_great_person_optionsB

When turn_status shows ENDTURN_BLOCKING_FREE_ITEMS: how many free Great People are owed and which unit types (UNIT_SCIENTIST, UNIT_ENGINEER, UNIT_MERCHANT, UNIT_ARTIST, UNIT_WRITER, UNIT_MUSICIAN, ...) qualify.

choose_free_great_personA

Claim a free Great Person, e.g. unit="UNIT_SCIENTIST". Only valid while turn_status shows ENDTURN_BLOCKING_FREE_ITEMS (e.g. right after completing the Liberty policy tree).

religion_overviewA

Religion Overview screen: faith, next Great Prophet threshold, my pantheon/religion and beliefs, all founded religions with their beliefs and city counts, per own city the followers and pressure of each religion, and auto_purchase: the automatic faith purchase pull-down (current selection and every option it lists with its faith cost; change it with set_faith_purchase).

set_faith_purchaseA

The Religion Overview's automatic faith purchase pull-down. kind is nothing, save_prophet, unit or building; index is the unit/building id from religion_overview().auto_purchase.options (each option lists its faith cost). Refused for anything the pull-down does not currently list.

change_ideologyA

The policy screen's Switch Ideology button: adopt the preferred ideology public opinion pushes toward, at the cost overview().public_opinion.switch_cost shows (anarchy turns, tenets kept). Refused while the button is grey (no public-opinion unhappiness).

faith_great_person_optionsA

When turn_status shows ENDTURN_BLOCKING_FAITH_GREAT_PERSON: the Great People the faith can buy now.

choose_faith_great_personC

Take one unit type from faith_great_person_options (it appears in the capital or holy city).

available_beliefsA

Beliefs still available for one slot (enum + name; what each does is in reference("beliefs")). kind: pantheon | founder | follower | enhancer | bonus | reformation. Founding a religion takes pantheon(if none yet)/founder/follower(/bonus for Byzantium); enhancing takes follower + enhancer. kind=founder also lists the religions nobody has founded.

add_reformation_beliefA

When turn_status shows ENDTURN_BLOCKING_ADD_REFORMATION_BELIEF (Piety's Reformation policy): pick one from available_beliefs(kind="reformation").

found_pantheonA

Found a pantheon with the given belief, e.g. BELIEF_GOD_OF_THE_SEA. Check turn_status first: only valid when blocking_name is ENDTURN_BLOCKING_FOUND_PANTHEON.

found_religionA

Found a religion (RELIGION_..., see available_beliefs(kind="founder").religions) in the city at (city_x, city_y) = data1, data2 of the pending BUTTONPOPUP_FOUND_RELIGION. beliefs in order: a pantheon belief (only if I have no pantheon yet), a founder belief, a follower belief (+ a bonus belief for Byzantium). Only valid when blocking_name is ENDTURN_BLOCKING_FOUND_RELIGION. custom_name renames the religion (empty keeps the stock name).

enhance_religionA

Enhance my founded religion: belief4 = a follower belief, belief5 = an enhancer belief (available_beliefs), in the city at (city_x, city_y) = data1, data2 of the pending BUTTONPOPUP_FOUND_RELIGION (the holy city, where the Great Prophet stands); custom_name is ignored unless the game asks for one. Only valid when blocking_name is ENDTURN_BLOCKING_ENHANCE_RELIGION.

available_researchA

Techs I can research right now (prereqs met). current marks the one already selected; progress is the science already stored in a tech (shown whenever it is nonzero). unlocks is the tech-tree button row for this seat: our units and buildings (not another civ's uniques), revealed resources, and the ability the button names (embark, ocean, embassy).

tech_treeA

The tech tree: have (already researched), techs (current / available / unavailable with prereqs and missing steps, turns-if-researchable, and unlocks — the buttons on that tech for this seat). No rival column: an embassy shows a capital, not a tech list (the steal-tech chooser is the only stock screen that names a rival's techs). available_research is the leaf list only.

steal_tech_optionsA

When a spy finished stealing: which civs I can take a tech from and the techs available from each. Each victim carries player_id -- pass that to steal_tech. Also listed on turn_status.todo.steal_tech even if blocking_name is still POLICY/PRODUCTION/etc. (the engine reports one blocker at a time).

steal_techA

Take a stolen tech (TECH_...) from player_id (steal_tech_options lists each victim and the techs available from it). Clears ENDTURN_BLOCKING_STEAL_TECH.

set_researchA

Choose current research, e.g. TECH_POTTERY, TECH_MINING, TECH_BRONZE_WORKING. Also the way to claim a free technology (blocking_name ENDTURN_BLOCKING_FREE_TECH, e.g. Oxford University): the named tech is granted outright (granted), current research is left as it was. A tech whose prerequisites are missing works like clicking it in the tech tree: the game researches the first missing step now and queues the rest (goal, queue in the reply).

dismiss_discussionA

Leave an AI leader's negotiation/demand/trade-offer screen (see wait_for_my_turn's discussion_pending) without agreeing to anything. For a trade already on the table, prefer incoming_deal + refuse_deal. Also closes a plain leader greeting (first meeting, echo of a war/peace just made), and every greeting queued behind it (closed_count), stopping at a screen that needs an answer. When another leader is queued behind this one (several can wait at a turn start), the answer carries still_pending: true, next (their screen, words, buttons and the deal on the table) and the gate it raises: answer that one next, no discussion() read needed.

discussionA

What the open leader screen says: the leader, their mood, their speech, the response buttons (id + text) and, on a trade screen, the deal on the table; screen="greeting" is a plain first-meeting / war / peace message with nothing to decide. Call this whenever turn_status or wait_for_my_turn reports discussion_pending, then answer with respond_discussion(button_id), accept_deal / refuse_deal (trade screen), or dismiss_discussion (plain acknowledgement, no buttons).

respond_discussionA

Press one of the response buttons listed by discussion() (1-4). Use this for AI demands, warnings, requests and post-deal remarks that offer choices such as apologise / dismiss / threaten. expect: optional words the button's text must contain (e.g. "no interest"); if it does not, nothing is pressed and the real buttons come back -- guards against pressing a remembered id on a different screen. When another leader is queued behind this one (several can wait at a turn start), the answer carries still_pending: true, next (their screen, words, buttons and the deal on the table) and the gate it raises: answer that one next, no discussion() read needed.

incoming_dealA

Read the current trade table (scratch deal): items already offered, who they are from. A VOTE_COMMITMENT row names the resolution, the pledged choice and the number of votes (votes); a THIRD_PARTY_WAR / THIRD_PARTY_PEACE row names the third party (other player id, other_name, minor). Empty items means no deal is on the table. Does not mutate the deal or open the trade screen.

current_dealsA

Diplomacy Overview current deals: who, items, turns remaining until each expires. Refuses if a trade is already on the scratch table (answer incoming_deal first). Does not construct or propose anything.

accept_dealA

Accept an incoming trade already on the table (see incoming_deal). Does not construct a new deal. To make an offer of my own use propose_deal. The answer carries the AI's remark, the accepted_items and measured effects (gold per turn, deal count, resources before vs after); new_deal is the row the deal now holds in current_deals (a renewal's offered rows carry the old deal's end; the new end replaces it, the offered one stays as final_turn_offered). When another leader is queued behind this one (several can wait at a turn start), the answer carries still_pending: true, next (their screen, words, buttons and the deal on the table) and the gate it raises: answer that one next, no discussion() read needed.

refuse_dealA

Refuse an incoming trade already on the table (see incoming_deal). Does not construct a new deal. When another leader is queued behind this one (several can wait at a turn start), the answer carries still_pending: true, next (their screen, words, buttons and the deal on the table) and the gate it raises: answer that one next, no discussion() read needed.

trade_catalogA

What can currently go on a trade table with this major civ (gold, GPT, embassy, open borders, pacts, resources, cities as name + pop, with x/y only once the plot is revealed, third_party.war/peace.us/them (the Other Players pocket: every third civ both sides know, ok or greyed with the screen's reason), World Congress vote_commitments: one row per pending proposal + choice either side may pledge, with votes_us/votes_them), peace (at war: the Negotiate Peace gate -- ok, locked_turns, the screen's note; the treaty itself is seeded on both sides of any table by the screens). Each resource carries class, us_available/them_available (spare copies each side holds) and last_copy: true when exporting it would give away our only copy of a luxury (costs happiness). Read-only: does not construct or send a deal. City-states: use city_state_gifts.

city_state_giftsA

Gold gift tiers and friendship for a met city-state. See minor_gold_gift to actually gift. ally is what the city-state screen's ally tooltip shows: {us: true}, {none: true, to_become_ally}, or the current ally (named only if met) with to_become_ally = influence we still need to pass it. Other majors' influence is not visible to a player and is not returned. Each tier carries influence_after and makes_ally -- whether that gift actually takes the alliance, or short_by how much it would miss the civ currently holding it.

city_capture_optionsA

When pending_popups shows BUTTONPOPUP_CITY_CAPTURED: the plunder, and each choice the popup offers (liberate / annex / puppet / raze) with its unhappiness change and the warmonger warning from the button tooltip.

choose_city_captureB

Decide a captured city: choice = liberate | annex | puppet | raze (only those city_capture_options lists).

war_consequencesA

Read before declare_war (or city_state_action declare_war): what the game's confirmation screen warns about -- a Declaration of Friendship being broken, denouncements, city-states allied to the target that join the war, majors protecting a targeted city-state, and trade routes that would be cancelled.

city_state_actionsC

The city-state screen beyond gifts: influence, quest_list (structured: type, turns_left, kill-camp x/y when that camp is revealed, contest scores), plus the same quest tooltip text as quests. Whether I can pledge / revoke protection, demand tribute (gold amount, or a Worker; details explains the strength check), declare war, or make peace.

city_state_actionB

Press one city-state screen button. action: pledge | revoke_pledge | bully_gold | bully_unit | declare_war | make_peace. Refused with the current state when the screen would not offer it.

gift_tile_improvement_optionsA

The city-state screen's "Gift Improvement" button, and the hexes it would highlight. can / cost / why_not are the button (allies only, and the gold has to be there); plots is every tile within search_radius of that city-state's capital where the gift is legal -- the same magenta hexes the stock interface mode lights up. A tile I have not revealed is listed as bare coordinates. Empty plots with can true means the ally has nothing left worth improving.

gift_tile_improvementA

Buy a city-state an improvement on one of its tiles (clicking a highlighted hex). x/y must be a plot from gift_tile_improvement_options. Reports the gold spent, the improvement that appeared, and influence before/after.

minor_gold_giftA

Gift gold to a city-state. amount must be city_state_gifts' small, medium, or large tier. Check that tier's makes_ally first: influence bought is not the alliance bought when another major is sitting above me. The reply says still_short when the gift lands under the current ally.

demographicsB

Demographics: our value/rank and public best, average and worst for population, food, production, gold, land, soldiers, approval and literacy. Unmet best/worst identities are masked.

domination_progressB

Original capitals of met civilizations and their current holders; unrevealed coordinates and unmet holders are masked. Includes whether our team controls each capital.

wonder_overviewB

World wonders held by met civilizations (Global Relations). Locations and captured/builder details only for cities in sight.

city_state_bonusesC

Met city-state's trait/bonus and personality tooltips, current food/culture/faith/happiness/ science benefits, unit gift estimate, unique military unit and exported resources.

gift_unit_optionsA

Units that can currently be gifted to this met city-state (the Gift Unit button), with the button's figures: influence_gain and travel_turns (the unit walks there; the influence lands with it). While a gift is still on its way (in_transit.arrives_in) the list is empty (why_empty): a city-state takes one gift at a time. gift_unit sends one.

gift_unitA

Gift one of my units to a met city-state (Network.SendGiftUnit). Verifies the unit left our army; influence_gain / travel_turns say what it earns and when (not at once). Refused while an earlier gift is still on its way. Use gift_unit_options to see who can go.

diplomacyB

Civs and city-states I have met: at war, score (majors), ally/friends (city-states). Unmet players are omitted.

relationshipB

Our standing with one civ or city-state: their visible approach toward us, friendship / denouncements / embassies / open borders / research agreement / defensive pact, the opinion lines the game shows, their public relations with every civ we have met (wars, friendships, denouncements, city-state alliances) and the recent messages they sent us. discuss lists the Discuss-screen buttons a human would see (share intrigue, stop spreading religion, stop spying, don't settle, stop digging, declare friendship). discussion() includes this for the leader on screen; call it directly before proposing or answering anything.

declare_warA

Declare war on a civ I have met. Irreversible for a while (can't make peace again immediately). Bypasses the leader-head screen entirely.

make_peaceA

Offer peace to a civ I'm at war with, through the real trade screen: the treaty goes on both sides and items (same shapes as propose_deal: GOLD, GOLD_PER_TURN, RESOURCES, CITIES, THIRD_PARTY_WAR/PEACE...) are the terms, from_us picking who gives what. An AI answers on the spot (accepted, reply, at_war afterwards; it can refuse for a while after a declaration even when nothing locks it). A human seat gets it as a pending proposal (pending: true) to accept_deal / refuse_deal on its turn. Refused with the leader screen's reason while locked into war (see trade_catalog(player_id).peace). Any propose_deal while at war is the same peace deal.

denounceB

Publicly denounce another civ. Worsens relations with them and their friends; cannot be undone.

spaceship_statusA

Science-victory progress: whether the Apollo Program is done, for each spaceship part how many are needed, already in the ship, built but not yet delivered to the capital, and which tech unlocks it; plus met rivals that finished Apollo and how many parts they have (the Victory Progress screen's space race). complete once every part is in the ship, with game_over (the win ends the game at once) and a note on the last part's unit, which the engine never gets to remove.

culture_overviewA

Culture-victory race (the Culture Overview screen): for each met major civ, how many civs it is Influential on out of how many it needs, its tourism, and its influence on every other major civ -- level (exotic .. dominant), percent, tourism per turn, trend, and turns_to_influential while rising. A civ you have not met appears as "unknown". Use it when a "Culture Victory Contender" alert names a rival.

propose_friendshipA

Ask an AI civ for a Declaration of Friendship (the leader screen's "work together"). Refused when already friends, asked too recently, at war or unmet. The reply says whether they accepted. Declarations expire after their term (a "Declaration of Friendship Has Expired" notification) -- this is how to renew one.

accept_friendshipA

Accept a pending Declaration of Friendship proposal (turn_digest's leader_message with state DISCUSS_WORK_WITH_US). Works even if the discussion dialog was already dismissed/declined -- the request stays acceptable server-side. Check diplomacy() or IsDoF via diplo_event's underlying call if you need to confirm it actually took.

diplo_eventA

Escape hatch for any other diplomatic action not covered above (accept/decline a coop-war offer, respond to a denounce request, agree to work with someone, etc). event is a FromUIDiploEventTypes name, with or without its FROM_UI_DIPLO_EVENT_ prefix -- see docs/NOTES.md for the list. Read a pending leader_message in turn_digest first to know what's being asked and what data1/data2 should be.

propose_dealA

Offer a trade to another civ. With an AI: drives the game's real leader / trade screens, proposes, reads the reply, closes them and reports measured effects (gold, gold/turn, happiness, per-resource import/export before vs after): nothing to poll afterwards. With another human seat: puts the same table on the PvP deal screen (pvp: true, pending: true); that seat answers with accept_deal / refuse_deal. items: [{"type":"RESOURCES","resource":"RESOURCE_DYE","from_us":true,"amount":1}, {"type":"GOLD_PER_TURN","from_us":false,"amount":5}] Types: GOLD / GOLD_PER_TURN (amount), RESOURCES (resource, amount), OPEN_BORDERS, ALLOW_EMBASSY, DEFENSIVE_PACT, RESEARCH_AGREEMENT, TRADE_AGREEMENT (from_us picks the direction), CITIES (city_id), VOTE_COMMITMENT (resolution_id, choice_id, repeal), THIRD_PARTY_WAR / THIRD_PARTY_PEACE (other: player id), PEACE_TREATY (implied while at war: any deal then is peace with terms; or make_peace). Read trade_catalog(player_id) first: what is legal, how much gold each side can put up, which cities may be traded (capitals never), the vote and third-party rows. Lump-sum gold needs a Declaration of Friendship (a Brave New World rule; trade_catalog's gold.note says so); gold per turn is not gated. Refuses without opening a screen an amount that is not a positive whole number or beyond what that side has, a city outside the catalog, or an item that does not land on the table at the requested amount. ask_counter=true also returns the AI's counter-offer (counter.items), which can go straight back in. Timed items last the game's deal length (30 turns). Item rules in full: how_to_play("propose_deal").

demandA

The leader screen's Demand button: tell an AI leader to hand over items for nothing, through the game's real screens (Demand -> table with only THEIR pocket -> DEMAND -> the leader's answer), then close up and report accepted, reply and measured effects like propose_deal. items take propose_deal's shapes and are all from_us:false (GOLD, GOLD_PER_TURN, RESOURCES, CITIES, OPEN_BORDERS, ALLOW_EMBASSY...); pick from trade_catalog(player_id)'s them side. AI leaders only (a human seat has no leader screen: propose_deal sends them a table), and the button is greyed at war (make_peace instead). As in the stock game a refused demand is remembered against you by that leader; use it deliberately.

negotiate_dealA

Ask an AI civ about a deal without committing to it (the trade screen's helper buttons), then close the screen. mode="equalize": put a draft on the table and ask what would make it acceptable; "what_will_ai_give": list only my items (from_us=true) and see what the AI offers for them; "what_does_ai_want": list only their items (from_us=false) and see what the AI asks in return. items takes propose_deal's rows, from_us saying who gives each one -- there is no offer/give/receive shape: [{"type":"RESOURCES","resource":"RESOURCE_GOLD","from_us":true,"amount":1}, {"type":"GOLD_PER_TURN","from_us":false,"amount":5}] Returns the AI's reply and the resulting table items, which can be passed to propose_deal as-is.

espionage_intrigueB

The Espionage Overview intrigue log: turn, spy, discoverer and the player-visible message.

available_trade_routesA

Valid trade-route destinations for a specific trade unit (caravan/cargo ship) right now, with the trade_type to pass into establish_trade_route. Yields are PER TURN: gold/science/food/production are what my end receives, *_them what the destination receives (an internal food/production route delivers to the destination city, so read food_them/production_them for those). Religious pressure, when the chooser would print it, is from_religion/from_pressure and to_religion/to_pressure. kind = international|food|production. detail="full" adds details, the gold and science hover behind each row (the same numbers, itemised: base, buildings, resources, river; a paragraph per destination). A list means there are destinations; when there are none it is an object instead, saying why -- a route starts inside one of my own cities, so a unit in the field gets the nearest one to walk to.

trade_routesB

Trade Route Overview: outgoing is Your TR (my caravans/cargo ships), incoming is With You (other civs' routes into my cities). Each row: from/to city and player, turns_left, per-turn yields for the origin (gold/science) and destination (gold_them / food_them / production_them). The religion columns are from_religion/from_pressure (left arrow) and to_religion/to_pressure (right arrow), omitted when that cell is blank. details is the gold and science hover. overview().free_trade_route_slots (available - used - queued) says whether a new caravan can be trained. path is the route line the map draws, plot by plot from the origin (vis=false where fogged), as the plot hover names it on any revealed plot. unit is the caravan/cargo ship on that line (ours always; a foreign one only while in sight) with escorted / escorted_by: our combat units on its plot, which an enemy must defeat before it can plunder; unit.matched is recorded (this caravan was seen alone on this route before), line or line_ambiguous (routes share the plot and no earlier read told them apart: it may be the other row's caravan). enemies_near_path lists visible enemy combat units within one hex of the line with their distance to the caravan.

establish_trade_routeA

Send a caravan/cargo ship to establish a trade route. Either pass dest_x/dest_y/trade_type from available_trade_routes(unit_id), or just city_name (e.g. "Antwerp") with kind = international/food/production when that city offers more than one route type.

plunder_trade_routeB

Order a military unit standing on an enemy trade route to plunder it.

spiesA

My spies: agent_id, name, rank, state, where stationed, and can_stage_coup. In a city-state the row carries the coup button's hover: coup_chance (percent) when it is enabled, otherwise coup_why_not (spy_dead / surveillance_pending / no_ally / we_are_ally) and coup_ally. In a foreign major city the row carries city_potential, the potential meter's hover: state potential (effective potential, base_potential, building/wonder/policy modifiers, catch_spies lines), cannot_steal, once_known or unknown. See available_spy_cities/move_spy/ stage_coup for actions.

available_spy_citiesA

Cities a given spy (agent_id, from spies()) could be sent to right now -- my own cities (counter-intel) and others' (steal tech / set up a future coup). Feeds move_spy. potential is the espionage screen's base potential: for a foreign city, how much there is to steal; for my own, how exposed it is to theft; "unknown" until a spy has had that city under surveillance.

move_spyB

Assign/relocate a spy (see available_spy_cities). Recall home instead with target_player_id=-1, target_city_id=-1. as_diplomat only applies when the target is another major civ's capital at peace.

stage_coupB

Attempt a coup against a city-state's current ally with a spy that has established surveillance there (spies()'s can_stage_coup). Returns the chance the confirm printed, the outcome notification and succeeded (the city-state's ally is now us); a refusal says why_not.

league_statusA

Read-only: World Congress state -- resolutions I can propose (between sessions) or vote on (during a session), each with the tooltip the League Overview shows (details). name is the button text with the choice's icon tag removed (the screen draws that icon): "World Religion: Tengriism", not "[ICON_RELIGION_TENGRIISM]". Greyed resolutions are unavailable_enact. Already in effect: active_resolutions and active_effects. Also projects (World's Fair / International Games / ISS: percent complete, our production, the hammers each reward tier needs). See league_propose_enact/league_propose_repeal/league_cast_votes. The same project paragraph is on a league process in available_production (league_project).

league_propose_enactA

Propose enacting a World Congress resolution, e.g. RESOLUTION_SCIENCES_FUNDING (see league_status() for what's currently proposable and any required choice). Needed to clear ENDTURN_BLOCKING_LEAGUE_CALL_FOR_PROPOSALS -- closing the popup without proposing does NOT clear it.

league_propose_repealA

Propose repealing an active World Congress resolution (see league_status()'s proposable_repeal).

league_cast_votesA

Vote on this session's World Congress proposals (see league_status()'s votable while in_session). votes: [{"resolution_id": id, "direction": "enact"|"repeal", "num_votes": n, "choice": id (optional)}]. For a plain yes/no proposal (every repeal; enacts with no choices listed) choice is required: "yes"/"no" or 1/0 (leagueoverview.lua's kChoiceYes/kChoiceNo). For proposals with choices (e.g. World Leader, host city) pass the listed choice id. Leftover votes are cast as abstain.

load_saveA

Load a save from the main menu by its bare name, no path or .Civ5Save extension (e.g. "QuickSave", or "Sejong_0180 AD-1200" for a manual save). Only works from a fresh main-menu state, not mid-game: exit_to_main_menu first. The answer carries seat, the player this server will play in the loaded game (auto seats are detected afresh; hotseat keeps the default, set_seat changes it).

load_latestA

Crash-recovery: load whichever save (quicksave OR autosave) has the newest filesystem mtime, regardless of name. Prefer this over load_save("QuickSave") when resuming after a crash -- an autosave made during play can be newer than the last explicit quicksave, and load_save only checks quick/manual saves before ever considering autosaves. Only works from a fresh main-menu state: exit_to_main_menu first. The answer carries seat like load_save.

exit_to_main_menuA

Leave the loaded game for the main menu, so load_save / load_latest can open another save. Quick-saves first when it is my turn in a solo game (save=false skips that); in a game with other people ask the human before leaving, as it ends the game for them too. Waits until the main menu is on screen. Usable while it is not my turn.

Prompts

Interactive templates invoked by user choice

NameDescription
play_turnPlay one turn of Civilization V through the civ5 tools.

Resources

Contextual data attached and managed by the client

NameDescription
referenceThe rule book: what every unit, building, tech, policy, promotion, belief, resource, terrain, improvement and unit action does, from this game's database. Markdown.
playbookHow to play through this harness: the turn loop, the blocker table, verification habits.

TDQS

B3.3/5.0

Scored across 144 tools

Disambiguation3/5

Many tools have distinct, well-documented purposes, but the set contains numerous overlapping read tools for map state (known_world, map_window, revealed_map, map_index, tactical_view, explore_frontier) and status (turn_status, briefing, overview, turn_digest). An agent must carefully read descriptions to choose the right one, and some choices (e.g., available_unit_actions vs todo_actions vs units vs unit_mission_targets) could be confused.

Naming Consistency4/5

Names are uniformly snake_case with predictable prefixes: read-only tools are nouns (units, cities, overview), actions are verbs (move_unit, set_production, choose_policy), option lists use available_* or *_options, and choosers use choose_*. A few generic names like do and noun-only reads deviate slightly from a strict verb_noun pattern, but the overall convention is clear and consistent.

Tool Count1/5

144 tools is far beyond the 3–15 range considered well-scoped, and the rubric explicitly flags 50+ as an extreme mismatch. Even for a complex game like Civilization V, this volume imposes a heavy selection burden on the agent and suggests many niche or overlapping tools could be consolidated.

Completeness5/5

The surface covers nearly every game subsystem: units, combat, cities, production, research, policies, religion, espionage, diplomacy, trade, map reading, save/load, notebook, and conditional orders. There are no obvious gaps in CRUD or lifecycle coverage for the domain, and dead ends are explicitly handled with blocker-clearing tools.

Maintenance

ActivityMaintained
ResponsivenessNo issues