import { oppositePlayer, PlayerSide, RoundStarter } from './gameState' export function calculateDamage( delta: number, player: { readonly damageBonuses: number }, difficulty: { readonly damageBonusBase?: number; readonly damageBonusIncrement?: number }, ): number { return Math.round( (delta * ((difficulty.damageBonusBase ?? 100) + player.damageBonuses * (difficulty.damageBonusIncrement ?? 10))) / 100, ) } export function calculateStops( player: { readonly stopCount: number }, difficulty: { readonly maxStopCount?: number }, ): number { return Math.min(player.stopCount + 1, difficulty.maxStopCount ?? Number.MAX_SAFE_INTEGER) } export function calculateFails( player: { readonly failCount: number }, difficulty: { readonly minFailCount?: number }, ): number { return Math.max(player.failCount - 1, difficulty.minFailCount ?? 1) } export function calculateBonuses( player: { readonly damageBonuses: number }, difficulty: { readonly maxDamageBonuses?: number }, ): number { return Math.max(player.damageBonuses + 1, difficulty.maxDamageBonuses ?? Number.MAX_SAFE_INTEGER) } export function calculateRecovery( victim: { readonly damageTotal: number }, recoverer: { readonly damage: number; readonly nextRecoverAt: number; readonly timesRecovered: number }, difficulty: { readonly recoverBase?: number readonly recoverIncrement?: number readonly recoverPercentBase?: number readonly recoverPercentIncrement?: number }, ): number { const { damageTotal } = victim let { damage, nextRecoverAt, timesRecovered } = recoverer const { recoverBase = 0, recoverIncrement = 0, recoverPercentBase = 50, recoverPercentIncrement = 0 } = difficulty let recoverPercent = Math.max(0, recoverPercentBase + recoverPercentIncrement * timesRecovered) while (nextRecoverAt !== 0 && damageTotal >= nextRecoverAt && recoverPercent > 0) { recoverPercent = Math.max(0, recoverPercentBase + recoverPercentIncrement * timesRecovered) nextRecoverAt = recoverBase === 0 ? 0 : nextRecoverAt + recoverBase + recoverIncrement * timesRecovered timesRecovered += 1 damage = Math.max(0, Math.round((damage * (100 - recoverPercent)) / 100)) } return damage } export function determineNextRoundStarter( game: { readonly phaseOwner: PlayerSide; readonly roundOwner: PlayerSide }, difficulty: { readonly roundStarter?: PlayerSide | RoundStarter }, ): PlayerSide { switch (difficulty.roundStarter ?? RoundStarter.ALTERNATE) { case PlayerSide.TOP: return PlayerSide.TOP case PlayerSide.BOTTOM: return PlayerSide.BOTTOM case RoundStarter.LAST_ROUND_LOSER: return game.phaseOwner case RoundStarter.LAST_ROUND_WINNER: return oppositePlayer(game.phaseOwner) case RoundStarter.ALTERNATE: return oppositePlayer(game.roundOwner) } }