GPT-6.1 Sol
by OpenAIreasoning defaultClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 1 min 32 s
- Cost
- $0.064
- Output tokens
- 6,309
- Spent thinking
- 838 tokens
- Speed
- 76.2 tok/s
- Console errors
- 0
- First token after
- 9.6 s
- First visible text after
- 32.4 s
- Prompt tokens
- 493
- Code size
- 16.4 KB
- Finish reason
- stop
- Served by
- OpenAI
- Model id
openai/gpt-6.1-sol- Reasoning sent
model default- Max output
- 128,000 tokens
- Generated
- Nov 12, 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 · 260 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Snake — A little less scrolling.</title>
<style>
:root{color-scheme:dark;--bg:#0b1312;--panel:#121e1b;--line:#263630;--text:#edf5e9;--muted:#81958b;--green:#bcf578}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--text);font-family:Arial,Helvetica,sans-serif;min-height:100vh;background-image:radial-gradient(ellipse at 35% 40%,#17272088,transparent 65%)}
button{font:inherit;cursor:pointer}
button:focus-visible,canvas:focus-visible{outline:2px solid var(--green);outline-offset:5px}
.page{max-width:1000px;margin:auto;padding:34px 28px 22px}
header{display:flex;align-items:center;justify-content:space-between;margin-bottom:32px}
.brand{display:flex;align-items:center;gap:12px;font-size:23px;font-weight:800;letter-spacing:-1px}
.mark{width:33px;height:33px;border:1px solid #455d3c;border-radius:10px;display:grid;place-items:center;background:#bcf5780c}
.mark svg{width:23px;height:23px}
.brand span:last-child{color:var(--green)}
.edition{font-size:10px;letter-spacing:2px;color:var(--muted);display:flex;align-items:center;gap:9px}
.dot{width:6px;height:6px;border-radius:50%;background:var(--green);box-shadow:0 0 12px #bcf57855;display:inline-block}
main{display:grid;grid-template-columns:minmax(0,592px) minmax(230px,1fr);gap:32px;align-items:start}
.board-wrap{border:1px solid #334238;border-radius:17px;background:#101b17;overflow:hidden;box-shadow:0 18px 70px #0004}
.board-bar{height:43px;display:flex;justify-content:space-between;align-items:center;padding:0 17px;border-bottom:1px solid #26352b;font-size:10px;letter-spacing:1.7px;color:#91a38e}
.mode{display:flex;gap:7px;align-items:center;color:#bcf578;font-size:9px;letter-spacing:1.3px}
.mode .dot{width:5px;height:5px}
.stage{position:relative;aspect-ratio:1}
canvas{display:block;width:100%;height:100%;touch-action:none}
.invite{position:absolute;bottom:24px;left:50%;transform:translateX(-50%);white-space:nowrap;padding:12px 18px;border:1px solid #506144;border-radius:10px;background:#152019ed;color:#e0ecd7;font-size:12px;box-shadow:0 6px 25px #0004;cursor:pointer}
.invite span{color:var(--green);margin-right:8px}
.overlay{position:absolute;inset:0;background:#0b1612b8;backdrop-filter:blur(5px);display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:24px}
.overlay[hidden],.invite[hidden]{display:none}
.overlay .eyebrow{color:var(--green);margin-bottom:15px}
.overlay h2{font-size:42px;letter-spacing:-2px;margin:0 0 12px}
.overlay p{color:#a7b5a6;font-size:14px;margin:0 0 24px}
.overlay button{min-width:180px}
.below-board{display:flex;justify-content:space-between;padding:15px 3px;font-size:10px;color:#728779;letter-spacing:.7px}
.below-board span{display:flex;gap:7px;align-items:center}
.food-dot{display:inline-block;width:6px;height:6px;background:#f6a190;border-radius:50%}
.side{padding-top:5px}
.eyebrow{font-size:10px;font-weight:600;letter-spacing:2px;color:var(--muted)}
h1{font-size:43px;line-height:1.07;letter-spacing:-2px;font-weight:500;margin:15px 0}
h1 em{font-style:normal;color:var(--green)}
.intro{font-size:13px;color:#93a397;line-height:1.7;margin:0 0 25px;max-width:250px}
.scores{display:grid;grid-template-columns:1fr 1fr;border:1px solid var(--line);border-radius:12px;background:#17211a88;margin-bottom:20px}
.score{padding:17px 15px}
.score+.score{border-left:1px solid var(--line)}
.score label{display:block;color:var(--muted);font-size:9px;letter-spacing:1.3px;margin-bottom:8px}
.score strong{font-size:37px;font-weight:500;letter-spacing:-1px;font-variant-numeric:tabular-nums}
.score:first-child strong{color:var(--green)}
.primary{border:0;border-radius:8px;background:var(--green);color:#17220f;padding:14px 18px;font-size:12px;font-weight:700;transition:background .2s,transform .2s}
.primary:hover{background:#d0ff99;transform:translateY(-1px)}
.actions{display:flex;gap:8px;margin-bottom:27px}
.actions .primary{flex:1;display:flex;align-items:center;justify-content:space-between}
.secondary{border:1px solid #354638;border-radius:8px;background:#17211b;color:#c9d8c4;width:45px;display:grid;place-items:center;font-size:15px}
.secondary:hover{background:#243325}
.controls{border-top:1px solid var(--line);padding-top:22px}
.control-row{display:flex;align-items:center;justify-content:space-between;margin-top:14px;color:#9bad9e;font-size:11px}
.keys{display:flex;gap:4px;align-items:center;color:#617466}
kbd{font-family:inherit;font-size:10px;min-width:22px;height:23px;padding:4px 5px;display:inline-flex;align-items:center;justify-content:center;border:1px solid #364438;border-bottom:2px solid #455442;border-radius:4px;background:#1a251d;color:#c9d4c3}
.key-set{display:flex;gap:3px}
.tip{font-size:11px;line-height:1.8;color:#718578;margin-top:23px}
.tip b{color:#b6c4ad;font-weight:400}
footer{border-top:1px solid #25332a;margin-top:15px;padding-top:19px;display:flex;justify-content:space-between;font-size:9px;letter-spacing:1.6px;color:#617768}
footer span:last-child{letter-spacing:.4px;color:#91a18e}
@media(max-width:720px){.page{max-width:570px;padding:23px 18px}header{margin-bottom:23px}.edition{font-size:8px;letter-spacing:1px}main{grid-template-columns:1fr;gap:15px}.side{display:grid;grid-template-columns:1fr 1fr;gap:0 16px}.side>.eyebrow,.intro,.tip{display:none}h1{font-size:29px;grid-column:1;margin:8px 0 18px;letter-spacing:-1px}.scores{grid-column:2;grid-row:1/3;margin:4px 0 16px}.score{padding:12px}.score strong{font-size:30px}.actions{grid-column:1;margin-bottom:0}.controls{grid-column:1/-1;margin-top:20px;display:flex;flex-wrap:wrap;gap:12px 20px;padding-top:15px}.controls>.eyebrow{width:100%}.control-row{margin-top:0;gap:10px}.control-row:nth-child(2){flex:1}.below-board{font-size:9px}footer{margin-top:24px;font-size:8px}.invite{font-size:11px;padding:11px 12px;bottom:18px}}
@media(prefers-reduced-motion:reduce){button{transition:none!important}}
</style>
</head>
<body>
<div class="page">
<header>
<div class="brand"><span class="mark"><svg viewBox="0 0 24 24" fill="none"><path d="M6 17h9a3 3 0 0 0 0-6H9a3 3 0 0 1 0-6h9" stroke="#bcf578" stroke-width="4" stroke-linecap="round"/><circle cx="17.5" cy="4.5" r=".8" fill="#17220f"/></svg></span>snake<span>.</span></div>
<div class="edition"><span class="dot"></span> THE CLASSIC, REIMAGINED</div>
</header>
<main>
<section>
<div class="board-wrap">
<div class="board-bar"><span>THE PLAYFIELD</span><span class="mode" id="mode"><i class="dot"></i> AUTOPILOT</span></div>
<div class="stage">
<canvas id="game" width="1152" height="1152" tabindex="0" aria-label="Snake game. Use arrow keys or WASD to move. P to pause."></canvas>
<div class="invite" id="invite"><span>↳</span> Click or press a key to start</div>
<div class="overlay" id="overlay" hidden>
<div class="eyebrow" id="overlayLabel">TAKE A BREATHER</div>
<h2 id="overlayTitle">On pause.</h2>
<p id="overlayText">Your next move can wait.</p>
<button class="primary" id="overlayButton">Resume game →</button>
</div>
</div>
</div>
<div class="below-board"><span><i class="food-dot"></i> EVERY BITE, +10 POINTS</span><span>24 × 24 GRID</span></div>
</section>
<aside class="side">
<div class="eyebrow">A LITTLE LESS SCROLLING.</div>
<h1>A little more<br><em>snake.</em></h1>
<p class="intro">Find your rhythm. Follow the food.<br>Try not to become your own worst enemy.</p>
<div class="scores">
<div class="score"><label>SCORE</label><strong id="score">00</strong></div>
<div class="score"><label>SESSION BEST</label><strong id="best">00</strong></div>
</div>
<div class="actions"><button class="primary" id="start"><span id="startText">Let's play</span><span>↗</span></button><button class="secondary" id="pause" aria-label="Pause game" title="Pause (P)">Ⅱ</button></div>
<div class="controls">
<div class="eyebrow">MAKE YOUR MOVE</div>
<div class="control-row"><span>Steer</span><div class="keys"><div class="key-set"><kbd>↑</kbd><kbd>←</kbd><kbd>↓</kbd><kbd>→</kbd></div><span>/</span><div class="key-set"><kbd>W</kbd><kbd>A</kbd><kbd>S</kbd><kbd>D</kbd></div></div></div>
<div class="control-row"><span>Pause</span><kbd>P</kbd></div>
<div class="control-row"><span>Restart</span><div class="keys"><kbd>space</kbd><span>/</span><kbd>↵</kbd></div></div>
</div>
<p class="tip"><b>A friendly reminder</b><br>The walls don't bend. Neither do the rules.</p>
</aside>
</main>
<footer><span>BUILT FOR THE JOY OF IT.</span><span>No rush. Just one more round.</span></footer>
</div>
<script>
(()=>{
const canvas=document.getElementById('game'),ctx=canvas.getContext('2d');
const $=id=>document.getElementById(id);
const N=24,S=24,STEP=125;
let snake,previous,dir,queue,food,score=0,best=0,state='demo',acc=0,last=0,particles=[],eatFlash=0;
const dirs=[{x:1,y:0},{x:0,y:1},{x:-1,y:0},{x:0,y:-1}];
const eq=(a,b)=>a.x===b.x&&a.y===b.y;
function stats(){$('score').textContent=String(score).padStart(2,'0');$('best').textContent=String(best).padStart(2,'0')}
function mode(){
$('mode').innerHTML='<i class="dot"></i> '+({demo:'AUTOPILOT',playing:'IN THE FLOW',paused:'PAUSED',over:'GAME OVER'}[state]);
$('invite').hidden=state!=='demo';
$('startText').textContent=state==='demo'?"Let's play":'New game';
$('pause').textContent=state==='paused'?'▶':'Ⅱ';
$('pause').setAttribute('aria-label',state==='paused'?'Resume game':'Pause game');
}
function reset(demo=false){
state=demo?'demo':'playing';score=0;queue=[];dir={x:1,y:0};particles=[];acc=0;
snake=Array.from({length:8},(_,i)=>({x:10-i,y:12}));
previous=snake.map(p=>({...p}));food={x:17,y:9};eatFlash=0;
$('overlay').hidden=true;stats();mode();
}
function spawnFood(){
const free=[];
for(let y=0;y<N;y++)for(let x=0;x<N;x++)if(!snake.some(p=>p.x===x&&p.y===y))free.push({x,y});
if(!free.length){finish(true);return}
if(state==='demo'){
const near=free.filter(p=>Math.abs(p.x-snake[0].x)+Math.abs(p.y-snake[0].y)>=4&&Math.abs(p.x-snake[0].x)+Math.abs(p.y-snake[0].y)<=8);
food=(near.length?near:free)[Math.floor(Math.random()*(near.length||free.length))];
}else food=free[Math.floor(Math.random()*free.length)];
}
function autopilot(){
const head=snake[0],blocked=new Set(snake.slice(0,-1).map(p=>p.x+','+p.y));
const nodes=[{...head,first:null}],seen=new Set([head.x+','+head.y]);
for(let i=0;i<nodes.length;i++){
const a=nodes[i];
if(eq(a,food)&&a.first)return a.first;
for(const d of dirs){
if(i===0&&d.x===-dir.x&&d.y===-dir.y)continue;
const b={x:a.x+d.x,y:a.y+d.y,first:a.first||d},key=b.x+','+b.y;
if(b.x<0||b.y<0||b.x>=N||b.y>=N||blocked.has(key)||seen.has(key))continue;
seen.add(key);nodes.push(b);
}
}
return dirs.find(d=>!(d.x===-dir.x&&d.y===-dir.y)&&head.x+d.x>=0&&head.x+d.x<N&&head.y+d.y>=0&&head.y+d.y<N&&!snake.slice(0,-1).some(p=>p.x===head.x+d.x&&p.y===head.y+d.y))||dir;
}
function burst(p){
for(let i=0;i<18;i++){
const a=Math.random()*Math.PI*2,v=35+Math.random()*65;
particles.push({x:(p.x+.5)*S,y:(p.y+.5)*S,vx:Math.cos(a)*v,vy:Math.sin(a)*v,life:.4+Math.random()*.35,max:.75,r:1+Math.random()*2,color:i%3?'#c3f78a':'#ffb09b'});
}
}
function tick(){
previous=snake.map(p=>({...p}));
if(state==='demo')dir=autopilot();else if(queue.length)dir=queue.shift();
const head={x:snake[0].x+dir.x,y:snake[0].y+dir.y},eating=eq(head,food);
if(head.x<0||head.y<0||head.x>=N||head.y>=N||snake.slice(0,eating?snake.length:snake.length-1).some(p=>eq(p,head))){
if(state==='demo'){reset(true);return}finish();return;
}
snake.unshift(head);
if(eating){score+=10;best=Math.max(best,score);stats();burst(food);eatFlash=1;spawnFood()}else snake.pop();
}
function finish(win=false){
state='over';mode();$('overlay').hidden=false;
$('overlayLabel').textContent=win?'INCREDIBLE RUN':'THAT’S A WRAP';
$('overlayTitle').textContent=win?'Full house.':'One more round?';
$('overlayText').textContent='You scored '+score+' points. Best this session: '+best+'.';
$('overlayButton').textContent='Play again →';
}
function pause(){
if(state==='demo'){reset();return}
if(state==='over')return;
state=state==='paused'?'playing':'paused';acc=0;previous=snake.map(p=>({...p}));mode();
$('overlay').hidden=state!=='paused';
$('overlayLabel').textContent='TAKE A BREATHER';$('overlayTitle').textContent='On pause.';
$('overlayText').textContent='Your next move can wait.';$('overlayButton').textContent='Resume game →';
}
function start(){reset();canvas.focus({preventScroll:true})}
$('start').onclick=start;
$('pause').onclick=pause;
$('overlayButton').onclick=()=>state==='paused'?pause():start();
$('invite').onclick=start;
canvas.onclick=()=>{if(state==='demo'||state==='over')start();else if(state==='paused')pause()};
const mappings={ArrowUp:{x:0,y:-1},w:{x:0,y:-1},ArrowDown:{x:0,y:1},s:{x:0,y:1},ArrowLeft:{x:-1,y:0},a:{x:-1,y:0},ArrowRight:{x:1,y:0},d:{x:1,y:0}};
document.addEventListener('keydown',e=>{
if(e.ctrlKey||e.metaKey||e.altKey||e.key==='Tab')return;
const key=e.key.length===1?e.key.toLowerCase():e.key;
if(mappings[key]||[' ','Enter','p'].includes(key))e.preventDefault();
if(e.repeat)return;
if(state==='demo'){start();if(!mappings[key])return}
if(key===' '||key==='Enter'){start();return}
if(key==='p'){pause();return}
if(state!=='playing'||!mappings[key])return;
const d=mappings[key],lastDir=queue.length?queue[queue.length-1]:dir;
if(d.x===-lastDir.x&&d.y===-lastDir.y||eq(d,lastDir))return;
queue.push({...d});
});
let touch=null;
canvas.addEventListener('pointerdown',e=>{touch={x:e.clientX,y:e.clientY};canvas.setPointerCapture(e.pointerId)});
canvas.addEventListener('pointerup',e=>{
if(!touch)return;const dx=e.clientX-touch.x,dy=e.clientY-touch.y;touch=null;
if(Math.max(Math.abs(dx),Math.abs(dy))<15)return;
if(state==='demo')start();
const d=Math.abs(dx)>Math.abs(dy)?{x:Math.sign(dx),y:0}:{x:0,y:Math.sign(dy)};
const lastDir=queue.length?queue[queue.length-1]:dir;
if(state==='playing'&&!(d.x===-lastDir.x&&d.y===-lastDir.y)&&!eq(d,lastDir))queue.push(d);
});
function draw(alpha,time,dt){
ctx.setTransform(2,0,0,2,0,0);ctx.clearRect(0,0,576,576);
ctx.fillStyle='#101c17';ctx.fillRect(0,0,576,576);
ctx.strokeStyle='#203026';ctx.lineWidth=.5;ctx.beginPath();
for(let i=1;i<N;i++){ctx.moveTo(i*S,0);ctx.lineTo(i*S,576);ctx.moveTo(0,i*S);ctx.lineTo(576,i*S)}ctx.stroke();
// Soft, luminous fruit.
const fx=(food.x+.5)*S,fy=(food.y+.5)*S,pulse=1+Math.sin(time/230)*.06;
const glow=ctx.createRadialGradient(fx,fy,2,fx,fy,28);glow.addColorStop(0,'#ef9d8030');glow.addColorStop(1,'#ef9d8000');
ctx.fillStyle=glow;ctx.fillRect(fx-28,fy-28,56,56);
ctx.save();ctx.translate(fx,fy);ctx.scale(pulse,pulse);
ctx.fillStyle='#f2a18b';ctx.beginPath();ctx.arc(0,1,6.8,0,Math.PI*2);ctx.fill();
ctx.fillStyle='#ffd0b8';ctx.beginPath();ctx.arc(-2,-1,2,0,Math.PI*2);ctx.fill();
ctx.strokeStyle='#9fbd78';ctx.lineWidth=2;ctx.lineCap='round';ctx.beginPath();ctx.moveTo(1,-5);ctx.quadraticCurveTo(2,-10,6,-9);ctx.stroke();ctx.restore();
const points=snake.map((p,i)=>{const old=previous[i]||previous[previous.length-1]||p;return {x:(old.x+(p.x-old.x)*alpha+.5)*S,y:(old.y+(p.y-old.y)*alpha+.5)*S}});
ctx.lineCap='round';ctx.lineJoin='round';
ctx.shadowColor='#9fe46a24';ctx.shadowBlur=14;
for(let i=points.length-1;i>0;i--){
const a=points[i],b=points[i-1],t=1-i/points.length;
ctx.strokeStyle=`rgb(${Math.round(103+t*86)},${Math.round(153+t*87)},${Math.round(75+t*42)})`;
ctx.lineWidth=15.5;ctx.beginPath();ctx.moveTo(a.x,a.y);ctx.lineTo(b.x,b.y);ctx.stroke();
}
ctx.shadowBlur=0;
const h=points[0];ctx.save();ctx.translate(h.x,h.y);ctx.rotate(Math.atan2(dir.y,dir.x));
ctx.fillStyle=eatFlash>0?'#d9ffa7':'#c4f58a';ctx.beginPath();ctx.roundRect(-10,-9,21,18,7);ctx.fill();
ctx.fillStyle='#1b3521';for(const y of [-4.4,4.4]){ctx.beginPath();ctx.arc(4.2,y,2.25,0,Math.PI*2);ctx.fill();ctx.fillStyle='#f0ffe3';ctx.beginPath();ctx.arc(4.9,y-.5,.7,0,Math.PI*2);ctx.fill();ctx.fillStyle='#1b3521'}ctx.restore();
if(state!=='paused'){
eatFlash=Math.max(0,eatFlash-dt*3);
particles=particles.filter(p=>p.life>0);
particles.forEach(p=>{p.life-=dt;p.x+=p.vx*dt;p.y+=p.vy*dt;p.vx*=Math.pow(.2,dt);p.vy*=Math.pow(.2,dt);ctx.globalAlpha=Math.max(0,p.life/p.max);ctx.fillStyle=p.color;ctx.beginPath();ctx.arc(p.x,p.y,p.r,0,Math.PI*2);ctx.fill()});
ctx.globalAlpha=1;
}
}
function frame(t){
const elapsed=last?Math.min(t-last,100):0;last=t;
if(state==='playing'||state==='demo'){acc+=elapsed;while(acc>=STEP){acc-=STEP;tick();if(state!=='playing'&&state!=='demo')break}}
draw(state==='playing'||state==='demo'?acc/STEP:1,t,elapsed/1000);requestAnimationFrame(frame);
}
reset(true);requestAnimationFrame(frame);
})();
</script>
</body>
</html>Reasoning trace (838 tokens)
**Designing layout for snake game** I need to create a polished dark mint version of the snake canvas layout with smooth movement and no reversals for the demo. For the design, I'm thinking about a midnight forest background with a subtle grid, complemented by mint accents. The header should feature a small arcade icon and the title "SNAKE / THE ORIGINAL, REIMAGINED." I’ll also include a central container for the game with specific dimensions and a side panel for stats and controls. Additionally, I want to incorporate overlays for messages and scores.**Developing snake game mechanics** I’m setting up a 24x24 board for the snake game, where the snake starts at a length of 7, positioned near the center, automatically following a path to food using BFS to avoid collisions, updating every 115ms. I will render the snake with thick, rounded lines that create a smooth gradient from dark mint at the tail to bright at the head. The food will be a glowing pink circle shaped like a peach, and I’m considering minimal audio effects to enhance gameplay.**Implementing game controls** I need to add a functional "New Game" button, along with a pause icon at the top of the board. The header should feature a mini row that displays "THE GARDEN" and the dimensions "24 × 24" above the external board. This setup will help clarify the game’s purpose and make the controls accessible for the player. I'll make sure everything is visually appealing while remaining user-friendly!