5.3 KiB
The Steward — Economic Event Stream
Current contract
Every successful food or wood movement creates an EconomicEventRecord using
the applicable event type:
resource_extracted
storage_deposited
storage_withdrawn
item_consumed
Each record contains a monotonically increasing event ID, event type,
simulation tick, actor ID, source ID, destination ID, item ID, and transferred
amount, plus the authoritative world position captured when the fact is
recorded. NPC events preserve their authoritative interaction target (or NPC
position when no target applies); player extraction/depletion events preserve
the ResourceNode interaction position. Actor -1 identifies a player-triggered
extraction until persistent player identity is introduced.
Events are immutable facts about completed transfers. They do not perform the transaction and are not replayed to reconstruct current state. Resource, inventory, and storage records remain authoritative.
SimulationEventLog owns ordered event identity, append/restore behavior, and
history/rate queries, including exact lookup through get_by_id().
VillageEconomy performs transactions and requests event records only after
state changes succeed; SimulationManager remains the public signal boundary
used by presentation.
An action whose definition-backed completion cost becomes unavailable records
a zero-amount task_blocked narrative fact with the action and shortfall
reason. This makes late contention inspectable without pretending that a
transfer occurred.
Persistence and determinism
SimulationStateRecord schema v7 stores the ordered event stream,
next_event_id, directed relationships that may reference an exact event, and
per-NPC known-event references with first-acquisition provenance. Schema v1 and
v2 saves migrate to an empty stream beginning at ID zero. Parsing rejects
duplicate event IDs, invalid or duplicate knowledge references, impossible
communicator sources, relationship causes the observer does not know, and a
next ID that could collide with restored history.
A successful food deposit can currently raise a hungry familiar NPC's directed
trust in its contributor only when that NPC knows the event. The actor and
living NPCs within the bounded witness radius receive a KnownEventStateRecord
at record time. Witness distance uses the event's captured position, never the
actor's later location. The relationship stores the same deposit event ID
rather than copied prose, so the inspector can resolve and display the real
completed fact. This is a first evidence-gated causal consumer of the event
stream, not general event sourcing.
Knowledge now records whether an NPC performed, witnessed, heard, or inherited a fact from a legacy save. When an NPC arrives beside an already-working NPC at the same non-storage activity site, the worker may communicate one newest direct fact within 2.5 metres. The listener references the same immutable event and retains the speaker ID; no transaction or event is replayed. Only performed/witnessed facts can cross this one social hop, so this is not yet a rumour cascade. Relationship appraisal uses the listener's state when the fact is acquired, not a reconstruction of their needs when the old event occurred.
Known facts are now bounded without deleting objective history. A fact is
lasting while it remains that NPC's current trust cause; other facts are recent.
An NPC keeps at most three recent facts, and a deterministic review once per
simulated-day-sized interval removes recent facts at least one day old. Current
causes remain so Relationship and Because never point at forgotten
evidence. Conversations prefer lasting direct facts, then the most recently
acquired direct fact. Communicated provenance snapshots how the speaker knew
the event, so a listener's memory stays valid after the speaker forgets.
The food-loop regression verifies this chain:
bush -> NPC inventory -> village pantry -> NPC inventory -> consumed
It checks event order, stable IDs, exact quantities, conservation, and save/restore continuity.
Presentation
npc_inventory_changed is a transient presentation signal. The active
NpcVisual shows a small food sack whenever its authoritative inventory
contains food. A newly loaded visual derives the same state directly from the
NPC record, so unloading presentation does not lose the fact.
The selected-NPC inspector shows up to four lasting-first retained facts with
acquisition provenance, separately from three objective events the NPC
personally performed. A real trust-changing consequence emits one transient
amber blossom above its observer. The cue is presentation-only, remains visible
in cinematic mode, and is neither saved nor replayed after visual rebuild.
Deliberate limits
The objective stream is currently kept in full for the small simulation garden; only per-NPC known references are bounded. Before large populations or long-running worlds, add measured archival/summary rules and query indexes. Proximity is the only current direct witness rule, and communication is intentionally one-hop and tied to shared activity arrival. Line of sight, hearing, personalized reinforcement/decay, multi-hop rumours, secrecy, false beliefs, and multi-event causal graphs belong in later event/history slices. They should extend this record family without making prose authoritative or recomputing old evidence from current positions.