Models 44
Train snakeOne-line

MiniMax M3.1 Flash

by MiniMaxReasoningClean
Open in new window

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

How it went

Total time
23.1 s
Cost
$0.0037
Output tokens
6,173
Spent thinking
362 tokens
Speed
273.9 tok/s
Console errors
0
First token after
522 ms
First visible text after
3.4 s
Prompt tokens
532
Code size
16.9 KB
Finish reason
stop
Served by
DigitalOcean
Model id
minimax/minimax-m3.1-flash
Reasoning sent
{"effort":"low"}
Max output
64,000 tokens
Generated
Nov 11, 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 · 432 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 — Train Snake</title>
<style>
  * { box-sizing: border-box; }
  html, body {
    margin: 0; min-height: 100%; background: #101827; color: #f8fafc;
    font-family: ui-rounded, "Trebuchet MS", system-ui, sans-serif;
    overflow-x: hidden;
  }
  body {
    display: flex; flex-direction: column; align-items: center;
    background: radial-gradient(circle at 50% -20%, #2d4664 0, #101827 65%);
    padding: 18px 12px 24px;
  }
  header {
    width: min(880px, 100%); display: flex; align-items: center;
    justify-content: space-between; gap: 14px; margin-bottom: 12px; flex-wrap: wrap;
  }
  .brand { display: flex; align-items: center; gap: 12px; }
  .logo {
    width: 48px; height: 48px; display: grid; place-items: center; font-size: 29px;
    background: linear-gradient(145deg, #fbbf24, #f97316); border-radius: 14px;
    box-shadow: 0 8px 22px #f9731640; border: 2px solid #fde68a;
  }
  h1 { margin: 0; font-size: clamp(21px, 4vw, 30px); letter-spacing: .3px; }
  .subtitle { color: #a9bbd3; font-size: 13px; margin-top: 2px; }
  .stats { display: flex; gap: 8px; }
  .stat {
    min-width: 92px; padding: 8px 13px; border-radius: 12px;
    background: #1b2a40; border: 1px solid #33465f; box-shadow: inset 0 1px #ffffff12;
  }
  .stat small { display: block; color: #9fb2ca; font-size: 10px; letter-spacing: 1.2px; text-transform: uppercase; }
  .stat strong { font-size: 20px; color: #fde68a; }
  .stage {
    position: relative; width: min(880px, 100%); border-radius: 20px; overflow: hidden;
    border: 3px solid #3b526d; box-shadow: 0 22px 55px #0008, 0 0 0 6px #0b1422;
    background: #142135;
  }
  canvas { display: block; width: 100%; height: auto; aspect-ratio: 864/576; }
  .overlay {
    position: absolute; inset: 0; display: grid; place-items: center;
    background: #07111bd9; backdrop-filter: blur(3px); transition: opacity .25s;
  }
  .overlay.hidden { opacity: 0; pointer-events: none; }
  .card {
    text-align: center; padding: 28px 34px; max-width: 430px; margin: 16px;
    background: linear-gradient(145deg, #20344eea, #142035ee);
    border: 1px solid #4b6686; border-radius: 22px; box-shadow: 0 18px 45px #0007;
  }
  .card .train-icon { font-size: 46px; margin-bottom: 6px; }
  .card h2 { margin: 0 0 8px; font-size: 26px; }
  .card p { margin: 6px 0; color: #c4d2e4; line-height: 1.45; }
  .key {
    display: inline-block; padding: 2px 7px; border-radius: 6px; background: #0b1625;
    border: 1px solid #526985; box-shadow: 0 2px 0 #02070d; color: white; font-size: 12px;
  }
  .start-btn {
    margin-top: 16px; border: 0; border-radius: 999px; padding: 12px 25px;
    background: linear-gradient(#fcd34d, #f59e0b); color: #392005; font-weight: 900;
    font-size: 15px; cursor: pointer; box-shadow: 0 5px 0 #b45309;
  }
  .start-btn:active { transform: translateY(3px); box-shadow: 0 2px 0 #b45309; }
  footer {
    width: min(880px, 100%); margin-top: 12px; color: #91a5bd; font-size: 12px;
    display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  }
  .legend { display: flex; gap: 15px; align-items: center; flex-wrap: wrap; }
  .dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 5px; }
  @media (max-width: 560px) {
    body { padding: 8px 8px 16px; }
    header { margin-bottom: 8px; }
    .subtitle { display: none; }
    .stat { min-width: 66px; padding: 6px 9px; }
    .stat strong { font-size: 16px; }
    .stage { border-radius: 13px; }
    .card { padding: 18px; }
    .card h2 { font-size: 21px; }
    .card .train-icon { font-size: 34px; }
  }
</style>
</head>
<body>
<header>
  <div class="brand">
    <div class="logo">🚂</div>
    <div>
      <h1>Platform Express</h1>
      <div class="subtitle">Collect every passenger before the next stop!</div>
    </div>
  </div>
  <div class="stats">
    <div class="stat"><small>Passengers</small><strong id="score">0</strong></div>
    <div class="stat"><small>Best</small><strong id="best">0</strong></div>
    <div class="stat"><small>Speed</small><strong id="speed">1×</strong></div>
  </div>
</header>

<div class="stage">
  <canvas id="game" width="864" height="576" aria-label="Platform Express train snake game"></canvas>
  <div class="overlay" id="overlay">
    <div class="card">
      <div class="train-icon">🚂</div>
      <h2 id="overlayTitle">All aboard!</h2>
      <p id="overlayText">Drive your colorful train along the rails and collect passengers waiting on the platform.</p>
      <p><span class="key">← ↑ ↓ →</span> or <span class="key">WASD</span> to steer</p>
      <p style="font-size:12px;color:#8fa6c0">The station conductor will demo the route automatically.</p>
      <button class="start-btn" id="startBtn">Click or press a key to start</button>
    </div>
  </div>
</div>

<footer>
  <div class="legend">
    <span><i class="dot" style="background:#fbbf24"></i>Locomotive</span>
    <span><i class="dot" style="background:#f472b6"></i>Passenger cars</span>
    <span><i class="dot" style="background:#38bdf8"></i>Waiting passengers</span>
  </div>
  <div>Tip: collect a passenger to add a colorful wagon.</div>
</footer>

<script>
(() => {
  const canvas = document.getElementById('game');
  const ctx = canvas.getContext('2d');
  const overlay = document.getElementById('overlay');
  const overlayTitle = document.getElementById('overlayTitle');
  const overlayText = document.getElementById('overlayText');
  const startBtn = document.getElementById('startBtn');
  const scoreEl = document.getElementById('score');
  const bestEl = document.getElementById('best');
  const speedEl = document.getElementById('speed');

  const COLS = 24, ROWS = 16, CELL = 36;
  const DIRS = {
    up: {x:0,y:-1}, down:{x:0,y:1}, left:{x:-1,y:0}, right:{x:1,y:0}
  };
  const colors = ['#ef476f','#06d6a0','#118ab2','#8b5cf6','#ff9f1c','#22c55e'];
  let train, passengers, direction, nextDirection, running, demo, score, best = 0;
  let stepTimer = 0, lastTime = 0, particles = [], flash = 0, level = 1;
  const keyMap = {
    ArrowUp:'up', ArrowDown:'down', ArrowLeft:'left', ArrowRight:'right',
    w:'up', s:'down', a:'left', d:'right', W:'up', S:'down', A:'left', D:'right'
  };

  function reset() {
    train = [{x:12,y:8},{x:11,y:8},{x:10,y:8},{x:9,y:8}];
    direction = DIRS.right;
    nextDirection = DIRS.right;
    passengers = [];
    score = 0; level = 1; stepTimer = 0; particles = []; flash = 0;
    spawnPassenger();
    spawnPassenger();
    updateHUD();
  }

  function spawnPassenger() {
    let spots = [];
    for (let x=1;x<COLS-1;x++) {
      spots.push({x,y:0}, {x,y:ROWS-1});
    }
    for (let y=2;y<ROWS-2;y++) {
      spots.push({x:0,y}, {x:COLS-1,y});
    }
    spots = spots.filter(p => !train.some(s => s.x===p.x && s.y===p.y) &&
                              !passengers.some(p2 => p2.x===p.x && p2.y===p.y));
    if (!spots.length) return;
    const p = spots[Math.floor(Math.random()*spots.length)];
    passengers.push({x:p.x,y:p.y,color:colors[Math.floor(Math.random()*colors.length)], phase:Math.random()*6});
  }

  function start() {
    reset();
    running = true; demo = true;
    overlay.classList.add('hidden');
    lastTime = performance.now();
    requestAnimationFrame(loop);
  }

  function gameOver() {
    running = false; demo = false;
    if (score > best) best = score;
    updateHUD();
    overlayTitle.textContent = 'End of the line!';
    overlayText.textContent = `You collected ${score} passenger${score===1?'':'s'}. The station is cheering for your railway!`;
    startBtn.textContent = 'Run the train again';
    overlay.classList.remove('hidden');
  }

  function isBlocked(p) {
    if (p.x<0 || p.x>=COLS || p.y<0 || p.y>=ROWS) return true;
    return train.slice(0,-1).some(s => s.x===p.x && s.y===p.y);
  }

  function chooseDemoDirection() {
    const options = Object.values(DIRS).filter(d => {
      const h = train[0];
      return !isBlocked({x:h.x+d.x,y:h.y+d.y});
    });
    if (!options.length) return direction;

    // BFS toward the nearest passenger, avoiding the train.
    const h = train[0], targetSet = new Set(passengers.map(p=>p.x+','+p.y));
    const queue = [{x:h.x,y:h.y,d:null,first:null}], seen = new Set([h.x+','+h.y]);
    let found = null;
    while(queue.length) {
      const n = queue.shift();
      for (const d of Object.values(DIRS)) {
        const nx=n.x+d.x, ny=n.y+d.y, k=nx+','+ny;
        if (nx<0||nx>=COLS||ny<0||ny>=ROWS||seen.has(k)) continue;
        if (train.some((s,i)=>i<train.length-1&&s.x===nx&&s.y===ny)) continue;
        seen.add(k);
        const first = n.first || d;
        if (targetSet.has(k)) { found=first; queue.length=0; break; }
        queue.push({x:nx,y:ny,first});
      }
    }
    if (found && !(found.x===-direction.x && found.y===-direction.y)) return found;
    if (options.includes(direction)) return direction;
    return options[Math.floor(Math.random()*options.length)];
  }

  function update() {
    if (demo) direction = chooseDemoDirection();
    else direction = nextDirection;
    const h = train[0];
    const nh = {x:h.x+direction.x, y:h.y+direction.y};
    if (isBlocked(nh)) { gameOver(); return; }
    train.unshift(nh);

    const caught = passengers.findIndex(p=>p.x===nh.x&&p.y===nh.y);
    if (caught>=0) {
      const p = passengers.splice(caught,1)[0];
      score++; level = 1 + Math.floor(score/4);
      flash = .3;
      for(let i=0;i<14;i++) particles.push({
        x:nh.x*CELL+CELL/2, y:nh.y*CELL+CELL/2,
        vx:(Math.random()-.5)*150, vy:(Math.random()-.5)*150,
        color:p.color, life:1
      });
      spawnPassenger();
      if (passengers.length<2 && score%2===0) spawnPassenger();
      updateHUD();
    }
    train.pop();
    particles.forEach(p=>{p.x+=p.vx/60;p.y+=p.vy/60;p.vy+=90/60;p.life-=.025;});
    particles = particles.filter(p=>p.life>0);
  }

  function updateHUD() {
    scoreEl.textContent = score;
    bestEl.textContent = Math.max(best,score);
    speedEl.textContent = level + '×';
  }

  function roundedRect(x,y,w,h,r) {
    r=Math.min(r,w/2,h/2); 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 drawBackground(t) {
    const g = ctx.createLinearGradient(0,0,0,canvas.height);
    g.addColorStop(0,'#15263a'); g.addColorStop(1,'#0d1929');
    ctx.fillStyle=g; ctx.fillRect(0,0,canvas.width,canvas.height);

    // Ballast and sleepers.
    ctx.fillStyle='#1d2c3d';
    for(let y=0;y<ROWS;y++) for(let x=0;x<COLS;x++) {
      if ((x+y)%2===0) ctx.fillRect(x*CELL,y*CELL,CELL,CELL);
    }
    ctx.strokeStyle='#314354'; ctx.lineWidth=3;
    for(let x=0;x<COLS;x++) {
      ctx.beginPath(); ctx.moveTo(x*CELL+7,0); ctx.lineTo(x*CELL+7,canvas.height); ctx.stroke();
    }
    ctx.strokeStyle='#61707d'; ctx.lineWidth=2;
    for(const y of [17,53]) {
      ctx.beginPath(); ctx.moveTo(0,y); ctx.lineTo(canvas.width,y); ctx.stroke();
    }

    // Platform edges.
    const platH=34;
    ctx.fillStyle='#526478'; ctx.fillRect(0,0,canvas.width,platH); ctx.fillRect(0,canvas.height-platH,canvas.width,platH);
    ctx.fillStyle='#f5c451'; ctx.fillRect(0,platH-6,canvas.width,6); ctx.fillRect(0,canvas.height-platH,canvas.width,6);
    ctx.fillStyle='#d9e1e8';
    for(let x=8;x<canvas.width;x+=28) {
      ctx.fillRect(x,9,15,4); ctx.fillRect(x,canvas.height-13,15,4);
    }
    ctx.fillStyle='#3f5266'; ctx.fillRect(0,0,10,canvas.height); ctx.fillRect(canvas.width-10,0,10,canvas.height);
    ctx.fillStyle='#f5c451'; ctx.fillRect(8,0,4,canvas.height); ctx.fillRect(canvas.width-12,0,4,canvas.height);

    // Station signs.
    ctx.font='bold 10px Trebuchet MS'; ctx.textAlign='center';
    for(let x=90;x<canvas.width;x+=170) {
      ctx.fillStyle='#273a4e'; roundedRect(x-36,6,72,20,5); ctx.fill();
      ctx.fillStyle='#d9e8f5'; ctx.fillText('PLATFORM '+(1+Math.floor(x/170)),x,20);
      ctx.fillStyle='#273a4e'; roundedRect(x-36,canvas.height-26,72,20,5); ctx.fill();
      ctx.fillStyle='#d9e8f5'; ctx.fillText('STATION',x,canvas.height-12);
    }
  }

  function drawPassenger(p,t) {
    const cx=p.x*CELL+CELL/2, cy=p.y*CELL+CELL/2;
    const py = p.y===0 ? cy+1 : cy-1;
    ctx.save();
    ctx.fillStyle='#0005'; ctx.beginPath(); ctx.ellipse(cx,py+10,10,4,0,0,Math.PI*2); ctx.fill();
    // body
    ctx.fillStyle=p.color; roundedRect(cx-9,py-1,18,13,5); ctx.fill();
    // head
    ctx.fillStyle='#ffd7b0'; ctx.beginPath(); ctx.arc(cx,py-8,8,0,Math.PI*2); ctx.fill();
    // hair
    ctx.fillStyle='#392b2a'; ctx.beginPath(); ctx.arc(cx,py-10,8,Math.PI,Math.PI*2); ctx.fill();
    // eyes
    ctx.fillStyle='#182230'; ctx.beginPath(); ctx.arc(cx-3,py-7,1.2,0,7); ctx.arc(cx+3,py-7,1.2,0,7); ctx.fill();
    // waving arm
    ctx.strokeStyle=p.color; ctx.lineWidth=4; ctx.lineCap='round';
    ctx.beginPath(); ctx.moveTo(cx+7,py+3); ctx.lineTo(cx+12,py-3+Math.sin(t/180+p.phase)*2); ctx.stroke();
    // sign
    ctx.fillStyle='#f8fafc'; roundedRect(cx-12,py-16,24,9,3); ctx.fill();
    ctx.fillStyle='#2563eb'; ctx.font='bold 7px Trebuchet MS'; ctx.textAlign='center';
    ctx.fillText('WAIT',cx,py-9);
    ctx.restore();
  }

  function drawWagon(x,y,index,t) {
    const pad=2, w=CELL-pad*2, h=CELL-pad*2;
    const color=colors[index%colors.length];
    ctx.save();
    ctx.translate(x*CELL+pad, y*CELL+pad);
    ctx.fillStyle='#0006'; roundedRect(2,4,w,h-2,7); ctx.fill();
    ctx.fillStyle=color; roundedRect(0,0,w,h-3,7); ctx.fill();
    ctx.fillStyle='#ffffff22'; roundedRect(3,3,w-6,8,4); ctx.fill();
    // windows
    for(let i=0;i<3;i++) {
      ctx.fillStyle='#bdeaff'; roundedRect(6+i*8,10,6,8,2); ctx.fill();
    }
    // little passenger faces
    ctx.fillStyle='#ffd7b0';
    for(let i=0;i<3;i++) { ctx.beginPath(); ctx.arc(9+i*8,14,3.2,0,7); ctx.fill(); }
    ctx.fillStyle='#26364a';
    for(let i=0;i<3;i++) { ctx.beginPath(); ctx.arc(8+i*8,13,1,0,7); ctx.arc(10+i*8,13,1,0,7); ctx.fill(); }
    // coupling and wheels
    ctx.fillStyle='#d9e2ec'; ctx.fillRect(-2,12,4,4);
    ctx.fillStyle='#111827';
    for(const wx of [7,w-7]) { ctx.beginPath(); ctx.arc(wx,h-1,5,0,7); ctx.fill(); ctx.fillStyle='#94a3b8'; ctx.beginPath(); ctx.arc(wx,h-1,2,0,7); ctx.fill(); ctx.fillStyle='#111827'; }
    ctx.restore();
  }

  function drawLocomotive(x,y,t) {
    const pad=2, w=CELL-pad*2, h=CELL-pad*2;
    ctx.save();
    ctx.translate(x*CELL+pad,y*CELL+pad);
    ctx.fillStyle='#0007'; roundedRect(3,4,w,h-2,7); ctx.fill();
    // boiler
    ctx.fillStyle='#f59e0b'; roundedRect(0,8,w,19,7); ctx.fill();
    ctx.fillStyle='#fbbf24'; roundedRect(2,8,w-4,7,4); ctx.fill();
    // cab
    ctx.fillStyle='#dc2626'; roundedRect(0,1,12,25,5); ctx.fill();
    ctx.fillStyle='#bdeaff'; roundedRect(3,5,7,9,2); ctx.fill();
    ctx.fillStyle='#334155'; ctx.beginPath(); ctx.arc(6.5,9.5,1.5,0,7); ctx.fill();
    // chimney and steam
    ctx.fillStyle='#374151'; roundedRect(w-12,1,6,11,2); ctx.fill();
    ctx.fillStyle='#e2e8f0'; roundedRect(w-13,-1,8,4,2); ctx.fill();
    const puff = (t/60)%1;
    ctx.fillStyle=`rgba(226,232,240,${.7-puff*.6})`;
    ctx.beginPath(); ctx.arc(w-8,-3-puff*9,3+puff*4,0,7); ctx.fill();
    // headlight
    ctx.fillStyle='#fff7b2'; ctx.beginPath(); ctx.arc(w-2,15,4,0,7); ctx.fill();
    ctx.strokeStyle='#fef08a'; ctx.beginPath(); ctx.moveTo(w+1,15); ctx.lineTo(w+8+Math.sin(t/100)*2,10); ctx.lineTo(w+8,20); ctx.stroke();
    // wheels
    ctx.fillStyle='#111827';
    for(const wx of [8,w-8]) { ctx.beginPath(); ctx.arc(wx,h-1,6,0,7); ctx.fill(); ctx.fillStyle='#94a3b8'; ctx.beginPath(); ctx.arc(wx,h-1,2.6,0,7); ctx.fill(); ctx.fillStyle='#111827'; }
    ctx.restore();
  }

  function drawTrain(t) {
    for(let i=train.length-1;i>=1;i--) drawWagon(train[i].x,train[i].y,i-1,t);
    drawLocomotive(train[0].x,train[0].y,t);
  }

  function draw(t) {
    drawBackground(t);
    passengers.forEach(p=>drawPassenger(p,t));
    drawTrain(t);
    particles.forEach(p=>{
      ctx.globalAlpha=p.life; ctx.fillStyle=p.color;
      ctx.fillRect(p.x-2,p.y-2,4,4);
    });
    ctx.globalAlpha=1;
    if(flash>0) {
      ctx.fillStyle=`rgba(253,224,71,${flash*.35})`; ctx.fillRect(0,0,canvas.width,canvas.height);
      flash-=.02;
    }
  }

  function loop(now) {
    if(!running) return;
    const dt=now-lastTime; lastTime=now;
    const interval=Math.max(75,145-(level-1)*12);
    stepTimer+=dt;
    if(stepTimer>=interval) { stepTimer=0; update(); }
    if(running) draw(now);
    if(running) requestAnimationFrame(loop);
  }

  window.addEventListener('keydown',e=>{
    const d=keyMap[e.key];
    if(d) {
      e.preventDefault();
      if(!running) { start(); return; }
      const nd=DIRS[d];
      if(nd.x!==-direction.x || nd.y!==-direction.y) nextDirection=nd;
      demo=false;
    } else if(e.key===' ' && !running) {
      e.preventDefault(); start();
    }
  });

  startBtn.addEventListener('click',start);
  canvas.addEventListener('click',()=>{ if(!running) start(); });

  reset();
  let idleT=0;
  function idleLoop(t){ if(!running){ idleT=t; draw(t); requestAnimationFrame(idleLoop);} }
  requestAnimationFrame(idleLoop);
})();
</script>
</body>
</html>
Reasoning trace (362 tokens)
We need create HTML snake train game, visible, self-playing demo behind click/press key message. Need single code block. Let's design polished canvas game. Train snake moving in grid, locomotive head + colorful wagons, passengers on platform waiting; train collects by passing over passenger. Self-play AI. Controls arrow/WASD; click to start. Score, passengers, level. Canvas 900x600 maybe responsive. Include instructions overlay.

Implementation: grid 24x16 cell 32? canvas logical 768x512. Use canvas responsive CSS. Station platforms along edges with waiting passengers; pickups at any cell on platform edge. Train grows wagons. Speed increases slightly.

AI demo: simple pathfinding-ish random safe moves; snake train body grid. To avoid complexity: direction changes at random when safe, prefer toward nearest passenger with basic BFS on occupied grid. Implement BFS from head to any passenger avoiding train occupancy, choose first step. Occasionally random. Fine.

Rendering: background dark, tracks grid rails, platforms edges (top and bottom rows? platforms along left/right columns better). Let's do canvas 900x600, grid 25x17 of 36px? 25*36=900, 17*36=612. Use 24x16 cell 36 = 864x576. Canvas logical 864x576.

Train occupies cells list head first. Locomotive drawn oriented with wheels, chimney, light. Wagons colorful with windows passengers inside. Passengers waiting on platforms (top and bottom rows, maybe columns edges). Pick up by head on passenger cell.

Scoring, passenger counter. When pick up, spawn new passenger elsewhere. Game over on collision; demo AI hopefully plays well.

Overlay with start message on top.

Need exactly one code block.