← run 2026-06-29T114508Z-e0d7de7-minimal

gemma-4-31b — web-platformer

rep 1 MANUAL pass/5

pi 237.3s · verify 4.1s · 28030 tok · responded: gemma-4-31b · transcript

smoke 3/3

screenshot

verify output
CHECK PASS: canvas #game exists and is sized
CHECK PASS: no uncaught JS errors on load
CHECK PASS: keyboard input does not throw
score: 3/3 (100%)
produced code
index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Super Mario Style Platformer</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #333;
            color: white;
            font-family: sans-serif;
            overflow: hidden;
        }
        #game-container {
            position: relative;
            box-shadow: 0 0 20px rgba(0,0,0,0.5);
        }
        canvas {
            background-color: #5c94fc; /* Classic Mario sky blue */
            display: block;
        }
        #ui {
            position: absolute;
            top: 10px;
            left: 10px;
            font-size: 20px;
            font-weight: bold;
            text-shadow: 2px 2px #000;
            pointer-events: none;
        }
        #overlay {
            position: absolute;
            top: 0;
            left: 0;
            width: 800px;
            height: 450px;
            display: none;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            background: rgba(0,0,0,0.6);
            font-size: 40px;
            text-align: center;
        }
    </style>
</head>
<body>

<div id="game-container">
    <div id="ui">Coins: <span id="score">0</span></div>
    <div id="overlay">
        <div id="message">YOU WIN!</div>
        <div style="font-size: 20px; margin-top: 20px;">Press R to Restart</div>
    </div>
    <canvas id="game" width="800" height="450"></canvas>
</div>

