Skip to content

World and Narrative Model

flukeairwalker edited this page Oct 12, 2026 · 16 revisions

World and Narrative Model

Reference. For Game Masters and builders. Holonovel has two infrastructure layers beneath every game — a world model (spatial simulation) and a narrative model (story depth). This page covers both in complete detail.


World Model

The world model is a spatial simulation layer — rooms, exits, containers, supports, doors. Every object knows where it is and what it contains. The server maintains a real containment graph, not prose the AI hopes to remember.

Its conventions are drawn from Inform, the interactive-fiction language behind decades of text-adventure classics.

Rooms

A room is a location. It has a name, a description, and contents (things and NPCs placed in it). Rooms connect to other rooms via exits.

"Create a room called Entrance Chamber." "Describe the Entrance Chamber: stone walls wet with condensation. A rusted crowbar holds the north door ajar. Three passages lead deeper."

When a character enters a room, the room's description is narrated. Exits are listed. The player knows what's here and where they can go.

Things

A thing is any object in the world — a lamp, a sword, a key, a book, a pile of bones. Things have properties:

Property Meaning
portable Can be taken and carried
openable Can be opened and closed
lockable Can be locked and unlocked
container Can hold other things
supporter Things can be placed on it

"Create a thing: a rusted crowbar. It's portable." "Create a thing: a stone sarcophagus. It's a container with a lock." "Make the altar support things."

Properties combine. A chest is openable, lockable, and a container. A table is a supporter. A door is openable and lockable.

Containment

Every thing has a container_id — the room or thing that holds it. The containment graph is real. Moving an object changes its parent. Opening a container reveals its contents. Locking a container prevents access.

"Take the lamp from the altar." "Open the sarcophagus." "Unlock the chest with the iron key."

Parser commands navigate the world with real containment logic. The engine tracks what's in every room, every container, and every character's inventory.

Exits

An exit connects two rooms in a direction. Create one direction and the reverse is created automatically.

"Create an exit: Entrance Chamber north to Flooded Crypt."

The reverse exit (Flooded Crypt south to Entrance Chamber) exists automatically. Exits are directional — north, south, east, west, up, down, in, out, northeast, northwest, southeast, southwest.

"Go north." "Enter the portal." "Climb down the ladder."

Delete an exit and both directions are removed.

Closed and locked exits

Doors, gates, and portcullises are things that block exits. Place a door in a room, then create the exit — the door gates passage.

"Create a thing: a heavy iron door. It closes and locks. Place it in the Entrance Chamber." "Create an exit: Entrance Chamber north to Flooded Crypt."

Now "Go north" checks the door. If it's closed, the engine reports it. If it's locked, the engine asks for a key. The player must open and unlock before passing.

Kind hierarchy

Every thing belongs to a kind — a category that determines its default properties. Kinds form a tree:

thing
  ├── container (openable)
  │     └── locked-container (lockable)
  ├── supporter
  ├── door (openable, lockable)
  ├── person
  └── device (switchable)

When you create a thing, its kind determines which properties it starts with. A door is openable and lockable by default. A container is openable. A locked-container is both. You can override any property per instance.

"Create a door called the Iron Gate. It starts locked." "Create a chest. It's a locked container."

The convert tool

Instead of building rooms and things by hand, you can write hybrid source text — prose descriptions annotated with RPG content tags — and parse it into a world model in one call.

"Parse this source text into a world model."

The Entrance Chamber is a room. Stone walls, wet with condensation. A
rusted crowbar holds the north door ajar. Three passages lead deeper:
north to the Flooded Crypt, east to a dry passage, south toward the sound
of running water.

In the Entrance Chamber is a stone altar. The altar supports a rusted
crowbar and an unlit lantern.

The Flooded Crypt is a room. Ankle-deep water. Three sarcophagi line the
walls. A wooden door leads east.

@treasure: The sarcophagi contain 50 gold pieces and a Potion of Grit.

@danger: A drowned priest rises from the water. Grit +2, Nerve +1.
Weapon: Rusty Blade (1d6 slashing).

manage_world (action: convert) produces rooms, things, exits, and annotations — all linked into the containment graph. The @treasure, @danger, and @npc tags become enrichment items. The world model is ready immediately.

Building rooms from adventure sources

Adventure modules ship ## World sections — structured room descriptions following the same conventions as manage_world (action: convert). During Build, these sections are parsed into the world model automatically. After Build, the rooms exist — no hand-creation needed.

