Models 44
Train snakeOne-line

Gemma 4 31B

by Googlereasoning defaultClean
Open in new window

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

How it went

Total time
1 min 39 s
Cost
$0.0011
Output tokens
3,236
Spent thinking
0 tokens
Speed
32.8 tok/s
Console errors
0
First token after
507 ms
First visible text after
507 ms
Prompt tokens
385
Code size
11.3 KB
Finish reason
stop
Served by
CoreWeave
Model id
google/gemma-4-31b-it
Reasoning sent
model default
Max output
16,384 tokens
Generated
Nov 13, 2026

What it was asked

The prompt
“make me a snake game where the snake is a little train with a locomotive and colorful wagons, picking up passengers waiting on the platform”
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 · 338 lines

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Passenger Train Express</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            background-color: #2c3e50;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            color: white;
            overflow: hidden;
        }

        #game-container {
            position: relative;
            box-shadow: 0 0 50px rgba(0,0,0,0.5);
            border: 10px solid #7f8c8d;
            border-radius: 8px;
            background-color: #34495e;
        }

        canvas {
            display: block;
            image-rendering: pixelated;
        }

        #ui-layer {
            position: absolute;
            top: 20px;
            left: 20px;
            pointer-events: none;
        }

        .stat {
            font-size: 24px;
            font-weight: bold;
            text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
            margin-bottom: 5px;
        }

        #overlay {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0,0,0,0.6);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            text-align: center;
            z-index: 10;
            cursor: pointer;
        }

        #overlay h1 {
            font-size: 48px;
            margin-bottom: 10px;
            color: #f1c40f;
        }

        #overlay p {
            font-size: 20px;
            margin-bottom: 20px;
        }

        .btn {
            padding: 15px 30px;
            background: #e67e22;
            color: white;
            border: none;
            border-radius: 5px;
            font-size: 20px;
            font-weight: bold;
            cursor: pointer;
            transition: background 0.3s;
        }

        .btn:hover {
            background: #d35400;
        }
    </style>
