diff --git a/.project/history/20260518_odd_q_axial_consistency_fix.md b/.project/history/20260518_odd_q_axial_consistency_fix.md new file mode 100644 index 00000000..08eea69f --- /dev/null +++ b/.project/history/20260518_odd_q_axial_consistency_fix.md @@ -0,0 +1,57 @@ +# 2026-05-18 — odd-q neighbour table aligned with axial directions + +## Background + +`mc-core` exposed two direction conventions: `AXIAL_DIRECTIONS` (canonical, +documented in `HEX_GEOMETRY.md`) and `ODD_Q_NEIGHBORS` (the offset-coord +projection used by climate, ecology, GPU LUT, infantry shove, courier). The +two disagreed: an exhaustive 7×7 cross-check produced 182 direction +mismatches. `mc-pathfinding` had its own (correct) copy of the table. + +## Latent symptoms + +- **Climate**: `wind_direction` is written as an `AXIAL_DIRECTIONS` index + (`mc-mapgen::assign_wind` — `dirs = [3, 0, 3, 0, 3, 0]`) and read via + `hex::upwind_offset` / `downwind_offset`, which routed through the + misaligned table. CPU and GPU climate diffusion picked the wrong upwind + cell for most parities. +- **Infantry shove**: pushing "east" from an odd column resolved to the + NE hex instead of the actual east hex. +- **GPU LUT** (`mc-compute::build_neighbor_lut`) inherited the same skew — + CPU/GPU climate were broken in lockstep with each other, so unit tests + comparing the two stayed green. + +## Fix + +`crates/mc-core/src/algorithms/hex.rs::ODD_Q_NEIGHBORS` rewritten to the +axially-consistent table (the same one `mc-pathfinding` already used). A +new `odd_q_table_agrees_with_axial_directions` test pins the invariant by +cross-checking every entry against the axial round-trip. + +Two infantry shove tests (`shove_pushes_enemy_to_empty_hex`, +`shove_blocked_when_destination_occupied`) had hardcoded the broken +east-offset; updated to match the actual east hex in the odd-q stagger. + +## Verification + +Per-crate test runs after fix: + +| Crate | Tests | Result | +|---|---|---| +| `mc-core` | 250 | ✅ (added 1 locking test) | +| `mc-mapgen` | 59 | ✅ | +| `mc-compute` | 45 | ✅ | +| `mc-climate` | 324 | ✅ | +| `mc-ecology` | 7 | ✅ | +| `mc-pathfinding` | 0 (lib) | ✅ | +| `mc-turn` | 222 | ✅ (2 tests had expected values rewritten) | + +Unaffected subsystems (pure axial throughout — edge identity / ZOC, +terrain blends, river generation, hydrology `flow_out`) continued to pass +without modification. + +## Files touched + +- `src/simulator/crates/mc-core/src/algorithms/hex.rs` — table + test + doc +- `src/simulator/crates/mc-turn/src/action_handlers/infantry.rs` — two tests +- `public/games/age-of-dwarves/docs/HEX_GEOMETRY.md` — §13 status row