feedback5 WV: a melee 突袭 member that blocks lands where its block applies — a tile ground units pass with an enemy path through it or its enemy on it — before a nearer one where it blocks nothing (a 围墙 tile only when nothing else covers its enemy; never a 高台), GitHub #148 (the owner's decision of 2026-10-06); the #148 regression test updated on purpose; golden: fields boss-boss_2-pair, boss-boss_3-pair, boss-boss_4-pair, boss-boss_6-pair, boss-boss_7-pair, hidden-boss_10-pair moved — their 突袭 members (伊内丝, 缄默德克萨斯, 仇白) now land on a road tile on the enemy path instead of a 围墙 tile (or an off-path road tile)
This commit is contained in:
1 parent
7aede84be9
commit
9d85467479
3 files changed
+326
-247
No files matched your search
@@ -36,7 +36,9 @@
|
||||
// next to the most advanced ground enemy it can reach: on a free tile its position may be deployed
|
||||
// on from which its range covers that enemy (GitHub issue #51 [ASSUMED]: the first of the 8 most
|
||||
// advanced that has such a tile; none → it stays and the next poll looks again, never a jump that
|
||||
// hits nothing); grid.canStand: never the 深水区 (player report #3 after 0.1.0, members dropped
|
||||
// hits nothing) — for a melee member that blocks, a tile where its block applies first (ground
|
||||
// units pass it, an enemy path runs through it: not a 围墙 — the owner's decision of 2026-10-06,
|
||||
// GitHub #148); grid.canStand: never the 深水区 (player report #3 after 0.1.0, members dropped
|
||||
// into 战场#08's pool after an enemy wading in it); Battle.isReservedTile: never a tile a knocked-out
|
||||
// operator lies on (player report F5, members landed on a fallen teammate). A real redeployment
|
||||
// (retreat + free redeploy on the landing tile, full HP, `deploy` fires — 部署时 traits such as
|
||||
@@ -268,25 +270,35 @@ function raidReach(u) {
|
||||
* Landing tile [row, col] of a jump to enemy `e`, or null: a tile from which the member's range (`reach`, raidReach)
|
||||
* covers the enemy's body (a huge enemy: any tile it occupies — body.js), within RAID_SEARCH tiles (Chebyshev) of the
|
||||
* enemy, inside the field rect, that the member's position may be deployed on (grid.canStand: never the 深水区 —
|
||||
* player report #3 after 0.1.0) and that is free (Battle.isReservedTile: no living unit, no knocked-out operator's
|
||||
* body — player report F5 —, no waiting piece's tile). The nearest first (Chebyshev, then 0.01·Manhattan); last
|
||||
* tie-break the offset in the member's facing-RIGHT frame (sim/dir.js localOrder; for a RIGHT-facing unit the plain
|
||||
* tile-key order), so the landing tile turns with its direction. Only the tiles a range offset leads back to from a
|
||||
* body tile are looked at, so a search that finds nothing stays cheap.
|
||||
* player report #3 after 0.1.0 —, and for a melee member low ground only, never a 高台: GitHub #148) and that is free
|
||||
* (Battle.isReservedTile: no living unit, no knocked-out operator's body — player report F5 —, no waiting piece's tile).
|
||||
* A melee member that blocks takes a tile where its block applies first — ground units pass it (not a 围墙 / 围栏 tile,
|
||||
* where a unit blocks no ground enemy: Battle._blockerFor) and an enemy ground path runs through it
|
||||
* (Battle.groundPathTiles) or its enemy stands on it — over one where it would block nothing (the owner's decision of
|
||||
* 2026-10-06 after GitHub
|
||||
* #148: a member landed on a 围墙 tile, drawn raised, while a road tile covered its enemy too [ASSUMED: the official
|
||||
* landing picks among the legal tiles at random]); then the nearest (Chebyshev, then 0.01·Manhattan); last tie-break
|
||||
* the offset in the member's facing-RIGHT frame (sim/dir.js localOrder; for a RIGHT-facing unit the plain tile-key
|
||||
* order), so the landing tile turns with its direction. Only the tiles a range offset leads back to from a body tile
|
||||
* are looked at, so a search that finds nothing stays cheap.
|
||||
*/
|
||||
function raidTile(battle, u, e, reach) {
|
||||
const er = Math.round(e.y), ec = Math.round(e.x);
|
||||
const ranged = u.def?.position === 'RANGED';
|
||||
let best = null, bd = Infinity, bo = null;
|
||||
for (const k of bodyKeys(e)) {
|
||||
const body = bodyKeys(e);
|
||||
const path = !ranged && u.s.blockCnt > 0 ? battle.groundPathTiles() : null;
|
||||
let best = null, bp = 2, bd = Infinity, bo = null;
|
||||
for (const k of body) {
|
||||
const br = Math.floor(k / COLS), bc = k - br * COLS;
|
||||
for (let i = 0; i < reach.length; i += 2) {
|
||||
const r = br - reach[i], c = bc - reach[i + 1], dr = r - er, dc = c - ec;
|
||||
if (Math.abs(dr) > RAID_SEARCH || Math.abs(dc) > RAID_SEARCH) continue;
|
||||
if (!battle.grid.inRect(r, c) || !battle.grid.canStand(r, c, { ranged }) || battle.isReservedTile(r, c)) continue;
|
||||
const t = r * COLS + c;
|
||||
const p = path && battle.grid.tile(r, c).pass === 'ALL' && (path.has(t) || body.includes(t)) ? 0 : 1; // its block applies
|
||||
const d = Math.max(Math.abs(dr), Math.abs(dc)) + 0.01 * (Math.abs(dr) + Math.abs(dc));
|
||||
const o = localOrder(dr, dc, u.dir);
|
||||
if (d < bd - 1e-9 || (Math.abs(d - bd) <= 1e-9 && localBefore(o, bo))) { best = [r, c]; bd = d; bo = o; }
|
||||
if (p < bp || (p === bp && (d < bd - 1e-9 || (Math.abs(d - bd) <= 1e-9 && localBefore(o, bo))))) { best = [r, c]; bp = p; bd = d; bo = o; }
|
||||
}
|
||||
}
|
||||
return best;
|
||||
|
||||
Reference in new issue
Block a user