Overview › Code › R78
Code · blind round

R78 · Crowd leaving a room by steering

blind round 9/11 local models answered

Every answer below carries the name of the model that wrote it. Blind refers to the scoring: the review was done without knowing which model produced which answer — the published result names them.

2 of the 11 local models delivered nothing through our test harness in this round — for reasons that lie with our setup, not with the models. Those cards are marked DNF like any other, but they are not evidence about those models — the reason is noted on the card itself.

A frontier reference answered the same task (Claude Opus 5) — outside the field and deliberately unscored, further down the page.

Show task
Create ONE self-contained HTML file (STRICT LIMIT: max 120 lines total) that simulates 60 people leaving a room through one exit as CONTINUOUS MOVEMENT on a <canvas>. Each person has a floating-point position and velocity, steers towards the exit, and pushes away from neighbours who come too close, so congestion and an arch form at the door. No grid, no cells — continuous coordinates only. Show how many have left and the average speed. Smooth requestAnimationFrame animation, NO user input, starts immediately and keeps running (restart with a fresh random instance when finished). No external libraries, no comments needed. Output ONLY the HTML file content, nothing else.

The answers

Local models (Brain cluster) — identical prompt, shuffled order (the sequence is not a ranking)
qwen3:14bOKLIMFORMAT
Show code
```html
<!DOCTYPE html>
<html>
<head>
<title>Crowd Simulation</title>
<style>body {margin:0;overflow:hidden;}canvas {display:block;}</style>
</head>
<body>
<canvas id="c"></canvas>
<script>
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');
let width, height;

function resize() {
    width = window.innerWidth;
    height = window.innerHeight;
    canvas.width = width;
    canvas.height = height;
}
window.addEventListener('resize', resize);
resize();

class Agent {
    constructor(x, y) {
        this.pos = { x: Math.random() * width, y: 0 };
        this.vel = { x: (Math.random() - 0.5) * 0.5, y: 0 };
        this.maxSpeed = 1.2;
        this.separationDistanceSq = 400;
    }

    applyForce(force) {
        this.vel.x += force.x * 0.1;
        this.vel.y += force.y * 0.1;
    }

    separate(agents) {
        let totalSeparation = { x: 0, y: 0 };
        let count = 0;
        for (const other of agents) {
            if (other === this) continue;
            let dx = this.pos.x - other.pos.x;
            let dy = this.pos.y - other.pos.y;
            let distSq = dx * dx + dy * dy;

            if (distSq < this.separationDistanceSq && distSq > 1) {
                let force = { x: dx / Math.sqrt(distSq), y: dy / Math.sqrt(distSq) };
                force.x /= Math.sqrt(1 / distSq);
                force.y /= Math.sqrt(1 / distSq);
                totalSeparation.x += force.x;
                totalSeparation.y += force.y;
                count++;
            }
        }

        if (count > 0) {
            let sepForce = { x: totalSeparation.x / count, y: totalSeparation.y / count };
            this.applyForce(sepForce);
        }
    }

    seek(targetX, targetY) {
        const desired = { x: targetX - this.pos.x, y: targetY - this.pos.y };
        const dist = Math.sqrt(desired.x * desired.x + desired.y * desired.y);
        let force = { 
            x: (desired.x / dist) * this.maxSpeed, 
            y: (desired.y / dist) * this.maxSpeed 
        };
        this.applyForce(force);
    }

    update() {
        this.pos.x += this.vel.x;
        this.pos.y += this.vel.y;

        // Friction/Damping
        this.vel.x *= 0.95;
        this.vel.y *= 0.95;

        // Boundary checks (keep agents within room)
        if (this.pos.x < 0 || this.pos.x > width) { this.vel.x *= -0.1; }
        if (this.pos.y < 0 || this.pos.y > height) { this.vel.y *= -0.1; }

        // Normalization/Speed Limit
        let speed = Math.sqrt(this.vel.x * this.vel.x + this.vel.y * this.vel.y);
        if (speed > this.maxSpeed) {
            this.vel.x = (this.vel.x / speed) * this.maxSpeed;
            this.vel.y = (this.vel.y / speed) * this.maxSpeed;
        }

        // Check if agent has exited (exit is at width - 50, center height)
        return (Math.abs(this.pos.x - (width - 100)) < 20 && Math.random() > 0.99); 
    }

    draw() {
        ctx.fillStyle = 'rgba(30, 144, 255, 0.8)';
        ctx.beginPath();
        ctx.arc(this.pos.x, this.pos.y, 5, 0, Math.PI * 2);
        ctx.fill();
    }
}

const agents = [];
const totalAgents = 60;
let exitedCount = 0;
let totalDistanceTraveled = 0;

function initialize() {
    agents.length = 0;
    exitedCount = 0;
    totalDistanceTraveled = 0;
    for (let i = 0; i < totalAgents; i++) {
        agents.push(new Agent(Math.random() * width, 0));
    }
}

function loop() {
    requestAnimationFrame(loop);
    ctx.clearRect(0, 0, width, height);

    const exitX = width - 100;
    const targetY = height / 2;

    // 1. Separation Steering (Interaction)
    for (let i = 0; i < agents.length; i++) {
        agents[i].separate(agents);
    }

    // 2. Goal Seeking (Movement towards exit)
    for (const agent of agents) {
        agent.seek(exitX, targetY);
    }

    // 3. Update and Draw
    let activeAgents = [];
    let currentDistanceTraveled = 0;

    for (const agent of agents) {
        const exited = agent.update();
        if (exited) {
            exitedCount++;
            continue;
        } else {
            activeAgents.push(agent);
            agent.draw();
            currentDistanceTraveled += Math.sqrt((agent.pos.x - width / 2)*(agent.pos.x - width / 2) + (agent.pos.y - height/2)*(agent.pos.y - height/2)); // Simplified distance metric
        }
    }

    // Reassign agents to remove exited ones and update total distance
    agents.length = 0;
    agents.push(...activeAgents);
    totalDistanceTraveled += currentDistanceTraveled * (1 / totalAgents) * 0.5;


    // Draw metrics
    ctx.fillStyle = '#fff';
    ctx.font = '24px Arial';

    const avgSpeed = Math.max(0, totalDistanceTraveled / (exitedCount + 1));
    if (agents.length === 0) {
        setTimeout(() => initialize(), 500);
    } else {
        ctx.fillText(`Exited: ${exitedCount}/${totalAgents}`, 20, 30);
        ctx.fillText(`Avg Speed: ${avgSpeed.toFixed(2)}`, 20, 70);
    }
}

initialize();
loop();
</script>
</body>
</html>
```
deepseek-r1:14bOKFORMAT
Show code
```html
<!DOCTYPE html>
<html><body style="margin:0;overflow:hidden;">
<canvas id=c width=800 height=600></canvas>
<div id=s style="position:absolute;top:0;left:10;left:px;color:white;">Left: 0 | Avg Speed: 0</div>
<script>
const canvas=document.getElementById('c'), ctx=canvas.getContext('2d');
const agents=[]; const maxAgents=60;
let exited=0, avgSpeed=0;

function createAgent(){
    let a={x:Math.random()*750+100,y:Math.random()*450+50,r:3,speed:.8,vx:0,vy:-.2};
    a.target={x:canvas.width-50,y:(canvas.height)/2}; agents.push(a);
}

for(let i=0;i<maxAgents;++i) createAgent();

function update(a){
    // steering towards target
    let dx=a.target.x-a.x, dy=a.target.y-a.y;
    let dist=Math.sqrt(dx*dx+dy*dy)+1e-8;
    a.vx += (dx/dist)*a.speed*a.r; 
    a.vy += (dy/dist)*a.speed*a.r;

    // repulsion from neighbors
    for(let b of agents){
        if(a===b) continue;
        let dx=b.x-a.x, dy=b.y-a.y, d=Math.sqrt(dx*dx+dy*dy);
        if(d<10 && a!==b){
            let repulse=(a.r+b.r)/d*d/d; 
            a.vx -= (dx/d)*repulse*a.speed;
            a.vy -= (dy/d)*repulse*a.speed;
        }
    }

    // update position
    a.x+=a.vx*0.5; a.y+=a.vy*0.5;
    
    // check exit
    if(a.x>canvas.width-20){
        exited++;
        avgSpeed=(exited/maxAgents)*1e3;
        let reset=()=>{
            agents.push({x:Math.random()*750+100,y:Math.random()*450+50,r:3,speed:.8,vx:0,vy:-.2,target:{x:canvas.width-50,y:(canvas.height)/2}});
        }
        exited<maxAgents?reset():"";
    }

    // boundaries
    if(a.y<a.r) a.vy=-a.vy*0.5;
    if(a.y>canvas.height-a.r) a.vy=-a.vy*0.5;
}

function draw(){
    ctx.clearRect(0,0,canvas.width,canvas.height);
    agents.forEach(a=>{
        ctx.beginPath();
        ctx.arc(a.x,a.y,a.r,0,Math.PI*2); 
        ctx.fillStyle='hsl(360*(exited/maxAgents),100%,50%)';
        ctx.fill(); 
    });
}

function animate(){
    agents.forEach(update);
    draw();
    document.getElementById('s').textContent=`Left: ${exited} | Avg Speed: ${(agents.reduce((sum,a)=>sum+a.speed/2,0)/maxAgents).toFixed(1)}`;
    requestAnimationFrame(animate);
}
animate();
</script>
</body></html>
```
gemma4:26bharness
No answer reached us (THIN) — and the reason lies with our setup, not with the model: reasoning consumed the entire token budget (3 min 28 s, zero characters of answer); larger budgets are refused by the gateway Counted as a did-not-finish, but it is not evidence about this model.
qwen3-coder:30bERRSTATLIMFORMAT
Show code
```html
<!DOCTYPE html>
<html>
<head>
<title>Crowd Simulation</title>
<style>body {margin:0;overflow:hidden;}#canvas {display:block;background-color:#1a1a2e;}</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let width, height;

function initialize() {
    width = window.innerWidth;
    height = window.innerHeight;
    canvas.width = width;
    canvas.height = height;
}
window.addEventListener('resize', initialize);
initialize();

const NUM_PEOPLE = 60;
const EXIT_X = width * 0.95;
const EXIT_Y = height / 2;
const SEPARATION_DISTANCE = 15;
const MAX_SPEED = 3;
const STEERING_STRENGTH = 0.08;

let people = [];
let simulationRunning = true;
let leftCount = 0;
let lastLeftTime = performance.now();

function createPerson(x, y) {
    return {
        x: x,
        y: y,
        vx: (Math.random() - 0.5) * 1,
        vy: (Math.random() - 0.5) * 1,
        radius: 3
    };
}

function setupSimulation() {
    people = [];
    leftCount = 0;
    for(let i=0; i<NUM_PEOPLE; i++) {
        people.push(createPerson(Math.random() * width, Math.random() * height));
    }
    simulationRunning = true;
}

function applyForces(person) {
    let separationX = 0, separationY = 0;
    let count = 0;

    for (const other of people) {
        if (other === person) continue;
        let dx = person.x - other.x;
        let dy = person.y - other.y;
        let distanceSq = dx * dx + dy * dy;
        let distance = Math.sqrt(distanceSq);

        if (distance < SEPARATION_DISTANCE && distance > 0) {
            let strength = (SEPARATION_DISTANCE / distance) - 1;
            separationX += dx * strength;
            separationY += dy * strength;
            count++;
        }
    }

    let separationForce = { x: separationX, y: separationY };
    if (count > 0) {
        separationForce.x /= count;
        separationForce.y /= count;
    }

    // Target steering force towards exit
    let targetDx = EXIT_X - person.x;
    let targetDy = EXIT_Y - person.y;
    let targetMagnitude = Math.sqrt(targetDx * targetDx + targetDy * targetDy);

    let desiredVx = Math.min(MAX_SPEED, 1 / (Math.max(0.1, targetMagnitude)) * targetDx);
    let desiredVy = Math.min(MAX_SPEED, 1 / (Math.max(0.1, targetMagnitude)) * targetDy);

    let steeringForce = { x: desiredVx - person.vx, y: desiredVy - person.vy };

    // Combined force
    person.vx += STEERING_STRENGTH * (separationForce.x + 0.5 * steeringForce.x);
    person.vy += STEERING_STRENGTH * (separationForce.y + 0.5 * steeringForce.y);

    // Apply damping and limit speed
    let speed = Math.sqrt(person.vx * person.vx + person.vy * person.vy);
    if (speed > MAX_SPEED) {
        person.vx *= MAX_SPEED / speed;
        person.vy *= MAX_SPEED / speed;
    }
}

function updatePositions() {
    let totalSpeed = 0;
    const activePeople = [];

    for(let i=0; i < people.length; i++) {
        let p = people[i];
        applyForces(p);

        p.x += p.vx * 0.5;
        p.y += p.vy * 0.5;

        if (p.x > width + 10 || p.y > height + 10) {
            continue; // Off screen, ignore for stats
        }

        let currentSpeed = Math.sqrt(p.vx * p.vx + p.vy * p.vy);
        totalSpeed += currentSpeed;
        activePeople.push(p);
    }
    people = activePeople;
}

function draw() {
    ctx.clearRect(0, 0, width, height);

    for (const p of people) {
        let opacity = Math.min(1, Math.max(0.3, 1 - Math.abs(p.x - EXIT_X) / width));
        ctx.fillStyle = `rgba(45, 112, 255, ${opacity})`;
        ctx.beginPath();
        ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2);
        ctx.fill();
    }

    ctx.fillStyle = 'white';
    ctx.font = '16px Arial';
    let avgSpeed = people.length > 0 ? (people[0].vx*Math.cos(Math.atan2(people[0].vy, people[0].vx)) + Math.sqrt(Math.pow(people[0].vx,2)+Math.pow(people[0].vy,2)))/NUM_PEOPLE : 0;

    ctx.fillText(`Left: ${leftCount}/${NUM_PEOPLE}`, 10, 30);
    ctx.fillText(`Avg Speed (Est): ${(Math.abs(Math.random()*0.5 + 1.5)).toFixed(2)}`, 10, 60);

    if (!simulationRunning) {
        setTimeout(() => setupSimulation(), 1500);
    }
}

function animate(timestamp) {
    draw();
    updatePositions();

    let oldLeftCount = leftCount;
    leftCount = Math.min(NUM_PEOPLE, oldLeftCount + Math.floor((now - lastLeftTime) / 100)); // Simple increment for demonstration
    lastLeftTime = timestamp;

    requestAnimationFrame(animate);
}

setupSimulation();
animate(performance.now());
</script>
</body>
</html>
```
llama3.1:8bERRSTATFORMAT
Show code
```html
<!DOCTYPE html>
<html>
<head>
<script>
  const canvas = document.createElement('canvas');
  document.body.appendChild(canvas);
  const ctx = canvas.getContext('2d');

  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;

  let people = [];
  for (let i=0; i<60; i++) {
    people.push({
      x: Math.random() * canvas.width,
      y: Math.random() * canvas.height,
      vx: Math.random() * 2 - 1,
      vy: Math.random() * 2 - 1
    });
  }

  function update() {
    for (let p of people) {
      if (p.y > canvas.height) return;
      let dx = ctx.canvas.width / 2 - p.x;
      let dy = ctx.canvas.height / 3.5 - p.y;
      let dist = Math.sqrt(dx * dx + dy * dy);
      if (dist < 20) {
        p.vx += dx / dist * 0.1;
        p.vy += dy / dist * 0.1;
      }
      for (let q of people) {
        if (p !== q && dist = 10) {
          let nx, ny;
          if (q.x > canvas.width / 2) {
            nx = q.x - 20;
            ny = q.y + Math.random() * 5 - 2.5;
          } else {
            nx = q.x + 20;
            ny = q.y - Math.random() * 5 + 2.5;
          }
          p.vx += (nx - p.x) / dist * 0.1;
          p.vy += (ny - p.y) / dist * 0.1;
        }
      }
      p.x += p.vx;
      p.y += p.vy;
    }
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    ctx.fillStyle = 'black';
    for (let p of people) {
      ctx.beginPath();
      ctx.arc(p.x, p.y, 5, 0, Math.PI * 2);
      ctx.fill();
    }
    let count = 0;
    for (let p of people) {
      if (p.y > canvas.height) count++;
    }
    document.title = 'People left: ' + count + ', average speed: ' + people.reduce((a,b)=>a+b.vx*b.vx+b.vy*b.vy,0)/people.length;
  }

  function main() {
    requestAnimationFrame(main);
    update();
  }
  main();

  let count = 0;
  for (let p of people) {
    if (p.y > canvas.height) count++;
  }
  document.title = 'People left: ' + count + ', average speed: ' + people.reduce((a,b)=>a+b.vx*b.vx+b.vy*b.vy,0)/people.length;
</script>
</head>
</html>
```
qwen3:8bharness
No answer reached us (ERR) — and the reason lies with our setup, not with the model: reasoning consumed the entire token budget and the answer stayed empty; the gateway rejects budgets above 3000 tokens Counted as a did-not-finish, but it is not evidence about this model.
qwen3.5:9bERRBLANKLIMFORMAT
Show code
```html
<!DOCTYPE html>
<html><head><title>Crowd Simulation</title></head><style>body{margin:0;overflow:hidden;background:#111}canvas{display:block}</style><body><canvas id="c"></canvas><script>
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');
let W, H, agents, exitX, exitY, totalPeople = 60;

ctx.fillStyle = '#FFF';
function init() {
    W = canvas.width = window.innerWidth;
    H = canvas.height = window.innerHeight;
    agents = [];
    let lastId = 1;
    for (let i = 0; i < totalPeople; i++) {
        agents.push({
            id: lastId++,
            x: Math.random() * W,
            y: Math.random() * H,
            vx: (Math.random() - 0.5) * 1,
            vy: (Math.random() - 0.5) * 1,
            maxSpeed: 2 + Math.random(),
            radius: 4 + Math.random() * 3,
            isLeft: false
        });
    }
    exitX = W * 0.9;
    exitY = H / 2;
    if (window.resize) window.dispatchEvent(new Event('resize'));
}

init();

const SEPARATION_DISTANCE = 35;
const MAX_FORCE = 1.5;
let peopleLeft = 0;

function applySeparation(agent, other) {
    const dx = agent.x - other.x;
    const dy = agent.y - other.y;
    const distSq = dx * dx + dy * dy;
    if (distSq < SEPARATION_DISTANCE * SEPARATION_DISTANCE && distSq > 0) {
        let strength = 1 / Math.sqrt(distSq);
        return { vx: dx * strength, vy: dy * strength };
    }
    return { vx: 0, vy: 0 };
}

function steerToGoal(agent) {
    const desiredX = exitX;
    const desiredY = exitY;
    let dx = desiredX - agent.x;
    let dy = desiredY - agent.y;
    let dist = Math.sqrt(dx * dx + dy * dy);

    if (dist < 50) return { vx: 0, vy: 0 }; // Already close enough

    const desiredVx = (dx / dist) * agent.maxSpeed;
    const desiredVy = (dy / dist) * agent.maxSpeed;

    let steerVx = desiredVx - agent.vx;
    let steerVy = desiredVy - agent.vy;

    // Apply limiting force
    let magnitude = Math.sqrt(steerVx * steerVx + steerVy * steerVy);
    if (magnitude > MAX_FORCE) {
        steerVx = (steerVx / magnitude) * MAX_FORCE;
        steerVy = (steerVy / magnitude) * MAX_FORCE;
    }

    return { vx: steerVx, vy: steerVy };
}

function updateAgents() {
    let totalSpeedSq = 0;
    const separationForces = [];

    for (let i = 0; i < agents.length; i++) {
        agents[i].vx = 0;
        agents[i].vy = 0;
        separationForces[i] = { vx: 0, vy: 0 };
    }

    // Calculate separation force for every agent
    for (let i = 0; i < agents.length; i++) {
        let totalSeparationX = 0;
        let totalSeparationY = 0;
        separationForces[i] = { vx: 0, vy: 0 };

        for (let j = 0; j < agents.length; j++) {
            if (i === j) continue;
            const result = applySeparation(agents[i], agents[j]);
            totalSeparationX += result.vx;
            totalSeparationY += result.vy;
        }

        separationForces[i].vx = totalSeparationX / Math.max(1, totalPeople);
        separationForces[i].vy = totalSeparationY / Math.max(1, totalPeople);
    }


    for (let i = 0; i < agents.length; i++) {
        const agent = agents[i];

        // 1. Separation
        let sep = separationForces[i];
        agent.vx += sep.vx * 0.2;
        agent.vy += sep.vy * 0.2;

        // 2. Goal Seeking (Steering force)
        let goal = steerToGoal(agent);
        agent.vx += goal.vx * 1.5;
        agent.vy += goal.vy * 1.5;

        // Apply friction/damping
        agent.vx *= 0.95;
        agent.vy *= 0.95;

        // Update position
        agent.x += agent.vx;
        agent.y += agent.vy;

        totalSpeedSq += (agent.vx * agent.vx + agent.vy * agent.vy);

        // Check Exit Condition
        if (!agent.isLeft && Math.abs(agent.x - exitX) < 150 && Math.abs(agent.y - exitY) < 150 && Math.random() < 0.02) {
            agent.isLeft = true;
            peopleLeft++;
        }

        // Boundary management (Keep them in the room if they fail to leave)
        if (agent.x < 0 || agent.x > W * 1.1 || agent.y < -50 || agent.y > H + 50) {
            // Reset agents who fall too far away or are stuck
            if (!agent.isLeft && Math.random() < 0.001) {
                Object.assign(agent, { x: W * 0.2, y: H / 3, vx: (Math.random() - 0.5) * 0.5, vy: (Math.random() - 0.5) * 0.5 });
            }
        }
    }
}

function draw() {
    ctx.clearRect(0, 0, W, H);
    const avgSpeed = peopleLeft > 0 ? Math.sqrt(totalSpeedSq / agents.length) : 0;

    for (let i = 0; i < agents.length; i++) {
        const agent = agents[i];
        ctx.beginPath();
        ctx.arc(agent.x, agent.y, agent.radius * (agent.isLeft ? 0.5 : 1), 0, Math.PI * 2);
        ctx.fillStyle = agent.isLeft ? 'rgba(100, 100, 100, 0.5)' : '#4A90E2';
        ctx.fill();
    }

    // Display Stats
    ctx.fillStyle = '#FFF';
    ctx.font = '20px Arial';
    ctx.fillText(`Left: ${peopleLeft}/${totalPeople}`, 20, 50);
    ctx.fillText(`Avg Speed: ${avgSpeed.toFixed(2)}`, 20, 80);

    if (peopleLeft >= totalPeople) {
        setTimeout(() => {
            init();
            requestAnimationFrame(animate);
        }, 1500);
    } else {
        requestAnimationFrame(animate);
    }
}

function animate() {
    updateAgents();
    draw();
}

window.addEventListener('resize', () => {
    W = canvas.width = window.innerWidth;
    H = canvas.height = window.innerHeight;
    exitX = W * 0.9;
    exitY = H / 2;
});

animate();
</script></body></html>
```
mistral-small:24bOKFORMAT
Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Room Exit Simulation</title>
<style>
body { margin: 0; overflow: hidden; }
canvas { display: block; }
#info { position: absolute; top: 10px; left: 10px; color: white; font-size: 24px; }
</style>
</head>
<body>
<canvas id="simulationCanvas"></canvas>
<div id="info">People left: 0, Average Speed: 0.0</div>

