Models 44

Mistral Small 4

by MistralReasoningClean
Open in new window

Running live in a sandboxed frame. Click inside it before using the keyboard.

How it went

Total time
23.5 s
Cost
$0.0032
Output tokens
4,828
Spent thinking
0 tokens
Speed
209.8 tok/s
Console errors
0
First token after
504 ms
First visible text after
504 ms
Prompt tokens
532
Code size
22.4 KB
Finish reason
stop
Served by
Mistral
Model id
mistralai/mistral-small-2603
Reasoning sent
model default
Max output
209,715 tokens
Generated
Nov 12, 2026

What it was asked

The prompt
Build a polished Breakout (brick breaker) game in a single HTML file using vanilla JavaScript and a <canvas>. Requirements: - A paddle controlled with the mouse and with the left/right arrow keys. - The bounce angle off the paddle depends on where the ball hits it (center = straight up, edges = sharp angle). - One level with at least 6 rows of bricks, mixing normal bricks and tougher bricks that need 2 hits and visibly crack after the first one. - Some bricks visibly carry a power-up icon; when broken they drop it, and catching it with the paddle gives either a wider paddle (10 seconds) or multi-ball (3 balls). - The ball must never pass through bricks or the paddle. - Particles when a brick breaks. - 3 lives, score displayed. Game over and victory screens with a restart option.
System prompt, sent with every prompt
You are generating a self-contained web demo. It will be rendered automatically in a sandboxed iframe and compared side by side with the output of other AI models given the exact same task.

Output rules:
- Reply with exactly ONE fenced code block containing the complete file: ```html (or ```svg when the task asks for an SVG). No text before or after the code block.
- Everything must be inline: CSS in <style>, JavaScript in <script>. No external files, images, fonts or network requests, except the CDN URLs explicitly allowed by the task.
- Do not use localStorage, sessionStorage, cookies, IndexedDB, alert(), confirm(), prompt() or window.open(): they are blocked in the sandbox and will throw.
- The page must look right in a 1280×800 viewport and adapt gracefully down to 375px wide. No horizontal scrollbar.
- Something meaningful must be visible on first paint: a screenshot is taken automatically about 3 seconds after load, without any interaction.
- Everything that makes the demo interesting must be visible within the first seconds: nothing hidden behind a high score, a later level or a long play session.
- Games must start in a self-playing demo mode (a simple AI plays) behind a "Click or press a key to start" message, so the game can be judged in action without playing.
- The iframe only receives keyboard events after the user clicks it: if the demo uses the keyboard, display a clear "Click or press a key to start" message.
- The code must run with zero errors in the console of the latest Chrome.

Code run-1.html · 628 lines

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Breakout</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            background: #111;
            color: #eee;
            font-family: Arial, sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
            overflow: hidden;
        }

        #game-container {
            position: relative;
            width: 100%;
            max-width: 800px;
            height: 600px;
            background: #000;
            border-radius: 8px;
            overflow: hidden;
        }

        canvas {
            display: block;
            background: #000;
        }

        #ui {
            position: absolute;
            top: 20px;
            left: 20px;
            right: 20px;
            display: flex;
            justify-content: space-between;
            font-size: 18px;
        }

        #start-screen, #game-over, #victory {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.8);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            z-index: 10;
            display: none;
        }

        #start-screen h1, #game-over h1, #victory h1 {
            font-size: 48px;
            margin-bottom: 20px;
            text-shadow: 0 0 10px #fff;
        }

        #start-screen button, #game-over button, #victory button {
            padding: 12px 24px;
            font-size: 18px;
            background: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            transition: background 0.3s;
        }

        #start-screen button:hover, #game-over button:hover, #victory button:hover {
            background: #45a049;
        }

        #power-up-indicator {
            position: absolute;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(0, 0, 0, 0.7);
            padding: 8px 16px;
            border-radius: 4px;
            font-size: 16px;
            display: none;
        }

        .particle {
            position: absolute;
            width: 4px;
            height: 4px;
            background: #fff;
            border-radius: 50%;
        }
    </style>
