- vegvisir-spec.md: full build spec (core flow, chargen subsystem, GM layer, world model, journey flow, data compilation pipeline) - TODO.md: spec broken into 8 sequential build phases - docs/: Norse-flavoured and general random encounter tables (authoring source for the compile step)
12 KiB
Vegvísir — Build Spec
Purpose
Standalone tool acting as a rules-aware GM to generate and resolve flavour encounters between major story beats in a fantasy manuscript. Ruleset is RQG (RuneQuest: Roleplaying in Glorantha) mechanics — not the Glorantha setting. Setting-specific RQG content (homelands, cults, family-history years, geography) is reflavored to Stef's own Norse-flavoured world during digitization; only the mechanical framework (procedures, dice math, tables' structure) is carried over as-is.
Core Flow
- User selects a scene type — or, for travel, selects a journey (origin → destination); see Journey Flow below.
- Tool rolls across relevant RQG-derived tables for that scene type and returns a few options at once (mixed: encounter / cultural detail / NPC quirk).
- User picks one (or none).
- GM layer resolves the picked encounter as a full mini-encounter: makes RQG skill/combat rolls against character stats, narrates outcomes.
- User saves the resolved result to a favourites list.
- Favourites persist across sessions, organized by scene type.
GM Layer
- Rules-aware, not just narration — uses actual RQG mechanics (skill checks via the Ability Results Table, combat resolution, opposed rolls via the Resistance Table, Augmentation, reaction rolls) to adjudicate outcomes.
- Needs access to character stats (characteristics, skills, Runes, Passions, Personality Traits) to make rolls against.
- Scope: full mini-encounter resolution (e.g. a combat encounter plays out roll-by-roll to an outcome, a skill challenge resolves with success/failure/degree).
Character source (subsystem — scope note)
Full RQG-derived character generator, reflavored to Stef's setting. Procedure follows RQG's chargen sequence, with setting-specific steps substituted:
- Homeland — Stef's own regions in place of Dragon Pass homelands.
- Family History — Stef's own calendar/history in place of Gloranthan years; same year-by-year event-roll structure.
- Rune Affinities — Runes/Elements kept as a mechanical system (not Glorantha-specific in structure); tied into characteristic modifiers as per RQG.
- Characteristics — seven stats: STR, CON, SIZ, INT, POW, DEX, CHA (RQG drops APP in favour of CHA vs RQ3). Derived: Magic Points, Hit Points (+ hit locations), Healing Rate, Damage Bonus, Max ENC, Strike Rank, Skill Category Modifiers.
- Occupation — reflavored occupation table (Warrior, Farmer, Healer, Merchant, etc. — renamed/adjusted to fit Stef's cultures).
- Kinship (RQG's "Cult") — Stef's own pantheon/Kinships in place of Gloranthan cults. Grants Common Rune Magic access (see Magic below).
- Personal Skill Bonuses.
- Other Information — gender, name, age, handedness, scars, family, tribe/settlement/clan, heirloom, starting reputation, movement.
- Passions (RQG) — directed emotional intensities (e.g. Loyalty [X], Hate [Y], Love [Z]), scored by %. Used for Augmentation on relevant skill rolls.
- Personality Traits (Pendragon-style, new addition) — classic opposed trait pairs (e.g. Merciful/Cruel, Honest/Deceitful, Generous/Selfish, Energetic/Lazy, Forgiving/Vengeful, Just/Arbitrary, Modest/Proud, Pious/Worldly, Prudent/Reckless, Temperate/Indulgent, Trusting/Suspicious, Valorous/Cowardly), each pair scored to 20. Not directed at anything specific — used by the GM layer to resolve ambiguous character behavior during encounter resolution (trait roll settles "would this character do X" instead of the player/GM deciding manually). Distinct from and complementary to Passions, not a replacement.
All rolls (chargen, Passions, Traits) must be user-editable/re-rollable after generation, not just at creation — implies a persistent, mutable character sheet, not a one-shot roll script.
This is a distinct subsystem from the flavour roller and GM layer. Treat as its own build phase: (1) chargen engine + editable sheet, (2) GM layer reads from that sheet.
Subsystem detail (v1 scope)
- Combat: full detail — strike ranks, hit locations, damage, resolved round-by-round until the encounter ends.
- Non-combat skill checks: simple — single roll against the Ability Results Table, pass/fail with degree of success, brief outcome (no strike ranks/rounds).
- Spirit Magic: characters can cast during resolution (combat or skill), consuming MP per RQG rules. Spell list to be digitized by Stef before coding starts (same pipeline as other tables).
- Rune Magic (now in scope): tied to Kinship membership (RQG's Common Rune Magic model). Characters spend Rune points from their Kinship's pool. Kinship-specific Rune spell lists to be digitized alongside the Kinship/pantheon content.
- Opposed checks (vs NPCs/environment): full Resistance Table where applicable, not flat skill %.
- Augmentation: relevant Passions can boost/hinder a skill roll per RQG's augmentation rules.
- Personality Trait checks: used mid-resolution when the encounter hinges on ambiguous character behavior rather than a mechanical roll.
- Out of scope for v1: Sorcery, Divine Intervention — flag as future extension if needed.
Scene Types (v1)
- Travel / Wilderness — now driven by Journey Flow (open-road legs), not manual pick.
- Tavern / Settlement — now driven by World Model (district checks), not manual pick.
- Combat / Danger — manual pick, standalone.
- Social / NPC — manual pick, standalone.
Data Compilation (build step)
- Markdown tables (RQG-derived rules, flavour tables, movement rates, NPC tables, Spirit Magic list, Kinship/Rune Magic lists, Occupation table) are the authoring source only — used once at compile time, then deleted. Compiled code becomes the source of truth; no markdown parsing at runtime.
- Personality Trait pair list is separately authored (not sourced from RQG digitization — it's a Pendragon-style addition) but compiled the same way.
- One-time compile script converts markdown → typed TS data files (e.g.
movementRates.generated.ts,flavourTables.generated.ts,runeMagic.generated.ts), clearly marked as generated/do-not-edit. - Hand-written TS files hold lookup/resolution logic (e.g. movement rate lookup, table roll functions, Resistance Table lookup) and import the generated data — generated data and hand-written logic stay in separate files.
- Applies to all tables: flavour/encounter tables, movement rates, NPC generation tables, Spirit Magic spell list, Rune Magic spell lists, Occupation table, Personality Trait pairs.
- If source markdown changes later, re-run the compile script to regenerate; no live re-parsing.
Requirements
- Source content: markdown tables in
docs/are compiled once into typed TS data (see Data Compilation) — app runs entirely off compiled code, no runtime markdown dependency. - Roll output: 3–4 options per roll, mixed category, tagged by scene type.
- Save/favourites: persistent storage across sessions, grouped by scene type, viewable/browsable list.
- Export: downloadable file (markdown dump of favourites, grouped by scene type).
- No chat interface — this is a quick roll/generate tool, not a conversational assistant.
World Model
Locations
- Name, type (Settlement / Wilderness Point / Dungeon / Landmark — maps to scene types), distinguishing features (freeform notes/tags).
- Settlements decompose into Districts (see below); other location types are atomic (no sub-zones).
Districts (settlement sub-locations)
- Name (e.g. "Market Quarter", "Docks", "Noble Ward").
- Danger level: none / low / med / high.
- Own NPC pool, scoped to the district (not the whole settlement).
- Encounter checks are manually triggered — user clicks "check" while in a district, tool rolls a chance weighted by that district's danger level (no timer, no fixed cadence).
Paths
- From location, to location.
- Distance — kilometres (stored value; not travel time directly).
- Mode of travel — walking / running / horseback / etc., per RQG movement/travel rules (already digitized — pull rates from that source rather than hardcoding).
- Travel time computed: distance ÷ movement rate for selected mode, per RQG rules.
- Danger level: none / low / med / high.
- Terrain/notes (freeform).
- If no direct path exists between two locations, the tool routes through intermediate locations and sums travel time across legs (multi-leg journeys in scope for v1).
NPCs
- Scoped to a location or a district.
- Reuses existing NPC generation fields (six rolled fields; filler NPCs use first three, per existing narrative-app spec).
- Presentation: both a random draw (like flavour rolls) and a browsable list are available — user's choice per interaction.
Journey Flow (replaces scene-type picking for travel)
- User selects origin, destination, and mode of travel (walking / running / horseback / etc.).
- Tool resolves the route (direct path, or multi-leg via intermediate locations) and computes total travel time from summed distance and the RQG movement rate for the selected mode (mode can change per leg if needed).
- Encounter rolls during travel:
- Open road legs: fixed cadence, one roll per day of travel.
- Within a settlement (district-to-district): no fixed cadence — user manually triggers a check per district, chance weighted by that district's danger level.
- Each triggered roll surfaces the usual mixed flavour options (encounter / cultural detail / NPC quirk), tagged by scene type (derived from location/path type) and danger level (from the path or district).
- GM layer resolves the picked option as before (full combat, simple skill check, etc.), reading from the active character sheet(s), including Augmentation from Passions and Personality Trait checks where relevant.
- Resolved results save to favourites as before, still grouped by scene type; danger level tag carries through for filtering.
Danger check probabilities
- Defaults, tunable in config: none 0%, low 15%, med 35%, high 60%.
Narration Layer (local LLM, optional)
- Mechanical resolution (rolls, checks, combat) stays deterministic code — no LLM involvement.
- Narration only: mechanical result → prose paragraph, via local Ollama instance (OpenAI-compatible endpoint,
localhost:11434). - Model name configurable (whatever's pulled locally).
- Fallback: plain templated text if Ollama unreachable or output unusable. Local 7B–14B models are inconsistent — template fallback keeps tool usable regardless.
- Keeps the tool fully local/offline-capable, consistent with self-hosted stack.
Open Questions (resolve before/during build)
- Seed source: markdown table files will live in
docs/at project root once set up. ← structure (headers, column format) still needed once files exist, including new RQG-derived tables (Rune Magic, Occupation, Resistance Table, Ability Results Table) Export format— resolved: downloadable file.Tagging— resolved: scene type + danger level (low/med/high). Tone dropped — subjective, redundant with scene type.Character stats supply— resolved: full chargen, editable/re-rollable rolls (see Character source note above).Spirit Magic list— resolved: Stef digitizes the Magic book before coding starts. No fallback/task queuing needed here.- Homeland/Kinship/Occupation reflavoring — Stef supplies replacement content (own regions, own pantheon/Kinships, adjusted occupation names) alongside digitization; mechanical structure (modifiers, table shape) stays RQG-derived.
- Personality Trait pair list — confirm final set of opposed pairs and starting-score generation method (rolled vs. assigned) before build.
Explicitly Out of Scope (v1)
- Fresh OCR/extraction from the physical book
- Chat-style generation
- Category selection separate from scene type
- Sorcery, Divine Intervention (magic systems)
- Using Glorantha as the actual setting — RQG is a mechanics source only