Train snakeOne-line
Gemma 4 31B
by Googlereasoning defaultClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 1 min 39 s
- Cost
- $0.0011
- Output tokens
- 3,236
- Spent thinking
- 0 tokens
- Speed
- 32.8 tok/s
- Console errors
- 0
- First token after
- 507 ms
- First visible text after
- 507 ms
- Prompt tokens
- 385
- Code size
- 11.3 KB
- Finish reason
- stop
- Served by
- CoreWeave
- Model id
google/gemma-4-31b-it- 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 · 338 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Passenger Train Express</title>
<style>
body {
margin: 0;
padding: 0;
background-color: #2c3e50;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
overflow: hidden;
}
#game-container {
position: relative;
box-shadow: 0 0 50px rgba(0,0,0,0.5);
border: 10px solid #7f8c8d;
border-radius: 8px;
background-color: #34495e;
}
canvas {
display: block;
image-rendering: pixelated;
}
#ui-layer {
position: absolute;
top: 20px;
left: 20px;
pointer-events: none;
}
.stat {
font-size: 24px;
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
margin-bottom: 5px;
}
#overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.6);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
z-index: 10;
cursor: pointer;
}
#overlay h1 {
font-size: 48px;
margin-bottom: 10px;
color: #f1c40f;
}
#overlay p {
font-size: 20px;
margin-bottom: 20px;
}
.btn {
padding: 15px 30px;
background: #e67e22;
color: white;
border: none;
border-radius: 5px;
font-size: 20px;
font-weight: bold;
cursor: pointer;
transition: background 0.3s;
}
.btn:hover {
background: #d35400;
}
</style>
</head>
<body>
<div id="game-container">
<div id="ui-layer">
<div class="stat">Passengers: <span id="score">0</span></div>
</div>
<canvas id="gameCanvas" width="800" height="600"></canvas>
<div id="overlay" id="start-screen">
<h1>Train Express</h1>
<p>Collect passengers to grow your train!<br>Don't hit the rails or yourself.</p>
<div class="btn">CLICK TO START</div>
<p style="margin-top: 20px; font-size: 14px;">(Arrow Keys or WASD to Drive)</p>
</div>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreEl = document.getElementById('score');
const overlay = document.getElementById('overlay');
// Constants
const GRID_SIZE = 40;
const WIDTH = canvas.width;
const HEIGHT = canvas.height;
const COLS = WIDTH / GRID_SIZE;
const ROWS = HEIGHT / GRID_SIZE;
// Game State
let score = 0;
let gameActive = false;
let autoPlay = true;
let train = [];
let direction = { x: 1, y: 0 };
let nextDirection = { x: 1, y: 0 };
let passenger = { x: 0, y: 0 };
let gameLoop;
const colors = ['#e74c3c', '#3498db', '#2ecc71', '#f1c40f', '#9b59b6', '#e67e22', '#1abc9c'];
function init() {
score = 0;
scoreEl.textContent = score;
direction = { x: 1, y: 0 };
nextDirection = { x: 1, y: 0 };
// Start with a locomotive and one wagon
train = [
{ x: 5, y: 7, color: '#333', isLocomotive: true },
{ x: 4, y: 7, color: colors[0], isLocomotive: false },
{ x: 3, y: 7, color: colors[1], isLocomotive: false }
];
spawnPassenger();
}
function spawnPassenger() {
passenger.x = Math.floor(Math.random() * COLS);
passenger.y = Math.floor(Math.random() * ROWS);
// Don't spawn on train
train.forEach(segment => {
if (segment.x === passenger.x && segment.y === passenger.y) {
spawnPassenger();
}
});
}
function update() {
if (!gameActive) return;
// AI Logic (Auto-play)
if (autoPlay) {
const head = train[0];
const dx = passenger.x - head.x;
const dy = passenger.y - head.y;
if (dx !== 0 && (Math.abs(dx) > Math.abs(dy) || nextDirection.y !== 0)) {
let wantX = dx > 0 ? 1 : -1;
if (!(nextDirection.x === -wantX && nextDirection.y === 0)) {
nextDirection = { x: wantX, y: 0 };
}
} else if (dy !== 0) {
let wantY = dy > 0 ? 1 : -1;
if (!(nextDirection.x === 0 && nextDirection.y === -wantY)) {
nextDirection = { x: 0, y: wantY };
}
}
}
direction = nextDirection;
const head = { ...train[0] };
head.x += direction.x;
head.y += direction.y;
// Collision: Walls
if (head.x < 0 || head.x >= COLS || head.y < 0 || head.y >= ROWS) {
gameOver();
return;
}
// Collision: Self
for (let i = 1; i < train.length; i++) {
if (head.x === train[i].x && head.y === train[i].y) {
gameOver();
return;
}
}
// Move train
train.unshift(head);
// Check passenger pickup
if (head.x === passenger.x && head.y === passenger.y) {
score++;
scoreEl.textContent = score;
// Add a new colorful wagon
const lastWagon = train[train.length - 1];
const newWagon = {
x: lastWagon.x,
y: lastWagon.y,
color: colors[score % colors.length],
isLocomotive: false
};
// We don't pop, so the train grows
spawnPassenger();
} else {
// Remove last wagon if no passenger eaten
train.pop();
}
// Ensure the head is always the locomotive
train[0].isLocomotive = true;
train[0].color = '#333';
for(let i=1; i<train.length; i++) train[i].isLocomotive = false;
}
function draw() {
// Clear Background
ctx.fillStyle = '#34495e';
ctx.fillRect(0, 0, WIDTH, HEIGHT);
// Draw Grid/Rails (Visual only)
ctx.strokeStyle = '#2c3e50';
ctx.lineWidth = 1;
for (let i = 0; i <= WIDTH; i += GRID_SIZE) {
ctx.beginPath(); ctx.moveTo(i, 0); ctx.lineTo(i, HEIGHT); ctx.stroke();
}
for (let j = 0; j <= HEIGHT; j += GRID_SIZE) {
ctx.beginPath(); ctx.moveTo(0, j); ctx.lineTo(WIDTH, j); ctx.stroke();
}
// Draw Passenger (The "Platform" person)
const pX = passenger.x * GRID_SIZE;
const pY = passenger.y * GRID_SIZE;
ctx.fillStyle = '#f1c40f';
ctx.beginPath();
ctx.arc(pX + GRID_SIZE/2, pY + GRID_SIZE/2, 12, 0, Math.PI * 2);
ctx.fill();
// Simple passenger stick figure
ctx.strokeStyle = 'white';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(pX + GRID_SIZE/2, pY + GRID_SIZE/2 + 12);
ctx.lineTo(pX + GRID_SIZE/2, pY + GRID_SIZE/2 + 20);
ctx.stroke();
// Draw Train
train.forEach((segment, index) => {
const x = segment.x * GRID_SIZE;
const y = segment.y * GRID_SIZE;
const padding = 4;
ctx.fillStyle = segment.color;
if (segment.isLocomotive) {
// Locomotive shape
ctx.fillRect(x + padding, y + padding, GRID_SIZE - padding * 2, GRID_SIZE - padding * 2);
// Chimney
ctx.fillStyle = '#222';
ctx.fillRect(x + GRID_SIZE/3, y + padding, GRID_SIZE/3, GRID_SIZE/3);
// Window
ctx.fillStyle = '#add8e6';
ctx.fillRect(x + GRID_SIZE/4, y + GRID_SIZE/3, GRID_SIZE/2, GRID_SIZE/4);
} else {
// Wagon shape
ctx.beginPath();
ctx.roundRect(x + padding + 2, y + padding + 4, GRID_SIZE - padding * 2 - 4, GRID_SIZE - padding * 2 - 8, 5);
ctx.fill();
// Wagon detail (line)
ctx.strokeStyle = 'rgba(0,0,0,0.2)';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(x + padding + 2, y + GRID_SIZE/2);
ctx.lineTo(x + GRID_SIZE - padding - 2, y + GRID_SIZE/2);
ctx.stroke();
}
});
}
function gameOver() {
gameActive = false;
overlay.style.display = 'flex';
overlay.innerHTML = `<h1>CRASH!</h1><p>You collected ${score} passengers.</p><div class="btn">TRY AGAIN</div>`;
}
function gameStep() {
update();
draw();
}
// Input Handling
window.addEventListener('keydown', (e) => {
if (!gameActive) return;
autoPlay = false; // Disable AI once user interacts
switch(e.key) {
case 'ArrowUp': case 'w': if (direction.y === 0) nextDirection = { x: 0, y: -1 }; break;
case 'ArrowDown': case 's': if (direction.y === 0) nextDirection = { x: 0, y: 1 }; break;
case 'ArrowLeft': case 'a': if (direction.x === 0) nextDirection = { x: -1, y: 0 }; break;
case 'ArrowRight': case 'd': if (direction.x === 0) nextDirection = { x: 1, y: 0 }; break;
}
});
overlay.addEventListener('click', () => {
overlay.style.display = 'none';
gameActive = true;
init();
});
// Start loop
init();
setInterval(gameStep, 150);
// To make the demo feel "alive" before the user clicks,
// we let it run in auto-play mode but keep the overlay.
gameActive = true;
// When overlay is clicked, gameActive remains true and autoPlay will eventually switch to false on keydown.
// However, to strictly follow "click to start", we set gameActive = false initially
// and let the a loop just draw the initial state, then toggle it.
// Actually, let's just let the AI play behind the overlay for the screenshot.
</script>
</body>
</html>