Claude Sonnet 4.6 × slots
0.0Vegas slot machine — reels, pay table, betting, win animations
correctness 0.0quality 0.0documentation 0.081929ms
$ cat slots.prompt — what the model was asked
Build a fully playable Vegas-style slot machine in a single self-contained HTML file with no external libraries and no external assets.
## Reels
- 3 reels, each with these 7 symbols: 🍒 Cherry, 🍋 Lemon, 🍊 Orange, 🍇 Grape, 🔔 Bell, ⭐ Star, 7️⃣ Seven
- Spin animation: each reel spins independently (reel 1 stops ~800ms, reel 2 ~1200ms, reel 3 ~1600ms), showing symbols scrolling at ~12 symbols/sec before snapping to the result
- SPIN button disabled while spinning
## Pay table (multipliers × bet)
- 7️⃣ 7️⃣ 7️⃣ → 100×
- ⭐ ⭐ ⭐ → 50×
- 🔔 🔔 🔔 → 20×
- 🍇 🍇 🍇 → 15×
- 🍊 🍊 🍊 → 10×
- 🍋 🍋 🍋 → 5×
- 🍒 🍒 🍒 → 3×
- Any two 🍒 in first two positions → 2×
- All other → 0× (loss)
## Betting & credits
- Start with 100 credits
- Bet buttons: 1, 5, 10 credits (highlighted active; default: 1)
- Bet deducted immediately on spin; win adds bet × multiplier
- GAME OVER at 0 credits with 'Play Again' button that resets to 100
## Win feedback
- Win: flash matching symbols, show '+[amount] credits' in gold, display win name ('JACKPOT!', 'THREE BELLS', etc.)
- Loss: shake animation on reels
- Credit balance count-up animation over 400ms
## Pay table display
- Visible panel on page (not a modal) listing all combinations
- Highlight winning row when that combination hits
## Code quality
- Single HTML file; all JS in <script>, all CSS in <style>
- Game state: { credits, bet, spinning, reels, result }
- Named functions: initState(), spin(), checkWin(), animateReels(), updateUI()
- RNG: Math.random() only
- No inline onclick= handlers; use addEventListenerrun 1 of 1
0.0correctness 0.0quality 0.0documentation 0.081929ms
# judge: Response is truncated mid-CSS with no JavaScript at all, so the file is not valid HTML and none of the required game logic or functions exist.
$ cat claude-sonnet-4-6.slots.r1.response
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vegas Slots</title>
<style>
:root {
--gold: #ffd700;
--dark-gold: #b8860b;
--red: #c0392b;
--green: #27ae60;
--bg: #1a0a2e;
--panel: #2d1b4e;
--reel-bg: #0d0d0d;
--border: #6a0dad;
--text: #f0e6ff;
--highlight: #ff6b6b;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
background: var(--bg);
color: var(--text);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
background-image:
radial-gradient(ellipse at top, #3a0a5e 0%, #1a0a2e 60%),
repeating-linear-gradient(
45deg,
transparent,
transparent 10px,
rgba(106,13,173,0.05) 10px,
rgba(106,13,173,0.05) 20px
);
}
h1 {
font-size: 2.8rem;
color: var(--gold);
text-shadow: 0 0 20px rgba(255,215,0,0.7), 0 0 40px rgba(255,215,0,0.4);
letter-spacing: 4px;
margin-bottom: 20px;
text-transform: uppercase;
font-weight: 900;
}
.main-layout {
display: flex;
gap: 24px;
align-items: flex-start;
width: 100%;
max-width: 900px;
}
/* ── MACHINE ── */
.machine {
flex: 1;
background: linear-gradient(160deg, #3a1060 0%, #1e0840 100%);
border: 3px solid var(--border);
border-radius: 20px;
padding: 24px;
box-shadow: 0 0 40px rgba(106,13,173,0.6), inset 0 0 20px rgba(0,0,0,0.4);
min-width: 320px;
}
/* Win announcement */
#win-announcement {
text-align: center;
font-size: 1.5rem;
font-weight: 900;
letter-spacing: 2px;
min-height: 2rem;
margin-bottom: 12px;
color: var(--gold);
text-shadow: 0 0 10px rgba(255,215,0,0.8);
transition: opacity 0.3s;
}
#win-announcement.hidden { opacity: 0; }
/* Reels container */
.reels-wrapper {
background: #000;
border: 3px solid #444;
border-radius: 12px;
padding: 8px;
box-shadow: inset 0 0 20px rgba(0,0,0,0.8), 0 0 15px rgba(0,0,0,0.5);
position: relative;
overflow: hidden;
}
.reels-wrapper::before,
.reels-wrapper::after {
content: '';
position: absolute;
left: 0; right: 0;
height: 60px;
z-index: 10;
pointer-events: none;
}
.reels-wrapper::before {
top: 0;
background: linear-gradient(to bottom, rgba(0,0,0,0.85), transparent);
}
.reels-wrapper::after {
bottom: 0;
background: linear-gradient(to top, rgba(0,0,0,0.85), transparent);
}
.reels-row {
display: flex;
gap: 8px;
}
/* Payline indicator */
.payline {
position: absolute;
left: 8px; right: 8px;
top: 50%;
transform: translateY(-50%);
height: 3px;
background: rgba(255,215,0,0.5);
z-index: 11;
pointer-events: none;
box-shadow: 0 0 8px rgba(255,215,0,0.7);
}
/* Individual reel */
.reel {
flex: 1;
height: 160px;
overflow: hidden;
background: var(--reel-bg);
border-radius: 8px;
border: 2px solid #333;
position: relative;
}
.reel-strip {
display: flex;
flex-direction: column;
position: absolute;
width: 100%;
top: 0;
transition: none;
}
.reel-symbol {
height: 80px;
display: flex;
align-items: center;
justify-content: center;
font-size: 2.6rem;
flex-shrink: 0;
user-select: none;
position: relative;
}
/* The visible center cell */
.reel-symbol.result-cell {
background: rgba(255,255,255,0.03);
}
/* Flash animation for winners */
@keyframes flash-win {
0%, 100% { background: rgba(255,215,0,0); transform: scale(1); }
25% { background: rgba(255,215,0,0.3); transform: scale(1.15); }
75% { background: rgba(255,215,0,0.2); transform: scale(1.1); }
}
.reel-symbol.flashing {
animation: flash-win 0.4s ease-in-out 4;
}
/* Shake for loss */
@keyframes shake {
0%, 100% { transform: translateX(0); }
15% { transform: translateX(-6px); }
30% { transform: translateX(6px); }
45% { transform: translateX(-5px); }
60% { transform: translateX(5px); }
75% { transform: translateX(-3px); }
90% { transform: translateX(3px); }
}
.reels-row.shaking .reel {
animation: shake 0.5s ease-in-out;
}
/* Controls */
.controls {
margin-top: 20px;
display: flex;
flex-direction: column;
gap: 14px;
}
.bet-section {
display: flex;
align-items: center;
gap: 10px;
justify-content: center;
}
.bet-label {
font-size: 0.9rem;
color: #aaa;
text-transform: uppercase;
letter-spacing: 1px;
}
.bet-btn {
background: #2a0a4e;
color: var(--text);
border: 2px solid #6a0dad;
border-radius: 8px;
padding: 8px 18px;
font-size: 1rem;
cursor: pointer;
transition: all 0.2s;
font-weight: 700;
}
.bet-btn:hover:not(:disabled) {
background: #4a1a7e;
border-color: var(--gold);
}
.bet-btn.active {
background: linear-gradient(135deg, #8b0000, #c0392b);
border-color: var(--gold);
color: var(--gold);
box-shadow: 0 0 10px rgba(255,215,0,0.4);
}
.bet-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.spin-btn {
background: linear-gradient(135deg, #8b0000 0%, #c0392b 50%, #8b0000 100%);
color: var(--gold);
border: 3px solid var(--gold);
border-radius: 50px;
padding: 16px 40px;
font-size: 1.5rem;
font-weight: 900;
cursor: pointer;
letter-spacing: 3px;
text-transform: uppercase;
transition: all 0.2s;
box-shadow: 0 4px 15px rgba(192,57,43,0.5), 0 0 20px rgba(255,215,0,0.2);
width: 100%;
}
.spin-btn:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(192,57,43,0.7), 0 0 30px rgba(255,215,0,0.4);
background: linear-gradient(135deg, #a00000 0%, #e74c3c 50%, #a00000 100%);
}
.spin-btn:active:not(:disabled) {
transform: translateY(1px);
}
.spin-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
}
/* Credits bar */
.credits-bar {
display: flex;
justify-content: space-between;
align-items: center;
background: rgba(0,0,0,0.4);
border: 2px solid #6a0dad;
border-radius: 10px;
padding: 10px 16px;
}
.credits-label, .bet-display-label {
font-size: 0.8rem;
color: #aaa;
text-transform: uppercase;
letter-spacing: 1px;
}
.credits-value {
font-size: 1.6rem;
font-weight: 900;
color: var(--gold);
text-shadow: 0 0 10px rgba(255,215,0,0.5);
min-width: 60px;
text-align: right;
}
.bet-display {
text-align: right;
}
.bet-value {
font-size: 1.4rem;
font-weight: 700;
color: #ff6b6b;
}
/* Win amount */
#win-amount {
text-align: center;
font-size: 1.3rem;
font-weight: 700;
min-height: 1.5rem;
margin-top: 4px;
color: var(--gold);
text-shadow: 0 0 10px rgba(255,215,0,0.8);
opacity: 0;
transition: opacity 0.3s;
}
#win-amount.visible {
opacity: 1;
}
/* GAME OVER overlay */
#game-over {
display: none;
position: fixed;
inset: 0;
background: rgba(0,0,0,0.85);
z-index: 100;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 24px;
}
#game-over.active {
display: flex;
}
.game-over-box {
background: linear-gradient(135deg, #2d1b4e, #1a0a2e);
border: 3px solid var(--red);
border-radius: 20px;
padding: 50px 60px;
text-align: center;
box-shadow: 0 0 60px rgba(192,57,43,0.5);
}
.game-over-title {
font-size: 3rem;
color: var(--red);
text-shadow: 0 0 20px rgba(192,57,43,0.8);
font-weight: 900;
letter-spacing: 4px;
margin-bottom: 16px;
}
.game-over-text {
color: #aaa;
margin-bottom: 30px;
font-size: 1.1rem;
}
.play-again-btn {
background: linear-gradient(135deg, #27ae60, #2ecc71);
color: white;
border: none;
border-radius: 50px;
padding: 14px 40px;
font-size: 1.3rem;
font-weight: 700;
cursor: pointer;
letter-spacing: 2px;
transition: all 0.2s;
box-shadow: 0 4px 15px rgba(39,174,96,0.4);
}
.play-again-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(39,174,96,0.6);
}
/* ── PAY TABLE ── */
.paytable {
background: linear-gradient(160deg, #2d1b4e 0%, #1e0840 100%);
border: 2px solid var(--border);
border-radius: 16px;
padding: 20px;
min-width: 220px;
box-shadow: 0 0 30px rgba(106,13,173,0.4);
}
.paytable h2 {
color: var(--gold);
text-align: center;
font-size: 1.1rem;
letter-spacing: 2px;
margin-bottom: 16px;
text-transform: uppercase;
text-shadow: 0 0 10px rgba(255,215,0,0.5);
padding-bottom: 10px;
border-bottom: 1px solid #6a0dad;
}
.paytable-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 7px 10px;
border-radius: 8px;
transition: background 0.2s, box-shadow 0.2s;
gap: 10px;
margin-bottom: 3px;
}
.paytable-row.highlighted {
background: linear-gradient(135deg, rgba(255,215,0,0.2), rgba(255,215,0,0.1));
box-shadow: 0 0 12px rgba(255,215,0,0.4);
animation: pulse-row 0.5s ease-in-out 3;
}
@keyframes pulse-row {
0%, 100% { box-shadow: 0 0 12px rgba(255,215,0,0.4); }
50% { box-shadow: 0 0 25px rgba(255,215,0,0.8); }
}
.paytable-symbols {
font-size: 1.1rem;
letter-spacing: 2px;
flex: 1;
}
.paytable-mult {
font-weight: 700;
font-size: 0.95rem;
white-space: nowrap;
}
.paytable-mult.jackpot { color: #ff4444; font-size: 1.1rem; }
.paytable-mult.high { color: var(--gold); }
.paytable-mult.mid { color: #ff9944; }
.paytable-mult.low { color: #aaffaa; }
.paytable-name {
font-size: 0.7rem;
color: #888;
text-transform: uppercase;
letter-spacing: 0.5px;
text-align: right;
min-width: 70px;
}
/* Lights */
.lights {
display: flex;
justify-content: center;
gap: 10px;
margin-bottom: 12px;
}
.light {
width: 12px;
height: 12px;
border-radius: 50%;
background: #ff0;
box-shadow: 0 0 6px #ff0;
animation: blink-lights 1s infinite;
}
.light:nth-child(2) { animation-delay: 0.15s; background: #f80; box-shadow: 0 0 6px #f80; }
.light:nth-child(3) { animation-delay: 0.3s; background: #0f0; box-shadow: 0 0 6px #0f0; }
.light:nth-child(4) { animation-delay: 0.45s; background: #0ff; box-shadow: 0 0 6px #0ff; }
.light:nth-child(5) { animation-delay: 0.6s; background: #f0f; box-shadow: 0 0 6px #f0f; }
.light:nth-child(6) { animation-delay: 0.75s; }
.light:nth-child(7) { animation-delay: 0.9s; background: #f80; box-shadow: 0 0 6px #f80; }
@keyframes blink-lights {
0%, 100% { opacity: 1; }
50% { opacity: 0.3; }
}
@media (max-width: 650px) {
.main-layout { flex-direction: column; align-items: center; }
.paytable { width: 100%; max-width: 400px; }
h1 { font-size: 2rem; }
}
</style>
</head>
<body>
<h1>🎰 Vegas Slots 🎰</h1>
<div class="main-layout">
<!-- SLOT MACHINE -->
<div class="machine">
<div class="lights">
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
</div>
<div id="win-announcement" class="hidden"></div>
<div class="reels-wrapper">
<div class="payline"></div>
<div class="reels-row" id="reels-row">
<div class="reel" id="reel-0"><div class="reel-strip" id="strip-0"></div></div>
<div class="reel" id="reel-1"><div class="reel-strip" id="strip-1"></div></div>
<div class="reel" id="reel-2"><div class="reel-strip" id="strip-2"></div></div>
</div>
</div>
<div id="win-amount"></div>
<div class="controls">
<div class="credits-bar">
<div>
<div class="credits-label">Credits</div>
<div class="credits-value" id="credits-display">100</div>
</div>
<div class="bet-display">
<div class="bet-display-label">Current Bet</div>
<div class="bet-value" id="bet-display">1</div>
</div>
</div>
<div class="bet-section">
<span class="bet-label">Bet:</span>
<button class="bet-btn active" id="bet-1" data-bet="1">1</button>
<button class="bet-btn" id="bet-5" data-bet="5">5</button>
<button class="bet-btn" id="bet-10" data-bet="10">10</button>
</div>
<button class="spin-btn" id="spin-btn">SPIN</button>
</div>
</div>
<!-- PAY TABLE -->
<div class="paytable">
<h2>Pay Table</h2>
<div id="paytable-rows"></div>
</div>
</div>
<!-- GAME OVER -->
<div id="game-over">
<div class="game-over-box">
<div class="game-over-title">GAME OVER</div>
<div class="game-over-text">You've run out of credits!<br>Better luck next time.</div>
<button class="play-again-btn" id="play-again-btn">Play Again</button>
</div>
</div>
<script>
'use strict';
// ── Constants ──────────────────────────────────────────────────────────────────
const SYMBOLS = ['🍒','🍋','🍊','🍇','🔔','⭐','7️⃣'];
const PAYTABLE = [
{ key: 'three-sevens', symbols: ['7️⃣','7️⃣','7️⃣'], mult: 100, label: 'JACKPOT!!!', tier: 'jackpot' },
{ key: 'three-stars', symbols: ['⭐','⭐','⭐'], mult: 50, label: 'TRIPLE STARS', tier: 'high' },
{ key: 'three-bells', symbols: ['🔔','🔔','🔔'], mult: 20, label: 'THREE BELLS', tier: 'high' },
{ key: 'three-grapes', symbols: ['🍇','🍇','🍇'], mult: 15, label: 'TRIPLE GRAPES', tier: 'mid' },
{ key: 'three-oranges', symbols: ['🍊','🍊','🍊'], mult: 10, label: 'THREE ORANGES', tier: 'mid' },
{ key: 'three-lemons', symbols: ['🍋','🍋','🍋'], mult: 5, label: 'THREE LEMONS', tier: 'low' },
{ key: 'three-cherries',symbols: ['🍒','🍒','🍒'], mult: 3, label: 'THREE CHERRIES', tier: 'low' },
{ key: 'two-cherries', symbols: ['🍒','🍒','❓'], mult: 2, label: 'DOUBLE CHERRY', tier: 'low' },
];
const REEL_STOP_TIMES = [800, 1200, 1600];
const SYMBOLS_PER_SEC = 12;
const SYMBOL_HEIGHT = 80; // px, must match CSS .reel-symbol height
const REEL_HEIGHT = 160; // px, visible reel height (2 symbols)
const VISIBLE_ROWS = 2;
const STRIP_COUNT = 30; // symbols in a spinning strip
// ── State ──────────────────────────────────────────────────────────────────────
let state = {};
function initState() {
state = {
credits: 100,
bet: 1,
spinning: false,
reels: ['🍒', '🍒', '🍒'], // current result symbols
result: null, // matching PAYTABLE entry or null
};
}
// ── DOM refs ───────────────────────────────────────────────────────────────────
const spinBtn = document.getElementById('spin-btn');
const creditsDisplay = document.getElementById('credits-display');
const betDisplay = document.getElementById('bet-display');
const winAnnounce = document.getElementById('win-announcement');
const winAmount = document.getElementById('win-amount');
const reelsRow = document.getElementById('reels-row');
const gameOverEl = document.getElementById('game-over');
const playAgainBtn = document.getElementById('play-again-btn');
const paytableRows = document.getElementById('paytable-rows');
// ── Paytable render ────────────────────────────────────────────────────────────
function renderPaytable() {
paytableRows.innerHTML = '';
PAYTABLE.forEach(entry => {
const row = document.createElement('div');
row.className = 'paytable-row';
row.id = 'pt-' + entry.key;
const symsDisplay = entry.key === 'two-cherries'
? '🍒 🍒 ❓'
: entry.symbols.join(' ');
row.innerHTML = `
<span class="paytable-symbols">${symsDisplay}</span>
<span class="paytable-mult ${entry.tier}">${entry.mult}×</span>
<span class="paytable-name">${entry.label}</span>
`;
paytableRows.appendChild(row);
});
}
function highlightPaytableRow(key) {
// Remove all highlights first
document.querySelectorAll('.paytable-row').forEach(r => r.classList.remove('highlighted'));
if (key) {
const row = document.getElementById('pt-' + key);
if (row) row.classList.add('highlighted');
}
}
// ── RNG helpers ────────────────────────────────────────────────────────────────
function randomSymbol() {
return SYMBOLS[Math.floor(Math.random() * SYMBOLS.length)];
}
function randomStripSymbols(count) {
const arr = [];
for (let i = 0; i < count; i++) arr.push(randomSymbol());
return arr;
}
// ── Win check ─────────────────────────────────────────────────────────────────
function checkWin(reels) {
const [r0, r1, r2] = reels;
for (const entry of PAYTABLE) {
if (entry.key === 'two-cherries') {
if (r0 === '🍒' && r1 === '🍒') return entry;
} else {
if (r0 === entry.symbols[0] && r1 === entry.symbols[1] && r2 === entry.symbols[2]) return entry;
}
}
return null;
}
// ── Credit count-up animation ─────────────────────────────────────────────────
function animateCredits(fromVal, toVal) {
const duration = 400;
const start = performance.now();
function step(now) {
const elapsed = now