docs: add current developer feature index
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
# 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)
|
||||
Reference in New Issue
Block a user