Models 44

GPT-6 Luna

by OpenAIReasoningClean
Open in new window

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

How it went

Total time
40.6 s
Cost
$0.0021
Output tokens
4,174
Spent thinking
211 tokens
Speed
138.9 tok/s
Console errors
0
First token after
10.5 s
First visible text after
11.9 s
Prompt tokens
493
Code size
11.5 KB
Finish reason
stop
Served by
OpenAI
Model id
openai/gpt-6-luna
Reasoning sent
{"effort":"low"}
Max output
64,000 tokens
Generated
Nov 10, 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 · 166 lines

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Snake — Arcade</title>
<style>
  :root{color-scheme:dark;--bg:#0a0e14;--panel:#111821;--line:#202b37;--muted:#8593a5;--green:#9df36b;--text:#eef4f8}
  *{box-sizing:border-box}
  body{margin:0;min-height:100vh;background:radial-gradient(ellipse at 50% 5%,#17231e 0%,#0b1116 39%,var(--bg) 76%);color:var(--text);font-family:Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;display:grid;place-items:center;padding:28px}
  .app{width:min(100%,1050px)}
  header{display:flex;align-items:center;justify-content:space-between;margin:0 0 22px;padding:0 4px}
  .brand{display:flex;gap:13px;align-items:center}
  .brand-icon{width:42px;height:42px;border:1px solid #34453b;background:#17231d;border-radius:13px;display:grid;place-items:center;color:var(--green);font-size:23px;box-shadow:inset 0 0 18px #9df36b0c}
  h1{font-size:20px;letter-spacing:-.5px;margin:0;font-weight:750}
  .subtitle{font-size:11px;color:var(--muted);margin-top:3px;letter-spacing:1.5px;text-transform:uppercase}
  .status{display:flex;align-items:center;gap:8px;color:#aeb9c3;font-size:12px}
  .dot{width:7px;height:7px;border-radius:50%;background:var(--green);box-shadow:0 0 10px #9df36b}
  .layout{display:grid;grid-template-columns:minmax(0,700px) 230px;gap:22px;align-items:stretch;justify-content:center}
  .board-wrap{position:relative;border:1px solid #26333b;border-radius:17px;padding:10px;background:linear-gradient(145deg,#141c22,#0d1318);box-shadow:0 25px 80px #0008,0 0 50px #8ce45b08}
  canvas{display:block;width:100%;aspect-ratio:1;border-radius:10px}
  .side{display:flex;flex-direction:column;gap:13px}
  .card{background:linear-gradient(145deg,#141d25,#10171e);border:1px solid var(--line);border-radius:14px;padding:18px}
  .label{color:var(--muted);font-size:10px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase}
  .score{font-size:38px;line-height:1.1;letter-spacing:-1.5px;font-weight:750;margin-top:10px;font-variant-numeric:tabular-nums}
  .score small{font-size:14px;color:var(--muted);font-weight:500;letter-spacing:0}
  .best{font-size:24px}
  .food-key{display:flex;align-items:center;gap:10px;margin-top:13px;color:#b6c1cb;font-size:12px}
  .food-icon{width:11px;height:11px;border-radius:50%;background:#ff7871;box-shadow:0 0 12px #ff787180}
  .controls{padding:16px 18px}
  .key-row{display:flex;gap:5px;margin-top:11px;align-items:center}
  kbd{min-width:27px;height:26px;padding:0 7px;display:grid;place-items:center;border-radius:6px;border:1px solid #35414c;background:#1a242d;color:#d8e0e6;font:600 11px ui-monospace,monospace;box-shadow:0 2px 0 #080c10}
  .control-note{font-size:11px;color:#95a2ae;line-height:1.6;margin-top:13px}
  .help{margin-top:auto;padding:4px 6px;color:#758291;font-size:11px;line-height:1.9}
  .help strong{color:#aeb9c3;font-weight:600}
  .banner{position:absolute;bottom:21px;left:50%;transform:translateX(-50%);width:max-content;max-width:calc(100% - 35px);padding:10px 15px;border-radius:9px;background:#0b1112dc;border:1px solid #405143;backdrop-filter:blur(8px);color:#dbe8d8;font-size:12px;text-align:center;box-shadow:0 5px 20px #0005}
  .banner b{color:var(--green);font-weight:700}
  .banner.over{border-color:#5a383a;color:#f0d6d4}
  .banner.over b{color:#ff938b}
  @media(max-width:760px){body{padding:15px}.layout{grid-template-columns:minmax(0,1fr);gap:12px}.side{display:grid;grid-template-columns:1fr 1fr;gap:10px}.card{padding:14px}.score{font-size:30px}.controls{grid-column:1/-1}.help{grid-column:1/-1;margin:0;display:flex;justify-content:center;gap:18px}.board-wrap{padding:7px}header{margin-bottom:13px}}
  @media(max-width:420px){body{padding:11px}.side{gap:8px}.card{padding:12px}.banner{font-size:10px;padding:9px 11px}.help{gap:10px;font-size:10px}}
</style>
</head>
<body>
<main class="app">
  <header>
    <div class="brand">
      <div class="brand-icon">蛇</div>
      <div><h1>Snake</h1><div class="subtitle">The classic, reimagined</div></div>
    </div>
    <div class="status"><span class="dot"></span><span id="mode">Demo running</span></div>
  </header>

  <div class="layout">
    <section class="board-wrap" aria-label="Snake game board">
      <canvas id="game" aria-label="Snake game canvas"></canvas>
      <div class="banner" id="banner"><b>DEMO MODE</b> &nbsp;·&nbsp; Click or press a key to start</div>
    </section>
    <aside class="side">
      <div class="card">
        <div class="label">Current score</div>
        <div class="score"><span id="score">0</span> <small>pts</small></div>
        <div class="food-key"><span class="food-icon"></span>Every apple is worth 10</div>
      </div>
      <div class="card">
        <div class="label">Best this session</div>
        <div class="score best" id="best">0</div>
        <div class="label" style="margin-top:7px">points</div>
      </div>
      <div class="card controls">
        <div class="label">How to play</div>
        <div class="key-row"><kbd>W</kbd><kbd>A</kbd><kbd>S</kbd><kbd>D</kbd><span style="color:#71808d;font-size:11px;margin:0 3px">or</span><kbd>↑</kbd><kbd>←</kbd><kbd>↓</kbd><kbd>→</kbd></div>
        <div class="control-note">Eat apples, grow longer, and don't hit the walls or yourself.</div>
      </div>
      <div class="help"><span><strong>P</strong> &nbsp;Pause</span><span><strong>Space / Enter</strong> &nbsp;Restart</span></div>
    </aside>
  </div>
</main>
<script>
(() => {
  const canvas=document.getElementById('game'), ctx=canvas.getContext('2d');
  const N=26, dirs={ArrowUp:[0,-1],w:[0,-1],ArrowDown:[0,1],s:[0,1],ArrowLeft:[-1,0],a:[-1,0],ArrowRight:[1,0],d:[1,0]};
  let snake,dir,food,score=0,best=0,mode='demo',paused=false,dead=false,queue=[],last=0,acc=0,stepMs=115,particles=[];
  const banner=document.getElementById('banner'), scoreEl=document.getElementById('score'), bestEl=document.getElementById('best'), modeEl=document.getElementById('mode');
  function resize(){const r=canvas.getBoundingClientRect(),dpr=Math.min(devicePixelRatio||1,2);canvas.width=Math.round(r.width*dpr);canvas.height=Math.round(r.height*dpr);ctx.setTransform(dpr,0,0,dpr,0,0)}
  new ResizeObserver(resize).observe(canvas); resize();
  function reset(demo=false){
    score=0;scoreEl.textContent='0';snake=[{x:7,y:13},{x:6,y:13},{x:5,y:13},{x:4,y:13}];dir={x:1,y:0};queue=[];dead=false;paused=false;mode=demo?'demo':'playing';stepMs=demo?105:115;particles=[];spawnFood();
    modeEl.textContent=demo?'Demo running':'Playing';setBanner(demo?'<b>DEMO MODE</b> &nbsp;·&nbsp; Click or press a key to start':'<b>GOOD LUCK</b> &nbsp;·&nbsp; P to pause');
  }
  function setBanner(html,cls=''){banner.innerHTML=html;banner.className='banner '+cls;banner.style.display='block'}
  function spawnFood(){
    let p; do{p={x:Math.floor(Math.random()*N),y:Math.floor(Math.random()*N)}}while(snake.some(s=>s.x===p.x&&s.y===p.y)); food=p;
  }
  function begin(){reset(false)}
  function key(e){
    const k=e.key, lower=k.toLowerCase();
    if([...Object.keys(dirs),' ','Enter','p'].includes(k)||lower==='p')e.preventDefault();
    if(mode==='demo'){begin();if(dirs[k]||dirs[lower])enqueue(dirs[k]||dirs[lower]);return}
    if(k===' '||k==='Enter'){if(dead){begin();return}if(paused){paused=false;modeEl.textContent='Playing';setBanner('<b>GOOD LUCK</b> &nbsp;·&nbsp; P to pause');return}}
    if(lower==='p'&&!dead){paused=!paused;modeEl.textContent=paused?'Paused':'Playing';setBanner(paused?'<b>PAUSED</b> &nbsp;·&nbsp; Press P to resume':'<b>GOOD LUCK</b> &nbsp;·&nbsp; P to pause');return}
    const d=dirs[k]||dirs[lower];if(d&&!dead&&!paused)enqueue(d);
  }
  function enqueue(d){
    const from=queue.length?queue[queue.length-1]:dir;
    if(d.x!==-from.x||d.y!==-from.y){if(queue.length<2)queue.push(d)}
  }
  document.addEventListener('keydown',key);canvas.addEventListener('pointerdown',()=>{if(mode==='demo')begin()});
  function ai(){
    // Find a short safe route to the apple, treating the body as obstacles.
    const start=snake[0], blocked=new Set(snake.slice(0,-1).map(p=>p.x+','+p.y)), q=[[start.x,start.y,[]]], seen=new Set([start.x+','+start.y]);
    while(q.length){
      const [x,y,path]=q.shift();
      if(x===food.x&&y===food.y&&path.length)return path[0];
      for(const [dx,dy] of [[1,0],[0,1],[-1,0],[0,-1]]){
        const nx=x+dx,ny=y+dy,key=nx+','+ny;
        if(nx<0||ny<0||nx>=N||ny>=N||blocked.has(key)||seen.has(key))continue;
        seen.add(key);q.push([nx,ny,path.concat([{x:dx,y:dy}])]);
      }
    }
    for(const d of [{x:dir.y,y:-dir.x},{x:-dir.y,y:dir.x},dir]){
      const x=start.x+d.x,y=start.y+d.y;
      if(x>=0&&y>=0&&x<N&&y<N&&!snake.slice(0,-1).some(p=>p.x===x&&p.y===y))return d;
    }
    return dir;
  }
  function burst(x,y){for(let i=0;i<14;i++){const a=Math.random()*Math.PI*2,s=1+Math.random()*2.6;particles.push({x:x+.5,y:y+.5,vx:Math.cos(a)*s,vy:Math.sin(a)*s,life:1})}}
  function tick(){
    if(dead||paused)return;
    if(mode==='demo'){queue=[];dir=ai()}else if(queue.length)dir=queue.shift();
    const h={x:snake[0].x+dir.x,y:snake[0].y+dir.y},eating=h.x===food.x&&h.y===food.y;
    if(h.x<0||h.y<0||h.x>=N||h.y>=N||snake.slice(0,eating?snake.length:snake.length-1).some(p=>p.x===h.x&&p.y===h.y)){
      dead=true;modeEl.textContent='Game over';setBanner('<b>GAME OVER</b> &nbsp;·&nbsp; Score '+score+' &nbsp;·&nbsp; Press Space or Enter to restart','over');return;
    }
    snake.unshift(h);if(eating){score+=10;scoreEl.textContent=score;if(score>best){best=score;bestEl.textContent=best}burst(food.x,food.y);spawnFood();if(mode==='playing')stepMs=Math.max(72,stepMs-1)}else snake.pop();
  }
  function draw(){
    const w=canvas.clientWidth,cell=w/N;ctx.clearRect(0,0,w,w);
    ctx.fillStyle='#0b1216';ctx.fillRect(0,0,w,w);
    ctx.strokeStyle='rgba(167,205,169,.055)';ctx.lineWidth=1;
    for(let i=0;i<=N;i++){const p=i*cell;ctx.beginPath();ctx.moveTo(p,0);ctx.lineTo(p,w);ctx.stroke();ctx.beginPath();ctx.moveTo(0,p);ctx.lineTo(w,p);ctx.stroke()}
    const t=performance.now()/1000;
    const fx=(food.x+.5)*cell,fy=(food.y+.5)*cell,glow=cell*(.29+.035*Math.sin(t*5));
    const grd=ctx.createRadialGradient(fx,fy,1,fx,fy,cell*.75);grd.addColorStop(0,'#ff857b65');grd.addColorStop(1,'#ff635000');ctx.fillStyle=grd;ctx.beginPath();ctx.arc(fx,fy,cell*.75,0,7);ctx.fill();
    ctx.fillStyle='#ff716c';ctx.beginPath();ctx.arc(fx,fy,glow,0,7);ctx.fill();ctx.fillStyle='#ffc0a4';ctx.beginPath();ctx.arc(fx-cell*.08,fy-cell*.09,cell*.085,0,7);ctx.fill();
    particles=particles.filter(p=>p.life>0);for(const p of particles){p.x+=p.vx*.015;p.y+=p.vy*.015;p.life-=.035;ctx.globalAlpha=p.life;ctx.fillStyle='#c2ff91';ctx.beginPath();ctx.arc(p.x*cell,p.y*cell,cell*.07,0,7);ctx.fill()}ctx.globalAlpha=1;
    snake.forEach((s,i)=>{
      const pad=cell*.09,x=s.x*cell+pad,y=s.y*cell+pad,size=cell-pad*2;
      ctx.fillStyle=i===0?'#b5ff82':`hsl(${103-i*1.35} 68% ${59-i*.27}%)`;
      ctx.beginPath();ctx.roundRect(x,y,size,size,cell*.28);ctx.fill();
      if(i===0){
        const forward=dir,side={x:-dir.y,y:dir.x};
        for(const sign of [-1,1]){
          const ex=(s.x+.5+forward.x*.21+side.x*.19*sign)*cell,ey=(s.y+.5+forward.y*.21+side.y*.19*sign)*cell;
          ctx.fillStyle='#17221a';ctx.beginPath();ctx.arc(ex,ey,cell*.075,0,7);ctx.fill();
          ctx.fillStyle='#f4ffe9';ctx.beginPath();ctx.arc(ex-forward.x*cell*.02,ey-forward.y*cell*.02,cell*.025,0,7);ctx.fill();
        }
      }
    });
  }
  function frame(now){const dt=Math.min(now-last,60);last=now;if(!paused&&!dead){acc+=dt;if(acc>=stepMs){tick();acc%=stepMs}}draw();requestAnimationFrame(frame)}
  reset(true);requestAnimationFrame(frame);
})();
</script>
</body>
</html>
Reasoning trace (211 tokens)
**Designing game demo features**

I need to create a game demo that autoplays behind a message. The canvas will be centered with a 26x26 grid, and attractive controls should maintain fast legal presses. The AI demo will start autoplaying when a call-to-action is clicked, and on the first click, it may reset the game. I want the demo overlay message visible for at least three seconds. There are various considerations, like responsive design and ensuring smooth gameplay, with clear instructions for users.