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.
This commit is contained in:
2026-09-13 16:41:20 +08:00
parent 6607ab1db3
commit 77ed233f8c
9 changed files with 146 additions and 0 deletions
+14
View File
@@ -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/<name>/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 <name>`.
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.
+7
View File
@@ -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
1 min max text tags
2 1 1 The Seeker — you left a safe life chasing a rumour seeker
3 2 2 The Warden — you are sworn to protect something you no longer trust warden
4 3 3 The Exile — you were cast out and have not stopped running exile
5 4 4 The Artisan — your hands make things that outlive you artisan
6 5 5 The Witness — you saw something you were never meant to see witness
7 6 6 The Debtor — someone paid for your life, and the bill is due debtor
+47
View File
@@ -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 <name>
```
| 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 <name>`
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.
+31
View File
@@ -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,
},
},
};
+14
View File
@@ -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:*"
}
}
+7
View File
@@ -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.
+12
View File
@@ -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 <name>`, 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.
@@ -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
1 min max text tags
2 1 1 A past debt comes due obligation
3 2 2 An ally's hidden motive surfaces npc
4 3 3 The environment turns hostile environment
5 4 4 A resource runs out at the worst time resource
6 5 5 Someone else wants the same thing rival
7 6 6 A truth is revealed that reframes the goal revelation
+7
View File
@@ -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
1 min max text tags
2 1 1 A sign of recent passage exploration
3 2 2 Something out of place mystery
4 3 3 A sound that does not belong tension
5 4 4 A memory surfaces unbidden character
6 5 5 A stranger with an offer npc
7 6 6 A chance to change the plan opportunity