feedback5 CB4: a 突袭 member lands only on its own player's board — never the boss field's hand / 临时整备区 rows, never the other half of a 联防 or boss field (community reports of 2026-10-06, items 40 and 16.3)
Cause: raidTile took any standable tile of the battle rect; BOSS_RECT holds rows 0-1 (tile_achand, buildable high ground) and UNITE_RECT both halves of the 联防 map. Battle.onOwnBoard(ps, r, c) maps the board region (rows 9-12, cols 2-10) onto the field as mapTile maps the pieces; raidTile takes only those tiles. Golden: 8 scenarios, each with members that landed on the partner's half on the parent (checked instrumented): fields boss-boss_2/3/4/5/6-pair, hidden-boss_8/10-pair; matches coop2-ABYSS-10-boosted (ai_0 on the right half). Tests: test/sim/feedback5-raid-own-board.test.js (4, fail on the parent). Docs: DESIGN §25.18.1, docs/SIM.md.
This commit is contained in:
1 parent
30d9a41c51
commit
219ab31a3d
7 files changed
+535
-352
No files matched your search
@@ -3,6 +3,7 @@
|
||||
// Installed on Battle.prototype by server/sim/Battle.js (a method container: never instantiated; `this` is the battle).
|
||||
|
||||
import { COLS, BOSS_ROW_OFFSET } from '../constants.js';
|
||||
import { GEO } from '../../../shared/constants.js';
|
||||
import { Unit } from '../units.js';
|
||||
import { normDir, mirrorDir } from '../dir.js';
|
||||
import { SkillRuntime } from '../skills.js';
|
||||
@@ -70,6 +71,29 @@ export class BattlePlayers {
|
||||
/** Board → field tile for a player (see header). */
|
||||
mapTile(ps, row, col, abs = false) {
|
||||
if (abs || ps.coords === 'field') return [row, col];
|
||||
return this._boardTile(ps, row, col);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether field tile (r, c) lies on player `ps`'s own board: the board region GEO.FIELD (rows 9–12, cols 2–10, the
|
||||
* tiles its pieces are deployed on) mapped onto this field — the 联防 right-hand helper's +8 columns, the boss field's
|
||||
* rows 2–5, the mirrored right half of a pair (whatever coordinates the player's input uses). Never the hand / 临时
|
||||
* 整备区 rows of a boss field (rows 0–1, inside BOSS_RECT) nor the other half of a 联防 or boss field. Automatic
|
||||
* redeployments that must stay where the player could deploy read it (the 突袭 landing, bonds/addon/battle.js raidTile).
|
||||
*/
|
||||
onOwnBoard(ps, r, c) {
|
||||
if (!ps) return false;
|
||||
let keys = ps._boardKeys;
|
||||
if (!keys) {
|
||||
keys = ps._boardKeys = new Set();
|
||||
for (let br = GEO.FIELD.r0; br <= GEO.FIELD.r1; br++) {
|
||||
for (let bc = GEO.FIELD.c0; bc <= GEO.FIELD.c1; bc++) { const [fr, fc] = this._boardTile(ps, br, bc); keys.add(fr * COLS + fc); }
|
||||
}
|
||||
}
|
||||
return keys.has(r * COLS + c);
|
||||
}
|
||||
|
||||
_boardTile(ps, row, col) {
|
||||
const bossLike = this.kind === 'boss' || this.kind === 'hidden';
|
||||
let r = row;
|
||||
if (ps.rowOffset != null) r = row + ps.rowOffset;
|
||||
|
||||
@@ -33,7 +33,9 @@
|
||||
// 助力 deputShip all operators DEF +(base + per·L), redeploy time ×(1 + respawn_time)
|
||||
// 突袭 raidShip member idle ≥ no_attack_duration s (or skill ready — a passive skill that is on counts, GitHub
|
||||
// #49, and so does a deploy-timed skill while it runs, #109) with no enemy in range → "保留技力立即再部署"
|
||||
// next to the most advanced ground enemy it can reach: on a free tile its position may be deployed
|
||||
// next to the most advanced ground enemy it can reach: on a free tile of its own board (Battle.onOwnBoard:
|
||||
// never a boss field's hand / 临时整备区 rows, never the other half of a 联防 or boss field — community
|
||||
// reports of 2026-10-06, items 40 and 16.3) 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) — for a melee member that blocks, a tile where its block applies first (ground
|
||||
@@ -269,7 +271,11 @@ 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 深水区 —
|
||||
* enemy, inside the field rect and on the member's own board (Battle.onOwnBoard — "再部署" goes where its player deploys:
|
||||
* never a boss field's hand row 0 or 临时整备区 row 1, both inside BOSS_RECT and buildable high ground, nor the half of the
|
||||
* 联防 or boss field that is not its player's; community reports of 2026-10-06, items 40 and 16.3: a ranged member landed
|
||||
* on the 临时整备区 row of a solo leader round, and on the right half of the one-helper 联防 map), that the member's
|
||||
* position may be deployed on (grid.canStand: never the 深水区 —
|
||||
* 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,
|
||||
@@ -293,7 +299,7 @@ function raidTile(battle, u, e, reach) {
|
||||
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;
|
||||
if (!battle.grid.inRect(r, c) || !battle.onOwnBoard(u.player, 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));
|
||||
|
||||
Reference in new issue
Block a user