Train snakeOne-line
Nemotron 3.5 Super VL (free)
by NVIDIAReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 1 min 9 s
- Cost
- $0
- Output tokens
- 6,504
- Spent thinking
- 0 tokens
- Speed
- 94.7 tok/s
- Console errors
- 0
- First token after
- 407 ms
- First visible text after
- 407 ms
- Prompt tokens
- 379
- Code size
- 18.1 KB
- Finish reason
- stop
- Served by
- Nvidia
- Model id
nvidia/nemotron-3.5-super-vl:free- Reasoning sent
{"effort":"none"}- Max output
- 32,000 tokens
- Generated
- Nov 9, 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 · 715 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Train Snake - Pick Up Passengers!</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
background: #87ceeb;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: #333;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
overflow: hidden;
touch-action: none;
}
h1 {
color: #e74c3c;
text-shadow: 2px 2px 0 #fff, 4px 4px 0 rgba(0,0,0,0.1);
font-size: 2.5rem;
margin-bottom: 0.5rem;
text-align: center;
}
.container {
position: relative;
background: linear-gradient(#a8e6cf, #7dceda);
border-radius: 16px;
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
padding: 20px;
max-width: 95vw;
max-height: 90vh;
display: flex;
flex-direction: column;
align-items: center;
border: 4px solid #2c3e50;
outline: none;
}
canvas {
border-radius: 8px;
background: #f1f8e9;
box-shadow: inset 0 0 20px rgba(0,0,0,0.1);
display: block;
max-width: 100%;
height: auto;
}
.ui {
position: absolute;
top: 15px;
left: 15px;
right: 15px;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 1.1rem;
font-weight: bold;
color: #2c3e50;
text-shadow: 1px 1px 0 rgba(255,255,255,0.8);
pointer-events: none;
}
.overlay {
position: absolute;
inset: 0;
background: rgba(255,255,255,0.85);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 16px;
z-index: 10;
cursor: pointer;
text-align: center;
padding: 20px;
}
.overlay h2 { color: #e74c3c; font-size: 2rem; margin-bottom: 0.5rem; }
.overlay p { margin-bottom: 1.5rem; font-size: 1.1rem; line-height: 1.4; color: #555; }
.start-btn {
background: #2ecc71;
color: white;
border: none;
padding: 12px 28px;
font-size: 1.1rem;
font-weight: bold;
border-radius: 8px;
cursor: pointer;
box-shadow: 0 4px #27ae60;
transform: translateY(0);
}
.start-btn:active { transform: translateY(2px); box-shadow: 0 2px #27ae60; }
.controls-hint {
margin-top: 0.8rem;
font-size: 0.85rem;
color: #777;
}
@media (max-width: 480px) {
h1 { font-size: 1.8rem; }
.container { padding: 10px; }
.ui { font-size: 0.95rem; top: 8px; left: 8px; right: 8px; }
.overlay h2 { font-size: 1.5rem; }
}
</style>
</head>
<body>
<h1>🚂 Train Snake</h1>
<p style="text-align:center; margin-bottom: 1rem; color:#555;">Pick up passengers waiting on the platform!</p>
<div class="container" tabindex="0" role="application" aria-label="Train Snake Game">
<div class="ui">
<span id="passengers">Passengers: 0</span>
<span id="score">Score: 0</span>
</div>
<canvas id="gameCanvas"></canvas>
<div class="overlay" id="overlay">
<h2>🚂 Train Snake</h2>
<p id="overlayText">Click or press a key to start</p>
<button class="start-btn" id="startBtn">Start Game</button>
<div class="controls-hint">Use Arrow Keys or WASD to steer</div>
</div>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const overlay = document.getElementById('overlay');
const overlayText = document.getElementById('overlayText');
const startBtn = document.getElementById('startBtn');
const passengersEl = document.getElementById('passengers');
const scoreEl = document.getElementById('score');
// Game constants
const GRID = 30; // grid cell size
let COLS, ROWS;
// Colors
const COLORS = {
grass: '#a8e6cf',
station: '#dfe6e9',
track: '#b2bec3',
trainLoco: '#e74c3c',
trainLocoDark: '#c0392b',
wagon1: '#f1c40f',
wagon2: '#3498db',
wagon3: '#2ecc71',
wagon4: '#9b59b6',
passenger: '#ff7675',
platformEdge: '#2d3436',
smoke: '#dfe6e9'
};
let gameRunning = false;
let gameOver = false;
let score = 0;
let passengers = 0;
let animationId;
let lastTime = 0;
let moveInterval = 140; // ms between moves
let lastMoveTime = 0;
// Game state
let train = []; // array of segments {x, y}
let direction = 'right'; // current direction
let nextDirection = 'right'; // queued direction
let passenger = null; // {x, y}
let platformTiles = []; // array of {x, y}
let stations = []; // array of {x, y, w, h} platform areas
let particles = []; // for pickup effects
function resize() {
const container = document.querySelector('.container');
const maxW = Math.min(container.clientWidth - 40, 600);
const maxH = Math.min(container.clientHeight - 120, 500);
// Fit canvas to container with grid alignment
let w = Math.floor(maxW / GRID) * GRID;
let h = Math.floor(maxH / GRID) * GRID;
// Minimum size
w = Math.max(w, 300);
h = Math.max(h, 300);
canvas.width = w;
canvas.height = h;
COLS = w / GRID;
ROWS = h / GRID;
}
window.addEventListener('resize', resize);
resize();
// Initialize game
function initGame() {
// Start position in middle
const startX = Math.floor(COLS / 2);
const startY = Math.floor(ROWS / 2);
train = [
{x: startX, y: startY}, // locomotive (head)
{x: startX - 1, y: startY}, // wagon 1
{x: startX - 2, y: startY} // wagon 2
];
direction = 'right';
nextDirection = 'right';
score = 0;
passengers = 0;
passengersEl.textContent = 'Passengers: 0';
scoreEl.textContent = 'Score: 0';
particles = [];
generateStations();
spawnPassenger();
gameRunning = true;
gameOver = false;
lastMoveTime = performance.now();
overlay.style.display = 'none';
if (animationId) cancelAnimationFrame(animationId);
animate(performance.now());
}
function generateStations() {
stations = [];
platformTiles = [];
// Create 2-3 stations on the edges
const numStations = 2 + Math.floor(Math.random() * 2);
for (let i = 0; i < numStations; i++) {
// Station on edge
const side = Math.floor(Math.random() * 4); // 0=top,1=right,2=bottom,3=left
const w = 4 + Math.floor(Math.random() * 3); // width in tiles
const h = 3 + Math.floor(Math.random() * 2); // height in tiles
let x, y;
if (side === 0) { // top
x = Math.floor(Math.random() * (COLS - w));
y = 2;
} else if (side === 1) { // right
x = COLS - w - 2;
y = Math.floor(Math.random() * (ROWS - h));
} else if (side === 2) { // bottom
x = Math.floor(Math.random() * (COLS - w));
y = ROWS - h - 2;
} else { // left
x = 2;
y = Math.floor(Math.random() * (ROWS - h));
}
// Clamp
x = Math.max(1, Math.min(x, COLS - w - 1));
y = Math.max(1, Math.min(y, ROWS - h - 1));
stations.push({x, y, w, h});
// Platform tiles (inner area)
for (let dy = 1; dy < h - 1; dy++) {
for (let dx = 1; dx < w - 1; dx++) {
platformTiles.push({x: x + dx, y: y + dy});
}
}
}
}
function spawnPassenger() {
// Try to spawn on a platform tile not occupied by train
let attempts = 0;
while (attempts < 100) {
const tile = platformTiles[Math.floor(Math.random() * platformTiles.length)];
const occupied = train.some(seg => seg.x === tile.x && seg.y === tile.y);
if (!occupied) {
passenger = {x: tile.x, y: tile.y};
return;
}
attempts++;
}
// Fallback: any empty tile
while (attempts < 100) {
const x = Math.floor(Math.random() * COLS);
const y = Math.floor(Math.random() * ROWS);
const occupied = train.some(seg => seg.x === x && seg.y === y);
if (!occupied) {
passenger = {x, y};
return;
}
attempts++;
}
}
function getHead() {
return train[0];
}
function getNextHead() {
const head = getHead();
let nx = head.x;
let ny = head.y;
if (direction === 'up') ny--;
else if (direction === 'down') ny++;
else if (direction === 'left') nx--;
else if (direction === 'right') nx++;
// Wrap around
if (nx < 0) nx = COLS - 1;
if (nx >= COLS) nx = 0;
if (ny < 0) ny = ROWS - 1;
if (ny >= ROWS) ny = 0;
return {x: nx, y: ny};
}
function checkSelfCollision(head) {
// Check against body (excluding tail which will move)
for (let i = 1; i < train.length - 1; i++) {
if (train[i].x === head.x && train[i].y === head.y) return true;
}
return false;
}
function update() {
if (!gameRunning || gameOver) return;
direction = nextDirection;
const newHead = getNextHead();
// Self collision
if (checkSelfCollision(newHead)) {
gameOver = true;
showGameOver();
return;
}
// Check passenger pickup
const atePassenger = passenger && newHead.x === passenger.x && newHead.y === passenger.y;
train.unshift(newHead);
if (atePassenger) {
passengers++;
score += 10 + train.length; // bonus for longer train
passengersEl.textContent = 'Passengers: ' + passengers;
scoreEl.textContent = 'Score: ' + score;
createParticles(newHead.x, newHead.y, '#f1c40f');
spawnPassenger();
// Don't pop tail - train grows
} else {
train.pop();
}
// Gradually speed up
moveInterval = Math.max(70, 140 - passengers * 4);
}
function createParticles(x, y, color) {
for (let i = 0; i < 8; i++) {
particles.push({
x: x * GRID + GRID/2,
y: y * GRID + GRID/2,
vx: (Math.random() - 0.5) * 4,
vy: (Math.random() - 0.5) * 4,
life: 1.0,
color: color
});
}
}
function updateParticles() {
for (let i = particles.length - 1; i >= 0; i--) {
const p = particles[i];
p.x += p.vx;
p.y += p.vy;
p.life -= 0.05;
if (p.life <= 0) particles.splice(i, 1);
}
}
function drawGrid() {
// Background
ctx.fillStyle = COLORS.grass;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw stations/platforms
for (const station of stations) {
// Station building
ctx.fillStyle = '#bdc3c7';
ctx.fillRect(station.x * GRID, station.y * GRID, station.w * GRID, station.h * GRID);
ctx.strokeStyle = '#7f8c8d';
ctx.lineWidth = 2;
ctx.strokeRect(station.x * GRID, station.y * GRID, station.w * GRID, station.h * GRID);
// Platform area (lighter)
ctx.fillStyle = '#ecf0f1';
ctx.fillRect((station.x + 1) * GRID, (station.y + 1) * GRID, (station.w - 2) * GRID, (station.h - 2) * GRID);
// Platform edge line
ctx.strokeStyle = '#95a5a6';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo((station.x + 1) * GRID, station.y * GRID);
ctx.lineTo((station.x + station.w - 1) * GRID, station.y * GRID);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(station.x * GRID, (station.y + 1) * GRID);
ctx.lineTo(station.x * GRID, (station.y + station.h - 1) * GRID);
ctx.stroke();
ctx.beginPath();
ctx.moveTo((station.x + station.w) * GRID, (station.y + 1) * GRID);
ctx.lineTo((station.x + station.w) * GRID, (station.y + station.h - 1) * GRID);
ctx.stroke();
ctx.beginPath();
ctx.moveTo((station.x + 1) * GRID, (station.y + station.h) * GRID);
ctx.lineTo((station.x + station.w - 1) * GRID, (station.y + station.h) * GRID);
ctx.stroke();
}
}
function drawPassenger() {
if (!passenger) return;
const px = passenger.x * GRID;
const py = passenger.y * GRID;
// Person waiting on platform
ctx.fillStyle = COLORS.passenger;
ctx.beginPath();
ctx.arc(px + GRID/2, py + GRID/3, GRID/4, 0, Math.PI * 2);
ctx.fill();
// Body
ctx.fillStyle = '#2c3e50';
ctx.fillRect(px + GRID/3, py + GRID/3, GRID/3, GRID/3);
// Arms out (waiting)
ctx.strokeStyle = '#2c3e50';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(px + GRID/3, py + GRID/2);
ctx.lineTo(px + GRID/4, py + GRID/2);
ctx.moveTo(px + GRID*2/3, py + GRID/2);
ctx.lineTo(px + GRID*3/4, py + GRID/2);
ctx.stroke();
// "!" sign
ctx.fillStyle = '#e74c3c';
ctx.font = 'bold 16px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('!', px + GRID/2, py + GRID/6);
}
function drawTrain() {
if (train.length === 0) return;
const head = train[0];
// Draw body segments (wagons) first (behind head)
for (let i = train.length - 1; i >= 1; i--) {
const seg = train[i];
const prev = train[i - 1];
const wagonColor = COLORS[`wagon${((i - 1) % 4) + 1}`];
drawWagon(seg.x, seg.y, prev.x, prev.y, wagonColor, i === train.length - 1);
}
// Draw locomotive (head)
drawLocomotive(head.x, head.y, direction);
}
function drawLocomotive(x, y, dir) {
const px = x * GRID;
const py = y * GRID;
const s = GRID;
ctx.save();
ctx.translate(px + s/2, py + s/2);
// Rotate based on direction
let angle = 0;
if (dir === 'right') angle = 0;
else if (dir === 'down') angle = Math.PI / 2;
else if (dir === 'left') angle = Math.PI;
else if (dir === 'up') angle = -Math.PI / 2;
ctx.rotate(angle);
// Shadow
ctx.fillStyle = 'rgba(0,0,0,0.15)';
ctx.beginPath();
ctx.roundRect? ctx.roundRect(-s/2 + 2, -s/2 + 2, s - 4, s - 4, 4) : ctx.rect(-s/2 + 2, -s/2 + 2, s - 4, s - 4);
ctx.fill();
// Main body
ctx.fillStyle = COLORS.trainLoco;
ctx.beginPath();
ctx.roundRect? ctx.roundRect(-s/2 + 1, -s/2 + 1, s - 2, s - 2, 5) : ctx.rect(-s/2 + 1, -s/2 + 1, s - 2, s - 2);
ctx.fill();
// Cab window
ctx.fillStyle = '#aed6f1';
ctx.fillRect(s/2 - 5, -s/2 + 4, 6, s - 8);
// Front cowcatcher
ctx.fillStyle = COLORS.trainLocoDark;
ctx.beginPath();
ctx.moveTo(-s/2 + 2, -s/2 + 2);
ctx.lineTo(-s/2 + 2, s/2 - 2);
ctx.lineTo(-s/2 - 3, 0);
ctx.closePath();
ctx.fill();
// Smokestack
ctx.fillStyle = COLORS.trainLocoDark;
ctx.fillRect(-s/2 + 4, -s/2 - 3, 5, 4);
// Smoke puffs
ctx.fillStyle = COLORS.smoke;
ctx.beginPath();
ctx.arc(-s/2 + 2, -s/2 - 6, 3, 0, Math.PI*2);
ctx.arc(-s/2 + 5, -s/2 - 8, 4, 0, Math.PI*2);
ctx.fill();
// Wheels
ctx.fillStyle = '#2c3e50';
ctx.beginPath();
ctx.arc(-s/2 + 6, s/2 - 3, 3, 0, Math.PI*2);
ctx.arc(s/2 - 6, s/2 - 3, 3, 0, Math.PI*2);
ctx.fill();
// Light
ctx.fillStyle = '#f1c40f';
ctx.beginPath();
ctx.arc(-s/2 + 3, 0, 2, 0, Math.PI*2);
ctx.fill();
ctx.restore();
}
function drawWagon(x, y, nextX, nextY, color, isLast) {
const px = x * GRID;
const py = y * GRID;
const s = GRID;
ctx.save();
ctx.translate(px + s/2, py + s/2);
// Determine orientation toward next segment (the one in front)
let angle = 0;
const dx = nextX - x;
const dy = nextY - y;
// Handle wrap-around
let adjDx = dx;
let adjDy = dy;
if (Math.abs(dx) > COLS/2) adjDx = dx > 0 ? -1 : 1;
if (Math.abs(dy) > ROWS/2) adjDy = dy > 0 ? -1 : 1;
if (adjDx === 1) angle = 0; // next is to right
else if (adjDx === -1) angle = Math.PI; // next is to left
else if (adjDy === 1) angle = Math.PI / 2; // next is down
else if (adjDy === -1) angle = -Math.PI / 2; // next is up
ctx.rotate(angle);
// Shadow
ctx.fillStyle = 'rgba(0,0,0,0.1)';
ctx.beginPath();
ctx.roundRect? ctx.roundRect(-s/2 + 2, -s/2 + 2, s - 4, s - 4, 3) : ctx.rect(-s/2 + 2, -s/2 + 2, s - 4, s - 4);
ctx.fill();
// Wagon body
ctx.fillStyle = color;
ctx.beginPath();
ctx.roundRect? ctx.roundRect(-s/2 + 1, -s/2 + 1, s - 2, s - 2, 4) : ctx.rect(-s/2 + 1, -s/2 + 1, s - 2, s - 2);
ctx.fill();
// Decorative stripe
ctx.fillStyle = 'rgba(255,255,255,0.3)';
ctx.fillRect(-s/2 + 4, -s/2 + 4, 4, s - 8);
// Wheels
ctx.fillStyle = '#34495e';
ctx.beginPath();
ctx.arc(-s/2 + 5, s/2 - 3, 2.5, 0, Math.PI*2);
ctx.arc(s/2 - 5, s/2 - 3, 2.5, 0, Math.PI*2);
ctx.fill();
// Coupling connector at back
if (isLast) {
ctx.fillStyle = '#7f8c8d';
ctx.fillRect(s/2 - 2, -2, 4, 4);
}
ctx.restore();
}
function drawParticles() {
for (const p of particles) {
ctx.globalAlpha = p.life;
ctx.fillStyle = p.color;
ctx.beginPath();
ctx.arc(p.x, p.y, 2, 0, Math.PI * 2);
ctx.fill();
ctx.globalAlpha = 1.0;
}
}
function drawUIOverlay() {
// Already drawn in HTML, but we can add a "Game Over" text here if needed
}
function animate(time) {
if (!gameRunning) return;
const delta = time - lastTime;
lastTime = time;
if (!lastMoveTime) lastMoveTime = time;
if (time - lastMoveTime > moveInterval) {
update();
lastMoveTime = time;
}
updateParticles();
drawGrid();
drawPassenger();
drawTrain();
drawParticles();
animationId = requestAnimationFrame(animate);
}
function showGameOver() {
gameRunning = false;
overlayText.textContent = `Game Over! You picked up ${passengers} passengers.`;
startBtn.textContent = 'Try Again';
overlay.style.display = 'flex';
}
// Input handling
function setDirection(dir) {
if (!gameRunning) return;
const opposites = {up: 'down', down: 'up', left: 'right', right: 'left'};
if (opposites[dir] !== direction) {
nextDirection = dir;
}
}
window.addEventListener('keydown', (e) => {
if (e.key === 'ArrowUp' || e.key === 'w') setDirection('up');
else if (e.key === 'ArrowDown' || e.key === 's') setDirection('down');
else if (e.key === 'ArrowLeft' || e.key === 'a') setDirection('left');
else if (e.key === 'ArrowRight' || e.key === 'd') setDirection('right');
// Allow starting with key
if (!gameRunning && (e.key === 'Enter' || e.key === ' ')) {
e.preventDefault();
initGame();
}
});
// Touch controls for mobile
let touchStartX = 0;
let touchStartY = 0;
canvas.addEventListener('touchstart', (e) => {
touchStartX = e.touches[0].clientX;
touchStartY = e.touches[0].clientY;
}, {passive: false});
canvas.addEventListener('touchend', (e) => {
if (!gameRunning) {
initGame();
return;
}
const touchEndX = e.changedTouches[0].clientX;
const touchEndY = e.changedTouches[0].clientY;
const dx = touchEndX - touchStartX;
const dy = touchEndY - touchStartY;
if (Math.abs(dx) > Math.abs(dy)) {
setDirection(dx > 0 ? 'right' : 'left');
} else {
setDirection(dy > 0 ? 'down' : 'up');
}
}, {passive: false});
// Button clicks
startBtn.addEventListener('click', () => {
initGame();
});
canvas.addEventListener('click', () => {
if (!gameRunning) {
initGame();
} else {
canvas.focus();
}
});
// Initial overlay
overlay.style.display = 'focus';
// Start animation loop (paused until init)
lastTime = performance.now();
animate(performance.now());
</script>
</body>
</html>