<script>
    const canvas = document.getElementById('game');
    const ctx = canvas.getContext('2d');
    const scoreEl = document.getElementById('score');
    const overlay = document.getElementById('overlay');
    const messageEl = document.getElementById('message');

    // Game Constants
    const GRAVITY = 0.8;
    const FRICTION = 0.8;
    const JUMP_FORCE = -16;
    const MOVE_SPEED = 5;

    // Game State
    let score = 0;
    let gameActive = true;
    let cameraX = 0;

    const keys = {};

    window.addEventListener('keydown', e => {
        keys[e.code] = true;
        if (e.code === 'KeyR' && !gameActive) resetGame();
    });
    window.addEventListener('keyup', e => keys[e.code] = false);

    class Player {
        constructor() {
            this.width = 32;
            this.height = 48;
            this.x = 50;
            this.y = 300;
            this.vx = 0;
            this.vy = 0;
            this.grounded = false;
            this.color = '#ff0000';
        }

        update() {
            if (keys['ArrowLeft'] || keys['KeyA']) this.vx -= 1;
            if (keys['ArrowRight'] || keys['KeyD']) this.vx += 1;
            if ((keys['ArrowUp'] || keys['KeyW'] || keys['Space']) && this.grounded) {
                this.vy = JUMP_FORCE;
                this.grounded = false;
            }

            this.vx *= FRICTION;
            this.vy += GRAVITY;

            this.x += this.vx;
            this.y += this.vy;

            this.grounded = false;
        }

        draw() {
            ctx.fillStyle = this.color;
            ctx.fillRect(this.x - cameraX, this.y, this.width, this.height);
            // Hat/Detail
            ctx.fillStyle = '#a00';
            ctx.fillRect(this.x - cameraX, this.y, this.width, 10);
        }
    }

    class Platform {
        constructor(x, y, w, h, color = '#8B4513') {
            this.x = x;
            this.y = y;
            this.w = w;
            this.h = h;
            this.color = color;
        }

        draw() {
            ctx.fillStyle = this.color;
            ctx.fillRect(this.x - cameraX, this.y, this.w, this.h);
            // Grass top
            if (this.color === '#8B4513') {
                ctx.fillStyle = '#228B22';
                ctx.fillRect(this.x - cameraX, this.y, this.w, 10);
            }
        }
    }

    class Coin {
        constructor(x, y) {
            this.x = x;
            this.y = y;
            this.w = 20;
            this.h = 20;
            this.collected = false;
        }

        draw() {
            if (this.collected) return;
            ctx.fillStyle = '#FFD700';
            ctx.beginPath();
            ctx.arc(this.x + 10 - cameraX, this.y + 10, 10, 0, Math.PI * 2);
            ctx.fill();
            ctx.strokeStyle = '#B8860B';
            ctx.stroke();
        }
    }

    class Goal {
        constructor(x, y) {
            this.x = x;
            this.y = y;
            this.w = 40;
            this.h = 150;
        }

        draw() {
            ctx.fillStyle = '#fff';
            ctx.fillRect(this.x - cameraX, this.y, 10, this.h);
            ctx.fillStyle = '#ff0000';
            ctx.beginPath();
            ctx.moveTo(this.x + 10 - cameraX, this.y);
            ctx.lineTo(this.x + 40 - cameraX, this.y + 20);
            ctx.lineTo(this.x + 10 - cameraX, this.y + 40);
            ctx.fill();
        }
    }

    let player;
    let platforms = [];
    let coins = [];
    let goal;

    function initLevel() {
        player = new Player();
        score = 0;
        scoreEl.innerText = score;
        cameraX = 0;
        gameActive = true;
        overlay.style.display = 'none';

        platforms = [
            new Platform(0, 400, 1200, 50), // Ground 1
            new Platform(1300, 400, 800, 50), // Ground 2 (gap)
            new Platform(2200, 400, 1000, 50), // Ground 3
            new Platform(200, 300, 150, 20),   // Platform 1
            new Platform(450, 220, 150, 20),   // Platform 2
            new Platform(700, 140, 150, 20),   // Platform 3
            new Platform(1400, 300, 200, 20),  // Platform 4
            new Platform(1700, 200, 200, 20),  // Platform 5
            new Platform(1900, 100, 200, 20),   // Platform 6
        ];

        coins = [
            new Coin(250, 270),
            new Coin(500, 190),
            new Coin(750, 110),
            new Coin(1450, 270),
            new Coin(1750, 170),
            new Coin(1950, 70),
        ];

        goal = new Goal(3000, 250);
    }

    function resetGame() {
        initLevel();
        requestAnimationFrame(gameLoop);
    }

    function checkCollision(p, plat) {
        return p.x < plat.x + plat.w &&
               p.x + p.width > plat.x &&
               p.y < plat.y + plat.h &&
               p.y + p.height > plat.y;
    }

    function update() {
        if (!gameActive) return;

        player.update();

        // Platform Collisions
        player.grounded = false;
        for (let plat of platforms) {
            if (checkCollision(player, plat)) {
                // Resolve collision from top
                if (player.vy > 0 && player.y + player.height - player.vy <= plat.y) {
                    player.y = plat.y - player.height;
                    player.vy = 0;
                    player.grounded = true;
                } 
                // Resolve collision from bottom
                else if (player.vy < 0 && player.y - player.vy >= plat.y + plat.h) {
                    player.y = plat.y + plat.h;
                    player.vy = 0;
                }
                // Resolve collision from sides
                else if (player.vx > 0 && player.x + player.width - player.vx <= plat.x) {
                    player.x = plat.x - player.width;
                    player.vx = 0;
                }
                else if (player.vx < 0 && player.x - player.vx >= plat.x + plat.w) {
                    player.x = plat.x + plat.w;
                    player.vx = 0;
                }
            }
        }

        // Coin Collection
        for (let coin of coins) {
            if (!coin.collected && checkCollision(player, {x: coin.x, y: coin.y, w: coin.w, h: coin.h})) {
                coin.collected = true;
                score++;
                scoreEl.innerText = score;
            }
        }

        // Goal Reach
        if (checkCollision(player, goal)) {
            gameActive = false;
            messageEl.innerText = "YOU WIN!";
            overlay.style.display = 'flex';
        }

        // Fall off map
        if (player.y > 600) {
            player.x = 50;
            player.y = 300;
            player.vx = 0;
            player.vy = 0;
        }

        // Camera follow
        cameraX = Math.max(0, player.x - 300);
    }

    function draw() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        // Draw Background clouds (simple shapes)
        ctx.fillStyle = 'rgba(255,255,255,0.5)';
        ctx.beginPath(); ctx.arc(100 - cameraX*0.2, 100, 30, 0, Math.PI*2); ctx.fill();
        ctx.beginPath(); ctx.arc(130 - cameraX*0.2, 100, 40, 0, Math.PI*2); ctx.fill();
        ctx.beginPath(); ctx.arc(160 - cameraX*0.2, 100, 30, 0, Math.PI*2); ctx.fill();
        
        ctx.beginPath(); ctx.arc(500 - cameraX*0.2, 150, 30, 0, Math.PI*2); ctx.fill();
        ctx.beginPath(); ctx.arc(530 - cameraX*0.2, 150, 40, 0, Math.PI*2); ctx.fill();
        ctx.beginPath(); ctx.arc(560 - cameraX*0.2, 150, 30, 0, Math.PI*2); ctx.fill();

        platforms.forEach(p => p.draw());
        coins.forEach(c => c.draw());
        goal.draw();
        player.draw();
    }

    function gameLoop() {
        update();
        draw();
        if (gameActive) {
            requestAnimationFrame(gameLoop);
        } else {
            draw();
        }
    }

    initLevel();
    gameLoop();
</script>

</body>
</html>

rep 2 MANUAL pass/5

pi 188.5s · verify 4.1s · 23310 tok · responded: gemma-4-31b · transcript

smoke 3/3

screenshot

