{"id":51441500,"url":"https://github.com/rc-ventura/fantasy-gamebook-engine","last_synced_at":"2026-07-05T12:01:38.363Z","repository":{"id":366467733,"uuid":"1276408944","full_name":"rc-ventura/fantasy-gamebook-engine","owner":"rc-ventura","description":"Solo-play Fighting Fantasy-style gamebook engine: an AI Game Master narrates while all randomness, state, and combat go through an MCP server (the AI never rolls dice in prose). Phase-1 MVP, 158 tests.","archived":false,"fork":false,"pushed_at":"2026-06-30T20:38:27.000Z","size":1943,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-30T22:17:57.111Z","etag":null,"topics":["claude-code","fantasy-gamebook","mcp-server"],"latest_commit_sha":null,"homepage":"https://rc-ventura.github.io/grimoire-claude-code/fantasy-gamebook/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rc-ventura.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-22T00:15:39.000Z","updated_at":"2026-06-23T17:20:33.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rc-ventura/fantasy-gamebook-engine","commit_stats":null,"previous_names":["rc-ventura/fantasy-gamebook-engine"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rc-ventura/fantasy-gamebook-engine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rc-ventura%2Ffantasy-gamebook-engine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rc-ventura%2Ffantasy-gamebook-engine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rc-ventura%2Ffantasy-gamebook-engine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rc-ventura%2Ffantasy-gamebook-engine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rc-ventura","download_url":"https://codeload.github.com/rc-ventura/fantasy-gamebook-engine/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rc-ventura%2Ffantasy-gamebook-engine/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35153109,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-05T02:00:06.290Z","response_time":100,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["claude-code","fantasy-gamebook","mcp-server"],"created_at":"2026-07-05T12:01:37.651Z","updated_at":"2026-07-05T12:01:38.357Z","avatar_url":"https://github.com/rc-ventura.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fantasy Gamebook Engine\n\nA solo-play **gamebook** (Fighting Fantasy–style) engine where an AI acts as the\ngame master and narrator. The whole design turns on one hard rule:\n\n\u003e **The AI never invents numbers or rolls dice in prose.** All randomness, state, and combat\n\u003e math go through an MCP server. The AI only narrates and offers choices.\n\nEverything numeric — dice, attribute generation, luck tests, combat rounds, persistence — is\nowned by a deterministic Python engine and exposed to the narrator as **MCP tools**. The\nnarrator (Phase 1: Claude Code) reads real state, calls tools, and writes the story around the\nresults.\n\n**Status:** Phase-1 MVP — implemented and green. Python engine under `src/gamebook/`, an MCP\nserver exposing **18 tools**, **158 passing tests** at **96% coverage** across `tests/engine`,\n`tests/server`, and `tests/qa`. The narrator harness lives as Claude Code skills and commands\nunder `.claude/`.\n\n---\n\n## Why it's built this way\n\nThe system decomposes into 8 modules, and the **golden rule of the design** is that\ndependency arrows point only at *interfaces/contracts*, never at concrete implementations.\nThat discipline is what makes three things swappable without touching the rest:\n\n1. **Storage** — `JSONStorage` today, `PostgresStorage` tomorrow. Injected at server startup.\n2. **Adventure** — swap the lore module without touching the engine. Today a `SKILL.md`.\n3. **Harness** — swap who narrates (terminal → web) while reusing the same MCP tool contract.\n\n```\n07 harness ───────► 05 mcp ◄──────── 08 commands\n                      │\n        ┌─────────────┼─────────────┐\n        ▼             ▼             ▼\n   01 rules      04 combat     03 storage (interface)\n        │             │             ▲\n        └──────►──────┘             │ implements\n                  │                 │\n                  ▼                 │\n            02 domain ◄─────────────┘   (shared data contracts)\n\n06 adventure-module ──(lore consumed by)──► 07 harness\n```\n\n| #  | Module             | Responsibility                                                                 | Pluggable?              |\n|----|--------------------|--------------------------------------------------------------------------------|-------------------------|\n| 01 | `rules`            | Pure rules engine — dice, attributes, luck test, one combat round. No I/O, RNG injected. | — (stable)   |\n| 02 | `domain`           | Shared data contracts + invariant validation. Depends on nothing.              | — (stable)              |\n| 03 | `storage`          | Persistence behind the `StorageBackend` interface.                             | ✅ JSON ↔ Postgres      |\n| 04 | `combat`           | Combat lifecycle (start → rounds → flee → end).                                | —                       |\n| 05 | `mcp`              | MCP server exposing tools to the harness. No game rules of its own.            | — (stable contract)     |\n| 06 | `adventure-module` | Pluggable static lore (zones, bestiary, victory). Debut: **Ignarok**.          | ✅ Ignarok ↔ others     |\n| 07 | `harness`          | The narrator/master that talks to the player and calls the MCP.                | ✅ Claude Code ↔ agent  |\n| 08 | `commands`         | System commands (`/hero`, `/backpack`, `/map`, `/save`).                       | ✅ add new ones         |\n\n## Project layout\n\n```\nsrc/gamebook/\n  domain/    # data contracts: CharacterSheet, World, Event, Combat, ArchiveRecord\n  rules/     # pure rules engine (interfaces + implementation), injectable RNG\n  storage/   # StorageBackend interface + JSONStorage + in-memory impl\n  combat/    # combat lifecycle (interfaces + implementation)\n  mcp/       # FastMCP server over stdio — orchestrates the modules\ndocs/\n  00-index.md … 08-commands.md   # specs (requirements)\n  CONTRACTS.md                   # authoritative English code contract\n  adrs/                          # architecture decision records\n  learning-lessons/              # captured gotchas\n.claude/\n  skills/    # game-master, combat-sub-agent, ignarok (the Phase-1 harness)\n  commands/  # /hero, /backpack, /map, /save\ntests/\n  engine/  server/  qa/\n```\n\n## Requirements\n\n- Python **3.13** (`.python-version`), `requires-python \u003e= 3.12`\n- [`uv`](https://docs.astral.sh/uv/) for dependency management and running\n\n## Quickstart\n\n```bash\n# Run the full test suite\nuv run pytest -q\n\n# Scope it\nuv run pytest tests/engine -q     # pure rules (seeded RNG, in-memory storage)\nuv run pytest tests/server -q     # storage + MCP server\nuv run pytest tests/qa -q         # plugability / isolation / e2e\n\n# The golden-rule plugability audit (catches any module reaching past an interface)\nuv run pytest tests/qa/test_dependencies.py tests/qa/test_isolation.py -q\n\n# Start the MCP server over stdio (exits cleanly on EOF)\nuv run python -m gamebook.mcp.server\n```\n\nThe server is registered for Claude Code in `.mcp.json`, so the narrator skills can call it\ndirectly.\n\n## MCP tools (18)\n\nThe authoritative contract is `docs/CONTRACTS.md` §6. Grouped by purpose:\n\n| Group       | Tools                                                                                   |\n|-------------|-----------------------------------------------------------------------------------------|\n| Dice \u0026 luck | `roll_dice`, `test_luck`                                                                 |\n| Character   | `create_character`, `read_character_sheet`, `update_character_sheet`, `archive_character`|\n| World       | `read_world`, `update_world`                                                             |\n| Chronicle   | `register_event`, `read_events`, `read_summary`, `update_summary`                        |\n| Combat      | `start_combat`, `resolve_combat_round`, `flee_combat`, `end_combat`                      |\n| Saves       | `save_progress`, `load_progress`                                                         |\n\n## Game rules (reference)\n\n- **Attributes:** `skill` = 1d6+6, `stamina` = 2d6+12, `luck` = 1d6+6 — each tracks `initial`/`current`.\n- **Luck test:** success if roll ≤ current luck; luck always decrements by exactly 1 afterward.\n- **Combat round:** each side's attack strength = `skill` + 2d6; higher AS hits for base\n  damage 2, a tie deals 0.\n- **Luck on a hit:** won+lucky → 4, won+unlucky → 1, lost+lucky → 1, lost+unlucky → 3.\n- **Death / flee:** hero at 0 stamina → `alive: false`; fleeing costs 2 stamina and only if allowed.\n\n`rules` and `combat` are tested in full isolation with a seeded RNG and in-memory storage —\ndeterministic, no disk, no AI.\n\n## Playing a session (Phase-1 harness)\n\nWhen you sit down to **play** rather than develop, Claude Code becomes the Game Master.\n\n**Session-opening rule:** before narrating anything, the master reads real engine state via\nMCP (`read_character_sheet`, `read_world`, `read_events`, `read_summary`). No living character\n→ it offers `create_character` and starts the adventure's opening. A living character → it\nresumes from the exact recorded point (never restarts, re-rolls, or contradicts recorded\nfacts). Every number and state change routes through MCP tools.\n\n- **Skills** (`.claude/skills/`): `game-master` (narrator), `combat-sub-agent` (runs one\n  fight), `ignarok` (the debut adventure — swap this file to swap adventures).\n- **Commands** (`.claude/commands/`): `/hero`, `/backpack`, `/map`, `/save` — read-outs and\n  checkpoints that reflect real MCP state and don't advance the story.\n\n## Documentation\n\n- **`docs/00-index.md`** — start here; maps every module.\n- **`docs/CONTRACTS.md`** — the authoritative English code contract (cross-module interfaces,\n  domain schema §2, MCP tool contract §6). When code and a spec disagree, CONTRACTS.md governs.\n- **`docs/adrs/`** — architecture decision records (ADR-001 … ADR-010).\n- **`docs/learning-lessons/`** — captured gotchas worth not relearning.\n- **`CLAUDE.md`** — guidance for Claude Code working in this repo.\n\n## Roadmap\n\n- **Phase 1 (current):** Claude Code as harness, `JSONStorage`, adventure as `SKILL.md`.\n- **Phase 2:** a PydanticAI/FastAPI harness with structured `Scene` output for a web frontend,\n  plus `PostgresStorage` — reusing the *same* MCP tool contract and adventure module unchanged.\n  That reuse is the entire point of the architecture.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frc-ventura%2Ffantasy-gamebook-engine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frc-ventura%2Ffantasy-gamebook-engine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frc-ventura%2Ffantasy-gamebook-engine/lists"}