feat(cards): implement retain keyword

This commit is contained in:
2026-06-15 00:45:11 +09:00
parent 6427d23f50
commit b43ee02014
5 changed files with 38 additions and 8 deletions

View File

@@ -212,7 +212,7 @@ export function simulateCombat(data, rng, stats) {
else if (pc.powerEffect === 'energyPerTurn') energyBonus += pc.value;
else if (pc.powerEffect === 'blockPerTurn') pBlock += pc.value;
}
let energy = ENERGY + energyBonus; hand = []; draw(HAND_SIZE);
let energy = ENERGY + energyBonus; draw(HAND_SIZE);
while (true) {
const alive = aliveList();
if (alive.length === 0) break;
@@ -230,7 +230,13 @@ export function simulateCombat(data, rng, stats) {
let burn = 0;
for (const hid of hand) { const hc = cards[hid]; if (hc && hc.endTurnDamage) burn += hc.endTurnDamage; }
if (burn > 0) { pHp -= burn; if (pHp < 0) pHp = 0; }
discard.push(...hand); hand = [];
const kept = [];
for (const hid of hand) {
const hc = cards[hid];
if (hc?.retain === true) kept.push(hid);
else discard.push(hid);
}
hand = kept;
if (pHp <= 0) return { win: false, turns, playerHpRemaining: 0 };
// 플레이어 디버프 감소 — Lua EndPlayerTurn 동기화 (적 행동 전)
if (pWeak > 0) pWeak--;

View File

@@ -390,3 +390,18 @@ test("simulateCombat: sly discarded card resolves for free", () => {
assert.equal(r.win, true);
assert.equal(r.turns, 1);
});
test("simulateCombat: retain keeps card in hand across turns", () => {
const data = {
cards: {
Boost: { name: "Boost", cost: 3, kind: "Power", powerEffect: "energyPerTurn", value: 98 },
Hold: { name: "Hold", cost: 100, kind: "Attack", damage: 10, retain: true },
Blank: { name: "Blank", cost: 99, kind: "Skill", block: 0 },
},
starterDeck: ["Blank", "Blank", "Blank", "Blank", "Blank", "Boost", "Hold", "Blank", "Blank", "Blank"],
monsters: [{ name: "Dummy", maxHp: 10, intents: [{ kind: "Defend", value: 0 }] }],
};
const r = simulateCombat(data, () => 0.999999);
assert.equal(r.win, true);
assert.equal(r.turns, 2);
});