verify output
CHECK PASS: canvas #game exists and is sized
CHECK PASS: no uncaught JS errors on load
CHECK PASS: keyboard input does not throw
score: 3/3 (100%)
produced code
index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simple Mario Platformer</title>
    <style>
        body {
            margin: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #333;
            color: white;
            font-family: sans-serif;
            overflow: hidden;
        }
        #game-container {
            position: relative;
            box-shadow: 0 0 20px rgba(0,0,0,0.5);
        }
        canvas {
            background-color: #5c94fc; /* Classic Mario Sky Blue */
            display: block;
            border: 4px solid #000;
        }
        #ui {
            position: absolute;
            top: 10px;
            left: 10px;
            font-size: 20px;
            text-shadow: 2px 2px 0 #000;
            pointer-events: none;
        }
        #message {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            font-size: 48px;
            text-align: center;
            text-shadow: 4px 4px 0 #000;
            display: none;
        }
    </style>
</head>
<body>

    <div id="game-container">
        <div id="ui">Coins: <span id="score">0</span></div>
        <div id="message">YOU WIN!</div>
        <canvas id="game" width="800" height="450"></canvas>
    </div>

    <script>
        const canvas = document.getElementById('game');
        const ctx = canvas.getContext('2d');
        const scoreElement = document.getElementById('score');
        const messageElement = document.getElementById('message');

        // Game Constants
        const GRAVITY = 0.6;
        const FRICTION = 0.8;
        const JUMP_FORCE = -12;
        const MOVE_SPEED = 5;

        // Game State
        let score = 0;
        let gameActive = true;
        let cameraX = 0;

        const keys = {
            left: false,
            right: false,
            up: false
        };

        const player = {
            x: 50,
            y: 300,
            width: 30,
            height: 40,
            vx: 0,
            vy: 0,
            grounded: false,
            color: '#e74c3c'
        };

        const platforms = [
            // Floor
            { x: 0, y: 400, width: 2000, height: 50, color: '#8B4513' }, 
            // Platforms
            { x: 200, y: 300, width: 150, height: 20, color: '#2ecc71' },
            { x: 450, y: 220, width: 150, height: 20, color: '#2ecc71' },
            { x: 700, y: 300, width: 150, height: 20, color: '#2ecc71' },
            { x: 950, y: 200, width: 150, height: 20, color: '#2ecc71' },
            { x: 1200, y: 300, width: 150, height: 20, color: '#2ecc71' },
        ];

        const coins = [
            { x: 250, y: 260, width: 20, height: 20, collected: false },
            { x: 500, y: 180, width: 20, height: 20, collected: false },
            { x: 750, y: 260, width: 20, height: 20, collected: false },
            { x: 1000, y: 160, width: 20, height: 20, collected: false },
            { x: 1250, y: 260, width: 20, height: 20, collected: false },
        ];

        const goal = {
            x: 1500,
            y: 300,
            width: 40,
            height: 100,
            color: '#f1c40f'
        };

        // Input handling
        window.addEventListener('keydown', (e) => {
            if (e.code === 'ArrowLeft' || e.code === 'KeyA') keys.left = true;
            if (e.code === 'ArrowRight' || e.code === 'KeyD') keys.right = true;
            if (e.code === 'ArrowUp' || e.code === 'KeyW' || e.code === 'Space') keys.up = true;
        });

        window.addEventListener('keyup', (e) => {
            if (e.code === 'ArrowLeft' || e.code === 'KeyA') keys.left = false;
            if (e.code === 'ArrowRight' || e.code === 'KeyD') keys.right = false;
            if (e.code === 'ArrowUp' || e.code === 'KeyW' || e.code === 'Space') keys.up = false;
        });

        function checkCollision(rect1, rect2) {
            return rect1.x < rect2.x + rect2.width &&
                   rect1.x + rect1.width > rect2.x &&
                   rect1.y < rect2.y + rect2.height &&
                   rect1.y + rect1.height > rect2.y;
        }

        function update() {
            if (!gameActive) return;

            // Movement
            if (keys.left) player.vx = -MOVE_SPEED;
            else if (keys.right) player.vx = MOVE_SPEED;
            else player.vx *= FRICTION;

            if (keys.up && player.grounded) {
                player.vy = JUMP_FORCE;
                player.grounded = false;
            }

            player.vy += GRAVITY;
            player.x += player.vx;
            player.y += player.vy;

            // Collision with platforms
            player.grounded = false;
            for (let plat of platforms) {
                if (checkCollision(player, plat)) {
                    // Resolve collision from top
                    if (player.vy > 0 && player.y + player.height - player.vy <= plat.y) {
                        player.y = plat.y - player.height;
                        player.vy = 0;
                        player.grounded = true;
                    } 
                    // Resolve collision from bottom
                    else if (player.vy < 0 && player.y - player.vy >= plat.y + plat.height) {
                        player.y = plat.y + plat.height;
                        player.vy = 0;
                    }
                    // Resolve collision from sides
                    else if (player.vx > 0) {
                        player.x = plat.x - player.width;
                    } else if (player.vx < 0) {
                        player.x = plat.x + plat.width;
                    }
                }
            }

            // Collect coins
            for (let coin of coins) {
                if (!coin.collected && checkCollision(player, coin)) {
                    coin.collected = true;
                    score++;
                    scoreElement.innerText = score;
                }
            }

            // Reach goal
            if (checkCollision(player, goal)) {
                gameActive = false;
                messageElement.style.display = 'block';
            }

            // Bounds
            if (player.x < 0) player.x = 0;
            
            // Camera follows player
            cameraX = player.x - canvas.width / 2;
            if (cameraX < 0) cameraX = 0;
        }

        function draw() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);

            ctx.save();
            ctx.translate(-cameraX, 0);

            // Draw Platforms
            for (let plat of platforms) {
                ctx.fillStyle = plat.color;
                ctx.fillRect(plat.x, plat.y, plat.width, plat.height);
                // Grass top
                if (plat.color === '#2ecc71') {
                    ctx.fillStyle = '#27ae60';
                    ctx.fillRect(plat.x, plat.y, plat.width, 5);
                }
            }

            // Draw Coins
            ctx.fillStyle = '#f1c40f';
            for (let coin of coins) {
                if (!coin.collected) {
                    ctx.beginPath();
                    ctx.arc(coin.x + coin.width/2, coin.y + coin.height/2, coin.width/2, 0, Math.PI*2);
                    ctx.fill();
                }
            }

            // Draw Goal
            ctx.fillStyle = goal.color;
            ctx.fillRect(goal.x, goal.y, goal.width, goal.height);
            ctx.fillStyle = '#000';
            ctx.fillRect(goal.x, goal.y, 5, goal.height); // Flag pole

            // Draw Player
            ctx.fillStyle = player.color;
            ctx.fillRect(player.x, player.y, player.width, player.height);
            // Eye
            ctx.fillStyle = 'white';
            ctx.fillRect(player.x + (player.vx >= 0 ? 20 : 5), player.y + 5, 5, 5);

            ctx.restore();

            requestAnimationFrame(() => {
                update();
                draw();
            });
        }

        draw();
    </script>