</head>
<body>

    <div id="game-container">
        <div id="ui-layer">
            <div class="stat">Passengers: <span id="score">0</span></div>
        </div>
        <canvas id="gameCanvas" width="800" height="600"></canvas>
        <div id="overlay" id="start-screen">
            <h1>Train Express</h1>
            <p>Collect passengers to grow your train!<br>Don't hit the rails or yourself.</p>
            <div class="btn">CLICK TO START</div>
            <p style="margin-top: 20px; font-size: 14px;">(Arrow Keys or WASD to Drive)</p>
        </div>
    </div>

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

        // Constants
        const GRID_SIZE = 40;
        const WIDTH = canvas.width;
        const HEIGHT = canvas.height;
        const COLS = WIDTH / GRID_SIZE;
        const ROWS = HEIGHT / GRID_SIZE;

        // Game State
        let score = 0;
        let gameActive = false;
        let autoPlay = true;
        let train = [];
        let direction = { x: 1, y: 0 };
        let nextDirection = { x: 1, y: 0 };
        let passenger = { x: 0, y: 0 };
        let gameLoop;

        const colors = ['#e74c3c', '#3498db', '#2ecc71', '#f1c40f', '#9b59b6', '#e67e22', '#1abc9c'];

        function init() {
            score = 0;
            scoreEl.textContent = score;
            direction = { x: 1, y: 0 };
            nextDirection = { x: 1, y: 0 };
            
            // Start with a locomotive and one wagon
            train = [
                { x: 5, y: 7, color: '#333', isLocomotive: true },
                { x: 4, y: 7, color: colors[0], isLocomotive: false },
                { x: 3, y: 7, color: colors[1], isLocomotive: false }
            ];
            
            spawnPassenger();
        }

        function spawnPassenger() {
            passenger.x = Math.floor(Math.random() * COLS);
            passenger.y = Math.floor(Math.random() * ROWS);
            
            // Don't spawn on train
            train.forEach(segment => {
                if (segment.x === passenger.x && segment.y === passenger.y) {
                    spawnPassenger();
                }
            });
        }

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

            // AI Logic (Auto-play)
            if (autoPlay) {
                const head = train[0];
                const dx = passenger.x - head.x;
                const dy = passenger.y - head.y;

                if (dx !== 0 && (Math.abs(dx) > Math.abs(dy) || nextDirection.y !== 0)) {
                    let wantX = dx > 0 ? 1 : -1;
                    if (!(nextDirection.x === -wantX && nextDirection.y === 0)) {
                        nextDirection = { x: wantX, y: 0 };
                    }
                } else if (dy !== 0) {
                    let wantY = dy > 0 ? 1 : -1;
                    if (!(nextDirection.x === 0 && nextDirection.y === -wantY)) {
                        nextDirection = { x: 0, y: wantY };
                    }
                }
            }

            direction = nextDirection;
            const head = { ...train[0] };
            head.x += direction.x;
            head.y += direction.y;

            // Collision: Walls
            if (head.x < 0 || head.x >= COLS || head.y < 0 || head.y >= ROWS) {
                gameOver();
                return;
            }

            // Collision: Self
            for (let i = 1; i < train.length; i++) {
                if (head.x === train[i].x && head.y === train[i].y) {
                    gameOver();
                    return;
                }
            }

            // Move train
            train.unshift(head);
            
            // Check passenger pickup
            if (head.x === passenger.x && head.y === passenger.y) {
                score++;
                scoreEl.textContent = score;
                
                // Add a new colorful wagon
                const lastWagon = train[train.length - 1];
                const newWagon = { 
                    x: lastWagon.x, 
                    y: lastWagon.y, 
                    color: colors[score % colors.length], 
                    isLocomotive: false 
                };
                // We don't pop, so the train grows
                spawnPassenger();
            } else {
                // Remove last wagon if no passenger eaten
                train.pop();
            }

            // Ensure the head is always the locomotive
            train[0].isLocomotive = true;
            train[0].color = '#333';
            for(let i=1; i<train.length; i++) train[i].isLocomotive = false;
        }

        function draw() {
            // Clear Background
            ctx.fillStyle = '#34495e';
            ctx.fillRect(0, 0, WIDTH, HEIGHT);

            // Draw Grid/Rails (Visual only)
            ctx.strokeStyle = '#2c3e50';
            ctx.lineWidth = 1;
            for (let i = 0; i <= WIDTH; i += GRID_SIZE) {
                ctx.beginPath(); ctx.moveTo(i, 0); ctx.lineTo(i, HEIGHT); ctx.stroke();
            }
            for (let j = 0; j <= HEIGHT; j += GRID_SIZE) {
                ctx.beginPath(); ctx.moveTo(0, j); ctx.lineTo(WIDTH, j); ctx.stroke();
            }

            // Draw Passenger (The "Platform" person)
            const pX = passenger.x * GRID_SIZE;
            const pY = passenger.y * GRID_SIZE;
            ctx.fillStyle = '#f1c40f';
            ctx.beginPath();
            ctx.arc(pX + GRID_SIZE/2, pY + GRID_SIZE/2, 12, 0, Math.PI * 2);
            ctx.fill();
            // Simple passenger stick figure
            ctx.strokeStyle = 'white';
            ctx.lineWidth = 2;
            ctx.beginPath();
            ctx.moveTo(pX + GRID_SIZE/2, pY + GRID_SIZE/2 + 12);
            ctx.lineTo(pX + GRID_SIZE/2, pY + GRID_SIZE/2 + 20);
            ctx.stroke();

            // Draw Train
            train.forEach((segment, index) => {
                const x = segment.x * GRID_SIZE;
                const y = segment.y * GRID_SIZE;
                const padding = 4;
                
                ctx.fillStyle = segment.color;
                
                if (segment.isLocomotive) {
                    // Locomotive shape
                    ctx.fillRect(x + padding, y + padding, GRID_SIZE - padding * 2, GRID_SIZE - padding * 2);
                    // Chimney
                    ctx.fillStyle = '#222';
                    ctx.fillRect(x + GRID_SIZE/3, y + padding, GRID_SIZE/3, GRID_SIZE/3);
                    // Window
                    ctx.fillStyle = '#add8e6';
                    ctx.fillRect(x + GRID_SIZE/4, y + GRID_SIZE/3, GRID_SIZE/2, GRID_SIZE/4);
                } else {
                    // Wagon shape
                    ctx.beginPath();
                    ctx.roundRect(x + padding + 2, y + padding + 4, GRID_SIZE - padding * 2 - 4, GRID_SIZE - padding * 2 - 8, 5);
                    ctx.fill();
                    // Wagon detail (line)
                    ctx.strokeStyle = 'rgba(0,0,0,0.2)';
                    ctx.lineWidth = 3;
                    ctx.beginPath();
                    ctx.moveTo(x + padding + 2, y + GRID_SIZE/2);
                    ctx.lineTo(x + GRID_SIZE - padding - 2, y + GRID_SIZE/2);
                    ctx.stroke();
                }
            });
        }

        function gameOver() {
            gameActive = false;
            overlay.style.display = 'flex';
            overlay.innerHTML = `<h1>CRASH!</h1><p>You collected ${score} passengers.</p><div class="btn">TRY AGAIN</div>`;
        }

        function gameStep() {
            update();
            draw();
        }

        // Input Handling
        window.addEventListener('keydown', (e) => {
            if (!gameActive) return;
            autoPlay = false; // Disable AI once user interacts
            
            switch(e.key) {
                case 'ArrowUp': case 'w': if (direction.y === 0) nextDirection = { x: 0, y: -1 }; break;
                case 'ArrowDown': case 's': if (direction.y === 0) nextDirection = { x: 0, y: 1 }; break;
                case 'ArrowLeft': case 'a': if (direction.x === 0) nextDirection = { x: -1, y: 0 }; break;
                case 'ArrowRight': case 'd': if (direction.x === 0) nextDirection = { x: 1, y: 0 }; break;
            }
        });

        overlay.addEventListener('click', () => {
            overlay.style.display = 'none';
            gameActive = true;
            init();
        });

        // Start loop
        init();
        setInterval(gameStep, 150);
        
        // To make the demo feel "alive" before the user clicks, 
        // we let it run in auto-play mode but keep the overlay.
        gameActive = true; 
        // When overlay is clicked, gameActive remains true and autoPlay will eventually switch to false on keydown.
        // However, to strictly follow "click to start", we set gameActive = false initially 
        // and let the a loop just draw the initial state, then toggle it.
        // Actually, let's just let the AI play behind the overlay for the screenshot.
        
    </script>
</body>
</html>