TypeScript 97.6%
SQL 1.4%
JavaScript 0.5%
1import { defineCrashGame, type CrashGameDefinition } from "@spinza/game-core";23/**4 * Spinza Risk Games — ten cash-out games sharing one provably-fair engine.5 * Every game: P(crash ≥ x) = 0.96 / x. Curves and events only change pacing.6 */78const RULES_COMMON = [9 "Place a bet and start the round. The multiplier begins at 1.00× and climbs.",10 "Press the big button at any moment to lock in your bet × the current multiplier.",11 "If the round ends before you cash out, the bet is lost.",12 "Optional auto cash-out settles automatically at your target multiplier.",13 "Every round is provably fair: the crash point is committed (SHA-256) before the round starts and revealed after it ends.",14];1516export const skyfall = defineCrashGame({17 slug: "skyfall",18 name: "Skyfall",19 version: "1.0.0",20 tagline: "How high before the sky runs out?",21 description: "A jet climbs through clouds, storms and the stratosphere into open space. The multiplier rises with the altitude — cash out before the aircraft vanishes.",22 theme: "aviation ascent",23 rtp: 0.96,24 maxMultiplier: 5000,25 volatility: "high",26 curve: { type: "exp", k: 0.075 },27 events: { chance: 0.35, max: 1, window: [3, 18], kinds: [{ id: "tailwind", label: "Tailwind", factor: 1.8, duration: [2, 4], weight: 1 }] },28 milestones: [29 { multiplier: 1.5, label: "Cloud layer" },30 { multiplier: 3, label: "Storm front" },31 { multiplier: 8, label: "Stratosphere" },32 { multiplier: 25, label: "Edge of space" },33 { multiplier: 100, label: "Orbit" },34 ],35 presentation: { scene: "sky", palette: { primary: "#7dd3fc", secondary: "#fbbf24", glow: "#bae6fd", bg: "#08111f", surface: "#0f2540" }, verb: "CASH OUT", unit: "m", unitScale: 1200, ambience: "lunar" },36 rules: [...RULES_COMMON, "A Tailwind event speeds the climb for a few seconds without changing the odds."],37});3839export const deepDive = defineCrashGame({40 slug: "deep-dive",41 name: "Deep Dive",42 version: "1.0.0",43 tagline: "The abyss pays. The abyss also implodes.",44 description: "A research submarine sinks into the ocean. 1,000 m is ×2, 3,000 m is ×5, the abyss is ×20 and beyond. Surface before the hull gives in. Leviathans sometimes drag you deeper, faster.",45 theme: "deep-sea descent",46 rtp: 0.96,47 maxMultiplier: 5000,48 volatility: "high",49 curve: { type: "exp", k: 0.07 },50 events: { chance: 0.3, max: 2, window: [4, 20], kinds: [{ id: "leviathan", label: "Leviathan current", factor: 2.2, duration: [1.5, 3], weight: 1 }] },51 milestones: [52 { multiplier: 2, label: "1,000 m — twilight zone" },53 { multiplier: 5, label: "3,000 m — midnight zone" },54 { multiplier: 20, label: "Abyssal plain" },55 { multiplier: 80, label: "Hadal trench" },56 ],57 presentation: { scene: "ocean", palette: { primary: "#22d3ee", secondary: "#34d399", glow: "#67e8f9", bg: "#03111c", surface: "#062a3a" }, verb: "SURFACE", unit: "m", unitScale: 500, ambience: "ocean" },58 rules: [...RULES_COMMON, "Leviathan currents briefly accelerate the descent — a pacing event only."],59});6061export const rocketRun = defineCrashGame({62 slug: "rocket-run",63 name: "Rocket Run",64 version: "1.0.0",65 tagline: "Mars or bust.",66 description: "A rocket leaves the pad for Mars. Every second adds to the multiplier and some runs reach absurd heights — until an engine failure, a collision or an overheat ends it instantly. Secure the payload whenever you like.",67 theme: "space launch",68 rtp: 0.96,69 maxMultiplier: 10000,70 volatility: "extreme",71 curve: { type: "exp", k: 0.095 },72 events: { chance: 0.25, max: 1, window: [2, 14], kinds: [{ id: "afterburner", label: "Afterburner", factor: 2, duration: [1.5, 3], weight: 1 }] },73 milestones: [74 { multiplier: 2, label: "Max-Q" },75 { multiplier: 5, label: "Stage separation" },76 { multiplier: 15, label: "Escape velocity" },77 { multiplier: 60, label: "Trans-Mars injection" },78 { multiplier: 300, label: "Mars orbit" },79 ],80 presentation: { scene: "rocket", palette: { primary: "#fb923c", secondary: "#f472b6", glow: "#fdba74", bg: "#0a0612", surface: "#1b0f2a" }, verb: "SECURE PAYLOAD", unit: "km", unitScale: 40, ambience: "space" },81 rules: [...RULES_COMMON, "Afterburner windows speed up the climb for a moment."],82});8384export const bankHeist = defineCrashGame({85 slug: "bank-heist",86 name: "Bank Heist",87 version: "1.0.0",88 tagline: "The bag keeps filling. The sirens keep coming.",89 description: "You are inside the vault and the bag of fictional cash keeps growing: ×1.1, ×1.4, ×2, ×3… Stay longer for more, but the police can arrive at any second. Escape before they do and the multiplier is yours.",90 theme: "heist",91 rtp: 0.96,92 maxMultiplier: 2500,93 volatility: "medium",94 curve: { type: "exp", k: 0.062 },95 events: { chance: 0.3, max: 1, window: [3, 16], kinds: [{ id: "jammer", label: "Signal jammer", factor: 1.6, duration: [2, 4], weight: 1 }] },96 milestones: [97 { multiplier: 1.4, label: "Teller drawers" },98 { multiplier: 2, label: "Safe deposit boxes" },99 { multiplier: 4, label: "Main vault" },100 { multiplier: 12, label: "Diamond room" },101 { multiplier: 50, label: "Federal reserve" },102 ],103 presentation: { scene: "bank", palette: { primary: "#c9a961", secondary: "#ef4444", glow: "#e8cf8f", bg: "#0b0a08", surface: "#1b1811" }, verb: "ESCAPE NOW", unit: "bags", unitScale: 1, ambience: "heist" },104 rules: [...RULES_COMMON, "Signal jammer windows fill the bag faster for a few seconds."],105});106107export const volcano = defineCrashGame({108 slug: "volcano",109 name: "Volcano",110 version: "1.0.0",111 tagline: "Deeper crystals. Rising lava.",112 description: "An explorer descends into a live volcano to harvest crystals. The deeper, the richer — but the lava level rises unpredictably. Trigger EVACUATE before the eruption.",113 theme: "volcanic descent",114 rtp: 0.96,115 maxMultiplier: 5000,116 volatility: "high",117 curve: { type: "exp", k: 0.08 },118 events: { chance: 0.3, max: 1, window: [3, 15], kinds: [{ id: "vein", label: "Crystal vein", factor: 1.9, duration: [1.5, 3], weight: 1 }] },119 milestones: [120 { multiplier: 1.5, label: "Ash caves" },121 { multiplier: 3, label: "Obsidian galleries" },122 { multiplier: 8, label: "Crystal chamber" },123 { multiplier: 30, label: "Magma core" },124 ],125 presentation: { scene: "volcano", palette: { primary: "#ff5c3d", secondary: "#fbbf24", glow: "#ff8a5c", bg: "#120604", surface: "#2a0c07" }, verb: "EVACUATE", unit: "m", unitScale: 60, ambience: "fire" },126 rules: [...RULES_COMMON, "Crystal veins speed up the harvest briefly."],127});128129export const blackHole = defineCrashGame({130 slug: "black-hole",131 name: "Black Hole",132 version: "1.0.0",133 tagline: "Time slows. The multiplier doesn't.",134 description: "Your ship drifts toward an event horizon. The multiplier creeps at first, then explodes as space-time bends: ×10 becomes ×15, ×25, ×50 in a heartbeat. WARP OUT before you are pulled in.",135 theme: "relativistic descent",136 rtp: 0.96,137 maxMultiplier: 10000,138 volatility: "extreme",139 curve: { type: "power", a: 0.02, p: 2.6 },140 milestones: [141 { multiplier: 1.5, label: "Accretion disk" },142 { multiplier: 4, label: "Photon sphere" },143 { multiplier: 15, label: "Spaghettification" },144 { multiplier: 60, label: "Event horizon" },145 ],146 presentation: { scene: "blackhole", palette: { primary: "#a78bfa", secondary: "#f0abfc", glow: "#c4b5fd", bg: "#050308", surface: "#120a24" }, verb: "WARP OUT", unit: "km", unitScale: 1000, ambience: "void" },147 rules: [...RULES_COMMON, "The curve accelerates sharply near the horizon — the same odds, much faster."],148});149150export const freefall = defineCrashGame({151 slug: "freefall",152 name: "Freefall",153 version: "1.0.0",154 tagline: "Pull late. Not too late.",155 description: "A skydiver leaps from the edge of the atmosphere. The reward grows during the fall — slowly at altitude, brutally fast near the ground. Open the chute in time or lose the round.",156 theme: "skydiving",157 rtp: 0.96,158 maxMultiplier: 5000,159 volatility: "high",160 curve: { type: "power", a: 0.05, p: 2.1 },161 events: { chance: 0.25, max: 1, window: [3, 14], kinds: [{ id: "thermal", label: "Thermal", factor: 0.5, duration: [2, 3], weight: 1 }] },162 milestones: [163 { multiplier: 1.3, label: "Terminal velocity" },164 { multiplier: 3, label: "Cloud deck" },165 { multiplier: 10, label: "Treetops" },166 { multiplier: 40, label: "Ground rush" },167 ],168 presentation: { scene: "freefall", palette: { primary: "#60a5fa", secondary: "#f97316", glow: "#93c5fd", bg: "#07101e", surface: "#0e2140" }, verb: "OPEN CHUTE", unit: "m", unitScale: -300, ambience: "lunar" },169 rules: [...RULES_COMMON, "Thermal updrafts slow the fall for a moment — more time to decide."],170});171172export const coreMeltdown = defineCrashGame({173 slug: "core-meltdown",174 name: "Core Meltdown",175 version: "1.0.0",176 tagline: "Stable… stable… SHUT DOWN.",177 description: "An experimental reactor produces energy as long as it stays stable. Temperature climbs; the multiplier climbs with it. Cooling events can buy you time. Shut down before the limit or lose the batch.",178 theme: "reactor control room",179 rtp: 0.96,180 maxMultiplier: 5000,181 volatility: "high",182 curve: { type: "exp", k: 0.07 },183 events: { chance: 0.45, max: 2, window: [2, 18], kinds: [{ id: "coolant", label: "Coolant surge", factor: 0.45, duration: [2, 3.5], weight: 3 }, { id: "spike", label: "Power spike", factor: 1.8, duration: [1, 2], weight: 1 }] },184 milestones: [185 { multiplier: 1.5, label: "Nominal" },186 { multiplier: 3, label: "Elevated" },187 { multiplier: 8, label: "Critical" },188 { multiplier: 25, label: "Containment stress" },189 ],190 presentation: { scene: "reactor", palette: { primary: "#a3e635", secondary: "#facc15", glow: "#bef264", bg: "#070c06", surface: "#111c0e" }, verb: "SHUT DOWN", unit: "°C", unitScale: 90, ambience: "reactor" },191 rules: [...RULES_COMMON, "Coolant surges slow the temperature climb; power spikes speed it up."],192});193194export const stormChase = defineCrashGame({195 slug: "storm-chase",196 name: "Storm Chase",197 version: "1.0.0",198 tagline: "Drive into the wall cloud.",199 description: "You race toward a giant tornado. The closer to the core, the higher the multiplier — but the storm can turn and swallow the truck without warning. ESCAPE while the road is still there.",200 theme: "storm chasing",201 rtp: 0.96,202 maxMultiplier: 5000,203 volatility: "high",204 curve: { type: "exp", k: 0.078 },205 events: { chance: 0.3, max: 1, window: [3, 15], kinds: [{ id: "gust", label: "Rear-flank gust", factor: 1.9, duration: [1.5, 3], weight: 1 }] },206 milestones: [207 { multiplier: 1.5, label: "Outflow" },208 { multiplier: 3, label: "Debris field" },209 { multiplier: 8, label: "Wall cloud" },210 { multiplier: 30, label: "Vortex" },211 ],212 presentation: { scene: "storm", palette: { primary: "#94a3b8", secondary: "#a3e635", glow: "#cbd5e1", bg: "#0a0d12", surface: "#1a212c" }, verb: "ESCAPE", unit: "m", unitScale: -400, ambience: "reactor" },213 rules: [...RULES_COMMON, "Rear-flank gusts pull you toward the core faster for a moment."],214});215216export const elevator999 = defineCrashGame({217 slug: "elevator-999",218 name: "Elevator 999",219 version: "1.0.0",220 tagline: "Every floor is a decision.",221 description: "An elevator climbs an endless tower. Each floor raises the multiplier; you may step out and cash out at any floor. The elevator can fail at any moment. Floors 25, 50, 100 and 250 are express zones where the climb accelerates.",222 theme: "infinite tower",223 rtp: 0.96,224 maxMultiplier: 10000,225 volatility: "high",226 curve: { type: "steps", stepSeconds: 0.55, base: 1.05 },227 milestones: [228 { multiplier: Math.pow(1.05, 25), label: "Floor 25 — Sky lobby" },229 { multiplier: Math.pow(1.05, 50), label: "Floor 50 — Observation deck" },230 { multiplier: Math.pow(1.05, 100), label: "Floor 100 — Cloud gardens" },231 { multiplier: Math.pow(1.05, 250), label: "Floor 250 — Stratos suite" },232 ],233 presentation: { scene: "elevator", palette: { primary: "#e8cf8f", secondary: "#38bdf8", glow: "#f3e2ad", bg: "#08090d", surface: "#151821" }, verb: "STEP OUT", unit: "floor", unitScale: 1, ambience: "obsidian" },234 rules: [...RULES_COMMON, "The multiplier grows 5% per floor (1.05× compounded). Special floors mark express zones."],235});236237export const CRASH_GAMES: CrashGameDefinition[] = [skyfall, deepDive, rocketRun, bankHeist, volcano, blackHole, freefall, coreMeltdown, stormChase, elevator999];238export const CRASH_BY_SLUG = new Map(CRASH_GAMES.map((g) => [g.slug, g]));239