</body>
</html>

rep 3 MANUAL partial/5

pi 184.4s · verify 4.1s · 22786 tok · responded: gemma-4-31b · transcript

smoke 3/3

screenshot

verify output
CHECK PASS: canvas #game exists and is sized
CHECK PASS: no uncaught JS errors on load
CHECK PASS: keyboard input does not throw
score: 3/3 (100%)
produced code
index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simple Platformer</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #222;
            color: white;
            font-family: sans-serif;
            overflow: hidden;
        }
        #game-container {
            position: relative;
            box-shadow: 0 0 20px rgba(0,0,0,0.5);
        }
        canvas {
            background-color: #5C94FC; /* Mario sky blue */
            display: block;
            border: 4px solid #fff;
        }
        #ui {
            position: absolute;
            top: 10px;
            left: 10px;
            font-size: 20px;
            font-weight: bold;
            text-shadow: 2px 2px #000;
            pointer-events: none;
        }
        #message {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            font-size: 48px;
            text-align: center;
            display: none;
            text-shadow: 4px 4px #000;
            pointer-events: none;
        }
    </style>
</head>
<body>

<div id="game-container">
    <div id="ui">Coins: <span id="score">0</span></div>
    <div id="message">YOU WIN!</div>
    <canvas id="game" width="800" height="450"></canvas>
</div>

