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.
Review follow-up to the water / tactical point change.
- Re-orienting 伺夜 / 缪尔赛思 in place while hand and temp are full could leave
a placed 狼群 / 流形 outside the new range (it had nowhere to go and stayed
put). The re-orientation is now refused with HAND_FULL when a summon it
would leave out has no stack and no free slot. On the other paths
(promotion, an owner moved with no room) such a summon leaves the board and
its stack comes back at the next round start (grantTokensFor), so no
out-of-range placement reaches the battle.
- Citation corrected: the 深水区 rule comes from the PRTS page 深水区 (地形信息
tile_deepsea: 部署类型 全部位, 地形机制 "拒绝部署(待补充)"), corroborated by
PRTS 作战机制 (地形标记 AdvancedBuildableMask lists 深水). There is no PRTS
page 地形.
- grid.js: the tie-break note now says what changed on 战场#08 (no gate
route; a few off-route smoothed steps of the boss field go around the water).
- Documented the known limit of the inactive act1 m05: its 特制水上平台 tiles
are deployable in the prep's deploy map only; the sim does not model the
canoes and keeps those tiles non-standable.
- gameLogic.summonRange reuses facing.js rangeTiles.
Player reports #3 and #9 after the 0.1.0 release.
#3 On 战场#08(下半) 涨潮控制 (act2autochess_m04) operators could be placed in the
pool and 突袭 members jumped into it. The 深水区 (tile_deepsea) has buildableType
ALL in the level file, but it refuses deployment (PRTS 地形 深水区 "地形机制:拒绝
部署"; the season-1 战场#05 puts a 特制水上平台 - "在水上建立可以部署任意单位的
平台" - on every one of its water tiles).
- grid.js DEPLOY_REFUSED_TILES: the legend's effective build is NONE, so
canStand (突袭 landing tile, tactical points, summon tiles) never picks the
water; a hard-blocked 射击台 / mound tile takes no melee unit either.
- build-data: stages.json legend `buildable` is the effective type (the level's
value kept in `buildableType`), deployTiles exclude the water, a 特制水上平台
makes its tile deployable (act1 m05, inactive). board.js / gameLogic.js
deploy maps follow (water platforms included); bots plan on the same map.
- Gate routes are unchanged; the water now counts as non-blockable ground in
the path tie-break (audit lists updated).
#9 伺夜's 狼群 and 缪尔赛思's 流形 ("只能部署在召唤者攻击范围内", tokens.json
`ownerRange`) could be placed anywhere.
- PlayerState._legal / summonRange: a range-bound summon only on a tile of its
owner's attack range (loadout grid rotated by the owner's facing); swaps with
the owner are checked from the owner's new tile; re-orienting (or promoting)
the owner sends a summon left outside back onto its stack with a toast.
- The client lights and accepts the same tiles (gameLogic.summonRange), the bot
plans inside them, the invariants check it, the 伺夜 kit re-uses the piece's
tile only inside her range.
Tests: test/match/feedback1-placement, test/sim/feedback1-water, the opt-in
headless-Chrome test/ui/feedback1-placement.e2e (fastServer hook SP_STAGE);
existing summon / deploy / pathing tests moved off the water tiles.