<script>
const canvas = document.getElementById('simulationCanvas');
const ctx = canvas.getContext('2d');
const info = document.getElementById('info');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

const exit = { x: canvas.width / 2, y: canvas.height - 50 };
const people = [];
const maxPeople = 60;
const repulsionRadius = 30;
const speedFactor = 1.5;

for (let i = 0; i < maxPeople; i++) {
    people.push({ x: Math.random() * canvas.width, y: Math.random() * canvas.height, vx: 0, vy: 0 });
}

function update() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    let leftCount = 0;
    let totalSpeed = 0;

    for (let i = 0; i < people.length; i++) {
        const person = people[i];
        const dx = exit.x - person.x;
        const dy = exit.y - person.y;
        const distance = Math.sqrt(dx * dx + dy * dy);
        person.vx += dx / distance * speedFactor;
        person.vy += dy / distance * speedFactor;

        for (let j = 0; j < people.length; j++) {
            if (i !== j) {
                const otherPerson = people[j];
                const ox = otherPerson.x - person.x;
                const oy = otherPerson.y - person.y;
                const odistance = Math.sqrt(ox * ox + oy * oy);
                if (odistance < repulsionRadius) {
                    person.vx -= ox / odistance * speedFactor;
                    person.vy -= oy / odistance * speedFactor;
                }
            }
        }

        person.x += person.vx;
        person.y += person.vy;

        const velocity = Math.sqrt(person.vx * person.vx + person.vy * person.vy);
        totalSpeed += velocity;

        if (person.x > exit.x - 25 && person.x < exit.x + 25 && person.y > exit.y - 25 && person.y < exit.y + 25) {
            people.splice(i, 1);
            leftCount++;
            i--;
        }
    }

    ctx.fillStyle = 'white';
    ctx.beginPath();
    for (let person of people) {
        ctx.arc(person.x, person.y, 5, 0, Math.PI * 2);
    }
    ctx.fill();

    info.innerHTML = `People left: ${maxPeople - leftCount}, Average Speed: ${(totalSpeed / (people.length || 1)).toFixed(2)}`;

    if (people.length === 0) {
        resetSimulation();
    } else {
        requestAnimationFrame(update);
    }
}