<script>
    const canvas = document.getElementById('game');
    const ctx = canvas.getContext('2d');
    const scoreElement = document.getElementById('score');
    const messageElement = document.getElementById('message');

    // Game Constants
    const GRAVITY = 0.6;
    const FRICTION = 0.8;
    const JUMP_FORCE = -12;
    const MOVE_SPEED = 5;

    // Game State
    const keys = {};
    let score = 0;
    let gameActive = true;
    let cameraX = 0;

    const player = {
        x: 50,
        y: 300,
        width: 32,
        height: 32,
        velX: 0,
        velY: 0,
        jumping: false,
        color: '#E74C3C'
    };

    const platforms = [
        // Floor
        { x: 0, y: 400, width: 2000, height: 50, color: '#8B4513' },
        // Platforms
        { x: 200, y: 300, width: 150, height: 20, color: '#CD853F' },
        { x: 450, y: 220, width: 150, height: 20, color: '#CD853F' },
        { x: 700, y: 300, width: 150, height: 20, color: '#CD853F' },
        { x: 950, y: 200, width: 200, height: 20, color: '#CD853F' },
        { x: 1250, y: 300, width: 100, height: 20, color: '#CD853F' },
    ];

    const coins = [
        { x: 250, y: 260, width: 20, height: 20, collected: false },
        { x: 500, y: 180, width: 20, height: 20, collected: false },
        { x: 750, y: 260, width: 20, height: 20, collected: false },
        { x: 1000, y: 160, width: 20, height: 20, collected: false },
        { x: 1100, y: 160, width: 20, height: 20, collected: false },
    ];

    const goal = {
        x: 1500,
        y: 300,
        width: 40,
        height: 100,
        color: '#FFD700'
    };

    // Input handling
    window.addEventListener('keydown', e => keys[e.code] = true);
    window.addEventListener('keyup', e => keys[e.code] = false);

    function checkCollision(rect1, rect2) {
        return rect1.x < rect2.x + rect2.width &&
               rect1.x + rect1.width > rect2.x &&
               rect1.y < rect2.y + rect2.height &&
               rect1.y + rect1.height > rect2.y;
    }

    function update() {
        if (!gameActive) return;

        // Horizontal movement
        if (keys['ArrowRight'] || keys['KeyD']) {
            if (player.velX < MOVE_SPEED) player.velX++;
        } else if (keys['ArrowLeft'] || keys['KeyA']) {
            if (player.velX > -MOVE_SPEED) player.velX--;
        }
        
        player.velX *= FRICTION;

        // Jump
        if ((keys['ArrowUp'] || keys['KeyW'] || keys['Space']) && !player.jumping) {
            player.velY = JUMP_FORCE;
            player.jumping = true;
        }

        // Apply Gravity
        player.velY += GRAVITY;

        // Apply velocity
        player.x += player.velX;
        player.y += player.velY;

        // Platform Collision
        player.jumping = true;
        for (let plat of platforms) {
            if (checkCollision(player, plat)) {
                // Resolve collision from top
                if (player.velY > 0 && player.y + player.height - player.velY <= plat.y) {
                    player.y = plat.y - player.height;
                    player.velY = 0;
                    player.jumping = false;
                } 
                // Resolve collision from bottom
                else if (player.velY < 0 && player.y - player.velY >= plat.y + plat.height) {
                    player.y = plat.y + plat.height;
                    player.velY = 0;
                }
                // Resolve collision from sides
                else {
                    if (player.velX > 0) player.x = plat.x - player.width;
                    else if (player.velX < 0) player.x = plat.x + plat.width;
                    player.velX = 0;
                }
            }
        }

        // Coin collection
        for (let coin of coins) {
            if (!coin.collected && checkCollision(player, coin)) {
                coin.collected = true;
                score++;
                scoreElement.innerText = score;
            }
        }

        // Goal check
        if (checkCollision(player, goal)) {
            gameActive = false;
            messageElement.style.display = 'block';
        }

        // Bound player to world
        if (player.x < 0) player.x = 0;

        // Camera follows player
        cameraX = player.x - canvas.width / 4;
        if (cameraX < 0) cameraX = 0;
    }

    function draw() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        ctx.save();
        ctx.translate(-cameraX, 0);

        // Draw Platforms
        for (let plat of platforms) {
            ctx.fillStyle = plat.color;
            ctx.fillRect(plat.x, plat.y, plat.width, plat.height);
            // Add some detail to platforms
            ctx.strokeStyle = 'rgba(0,0,0,0.2)';
            ctx.strokeRect(plat.x, plat.y, plat.width, plat.height);
        }

        // Draw Coins
        ctx.fillStyle = '#F1C40F';
        for (let coin of coins) {
            if (!coin.collected) {
                ctx.beginPath();
                ctx.arc(coin.x + 10, coin.y + 10, 10, 0, Math.PI * 2);
                ctx.fill();
                ctx.strokeStyle = '#B8860B';
                ctx.stroke();
            }
        }

        // Draw Goal
        ctx.fillStyle = goal.color;
        ctx.fillRect(goal.x, goal.y, goal.width, goal.height);
        ctx.fillStyle = '#000';
        ctx.fillRect(goal.x, goal.y, 10, goal.height); // Goal pole

        // Draw Player
        ctx.fillStyle = player.color;
        ctx.fillRect(player.x, player.y, player.width, player.height);
        // Player eyes
        ctx.fillStyle = 'white';
        ctx.fillRect(player.x + 18, player.y + 6, 6, 6);
        ctx.fillRect(player.x + 6, player.y + 6, 6, 6);

        ctx.restore();

        requestAnimationFrame(() => {
            update();
            draw();
        });
    }

    draw();
</script>
</body>
</html>

rep 4 MANUAL partial/5

pi 179.3s · verify 4.1s · 22388 tok · responded: gemma-4-31b · transcript

smoke 3/3

screenshot

