Models 44
Train snakeOne-line

North Mini Code (free)

by CohereReasoningClean
Open in new window

Running live in a sandboxed frame. Click inside it before using the keyboard.

How it went

Total time
11.6 s
Cost
$0
Output tokens
2,854
Spent thinking
0 tokens
Speed
250.7 tok/s
Console errors
0
First token after
237 ms
First visible text after
237 ms
Prompt tokens
350
Code size
9.2 KB
Finish reason
stop
Served by
Cohere
Model id
cohere/north-mini-code: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 · 353 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Colorful Train Snake</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
/* Reset */
* { margin:0; padding:0; box-sizing:border-box; }
body {
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  background: #e0f7fa;
  color: #333;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  overflow: hidden;
}

/* Game container */
#gameContainer {
  position: relative;
  width: 640px;
  height: 480px;
  background: #fffde7;
  border: 4px solid #4a90e2;
  border-radius: 12px;
  box-shadow: 0 6px 20px rgba(0,0,0,.2);
}

/* Canvas fills container */
canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* UI overlay */
#uiOverlay {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  background: rgba(255,255,255,.95);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  z-index: 10;
}
#uiOverlay.hidden {
  display: none;
}
#uiOverlay h1 {
  font-size: 2.5rem;
  margin-bottom: .5rem;
  color: #4a90e2;
}
#uiOverlay p {
  font-size: 1.2rem;
  margin-bottom: 1.5rem;
}
.startBtn {
  padding: .8rem 2rem;
  font-size: 1.2rem;
  background: #4caf50;
  color: white;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: background .3s;
}
.startBtn:hover { background: #45a049; }

/* Score panel */
#scorePanel {
  position: absolute;
  top: 10px;
  left: 10px;
  font-size: 1.4rem;
  font-weight: bold;
  color: #e53935;
  display: none;
}

/* Game over overlay */
#gameOver {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  background: rgba(0,0,0,.7);
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: white;
  z-index: 20;
}
#gameOver h2 { font-size: 3rem; margin-bottom: .5rem; }
#gameOver p { font-size: 1.5rem; margin-bottom: 1.5rem; }
#gameOver button {
  padding: .6rem 1.5rem;
  font-size: 1.2rem;
  background: #ff5252;
  color: white;
  border: none;
  border-radius: 6px;
  cursor: pointer;
}
#gameOver button:hover { background: #e53935; }

</style>
</head>
<body>

<div id="gameContainer">
  <canvas id="gameCanvas"></canvas>
  <div id="uiOverlay">
    <h1>Train Snake</h1>
    <p>Click or press any key to start</p>
    <button class="startBtn" id="startBtn">Start Game</button>
  </div>
  <div id="scorePanel">Score: <span id="scoreVal">0</span></div>
  <div id="gameOver">
    <h2>Game Over</h2>
    <p>Your score: <span id="finalScore">0</span></p>
    <button id="restartBtn">Restart</button>
  </div>
</div>

<script>
// Game constants
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const startBtn = document.getElementById('startBtn');
const uiOverlay = document.getElementById('uiOverlay');
const scorePanel = document.getElementById('scorePanel');
const scoreVal = document.getElementById('scoreVal');
const gameOver = document.getElementById('gameOver');
const finalScore = document.getElementById('finalScore');
const restartBtn = document.getElementById('restartBtn');

// Scale to fill container nicely
let scale = 1;
function resize() {
  const container = canvas.parentElement;
  const w = container.clientWidth;
  const h = container.clientHeight;
  canvas.width = w;
  canvas.height = h;
}
window.addEventListener('resize', resize);
resize();

// Train snake segment images (drawn as simple shapes for demo)
const colors = ['#ff5252', '#ffca28', '#69f0ae', '#40c4ff', '#7c4dff'];
const wagonColors = ['#ff8a65', '#ffd54f', '#81c784', '#64b5f6', '#ba68c8'];

// Game state
let gameRunning = false;
let snake = []; // each segment: {x, y, width, height, type: 'locomotive'|'wagon', color}
let direction = {x:0, y:0};
let food = null;
let score = 0;
let lastTime = 0;
let animId = null;

// Input
const keys = {};
document.addEventListener('keydown', e => {
  if (!gameRunning) {
    // start on any key
    startGame();
    return;
  }
  keys[e.code] = true;
});
document.addEventListener('keyup', e => { keys[e.code] = false; });
canvas.addEventListener('click', () => {
  if (!gameRunning) startGame();
});

// Start button click
startBtn.addEventListener('click', startGame);

function startGame() {
  // reset UI
  uiOverlay.classList.add('hidden');
  gameOver.style.display = 'none';
  scorePanel.style.display = 'block';
  score = 0;
  scoreVal.textContent = score;
  
  // initial snake: three segments, locomotive + 2 wagons
  snake = [];
  const cell = Math.min(canvas.width, canvas.height) / 20; // segment size
  const startX = canvas.width/2;
  const startY = canvas.height/2;
  // locomotive
  snake.push({x: startX, y: startY, w: cell*2, h: cell, type: 'locomotive', color: '#4a90e2'});
  // first wagon
  snake.push({x: startX - cell*2, y: startY, w: cell, h: cell, type: 'wagon', color: wagonColors[0]});
  // second wagon
  snake.push({x: startX - cell*4, y: startY, w: cell, h: cell, type: 'wagon', color: wagonColors[1]});
  
  direction = {x: cell, y:0}; // moving right initially
  food = createFood();
  gameRunning = true;
  lastTime = performance.now();
  gameLoop();
}

