01 the investigation begins · ⌁ in Night City
The same words.
Two different reactions.
No randomness.
Equilibrium Engine models RPG characters as inspectable inner dynamics: events disturb an internal balance, memory carries tension forward, and visible behaviour emerges when a threshold is crossed.
Deterministic. Debuggable. The same inputs always produce the same life.
02 first discovery
The split happens before the trigger.
The visible outburst happens at 09:40 — but the cause started hours earlier. Rain on the neon strip, frustration, fatigue, and self-control were already shifting the internal equilibrium. The remark only crossed the threshold.
a flat word, a held breath
the same remark lands on a system near its limit
But what changed before the remark? Look inside ↓
03 the reveal
What the story did not show.
Outside, it looked like a sudden temper. Inside, it was a deterministic state trajectory. The same words arrive at the same minute on both mornings — but on the cold run, frustration and stress have been accumulating since dawn, self-control has eroded, and the trigger lands on a system already near its limit. Not random — inspectable dynamics.
on the divergence
Same event marker. Different prior trajectories. One crosses the threshold; one doesn't.
on the slow line
And one state — resentment toward Marta — moves on a slower clock than the rest. Hold that thought.
How does an event become these state changes? Open the loop ↓
04 the mechanism
The inner loop.
The engine does not script emotions. Each tick, it turns an event into semantic inputs, filters them through what the character feels about who and what the event involves, updates a small set of state variables (which accumulate and decay), lets sparse feedback couplings pull them on each other, computes a reaction potential, and emits a trace explaining exactly why it did what it did.
Show the update rule advanced
Every state is the same generic element — a value that retains part of its past, drifts toward a resting level, and sums what arrives this tick from the world and from the other states:
new = decay·old + (1 − decay)·setpoint + drift
+ Σ gain·input (events, after the relational / affinity filters)
+ Σ coupling·other_state (sparse feedback between states)
No numeric literals live in the engine — the topology is fixed; the constants come from an offline calibration pass. Behaviour is selected from the resulting state, never from an if insulted → angry rule.
States change — but what lasts? Stay overnight ↓
05 the slow memory
Sleep clears the mood. It does not erase the wound.
Fast states — anger, stress, frustration — discharge overnight; the character wakes calm. But the relationship states leak far more slowly, and sleep never touches them. Branic wakes rested and even-tempered — and a little colder toward Marta than he was yesterday. The temper was today. The grudge is a relationship.
The same dynamics, pushed further — choose a scenario ↓
06 step inside
Pick a scenario. Open its world.
The same small set of dynamics, pushed four ways — across two worlds, scaled up to a whole city, and read whole, tick by tick. Open any block to step inside.
Relations Between Cities
Diplomacy at scale — trust, resentment, and alliance between polities.
Explore faction dynamics
A Whole City
One engine, hundreds of souls, talking back.
Scale it up
One Morning, Three Ways
A controlled experiment: three identical runs, one differing input — the same words held on the dry morning, an outburst in the rain.
Run the experiment
One Day, Two Worlds
One engine run, two blind writers, two costumes — strip the prose and the same skeleton stares back.
Enter the proof
Poke the Engine
The real update rule, in your hands: insult a character, watch the threshold crossing fire, and read the arithmetic of why. Three tempers, four guided scenarios, twelve border-case proofs — zero scripts.
Open the playgroundAnd the boldest claim of all: none of this depends on the world. See the proof ↓
07 the proof
The body stays. The costume changes.
The language model is allowed to change the skin — a frontier keep, a neon bar, a court intrigue, a colony ship — but the deterministic run underneath stays the same. Anger, the displaced flare, the grudge that survives the night: identical numbers, different words. This page does it too — you chose a costume at the gate, not a content.
⇄ You are reading Night City. Every number on this page stays put when you
| character | ⚔ Keep · now showing | ⌁ Night City | in a line |
|---|---|---|---|
| Edda | castellan | floor boss / fixer | composed, respected; command is her default mode |
| Halgrim | sergeant of the watch | head of the door | iron self-control; never raises his voice |
| Wojsław | man-at-arms | merc regular | proud, thin-skinned; an insult is a spark |
| Cichy | prisoner in the undercroft | a debtor in the back room | hates his captor; a “kindness” deepens it |
| Branic | green recruit | rookie bouncer | eager; feelings close to the surface; bores fast |
| Lutek | bard at the keep | rockerboy on the corner | all wit; an insult slides off him |
| Welf | keep hand | barback | idle, fidgety; takes almost nothing to heart |
| Marta | the cook | the cook | the cabbage soup is hers — and it stays soup in both worlds |
One more night — all seven of them, side by side. Stay up ↓
08 the night closes in
Every night empties the day. It does not empty the grudge.
Run the same three days through all seven. Sleep discharges the day's heat for every one of them — anger climbs through the wet, tedious door shift and falls to nothing by each dawn. But how each comes to stand toward Marta can outlast the night: where the remark booked a grudge, the grudge is still there in the morning; where someone warmed to her soup, the warmth stays too. The same night. Seven different mornings.
✵ appendix · for the curious
Field notes from the engine.
Needling someone already strained snaps them; the same words get a shrug when they're fresh.
A blind believability panel rated seven characters built only from parameter sheets as in-character, without ever seeing the parameters.
Hunger, fatigue, and a cold-rain channel erode self-control; displaced strain from an unrelated cause, not a special case.
One character's order becomes another's event next tick, resolved through the same obedience pipeline: obey the respected officer, resent the despised one — with the same order.
Characters are parameter sheets, runs are deterministic; “did my tweak make him out of character?” becomes a test you run in CI.
Each names the real mechanism it would extend — slow states with floors, the cross-agent router, emergent loops. Clearly marked as where it could go.
✦ the last scene
Look back the way you came.
You walked through a keep.
You walked through a night city.
The costumes changed.
The signals did not.
That is the point.
Equilibrium Engine does not script a world.
It models the dynamics beneath it.
✦ the gate stands open
This keep is open source. Walk in.
Everything underneath this page — the integrators, the filters, the grudges — is Apache-2.0 and public. Every plot you scrolled past was drawn from a run you can reproduce bit-for-bit on your own machine. And the keep is short of everything that matters: personas, scenarios, whole worlds to wear. The engine is small on purpose. The cast doesn't have to be.
Open the live playground and push a persona until it stops being itself. If you manage it, tell us how — “he went out of character” is a bug report here, and we treasure those.
A persona is a parameter sheet, not code — half-lives, gains, a few relations. Bring a jealous innkeeper, a homesick golem, a saint with one weakness. If it has tensions, the dynamics can carry it.
Pure functions with explicit contracts, a sparse frozen topology, property tests instead of magic numbers. If you’ve ever stabilised a control loop — or wanted to learn on one that holds grudges — start at the issues.
No CLA theatre. Apache-2.0, deterministic tests, and a maintainer who reads every issue.

