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.