Skip to content

Mørkyn 0.9.0

Choose a tag to compare

@Stelliro Stelliro released this 20 Aug 13:58
· 52 commits to main since this release

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 bandtrivial, 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.