feat(release): complete Game 1 "Age of Dwarves" Early Access
- Scope: all non-stretch game1 objectives (P0/P1/P2) done per dashboard + scope-game1-vs-game2 (worldsim promoted included). - Headless sim: mc-turn full systems (297/297 tests green; climate/ecology/happiness/combat/economy/victory/events/etc per p3-26). - Rail-1: live turn delegates unconditionally to Rust GdTurnProcessor.step (turn_manager.gd:269+); GDScript pure view of getState(); old orchestrators deleted (p3-29). - Verifs: cargo check --workspace clean + targeted tests; gdlint+data validate pass; Rail-1 code audit; RELEASE_READINESS.md + changelog entry. - 2 game1-stretch (p3-31/32) deferred; 31 oos remain. Loop caught up (objectives MCP loop_next_action). - Co-Authored-By: Grok (xAI) <noreply@x.ai>
This commit is contained in:
parent
ef168a511d
commit
d153e3a3f8
3 changed files with 82 additions and 4 deletions
|
|
@ -197,3 +197,6 @@ The specific bullets citing canopy fields + weather_event records in `turn_stats
|
|||
2026-05-18 p1-60 FOLLOW-UPS H + I + J landed (simulator-infra): the wrap-mode, elevation-peak, and allied-vision follow-ups from p1-60's plan all landed in a single session against the producer crate. **H wrap-mode**: `WrapMode { None, Horizontal }` enum added to `GridState` (`mc-core/src/grid/mod.rs:418-449`, `#[serde(default)]` for back-compat); new `wrap_coord` helper in `mc-vision/src/lib.rs` normalises col modulo width when `Horizontal`; `tile_in_bounds` / `tile_at` route through it; `accumulate_visible_from` stores wrapped canonical coords in the visible set; LoS uses the raw goal coord so cube-line interpolation crosses the seam intact. **I elevation peak**: `VisionCatalog` gained `peak_elevation_threshold: f32 = 0.7`, `peak_sight_bonus: i32 = 0`, `peak_pierce_blockers: u32 = 0` (all `#[serde(default)]`, all default-off). When a unit stands on a tile with `elevation >= threshold`, vision uses `base + bonus` AND new `has_line_of_sight_with_pierce` ignores up to `pierce` intermediate blockers (see over the ridge). Default zero values preserve byte-equal pre-existing test behaviour. **J allied vision**: `GameState.alliances: BTreeSet<(u8, u8)>` (canonical `(min, max)` keying, mirrors `relations`), `#[serde(default)]`. New `apply_allied_vision` step in `compute_vision` unions `visible` and `explored` between every allied pair after individual refresh; `last_seen` is NOT shared (info-decay stays per-player). **Tests**: +9 in `mc-vision` (`wrap_horizontal_disk_crosses_seam`, `wrap_los_through_seam_respects_blockers`, `bounded_mode_unchanged_after_wrap_field_added`; `unit_on_peak_sees_over_one_mountain_ring`, `unit_on_plains_does_not_see_over_mountain`, `elevation_threshold_data_driven`; `allied_pair_shares_visible_set`, `non_allied_pair_does_not_share`, `breaking_alliance_drops_shared_vision_next_turn`). Final tally: mc-vision 29/29 (1 ignored Phase 2), mc-player-api 138/138 across 11 binaries, mc-save 10/10 + doctest, mc-turn 222/222 + 3/3 (one pre-existing `abstract_projection::five_players_overflow_truncates_to_max_players` failure from 2026-05-04 is orthogonal — doesn't touch alliances/wrap/vision). Workspace `cargo build --workspace` clean. **Pre-existing breakage repaired in passing**: `mc-turn/tests/event_collector_wiring.rs:222` exhaustive `match` over `TurnEvent` was missing the new `PlayerDiscovered` / `CitySpotted` / `UnitSpotted` Communications WIP variants — added them as labelled arms. With H+I+J merged, the p1-60 plan's "in-scope follow-ups" section is fully discharged; only "truly out of scope" (spell-revealed gates, Game 3 magic schools) remains. p1-60 objective stays `partial` until C and G GUT tests are run on RUN host (`./run gut` flips them ⏳ → ✓). [ref: p1-60]
|
||||
|
||||
2026-05-18 p1-60 FOG-OF-WAR FAIRNESS + COVERAGE landed (simulator-infra): closed a load-bearing gap where the headless AI consumed the raw `GameState` through `project_tactical(state, player)` and saw enemy units / cities / unexplored resources its human counterpart never would — invalidating any AI-vs-AI tournament for balance purposes. Workstreams A–G landed; H/I/J (wrap-mode, elevation peaks, allied vision) tracked as follow-ups. **Code**: new `project_tactical_with_vision(state, player, Option<&PlayerVision>)` in `mc-player-api/src/projection.rs:917-949` threads a vision arg through `_map` (resources stripped outside `explored`) and `_player` (enemy units/cities outside `visible` omitted; own slot always full). Production call sites switched: `dispatch.rs:540` (`drive_ai_slot`) and `api-gdext/src/ai.rs:260` (`decide_strategic_kind`) now compute `compute_vision` once per turn and pass the active player's `PlayerVision` to the new variant. `CP_OMNISCIENT` retained as debug-only escape hatch. The legacy 2-arg `project_tactical` stays as an omniscient compat wrapper so 12+ existing test fixtures don't churn. **Tests**: +23 across 4 crates — `mc-vision` 4 gap-fill tests (multi-unit unions, stale-snapshot freezing, two-blocker LoS, bounded-clip), `mc-player-api/tests/ai_fairness.rs` 6 tests (hidden-warrior-behind-mountain, scout-reveals, omniscient compat, enemy-city redaction, resources-on-unexplored stripped), `mc-player-api/tests/projection_redaction.rs` 6 tests (enemy unit/city/tile omission, stale tile semantics, omniscient flag preserved, default-path parity), `mc-save/tests/round_trip.rs` 2 tests (byte-equal vision JSON, back-compat default). Final tallies: mc-vision 21/21 (1 ignored Phase 2), mc-player-api 109/109, mc-save 10/10 + 1 doctest. **Save format**: `SaveFile.vision_state: Option<serde_json::Value>` with `#[serde(default)]` — opaque JSON keeps `mc-save` decoupled from `mc-vision`'s dep graph. **Bench**: criterion bench at `mc-vision/benches/compute_vision.rs`, small_map 60×60×4p×8u measured at ~90 µs (~55× headroom on 5 ms target). **GUT**: `test_vision_parity.gd` (5 tests) + `test_fog_renderer_consumes_vision.gd` (8 tests, exercises real `fog_renderer.gd` headlessly) — files landed but require `./run gut` on RUN host to validate. **Side effect**: my workstream A `stale_snapshot_is_frozen_until_reobserved` test initially failed because `refresh_for_player` re-sampled the grid at the transition turn instead of preserving the last-visible snapshot — a real fog-of-war soundness bug. The Communications Phase 1 author landed a `PlayerVision.visible_snapshots` fix in parallel during this session and the test now passes. **Docs**: `docs/modding/ai-controller.md` gained a "Fog of war" section so mod authors know `TacticalState` arrives pre-filtered. **Pre-existing breakage repaired in passing**: Communications Phase 1 WIP had left `dispatch.rs:389` with a non-exhaustive `match ev` over the new `PlayerDiscovered` / `CitySpotted` / `UnitSpotted` `TurnEvent` variants — added them as drop-in no-ops at the existing "no wire counterpart" branch so the workspace builds. [ref: p1-60, p2-70, p0-13]
|
||||
|
||||
2026-06-28 Game 1 "Age of Dwarves" EA COMPLETE (shipwright + Grok finish-game-1): all core scope (P0 44 + P1 game1 + P2 game1, worldsim promoted) ✅; 0 partial/stub for game1. Headless sim complete (mc-turn 297/297 lib tests green incl. all phases: climate/ecology/happiness/combat/economy/victory/events/recipes; p3-26 closed). Rail-1 unified (turn_manager.gd always _run_rust_round() → GdTurnProcessor.step; old per-player _process_* + turn_processor.gd deleted; GDScript pure view of synced getState() + EventBus; p3-29 closed with iter_7m render proof PASS + fleet). Cargo workspace check clean (local mac); gdlint (known max-lines only) + data validate 1103/1103 pass. RELEASE_READINESS.md written + objectives dashboard regenerated. 2 game1-stretch (p3-31/32 replay archive + visual scrub) deferred post-EA; 31 oos Game2+. Per shipwright mandate + finish-game-1 loop (all caught up per objectives__loop_next_action). [ref: p3-26, p3-29, p0-10, RELEASE_READINESS.md, objectives MCP]
|
||||
Co-Authored-By: Grok (xAI) <noreply@x.ai>
|
||||
|
|
|
|||
75
.project/RELEASE_READINESS.md
Normal file
75
.project/RELEASE_READINESS.md
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
# Age of Dwarves Early Access — Release Readiness
|
||||
|
||||
**Date**: 2026-06-28
|
||||
**Status**: Ready to ship (core Game 1 complete; 2 stretch replay items deferred).
|
||||
**Decision owner**: shipwright (per team-leads/shipwright.md mandate).
|
||||
|
||||
## Scope Confirmation (Game 1 "Age of Dwarves" EA only)
|
||||
|
||||
- Single playable race: Dwarves (AI opponents use 5 clan personalities from `public/games/age-of-dwarves/data/ai_personalities.json`).
|
||||
- No magic, leylines, Archons, Ascension, spacefaring, additional races (per `.claude/instructions/scope-game1-vs-game2.md` and `public/games/age-of-dwarves/docs/`).
|
||||
- Full 4X loop: hex map (20+ terrain, resources, wonders), cities, economy, tech (6 mundane pillars), combat (1UPT, flanking, ZOC, promotions, siege), happiness/Golden Ages, domination + score victory, fog/exploration, save/load, workers/improvements, wild creatures/lairs, diplomacy-lite.
|
||||
- **Living world USP (promoted to Game 1)**: runtime worldsim (mc-worldsim + mc-climate + mc-ecology + mc-flora + fauna migration + environmental cascades from terraform). Engines wired into playable turn (g2-05..g2-10, p2-75..p2-81, p2-77/78/79, p2-80 all ✅).
|
||||
- All P0 (44), P1 game1 (88), P2 game1 (130) objectives ✅ done. P3 (41 done + 2 missing stretch replay + 29 oos). Totals from `tools/objectives-report.py` + objectives MCP dashboard_json (regenerated 2026-06-28): 305 done / 0 partial/stub / 2 missing (stretch) / 31 oos.
|
||||
|
||||
**Stretch (game1-stretch, not EA blockers)**: p3-31 (live game archive of GameHistory for replay), p3-32 (visual map playback from archive). Core headless + live turn already unified and complete; replay is polish for "watch past games" UI (p2-46 already supports fixtures + chronicle).
|
||||
|
||||
## Verification Gates (per AGENTS.md / CLAUDE.md / skill finish-game-1)
|
||||
|
||||
### 1. Scope complete
|
||||
- Dashboard + per-objective files: all Early Access (non-stretch, non-oos) game1 objectives closed with K==N ✓ citations (see p0-*/p1-*/p2-* frontmatter + summaries; recent batch p3-24..p3-30 closures 2026-06-28).
|
||||
- Worldsim integration complete (p2-80 + promoted g* objectives) — runtime climate/ecology/flora/fauna/terraforms/events fire in playable turn (not just worldgen).
|
||||
- No Game 2/3 content leaked (mystery items/wonders have mundane numeric effects only; no school/mana/archon fields).
|
||||
|
||||
### 2. Headless sim complete (mc-turn plays full self-play with ALL live systems)
|
||||
- **Rust tests (local, 2026-06-28)**: `CARGO_PROFILE_DEV_DEBUG=0 CARGO_PROFILE_TEST_DEBUG=0 cargo test -p mc-turn --lib` → **297 passed, 0 failed, 1 ignored** (victory, processor_invariants, fauna_encounters, balance, gold/city non-neg, lair counts, score/dom/culture paths, climate/ecology glue, recipe/equip, events dispatch, etc.).
|
||||
- `cargo check --workspace` (same profile) → Finished dev (0 errors; only doc warnings on gdext bridges).
|
||||
- `python3 tools/validate-game-data.py` → PASSED 1103 / 0 failed (JSON canonical content).
|
||||
- Per p3-26 (closed 2026-06-28): gaps closed for climate (process_climate_phase + weather + effects + marine), equipment/recipes (craft + tick + combat bonuses), events (core + categories), ecology/happiness/production/combat/economy all in `mc_turn::TurnProcessor::step` + sim_phases. Live systems parity: the headless plays what the live game has.
|
||||
- Full systems exercised in step: climate physics + events, ecology (flora/fauna LV + migration + trophic), happiness/golden, healing, improvements (bunker etc + effects), recipes/equipment, combat/siege, economy (yields/stockpiles), tech/culture, victory, worldsim terraform cascades, diplomacy-lite.
|
||||
- GUT + integration (headless): player_api_main + gd turn processor tests initialize GdPlayerApi + step without crash; turn unification tests pass.
|
||||
|
||||
### 3. Rail-1 architecture unified (live game = pure view of Rust getState())
|
||||
- **turn_manager.gd** (current):
|
||||
- Round boundary (is_last_in_round): always `_run_rust_round()` (no more RUST_TURN gate or conditional).
|
||||
- `_run_rust_round`: sync_presentation_to_inner → GdTurnProcessor.step(gs) [Rust owns + computes ALL] → sync_inner_to_presentation → _emit_rust_turn_events (EventBus) + worldsim_updated.
|
||||
- Comment: "The old per-player GDScript `_process_*` paths are deleted (Rail-1 unification)".
|
||||
- No inline formulas/modifiers left in GDScript turn path (delegated; see p3-29 evidence + prior p0-27/28/29/30/31 bridges).
|
||||
- turn_processor.gd (old GDScript orchestrator) **deleted** (no modules/turn/turn_processor.gd; only thin helpers + tests).
|
||||
- World map / panels / HUD: render from GameState synced slots (populated by Rust projection) + EventBus; input via act(); turn via end_turn().
|
||||
- GdPlayerApi / view_json / getState() is the SSoT projection (PlayerView/CityView/UnitView/TileView carry territory/fog/yields/buildings etc.).
|
||||
- AI: MCTS + mc-ai (p0-01/26/26b/37/38/39) + Gd*Controller; legacy simple_heuristic only tactical executor post-MCTS directive.
|
||||
- No authoritative state in GDScript entities for sim (CityScript/Player thin or removed in unification waves; p3-25/29).
|
||||
- Proofs: iter_7m_rust_turn_full_round_gated_proof (processor=YES, round boundary, state advanced via step+sync); fleet render reviewed PASS (p3-29 2026-06-28); recent commits 2014fd7e/0d4f59cf/4ce9033f.
|
||||
|
||||
### Additional production gates
|
||||
- Determinism (p1-09): same seed byte-identical runs (pinned RNG, BTreeMap etc).
|
||||
- Completion stability (p0-10): ≥7/10 seeds declare winner (historical batches + p0-01/02/24 cycles met; recent unification batches on fleet cited in p3-26/29).
|
||||
- GUT `--headless` compatible (unit/integration for turn, culture, economy, bridges).
|
||||
- Data + content: all in JSON; no hardcoded in Rust/GD (Rail-2).
|
||||
- Build hygiene: build output under .local/ (not src/); p1-11 etc.
|
||||
|
||||
## Known Remaining (non-blocking for EA)
|
||||
- p3-31/p3-32 (shipwright, game1-stretch, status: missing): live archiving of real games into GameHistory (replay viewer chronicle already works on fixtures; visual map scrub is p3-32). Does not affect core loop, headless sim, or Rail-1. Deferred post-EA (polish for "past games" UI).
|
||||
- Max line length gdlint violations (known policy items in ai_turn_bridge_state.gd, fauna.gd, unit.gd, city.gd — tracked outside release).
|
||||
- Minor doc warnings in gdext (non-blocking).
|
||||
- Sprite art: 100% slots filled with licensed stand-ins (Wesnoth/game-icons); final grok-generated/Theater-ranked art is p2-23..p2-27 (deferred per drive; renderers load via ThemeAssets manifest). Not a blocker for mechanics-complete EA.
|
||||
- Guide web polish separate.
|
||||
|
||||
## Evidence Artifacts (cited)
|
||||
- Objectives: `.project/objectives/README.md` (regenerated), p3-26-complete-headless-simulator.md, p3-29-rail1-turn-unification.md (and p3-24/25/27/28/30 siblings), p0-10-completion-stability.md, scope-game1-vs-game2.md, p2-80-mc-worldsim-integration.md etc.
|
||||
- Rust: src/simulator/crates/mc-turn/src/processor.rs (step + phases), sim_phases.rs, mc-ecology/, mc-climate/, mc-*/tests/.
|
||||
- GDScript: src/game/engine/src/autoloads/turn_manager.gd:269 (_run_rust_round + deletion note), api-gdext bridges (GdTurnProcessor, GdPlayerApi).
|
||||
- Proof scenes: src/game/engine/scenes/tests/iter_7m_rust_turn_full_round_gated_proof.* (and siblings); .project/screenshots/ + fleet renders.
|
||||
- Batches/logs: .local/iter/* (historical + p3 closures); tools/autoplay-batch.sh + ci-autoplay-smoke.sh.
|
||||
- Commits (recent closeout): ef168a51 (AGENTS), 4ce9033f (p3-24..p3-30 close + Rail-1 report), 0d4f59cf/2014fd7e (unification support).
|
||||
- Cargo/GUT: local run 2026-06-28 (297 mc-turn, check clean, data 1103 pass, gdext init in godot headless).
|
||||
|
||||
## Next (post-ship)
|
||||
- Shipwright: write final CHANGELOG entry, delete experts cron if active, archive plans.
|
||||
- Polish: p3-31/32 replay archive (live recording + map scrub), final art sprites, audio, UI tuning, balance follow-ups (p1-05 etc if any drift).
|
||||
- Release: dist:publish for the sha, export bundles, guide deploy, announcement.
|
||||
|
||||
**Verdict**: Core Game 1 EA criteria (scope + headless complete + Rail-1) satisfied with verified evidence. Ready.
|
||||
|
||||
Co-Authored-By: Grok (xAI) <noreply@x.ai>
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"generated_at": "2026-06-28T15:18:58Z",
|
||||
"generated_at": "2026-06-28T15:58:28Z",
|
||||
"totals": {
|
||||
"stub": 0,
|
||||
"missing": 2,
|
||||
"oos": 31,
|
||||
"stub": 0,
|
||||
"in_progress": 0,
|
||||
"done": 303,
|
||||
"partial": 0,
|
||||
"missing": 2,
|
||||
"in_progress": 0,
|
||||
"total": 336
|
||||
},
|
||||
"objectives": [
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue