Standing orders keep an empire running without a bot polling: triggers react to conditions, and schedules run programs aboard ships, stations and facilities.
The language
- Triggers and schedules are data, in one small JSON language shaped like ship queries. There is no code and there are no variables.
- An action is
{"do": verb, "args": {...}}. The verbs are the ship verbs, with the sameargsas each verb's own endpoint. - A
jumpwith{"to": "unsurveyed"}in place ofsystem_idgoes to the charted system its owner has not surveyed with the shortest route from the ship's, picked when the order resolves. With none left, the order fails withnothing_unsurveyed. The jump endpoint and group orders take it too. - Every action becomes ordinary orders, resolved like any other. Each carries
source, such astrigger:unloadorschedule:miners. - Creating, replacing, pausing, resuming and dropping a standing order are orders too, resolved in the tick.
Conditions
| Condition | Holds when |
|---|---|
{"ships": <selection>, "count": <threshold>} |
The number of ships a group, query or node matches meets the threshold |
{"body": id, "distance": <threshold>} |
A body is that far from its star, by its last seen orbit. temperature checks its warmth |
{"cargo": {"station": id, "<commodity>": <threshold>}} |
A station, or a ship with ship, holds that much of a commodity |
{"tick": <threshold>} |
The current tick meets the threshold |
{"every": n} |
The current tick is a multiple of n |
{"ship": <match>} |
Schedules only: the ship running the program matches the ship query fields |
{"and": [...]}, {"or": [...]}, {"not": {...}} |
Combine conditions |
- A threshold uses the ship query operators:
<,<=,>,>=and=. - Conditions are checked during the tick, after arrivals and jobs, against the world as it is then.
- A body never seen never holds. A ship or station not owned reads as holding nothing.
POST /v1/fleet/conditions/checkreports whether a condition holds now.?ship_id=tests ashipcondition against one ship.
Triggers
A trigger checks a condition every tick and, when it holds, gives one order to a selection of ships.
{"when": {"ships": {"group": "full"}, "count": {">=": 1}},
"do": "transfer",
"args": {"commodity": "iron", "to_kind": "station", "to_id": 1},
"ships": {"group": "full"},
"on_fail": {"do": "move", "args": {"body_id": 17}},
"until_tick": 9000}
PUT /v1/fleet/triggers/{name}creates or replaces a trigger.POST .../pause,POST .../resumeandDELETEcontrol it.GET /v1/fleet/triggerslists them.- Every active trigger is checked once per tick, after hand-sent orders. When
whenholds, the action goes toshipsas one batch (trigger.fired). - A trigger fires at most once per tick. One whose
shipsmatch nothing does nothing. on_failsends one action to each ship whose order fails.until_tickexpires the trigger.- A trigger's orders travel the Infonet like hand-sent orders.
- A trigger has no ship of its own, so a
shipcondition is refused (needs_ship).
Schedules
A schedule gives a program to a selection of ships, each running its own copy, or to one station or facility.
{"ships": {"node": 2},
"program": [
{"forever": [
{"do": "move", "args": {"body_id": 18}},
{"do": "extract", "args": {"body_id": 18}, "on_fail": [{"break": true}]},
{"wait": {"until": {"cargo": {"station": 1, "iron": {"<": 1900}}}, "at_most": 100},
"on_timeout": [{"stop": true}]},
{"do": "move", "args": {"body_id": 17}},
{"do": "transfer", "args": {"commodity": "iron", "to_kind": "station", "to_id": 1}}
]},
{"do": "move", "args": {"body_id": 17}}
]}
| Block | Does |
|---|---|
{"do": verb, "args": {...}} |
Gives an order. The step ends when the ship is idle again |
"on_fail": [...] |
On a do: steps to run if its order fails |
{"wait": {"ticks": n}} |
Waits n ticks |
{"wait": {"until": <condition>}} |
Waits until the condition holds. at_most and on_timeout give up after a time |
{"if": <condition>, "then": [...], "else": [...]} |
Runs one branch |
{"forever": [...]} |
Repeats until a break or stop |
{"repeat": n, "loop": [...]} |
Repeats n times |
{"while": <condition>, "loop": [...]} |
Repeats while the condition holds |
{"break": true} |
Leaves the innermost loop |
{"stop": true} |
Ends the program for this ship |
PUT /v1/fleet/schedules/{name}creates or replaces a schedule. Pause, resume and drop work as for triggers.GET /v1/fleet/schedules/{name}shows where each runner is.shipsis read every tick. Each matching ship runs its own copy from the top, and a ship that stops matching leaves.- A ship busy when it joins starts once idle, so a schedule never interrupts work in progress.
- A ship runs one schedule at a time: the newest one it matches.
- Replacing a schedule restarts every runner from the top. Pausing freezes them after their current job.
- Each tick a runner works through control flow until it reaches a
door await, which ends its turn. Control flow costs nothing. - A finished or stopped program leaves its ship in the schedule, doing nothing.
Stations and facilities
- A schedule with
stationorfacilityin place ofshipsruns on one of the owner's stations or facilities. - A station can
transferandbuilda facility. A facility canproduce,builda ship at a shipyard, andset_priority. - A change to a station's or facility's schedule travels to its station like a change to a ship's.
Latency
- A change to a trigger or schedule goes as a packet to every ship, station or facility it covers, before and after the change. It applies to all of them once the last packet is delivered; until then the old version runs.
- A schedule's steps run aboard and pay no latency. A trigger's orders travel like any order.
- A ship, station or facility beyond the Infonet keeps the schedule it has. It joins or leaves a schedule, as
shipschanges, only once a change could reach it.
Tracing
- A ship running a schedule shows
program: the schedule, its state, and where it is as a path, such as[0, "forever", 2]. GET /v1/fleet/triggers/{name}/historyandGET /v1/fleet/schedules/{name}/historylist recent entries, newest first: what happened, any rejection code, and the order sent. History is kept by name, so it outlives the standing order.- Entries:
fired,did,failed,waited,timed_out,broke,stopped,finished,pausedandexpired. - The digest's
standingsection sums up each standing order over a span. See Events. - A standing order that hits a server fault is paused, with change
failed.