feat(simulation): interaction tracking + trust progression (#325, #324)

InteractionMemory component tracks interaction_count, last_interaction_tick,
and notable_events per NPC. Drives D-028 Layer 2 situation activation:
first_meeting (count==0) and repeated_visit (count>=3). warm_active in mood
system now derives from InteractionMemory within a 300-tick window.

Trust progression wired into dialogue systems: talk completion (+1),
walk-away (-1), confrontation (-2) emit TrustEvents consumed by update_trust.
InteractionEvent (WalkAway, Confrontation) recorded in notable_events for
fast per-pair access.

Adds FirstMeeting and RepeatedVisit Situation variants. 18 unit tests in
interaction.rs. All arithmetic integer-only (D-010 determinism). No HashMap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-20 18:52:23 +01:00
co-authored by Claude Sonnet 4.6
parent a14c980aad
commit dcd15a330f
7 changed files with 338 additions and 9 deletions
+13
View File
@@ -2,6 +2,7 @@
// Implements D-024: 10-axis NPC model + CombatCapability component
// Background tier state machines for schedule, mood, relationships, job
pub mod interaction;
pub mod mood;
pub mod relationships;
pub mod routine;
@@ -22,6 +23,7 @@ pub struct NpcPlugin;
impl Plugin for NpcPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<relationships::RelationshipGraph>()
.init_resource::<relationships::TrustEventQueue>()
.init_resource::<routine::PreviousDayPhase>()
.add_systems(
Update,
@@ -31,6 +33,17 @@ impl Plugin for NpcPlugin {
mood::update_mood
.after(routine::check_phase_transition)
.before(crate::simulation::dialogue::process_talk_interaction),
relationships::update_trust
.after(crate::simulation::dialogue::process_talk_interaction)
.after(crate::simulation::dialogue::process_walk_away)
.after(crate::simulation::dialogue::process_confrontation_response)
.before(crate::simulation::time::advance_tick),
relationships::update_relationship_dynamics
.after(relationships::update_trust)
.before(crate::simulation::time::advance_tick),
routine::enter_activity
.after(crate::simulation::movement::validate_movement)
.before(crate::perception::observer::compute_observer_snapshot),
),
);