diff --git a/content/roadmap.md b/content/roadmap.md index 7464a06..79aac34 100644 --- a/content/roadmap.md +++ b/content/roadmap.md @@ -128,16 +128,22 @@ six kings and their cults. All parked in the Backlog. a gold coin is a plot point. The party counting coppers for an inn bed is §3 grit, and Brannoc has an opinion about it. -**This is a change, not a new thing — and it has a client consumer. It lands as its -own small item before M7**, cheapest now while `content/world/items/` holds exactly -two files: +**The value type landed ✅** ahead of M7, as its own item +([spec](../docs/superpowers/specs/2026-07-12-currency-copper-design.md), merged to +`dev`): a `Currency` value type storing **everything in copper** and formatting only +at the display edge; `coin.json` replaced by `copper`/`silver`/`gold`; the purse as a +single `GameState.purse_copper` int; the shell's command bar reading `◈ 3s 47c`. -- A `Currency` value type — **store everything in copper**, format only at the - display edge (`12g 40s 8c`). -- `coin.json` → real denominations; all prices re-denominated. -- The Main Window shell's command-bar purse (it currently shows a flat gold value). +Money is **not** an inventory item. `give_item`/`accept_item` carry no quantity and +`gifts_given` is a global one-shot, so a lone `copper` id would be givable *once, for +one copper, per campaign*. The denominations are **move tokens** instead — +`give_item(gold)` is +10,000c — and currency routes to the purse, never the +`inventory` dict, so it cannot surface in an inventory grid by construction. -*§2: state · depends on nothing · goal: money that means something.* +**What is left is the numbers.** The **price table** (above) is content and belongs to +M8's BOM. Nothing is priced yet. + +*§2: state · done · goal: money that means something.* --- diff --git a/docs/roadmap.md b/docs/roadmap.md index 94c8440..bca123b 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -35,14 +35,22 @@ M0–M2 built the **engine** (the contract, the client, the server loop, bounded | **M0 — Foundations** ✅ | The contract and the client-side engine exist and are trustworthy. | | **M1 — Prove the server loop** ✅ | A real model sits behind `/dm/narrate` and the pipeline is reusable. | | **M2 — Prove aliveness** ✅ | **Does bounded AI dialogue feel alive?** — answered; bounded NPC dialogue + DM loop live-proven. | -| **M3 — Visual foundation & shell** ◀ *here* | The `Theme` + the exploration HUD; every screen inherits the look and lives in the shell. | -| **M4 — Character creation** | The player enters the world; the proven stat/Luck model gets its UI. | +| **M3 — Visual foundation & shell** ✅ | The `Theme` + the exploration HUD; every screen inherits the look and lives in the shell. | +| **M4 — Character creation** ◀ *here* | The player enters the world; the proven stat/Luck model gets its UI. | | **M5 — Tactical combat (gridless)** | Real stakes: the Combat HUD turn manager. | | **M6 — Dialogue screen** | The proven NPC free-text loop inside the mock's conversation UI. | | **M7 — Inventory & character sheet** | State the player can see and manage. | | **M8 — World systems** | World-map travel, a shop economy, the quest log. | | **M9 — Framing, AI-flavor & persistence** | Title/pause, save/load, and the Improviser/Banter/Luck-drift roles + fallback sweep. | +### Landed out of band + +Not every item is a milestone. These shipped on their own because a later milestone +would have been more expensive to build on top of the old shape. + +- ✅ **Currency — copper with real denominations** ([spec](superpowers/specs/2026-07-12-currency-copper-design.md)). `1g = 100s = 10,000c`, **stored entirely in copper** as one `GameState.purse_copper` int, formatted only at the display edge (`◈ 3s 47c`). `coin.json` → `copper`/`silver`/`gold`. Money is **not** an inventory item: `give_item`/`accept_item` carry no quantity and `gifts_given` is a global one-shot, so a lone `copper` id would have been givable once, for one copper, per campaign — the denominations are **move tokens** instead (`give_item(gold)` = +10,000c), routed to the purse and never into `inventory`, so money cannot surface in an inventory grid by construction. Taken before M7 while `content/world/items/` held two files. **Prices remain M8's content BOM — nothing is priced yet.** *§2: state · goal: money that means something.* +- ✅ **A move applies at most once per reply** — found by the review of the above. `TagExtractor` returns *every* tag occurrence and `MoveValidator` is a membership test, so a model repeating a tag N times picked an amount **in unary** (§2 breach: the AI choosing a number). Now deduped by (name, id) across a reply, and `adjust_disposition`'s `MAX_DELTA` caps the reply's **net** swing rather than each tag — it was per-tag, so three `+15`s moved standing by 45, the exact "wholesale swing" the constant forbids. *§2: state · goal: the bounded vocabulary stays bounded.* + --- ### M0 — Foundations ✅ @@ -83,7 +91,7 @@ Each screen is recreated as a Godot 4.7 Control-node scene against the mockups ( - ○ **Character sheet** — attributes (modifier-forward, LCK still hidden), saving throws, the "in a fight" derived grid, skills, talents, afflictions/conditions, the DM's-notes bio. *§2: state (display) · depends on the stat model · goal: the character, legible.* ### M8 — World systems -*Content it consumes → [BOM](../content/roadmap.md#2-bill-of-materials): the **price table in copper** (fixed); 3 map locations + the road, shop stock, the quest chain (variable). **~8 pieces.** The **currency change lands before M7** — store everything in copper, format at the display edge; it has a client consumer (the shell's purse).* +*Content it consumes → [BOM](../content/roadmap.md#2-bill-of-materials): the **price table in copper** (fixed); 3 map locations + the road, shop stock, the quest chain (variable). **~8 pieces.** The **currency value type already landed** (see *Landed out of band*, above) — everything is stored in copper and formatted at the display edge, so the Shop economy inherits a real purse. What M8 still owes is the **numbers**: nothing is priced yet.* - ○ **World-map travel** — region map, location markers (settlement/dungeon/fog), roads + planned route, danger ratings, travel time, set-out. *§2: state · depends on the shell · goal: move between places.* - ○ **Shop economy** — buy/sell with a fence: purses, stock/owned, the ~40%-sell loop, gritty disabled-CTA reasons, merchant reaction lines. *§2: state (merchant reaction = a thin authored/AI layer) · depends on inventory · goal: an economy loop.* - ○ **Quest log** — active/completed/failed tabs, objectives checklists, rewards, tracked quest; reads the canon log's `active_quests` (§11). *§2: state · depends on the quest model · goal: track the story.*