Models 44

Nemotron 3 Ultra (free)

by NVIDIAReasoningClean
Open in new window

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

How it went

Total time
1 min 16 s
Cost
$0
Output tokens
5,769
Spent thinking
0 tokens
Speed
77.2 tok/s
Console errors
0
First token after
949 ms
First visible text after
949 ms
Prompt tokens
517
Code size
22.1 KB
Finish reason
stop
Served by
Nvidia
Model id
nvidia/nemotron-3-ultra-550b-a55b:free
Reasoning sent
{"effort":"none"}
Max output
32,000 tokens
Generated
Nov 9, 2026

What it was asked

The prompt
Build a polished Snake game in a single HTML file using vanilla JavaScript and a <canvas>. Requirements: - A grid of at least 20×20 cells, centered on the page. - Arrow keys and WASD control the snake. Quick successive key presses must both be honored, but the snake can never reverse onto itself. - Eating food adds 10 points and grows the snake by one cell; new food never spawns on the snake. - Game over when the snake hits a wall or itself, with an overlay showing the score; Space or Enter restarts, P pauses. - Visual polish: smooth movement, a snake with a distinct head and eyes facing its direction, and a small particle burst when eating. - Display the current score and the best score of the session.
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 · 705 lines

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Snake Game</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            padding: 20px;
            overflow: hidden;
        }
        
        .game-container {
            position: relative;
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 20px;
        }
        
        h1 {
            color: #e94560;
            font-size: clamp(1.5rem, 5vw, 2.5rem);
            text-shadow: 0 0 20px rgba(233, 69, 96, 0.5);
            letter-spacing: 2px;
        }
        
        .score-board {
            display: flex;
            gap: 30px;
            padding: 15px 30px;
            background: rgba(0, 0, 0, 0.4);
            border-radius: 12px;
            border: 2px solid rgba(233, 69, 96, 0.3);
            backdrop-filter: blur(10px);
        }
        
        .score-item {
            display: flex;
            flex-direction: column;
            align-items: center;
            min-width: 100px;
        }
        
        .score-label {
            color: #a0a0b0;
            font-size: 0.75rem;
            text-transform: uppercase;
            letter-spacing: 1px;
            margin-bottom: 4px;
        }
        
        .score-value {
            color: #fff;
            font-size: 1.5rem;
            font-weight: 700;
            font-variant-numeric: tabular-nums;
        }
        
        .score-value.high-score {
            color: #e94560;
        }
        
        canvas {
            background: #0a0a15;
            border: 3px solid #e94560;
            border-radius: 8px;
            box-shadow: 
                0 0 30px rgba(233, 69, 96, 0.3),
                inset 0 0 60px rgba(0, 0, 0, 0.5);
            display: block;
        }
        
        .overlay {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(10, 10, 21, 0.95);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 20px;
            border-radius: 5px;
            opacity: 0;
            visibility: hidden;
            transition: opacity 0.3s ease, visibility 0.3s ease;
            border: 3px solid #e94560;
            border-radius: 8px;
            pointer-events: none;
        }
        
        .overlay.visible {
            opacity: 1;
            visibility: visible;
            pointer-events: auto;
        }
        
        .overlay h2 {
            color: #e94560;
            font-size: clamp(1.5rem, 5vw, 2.5rem);
            text-shadow: 0 0 20px rgba(233, 69, 96, 0.5);
        }
        
        .overlay p {
            color: #c0c0d0;
            font-size: 1.1rem;
        }
        
        .final-score {
            color: #fff;
            font-size: 2rem;
            font-weight: 700;
        }
        
        .controls-hint {
            color: #606070;
            font-size: 0.85rem;
            line-height: 1.8;
            text-align: center;
        }
        
        .btn {
            padding: 12px 32px;
            font-size: 1rem;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 1px;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            transition: all 0.2s ease;
        }
        
        .btn-primary {
            background: linear-gradient(135deg, #e94560, #c73659);
            color: #fff;
            box-shadow: 0 4px 15px rgba(233, 69, 96, 0.4);
        }
        
        .btn-primary:hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 20px rgba(233, 69, 96, 0.6);
        }
        
        .btn-primary:active {
            transform: translateY(0);
        }
        
        @media (max-width: 480px) {
            .score-board {
                gap: 20px;
                padding: 12px 20px;
            }
            
            .score-item {
                min-width: 80px;
            }
            
            .score-value {
                font-size: 1.25rem;
            }
        }
    </style>
