Realm is built as three separable concerns that communicate through a single contract: simulation + services + clients. The simulation engine is the sole authority on game state. Every other component — web client, mobile app, AI agent, or player-authored Lua service — submits proposed actions and waits for the engine to validate and commit or reject them.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/at6132/econ/llms.txt
Use this file to discover all available pages before exploring further.
The simulation engine is the only thing that can mutate game state. All other parties submit proposed actions; the engine validates and commits or rejects.
Architecture diagram
The full system is organized into four horizontal layers: clients at the top, then the API gateway, then the three runtime services (simulation, agent, user-code), and finally the data layer at the bottom.v1 vs v2+ stack
The v1 design collapses the full architecture into a single Python process and a Next.js client — no distributed systems required until multiplayer. v2+ splits each concern into its own service.- v1 — Solo mode
- v2+ — Multiplayer
| Concern | Choice | Rationale |
|---|---|---|
| Web frontend | Next.js 14 + React 18 + TypeScript | Standard, fast iteration, great tooling |
| 2D map rendering | Pixi.js 8 (Canvas/WebGL) | Performant 2D, works in browser, mature |
| Charts / data viz | Recharts | Standard for trading-style UIs |
| Simulation engine | Python (FastAPI + uvicorn) | Fastest design iteration; fine for solo scale |
| Database | SQLite per save file | One save = one file; easy to copy and back up |
| In-process cache | In-memory (Python dict) | Solo doesn’t need Redis |
| Mobile | React Native + Expo (later phase) | Codeshare with web where possible |
| User-code sandbox | Lua via lupa (Phase 4) | Sandboxable, familiar, fast |
| LLM agents | Anthropic API (Claude) | Tier 3 agents; Claude Haiku by default |
The simulation engine
The engine is a deterministic tick-based system. It holds the entire world in memory (solo mode) and advances one tick at a time.Tick loop
Each tick processes the world in a fixed, ordered sequence:tick.py implementation, one simulation step runs: transit delivery → building decay → production → material spoilage → employment → Tier 1 agents → Tier 2 agents → Tier 3 LLM agents → clock advance → contract breach checks → financial contract processing → market history snapshot.
Tick rate
In public mode, 1 game-day = 1 real-hour, but ticks happen much more often (for example, 1 game-minute per tick = 1 real-second per tick = 1,440 ticks per game-day). This gives smooth real-time-ish gameplay without forcing the engine to tick at 60Hz. In solo mode, the tick rate is configurable per save: 1×, 2×, 4×, or paused.Determinism
Same starting state + same inputs = same outputs. The engine enforces this rigorously:- All randomness derives from
(world.tick, randomness_purpose)seeds —world.rng(purpose)returns a seededrandom.Randominstance. - Wall-clock time is never used inside game logic.
- Agent decisions, price formation, and decay all use deterministic functions.
- This makes replays, debugging, and offline simulation possible.
Data model
Every state change is a transaction. No direct mutations. The transaction layer enforces conservation laws (money and matter cannot be created or destroyed).| Table | Contents |
|---|---|
worlds | One row per shard / save file |
players | One per human player |
accounts | Financial accounts (player-owned, business-owned, system-owned) |
plots | One per plot: ownership, terrain, hidden subsurface |
surveys | Survey results — who knows what about which plot |
inventories | Material holdings, indexed by owner + location |
materials | Material catalog |
production_units | Built infrastructure on plots |
labor_pools | Regional labor markets |
employments | Active employment relationships |
orders | Open buy/sell orders on order books |
trades | Historical executions |
contracts | Active contracts (template + parameters + state) |
contract_events | Payment, delivery, and breach events |
messages | Player-to-player and agent-to-player messages |
services | User-deployed code services |
service_subscriptions | Who subscribes to what |
service_calls | Call logs for billing |
agents | AI agent records |
agent_memories | Tier 3 memory blobs |
reputation_events | Auditable reputation history |
Real-time updates
The web and mobile clients react to changes via WebSocket:- New order on an order book → push to subscribers
- Contract proposed → push to counterparty
- Agent message → push to recipient
- Price tick → push to chart subscribers
User-code runtime
Each deployed Lua service runs in its own sandbox with:- A Lua interpreter (with a restricted standard library — no
io,os,require,debug, orcoroutine) - A connection to the simulation API (read and write actions)
- A storage allocation (key-value store per service)
- A CPU budget per tick or per call
- An execution history for debugging and audit
Persistence strategy
- Solo mode
- Public mode
Save files are SQLite files. One save = one file. Easy to copy, share, and back up. Cloud sync is optional via account. Use
POST /persistence/save and POST /persistence/load to write and restore saves from the engine API.Performance targets
| Mode | Scale | Target |
|---|---|---|
| v1 solo | 50 plots, 15 agents, ~100 active orders | Tick < 50ms on a mid laptop |
| v2 multiplayer (per shard) | 500 plots, 200 agents, 100 humans, 10K active orders | Tick < 500ms on a single server |
| v3+ scale | 5K plots, 1K humans | Hot path likely needs Rust; multiple independent shards |