Xing4.0 29B A4B (free)
by XingChenReasoning1 console error
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 1 min 20 s
- Cost
- $0
- Output tokens
- 5,812
- Spent thinking
- 0 tokens
- Speed
- 74 tok/s
- Console errors
- 1
- First token after
- 1.1 s
- First visible text after
- 1.1 s
- Prompt tokens
- 519
- Code size
- 14.5 KB
- Finish reason
- stop
- Served by
- Phala
- Model id
xingchen-agi/xing4.0-29b-a4b:free- Reasoning sent
{"effort":"none"}- Max output
- 32,000 tokens
- Generated
- Nov 9, 2026
Console errors
Caught in the first 3 seconds after load, in a sandboxed iframe like the one above.
updateHUD is not defined
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 · 564 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Neon Snake</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: #0a0a12;
color: #e0e0e0;
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
overflow: hidden;
user-select: none;
}
.game-wrap {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
padding: 16px;
}
#scoreboard {
display: flex;
justify-content: space-between;
width: 520px;
max-width: 96vw;
font-size: 14px;
font-weight: 600;
letter-spacing: 0.1em;
}
#scoreboard .label {
color: #6a6a8a;
font-size: 11px;
text-transform: uppercase;
}
#scoreboard .value {
font-variant-numeric: tabular-nums;
font-size: 24px;
}
#board-container {
position: relative;
border-radius: 14px;
overflow: hidden;
box-shadow: 0 0 30px rgba(0, 200, 255, 0.12), inset 0 0 2px rgba(0, 200, 255, 0.3);
}
canvas {
display: block;
background: #0e0e1a;
}
/* Overlay */
.overlay {
position: absolute;
inset: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: rgba(10, 10, 20, 0.78);
backdrop-filter: blur(4px);
z-index: 10;
text-align: center;
transition: opacity 0.25s ease;
}
.overlay.hidden { opacity: 0; pointer-events: none; }
.overlay h1 {
font-size: 38px;
letter-spacing: 0.06em;
margin-bottom: 6px;
background: linear-gradient(135deg, #00ffcc, #00aaff);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.overlay p {
color: #8a8aa0;
font-size: 14px;
margin-bottom: 20px;
}
.overlay .restart-hint {
font-size: 13px;
color: #555570;
margin-top: 18px;
}
#best-label { color: #8a8aa0; font-size: 11px; text-transform: uppercase; letter-spacing: 0.1em; }
/* Footer controls hint */
.controls-hint {
font-size: 11px;
color: #3a3a50;
text-align: center;
}
</style>
</head>
<body>
<div class="game-wrap">
<div id="scoreboard">
<span>
<span class="label">Score</span>
<br>
<span class="value" id="score" style="color:#00ffcc;">0</span>
</span>
<span>
<span class="label">Best</span>
<br>
<span class="value" id="best" style="color:#ffd700;">0</span>
</span>
</div>
<div id="board-container">
<canvas id="game" width="520" height="520"></canvas>
<div class="overlay" id="overlay">
<h1>NEON SNAKE</h1>
<p>WASD or Arrow keys to move</p>
<div class="restart-hint">Space or Enter to restart · P to pause</div>
</div>
</div>
</div>
<p class="controls-hint">Arrow keys / WASD | Space/Enter restart | P pause</p>
<script>
(() => {
'use strict';
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const W = canvas.width;
const H = canvas.height;
// ---- Game constants ----
const GRID_SIZE = 20; // cells per side
const CELL_SIZE = W / GRID_SIZE; // = 26
const MOVE_INTERVAL = 110; // ms between steps
const MAX_SPEED = 180; // ms per step cap
const INITIAL_LENGTH = 3;
const FOOD_POINTS = 10;
// ---- DOM refs ----
const scoreEl = document.getElementById('score');
const bestEl = document.getElementById('best');
const overlay = document.getElementById('overlay');
// ---- State ----
let snake = []; // array of {x, y} from head to tail
let direction = { x: 1, y: 0 };
let nextDirection = { x: 1, y: 0 };
let food = {};
let score = 0;
let bestScore = 0;
let running = false;
let paused = false;
let gameOver = false;
let particles = [];
let highScoreLocal = null;
let tickTimer = null;
let lastMoveTime = 0;
let animationFrameId = null;
let blinkTimer = null;
let showStartBanner = true;
// ---- Init snake ----
function createSnake() {
snake = [];
const startX = Math.floor(GRID_SIZE / 2);
const startY = Math.floor(GRID_SIZE / 2);
for (let i = 0; i < INITIAL_LENGTH; i++) {
snake.push({ x: startX - i, y: startY });
}
}
// ---- Food placement ----
function placeFood() {
let attempts = 0;
while (attempts < 500) {
const fx = Math.floor(Math.random() * GRID_SIZE);
const fy = Math.floor(Math.random() * GRID_SIZE);
if (!snake.some(s => s.x === fx && s.y === fy)) {
food = { x: fx, y: fy };
return;
}
attempts++;
}
}
// ---- Input handling ----
function handleKeyDown(e) {
if (running && !gameOver) {
switch (e.key.toLowerCase()) {
case 'arrowup': case 'w': if (direction.y !== 1) { nextDirection = { x: 0, y: -1 }; e.preventDefault(); } break;
case 'arrowdown': case 's': if (direction.y !== -1) { nextDirection = { x: 0, y: 1 }; e.preventDefault(); } break;
case 'arrowleft': case 'a': if (direction.x !== 1) { nextDirection = { x: -1, y: 0 }; e.preventDefault(); } break;
case 'arrowright': case 'd': if (direction.x !== -1) { nextDirection = { x: 1, y: 0 }; e.preventDefault(); } break;
case 'p': togglePause(); break;
default: break;
}
return;
}
// During non-running states (start screen / game over), Space/Enter restarts
if (e.code === 'Space' || e.code === 'Enter') {
restart();
e.preventDefault();
}
}
document.addEventListener('keydown', handleKeyDown);
document.addEventListener('touchstart', handleTouch);
function handleTouch(e) {
if (!running || gameOver) return;
const t = e.changedTouches[0];
const rect = canvas.getBoundingClientRect();
const scale = canvas.width / rect.width;
const tx = Math.round((t.clientX - rect.left) * scale / CELL_SIZE);
const ty = Math.round((t.clientY - rect.top) * scale / CELL_SIZE);
tryDirection(tx, ty);
}
function tryDirection(targetX, targetY) {
if (targetX > 0 && direction.x < 1) nextDirection = { x: 1, y: 0 };
else if (targetX < 0 && direction.x > -1) nextDirection = { x: -1, y: 0 };
else if (targetY > 0 && direction.y < 1) nextDirection = { x: 0, y: 1 };
else if (targetY < 0 && direction.y > -1) nextDirection = { x: 0, y: -1 };
// else ignore — would reverse
}
// ---- Core game loop ----
function gameTick() {
if (!running || paused || gameOver) return;
direction = nextDirection;
const head = snake[0];
const newHead = { x: head.x + direction.x, y: head.y + direction.y };
// Wall collision
if (newHead.x < 0 || newHead.x >= GRID_SIZE || newHead.y < 0 || newHead.y >= GRID_SIZE) {
endGame();
return;
}
// Self collision (skip the tail cell that will move away, unless eating food)
const eating = (newHead.x === food.x && newHead.y === food.y);
const checkCollision = snake.slice(0, 1).concat(eating ? snake : snake.slice(1));
if (checkCollision.some(s => s.x === newHead.x && s.y === newHead.y)) {
endGame();
return;
}
snake.unshift(newHead);
if (eating) {
score += FOOD_POINTS;
spawnParticles(newHead.x * CELL_SIZE + CELL_SIZE / 2, newHead.y * CELL_SIZE + CELL_SIZE / 2);
placeFood();
updateHUD();
} else {
snake.pop();
}
draw();
scheduleNextTick();
}
function scheduleNextTick() {
lastMoveTime = performance.now();
tickTimer = setTimeout(gameTick, MOVE_INTERVAL);
}
function gameLoopAnimation() {
if (running && !paused && !gameOver) {
updateParticles();
}
animationFrameId = requestAnimationFrame(renderLoop);
}
function renderLoop() {
if (running && !paused && !gameOver) {
draw();
}
animationFrameId = requestAnimationFrame(renderLoop);
}
// ---- Particles ----
function spawnParticles(cx, cy) {
const count = 14;
for (let i = 0; i < count; i++) {
const angle = (Math.PI * 2 * i) / count + Math.random() * 0.4;
const speed = 1.2 + Math.random() * 2.5;
particles.push({
x: cx,
y: cy,
vx: Math.cos(angle) * speed,
vy: Math.sin(angle) * speed,
life: 1.0,
decay: 0.02 + Math.random() * 0.02,
size: 1.5 + Math.random() * 2.5
});
}
}
function updateParticles() {
for (let i = particles.length - 1; i >= 0; i--) {
const p = particles[i];
p.x += p.vx;
p.y += p.vy;
p.vx *= 0.94;
p.vy *= 0.94;
p.life -= p.decay;
if (p.life <= 0) particles.splice(i, 1);
}
}
// ---- Drawing ----
function draw() {
ctx.clearRect(0, 0, W, H);
// Grid background
drawGrid();
// Draw food
drawFood();
// Draw snake
drawSnake();
// Draw particles
drawParticles();
}
function drawGrid() {
ctx.strokeStyle = 'rgba(40, 40, 70, 0.4)';
ctx.lineWidth = 1;
for (let i = 0; i <= GRID_SIZE; i++) {
const p = i * CELL_SIZE;
ctx.beginPath();
ctx.moveTo(p, 0);
ctx.lineTo(p, H);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(0, p);
ctx.lineTo(W, p);
ctx.stroke();
}
}
function drawFood() {
const cx = food.x * CELL_SIZE + CELL_SIZE / 2;
const cy = food.y * CELL_SIZE + CELL_SIZE / 2;
const r = CELL_SIZE * 0.38;
// Glow pulse
const pulse = 0.6 + 0.4 * Math.sin(performance.now() * 0.005);
ctx.save();
ctx.shadowColor = '#ff3377';
ctx.shadowBlur = 18 * pulse;
ctx.fillStyle = '#ff3377';
ctx.beginPath();
ctx.arc(cx, cy, r, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
// Inner highlight
ctx.save();
ctx.shadowBlur = 0;
ctx.fillStyle = '#ffcce8';
ctx.beginPath();
ctx.arc(cx - r * 0.25, cy - r * 0.25, r * 0.35, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
}
function drawSnake() {
for (let i = 0; i < snake.length; i++) {
const seg = snake[i];
const px = seg.x * CELL_SIZE;
const py = seg.y * CELL_SIZE;
const isHead = (i === 0);
const pad = isHead ? 1 : 2;
// Color gradient from head (bright) to tail (dim)
const t = i / Math.max(snake.length - 1, 1);
const r = Math.round(0 + t * 0 * 0);
const g = Math.round(255 * (1 - t * 0.35));
const b = Math.round(200 + t * 55);
const alpha = 1 - t * 0.25;
ctx.save();
if (isHead) {
ctx.shadowColor = '#00ffcc';
ctx.shadowBlur = 12;
ctx.fillStyle = `rgba(${r},${g},${b},${alpha})`;
} else {
ctx.fillStyle = `rgba(${r},${g},${b},${alpha})`;
}
roundRect(ctx, px + pad, py + pad, CELL_SIZE - pad * 2, CELL_SIZE - pad * 2, 6);
ctx.fill();
ctx.restore();
}
}
function drawEyes(headX, headY, dirX, dirY) {
const cx = headX * CELL_SIZE + CELL_SIZE / 2;
const cy = headY * CELL_SIZE + CELL_SIZE / 2;
const eyeR = 2.2;
// Offset eye positions based on direction
const off = CELL_SIZE * 0.16;
let ex1, ey1, ex2, ey2;
const dx = dirX, dy = dirY;
// Perpendicular offset for eye separation
let px = -dy, py = dx;
ex1 = cx + dx * off + px * 3;
ey1 = cy + dy * off + py * 3;
ex2 = cx + dx * off - px * 3;
ey2 = cy + dy * off - py * 3;
ctx.fillStyle = '#ffffff';
ctx.beginPath();
ctx.arc(ex1, ey1, eyeR, 0, Math.PI * 2);
ctx.arc(ex2, ey2, eyeR, 0, Math.PI * 2);
ctx.fill();
// Pupils
ctx.fillStyle = '#0e0e1a';
ctx.beginPath();
ctx.arc(ex1 + dx * 0.6, ey1 + dy * 0.6, eyeR * 0.45, 0, Math.PI * 2);
ctx.arc(ex2 + dx * 0.6, ey2 + dy * 0.6, eyeR * 0.45, 0, Math.PI * 2);
ctx.fill();
}
function roundRect(ctx, x, y, w, h, r) {
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.lineTo(x + w - r, y);
ctx.quadraticCurveTo(x + w, y, x + w, y + r);
ctx.lineTo(x + w, y + h - r);
ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
ctx.lineTo(x + r, y + h);
ctx.quadraticCurveTo(x, y + h, x, y + h - r);
ctx.lineTo(x, y + r);
ctx.quadraticCurveTo(x, y, x + r, y);
ctx.closePath();
}
function drawParticles() {
for (const p of particles) {
ctx.save();
ctx.globalAlpha = Math.max(0, p.life);
ctx.fillStyle = '#00ffcc';
ctx.shadowColor = '#00ffcc';
ctx.shadowBlur = 8;
ctx.beginPath();
ctx.arc(p.x, p.y, p.size * p.life, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
}
}
// ---- Game control ----
function startGame() {
createSnake();
placeFood();
score = 0;
scoreEl.textContent = '0';
particles = [];
updateHUD();
running = true;
gameOver = false;
paused = false;
showStartBanner = false;
if (blinkTimer) clearInterval(blinkTimer);
overlay.classList.add('hidden');
scheduleNextTick();
}
function restart() {
startGame();
}
function endGame() {
gameOver = true;
running = false;
if (tickTimer) clearTimeout(tickTimer);
// Best score tracking
if (score > bestScore) {
bestScore = score;
}
highScoreLocal = bestScore;
updateHUD();
// Show overlay
overlay.classList.remove('hidden');
overlay.innerHTML = '';
const h1 = document.createElement('h1');
h1.textContent = 'GAME OVER';
const p1 = document.createElement('p');
p1.textContent = `Score: ${score}`;
const hints = document.createElement('div');
hints.className = 'restart-hint';
hints.textContent = 'Press Space or Enter to play again · Press P to pause';
overlay.appendChild(h1);
overlay.appendChild(p1);
overlay.appendChild(hints);
}
function togglePause() {
if (!running || gameOver) return;
paused = !paused;
if (paused) {
if (tickTimer) clearTimeout(tickTimer);
overlay.innerHTML = '';
const h1 = document.createElement('h1');
h1.textContent = 'PAUSED';
h1.style.fontSize = '34px';
const p = document.createElement('p');
p.textContent = 'Press P or Esc to resume';
const hints = document.createElement('div');
hints.className = 'restart-hint';
hints.textContent = 'Press P to resume';
overlay.appendChild(h1);
overlay.appendChild(p);
overlay.appendChild(hints);
overlay.classList.remove('hidden');
} else {
overlay.classList.add('hidden');
scheduleNextTick();
}
}
// Start render loop so the game animates in the background immediately
renderLoop();
// Auto-start demo after a short delay so something meaningful shows on first paint
setTimeout(() => {
startGame();
}, 600);
})();
</script>
</body>
</html>