From 19691d0b0675b1ed49825942a0a2b75423049d5f Mon Sep 17 00:00:00 2001 From: sganggs Date: Tue, 6 Oct 2026 16:04:12 +0800 Subject: [PATCH] =?UTF-8?q?feedback5=20WE2:=20GitHub=20#148=20reproduced?= =?UTF-8?q?=20=E2=80=94=20a=20melee=20=E7=AA=81=E8=A2=AD=20member=20lands?= =?UTF-8?q?=20on=20a=20=E5=9B=B4=E5=A2=99=20tile,=20never=20a=20=E9=AB=98?= =?UTF-8?q?=E5=8F=B0;=20regression=20test=20(#3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On 战场#08 (act2 m04) the jump can land on tile_fence_bound (LOW, buildable ALL: deployable, attacks, blocks no ground enemy) when the enemy stands in the 深水区 / on floor next to the fenced blocks; the board draws the fenced region raised, the likely 「高台」 of the report. No rule change (the official landing does not say it avoids 围墙). The test runs a melee member's jump on every battle stage and enemy tile: low ground only. --- test/content/feedback5-we2-raid-148.test.js | 48 +++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 test/content/feedback5-we2-raid-148.test.js diff --git a/test/content/feedback5-we2-raid-148.test.js b/test/content/feedback5-we2-raid-148.test.js new file mode 100644 index 00000000..2ddb03f7 --- /dev/null +++ b/test/content/feedback5-we2-raid-148.test.js @@ -0,0 +1,48 @@ +// test/content/feedback5-we2-raid-148.test.js — 0.2.0 WE2 #3 (GitHub #148 「突袭近战干员部署在高台」, a battle screenshot on the +// 深水区 map): reproduced on every battle stage — a melee 突袭 member's jump (content/bonds/addon/battle.js raidTile: +// grid.canStand for its position) lands on low ground only, never on a 高台; on 战场#08 (act2 m04) it may land on a 围墙 tile +// (tile_fence_bound: LOW, buildable ALL — deployable, it attacks from there and blocks no ground enemy, DESIGN §21.23), which +// the board draws as a raised concrete area inside an orange railing: what the screenshot most likely shows. +// Run: node --test test/content/feedback5-we2-raid-148.test.js + +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { makeBattle, chessRec, enemyRec } from '../helpers/battleHarness.js'; +import { getData } from '../../server/data.js'; + +const D = getData({ log: { warn() {}, error() {}, info() {} } }); +const STAGES = Object.keys(D.stages).filter((id) => D.stages[id].kind !== 'unite'); +const defs = { + chess: { m: chessRec({ id: 'm', bonds: ['raidShip'], position: 'MELEE', range: [[0, 0], [0, 1]] }) }, + enemies: { e: enemyRec({ key: 'e', hp: 1e9, speed: 0, mass: 0 }) }, +}; +const RAID = { raidShip: { count: 3, active: true, tier: 1, layers: 1 } }; + +test('#3 / GitHub #148: a melee 突袭 member never lands on a 高台 (any stage, any enemy tile of the field); 战场#08 lands it on 围墙 tiles', () => { + let jumps = 0, fence = 0; + for (const stageId of STAGES) { + const st = D.stages[stageId]; + const tileAt = (r, c) => st.tiles[st.rows[r]?.[c]]; + // the member's start: the first deployable melee tile of the field + let home = null; + for (let r = 12; r >= 9 && !home; r--) for (let c = 2; c <= 10 && !home; c++) { + const t = tileAt(r, c); + if (t && t.height === 'LOW' && (t.buildable === 'ALL' || t.buildable === 'MELEE') && t.tileKey === 'tile_road') home = [r, c]; + } + if (!home) continue; + for (let er = 9; er <= 12; er++) for (let ec = 2; ec <= 10; ec++) { + const t = tileAt(er, ec); + if (!t || t.height !== 'LOW' || (er === home[0] && ec === home[1])) continue; + const h = makeBattle({ stageId, defs, bonds: RAID, enemies: [{ key: 'e', pos: [er, ec] }], units: [{ chessId: 'm', row: home[0], col: home[1] }], autoFinish: false, timeLimit: 60 }); + const u = h.unit('m'); + h.run(12); + if (u.tileR === home[0] && u.tileC === home[1]) continue; + jumps++; + const lt = tileAt(u.tileR, u.tileC); + assert.ok(lt && lt.height === 'LOW' && (lt.buildable === 'ALL' || lt.buildable === 'MELEE'), `${stageId}: enemy ${er},${ec} → ${u.tileR},${u.tileC} ${lt?.tileKey}/${lt?.height}`); + if (lt.tileKey === 'tile_fence_bound') fence++; + } + } + assert.ok(jumps > 50, `${jumps} jumps checked`); + assert.ok(fence > 0, 'some land on a 围墙 tile (the #148 look)'); +});