GitHub #375 (FrogThai): 「水图boss会从下面这条路往蓝门走,实际应该从上路走」. The walking leaders of 战场#08(下半) 涨潮控制
(act2autochess_m04) are 铳 (level_act1autochess_h07_02 route 6; the Hidden Core 铳 on act1autochess_h08_02's patrol
routes) and 卢西恩 (act2autochess_h07_05 route 8): PATROL_MOVE (3,9) → (2,3) → (5,9). Measured (notes repro-375.mjs):
ours 「3,9 2,9 2,6 4,6 4,4 2,4 2,3」 — the lower road through the 深水区 (3,6) / (4,6) — against the official SPFA
「3,9 5,9 5,4 2,4 2,3」 along row 5 with one 深水区 (5,6); the mirrored (3,11) → (2,17) split the same way.
Cause: grid.js _buildField takes the blockable-ground preference pointer (user playtest #2) when its route crosses
strictly fewer non-blockable tiles; 深水区 is non-blockable itself (no deployment), so the lower road counted 2 against
the upper road's 3 (two floor tiles and one water tile) and won. Official pathfinding is the plain 4-neighbour SPFA
(research 08 §3.1). Now the preference pointer is taken only when its route also crosses no more 深水区 than the official
pointer's (a per-tile `deep` count beside `cost`, start excluded). Rule from the Grok triage (scratch-i1b/375.patch),
re-implemented with a precomputed Grid.deepWater mask (terrain 'deepsea': tile_deepsea and tile_deepwater).
Scope (notes dump-fields.mjs / check-official.mjs, every stage × normal / 联防 / boss rect × every walkable
destination): 48 fields change, only on the two water maps (act2 m04 boss field; the inactive act1 m05), 149 pointers,
every one back to the official pointer. The 21 accepted DEVIATIONS (战场#01 / #02 floor, #07, the inactive #05's 7
water-avoiding routes) are unchanged, as are all 154 audited gate routes and data/stages.json's groundPaths
(tools/build-data.mjs --offline into a scratch dir: every data file identical). Other boss-field preference routes of
m04 that cross fewer 深水区 than the official one stay.
Tests: test/sim/pathing-official.test.js — two new #375 tests (the four patrol legs equal the pure official waypoints;
in a real battle the 铳 climbs to row 5 and steps on the 深水区 (5,6) only), both failing on the parent;
test/sim/pathing-crosscheck.test.js — the independent reference port gets the same 深水区 rule (it flagged both the
patrol leg and a random-crate normal-field route of act2 m04 until then); test/sim/pathing-blockable.test.js — the WALK-leg
audit compares with the equal-length routes that cross no more 深水区 than ours (the 14 accepted arena exceptions
unchanged). Grid-related suites 777/777.
Golden:
- fields boss-boss_2-pair (铳 pair on act2autochess_m04, act1autochess_h07_02): the two 铳 patrol the upper roads;
leader left 5311560 → 5301010, p1 damage up / p2 down, deaths 0 / 2 → 1 / 3; still 8 / 8 kills.
- matches coop2-ABYSS-10-boosted (act2 m04; Final Assault 卢西恩, Hidden Core 铳): still cleared, team LP 800 → 615. The
bots' operators stand on the lower rows (the same tiles as before); with the leaders on the upper road the Final
Assault lasts 335 game s instead of 247 and the Hidden Core 638 instead of 190, both past the 150 real-second mark:
the overtime drain takes 17 + 168 LP (none before), no leak.
Review follow-up to the D5 fix. Two changes in grid.js _buildField:
- The road-over-floor preference smoothing is 0.1.0's again: its line of sight
may cover non-blockable tiles (Bresenham footprint, diagonal-step corners
included) only on the tile's own raw chain, and the jump stops at the first
ancestor it cannot see so. Exact crossings (a corner touch is not a crossing)
are used only to choose between the official and the preference pointer.
The previous version let the preference brush the corner of off-chain floor,
so on 战场#02's Final Assault the right-half exit route (2,10) -> (3,11)
slipped past an operator on (2,11) while the left half was still blocked on
(2,9). Both halves now mirror each other again ((2,10) -> (2,11) -> (4,11)).
- On an equal floor count the official pointer stays; the preference pointer
wins only when it merely skips a collinear official waypoint (same walk).
The old "farther waypoint" tie-break could bend an official route without
saving any floor, e.g. a crate on (10,6) of 战场#04 brought back the L via
(9,8) for the lower gate.
Still 140 of 154 stage routes official; data/stages.json groundPaths
regenerated (战场#02 boss right exit back to 0.1.0's, device-less helper paths
of #03 / #04 / #06 follow the same rule). New tests: 战场#02 boss exits mirror
and are blocked beside the exit; a single crate on any tile of an active stage
never leaves a gate route non-official without crossing strictly less floor.
The cross-check reference port follows both rules.
Community report: on 战场#04 活性源石 the lower-gate enemies walked two tiles left
of the red gate and then straight up instead of crossing diagonally from row 9
into row 10 as in the official game. The playtest #2 road-over-floor smoothing
counted the corner tiles of a diagonal step as crossed, so it bent the official
(9,10) -> (10,7) into (9,10) -> (9,8) -> (10,8) although that line only brushes
the corner of the floor tile (10,9).
grid.js now keeps the official flow field (research 08 §3.1) and replaces a
tile's pointer by the road-over-floor preference one only where its route
crosses strictly fewer non-blockable tiles (or as few with a farther waypoint);
a segment crosses the tiles whose interior it passes through (segmentTiles,
exact geometry). 140 of the 154 stage x gate x field routes are now official
(was 109); the 14 left avoid floor the official route walks over (战场#01's
col-8 road of playtest #2, boss exits of 战场#01 / #02, two 联防 partner gates).
data/stages.json groundPaths regenerated.