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 21 s
Cost
$0
Output tokens
6,181
Spent thinking
201 tokens
Speed
77.6 tok/s
Console errors
0
First token after
1.0 s
First visible text after
6.1 s
Prompt tokens
517
Code size
19.4 KB
Finish reason
stop
Served by
Nvidia
Model id
nvidia/nemotron-3-ultra-550b-a55b:free
Reasoning sent
{"effort":"medium"}
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 · 630 lines

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Snake</title>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      min-height: 100vh;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f0f23 100%);
      font-family: 'Segoe UI', system-ui, sans-serif;
      color: #e8e8e8;
      overflow: hidden;
    }
    .game-container {
      position: relative;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 16px;
    }
    .score-board {
      display: flex;
      gap: 32px;
      font-size: 1.4rem;
      font-weight: 600;
      letter-spacing: 0.5px;
    }
    .score-item { display: flex; flex-direction: column; align-items: center; gap: 4px; }
    .score-label { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 1px; opacity: 0.6; font-weight: 400; }
    .score-value { font-family: 'Courier New', monospace; color: #00ff88; text-shadow: 0 0 10px rgba(0,255,136,0.5); }
    #gameCanvas { 
      border-radius: 8px; 
      box-shadow: 
        0 0 0 2px rgba(255,255,255,0.1),
        0 20px 60px rgba(0,0,0,0.5),
        inset 0 0 60px rgba(0,0,0,0.3);
      background: #0a0a12;
      display: block;
    }
    .overlay {
      position: absolute;
      inset: 0;
      border-radius: 8px;
      background: rgba(10,10,18,0.95);
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 16px;
      opacity: 0;
      pointer-events: none;
      transition: opacity 0.3s ease;
      backdrop-filter: blur(4px);
    }
    .overlay.visible { opacity: 1; pointer-events: auto; }
    .overlay h1 { 
      font-size: 2.5rem; 
      font-weight: 700; 
      background: linear-gradient(135deg, #ff4757, #ff6b7a);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
      background-clip: text;
      text-shadow: none;
    }
    .overlay p { font-size: 1.1rem; opacity: 0.8; line-height: 1.6; text-align: center; max-width: 300px; }
    .overlay .final-score { font-size: 2rem; font-weight: 700; color: #00ff88; font-family: 'Courier New', monospace; }
    .overlay .controls-hint { font-size: 0.85rem; opacity: 0.5; margin-top: 8px; }
    .paused .overlay { opacity: 1; pointer-events: auto; }
    .paused .overlay h1 { background: linear-gradient(135deg, #ffa502, #ffbe0b); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
    @media (max-width: 480px) {
      .score-board { gap: 16px; font-size: 1.1rem; }
      .overlay h1 { font-size: 1.8rem; }
      .overlay .final-score { font-size: 1.5rem; }
    }
  </style>
</head>
<body>
  <div class="game-container">
    <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" id="bestScore">0</span>
      </div>
    </div>
    <canvas id="gameCanvas"></canvas>
    <div class="overlay" id="overlay">
      <h1 id="overlayTitle">Game Over</h1>
      <p class="final-score" id="finalScore">0</p>
      <p id="overlayMessage">Press Space or Enter to restart</p>
      <p class="controls-hint">Arrow keys / WASD to move • P to pause</p>
    </div>
  </div>

  <script>
    // Configuration
    const GRID_SIZE = 22;
    const CELL_SIZE = 30;
    const CANVAS_SIZE = GRID_SIZE * CELL_SIZE;
    const INITIAL_SPEED = 130; // ms per step
    const SPEED_INCREMENT = 1.5; // ms faster per food
    const MIN_SPEED = 60;
    
    // Colors
    const BG_COLOR = '#0a0a12';
    const GRID_COLOR = '#1a1a2e';
    const FOOD_COLOR = '#ff4757';
    const FOOD_GLOW = '#ff6b7a';
    const SNAKE_HEAD = '#00ff88';
    const SNAKE_BODY = '#00cc6a';
    const SNAKE_TAIL = '#009950';
    const EYE_WHITE = '#ffffff';
    const EYE_PUPIL = '#1a1a2e';
    const PARTICLE_COLORS = ['#ff4757', '#ff6b7a', '#ffa502', '#ffbe0b', '#00ff88', '#00cc6a'];

    // Game state
    let snake = [];
    let direction = { x: 1, y: 0 };
    let nextDirection = { x: 1, y: 0 };
    let food = { x: 0, y: 0 };
    let score = 0;
    let bestScore = 0;
    let gameSpeed = INITIAL_SPEED;
    let lastStepTime = 0;
    let gameOver = false;
    let paused = false;
    let animationId = null;
    
    // Smooth movement
    let interpolatedSegments = [];
    let stepProgress = 0;
    
    // Particles
    let particles = [];
    
    // Input queue for quick successive presses
    let inputQueue = [];
    const MAX_QUEUE = 2;
    
    // Canvas setup
    const canvas = document.getElementById('gameCanvas');
    const ctx = canvas.getContext('2d');
    canvas.width = CANVAS_SIZE;
    canvas.height = CANVAS_SIZE;
    
    // DOM elements
    const currentScoreEl = document.getElementById('currentScore');
    const bestScoreEl = document.getElementById('bestScore');
    const overlay = document.getElementById('overlay');
    const overlayTitle = document.getElementById('overlayTitle');
    const finalScoreEl = document.getElementById('finalScore');
    const overlayMessage = document.getElementById('overlayMessage');
    const gameContainer = document.querySelector('.game-container');

    function init() {
      // Center snake
      const startX = Math.floor(GRID_SIZE / 2);
      const startY = Math.floor(GRID_SIZE / 2);
      snake = [
        { x: startX, y: startY },
        { x: startX - 1, y: startY },
        { x: startX - 2, y: startY }
      ];
      direction = { x: 1, y: 0 };
      nextDirection = { x: 1, y: 0 };
      inputQueue = [];
      score = 0;
      gameSpeed = INITIAL_SPEED;
      gameOver = false;
      paused = false;
      particles = [];
      stepProgress = 0;
      updateInterpolatedSegments(0);
      spawnFood();
      updateScoreDisplay();
      hideOverlay();
      gameContainer.classList.remove('paused');
      if (animationId) cancelAnimationFrame(animationId);
      lastStepTime = performance.now();
      requestAnimationFrame(gameLoop);
    }

    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 updateScoreDisplay() {
      currentScoreEl.textContent = score;
      bestScoreEl.textContent = bestScore;
    }

    function showOverlay(title, message, showFinalScore = true) {
      overlayTitle.textContent = title;
      overlayMessage.textContent = message;
      finalScoreEl.textContent = score;
      finalScoreEl.style.display = showFinalScore ? 'block' : 'none';
      overlay.classList.add('visible');
    }

    function hideOverlay() {
      overlay.classList.remove('visible');
    }

    function handleInput(newDir) {
      // Prevent reversing
      if (newDir.x === -direction.x && newDir.y === -direction.y) return;
      if (newDir.x === direction.x && newDir.y === direction.y) return;
      
      // Queue input
      if (inputQueue.length < MAX_QUEUE) {
        const lastQueued = inputQueue.length > 0 ? inputQueue[inputQueue.length - 1] : direction;
        if (newDir.x !== -lastQueued.x || newDir.y !== -lastQueued.y) {
          inputQueue.push(newDir);
        }
      }
    }

    function processInputQueue() {
      if (inputQueue.length > 0) {
        nextDirection = inputQueue.shift();
      }
    }

    function step() {
      if (gameOver || paused) return;
      
      processInputQueue();
      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) {
        endGame();
        return;
      }
      
      // Self collision
      if (snake.some(seg => seg.x === head.x && seg.y === head.y)) {
        endGame();
        return;
      }
      
      snake.unshift(head);
      
      // Food collision
      if (head.x === food.x && head.y === food.y) {
        score += 10;
        if (score > bestScore) bestScore = score;
        updateScoreDisplay();
        createParticles(food.x, food.y);
        gameSpeed = Math.max(MIN_SPEED, gameSpeed - SPEED_INCREMENT);
        spawnFood();
      } else {
        snake.pop();
      }
      
      stepProgress = 0;
    }

    function createParticles(gridX, gridY) {
      const centerX = (gridX + 0.5) * CELL_SIZE;
      const centerY = (gridY + 0.5) * CELL_SIZE;
      for (let i = 0; i < 12; i++) {
        const angle = (Math.PI * 2 * i) / 12 + Math.random() * 0.3;
        const speed = 2 + Math.random() * 3;
        particles.push({
          x: centerX,
          y: centerY,
          vx: Math.cos(angle) * speed,
          vy: Math.sin(angle) * speed,
          radius: 3 + Math.random() * 3,
          color: PARTICLE_COLORS[Math.floor(Math.random() * PARTICLE_COLORS.length)],
          life: 1,
          decay: 0.02 + Math.random() * 0.02
        });
      }
    }

    function updateParticles(dt) {
      for (let i = particles.length - 1; i >= 0; i--) {
        const p = particles[i];
        p.x += p.vx;
        p.y += p.vy;
        p.vy += 0.15; // gravity
        p.life -= p.decay;
        p.radius *= 0.98;
        if (p.life <= 0) particles.splice(i, 1);
      }
    }

    function drawParticles() {
      particles.forEach(p => {
        ctx.globalAlpha = p.life;
        ctx.fillStyle = p.color;
        ctx.beginPath();
        ctx.arc(p.x, p.y, Math.max(1, p.radius), 0, Math.PI * 2);
        ctx.fill();
      });
      ctx.globalAlpha = 1;
    }

    function endGame() {
      gameOver = true;
      showOverlay('Game Over', 'Press Space or Enter to restart');
      cancelAnimationFrame(animationId);
    }

    function togglePause() {
      if (gameOver) return;
      paused = !paused;
      gameContainer.classList.toggle('paused', paused);
      if (paused) {
        showOverlay('Paused', 'Press P to resume', false);
        cancelAnimationFrame(animationId);
      } else {
        hideOverlay();
        lastStepTime = performance.now();
        requestAnimationFrame(gameLoop);
      }
    }

    function updateInterpolatedSegments(progress) {
      interpolatedSegments = snake.map((seg, i) => {
        if (i === 0) return { ...seg, progress: 0 };
        const prev = snake[i - 1];
        return {
          x: prev.x + (seg.x - prev.x) * progress,
          y: prev.y + (seg.y - prev.y) * progress,
          progress
        };
      });
    }

    function drawGrid() {
      ctx.strokeStyle = GRID_COLOR;
      ctx.lineWidth = 0.5;
      ctx.beginPath();
      for (let i = 0; i <= GRID_SIZE; i++) {
        const pos = i * CELL_SIZE;
        ctx.moveTo(pos, 0);
        ctx.lineTo(pos, CANVAS_SIZE);
        ctx.moveTo(0, pos);
        ctx.lineTo(CANVAS_SIZE, pos);
      }
      ctx.stroke();
    }

    function drawFood() {
      const centerX = (food.x + 0.5) * CELL_SIZE;
      const centerY = (food.y + 0.5) * CELL_SIZE;
      const radius = CELL_SIZE * 0.35;
      const pulse = Math.sin(performance.now() / 200) * 0.15 + 1;
      
      // Glow
      const gradient = ctx.createRadialGradient(centerX, centerY, 0, centerX, centerY, radius * 1.5 * pulse);
      gradient.addColorStop(0, FOOD_GLOW);
      gradient.addColorStop(1, 'rgba(255, 71, 87, 0)');
      ctx.fillStyle = gradient;
      ctx.beginPath();
      ctx.arc(centerX, centerY, radius * 1.5 * pulse, 0, Math.PI * 2);
      ctx.fill();
      
      // Food body
      ctx.fillStyle = FOOD_COLOR;
      ctx.beginPath();
      ctx.arc(centerX, centerY, radius * pulse, 0, Math.PI * 2);
      ctx.fill();
      
      // Highlight
      ctx.fillStyle = 'rgba(255,255,255,0.3)';
      ctx.beginPath();
      ctx.arc(centerX - radius * 0.2, centerY - radius * 0.2, radius * 0.25, 0, Math.PI * 2);
      ctx.fill();
    }

    function drawSnake() {
      // Draw body segments (from tail to head-1)
      for (let i = interpolatedSegments.length - 1; i > 0; i--) {
        const seg = interpolatedSegments[i];
        const nextSeg = interpolatedSegments[i - 1];
        const isTail = i === interpolatedSegments.length - 1;
        
        const cx = seg.x * CELL_SIZE;
        const cy = seg.y * CELL_SIZE;
        const nx = nextSeg.x * CELL_SIZE;
        const ny = nextSeg.y * CELL_SIZE;
        
        const radius = CELL_SIZE * 0.42;
        const tailRadius = isTail ? radius * 0.6 : radius;
        
        // Segment color gradient from tail to head
        const t = i / (interpolatedSegments.length - 1);
        const r = Math.round(0 + (0 - 0) * t); // placeholder
        ctx.fillStyle = isTail ? SNAKE_TAIL : SNAKE_BODY;
        
        // Draw rounded rectangle connecting to next segment
        const dx = nx - cx;
        const dy = ny - cy;
        const dist = Math.sqrt(dx * dx + dy * dy);
        
        if (dist > 0.5) {
          const angle = Math.atan2(dy, dx);
          ctx.save();
          ctx.translate(cx, cy);
          ctx.rotate(angle);
          
          // Body segment
          ctx.beginPath();
          ctx.roundRect(-radius, -radius, dist + radius * 2, radius * 2, radius);
          ctx.fill();
          
          ctx.restore();
        } else {
          ctx.beginPath();
          ctx.arc(cx, cy, radius, 0, Math.PI * 2);
          ctx.fill();
        }
        
        // Tail tip
        if (isTail) {
          const tailAngle = Math.atan2(snake[snake.length - 1].y - snake[snake.length - 2].y, 
                                       snake[snake.length - 1].x - snake[snake.length - 2].x);
          ctx.save();
          ctx.translate(cx, cy);
          ctx.rotate(tailAngle);
          ctx.fillStyle = SNAKE_TAIL;
          ctx.beginPath();
          ctx.moveTo(-radius * 0.8, 0);
          ctx.lineTo(-radius * 1.5, -radius * 0.5);
          ctx.lineTo(-radius * 1.5, radius * 0.5);
          ctx.closePath();
          ctx.fill();
          ctx.restore();
        }
      }
      
      // Draw head
      const head = interpolatedSegments[0];
      const hx = head.x * CELL_SIZE;
      const hy = head.y * CELL_SIZE;
      const headRadius = CELL_SIZE * 0.45;
      
      // Head glow
      const headGlow = ctx.createRadialGradient(hx, hy, 0, hx, hy, headRadius * 1.3);
      headGlow.addColorStop(0, 'rgba(0, 255, 136, 0.4)');
      headGlow.addColorStop(1, 'rgba(0, 255, 136, 0)');
      ctx.fillStyle = headGlow;
      ctx.beginPath();
      ctx.arc(hx, hy, headRadius * 1.3, 0, Math.PI * 2);
      ctx.fill();
      
      // Head body
      ctx.fillStyle = SNAKE_HEAD;
      ctx.beginPath();
      ctx.arc(hx, hy, headRadius, 0, Math.PI * 2);
      ctx.fill();
      
      // Eyes
      const eyeOffset = headRadius * 0.35;
      const eyeRadius = headRadius * 0.18;
      const pupilRadius = eyeRadius * 0.5;
      const dirAngle = Math.atan2(direction.y, direction.x);
      
      // Eye positions (perpendicular to direction)
      const perpAngle = dirAngle + Math.PI / 2;
      const eye1x = hx + Math.cos(perpAngle) * eyeOffset + Math.cos(dirAngle) * headRadius * 0.2;
      const eye1y = hy + Math.sin(perpAngle) * eyeOffset + Math.sin(dirAngle) * headRadius * 0.2;
      const eye2x = hx - Math.cos(perpAngle) * eyeOffset + Math.cos(dirAngle) * headRadius * 0.2;
      const eye2y = hy - Math.sin(perpAngle) * eyeOffset + Math.sin(dirAngle) * headRadius * 0.2;
      
      // Eye whites
      ctx.fillStyle = EYE_WHITE;
      ctx.beginPath();
      ctx.arc(eye1x, eye1y, eyeRadius, 0, Math.PI * 2);
      ctx.arc(eye2x, eye2y, eyeRadius, 0, Math.PI * 2);
      ctx.fill();
      
      // Pupils (look in movement direction)
      const pupilOffset = eyeRadius * 0.4;
      ctx.fillStyle = EYE_PUPIL;
      ctx.beginPath();
      ctx.arc(eye1x + Math.cos(dirAngle) * pupilOffset, eye1y + Math.sin(dirAngle) * pupilOffset, pupilRadius, 0, Math.PI * 2);
      ctx.arc(eye2x + Math.cos(dirAngle) * pupilOffset, eye2y + Math.sin(dirAngle) * pupilOffset, pupilRadius, 0, Math.PI * 2);
      ctx.fill();
      
      // Eye highlights
      ctx.fillStyle = 'rgba(255,255,255,0.8)';
      ctx.beginPath();
      ctx.arc(eye1x - Math.cos(dirAngle) * pupilOffset * 0.3, eye1y - Math.sin(dirAngle) * pupilOffset * 0.3, pupilRadius * 0.4, 0, Math.PI * 2);
      ctx.arc(eye2x - Math.cos(dirAngle) * pupilOffset * 0.3, eye2y - Math.sin(dirAngle) * pupilOffset * 0.3, pupilRadius * 0.4, 0, Math.PI * 2);
      ctx.fill();
    }

    function render(progress) {
      // Clear
      ctx.fillStyle = BG_COLOR;
      ctx.fillRect(0, 0, CANVAS_SIZE, CANVAS_SIZE);
      
      // Grid
      drawGrid();
      
      // Food
      drawFood();
      
      // Update interpolated positions for smooth movement
      updateInterpolatedSegments(progress);
      
      // Snake
      drawSnake();
      
      // Particles
      drawParticles();
    }

    function gameLoop(timestamp) {
      if (gameOver) return;
      
      const dt = timestamp - lastStepTime;
      stepProgress = Math.min(1, dt / gameSpeed);
      
      if (dt >= gameSpeed) {
        step();
        lastStepTime = timestamp;
        stepProgress = 0;
      }
      
      updateParticles(16);
      render(stepProgress);
      
      animationId = requestAnimationFrame(gameLoop);
    }

    // Keyboard handling
    window.addEventListener('keydown', e => {
      if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
      
      const key = e.key.toLowerCase();
      
      if (key === ' ' || key === 'enter') {
        e.preventDefault();
        if (gameOver) {
          init();
        } else if (paused) {
          togglePause();
        }
        return;
      }
      
      if (key === 'p') {
        e.preventDefault();
        togglePause();
        return;
      }
      
      if (paused || gameOver) return;
      
      let newDir = null;
      switch (key) {
        case 'arrowup': case 'w': newDir = { x: 0, y: -1 }; break;
        case 'arrowdown': case 's': newDir = { x: 0, y: 1 }; break;
        case 'arrowleft': case 'a': newDir = { x: -1, y: 0 }; break;
        case 'arrowright': case 'd': newDir = { x: 1, y: 0 }; break;
      }
      
      if (newDir) {
        e.preventDefault();
        handleInput(newDir);
      }
    });

    // Touch/swipe support for mobile
    let touchStartX = 0;
    let touchStartY = 0;
    
    canvas.addEventListener('touchstart', e => {
      touchStartX = e.touches[0].clientX;
      touchStartY = e.touches[0].clientY;
    }, { passive: true });
    
    canvas.addEventListener('touchend', e => {
      if (paused || gameOver) return;
      const dx = e.changedTouches[0].clientX - touchStartX;
      const dy = e.changedTouches[0].clientY - touchStartY;
      const absX = Math.abs(dx);
      const absY = Math.abs(dy);
      
      if (Math.max(absX, absY) < 30) return; // Minimum swipe distance
      
      let newDir = null;
      if (absX > absY) {
        newDir = dx > 0 ? { x: 1, y: 0 } : { x: -1, y: 0 };
      } else {
        newDir = dy > 0 ? { x: 0, y: 1 } : { x: 0, y: -1 };
      }
      
      if (newDir) handleInput(newDir);
    }, { passive: true });

    // Prevent context menu on long press
    canvas.addEventListener('contextmenu', e => e.preventDefault());

    // Handle visibility change
    document.addEventListener('visibilitychange', () => {
      if (!gameOver && !paused && document.hidden) {
        togglePause();
      }
    });

    // Start
    init();
  </script>
</body>
</html>
Reasoning trace (201 tokens)
The user wants a polished Snake game in a single HTML file. Let me break down the requirements:

1. Grid of at least 20x20 cells, centered on page
2. Arrow keys and WASD control, quick successive key presses honored but no reversing
3. Eating food: +10 points, grows by 1 cell, food never spawns on snake
4. Game over on wall/self collision, overlay with score, Space/Enter restarts, P pauses
5. Visual polish: smooth movement, distinct head with eyes facing direction, particle burst on eating
6. Display current score and best score of session

I'll create a polished implementation with:
- Smooth interpolation between grid positions
- Particle effects on food consumption
- Nice visual styling for snake (head with eyes, body segments)
- Responsive design
- Proper keyboard handling with input queue
- Session high score storage in memory

Let me write the complete HTML file.