diff --git a/.project/objectives/p2-10l-followup-gdai-set-map.md b/.project/objectives/p2-10l-followup-gdai-set-map.md index c6e91c62..b74000fe 100644 --- a/.project/objectives/p2-10l-followup-gdai-set-map.md +++ b/.project/objectives/p2-10l-followup-gdai-set-map.md @@ -7,7 +7,7 @@ scope: game1 category: simulation owner: simulator-infra created: 2026-05-14 -updated_at: 2026-05-14b +updated_at: 2026-05-15 blocked_by: [] follow_ups: [p2-10l] --- @@ -103,6 +103,32 @@ and verify GUT passes. - ☐ `bash tools/gut-headless.sh` reports 0 failures attributable to cluster #2 — requires apricot run; deferred to ACS/CI sweep. +## 2026-05-15 — coord-space producer fix + +Production runtime exposed a deeper bug after the `update_tile` coordinate +fix (`e200634df`): `set_map` cached 960 tiles with `hex` fields written in +offset coordinates, while `update_tile` (and `mc-ai::tactical::settle::tile_at`) +search by **axial** `hex`. Negative axial r (e.g. `(25, -2)`), legitimately +emitted by every EventBus signal that drives `update_tile`, was never +present in the cache — the producer iterated an offset rectangle +`for row in range(height): for col in range(width)` and emitted +`"hex": [col, row]`. + +Fix landed in `src/game/engine/src/modules/ai/ai_turn_bridge_state.gd`: +- `build_tactical_tiles_json` now iterates `game_map.tiles.keys()` directly + (axial-keyed dict, includes negative r tiles the offset rectangle missed). +- `tile_to_dict(game_map, q, r)` renamed and documented as axial-only; the + emitted `hex` field is the axial pair so the linear-search contract in + `mc-ai::tactical::settle::tile_at` (`api-gdext/src/ai.rs:469`) matches. +- `build_single_tile_json(q, r)` renamed; all callers in `ai_turn_bridge.gd` + already pass `tile.position` (axial), so no caller-side changes needed. + +New regression test in `api-gdext/src/ai.rs::set_map_json_roundtrip_preserves_negative_axial_r` +pins the Rust contract: a JSON tile array carrying axial coords (including +negative r) round-trips faithfully and `tiles.iter().find(|t| t.hex == key)` +locates the tile. The test deliberately verifies the buggy offset pair +`(25, 22)` is absent, so it would have failed against the prior producer. + ## References - `src/simulator/api-gdext/src/ai.rs` — current `GdAiController` surface