{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "start_script", "title": "Game-start script", "description": "Declarative opening sequence for a game. The bundled default (default_dwarf_tribe) reproduces the freepeople tribe-founding prologue; scenario-makers author their own and point setup.json:start_script at the file id. The runner lives in Rust (mc-turn::start_script); this script is content. Every op maps to an existing simulation primitive — the runner sequences, it does not add new behaviour.", "type": "object", "additionalProperties": false, "required": ["id", "schema_version", "actors", "phases"], "properties": { "id": { "type": "string", "description": "Unique script id; matches the filename stem and the value of setup.json:start_script.", "pattern": "^[a-z0-9_]+$" }, "schema_version": { "type": "integer", "description": "Schema version this script targets. Current: 1.", "const": 1 }, "label": { "type": "string", "description": "Human-readable name shown in scenario/new-game UI." }, "description": { "type": "string", "description": "What this opening does, for the scenario picker." }, "rng_domain": { "type": "string", "description": "SeedDomain tag for this script's PRNG substream — keeps it disjoint from worldgen/other streams. Default: 'start_script'.", "default": "start_script" }, "actors": { "type": "array", "description": "Actor archetypes the ops reference by tag (e.g. the wanderers that converge, the tribe unit they become).", "items": { "$ref": "#/$defs/actor" } }, "params": { "type": "object", "description": "Named tunables that ops reference via *_ref. Each resolves a value (today: from a setup.json key via from_setup) so a scenario retunes counts/mode/radius without editing ops.", "additionalProperties": { "$ref": "#/$defs/param" } }, "phases": { "type": "array", "description": "Ordered scripted turns. The runner is at one phase at a time; End Turn resolves the current phase and enters the next. Must contain at least one phase of kind 'normal' (the hand-off to normal play).", "minItems": 1, "items": { "$ref": "#/$defs/phase" } } }, "$defs": { "actor": { "type": "object", "additionalProperties": false, "required": ["tag", "unit_id"], "properties": { "tag": { "type": "string", "description": "Reference name used by ops (e.g. 'wanderer', 'tribe')." }, "unit_id": { "type": "string", "description": "Unit definition id this actor instantiates (must exist in the unit catalog)." }, "controlled": { "type": "boolean", "default": false, "description": "True if the player commands this actor (e.g. the tribe on the hand-off turn)." } } }, "param": { "type": "object", "additionalProperties": false, "required": ["from_setup"], "properties": { "from_setup": { "type": "string", "description": "setup.json key whose value this param resolves to." } } }, "phase": { "type": "object", "additionalProperties": false, "required": ["id", "display_turn", "kind"], "properties": { "id": { "type": "string", "description": "Phase id; used in validator error messages." }, "display_turn": { "type": "integer", "description": "Turn counter the HUD shows during this phase (need not be contiguous or monotonic)." }, "kind": { "type": "string", "enum": ["prologue", "normal"], "description": "'prologue' = input-gated scripted turn; 'normal' = hand-off marker (its on_enter runs, then normal play takes over)." }, "banner_key": { "type": "string", "description": "ThemeVocabulary key for the centered banner shown this phase." }, "banner_persist": { "type": "boolean", "description": "True = banner stays until the next phase; false = auto-dismiss. Default: true for 'prologue', false for 'normal'." }, "allowed_actions": { "type": "array", "items": { "type": "string" }, "description": "Player input gate for this phase. Default: ['end_turn'] for 'prologue'." }, "on_enter": { "type": "array", "description": "Ops run when the phase becomes active.", "items": { "$ref": "#/$defs/op" } }, "on_resolve": { "type": "array", "description": "Ops run on End Turn, before entering the next phase.", "items": { "$ref": "#/$defs/op" } } } }, "op": { "type": "object", "required": ["op"], "description": "A single declarative operation. Each maps to an existing simulation primitive. The 'op' discriminator selects the variant; see each variant's required args.", "properties": { "op": { "type": "string", "enum": [ "place_spawn_box", "roll_actor_directions", "step_actors", "converge_actors", "spawn_unit", "set_unit_actions", "set_banner", "lift_fog", "emit_chronicle", "found_city" ] } }, "allOf": [ { "if": { "properties": { "op": { "const": "place_spawn_box" } } }, "then": { "required": ["actor", "count_ref", "mode_ref", "radius_ref"], "properties": { "actor": { "type": "string", "description": "Actor tag to seed." }, "count_ref": { "type": "string", "description": "params key giving the per-mode wanderer count." }, "mode_ref": { "type": "string", "description": "params key for the start mode (tournament|custom)." }, "radius_ref": { "type": "string", "description": "params key for the spawn-box radius." } } } }, { "if": { "properties": { "op": { "const": "roll_actor_directions" } } }, "then": { "required": ["actor", "mode_ref", "bias_ref"], "properties": { "actor": { "type": "string" }, "mode_ref": { "type": "string", "description": "params key for the start mode (tournament|custom)." }, "bias_ref": { "type": "string", "description": "params key for the inward-bias probability." } } } }, { "if": { "properties": { "op": { "const": "step_actors" } } }, "then": { "required": ["actor"], "properties": { "actor": { "type": "string" } } } }, { "if": { "properties": { "op": { "const": "converge_actors" } } }, "then": { "required": ["actor", "radius_ref", "min_count_ref", "produce", "mode_ref", "cap_ref"], "properties": { "actor": { "type": "string", "description": "Actor tag to merge." }, "radius_ref": { "type": "string", "description": "params key for the convergence radius." }, "min_count_ref": { "type": "string", "description": "params key for the minimum to form the group." }, "produce": { "type": "string", "description": "Actor tag produced by the merge (e.g. 'tribe')." }, "mode_ref": { "type": "string", "description": "params key selecting the founding-pop formula (start mode)." }, "cap_ref": { "type": "string", "description": "params key bounding the bonus founding pop." } } } }, { "if": { "properties": { "op": { "const": "spawn_unit" } } }, "then": { "required": ["unit_id", "at"], "properties": { "unit_id": { "type": "string" }, "at": { "description": "'centroid' | 'start' | {q,r}.", "oneOf": [ { "type": "string", "enum": ["centroid", "start"] }, { "type": "object", "additionalProperties": false, "required": ["q", "r"], "properties": { "q": { "type": "integer" }, "r": { "type": "integer" } } } ] }, "count": { "type": "integer", "minimum": 1, "default": 1 }, "controlled": { "type": "boolean", "default": false } } } }, { "if": { "properties": { "op": { "const": "set_unit_actions" } } }, "then": { "required": ["actor", "actions"], "properties": { "actor": { "type": "string" }, "actions": { "type": "array", "items": { "type": "string" } } } } }, { "if": { "properties": { "op": { "const": "set_banner" } } }, "then": { "required": ["text_key"], "properties": { "text_key": { "type": "string" }, "persist": { "type": "boolean", "default": false } } } }, { "if": { "properties": { "op": { "const": "lift_fog" } } }, "then": { "required": ["area"], "properties": { "area": { "type": "string", "description": "'spawn_box' or 'radius:N'." } } } }, { "if": { "properties": { "op": { "const": "emit_chronicle" } } }, "then": { "required": ["event"], "properties": { "event": { "type": "string", "description": "Chronicle event id." } } } }, { "if": { "properties": { "op": { "const": "found_city" } } }, "then": { "required": ["from", "mode_ref", "cap_ref"], "properties": { "from": { "type": "string", "description": "Actor tag to consume into the city." }, "mode_ref": { "type": "string", "description": "params key selecting the founding-pop formula (start mode)." }, "cap_ref": { "type": "string", "description": "params key bounding the bonus founding pop." } } } } ] } } }