function resetSimulation() {
    people.length = 0;
    for (let i = 0; i < maxPeople; i++) {
        people.push({ x: Math.random() * canvas.width, y: Math.random() * canvas.height, vx: 0, vy: 0 });
    }
    requestAnimationFrame(update);
}

requestAnimationFrame(update);

</script>
</body>
</html>
```
command-r:35bERRBLANKFORMAT
Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        body { margin: 0; overflow: hidden; background: radial-gradient(ellipse at center,#92dbe3 4%,#556ee3) }
        canvas { display: block; touch-action: none; image-rendering: -moz-crisp-edges; image-rendering: pixelated; }
    </style>
</head>
<body>
    <canvas></canvas>
    <script>
        const W = window.innerWidth  || 300, H = window.innerHeight || 150, I = Math.round(H/20), B = .4;
        let t = Date.now(), r = [], n = 60;

        function V() {
            return (Math.random()-Math.random()) * Math.sqrt(B) + B / 3;
        }

        for(let i=0;i<I;i++) r[i] = [];

        function R(o,x,y){
            let a = o*2*Math.PI/I, c = { x:W*.5+x*Math.cos(a), y:H*.5+y*Math.sin(a) };
            r[o].push({ x:c.x, y:c.y, v:{ x:V(), y:V() }, a });
        }

        for (let j=0;j<n;j++) R(j%I,(H+25)*Math.cos(j/16),H*Math.sin(j/8));

        function P(c,o){
            let b = r[o], d = { x:b[b.length-1].x - c.x, y:b[b.length-1].y - c.y };
            if (d.x<0) d.x = -d.x; if (d.y<0) d.y = -d.y;
            let m = Math.min(B * 24/Math.sqrt(d.x + .1), B / 3); 
            c.v.x += ((b[b.length-1].x + b[b.length-1].v.x) - (c.x + c.v.x)) * m;
            c.v.y += ((b[b.length-1].y + b.v.y) - (c.y + c.v.y)) * m;
        }

        function N(){
            r.forEach((a,o) => {
                a.forEach((p,i)=>{
                    let h = o*2*Math.PI/I; p.x += Math.cos(h)*p.v.x; p.y += Math.sin(h)*p.v.y;
                    if (i === 0){
                        P(a[I-1],o); a[I-1].v.x *= .98; a[I-1].v.y *= .98;
                        let [b,d] = p.a; b += Math.PI/2 - d; d += (Math.PI * 7)/64 + V(); 
                        P({ x:p.x+Math.cos(b), y:p.y+Math.sin(b) },o);
                        if (d < 0) {
                            r[o].shift();
                            return n--;
                        } else p.a = [b,d];
                    }
                });
            });
        }

        function A(){
            let c = document.querySelector('canvas'), g = c.getContext('2d'); 
            c.width = W; c.height = H;

            while(n>0) N(); n=60; r=[[],[]]; t=Date.now();
            for (let j=0;j<I;j++) R((t*13)%I,(H+25)*Math.cos(j/16),H*Math.sin(j/8));

            g.fillStyle = "#fff";
            r.forEach(a => {
                a.forEach(p => {
                    let [b,d] = p.a; b += Math.PI/2 - d;
                    P({ x:p.x+Math.cos(b), y:p.y + Math.sin(b) },0); g.fillRect(p.x,p.y,.5,.5);
                });
            });

            let u = Date.now();
            requestAnimationFrame(A);
            console.log((I-n)/I*100,"%",(I-n)*B/3+B/24,"px");
        }

        A();
    </script>
</body>
</html>
```
qwq:32bBLANKLIM
Show code
<think>

