diff --git a/test/docs-consistency.test.js b/test/docs-consistency.test.js index eba2a1d2..ba5aa63e 100644 --- a/test/docs-consistency.test.js +++ b/test/docs-consistency.test.js @@ -301,11 +301,12 @@ test('user playtest #4 (DESIGN §18): picking by tile, timers, 机变 two taps, assert.deepEqual(ELEMENT_ORDER.slice(0, 4), ['neural', 'erosion', 'burn', 'apoptosis']); assert.deepEqual({ ...DOWN_STATE }, { COUNTING: 0, WAIT_DP: 1, WAIT_TILE: 2 }); assert.match(DESIGN, /\*\*爆发冷却\*\*/); - assert.match(DESIGN, /`down: \[\[id, respawnAt \(game s\), respawnTime \(s\), state\]\]`/); + // player report F5 after 0.1.0: the entries carry the tile the operator lies on (DESIGN §8.2 follows at integration) + assert.match(DESIGN, /`down: \[\[id, respawnAt \(game s\), respawnTime \(s\), state(, row, col)?\]\]`/); assert.match(SIM, /`burstLocked\(unit\)` in damage\.js/); assert.match(SIM, /损伤抵抗 = the target's data `epResistance`/); assert.ok(!/800 phys; no lock/.test(SIM), 'SIM §3: operators\' 侵蚀 locks too'); - assert.match(SIM, /`down: \[\[id, respawnAt, respawnTime, state\]\]`/); + assert.match(SIM, /`down: \[\[id, respawnAt, respawnTime, state, row, col\]\]`/); // #5 / #11 / #12 data rules const special = DATA.items.chess_item_4_09_e_a; assert.ok(special.shopExcluded && special.shopExcludedBy, '灼燃维式重锤 is never sold'); diff --git a/test/sim/engine-requests.test.js b/test/sim/engine-requests.test.js index 140fd104..d8521c2e 100644 --- a/test/sim/engine-requests.test.js +++ b/test/sim/engine-requests.test.js @@ -369,7 +369,7 @@ test('skill end: onEnd runs with the skill mods and range still applied, then th // --------------------------------------------------------------------------------------------------------------- // 9) redeploy { free, tile, keepSp } -test('redeploy: { tile } lands on another tile (home unchanged, later redeploys at home); { keepSp } restores SP before deploy fires', () => { +test('redeploy: { tile } lands on another tile (home unchanged; knocked out there, it comes back there); { keepSp } restores SP before deploy fires', () => { let atDeploy = null; const h = makeBattle({ defs: { chess: { t_gd: guard({ skill: { spCost: 10, initSp: 2 } }), t_x: guard({ id: 't_x' }) } }, @@ -391,7 +391,8 @@ test('redeploy: { tile } lands on another tile (home unchanged, later redeploys assert.equal(h.b.unitAt(12, 8), u); approx(atDeploy, sp, 1e-9, 'SP restored before the deploy hook'); approx(u.hp, u.s.maxHp); - // plain redeploy: initSp; knocked out later → the auto-redeploy goes home + // plain redeploy: initSp; knocked out there later → the auto-redeploy comes back on that tile (PRTS 卫戍协议/帮助 + // "…原地留下一个“倒地干员”…满足再部署条件时…自动部署至该位置"; player report F5 after 0.1.0); a retreat → home h.b.retreat(u); h.b.redeploy(u, { tile: [12, 8] }); approx(u.skill.sp, 2, 1e-9, 'without keepSp: initial SP'); @@ -399,7 +400,10 @@ test('redeploy: { tile } lands on another tile (home unchanged, later redeploys p.dp = 50; h.b.dealDamage(null, u, { amount: 1e9, type: 'true' }); assert.ok(h.runUntil(() => u.alive, u.base.respawnTime + 1)); - assert.deepEqual([u.tileR, u.tileC], [10, 4], 'auto-redeploy on the home tile'); + assert.deepEqual([u.tileR, u.tileC], [12, 8], 'auto-redeploy on the tile it lay on'); + h.b.retreat(u); + assert.equal(h.b.redeploy(u), true); + assert.deepEqual([u.tileR, u.tileC], [10, 4], 'a retreated unit comes back on its home tile'); // paid redeploy on a tile h.b.retreat(u); const dp = p.dp; diff --git a/test/sim/robustness.test.js b/test/sim/robustness.test.js index 769a06a7..26c48916 100644 --- a/test/sim/robustness.test.js +++ b/test/sim/robustness.test.js @@ -340,12 +340,13 @@ test('helpers validate their inputs: spawnDevice / relocate / spawnToken / spawn assert.ok(g.baseRangeKeys.includes(10 * 21 + 6), 'initial (DEFAULT trigger) range follows the unit'); b.kill(g); assert.equal(b.relocate(g, 12, 6), false, 'dead units stay put'); - b.redeploy(g); + b.redeploy(g); // back on the tile it was knocked out on, (10,6) (PRTS 卫戍协议/帮助: 自动部署至该位置) // spawnToken on a busy tile (even with force) → null, no half-built token left behind const aliveBefore = b.allyUnits.filter((u) => u.alive).length; const hooks = hookCount(b); assert.equal(g.alive, true); - assert.equal(b.spawnToken('p1', 'x_token', 9, 5, { def: { name: 't', stats: { maxHp: 100 } }, force: true }), null); + assert.deepEqual([g.tileR, g.tileC], [10, 6]); + assert.equal(b.spawnToken('p1', 'x_token', 10, 6, { def: { name: 't', stats: { maxHp: 100 } }, force: true }), null); assert.equal(b.allyUnits.filter((u) => u.alive).length, aliveBefore, 'no half-built token'); assert.ok(hookCount(b) <= hooks); const t = b.spawnToken('p1', 'x_token', 12, 8, { def: { name: 't', stats: { maxHp: 100 } }, hp: NaN, stats: { atk: NaN, def: 50 } });