Mørkyn 0.9.0
Mørkyn is a local-first browser RPG: a local LLM narrates turns and proposes structured world changes, while SQLite stays the source of truth.
0.9.0 moves the decisions a 7B keeps getting wrong out of the model and into the server, then verifies each one against a live local model.
Install
Download start.bat (Windows) or start.sh (Linux / macOS) from the assets below, drop it in an empty folder, and run it. Nothing else to fetch first.
Windows double-click start.bat
Linux / macOS bash start.sh
It clones the project, builds a private .venv, installs the dependencies and starts the game. Every run after that checks for updates and asks before applying them — answer no and it starts the copy you already have. Offline, it skips the check and starts anyway. It will not touch a checkout that has local changes or local commits.
--full also installs llama-cpp-python for the built-in GGUF server; the default install leaves it out, because its CUDA wheels are a large download that fails without a matching toolchain and neither Ollama nor the cloud APIs need it. --update and --no-update skip the prompt in either direction; --help lists everything.
Requires Git and Python 3.11+. Verified from empty folder to a served UI on Windows 11 and on Alpine 3.23 (musl, Python 3.12).
Server-rolled dice
The model writes a band — trivial, small, large — and the app rolls the amount, scaled by level, difficulty and growth settings. Every roll is audited in dice_rolls. Deterministic blake2b seeding means a rewind reproduces the same dice.
Content packs
JSON files that add, retune or remove skills, powers, items and tables with no code changes. Drop one in data/packs/. GET /api/content-packs/authoring-bundle returns a self-contained spec you can hand to any LLM to author content.
Venues
Shops, inns, forges and temples are real places you walk into and back out of.
A venue is a locations row whose parent_id is the place you enter it from, so entering is an ordinary move and everything downstream — visit counts, entity codes, the map, export/import — keeps working. On top of that:
- Opening hours against the world clock, wrap-aware (a tavern open 11:00–02:00 is open at 01:00, shut at 03:00).
- Containment: you enter a shop from the street outside it. Naming one from two locations away walks you to its door; going in costs the next turn.
- Commonality: a hamlet has no apothecary, a town has no counting house, and each kind is capped per settlement.
- A keeper who stays the same person.
What this replaced: a probe walked into an apothecary, talked to the keeper, stepped out and went back in — and the database recorded one location and zero movement for all four turns. Asking to return from two locations away minted an unrelated top-level Apothecary and teleported the player inside it, at night. The keeper was a man, then a woman, then a different man.
Continuity
Movement, narrative person and NPC identity are server contracts with deterministic repair rather than things the model is asked to remember. A doorway turned out to be the move the model reliably narrates and reliably fails to record, so movement repair gained venue_enter / venue_exit / venue_opened / venue_return.
Encounters
Travel, wait and rest danger now accounts for stats, skills, wounds, fatigue, carried load, terrain, weather and time of day. Participant counts and threat are rolled server-side.
Setup and backstory
- A character you wrote as native is no longer rewritten into an isekai one. Origin classification is scored instead of first-hit — "a compound clerk who tallies grain fees at the gate office" was matching "office" and being rewritten.
- The stitch path now keeps the former life you wrote instead of drawing a fresh one.
- Backstory rewrites are seeded by blake2b.
abs(hash(text))made every repair identical within a run and irreproducible across runs.
Also in this release
Character art hires/upscale path with LoRA persistence, and Simple Start setup fixes so expand/compose stops clobbering surface edits. 16 proof harnesses under tools/, all passing.
Verified
355 unit and regression tests plus 7 behavior checks, passing and order-independent. Live probes against a local qwen2.5:7b-instruct for narration quality, movement, continuity and venues. The schema migration was checked against a hand-built pre-venue database with its rows intact.
Not verified
The browser UI was not exercised end to end in this pass, and it has no venue awareness — entering a shop changes the location name the UI already shows, but there is no "shops here" list and no open/closed indicator. Venues reach the player through prose and the location name only.
Upgrading
The locations schema gains six additive columns (parent_id, kind, open_minute, close_minute, settlement_size, keeper_npc_id). Existing saves migrate in place on first launch; nothing is dropped. Export your world first if you want a rollback point.
Run python tools/make_debug_save.py for an importable world that already has gold, equipped items, a locked ability, part-spent resources and three venues on one square — useful for testing without burning a setup.