Nemotron 3 Ultra (free)
by NVIDIAReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 1 min 21 s
- Cost
- $0
- Output tokens
- 6,181
- Spent thinking
- 201 tokens
- Speed
- 77.6 tok/s
- Console errors
- 0
- First token after
- 1.0 s
- First visible text after
- 6.1 s
- Prompt tokens
- 517
- Code size
- 19.4 KB
- Finish reason
- stop
- Served by
- Nvidia
- Model id
nvidia/nemotron-3-ultra-550b-a55b:free- Reasoning sent
{"effort":"medium"}- Max output
- 32,000 tokens
- Generated
- Nov 9, 2026
What it was asked
The prompt
Build a polished Snake game in a single HTML file using vanilla JavaScript and a <canvas>. Requirements: - A grid of at least 20×20 cells, centered on the page. - Arrow keys and WASD control the snake. Quick successive key presses must both be honored, but the snake can never reverse onto itself. - Eating food adds 10 points and grows the snake by one cell; new food never spawns on the snake. - Game over when the snake hits a wall or itself, with an overlay showing the score; Space or Enter restarts, P pauses. - Visual polish: smooth movement, a snake with a distinct head and eyes facing its direction, and a small particle burst when eating. - Display the current score and the best score of the session.
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 · 630 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Snake</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f0f23 100%);
font-family: 'Segoe UI', system-ui, sans-serif;
color: #e8e8e8;
overflow: hidden;
}
.game-container {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
}
.score-board {
display: flex;
gap: 32px;
font-size: 1.4rem;
font-weight: 600;
letter-spacing: 0.5px;
}
.score-item { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.score-label { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 1px; opacity: 0.6; font-weight: 400; }
.score-value { font-family: 'Courier New', monospace; color: #00ff88; text-shadow: 0 0 10px rgba(0,255,136,0.5); }
#gameCanvas {
border-radius: 8px;
box-shadow:
0 0 0 2px rgba(255,255,255,0.1),
0 20px 60px rgba(0,0,0,0.5),
inset 0 0 60px rgba(0,0,0,0.3);
background: #0a0a12;
display: block;
}
.overlay {
position: absolute;
inset: 0;
border-radius: 8px;
background: rgba(10,10,18,0.95);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 16px;
opacity: 0;
pointer-events: none;
transition: opacity 0.3s ease;
backdrop-filter: blur(4px);
}
.overlay.visible { opacity: 1; pointer-events: auto; }
.overlay h1 {
font-size: 2.5rem;
font-weight: 700;
background: linear-gradient(135deg, #ff4757, #ff6b7a);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-shadow: none;
}
.overlay p { font-size: 1.1rem; opacity: 0.8; line-height: 1.6; text-align: center; max-width: 300px; }
.overlay .final-score { font-size: 2rem; font-weight: 700; color: #00ff88; font-family: 'Courier New', monospace; }
.overlay .controls-hint { font-size: 0.85rem; opacity: 0.5; margin-top: 8px; }
.paused .overlay { opacity: 1; pointer-events: auto; }
.paused .overlay h1 { background: linear-gradient(135deg, #ffa502, #ffbe0b); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
@media (max-width: 480px) {
.score-board { gap: 16px; font-size: 1.1rem; }
.overlay h1 { font-size: 1.8rem; }
.overlay .final-score { font-size: 1.5rem; }
}
</style>
</head>
<body>
<div class="game-container">
<div class="score-board">
<div class="score-item">
<span class="score-label">Score</span>
<span class="score-value" id="currentScore">0</span>
</div>
<div class="score-item">
<span class="score-label">Best</span>
<span class="score-value" id="bestScore">0</span>
</div>
</div>
<canvas id="gameCanvas"></canvas>
<div class="overlay" id="overlay">
<h1 id="overlayTitle">Game Over</h1>
<p class="final-score" id="finalScore">0</p>
<p id="overlayMessage">Press Space or Enter to restart</p>
<p class="controls-hint">Arrow keys / WASD to move • P to pause</p>
</div>
</div>
<script>
// Configuration
const GRID_SIZE = 22;
const CELL_SIZE = 30;
const CANVAS_SIZE = GRID_SIZE * CELL_SIZE;
const INITIAL_SPEED = 130; // ms per step
const SPEED_INCREMENT = 1.5; // ms faster per food
const MIN_SPEED = 60;
// Colors
const BG_COLOR = '#0a0a12';
const GRID_COLOR = '#1a1a2e';
const FOOD_COLOR = '#ff4757';
const FOOD_GLOW = '#ff6b7a';
const SNAKE_HEAD = '#00ff88';
const SNAKE_BODY = '#00cc6a';
const SNAKE_TAIL = '#009950';
const EYE_WHITE = '#ffffff';
const EYE_PUPIL = '#1a1a2e';
const PARTICLE_COLORS = ['#ff4757', '#ff6b7a', '#ffa502', '#ffbe0b', '#00ff88', '#00cc6a'];
// Game state
let snake = [];
let direction = { x: 1, y: 0 };
let nextDirection = { x: 1, y: 0 };
let food = { x: 0, y: 0 };
let score = 0;
let bestScore = 0;
let gameSpeed = INITIAL_SPEED;
let lastStepTime = 0;
let gameOver = false;
let paused = false;
let animationId = null;
// Smooth movement
let interpolatedSegments = [];
let stepProgress = 0;
// Particles
let particles = [];
// Input queue for quick successive presses
let inputQueue = [];
const MAX_QUEUE = 2;
// Canvas setup
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
canvas.width = CANVAS_SIZE;
canvas.height = CANVAS_SIZE;
// DOM elements
const currentScoreEl = document.getElementById('currentScore');
const bestScoreEl = document.getElementById('bestScore');
const overlay = document.getElementById('overlay');
const overlayTitle = document.getElementById('overlayTitle');
const finalScoreEl = document.getElementById('finalScore');
const overlayMessage = document.getElementById('overlayMessage');
const gameContainer = document.querySelector('.game-container');
function init() {
// Center snake
const startX = Math.floor(GRID_SIZE / 2);
const startY = Math.floor(GRID_SIZE / 2);
snake = [
{ x: startX, y: startY },
{ x: startX - 1, y: startY },
{ x: startX - 2, y: startY }
];
direction = { x: 1, y: 0 };
nextDirection = { x: 1, y: 0 };
inputQueue = [];
score = 0;
gameSpeed = INITIAL_SPEED;
gameOver = false;
paused = false;
particles = [];
stepProgress = 0;
updateInterpolatedSegments(0);
spawnFood();
updateScoreDisplay();
hideOverlay();
gameContainer.classList.remove('paused');
if (animationId) cancelAnimationFrame(animationId);
lastStepTime = performance.now();
requestAnimationFrame(gameLoop);
}
function spawnFood() {
let newFood;
do {
newFood = {
x: Math.floor(Math.random() * GRID_SIZE),
y: Math.floor(Math.random() * GRID_SIZE)
};
} while (snake.some(seg => seg.x === newFood.x && seg.y === newFood.y));
food = newFood;
}
function updateScoreDisplay() {
currentScoreEl.textContent = score;
bestScoreEl.textContent = bestScore;
}
function showOverlay(title, message, showFinalScore = true) {
overlayTitle.textContent = title;
overlayMessage.textContent = message;
finalScoreEl.textContent = score;
finalScoreEl.style.display = showFinalScore ? 'block' : 'none';
overlay.classList.add('visible');
}
function hideOverlay() {
overlay.classList.remove('visible');
}
function handleInput(newDir) {
// Prevent reversing
if (newDir.x === -direction.x && newDir.y === -direction.y) return;
if (newDir.x === direction.x && newDir.y === direction.y) return;
// Queue input
if (inputQueue.length < MAX_QUEUE) {
const lastQueued = inputQueue.length > 0 ? inputQueue[inputQueue.length - 1] : direction;
if (newDir.x !== -lastQueued.x || newDir.y !== -lastQueued.y) {
inputQueue.push(newDir);
}
}
}
function processInputQueue() {
if (inputQueue.length > 0) {
nextDirection = inputQueue.shift();
}
}
function step() {
if (gameOver || paused) return;
processInputQueue();
direction = { ...nextDirection };
const head = { x: snake[0].x + direction.x, y: snake[0].y + direction.y };
// Wall collision
if (head.x < 0 || head.x >= GRID_SIZE || head.y < 0 || head.y >= GRID_SIZE) {
endGame();
return;
}
// Self collision
if (snake.some(seg => seg.x === head.x && seg.y === head.y)) {
endGame();
return;
}
snake.unshift(head);
// Food collision
if (head.x === food.x && head.y === food.y) {
score += 10;
if (score > bestScore) bestScore = score;
updateScoreDisplay();
createParticles(food.x, food.y);
gameSpeed = Math.max(MIN_SPEED, gameSpeed - SPEED_INCREMENT);
spawnFood();
} else {
snake.pop();
}
stepProgress = 0;
}
function createParticles(gridX, gridY) {
const centerX = (gridX + 0.5) * CELL_SIZE;
const centerY = (gridY + 0.5) * CELL_SIZE;
for (let i = 0; i < 12; i++) {
const angle = (Math.PI * 2 * i) / 12 + Math.random() * 0.3;
const speed = 2 + Math.random() * 3;
particles.push({
x: centerX,
y: centerY,
vx: Math.cos(angle) * speed,
vy: Math.sin(angle) * speed,
radius: 3 + Math.random() * 3,
color: PARTICLE_COLORS[Math.floor(Math.random() * PARTICLE_COLORS.length)],
life: 1,
decay: 0.02 + Math.random() * 0.02
});
}
}
function updateParticles(dt) {
for (let i = particles.length - 1; i >= 0; i--) {
const p = particles[i];
p.x += p.vx;
p.y += p.vy;
p.vy += 0.15; // gravity
p.life -= p.decay;
p.radius *= 0.98;
if (p.life <= 0) particles.splice(i, 1);
}
}
function drawParticles() {
particles.forEach(p => {
ctx.globalAlpha = p.life;
ctx.fillStyle = p.color;
ctx.beginPath();
ctx.arc(p.x, p.y, Math.max(1, p.radius), 0, Math.PI * 2);
ctx.fill();
});
ctx.globalAlpha = 1;
}
function endGame() {
gameOver = true;
showOverlay('Game Over', 'Press Space or Enter to restart');
cancelAnimationFrame(animationId);
}
function togglePause() {
if (gameOver) return;
paused = !paused;
gameContainer.classList.toggle('paused', paused);
if (paused) {
showOverlay('Paused', 'Press P to resume', false);
cancelAnimationFrame(animationId);
} else {
hideOverlay();
lastStepTime = performance.now();
requestAnimationFrame(gameLoop);
}
}
function updateInterpolatedSegments(progress) {
interpolatedSegments = snake.map((seg, i) => {
if (i === 0) return { ...seg, progress: 0 };
const prev = snake[i - 1];
return {
x: prev.x + (seg.x - prev.x) * progress,
y: prev.y + (seg.y - prev.y) * progress,
progress
};
});
}
function drawGrid() {
ctx.strokeStyle = GRID_COLOR;
ctx.lineWidth = 0.5;
ctx.beginPath();
for (let i = 0; i <= GRID_SIZE; i++) {
const pos = i * CELL_SIZE;
ctx.moveTo(pos, 0);
ctx.lineTo(pos, CANVAS_SIZE);
ctx.moveTo(0, pos);
ctx.lineTo(CANVAS_SIZE, pos);
}
ctx.stroke();
}
function drawFood() {
const centerX = (food.x + 0.5) * CELL_SIZE;
const centerY = (food.y + 0.5) * CELL_SIZE;
const radius = CELL_SIZE * 0.35;
const pulse = Math.sin(performance.now() / 200) * 0.15 + 1;
// Glow
const gradient = ctx.createRadialGradient(centerX, centerY, 0, centerX, centerY, radius * 1.5 * pulse);
gradient.addColorStop(0, FOOD_GLOW);
gradient.addColorStop(1, 'rgba(255, 71, 87, 0)');
ctx.fillStyle = gradient;
ctx.beginPath();
ctx.arc(centerX, centerY, radius * 1.5 * pulse, 0, Math.PI * 2);
ctx.fill();
// Food body
ctx.fillStyle = FOOD_COLOR;
ctx.beginPath();
ctx.arc(centerX, centerY, radius * pulse, 0, Math.PI * 2);
ctx.fill();
// Highlight
ctx.fillStyle = 'rgba(255,255,255,0.3)';
ctx.beginPath();
ctx.arc(centerX - radius * 0.2, centerY - radius * 0.2, radius * 0.25, 0, Math.PI * 2);
ctx.fill();
}
function drawSnake() {
// Draw body segments (from tail to head-1)
for (let i = interpolatedSegments.length - 1; i > 0; i--) {
const seg = interpolatedSegments[i];
const nextSeg = interpolatedSegments[i - 1];
const isTail = i === interpolatedSegments.length - 1;
const cx = seg.x * CELL_SIZE;
const cy = seg.y * CELL_SIZE;
const nx = nextSeg.x * CELL_SIZE;
const ny = nextSeg.y * CELL_SIZE;
const radius = CELL_SIZE * 0.42;
const tailRadius = isTail ? radius * 0.6 : radius;
// Segment color gradient from tail to head
const t = i / (interpolatedSegments.length - 1);
const r = Math.round(0 + (0 - 0) * t); // placeholder
ctx.fillStyle = isTail ? SNAKE_TAIL : SNAKE_BODY;
// Draw rounded rectangle connecting to next segment
const dx = nx - cx;
const dy = ny - cy;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0.5) {
const angle = Math.atan2(dy, dx);
ctx.save();
ctx.translate(cx, cy);
ctx.rotate(angle);
// Body segment
ctx.beginPath();
ctx.roundRect(-radius, -radius, dist + radius * 2, radius * 2, radius);
ctx.fill();
ctx.restore();
} else {
ctx.beginPath();
ctx.arc(cx, cy, radius, 0, Math.PI * 2);
ctx.fill();
}
// Tail tip
if (isTail) {
const tailAngle = Math.atan2(snake[snake.length - 1].y - snake[snake.length - 2].y,
snake[snake.length - 1].x - snake[snake.length - 2].x);
ctx.save();
ctx.translate(cx, cy);
ctx.rotate(tailAngle);
ctx.fillStyle = SNAKE_TAIL;
ctx.beginPath();
ctx.moveTo(-radius * 0.8, 0);
ctx.lineTo(-radius * 1.5, -radius * 0.5);
ctx.lineTo(-radius * 1.5, radius * 0.5);
ctx.closePath();
ctx.fill();
ctx.restore();
}
}
// Draw head
const head = interpolatedSegments[0];
const hx = head.x * CELL_SIZE;
const hy = head.y * CELL_SIZE;
const headRadius = CELL_SIZE * 0.45;
// Head glow
const headGlow = ctx.createRadialGradient(hx, hy, 0, hx, hy, headRadius * 1.3);
headGlow.addColorStop(0, 'rgba(0, 255, 136, 0.4)');
headGlow.addColorStop(1, 'rgba(0, 255, 136, 0)');
ctx.fillStyle = headGlow;
ctx.beginPath();
ctx.arc(hx, hy, headRadius * 1.3, 0, Math.PI * 2);
ctx.fill();
// Head body
ctx.fillStyle = SNAKE_HEAD;
ctx.beginPath();
ctx.arc(hx, hy, headRadius, 0, Math.PI * 2);
ctx.fill();
// Eyes
const eyeOffset = headRadius * 0.35;
const eyeRadius = headRadius * 0.18;
const pupilRadius = eyeRadius * 0.5;
const dirAngle = Math.atan2(direction.y, direction.x);
// Eye positions (perpendicular to direction)
const perpAngle = dirAngle + Math.PI / 2;
const eye1x = hx + Math.cos(perpAngle) * eyeOffset + Math.cos(dirAngle) * headRadius * 0.2;
const eye1y = hy + Math.sin(perpAngle) * eyeOffset + Math.sin(dirAngle) * headRadius * 0.2;
const eye2x = hx - Math.cos(perpAngle) * eyeOffset + Math.cos(dirAngle) * headRadius * 0.2;
const eye2y = hy - Math.sin(perpAngle) * eyeOffset + Math.sin(dirAngle) * headRadius * 0.2;
// Eye whites
ctx.fillStyle = EYE_WHITE;
ctx.beginPath();
ctx.arc(eye1x, eye1y, eyeRadius, 0, Math.PI * 2);
ctx.arc(eye2x, eye2y, eyeRadius, 0, Math.PI * 2);
ctx.fill();
// Pupils (look in movement direction)
const pupilOffset = eyeRadius * 0.4;
ctx.fillStyle = EYE_PUPIL;
ctx.beginPath();
ctx.arc(eye1x + Math.cos(dirAngle) * pupilOffset, eye1y + Math.sin(dirAngle) * pupilOffset, pupilRadius, 0, Math.PI * 2);
ctx.arc(eye2x + Math.cos(dirAngle) * pupilOffset, eye2y + Math.sin(dirAngle) * pupilOffset, pupilRadius, 0, Math.PI * 2);
ctx.fill();
// Eye highlights
ctx.fillStyle = 'rgba(255,255,255,0.8)';
ctx.beginPath();
ctx.arc(eye1x - Math.cos(dirAngle) * pupilOffset * 0.3, eye1y - Math.sin(dirAngle) * pupilOffset * 0.3, pupilRadius * 0.4, 0, Math.PI * 2);
ctx.arc(eye2x - Math.cos(dirAngle) * pupilOffset * 0.3, eye2y - Math.sin(dirAngle) * pupilOffset * 0.3, pupilRadius * 0.4, 0, Math.PI * 2);
ctx.fill();
}
function render(progress) {
// Clear
ctx.fillStyle = BG_COLOR;
ctx.fillRect(0, 0, CANVAS_SIZE, CANVAS_SIZE);
// Grid
drawGrid();
// Food
drawFood();
// Update interpolated positions for smooth movement
updateInterpolatedSegments(progress);
// Snake
drawSnake();
// Particles
drawParticles();
}
function gameLoop(timestamp) {
if (gameOver) return;
const dt = timestamp - lastStepTime;
stepProgress = Math.min(1, dt / gameSpeed);
if (dt >= gameSpeed) {
step();
lastStepTime = timestamp;
stepProgress = 0;
}
updateParticles(16);
render(stepProgress);
animationId = requestAnimationFrame(gameLoop);
}
// Keyboard handling
window.addEventListener('keydown', e => {
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
const key = e.key.toLowerCase();
if (key === ' ' || key === 'enter') {
e.preventDefault();
if (gameOver) {
init();
} else if (paused) {
togglePause();
}
return;
}
if (key === 'p') {
e.preventDefault();
togglePause();
return;
}
if (paused || gameOver) return;
let newDir = null;
switch (key) {
case 'arrowup': case 'w': newDir = { x: 0, y: -1 }; break;
case 'arrowdown': case 's': newDir = { x: 0, y: 1 }; break;
case 'arrowleft': case 'a': newDir = { x: -1, y: 0 }; break;
case 'arrowright': case 'd': newDir = { x: 1, y: 0 }; break;
}
if (newDir) {
e.preventDefault();
handleInput(newDir);
}
});
// Touch/swipe support for mobile
let touchStartX = 0;
let touchStartY = 0;
canvas.addEventListener('touchstart', e => {
touchStartX = e.touches[0].clientX;
touchStartY = e.touches[0].clientY;
}, { passive: true });
canvas.addEventListener('touchend', e => {
if (paused || gameOver) return;
const dx = e.changedTouches[0].clientX - touchStartX;
const dy = e.changedTouches[0].clientY - touchStartY;
const absX = Math.abs(dx);
const absY = Math.abs(dy);
if (Math.max(absX, absY) < 30) return; // Minimum swipe distance
let newDir = null;
if (absX > absY) {
newDir = dx > 0 ? { x: 1, y: 0 } : { x: -1, y: 0 };
} else {
newDir = dy > 0 ? { x: 0, y: 1 } : { x: 0, y: -1 };
}
if (newDir) handleInput(newDir);
}, { passive: true });
// Prevent context menu on long press
canvas.addEventListener('contextmenu', e => e.preventDefault());
// Handle visibility change
document.addEventListener('visibilitychange', () => {
if (!gameOver && !paused && document.hidden) {
togglePause();
}
});
// Start
init();
</script>
</body>
</html>Reasoning trace (201 tokens)
The user wants a polished Snake game in a single HTML file. Let me break down the requirements: 1. Grid of at least 20x20 cells, centered on page 2. Arrow keys and WASD control, quick successive key presses honored but no reversing 3. Eating food: +10 points, grows by 1 cell, food never spawns on snake 4. Game over on wall/self collision, overlay with score, Space/Enter restarts, P pauses 5. Visual polish: smooth movement, distinct head with eyes facing direction, particle burst on eating 6. Display current score and best score of session I'll create a polished implementation with: - Smooth interpolation between grid positions - Particle effects on food consumption - Nice visual styling for snake (head with eyes, body segments) - Responsive design - Proper keyboard handling with input queue - Session high score storage in memory Let me write the complete HTML file.