Data Model

Game development workspace with behavioral timeline visuals

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
}
Diagram showing game event and magnitude mapped to event type and severity

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 default
  • calculate_impact() -> Vec<BpImpact> - final impact after NPC-specific adjustments
  • apply() - 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"
  }
}
Game design planning materials with behavior curves and level layout

Scenario: IndividualInsulted

  1. A player insults NPC alex during a negotiation scene.
  2. The event handler emits a default impact: EventType::SocialRejection with severity = 0.55.
  3. calculate_impact() adjusts severity based on NPC sensitivities (e.g., high Emotionality increases impact to 0.70).
  4. apply() writes the event to BP and queries state for immediate reaction.
  5. 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.