Files
vegvisir/vegvisir-spec.md
T
stefwill c0ef70d7fe docs: add build spec, TODO, and encounter table sources
- 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)
2026-07-04 20:06:03 +10:00

12 KiB
Raw Blame History

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

  1. User selects a scene type — or, for travel, selects a journey (origin → destination); see Journey Flow below.
  2. Tool rolls across relevant RQG-derived tables for that scene type and returns a few options at once (mixed: encounter / cultural detail / NPC quirk).
  3. User picks one (or none).
  4. GM layer resolves the picked encounter as a full mini-encounter: makes RQG skill/combat rolls against character stats, narrates outcomes.
  5. User saves the resolved result to a favourites list.
  6. 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:

  1. Homeland — Stef's own regions in place of Dragon Pass homelands.
  2. Family History — Stef's own calendar/history in place of Gloranthan years; same year-by-year event-roll structure.
  3. Rune Affinities — Runes/Elements kept as a mechanical system (not Glorantha-specific in structure); tied into characteristic modifiers as per RQG.
  4. 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.
  5. Occupation — reflavored occupation table (Warrior, Farmer, Healer, Merchant, etc. — renamed/adjusted to fit Stef's cultures).
  6. Kinship (RQG's "Cult") — Stef's own pantheon/Kinships in place of Gloranthan cults. Grants Common Rune Magic access (see Magic below).
  7. Personal Skill Bonuses.
  8. Other Information — gender, name, age, handedness, scars, family, tribe/settlement/clan, heirloom, starting reputation, movement.
  9. Passions (RQG) — directed emotional intensities (e.g. Loyalty [X], Hate [Y], Love [Z]), scored by %. Used for Augmentation on relevant skill rolls.
  10. 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: 34 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)

  1. User selects origin, destination, and mode of travel (walking / running / horseback / etc.).
  2. 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).
  3. 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.
  4. 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).
  5. 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.
  6. 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 7B14B 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)

  1. 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)
  2. Export format — resolved: downloadable file.
  3. Tagging — resolved: scene type + danger level (low/med/high). Tone dropped — subjective, redundant with scene type.
  4. Character stats supply — resolved: full chargen, editable/re-rollable rolls (see Character source note above).
  5. Spirit Magic list — resolved: Stef digitizes the Magic book before coding starts. No fallback/task queuing needed here.
  6. 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.
  7. 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