Skip to content

Personality ​

Every NPC has a personality. It biases every decision, every diary entry, every interaction.

Why Personality? ​

Without personality, NPCs behave identically. With it, they become people.

Personality in AI World Sim is:

  • ✅ Quantified — stored as numeric traits, not free text
  • ✅ Stable — rarely changes (only through major life events)
  • ✅ Influential — biases every NPC behavior

The Model: Big Five + Custom ​

We use a hybrid approach:

Big Five Traits (OCEAN) ​

Every NPC has scores on the Big Five personality dimensions:

TraitRangeWhat it means
Openness0-1Curiosity, creativity, openness to experience
Conscientiousness0-1Organization, discipline, reliability
Extraversion0-1Sociability, energy, talkativeness
Agreeableness0-1Trust, altruism, cooperation
Neuroticism0-1Anxiety, moodiness, emotional volatility

Custom Traits ​

Plus, every NPC has a small set of binary or scaled custom traits:

TraitRangeWhat it means
romantic0-1Likelihood to seek romantic relationships
aggressive0-1Likelihood to start arguments
religious0-1Frequency of church visits, prayer
alcohol_tolerance0-1How much they drink at the pub
risk_taking0-1Willingness to take physical/financial risks
parental0-1Concern for their children's wellbeing
gossipy0-1Tendency to talk about others

How Personality Affects Behavior ​

Decision Bias ​

In the Decision module, personality modifiers are applied:

ts
function applyPersonality(action: Action, personality: Personality): number {
  let modifier = 1.0;

  if (action.type === 'go_to_pub' && personality.extraversion < 0.3) {
    modifier *= 0.5;  // introvert avoids pub
  }
  if (action.type === 'start_argument' && personality.agreeableness > 0.7) {
    modifier *= 0.3;  // agreeable person avoids arguments
  }
  if (action.type === 'try_new_food' && personality.openness > 0.7) {
    modifier *= 1.5;  // open person is curious
  }

  return modifier;
}

Diary Tone ​

Personality biases diary generation:

  • High neuroticism → more emotional, anxious tone
  • High openness → more reflective, philosophical
  • Low agreeableness → more critical of others
  • High conscientiousness → more structured, mentions duties

Conversation Style ​

When two NPCs interact, personality affects who speaks more, who interrupts, who apologizes.


Personality Profiles (Sample NPCs) ​

Margaret Caldwell (58, retired librarian) ​

yaml
big_five:
  openness: 0.8
  conscientiousness: 0.85
  extraversion: 0.4
  agreeableness: 0.7
  neuroticism: 0.6

custom:
  romantic: 0.2
  aggressive: 0.1
  religious: 0.5
  alcohol_tolerance: 0.4
  risk_taking: 0.1
  parental: 0.7
  gossipy: 0.6

Interpretation: Reserved but warm, well-organized, occasionally anxious. Likes to chat but doesn't initiate much. Loves her children deeply.

Tom Whitfield (52, hospital orderly, night shift) ​

yaml
big_five:
  openness: 0.4
  conscientiousness: 0.7
  extraversion: 0.6
  agreeableness: 0.6
  neuroticism: 0.4

custom:
  romantic: 0.3
  aggressive: 0.4
  religious: 0.2
  alcohol_tolerance: 0.7
  risk_taking: 0.5
  parental: 0.5
  gossipy: 0.4

Interpretation: Practical, social but not effusive. Drinks at the pub more than most. Not afraid to speak his mind.


Personality Change ​

Personality is mostly stable. But it can shift due to major life events:

EventPossible shift
Death of a loved oneNeuroticism ↑
Falling in loveAgreeableness ↑
Major illnessConscientiousness ↑, Openness ↓
Promotion at workExtraversion ↑
Moving to a new townOpenness ↑

These shifts are small (≤ 0.1 per event) and slow (one event rarely changes someone).


Generation ​

NPC personalities are generated once at world creation using:

  1. A seed (the NPC's archetype: "retired librarian", "nocturnal orderly").
  2. A small random variance.
  3. Constraints (no trait below 0.1 or above 0.95 — humans aren't extreme).

Same seed → same personality, so personalities are reproducible across worlds.


Data Model ​

ts
interface Personality {
  npcId: string;

  big_five: {
    openness: number;
    conscientiousness: number;
    extraversion: number;
    agreeableness: number;
    neuroticism: number;
  };

  custom: {
    romantic: number;
    aggressive: number;
    religious: number;
    alcohol_tolerance: number;
    risk_taking: number;
    parental: number;
    gossipy: number;
  };

  version: number;       // incremented on each change
  lastChangedAt: WorldTime;
}

Stored in D1 table npc_personality.

Last updated:

Released under the MIT License.