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:
| Trait | Range | What it means |
|---|---|---|
| Openness | 0-1 | Curiosity, creativity, openness to experience |
| Conscientiousness | 0-1 | Organization, discipline, reliability |
| Extraversion | 0-1 | Sociability, energy, talkativeness |
| Agreeableness | 0-1 | Trust, altruism, cooperation |
| Neuroticism | 0-1 | Anxiety, moodiness, emotional volatility |
Custom Traits
Plus, every NPC has a small set of binary or scaled custom traits:
| Trait | Range | What it means |
|---|---|---|
romantic | 0-1 | Likelihood to seek romantic relationships |
aggressive | 0-1 | Likelihood to start arguments |
religious | 0-1 | Frequency of church visits, prayer |
alcohol_tolerance | 0-1 | How much they drink at the pub |
risk_taking | 0-1 | Willingness to take physical/financial risks |
parental | 0-1 | Concern for their children's wellbeing |
gossipy | 0-1 | Tendency to talk about others |
How Personality Affects Behavior
Decision Bias
In the Decision module, personality modifiers are applied:
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)
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.6Interpretation: 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)
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.4Interpretation: 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:
| Event | Possible shift |
|---|---|
| Death of a loved one | Neuroticism ↑ |
| Falling in love | Agreeableness ↑ |
| Major illness | Conscientiousness ↑, Openness ↓ |
| Promotion at work | Extraversion ↑ |
| Moving to a new town | Openness ↑ |
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:
- A seed (the NPC's archetype: "retired librarian", "nocturnal orderly").
- A small random variance.
- 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
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.