feat: deliver emergent Jajce commitments
This commit is contained in:
+129
-120
@@ -2,154 +2,163 @@
|
||||
|
||||
## Purpose
|
||||
|
||||
Stable IDs and immutable definitions now form the vocabulary shared by
|
||||
simulation state, systems, world adapters, scenes, tests, and future save
|
||||
migrations.
|
||||
Stable IDs and immutable definitions form the vocabulary shared by simulation
|
||||
state, systems, world adapters, scenes, tests, and save migrations.
|
||||
|
||||
`SimulationIds` is the canonical source for code-facing `StringName` IDs.
|
||||
`ActionDefinition` and `ProfessionDefinition` are editor-readable custom
|
||||
resources. `SimulationDefinitions` loads, resolves, and validates the complete
|
||||
prototype set.
|
||||
`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.
|
||||
|
||||
## Current action contract
|
||||
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.
|
||||
|
||||
Each executable action definition contains:
|
||||
## Content-pack contract
|
||||
|
||||
- stable `action_id`;
|
||||
- display name;
|
||||
- default duration;
|
||||
- optional preferred profession ID;
|
||||
- target type: resource, activity, animal, or free movement;
|
||||
- resource action ID when the action targets a ResourceNode;
|
||||
- optional completion-cost resource ID and amount.
|
||||
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 stable state sentinels, not executable action
|
||||
definitions.
|
||||
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.
|
||||
|
||||
`defend` is the raid-response action: eligible strong villagers and guards
|
||||
prefer it during an active raid, travel to the guard post, and raise village
|
||||
safety while they work. Patrol activity sites accept it as a rally point.
|
||||
## Items, resources, and storage
|
||||
|
||||
SimNPC reads default duration and preferred-profession metadata from these
|
||||
definitions. WorldViewManager reads target type and resource-action metadata
|
||||
instead of maintaining a separate gather-action map. ActionSelectionSystem and
|
||||
SimulationManager share the same completion-cost metadata, so patrol and study
|
||||
both require one stored wood without duplicating that rule.
|
||||
`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.
|
||||
|
||||
`feed_animal` is the first animal-targeted action. Its definition prefers the
|
||||
farmer profession and declares an exact one-food completion cost. Selection,
|
||||
animal target reservation, supply pickup, and completion remain separate. NPC
|
||||
care pays that definition cost from carried inventory after a real pantry
|
||||
pickup; player care pays it directly from the pantry while player inventory is
|
||||
deferred. Both paths use `AnimalCareSystem` and mutate only the exact target.
|
||||
`SimulationIds` names Dunja and Zora, their private shelter anchors, and the
|
||||
shared pasture anchor. These IDs are saved routine vocabulary; their loaded
|
||||
positions and private/shared ownership come from `AnimalRoutineSite` rather
|
||||
than entering an action definition or resource registry.
|
||||
`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.
|
||||
|
||||
## Current profession 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.
|
||||
|
||||
Each profession definition contains a stable `profession_id`, display name,
|
||||
body color, and prop color. The current professions are farmer, woodcutter,
|
||||
guard, scholar, and wanderer.
|
||||
## Professions and capabilities
|
||||
|
||||
NPC generation chooses from the registry's stable IDs. NPC state stores and
|
||||
restores those IDs as `StringName`, and rejects records that reference an
|
||||
unknown profession or executable action.
|
||||
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.
|
||||
|
||||
## Opportunity vocabulary
|
||||
`CapabilityTagDefinition` gives actions and targets a validated shared
|
||||
vocabulary. Tags express composable affordances; they do not mutate state or
|
||||
replace concrete authority checks.
|
||||
|
||||
`SimulationIds` defines the four proven opportunity types,
|
||||
`restock_empty_pantry`, `supply_missing_wood`, `feed_weak_villager`, and
|
||||
`repair_home_roof`, plus the stable `open`, `resolved`, and `invalidated`
|
||||
statuses. Invalidation reasons currently distinguish `interested_died` from
|
||||
`evidence_stale`. These are serialized vocabulary, not editor-authored quest
|
||||
definitions. Dynamic trigger, interested NPC, storage/resource goal, progress,
|
||||
exact resolution-event identity, and close reason belong to
|
||||
`OpportunityStateRecord` and `VillageOpportunitySystem`.
|
||||
## Enemies and combat
|
||||
|
||||
The shared record and lifecycle collaborator was extracted only after the
|
||||
food and wood consumers proved those fields. Their evidence, care, resolution,
|
||||
and invalidation rules remain explicit branches. `feed_weak_villager` opens on
|
||||
a `villager_weak` fact when a starving low-energy villager cannot eat and
|
||||
resolves only when that same villager actually consumes food; `repair_home_roof`
|
||||
opens on a `home_damaged` fact when a villager sleeps through low safety and
|
||||
resolves through the real wood-deposit path. Do not add a generic quest-
|
||||
definition registry until real acceptance, assignment, reward, or dialogue
|
||||
consumers establish a second shared contract.
|
||||
`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.
|
||||
|
||||
## Player actor vocabulary
|
||||
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.
|
||||
|
||||
`SimulationIds.PLAYER_ACTOR_ID` (`-1`) is the stable event actor for
|
||||
player-performed actions, and `SimulationIds.PLAYER_INVENTORY_ID` names the
|
||||
carried-inventory holder in economic events. Player-performed pantry food
|
||||
supply is witnessed by nearby villagers and can raise their directed trust
|
||||
toward the player, with the player as a relationship subject.
|
||||
## Animals
|
||||
|
||||
## Item and weapon vocabulary
|
||||
`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.
|
||||
|
||||
`ItemDefinition` is the editor-readable resource contract for items, and
|
||||
`SimulationItems` is the current registry. Weapons carry `damage`, `reach`,
|
||||
and `attack_cooldown` and fill the `hand` equip slot, so the same contract can
|
||||
later host non-weapon items (food sacks, tools, armour) in a full inventory.
|
||||
The current weapons are `item_sword` (the player's equipped blade) and
|
||||
`item_claw` (wolf bites and unarmed defenders). NPC guards are equipped with
|
||||
swords; other villagers fight with claws, which feeds the village-defense
|
||||
derivation.
|
||||
## Situations and dialogue
|
||||
|
||||
## Conflict vocabulary
|
||||
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`.
|
||||
|
||||
`CombatantStateRecord` and `FactionStateRecord` use stable IDs. Combatant kinds
|
||||
are `npc`, `raider`, `wolf`, and `player`; NPC combatants reference their
|
||||
`SimNPC` by stable ID. Factions are `faction_village` and `faction_tribe`, with
|
||||
`neutral`/`hostile` stances and `none`/`planned`/`raiding`/`aborted` war plans.
|
||||
Combat, raid, and war narrative facts use the stable event types
|
||||
`combatant_hurt`, `combatant_killed`, `raid_started`, `war_resolved`,
|
||||
`war_aborted`, and `wolf_hunt`.
|
||||
`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.
|
||||
|
||||
## Enemy vocabulary
|
||||
## Validation and authoring report
|
||||
|
||||
`EnemyDefinition` is the data contract for hostile creatures and
|
||||
`SimulationEnemies` is the current registry. Each enemy carries a `kind`
|
||||
(raider/wolf), equipped weapon, health, move speed, body/accent colors, and a
|
||||
visual scale, so a new bear, bandit, or boar is mostly one definition plus a
|
||||
small `_build_*` visual hook on the shared `CreatureVisual` root. The current
|
||||
enemies are `enemy_raider` (sword) and `enemy_wolf` (claw).
|
||||
The catalog rejects:
|
||||
|
||||
## Validation
|
||||
|
||||
The registry rejects:
|
||||
|
||||
- missing or duplicate IDs;
|
||||
- empty display names;
|
||||
- non-positive action durations;
|
||||
- invalid target types;
|
||||
- resource actions without a resource-action ID;
|
||||
- incomplete, non-positive, or unknown completion-cost resources;
|
||||
- references to unknown professions or resource actions;
|
||||
- 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.
|
||||
|
||||
`tests/simulation_definitions_test.gd` verifies registry integrity,
|
||||
definition-backed behavior, unknown-ID rejection, and serialization
|
||||
round-tripping.
|
||||
`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 currently own identity and the static metadata already proven by
|
||||
the prototype, including the patrol/study completion-cost contract. They do not
|
||||
yet own:
|
||||
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.
|
||||
|
||||
- utility thresholds and consideration curves;
|
||||
- general preconditions beyond stored-resource completion costs;
|
||||
- completion effects;
|
||||
- interruption and failure policy;
|
||||
- reservation strategy;
|
||||
- detailed target-selection policy beyond current resource/activity/free
|
||||
metadata;
|
||||
- richer presentation hints beyond the current profession palette.
|
||||
|
||||
Selection, execution, target resolution, and visual travel are now separate
|
||||
responsibilities. The remaining concerns should move into definitions only
|
||||
when the action-system implementations prove a stable, reusable 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.
|
||||
|
||||
Reference in New Issue
Block a user