// Create food (passenger on platform)
function createFood() {
  const cell = Math.min(canvas.width, canvas.height) / 20;
  const maxX = Math.floor((canvas.width - cell) / cell) * cell;
  const maxY = Math.floor((canvas.height - cell) / cell) * cell;
  let x, y;
  do {
    x = Math.floor(Math.random() * (maxX/cell)) * cell;
    y = Math.floor(Math.random() * (maxY/cell)) * cell;
  } while (isOnSnake(x, y));
  
  return {x, y, w: cell, h: cell, color: '#e53935'};
}

// Check if position overlaps snake
function isOnSnake(x, y) {
  return snake.some(seg => x < seg.x + seg.w && x + seg.w > seg.x &&
                            y < seg.y + seg.h && y + seg.h > seg.y);
}

// Draw train snake
function drawSnake() {
  snake.forEach((seg, idx) => {
    // locomotive front has a simple "engine" shape
    if (seg.type === 'locomotive') {
      ctx.fillStyle = seg.color;
      ctx.fillRect(seg.x, seg.y, seg.w, seg.h);
      // Add a small window
      ctx.fillStyle = '#fff';
      ctx.fillRect(seg.x + seg.w*0.6, seg.y + seg.h*0.3, seg.w*0.3, seg.h*0.4);
    } else {
      // Wagons are colored rectangles with a roof
      ctx.fillStyle = seg.color;
      ctx.fillRect(seg.x, seg.y, seg.w, seg.h);
      // roof
      ctx.fillStyle = seg.color;
      ctx.beginPath();
      ctx.moveTo(seg.x, seg.y);
      ctx.lineTo(seg.x + seg.w*0.5, seg.y - seg.h*0.3);
      ctx.lineTo(seg.x + seg.w, seg.y);
      ctx.closePath();
      ctx.fill();
    }
  });
}

// Draw food (passenger)
function drawFood() {
  ctx.fillStyle = food.color;
  ctx.beginPath();
  ctx.arc(food.x + food.w*0.5, food.y + food.h*0.5, food.w*0.4, 0, Math.PI*2);
  ctx.fill();
}

// Update snake position
function updateSnake() {
  const cell = Math.min(canvas.width, canvas.height) / 20;
  const head = snake[0];
  const newHead = {x: head.x + direction.x, y: head.y + direction.y, 
                    w: head.w, h: head.h, type: head.type, color: head.color};
  
  // Check collisions with walls
  if (newHead.x < 0 || newHead.x + newHead.w > canvas.width ||
      newHead.y < 0 || newHead.y + newHead.h > canvas.height) {
    gameRunning = false;
    endGame();
    return;
  }
  
  // Check self-collision (excluding tail that will move)
  for (let i = 1; i < snake.length; i++) {
    if (newHead.x < snake[i].x + snake[i].w && newHead.x + newHead.w > snake[i].x &&
        newHead.y < snake[i].y + snake[i].h && newHead.y + newHead.h > snake[i].y) {
      gameRunning = false;
      endGame();
      return;
    }
  }
  
  snake.unshift(newHead);
  
  // Check food collision
  if (newHead.x < food.x + food.w && newHead.x + newHead.w > food.x &&
      newHead.y < food.y + food.h && newHead.y + food.h > food.y) {
    // grow snake: add a new wagon at the tail
    const tail = snake[snake.length-1];
    const newWagon = {
      x: tail.x,
      y: tail.y,
      w: tail.w,
      h: tail.h,
      type: 'wagon',
      color: wagonColors[snake.length % wagonColors.length]
    };
    snake.push(newWagon);
    score += 10;
    scoreVal.textContent = score;
    food = createFood();
  } else {
    snake.pop(); // shrink if no food eaten
  }
  
  // Direction handling (arrow keys)
  if (keys['ArrowUp'] && direction.y === 0) direction = {x:0, y: -cell};
  if (keys['ArrowDown'] && direction.y === 0) direction = {x:0, y: cell};
  if (keys['ArrowLeft'] && direction.x === 0) direction = {x: -cell, y:0};
  if (keys['ArrowRight'] && direction.x === 0) direction = {x: cell, y:0};
}

// Game loop
function gameLoop(timestamp) {
  if (!gameRunning) return;
  const delta = timestamp - lastTime;
  lastTime = timestamp;
  
  ctx.clearRect(0,0,canvas.width,canvas.height);
  
  updateSnake();
  
  drawFood();
  drawSnake();
  
  animId = requestAnimationFrame(gameLoop);
}

// End game
function endGame() {
  gameOver.style.display = 'flex';
  finalScore.textContent = score;
  cancelAnimationFrame(animId);
}

// Prevent scrolling on space
window.addEventListener('wheel', e => e.preventDefault(), {passive: false});
window.addEventListener('keydown', e => {
  if (e.key === ' ') e.preventDefault();
});

// Initial draw until started
ctx.fillStyle = '#4a90e2';
ctx.font = '24px Segoe UI';
ctx.fillText('Click or press any key to start', canvas.width/2 - 120, canvas.height/2);