Files
gamedev-the-steward/docs/FEATURE_EVENTS_KNOWLEDGE_SITUATIONS_DIALOGUE.md
T
2026-08-13 00:26:55 +02:00

174 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Feature slice: events, memory, situations, quests, and dialogue
This is the emergent narrative pipeline. It turns real world mutations into
evidence, social meaning, unresolved situations, commitments, and semantic
conversation options without creating a parallel scripted world.
## One causal chain
```text
authoritative mutation
-> WorldEventRecord / EconomicEventRecord
-> indexed WorldEventStore + compatibility SimulationEventLog
-> performed/witnessed knowledge with provenance
-> relationship dimensions with exact causal event IDs
-> SituationSystem evaluates unresolved predicates
-> QuestJournalSystem exposes discovery/tracking metadata
-> SocialCommitmentSystem records promises and outcomes
-> ConversationService plans semantic intents/topics/options
-> Dialogue Manager presenter renders one derived turn
```
The event is the shared join key. A quest, journal entry, relationship, or
dialogue line may reference it, but none of those layers may invent an item,
resource, damage result, enemy, or reward.
## World facts
`WorldEntityRef` identifies an actor/participant by typed stable ID.
`SpatialAddress` identifies `(world_id, location_id, local_position)` and keeps
coincident local coordinates from crossing contexts. `WorldEventRecord` stores
event ID/type/tick, participants, optional location, and JSON-safe payload.
`WorldEventStore` provides O(1) ID lookup plus deterministic indexes by type,
participant, location, exact tick, and tick range.
`SimulationEventLog` remains the local Jajce compatibility façade. It records
economic and activity facts, enforces the configured world/location scope, and
refuses to reinterpret retained events under a different active context.
`ActivityEventValidator` validates definition-backed success and blocked
facts, including legacy markers. Older unstructured blocked facts remain
loadable only with explicit migration provenance and cannot become new
knowable evidence.
## Knowledge and relationships
`EventKnowledgeSystem` stores a bounded `(knower, event)` record, not copied
prose. Each memory carries acquisition method, source actor, hop count,
confidence, salience, pinning, and acquisition tick. Direct actor/witness
observation happens when the event is recorded; restore never recomputes old
witnesses from current positions. Communication is one hop from a performed or
witnessed fact, and the player is a valid knower/source sentinel.
Ordinary recent memories are bounded to three per knower; pinned causal facts
and facts referenced by situations/commitments are protected. The retention
system changes memory references only; it never deletes objective event facts.
`RelationshipSystem` stores sparse directed edges. The seven dimensions are
familiarity, trust, affection, respect, fear, obligation, and hostility. Each
non-neutral dimension can retain its exact causal event ID. Consequences are
bounded and replay-safe: for example, food aid can increase a hungry familiar
villager's trust toward the actor, while commitment lifecycle consequences
adjust obligation/trust/hostility by commitment and outcome identity.
## Situations and journal entries
`SituationDefinition` declares triggering predicates, interested-party and
participant context, dedupe fields, severity/priority, alternatives, valid
resolution patterns, expiry/invalidation rules, topics, and commitment terms.
`SituationSystem` evaluates definitions in deterministic order, caps the
initial Jajce slice at three active situations, deduplicates by configured
context, and stores only a `SituationStateRecord` with exact trigger and
resolution event IDs. Progress is derived live from current state and ordinary
events.
`QuestJournalSystem` stores `QuestJournalEntryStateRecord`: situation ID,
discovery tick, selected alternative, tracking preference, and close/archive
state. It never copies objectives or progress. The journal remains empty until
the player acquires knowledge of the situation through an ordinary path.
The current authored pantry shortage is in
`simulation/situations/resources/pantry_shortage.tres`. Four legacy local
opportunity types are retained as a compatibility family in
`VillageOpportunitySystem`; the generic situation system is the direction for
new content. Roof repair remains disabled until authoritative home-condition
state exists.
## Commitments
`SocialCommitmentSystem` creates a `CommitmentStateRecord` when a social promise
is accepted. It stores debtor/creditor refs, situation, terms, deadline, status,
and exact acceptance/outcome event IDs. Acceptance does not reserve stock or
prevent another actor from resolving the situation.
`CommitmentLifecycleService` records accepted, fulfilled, broken, released, and
superseded facts and applies relationship consequences idempotently. A matching
outcome performed by the debtor fulfills; an outcome performed by another actor
supersedes without penalty. A still-achievable deadline reached at or after its
due tick breaks the promise. Release and external impossibility are explicit
outcomes. Untracking a journal entry is not cancellation.
## Deterministic conversations
`ConversationService` owns transient conversation records and semantic turns:
- `begin(speaker, listener, context)` validates typed participants and context;
- `get_turn(conversation_id)` returns a copied current turn;
- `select_option(conversation_id, option_id, expected_revision)` revalidates
the revision and recomputes the next turn/action;
- `end()` or `invalidate()` closes the transient session.
The planner reads current relationship dimensions/causes, knowledge, performed
and witnessed history, task/need/profession/role, known situations,
commitments, and retained conversation acts. Intent definitions provide
preconditions, deterministic scoring, response intents, cooldowns, and optional
authoritative actions. Current Jajce intents include greeting, work/wellbeing,
what happened, sharing a fact, describing a need, offering help, commitment
accept/decline/renegotiation, progress, thanks/reproach, supersession, and
goodbye.
Only `ConversationActStateRecord` is persisted: typed speaker/listener refs,
intent ID, topic IDs, tick, and a bounded history. Conversation IDs, revision,
options, rendered text, and balloon state are transient.
## Dialogue Manager boundary
The project vendors Dialogue Manager v3.10.4 under `addons/dialogue_manager`
with provenance/checksum and MIT license in `addons/dialogue_manager/UPSTREAM.md`.
`DialogueManagerConversationPresenter` receives one planned `ConversationTurn`,
selects a stable template variant, escapes dynamic names/topics, and creates an
ephemeral resource. It does not execute game mutations, conditions, or
authority shortcuts. Controlled option tags map back to stable option IDs and
the presented revision.
`DialogueModeController` owns the loaded player mode: nearest-NPC Talk has
priority, movement/combat/ordinary interaction lock while open, simulation
speed is normalized to 1×, stale option selections refresh safely, and the
mode closes if the speaker dies, unloads, or leaves range. The fake presenter
tests keep domain tests renderer-independent; parser and mapping tests cover
the vendored plugin.
## Vertical slice and extension recipe
The complete Jajce proof is in `tests/emergent_jajce_slice_test.gd` and
`tests/conversation_domain_test.gd`:
1. exact pantry shortage evidence opens a situation;
2. an NPC knows it while the player does not;
3. speaking transfers knowledge and discovers the journal entry;
4. generated options reflect hunger, relationship, evidence, and need;
5. accepting creates a commitment without reserving stock;
6. ordinary food gather/deposit resolves the real shortage;
7. the commitment fulfills or, in variants, breaks/supersedes;
8. later conversation references the actual outcome;
9. save/reload preserves semantic history and deterministic options.
To add a new emergent story, author an event type and situation definition,
ensure the authoritative action emits the event, add any social consequence or
dialogue intent/template, and test the complete causal chain. Do not begin with
a quest-only enemy/item or a dialogue graph that mutates state behind the
simulation.
## Reference tests and deeper contracts
- `tests/unit/test_world_event_store.gd`
- `tests/unit/test_social_foundations.gd`
- `tests/unit/test_situation_system.gd`
- `tests/unit/test_commitment_lifecycle_service.gd`
- `tests/conversation_domain_test.gd`
- `tests/dialogue_manager_conversation_presenter_test.gd`
- `tests/dialogue_mode_controller_test.gd`
- `tests/emergent_jajce_slice_test.gd`
- [Economic event stream](ECONOMIC_EVENTS.md)
- [Simulation state schema](SIMULATION_STATE_SCHEMA.md)
- [ADR 0002](decisions/0002-emergent-world-content-and-narrative.md)