docs(@projects/@magic-civilization): 🗺️ p3-26 — roadmap to complete the headless simulator (loop done-criterion)
Owner directive: the /loop isn't finished until the SIMULATOR is complete — the headless Rust sim must play full self-play games with ALL systems, not the reduced subset. p3-26 enumerates the verified live-vs-headless gaps + sequenced plan: - Gap 1: climate/environment runtime (port the marine→climate→weather→effects chain into mc-turn; physics already in mc-climate). - Gap 2: natural/"apocalyptic" events (M3 milestone — port .messy ecological_events.gd, 12 categories, deterministic per EVENT_FREQUENCY_SPEC). - Gap 3: equipment/crafting (recipes exist; no headless Craft action). - Gap 4: per-building build queues (dual city-model; bench has a single queue). Corrects my earlier "apocalyptic events don't exist" — they're specced (m3-natural-events) with a .messy reference impl, just unimplemented in Rust. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4fe3bc6091
commit
f9593c4d29
3 changed files with 76 additions and 8 deletions
|
|
@ -17,8 +17,8 @@
|
|||
| **P0** | 44 | 0 | 0 | 0 | 0 | 0 | 44 |
|
||||
| **P1** | 88 | 0 | 0 | 0 | 0 | 1 | 89 |
|
||||
| **P2** | 130 | 0 | 0 | 0 | 0 | 1 | 131 |
|
||||
| **P3 (oos)** | 34 | 0 | 2 | 0 | 0 | 29 | 65 |
|
||||
| **total** | **296** | **0** | **2** | **0** | **0** | **31** | **329** |
|
||||
| **P3 (oos)** | 34 | 0 | 3 | 0 | 0 | 29 | 66 |
|
||||
| **total** | **296** | **0** | **3** | **0** | **0** | **31** | **330** |
|
||||
|
||||
</td><td valign='top' style='padding-left:2em'>
|
||||
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
| Team Lead | Remaining |
|
||||
|---|---|
|
||||
| [warcouncil](../team-leads/warcouncil.md) | 2 |
|
||||
| [warcouncil](../team-leads/warcouncil.md) | 3 |
|
||||
|
||||
</td></tr></table>
|
||||
|
||||
|
|
|
|||
58
.project/objectives/p3-26-complete-headless-simulator.md
Normal file
58
.project/objectives/p3-26-complete-headless-simulator.md
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
---
|
||||
id: p3-26
|
||||
title: Complete the headless simulator — close the live-vs-headless system gaps (loop done-criterion)
|
||||
priority: p3
|
||||
scope: game1
|
||||
owner: warcouncil
|
||||
status: partial
|
||||
updated_at: 2026-06-26
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
> **Owner directive (2026-06-26):** the /loop "continue until Game-1 done" is **not
|
||||
> finished until the SIMULATOR is complete** — the headless Rust sim
|
||||
> (`mc-turn::TurnProcessor`, driven via `GdPlayerApi`/`magic_civ_*`) must play a full
|
||||
> self-play game with ALL systems, not the reduced subset shipped so far. See
|
||||
> [[project_loop_done_means_simulator_complete]].
|
||||
|
||||
The headless `step()` ([processor.rs:392+](../../src/simulator/crates/mc-turn/src/processor.rs))
|
||||
currently runs: trade (p3-25), economy, city_production (single queue), culture+border
|
||||
expansion, tech/science, fauna encounters, combat/siege, diplomacy. Verified live via
|
||||
`magic_civ_view` (e.g. border expansion fired turn 0→1: `owned_tiles [[1,6]]→[[1,6],[0,6]]`).
|
||||
|
||||
**Gaps (each verified absent from the headless turn):**
|
||||
|
||||
## Acceptance (sequenced; each gap closed in bounded, cargo+e2e-verified increments)
|
||||
|
||||
- [ ] **Gap 1 — Climate / environment runtime.** Port the live per-turn chain
|
||||
`marine_harvest → climate(ecology+climate physics) → weather → climate_effects`
|
||||
(`turn_processor.gd::_process_climate`) into a `mc-turn` climate phase. The PHYSICS is
|
||||
already Rust (`mc-climate`: `physics.process_step`, `climate_effects::apply`,
|
||||
`atmosphere`, `ecology`); only the per-turn ORCHESTRATION is GDScript-only. Wire it onto
|
||||
`state.grid` in `step()`. Effects: weather events + unit HP damage + tile climate shifts
|
||||
in the headless sim.
|
||||
- [ ] **Gap 2 — Natural / "apocalyptic" events (M3 milestone).** Port the `.messy`
|
||||
`ecological_events.gd` (992 lines) → Rust, split per the milestone plan
|
||||
(`.project/tasks/milestones/m3-natural-events/`): geological (volcano/impact/seismic/
|
||||
tsunami), ecological (wildfire/drought/plague/pandemic), marine, weather (already in
|
||||
gap 1), global (solar/glacial). Deterministic from seed per `EVENT_FREQUENCY_SPEC.md`;
|
||||
triggers from climate (gap 1), damage targets in biology (fauna/ecology). Wire into the
|
||||
turn. (Magic category excluded — M4.)
|
||||
- [ ] **Gap 3 — Equipment / crafting.** `mc-city/recipes.rs` + `enqueue_item` exist but
|
||||
there is no headless `Craft`/`Equip` `PlayerAction` and crafting isn't in the bench
|
||||
turn. Add the action(s) + dispatch + wire recipe resolution (gating resources, quality)
|
||||
into the headless production/turn so equipment is craftable in self-play.
|
||||
- [ ] **Gap 4 — Per-building build queues.** Bench `CityState` has a single `queue`;
|
||||
per-building queues live in the full `mc_city::City` (live game). This is the dual
|
||||
city-model split ([[p3-25 ...]] step 6 / city_slot.rs). Either give `CityState`
|
||||
per-building queues or unify the models so the headless turn simulates them.
|
||||
|
||||
## Notes
|
||||
|
||||
Created 2026-06-26. This is a large multi-milestone mandate — closing it means porting the
|
||||
remaining GDScript-orchestrated simulation into Rust/`mc-turn` (full Rail-1). Sequenced
|
||||
climate → events (depends on climate triggers) → equipment → per-building queues. Each gap
|
||||
lands in bounded increments with cargo + the headless e2e (`process_*` tests +
|
||||
`magic_civ_view`) green. Reference impls in `@magic-civilization.messy/` per
|
||||
[[atomic-porting]] rules. Related: [[p3-25 ...]] (the dual city model underlies gaps 1+4).
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
{
|
||||
"generated_at": "2026-06-26T11:15:15Z",
|
||||
"generated_at": "2026-06-26T12:25:01Z",
|
||||
"totals": {
|
||||
"oos": 31,
|
||||
"missing": 0,
|
||||
"done": 296,
|
||||
"partial": 3,
|
||||
"oos": 31,
|
||||
"in_progress": 0,
|
||||
"stub": 0,
|
||||
"partial": 2,
|
||||
"total": 329
|
||||
"done": 296,
|
||||
"total": 330
|
||||
},
|
||||
"objectives": [
|
||||
{
|
||||
|
|
@ -3299,6 +3299,16 @@
|
|||
"owner": "warcouncil",
|
||||
"updated_at": "2026-06-26",
|
||||
"summary": "> **Owner directive (2026-06-26):** \"gd should only be UI view of simulation\" +\n> \"simulator should provide everything\" + \"no stubs — prod code only\". A player-like\n> the headless adapter (or any UI) must get the *full* game state from the simulator's\n> projected view (`GdPlayerApi.view_json` → `PlayerView`), not by GDScript re-deriving\n> simulation facts.\n\n**Root cause (verify-first investigation).** The simulator holds **two parallel city\nmodels** ([api-gdext/src/city_slot.rs:3-6](../../src/simulator/api-gdext/src/city_slot.rs)):\n\n- `GdGameState.presentation_cities: Vec<Vec<mc_city::City>>` — the **authoritative**\n rich model: `owned_tiles`, `worked_tiles`, `position`, `culture_stored`, buildings\n ([mc-city/src/city.rs](../../src/simulator/crates/mc-city/src/city.rs)).\n- `GameState.players[pi].cities: Vec<mc_state::CityState>` — a **bench** model with NO\n territory ([mc-city/src/lib.rs:126](../../src/simulator/crates/mc-city/src/lib.rs)),\n explicitly *\"left untouched\"*. City position lives in the parallel\n `PlayerState.city_positions`.\n\n`project_view` ([mc-player-api/src/projection.rs](../../src/simulator/crates/mc-player-api/src/projection.rs))\nreads the **bench** model, so `view_json` is structurally blind to territory — and thus\nto worked tiles and to inter-player trades (which need owned-tile resource sourcing).\n`GdPlayerApi` (the headless harness) holds only `GameState` — no `presentation_cities` —\nso the fix for the headless path is to give the bench state real territory, not to reach\ninto the rich `City`.\n\nConsequences observed: `CityView.owned_tiles` and `DiplomacyView.{open_borders,\nshared_map,agreements_active}` were hardcoded stubs in the projection; there are no\ntrade-deal fields on `DiplomacyView` at all; `mc-turn::process_trade_phase` sources trade\ninputs from bench proxies (`tile_strategics: Vec::new()`, `tile_luxuries` proxy) and does\nnot persist its computed ledger to `state.trade_ledger`. The live game's working trade\npath (p3-23) is GDScript-orchestrated and parses `trade_ledger_json` itself — a\npresentation-layer workaround that this objective supersedes for the headless/sim path.\n\nThe data needed *does* exist in Rust: `GridState.tile(col,row)→{biome,quality}` +\n`mc_core::collectibles::tile_collectibles(biome,quality,rng)` resolve a tile's resources\ndeterministically. What's missing is (a) owned-tile territory in the bench state, (b) a\nresource-category catalog (luxury/strategic) in Rust, (c) persistence of swap/sale deals\nto `state.trade_ledger`, (d) projecting it all."
|
||||
},
|
||||
{
|
||||
"id": "p3-26",
|
||||
"title": "Complete the headless simulator — close the live-vs-headless system gaps (loop done-criterion)",
|
||||
"priority": "p3",
|
||||
"status": "partial",
|
||||
"scope": "game1",
|
||||
"owner": "warcouncil",
|
||||
"updated_at": "2026-06-26",
|
||||
"summary": "> **Owner directive (2026-06-26):** the /loop \"continue until Game-1 done\" is **not\n> finished until the SIMULATOR is complete** — the headless Rust sim\n> (`mc-turn::TurnProcessor`, driven via `GdPlayerApi`/`magic_civ_*`) must play a full\n> self-play game with ALL systems, not the reduced subset shipped so far. See\n> [[project_loop_done_means_simulator_complete]].\n\nThe headless `step()` ([processor.rs:392+](../../src/simulator/crates/mc-turn/src/processor.rs))\ncurrently runs: trade (p3-25), economy, city_production (single queue), culture+border\nexpansion, tech/science, fauna encounters, combat/siege, diplomacy. Verified live via\n`magic_civ_view` (e.g. border expansion fired turn 0→1: `owned_tiles [[1,6]]→[[1,6],[0,6]]`).\n\n**Gaps (each verified absent from the headless turn):**"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue