From 1291c52346132e09de79a63b7e5daff6e1192612 Mon Sep 17 00:00:00 2001 From: gahusb Date: Mon, 29 Jun 2026 18:50:22 +0900 Subject: [PATCH] =?UTF-8?q?fix(balance):=20=EC=8B=9C=EB=AE=AC=20enemyStren?= =?UTF-8?q?gthLoss=EB=A5=BC=20=EC=9D=8C=EC=88=98=20=ED=9E=98=20=ED=97=88?= =?UTF-8?q?=EC=9A=A9=EC=9C=BC=EB=A1=9C=20(Lua=20=EB=8F=99=EA=B8=B0?= =?UTF-8?q?=ED=99=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PiercingWail(귀를 찢는 비명: 모든 적 힘 -6)에서 Lua는 적 공격을 (value+str-loss, 0클램프)로 줄여 StS처럼 힘이 음수로 작동하는데, JS 시뮬은 max(0, str-loss)로 힘을 0에서 클램프해 모든 적 str=0일 때 공격이 전혀 안 줄었다(게임 -6, 시뮬 -0). 기존 테스트는 str>=loss 구간만 봐서 못 잡음. Lua가 정답(게임은 정상) — 시뮬만 수정. calcEnemyAttack의 max(0,...) 제거(음수 힘 허용, 최종 calcAttack이 0클램프) + EnemyActStep을 그 헬퍼로 통일(중복 제거). RED-GREEN 테스트로 loss>str 구간 검증. 86개. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01UUvHKjrt8jqLzDeCsRRGmj --- tools/balance/sim-balance.mjs | 5 +++-- tools/balance/sim-balance.test.mjs | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/balance/sim-balance.mjs b/tools/balance/sim-balance.mjs index 3cd2b2b..c783ac6 100644 --- a/tools/balance/sim-balance.mjs +++ b/tools/balance/sim-balance.mjs @@ -55,7 +55,8 @@ export function calcAttack(base, str, weak, vulnOnTarget) { } export function calcEnemyAttack(base, str, weak, vulnOnTarget, strengthLoss = 0) { - return calcAttack(base, Math.max(0, str - strengthLoss), weak, vulnOnTarget); + // Lua EnemyActStep 동기화: 힘 손실은 (value+str) 전체에서 차감(음수 힘 허용), 최종 calcAttack이 0 클램프. + return calcAttack(base, str - strengthLoss, weak, vulnOnTarget); } // 방어 우선 차감 후 hp 적용 → { hp, block } @@ -721,7 +722,7 @@ export function simulateCombat(data, rng, stats) { const it = m.intents.length ? m.intents[Math.floor(rng() * m.intents.length)] : null; if (it) { if (it.kind === 'Attack') { - const atk = calcAttack(it.value, Math.max(0, m.str - enemyStrengthLossThisTurn), m.weak, pVuln); + const atk = calcEnemyAttack(it.value, m.str, m.weak, pVuln, enemyStrengthLossThisTurn); const beforeHp = pHp; let incoming = atk; if (pIntangible > 0 && incoming > 1) incoming = 1; diff --git a/tools/balance/sim-balance.test.mjs b/tools/balance/sim-balance.test.mjs index dabeab9..fe44e5e 100644 --- a/tools/balance/sim-balance.test.mjs +++ b/tools/balance/sim-balance.test.mjs @@ -895,6 +895,13 @@ test("calcEnemyAttack: enemyStrengthLossThisTurn reduces enemy attack damage", ( assert.equal(calcEnemyAttack(10, 6, 0, 0, 0), 16); }); +test("calcEnemyAttack: 힘 손실이 base 아래로 공격을 낮춘다 (음수 힘, Lua 동기화)", () => { + // 적 str=0, loss=6 → 힘 -6 → 10-6=4. JS가 str을 0에서 클램프하면 10(버그). Lua는 전체에서 차감. + assert.equal(calcEnemyAttack(10, 0, 0, 0, 6), 4); + assert.equal(calcEnemyAttack(10, 3, 0, 0, 6), 7); + assert.equal(calcEnemyAttack(5, 0, 0, 0, 6), 0); // 5-6=-1 → 0 클램프 +}); + test("simulateCombat: repeatOnKill repeats an attack until no kill occurs", () => { const shared = { cards: {