verify output
CHECK PASS: canvas #game exists and is sized
CHECK PASS: no uncaught JS errors on load
CHECK PASS: keyboard input does not throw
score: 3/3 (100%)
produced code
index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Super Simple Platformer</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
            background-color: #333;
            color: white;
            font-family: sans-serif;
            overflow: hidden;
        }
        #ui {
            margin-bottom: 10px;
            font-size: 24px;
        }
        canvas {
            background-color: #5c94fc; /* Mario Sky Blue */
            border: 4px solid #000;
            box-shadow: 0 0 20px rgba(0,0,0,0.5);
        }
    </style>
</head>
<body>
    <div id="ui">Coins: <span id="score">0</span></div>
    <canvas id="game" width="800" height="450"></canvas>

    <script>
        const canvas = document.getElementById('game');
        const ctx = canvas.getContext('2d');
        const scoreElement = document.getElementById('score');

        // Game Configuration
        const GRAVITY = 0.6;
        const FRICTION = 0.8;
        const JUMP_FORCE = -12;
        const MOVE_SPEED = 5;

        let score = 0;
        let gameActive = true;
        let cameraX = 0;

        const keys = {
            left: false,
            right: false,
            up: false
        };

        // Player Object
        const player = {
            x: 50,
            y: 300,
            width: 32,
            height: 32,
            velX: 0,
            velY: 0,
            jumping: false,
            color: '#e74c3c'
        };

        // Platforms
        const platforms = [
            { x: 0, y: 400, width: 2000, height: 50, color: '#8B4513' }, // Ground
            { x: 200, y: 300, width: 100, height: 20, color: '#2ecc71' },
            { x: 400, y: 220, width: 150, height: 20, color: '#2ecc71' },
            { x: 650, y: 320, width: 100, height: 20, color: '#2ecc71' },
            { x: 850, y: 250, width: 200, height: 20, color: '#2ecc71' },
            { x: 1100, y: 180, width: 100, height: 20, color: '#2ecc71' },
            { x: 1300, y: 300, width: 200, height: 20, color: '#2ecc71' },
        ];

        // Collectibles
        const coins = [
            { x: 230, y: 270, width: 20, height: 20, collected: false },
            { x: 450, y: 190, width: 20, height: 20, collected: false },
            { x: 700, y: 290, width: 20, height: 20, collected: false },
            { x: 900, y: 220, width: 20, height: 20, collected: false },
            { x: 1130, y: 150, width: 20, height: 20, collected: false },
            { x: 1400, y: 270, width: 20, height: 20, collected: false },
        ];

        // Goal
        const goal = {
            x: 1600,
            y: 300,
            width: 40,
            height: 100,
            color: '#f1c40f'
        };

        window.addEventListener('keydown', e => {
            if (e.code === 'ArrowLeft' || e.code === 'KeyA') keys.left = true;
            if (e.code === 'ArrowRight' || e.code === 'KeyD') keys.right = true;
            if (e.code === 'ArrowUp' || e.code === 'KeyW' || e.code === 'Space') keys.up = true;
        });

        window.addEventListener('keyup', e => {
            if (e.code === 'ArrowLeft' || e.code === 'KeyA') keys.left = false;
            if (e.code === 'ArrowRight' || e.code === 'KeyD') keys.right = false;
            if (e.code === 'ArrowUp' || e.code === 'KeyW' || e.code === 'Space') keys.up = false;
        });

        function checkCollision(rect1, rect2) {
            return rect1.x < rect2.x + rect2.width &&
                   rect1.x + rect1.width > rect2.x &&
                   rect1.y < rect2.y + rect2.height &&
                   rect1.y + rect1.height > rect2.y;
        }

        function update() {
            if (!gameActive) return;

            // Movement
            if (keys.left) player.velX = -MOVE_SPEED;
            else if (keys.right) player.velX = MOVE_SPEED;
            else player.velX *= FRICTION;

            if (keys.up && !player.jumping) {
                player.velY = JUMP_FORCE;
                player.jumping = true;
            }

            player.velY += GRAVITY;
            player.x += player.velX;
            player.y += player.velY;

            // Ground/Platform collision
            let onGround = false;
            for (let plat of platforms) {
                if (player.x < plat.x + plat.width &&
                    player.x + player.width > plat.x &&
                    player.y + player.height > plat.y &&
                    player.y + player.height < plat.y + plat.height + player.velY + 1 &&
                    player.velY >= 0) {
                    player.y = plat.y - player.height;
                    player.velY = 0;
                    player.jumping = false;
                    onGround = true;
                }
            }

            // Coin collection
            for (let coin of coins) {
                if (!coin.collected && checkCollision(player, coin)) {
                    coin.collected = true;
                    score++;
                    scoreElement.innerText = score;
                }
            }

            // Goal check
            if (checkCollision(player, goal)) {
                gameActive = false;
                setTimeout(() => {
                    alert("You Win! Final Score: " + score);
                    location.reload();
                }, 10);
            }

            // Out of bounds (bottom)
            if (player.y > canvas.height) {
                player.x = 50;
                player.y = 300;
                player.velX = 0;
                player.velY = 0;
            }

            // Camera follow
            cameraX = player.x - canvas.width / 4;
            if (cameraX < 0) cameraX = 0;
        }

        function draw() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);

            ctx.save();
            ctx.translate(-cameraX, 0);

            // Draw Platforms
            platforms.forEach(plat => {
                ctx.fillStyle = plat.color;
                ctx.fillRect(plat.x, plat.y, plat.width, plat.height);
                if (plat.height > 20) {
                    ctx.fillStyle = 'rgba(0,0,0,0.1)';
                    ctx.fillRect(plat.x, plat.y + 10, plat.width, 5);
                }
            });

            // Draw Coins
            ctx.fillStyle = '#f1c40f';
            coins.forEach(coin => {
                if (!coin.collected) {
                    ctx.beginPath();
                    ctx.arc(coin.x + 10, coin.y + 10, 10, 0, Math.PI * 2);
                    ctx.fill();
                    ctx.strokeStyle = '#d4ac0d';
                    ctx.stroke();
                }
            });

            // Draw Goal
            ctx.fillStyle = goal.color;
            ctx.fillRect(goal.x, goal.y, goal.width, goal.height);
            ctx.fillStyle = '#000';
            ctx.fillRect(goal.x, goal.y, 5, goal.height);

            // Draw Player
            ctx.fillStyle = player.color;
            ctx.fillRect(player.x, player.y, player.width, player.height);
            ctx.fillStyle = 'white';
            ctx.fillRect(player.x + 20, player.y + 5, 5, 5);

            ctx.restore();

            requestAnimationFrame(() => {
                update();
                draw();
            });
        }

        draw();
    </script>
