Use Case · States No. 1
The World That Remembers
Persistent, society-scale NPC populations.
The Story
For forty years, game characters have forgotten you the moment you walked away. The guard who watched you rob the granary greets you the next morning with the same two lines of dialogue he has said since the day the game shipped. He is not a character. He is a doorbell.
The World That Remembers gives every character in a game world a
persistent, LLM-managed inner life. Each NPC is a @Persona
POJO whose @Trait fields — morale, suspicion, loyalty,
memory — are updated by an LLM and persisted to a database. Guards
accumulate grievances. Rumours of the player's deeds spread through
taverns, getting less accurate with each retelling. Allegiances shift
on schedule. And at night, while the server is quiet, the characters
process what happened to them and wake up slightly different.
The first world that remembers, gossips, holds grudges — and dreams.
How It Is Built
Three capabilities, never before shipped together, carry the whole design.
Gossip with physics
guards.phaseManager().broadcast(
crimeWitnessed,
EventPipeline.create()
.blastRadius(BlastRadius.WITNESSED
.union(BlastRadius.FACTION))
.attenuation(AttenuationModel.RUMOUR)
.timing(EventTiming.IMMEDIATE)
.minSeverity(EventSeverity.WARNING));
Information becomes a simulated, decaying medium. Witnesses know
what they saw; their faction hears a version of it; and
AttenuationModel.RUMOUR applies the classic rumour
psychology — details flatten, drama sharpens, and the story bends to
fit what each listener already believed. One declarative pipeline,
and your world has a grapevine.
NPCs that dream
@Persona(internalLoop = true, loopSchedule = "@daily",
loopDepth = LoopDepth.SHALLOW) means that during quiet hours,
each character consolidates the day's encounters into trait changes —
tagged UpdateSource.INTERNAL_LOOP in the history table.
A weekly DEEP loop reaches genuine belief revision: this
is where a loyal guard, after a month of unpaid wages and unsettling
rumours, quietly stops being a loyal guard.
The society is a database
List<GuardNpc> mutinous = guards.loadWhere(
"morale < 20 AND political_sympathy < -40 AND fatigue > 70");
Designers query disposition the way they query inventory, target
events with WHERE clauses, and read
EvolutionReports — inflection points, trait
correlations, forward projections — as production telemetry for
souls. Deterministic game logic stays in charge through
@OnPersonaEvent thresholds:
@PersonaSubscriber
public class CityAlertService {
@OnPersonaEvent(persona = GuardNpc.class,
type = PersonaEventType.THRESHOLD_CROSSED,
trait = "suspicion", threshold = 80,
direction = Direction.ABOVE)
public void lockdown(TraitChangeEvent<GuardNpc> e) {
world.triggerGateLockdown(e);
}
@OnPersonaEvent(persona = GuardNpc.class,
type = PersonaEventType.POPULATION_TREND,
trend = Trend.FALLING)
public void watchCollapse(PopulationTrendEvent e) {
story.unlockMutinyArc();
}
}
Why It Is Unprecedented
“Emergent narrative” has historically been a polite euphemism for randomness. Here it stops being one: it is threshold mechanics over LLM-managed psychology, with an audit trail. The designer's relationship to the game changes from scripting characters to authoring a society — writing the laws of how feelings move, then reading the chronicles of what happened. No game-AI stack has ever offered persistent state, social transmission with distortion, and database-grade queryability in one system. This is a game world with a paper trail.
The Fine Print
The local tier bounds per-NPC eloquence — this design is about
state (memory, disposition, society); dialogue generation is
a separable concern. LLM-managed psychology can drift implausibly,
which is why PersonaUpdateVetoException exists: the
designer's hard veto on nonsense. And a society that genuinely
evolves can evolve away from the fun — the nightly authorial rules
are the steering wheel, and they are mandatory authorship, not
optional seasoning.