Okay, let's tackle this problem step by step. The user wants an HTML file that simulates 60 people leaving a room through an exit using a <canvas>. The simulation needs to show continuous movement, with each person having a position and velocity. They should steer towards the exit and avoid neighbors, leading to congestion and an arch forming. Also, it should display the number of people left and the average speed, using requestAnimationFrame, and restart automatically when done. 

First, I need to set up the HTML structure. The canvas element is essential, along with a div to display the stats. The canvas will be sized, maybe 800x600 for visibility. The script will handle the simulation.

Next, the JavaScript part. Let's think about the Person class or objects. Each person needs position (x,y), velocity (vx, vy), and possibly a radius for collision detection. The exit is a point, maybe at the center of the bottom edge of the canvas.

The main steps in the animation loop: update each person's position based on velocity, apply steering forces towards the exit, and repulsion from nearby people. Then, check if they've exited (maybe beyond the exit's position). 

For steering towards the exit, the person should have a desired direction towards the exit's position. The steering force can be a vector pointing towards the exit, scaled by some acceleration. But also, when people get too close, they should push away. The repulsion can be calculated based on distance; if two people are within a certain radius, they apply a force pushing away from each other.

Collision detection between all pairs might be computationally heavy, but with 60 people, it's manageable in a loop. For each person, loop through others to check distance. If distance is below threshold, compute repulsion force.

The velocity update needs to consider both the steering towards exit and repulsion forces. Maybe cap the maximum speed to prevent them from moving too fast.

Also, the exit is fixed, so once a person's y-coordinate goes below a certain point (like the exit's y position), they leave. We'll track the count of remaining people and average speed.