</body>
</html>

rep 5 MANUAL partial/5

pi 202.7s · verify 4.1s · 24526 tok · responded: gemma-4-31b · transcript

smoke 3/3

screenshot

verify output
CHECK PASS: canvas #game exists and is sized
CHECK PASS: no uncaught JS errors on load
CHECK PASS: keyboard input does not throw
score: 3/3 (100%)
produced code
index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Super Mini Platformer</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #333;
            color: white;
            font-family: sans-serif;
            overflow: hidden;
        }
        #game-container {
            position: relative;
            box-shadow: 0 0 20px rgba(0,0,0,0.5);
        }
        canvas {
            background-color: #5c94fc; /* Classic Mario sky blue */
            display: block;
        }
        #ui {
            position: absolute;
            top: 10px;
            left: 10px;
            font-size: 20px;
            font-weight: bold;
            text-shadow: 2px 2px 0 #000;
            pointer-events: none;
        }
        #win-screen {
            position: absolute;
            top: 0;
            left: 0;
            width: 800px;
            height: 450px;
            background: rgba(0,0,0,0.7);
            display: none;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            text-align: center;
        }
        #win-screen h1 {
            font-size: 48px;
            margin-bottom: 10px;
        }
    </style>
</head>
<body>

<div id="game-container">
    <div id="ui">Coins: <span id="score">0</span></div>
    <canvas id="game" width="800" height="450"></canvas>
    <div id="win-screen">
        <h1>YOU WIN!</h1>
        <p>Press F5 to restart</p>
    </div>
</div>

