MODEL Aqwen3:8bDNF
No usable answer reached the harness (ERR). Counted as a did-not-finish.
Answers below are anonymized and shuffled. Read, judge, pick a favourite — then scroll down and reveal the models.
The reveal also holds a frontier reference on the same task (Claude Opus 5) — kept out of sight here so it cannot steer your judgement.
Create ONE self-contained HTML file (STRICT LIMIT: max 120 lines total) that shows a billiard break with rolling friction on a <canvas>. A cue ball strikes a rack of exactly 10 numbered balls on a table with cushions. Model ball-to-ball elastic collisions, cushion bounces and rolling friction so the balls slow down and come to rest. When all balls have stopped, re-rack and break again automatically. Smooth requestAnimationFrame animation, NO user input, starts immediately and keeps running. No external libraries, no comments needed. Output ONLY the HTML file content, nothing else.
```html
<!DOCTYPE html>
<html>
<head><title>Billiard Break</title></head>
<body style="margin: 0; background-color: #2c3e50;"><canvas id="billiardsCanvas" width="800" height="450" style="background-color: #1abc9c; border: 10px solid #2ecc71;"></canvas><script>
const canvas = document.getElementById('billiardsCanvas');
const ctx = canvas.getContext('2d');
let balls = [];
let isBreaking = false;
let frameCount = 0;
const R = 8; // Ball radius
const FRICTION = 0.995;
const STOP_THRESHOLD = 0.1;
const TABLE_WIDTH = canvas.width - 20;
const TABLE_HEIGHT = canvas.height - 20;
function initRack() {
balls = [];
// Cue Ball (Ball 0)
balls.push({ x: 50, y: 225, vx: 10, vy: 0, radius: R, id: 0, color: 'white', isCue: true });
// Rack of 10 balls (Numbered 1 to 10)
for (let i = 0; i < 3; i++) { // Rows (i=0 is top)
for (let j = 0; j < 4 - Math.min(i, 2); j++) { // Columns
const index = 1 + i * 4 + j;
if (index <= 10) {
balls.push({ x: 50 + 30 + j * 30, y: 225 - i * 30, vx: 0, vy: 0, radius: R, id: index, color: ['#e74c3c', '#f1c40f', '#9b59b6', '#3498db'][index % 4], isCue: false });
}
}
}
// Adjust cue ball starting position slightly for better break angle
balls[0].x = 50; balls[0].y = 225;
}
function update() {
if (!isBreaking) return;
for (let i = 0; i < balls.length; i++) {
const ball = balls[i];
// Apply friction
ball.vx *= FRICTION;
ball.vy *= FRICTION;
// Check if stationary
if (Math.hypot(ball.vx, ball.vy) < STOP_THRESHOLD && Math.abs(ball.x - balls[0].x) > 10) {
// Only mark as stopped if not the cue ball and moving slowly
if (!ball.isCue && Math.random() < 0.95) { // Simple random check to prevent immediate re-break
ball.vx = 0;
ball.vy = 0;
}
}
// Update position
ball.x += ball.vx;
ball.y += ball.vy;
}
let collisionsOccurred = false;
// Cushion Collision
for (const ball of balls) {
if (ball.x - R < 0 || ball.x + R > canvas.width) {
ball.vx *= -1;
ball.x = Math.max(R, Math.min(canvas.width - R, ball.x));
collisionsOccurred = true;
}
if (ball.y - R < 0 || ball.y + R > canvas.height) {
ball.vy *= -1;
ball.y = Math.max(R, Math.min(canvas.height - R, ball.y));
collisionsOccurred = true;
}
}
// Ball-to-Ball Collision (N^2 check)
for (let i = 0; i < balls.length; i++) {
const b1 = balls[i];
for (let j = i + 1; j < balls.length; j++) {
const b2 = balls[j];
const dx = b2.x - b1.x;
const dy = b2.y - b1.y;
const distSq = dx * dx + dy * dy;
const minDist = b1.radius + b2.radius;
if (distSq < minDist * minDist) {
collisionsOccurred = true;
// Collision resolution: Overlap correction
const distance = Math.sqrt(distSq);
const correctionX = ((minDist / distance) - 1) * dx * 0.5;
const correctionY = ((minDist / distance) - 1) * dy * 0.5;
b1.x -= correctionX; b1.y -= correctionY;
b2.x += correctionX; b2.y += correctionY;
// Calculate relative velocity and normal vector
const dvx = b2.vx - b1.vx;
const dvy = b2.vy - b1.vy;
const dotProd = dvx * dx + dvy * dy;
if (dotProd > 0) continue; // Balls moving away
// Impulse calculation (Elastic collision, masses assumed equal to 1)
const impulse = -(1 + 1) / (1/1 + 1/1) * dotProd;
b1.vx -= dvx * impulse * dx / (dx * dx + dy * dy);
b1.vy -= dvy * impulse * dy / (dx * dx + dy * dy);
b2.vx += dvx * impulse * dx / (dx * dx + dy * dy);
b2.vy += dvy * impulse * dy / (dx * dx + dy * dy);
}
}
}
// Check if all balls have stopped
const activeBalls = balls.filter(b => Math.hypot(b.vx, b.vy) >= STOP_THRESHOLD);
if (activeBalls.length === 0 && collisionsOccurred === false && frameCount > 60) {
isBreaking = false;
setTimeout(() => {
initRack();
// Give the cue ball a strong initial hit vector after waiting 1 second
balls[0].vx = Math.cos(Math.PI / 4) * 15;
balls[0].vy = -Math.sin(Math.PI / 4) * 15;
isBreaking = true;
}, 1200);
}
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (const ball of balls) {
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
ctx.fillStyle = ball.color;
if (ball.isCue) ctx.strokeStyle = 'white'; else ctx.strokeStyle = '#333';
ctx.lineWidth = 1;
ctx.fill();
ctx.stroke();
// Draw number on balls 1-9
if (!ball.isCue && ball.id >= 1 && ball.id <= 9) {
ctx.fillStyle = 'black';
ctx.font = 'bold 14px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(ball.id, ball.x, ball.y);
}
}
}
function gameLoop() {
update();
draw();
requestAnimationFrame(gameLoop);
}
initRack(); // Initial setup
gameLoop(); // Start the animation loop
</script></body></html>
``````html
<!DOCTYPE html>
<html>
<head>
<canvas id="c" width=800 height=600 style="background:#4CAF50"></canvas>
<style>canvas{position:absolute; left:0; top:-30px}</style>
</head>
<body>
<script>
const c=document.getElementById('c'), ctx=c.getContext('2d');
class Ball {
constructor(x,y) {this.x=x,this.y=y,this.vx=0,this.vy=0;
this.r=15;this.friction=.98;this restitution=.7}
draw() {
ctx.fillStyle=randomColor();
ctx.beginPath();ctx.arc(this.x,this.y,this.r,0,Math.PI*2);
ctx.fill()
}
update() {
if(Math.abs(this.vx)<.1 && Math.abs(this.vy)<.1) return;
this.vx *= this.friction;this.vy *= this.friction;
this.x += this.vx;this.y += this.vy
}
}
let balls=[...Array(10)].map((_,i)=>new Ball(400+Math.random()*200-100,300));
balls[0].vx=5;balls[0].vy=-5;
const cue=new Ball(100,300);
let stopped=true;
function randomColor(){return`hsl(${Math.random()*360},70%,80%)`}
function animate(){
ctx.clearRect(0,0,c.width,c.height);
balls.forEach(b=>{b.update();b.draw()});
cue.draw();
if(!stopped && balls.every(b=>{
return Math.abs(b.vx)<.1 && Math.abs(b.vy)<.1
})){
stopped=true;balls.splice(1);balls.push(new Ball(400+Math.random()*200-100,300));
cue.x=100;cue.y=300;
}
requestAnimationFrame(animate)
}
function Collision(b1,b2){
if(BBoxCollision(b1,b2)){
let dx=b2.x-b1.x, dy=b2.y-b1.y;
let dvx=b2.vx - b1.vx, dvy=b2.vy - b1.vy;
let dot=(dx*dx + dy*dy);
if(dot>0){
let temp = (b1.vx*b2.vx + b1.vy*b2.vy) / dot * 0.5;
b1.vx -= (dvx * temp)
b1.vy -= (dvy * temp)
b2.vx += (dvx * temp)
b2.vy += (dvy * temp)
}
}
}
function BBoxCollision(b1,b2){
return Math.abs(b1.x - b2.x) < b1.r + b2.r &&
Math.abs(b1.y - b2.y) < b1.r + b2.r
}
animate()
</script>
</body>
</html>
``````html
<!DOCTYPE html>
<html>
<head>
<title>Billiard Break Simulation</title>
<style>body { margin: 0; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #222; }</style>
</head>
<body>
<canvas id="billiardCanvas"></canvas>
<script>
const canvas = document.getElementById('billiardCanvas');
const ctx = canvas.getContext('2d');
let ws, balls = [];
const TABLE_WIDTH = 800;
const TABLE_HEIGHT = 400;
const BALL_RADIUS = 10;
const FRICTION = 0.995;
const DAMPING = 0.999;
const CUE_BALL_START_POS = { x: TABLE_WIDTH / 2, y: TABLE_HEIGHT - 3 * BALL_RADIUS };
canvas.width = TABLE_WIDTH;
canvas.height = TABLE_HEIGHT;
function createBalls(racked) {
balls = [];
const ballCount = racked ? 10 : 11;
for (let i = 0; i < ballCount; i++) balls.push({ x: Math.random() * TABLE_WIDTH, y: Math.random() * TABLE_HEIGHT, vx: 0, vy: 0, r: BALL_RADIUS, id: i });
// Set up the rack structure
const startX = TABLE_WIDTH / 2 - (ballCount > 1 ? 5 * BALL_RADIUS : 0);
const startY = TABLE_HEIGHT / 2 - 3 * BALL_RADIUS;
for (let i = 0; i < ballCount; i++) {
balls[i].x = startX + (i % 4) * (BALL_RADIUS * 2.5);
balls[i].y = startY + Math.floor(i / 4) * (BALL_RADIUS * 2.5);
}
// Cue ball setup (last ball added is the cue ball)
const cueBall = { x: CUE_BALL_START_POS.x, y: CUE_BALL_START_POS.y, vx: -10, vy: 0, r: BALL_RADIUS, id: 'cue' };
balls[ballCount - 1] = cueBall;
}
function checkCollision(b1, b2) {
const dx = b2.x - b1.x;
const dy = b2.y - b1.y;
const distSq = dx * dx + dy * dy;
const minDistance = b1.r + b2.r;
if (distSq < minDistance * minDistance) {
let angle = Math.atan2(dy, dx);
let overlap = minDistance - Math.sqrt(distSq);
// Resolve overlap by pushing them apart along the collision normal
b1.x -= (overlap / 2) * Math.cos(angle);
b1.y -= (overlap / 2) * Math.sin(angle);
b2.x += (overlap / 2) * Math.cos(angle);
b2.y += (overlap / 2) * Math.sin(angle);
// Calculate impulse for elastic collision
let nx = dx / Math.sqrt(distSq);
let ny = dy / Math.sqrt(distSq);
let v1n = b1.vx * nx + b1.vy * ny;
let v2n = b2.vx * nx + b2.vy * ny;
let impulseMagnitude = 2 * (v2n - v1n) / (1/1 + 1/1); // Mass=1 for all balls
b1.vx -= impulseMagnitude * nx;
b1.vy -= impulseMagnitude * ny;
b2.vx += impulseMagnitude * nx;
b2.vy += impulseMagnitude * ny;
return true;
}
return false;
}
function updatePhysics() {
for (let i = 0; i < balls.length; i++) {
const b = balls[i];
// Apply friction and damping
b.vx *= FRICTION;
b.vy *= FRICTION;
b.vx *= DAMPING;
b.vy *= DAMPING;
// Update position
b.x += b.vx;
b.y += b.vy;
// Wall collisions (Cushions)
if (b.x - b.r < 0 || b.x + b.r > TABLE_WIDTH) {
b.vx *= -1;
b.x = Math.max(b.r, Math.min(b.x, TABLE_WIDTH - b.r));
}
if (b.y - b.r < 0 || b.y + b.r > TABLE_HEIGHT) {
b.vy *= -1;
b.y = Math.max(b.r, Math.min(b.y, TABLE_HEIGHT - b.r));
}
// Collisions with other balls
for (let j = i + 1; j < balls.length; j++) {
if (checkCollision(b, balls[j])) {}
}
}
}
function draw() {
ctx.fillStyle = '#004c00';
ctx.fillRect(0, 0, TABLE_WIDTH, TABLE_HEIGHT);
balls.forEach(b => {
ctx.beginPath();
ctx.arc(b.x, b.y, b.r, 0, Math.PI * 2);
ctx.fillStyle = (b.id === 'cue') ? '#333' : (parseInt(b.id) % 2 == 0 ? '#ccc' : '#eee');
ctx.fill();
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
ctx.stroke();
});
}
function animate() {
updatePhysics();
draw();
let activeBalls = balls.filter(b => Math.abs(b.vx) > 0.1 || Math.abs(b.vy) > 0.1);
if (activeBalls.length > 0) {
requestAnimationFrame(animate);
} else {
setTimeout(() => {
createBalls(true); // Re-rack and re-break
requestAnimationFrame(animate);
}, 1000);
}
}
createBalls(false);
animate();
</script>
</body>
</html>
``````html
<!DOCTYPE html>
<html>
<head>
<title>Billiard Break</title>
<style>body{margin:0;overflow:hidden;background:#333}canvas{display:block}</style>
</head>
<body>
<canvas id="billiardsCanvas"></canvas>
<script>
const canvas = document.getElementById('billiardsCanvas');
const ctx = canvas.getContext('2d');
let W, H;
function setup() {
W = canvas.width = 800;
H = canvas.height = 500;
}
setup();
const R = 8;
const DAMPING = 0.995; // Rolling friction factor
const WALL_DAMPING = 0.85; // Energy loss on cushion bounce
let balls = [];
let frameCount = 0;
function createRack(startX, startY, spacing) {
balls = [];
for (let r = 0; r < 3; r++) {
for (let c = 0; c < 4; c++) {
// Creates a semi-rack pattern
if ((r + c) % 2 === 0) {
balls.push({ x: startX + c * spacing, y: startY - r * spacing, vx: (c === 3 ? 1 : 0), vy: (r === 0 ? 0.5 : 0), id: (r * 4 + c) });
} else {
balls.push({ x: startX + c * spacing, y: startY - r * spacing, vx: (c === 3 ? 1 : 0), vy: (r === 0 ? 0.5 : 0), id: (r * 4 + c) });
}
}
}
// Cue ball initialization (index 0)
balls[0] = { x: startX - spacing, y: startY, vx: 12, vy: 0 };
}
function initGame() {
createRack(W * 0.4, H * 0.75, R * 3);
frameCount = 0;
}
function checkCollisions(b1, b2) {
const dx = b2.x - b1.x;
const dy = b2.y - b1.y;
let distSq = dx * dx + dy * dy;
let minDistSq = 4 * R * R;
if (distSq < minDistSq) {
let nx = dx / Math.sqrt(distSq);
let ny = dy / Math.sqrt(distSq);
let overlap = Math.sqrt(minDistSq) - Math.sqrt(distSq);
// Separate balls slightly to prevent sticking
b1.x -= nx * overlap * 0.5;
b1.y -= ny * overlap * 0.5;
b2.x += nx * overlap * 0.5;
b2.y += ny * overlap * 0.5;
// Elastic collision response (simplified)
let v_dot = b1.vx * nx + b1.vy * ny;
let v_other_dot = b2.vx * nx + b2.vy * ny;
b1.vx -= 2 * v_other_dot * nx;
b1.vy -= 2 * v_other_dot * ny;
b2.vx += 2 * v_dot * nx;
b2.vy += 2 * v_dot * ny;
}
}
function updatePhysics() {
let allStopped = true;
for (let i = 0; i < balls.length; i++) {
const b = balls[i];
if (Math.abs(b.vx) > 0.1 || Math.abs(b.vy) > 0.1) allStopped = false;
// Apply friction damping
b.vx *= DAMPING;
b.vy *= DAMPING;
// Update position
b.x += b.vx;
b.y += b.vy;
// Wall collisions (Horizontal)
if (Math.abs(b.x - R) < 0 || Math.abs(b.x - W - R) < 0) {
b.vx *= -WALL_DAMPING;
b.x = Math.max(R, Math.min(W - R, b.x));
}
// Wall collisions (Vertical)
if (Math.abs(b.y - R) < 0 || Math.abs(b.y - H - R) < 0) {
b.vy *= -WALL_DAMPING;
b.y = Math.max(R, Math.min(H - R, b.y));
}
// Check collisions with other balls
for (let j = i + 1; j < balls.length; j++) {
checkCollisions(b, balls[j]);
}
}
return allStopped;
}
function draw() {
ctx.fillStyle = '#0B283D'; // Table color
ctx.fillRect(0, 0, W, H);
balls.forEach((b, i) => {
let color = (i === 0) ? 'red' : (i % 2 === 0 ? 'white' : '#CC6633'); // Cue ball is red
ctx.beginPath();
ctx.arc(b.x, b.y, R, 0, Math.PI * 2);
ctx.fillStyle = color;
ctx.fill();
});
}
function gameLoop() {
const stopped = updatePhysics();
draw();
if (stopped && frameCount % 60 === 0) {
setTimeout(initGame, 1000); // Re-rack after a delay
} else if (!stopped) {
frameCount++;
requestAnimationFrame(gameLoop);
}
}
window.onload = () => {
initGame();
requestAnimationFrame(gameLoop);
};
</script>
</body>
</html>
```| Blind label | Model | Blind score | Latency | Status |
|---|---|---|---|---|
| MODEL A | qwen3:8b | — | — | DNF |
| MODEL B | gemma4:26b | — | — | DNF |
| MODEL C | qwen3:14b | — | 45.9 s | OK |
| MODEL D | mistral-small:24b | — | — | DNF |
| MODEL E | deepseek-r1:14b | — | 81.8 s | OK |
| MODEL F | qwen3-coder:30b | — | 26.2 s | OK |
| MODEL G | qwen3.5:9b | — | 49.5 s | OK |
| MODEL H | llama3.1:8b | — | — | DNF |
These models answered the identical prompt outside the blind field. They are deliberately not scored and not part of the blind comparison — they are there so you can see where a frontier model lands on the same task.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Billiard Break</title>
<style>
html,body{margin:0;height:100%;background:#12100e;display:flex;align-items:center;justify-content:center;font-family:system-ui,sans-serif}
canvas{max-width:96vw;max-height:92vh;border-radius:14px;box-shadow:0 24px 60px #000a}
</style>
</head>
<body>
<canvas id="c" width="900" height="480"></canvas>
<script>
const cv=document.getElementById('c'),g=cv.getContext('2d');
const W=900,H=480,R=11,PAD=42,L=PAD,T=PAD,Rt=W-PAD,B=H-PAD;
const COL={1:'#e8c22a',2:'#1f5fd0',3:'#d02b25',4:'#7a2bb5',5:'#e07a1c',6:'#1d8a4a',7:'#8a2a22',8:'#141414',9:'#e8c22a',10:'#1f5fd0'};
let balls=[],rest=0;
function rack(){
balls=[];let n=1;const ax=Rt-190,ay=H/2,d=R*2+0.6;
for(let row=0;row<4;row++)for(let k=0;k<=row;k++)
balls.push({x:ax+row*d*0.866,y:ay+(k-row/2)*d,vx:0,vy:0,n:n,c:COL[n++]});
balls.push({x:L+150,y:H/2+(Math.random()-.5)*10,vx:12+Math.random()*5,vy:(Math.random()-.5)*1.4,n:0,c:'#f6f3ea'});
rest=0;
}
function step(dt){
for(const b of balls){b.x+=b.vx*dt;b.y+=b.vy*dt;}
for(const b of balls){
if(b.x-R<L){b.x=L+(L-(b.x-R))-R;b.vx=-b.vx*0.92;}
if(b.x+R>Rt){b.x=Rt-((b.x+R)-Rt)-R;b.vx=-b.vx*0.92;}
if(b.y-R<T){b.y=T+(T-(b.y-R))-R;b.vy=-b.vy*0.92;}
if(b.y+R>B){b.y=B-((b.y+R)-B)-R;b.vy=-b.vy*0.92;}
}
for(let i=0;i<balls.length;i++)for(let j=i+1;j<balls.length;j++){
const a=balls[i],b=balls[j];let dx=b.x-a.x,dy=b.y-a.y,d=Math.hypot(dx,dy);
if(d===0){dx=0.01;d=0.01;}
if(d<R*2){
const nx=dx/d,ny=dy/d,ov=(R*2-d)/2;
a.x-=nx*ov;a.y-=ny*ov;b.x+=nx*ov;b.y+=ny*ov;
const p=(a.vx-b.vx)*nx+(a.vy-b.vy)*ny;
if(p>0){const e=p*0.98;a.vx-=e*nx;a.vy-=e*ny;b.vx+=e*nx;b.vy+=e*ny;}
}
}
}
function friction(){
let moving=false;
for(const b of balls){
const s=Math.hypot(b.vx,b.vy);
if(s<0.06){b.vx=0;b.vy=0;continue;}
const f=Math.max(0,1-0.012-0.02/s);
b.vx*=f;b.vy*=f;moving=true;
}
return moving;
}
function felt(){
g.fillStyle='#3a2113';g.fillRect(0,0,W,H);
g.fillStyle='#4d2c19';g.fillRect(8,8,W-16,H-16);
const grd=g.createRadialGradient(W/2,H/2,40,W/2,H/2,W*0.62);
grd.addColorStop(0,'#1f8a55');grd.addColorStop(1,'#0e5231');
g.fillStyle=grd;g.fillRect(L-14,T-14,Rt-L+28,B-T+28);
g.strokeStyle='#0a3a24';g.lineWidth=3;g.strokeRect(L-14,T-14,Rt-L+28,B-T+28);
g.strokeStyle='rgba(255,255,255,.12)';g.lineWidth=1;
g.beginPath();g.moveTo(L+150,T-14);g.lineTo(L+150,B+14);g.stroke();
}
function draw(){
felt();
for(const b of balls){
g.beginPath();g.ellipse(b.x+4,b.y+7,R*1.05,R*0.7,0,0,7);g.fillStyle='rgba(0,0,0,.32)';g.fill();
}
for(const b of balls){
g.beginPath();g.arc(b.x,b.y,R,0,7);g.fillStyle=b.c;g.fill();
if(b.n>8){g.save();g.beginPath();g.arc(b.x,b.y,R,0,7);g.clip();
g.fillStyle='#f6f3ea';g.fillRect(b.x-R,b.y-R,R*2,R*0.62);g.fillRect(b.x-R,b.y+R*0.38,R*2,R*0.62);g.restore();}
const sh=g.createRadialGradient(b.x-R*0.4,b.y-R*0.45,1,b.x,b.y,R*1.3);
sh.addColorStop(0,'rgba(255,255,255,.55)');sh.addColorStop(0.5,'rgba(255,255,255,0)');sh.addColorStop(1,'rgba(0,0,0,.4)');
g.fillStyle=sh;g.beginPath();g.arc(b.x,b.y,R,0,7);g.fill();
if(b.n>0){
g.beginPath();g.arc(b.x,b.y,R*0.52,0,7);g.fillStyle='#f6f3ea';g.fill();
g.fillStyle='#111';g.font='bold 10px system-ui';g.textAlign='center';g.textBaseline='middle';
g.fillText(b.n,b.x,b.y+0.5);
}
g.strokeStyle='rgba(0,0,0,.35)';g.lineWidth=1;g.beginPath();g.arc(b.x,b.y,R-0.5,0,7);g.stroke();
}
}
function loop(){
for(let s=0;s<5;s++)step(0.2);
const moving=friction();
if(!moving){if(++rest>70)rack();}else rest=0;
draw();
requestAnimationFrame(loop);
}
rack();loop();
</script>
</body>
</html>