diff --git a/.env b/.env index 3026d662..64f2b6f7 100644 --- a/.env +++ b/.env @@ -11,17 +11,17 @@ # New keys: document them in `.env.example` with a one-line comment. # ── Forgejo forge (non-secret: host URL only) ────────────────────── -FORGEJO_HOST=http://forge.black.local +FORGEJO_HOST=http://forge.black.lan FORGEJO_ORG=magicciv # ── Two-host workflow (edit host → run host) ─────────────────────── -AUTOPLAY_HOST=lilith@apricot.local +AUTOPLAY_HOST=lilith@apricot.lan PROJECT_ROOT_REMOTE=~/Code/@projects/@magic-civilization REMOTE_RUNNER=~/bin/run_ap3.sh -SCREENSHOT_HOST=natalie@plum.local +SCREENSHOT_HOST=natalie@plum.lan # ── Dev-guide deploy (p1-15, tourguide) ──────────────────────────── -NEXT_DEPLOY_HOST=lilith@black.local +NEXT_DEPLOY_HOST=lilith@black.lan NEXT_DEPLOY_PATH=/bigdisk/next/mc/ # ── Guide resource / simulator paths (relative to repo root) ─────── diff --git a/.project/objectives/DASHBOARD_CATEGORIES.md b/.project/objectives/DASHBOARD_CATEGORIES.md index 45d07df8..6b055a59 100644 --- a/.project/objectives/DASHBOARD_CATEGORIES.md +++ b/.project/objectives/DASHBOARD_CATEGORIES.md @@ -492,7 +492,7 @@ | [p2-72a-save-format-migration](p2-72a-save-format-migration.md) | 🟡 partial | P2 | Decouple save format from GDScript-class shape | [simulator-infra](../team-leads/simulator-infra.md) | 🔒 p2-72a-gdgamestate-canonical-render-source | | [p2-72b-promote-playerstate-cities-to-city](p2-72b-promote-playerstate-cities-to-city.md) | ✅ done | P2 | Parallel-field cities synthesis at Godot bridge (Option C) | [simulator-infra](../team-leads/simulator-infra.md) | 🟢 | | [p2-73-ui-theme-token-pipeline](p2-73-ui-theme-token-pipeline.md) | ✅ done | P2 | UI theme pipeline — generate ui_theme.tres from design-tokens.json + apply globally | [wireguard](../team-leads/wireguard.md) | 🟢 | -| [p2-74-ui-dehardcode-to-tokens](p2-74-ui-dehardcode-to-tokens.md) | 🔴 stub | P2 | De-hardcode the Godot UI — route 45 scene scripts off raw Color() onto theme/tokens | [wireguard](../team-leads/wireguard.md) | 🟢 | +| [p2-74-ui-dehardcode-to-tokens](p2-74-ui-dehardcode-to-tokens.md) | 🟡 partial | P2 | De-hardcode the Godot UI — route 45 scene scripts off raw Color() onto theme/tokens | [wireguard](../team-leads/wireguard.md) | 🟢 | | [p2-75](p2-75-improvement-effects-subsystem.md) | 🟡 partial | P2 | Improvement-completion effects subsystem in Rust — move completion side-effects out of GDScript | — | 🟢 | | [p2-76](p2-76-bunker-improvement.md) | ✅ done | P2 | Bunker improvement — deposit-destroying fortified subterranean chamber | — | 🟢 | | [p2-77](p2-77-deposit-destruction-taxonomy.md) | ❌ missing | P2 | Deposit-destruction environmental taxonomy — destruction_effect classes + contamination engine | — | 🟢 | @@ -501,6 +501,9 @@ | [p2-80](p2-80-mc-worldsim-integration.md) | ✅ done | P1 | mc-worldsim orchestration crate — drive the existing worldsim engines in the playable turn | — | 🟢 | | [p2-81](p2-81.md) | 🟡 partial | P2 | Improvement effects authored-but-unwired — move moisture/wind/erosion/movement to Rust | — | 🟢 | | [p2-82](p2-82-climate-input-save-fidelity.md) | ✅ done | P2 | Climate-input save-fidelity — persist (or re-derive) worldgen-static grid inputs across save/load | — | 🟢 | +| [p2-85](p2-85-poi-sprites-and-tooltips.md) | 🟡 partial | P2 | POI sprites + hover tooltips — lairs (and resources) legible on the map | [asset-sprite](../team-leads/asset-sprite.md) | 🟢 | +| [p2-86](p2-86-mcp-rendered-driver.md) | 🟡 partial | P2 | Claude-player MCP — rendered driver mode (drive UI + capture screenshots) | [simulator-infra](../team-leads/simulator-infra.md) | 🟢 | +| [p2-87-single-color-system-sot](p2-87-single-color-system-sot.md) | 🟡 partial | P2 | Single game-wide colour system — one source of truth, layered tokens, every consumer derives from it | [wireguard](../team-leads/wireguard.md) | 🟢 | | [p3-01](p3-01-courier-diplomacy.md) | ✅ done | P3 | Courier-gated diplomacy — open borders + shared maps via tech-tiered courier units | [envoy](../team-leads/envoy.md) | 🟢 | | [p3-03](p3-03-courier-route-resolver.md) | ✅ done | P3 | Courier route resolver — real hex pathfinding, per-tier movement, severable infrastructure | [envoy](../team-leads/envoy.md) | 🟢 | | [p3-04](p3-04-per-hex-improvement-layer.md) | ✅ done | P3 | Per-hex improvement layer in `mc-core` / `mc-turn` — anchor improvements at (col,row) | [envoy](../team-leads/envoy.md) | 🟢 | diff --git a/.project/objectives/objectives.json b/.project/objectives/objectives.json index 9a590b6b..05fda5df 100644 --- a/.project/objectives/objectives.json +++ b/.project/objectives/objectives.json @@ -1,13 +1,13 @@ { - "generated_at": "2026-06-10T11:07:40Z", + "generated_at": "2026-06-19T01:25:02Z", "totals": { "done": 249, "in_progress": 0, - "partial": 30, - "stub": 7, + "partial": 34, + "stub": 6, "missing": 5, "oos": 31, - "total": 322 + "total": 325 }, "objectives": [ { @@ -361,7 +361,7 @@ "owner": "shipwright", "updated_at": "2026-04-18", "blocked_by": [], - "summary": "Implement a scripted opening sequence that runs on turns **-1**, **0**, and **1** before normal gameplay begins. Turn numbering skips from -1 to 0 to 1 (no \"turn -0.5\" or similar; -1 and 0 are both real turns but the player has no unit to command).\n\n1. **Turn -1 — Dispersed wanderers.** A **spawn box** is placed around each player's designated starting region. Inside the box, `N` ordinary free-dwarf wanderers spawn — **no `player_ancestor` flag, no pre-decided allegiance**. They are just freepeople. Each wanderer independently rolls a movement direction for turn -1 → 0. The roll is biased so that **at least `min_ancestors_to_form_tribe` (default 3) are guaranteed to roll \"toward box center\"** — these become the tribe founders at resolution time, *emergently*, not by pre-tagging. The remaining wanderers roll freely and may move outward or laterally. Fog is partially lifted so the player sees the whole box. The only legal input is **End Turn** (or Enter).\n2. **Turn 0 — Convergence / tribe formation.** Wanderers step along their rolled directions (deterministic from seed). At end-of-turn-0 resolution: the wanderers that ended up within `tribe_convergence_radius` of the box centroid merge into a single **Dwarf Tribe** unit at the centroid hex and are consumed. This is the player's founding tribe. **Wanderers that did NOT converge are NOT consumed** — they remain on the map as ordinary freepeople NPCs and continue their wander behavior (per `public/resources/villages/freepeople.json` rules). Pairs/trios of surviving non-converged wanderers may later coalesce into `nomadic_band` camps → grow into **freehavens** → evolve into city-states adjacent to the player (human or AI). This is the same mechanic as the player's own founding, applied generally: **any** 3+ freepeople that get within convergence radius form a camp; camps grow into havens. Again the only legal input is End Turn during this opening.\n3. **Turn 1 — First city.** The Dwarf Tribe unit appears under player control with exactly one available action: **Found Capital**. On founding, the capital's starting population is determined by the mode (see below), the Dwarf Tribe unit is consumed, and normal Game 1 play begins. All *subsequent* settlers built by cities are ordinary **Founder** units that always produce a pop-1 city.\n\n### Starting-population modes\n\n| Mode | Formula | Cap |\n|---|---|---|\n| **Tournament** | Starting pop = **1**, regardless of how many wanderers converged (min 3 still required). Guaranteed-convergence count is pinned to exactly 3; no extras are biased inward. | Fixed. |\n| **Lucky** (default for single-player casual) | Starting pop = `1 + floor((wanderers_converged - 3) / 3)` — each wanderer past the 3rd contributes **+1/3 pop**, rounded down at founding. Extra inward-biased rolls (beyond the guaranteed 3) are possible so variance can go up. | `max_lucky_bonus_pop = 3` (pop 4 from 12 converged). Tunable in `setup.json`. |\n\nRationale: tournament mode guarantees identical starting conditions across all five AI clans + human player for balanced tournaments / multi-seed validation batches. Lucky mode lets the spawn roll matter and rewards regions where more wanderers happen to converge (slightly favoring bountiful biomes in a later \"starting position type\" selector — out of scope here).\n\n### Roll bias mechanics\n\nFor each player's spawn box of `N` wanderers (`N ≈ 3..12`, seeded per map):\n- **Tournament**: exactly 3 wanderers get `direction = inward`; the remaining `N-3` roll uniformly from all 6 hex directions.\n- **Lucky**: 3 wanderers are pinned inward (floor guarantee); each of the remaining `N-3` independently rolls `inward_bias_prob` (default `0.33`) to also go inward, else uniform. This lets 3–`N` converge.\n- \"Inward\" means \"one of the 2 hex directions whose dot product with `centroid - wanderer_pos` is most positive\" — picked uniformly among ties, still deterministic from seed.\n\n### Non-converging wanderers become ordinary freepeople\n\nWanderers that drift outward / laterally on turn 0 are not special. They persist as standard freepeople NPCs and feed into the existing system:\n- They continue wandering via the scripted AI in `public/resources/ai/freepeople/freepeople.json`.\n- When 3+ freepeople (from *any* source — prologue drift, ongoing camp expansion, migration) get within `tribe_convergence_radius` of each other, they form a `nomadic_band` camp (`freepeople.json:camp_types[0]`).\n- Camps grow per `freepeople.json:growth` — at `expansion_threshold = 30` they may become **freehavens**, and high-ecology-tier havens may eventually emerge as city-states neighboring the player.\n- This means the opening cinematic *also* seeds rival neighbors: players who spawned with a dense box get more surviving drifters → more potential adjacent freehavens → more mid-game pressure. That pressure is symmetric across tournament mode (all players get `N=baseline`) and asymmetric in lucky mode.\n\n### Why Dwarf Tribe ≠ Founder\n\n- **Dwarf Tribe** (new unit): spawned only by the turn-0 convergence event. Carries `founding_pop_override: int` set at spawn time. Has one action: **Found Capital**. Cannot be built by cities. Never appears again after turn 1.\n- **Founder** (existing settler/pioneer unit): built normally by cities starting from turn 2+. Always founds a pop-1 city. No `founding_pop_override`.\n\nKeeping them separate means the variance only exists at game-start, not inside the mid-game economy." + "summary": "Implement a scripted opening sequence that runs on turns **-1**, **0**, and **1** before normal gameplay begins. Turn numbering skips from -1 to 0 to 1 (no \"turn -0.5\" or similar; -1 and 0 are both real turns but the player has no unit to command).\n\n1. **Turn -1 — Dispersed wanderers.** A **spawn box** is placed around each player's designated starting region. Inside the box, `N` ordinary free-dwarf wanderers spawn — **no `player_ancestor` flag, no pre-decided allegiance**. They are just freepeople. Each wanderer independently rolls a movement direction for turn -1 → 0. The roll is biased so that **at least `min_ancestors_to_form_tribe` (default 3) are guaranteed to roll \"toward box center\"** — these become the tribe founders at resolution time, *emergently*, not by pre-tagging. The remaining wanderers roll freely and may move outward or laterally. Fog is partially lifted so the player sees the whole box. The only legal input is **End Turn** (or Enter).\n2. **Turn 0 — Convergence / tribe formation.** Wanderers step along their rolled directions (deterministic from seed). At end-of-turn-0 resolution: the wanderers that ended up within `tribe_convergence_radius` of the box centroid merge into a single **Dwarf Tribe** unit at the centroid hex and are consumed. This is the player's founding tribe. **Wanderers that did NOT converge are NOT consumed** — they remain on the map as ordinary freepeople NPCs and continue their wander behavior (per `public/resources/villages/freepeople.json` rules). Pairs/trios of surviving non-converged wanderers may later coalesce into `nomadic_band` camps → grow into **freehavens** → evolve into city-states adjacent to the player (human or AI). This is the same mechanic as the player's own founding, applied generally: **any** 3+ freepeople that get within convergence radius form a camp; camps grow into havens. Again the only legal input is End Turn during this opening.\n3. **Turn 1 — First city.** The Dwarf Tribe unit appears under player control as a **movable unit** with action bar `[\"found_capital\", \"move\"]` and **1 movement point**: the player may either found the capital on the centroid hex immediately or relocate it one hex before founding. On founding, the capital's starting population is determined by the mode (see below), the Dwarf Tribe unit is consumed, and normal Game 1 play begins. (AI/NPC tribes do not exercise the move option — they auto-found at the centroid; only player-controlled tribes get the move-vs-found choice.) All *subsequent* settlers built by cities are ordinary **Founder** units that always produce a pop-1 city.\n\n### Starting-population modes\n\n| Mode | Formula | Cap |\n|---|---|---|\n| **Tournament** | Starting pop = **1**, regardless of how many wanderers converged (min 3 still required). Guaranteed-convergence count is pinned to exactly 3; no extras are biased inward. | Fixed. |\n| **Custom** (default for single-player casual) | Starting pop = `1 + floor((wanderers_converged - 3) / 3)` — each wanderer past the 3rd contributes **+1/3 pop**, rounded down at founding. Extra inward-biased rolls (beyond the guaranteed 3) are possible so variance can go up. | `custom_max_bonus_pop = 3`; with the custom wanderer count capped at 9 the practical ceiling is **pop 3 from 9 converged**. Tunable in `setup.json`. |\n\nRationale: tournament mode guarantees identical starting conditions across all five AI clans + human player for balanced tournaments / multi-seed validation batches. Custom mode lets the spawn roll matter and rewards regions where more wanderers happen to converge (slightly favoring bountiful biomes in a later \"starting position type\" selector — out of scope here).\n\n### Roll bias mechanics\n\nFor each player's spawn box of `N` wanderers (`N ≈ 3..9`, seeded per map; tournament pins `N = 3`, custom rolls `N ∈ [3, 9]`):\n- **Tournament**: exactly 3 wanderers get `direction = inward`; the remaining `N-3` roll uniformly from all 6 hex directions.\n- **Custom**: 3 wanderers are pinned inward (floor guarantee); each of the remaining `N-3` independently rolls `inward_bias_prob` (default `0.33`) to also go inward, else uniform. This lets 3–`N` converge.\n- \"Inward\" means \"one of the 2 hex directions whose dot product with `centroid - wanderer_pos` is most positive\" — picked uniformly among ties, still deterministic from seed.\n\n### Non-converging wanderers become ordinary freepeople\n\nWanderers that drift outward / laterally on turn 0 are not special. They persist as standard freepeople NPCs and feed into the existing system:\n- They continue wandering via the scripted AI in `public/resources/ai/freepeople/freepeople.json`.\n- When 3+ freepeople (from *any* source — prologue drift, ongoing camp expansion, migration) get within `tribe_convergence_radius` of each other, they form a `nomadic_band` camp (`freepeople.json:camp_types[0]`).\n- Camps grow per `freepeople.json:growth` — at `expansion_threshold = 30` they may become **freehavens**, and high-ecology-tier havens may eventually emerge as city-states neighboring the player.\n- This means the opening cinematic *also* seeds rival neighbors: players who spawned with a dense box get more surviving drifters → more potential adjacent freehavens → more mid-game pressure. That pressure is symmetric across tournament mode (all players get `N=baseline`) and asymmetric in custom mode.\n\n### Why Dwarf Tribe ≠ Founder\n\n- **Dwarf Tribe** (new unit): spawned only by the turn-0 convergence event. Carries `founding_pop_override: int` set at spawn time. **Movable** under player control — action bar `[\"found_capital\", \"move\"]`, 1 MP — so the player can reposition one hex before founding; AI/NPC tribes auto-found at the centroid and never move. Cannot be built by cities. Never appears again after turn 1.\n- **Founder** (existing settler/pioneer unit): built normally by cities starting from turn 2+. Always founds a pop-1 city. No `founding_pop_override`.\n\nKeeping them separate means the variance only exists at game-start, not inside the mid-game economy." }, { "id": "p0-37", @@ -2869,7 +2869,7 @@ "id": "p2-74-ui-dehardcode-to-tokens", "title": "De-hardcode the Godot UI — route 45 scene scripts off raw Color() onto theme/tokens", "priority": "p2", - "status": "stub", + "status": "partial", "scope": "game1", "owner": "wireguard", "updated_at": "2026-06-06", @@ -2986,6 +2986,39 @@ "blocked_by": [], "summary": "**A development-time profiling layer that attributes compute cost (CPU / RAM / GPU) to the feature that incurred it, over game-time, tagged by what triggered it — so optimization effort is data-driven, not guessed. It MUST compile/gate out to zero overhead in the shipped game.**" }, + { + "id": "p2-85", + "title": "POI sprites + hover tooltips — lairs (and resources) legible on the map", + "priority": "p2", + "status": "partial", + "scope": "game1", + "owner": "asset-sprite", + "updated_at": "2026-06-18", + "blocked_by": [], + "summary": "" + }, + { + "id": "p2-86", + "title": "Claude-player MCP — rendered driver mode (drive UI + capture screenshots)", + "priority": "p2", + "status": "partial", + "scope": "game1", + "owner": "simulator-infra", + "updated_at": "2026-06-18", + "blocked_by": [], + "summary": "" + }, + { + "id": "p2-87-single-color-system-sot", + "title": "Single game-wide colour system — one source of truth, layered tokens, every consumer derives from it", + "priority": "p2", + "status": "partial", + "scope": "game1", + "owner": "wireguard", + "updated_at": "2026-06-18", + "blocked_by": [], + "summary": "" + }, { "id": "g2-01", "title": "Ley lines — Game 2 (Age of Kzzykt)", @@ -3885,7 +3918,7 @@ "remaining_by_lead": [ { "owner": "simulator-infra", - "remaining": 9 + "remaining": 10 }, { "owner": "warcouncil", @@ -3893,7 +3926,7 @@ }, { "owner": "asset-sprite", - "remaining": 5 + "remaining": 6 }, { "owner": "shipwright", @@ -3903,6 +3936,10 @@ "owner": "unassigned", "remaining": 3 }, + { + "owner": "wireguard", + "remaining": 2 + }, { "owner": "asset-audio", "remaining": 1 @@ -3910,10 +3947,6 @@ { "owner": "testwright", "remaining": 1 - }, - { - "owner": "wireguard", - "remaining": 1 } ] } diff --git a/public/games/age-of-dwarves/guide/.env.development b/public/games/age-of-dwarves/guide/.env.development index 510c8749..158d91c0 100644 --- a/public/games/age-of-dwarves/guide/.env.development +++ b/public/games/age-of-dwarves/guide/.env.development @@ -4,6 +4,6 @@ # and append Episodes 2-5 to the sidebar. Keeps contributor-facing dev runs # in "all episodes" mode so scope drift is visible early. Production builds # ignore this file — see .env.production (+ the explicit override -# `VITE_DEV_GUIDE=1` in `./run deploy:guide:next` for the mc.next.black.local +# `VITE_DEV_GUIDE=1` in `./run deploy:guide:next` for the mc.next.black.lan # dev-preview deploy). VITE_DEV_GUIDE=1 diff --git a/public/games/age-of-dwarves/guide/.env.production b/public/games/age-of-dwarves/guide/.env.production index 5e0ae4c8..46bc6617 100644 --- a/public/games/age-of-dwarves/guide/.env.production +++ b/public/games/age-of-dwarves/guide/.env.production @@ -1,6 +1,6 @@ # Vite prod-mode env (tracked). Loaded automatically by `pnpm build`. # # Production build = Episode 1 only (Age of Dwarves Early Access). The -# dev-preview deploy at mc.next.black.local overrides VITE_DEV_GUIDE in the +# dev-preview deploy at mc.next.black.lan overrides VITE_DEV_GUIDE in the # shell env (see `./run deploy:guide:next`). VITE_DEV_GUIDE=0