Models 44
Train snakeOne-line

Dots3-Note Preview (free)

by Dots StudioReasoningClean
Open in new window

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>