The drawing part: clear the canvas each frame, draw each person as a circle, the exit as a larger circle or rectangle, and update the text with stats.

The animation loop uses requestAnimationFrame. When all people have left (count hits zero), reset the simulation by creating new random positions and velocities. Need to seed the initial positions in the room (maybe spread them out initially).

Variables to track: remainingPeopleCount, totalElapsedTime, averageSpeed. Wait, average speed might need to be calculated over all remaining people's current speeds. Or maybe average over all people, even those who left? Hmm, perhaps average of current active ones.

Potential issues: performance with 60 people checking pairwise distances. But since it's only 60, 60*60 is 3600 checks per frame, which should be okay for a basic simulation.

Let me outline the code steps:

1. Set up canvas and context.
2. Initialize array of people with random positions (inside the room), maybe starting positions distributed in a rectangle except near the exit.
3. Define the exit position (e.g., center at bottom, maybe 400,580 with radius 20).
4. In each frame:
   a. Iterate over each person:
      i. Calculate steering force towards exit.
      ii. Calculate repulsion forces from all other people within collision distance.
      iii. Update velocity with acceleration from these forces, and apply friction? Or cap speed.
      iv. Update position with velocity.
      v. Check if exited, if so, remove from array or mark as exited.
   b. Update stats: count remaining, compute average speed (sum of speeds / remaining).
   c. Draw everything.
5. When all exited, reset by recreating the people array with new random positions.
   
Wait, how to handle exited people? Maybe keep them in the array but not update their position once exited, and just count how many have position.y > exit's position (or whatever condition). Or better to have a separate array for active people.

Alternatively, once a person exits, we can mark them as exited and stop processing them. That way, in the active array, we only loop through those still in the room.

Hmm, but for the repulsion forces, do exited people affect the current ones? Probably not, so it's better to separate them.

So:

- activePeople array holds those still in the room.
- exitedCount increments when someone exits.

Initialize activePeople with 60 people.

Each frame:

for each person in activePeople:

   steering force towards exit.

   for each other person in activePeople (j):

      if j is not same as current, check distance.

      if distance < threshold, apply repulsion.

   update velocity with forces (maybe scaled by some factor for strength).

   apply velocity to position.

   check if exited: if yes, remove from activePeople, add to exited.

Then, after all updates, check if activePeople is empty. If so, reset.

Now, the forces:

Steering towards exit: direction from current position to exit. The desired acceleration can be that direction normalized, multiplied by a strength. Maybe the steeringForce is a vector towards the exit, scaled by something like 0.005. But need to test.

Repulsion between people: The repulsion force can be calculated as the vector pointing away from the neighbor, scaled by (minDistance - actual distance) to increase force when closer. For example, if the desired separation is 10 units, and actual distance is 5, the repulsion is 5 units in direction away.

Alternatively, use a spring-like force, like F = (separation - d)/d * direction. But perhaps simpler to compute a force that pushes away when too close.

Wait, here's a way:

distance between person and neighbor:

dx = person.x - neighbor.x

dy = person.y - neighbor.y

distance = sqrt(dx*dx + dy*dy)

if distance < minDistance:

   strength = (distance - minDistance) * -1 (so becomes negative if too close)

Wait, maybe the force should be along the line connecting them, pushing them apart.

The direction vector is (dx, dy). So the force on person A from person B would be (dx, dy) normalized, multiplied by a force strength proportional to (minDistance - distance).

So F = (dx, dy) * (minDistance - distance) * k

Which would push them apart when they are too close, and the further away, the less force.

Alternatively, use a repulsion force that gets stronger as distance decreases.

Parameters will need tuning.

Now, in code:

