Files
ark-stronghold-protocol/test/content/feedback5-swire2-self-heal.test.js
T
sganggs 5d3ca339e4 feedback5 CB2: 琳琅诗怀雅's S1 仗义疏财 heals herself too — the 3×3 around her includes her own tile (community report of 2026-10-06 「琳琅诗怀雅不会治疗自己」)
Official: S1 「下一次攻击会为周围八格内血量不足70%的一名友方单位恢复…」; the client charpack (char_1033_swire2, mode S1,
ability HealAlly) selects with range x-4 (the 3×3 with her tile), ally side, _excludeOwner 0, max HP ratio 0.7, one target.
Cause: kits/ops/chess_char_3_04-swire2.js healTarget skipped her (a === unit) and kept only Chebyshev distance 1.
Now: the lowest HP ratio below 70 % of the 3×3, herself included (her own 禁疗 still stops it); the owner's 2026-10-04
cadence (a heal without an attack, once per attack cycle) unchanged.

Golden: roster-027 (琳琅诗怀雅 elite S1 in band 4: she heals herself below 70 %).
Tests: test/content/feedback5-swire2-self-heal.test.js (2, fail on the parent).
2026-10-07 02:12:34 +08:00

49 lines
2.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// test/content/feedback5-swire2-self-heal.test.js — 琳琅诗怀雅 S1 仗义疏财 heals herself too (community report of 2026-10-06
// 「干员琳琅诗怀雅不会治疗自己」): 「下一次攻击会为周围八格内血量不足70%的一名友方单位恢复…」 — the client charpack
// (char_1033_swire2, mode S1, ability HealAlly) selects with range x-4 (the 3×3 with her own tile), ally side,
// `_excludeOwner` 0, max HP ratio 0.7, one target. kits/ops/chess_char_3_04-swire2.js used to skip her own tile.
// Run: node --test test/content/feedback5-swire2-self-heal.test.js
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { makeBattle, enemyRec, checkInvariants } from '../helpers/battleHarness.js';
import { getDefaultSource } from '../../server/sim/simdata.js';
const ds = getDefaultSource();
const ID = 'chess_char_3_04_a', S1 = 'skchr_swire2_1';
const S1_INDEX = ds.rawChess(ID).skills.find((s) => s.skillId === S1).index;
const NEIGHBOUR = 'chess_char_3_16_a';
/** 琳琅诗怀雅 (S1) on (9, 5), an ally on (10, 5); HP ratios set after the deployment; coins to spare. */
function field(herRatio, allyRatio) {
const h = makeBattle({
defs: { enemies: { enemy_d: enemyRec({ key: 'enemy_d', hp: 1e7, speed: 0 }) } },
units: [{ chessId: ID, row: 9, col: 5, skillIndex: S1_INDEX }, { chessId: NEIGHBOUR, row: 10, col: 5 }],
timeLimit: 60, autoFinish: false, hooks: ['heal'], captureNoisy: true, flags: { dpInit: 60, dpMax: 99 },
});
h.step();
const u = h.unit(ID), ally = h.unit(NEIGHBOUR);
u.mem.coins = 2;
u.hp = u.s.maxHp * herRatio;
ally.hp = ally.s.maxHp * allyRatio;
h.run(1);
return { h, u, ally, heals: h.hooksOf('heal').filter((c) => c.source === u) };
}
test('alone below 70 %: a coin heals herself (her own tile is in the x-4 selector)', () => {
const { h, u, heals } = field(0.5, 1);
assert.equal(heals.length, 1, 'one heal');
assert.equal(heals[0].target, u, 'on herself');
assert.equal(u.mem.coins, 1, 'one coin spent');
checkInvariants(h.b);
assert.equal(h.b.errors.length, 0);
});
test('the lowest HP ratio of the 3×3 wins: herself below the neighbour, the neighbour below her; 70 % or more is never healed', () => {
assert.equal(field(0.4, 0.6).heals[0].target.defId, ID, 'she is lower: herself');
assert.equal(field(0.6, 0.4).heals[0].target.defId, NEIGHBOUR, 'the neighbour is lower: the neighbour');
const none = field(0.75, 1);
assert.equal(none.heals.length, 0, 'not below 70 %: no heal, the coin is kept');
assert.equal(none.u.mem.coins, 2);
});