Models 44
Train snakeOne-line

Muse Ember

by MetaReasoning1 console error
Open in new window

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

How it went

Total time
16.7 s
Cost
$0.0044
Output tokens
8,732
Spent thinking
2,484 tokens
Speed
619.7 tok/s
Console errors
1
First token after
2.6 s
First visible text after
8.6 s
Prompt tokens
380
Code size
17.9 KB
Finish reason
stop
Served by
Meta
Model id
meta/muse-ember
Reasoning sent
{"effort":"high"}
Max output
943,718 tokens
Generated
Nov 12, 2026

Console errors

Caught in the first 3 seconds after load, in a sandboxed iframe like the one above.

Cannot read properties of undefined (reading 'x')

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 · 293 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Happy Express — Snake Train</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;background:#0f172a;color:#fff;min-height:100vh}
header{background:linear-gradient(90deg,#0f766e,#0369a1,#7c3aed);padding:10px 16px;display:flex;flex-wrap:wrap;gap:10px;align-items:center;justify-content:space-between;box-shadow:0 4px 20px rgba(0,0,0,.4)}
.logo{display:flex;align-items:center;gap:12px}
.logo .emoji{font-size:38px;background:#fff;border-radius:50%;width:56px;height:56px;display:grid;place-items:center;box-shadow:0 4px 0 #facc15}
h1{font-size:24px;letter-spacing:.3px;line-height:1}
h1 span{font-size:13px;opacity:.9;font-weight:600;letter-spacing:1px;text-transform:uppercase}
.stats{display:flex;gap:8px;flex-wrap:wrap}
.pill{background:rgba(255,255,255,.95);color:#0f172a;padding:7px 12px;border-radius:999px;font-weight:800;font-size:13px;display:flex;gap:6px;align-items:center}
.pill small{font-weight:600;opacity:.6;font-size:11px;text-transform:uppercase}
main{max-width:1280px;margin:0 auto;padding:14px;display:flex;gap:16px;align-items:flex-start}
.board-wrap{flex:1;min-width:0}
.board-frame{background:#1e293b;border:6px solid #facc15;border-radius:20px;padding:10px;box-shadow:0 20px 50px rgba(0,0,0,.5);position:relative}
canvas{width:100%;height:auto;display:block;border-radius:12px;background:#14532d;aspect-ratio:1}
.overlay{position:absolute;left:50%;top:14px;transform:translateX(-50%);background:#fef08a;color:#422006;padding:8px 14px;border-radius:999px;font-weight:900;font-size:13px;box-shadow:0 6px 16px rgba(0,0,0,.35);border:2px solid #fff;white-space:nowrap;z-index:5}
.overlay.hidden{display:none}
.overlay.gameover{background:#ef4444;color:#fff;top:50%;transform:translate(-50%,-50%);flex-direction:column;display:flex;gap:8px;padding:18px 22px;border-radius:16px;text-align:center;white-space:normal}
.overlay.gameover.hidden{display:none}
.overlay.gameover button{background:#fff;border:0;padding:9px 16px;border-radius:999px;font-weight:900;cursor:pointer}
aside{width:320px;flex-shrink:0;display:flex;flex-direction:column;gap:12px}
.card{background:#fff;color:#0f172a;border-radius:16px;padding:14px;box-shadow:0 10px 24px rgba(0,0,0,.25)}
.card h2{font-size:15px;margin-bottom:8px}
.card p{font-size:13px;line-height:1.5;color:#334155}
.btns{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:10px}
button{border:0;padding:10px 12px;border-radius:10px;font-weight:900;cursor:pointer;font-size:13px}
.btn-primary{background:#dc2626;color:#fff}
.btn-blue{background:#2563eb;color:#fff}
.btn-amber{background:#f59e0b;color:#fff}
.btn-dark{background:#0f172a;color:#fff}
.legend{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.dot{width:22px;height:22px;border-radius:50%;border:2px solid #fff;box-shadow:0 1px 4px rgba(0,0,0,.3)}
.dpad{display:grid;grid-template-columns:repeat(3,52px);justify-content:center;gap:6px;margin-top:10px}
.dpad button{height:48px;font-size:20px;background:#e2e8f0;color:#0f172a;border-radius:12px}
.dpad button:active{background:#facc15}
.keys{font-family:monospace;background:#f1f5f9;padding:2px 6px;border-radius:6px;font-size:12px}
.progress{height:10px;background:#e2e8f0;border-radius:999px;overflow:hidden;margin-top:8px}
.progress i{display:block;height:100%;background:linear-gradient(90deg,#ef4444,#f59e0b,#22c55e,#3b82f6,#a855f7);width:10%}
.station{background:linear-gradient(135deg,#fef3c7,#fde68a);border:2px dashed #d97706}
@media(max-width:900px){
 main{flex-direction:column;padding:10px}
 aside{width:100%}
 h1{font-size:20px}
 .overlay{font-size:11px;top:10px;max-width:92%;white-space:normal;text-align:center}
}
</style>
</head>
<body>
<header>
  <div class="logo">
    <div class="emoji">🚂</div>
    <h1>HAPPY EXPRESS<br><span>Snake Train • Passenger Pick-up</span></h1>
  </div>
  <div class="stats">
    <div class="pill"><small>Score</small> <span id="score">0</span></div>
    <div class="pill"><small>Passengers</small> <span id="picked">0</span></div>
    <div class="pill"><small>Wagons</small> <span id="wagons">4</span></div>
    <div class="pill"><small>Best</small> <span id="best">0</span></div>
  </div>
</header>
<main>
  <div class="board-wrap">
    <div class="board-frame">
      <div id="demoMsg" class="overlay">▶ DEMO IS PLAYING — Click or press a key to start driving yourself!</div>
      <div id="overMsg" class="overlay gameover hidden"><div style="font-size:22px">💥 Derailment!</div><div id="overText">Your train crashed.</div><button id="restartBtn2">↻ Start Again</button></div>
      <canvas id="game" width="660" height="660"></canvas>
    </div>
  </div>
  <aside>
    <div class="card station">
      <h2>🚏 How to play</h2>
      <p>Your snake is a little train! Drive the <b>locomotive</b> over the <b>waiting passengers</b> on the 4 platforms. Each passenger hops into a new <b>colourful wagon</b> — the train grows longer!</p>
      <div class="legend"><span class="dot" style="background:#ef4444"></span><span class="dot" style="background:#f59e0b"></span><span class="dot" style="background:#84cc16"></span><span class="dot" style="background:#06b6d4"></span><span class="dot" style="background:#8b5cf6"></span><span class="dot" style="background:#ec4899"></span><span style="align-self:center;font-size:12px;font-weight:700">passenger shirt = wagon colour</span></div>
      <div class="progress"><i id="prog"></i></div>
      <p style="margin-top:6px;font-size:12px"><span id="nextGoal">Next stop: pick up a passenger!</span></p>
    </div>
    <div class="card">
      <h2>🎮 Controls</h2>
      <p><span class="keys">← ↑ ↓ →</span> or <span class="keys">W A S D</span> to steer &bull; <span class="keys">Space</span> pause &bull; <span class="keys">R</span> restart</p>
      <div class="btns">
        <button class="btn-primary" id="pauseBtn">⏸ Pause</button>
        <button class="btn-blue" id="autoBtn">🤖 AI Driver: ON</button>
        <button class="btn-amber" id="restartBtn">↻ New Train</button>
        <button class="btn-dark" id="soundBtn">🔔 Sound: ON</button>
      </div>
      <div class="dpad">
        <span></span><button data-d="0,-1">▲</button><span></span>
        <button data-d="-1,0">◀</button><button data-d="0,1">▼</button><button data-d="1,0">▶</button>
      </div>
    </div>
    <div class="card">
      <h2>🚂 The Train</h2>
      <p><b style="color:#dc2626">● Locomotive</b> — red engine, watch for smoke!<br>Each wagon carries its passenger — look for little heads in the windows. The longer your train, the harder it is to turn. Don't hit walls or your own wagons!</p>
    </div>
  </aside>
</main>

<script>
const COLS=22, ROWS=22, CELL=30;
const canvas=document.getElementById('game'), ctx=canvas.getContext('2d');
const scoreEl=document.getElementById('score'), pickedEl=document.getElementById('picked'), wagonsEl=document.getElementById('wagons'), bestEl=document.getElementById('best');
const demoMsg=document.getElementById('demoMsg'), overMsg=document.getElementById('overMsg'), overText=document.getElementById('overText');
const prog=document.getElementById('prog'), nextGoal=document.getElementById('nextGoal');

const COLORS=['#ef4444','#f59e0b','#84cc16','#06b6d4','#8b5cf6','#ec4899','#22c55e','#f97316'];
const PLATFORMS=[
 {x:3,y:2,w:6,h:1,label:'1'},{x:19,y:9,w:1,h:6,label:'2'},
 {x:12,y:19,w:6,h:1,label:'3'},{x:2,y:13,w:1,h:6,label:'4'}
];
let platformSet=new Set(), platformList=[];
PLATFORMS.forEach(p=>{for(let y=p.y;y<p.y+p.h;y++)for(let x=p.x;x<p.x+p.w;x++){platformSet.add(x+','+y);platformList.push({x,y,label:p.label})}});

let snake, dir, nextDir, passengers, score, picked, best=0, alive, auto=true, paused=false, sound=true, tickMs, smoke=[], popups=[], frame=0, timer=null, userStarted=false;

function init(){
  snake=[{x:11,y:11},{x:10,y:11},{x:9,y:11},{x:8,y:11},{x:7,y:11}];
  dir={x:1,y:0}; nextDir={x:1,y:0};
  passengers=[]; score=0; picked=0; alive=true; paused=false; smoke=[]; popups=[]; tickMs=150;
  for(let i=0;i<4;i++) spawnPassenger();
  updateHUD(); schedule();
  overMsg.classList.add('hidden');
}
function spawnPassenger(){
  const free=platformList.filter(c=>!snake.some(s=>s.x===c.x&&s.y===c.y)&&!passengers.some(p=>p.x===c.x&&p.y===c.y));
  if(!free.length) return;
  const c=free[Math.floor(Math.random()*free.length)];
  passengers.push({x:c.x,y:c.y,color:COLORS[Math.floor(Math.random()*COLORS.length)],plat:c.label});
}
function updateHUD(){
  scoreEl.textContent=score; pickedEl.textContent=picked; wagonsEl.textContent=snake?snake.length-1:0;
  best=Math.max(best,score); bestEl.textContent=best;
  prog.style.width=Math.min(100,10+picked*10)+'%';
  if(passengers.length){const p=passengers[0]; nextGoal.textContent=`Next stop: Platform ${p.plat} — ${passengers.length} passenger${passengers.length>1?'s':''} waiting!`}
}
function schedule(){clearTimeout(timer); if(!alive||paused) return; timer=setTimeout(()=>{tick(); schedule();}, tickMs);}
function setDir(x,y){ if(!alive) return; if(dir.x===-x && dir.y===-y && snake.length>2) return; nextDir={x,y}; }
function tick(){
  if(!alive||paused) return;
  if(auto){ const d=aiDir(); if(d) nextDir=d; }
  dir={...nextDir};
  const head={x:snake[0].x+dir.x, y:snake[0].y+dir.y};
  if(head.x<0||head.x>=COLS||head.y<0||head.y>=ROWS||snake.some((s,i)=>i<snake.length-1&&s.x===head.x&&s.y===head.y)){
    if(auto){ /* try to survive */ init(); return; }
    alive=false; overText.textContent=`You picked up ${picked} passengers and scored ${score}. The train derailed!`; overMsg.classList.remove('hidden'); updateHUD(); return;
  }
  const idx=passengers.findIndex(p=>p.x===head.x&&p.y===head.y);
  const eating=idx!==-1;
  snake.unshift(head);
  if(eating){
    const p=passengers.splice(idx,1)[0];
    picked++; score+=10+picked; tickMs=Math.max(78,150-picked*4);
    popups.push({x:head.x,y:head.y,text:'+'+(10+picked)+' 👋',t:0});
    for(let i=0;i<10;i++) smoke.push({x:head.x*CELL+15,y:head.y*CELL+10,vx:(Math.random()-.5)*1.4,vy:-Math.random()*1.6-0.6,r:4+Math.random()*6,a:0.9});
    spawnPassenger(); beep(eating);
  } else snake.pop();
  // smoke from chimney
  smoke.push({x:snake[0].x*CELL+18+dir.x*8,y:snake[0].y*CELL+6,vx:-dir.x*0.4+(Math.random()-.5)*.6,vy:-0.9,r:5,a:0.7});
  updateHUD();
}
function beep(){ if(!sound) return; try{ const a=new (window.AudioContext||window.webkitAudioContext)(); const o=a.createOscillator(), g=a.createGain(); o.frequency.value=880; o.type='sine'; g.gain.value=0.08; o.connect(g); g.connect(a.destination); o.start(); o.stop(a.currentTime+0.12);}catch(e){} }

// AI BFS
function aiDir(){
  const targetSet=new Set(passengers.map(p=>p.x+','+p.y));
  const body=new Set(snake.slice(0,-1).map(s=>s.x+','+s.y));
  const q=[{...snake[0],first:null}]; const seen=new Set([snake[0].x+','+snake[0].y]); let found=null;
  const dirs=[{x:1,y:0},{x:-1,y:0},{x:0,y:1},{x:0,y:-1}];
  while(q.length){ const cur=q.shift();
    if(targetSet.has(cur.x+','+cur.y)&&cur.first){found=cur.first;break;}
    for(const d of dirs){ const nx=cur.x+d.x, ny=cur.y+d.y, k=nx+','+ny;
      if(nx<0||nx>=COLS||ny<0||ny>=ROWS||seen.has(k)||body.has(k)) continue;
      if(cur.first===null && d.x===-dir.x&&d.y===-dir.y) continue;
      seen.add(k); q.push({x:nx,y:ny,first:cur.first||d});
    }
  }
  if(found) return found;
  let bestD=null,bestScore=-1;
  for(const d of dirs){ if(d.x===-dir.x&&d.y===-dir.y&&snake.length>2) continue;
    const nx=snake[0].x+d.x, ny=snake[0].y+d.y;
    if(nx<0||nx>=COLS||ny<0||ny>=ROWS||snake.some((s,i)=>i<snake.length-1&&s.x===nx&&s.y===ny)) continue;
    // flood fill
    const seen2=new Set([nx+','+ny]); const qq=[{x:nx,y:ny}]; let cnt=0;
    while(qq.length){const c=qq.pop(); cnt++; for(const dd of dirs){const mx=c.x+dd.x,my=c.y+dd.y,k=mx+','+my; if(mx<0||mx>=COLS||my<0||my>=ROWS||seen2.has(k)||snake.some((s,i)=>i<snake.length-1&&s.x===mx&&s.y===my)) continue; seen2.add(k); qq.push({x:mx,y:my});}}
    if(cnt>bestScore){bestScore=cnt;bestD=d;}
  }
  return bestD||dir;
}

function render(){
  frame++;
  ctx.clearRect(0,0,660,660);
  ctx.fillStyle='#14532d'; ctx.fillRect(0,0,660,660);
  // sleepers + rails
  ctx.fillStyle='#7c5a2e';
  for(let y=0;y<ROWS;y++) for(let x=0;x<COLS;x++){ ctx.fillRect(x*CELL+2, y*CELL+CELL/2-2, CELL-4, 4); }
  ctx.strokeStyle='rgba(226,232,240,0.55)'; ctx.lineWidth=2;
  for(let x=0;x<COLS;x++){ ctx.beginPath(); ctx.moveTo(x*CELL+9,0); ctx.lineTo(x*CELL+9,660); ctx.moveTo(x*CELL+21,0); ctx.lineTo(x*CELL+21,660); ctx.stroke(); }
  ctx.strokeStyle='rgba(255,255,255,0.08)'; ctx.lineWidth=1;
  for(let i=0;i<=COLS;i++){ctx.beginPath();ctx.moveTo(i*CELL,0);ctx.lineTo(i*CELL,660);ctx.stroke();ctx.beginPath();ctx.moveTo(0,i*CELL);ctx.lineTo(660,i*CELL);ctx.stroke();}

  // platforms
  PLATFORMS.forEach(p=>{
    ctx.fillStyle='#e7e5e4'; ctx.fillRect(p.x*CELL-3,p.y*CELL-3,p.w*CELL+6,p.h*CELL+6);
    ctx.fillStyle='#facc15'; ctx.fillRect(p.x*CELL-3,p.y*CELL+p.h*CELL-2,p.w*CELL+6,4);
    if(p.h===1){ctx.fillRect(p.x*CELL-3,p.y*CELL-3,p.w*CELL+6,4);} else {ctx.fillRect(p.x*CELL-3,p.y*CELL-3,4,p.h*CELL+6);}
    ctx.fillStyle='#0f172a'; ctx.beginPath(); ctx.arc(p.x*CELL+p.w*CELL/2, p.y*CELL+p.h*CELL/2, 11,0,Math.PI*2); ctx.fill();
    ctx.fillStyle='#fff'; ctx.font='bold 13px Arial'; ctx.textAlign='center'; ctx.textBaseline='middle'; ctx.fillText(p.label, p.x*CELL+p.w*CELL/2, p.y*CELL+p.h*CELL/2+1);
  });

  // waiting passengers
  passengers.forEach((p,i)=>{
    const cx=p.x*CELL+15, cy=p.y*CELL+18+Math.sin(frame/9+i)*2;
    ctx.fillStyle='rgba(0,0,0,0.25)'; ctx.beginPath(); ctx.ellipse(cx, p.y*CELL+27,10,3,0,0,Math.PI*2); ctx.fill();
    ctx.fillStyle=p.color; ctx.fillRect(cx-5,cy-2,10,11); // body
    ctx.fillStyle='#fcd9b8'; ctx.beginPath(); ctx.arc(cx,cy-7,6,0,Math.PI*2); ctx.fill(); // head
    ctx.fillStyle='#1e293b'; ctx.fillRect(cx-6,cy-13,12,4); // hair
    ctx.fillStyle='#fff'; ctx.font='9px Arial'; ctx.fillText('👋',cx+10,cy-10);
  });

  // smoke
  smoke=smoke.filter(s=>s.a>0.05);
  smoke.forEach(s=>{ s.x+=s.vx; s.y+=s.vy; s.r+=0.25; s.a*=0.96; ctx.fillStyle=`rgba(226,232,240,${s.a})`; ctx.beginPath(); ctx.arc(s.x,s.y,s.r,0,Math.PI*2); ctx.fill(); });

  // train tail to head
  for(let i=snake.length-1;i>=0;i--){
    const seg=snake[i];
    let ang;
    if(i===0) ang=Math.atan2(dir.y,dir.x);
    else ang=Math.atan2(snake[i-1].y-seg.y, snake[i-1].x-seg.x);
    const cx=seg.x*CELL+15, cy=seg.y*CELL+15;
    ctx.save(); ctx.translate(cx,cy); ctx.rotate(ang);
    const isHead=i===0;
    const col=isHead?'#dc2626':COLORS[(i-1)%COLORS.length];
    // body
    ctx.fillStyle=col; roundRect(-13,-10,26,20,5); ctx.fill();
    ctx.fillStyle='rgba(0,0,0,0.18)'; ctx.fillRect(-13,4,26,6);
    if(isHead){
      ctx.fillStyle='#991b1b'; ctx.fillRect(-12,-9,10,18); // cab
      ctx.fillStyle='#fef9c3'; ctx.fillRect(-10,-6,6,7);
      ctx.fillStyle='#334155'; ctx.fillRect(7,-4,5,8); // chimney base
      ctx.fillStyle='#64748b'; ctx.fillRect(6,-8,7,5);
      ctx.fillStyle='#facc15'; ctx.beginPath(); ctx.arc(13,0,3.5,0,Math.PI*2); ctx.fill();
      ctx.fillStyle='#111'; [[-7,10],[6,10],[-7,-10],[6,-10]].forEach(w=>{ctx.beginPath();ctx.arc(w[0],w[1],3.5,0,Math.PI*2);ctx.fill();});
    } else {
      ctx.fillStyle='#fff'; ctx.fillRect(-8,-6,7,8); ctx.fillRect(2,-6,7,8);
      // passenger head in window
      if(i<=picked+1){ ctx.fillStyle='#fcd9b8'; ctx.beginPath(); ctx.arc(-4.5,-2,3,0,Math.PI*2); ctx.fill(); ctx.fillStyle=COLORS[(i-1)%COLORS.length]; ctx.fillRect(-7,0,5,4); }
      ctx.fillStyle='#111'; [[-7,10],[6,10],[-7,-10],[6,-10]].forEach(w=>{ctx.beginPath();ctx.arc(w[0],w[1],3,0,Math.PI*2);ctx.fill();});
      ctx.fillStyle='#fff'; ctx.font='bold 7px Arial'; ctx.textAlign='center'; ctx.textBaseline='middle'; ctx.fillText(i, -0, 6);
    }
    ctx.restore();
    // coupling
    if(i<snake.length-1){ ctx.strokeStyle='#111'; ctx.lineWidth=2; ctx.beginPath(); ctx.moveTo(cx,cy); ctx.lineTo(snake[i-1].x*CELL+15, snake[i-1].y*CELL+15); ctx.stroke(); }
  }
  // popups
  popups=popups.filter(p=>p.t<40);
  popups.forEach(p=>{ p.t++; ctx.fillStyle='#fef08a'; ctx.font='bold 14px Arial'; ctx.textAlign='center'; ctx.strokeStyle='#000'; ctx.lineWidth=3; const y=p.y*CELL-p.t*0.7; ctx.strokeText(p.text,p.x*CELL+15,y); ctx.fillText(p.text,p.x*CELL+15,y); });

  requestAnimationFrame(render);
}
function roundRect(x,y,w,h,r){ctx.beginPath();ctx.moveTo(x+r,y);ctx.arcTo(x+w,y,x+w,y+h,r);ctx.arcTo(x+w,y+h,x,y+h,r);ctx.arcTo(x,y+h,x,y,r);ctx.arcTo(x,y,x+w,y,r);ctx.closePath();}

function startUser(){ if(!userStarted){ userStarted=true; auto=false; document.getElementById('autoBtn').textContent='🤖 AI Driver: OFF'; demoMsg.classList.add('hidden'); } }
window.addEventListener('keydown',e=>{
  startUser();
  const k=e.key.toLowerCase();
  if(k==='arrowup'||k==='w'){setDir(0,-1);e.preventDefault();}
  if(k==='arrowdown'||k==='s'){setDir(0,1);e.preventDefault();}
  if(k==='arrowleft'||k==='a'){setDir(-1,0);e.preventDefault();}
  if(k==='arrowright'||k==='d'){setDir(1,0);e.preventDefault();}
  if(k===' '){togglePause();e.preventDefault();}
  if(k==='r'){init();}
});
canvas.addEventListener('click',startUser);
document.querySelector('.board-frame').addEventListener('click',startUser);
document.querySelectorAll('.dpad button').forEach(b=>b.addEventListener('click',()=>{startUser(); const [x,y]=b.dataset.d.split(',').map(Number); setDir(x,y);}));
function togglePause(){ if(!alive) return; paused=!paused; document.getElementById('pauseBtn').textContent=paused?'▶ Resume':'⏸ Pause'; if(!paused) schedule(); }
document.getElementById('pauseBtn').addEventListener('click',togglePause);
document.getElementById('restartBtn').addEventListener('click',()=>{startUser();init();});
document.getElementById('restartBtn2').addEventListener('click',()=>{overMsg.classList.add('hidden');init();});
document.getElementById('autoBtn').addEventListener('click',e=>{ startUser(); auto=!auto; e.target.textContent=auto?'🤖 AI Driver: ON':'🤖 AI Driver: OFF'; if(auto&&!alive) init();});
document.getElementById('soundBtn').addEventListener('click',e=>{sound=!sound; e.target.textContent=sound?'🔔 Sound: ON':'🔕 Sound: OFF';});

init(); render();
</script>
</body>
</html>
Reasoning trace (2,484 tokens)
Designing a single-file HTML snake game with a locomotive and wagons, track grid, and passenger pickup mechanics that adapts from 1280x800 to 375 and includes self-playing demo mode.Adding platform zones for passenger pickup, canvas visuals, BFS AI, and responsive UI layout.Defining platform coordinates, AI pathfinding, and canvas rendering for train, wagons, and passengers.Implementing BFS pathfinding with fallback scoring and rendering smoke, wagons, and UI controls.