Skip to content

Map: fix immobile-unit bookkeeping and refresh gradients on painted forbidden area - #187

Merged
genixpro merged 3 commits into
masterfrom
fix/immobile-units
Sep 8, 2026
Merged

Map: fix immobile-unit bookkeeping and refresh gradients on painted forbidden area#187
genixpro merged 3 commits into
masterfrom
fix/immobile-units

Conversation

@Giszmo

@Giszmo Giszmo commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Fix two pathfinding bookkeeping problems on the weighted-gradient engine now in master.

Fresh-map occupancy. Map::setSize initialized immobileUnits with zero, which denotes team 0 rather than an empty tile. Initialize it to IMMOBILE_UNIT_NONE (255), matching the loader. Empty cells on new maps no longer masquerade as immobile-unit obstacles.

Forbidden-area painting. Adding forbidden tiles now invalidates the team's cached building gradients, just as erasing already does. The next query rebuilds a route using the new restrictions. This invalidates all allocated swim classes through the existing resetPathfindGradients implementation; it does not add another refresh policy.

The original local-gradient indexing fix and local-dirty-flag changes are no longer part of the patch: #184 removed that pathfinder. The regression now uses full-map Uint16 gradients and all seven swim classes. It covers fresh-map occupancy, immobile units blocking exactly their own cells, closing the only gap through actual paint orders, and reopening it through an erase order. The new harness runs in Linux CI.

Validation on the adapted patch:

  • The unfixed current-master code fails the fresh-map scenario and, independently, the forbidden-paint scenario. The weighted occupancy scenario already passes on the base.
  • The fixed release harness passes all three scenarios. The latter two explicitly clear initial occupancy so the two bugs remain independently reproducible.
  • All 170 local unit tests pass. Two fixed-build runs of G2 for 15,000 ticks produce identical replay bytes and every per-tick checksum.
  • Final Ubuntu 22.04, Ubuntu 24.04 and Windows CI all pass, including the new regression on both Linux jobs.
  • A separate 90,000-tick seeded game completed, but its repeat exceeded a 600-second timeout. That longer pair is not counted as a completed determinism check.

Run scons release=1 server=0 immobile-unit-gradient-test and ./build/src/ImmobileUnitGradientHarness; use fresh, occupancy or forbidden to select a scenario. Normal game data is required; no display or external save fixture is needed.

This intentionally corrects routing behavior. Existing replay outcomes can change; repeatability of the fixed simulation is checked separately from equivalence to the broken behavior. Broad invalidation after painting may require more gradient rebuilding during brush use; allocation and rebuild remain on demand. Bradley approved the PR subject to this cleanup.

Map::setSize filled immobileUnits with 0, which is team 0's marker; the
"no unit here" sentinel is IMMOBILE_UNIT_NONE, as MapIO uses on load. On
any freshly built map (random maps, the editor, harnesses) every free
tile counted as blocked by an immobile unit, the local gradient marked
the whole window forbidden, the building was declared unreachable, and
every unit fell through to the full-map global gradient. Loaded maps
were unaffected.

Map::updateLocalGradient indexed immobileUnits with the local-window
index instead of the map index used for cases[] on the line above and
by MapGradientBuilding.cpp, so an immobile unit blocked whichever window
tile shared its number with the unit's map index, never its own tile.

test/ImmobileUnitGradientHarness.cpp links the real engine on a 64x64
map and checks both: a fresh map has no immobile unit and reachable
local gradients, and a marked unit blocks exactly its own tile. Each
scenario fails on its unfixed line.

Fable 5.1 helped authoring this commit.
@Giszmo
Giszmo requested a review from a team September 7, 2026 16:29
Game::executeAlterForbidden dropped the team's building gradients only
when area was erased. After a paint, every gradient still led through
the tiles just closed; units kept walking toward a former gap until one
of them reached the wall and the near-field check refused the step, and
the global gradient is recomputed at most once per 128 ticks on top of
that. Painting now invalidates like erasing does.

Team::dirtyGlobalGradient also marks the local gradients dirty. They
depend on the same forbidden bits, and nothing else ever invalidated
them; on generated maps this was masked until the immobile-unit fix
made local gradients usable at all.

The harness paints two forbidden rows through OrderAlterForbidden with
one gap, checks that a unit inside the local window and one outside it
both route through the gap, closes it and checks that both are cut off
at once. It fails on the unfixed code.

Fable 5.1 helped authoring this commit.
@Giszmo Giszmo changed the title Map: fix immobile-unit bookkeeping in local gradients Map: fix immobile-unit bookkeeping and refresh gradients on painted forbidden area Sep 7, 2026
@genixpro

genixpro commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Bradley approved #187 subject to removing the obsolete local-gradient changes. The adapted head is 3549fd0c5.

The remaining production changes initialize immobileUnits to its empty sentinel and invalidate weighted building gradients when painting forbidden tiles. The deleted local pathfinder remains deleted; current master's resetPathfindGradients handles all swim classes.

Verified with Apple Clang release builds in an isolated local build checkout:

  • On unfixed master, the new harness fails fresh and independently fails forbidden; occupancy already passes, confirming the old indexing repair is obsolete.
  • With the fix, all three harness scenarios pass across all seven swim classes, including closing and reopening the only route using real paint/erase orders.
  • 170 CppUnit tests pass.
  • Two completed --nox games/G2.game 15000 1 runs produce identical replay bytes and every per-tick checksum.
  • An additional seeded 90,000-tick game completed; its repeat hit a 600-second timeout and is not claimed as a completed determinism pass.
  • Ubuntu 22.04, Ubuntu 24.04 and Windows CI pass on this head (run 34180070170). The new real-engine harness is now included in Linux CI.

Commands, controls, logs and repeatability digests are retained locally in /Users/bradley/glob2-immobile-results/. The initialization and paint fixes deliberately correct routing; old replay outcomes need not remain identical to buggy behavior.

@genixpro
genixpro merged commit 546397e into master Sep 8, 2026
3 checks passed
@genixpro
genixpro deleted the fix/immobile-units branch September 8, 2026 02:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants