oneshotlm
Compare all models on this prompt →

Tetris · deepseek-chat

Build a playable Tetris on a canvas with all seven tetrominoes, rotation, line clears, increasing speed, a next-piece preview, and score.

⛨ sandboxed Open in new tab ↗
transcript · 4 messages
user

Build a playable Tetris on a canvas with all seven tetrominoes, rotation, line clears, increasing speed, a next-piece preview, and score.

assistant

The Tetris implementation in a single self-contained index.html file: ```html <!DOCTYPE html> <html> <head> <title>Tetris</title> <style> body { margin: 0; display: flex; justify-content: center; align-items: center; height: 100vh; background: #333; } canvas { background: #000; border: 2px solid #fff; } #sidebar { margin-left: 20px; color: white; font-family: monospace; } .label { color: #aaa; margin-bottom: 10px; } </style> </head> <body> <canvas id="canvas" width="300" height="600"></canvas> <div id="sidebar"> <div class="label">Next:</div> <canvas id="nextPiece" width="120" height="120"></canvas> <div style="margin-top: 30px;"><span class="label">Score:</span> <span id="score">0</span></div> </div> <script> const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const nextCanvas = document.getElementById('nextPiece'); const nextCtx = nextCanvas.getContext('2d'); const scoreElement = document.getElementById('score'); const COLS = 10, ROWS = 20, BLOCK_SIZE = 30; let board = Array.from({ length: ROWS }, () => Array(COLS).fill(0)); let piece, nextPiece, score = 0, speed = 1000, gameInterval; const TETROMINOES = [ { shape: [[1,1,1,1]], color: 'cyan' }, // I { shape: [[1,1],[1,1]], color: 'yellow' }, // O { shape: [[0,1,0],[1,1,1]], color: 'purple' }, // T { shape: [[1,1,0],[0,1,1]], color: 'red' }, // Z { shape: [[0,1,1],[1,1,0]], color: 'green' }, // S { shape: [[1,0,0],[1,1,1]], color: 'orange' }, // L { shape: [[0,0,1],[1,1,1]], color: 'blue' } // J ]; function spawnPiece() { piece = nextPiece || randomPiece(); nextPiece = randomPiece(); drawNextPiece(); piece.x = Math.floor((COLS - piece.shape[0].length) / 2); piece.y = 0; if (collision()) { gameOver(); return; } } function randomPiece() { const tetromino = TETROMINOES[Math.floor(Math.random() * TETROMINOES.length)]; return { shape: tetromino.shape, color: tetromino.color, x: 0, y: 0 }; } function drawPiece() { piece.shape.forEach((row, y) => { row.forEach((value, x) => { if (value) { ctx.fillStyle = piece.color; ctx.fillRect((piece.x + x) * BLOCK_SIZE, (piece.y + y) * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE); ctx.strokeStyle = '#111'; ctx.strokeRect((piece.x + x) * BLOCK_SIZE, (piece.y + y) * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE); } }); }); } function drawBoard() { ctx.clearRect(0, 0, canvas.width, canvas.height); board.forEach((row, y) => { row.forEach((value, x) => { if (value) { ctx.fillStyle = value; ctx.fillRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE); ctx.strokeStyle = '#333'; ctx.strokeRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE); } }); }); } function drawNextPiece() { nextCtx.clearRect(0, 0, nextCanvas.width, nextCanvas.height); nextPiece.shape.forEach((row, y) => { row.forEach((value, x) => { if (value) { nextCtx.fillStyle = nextPiece.color; const offsetX = (4 - nextPiece.shape[0].length) * (BLOCK_SIZE / 2); nextCtx.fillRect(x * BLOCK_SIZE + offsetX, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE); nextCtx.strokeStyle = '#111'; nextCtx.strokeRect(x * BLOCK_SIZE + offsetX, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE); } }); }); } function collision() { return piece.shape.some((row, y) => row.some((value, x) => value && (board[piece.y + y] && board[piece.y + y][piece.x + x]) ) ); } function lockPiece() { piece.shape.forEach((row, y) => { row.forEach((value, x) => { if (value) board[piece.y + y][piece.x + x] = piece.color; }); }); clearLines(); spawnPiece(); } function clearLines() { let linesCleared = 0; for (let y = ROWS - 1; y >= 0; y--) { if (board[y].every(cell => cell !== 0)) { board.splice(y, 1); board.unshift(Array(COLS).fill(0)); linesCleared++; y++; } } if (linesCleared) { score += [0, 40, 100, 300, 1200][linesCleared]; speed = Math.max(200, speed - 50); clearInterval(gameInterval); gameInterval = setInterval(update, speed); scoreElement.textContent = score; } } function rotate(piece) { const newShape = piece.shape[0].map((val, index) => piece.shape.map(row => row[index]).reverse() ); const oldShape = piece.shape; piece.shape = newShape; if (collision()) { piece.shape = oldShape; } } function gameOver() { clearInterval(gameInterval); alert('Game Over!'); resetGame(); } function resetGame() { board = Array.from({ length: ROWS }, () => Array(COLS).fill(0)); score = 0; speed = 1000; scoreElement.textContent = score; clearInterval(gameInterval); spawnPiece(); gameInterval = setInterval(update, speed); } function update() { piece.y++; if (collision()) { piece.y--; lockPiece(); } drawBoard(); drawPiece(); } document.addEventListener('keydown', e => { if (e.key === 'ArrowLeft') { piece.x--; if (collision()) piece.x++; } if (e.key === 'ArrowRight') { piece.x++; if (collision()) piece.x--; } if (e.key === 'ArrowDown') { piece.y++; if (collision()) { piece.y--; lockPiece(); } } if (e.key === 'ArrowUp') { rotate(piece); } }); resetGame(); </script> </body> </html> ``` This implementation includes: 1. All 7 classic tetromino shapes 2. Rotation functionality 3. Line clearing with proper scoring (single, double, triple, tetris) 4. Increasing speed as game progresses 5. Next piece preview 6. Score display 7. Keyboard controls (arrow keys for movement and rotation) 8. Game over state detection 9. No external dependencies - fully self-contained To save this as index.html:

write index.html (6024 bytes)
toolResult

Successfully wrote 6024 bytes to index.html

assistant

The Tetris game has been created in a single self-contained `index.html` file. You can open it in any web browser to play. It includes: 1. All 7 classic tetromino shapes (I, O, T, Z, S, L, J) 2. Rotation with the Up arrow key 3. Movement with Left/Right/Down arrow keys 4. Line clearing with scoring (40, 100, 300, 1200 for 1-4 lines) 5. Increasing speed as you clear lines 6. Next piece preview 7. Score display 8. Game over detection and reset Just open `index.html` in your browser to play! No internet connection or external resources are needed.

TAKE IT TO CODE

A single self-contained HTML file — copy it and open in any browser, or reuse the prompt with your own pi-agent run.

RUN

modeldeepseek-chat
vendorDeepSeek
harnesspi-agent
generated2026-08-01

EVALUATION

2/5 partial

Piece falls automatically and shows next-piece preview, but arrow/WASD keys don't move or rotate it, no visible line clears or scoring.

Vision grade · anthropic/claude-sonnet-5

MEASUREMENTS

Raw readings from the capture, not a verdict — the grade above is the only judgement. Percentages are how much of the screen changed; the measure under-reports sparse motion on a dark background.

idle motion0.7%
on click1.0%
on drag1.0%
on wheel1.0%
on enter + space0.7%
on arrow keys0.0%
on w/a/s/d0.0%
frame spread21.2 / 255
console errors0
js errors none

METRICS

runtime179.4s
tokens in7.3k
tokens out4.0k
cached0
cost / run$0.0047