splinter-keep/session/book.md
Dejvino 4b9078d41f TUI now owns the full game loop with embedded LLM engine
The game is now self-contained: run.sh starts the TUI, which calls the
LLM directly via engine.py. No external agent (OpenCode) needed.

- tools/engine.py: Game engine with prompt builder, litellm client,
  response parser (JSON block extraction), and state persistence
- tools/run.py: Refactored TUI with PLAY/CHAR/LOG/BOOK tabs. PLAY tab
  has streaming narrative pane, dynamic choice buttons, and text input.
  Game loop: scene -> input -> resolve -> archive -> apply -> scene
- session/config.json: LLM provider configuration (model, api_key, etc.)
- AGENTS.md: Updated to document the new architecture
- tools/__init__.py: Package marker for clean imports
- session/turn_description.md, turn_reaction.md: Deprecated - no longer
  needed now that the TUI drives the game loop internally
2026-06-25 12:12:04 +02:00

238 lines
16 KiB
Markdown

## Turn — 2026-06-25
The common room of the Splintered Tankard hums with the low murmur of morning. Smoke coils from the hearth fire, mixing with the smell of barley stew and wet wool. Mistress Otta Venn moves between tables with the practised ease of a woman who has survived things — her curved knife catching the firelight as she passes.
Dillion sits near the stump of the enormous black tree that gives the tavern its name, finishing a bowl of thick porridge. He is a newcomer to the Keep — a mud-spattered walled town where two rivers meet beneath a granite outcrop. The faces around him are half hopeful, half haunted.
The morning bells ring — tinny and dissonant — and the Market Square beyond the tavern door begins to stir. A dead oak at the square's centre bears a notice board nailed with handbills and pleas.
Dillion drains his cup, leaves a few coppers on the table, and steps out into the Market Square. The board is crowded with papers curling at the edges.
Four notices catch his eye:
**Old mill at Three Bridges.** The miller vanished months ago. Neighbours report a clicking sound at night. Ask at Weber's Smithy. 5 silver offered.
**Vanished caravan.** A merchant caravan on the Eastern road. Cargo found intact. People gone. No tracks. 15 silver at the Guild Hall for information.
**Bones wanted.** Baron's hunters found a pit of bones in the Amber Hills. 2 silver per skeleton delivered to the Guild Hall.
**Lost signet ring.** Family heirloom. Ask at Fenna's Curios. Reward negotiable.
The mill job tugs at him — coin, and close enough to test his mettle. He heads for Weber's Smithy.
## Turn — 2026-06-25
Weber's Smithy clangs and hisses at the west edge of the Market Square. The smith himself is a hunchbacked man with forearms like hawsers, who carries on a constant low conversation with his hammer — a tool he calls "Bell."
"The old mill?" Weber grunts, not looking up from a glowing horseshoe. "Been dead ten years. Then three months ago, the clicking started. Gears turning on their own in the dead of night. Kids dare each other to go look. None of 'em go twice."
He offers 5 silver to investigate. Dillion haggles.
Dillion talks Weber up to 8 silver, plus a free mace sharpening if there's danger. They spit-shake on it.
In the Market Square, Dillion spots Lark — a scrawny errand boy with quick eyes and dirt-caked knees. The kid knows every shortcut in the Keep. For the promise of a share of loot, Lark spills what he knows: a loose board behind the mill's water wheel, scratching sounds from inside, and once — a dark shape moving past a cracked window.
Dillion grabs a pitchfork from a stall for Lark, and the two head east on the King's Road as the sun climbs toward noon.
## Turn — 2026-06-25
The old mill squats at Three Bridges where the Greywater bends east. Its wheel is half-rotted, motionless. The roof sags. Wind moans through gaps in the planking. The air smells of damp wood and something underneath — a sweet, acrid tang.
Through a grime-caked window, Dillion glimpses a dark shape. Motionless. Waiting.
Behind the water wheel, just as Lark said: a loose board, nails rusted half-through. Beyond it, darkness.
Dillion pries the board open — the nails give with a groan. He lights a torch, the flame pushing back a small circle of darkness, and crawls inside.
The storage room is thick with dust. Crates rot in the corners. And above — a rustle of dry sinew.
A creature drops from the ceiling. Pale skin, sinewy limbs, a mouth full of too many needles. It hisses and lunges.
Dillion's mace meets it mid-air. The impact crunches ribs — 2 damage, and the creature staggers. Before it can recover, Dillion brings the mace down on its skull. A wet crack, and it crumples. 5 damage — dead.
He cuts off an ear as proof for Weber, and finds the creature's gut holds 3 silver and a rusted iron key.
## Turn — 2026-06-25
The iron key fits an iron-bound chest in the corner. Inside: 12 silver, a silver locket holding a lock of auburn hair, and a bundle of love letters — from a woman named Marren to a woman named Elara. The later letters grow desperate. Someone was watching the mill. Someone in hoods.
Upstairs, the creature's nest: shredded cloth, gnawed bones, a scattering of coins. And a leather-bound journal. The miller's hand: cramped, sloping.
He'd trapped the creature in the cellar. Then the Guild came — stored something below. Then the hooded watchers arrived. The last entry is a single line:
*"They know I've seen it. I'll seal the hatch and pray."*
A clay jar sits beside the journal. Grey powder inside, and a note: *"For the lock. Sprinkle on the hasp."* A collapsed shelf hides a padlocked trapdoor in the floorboards.
Dillion sprinkles the grey powder on the padlock. The metal hisses, bubbles, and crumbles like chalk. He swings the trapdoor open and shouts into the darkness below — a taunt, a challenge.
Something answers. A smaller version of the pale creature scrabbles up the ladder. Dillion's mace takes its head off in a single blow — 7 damage. It twitches and stills.
He lights a fresh torch and drops it into the cellar. The light reveals an iron chest — and a woman, gaunt and filthy, shielding her eyes. Lark pats her down — clean. She says her name is Rina. A locksmith. Hired to crack the chest. Ambushed by hooded figures. Locked in for three days.
Dillion jumps down. The chest is empty — whatever was inside is gone. But on the floor lies a brass button bearing a crest: a closed fist gripping a gear. Beyond a crack in the wall, a natural tunnel slopes downward, its walls sweating moisture. The air moving through it smells of the river — it likely passes under the Greywater.
Dillion decides to head back to the Keep. Report to Weber. Get paid. Gear up Rina. The tunnel can wait.
## Turn — 2026-06-25
Back at the Keep, morning light washes the muddy streets. Dillion leads Rina and Lark through the Market Square, drawing a few glances — a blood-spattered man, a gaunt woman in a dead miller's coat, a grinning boy carrying a pitchfork.
At Weber's Smithy, the hunchback examines the creature's ear with a grunt of approval. He counts out 8 silver and sharpens Dillion's mace — the edge gleams, fresh and deadly. He eyes Rina. "She one of Fenna's lot?"
At the Splintered Tankard, Otta takes one look at Rina and ushers her to the back for a bath and clean clothes. Dillion has a pocket of time.
Dillion hits the Market Square. He buys 6 fresh torches and 5 days of rations. He pays Lark 5 silver for his help — the boy pockets it with a wide grin and disappears into the crowd.
Rina emerges from the Tankard's back room scrubbed pink, wearing a patched shirt and breeches that Otta found for her. Over a bowl of stew, she lays out her skills: locks, traps, a steady hand with a crossbow, and the quiet nerves of someone who has worked in the dark before.
Dillion takes her to Weber's for a light crossbow, then to a stall for a padded leather vest. Armed and armoured, Rina nods — ready.
They buy two long ropes and head east on the King's Road as the sun begins its afternoon slope. The mill waits. The tunnel waits. And somewhere below, whatever the Guild was hiding.
## Turn — 2026-06-25
The mill is quiet as they slip through the loose board and descend into the cellar. The bodies of the creatures still lie where they fell. The crack in the wall breathes cool, damp air.
Dillion goes first, torch high. The tunnel slopes steadily down, rough-hewn at first, then opening into a natural cavern. The ceiling pulses with bioluminescent fungi — pale blue light that throws no shadows. The air thickens with the smell of damp stone, blood, and something sharp — mint? Medicine?
A stone door stands on the far wall, carved with the fist-and-gear crest. It sits slightly ajar.
Beyond it: a chamber. A tall construct of grey stone stands motionless — red eyes fixed on the entrance. It wears tattered cloth and rusted armour. It watches. It does not attack.
Rina spots a tripwire at ankle height. They step over it and edge along the wall toward a left-hand corridor. The construct's red eyes track them, but it does not move.
The corridor leads to an iron-banded wooden door with a heavy lock. Rina's picks are quiet. The lock clicks open.
Beyond: a storage room. Two men — one bearded, one scarred — sit playing cards on an upturned crate. Crossbows lean against the wall.
Dillion and Rina slip behind a stack of crates. The guards haven't seen them.
Dillion catches Rina's eye. She nods — she's ready. On his signal, she rises and looses a bolt. It takes Scar through the neck — he gurgles and drops, dead before he hits the floor.
Beard lunges for his crossbow. Dillion is faster — his mace catches the man across the throat. A wet crunch. Beard joins his partner.
Silent. Clean.
They drag the bodies into the shadows. Search yields: 19 silver, a brass key ring with two keys, and a handbill bearing the fist-and-gear crest — a list of names with "Kellis — LATE" scrawled beside one.
Rina finds a stack of delivery manifests and a folded note: *"The Weeper is restless. Bring another before the Chime. — H."*
An iron-reinforced door stands at the far end. Dillion listens — nothing. He rigs a rope from behind the crates and opens it from a safe distance. Beyond: darkness, and a tunnel sloping deeper into the earth.
The air grows warmer, wetter. A sound emerges from the dark ahead — slow, rhythmic breathing. Not human.
The tunnel opens into a chamber with a pit at its centre. Chains descend into the darkness. The breathing comes from below. On the far side, a second iron door.
Dillion and Rina skirt the pit, keeping to the wall. Whatever is down there does not stir.
Beyond the far door: a short hallway ends in a heavy velvet curtain. Warm light glows at its edges. A voice chants in a low rhythm — words Dillion doesn't recognise.
Dillion parts the curtain a finger's width. A study. A chalk circle on the floor, candles at each cardinal point. A dagger at the centre, its blade dark with old blood. A figure in a hooded robe stands over it, chanting.
A weaver. Working something.
Dillion lets the curtain fall and steps back to consult Rina.
## Turn — 2026-06-25
You pull back from the velvet curtain, your heart hammering. Rina watches you, crossbow raised, eyes asking the question.
You motion her closer, pressing your back to the damp stone wall. The chanting continues beyond the curtain — a low, rhythmic murmur in a language you don't recognise. Male voice. Steady. Building toward something.
*The room beyond:* Warm candlelight. A chalk circle on the floor — intricate, layered symbols spiralling inward to a centre where a curved dagger rests on what looks like a folded piece of cloth. Shelves along the walls crammed with jars, scrolls, bones. A low wooden table with an open book, a smoking censer, and a human skull.
And the weaver himself — you caught only a glimpse. Dark robes. Seated cross-legged before the circle, hands raised, chanting.
The corridor continues past the curtain — you saw it curve to the right before you pulled back. Another door, maybe, or another chamber.
Rina whispers: *"That's blood magick. I've seen the signs before. He's not just praying — he's winding something up. If he finishes..."*
She looks at you, waiting.
Waits and deliberates, weighing the risk of waiting for the ritual to finish against the danger of interrupting a blood-weaver mid-chant.
## Turn — 2026-06-25
The weaver's voice rises to a shout — a single word, sharp and resonant. The candle flames all gutter at once, then flare back a deep, pulsing red. A low thrum vibrates through the stone under your boots.
Through the gap in the curtain, you see the dagger in the circle begin to glow — a dull, hungry orange, like iron pulled from a forge. The weaver's hands tremble as he holds them over the blade, chanting faster now, sweat gleaming on his face.
Rina's fingers brush your arm. She points — past the curtain, where the corridor curves right. A heavy wooden door, banded in iron. The same crest: a fist gripping a gear.
The weaver's chant is building toward its final note. The dagger pulses brighter. Whatever he's summoning is almost here.
You have seconds.
Decides to hide and wait. Slipping into the weaver's study behind shelves and furniture, Dillion and Rina watch as the ritual reaches its peak and something begins to take shape in the chalk circle.
## Turn — 2026-06-25
The light in the chalk circle collapses inward, then explodes outward in a wave of heat and pressure. The weaver stumbles back, arms shielding his face.
Where the dagger lay, a figure now stands.
It is man-shaped, but wrong — tall and gaunt, skin the colour of old ash. A jagged blade protrudes from its own chest, driven in at an angle, crusted with dried black blood. Deep wounds crater its torso and arms — some fresh, some scarred. Its eyes open. They have no pupil, only a dull orange glow, like embers guttering in a dead fire.
The temperature in the room drops. Frost spiderwebs across the stone floor from the demon's feet. The candles gutter blue again, then die. Only the orange glow of the demon's eyes lights the room.
The weaver stares, breathless, a grin spreading across his face. *"It worked... it actually worked..."*
The demon's head turns — slowly — toward the weaver. Then toward the shelf where Rina hides. Then toward the table.
*A damned thing. Summoned. Wounded. Looking for something to defend — or destroy.*
Rina's fingers tighten on her crossbow. She's frozen, waiting for your signal.
Signals Rina to hold steady. They watch as the weaver tries to command the summoned demon — it resists, kills him, and now stands in the dark, aware it is not alone.
## Turn — 2026-06-25
Silence. Just the drip of moisture somewhere in the tunnel, and the slow, wet breathing of the demon.
It takes a step toward the shelves — toward Rina. Its bare foot leaves a frozen print on the stone. The blade in its chest grinds with every movement. Its orange eyes sweep the jars, the scrolls, the shadows.
It stops. Tilts its head.
*A low, guttural voice, like stones grinding together:* **"I smell you."**
Rina's hand drifts to her crossbow.
The demon turns — slowly — toward the table where Dillion crouches. Its cracked lips peel back from teeth that are too long, too many. The cold intensifies. Your breath fogs.
**"Fresh meat. Wrapped in leather and fear."**
It takes another step. Then another. The frost crawls up the table legs.
## Turn — 2026-06-25
The demon stands over you, frost crackling across its scarred hide. The blade in its chest glints in the dim orange light of its eyes. It's close — too close — but it's wounded, slow, and you still have your mace.
Rina yanks the string of her crossbow, slotting a fresh bolt with trembling fingers. *"Buy me three seconds!"*
The demon's lips peel back. **"The warm one first. Then the other."** It raises a hand — the same hand that froze your chest — and the temperature in the room plummets again.
You have a split second. The mace is heavy in your grip — freshly sharpened, never used since Weber's stone. It wants to bite.
## Turn — 2026-06-25
The demon plants its feet, frost spiderwebbing across the floor. Its eyes fix on you — then dart to Rina, crossbow raised. It's weighing which of you to strike first.
Rina's voice, low and steady: *"Say the word. I'll put one through its eye."*
The demon's lips curl. **"The crossbow won't save you, little thing. I've been killed before. It didn't stick."** It takes a step toward Rina, testing.
You're between them. Mace in hand. Blood still cold where it touched you.