Train snakeOne-line
GPT-6.1 Terra
by OpenAIReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 1 min 5 s
- Cost
- $0.027
- Output tokens
- 5,296
- Spent thinking
- 219 tokens
- Speed
- 92.3 tok/s
- Console errors
- 0
- First token after
- 7.2 s
- First visible text after
- 7.2 s
- Prompt tokens
- 361
- Code size
- 14.3 KB
- Finish reason
- stop
- Served by
- OpenAI
- Model id
openai/gpt-6.1-terra- Reasoning sent
{"effort":"low"}- Max output
- 128,000 tokens
- Generated
- Nov 12, 2026
What it was asked
The prompt
“make me a snake game where the snake is a little train with a locomotive and colorful wagons, picking up passengers waiting on the platform”
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 · 209 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Platform Express</title>
<style>
@import url('data:text/css,');
*{box-sizing:border-box}
:root{color-scheme:dark;--ink:#f8f4e7;--muted:#a9b7b7;--lime:#d9ed91;--orange:#f7ac6c}
body{margin:0;background:#101b1c;color:var(--ink);font-family:ui-rounded,"Trebuchet MS",system-ui,sans-serif}
body:before{content:"";position:fixed;inset:0;background:radial-gradient(circle at 15% 0%,#29433a 0,transparent 33%),radial-gradient(circle at 92% 80%,#243c35 0,transparent 30%);pointer-events:none}
.wrap{position:relative;max-width:1280px;margin:auto;padding:26px 38px 22px}
header{display:flex;align-items:center;justify-content:space-between;margin-bottom:23px}
.brand{display:flex;align-items:center;gap:12px}
.brand-icon{width:43px;height:43px;background:var(--lime);border-radius:13px;display:grid;place-items:center;color:#21392b;font-size:24px}
.brand-name{font-weight:900;letter-spacing:-.04em;font-size:21px;line-height:1}
.brand-sub{font-size:10px;letter-spacing:.19em;text-transform:uppercase;color:#9eafa8;margin-top:5px}
.top-tag{font-size:11px;letter-spacing:.13em;text-transform:uppercase;color:#aec0b6;border:1px solid #40544a;border-radius:30px;padding:9px 13px}
.layout{display:grid;grid-template-columns:minmax(0,1fr) 252px;gap:23px}
.game-area{min-width:0}
.title-row{display:flex;align-items:end;justify-content:space-between;gap:15px;margin-bottom:17px}
.eyebrow{font-size:10px;text-transform:uppercase;letter-spacing:.2em;color:#c9df91;font-weight:800;margin-bottom:7px}
h1{font-size:clamp(27px,3vw,38px);letter-spacing:-.055em;line-height:1;margin:0;font-weight:900}
.subtitle{color:#a8b9b1;font-size:13px;margin:7px 0 0}
.live{display:flex;align-items:center;gap:7px;color:#b5cbbd;font-size:11px;white-space:nowrap;padding-bottom:4px}
.dot{width:7px;height:7px;background:#bfdf84;border-radius:50%;box-shadow:0 0 12px #b5ea7b}
.board-shell{background:#243a31;border:1px solid #496052;border-radius:16px;padding:7px;box-shadow:0 16px 45px #07110d55}
.board{position:relative;overflow:hidden;border-radius:10px;background:#1b3028;aspect-ratio:3/2}
canvas{width:100%;height:100%;display:block}
.start-banner{position:absolute;bottom:16px;left:50%;transform:translateX(-50%);background:#f2f1dc;color:#26382b;border-radius:9px;padding:10px 18px;box-shadow:0 5px 20px #09140db0;text-align:center;white-space:nowrap;cursor:pointer;font-size:12px;font-weight:900}
.start-banner small{display:block;color:#768171;font-size:9px;letter-spacing:.09em;text-transform:uppercase;margin-top:3px}
.board-bottom{display:flex;justify-content:space-between;color:#80988a;font-size:10px;letter-spacing:.09em;text-transform:uppercase;padding:11px 4px 0}
aside{padding-top:2px}
.ticket{background:#e9ead7;color:#253b2d;border-radius:14px;overflow:hidden;box-shadow:0 10px 30px #09140d44}
.ticket-head{padding:20px 20px 16px;border-bottom:1px dashed #abb7a2}
.ticket-label{font-size:10px;letter-spacing:.18em;font-weight:900;color:#6a8069;text-transform:uppercase}
.ticket h2{font-size:23px;letter-spacing:-.05em;margin:8px 0 3px}
.ticket p{font-size:12px;line-height:1.5;color:#748171;margin:0}
.stats{display:grid;grid-template-columns:1fr 1fr;padding:18px 20px;gap:8px}
.stat-label{font-size:9px;letter-spacing:.13em;text-transform:uppercase;color:#7d8c7c;font-weight:bold}
.stat-value{font-size:30px;font-weight:900;letter-spacing:-.05em;line-height:1.15;margin-top:5px}
.ticket-foot{background:#d9e1c8;padding:11px 20px;display:flex;justify-content:space-between;align-items:center;font-size:10px;color:#61765e;font-weight:800;letter-spacing:.1em}
.mini-train{font-size:19px;letter-spacing:0}
.side-block{border:1px solid #405349;border-radius:14px;padding:18px 19px;margin-top:14px;background:#21332c99}
.side-title{font-size:10px;letter-spacing:.17em;color:#a5b9a9;font-weight:800;text-transform:uppercase;margin-bottom:14px}
.instruction{display:flex;gap:11px;align-items:flex-start;margin:13px 0;color:#c1cec1;font-size:12px;line-height:1.4}
.instruction .icon{width:27px;height:27px;flex:none;border-radius:7px;background:#354b3d;display:grid;place-items:center;font-size:14px}
.instruction strong{color:#f1f2dc;display:block;font-size:12px}
.keys{display:flex;gap:4px;margin-top:14px}
kbd{font:700 11px system-ui;background:#344a3d;color:#e0ead8;border:1px solid #506756;border-bottom-width:3px;border-radius:5px;min-width:27px;text-align:center;padding:5px}
.or{font-size:10px;color:#91a596;align-self:center;margin:0 5px}
button{width:100%;border:1px solid #566b59;background:transparent;color:#d7e1ce;border-radius:9px;padding:11px;font:700 12px inherit;cursor:pointer;margin-top:14px}
button:hover{background:#344a3b}
.footer{display:flex;justify-content:space-between;margin-top:20px;font-size:10px;color:#728a7c;letter-spacing:.08em;text-transform:uppercase}
@media(max-width:800px){.wrap{padding:20px 16px}.layout{grid-template-columns:1fr}.title-row{margin-top:4px}aside{display:grid;grid-template-columns:1fr 1fr;gap:12px}.side-block{margin:0}.footer{margin-top:15px}}
@media(max-width:480px){.top-tag{display:none}.brand-name{font-size:19px}.subtitle{font-size:12px}.live{display:none}.start-banner{font-size:10px;bottom:8px;padding:7px 12px}.board-bottom{font-size:8px}aside{grid-template-columns:1fr}.side-block{padding:15px}.instruction{margin:8px 0}.footer span:last-child{display:none}}
</style>
</head>
<body>
<div class="wrap">
<header>
<div class="brand"><div class="brand-icon">▰</div><div><div class="brand-name">platform express</div><div class="brand-sub">A little journey, a lot of joy</div></div></div>
<div class="top-tag">✦ The scenic route ✦</div>
</header>
<main class="layout">
<section class="game-area">
<div class="title-row"><div><div class="eyebrow">All aboard! / No. 01</div><h1>Next stop: everywhere.</h1><p class="subtitle">Pick up passengers, grow your train, and enjoy the ride.</p></div><div class="live"><span class="dot"></span><span id="status">AUTOPILOT IS ON</span></div></div>
<div class="board-shell"><div class="board"><canvas id="game" width="900" height="600"></canvas><div class="start-banner" id="banner">Click or press a key to start<small>You're watching the train take a little test drive</small></div></div></div>
<div class="board-bottom"><span>✳ A railway adventure</span><span>Mind the tracks • Enjoy the journey</span></div>
</section>
<aside>
<div class="ticket">
<div class="ticket-head"><div class="ticket-label">✦ Your journey ticket</div><h2>All aboard!</h2><p>There's always room for one more.</p></div>
<div class="stats"><div><div class="stat-label">Passengers</div><div class="stat-value" id="score">00</div></div><div><div class="stat-label">Train cars</div><div class="stat-value" id="cars">04</div></div></div>
<div class="ticket-foot"><span>ONE WAY · ADVENTURE</span><span class="mini-train">▰ ▰ ▰</span></div>
</div>
<div class="side-block"><div class="side-title">The conductor's guide</div>
<div class="instruction"><span class="icon">☺</span><div><strong>Pick up passengers</strong>Find the folks waiting at the platforms.</div></div>
<div class="instruction"><span class="icon">✦</span><div><strong>Keep on track</strong>Don't run into the edge or your own train.</div></div>
<div class="keys"><kbd>↑</kbd><kbd>←</kbd><kbd>↓</kbd><kbd>→</kbd><span class="or">or</span><kbd>W</kbd><kbd>A</kbd><kbd>S</kbd><kbd>D</kbd></div>
</div>
<button id="restart">↻ Restart journey</button>
</aside>
</main>
<div class="footer"><span>Made for the long way around</span><span>Take your time. Enjoy the view. ✳</span></div>
</div>
<script>
const canvas=document.getElementById('game'),ctx=canvas.getContext('2d');
const banner=document.getElementById('banner'),statusEl=document.getElementById('status');
const W=18,H=12,S=50;
let train,dir,nextDir,passengers,score,demo=true,ended=false,last=0,steps=0;
const colors=['#f2b15e','#e97968','#91b7a5','#d6bd77','#aa9bc7','#eb8f79','#8bbac3'];
function init(isDemo){
demo=isDemo;ended=false;score=0;steps=0;
train=[{x:7,y:6},{x:6,y:6},{x:5,y:6},{x:4,y:6}];
dir={x:1,y:0};nextDir={...dir};
passengers=[{x:12,y:3,c:'#f5b86c'},{x:14,y:9,c:'#ef927b'},{x:3,y:2,c:'#9ec9c3'}];
updateUI();draw();
}
function updateUI(){
document.getElementById('score').textContent=String(score).padStart(2,'0');
document.getElementById('cars').textContent=String(train.length).padStart(2,'0');
statusEl.textContent=ended?'JOURNEY COMPLETE':demo?'AUTOPILOT IS ON':'YOU ARE THE CONDUCTOR';
banner.style.display=(demo||ended)?'block':'none';
banner.innerHTML=ended?'End of the line! Click or press a key to ride again<small>Every journey deserves another go</small>':'Click or press a key to start<small>You’re watching the train take a little test drive</small>';
}
function spawn(){
let free=[];for(let y=1;y<H-1;y++)for(let x=1;x<W-1;x++)if(!train.some(a=>a.x===x&&a.y===y)&&!passengers.some(a=>a.x===x&&a.y===y))free.push({x,y});
if(free.length){let p=free[Math.floor(Math.random()*free.length)];p.c=['#f5b86c','#ef927b','#9ec9c3','#d8a6bf'][Math.floor(Math.random()*4)];passengers.push(p)}
}
function auto(){
const head=train[0], blocked=new Set(train.slice(0,-1).map(p=>p.x+','+p.y));
let queue=[{x:head.x,y:head.y,first:null}],seen=new Set([head.x+','+head.y]);
const dirs=[dir,{x:-dir.y,y:dir.x},{x:dir.y,y:-dir.x}];
for(let i=0;i<queue.length;i++){
let a=queue[i];
if(a.first&&passengers.some(p=>p.x===a.x&&p.y===a.y))return a.first;
for(const d of dirs){let x=a.x+d.x,y=a.y+d.y,k=x+','+y;
if(x<0||x>=W||y<0||y>=H||blocked.has(k)||seen.has(k))continue;
seen.add(k);queue.push({x,y,first:a.first||d});
}
}
for(const d of dirs){let x=head.x+d.x,y=head.y+d.y;if(x>=0&&x<W&&y>=0&&y<H&&!blocked.has(x+','+y))return d}
return dir;
}
function tick(){
if(ended)return;
if(demo)nextDir=auto();
dir=nextDir;
const head={x:train[0].x+dir.x,y:train[0].y+dir.y};
const pi=passengers.findIndex(p=>p.x===head.x&&p.y===head.y);
if(head.x<0||head.x>=W||head.y<0||head.y>=H||train.slice(0,pi<0?-1:undefined).some(p=>p.x===head.x&&p.y===head.y)){
if(demo){init(true);return}
ended=true;updateUI();return;
}
train.unshift(head);
if(pi>=0){passengers.splice(pi,1);score++;spawn()}else train.pop();
steps++;updateUI();
}
function round(x,y,w,h,r,fill){ctx.fillStyle=fill;ctx.beginPath();ctx.roundRect(x,y,w,h,r);ctx.fill()}
function draw(){
ctx.fillStyle='#20382d';ctx.fillRect(0,0,900,600);
// Quiet checkerboard and subtle railway-map lines
for(let y=0;y<H;y++)for(let x=0;x<W;x++){
ctx.fillStyle=(x+y)%2?'#233c30':'#263f32';ctx.fillRect(x*S,y*S,S,S);
ctx.strokeStyle='#ffffff08';ctx.strokeRect(x*S+.5,y*S+.5,S,S);
}
// decorative landscape
const shrubs=[[1,1],[9,1],[16,1],[2,5],[15,5],[1,10],[8,10],[16,10],[11,7]];
shrubs.forEach(([x,y],i)=>{let px=x*S+13,py=y*S+17;ctx.fillStyle='#496951';ctx.beginPath();ctx.arc(px,py,3,0,7);ctx.arc(px+8,py-3,4,0,7);ctx.arc(px+14,py+2,3,0,7);ctx.fill();ctx.fillStyle='#8ca47a';ctx.fillRect(px+5,py+7,2,2)});
// Platform tiles and waiting passengers
passengers.forEach((p,i)=>{
let x=p.x*S,y=p.y*S;
round(x+3,y+4,44,42,6,'#b6b49a');round(x+6,y+7,38,36,4,'#dedbc1');
ctx.fillStyle='#a5a48c';for(let j=0;j<5;j++)ctx.fillRect(x+8+j*7,y+38,4,2);
ctx.fillStyle='#c5aa75';ctx.fillRect(x+8,y+9,34,2);
// shadow, body, head and hair
ctx.fillStyle='#61705c55';ctx.beginPath();ctx.ellipse(x+25,y+36,11,4,0,0,7);ctx.fill();
round(x+19,y+22,12,14,4,p.c);
ctx.fillStyle='#4d5147';ctx.fillRect(x+20,y+33,3,4);ctx.fillRect(x+27,y+33,3,4);
ctx.fillStyle='#f4ceaa';ctx.beginPath();ctx.arc(x+25,y+17,6,0,7);ctx.fill();
ctx.fillStyle=i%2?'#735044':'#514e43';ctx.beginPath();ctx.arc(x+25,y+15,6,Math.PI,Math.PI*2);ctx.fill();
ctx.fillStyle='#f7e9ba';ctx.beginPath();ctx.arc(x+39,y+13,2,0,7);ctx.fill();
});
// connections between cars
ctx.strokeStyle='#a9b1a0';ctx.lineWidth=5;ctx.lineCap='round';ctx.beginPath();
train.forEach((p,i)=>{let x=p.x*S+25,y=p.y*S+25;if(i===0)ctx.moveTo(x,y);else ctx.lineTo(x,y)});ctx.stroke();
train.forEach((p,i)=>{
let d=i===0?dir:{x:train[i-1].x-p.x,y:train[i-1].y-p.y};
if(Math.abs(d.x)+Math.abs(d.y)!==1)d={x:1,y:0};
ctx.save();ctx.translate(p.x*S+25,p.y*S+25);ctx.rotate(Math.atan2(d.y,d.x));
// wheels
round(-17,-20,12,5,2,'#17251e');round(6,-20,12,5,2,'#17251e');round(-17,15,12,5,2,'#17251e');round(6,15,12,5,2,'#17251e');
if(i===0){
round(-21,-15,42,30,7,'#c96751');round(-19,-13,38,26,6,'#eb8a6b');
round(-18,-12,14,24,4,'#f8c68f');round(-15,-9,8,18,2,'#527c72');
round(0,-10,17,20,5,'#d76e58');round(4,-6,8,12,4,'#3b4c3f');
round(17,-10,5,20,2,'#f3c276');
ctx.fillStyle='#fff0bd';ctx.beginPath();ctx.arc(21,0,3,0,7);ctx.fill();
round(-20,-2,3,4,1,'#e8d29e');
}else{
let color=colors[(i-1)%colors.length];round(-20,-15,40,30,6,'#526357');round(-19,-14,38,28,6,color);
round(-14,-10,28,20,4,'#f4dfb8');round(-11,-8,22,16,3,'#52786e');
ctx.fillStyle='#d0e3c9';ctx.fillRect(-2,-8,3,16);
ctx.fillStyle='#ffffff3d';ctx.fillRect(-10,-7,5,3);ctx.fillRect(3,-7,5,3);
round(-18,-13,36,3,2,'#ffffff40');
}
ctx.restore();
});
// little map details
ctx.fillStyle='#a7bb9a';ctx.font='bold 9px system-ui';ctx.letterSpacing='2px';ctx.fillText('NORTH',22,28);ctx.letterSpacing='0px';
ctx.strokeStyle='#9cb398';ctx.lineWidth=1;ctx.beginPath();ctx.moveTo(25,39);ctx.lineTo(25,52);ctx.moveTo(21,43);ctx.lineTo(25,38);ctx.lineTo(29,43);ctx.stroke();
}
function start(){if(demo||ended)init(false)}
banner.addEventListener('click',start);
canvas.addEventListener('click',start);
document.getElementById('restart').addEventListener('click',()=>init(false));
window.addEventListener('keydown',e=>{
const map={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}};
let d=map[e.key]||map[e.key.toLowerCase()];
if(d||e.key===' '){e.preventDefault();if(demo||ended){start();if(d&&!(d.x===-dir.x&&d.y===-dir.y))nextDir=d;return}if(d&&!(d.x===-dir.x&&d.y===-dir.y))nextDir=d}
else if(demo||ended)start();
});
function loop(t){if(t-last>180){tick();last=t}draw();requestAnimationFrame(loop)}
init(true);requestAnimationFrame(loop);
</script>
</body>
</html>