// The gamble (a "quantum computer" in the first theme): chips are a second // currency, hard to buy (the price rises with every chip owned) and hard to // grow. Stake chips on a cycle: win and the stake doubles, hit a jackpot and it // is multiplied, lose it, or crash and lose more than you bet. Reliability // upgrades (paid in funds) tilt the odds. Chips give a diminishing demand bonus. import { clamp } from './formulas.js'; const MAX_EXPONENT = 200; export function chipCost(state, ctx) { const g = ctx.rules.gamble; return Math.ceil(g.baseChipCost * g.chipCostGrowth ** Math.min(state.chips, MAX_EXPONENT)); } export function reliabilityCost(state, ctx) { const r = ctx.rules.gamble.reliability; return Math.ceil(r.baseCost * r.costGrowth ** state.reliabilityLevel); } /** Probabilities of each outcome of one cycle. They always sum to 1. */ export function odds(state, ctx, mods) { const g = ctx.rules.gamble; const crash = g.crashChance; const jackpot = g.jackpotChance; const reliability = g.baseWin + state.reliabilityLevel * g.reliability.perLevel + mods.reliability; const win = clamp(reliability, 0.05, g.maxWin - crash - jackpot); return { crash, jackpot, win, lose: 1 - crash - jackpot - win }; } export function buyChip(state, ctx) { const cost = chipCost(state, ctx); if (state.funds < cost || state.chips >= ctx.rules.gamble.maxChips) return false; state.funds -= cost; state.chips += 1; return true; } export function buyReliability(state, ctx) { if (state.reliabilityLevel >= ctx.rules.gamble.reliability.maxLevel) return false; const cost = reliabilityCost(state, ctx); if (state.funds < cost) return false; state.funds -= cost; state.reliabilityLevel += 1; return true; } /** * Stake `stake` chips on one cycle. Returns { outcome, stake, delta } or null * when it cannot be played (no chips, nothing staked, still cooling down). */ export function gamble(state, ctx, stake, mods, rng = Math.random) { const g = ctx.rules.gamble; const bet = Math.min(Math.floor(stake), state.chips); if (!(bet >= 1) || state.gambleCooldown > 0) return null; const p = odds(state, ctx, mods); const roll = rng(); let outcome = 'lose'; let delta = -bet; if (roll < p.crash) { outcome = 'crash'; delta = -Math.min(state.chips, Math.ceil(bet * g.crashMultiplier)); } else if (roll < p.crash + p.jackpot) { outcome = 'jackpot'; delta = bet * g.jackpotMultiplier; } else if (roll < p.crash + p.jackpot + p.win) { outcome = 'win'; delta = bet; } state.chips = clamp(state.chips + delta, 0, g.maxChips); state.gambleCooldown = g.cooldownSeconds; if (delta > 0) state.stats.gambleWins += 1; else state.stats.gambleLosses += 1; return { outcome, stake: bet, delta }; }