Files
gamedev-the-steward/docs/SIMULATION_DEFINITIONS.md
T
2026-08-12 21:15:58 +02:00

165 lines
7.7 KiB
Markdown

# The Steward — Simulation Definitions
## Purpose
Stable IDs and immutable definitions form the vocabulary shared by simulation
state, systems, world adapters, scenes, tests, and save migrations.
`SimulationIds` remains the append-only source for code-facing compatibility
IDs. `SimulationContentPack` is the no-code authoring manifest and
`ContentCatalog` transactionally validates and publishes typed definitions in
stable-ID order. The current core pack contains actions, professions,
capability tags, items, resources, storage policies, and enemies. A failed pack
publishes nothing: duplicate IDs, unknown references, unsupported handlers, or
missing presentation cues are authoring errors rather than silent overrides.
Simulation code resolves definitions through the catalog. Presentation cue IDs
remain headless strings and are mapped separately to scenes, materials, icons,
or animation hooks. Runtime quantities and ownership stay in state records;
saves do not contain `.tres` paths or copied definition balance.
## Content-pack contract
Each pack has a stable `pack_id`, display name, explicit pack dependencies,
required handler IDs, and typed definition arrays. Pack and definition IDs are
unique across the whole catalog. Packs cannot override each other in the first
version, and enumeration is sorted independently of resource load order.
Adding data-only content is:
1. create a typed `.tres` definition;
2. add it to an explicit pack;
3. optionally register its stable presentation cue in the presentation layer;
4. place or spawn an instance with its own canonical runtime ID.
Adding a fundamentally new mechanic still requires one bounded reusable
handler. The pack declares that dependency so missing runtime support fails
validation rather than becoming a partially functioning object.
## Action contract
Each executable `ActionDefinition` contains:
- stable action ID and display name;
- duration and optional preferred profession;
- target family and resource-action metadata;
- optional completion cost;
- actor and target capability tags;
- selection, target, and completion handler IDs;
- reusable typed effects;
- event and presentation cue IDs.
Reusable `ActionEffect` definitions cover metric/need change, exact inventory
transfer, damage/healing, relationship-dimension change, scheduling an ordinary
action, and site-condition change. `ActionCommand` carries stable actor/action/
target/item IDs, amount, and expected revision; `ActionOffer` and `ActionResult`
are copy-only values. `ActionCommandService` is the authority boundary and must
revalidate range, capabilities, reservation, permission, cost, and target state
at execution time for either a player or NPC caller.
The current actions are gather food, gather wood, feed animal, deposit food,
deposit wood, withdraw food, patrol, study, eat, rest, sleep, wander, and
defend. Idle and dead are state sentinels, not executable definitions. The
two-leg animal-feeding transaction remains a custom completion handler because
it has a real compound pickup/delivery contract and no second shared consumer
yet.
## Items, resources, and storage
`ItemDefinition` validates fields by category. Weapons require damage, reach,
cooldown, and an equip slot; materials and consumables do not carry fake weapon
fields. The core pack contains food, wood, herb, sword, and claw. Herb proves a
new non-weapon item and route without a manager branch.
`ResourceDefinition` owns yielded item, gather action, capability tags, base
capacity/yield/regrowth, access policy, and presentation cue. Placement/state
records retain unique contextual IDs and overrides such as safety risk,
comfort, and discovery priority. Berry patches, trees, and herb patches share
this contract.
`StorageDefinition` declares accepted item IDs/tags, policy priority, capacity,
settlement scope, deposit/withdraw actions, and presentation cue.
`StorageRoutingPolicy` ranks compatible destinations deterministically by
priority then stable target ID. Food-to-pantry and wood-to-woodpile remain
covered; herb-to-apothecary proves data-only routing beyond those legacy cases.
## Professions and capabilities
Each `ProfessionDefinition` contains a stable ID, display name, body color, and
prop color. Farmer, woodcutter, guard, scholar, and wanderer are registered in
the core pack. NPC state saves only the ID and rejects unknown definitions.
`CapabilityTagDefinition` gives actions and targets a validated shared
vocabulary. Tags express composable affordances; they do not mutate state or
replace concrete authority checks.
## Enemies and combat
`EnemyDefinition` carries a behavior profile, combatant ID prefix, faction,
hostility, weapon, health, movement, and visual parameters.
`CombatantFactory` creates/restores every hostile and rebuilds collision-free
per-prefix allocators. The core boar reuses the wolf-hunt behavior without a
new manager or combat switch; raider and wolf compatibility spawn APIs delegate
to the same factory.
Combatant and faction state use stable IDs. NPC combatants point to their
person ID; hostile records persist `enemy_definition_id`. Weapons resolve
through the same item catalog used by inventory rather than a parallel combat
item table.
## Animals
`AnimalDefinition` + `AnimalCatalog` + `AnimalFactory` apply the same
definition-instance-state-presentation contract to domestic animals. Goat and
sheep reuse the `grazer_routine`, feeding capability, generic CozyGrazer scene,
state migration, and care system; definition and visual parameters are the only
type-specific pieces. The animal catalog remains isolated until the next
shared content-pack migration adds that record family without destabilizing
the already validated core pack.
## Situations and dialogue
Legacy `OpportunityStateRecord` vocabulary remains for save compatibility.
New emergent content uses typed `SituationDefinition` resources: reusable
predicates, evidence requirements, dedupe fields, priority/severity,
alternative objectives, exact ordinary resolution patterns, expiry/cooldown,
and dialogue topic IDs. Situation state saves the definition ID and causal
facts; progress is re-derived from authoritative state and `WorldEventStore`.
`DialogueIntentDefinition` owns semantic preconditions, score, response intent
IDs, template variants, and optional action metadata. Stable hashing selects a
variant from conversation/turn/intent/topics without consuming shared RNG.
Rendered prose and Dialogue Manager resources are presentation and never
authoritative state.
## Validation and authoring report
The catalog rejects:
- missing, empty, or duplicate pack/definition IDs;
- silent cross-pack overrides;
- unknown pack, handler, capability, item, profession, action, storage,
behavior-profile, or presentation-cue references;
- category-invalid item fields;
- incomplete or non-positive costs/effects;
- resources or storage routes with inconsistent item/action contracts;
- definition resources that fail to load.
`ContentCatalog.get_authoring_report()` exposes validity, sorted published IDs,
and exact errors for CLI/editor tooling. Tests prove transactional failure,
deterministic enumeration, core cross-references, boar behavior reuse, shared
goat/sheep behavior, and herb routing.
## Deliberate boundary
Definitions own reusable static metadata, not mutable inventory, reservations,
relationships, situation progress, entity ownership, or presentation nodes.
Handler implementations remain bounded typed strategies. A universal
reflection DSL, arbitrary scripts embedded in saves, and a full ECS are outside
the contract.
Selection, execution, target resolution, simulation authority, and visual
travel remain separate responsibilities. Extend definitions only after a real
consumer proves a stable shared field; extend a handler when the mechanic itself
is genuinely new.