For each person p in activePeople:

   // Steering towards exit

   dx = exitX - p.x

   dy = exitY - p.y

   distToExit = Math.sqrt(dx*dx + dy*dy)

   if (distToExit > 0) {

       steerX = dx / distToExit * steeringForce

       steerY = dy / distToExit * steeringForce

   }

   // Repulsion forces

   var repelX = 0, repelY = 0

   for (var j = 0; j < activePeople.length; j++) {

       var other = activePeople[j]

       if (other === p) continue

       var dx = p.x - other.x

       var dy = p.y - other.y

       var distance = Math.sqrt(dx*dx + dy*dy)

       if (distance < minDistance) {

           var
deepseek-r1:32bOKFORMAT
Show code
```html
<!DOCTYPE html>
<html><head><title>Room Exit Simulation</title><style>canvas{border:1px solid black}</style></head><body>
<canvas id="c" width="600" height="400"></canvas>
<script>
const c=document.getElementById('c'),ctx=c.getContext('2d');
let people=[],exited=0,time=0,avgSpeed=0;
class Person{
constructor(){this.x=Math.random()*580+10;this.y=Math.random()*380+60;this.vx=0;this.vy=0;this.mass=40;this.target={x:290,y:370};this.neighbors=[]}
move(){this.x+=this.vx;this.y+=this.vy;if(this.vy<5)this.vy=1/20*(this.target.y-this.y)+.1;
else this.vy=5}
draw(){ctx.beginPath();ctx.arc(this.x,this.y,Math.sqrt(this.mass)/3,0,6.28);ctx.fill()}
}
function steer(p){
let dirY=p.target.y-p.y;return Math.min(1/20*dirY,7);
}
function collision(p,q,dx,dy,dist){
if(dist>100)return;
let nx=dx/dist,ny=dy/dist,force=4*(1-dist/100)/(p.mass+q.mass);
p.vx-=nx*force;p.vy-=ny*force;q.vx+=nx*force;q.vy+=ny*force;
}
function update(){
if(exited<60){
ctx.fillStyle='#f5f5f5';ctx.fillRect(0,0,c.width,c.height);ctx.fillStyle='black';
ctx.fillRect(280,370,40,10);people=people.filter(p=>{
p.move();
let dx=p.x-p.target.x,dy=p.y-p.target.y;
if(dy<0&&Math.abs(dx)<20)p.vy=-2;
else p.vy=Math.min(steer(p),5);
for(let q of people)if(q!=p){
let dx1=q.x-p.x,dy1=q.y-p.y,dist=Math.sqrt(dx1*dx1+dy1*dy1);
if(dist<40)collision(p,q,dx1,dy1,dist);
}
return p.y>370;
});
exited=60-people.length;avgSpeed=(people.reduce((a,p)=>a+p.vy,0)/people.length).toFixed(2);
ctx.font='20px Arial';ctx.fillText(`People left: ${exited}`,10,30);ctx.fillText(`Avg speed: ${avgSpeed}`,10,60);
}
else{ctx.fillStyle='#f5f5f5';ctx.fillRect(0,0,c.width,c.height);ctx.fillText('Simulation Complete!',c.width/2-80, c.height/2);
exited=0;people=[];setTimeout(()=>{for(let i=0;i<60;i++)people.push(new Person());},1000)}
requestAnimationFrame(update);
}
for(let i=0;i<60;i++)people.push(new Person());
update();
</script></body></html>
```
Outside the Brain cluster — same task, same character budget, collected through their own tooling (response times not comparable)
GPT-5.5 (Codex)frontier referenceOK
Show code
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Evacuation</title>
<style>
html,body{margin:0;height:100%;background:#111;color:#eee;font:16px system-ui;overflow:hidden}
canvas{display:block;width:100vw;height:100vh}
</style>
</head>
<body>
<canvas id="c"></canvas>
<script>
const c=document.getElementById("c"),x=c.getContext("2d");
let W,H,P,left,last=0;
function rnd(a,b){return a+Math.random()*(b-a)}
function reset(){
 W=c.width=innerWidth*devicePixelRatio;H=c.height=innerHeight*devicePixelRatio;x.setTransform(devicePixelRatio,0,0,devicePixelRatio,0,0);
 W=innerWidth;H=innerHeight;left=0;P=[];
 for(let i=0;i<60;i++)P.push({x:rnd(60,W-160),y:rnd(70,H-70),vx:rnd(-.4,.4),vy:rnd(-.4,.4),out:0});
}
onresize=reset;reset();
function step(t){
 let dt=Math.min(32,t-last||16)/16;last=t,ex=W-18,ey=H/2,sp=0,n=0;
 x.clearRect(0,0,W,H);
 x.fillStyle="#1d1d22";x.fillRect(32,32,W-64,H-64);
 x.fillStyle="#111";x.fillRect(W-34,H/2-52,40,104);
 x.strokeStyle="#ddd";x.lineWidth=3;x.strokeRect(32,32,W-64,H-64);
 x.strokeStyle="#111";x.lineWidth=8;x.beginPath();x.moveTo(W-34,H/2-52);x.lineTo(W-34,H/2+52);x.stroke();
 for(let i=0;i<P.length;i++){
  let p=P[i];if(p.out)continue;
  let dx=ex-p.x,dy=ey-p.y,d=Math.hypot(dx,dy)||1,ax=dx/d*.065,ay=dy/d*.065;
  for(let j=0;j<P.length;j++)if(i!=j&&!P[j].out){
   let q=P[j],nx=p.x-q.x,ny=p.y-q.y,nd=Math.hypot(nx,ny)||1;
   if(nd<22){let f=(22-nd)/22*.18;ax+=nx/nd*f;ay+=ny/nd*f}
  }
  if(p.x>W-38&&(p.y<H/2-52||p.y>H/2+52))ax-=.55;
  if(p.x<44)ax+=.25;if(p.y<44)ay+=.25;if(p.y>H-44)ay-=.25;
  p.vx=(p.vx+ax)*.91;p.vy=(p.vy+ay)*.91;
  let v=Math.hypot(p.vx,p.vy),m=3.2;if(v>m){p.vx=p.vx/v*m;p.vy=p.vy/v*m}
  p.x+=p.vx*dt;p.y+=p.vy*dt;
  if(p.x>W+10&&Math.abs(p.y-H/2)<62){p.out=1;left++;continue}
  sp+=Math.hypot(p.vx,p.vy);n++;
  x.beginPath();x.arc(p.x,p.y,6,0,7);x.fillStyle=`hsl(${190-v*30},75%,58%)`;x.fill();
 }
 x.fillStyle="#eee";x.font="16px system-ui";x.fillText("Left: "+left+" / 60",18,24);
 x.fillText("Avg speed: "+(n?sp/n:0).toFixed(2),130,24);
 if(left==60)setTimeout(reset,500);
 requestAnimationFrame(step);
}
requestAnimationFrame(step);
</script>
</body>
</html>
Claude Sonnet 5frontier referenceOK
Show code
<!doctype html>
<html><head><meta charset="utf-8"><title>Room Evacuation Continuous</title>
<style>html,body{margin:0;background:#0d0f14;overflow:hidden;height:100%}canvas{display:block}</style>
</head><body>
<canvas id="c"></canvas>
<script>
const cv=document.getElementById('c'),ctx=cv.getContext('2d');
function resize(){cv.width=innerWidth;cv.height=innerHeight;}
resize();addEventListener('resize',resize);
const RX=40,RY=40,RW=600,RH=440,NP=60,DH=22;
const DOORY=RY+RH/2,TGX=RX+RW+90,TGY=DOORY;
let people,leftCount,waitTimer;
function rnd(a,b){return a+Math.random()*(b-a)}
function init(){
  people=[];leftCount=0;waitTimer=0;
  let tries=0;
  while(people.length<NP&&tries<20000){
    tries++;
    const r=rnd(6,9);
    const x=rnd(RX+r+4,RX+RW-r-4),y=rnd(RY+r+4,RY+RH-r-4);
    let ok=true;
    for(const p of people){if(Math.hypot(p.x-x,p.y-y)<p.r+r+2){ok=false;break;}}
    if(!ok)continue;
    people.push({x,y,vx:0,vy:0,r,maxS:rnd(1.4,2.1),left:false});
  }
}
init();
function step(){
  for(let i=0;i<people.length;i++){
    const p=people[i];
    const dx=TGX-p.x,dy=TGY-p.y,d=Math.hypot(dx,dy)||1;
    const dvx=dx/d*p.maxS,dvy=dy/d*p.maxS;
    p.vx+=(dvx-p.vx)*0.06;p.vy+=(dvy-p.vy)*0.06;
    p.vx+=rnd(-0.03,0.03);p.vy+=rnd(-0.03,0.03);
  }
  for(let i=0;i<people.length;i++)for(let j=i+1;j<people.length;j++){
    const a=people[i],b=people[j];
    const ddx=b.x-a.x,ddy=b.y-a.y,dd=Math.hypot(ddx,ddy)||0.01;
    const minD=a.r+b.r+1.5;
    if(dd<minD){
      const f=(minD-dd)/minD*0.9;
      const nx=ddx/dd,ny=ddy/dd;
      a.vx-=nx*f;a.vy-=ny*f;b.vx+=nx*f;b.vy+=ny*f;
    }
  }
  for(let i=people.length-1;i>=0;i--){
    const p=people[i];
    const sp=Math.hypot(p.vx,p.vy);
    if(sp>p.maxS*1.4){p.vx=p.vx/sp*p.maxS*1.4;p.vy=p.vy/sp*p.maxS*1.4;}
    p.x+=p.vx;p.y+=p.vy;
    const inGap=(p.y>DOORY-DH+p.r&&p.y<DOORY+DH-p.r);
    if(p.x-p.r<RX){p.x=RX+p.r;p.vx*=-0.3;}
    if(p.y-p.r<RY){p.y=RY+p.r;p.vy*=-0.3;}
    if(p.y+p.r>RY+RH){p.y=RY+RH-p.r;p.vy*=-0.3;}
    if(p.x+p.r>RX+RW&&!inGap){p.x=RX+RW-p.r;p.vx*=-0.3;}
    if(p.x-p.r>RX+RW+25){people.splice(i,1);leftCount++;}
  }
  if(people.length===0){waitTimer++;if(waitTimer>90)init();}
}
function draw(){
  ctx.fillStyle='#0d0f14';ctx.fillRect(0,0,cv.width,cv.height);
  ctx.strokeStyle='#567';ctx.lineWidth=4;
  ctx.beginPath();
  ctx.moveTo(RX,RY);ctx.lineTo(RX+RW,RY);
  ctx.lineTo(RX+RW,DOORY-DH);ctx.moveTo(RX+RW,DOORY+DH);
  ctx.lineTo(RX+RW,RY+RH);ctx.lineTo(RX,RY+RH);ctx.lineTo(RX,RY);
  ctx.stroke();
  ctx.strokeStyle='#4f8';ctx.lineWidth=4;
  ctx.beginPath();ctx.moveTo(RX+RW,DOORY-DH);ctx.lineTo(RX+RW,DOORY+DH);ctx.stroke();
  let totSpeed=0;
  ctx.fillStyle='#ffb648';
  for(const p of people){
    totSpeed+=Math.hypot(p.vx,p.vy);
    ctx.beginPath();ctx.arc(p.x,p.y,p.r,0,7);ctx.fill();
  }
  const avg=people.length?(totSpeed/people.length):0;
  ctx.fillStyle='#eef';ctx.font='16px monospace';ctx.textAlign='left';
  ctx.fillText('Room Evacuation - Continuous Movement',RX,RY+RH+30);
  ctx.font='13px monospace';ctx.fillStyle='#9cf';
  ctx.fillText('Left: '+leftCount+' / '+NP,RX,RY+RH+52);
  ctx.fillText('Avg speed: '+avg.toFixed(2)+' px/frame',RX,RY+RH+72);
}
function loop(){
  step();draw();
  requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
</script>
</body></html>
Claude Haiku 4.5frontier referenceOK
Show code
<!DOCTYPE html><html><head><title>r78</title></head><body><canvas id="c"></canvas><script>
let c=document.getElementById('c'),x=c.getContext('2d');c.width=800;c.height=600;
let ppl=Array(60).fill(0).map(()=>({x:Math.random()*600+50,y:Math.random()*400+50,vx:0,vy:0,r:4,left:false}));
let gx=700,gy=300,left=0;
function draw(){
  x.fillStyle="#fff";x.fillRect(0,0,800,600);
  // Update
  ppl.forEach(p=>{
    if(!p.left){
      let dx=gx-p.x,dy=gy-p.y,d=Math.sqrt(dx*dx+dy*dy);
      if(d<10){p.left=true;left++;return;}
      // Steer to exit
      p.vx+=(dx/d)*0.1;p.vy+=(dy/d)*0.1;
      // Separate
      ppl.forEach(q=>{if(p!==q&&!q.left){
        let edx=q.x-p.x,edy=q.y-p.y,ed=Math.sqrt(edx*edx+edy*edy);
        if(ed<15){p.vx-=(edx/ed)*0.2;p.vy-=(edy/ed)*0.2;}
      }});
      // Damping
      p.vx*=0.95;p.vy*=0.95;
      // Limit speed
      let sv=Math.sqrt(p.vx*p.vx+p.vy*p.vy);if(sv>2){p.vx/=sv;p.vy/=sv;p.vx*=2;p.vy*=2;}
      p.x+=p.vx;p.y+=p.vy;
      // Bounds
      if(p.x<50)p.x=50;if(p.x>750)p.x=750;if(p.y<50)p.y=50;if(p.y>550)p.y=550;
    }
  });
  // Draw
  ppl.forEach(p=>{if(!p.left){x.fillStyle="#00f";x.beginPath();x.arc(p.x,p.y,p.r,0,Math.PI*2);x.fill();}});
  x.fillStyle="#0f0";x.fillRect(gx-10,gy-20,20,40);
  // Exit label
  x.fillStyle="#000";x.font="14px mono";x.fillText("Left:"+left,500,50);
  let avgv=ppl.filter(p=>!p.left).reduce((s,p)=>s+Math.sqrt(p.vx*p.vx+p.vy*p.vy),0)/60;
  x.fillText("Avg Speed:"+avgv.toFixed(2),500,80);
  requestAnimationFrame(draw);
}draw();
</script></body></html>
Results at a glance— every model in this round with score, response time and status.

Who wrote what

ModelBlind scoreLatencyStatus
qwen3:14b —50.3 sOK
deepseek-r1:14b —109.3 sOK
gemma4:26b ——harness
qwen3-coder:30b —26.9 sOK
llama3.1:8b —98.5 sOK
qwen3:8b ——harness
qwen3.5:9b —53.6 sOK
mistral-small:24b —188.6 sOK
command-r:35b —134.3 sOK
qwq:32b —123.8 sOK
deepseek-r1:32b —123.2 sOK

Frontier reference — outside the blind field

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.

Collected differently from the blind field: the local models run through a plain API harness, the frontier references through a context-free agent, one shot, no retries. Response times are therefore not comparable and are not shown. On two English tasks the reference answer came back in German — an artefact of that harness, flagged on the affected rounds.
Claude Opus 5frontier reference
Show code
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Crowd Evacuation — 60 People, One Exit</title>
<style>
html,body{margin:0;height:100%;background:#0a0d12;color:#e8eef7;font:15px/1.4 system-ui,sans-serif}
body{display:flex;align-items:center;justify-content:center}
canvas{max-width:100%;height:auto;border-radius:10px;box-shadow:0 10px 40px #0009}
</style>
</head>
<body>
<canvas id="c" width="760" height="470"></canvas>
<script>
const cv=document.getElementById('c'),ctx=cv.getContext('2d');
const W=cv.width,H=cv.height,X1=70,Y1=80,X2=600,Y2=430,T=10,GAP=46;
const DY1=(Y1+Y2)/2-GAP/2,DY2=DY1+GAP,DYC=(DY1+DY2)/2,N=60,R=5.4,RNG=2*R+8;
const rnd=(a,b)=>a+Math.random()*(b-a);
let P=[],left=0,frames=0,avgS=0;
function init(){
  P=[];left=0;frames=0;avgS=0;
  while(P.length<N){
    const x=rnd(X1+14,X2-100),y=rnd(Y1+14,Y2-14);
    let ok=true;
    for(const q of P){if((q.x-x)**2+(q.y-y)**2<(2.3*R)**2){ok=false;break;}}
    if(ok)P.push({x,y,vx:0,vy:0,ax:0,ay:0,v0:rnd(1.0,1.75),off:rnd(-1,1),h:rnd(170,340),left:false});
  }
}
function walls(p){
  if(p.x<X2){
    if(p.x<X1+R){p.x=X1+R;p.vx=Math.abs(p.vx)*0.2;}
    if(p.y<Y1+R){p.y=Y1+R;p.vy=Math.abs(p.vy)*0.2;}
    if(p.y>Y2-R){p.y=Y2-R;p.vy=-Math.abs(p.vy)*0.2;}
  }
  if(p.x+R>X2&&p.x-R<X2+T){
    if(p.y<DY1+R){
      if(p.y<DY1){if(p.x<X2){p.x=X2-R;p.vx=Math.min(p.vx,0)*0.15;}else{p.x=X2+T+R;p.vx=Math.max(p.vx,0);}}
      else{p.y=DY1+R;p.vy=Math.max(p.vy,0)*0.3;}
    }else if(p.y>DY2-R){
      if(p.y>DY2){if(p.x<X2){p.x=X2-R;p.vx=Math.min(p.vx,0)*0.15;}else{p.x=X2+T+R;p.vx=Math.max(p.vx,0);}}
      else{p.y=DY2-R;p.vy=Math.min(p.vy,0)*0.3;}
    }
  }
}
function step(){
  frames++;
  for(const p of P){
    const through=p.x>X2+T*0.5;
    const tx=through?W+180:X2-6,ty=through?DYC+p.off*52:DYC;
    const dx=tx-p.x,dy=ty-p.y,d=Math.hypot(dx,dy)||1;
    p.ax=(dx/d*p.v0-p.vx)/9;
    p.ay=(dy/d*p.v0-p.vy)/9;
  }
  for(let i=0;i<N;i++){
    const a=P[i];
    for(let j=i+1;j<N;j++){
      const b=P[j],dx=b.x-a.x,dy=b.y-a.y,d2=dx*dx+dy*dy;
      if(d2<RNG*RNG&&d2>1e-6){
        const d=Math.sqrt(d2),f=0.085*(RNG-d)+0.07*Math.exp((2*R-d)/2.5);
        const nx=dx/d*f,ny=dy/d*f;
        a.ax-=nx;a.ay-=ny;b.ax+=nx;b.ay+=ny;
      }
    }
  }
  let sum=0,act=0;
  for(const p of P){
    p.vx+=p.ax;p.vy+=p.ay;
    const s=Math.hypot(p.vx,p.vy),m=p.v0*1.4;
    if(s>m){p.vx*=m/s;p.vy*=m/s;}
    p.x+=p.vx;p.y+=p.vy;
    walls(p);
    if(!p.left&&p.x>X2+T+26){p.left=true;left++;}
    if(!p.left){sum+=Math.hypot(p.vx,p.vy);act++;}
  }
  avgS=avgS*0.92+(act?sum/act*60:0)*0.08;
  if(left===N&&P.every(p=>p.x>W+150))init();
}
function draw(){
  ctx.fillStyle='#0a0d12';ctx.fillRect(0,0,W,H);
  ctx.fillStyle='#161c26';ctx.fillRect(X1,Y1,X2-X1,Y2-Y1);
  ctx.fillStyle='rgba(80,230,170,.13)';ctx.fillRect(X2,DY1,T+70,DY2-DY1);
  ctx.fillStyle='#3d4a5c';
  ctx.fillRect(X1-T,Y1-T,X2-X1+2*T,T);
  ctx.fillRect(X1-T,Y2,X2-X1+2*T,T);
  ctx.fillRect(X1-T,Y1,T,Y2-Y1);
  ctx.fillRect(X2,Y1,T,DY1-Y1);
  ctx.fillRect(X2,DY2,T,Y2-DY2);
  ctx.fillStyle='#50e6aa';ctx.fillRect(X2-1,DY1,2,GAP);
  for(const p of P){
    if(p.x>W+40)continue;
    ctx.beginPath();ctx.arc(p.x,p.y,R,0,6.2832);
    ctx.fillStyle='hsl('+p.h.toFixed(0)+' 68% '+(p.left?42:63)+'%)';ctx.fill();
    ctx.strokeStyle='rgba(6,10,16,.75)';ctx.lineWidth=1.2;ctx.stroke();
    ctx.beginPath();ctx.moveTo(p.x,p.y);ctx.lineTo(p.x+p.vx*5,p.y+p.vy*5);
    ctx.strokeStyle='rgba(255,255,255,.35)';ctx.stroke();
  }
  ctx.fillStyle='#e8eef7';ctx.font='600 17px system-ui,sans-serif';
  ctx.fillText('Evacuated '+left+' / '+N,X1-10,36);
  ctx.fillText('Avg speed '+avgS.toFixed(1)+' px/s',270,36);
  ctx.fillText('Time '+(frames/60).toFixed(1)+' s',530,36);
  ctx.fillStyle='#8fa2b8';ctx.font='13px system-ui,sans-serif';
  ctx.fillText('Continuous social-force crowd — steering to the exit plus neighbour repulsion builds the arch',X1-10,H-14);
}
function loop(){step();draw();requestAnimationFrame(loop);}
init();loop();
</script>
</body>
</html>