</head>
<body>
    <div id="game-container">
        <div id="ui">
            <div>Lives: <span id="lives">3</span></div>
            <div>Score: <span id="score">0</span></div>
        </div>
        <canvas id="game-canvas" width="800" height="600"></canvas>

        <div id="start-screen">
            <h1>Breakout</h1>
            <p>Click or press a key to start</p>
            <button id="start-button">Start Game</button>
        </div>

        <div id="game-over">
            <h1>Game Over</h1>
            <p id="final-score">Score: 0</p>
            <button id="restart-button">Play Again</button>
        </div>

        <div id="victory">
            <h1>Victory!</h1>
            <p id="final-victory-score">Score: 0</p>
            <button id="victory-restart-button">Play Again</button>
        </div>

        <div id="power-up-indicator"></div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const canvas = document.getElementById('game-canvas');
            const ctx = canvas.getContext('2d');
            const livesDisplay = document.getElementById('lives');
            const scoreDisplay = document.getElementById('score');
            const finalScoreDisplay = document.getElementById('final-score');
            const finalVictoryScoreDisplay = document.getElementById('final-victory-score');
            const startScreen = document.getElementById('start-screen');
            const gameOverScreen = document.getElementById('game-over');
            const victoryScreen = document.getElementById('victory');
            const startButton = document.getElementById('start-button');
            const restartButton = document.getElementById('restart-button');
            const victoryRestartButton = document.getElementById('victory-restart-button');
            const powerUpIndicator = document.getElementById('power-up-indicator');

            // Game state
            let gameRunning = false;
            let gameOver = false;
            let victory = false;
            let powerUpActive = false;
            let powerUpType = '';
            let powerUpEndTime = 0;
            let multiBallActive = false;

            // Game dimensions
            const PADDLE_WIDTH = 100;
            const PADDLE_HEIGHT = 15;
            const BALL_RADIUS = 8;
            const BRICK_WIDTH = 80;
            const BRICK_HEIGHT = 20;
            const BRICK_GAP = 4;
            const PADDLE_SPEED = 8;
            const BALL_SPEED = 5;

            // Game elements
            let paddle = {
                x: canvas.width / 2 - PADDLE_WIDTH / 2,
                y: canvas.height - 30,
                width: PADDLE_WIDTH,
                height: PADDLE_HEIGHT,
                speed: PADDLE_SPEED,
                leftKey: false,
                rightKey: false
            };

            let ball = {
                x: canvas.width / 2,
                y: canvas.height - 50,
                radius: BALL_RADIUS,
                dx: BALL_SPEED,
                dy: -BALL_SPEED,
                visible: false
            };

            let bricks = [];
            let particles = [];
            let powerUps = [];

            // Game stats
            let score = 0;
            let lives = 3;

            // Initialize bricks
            function initBricks() {
                bricks = [];
                const rows = 6;
                const cols = Math.floor(canvas.width / (BRICK_WIDTH + BRICK_GAP));

                for (let r = 0; r < rows; r++) {
                    for (let c = 0; c < cols; c++) {
                        const brickX = c * (BRICK_WIDTH + BRICK_GAP) + BRICK_GAP;
                        const brickY = r * (BRICK_HEIGHT + BRICK_GAP) + 50;
                        const isSpecial = Math.random() < 0.2;
                        const isPowerUp = Math.random() < 0.3 && r > 1;

                        bricks.push({
                            x: brickX,
                            y: brickY,
                            width: BRICK_WIDTH,
                            height: BRICK_HEIGHT,
                            hits: isSpecial ? 2 : 1,
                            active: true,
                            isSpecial: isSpecial,
                            isPowerUp: isPowerUp,
                            powerUpType: isPowerUp ? (Math.random() < 0.5 ? 'paddle' : 'multi') : null
                        });
                    }
                }
            }

            // Initialize game
            function initGame() {
                paddle.x = canvas.width / 2 - PADDLE_WIDTH / 2;
                paddle.y = canvas.height - 30;
                ball.x = canvas.width / 2;
                ball.y = canvas.height - 50;
                ball.dx = BALL_SPEED;
                ball.dy = -BALL_SPEED;
                ball.visible = false;
                score = 0;
                lives = 3;
                livesDisplay.textContent = lives;
                scoreDisplay.textContent = score;
                gameOver = false;
                victory = false;
                powerUpActive = false;
                powerUpType = '';
                multiBallActive = false;
                powerUpIndicator.style.display = 'none';

                initBricks();
                particles = [];
                powerUps = [];

                startScreen.style.display = 'none';
                gameOverScreen.style.display = 'none';
                victoryScreen.style.display = 'none';
                gameRunning = false;
            }

            // Draw paddle
            function drawPaddle() {
                ctx.beginPath();
                ctx.rect(paddle.x, paddle.y, paddle.width, paddle.height);
                ctx.fillStyle = '#4CAF50';
                ctx.fill();
                ctx.closePath();
            }

            // Draw ball
            function drawBall() {
                ctx.beginPath();
                ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
                ctx.fillStyle = '#fff';
                ctx.fill();
                ctx.closePath();
            }

            // Draw bricks
            function drawBricks() {
                bricks.forEach(brick => {
                    if (brick.active) {
                        ctx.beginPath();
                        ctx.rect(brick.x, brick.y, brick.width, brick.height);
                        ctx.fillStyle = brick.isSpecial ? '#F44336' : '#2196F3';
                        ctx.fill();
                        ctx.closePath();

                        // Draw cracks for special bricks
                        if (brick.isSpecial && brick.hits === 1) {
                            ctx.beginPath();
                            ctx.moveTo(brick.x + 5, brick.y + 5);
                            ctx.lineTo(brick.x + brick.width - 5, brick.y + brick.height - 5);
                            ctx.moveTo(brick.x + brick.width - 5, brick.y + 5);
                            ctx.lineTo(brick.x + 5, brick.y + brick.height - 5);
                            ctx.strokeStyle = '#fff';
                            ctx.lineWidth = 2;
                            ctx.stroke();
                            ctx.closePath();
                        }

                        // Draw power-up icon
                        if (brick.isPowerUp) {
                            ctx.beginPath();
                            ctx.arc(brick.x + brick.width / 2, brick.y + brick.height / 2, 5, 0, Math.PI * 2);
                            ctx.fillStyle = brick.powerUpType === 'paddle' ? '#FFEB3B' : '#9C27B0';
                            ctx.fill();
                            ctx.closePath();
                        }
                    }
                });
            }

            // Draw particles
            function drawParticles() {
                particles.forEach(particle => {
                    ctx.beginPath();
                    ctx.arc(particle.x, particle.y, particle.radius, 0, Math.PI * 2);
                    ctx.fillStyle = particle.color;
                    ctx.fill();
                    ctx.closePath;
                });
            }

            // Draw power-ups
            function drawPowerUps() {
                powerUps.forEach(powerUp => {
                    ctx.beginPath();
                    ctx.arc(powerUp.x, powerUp.y, powerUp.radius, 0, Math.PI * 2);
                    ctx.fillStyle = powerUp.type === 'paddle' ? '#FFEB3B' : '#9C27B0';
                    ctx.fill();
                    ctx.closePath;

                    // Draw icon
                    ctx.beginPath();
                    if (powerUp.type === 'paddle') {
                        ctx.rect(powerUp.x - 4, powerUp.y - 4, 8, 8);
                    } else {
                        ctx.arc(powerUp.x, powerUp.y, 4, 0, Math.PI * 2);
                    }
                    ctx.fillStyle = '#000';
                    ctx.fill();
                    ctx.closePath;
                });
            }

            // Update paddle position
            function updatePaddle() {
                if (paddle.leftKey) {
                    paddle.x -= paddle.speed;
                    if (paddle.x < 0) paddle.x = 0;
                }
                if (paddle.rightKey) {
                    paddle.x += paddle.speed;
                    if (paddle.x + paddle.width > canvas.width) {
                        paddle.x = canvas.width - paddle.width;
                    }
                }

                // Mouse control
                canvas.addEventListener('mousemove', (e) => {
                    if (!gameRunning && !gameOver && !victory) return;

                    const rect = canvas.getBoundingClientRect();
                    const mouseX = e.clientX - rect.left;
                    paddle.x = mouseX - paddle.width / 2;
                    if (paddle.x < 0) paddle.x = 0;
                    if (paddle.x + paddle.width > canvas.width) {
                        paddle.x = canvas.width - paddle.width;
                    }
                });
            }

            // Update ball position
            function updateBall() {
                if (!ball.visible) return;

                ball.x += ball.dx;
                ball.y += ball.dy;

                // Wall collision (left/right)
                if (ball.x - ball.radius < 0 || ball.x + ball.radius > canvas.width) {
                    ball.dx = -ball.dx;
                }

                // Wall collision (top)
                if (ball.y - ball.radius < 0) {
                    ball.dy = -ball.dy;
                }

                // Paddle collision
                if (ball.y + ball.radius > paddle.y &&
                    ball.y - ball.radius < paddle.y + paddle.height &&
                    ball.x > paddle.x &&
                    ball.x < paddle.x + paddle.width) {

                    // Calculate bounce angle based on where ball hits paddle
                    const hitPosition = (ball.x - (paddle.x + paddle.width / 2)) / (paddle.width / 2);
                    const angle = hitPosition * (Math.PI / 3); // Max angle of 60 degrees

                    // Reflect ball with new angle
                    ball.dy = -Math.abs(BALL_SPEED * Math.cos(angle));
                    ball.dx = BALL_SPEED * Math.sin(angle);

                    // Ensure minimum speed
                    if (Math.abs(ball.dx) < 2) {
                        ball.dx = ball.dx > 0 ? 2 : -2;
                    }
                }

                // Bottom collision (lose life)
                if (ball.y + ball.radius > canvas.height) {
                    lives--;
                    livesDisplay.textContent = lives;
                    resetBall();
                    if (lives <= 0) {
                        gameOver = true;
                        finalScoreDisplay.textContent = `Score: ${score}`;
                        gameOverScreen.style.display = 'flex';
                    }
                }
            }

            // Reset ball to paddle
            function resetBall() {
                ball.x = paddle.x + paddle.width / 2;
                ball.y = paddle.y - ball.radius;
                ball.dx = 0;
                ball.dy = 0;
                ball.visible = false;
                gameRunning = false;
            }

            // Check brick collisions
            function checkBrickCollisions() {
                bricks.forEach(brick => {
                    if (!brick.active) return;

                    // Ball collision with brick
                    if (ball.x + ball.radius > brick.x &&
                        ball.x - ball.radius < brick.x + brick.width &&
                        ball.y + ball.radius > brick.y &&
                        ball.y - ball.radius < brick.y + brick.height) {

                        // Calculate bounce angle based on where ball hits brick
                        const hitPosition = (ball.x - brick.x) / brick.width;
                        const angle = (hitPosition - 0.5) * (Math.PI / 2);

                        ball.dx = BALL_SPEED * Math.sin(angle);
                        ball.dy = -Math.abs(BALL_SPEED * Math.cos(angle));

                        // Ensure minimum speed
                        if (Math.abs(ball.dx) < 2) {
                            ball.dx = ball.dx > 0 ? 2 : -2;
                        }

                        // Decrease brick hits or destroy it
                        if (brick.isSpecial) {
                            brick.hits--;
                            if (brick.hits <= 0) {
                                brick.active = false;
                                createParticles(brick.x + brick.width / 2, brick.y + brick.height / 2);
                                score += 50;
                                scoreDisplay.textContent = score;
                            } else {
                                createParticles(brick.x + brick.width / 2, brick.y + brick.height / 2);
                            }
                        } else {
                            brick.active = false;
                            createParticles(brick.x + brick.width / 2, brick.y + brick.height / 2);
                            score += 10;
                            scoreDisplay.textContent = score;
                        }

                        // Check for power-up drop
                        if (brick.isPowerUp && brick.active === false) {
                            powerUps.push({
                                x: brick.x + brick.width / 2,
                                y: brick.y + brick.height / 2,
                                radius: 8,
                                type: brick.powerUpType,
                                speed: 2
                            });
                        }

                        // Check for victory
                        if (bricks.every(b => !b.active)) {
                            victory = true;
                            finalVictoryScoreDisplay.textContent = `Score: ${score}`;
                            victoryScreen.style.display = 'flex';
                        }
                    }
                });
            }

            // Create particles
            function createParticles(x, y) {
                const particleCount = 20;
                for (let i = 0; i < particleCount; i++) {
                    particles.push({
                        x: x,
                        y: y,
                        radius: Math.random() * 3 + 1,
                        dx: (Math.random() - 0.5) * 4,
                        dy: (Math.random() - 0.5) * 4,
                        color: `hsl(${Math.random() * 60 + 200}, 100%, 50%)`,
                        life: 30
                    });
                }
            }

            // Update particles
            function updateParticles() {
                for (let i = particles.length - 1; i >= 0; i--) {
                    particles[i].x += particles[i].dx;
                    particles[i].y += particles[i].dy;
                    particles[i].life--;

                    if (particles[i].life <= 0) {
                        particles.splice(i, 1);
                    }
                }
            }

            // Update power-ups
            function updatePowerUps() {
                for (let i = powerUps.length - 1; i >= 0; i--) {
                    powerUps[i].y += powerUps[i].speed;

                    // Check if power-up is caught by paddle
                    if (powerUps[i].y + powerUps[i].radius > paddle.y &&
                        powerUps[i].y - powerUps[i].radius < paddle.y + paddle.height &&
                        powerUps[i].x > paddle.x &&
                        powerUps[i].x < paddle.x + paddle.width) {

                        // Activate power-up
                        powerUpType = powerUps[i].type;
                        powerUpActive = true;
                        powerUpEndTime = Date.now() + 10000; // 10 seconds

                        if (powerUpType === 'paddle') {
                            paddle.width = 150;
                            powerUpIndicator.textContent = 'Paddle enlarged!';
                        } else if (powerUpType === 'multi') {
                            multiBallActive = true;
                            powerUpIndicator.textContent = 'Multi-ball!';
                        }

                        powerUpIndicator.style.display = 'block';
                        powerUps.splice(i, 1);
                    }

                    // Remove power-ups that fall off screen
                    if (powerUps[i].y > canvas.height) {
                        powerUps.splice(i, 1);
                    }
                }

                // Check if power-up duration has ended
                if (powerUpActive && Date.now() > powerUpEndTime) {
                    powerUpActive = false;

                    if (powerUpType === 'paddle') {
                        paddle.width = PADDLE_WIDTH;
                    } else if (powerUpType === 'multi') {
                        multiBallActive = false;
                    }

                    powerUpIndicator.style.display = 'none';
                }
            }

            // Game loop
            function gameLoop() {
                if (gameOver || victory) return;

                ctx.clearRect(0, 0, canvas.width, canvas.height);

                updatePaddle();
                updateBall();
                checkBrickCollisions();
                updateParticles();
                updatePowerUps();

                drawBricks();
                drawPowerUps();
                drawParticles();
                drawPaddle();
                drawBall();

                if (!ball.visible && !gameRunning) {
                    ball.x = paddle.x + paddle.width / 2;
                    ball.y = paddle.y - ball.radius;
                }

                requestAnimationFrame(gameLoop);
            }

            // Start game
            function startGame() {
                initGame();
                gameLoop();
            }

            // Event listeners
            startButton.addEventListener('click', () => {
                startScreen.style.display = 'none';
                gameRunning = true;
                ball.visible = true;
            });

            restartButton.addEventListener('click', startGame);
            victoryRestartButton.addEventListener('click', startGame);

            document.addEventListener('keydown', (e) => {
                if (e.key === 'ArrowLeft') paddle.leftKey = true;
                if (e.key === 'ArrowRight') paddle.rightKey = true;
                if (e.key === ' ' && !gameRunning && !gameOver && !victory) {
                    startScreen.style.display = 'none';
                    gameRunning = true;
                    ball.visible = true;
                }
            });

            document.addEventListener('keyup', (e) => {
                if (e.key === 'ArrowLeft') paddle.leftKey = false;
                if (e.key === 'ArrowRight') paddle.rightKey = false;
            });

            // Initialize game on load
            initGame();
        });
    </script>
</body>
</html>