feat: add missing wood opportunities

This commit is contained in:
Rijad Zuzo
2026-07-16 01:50:19 +02:00
parent f82d9683de
commit 79dd503343
26 changed files with 1054 additions and 175 deletions
+5 -5
View File
@@ -17,7 +17,7 @@ SimulationClock
-> SimulationEventLog records completed facts
-> EventKnowledgeSystem records, ranks, transfers, and retains bounded knowledge
-> RelationshipSystem applies evidence-gated social consequences
-> FoodShortageOpportunitySystem projects one known unresolved need
-> VillageOpportunitySystem projects one known unresolved need
-> WorldViewManager presents travel, NPC state, and world-state cues
-> ActiveWorldAdapter supplies loaded-world positions/capacity
-> NpcVisual performs local navigation, animation, and transient reactions
@@ -40,10 +40,10 @@ would otherwise obscure that lifecycle:
retention/importance ranking;
- `simulation/relationships/RelationshipSystem.gd` owns directed relationship
queries, event-driven trust changes, and deterministic social tie-breaking;
- `simulation/opportunities/FoodShortageOpportunitySystem.gd` observes
immutable event references plus current pantry/NPC state, then owns the
bounded open/resolved pantry-restock lifecycle without changing resources or
assigning tasks;
- `simulation/opportunities/VillageOpportunitySystem.gd` observes immutable
event references plus current NPC/storage state, then owns the bounded shared
open/resolved/invalidated lifecycle for the proven pantry-food and blocked-
work wood consumers without changing resources or assigning tasks;
- `simulation/persistence/` owns save-slot file safety;
- `simulation/state/` owns versioned serialized record contracts;
- `simulation/definitions/` owns stable IDs and immutable action/profession
+9 -4
View File
@@ -726,13 +726,18 @@ Completed:
concern cue; a real deposit clears it and briefly animates the refilled
pantry. The capture tool writes an edit-ready empty/restocked close pair
while leaving gameplay camera defaults and simulation authority unchanged.
27. Missing-wood village need: a real patrol/study shortfall now opens one
wood-specific need from its structured `task_blocked` fact. NPC deposit and
player tree-harvest resolutions use real economy history; interested-party
death and one-day staleness close the need cleanly. The compact UI explains
the blocked action without reusing the pantry's hunger cue.
Next:
1. Resume the second bounded opportunity proof from a real missing-wood
`task_blocked` fact. Include deterministic interested-party death/staleness
handling before extracting shared opportunity machinery, as sequenced in
`LEARNING_ROADMAP.md`.
1. Add the first read-only capable-helper query for an open need. Expose one
deterministic viable villager and the real knowledge, relationship, action,
inventory, and resource facts behind that result before allowing it to
affect autonomous selection, as sequenced in `LEARNING_ROADMAP.md`.
Do not start with GIS data, a full city, a large asset pack, or more NPC
mechanics. The next proof is a beautiful stage for the systems that already
+32 -21
View File
@@ -31,25 +31,28 @@ 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
a zero-amount `task_blocked` narrative fact with stable action, source storage,
resource, and required-amount fields plus the readable shortfall reason. This
makes late contention queryable and inspectable without pretending that a
transfer occurred.
## Persistence and determinism
`SimulationStateRecord` schema v8 stores the ordered event stream,
`SimulationStateRecord` schema v9 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, plus
opportunity records that reference exact trigger/resolution events. Schema v1
and v2 saves migrate to an empty stream beginning at ID zero; world schemas
v1v7 migrate to an empty opportunity list. Parsing rejects duplicate event
v1v7 migrate to an empty opportunity list, while world schema v8 preserves and
normalizes its pantry opportunity history. Parsing rejects duplicate event
IDs, invalid or duplicate knowledge/opportunity references, impossible
communicator sources, relationship causes the observer does not know, and next
IDs that could collide with restored history.
Positive food deposits and positive NPC food withdrawals from
`village_pantry` into that actor's matching inventory are currently knowable.
The actor and living NPCs within the bounded witness radius receive a
Positive food deposits, positive NPC food withdrawals from `village_pantry`
into that actor's matching inventory, and definition-backed patrol/study
`task_blocked` facts caused by missing wood at `village_woodpile` are currently
knowable. 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. A successful food deposit
can raise a hungry familiar witness's directed trust; the relationship stores
@@ -75,19 +78,25 @@ 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.
`FoodShortageOpportunitySystem` is another read-only consumer of immutable
facts. A known positive NPC pantry withdrawal, combined with the pantry
currently being empty and a living critically hungry knower, can open one
`restock_empty_pantry` record. The opportunity does not perform a transaction,
assign an NPC, or append a quest-only event. It resolves only after the pantry
actually reaches its target through either:
`VillageOpportunitySystem` is another read-only consumer of immutable facts.
A known positive NPC pantry withdrawal, combined with the pantry currently
being empty and a living critically hungry knower, can open one
`restock_empty_pantry` record. A known missing-wood `task_blocked` fact can open
one `supply_missing_wood` record for its living performer. At most one need is
open globally. The system does not perform a transaction, assign an NPC, or
append a quest-only event. A need resolves only after its target storage
actually reaches the one-unit target through either:
- a later positive `storage_deposited` event from a real NPC inventory; or
- a later player `resource_extracted` event from an existing player-usable food
ResourceNode directly into `village_pantry`.
- a later matching positive `storage_deposited` event from a real NPC
inventory; or
- a later player `resource_extracted` event from an existing player-usable
matching ResourceNode directly into the target storage.
The exact trigger and resolution IDs remain in opportunity history. The active
trigger memory is protected until resolution, then returns to normal bounded
trigger memory is protected until closure. A wood need is invalidated if its
interested performer dies or if it is still unresolved one simulated day after
opening; invalidation emits no event and stores the close tick and stable
reason. Resolution or invalidation returns the trigger to normal bounded
retention.
The food-loop regression verifies this chain:
@@ -110,9 +119,11 @@ 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.
The village summary also shows one compact active need with its real food
The village summary also shows one compact active need with its real target
progress and interested villager; only that villager's inspector retains its
open/resolved detail and names the exact supplier.
open/closed detail and names the exact supplier for a resolution. The empty-bowl
world cue remains specific to the pantry shortage rather than representing a
wood need as hunger.
## Deliberate limits
@@ -125,5 +136,5 @@ 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.
The current opportunity is likewise a single bounded projection, not a generic
quest, reward, acceptance, dialogue, or capable-helper framework.
The current opportunity family is likewise a bounded two-consumer projection,
not a generic quest, reward, acceptance, dialogue, or capable-helper framework.
+25 -6
View File
@@ -757,11 +757,29 @@ The outcome-defined pantry-crisis demo loop is complete:
replacing state-driven world cues, while a runtime validator measures the
unassisted route and a headless scenario verifies its full event chain.
Milestone 7 is not complete. The immediate next slice is the second bounded
unresolved-condition consumer from a real missing-wood `task_blocked` fact,
including deterministic interested-party death/staleness handling. Extract
shared opportunity machinery only after that second consumer proves the common
contract.
The second bounded Milestone 7 consumer is complete:
- patrol or study that loses its definition-backed wood cost at completion
records one zero-transfer `task_blocked` fact with stable action, woodpile,
wood, and required-amount fields, without applying the work effect;
- the performer and nearby witnesses retain that objective fact, and the
performer becomes the interested party for one `supply_missing_wood` need;
- a real later NPC wood deposit or player tree extraction into the woodpile
resolves the record through its exact existing event;
- interested-party death or evidence that remains unresolved for one simulated
day invalidates the need deterministically, emits no quest-only fact, and
releases the protected trigger memory;
- world schema v9, nested opportunity schema v2, wood-specific UI text, and
focused headless/runtime regressions preserve the full open, resolved, and
invalidated lifecycle;
- the two proven consumers now share `VillageOpportunitySystem` and the common
lifecycle fields, while their evidence and care rules remain explicit.
Milestone 7 is not complete. The immediate next slice is a bounded
capable-helper query for an open need: derive one viable helper from existing
knowledge, relationship, action, inventory, and resource facts and expose the
reason for that result. Keep it read-only first; only a later proven slice
should let opportunity awareness influence autonomous task selection.
Recently completed:
@@ -819,7 +837,8 @@ Recently completed:
- Action completion costs are definition-backed: patrol and study share one
stored-resource contract across selection and execution. The inspector shows
readable unavailable reasons, and a late shortfall creates a persisted
`task_blocked` fact without applying the work effect.
`task_blocked` fact with stable action/resource/requirement fields without
applying the work effect.
- Structured event feed: EconomicEventRecord now supports narrative events
(task started, NPC slept, NPC died) alongside economic transfers.
Per-NPC event history with human-readable descriptions exposed in the
+28 -16
View File
@@ -427,9 +427,9 @@ Focused `RefCounted` collaborators keep rule ownership visible:
importance ranking for presentation/communication queries;
- `RelationshipSystem` owns directed relationship state, event-driven trust
consequences, and deterministic social queries;
- `FoodShortageOpportunitySystem` projects the first knowledge-gated unresolved
condition into a persisted open/resolved record without changing resources
or assigning work.
- `VillageOpportunitySystem` projects the proven pantry-food and blocked-work
wood conditions into persisted open/resolved/invalidated records without
changing resources or assigning work.
`SimulationManager` remains the scene-tree façade and signal boundary rather
than duplicating these responsibilities across additional manager nodes.
@@ -505,7 +505,7 @@ NpcVisual navigates through the active world
| -> SimulationEventLog appends completed facts
| -> EventKnowledgeSystem captures actor/nearby knowledge
| -> RelationshipSystem applies evidence-gated social consequences
| -> FoodShortageOpportunitySystem may open or resolve a real need
| -> VillageOpportunitySystem may open, resolve, or invalidate a real need
| |
| v
| village_changed signal updates the UI
@@ -560,7 +560,8 @@ NpcVisual navigates through the active world
│ ├── resource_node_player_parity_test.gd
│ ├── simulation_definitions_test.gd
│ ├── simulation_state_serialization_test.gd
│ ├── unit/test_food_shortage_opportunity_system.gd
│ ├── unit/test_village_opportunity_system.gd
│ ├── wood_shortage_opportunity_test.gd
│ └── witnessed_knowledge_consequence_test.gd
├── terrain/jajce/ Dedicated Terrain3D seed data and assets
├── tools/
@@ -593,7 +594,7 @@ These are expected prototype constraints, not necessarily isolated bugs:
gathering use `ResourceNode` instances with no fallback, food transfer uses
the typed pantry `StorageNode`, and patrol/study/rest use `ActivitySite`.
- Current NPC, village, resource, storage, event, knowledge, relationship,
opportunity, clock, and RNG state serialize through world schema v8. F5/F9
opportunity, clock, and RNG state serialize through world schema v9. F5/F9
provide one validated local quicksave; a save menu, metadata, and
player-transform persistence remain deferred.
- Simulation-owned resource records retain live amounts, reservations, and
@@ -608,15 +609,17 @@ These are expected prototype constraints, not necessarily isolated bugs:
located items.
- NPCs have home positions, schedule periods, carried food/wood, and directed
familiarity/trust. They retain direct or one-hop communicated knowledge of a
food deposit or NPC pantry withdrawal with first-acquisition provenance.
food deposit or NPC pantry withdrawal, plus direct missing-wood blocked-work
facts, with first-acquisition provenance.
Current trust causes and the trigger of an open opportunity are lasting;
other knowledge is capped and reviewed after one simulated day. NPCs do not
yet have wider social dimensions, goals, line-of-sight/hearing evidence,
personalized reinforcement/decay, false beliefs, or multi-hop rumours.
- One persisted `restock_empty_pantry` opportunity can emerge from a known
withdrawal plus current emptiness and critical hunger. It has exact NPC and
player supply resolutions, but no generic opportunity definitions, capable-
helper assignment, acceptance, rewards, free-form dialogue, or quest log.
- The bounded opportunity family supports one open `restock_empty_pantry` or
`supply_missing_wood` need from exact known evidence. Both have exact NPC and
player supply resolutions; the wood need also closes deterministically on
interested-party death or one-day staleness. There is still no capable-helper
assignment, acceptance, rewards, free-form dialogue, or quest log.
- The reason inspector exposes current decisions, utility rejections, one exact
relationship cause, and a compact person-history view that distinguishes
importance-ranked retained memories from objective personal actions.
@@ -872,7 +875,7 @@ produce a short observer-only amber blossom without altering saved state.
The first bounded opportunity proof is complete. A positive NPC pantry
withdrawal plus current pantry emptiness opens one need only for a critically
hungry villager who knows that exact event. The schema-v8 record persists its
hungry villager who knows that exact event. The persisted record retains its
stable trigger, interested villager, pantry/food target, status, and later
resolution event; active evidence remains lasting. A real later NPC deposit or
player harvest into the pantry resolves it without quest-only history, economy
@@ -890,10 +893,19 @@ finite berry source, visibly carries its yield, deposits it, and causes the
physical recovery. A headless lifecycle scenario and an unassisted runtime
timing validator cover the complete path.
Milestone 7 remains in progress. The immediate next slice is the second
missing-wood consumer from a real `task_blocked` fact, including deterministic
interested-party death/staleness handling before common opportunity machinery
is extracted.
The second bounded opportunity proof is complete. Patrol or study that cannot
pay its wood cost records a stable zero-transfer `task_blocked` fact and opens
one `supply_missing_wood` need for its performer. A real NPC wood deposit or
player tree harvest resolves it; interested-party death or one simulated day
of unresolved evidence invalidates it without quest-only history. World schema
v9 and nested opportunity schema v2 preserve open, resolved, and invalidated
history. The two consumers now share `VillageOpportunitySystem`, while their
evidence and care rules remain explicit.
Milestone 7 remains in progress. The immediate next slice is a read-only,
deterministic capable-helper query for an open need, derived from existing
knowledge, relationship, action, inventory, and resource facts before it is
allowed to influence autonomous task selection.
The remaining simulation-garden target still aims for:
+13 -8
View File
@@ -45,15 +45,20 @@ unknown profession or executable action.
## Opportunity vocabulary
`SimulationIds` also defines the first proven opportunity type,
`restock_empty_pantry`, and its `open`/`resolved` statuses. These are stable
serialized vocabulary, not editor-authored quest definitions. Dynamic trigger,
interested NPC, pantry/food goal, progress, and exact resolution-event identity
belong to `OpportunityStateRecord` and the focused opportunity system.
`SimulationIds` defines the two proven opportunity types,
`restock_empty_pantry` and `supply_missing_wood`, 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`.
Do not extract a generic quest-definition registry until another real
unresolved-condition consumer proves which lifecycle fields and rules are
actually shared.
The shared record and lifecycle collaborator were extracted only after the
food and wood consumers proved those fields. Their evidence, care, resolution,
and invalidation rules remain explicit branches. Do not add a generic quest-
definition registry until real acceptance, assignment, reward, or dialogue
consumers establish a second shared contract.
## Validation
+39 -18
View File
@@ -3,7 +3,7 @@
## Current contract
`SimulationStateRecord` is the versioned JSON boundary for the current
simulation. The current world schema is v8 and captures:
simulation. The current world schema is v9 and captures:
- simulation seed, tick interval, tick count, clock remainder, and elapsed
clock ticks;
@@ -21,14 +21,15 @@ simulation. The current world schema is v8 and captures:
copying it, including first-acquisition method, acquisition tick, and
historical communicator provenance;
- opportunity records with stable type/status, interested NPC, trigger event,
target storage/resource/amount, and exact later resolution event identity.
target storage/resource/amount, exact later resolution event identity, or a
deterministic invalidation reason and close tick.
The top-level identity is:
```json
{
"schema": "the_steward.simulation",
"schema_version": 8
"schema_version": 9
}
```
@@ -61,8 +62,9 @@ It also verifies clock remainder, resource amount/reservation/enabled
round-tripping, presentation unload/rebind, directed relationship/cause
round-tripping, divergent known-event state, communicated provenance, and
deterministic retention boundaries, and rejection of unsupported schemas.
Active and resolved opportunity round-tripping, contradictory target state,
invalid resource sources, and cross-record event references are covered too.
Active, resolved, and invalidated opportunity round-tripping, contradictory
target state, invalid resource sources, and cross-record event references are
covered too.
NPCStateRecord v2 adds the resolved travel destination and whether it is
active. Nested v1 NPC records migrate explicitly with no invented active
@@ -158,22 +160,41 @@ schema stores `opportunity_id`, `opportunity_type`, `status`, `created_tick`,
`target_amount`, `resolution_event_id`, and `resolved_tick`. World schemas
v1v7 migrate explicitly to an empty opportunity list with next ID zero.
The bounded `restock_empty_pantry` contract accepts at most one open record.
SimulationStateRecord v9 preserves world-v8 opportunity history and upgrades
the nested record to `OpportunityStateRecord` v2. The nested schema adds
`closed_tick` and `invalidation_reason`, accepts `supply_missing_wood`, and adds
the stable `invalidated` status. Nested opportunity v1 records normalize their
resolved tick into the close tick and remain valid pantry history. Economic
event schema v3 adds normalized `action_id` and `required_amount` fields;
nested v1/v2 events receive empty/zero defaults, while a new `task_blocked`
event requires its stable action, source storage, resource, and positive
requirement contract.
The bounded opportunity family accepts at most one open record globally.
Opportunity, trigger-event, and resolution-event IDs are unique and the next
ID must remain above restored history. The interested NPC, pantry, food
resource, and referenced events must exist. Its trigger is a positive NPC food
ID must remain above restored history. Referenced NPCs, storage, resources, and
events must exist. A `restock_empty_pantry` trigger is a positive NPC food
withdrawal from `village_pantry` to that actor's matching inventory; an open
record additionally requires the pantry to remain below its one-food target
and the interested NPC to have acquired that fact no later than creation.
Resolution references an exact later NPC inventory-to-pantry food deposit or a
player `resource_extracted` event from an existing player-usable food resource
into the pantry, with a matching resolved tick. Resolved history does not
require the pantry still to contain food because later consumption is valid.
and its interested NPC to have acquired that fact no later than creation. A
`supply_missing_wood` trigger is the performer's known patrol or study
`task_blocked` fact against `village_woodpile` with a one-wood requirement; an
open record additionally requires a living interested performer and the
woodpile below target.
While the need is open, its interested villager's trigger evidence is treated
as lasting during deterministic memory maintenance. Resolution releases that
fact back to the normal bounded-retention rules; it does not delete objective
event or opportunity history.
Resolution references an exact later matching NPC inventory-to-storage deposit
or player `resource_extracted` event from an existing player-usable matching
resource into the target storage, with matching resolved and closed ticks.
Resolved history does not require the storage still to contain the resource
because later use is valid. Invalidation has no resolution event and requires a
stable close tick and is currently valid only for `supply_missing_wood`.
`interested_died` must agree with the restored NPC's death state; the runtime
creates `evidence_stale` at the one-day unresolved boundary.
While a need is open, its interested villager's trigger evidence is treated as
lasting during deterministic memory maintenance. Resolution or invalidation
releases that fact back to the normal bounded-retention rules; neither deletes
objective event or opportunity history.
## Resource authority
@@ -211,7 +232,7 @@ This phase does not yet provide:
- a save-slot menu, metadata, thumbnails, autosaves, or multiple profiles;
- migrations from any historical world schema other than the explicitly
supported v1v7 layouts;
supported v1v8 layouts;
- player inventory or player relationship records;
- broader relationship dimensions, line-of-sight/hearing evidence,
continuous or personalized memory decay, reinforcement, false beliefs, or