feedback7: merge fb7-owner-sim (48a2d37e) — #316: 突袭 members jump to 隐匿 ground enemies too and one in range counts as 范围内有敌人 (the owner's decision of 2026-10-08)
- Golden union: coop2-ABYSS-10-boosted and coop2-NORMAL-14-standins differ from HEAD though the commit alone left them — HEAD's side had moved both, and on the new paths 隐匿 enemies meet active 突袭 members (14-standins: raidShip on; round 10 kills 26 → 27, leaks 3 → 2, team LP 39 → 40; ABYSS-10: a few 阿戈尔 layers, team LP 793 → 795); no outcome change. - Broad node --test 5575 (5574 pass, 0 fail, 1 skipped); lint 0 errors.
This commit is contained in:
commit
3969e4b012
4 files changed
+141
-29
No files matched your search
@@ -0,0 +1,85 @@
|
||||
// test/sim/feedback7-raid-stealth.test.js — 突袭 and 隐匿 ground enemies: the owner's decision of 2026-10-08 (GitHub #316
|
||||
// "Raid operator doesn't deploy to invisible enemy units, it does in official", confirmed by the owner's own play): a 突袭
|
||||
// member jumps next to a 隐匿 (unrevealed) ground enemy, and one already in its range counts for 「若范围内没有敌人」 (no
|
||||
// hop). Asleep, untargetable and flying enemies stay out, as before (bond text: 「再部署至一名地面敌人周围」).
|
||||
// Run: node --test test/sim/feedback7-raid-stealth.test.js
|
||||
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { makeBattle, chessRec, enemyRec, checkInvariants } from '../helpers/battleHarness.js';
|
||||
import { enemyStealthed } from '../../server/sim/targeting.js';
|
||||
|
||||
const HOME = [12, 3];
|
||||
const BONDS = { raidShip: { count: 2, active: true, tier: 1, layers: 0 } };
|
||||
/**
|
||||
* A field where (10,7) is the only tile a melee member may land on beside the enemy at (10,8): the rest of rows 9–12 is
|
||||
* undeployable floor ('f'), its home (12,3) road.
|
||||
*/
|
||||
const ONE_SPOT = { rows: {
|
||||
9: '##Efffffff' + 'S' + 'fffffffS##',
|
||||
10: '##hffffrff' + 'f' + 'ffffffff##',
|
||||
11: '##hfffffff' + 'f' + 'ffffffff##',
|
||||
12: '##hrffffff' + 'S' + 'fffffffS##',
|
||||
} };
|
||||
|
||||
/** `foe` at `pos` (with the buff flags `flags`), and optionally a visible `vis` at `visible`. */
|
||||
function field({ pos = [10, 8], flags = null, fly = false, visible = null, range = [[0, 0], [0, 1]] } = {}) {
|
||||
const h = makeBattle({
|
||||
flat: ONE_SPOT, bonds: BONDS, autoFinish: false, timeLimit: 60, hooks: ['deploy'],
|
||||
defs: {
|
||||
chess: { raider: chessRec({ id: 'raider', profession: 'WARRIOR', position: 'MELEE', bonds: ['raidShip'], rangeGrid: range, skill: { spCost: 10, initSp: 10 } }) },
|
||||
enemies: {
|
||||
foe: enemyRec({ key: 'foe', hp: 1e7, speed: 0, atk: 0, motion: fly ? 'FLY' : 'WALK' }),
|
||||
vis: enemyRec({ key: 'vis', hp: 1e7, speed: 0, atk: 0 }),
|
||||
},
|
||||
},
|
||||
units: [{ chessId: 'raider', row: HOME[0], col: HOME[1], dir: 'RIGHT' }],
|
||||
enemies: [{ key: 'foe', pos }, ...(visible ? [{ key: 'vis', pos: visible }] : [])],
|
||||
setup(b) {
|
||||
if (flags) b.on('enemySpawn', (c) => { if (/foe$/.test(c.enemy.defId)) b.addBuff(c.enemy, { key: 'test:mark', persist: true, flags }); });
|
||||
},
|
||||
});
|
||||
return h;
|
||||
}
|
||||
const jumps = (h) => h.hooksOf('deploy').filter((c) => c.unit === h.unit('raider') && !c.initial).length;
|
||||
const at = (h) => [h.unit('raider').tileR, h.unit('raider').tileC];
|
||||
const foe = (h) => h.b.enemies.find((e) => e.alive && /foe$/.test(e.defId));
|
||||
|
||||
test('a ready 突袭 member jumps to the only landing spot beside a 隐匿 ground enemy, and does not hop again', () => {
|
||||
const h = field({ flags: { stealth: true } });
|
||||
h.run(1);
|
||||
assert.equal(enemyStealthed(foe(h)), true, 'still 隐匿 (not blocked, not revealed)');
|
||||
assert.deepEqual(at(h), [10, 7], 'landed on the one tile beside it');
|
||||
assert.equal(jumps(h), 1);
|
||||
h.run(3);
|
||||
assert.equal(jumps(h), 1, 'the 隐匿 enemy in its range is an enemy in range: no hop');
|
||||
assert.deepEqual(at(h), [10, 7]);
|
||||
checkInvariants(h.b);
|
||||
});
|
||||
|
||||
test('a visible ground enemy: the same landing (control)', () => {
|
||||
const h = field();
|
||||
h.run(1);
|
||||
assert.deepEqual(at(h), [10, 7]);
|
||||
assert.equal(jumps(h), 1);
|
||||
checkInvariants(h.b);
|
||||
});
|
||||
|
||||
test('a 隐匿 ground enemy already in its range: 「范围内没有敌人」 is false — it stays, though a visible one waits elsewhere', () => {
|
||||
const h = field({ pos: [12, 4], flags: { stealth: true }, visible: [10, 8] });
|
||||
h.run(3);
|
||||
assert.equal(enemyStealthed(foe(h)), true);
|
||||
assert.deepEqual(at(h), HOME);
|
||||
assert.equal(jumps(h), 0);
|
||||
checkInvariants(h.b);
|
||||
});
|
||||
|
||||
test('asleep or flying 隐匿 enemies are still no destination', () => {
|
||||
for (const opts of [{ flags: { stealth: true, sleep: true } }, { flags: { stealth: true }, fly: true }]) {
|
||||
const h = field(opts);
|
||||
h.run(3);
|
||||
assert.deepEqual(at(h), HOME, JSON.stringify(opts));
|
||||
assert.equal(jumps(h), 0);
|
||||
checkInvariants(h.b);
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user