You can also build rooms by hand during play:

"Create a room called the Wizard's Study. Bookshelves line every wall. A faint glow comes from the crystal on the desk." "Place a locked chest under the desk." "Create an exit: Wizard's Study east to the Observatory."

Navigation

The world model responds to parser commands. You speak them in natural language — the AI translates to parser input.

Player says Parser command What happens
"Go north." go north Moves the active entity to the room connected via the north exit
"Take the lamp." take lamp Moves the thing from the room to inventory
"Drop the crowbar." drop crowbar Moves the thing from inventory to the room
"Look around." look Describes the current room and its contents
"Examine the altar." examine altar Describes the thing in detail
"Open the chest." open chest Opens the container
"Lock the door." lock door Locks the lockable thing
"What am I carrying?" inventory Lists carried things

Navigation is available when adventures provide spatial maps. It is never required to be in the story — the ruleset, not the world model, drives the narrative. Parser commands are a secondary surface, configurable via TTRPG_WORLD_PROMINENCE (REQ-309).


Narrative Model

The narrative model is everything that gives your world depth. Scenes, NPCs, lore, factions, secrets, relationships, vows, countdowns, and the story journal — every element is a first-class data structure, not a paragraph of prose the AI might forget.

Scenes

A scene sets the stage. It has a description (what the players see), a location, a time of day, and an atmosphere.

"Set the scene: a flooded ossuary deep beneath the temple. The air is thick with old incense. Water drips from the ceiling. Three stone sarcophagi line the walls." "Set the location: Ossuary of the Drowned Priests." "Time of day: midnight. Atmosphere: oppressive, sacred."

The scene description governs lore trigger matching — when a keyword in the scene text matches a lore entry's trigger, that entry fires. It also provides context for action suggestions and determines tool ordering in the GM briefing.

Scene types tag the narrative mode:

"This is a combat scene. Also social — there's negotiation happening mid-fight."

Types can be single (combat, social, exploration, neutral) or compound (combat + social for a duel amidst negotiation, exploration + social for investigating a village). Scene type shapes which tools and suggestions the AI surfaces.

Every scene change records a transition hook in the audit log. Narrative countdowns tick automatically on scene transitions. Suppress the hook for detail updates within the same scene:

"Update the scene: the chanting grows louder. Skip the transition hook."

NPCs

NPCs are the people in your world. They carry more than stats:

Field What it holds
name Identity
description Physical appearance, mannerisms
disposition Current attitude: hostile, suspicious, neutral, friendly, allied
location Where they are in the world
personality Traits, beliefs, flaws, bonds
voice How they speak — cadence, vocabulary, accent
voice_examples Dialogue snippets teaching the AI their voice
goals What they want
background History the AI draws on for consistency

"Create an NPC: Sister Mora, an acolyte of the ossuary. She's terrified, not hostile. Her voice is hushed, urgent, full of half-finished sentences. She knows the drowned priests still pray down here, but she won't say why."

Voice examples are dialogue snippets tagged with context — they teach the AI how the NPC speaks rather than describing it:

"Give Sister Mora these voice examples." "Context: first meeting. 'You shouldn't be here. The priests — they don't like visitors.'" "Context: pressed for information. 'I can't. I swore an oath. But the altar — the altar knows what you need.'"

When the NPC speaks in-character, examples render ahead of trait descriptions. The AI learns cadence from examples and personality from traits.

NPC memory and evolution

NPCs maintain independent memories. The engine records what each NPC witnessed and evolves their disposition automatically:

"Threaten the blacksmith. Tell him his forge is a death trap."

The NPC's disposition shifts toward hostile. Every subsequent interaction reflects it. This isn't a prompt — it's structured state.

"Help the blacksmith repair his bellows. Offer to guard the forge tonight."

Disposition shifts toward friendly. The engine tracks it. The AI reads it.

NPCs also evolve through the World in Motion system — between scenes, NPCs pursue goals, faction agendas advance, and consequences ripple. The GM sees proposed changes in their briefing with accept/modify/defer controls.

Lore

Lore entries are keyword-triggered facts. They fire when any trigger appears in the scene text or recent narration. They surface in the GM briefing exactly when relevant.

"When anyone mentions the ossuary, remind me: the drowned priests still pray down here. They will not harm anyone who leaves an offering." "Trigger on 'altar,' 'sacrifice,' or 'offering.' Show me this for the next three scenes after it fires."

