Llama 3.3 70B × doom
0.3DDA raycaster + textures + door + minimap + Z-buffer — the signature challenge
correctness 0.0quality 1.0documentation 0.04262ms
$ cat doom.prompt — what the model was asked
Implement a first-person 3D raycasting engine in a single self-contained HTML file with no external libraries, no external images, and no CDN scripts. This is the hardest challenge in the benchmark. Partial credit is given per requirement met. ## Rendering - DDA (Digital Differential Analysis) raycasting — not a simplified ray-box approximation - Fish-eye correction applied to all wall distances - **Procedurally generated wall textures** using canvas math only (no image files, no data URIs): at least 3 distinct texture patterns (e.g. checkerboard, brick, stripe) assigned to different wall types in the map - Perspective-correct texture mapping onto wall columns - Distance-based shading: walls darken smoothly as they recede (multiply shade by 1/distance, clamped) - Ceiling rendered as a flat dark color; floor as a slightly lighter flat color - Target: 60fps at 640×480 internal resolution scaled to fill the browser window ## Map - Hard-coded map of at least 16×16 cells encoded as a 2D array - Non-trivial layout: at least 3 distinct rooms connected by corridors, one dead end, one secret area - At least 3 wall types (mapped to the 3 texture patterns) - One door cell (wall type 4) that opens when the player is within 1.5 cells and presses E; opened doors become passable and render as open archways - One exit cell — reaching it displays a 'LEVEL COMPLETE — [MM:SS]' overlay - Player spawn position defined in the map; facing toward the first corridor ## Player - WASD movement with smooth speed (moveSpeed: 3 cells/sec, rotSpeed: 2 rad/sec) - Mouse-look for horizontal rotation using the Pointer Lock API (click canvas to lock) - Collision detection: AABB against all solid walls (player radius: 0.2 cells) - Field of view: 66 degrees ## Z-buffer - Maintain a per-column Z-buffer (array of wall distances) for correct depth ordering - Use it to clip any future sprite/overlay rendering to avoid drawing behind walls ## HUD - Minimap in top-left corner: draw map cells as colored squares, player as a dot with a direction arrow; scale: 6px per cell - FPS counter (rolling average over last 30 frames) in top-right corner - 'Press E to open door' hint rendered in the center-bottom when a door is within 1.5 cells ## Code quality - Single HTML file, all JS inline in <script> tags, all CSS inline in <style> - requestAnimationFrame game loop with delta-time movement - Organized into clearly named functions: initMap(), castRay(), drawWallColumn(), drawHUD(), drawMinimap(), gameLoop(), handleInput() - No god-object — game state in a plain JS object, renderer functions take state as argument Scoring: the judge scores each major section (rendering, map, player, HUD, code) independently. A beautiful but mathematically wrong perspective loses on correctness. A correct raycaster with unreadable code loses on quality. Both must be right to score above 8.
run 1 of 1
0.3correctness 0.0quality 1.0documentation 0.04262ms
# judge: The response is truncated mid-code, leaving the file syntactically invalid and missing nearly all required features (textures, HUD, minimap, input, game loop, door/exit logic, Z-buffer usage).
$ cat llama-3.3-70b.doom.r1.response
Below is a basic implementation of a first-person 3D raycasting engine in a single self-contained HTML file.
```html
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
background-color: #f0f0f0;
}
#canvas {
width: 100%;
height: 100vh;
display: block;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const map = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
];
const textures = {
1: 'checkerboard',
2: 'brick',
3: 'stripe'
};
const player = {
x: 1.5,
y: 1.5,
dirX: 0,
dirY: 1,
planeX: 0,
planeY: 0.66,
speed: 3,
rotSpeed: 2,
radius: 0.2
};
const door = {
x: 8,
y: 8,
opened: false
};
const exit = {
x: 15,
y: 15
};
const zBuffer = new Array(canvas.width).fill(Infinity);
let fps = 0;
let lastTime = 0;
let running = false;
function initMap() {
for (let i = 0; i < map.length; i++) {
for (let j = 0; j < map[i].length; j++) {
if (map[i][j] === 4) {
door.x = j;
door.y = i;
} else if (map[i][j] === 5) {
exit.x = j;
exit.y = i;
}
}
}
}
function castRay(x, y, dirX, dirY) {
let mapX = Math.floor(x);
let mapY = Math.floor(y);
let sideDistX;
let sideDistY;
let deltaDistX = Math.sqrt(1 + (dirY * dirY) / (dirX * dirX));
let deltaDistY = Math.sqrt(1 + (dirX * dirX) / (dirY * dirY));
let stepX;
let stepY;
let hit = 0;
let side;
if (dirX < 0) {
stepX = -1;
sideDistX = (x - mapX) * deltaDistX;
} else {
stepX = 1;
sideDistX = (mapX + 1 - x) * deltaDistX;
}
if (dirY < 0) {
stepY = -1;
sideDistY = (y - mapY) * deltaDistY;
} else {
stepY = 1;
sideDistY = (mapY + 1 - y) * deltaDistY;
}
while (hit === 0) {
if (sideDistX < sideDistY) {
sideDistX += deltaDistX;
mapX += stepX;
side = 0;
} else {
sideDistY += deltaDistY;
mapY += stepY;
side = 1;
}
if (map[mapY][mapX] > 0) {
if (map[mapY][mapX] === 4 && door.opened) {
continue;
}
hit = 1;
}
}
let perpWallDist;
if (side === 0) {
perpWallDist = Math.abs((mapX - x + (1 - stepX) / 2) / dirX);
} else {
perpWallDist = Math.abs((mapY - y + (1 - stepY) / 2) / dirY);
}
return perpWallDist;
}
function drawWallColumn(x, perpWallDist) {
let wallHeight = Math.floor(48000 / perpWallDist);
let start = Math.floor((240 - wallHeight) / 2);
let end = start + wallHeight;
for (let i = start; i < end; i++) {
let textureY = Math.floor(((i * 2 - 240 + wallHeight) / wallHeight) * 8);
let color;
if (map[Math.floor(player.y + player.dirY * perpWallDist)][Math.floor(player.x + player.dirX * perpWallDist)] === 1) {
color = '#aaaaaa';
} else if (map[Math.floor(player.y + player.dirY * perpWallDist)][Math.floor(player.x + player.dirX * perpWallDist)] === 2) {
color = '#ff0000';
} else if (map[Math.floor(player.y + player.dirY * perpWallDist)][Math.floor(player.x + player.dirX * perpWallDist)] === 3) {
color = '#00ff00';
}
ctx.fillStyle = color;
ctx.fillRect(x, start, 1, wallHeight);
}
return perpWallDist;
}
function drawHUD() {
ctx.fillStyle = '#000000';
ctx.fillRect(0, 0, 80, 80);
ctx.fillStyle = '#ffffff';
ctx.font = '12px Arial';
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.fillText('FPS: ' + fps.toFixed(2), 10, 10);
ctx.fillStyle = '#000000';
ctx.fillRect(canvas.width - 80, 0, 80, 80);
ctx.fillStyle = '#ffffff';
ctx.font = '12px Arial