<script>
    const canvas = document.getElementById('game');
    const ctx = canvas.getContext('2d');
    const scoreEl = document.getElementById('score');
    const winScreen = document.getElementById('win-screen');

    // Game Constants
    const GRAVITY = 0.6;
    const FRICTION = 0.8;
    const JUMP_FORCE = -12;
    const SPEED = 0.8;
    const MAX_SPEED = 5;

    // Game State
    let score = 0;
    let gameActive = true;
    const keys = {};

    const player = {
        x: 50,
        y: 300,
        width: 32,
        height: 48,
        vx: 0,
        vy: 0,
        grounded: false,
        color: '#ff4444'
    };

    const world = {
        offsetX: 0,
        platforms: [
            // Ground
            { x: 0, y: 400, width: 2000, height: 50, color: '#8b4513' },
            // Platforms
            { x: 200, y: 300, width: 150, height: 20, color: '#ccaa00' },
            { x: 450, y: 220, width: 150, height: 20, color: '#ccaa00' },
            { x: 700, y: 300, width: 150, height: 20, color: '#ccaa00' },
            { x: 950, y: 200, width: 100, height: 20, color: '#ccaa00' },
            { x: 1200, y: 300, width: 200, height: 20, color: '#ccaa00' },
            { x: 1500, y: 250, width: 100, height: 20, color: '#ccaa00' },
        ],
        coins: [
            { x: 250, y: 260, width: 20, height: 20, collected: false },
            { x: 500, y: 180, width: 20, height: 20, collected: false },
            { x: 750, y: 260, width: 20, height: 20, collected: false },
            { x: 980, y: 160, width: 20, height: 20, collected: false },
            { x: 1300, y: 260, width: 20, height: 20, collected: false },
        ],
        goal: { x: 1800, y: 300, width: 40, height: 100, color: '#00ff00' }
    };

    // Input handling
    window.addEventListener('keydown', e => keys[e.code] = true);
    window.addEventListener('keyup', e => keys[e.code] = false);

    function update() {
        if (!gameActive) return;

        // Horizontal movement
        if (keys['ArrowRight'] || keys['KeyD']) {
            if (player.vx < MAX_SPEED) player.vx += SPEED;
        } else if (keys['ArrowLeft'] || keys['KeyA']) {
            if (player.vx > -MAX_SPEED) player.vx -= SPEED;
        } else {
            player.vx *= FRICTION;
        }

        // Jump
        if ((keys['ArrowUp'] || keys['KeyW'] || keys['Space']) && player.grounded) {
            player.vy = JUMP_FORCE;
            player.grounded = false;
        }

        // Apply gravity
        player.vy += GRAVITY;

        // Move player
        player.x += player.vx;
        player.y += player.vy;

        // Collision detection
        player.grounded = false;
        for (let plat of world.platforms) {
            if (player.x < plat.x + plat.width &&
                player.x + player.width > plat.x &&
                player.y < plat.y + plat.height &&
                player.y + player.height > plat.y) {
                
                // Resolve collision from top
                if (player.vy > 0 && player.y + player.height - player.vy <= plat.y) {
                    player.y = plat.y - player.height;
                    player.vy = 0;
                    player.grounded = true;
                } 
                // Resolve collision from bottom
                else if (player.vy < 0 && player.y - player.vy >= plat.y + plat.height) {
                    player.y = plat.y + plat.height;
                    player.vy = 0;
                }
                // Resolve collision from sides
                else {
                    if (player.vx > 0) {
                        player.x = plat.x - player.width;
                    } else if (player.vx < 0) {
                        player.x = plat.x + plat.width;
                    }
                }
            }
        }

        // Coin collection
        for (let coin of world.coins) {
            if (!coin.collected && 
                player.x < coin.x + coin.width &&
                player.x + player.width > coin.x &&
                player.y < coin.y + coin.height &&
                player.y + player.height > coin.y) {
                coin.collected = true;
                score++;
                scoreEl.innerText = score;
            }
        }

        // Goal check
        if (player.x < world.goal.x + world.goal.width &&
            player.x + player.width > world.goal.x &&
            player.y < world.goal.y + world.goal.height &&
            player.y + player.height > world.goal.y) {
            gameActive = false;
            winScreen.style.display = 'flex';
        }

        // Camera follow
        world.offsetX = player.x - canvas.width / 2;
        if (world.offsetX < 0) world.offsetX = 0;
        if (world.offsetX > 2000 - canvas.width) world.offsetX = 2000 - canvas.width;
    }

    function draw() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        ctx.save();
        ctx.translate(-world.offsetX, 0);

        // Draw Platforms
        for (let plat of world.platforms) {
            ctx.fillStyle = plat.color;
            ctx.fillRect(plat.x, plat.y, plat.width, plat.height);
            // Adding a simple highlight for "3D" look
            ctx.fillStyle = 'rgba(255,255,255,0.2)';
            ctx.fillRect(plat.x, plat.y, plat.width, 4);
        }

        // Draw Coins
        ctx.fillStyle = '#ffff00';
        for (let coin of world.coins) {
            if (!coin.collected) {
                ctx.beginPath();
                ctx.arc(coin.x + 10, coin.y + 10, 10, 0, Math.PI * 2);
                ctx.fill();
                // Coin shine
                ctx.fillStyle = '#fff';
                ctx.fillRect(coin.x + 12, coin.y + 6, 3, 8);
                ctx.fillStyle = '#ffff00';
            }
        }

        // Draw Goal
        ctx.fillStyle = world.goal.color;
        ctx.fillRect(world.goal.x, world.goal.y, world.goal.width, world.goal.height);
        ctx.fillStyle = 'white';
        ctx.fillRect(world.goal.x, world.goal.y, 10, world.goal.height);

        // Draw Player
        ctx.fillStyle = player.color;
        ctx.fillRect(player.x, player.y, player.width, player.height);
        // Player eyes
        ctx.fillStyle = 'white';
        ctx.fillRect(player.x + 20, player.y + 10, 6, 6);
        ctx.fillStyle = 'black';
        ctx.fillRect(player.x + 24, player.y + 12, 3, 3);

        ctx.restore();
    }

    function loop() {
        update();
        draw();
        requestAnimationFrame(loop);
    }

    loop();
</script>
</body>
</html>