</head>
<body>
    <div class="game-container">
        <h1>SNAKE</h1>
        <div class="score-board">
            <div class="score-item">
                <span class="score-label">Score</span>
                <span class="score-value" id="currentScore">0</span>
            </div>
            <div class="score-item">
                <span class="score-label">Best</span>
                <span class="score-value high-score" id="bestScore">0</span>
            </div>
        </div>
        <canvas id="gameCanvas" width="500" height="500"></canvas>
        <div class="overlay" id="startOverlay">
            <h2>SNAKE</h2>
            <p class="controls-hint">
                Arrow Keys or WASD to move<br>
                Space or Enter to start<br>
                P to pause
            </p>
            <button class="btn btn-primary" id="startBtn">Start Game</button>
        </div>
        <div class="overlay" id="gameOverOverlay">
            <h2>GAME OVER</h2>
            <p class="final-score" id="finalScore">Score: 0</p>
            <p class="controls-hint">Press Space, Enter or click Restart</p>
            <button class="btn btn-primary" id="restartBtn">Restart</button>
        </div>
        <div class="overlay" id="pauseOverlay">
            <h2>PAUSED</h2>
            <p class="controls-hint">Press P or Space to resume</p>
            <button class="btn btn-primary" id="resumeBtn">Resume</button>
        </div>
    </div>

    <script>
        // Game Constants
        const GRID_SIZE = 25;
        const CELL_SIZE = 20;
        const CANVAS_SIZE = GRID_SIZE * CELL_SIZE;
        const INITIAL_SPEED = 120;
        const SPEED_INCREASE = 2;
        const MIN_SPEED = 50;
        
        // Colors
        const COLORS = {
            bg: '#0a0a15',
            grid: '#1a1a2e',
            snakeBody: '#00d4aa',
            snakeHead: '#00ffcc',
            snakeEye: '#0a0a15',
            snakeEyeGlow: '#00ffcc',
            food: '#e94560',
            foodGlow: '#ff6b6b',
            particle: ['#e94560', '#00ffcc', '#ffd700', '#ff6b6b', '#00d4aa'],
            text: '#ffffff'
        };
        
        // Directions
        const DIRS = {
            UP: { x: 0, y: -1 },
            DOWN: { x: 0, y: 1 },
            LEFT: { x: -1, y: 0 },
            RIGHT: { x: 1, y: 0 }
        };
        
        // Game State
        let snake = [];
        let direction = DIRS.RIGHT;
        let nextDirection = DIRS.RIGHT;
        let food = { x: 0, y: 0 };
        let score = 0;
        let bestScore = 0;
        let gameSpeed = INITIAL_SPEED;
        let gameLoopId = null;
        let lastMoveTime = 0;
        let isGameOver = false;
        let isPaused = false;
        let isStarted = false;
        let animationFrameId = null;
        let particles = [];
        
        // DOM Elements
        const canvas = document.getElementById('gameCanvas');
        const ctx = canvas.getContext('2d');
        const currentScoreEl = document.getElementById('currentScore');
        const bestScoreEl = document.getElementById('bestScore');
        const finalScoreEl = document.getElementById('finalScore');
        const startOverlay = document.getElementById('startOverlay');
        const gameOverOverlay = document.getElementById('gameOverOverlay');
        const pauseOverlay = document.getElementById('pauseOverlay');
        const startBtn = document.getElementById('startBtn');
        const restartBtn = document.getElementById('restartBtn');
        const resumeBtn = document.getElementById('resumeBtn');
        
        // Set canvas size
        canvas.width = CANVAS_SIZE;
        canvas.height = CANVAS_SIZE;
        
        // Input handling
        const keyMap = {
            'ArrowUp': DIRS.UP, 'KeyW': DIRS.UP,
            'ArrowDown': DIRS.DOWN, 'KeyS': DIRS.DOWN,
            'ArrowLeft': DIRS.LEFT, 'KeyA': DIRS.LEFT,
            'ArrowRight': DIRS.RIGHT, 'KeyD': DIRS.RIGHT
        };
        
        const oppositeDir = {
            [DIRS.UP]: DIRS.DOWN,
            [DIRS.DOWN]: DIRS.UP,
            [DIRS.LEFT]: DIRS.RIGHT,
            [DIRS.RIGHT]: DIRS.LEFT
        };
        
        function handleKeyDown(e) {
            const dir = keyMap[e.code];
            if (dir && dir !== oppositeDir[direction]) {
                nextDirection = dir;
                e.preventDefault();
            }
            
            if (e.code === 'Space' || e.code === 'Enter') {
                e.preventDefault();
                if (!isStarted) {
                    startGame();
                } else if (isGameOver) {
                    restartGame();
                } else if (isPaused) {
                    resumeGame();
                }
            }
            
            if (e.code === 'KeyP') {
                e.preventDefault();
                if (isStarted && !isGameOver) {
                    togglePause();
                }
            }
        }
        
        document.addEventListener('keydown', handleKeyDown);
        
        // Button handlers
        startBtn.addEventListener('click', startGame);
        restartBtn.addEventListener('click', restartGame);
        resumeBtn.addEventListener('click', resumeGame);
        
        // Canvas click to focus/start
        canvas.addEventListener('click', () => {
            canvas.focus();
            if (!isStarted) startGame();
            else if (isGameOver) restartGame();
            else if (isPaused) resumeGame();
        });
        
        // Particle System
        class Particle {
            constructor(x, y, color) {
                this.x = x;
                this.y = y;
                this.color = color;
                this.size = Math.random() * 4 + 2;
                this.speed = Math.random() * 3 + 1;
                this.angle = Math.random() * Math.PI * 2;
                this.life = 1;
                this.decay = Math.random() * 0.02 + 0.015;
            }
            
            update() {
                this.x += Math.cos(this.angle) * this.speed;
                this.y += Math.sin(this.angle) * this.speed;
                this.life -= this.decay;
                this.size *= 0.98;
            }
            
            draw(ctx) {
                ctx.save();
                ctx.globalAlpha = this.life;
                ctx.fillStyle = this.color;
                ctx.shadowColor = this.color;
                ctx.shadowBlur = 10;
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
                ctx.fill();
                ctx.restore();
            }
        }
        
        function createParticles(x, y, count = 15) {
            for (let i = 0; i < count; i++) {
                const color = COLORS.particle[Math.floor(Math.random() * COLORS.particle.length)];
                particles.push(new Particle(x, y, color));
            }
        }
        
        function updateParticles() {
            particles = particles.filter(p => p.life > 0);
            particles.forEach(p => p.update());
        }
        
        function drawParticles() {
            particles.forEach(p => p.draw(ctx));
        }
        
        // Game Logic
        function initGame() {
            snake = [
                { x: 12, y: 12 },
                { x: 11, y: 12 },
                { x: 10, y: 12 }
            ];
            direction = DIRS.RIGHT;
            nextDirection = DIRS.RIGHT;
            score = 0;
            gameSpeed = INITIAL_SPEED;
            isGameOver = false;
            isPaused = false;
            particles = [];
            updateScoreDisplay();
            spawnFood();
        }
        
        function startGame() {
            if (isStarted && !isGameOver) return;
            initGame();
            isStarted = true;
            hideAllOverlays();
            lastMoveTime = performance.now();
            gameLoop();
        }
        
        function restartGame() {
            initGame();
            hideAllOverlays();
            lastMoveTime = performance.now();
            gameLoop();
        }
        
        function togglePause() {
            if (isGameOver) return;
            isPaused = !isPaused;
            if (isPaused) {
                showOverlay(pauseOverlay);
                cancelAnimationFrame(animationFrameId);
            } else {
                hideOverlay(pauseOverlay);
                lastMoveTime = performance.now();
                gameLoop();
            }
        }
        
        function resumeGame() {
            if (!isPaused) return;
            isPaused = false;
            hideOverlay(pauseOverlay);
            lastMoveTime = performance.now();
            gameLoop();
        }
        
        function gameOver() {
            isGameOver = true;
            isStarted = false;
            cancelAnimationFrame(animationFrameId);
            if (score > bestScore) {
                bestScore = score;
                bestScoreEl.textContent = bestScore;
            }
            finalScoreEl.textContent = `Score: ${score}`;
            showOverlay(gameOverOverlay);
        }
        
        function showOverlay(overlay) {
            overlay.classList.add('visible');
        }
        
        function hideOverlay(overlay) {
            overlay.classList.remove('visible');
        }
        
        function hideAllOverlays() {
            hideOverlay(startOverlay);
            hideOverlay(gameOverOverlay);
            hideOverlay(pauseOverlay);
        }
        
        function updateScoreDisplay() {
            currentScoreEl.textContent = score;
        }
        
        function spawnFood() {
            let newFood;
            do {
                newFood = {
                    x: Math.floor(Math.random() * GRID_SIZE),
                    y: Math.floor(Math.random() * GRID_SIZE)
                };
            } while (snake.some(seg => seg.x === newFood.x && seg.y === newFood.y));
            food = newFood;
        }
        
        function moveSnake() {
            direction = nextDirection;
            const head = { 
                x: snake[0].x + direction.x, 
                y: snake[0].y + direction.y 
            };
            
            // Wall collision
            if (head.x < 0 || head.x >= GRID_SIZE || head.y < 0 || head.y >= GRID_SIZE) {
                gameOver();
                return false;
            }
            
            // Self collision
            if (snake.some(seg => seg.x === head.x && seg.y === head.y)) {
                gameOver();
                return false;
            }
            
            snake.unshift(head);
            
            // Food collision
            if (head.x === food.x && head.y === food.y) {
                score += 10;
                updateScoreDisplay();
                gameSpeed = Math.max(MIN_SPEED, gameSpeed - SPEED_INCREASE);
                
                // Particle burst at food position
                const particleX = (food.x + 0.5) * CELL_SIZE;
                const particleY = (food.y + 0.5) * CELL_SIZE;
                createParticles(particleX, particleY, 20);
                
                spawnFood();
            } else {
                snake.pop();
            }
            
            return true;
        }
        
        // Rendering
        function drawGrid() {
            ctx.strokeStyle = COLORS.grid;
            ctx.lineWidth = 0.5;
            ctx.beginPath();
            for (let i = 0; i <= GRID_SIZE; i++) {
                ctx.moveTo(i * CELL_SIZE, 0);
                ctx.lineTo(i * CELL_SIZE, CANVAS_SIZE);
                ctx.moveTo(0, i * CELL_SIZE);
                ctx.lineTo(CANVAS_SIZE, i * CELL_SIZE);
            }
            ctx.stroke();
        }
        
        function drawFood() {
            const x = food.x * CELL_SIZE;
            const y = food.y * CELL_SIZE;
            const centerX = x + CELL_SIZE / 2;
            const centerY = y + CELL_SIZE / 2;
            const radius = CELL_SIZE / 2 - 2;
            
            // Glow
            const gradient = ctx.createRadialGradient(
                centerX, centerY, 0,
                centerX, centerY, radius + 4
            );
            gradient.addColorStop(0, COLORS.foodGlow);
            gradient.addColorStop(1, 'transparent');
            ctx.fillStyle = gradient;
            ctx.beginPath();
            ctx.arc(centerX, centerY, radius + 4, 0, Math.PI * 2);
            ctx.fill();
            
            // Food body
            ctx.fillStyle = COLORS.food;
            ctx.shadowColor = COLORS.food;
            ctx.shadowBlur = 15;
            ctx.beginPath();
            ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
            ctx.fill();
            ctx.shadowBlur = 0;
            
            // Highlight
            ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
            ctx.beginPath();
            ctx.arc(centerX - 3, centerY - 3, radius * 0.3, 0, Math.PI * 2);
            ctx.fill();
        }
        
        function drawSnake() {
            snake.forEach((seg, i) => {
                const x = seg.x * CELL_SIZE;
                const y = seg.y * CELL_SIZE;
                const isHead = i === 0;
                const isTail = i === snake.length - 1;
                
                // Determine segment colors
                const bodyColor = isHead ? COLORS.snakeHead : COLORS.snakeBody;
                
                // Draw segment with rounded corners
                const radius = 4;
                ctx.fillStyle = bodyColor;
                ctx.shadowColor = bodyColor;
                ctx.shadowBlur = isHead ? 10 : 5;
                
                // Main body
                roundRect(ctx, x + 1, y + 1, CELL_SIZE - 2, CELL_SIZE - 2, radius);
                ctx.fill();
                ctx.shadowBlur = 0;
                
                // Head details
                if (isHead) {
                    drawEyes(x, y, direction);
                }
                
                // Segment highlight
                ctx.fillStyle = 'rgba(255, 255, 255, 0.15)';
                roundRect(ctx, x + 2, y + 2, CELL_SIZE - 4, 4, 2);
                ctx.fill();
            });
        }
        
        function roundRect(ctx, x, y, w, h, r) {
            ctx.beginPath();
            ctx.moveTo(x + r, y);
            ctx.lineTo(x + w - r, y);
            ctx.quadraticCurveTo(x + w, y, x + w, y + r);
            ctx.lineTo(x + w, y + h - r);
            ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
            ctx.lineTo(x + r, y + h);
            ctx.quadraticCurveTo(x, y + h, x, y + h - r);
            ctx.lineTo(x, y + r);
            ctx.quadraticCurveTo(x, y, x + r, y);
            ctx.closePath();
        }
        
        function drawEyes(x, y, dir) {
            const eyeSize = 3;
            const eyeOffset = 5;
            const centerX = x + CELL_SIZE / 2;
            const centerY = y + CELL_SIZE / 2;
            
            let leftEyeX, leftEyeY, rightEyeX, rightEyeY;
            
            if (dir === DIRS.RIGHT) {
                leftEyeX = centerX + 2; leftEyeY = centerY - eyeOffset;
                rightEyeX = centerX + 2; rightEyeY = centerY + eyeOffset;
            } else if (dir === DIRS.LEFT) {
                leftEyeX = centerX - 2; leftEyeY = centerY - eyeOffset;
                rightEyeX = centerX - 2; rightEyeY = centerY + eyeOffset;
            } else if (dir === DIRS.UP) {
                leftEyeX = centerX - eyeOffset; leftEyeY = centerY - 2;
                rightEyeX = centerX + eyeOffset; rightEyeY = centerY - 2;
            } else { // DOWN
                leftEyeX = centerX - eyeOffset; leftEyeY = centerY + 2;
                rightEyeX = centerX + eyeOffset; rightEyeY = centerY + 2;
            }
            
            // Eye whites
            ctx.fillStyle = '#fff';
            ctx.shadowColor = COLORS.snakeEyeGlow;
            ctx.shadowBlur = 5;
            ctx.beginPath();
            ctx.arc(leftEyeX, leftEyeY, eyeSize, 0, Math.PI * 2);
            ctx.arc(rightEyeX, rightEyeY, eyeSize, 0, Math.PI * 2);
            ctx.fill();
            ctx.shadowBlur = 0;
            
            // Pupils
            ctx.fillStyle = COLORS.snakeEye;
            let pupilOffsetX = 0, pupilOffsetY = 0;
            if (dir === DIRS.RIGHT) pupilOffsetX = 1;
            else if (dir === DIRS.LEFT) pupilOffsetX = -1;
            else if (dir === DIRS.UP) pupilOffsetY = -1;
            else pupilOffsetY = 1;
            
            ctx.beginPath();
            ctx.arc(leftEyeX + pupilOffsetX, leftEyeY + pupilOffsetY, eyeSize * 0.5, 0, Math.PI * 2);
            ctx.arc(rightEyeX + pupilOffsetX, rightEyeY + pupilOffsetY, eyeSize * 0.5, 0, Math.PI * 2);
            ctx.fill();
        }
        
        function render() {
            // Clear
            ctx.fillStyle = COLORS.bg;
            ctx.fillRect(0, 0, CANVAS_SIZE, CANVAS_SIZE);
            
            // Grid
            drawGrid();
            
            // Game objects
            drawFood();
            drawSnake();
            drawParticles();
        }
        
        // Game Loop
        function gameLoop(timestamp) {
            if (isGameOver || isPaused) return;
            
            const deltaTime = timestamp - lastMoveTime;
            
            if (deltaTime >= gameSpeed) {
                if (!moveSnake()) return;
                lastMoveTime = timestamp;
            }
            
            render();
            updateParticles();
            animationFrameId = requestAnimationFrame(gameLoop);
        }
        
        // Initialize
        function init() {
            canvas.width = CANVAS_SIZE;
            canvas.height = CANVAS_SIZE;
            canvas.focus();
            showOverlay(startOverlay);
        }
        
        init();
    </script>
</body>
</html>