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 3 s
- Cost
- $0
- Output tokens
- 5,252
- Spent thinking
- 405 tokens
- Speed
- 83.5 tok/s
- Console errors
- 0
- First token after
- 568 ms
- First visible text after
- 8.5 s
- Prompt tokens
- 517
- Code size
- 14.1 KB
- Finish reason
- stop
- Served by
- Nvidia
- Model id
nvidia/nemotron-3-ultra-550b-a55b:free- Reasoning sent
{"effort":"high"}- 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 · 485 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: #1a1a2e;
font-family: 'Segoe UI', system-ui, sans-serif;
color: #eaeaea;
overflow: hidden;
}
.header {
display: flex;
gap: 2rem;
margin-bottom: 1rem;
font-size: 1.25rem;
font-weight: 600;
letter-spacing: 0.5px;
}
.score-box { display: flex; flex-direction: column; align-items: center; gap: 0.25rem; }
.score-label { font-size: 0.75rem; color: #888; text-transform: uppercase; letter-spacing: 1px; }
.score-value { font-size: 1.5rem; font-variant-numeric: tabular-nums; }
#score { color: #4ecdc4; }
#best { color: #ffe66d; }
canvas {
display: block;
border-radius: 8px;
box-shadow: 0 0 0 2px #2d2d44, 0 20px 40px rgba(0,0,0,0.5);
background: #161628;
}
.overlay {
position: fixed;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: rgba(22, 22, 40, 0.95);
backdrop-filter: blur(4px);
z-index: 10;
opacity: 0;
pointer-events: none;
transition: opacity 0.3s ease;
}
.overlay.visible { opacity: 1; pointer-events: auto; }
.overlay-content { text-align: center; transform: scale(0.9); transition: transform 0.3s ease; }
.overlay.visible .overlay-content { transform: scale(1); }
.overlay h1 { font-size: 3rem; margin-bottom: 0.5rem; background: linear-gradient(135deg, #ff6b6b, #ee5a5a); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
.overlay .final-score { font-size: 2rem; color: #4ecdc4; margin-bottom: 1.5rem; font-variant-numeric: tabular-nums; }
.overlay p { color: #aaa; font-size: 1.1rem; line-height: 1.6; }
.overlay kbd {
display: inline-block;
padding: 0.3rem 0.7rem;
margin: 0 0.2rem;
background: #2d2d44;
border: 1px solid #3d3d5c;
border-radius: 4px;
font-family: inherit;
font-size: 0.9rem;
color: #fff;
box-shadow: 0 2px 0 #1a1a2e;
}
.pause-indicator {
position: fixed;
top: 1rem;
right: 1rem;
padding: 0.5rem 1rem;
background: rgba(255, 230, 109, 0.2);
border: 1px solid #ffe66d;
border-radius: 4px;
color: #ffe66d;
font-size: 0.85rem;
font-weight: 600;
letter-spacing: 1px;
opacity: 0;
transform: translateY(-10px);
transition: all 0.2s ease;
pointer-events: none;
}
.pause-indicator.visible { opacity: 1; transform: translateY(0); }
@media (max-width: 500px) {
.header { font-size: 1rem; gap: 1.5rem; }
.score-value { font-size: 1.25rem; }
.overlay h1 { font-size: 2rem; }
.overlay .final-score { font-size: 1.5rem; }
.overlay p { font-size: 1rem; }
}
</style>
</head>
<body>
<div class="header">
<div class="score-box"><span class="score-label">Score</span><span class="score-value" id="score">0</span></div>
<div class="score-box"><span class="score-label">Best</span><span class="score-value" id="best">0</span></div>
</div>
<canvas id="game"></canvas>
<div class="pause-indicator" id="pauseIndicator">PAUSED</div>
<div class="overlay" id="overlay">
<div class="overlay-content">
<h1>Game Over</h1>
<div class="final-score" id="finalScore">0</div>
<p>Press <kbd>Space</kbd> or <kbd>Enter</kbd> to restart</p>
</div>
</div>
<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const scoreEl = document.getElementById('score');
const bestEl = document.getElementById('best');
const finalScoreEl = document.getElementById('finalScore');
const overlay = document.getElementById('overlay');
const pauseIndicator = document.getElementById('pauseIndicator');
const GRID_SIZE = 20;
const CELL_PADDING = 2;
let cellSize = 0;
let canvasSize = 0;
let snake = [];
let direction = { x: 1, y: 0 };
let nextDirection = { x: 1, y: 0 };
let directionQueue = [];
let food = { x: 0, y: 0 };
let score = 0;
let bestScore = 0;
let gameOver = false;
let paused = false;
let lastUpdateTime = 0;
const UPDATE_INTERVAL = 100;
let accumulator = 0;
let interpolationAlpha = 0;
let prevSnake = [];
const particles = [];
const COLORS = {
bg: '#161628',
grid: '#1f1f3a',
snakeBody: '#4ecdc4',
snakeHead: '#7fffd4',
snakeEye: '#1a1a2e',
food: '#ff6b6b',
foodGlow: '#ff6b6b',
particle: ['#ff6b6b', '#ffe66d', '#4ecdc4', '#7fffd4', '#ff9f1c']
};
function resize() {
const maxWidth = Math.min(window.innerWidth - 40, 800);
const maxHeight = Math.min(window.innerHeight - 160, 800);
const size = Math.min(maxWidth, maxHeight);
canvasSize = Math.floor(size / GRID_SIZE) * GRID_SIZE;
cellSize = canvasSize / GRID_SIZE;
canvas.width = canvasSize;
canvas.height = canvasSize;
canvas.style.width = canvasSize + 'px';
canvas.style.height = canvasSize + 'px';
}
window.addEventListener('resize', resize);
resize();
function initGame() {
snake = [
{ x: 9, y: 10 },
{ x: 8, y: 10 },
{ x: 7, y: 10 }
];
prevSnake = snake.map(s => ({ ...s }));
direction = { x: 1, y: 0 };
nextDirection = { x: 1, y: 0 };
directionQueue = [];
score = 0;
gameOver = false;
paused = false;
particles.length = 0;
updateScoreDisplay();
spawnFood();
overlay.classList.remove('visible');
pauseIndicator.classList.remove('visible');
}
function spawnFood() {
const emptyCells = [];
for (let y = 0; y < GRID_SIZE; y++) {
for (let x = 0; x < GRID_SIZE; x++) {
if (!snake.some(seg => seg.x === x && seg.y === y)) {
emptyCells.push({ x, y });
}
}
}
if (emptyCells.length > 0) {
food = emptyCells[Math.floor(Math.random() * emptyCells.length)];
}
}
function updateScoreDisplay() {
scoreEl.textContent = score;
bestEl.textContent = bestScore;
}
function handleKeydown(e) {
const key = e.key.toLowerCase();
if (['arrowup', 'w'].includes(key)) queueDirection(0, -1);
else if (['arrowdown', 's'].includes(key)) queueDirection(0, 1);
else if (['arrowleft', 'a'].includes(key)) queueDirection(-1, 0);
else if (['arrowright', 'd'].includes(key)) queueDirection(1, 0);
else if (key === 'p') togglePause();
else if ((key === ' ' || key === 'enter') && gameOver) initGame();
else if ((key === ' ' || key === 'enter') && !gameOver && !paused) togglePause();
}
function queueDirection(x, y) {
if (directionQueue.length === 0) {
if ((x !== -direction.x || y !== -direction.y) && (x !== 0 || y !== 0)) {
directionQueue.push({ x, y });
}
} else {
const last = directionQueue[directionQueue.length - 1];
if ((x !== -last.x || y !== -last.y) && (x !== 0 || y !== 0)) {
directionQueue.push({ x, y });
}
}
}
function togglePause() {
if (gameOver) return;
paused = !paused;
pauseIndicator.classList.toggle('visible', paused);
}
function createParticles(x, y) {
const centerX = (x + 0.5) * cellSize;
const centerY = (y + 0.5) * cellSize;
for (let i = 0; i < 12; i++) {
const angle = (Math.PI * 2 / 12) * i + Math.random() * 0.5;
const speed = 1.5 + Math.random() * 2;
particles.push({
x: centerX,
y: centerY,
vx: Math.cos(angle) * speed,
vy: Math.sin(angle) * speed,
life: 1,
color: COLORS.particle[Math.floor(Math.random() * COLORS.particle.length)],
size: 3 + Math.random() * 3
});
}
}
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;
p.life -= dt * 3;
p.size *= 0.97;
if (p.life <= 0) particles.splice(i, 1);
}
}
function updateGame() {
if (directionQueue.length > 0) {
nextDirection = directionQueue.shift();
if (!(nextDirection.x === -direction.x && nextDirection.y === -direction.y)) {
direction = { ...nextDirection };
}
}
prevSnake = snake.map(s => ({ ...s }));
const head = { x: snake[0].x + direction.x, y: snake[0].y + direction.y };
if (head.x < 0 || head.x >= GRID_SIZE || head.y < 0 || head.y >= GRID_SIZE ||
snake.some(seg => seg.x === head.x && seg.y === head.y)) {
gameOver = true;
bestScore = Math.max(bestScore, score);
finalScoreEl.textContent = score;
overlay.classList.add('visible');
return;
}
snake.unshift(head);
if (head.x === food.x && head.y === food.y) {
score += 10;
updateScoreDisplay();
createParticles(food.x, food.y);
spawnFood();
} else {
snake.pop();
}
}
function lerp(a, b, t) { return a + (b - a) * t; }
function drawGrid() {
ctx.strokeStyle = COLORS.grid;
ctx.lineWidth = 0.5;
ctx.beginPath();
for (let i = 0; i <= GRID_SIZE; i++) {
const pos = i * cellSize;
ctx.moveTo(pos, 0);
ctx.lineTo(pos, canvasSize);
ctx.moveTo(0, pos);
ctx.lineTo(canvasSize, pos);
}
ctx.stroke();
}
function drawFood() {
const cx = (food.x + 0.5) * cellSize;
const cy = (food.y + 0.5) * cellSize;
const radius = (cellSize * 0.5 - CELL_PADDING) * 0.7;
const time = performance.now() * 0.003;
const pulse = Math.sin(time) * 0.15 + 1;
const gradient = ctx.createRadialGradient(cx, cy, 0, cx, cy, radius * pulse);
gradient.addColorStop(0, '#ff8a8a');
gradient.addColorStop(0.5, COLORS.food);
gradient.addColorStop(1, '#c0392b');
ctx.shadowColor = COLORS.foodGlow;
ctx.shadowBlur = 15 * pulse;
ctx.fillStyle = gradient;
ctx.beginPath();
ctx.arc(cx, cy, radius * pulse, 0, Math.PI * 2);
ctx.fill();
ctx.shadowBlur = 0;
}
function drawSnake() {
snake.forEach((seg, i) => {
const prevSeg = prevSnake[i] || seg;
const x = lerp(prevSeg.x, seg.x, interpolationAlpha);
const y = lerp(prevSeg.y, seg.y, interpolationAlpha);
const px = x * cellSize + CELL_PADDING;
const py = y * cellSize + CELL_PADDING;
const pw = cellSize - CELL_PADDING * 2;
const ph = cellSize - CELL_PADDING * 2;
const radius = Math.min(pw, ph) * 0.45;
const isHead = i === 0;
const isTail = i === snake.length - 1;
if (isHead) {
const gradient = ctx.createLinearGradient(px, py, px + pw, py + ph);
gradient.addColorStop(0, COLORS.snakeHead);
gradient.addColorStop(1, COLORS.snakeBody);
ctx.fillStyle = gradient;
} else {
const t = i / (snake.length - 1 || 1);
const r = Math.round(lerp(78, 100, t));
const g = Math.round(lerp(205, 205, t));
const b = Math.round(lerp(196, 196, t));
ctx.fillStyle = `rgb(${r}, ${g}, ${b})`;
}
ctx.beginPath();
if (isHead) {
let nextSeg = snake[1];
let dx = seg.x - (nextSeg ? nextSeg.x : seg.x - direction.x);
let dy = seg.y - (nextSeg ? nextSeg.y : seg.y - direction.y);
const corners = [
{ x: px + pw, y: py },
{ x: px + pw, y: py + ph },
{ x: px, y: py + ph },
{ x: px, y: py }
];
const headRadius = radius + 2;
if (dx === 1) { corners[0].x -= headRadius; corners[1].x -= headRadius; }
else if (dx === -1) { corners[2].x += headRadius; corners[3].x += headRadius; }
else if (dy === 1) { corners[0].y -= headRadius; corners[3].y -= headRadius; }
else if (dy === -1) { corners[1].y += headRadius; corners[2].y += headRadius; }
ctx.roundRect(px, py, pw, ph, headRadius);
} else if (isTail) {
ctx.roundRect(px, py, pw, ph, [radius, radius, 4, 4]);
} else {
ctx.roundRect(px, py, pw, ph, radius);
}
ctx.fill();
if (isHead) {
drawEyes(px, py, pw, ph, direction);
}
});
}
function drawEyes(px, py, pw, ph, dir) {
const eyeSize = Math.max(4, cellSize * 0.12);
const eyeOffset = cellSize * 0.22;
const pupilSize = eyeSize * 0.5;
let leftEye, rightEye;
if (dir.x === 1) {
leftEye = { x: px + pw - eyeOffset, y: py + eyeOffset };
rightEye = { x: px + pw - eyeOffset, y: py + ph - eyeOffset };
} else if (dir.x === -1) {
leftEye = { x: px + eyeOffset, y: py + eyeOffset };
rightEye = { x: px + eyeOffset, y: py + ph - eyeOffset };
} else if (dir.y === -1) {
leftEye = { x: px + eyeOffset, y: py + eyeOffset };
rightEye = { x: px + pw - eyeOffset, y: py + eyeOffset };
} else {
leftEye = { x: px + eyeOffset, y: py + ph - eyeOffset };
rightEye = { x: px + pw - eyeOffset, y: py + ph - eyeOffset };
}
ctx.fillStyle = '#fff';
ctx.beginPath();
ctx.arc(leftEye.x, leftEye.y, eyeSize, 0, Math.PI * 2);
ctx.arc(rightEye.x, rightEye.y, eyeSize, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = COLORS.snakeEye;
const pupilOffset = eyeSize * 0.25;
let pxOff = 0, pyOff = 0;
if (dir.x === 1) pxOff = pupilOffset;
else if (dir.x === -1) pxOff = -pupilOffset;
else if (dir.y === -1) pyOff = -pupilOffset;
else pyOff = pupilOffset;
ctx.beginPath();
ctx.arc(leftEye.x + pxOff, leftEye.y + pyOff, pupilSize, 0, Math.PI * 2);
ctx.arc(rightEye.x + pxOff, rightEye.y + pyOff, pupilSize, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = 'rgba(255,255,255,0.6)';
ctx.beginPath();
ctx.arc(leftEye.x + pxOff - pupilSize * 0.3, leftEye.y + pyOff - pupilSize * 0.3, pupilSize * 0.35, 0, Math.PI * 2);
ctx.arc(rightEye.x + pxOff - pupilSize * 0.3, rightEye.y + pyOff - pupilSize * 0.3, pupilSize * 0.35, 0, Math.PI * 2);
ctx.fill();
}
function drawParticles() {
particles.forEach(p => {
ctx.globalAlpha = p.life;
ctx.fillStyle = p.color;
ctx.beginPath();
ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
ctx.fill();
});
ctx.globalAlpha = 1;
}
function render() {
ctx.fillStyle = COLORS.bg;
ctx.fillRect(0, 0, canvasSize, canvasSize);
drawGrid();
drawFood();
drawSnake();
drawParticles();
}
function gameLoop(timestamp) {
if (!lastUpdateTime) lastUpdateTime = timestamp;
const dt = (timestamp - lastUpdateTime) / 1000;
lastUpdateTime = timestamp;
if (!paused && !gameOver) {
accumulator += dt;
while (accumulator >= UPDATE_INTERVAL / 1000) {
updateGame();
accumulator -= UPDATE_INTERVAL / 1000;
}
interpolationAlpha = accumulator / (UPDATE_INTERVAL / 1000);
updateParticles(dt);
}
render();
requestAnimationFrame(gameLoop);
}
window.addEventListener('keydown', handleKeydown);
requestAnimationFrame(gameLoop);
initGame();
</script>
</body>
</html>Reasoning trace (405 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 controls 3. Quick successive key presses honored, but no reversing 4. Eating food: +10 points, grow by 1, new food not on snake 5. Game over on wall/self collision, overlay with score, Space/Enter restarts, P pauses 6. Visual polish: smooth movement, distinct head with eyes facing direction, particle burst on eating 7. Display current score and best score of session I need to create a self-contained HTML file with canvas, CSS, and JS inline. No external resources except allowed CDN URLs (none mentioned, so none). Key technical considerations: - Smooth movement: use interpolation between grid positions - Input handling: queue direction changes, prevent 180-degree turns - Particle system for eating food - Snake rendering with head and eyes - Game loop with fixed timestep for logic, variable for rendering - Responsive design for 1280x800 down to 375px Let me plan the implementation: 1. Canvas setup: calculate cell size based on viewport, minimum 20x20 grid 2. Game state: snake segments, food position, score, best score, direction, next direction queue 3. Input handling: keydown event, queue direction changes 4. Game loop: update at fixed interval (e.g., 100ms), render with interpolation 5. Rendering: draw grid, snake with gradient/eyes, food, particles 6. Particle system: small circles that fade out 7. Game over overlay with restart instructions 8. Pause functionality For smooth movement: store current and previous positions, interpolate based on accumulator. Let me write the code now.