Files
i-want-to-heal/src/combat/stadiumLifecycle.ts
T
2026-06-29 22:35:49 -04:00

82 lines
2.3 KiB
TypeScript

export type StadiumRoundOutcome = 'win' | 'loss' | 'tie'
export type StadiumWins = {
player: number
opponent: number
}
export type StadiumRoundStatus = 'playing' | 'shop' | 'won' | 'lost'
export type StadiumExperienceMode =
| 'pvp-stadium-round-win-quarter-level'
| 'pvp-stadium-round-loss-tenth-level'
| 'pvp-stadium-match-half-level'
export const DEFAULT_STADIUM_WIN_ROUNDS = 3
export function stadiumShopPointsForOutcome(outcome: StadiumRoundOutcome, side: 'player' | 'opponent') {
if (side === 'player') return outcome === 'loss' ? 4 : 3
return outcome === 'win' ? 4 : 3
}
export function resolveStadiumRound({
outcome,
roundIndex,
wins,
winRounds = DEFAULT_STADIUM_WIN_ROUNDS,
}: {
outcome: StadiumRoundOutcome
roundIndex: number
wins: StadiumWins
winRounds?: number
}) {
const roundExperienceMode: StadiumExperienceMode = outcome === 'loss'
? 'pvp-stadium-round-loss-tenth-level'
: 'pvp-stadium-round-win-quarter-level'
const logTone = outcome === 'loss' ? 'danger' as const : 'loot' as const
const nextWins = {
player: wins.player + (outcome === 'win' ? 1 : 0),
opponent: wins.opponent + (outcome === 'loss' ? 1 : 0),
}
const status: StadiumRoundStatus = nextWins.player >= winRounds
? 'won'
: nextWins.opponent >= winRounds
? 'lost'
: 'shop'
return {
nextWins,
status,
playerRoundStatus: status,
roundExperience: {
key: `round-${roundIndex}-${outcome}`,
mode: roundExperienceMode,
},
matchExperience: status === 'won'
? { key: 'match-win', mode: 'pvp-stadium-match-half-level' as StadiumExperienceMode }
: null,
log: {
text: outcome === 'win'
? `Round ${roundIndex} won.`
: outcome === 'loss'
? `Round ${roundIndex} lost.`
: `Round ${roundIndex} tied.`,
tone: logTone,
},
}
}
export function chooseStadiumCpuPurchases<TId extends string, TBuff extends { id: TId; cost: number }>(
catalog: readonly TBuff[],
points: number,
random = Math.random,
) {
let remaining = points
const purchases: TId[] = []
while (remaining > 0) {
const affordable = catalog.filter((buff) => buff.cost <= remaining)
if (affordable.length === 0) break
const selected = affordable[Math.floor(random() * affordable.length)]
purchases.push(selected.id)
remaining -= selected.cost
}
return purchases
}