From 77ed233f8c7e54c1fed0259c8fdda9141586e115 Mon Sep 17 00:00:00 2001 From: hypercross Date: Sun, 13 Sep 2026 16:41:20 +0800 Subject: [PATCH] feat(games): add the generic d6 oracle game package Serves as the reference implementation of the game package contract: rules, spark tables, character backgrounds, and an example command. --- games/generic/characters/README.md | 14 ++++++ games/generic/characters/backgrounds.csv | 7 +++ games/generic/game.md | 47 ++++++++++++++++++++ games/generic/index.js | 31 +++++++++++++ games/generic/package.json | 14 ++++++ games/generic/rules/README.md | 7 +++ games/generic/scripts/README.md | 12 +++++ games/generic/tables/complication-themes.csv | 7 +++ games/generic/tables/sparks.csv | 7 +++ 9 files changed, 146 insertions(+) create mode 100644 games/generic/characters/README.md create mode 100644 games/generic/characters/backgrounds.csv create mode 100644 games/generic/game.md create mode 100644 games/generic/index.js create mode 100644 games/generic/package.json create mode 100644 games/generic/rules/README.md create mode 100644 games/generic/scripts/README.md create mode 100644 games/generic/tables/complication-themes.csv create mode 100644 games/generic/tables/sparks.csv diff --git a/games/generic/characters/README.md b/games/generic/characters/README.md new file mode 100644 index 0000000..d1f3883 --- /dev/null +++ b/games/generic/characters/README.md @@ -0,0 +1,14 @@ +# Character backgrounds + +The game's menu of character options: backgrounds, playbooks, and starting +packages. Campaigns do not copy these files — the *actual* PC sheet lives in +`campaigns//characters/`. This directory is where the options come from. + +## Files + +- `backgrounds.csv` — rollable starting backgrounds (`min,max,text,tags`). + Roll one with `journal background --campaign `. + +Add more files here for playbooks, archetypes, or species. If a file should be +rollable through `journal roll`, put it in `tables/` instead; files here are +read by game commands or by the agent directly. diff --git a/games/generic/characters/backgrounds.csv b/games/generic/characters/backgrounds.csv new file mode 100644 index 0000000..c483f93 --- /dev/null +++ b/games/generic/characters/backgrounds.csv @@ -0,0 +1,7 @@ +min,max,text,tags +1,1,"The Seeker — you left a safe life chasing a rumour",seeker +2,2,"The Warden — you are sworn to protect something you no longer trust",warden +3,3,"The Exile — you were cast out and have not stopped running",exile +4,4,"The Artisan — your hands make things that outlive you",artisan +5,5,"The Witness — you saw something you were never meant to see",witness +6,6,"The Debtor — someone paid for your life, and the bill is due",debtor diff --git a/games/generic/game.md b/games/generic/game.md new file mode 100644 index 0000000..b82a705 --- /dev/null +++ b/games/generic/game.md @@ -0,0 +1,47 @@ +# Generic d6 Oracle + +System-agnostic solo play. No stats are required: the fiction and the d6 carry +the game. Use this as a base for a setting, or as the reference for how a game +package is structured. + +## Resolution + +Ask the oracle one yes/no question at a time: + +``` +journal oracle "Is the bridge still standing?" --campaign +``` + +| d6 | Result | Meaning | +|----|--------|---------| +| 6 | **Yes, and…** | It works, with a fortunate extra. | +| 5 | **Yes** | It works, plainly. | +| 4 | **Yes, but…** | It works, at a cost. | +| 3 | **No, but…** | It fails, with an opening. | +| 2 | **No** | It fails, plainly. | +| 1 | **No, and…** | It fails, and something gets worse. | + +On `and`/`but` results, pass `--complicate` to fold in a twist. + +## The PC + +Keep a minimal sheet: name, background, inventory, and any lasting conditions. +`stats` and `tracks` may stay empty. If a stat grows out of play, record its +shape in the campaign's `house-rules.md` so it stays consistent. + +## Character creation + +1. Roll a background: `journal background --campaign ` +2. Give the PC a name and one relationship to the world. +3. Write a starting situation into `campaign.md`. + +## Pacing + +End a scene when the situation changes or the player's intent resolves. Append +scenes; never rewrite them. + +## Content + +- `tables/sparks.csv` — general content prompts. +- `tables/complication-themes.csv` — twists on `and`/`but` results. +- `characters/backgrounds.csv` — rollable starting backgrounds. diff --git a/games/generic/index.js b/games/generic/index.js new file mode 100644 index 0000000..b949bea --- /dev/null +++ b/games/generic/index.js @@ -0,0 +1,31 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { parseTable, rollTable } from '@solo/oracle'; + +const HERE = path.dirname(fileURLToPath(import.meta.url)); + +/** Roll a starting background from characters/backgrounds.csv. */ +function background() { + const file = path.join(HERE, 'characters', 'backgrounds.csv'); + const entries = parseTable(fs.readFileSync(file, 'utf8')); + const { roll, entry } = rollTable(entries); + const tags = entry.tags.length ? ` [${entry.tags.join(', ')}]` : ''; + console.log(`background roll ${roll} → "${entry.text}"${tags}`); +} + +/** + * A game package's default export is its manifest. See docs/games.md. + */ +export default { + id: 'generic', + title: 'Generic d6 Oracle', + description: 'System-agnostic solo play driven by the d6 oracle and spark tables.', + rules: 'game.md', + commands: { + background: { + description: 'Roll a starting character background.', + run: background, + }, + }, +}; diff --git a/games/generic/package.json b/games/generic/package.json new file mode 100644 index 0000000..27f74d6 --- /dev/null +++ b/games/generic/package.json @@ -0,0 +1,14 @@ +{ + "name": "@solo/game-generic", + "version": "0.0.0", + "private": true, + "type": "module", + "description": "System-agnostic d6 oracle play for solo journaling.", + "main": "index.js", + "exports": { + ".": "./index.js" + }, + "dependencies": { + "@solo/oracle": "workspace:*" + } +} diff --git a/games/generic/rules/README.md b/games/generic/rules/README.md new file mode 100644 index 0000000..5decfbc --- /dev/null +++ b/games/generic/rules/README.md @@ -0,0 +1,7 @@ +# Rulebook + +Longer-form rules content for this game, one markdown file per topic +(`resolution.md`, `harm.md`, `advancement.md`, ...). + +`game.md` is the authoritative summary the agent reads before every session. +The chapters here expand on it and are read on demand. diff --git a/games/generic/scripts/README.md b/games/generic/scripts/README.md new file mode 100644 index 0000000..71dfa91 --- /dev/null +++ b/games/generic/scripts/README.md @@ -0,0 +1,12 @@ +# Tool scripts + +Game-specific tooling lives here. There are two ways to ship it: + +1. **CLI commands** — export a `commands` map from the game's `index.js`. The + `journal` CLI exposes each entry as `journal `, with the shared dice + and table helpers passed in. This is the recommended path for anything the + agent calls during play (see `../index.js` for the `background` example). +2. **Standalone scripts** — drop one-off executables in this directory, for + jobs like importing content or converting data, and run them with `node`. + +See `docs/games.md` for the full contract. diff --git a/games/generic/tables/complication-themes.csv b/games/generic/tables/complication-themes.csv new file mode 100644 index 0000000..ca8b90f --- /dev/null +++ b/games/generic/tables/complication-themes.csv @@ -0,0 +1,7 @@ +min,max,text,tags +1,1,"A past debt comes due",obligation +2,2,"An ally's hidden motive surfaces",npc +3,3,"The environment turns hostile",environment +4,4,"A resource runs out at the worst time",resource +5,5,"Someone else wants the same thing",rival +6,6,"A truth is revealed that reframes the goal",revelation diff --git a/games/generic/tables/sparks.csv b/games/generic/tables/sparks.csv new file mode 100644 index 0000000..4a0b81e --- /dev/null +++ b/games/generic/tables/sparks.csv @@ -0,0 +1,7 @@ +min,max,text,tags +1,1,"A sign of recent passage",exploration +2,2,"Something out of place",mystery +3,3,"A sound that does not belong",tension +4,4,"A memory surfaces unbidden",character +5,5,"A stranger with an offer",npc +6,6,"A chance to change the plan",opportunity