feedback7 R22-OSIM: 突袭 members jump to 隐匿 ground enemies too, and one in range counts for 「范围内没有敌人」 (the owner's decision, GitHub #316); golden: 5 match scenarios move

GitHub #316 (warpgenius): "Raid operator doesn't deploy to invisible enemy units, it does in official". The owner's
decision of 2026-10-08 from their official play: a 突袭 member considers 隐匿 (unrevealed) ground enemies both as landing
targets and for 「若范围内没有敌人」. Until now raidTargets and the poll used canTargetEnemy / enemiesInKeys, which leave
隐匿 out (the bond text only says 敌人 / 地面敌人).

content/bonds/addon/battle.js: raidGroundEnemy accepts what canTargetEnemy (ground) accepts, plus a 隐匿 ground enemy that
only its 隐匿 keeps out; asleep, untargetable and flying enemies stay excluded (skipEnemy too). raidStealthInRange: a 隐匿
ground enemy on the member's range stops the jump, so a ready member next to one does not hop every poll. The landing
rules are unchanged (the target in range from the landing tile; a melee member's blocking tile first).

Golden: solo-HARD-1, solo-ABYSS-1, coop2-NORMAL-3, coop4-ABYSS-7, coop2-NORMAL-70-diy — their 突袭 members (斯卡蒂, 瑕光,
宴, 伊内丝) now jump to 隐匿 enemies (潜伏者, 隐形弩手组长, …) or stay because one stands in their range.

Tests: test/sim/feedback7-raid-stealth.test.js (4; 2 fail on the parent: the jump to the only landing spot beside a 隐匿
enemy, and staying with one in range while a visible enemy waits elsewhere).
This commit is contained in:
sganggs committed 2026-10-08 21:21:44 +08:00
1 parent 69d791f9c6
commit 48a2d37e9b
4 files changed
+162 -50

No files matched your search

+85
View File
@@ -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);
}
});