import { drawCards } from "./state.js"; export function calculateHitDamage( base, strength, targetVulnerable, attackerWeak, ) { if (targetVulnerable && attackerWeak) { return base + strength; } let damage = base + strength; if (targetVulnerable) { damage *= 2; } if (attackerWeak) { damage -= 1; } return Math.max(0, damage); } export function resolveEffects(state, effects, source, target) { let current = state; for (const effect of effects) { current = resolveSingleEffect(current, effect, source, target); } return current; } function resolveSingleEffect(state, effect, source, target) { switch (effect.type) { case "hit": return resolveHit(state, effect.value, source, target); case "block": return resolveBlock(state, effect.value, source); case "vulnerable": return applyStatus(state, target, "vulnerable", effect.value, 3); case "weak": return applyStatus(state, target, "weak", effect.value, 3); case "strength": return applyStatus(state, source, "strength", effect.value, 8); case "draw": return drawCards(state, effect.value); case "lose_hp": return directDamage(state, source, effect.value); case "exhaust": // handled by playCard — card goes to exhaustPile instead of discardPile return state; default: console.debug(`unhandled effect type: ${effect.type}`); return state; } } function resolveHit(state, baseValue, source, target) { const attacker = state[source]; const defender = state[target]; const damage = calculateHitDamage( baseValue, attacker.strength, defender.vulnerable > 0, attacker.weak > 0, ); let block = defender.block; let hp = defender.hp; let remaining = damage; if (block > 0) { const absorbed = Math.min(block, remaining); block -= absorbed; remaining -= absorbed; } hp = Math.max(0, hp - remaining); const vulnerable = Math.max(0, defender.vulnerable - 1); const attackerWeak = Math.max(0, state[source].weak - 1); return { ...state, [target]: { ...defender, hp, block, vulnerable }, [source]: { ...state[source], weak: attackerWeak }, }; } function resolveBlock(state, value, source) { const entity = state[source]; const maxBlock = source === "player" ? 20 : 999; const block = Math.min(entity.block + value, maxBlock); return { ...state, [source]: { ...entity, block }, }; } function applyStatus(state, target, status, value, max) { const entity = state[target]; const current = entity[status] || 0; return { ...state, [target]: { ...entity, [status]: Math.min(current + value, max) }, }; } function directDamage(state, target, value) { const entity = state[target]; return { ...state, [target]: { ...entity, hp: Math.max(0, entity.hp - value) }, }; }