Entry properties:

Property Effect
priority Sort order in briefing — higher numbers surface first
sticky Number of briefings the entry persists after triggers leave the scene
badge_scope game_master (GM only) or shared (visible to players)
group Named group — faction lore, location lore, plot threads

"Put the ossuary secret in the 'locations' group." "Show me all lore entries in the 'factions' group."

A token budget caps lore output. When entries exceed the budget, low-priority ones are omitted and reported. manage_lore (action: toggle) enables or disables individual entries without deleting them:

"Disable the ossuary secret for now. The party left the temple."

Factions

Factions track standing and agendas. Every major group in your world is a faction with a numeric standing toward the party and a descriptive agenda.

"Create a faction: The Thieves' Guild. Standing: -3. They want the party dead for interfering with the heist." "Create a faction: The Temple Wardens. Standing: +2. They owe the party for recovering the stolen relic."

Faction standing evolves as the party acts. Help a faction, standing rises. Cross them, standing falls. The engine tracks it. The AI reads it. The GM briefing surfaces current standings with recent change indicators.

Secrets

Secrets gate knowledge behind discovery. A secret is a fact the GM knows but the players might never learn. Secrets have a discovery condition — a scene element or player action that reveals them.

"Create a secret: Sister Mora is the last drowned priest. Discovery condition: examining the altar while she's present."

Secrets persist until discovered. Undiscovered secrets remain invisible to the Player badge — they can't be leaked by accident.

Relationships

Relationships connect entities with a type and intensity. They evolve with every interaction.

"Sister Mora and the High Priest have a relationship: bound by oath. She fears him." "Kael the rogue and the Thieves' Guild have a relationship: wanted. They put a bounty on his head."

The relationship graph is part of the Novel. badge_briefing surfaces relationships relevant to the current scene.

Vows

A vow binds a character to a quest with milestone tracking. Each vow has a statement, milestones (with completion states), and consequences for failure.

"Kael swears a vow: recover the Lantern of Lost Souls. Milestones: find the temple entrance, descend to the crypt, defeat the guardian, claim the lantern. Consequence of failure: Sister Mora's spirit is trapped forever."

Track vow progress, mark milestones complete, face consequences. Vows are a first-class data structure — the engine remembers what was sworn.

Countdowns

Countdowns escalate tension on a schedule. They are named timers with a tick count, a type, and a direction.

"The ritual completes in five rounds. Start the countdown." "The ship hull buckles. It'll hold for three more hits."

Two types:

Type When it ticks
round Every combat round via manage_combat (action: advance)
narrative On scene transitions (if on_scene_transition is set) or on manage_countdown (action: advance)

Direction: decrement counts down to zero (doom clock). increment counts up (progress clock — 4 of 6 clues found, 3 of 5 locks picked).

"Advance the countdown: the ritual is closer to completion."

Expired countdowns fire an audit entry and free their name slot. A new countdown with the same name creates a fresh timer. Badge scope: GM-only for hidden threats, shared for player-visible tension.

Narrative directives

Standing instructions that shape every GM response. Directives are stacked arrays — each has a label and an instruction.

"Directive: the ossuary is sacred ground. Desecration has consequences." "Directive: Sister Mora knows more than she's saying. She watches the party with guilty eyes."

Duplicate labels replace the prior entry. Directives are GM-only; players never see them.

Story journal

The story journal records decisions, moments, revelations, bonds, and consequences. It is the Novel's narrative memory — the GM chooses what to record, and the engine remembers it forever.

"Record this in the story journal: Kael chose to leave the offering at the altar. The drowned priests are now silent." "Record: Sister Mora revealed the High Priest's betrayal. She joined the party."

Journal entries survive every rebuild. They are surfaced in manage_session (action: recap), badge_briefing, and manage_novel (action: export). The journal is typed — each entry has a category (decision, moment, revelation, bond, consequence) and a timestamp.

Adventure generation

Generate adventures, encounters, and world elements from prompts:

"Generate an adventure: a heist at the wizard's auction house. The vault holds a phylactery no one knows about."

One sentence becomes a campaign scaffold — scenes, NPCs, hooks. The generator produces an outline the GM develops during play.

"Create an encounter: the party triggers the ossuary's flood trap."

Each encounter is a single undoable step — scene, NPC, and lore entry snapshotted together. Undo restores the world to before the encounter existed.


Last updated: 2026-10-12.

Clone this wiki locally