Train snakeOne-line
GPT-6 Luna
by OpenAIReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 42.8 s
- Cost
- $0.0025
- Output tokens
- 4,903
- Spent thinking
- 185 tokens
- Speed
- 142 tok/s
- Console errors
- 0
- First token after
- 8.2 s
- First visible text after
- 9.4 s
- Prompt tokens
- 361
- Code size
- 13.1 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
“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 · 302 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Little Platform Express</title>
<style>
* { box-sizing: border-box; }
:root {
--ink: #193340;
--muted: #728894;
--cream: #fffaf0;
--teal: #167b78;
--gold: #f2b94b;
}
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
padding: 26px;
overflow-x: hidden;
background:
radial-gradient(ellipse at 50% 0%, #f5e9cf 0, transparent 57%),
#e9e3d5;
color: var(--ink);
font-family: "Trebuchet MS", "Segoe UI", sans-serif;
}
.game {
width: min(100%, 1100px);
background: var(--cream);
border: 1px solid rgba(48, 71, 74, .13);
border-radius: 22px;
overflow: hidden;
box-shadow: 0 24px 70px rgba(54, 58, 46, .16), 0 3px 9px rgba(54, 58, 46, .07);
}
header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;
padding: 22px 29px 19px;
}
.brand { display: flex; align-items: center; gap: 14px; }
.brand-icon {
width: 48px; height: 48px; border-radius: 15px;
display: grid; place-items: center; background: #e3f1e8;
font-size: 27px; box-shadow: inset 0 0 0 1px #d6e8db;
}
.eyebrow {
color: #648273; font-size: 10px; font-weight: 800;
letter-spacing: .19em; text-transform: uppercase; margin-bottom: 4px;
}
h1 { margin: 0; font-size: clamp(20px, 3vw, 28px); letter-spacing: -.045em; line-height: 1; }
.stats { display: flex; gap: 10px; }
.stat {
min-width: 100px; padding: 9px 14px 8px; border-radius: 12px;
background: #f3f1e8; text-align: center;
}
.stat span { display: block; font-size: 9px; letter-spacing: .14em; font-weight: 800; color: #82918b; }
.stat strong { display: block; margin-top: 2px; font-size: 20px; line-height: 1.1; }
.board-wrap { padding: 0 18px 17px; }
.board {
position: relative; overflow: hidden; border-radius: 14px;
background: #dce9dd; border: 1px solid #ceded2;
box-shadow: inset 0 2px 6px rgba(31, 64, 52, .08);
}
canvas { display: block; width: 100%; height: auto; }
.veil {
position: absolute; inset: 0; display: grid; place-items: center;
pointer-events: none;
background: linear-gradient(90deg, rgba(23,49,49,.04), rgba(23,49,49,.22), rgba(23,49,49,.04));
}
.prompt {
text-align: center; color: white; padding: 13px 23px;
border: 1px solid rgba(255,255,255,.38); border-radius: 14px;
background: rgba(24, 55, 56, .72); backdrop-filter: blur(5px);
text-shadow: 0 1px 2px rgba(0,0,0,.2);
box-shadow: 0 8px 22px rgba(0,0,0,.13);
}
.prompt b { display: block; font-size: 17px; letter-spacing: -.02em; }
.prompt small { display: block; margin-top: 4px; color: #d6e7dd; font-size: 11px; }
footer {
display: flex; justify-content: space-between; align-items: center;
gap: 14px; padding: 0 28px 19px; color: var(--muted); font-size: 11px;
}
.legend { display: flex; align-items: center; gap: 8px; }
.dot { width: 8px; height: 8px; display: inline-block; border-radius: 50%; background: #f2a445; box-shadow: 0 0 0 3px #f8e6c9; }
.controls { font-weight: 700; color: #6d817e; }
@media (max-width: 600px) {
body { padding: 12px; }
header { padding: 17px 16px 14px; gap: 10px; }
.brand { gap: 9px; }
.brand-icon { width: 40px; height: 40px; font-size: 23px; border-radius: 12px; }
.stats { gap: 6px; }
.stat { min-width: 62px; padding: 8px 7px; }
.stat span { font-size: 8px; }
.stat strong { font-size: 17px; }
.board-wrap { padding: 0 8px 12px; }
footer { padding: 0 14px 15px; font-size: 10px; }
.controls { text-align: right; }
.prompt { padding: 11px 16px; }
.prompt b { font-size: 15px; }
}
</style>
</head>
<body>
<main class="game">
<header>
<div class="brand">
<div class="brand-icon" aria-hidden="true">🚂</div>
<div>
<div class="eyebrow">A tiny railway adventure</div>
<h1>Little Platform Express</h1>
</div>
</div>
<div class="stats">
<div class="stat"><span>PASSENGERS</span><strong id="score">00</strong></div>
<div class="stat"><span>WAGONS</span><strong id="wagons">02</strong></div>
</div>
</header>
<div class="board-wrap">
<div class="board" id="board">
<canvas id="canvas" aria-label="Train game board"></canvas>
<div class="veil" id="veil"><div class="prompt"><b>Click or press a key to start</b><small>Your little train is already on its way</small></div></div>
</div>
</div>
<footer>
<div class="legend"><i class="dot"></i> Passengers are waiting on the platform</div>
<div class="controls">Arrow keys / WASD to steer</div>
</footer>
</main>
<script>
(() => {
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const board = document.getElementById('board');
const veil = document.getElementById('veil');
const cols = 26, rows = 16;
let cell = 24, w, h, running = false, score = 0, tick = 0, timer;
let train = [{x:7,y:8},{x:6,y:8},{x:5,y:8}];
let dir = {x:1,y:0}, queued = {x:1,y:0};
let passengers = [];
const colors = ['#ee7666','#eeb64d','#68a8c4','#a487c7','#77ad78','#e18aa8'];
const rand = n => Math.floor(Math.random()*n);
function resize() {
const rect = board.getBoundingClientRect();
cell = Math.floor(rect.width / cols);
w = cell * cols; h = cell * rows;
canvas.width = w * devicePixelRatio;
canvas.height = h * devicePixelRatio;
canvas.style.width = w + 'px';
canvas.style.height = h + 'px';
ctx.setTransform(devicePixelRatio,0,0,devicePixelRatio,0,0);
draw();
}
function passengerSpot() {
for (let i=0;i<200;i++) {
const p = {x:2+rand(cols-4), y:2+rand(rows-4), color:colors[rand(colors.length)]};
if (!train.some(t=>t.x===p.x&&t.y===p.y) && !passengers.some(q=>q.x===p.x&&q.y===p.y)) {
passengers.push(p); return;
}
}
}
for(let i=0;i<5;i++) passengerSpot();
function rounded(x,y,width,height,r,color) {
ctx.fillStyle=color; ctx.beginPath(); ctx.roundRect(x,y,width,height,r); ctx.fill();
}
function draw() {
if (!w) return;
ctx.clearRect(0,0,w,h);
ctx.fillStyle='#dce9dd'; ctx.fillRect(0,0,w,h);
// Gentle station-garden ground
for(let y=0;y<rows;y++) for(let x=0;x<cols;x++) {
if ((x*13+y*7)%29===0) {
ctx.fillStyle='rgba(90,137,101,.10)';
ctx.beginPath(); ctx.arc(x*cell+cell*.7,y*cell+cell*.7,cell*.055,0,Math.PI*2); ctx.fill();
}
}
// Platform: a welcoming tiled strip across the middle
const py=2.15*cell, ph=2.35*cell;
ctx.fillStyle='#c8d4c8'; ctx.fillRect(0,py,w,ph);
ctx.fillStyle='#f2ead4'; ctx.fillRect(0,py+cell*.16,w,cell*.13);
ctx.fillStyle='#b8c8bf'; ctx.fillRect(0,py+ph-cell*.17,w,cell*.17);
for(let x=0;x<cols;x+=2) {
ctx.strokeStyle='rgba(89,117,107,.12)'; ctx.lineWidth=1;
ctx.beginPath(); ctx.moveTo(x*cell,py); ctx.lineTo(x*cell,py+ph-cell*.18); ctx.stroke();
}
// Little benches and platform lamps
for(let x=2;x<cols;x+=8) {
const bx=x*cell, by=py+cell*.38;
rounded(bx,by,cell*1.15,cell*.16,3,'#9b7655');
rounded(bx+cell*.08,by+cell*.21,cell*.13,cell*.27,2,'#8b6a50');
rounded(bx+cell*.93,by+cell*.21,cell*.13,cell*.27,2,'#8b6a50');
ctx.fillStyle='#e9d58c'; ctx.beginPath(); ctx.arc(bx+cell*.58,py+cell*.12,cell*.12,0,Math.PI*2); ctx.fill();
}
// Passengers waiting in a neat line
passengers.forEach((p,i)=>{
const x=(p.x+.5)*cell, y=(p.y+.5)*cell;
ctx.fillStyle='rgba(31,58,49,.13)'; ctx.beginPath(); ctx.ellipse(x,y+cell*.36,cell*.25,cell*.07,0,0,Math.PI*2); ctx.fill();
// suitcase
rounded(x-cell*.29,y+cell*.12,cell*.19,cell*.19,3,'#b98155');
ctx.strokeStyle='#865c40'; ctx.lineWidth=1; ctx.beginPath(); ctx.arc(x-cell*.195,y+cell*.12,cell*.045,Math.PI,0); ctx.stroke();
// body + head
ctx.fillStyle=p.color; ctx.beginPath(); ctx.roundRect(x-cell*.16,y-cell*.02,cell*.32,cell*.35,cell*.1); ctx.fill();
ctx.fillStyle='#f1c59f'; ctx.beginPath(); ctx.arc(x,y-cell*.16,cell*.16,0,Math.PI*2); ctx.fill();
ctx.fillStyle='#344b47'; ctx.beginPath(); ctx.arc(x-cell*.055,y-cell*.18,cell*.025,0,Math.PI*2); ctx.fill();
// ticket sparkle
ctx.fillStyle='#fff1af'; ctx.font=`${cell*.25}px sans-serif`; ctx.fillText('✦',x+cell*.22,y-cell*.17);
});
// Train wagons, drawn tail to head
for(let i=train.length-1;i>=1;i--) {
const t=train[i], x=t.x*cell, y=t.y*cell, c=colors[(i-1)%colors.length];
ctx.fillStyle='rgba(34,55,49,.18)'; ctx.beginPath(); ctx.ellipse(x+cell/2,y+cell*.76,cell*.4,cell*.12,0,0,Math.PI*2); ctx.fill();
rounded(x+cell*.08,y+cell*.13,cell*.84,cell*.65,cell*.18,c);
rounded(x+cell*.18,y+cell*.23,cell*.64,cell*.23,cell*.09,'rgba(255,255,255,.24)');
ctx.fillStyle='#39484a';
ctx.beginPath(); ctx.arc(x+cell*.25,y+cell*.79,cell*.105,0,Math.PI*2); ctx.arc(x+cell*.75,y+cell*.79,cell*.105,0,Math.PI*2); ctx.fill();
ctx.fillStyle='#f8e7ae'; ctx.beginPath(); ctx.arc(x+cell*.5,y+cell*.49,cell*.065,0,Math.PI*2); ctx.fill();
// coupler
if(i===train.length-1) {}
}
// Connecting couplers
for(let i=0;i<train.length-1;i++) {
const a=train[i], b=train[i+1];
ctx.strokeStyle='#53615e'; ctx.lineWidth=Math.max(2,cell*.07);
ctx.beginPath(); ctx.moveTo((a.x+.5)*cell,(a.y+.5)*cell); ctx.lineTo((b.x+.5)*cell,(b.y+.5)*cell); ctx.stroke();
}
// Locomotive
const head=train[0], x=head.x*cell, y=head.y*cell;
ctx.fillStyle='rgba(34,55,49,.2)'; ctx.beginPath(); ctx.ellipse(x+cell*.52,y+cell*.78,cell*.46,cell*.13,0,0,Math.PI*2); ctx.fill();
rounded(x+cell*.05,y+cell*.29,cell*.91,cell*.48,cell*.16,'#247d79');
rounded(x+cell*.38,y+cell*.02,cell*.48,cell*.48,cell*.12,'#246d6b');
rounded(x+cell*.48,y+cell*.12,cell*.26,cell*.21,cell*.055,'#bde0d1');
rounded(x+cell*.43,y+cell*.46,cell*.45,cell*.17,cell*.06,'#e5ad4b');
rounded(x+cell*.11,y+cell*.48,cell*.19,cell*.17,cell*.06,'#f7d67f');
ctx.fillStyle='#354448';
ctx.beginPath(); ctx.arc(x+cell*.25,y+cell*.79,cell*.115,0,Math.PI*2); ctx.arc(x+cell*.76,y+cell*.79,cell*.115,0,Math.PI*2); ctx.fill();
ctx.fillStyle='#f8eebf'; ctx.beginPath(); ctx.arc(x+cell*.15,y+cell*.36,cell*.07,0,Math.PI*2); ctx.fill();
// Smokestack and puffs
rounded(x+cell*.18,y+cell*.1,cell*.16,cell*.2,cell*.035,'#425a58');
const puff=(tick%4)*cell*.035;
ctx.fillStyle='rgba(255,255,255,.75)'; ctx.beginPath(); ctx.arc(x+cell*.26-puff,y+cell*.04-puff,cell*.11+puff,0,Math.PI*2); ctx.fill();
ctx.fillStyle='#254a48'; ctx.font=`bold ${cell*.16}px sans-serif`; ctx.textAlign='center';
ctx.fillText('EXPRESS',x+cell*.65,y+cell*.74);
ctx.textAlign='start';
}
function step() {
tick++;
dir=queued;
const next={x:train[0].x+dir.x,y:train[0].y+dir.y};
// Keep the demo moving safely around the board edges and its own wagons
if(next.x<1||next.x>=cols-1||next.y<1||next.y>=rows-1||train.slice(0,-1).some(t=>t.x===next.x&&t.y===next.y)) {
const choices=[{x:1,y:0},{x:0,y:1},{x:-1,y:0},{x:0,y:-1}].filter(d=>{
const p={x:train[0].x+d.x,y:train[0].y+d.y};
return p.x>0&&p.x<cols-1&&p.y>0&&p.y<rows-1&&!train.slice(0,-1).some(t=>t.x===p.x&&t.y===p.y)&&!(d.x===-dir.x&&d.y===-dir.y);
});
queued=choices[rand(choices.length)]||{x:-dir.y,y:dir.x};
dir=queued;
next.x=train[0].x+dir.x; next.y=train[0].y+dir.y;
}
train.unshift(next);
const found=passengers.findIndex(p=>p.x===next.x&&p.y===next.y);
if(found>=0) { passengers.splice(found,1); score++; passengerSpot(); }
else train.pop();
// AI steers toward the nearest waiting traveler, while avoiding reversals
const target=passengers.reduce((best,p)=>!best||Math.abs(p.x-next.x)+Math.abs(p.y-next.y)<Math.abs(best.x-next.x)+Math.abs(best.y-next.y)?p:best,null);
if(target) {
let opts=[{x:1,y:0},{x:0,y:1},{x:-1,y:0},{x:0,y:-1}]
.filter(d=>!(d.x===-dir.x&&d.y===-dir.y))
.sort((a,b)=>(Math.abs(next.x+a.x-target.x)+Math.abs(next.y+a.y-target.y))-(Math.abs(next.x+b.x-target.x)+Math.abs(next.y+b.y-target.y)));
for(const d of opts) {
const p={x:next.x+d.x,y:next.y+d.y};
if(p.x>0&&p.x<cols-1&&p.y>0&&p.y<rows-1&&!train.slice(1,-1).some(t=>t.x===p.x&&t.y===p.y)) { queued=d; break; }
}
}
document.getElementById('score').textContent=String(score).padStart(2,'0');
document.getElementById('wagons').textContent=String(train.length-1).padStart(2,'0');
draw();
}
function start() {
if(running) return;
running=true; veil.style.display='none';
timer=setInterval(step,250);
}
window.addEventListener('keydown',e=>{
const keys={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}};
const d=keys[e.key]||keys[e.key.toLowerCase()];
if(d) { e.preventDefault(); start(); if(!(d.x===-dir.x&&d.y===-dir.y)) queued=d; }
else start();
});
board.addEventListener('pointerdown',start);
window.addEventListener('resize',resize);
resize();
// The train is already in motion behind the invitation on first paint.
running=true; timer=setInterval(step,250);
})();
</script>
</body>
</html>Reasoning trace (185 tokens)
**Designing a Game Interface** I'm focused on creating a polished HTML game visual, featuring a self-playing demo with a click or key start overlay while showing immediate action. The canvas should be responsive for a train snake and platforms with passengers. I want to design a 26x16 board with animated movement driven by AI that auto-routes toward target passengers. The game will have user controls with arrows after the demo starts, allowing pickups to add wagons and score. I'll also ensure ambient visuals and responsive scaling.