Train snakeOne-line
Dots3-Note Preview (free)
by Dots StudioReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 26.8 s
- Cost
- $0
- Output tokens
- 2,639
- Spent thinking
- 0 tokens
- Speed
- 100.7 tok/s
- Console errors
- 0
- First token after
- 553 ms
- First visible text after
- 553 ms
- Prompt tokens
- 365
- Code size
- 7.8 KB
- Finish reason
- stop
- Served by
- AtlasCloud
- Model id
dots-studio/dots-3-note-preview: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 · 281 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</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { height: 100%; background: #1a1a2e; color: #fff; font-family: 'Segoe UI', sans-serif; overflow: hidden; }
#wrap { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; }
canvas { background: #0f3460; border: 4px solid #16213e; border-radius: 12px; box-shadow: 0 0 20px rgba(0,0,0,0.5); display: block; max-width: 100%; height: auto; }
#hud { margin-top: 12px; font-size: 18px; display: flex; gap: 24px; }
#overlay { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; background: rgba(0,0,0,0.7); z-index: 10; }
#overlay h1 { font-size: 48px; color: #e94560; margin-bottom: 8px; text-shadow: 0 0 10px #e94560; }
#overlay p { font-size: 20px; margin-bottom: 24px; color: #aaa; }
button { padding: 12px 32px; font-size: 18px; background: #e94560; color: white; border: none; border-radius: 8px; cursor: pointer; transition: background 0.2s; }
button:hover { background: #ff6b81; }
#score { color: #e94560; font-weight: bold; }
</style>
</head>
<body>
<div id="wrap">
<canvas id="game" width="600" height="600"></canvas>
<div id="hud">
<div>Score: <span id="score">0</span></div>
<div>Passengers: <span id="passengers">0</span></div>
</div>
</div>
<div id="overlay">
<h1>Train Snake</h1>
<p>Click or press a key to start</p>
<button id="startBtn">Start Game</button>
</div>
<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const scoreEl = document.getElementById('score');
const passengersEl = document.getElementById('passengers');
const overlay = document.getElementById('overlay');
const startBtn = document.getElementById('startBtn');
const GRID = 20;
const CELL = canvas.width / GRID;
let snake, direction, nextDir, food, score, passengers, gameLoop, running, autoPlay;
const LOCO_COLORS = ['#e94560', '#ffd324', '#2ed573', '#1dd1a1', '#a55eea', '#ff9f43'];
const WAGON_COLORS = ['#ff6b6b', '#feca57', '#48dbfb', '#1dd1a1', '#a55eea', '#ff9ff3'];
function init() {
snake = [
{x: 5, y: 10, type: 'loco'},
{x: 4, y: 10, type: 'wagon'},
{x: 3, y: 10, type: 'wagon'}
];
direction = {x: 1, y: 0};
nextDir = direction;
score = 0;
passengers = 0;
spawnFood();
updateHUD();
}
function spawnFood() {
let valid = false;
while (!valid) {
food = {
x: Math.floor(Math.random() * GRID),
y: Math.floor(Math.random() * GRID),
color: WAGON_COLORS[Math.floor(Math.random() * WAGON_COLORS.length)],
type: 'passenger'
};
valid = !snake.some(s => s.x === food.x && s.y === food.y);
}
}
function updateHUD() {
scoreEl.textContent = score;
passengersEl.textContent = passengers;
}
function draw() {
// Background
ctx.fillStyle = '#0f3460';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Grid lines
ctx.strokeStyle = 'rgba(255,255,255,0.05)';
ctx.lineWidth = 1;
for (let i = 0; i <= GRID; i++) {
ctx.beginPath();
ctx.moveTo(i * CELL, 0);
ctx.lineTo(i * CELL, canvas.height);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(0, i * CELL);
ctx.lineTo(canvas.width, i * CELL);
ctx.stroke();
}
// Draw food (passenger)
ctx.fillStyle = food.color;
ctx.beginPath();
ctx.arc(food.x * CELL + CELL/2, food.y * CELL + CELL/2, CELL/2 - 2, 0, Math.PI * 2);
ctx.fill();
// Add passenger details
ctx.strokeStyle = 'rgba(255,255,255,0.6)';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(food.x * CELL + CELL/4, food.y * CELL + CELL/2);
ctx.lineTo(food.x * CELL + 3*CELL/4, food.y * CELL + CELL/2);
ctx.stroke();
// Draw snake
snake.forEach((seg, i) => {
if (i === 0) {
// Locomotive
ctx.fillStyle = LOCO_COLORS[0];
roundRect(ctx, seg.x * CELL + 1, seg.y * CELL + 1, CELL - 2, CELL - 2, 6);
ctx.fill();
// Smoke stack
ctx.fillStyle = '#333';
ctx.fillRect(seg.x * CELL + CELL/2 - 2, seg.y * CELL + 2, 4, 6);
// Headlight
ctx.fillStyle = '#ffd324';
ctx.beginPath();
ctx.arc(seg.x * CELL + CELL/2, seg.y * CELL + CELL/2, 3, 0, Math.PI * 2);
ctx.fill();
} else {
// Wagons
ctx.fillStyle = WAGON_COLORS[(i - 1) % WAGON_COLORS.length];
roundRect(ctx, seg.x * CELL + 1, seg.y * CELL + 1, CELL - 2, CELL - 2, 6);
ctx.fill();
// Windows
ctx.fillStyle = 'rgba(255,255,255,0.8)';
ctx.fillRect(seg.x * CELL + 4, seg.y * CELL + 4, CELL/3, CELL/3);
ctx.fillRect(seg.x * CELL + 2*CELL/3, seg.y * CELL + 4, CELL/3, CELL/3);
}
});
}
function roundRect(ctx, 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 update() {
direction = nextDir;
const head = {x: snake[0].x + direction.x, y: snake[0].y + direction.y};
// Wall collision
if (head.x < 0 || head.x >= GRID || head.y < 0 || head.y >= GRID) {
gameOver();
return;
}
// Self collision
if (snake.some(s => s.x === head.x && s.y === head.y)) {
gameOver();
return;
}
snake.unshift(head);
// Check food collision
if (head.x === food.x && head.y === food.y) {
score += 10;
passengers += 1;
// Add a new wagon
const lastWagon = snake[snake.length - 1];
snake.push({
x: lastWagon.x,
y: lastWagon.y,
type: 'wagon'
});
spawnFood();
updateHUD();
} else {
snake.pop();
}
}
function gameOver() {
running = false;
clearInterval(gameLoop);
overlay.querySelector('h1').textContent = 'Game Over!';
overlay.querySelector('p').textContent = `Score: ${score} | Passengers: ${passengers}`;
startBtn.textContent = 'Play Again';
overlay.style.display = 'flex';
}
function startGame() {
init();
running = true;
overlay.style.display = 'none';
gameLoop = setInterval(() => {
if (running) {
update();
draw();
}
}, 120);
// Auto-play AI
autoPlay = setInterval(aiMove, 120);
}
function aiMove() {
if (!running) return;
const head = snake[0];
const possibleDirs = [
{x: 1, y: 0}, {x: -1, y: 0}, {x: 0, y: 1}, {x: 0, y: -1}
].filter(d => !(d.x === -direction.x && d.y === -direction.y));
// Simple AI: move towards food
let bestDir = possibleDirs[0];
let bestDist = Infinity;
possibleDirs.forEach(dir => {
const newHead = {x: head.x + dir.x, y: head.y + dir.y};
const dist = Math.abs(newHead.x - food.x) + Math.abs(newHead.y - food.y);
if (dist < bestDist) {
bestDist = dist;
bestDir = dir;
}
});
// Avoid walls and self
const safeDir = possibleDirs.find(dir => {
const newHead = {x: head.x + dir.x, y: head.y + dir.y};
return newHead.x >= 0 && newHead.x < GRID && newHead.y >= 0 && newHead.y < GRID &&
!snake.some(s => s.x === newHead.x && s.y === newHead.y);
}) || bestDir;
nextDir = safeDir;
}
// Input handling
window.addEventListener('keydown', (e) => {
if (!running) {
if (e.key === 'Enter' || e.key === ' ') startGame();
return;
}
switch(e.key) {
case 'ArrowUp':
case 'w':
case 'W':
if (direction.y !== 1) nextDir = {x: 0, y: -1};
break;
case 'ArrowDown':
case 's':
case 'S':
if (direction.y !== -1) nextDir = {x: 0, y: 1};
break;
case 'ArrowLeft':
case 'a':
case 'A':
if (direction.x !== 1) nextDir = {x: -1, y: 0};
break;
case 'ArrowRight':
case 'd':
case 'D':
if (direction.x !== -1) nextDir = {x: 1, y: 0};
break;
}
});
startBtn.addEventListener('click', startGame);
// Initial draw
init();
draw();
</script>
</body>
</html>