Train snakeOne-line
Nemotron 3 Super
by NVIDIAreasoning defaultClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 34.4 s
- Cost
- $0.0021
- Output tokens
- 5,104
- Spent thinking
- 3,363 tokens
- Speed
- 151.8 tok/s
- Console errors
- 0
- First token after
- 775 ms
- First visible text after
- 27.2 s
- Prompt tokens
- 379
- Code size
- 5.5 KB
- Finish reason
- stop
- Served by
- DeepInfra
- Model id
nvidia/nemotron-3-super-120b-a12b- Reasoning sent
model default- Max output
- 16,384 tokens
- Generated
- Nov 13, 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 · 185 lines
<!DOCTYPE html>
<html lang="en">
<html>
<head>
<meta charset="UTF-8">
<title>Train Snake – Pick Up Passengers</title>
<style>
body{margin:0;overflow:hidden;background:#111;display:flex;height:100vh;align-items:center;justify-content:center;color:#fff;font-family:sans-serif;}
#overlay{position:absolute;font-size:2rem;text-align:center;pointer-events:none;user-select:none;}
canvas{background:#0a0a0a;display:block;}
</style>
</head>
<body>
<div id="overlay">Click or press a key to start</canvas>
<canvas id="game"></canvas>
<script>
(() => {
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const overlay = document.getElementById('overlay');
let started = false;
// Game config
const COLS = 20;
const ROWS = 15;
let cellSize = 20;
let delay = 150; // ms between updates
let lastTick = 0;
// Snake data
let snake = []; // {x,y}
let wagonColors = []; // same length as snake, index 0 unused (head)
let dir = {x:1, y:0}; // initial direction right
let passenger = null;
const colors = ['#e74c3c','#f1c40f','#2ecc71','#3498db','#9b59b6','#1abc9c'];
function randomColor() {
return colors[Math.floor(Math.random()*colors.length)];
}
function resize() {
const wh = Math.min(window.innerWidth, window.innerHeight*0.9);
cellSize = Math.floor(wh / Math.max(COLS, ROWS));
canvas.width = COLS * cellSize;
canvas.height = ROWS * cellSize;
}
window.addEventListener('resize', resize);
resize();
function placePassenger() {
let pos;
do {
pos = {x: Math.floor(Math.random()*COLS), y: Math.floor(Math.random()*ROWS)};
} while (snake.some(s=>s.x===pos.x && s.y===pos.y));
passenger = pos;
}
function reset() {
snake = [{x:Math.floor(COLS/2), y:Math.floor(ROWS/2)}];
wagonColors = [null]; // head placeholder
dir = {x:1, y:0};
placePassenger();
}
function update() {
const head = {x:snake[0].x+dir.x, y:snake[0].y+dir.y};
// Simple AI: move towards passenger, avoid immediate reversal
let desired = {x:0, y:0};
if (Math.abs(passenger.x - snake[0].x) > Math.abs(passenger.y - snake[0].y)) {
desired.x = passenger.x > snake[0].x ? 1 : -1;
} else {
desired.y = passenger.y > snake[0].y ? 1 : -1;
}
// prevent reversing
if (desired.x === -dir.x && desired.y === -dir.y) {
// try orthogonal
if (desired.x !== 0) desired = {x:0, y: passenger.y > snake[0].y ? 1 : -1};
else desired = {x: passenger.x > snake[0].x ? 1 : -1, y:0};
}
// check if desired leads to self‑collision (except tail that will move)
let willCollide = snake.some((seg,i)=>{
if (i===snake.length-1) return false; // tail moves away
return seg.x===head.x && seg.y===head.y;
});
if (willCollide || head.x<0 || head.x>=COLS || head.y<0 || head.y>=ROWS) {
// try other directions in order
const opts = [{x:0,y:-1},{x:0,y:1},{x:-1,y:0},{x:1,y:0}];
for (const d of opts) {
if (d.x===-dir.x && d.y===-dir.y) continue;
const nh = {x:snake[0].x+d.x, y:snake[0].y+d.y};
let coll = snake.some((seg,i)=>{
if (i===snake.length-1) return false;
return seg.x===nh.x && seg.y===nh.y;
});
if (nh.x>=0 && nh.x<COLS && nh.y>=0 && nh.y<ROWS && !coll) {
desired = d;
break;
}
}
}
dir = desired;
// add new head
snake.unshift({x:snake[0].x+dir.x, y:snake[0].y+dir.y});
wagonColors.unshift(null); // placeholder for head
const ate = snake[0].x===passenger.x && snake[0].y===passenger.y;
if (ate) {
placePassenger();
wagonColors.push(randomColor()); // color for the new tail segment
} else {
snake.pop();
wagonColors.pop();
}
}
function draw() {
ctx.clearRect(0,0,canvas.width,canvas.height);
// ground
ctx.fillStyle = '#0a0a0a';
ctx.fillRect(0,0,canvas.width,canvas.height);
// rails
ctx.strokeStyle = '#555';
ctx.lineWidth = 4;
ctx.beginPath();
ctx.moveTo(0, canvas.height/2 - 10);
ctx.lineTo(canvas.width, canvas.height/2 - 10);
ctx.moveTo(0, canvas.height/2 + 10);
ctx.lineTo(canvas.width, canvas.height/2 + 10);
ctx.stroke();
// passenger
if (passenger) {
ctx.fillStyle = '#ffd700';
const px = passenger.x*cellSize + cellSize/2;
const py = passenger.y*cellSize + cellSize/2;
ctx.beginPath();
ctx.arc(px, py, cellSize*0.3, 0, Math.PI*2);
ctx.fill();
}
// snake
snake.forEach((seg,i)=>{
const x = seg.x*cellSize;
const y = seg.y*cellSize;
if (i===0) { // locomotive
ctx.fillStyle = '#8b4513';
ctx.fillRect(x, y, cellSize, cellSize);
// chimney
ctx.fillStyle = '#555';
ctx.fillRect(x+cellSize*0.3, y-cellSize*0.2, cellSize*0.4, cellSize*0.2);
} else {
ctx.fillStyle = wagonColors[i] || '#aaa';
ctx.fillRect(x, y, cellSize, cellSize);
}
});
}
function loop(timestamp) {
if (!lastTick) lastTick = timestamp;
const elapsed = timestamp - lastTick;
if (elapsed < delay) {
requestAnimationFrame(loop);
return;
}
lastTick = timestamp;
update();
draw();
requestAnimationFrame(loop);
}
function start() {
if (started) return;
started = true;
overlay.style.display = 'none';
reset();
requestAnimationFrame(loop);
}
// start on click or key press
window.addEventListener('click', start);
window.addEventListener('keydown', start);
})();
</script>
</body>
</html>Reasoning trace (3,363 tokens)
We need to create a Snake game where snake is a train: locomotive head and colorful wagons as body segments. The train picks up passengers waiting on the platform (like food). The game should be self-playing demo mode with a simple AI playing, behind a "Click or press a key to start" message.
Constraints: single HTML file, inline CSS and JS, no external resources except allowed CDN URLs (none specified). Must be responsive for 1280x800 and down to 375 width, no horizontal scroll.
We need to ensure something visible on first paint: perhaps a start screen with a train and platform and passengers.
Implement snake game: grid board, train moves, each time it eats a passenger, it adds a wagon (segment) of a random color. The locomotive is head. Passengers appear randomly on platform (grid cells). If train collides with itself or wall, game over.
Demo mode: simple AI that moves towards nearest passenger using simple logic (e.g., if head x < target x move right else left, else up/down). When start, we show message "Click or press a key to start". After click or keypress, start game with AI playing automatically. Or we could start AI immediately after click, but we need message before start.
We'll implement event listener for click or keydown to start.
We need to make it fit viewport: use canvas that scales.
Simplify: Use CSS to set canvas width/height to 100% width, max-width maybe. Use aspect ratio.
We'll set canvas width = min(window.innerWidth, window.innerHeight * (some ratio)). Use CSS to make canvas display:block; margin:auto; width:90vw; height:90vh; maybe.
But ensure no horizontal scroll: set body margin 0, overflow hidden.
Implementation details:
- Define constants: cellSize = 20 (or dynamic based on canvas size and grid count). Let's define grid size 20x20 or 25x25. Compute cellSize = canvas.width / cols.
- Use requestAnimationFrame for game loop.
- Snake: array of segments each {x,y}. Head at index 0. Each segment will be drawn as rectangle: locomotive (head) maybe a different shape (like a rectangle with a chimney). Wagons: rectangles with different colors.
Simplify: draw head as a darker color (e.g., #8B4513) with a small rectangle for chimney. Wagons: each segment gets a random color from a palette when added.
When train grows, we add a new segment at tail with a random color.
Passengers: small circles or rectangles representing people waiting on platform. Perhaps draw as small circles of a color (e.g., yellow) on top of track.
Platform: just background maybe with a line representing rails.
Simplify drawing: fill background with a dark color for ground, draw rails as two parallel lines, then draw train on top of rails, passengers as circles on rails.
But for simplicity, we can just draw grid cells and treat snake occupying cells, passengers occupying cells. Draw snake segments as rectangles filling cell, passengers as smaller circles inside cell.
We'll need to render.
Implement AI: each frame compute direction towards target passenger using simple Manhattan logic: if head.x < target.x -> dir = RIGHT; else if head.x > target.x -> LEFT; else if head.y < target.y -> DOWN; else UP. Prevent reversing into itself (if opposite direction of current). If would cause collision with body (except tail moving), we could try alternative direction (e.g., try other axis). Keep simple.
Game loop speed: update every 150ms.
Start screen: display message "Click or press a key to start". After start, hide message and begin game loop.
We need to ensure that after game over we could show "Game Over" and maybe restart on click.
But for demo mode, we can just let AI play continuously; after game over, reset and start again automatically? Could just reset after a short delay.
Implement.
Now code.
Let's craft HTML.
We'll have:
<body>
<div id="overlay">Click or press a key to start</div>
<canvas id="game"></canvas>
</div>
Style: body {margin:0; overflow:hidden; background:#222; display:flex; justify-content:center; align-items:center; height:100vh;}
#game {background:#111;}
#overlay {position:absolute; color:#fff; font-size:2rem; text-align:center; pointer-events:none; user-select:none;}
When start, we set overlay.style.display='none'.
Game logic:
- let canvas, ctx
- let cols, rows
- let cellSize
- let snake = [{x:Math.floor(cols/2), y:Math.floor(rows/2)}]
- let dir = {x:0, y:-1} initially up? We'll set initial direction right maybe.
- let passenger = null
- let wagonColors = [] parallel to snake body (excluding head?). We'll store color per segment.
When snake eats passenger: add new segment at tail (copy of current tail), assign random color from palette.
Draw:
function draw() {
ctx.clearRect(0,0,canvas.width,canvas.height);
// draw background
ctx.fillStyle = '#0a0a0a';
ctx.fillRect(0,0,canvas.width,canvas.height);
// draw rails
ctx.strokeStyle = '#555';
ctx.lineWidth = 4;
ctx.beginPath();
ctx.moveTo(0, canvas.height/2 - 10);
ctx.lineTo(canvas.width, canvas.height/2 - 10);
ctx.moveTo(0, canvas.height/2 + 10);
ctx.lineTo(canvas.width, canvas.height/2 + 10);
ctx.stroke();
// draw passengers
if (passenger) {
ctx.fillStyle = '#ffd700';
let px = passenger.x * cellSize + cellSize/2;
let py = passenger.y * cellSize + cellSize/2;
ctx.beginPath();
ctx.arc(px, py, cellSize*0.3, 0, Math.PI*2);
ctx.fill();
}
// draw snake
snake.forEach((seg,i)=> {
let x = seg.x * cellSize;
let y = seg.y * cellSize;
if (i===0) { // locomotive
ctx.fillStyle = '#8b4513';
ctx.fillRect(x, y, cellSize, cellSize);
// chimney
ctx.fillStyle = '#555';
ctx.fillRect(x+cellSize*0.3, y-cellSize*0.2, cellSize*0.4, cellSize*0.2);
} else {
// wagon color stored in wagonColors[i-1]
ctx.fillStyle = wagonColors[i-1] || '#aaa';
ctx.fillRect(x, y, cellSize, cellSize);
}
});
}
Update function:
function update() {
// AI logic to set dir if not set by user? We'll ignore user input for demo.
// but allow user to optionally control after start? Not required.
// compute target
if (!passenger) placePassenger();
let head = snake[0];
let dx = passenger.x - head.x;
let dy = passenger.y - head.y;
let newDir = {x:0, y:0};
if (Math.abs(dx) > Math.abs(dy)) {
newDir.x = dx > 0 ? 1 : -1;
newDir.y = 0;
} else {
newDir.x = 0;
newDir.y = dy > 0 ? 1 : -1;
}
// prevent reversing
if (newDir.x === -dir.x && newDir.y === -dir.y) {
// try alternative axis
if (Math.abs(dx) > 0) {
newDir = {x:0, y: dy>0 ? 1 : -1};
} else {
newDir = {x: dx>0 ? 1 : -1, y:0};
}
}
// check if moving newDir would cause self collision (except tail moving)
let nextHead = {x: head.x + newDir.x, y: head.y + newDir.y};
let collision = snake.some((seg,i)=> {
// allow overlap with tail segment that will move away this frame
if (i === snake.length-1) return false; // tail will move
return seg.x === nextHead.x && seg.y === nextHead.y;
});
// also wall collision
if (nextHead.x <0 || nextHead.x >= cols || nextHead.y <0 || nextHead.y >= rows || collision) {
// try other direction (simple fallback)
// try orthogonal direction
let altDirs = [{x:0,y:-1},{x:0,y:1},{x:-1,y:0},{x:1,y:0}];
for (let d of altDirs) {
if (d.x === -dir.x && d.y === -dir.y) continue;
let nh = {x: head.x + d.x, y: head.y + d.y};
let coll = snake.some((seg,i)=>{
if (i===snake.length-1) return false;
return seg.x===nh.x && seg.y===nh.y;
});
if (nh.x>=0 && nh.x<cols && nh.y>=0 && nh.y<rows && !coll) {
newDir = d;
break;
}
}
}
dir = newDir;
// move snake
let newHead = {x: head.x + dir.x, y: head.y + dir.y};
snake.unshift(newHead);
// check if ate passenger
if (newHead.x === passenger.x && newHead.y === passenger.y) {
// grow: add a wagon at tail (will be added next frame before removing tail? Actually we don't pop tail)
// assign random color to new wagon
wagonColors.unshift(randomColor()); // because new segment inserted at head? Actually we need to add at tail; easier: push color to wagonColors array when we grow, and when we move we shift colors accordingly.
// We'll handle: when we add new head, we also add a color for head? Head has no wagon color; wagons correspond to body segments indices 1..end.
// So we need to add a color for the new segment that will become the new tail later? Actually when we grow, we don't remove tail this frame, so length increases by 1.
// We'll push a color to wagonColors for the new segment (which will be at the same index as the new tail).
// Simpler: maintain wagonColors same length as snake-1 (body). When we add new head, we shift colors: unshift a placeholder? Actually head doesn't have color, so we shift colors array: unshift null? Then when we pop tail (if not growing) we pop last color.
// Let's implement: each frame we compute newHead, then we check if ate.
// If ate: we push newHead to snake, and we also push a new color to wagonColors (for the new segment that will become the tail later? Actually the new segment is at head, but we need colors for body segments (excluding head). The new head will become head, so we need to add a color for the segment that will be just behind head after movement? Actually after moving, the previous head becomes second segment (first wagon). So we need to shift colors accordingly.
// Simpler approach: store colors per segment same length as snake, but ignore for head.
// When we add new head, we unshift a dummy color (e.g., null) for head, and keep existing colors shifted.
// When we move without eating, we shift colors and pop last.
// Let's implement: wagonColors array same length as snake, where index 0 corresponds to head (unused). We'll set wagonColors[0] = null always.
// When moving: we unshift null (for new head) and if not ate, we pop last; if ate, we keep length (so we don't pop) and also assign a random color to the new tail? Actually the new tail is the previous last segment; we want to give it a color when it becomes a wagon (i.e., when we add a segment). The new segment added is at tail after we decide not to pop.
// So algorithm:
// let newHead = {...}
// snake.unshift(newHead)
// wagonColors.unshift(null) // placeholder for head
// if ate {
// wagonColors.push(randomColor()) // assign color to new tail (which is the old tail that we didn't pop)
// } else {
// wagonColors.pop() // remove last color (tail removed)
// }
// This works.
}
// else normal move: we will pop tail after updating colors.
// We'll implement after checking ate.
// Let's code accordingly.
// Actually we need to place passenger after eating.
// If ate: placePassenger()
// else: do nothing.
// After updating snake and wagonColors, if !ate we pop tail from snake and pop last from wagonColors (which we already did via pop?). Actually we popped wagonColors already; we need to also pop snake tail.
// Let's restructure.
We'll implement:
let ate = false;
let newHead = {x: snake[0].x + dir.x, y: snake[0].y + dir.y};
snake.unshift(newHead);
wagonColors.unshift(null); // placeholder for head
if (newHead.x === passenger.x && newHead.y === passenger.y) {
ate = true;
placePassenger();
wagonColors.push(randomColor()); // color for new tail
} else {
snake.pop();
wagonColors.pop();
}
Now draw using wagonColors[i] for segment i (i>=1). For i=0 we ignore.
Now implement placePassenger: random cell not occupied by snake.
Function randomColor: pick from palette e.g., ['#e74c3c','#f1c40f','#2ecc71','#3498db','#9b59b6','#1abc9c'].
Now AI may need to avoid immediate collision; our simple logic may cause it to reverse into itself occasionally; we have fallback.
Now implement game loop:
let lastTime = 0;
function tick(timestamp) {
if (!lastTime) lastTime = timestamp;
let delta = timestamp - lastTime;
if (delay > delta) {
requestAnimationFrame(tick);
return;
}
lastTime = timestamp;
update();
draw();
requestAnimationFrame(tick);
}
Set delay = 150.
Initialize: set canvas size based on window.
We'll add resize listener to adjust canvas size and recalc cols, rows, cellSize.
Now overlay: show initially. Add click and keydown listeners to start game: hide overlay, initialize game if not started, start loop.
We need to prevent multiple starts.
Let's code.
Potential pitfalls: need to ensure that canvas width/height are integer multiples of cellSize to avoid subpixel.
We'll compute cols = 20, rows = 15 (or based on size). Then set canvas.width = cols * cellSize, canvas.height = rows * cellSize. Choose cellSize = Math.min(Math.floor(window.innerWidth/cols), Math.floor(window.innerHeight/rows)). Then set canvas size accordingly.
Implement resize.
Now produce final code within a single HTML file.
Let's craft.
Check for errors: ensure variables scoped.
Let's write final code.