feat(simulation): add storyteller engagement tracking and activation pass
Storyteller chain for Sprint 23 (#570, #571, #572, #579): - EngagementRecord component: per-NPC observation_time_ticks, conversation_count, monologue_trigger_count — incremented by perception, dialogue, and monologue systems - MovementHistoryBuffer resource: ring buffer of player positions over last 3000 ticks with npcs_copresent_in_window() query - Lifecycle rules: single activation per session, no concurrency, no cooldown, terminal resolution constants - activation_pass() system: gate check, proximity query, engagement scoring, unentangled-NPC routing, module selection, emits TriangleActivatedEvent on 10-tick cadence after contamination Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -33,6 +33,7 @@ use crate::simulation::interaction::Interactable;
|
||||
use crate::simulation::movement::TilePosition;
|
||||
use crate::simulation::tier::ActiveSim;
|
||||
use crate::simulation::time::DayPhase;
|
||||
use crate::storyteller::EngagementRecord;
|
||||
|
||||
// #166 — Template-to-instance mapping
|
||||
use rand::Rng as _;
|
||||
@@ -133,6 +134,9 @@ fn spawn_npc(world: &mut World, profile: &types::NpcProfile, result: &mut SpawnR
|
||||
// Mood state — drives Layer 4 dialogue selection and monologue tone (#323)
|
||||
entity_commands.insert(npc::mood::MoodState::default());
|
||||
|
||||
// Engagement metrics — storyteller activation scoring (#570, #162)
|
||||
entity_commands.insert(EngagementRecord::default());
|
||||
|
||||
// Axis 1: Want
|
||||
if let Some(want) = &profile.want {
|
||||
if let Some(kind) = parse_want_kind(&want.primary) {
|
||||
|
||||
Reference in New Issue
Block a user