This page documents the internal adapter model used by a game to translate in-world events into Behavioral Pathways (BP) inputs. It is intentionally minimal: a small bridge structure that is easy to implement, easy to audit, and stable over time.
BpImpact: The Bridge Model
Location: src/npc/events/base.rs
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BpImpact {
pub event_type: EventType, // behavioral_pathways::enums::EventType
pub severity: f64, // 0.0 to 1.0 intensity
}
This is the internal game model that gets translated to BP. It is a simple adapter that maps:
- Game concept (what happened) →
event_type(BP's psychological event category) - Game magnitude (how significant) →
severity(impact intensity)
Supporting Structures
NpcEventBase (src/npc/events/base.rs) provides event context:
pub struct NpcEventBase {
pub npc_id: String,
pub timestamp: Timestamp,
pub event_name: String,
}
NpcEventHandler is the trait every game event implements. It provides:
default_impact() -> Vec<BpImpact>- what the event produces by defaultcalculate_impact() -> Vec<BpImpact>- final impact after NPC-specific adjustmentsapply()- sends to BP and computes the resulting state change
Flow Summary
Game Event (IndividualInsulted, etc.)
↓
default_impact() → Vec
↓
calculate_impact() (merges NPC sensitivities)
↓
apply() → behavioral_pathways::Simulation
↓
IndividualState (BP's output)
Reference implementation: see your game codebase under src/npc/events/base.rs.
Product Use Case Mode
This is a concrete game-style use of the model, showing how a single event becomes an internal BP query.
Example Full Character Model (JSON)
This is a complete in-game character snapshot: identity, personality, current state, relationships, and event history. It is not the BP internal state; it is the game-side model that feeds BP.
{
"npc_id": "alex",
"display_name": "Alex Rivera",
"species": "Human",
"birth_date": "1996-04-18",
"age": 28,
"anchor_timestamp": "2024-01-01T00:00:00Z",
"location": {
"region": "West District",
"scene": "MarketSquare"
},
"personality": {
"hexaco": {
"honesty_humility": 0.62,
"emotionality": 0.58,
"extraversion": 0.44,
"agreeableness": 0.71,
"conscientiousness": 0.64,
"openness": 0.52
},
"disposition": {
"impulse_control": 0.55,
"empathy": 0.67,
"aggression": 0.20,
"grievance": 0.10,
"reactance": 0.18,
"trust_propensity": 0.62
}
},
"state": {
"mood": {
"valence": { "base": 0.10, "delta": -0.18, "chronic_delta": -0.04, "decay_half_life_days": 4 },
"arousal": { "base": 0.08, "delta": 0.22, "chronic_delta": 0.03, "decay_half_life_days": 3 },
"dominance": { "base": 0.12, "delta": -0.10, "chronic_delta": 0.00, "decay_half_life_days": 5 }
},
"needs": {
"belonging": { "base": 0.55, "delta": -0.12, "chronic_delta": -0.06, "decay_half_life_days": 10 },
"purpose": { "base": 0.48, "delta": -0.05, "chronic_delta": 0.00, "decay_half_life_days": 14 },
"safety": { "base": 0.60, "delta": 0.00, "chronic_delta": 0.02, "decay_half_life_days": 20 }
},
"mental_health": {
"hopelessness": { "base": 0.12, "delta": 0.08, "chronic_delta": 0.03, "decay_half_life_days": 21 },
"depression": { "base": 0.18, "delta": 0.10, "chronic_delta": 0.04, "decay_half_life_days": 30 }
},
"social_cognition": {
"loneliness": { "base": 0.35, "delta": 0.14, "chronic_delta": 0.08, "decay_half_life_days": 12 },
"perceived_caring": { "base": 0.52, "delta": -0.09, "chronic_delta": -0.03, "decay_half_life_days": 9 },
"perceived_liability": { "base": 0.20, "delta": 0.05, "chronic_delta": 0.02, "decay_half_life_days": 18 }
}
},
"relationships": [
{
"other_id": "mara",
"type": "Colleague",
"context": "Work",
"trust": { "ability": 0.58, "benevolence": 0.46, "integrity": 0.51 },
"quality": 0.52
},
{
"other_id": "jon",
"type": "Friend",
"context": "Personal",
"trust": { "ability": 0.70, "benevolence": 0.74, "integrity": 0.69 },
"quality": 0.77
}
],
"history": {
"events": [
{
"timestamp": "2024-03-15T14:32:00Z",
"event_name": "IndividualInsulted",
"impacts": [
{ "event_type": "SocialRejection", "severity": 0.55 }
]
},
{
"timestamp": "2024-03-18T09:10:00Z",
"event_name": "TeamLunchExcluded",
"impacts": [
{ "event_type": "GroupExclusion", "severity": 0.48 }
]
},
{
"timestamp": "2024-04-02T20:05:00Z",
"event_name": "ReceivedPraise",
"impacts": [
{ "event_type": "Achievement", "severity": 0.42 }
]
}
],
"last_query": "2024-04-03T12:00:00Z"
}
}
Scenario: IndividualInsulted
- A player insults NPC
alexduring a negotiation scene. - The event handler emits a default impact:
EventType::SocialRejectionwithseverity = 0.55. calculate_impact()adjusts severity based on NPC sensitivities (e.g., high Emotionality increases impact to 0.70).apply()writes the event to BP and queries state for immediate reaction.- The game reads the resulting
IndividualState(lower valence, lower dominance) and updates dialog/behavior.
Why This Matters
- Consistency: All events map into the same BP vocabulary.
- Auditability: Impacts are explicit, enumerable, and testable.
- Behavioral depth: NPC differences emerge from personality and context, not custom logic per event.
When the game team wants new behavior, they add a new event type or adjust impact mappings instead of writing bespoke AI logic.