Models 44

gpt-oss-120b

by OpenAIReasoningClean
Open in new window

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

How it went

Total time
5.9 s
Cost
$0.0017
Output tokens
2,662
Spent thinking
434 tokens
Speed
475.8 tok/s
Console errors
0
First token after
312 ms
First visible text after
1.2 s
Prompt tokens
557
Code size
7.1 KB
Finish reason
stop
Served by
Groq
Model id
openai/gpt-oss-120b
Reasoning sent
{"effort":"medium"}
Max output
64,000 tokens
Generated
Nov 11, 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 · 270 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Polished Snake Demo</title>
<style>
  html,body{margin:0;height:100%;display:flex;align-items:center;justify-content:center;background:#111;color:#fff;font-family:sans-serif;overflow:hidden;}
  #game{position:relative;display:flex;flex-direction:column;align-items:center;}
  canvas{background:#222;display:block;border:2px solid #555;}
  #info{margin:5px 0;}
  #overlay{
    position:absolute;top:0;left:0;width:100%;height:100%;
    background:rgba(0,0,0,0.7);color:#fff;display:flex;align-items:center;justify-content:center;
    font-size:1.5rem;cursor:pointer;text-align:center;padding:20px;box-sizing:border-box;
  }
</style>
</head>
<body>
<div id="game">
  <div id="info">Score: <span id="score">0</span> | Best: <span id="best">0</span></div>
  <canvas id="c"></canvas>
  <div id="overlay">Click or press any key to start<br>(Use Arrow keys / WASD to move, P to pause, Space/Enter to restart)</div>
</div>
<script>
(() => {
  const canvas = document.getElementById('c');
  const ctx = canvas.getContext('2d');
  const CELL = 20;
  const COLS = 20;
  const ROWS = 20;
  const WIDTH = COLS * CELL;
  const HEIGHT = ROWS * CELL;
  canvas.width = WIDTH;
  canvas.height = HEIGHT;

  const overlay = document.getElementById('overlay');
  const scoreEl = document.getElementById('score');
  const bestEl = document.getElementById('best');

  let bestScore = 0;
  let score = 0;
  let snake, dir, nextDir, food, particles, tick, lastTime, paused, demoMode;

  const DIRS = {
    ArrowUp:    {x:0, y:-1},
    ArrowDown:  {x:0, y:1},
    ArrowLeft:  {x:-1, y:0},
    ArrowRight: {x:1, y:0},
    w: {x:0, y:-1},
    s: {x:0, y:1},
    a: {x:-1, y:0},
    d: {x:1, y:0}
  };

  function init() {
    snake = [{x:9,y:9},{x:8,y:9},{x:7,y:9}];
    dir = {x:1,y:0};
    nextDir = dir;
    spawnFood();
    particles = [];
    tick = 0;
    lastTime = performance.now();
    paused = false;
    score = 0;
    updateScore();
  }

  function spawnFood() {
    let pos;
    do {
      pos = {x:Math.floor(Math.random()*COLS), y:Math.floor(Math.random()*ROWS)};
    } while (snake.some(s=>s.x===pos.x && s.y===pos.y));
    food = pos;
  }

  function updateScore() {
    scoreEl.textContent = score;
    if (score > bestScore) bestScore = score;
    bestEl.textContent = bestScore;
  }

  function setDirection(d) {
    // prevent reverse
    if (d.x===-dir.x && d.y===-dir.y) return;
    nextDir = d;
  }

  function step() {
    if (paused) return;
    dir = nextDir;
    const head = {x: snake[0].x + dir.x, y: snake[0].y + dir.y};

    // wall collision
    if (head.x<0||head.x>=COLS||head.y<0||head.y>=ROWS) return gameOver();

    // self collision
    if (snake.some(s=>s.x===head.x && s.y===head.y)) return gameOver();

    snake.unshift(head);
    // eat
    if (head.x===food.x && head.y===food.y) {
      score+=10;
      updateScore();
      spawnFood();
      createBurst(head.x,head.y);
    } else {
      snake.pop();
    }
  }

  function createBurst(cx,cy){
    for(let i=0;i<12;i++){
      const angle=Math.random()*Math.PI*2;
      const speed=Math.random()*0.8+0.2;
      particles.push({
        x:cx+0.5, y:cy+0.5,
        vx:Math.cos(angle)*speed, vy:Math.sin(angle)*speed,
        life:0.6
      });
    }
  }

  function drawParticles(dt){
    particles = particles.filter(p=>{
      p.x+=p.vx*dt;
      p.y+=p.vy*dt;
      p.life-=dt;
      if(p.life>0){
        ctx.fillStyle=`rgba(255,200,0,${p.life})`;
        ctx.beginPath();
        ctx.arc(p.x*CELL, p.y*CELL, 3,0,Math.PI*2);
        ctx.fill();
        return true;
      }
      return false;
    });
  }

  function draw() {
    ctx.clearRect(0,0,WIDTH,HEIGHT);
    // grid (optional subtle)
    ctx.strokeStyle='#333';
    ctx.lineWidth=0.5;
    for(let i=0;i<=COLS;i++){
      ctx.beginPath();ctx.moveTo(i*CELL,0);ctx.lineTo(i*CELL,HEIGHT);ctx.stroke();
    }
    for(let i=0;i<=ROWS;i++){
      ctx.beginPath();ctx.moveTo(0,i*CELL);ctx.lineTo(WIDTH,i*CELL);ctx.stroke();
    }

    // food
    ctx.fillStyle='red';
    ctx.fillRect(food.x*CELL, food.y*CELL, CELL, CELL);

    // snake
    snake.forEach((seg,i)=>{
      ctx.fillStyle = i===0 ? '#0f0' : '#5f5';
      ctx.fillRect(seg.x*CELL, seg.y*CELL, CELL, CELL);
      // head eyes
      if(i===0){
        ctx.fillStyle='black';
        const eyeSize=2;
        const offset=2;
        let ex=seg.x*CELL+offset, ey=seg.y*CELL+offset;
        if(dir.x===1){ // right
          ex=seg.x*CELL+CELL- offset - eyeSize;
          ey=seg.y*CELL+offset;
        } else if(dir.x===-1){ // left
          ey=seg.y*CELL+offset;
        } else if(dir.y===1){ // down
          ey=seg.y*CELL+CELL- offset - eyeSize;
          ex=seg.x*CELL+offset;
        } else if(dir.y===-1){ // up
          ey=seg.y*CELL+offset;
        }
        // two eyes
        ctx.fillRect(ex,ey,eyeSize,eyeSize);
        ctx.fillRect(ex,ey+CELL/2,eyeSize,eyeSize);
      }
    });

    // particles
    const now = performance.now();
    const dt = (now - lastTime)/1000;
    drawParticles(dt);
    lastTime = now;
  }

  function loop(time){
    if (!paused) {
      const delta = time - lastTime;
      if (delta >= 100) { // 100ms per step
        step();
        lastTime = time;
      }
    }
    draw();
    requestAnimationFrame(loop);
  }

  function gameOver(){
    paused = true;
    overlay.innerHTML = `Game Over! Score: ${score}<br>Press Space/Enter to restart`;
    overlay.style.display = 'flex';
  }

  // Input handling
  window.addEventListener('keydown', e=>{
    if (overlay.style.display !== 'none') {
      // start demo or player
      overlay.style.display = 'none';
      if (demoMode) return; // already demo
      demoMode = false;
      paused = false;
      return;
    }
    const key = e.key;
    if (key==='p' || key==='P'){
      paused = !paused;
      return;
    }
    if (key===' '||key==='Enter'){
      init();
      paused = false;
      overlay.style.display='none';
      return;
    }
    if (DIRS[key]) {
      setDirection(DIRS[key]);
    }
  });

  // Demo AI
  function demoAI(){
    if (!demoMode) return;
    const head = snake[0];
    const dx = food.x - head.x;
    const dy = food.y - head.y;
    let preferred = [];
    if (Math.abs(dx)>Math.abs(dy)){
      preferred.push(dx>0?DIRS['ArrowRight']:DIRS['ArrowLeft']);
      if(dy!==0) preferred.push(dy>0?DIRS['ArrowDown']:DIRS['ArrowUp']);
    } else {
      if(dy!==0) preferred.push(dy>0?DIRS['ArrowDown']:DIRS['ArrowUp']);
      if (dx!==0) preferred.push(dx>0?DIRS['ArrowRight']:DIRS['ArrowLeft']);
    }
    // fallback random safe direction
    for(const d of preferred){
      const nx = head.x + d.x;
      const ny = head.y + d.y;
      if (nx<0||nx>=COLS||ny<0||ny>=ROWS) continue;
      if (snake.some(s=>s.x===nx && s.y===ny)) continue;
      setDirection(d);
      return;
    }
    // try any safe direction
    const dirs = Object.values(DIRS).filter(d=>!snake.some(s=>s.x===head.x+d.x && s.y===head.y+d.y));
    if (dirs.length) setDirection(dirs[Math.floor(Math.random()*dirs.length)]);
  }

  // start everything
  init();
  demoMode = true;
  requestAnimationFrame(loop);
  // run AI every step (sync with game step)
  setInterval(demoAI, 100);
})();
</script>
</body>
</html>
Reasoning trace (434 tokens)
We need to output a single HTML file with canvas snake game meeting requirements. Must be self-contained. Must include message "Click or press a key to start" overlay before start, as keyboard events only after click. The game should start in self-playing demo mode behind that message, so that screenshot shows something. Could automatically start after a short delay or after user click? Requirement: "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." So we need to have a demo AI that controls snake automatically while overlay message displayed. The overlay message visible, but the game runs behind it. After user clicks or presses a key, overlay disappears and user can control.

Implement: set up canvas with size based on grid cell size, maybe 20x20 cells each 20px = 400x400 canvas. Center it with CSS flex.

Game logic: grid, snake array of positions, direction vector. Input handling: arrow/WASD, ignore reverse.

Movement smooth: we can animate between cells using requestAnimationFrame and progress variable.

Particle burst: small circles that expand/fade.

Score and best score displayed maybe above canvas.

Overlay: a semi-transparent div with message and start instructions.

Demo AI: simple algorithm that chooses direction towards food while avoiding walls/self. Could be simple: if snake.x < food.x go right, else left; similar for y; but ensure not reverse. Also ensure not colliding with self; simple fallback.

Implement main loop: set interval for steps (e.g., 100ms per step) but smooth movement uses interpolation.

Simplify: we can move snake by cells each tick, but animate between positions over a duration.

Implementation details: Use requestAnimationFrame to draw, track elapsed time.

Key handling: add event listeners for keydown.

Restart: space or enter.

Pause: P.

Score displayed.

Best score stored in variable (session only) not localStorage.

Make sure no external resources.

Now produce HTML code.

We need to ensure no errors.

Let's craft.