Overview › Code › R90
Code · blind round

R90 · Poisson-disk sampling, Bridson's algorithm

blind round 8/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.

Show task
Create ONE self-contained HTML file (STRICT LIMIT: max 7000 characters in total — this is a budget on characters, not on lines, so removing line breaks does not help) that fills a <canvas> with evenly spaced random points using Bridson's Poisson-disk sampling: keep a background grid for fast neighbour lookups and an active list, spawn candidate points in the ring around an active sample, and accept only those that keep the minimum distance to every neighbour. Draw each point the moment it is accepted, so the blue-noise pattern visibly fills the area. Show the sample count and start a fresh pattern once no active samples remain. 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)
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.5:9bBLANKFORMAT
Show code
```html
<!DOCTYPE html>
<html><head><title>Poisson Disk Sampling</title></head><body style="margin:0;overflow:hidden;"><canvas id="c"></canvas><script>
const c=document.getElementById('c');
const ctx=c.getContext('2d');

let W, H;
let grid, active=[];
let max_dist;
let count=0;
let running=true;

function init() {
    W=H=window.innerWidth;
    c.width=W;
    c.height=H;
    grid=new Map();
    active=[];
    count=0;
    running=true;
}

init();

function getGridKey(x, y) {
    const gx=Math.floor((x/max_dist));
    const gy=Math.floor((y/max_dist));
    return `${gx},${gy}`;
}

function setPoint(x, y, r) {
    ctx.beginPath();
    ctx.arc(x, y, r, 0, Math.PI*2);
    ctx.fillStyle=rgba(0,150,255,0.8);
    ctx.fill();
}

function isSafe(px, py) {
    const gx=Math.floor((px/max_dist));
    const gy=Math.floor((py/max_dist));
    const key=`${gx},${gy}`;
    if (!grid.has(key)) return true;

    const neighbors=grid.get(key);
    for (let n of neighbors) {
        const distSq = (px-n[0])**2 + (py-n[1])**2;
        return distSq >= max_dist**2 - 1e-6;
    }
    return true;
}

function addPoint(x, y) {
    if (!isSafe(x, y)) return false;
    grid.set(getGridKey(x,y), (grid.get(getGridKey(x,y)))||[]);
    grid.get(getGridKey(x,y)).push([x, y]);
    active.push({x:x, y:y});
    setPoint(x, y);
    count++;
    return true;
}

function sampleDisk() {
    if (active.length === 0) {
        init();
        return;
    }

    const p=Math.random()*W;
    const q=Math.random()*H;
    let attemptCount=0;
    while(attemptCount++<100){
        const nextX = p + (Math.cos(attemptCount*0.1)*max_dist/2); // Ring sampling approximation
        const nextY = q + (Math.sin(attemptCount*0.1)*max_dist/2);

        if (addPoint(nextX, nextY)) {
            return true;
        }
    }
    return false;
}

function animate() {
    // Draw a faint background grid to aid visualization of sampling structure
    ctx.fillStyle="#050";
    for(let i=0;i<W/max_dist; i++) {
        for(let j=0;j<H/max_dist; j++) {
            ctx.fillRect(i*max_dist, j*max_dist, 1, 1);
        }
    }

    if (running) {
        const success = sampleDisk();
        
        // Update status text (optional but good for demonstration)
        if (!window.statusDiv) {
            const s=document.createElement('div');
            s.id='status';
            s.style.position='absolute';
            s.top='10px';
            s.left='10px';
            s.color='#fff';
            document.body.appendChild(s);
        }
        const s=document.getElementById('status');
        if (success) {
             s.textContent=`Points: ${count}. Running...`;
        } else if (active.length === 0 && count > 0) {
             running=false;
             s.textContent=`Finished! Total Points: ${count}. Restarting in 2s...`;
             setTimeout(() => { active=[]; init(); }, 2000);
        }

    }
    requestAnimationFrame(animate);
}

// Since we are limited on characters, I will use a shorthand for rgba.
function rgba(r, g, b, a) { return `rgba(${r},${g},${b},${a})`; }

animate();
</script></body></html>
```
qwen3-coder:30bERRBLANKMINIFIED
Show code
<!DOCTYPE html>
<html><head><title id="blue-noise"></title><style>body{margin:0;overflow:hidden;background:#111}canvas{display:block}</style></head><body onload="init()"><canvas id="c"></canvas><script>window.onload=function(){var c=document.getElementById('c'),ctx=c.getContext('2d');let R=50,GRID_SIZE=R*2;c.width=1280;c.height=720;let active=[];let grid=new Array(Math.ceil(c.width/GRID_SIZE)).fill(null).map(()=>new Array(Math.ceil(c.height/GRID_SIZE)).fill(false));function drawPoint(x,y){ctx.fillStyle='#00ffff';ctx.fillRect(x-1,y-1,2,2);}function getGridCoords(x,y){let gx=Math.floor(x/(R*2));let gy=Math.floor(y/(R*2));return [gx,gy];}function checkNeighbors(x,y,rMin){for(let i=Math.max(0, Math.floor((x-R)/GRID_SIZE));i<=Math.min(Math.ceil((x+R)/GRID_SIZE),grid.length-1);++i){for(let j=Math.max(0, Math.floor((y-R)/GRID_SIZE));j<=Math.min(Math.ceil((y+R)/GRID_SIZE),grid[0].length-1);++j)){if(!grid[i][j])continue;let nx=i*GRID_SIZE+(Math.random()*-R);let ny=j*GRID_SIZE+(Math.random()*-R);if(Math.hypot(nx-x,ny-y)<rMin){return false;}}}function findCandidate(p1){let angleStep=0.2;for(let i=0;i<4;++i){let theta=angleStep*i+Math.random()*Math.PI/2;let dist=R*(1+Math.sin(active.length/5));let cx=p1.x+Math.cos(theta)*dist;let cy=p1.y+Math.sin(theta)*dist;if(checkNeighbors(cx,cy,R)){return {x:cx,y:cy};}}return null;}function attemptSample(p){let count=0;for(let i=0;i<5;++i){let candidate={x:p.x+Math.random()*2*R-R,y:p.y+Math.random()*2*R-R};if(checkNeighbors(candidate.x,candidate.y,R)){return true;}else{count++;}}return count>=5}function init(){active=[];grid=new Array(Math.ceil(c.width/GRID_SIZE)).fill(null).map(()=>new Array(Math.ceil(c.height/GRID_SIZE)).fill(false));animate();}// Main loop functionvar frameId;function animate(){if(frameId){cancelAnimationFrame(frameId);}let p1={x:Math.random()*c.width,y:Math.random()*c.height};if(!active.length||active[active.length-1].x < Math.max(0,c.width)/2){active.push(p1);drawPoint(p1.x,p1.y);let startP=p1;}else{let startP=active[Math.floor(Math.random()*active.length)];}if(!startP)return;let success=false;for(let i=0;i<30;++i){let p2={x:Math.random()*c.width,y:Math.random()*c.height};let candidate=findCandidate(startP);if(candidate){drawPoint(candidate.x,candidate.y);active.push(candidate);success=true;break;}else{/* Try resampling from the last known point */}}if(!success && active.length>0){console.log("Attempting restart/resampling...");}requestAnimationFrame(animate)}</script></body></html>
No usable answer reached the harness (ERR). Counted as a did-not-finish.
llama3.1:8bSTATFORMAT
Show code
```html
<!DOCTYPE html>
<html>
<head>
<style>
body { margin: 0; padding: 0; overflow: hidden; }
canvas { border: 1px solid black; }
</style>
</head>
<body>
<canvas id="c" width="800" height="600"></canvas>
<script>
const c = document.getElementById('c');
let ctx = c.getContext('2d');
ctx.translate(400, 300);
ctx.scale(20, 20);

const n = Math.floor(Math.sqrt(c.width / 20) * Math.sqrt(c.height / 20));
ctx.fillStyle = 'lightgray';
for (let i = -n; i <= n; ++i) {
  for (let j = -n; j <= n; ++j) {
    if (Math.abs(i) + Math.abs(j) <= n) {
      ctx.fillRect(i, j, 1, 1);
    }
  }
}

const r0 = 20;
const r1 = 50;
const points = [];
let active = [ {x: -n, y: -n} ];
let i = 0;

function animate() {
  if (active.length) {
    const p = active.shift();
    for (let j = 0; j < Math.PI * 2; ++j) {
      const a = j / 32;
      const x = r1 + r0 * Math.cos(a);
      const y = r1 + r0 * Math.sin(a);
      let minDistance = Infinity;
      for (const q of points) {
        if (q.x !== p.x && q.y !== p.y) {
          const dx = x - q.x, dy = y - q.y;
          const d2 = dx * dx + dy * dy;
          if (d2 < minDistance) {
            minDistance = d2;
          }
        }
      }
      if (minDistance > r0 * r0) {
        points.push({x: x / 20, y: y / 20});
        ctx.fillStyle = 'blue';
        ctx.beginPath();
        ctx.arc(x / 20, y / 20, 1, 0, Math.PI * 2);
        ctx.fill();
      }
    }
    i++;
    document.title = `Points: ${i}`;
  } else {
    active.push({x: -n + Math.floor(Math.random() * (2 * n))});
  }
}

function main() {
  for (let j = 0; j < Math.PI * 2; ++j) {
    const a = j / 32;
    const x = r1 + r0 * Math.cos(a);
    const y = r1 + r0 * Math.sin(a);
    let minDistance = Infinity;
    for (const q of points) {
      if (q.x !== active[active.length - 1].x && q.y !== active[active.length - 1].y) {
        const dx = x / 20 - q.x, dy = y / 20 - q.y;
        const d2 = dx * dx + dy * dy;
        if (d2 < minDistance) {
          minDistance = d2;
        }
      }
    }
    if (minDistance > r0 * r0) {
      active.push({x: x / 20, y: y / 20});
    }
  }
}

main();
setInterval(animate.bind(this), 16);
</script>
</body>
</html>
```
qwen3:14bERRBLANKFORMAT
Show code
```html
<!DOCTYPE html>
<html>
<head>
<title>Poisson Disk Sampling</title>
<style>body{margin:0;overflow:hidden;background-color:#111}canvas{display:block}</style>
</head>
<body>
<canvas id="c"></canvas>
<script>
const c = document.getElementById('c');
const ctx = c.getContext('2d');

let W, H;
let grid, active, samples, minD;
let pointCount = 0;

function init() {
    W = window.innerWidth;
    H = window.innerHeight;
    c.width = W;
    c.height = H;
    grid = new Array(Math.ceil(W / (minD * 1.5))).fill(null).map(() => new Array(Math.ceil(H / (minD * 1.5))).fill(0));
    active = [];
    samples = [];
    pointCount = 0;
}

function reset() {
    init();
    for(let y=0; y<H; y+=2) { for(let x=0; x<W; x+=2) { grid[Math.floor(x/(minD*1.5))][Math.floor(y/(minD*1.5))] = 0; } }
}

function check(x, y, rSq) {
    let k = Math.floor(x/(minD*1.5));
    let j = Math.floor(y/(minD*1.5));
    if (k < 0 || k >= grid.length || j < 0 || j >= grid[0].length) return false;
    return grid[k][j] === 0;
}

function findNeighbors(x, y) {
    let a = Math.floor((x - minD/2) / (minD * 1.5));
    let b = Math.floor((y - minD/2) / (minD * 1.5));
    for (let i = a-1; i <= a+1; ++i) {
        for (let j = b-1; j <= b+1; ++j) {
            if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length) continue;
            const n = [i * minD * 1.5 + (i+1)/2, j * minD * 1.5 + (j+1)/2];
            if (grid[i][j] > 0) {
                samples.push({x: grid[i][j].x, y: grid[i][j].y});
            }
        }
    }
}

function sample() {
    const r = Math.random() * minD * 2;
    const theta = Math.random() * Math.PI * 2;
    let x = active[active.length - 1].x + r * Math.cos(theta);
    let y = active[active.length - 1].y + r * Math.sin(theta);

    if (x < 0 || x > W || y < 0 || y > H) return false;

    const dSq = samples.reduce((max, s) => Math.max(max, (s.x - x)**2 + (s.y - y)**2), 0);
    if (dSq >= minD * minD) {
        // Accept point
        samples.push({x: x, y: y});
        active.push({x: x, y: y});
        grid[Math.floor(x/(minD*1.5))][Math.floor(y/(minD*1.5))] = 1;
        ctx.fillStyle='#6aa';
        ctx.fillRect(x-2, y-2, 4, 4);
        pointCount++;
        return true;
    }
    return false;
}

function loop() {
    if (active.length === 0) {
        reset();
    }

    let accepted = false;
    while (accepted && active.length < 1000) {
        accepted = sample();
    }

    if (!accepted || active.length >= samples.length * 2) {
        requestAnimationFrame(loop);
        return;
    }

    requestAnimationFrame(loop);
}

window.addEventListener('resize', () => {
    W = window.innerWidth;
    H = window.innerHeight;
    init();
});

let minD = Math.min(Math.random() * 0.1 + 0.3, 0.5);
if (typeof requestAnimationFrame === 'function') {
    loop();
} else {
    // Fallback for older environments
    setInterval(loop, 16);
}
</script>
</body>
</html>
```
deepseek-r1:14bERRBLANKFORMAT
Show code
```html
<!DOCTYPE html>
<html><head><style>body{background:#000}canvas{position:fixed;top:0;left:0;z-index:-1}</style></head>
<body><h2 style="color:#fff;padding:15px;">Poisson Disk Sampling</h2>
<canvas id=c width=800 height=600></canvas>
<div id=s stats></div>
<script>
const c=document.getElementById('c'), ctx=c.getContext('2d');
const w=c.width,h=c.height,d=Math.sqrt,minD=.05;
let grid=[],active=[],candidates=[];
function init(){grid=Array(h).fill().map(()=>[]);active=[];candidates=[];}
function addPoint(px,py){if(px<0||py<0||px>w||py>h)return false;
const x=~~(py/CELL), y=~~(px/CELL);if(grid[x][y])return false;
let canAdd=true,dx=CELL/2 - Math.abs(px%CELL-CELL/2);
for(let i=-1;i<3;i++)for(let j=-1;j<3;j++){
const nx=x+i,ny=y+j;if(!grid[nx]||!grid[ny][j])continue;
for(const p of grid[nx][ny]){let distSq=(px - p.x)*(px-p.x)+(py-p.y)*(py-p.y);
if(distSq < minD*minD){canAdd=false;break;} }
if(!canAdd)break; }if(canAdd){
active.push({x, y: py, cx: px, cy: py});grid[x][y].push({x:px,y:py});
ctx.beginPath();ctx.arc(px, py, 1.5,0,2*Math.PI);ctx.fillStyle='#fff';ctx.fill();
return true;}return false;}
function generateCandidates(){const len=active.length;
for(let i=len-1;i>=0;i--){const p=active[i];
for(let a=0;a<Math.PI*2;a+=.5){
const da=a + (Math.random()-0.5)*45,dr=Math.random()*minD/2 + minD*.5;
const dx=dr*Math.cos(da), dy=dr*Math.sin(da);
candidates.push({x:p.x+dx,y:p.y+dy});} } }
function update(){if(active.length==0){init();addPoint(w/2,h/2);return requestAnimationFrame(update);}
let count=0;while(candidates.length>0 && active.length>0){
const c=candidates.shift(),cx= ~~(c.x/CELL), cy=~~(c.y/CELL);
let canAdd=true;if(!grid[cx]||!grid[cy])continue;
for(let i=-1;i<3;i++)for(let j=-1;j<3;j++){
if(cx+i<0||cx+i>=h/cellSize)continue;if(cy+j<0||cy+j>=w/cellSize)continue;
for(const p of grid[cx+i][cy+j]){let distSq=(c.x - p.x)*(c.x-p.x)+(c.y-p.y)*(c.y-p.y);
if(distSq < minD*minD){canAdd=false;break;} } if(!canAdd)break; }
if(canAdd){
grid[cx].push({x:c.x,y:c.y});active.push(c);count++;} }
document.getElementById('s').textContent=`Samples: ${active.length}`;
requestAnimationFrame(update);}
init();addPoint(w/2,h/2);update();
</script>
</body></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.
command-r:35bERRBLANKFORMAT
Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Poisson Disk Sampling</title>
    <style>
        body { margin:0; }
        canvas { display:block; image-rendering:optimizeSpeed; }
    </style>
</head>
<body>

    <canvas></canvas>

    <script>

        let width, height, gridSize, samples, cells, radius, active;

        function Cell(x, y) {
            this.x = x;
            this.y = y;
        };

        const makeGrid = (w, h, s) => {
            const c = [];
            for (let i=0; i<Math.ceil(h/s); ++i) {
                let row = [];
                for (let j=0; j<Math.ceil(w/s); ++j) {
                    row.push(new Cell(j*s, i*s));
                }
                c.push(row);
            }
            return c;
        };

        const distanceSq = (x1, y1, x2, y2) => {
            let dx = x1 - x2;
            let dy = y1 - y2;
            return (dx * dx + dy * dy);
        };

        const randomInt = max => Math.floor(Math.random() * max);

        const neighbors = (x, y, cells, gridSize) => {
            let lx = x - gridSize;
            let ly = y - gridSize;

            if (lx < 0) lx += gridSize;
            else if (lx >= width) lx -= gridSize;

            if (ly < 0) ly += gridSize;
            else if (ly >= height) ly -= gridSize;

            return [
                cells[Math.floor(y/gridSize)][Math.floor(x/gridSize)], 
                cells[Math.floor(y/gridSize)][lx], 
                cells[ly][Math.floor(x/gridSize)], 
                cells[ly][lx]
            ];
        };

        const sample = (cell, samples, active, cells) => {
            let count = 0;
            while (count < 50) {
                ++count;

                if (!samples || Math.random() < 0.5) {
                    let x = cell.x + randomInt(radius);
                    let y = cell.y + randomInt(radius);

                    if (x >= width || y >= height) continue;

                    const point = neighbors(x, y, cells, gridSize); 

                    for (let i=0; i<point.length; ++i) {
                        if (!distanceSq(x, y, point[i].x, point[i].y)) {
                            break;
                        }

                        let dx = x - point[i].x;
                        let dy = y - point[i].y;

                        if (dx * dx + dy * dy < radius) {
                            break;
                        }
                    }

                    samples.push({ 
                        x, y 
                    });                          

                    context.beginPath();
                    context.fillStyle = "#09f";
                    context.arc(x, y, 2, 0, 2*Math.PI);
                    context.closePath();
                    context.fill();

                    active.push({
                        x: x + randomInt(radius) - radius/2, 
                        y: y + randomInt(radius) - radius/2 
                    }); 

                } else {
                    let index = Math.floor(samples.length * Math.random());
                    samples[index] = null;
                    active.push({
                        x: samples[index].x + randomInt(radius) - radius/2, 
                        y: samples[index].y + randomInt(radius) - radius/2 
                    });
                }
            }
        };

        const animate = () => {
            context.clearRect(0, 0, width, height);

            for (let i=0; i<active.length;) {

                let x = Math.floor(active[i].x + gridSize / 2);
                let y = Math.floor(active[i].y + gridSize/2);
                
                if (!cells[Math.floor(y/gridSize)][Math.floor(x/gridSize)]) continue;

                sample(
                    cells[Math.floor(y/gridSize)][Math.floor(x/gridSize)], 
                    samples, active, cells
                );
            }

            active = active.filter(item => !!item); // Remove nulls
            
            context.fillText(`Count: ${samples.length}`, 10, height - 15);

            if (active.length == 0) {
                sample(cells[0][0], samples, [], cells);
            }

            requestAnimationFrame(animate);
        };

        const canvas = document.querySelector('canvas');
        width = window.innerWidth; 
        height = window.innerHeight;
        gridSize = Math.floor((width + height)/150) || 4;
        radius = gridSize * 2;
        active = [];
        samples = [
            { x: width/2, y: height/2 }
        ];

        canvas.width = width; 
        canvas.height = height;

        const context = canvas.getContext('2d');
        cells = makeGrid(width, height, gridSize);

        sample(cells[0][0], samples, active, cells);
        
        requestAnimationFrame(animate);

    </script>
</body>
</html>
```
qwq:32bBLANKFORMAT
Show code
<think>

Okay, let me tackle this. The user wants a self-contained HTML file that uses Bridson's Poisson-disk sampling to fill a canvas. The requirements are pretty specific, so I need to make sure I cover all the points.

First, I'll start by setting up the basic HTML structure with a canvas element. Since it needs to be self-contained, all the code has to be in the <script> tags. The canvas needs to be responsive, so maybe set width and height with a resize listener. Wait, the user mentioned a smooth animation with requestAnimationFrame and no user input, so maybe the canvas size should be fixed. Hmm, perhaps just set a default size and have it scale with the viewport? Or maybe just a fixed size for simplicity. Let's go with a fixed size for now to avoid complications.

Next, implementing Bridson's algorithm. The steps are:

1. Create a background grid to track neighbors quickly. The grid size should be half the minimum distance (since any point in an adjacent cell is within the min distance). Let's say the min distance is 50, so grid cell size is 25.

2. The active list holds all the points we're currently considering neighbors for new points.

3. Start with a random point, add it to the grid and active list.

4. While the active list isn't empty, pick a random point from it (maybe the last one for efficiency?), and generate candidate points in the ring between min/2 and min around it. The ring is a circle with inner radius min/2 and outer radius min.

5. For each candidate, check all neighboring cells in the grid (up to 3x3 around the cell the candidate is in) to see if any existing points are too close.

6. If a candidate has no close neighbors, accept it by adding to grid and active list, and draw it on the canvas.

7. When the active list is empty, start over with a new random pattern.

I need to draw each point as soon as it's accepted, so the canvas should update each time a new point is added. Using requestAnimationFrame seems good here because it allows the animation to be smooth and responsive.

Wait, but how to structure the loop. Since Bridson's can take a while depending on parameters, we need to run it step by step each frame. Otherwise, if we run it all in one go, it might block the UI. So each frame, we try to process one iteration of the algorithm: pick a random active point, generate candidates, check, add new points if possible, then draw.

So the main loop will be inside the animation frame callback. Each frame, we process the active points, check for candidates, add new ones, etc. Also, when done, reset the grid and active list to restart.

Variables needed:

- canvas and context
- width and height of the canvas
- grid (array of arrays, or a 1D array with indices calculated)
- active list (array of points)
- minDistance (maybe 50 initially, but could be adjusted)
- cellSize = minDistance / 2
- sampleCount (to display)
- isDone (flag to know when to reset)

Drawing each point as soon as it's accepted. The draw function can be called every time a new point is added.

Now, the grid. Since we need to quickly find neighbors of a point, the grid can be an array where each cell is a pointer to a point, or null if empty. The cell indices are calculated based on x and y divided by cellSize. The grid dimensions would be ceil(canvasWidth/cellSize) x ceil(canvasHeight/cellSize). So maybe store them as a 1D array where index is (y/cellSize)*gridWidth + (x/cellSize). Or maybe a 2D array for easier access.

Wait, in JavaScript, a 2D array might be more manageable. Let's say grid is an array where grid[y][x] holds the point or null. Wait, no, actually, the grid will need to be a grid of cells, each cell can have a point or not. So maybe grid[y][x] is the point, or null. But for efficiency, perhaps a 1D array is better. Let me think.

Alternatively, the grid can be an object where the keys are computed from the coordinates. Hmm, but that's more complex. Let me go with a 2D array.

The grid will be an array of rows, each row is an array of cells. So grid[y][x] = point? Or just a flag? Actually, each cell can store a reference to the point that is located in that cell. Wait, but a point could be in multiple cells? No, each point is in exactly one cell. So the grid's purpose is to allow us to quickly check neighboring cells.

So to create the grid, when adding a point (x,y), compute its grid cell:

cellX = Math.floor(x / cellSize);
cellY = Math.floor(y / cellSize);

Then, the grid at cellY and cellX will store the point. Wait, but maybe multiple points can be in adjacent cells? Actually, since the cell size is half the minimum distance, any two points within the same cell are at least min/2 apart? Or maybe the cell size is chosen so that any two points in adjacent cells are within the minimum distance? Hmm, Bridson's algorithm uses cell size equal to the minimum distance divided by sqrt(2) or something? Wait, I might need to recall the proper setup for Bridson's grid.

I think in Bridson's paper, the grid is used to quickly find neighbors within the minimum distance. To do that, the grid cell size should be no more than half the minimum distance. That way, any point in the cell can only have neighbors in adjacent cells (up to 3x3 grid cells around the current cell). So the cell size is set to minDistance / 2. That way, any two points within minDistance must be in adjacent grid cells or the same cell.

Therefore, each time a new candidate point is generated, we can check all the adjacent grid cells (including the current cell) to see if any points are within radius minDistance.

So the grid will need to be a 2D array where each cell can store a point (or just a flag indicating presence), but perhaps storing the point reference is better for distance checks.

Wait, but we'll have to check all points in the neighboring cells. So maybe the grid stores pointers to the points in each cell, so that for a candidate point, we can check all the points in the neighboring grid cells.

Alternatively, since the grid is a background grid, each cell can store the point (or null), and to check neighbors, we look at the surrounding cells (up to 3x3) and check if any of those cells have a point, then compute the distance between the candidate and each such point.

So the steps for adding a new point:

1. Select a random active point (maybe from the end of the list for efficiency, but Bridson's algorithm usually picks randomly from the active list).

2. Generate 10 or so random candidate points in the annulus between minDistance/2 and minDistance from the current point.

3. For each candidate, compute which grid cell it's in.

4. Then check all neighboring grid cells (up to 3x3 cells around the candidate's cell), and for each non-null cell, check the distance between the candidate and that point.

5. If any of those points are within minDistance, discard the candidate.

6. If none, then accept the candidate: add it to the grid, add to active list, increment sampleCount, draw it on canvas.

7. If after generating 10 candidates and none are accepted, remove the current point from the active list, since no more points can be added from it.

Okay, so the grid is crucial here. The grid's cell size is minDistance / 2.

Now, implementing this in JS:

First, the canvas setup:

<canvas id="canvas"></canvas>

Then in script:

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

Set the canvas dimensions. Maybe set to full viewport for responsiveness, but since it must be self-contained, perhaps hardcode a size like 600x600? Or maybe set it to 400x400 for simplicity. Let's go with 600x600 initially. The user didn't specify size, so maybe it's okay. Also, using style to make it visible, maybe 100% width and height, but the actual canvas is fixed size. Alternatively, use the CSS to set it, but the user wants it without comments, so proceed.

Wait, the user says "Draw each point the moment it is accepted, so the blue-noise pattern visibly fills the area." So the drawing is done as points are added. So each time a point is accepted, it should be drawn.

The drawing can be done by filling a circle at the point's coordinates with a certain radius. Maybe 1px? Or 2px? The user didn't specify, but for visibility, perhaps 2px.

Now, variables:

Let me outline variables:

const minDistance = 50; // adjust as needed
const cellSize = minDistance / 2;
let width = 600;
let height = 600;
canvas.width = width;
canvas.height = height;

Wait, but in code, need to set the canvas' attributes:

canvas.width = width;
canvas.height = height;

Then the grid:

const gridWidth = Math.ceil(width / cellSize);
const gridHeight = Math.ceil(height / cellSize);
// Create a 2D grid array with nulls
let grid = [];
for (let y = 0; y < gridHeight; y++) {
  grid[y] = [];
  for (let x = 0; x < gridWidth; x++) {
    grid[y][x] = null;
  }
}

Wait, but in JS, 2D arrays can be created with Array.from or nested loops. Alternatively, using a 1D array with x + y * gridWidth. Maybe that's more efficient. Let me see:

Alternatively:

const grid = new Array(gridHeight);
for (let y = 0; y < gridHeight; y++) {
  grid[y] = new Array(gridWidth).fill(null);
}

Hmm, but in strict code, it might be better to initialize properly.

The active list:

let activeList = [];
let sampleCount = 0;

Then, the function to add a point:

function addPoint(x, y) {
  const cellX = Math.floor(x / cellSize);
  const cellY = Math.floor(y / cellSize);
  grid[cellY][cellX] = {x, y}; // or store as an object
  activeList.push({x, y});
  sampleCount++;
  ctx.fillRect(x-1, y-1, 2, 2); // draw a small square
}

Wait, but maybe using ctx.fillRect with 2x2 pixels centered at (x,y), so subtract 1 from each coordinate.

Alternatively, using ctx.beginPath(); ctx.arc(x, y, 2, 0, Math.PI*2); ctx.fill(); but that's more code. For efficiency, maybe rectangles.

Wait, the drawing code needs to be efficient as there might be many points. Using rectangles is faster? Not sure, but for the purpose here, maybe rectangles are better.

Wait, but if the points are small, maybe a single pixel. Hmm. Alternatively, just draw a point with a 2px radius, but the user might want it to be visible.

Perhaps using ctx.fillRect(x, y, 1, 1) but that's just a single pixel. To make it visible, maybe 2px. So subtract 1 from x and y to center.

Wait, but the coordinates might not be integers. So maybe better to use ctx.fillRect with the position as is, but with a size of 2, so the center is (x+1, y+1) if using 2x2.

Wait, perhaps better to use:

ctx.fillStyle = 'hsl(' + Math.random() * 360 + ',50%,50%)';

Wait, but the user didn't mention colors, so maybe just a simple color like black. Let's set ctx.fillStyle to 'black' and use:

ctx.fillRect(x, y, 1, 1);

But that's a single pixel. To make it visible, maybe 2px. Let me adjust:

ctx.fillRect(x - 0.5, y - 0.5, 1, 1); // centered 1x1 pixel?

Alternatively:

ctx.fillStyle = 'black';
ctx.fillRect(Math.floor(x), Math.floor(y), 1, 1);

But that might not be precise. Hmm. Well, for the purpose of the visualization, maybe it's okay. Let's proceed without worrying too much about the exact drawing method as long as points are visible.

Now, the main algorithm loop.

The function that runs each frame: let's call it animate() which is called via requestAnimationFrame.

Inside animate, while activeList is not empty, process a point:

Wait, but frame-based processing can't just loop all the time, else it blocks. So in each frame, we process one or a few steps, then request another frame.

Let me structure it like this:

let isRunning = true;

function animate() {
  if (!isRunning) return;
  let stepCount = 0;
  while (activeList.length > 0 && stepCount < 10) { // process up to 10 steps per frame
    // pick a random active point
    const index = Math.floor(Math.random() * activeList.length);
    const [currentX, currentY] = activeList[index]; // Wait, need to store the points correctly in activeList. Maybe as objects.
    Wait, in the addPoint function earlier, we pushed an object {x, y} to activeList. So:

    const current = activeList[index];
    const currentX = current.x;
    const currentY = current.y;

    // Generate 10 candidate points around the current point
    let found = false;
    for (let i = 0; i < 10; i++) {
      const angle = Math.random() * Math.PI * 2;
      const radius = minDistance * (0.5 + Math.random() * 0.5); // between min/2 and min
      const dx = Math.cos(angle) * radius;
      const dy = Math.sin(angle) * radius;
      const candidateX = currentX + dx;
      const candidateY = currentY + dy;

      // Check if candidate is within canvas boundaries
      if (candidateX < 0 || candidateX >= width || candidateY < 0 || candidateY >= height) {
        continue;
      }

      // Determine the candidate's grid cell
      const cellX = Math.floor(candidateX / cellSize);
      const cellY = Math.floor(candidateY / cellSize);

      // Check neighboring cells for conflicts
      let conflict = false;
      for (let ky = -1; ky <= 1; ky++) {
        for (let kx = -1; kx <= 1; kx++) {
          const neighborCellY = cellY + ky;
          const neighborCellX = cellX + kx;
          if (neighborCellY < 0 || neighborCellY >= gridHeight || neighborCellX < 0 || neighborCellX >= gridWidth) {
            continue;
          }
          const neighborPoint = grid[neighborCellY][neighborCellX];
          if (neighborPoint) {
            const dx = candidateX - neighborPoint.x;
            const dy = candidateY - neighborPoint.y;
            if (dx*dx + dy*dy < minDistance*minDistance) {
              conflict = true;
              break;
            }
          }
        }
        if (conflict) break;
      }

      if (!conflict) {
        // Accept candidate
        addPoint(candidateX, candidateY);
        found = true;
        break;
      }
    }

    if (!found) {
      // No candidates found, remove this point from active list
      activeList.splice(index, 1);
    }

    stepCount++;
  }

  if (activeList.length === 0) {
    // Done, reset
    reset();
  }

  // Update the counter
  ctx.fillText('Samples: ' + sampleCount, 10, 20);

  // Request next frame
  requestAnimationFrame(animate);
}

Wait, but the addPoint function also needs to draw the point. Let me adjust that.

Wait, in the addPoint function:

function addPoint(x, y) {
  const cellX = Math.floor(x / cellSize);
  const cellY = Math.floor(y / cellSize);
  grid[cellY][cellX] = {x, y}; // storing the point in grid
  activeList.push({x, y});
  sampleCount++;
  // Draw the point
  ctx.fillRect(x - 0.5, y - 0.5, 1, 1); // assuming 1x1 pixel centered
}

Alternatively, using ctx.arc:

ctx.beginPath();
ctx.arc(x, y, 1, 0, Math.PI*2);
ctx.fill();

But that's a bit more code. Maybe the rectangle is better for brevity.

Also, the canvas needs to clear before starting? Or not, since each new pattern should overwrite. Wait, when resetting, the grid and active list are cleared, but the canvas must be cleared as well. So in the reset function:

function reset() {
  grid.forEach(row => row.fill(null));
  activeList.length = 0;
  sampleCount = 0;
  // Clear the canvas
  ctx.clearRect(0, 0, width, height);
  // Start again
  // Pick a random initial point
  const firstX = Math.random() * width;
  const firstY = Math.random() * height;
  addPoint(firstX, firstY);
}

Wait, but initially, when the page loads, the animate function and reset need to be called. So in the setup:

// Initialize on start
reset();
requestAnimationFrame(animate);

Putting all together, need to structure the code properly in the script tags.

Wait, also, in the grid initialization, since grid is a 2D array, maybe the code for grid needs to be:

grid = [];
for (let y = 0; y < gridHeight; y++) {
  grid[y] = [];
  for (let x = 0; x < gridWidth; x++) {
    grid[y][x] = null;
  }
}

Alternatively, using Array.from:

grid = Array.from({length: gridHeight}, () => 
  Array.from({length: gridWidth}, () => null)
);

Which is shorter.

Additionally, the initial point must be added in reset().

Testing possible issues:

- When calculating cellX and cellY, need to ensure that even if the coordinate is exactly on the grid boundary (e.g., x = cellSize * gridWidth), it doesn't go out of bounds.

Wait, gridWidth is Math.ceil(width / cellSize). For example, if width is exactly divisible by cellSize, then gridWidth is exactly width/cellSize, so cellSize * gridWidth = width. But in that case, candidateX could be exactly width, which would give cellX = (width / cellSize) - 1, since floor would drop the decimal.

Wait, for example:

width = 600, cellSize = 50 → gridWidth = 12 (600/50=12). So x=600 would have cellX = 600/50 = 12, floor is 12, but gridWidth is 12, so indexes go up to 11.

Thus, candidateX = 600 is invalid because it's >= width (600). So in that case, the condition candidateX >= width would exclude it.

Therefore, the boundary conditions should be okay.

Another possible issue: when the candidate is inside the canvas, but the grid cell might be at the edge.

Another point: in the loop over neighboring cells (ky and kx), we need to ensure that neighborCellY and neighborCellX are within the grid dimensions.

Also, in the code for checking neighborPoint, grid[neighborCellY][neighborCellX] is an object with x and y. So neighborPoint.x is accessible.

Now, putting all together in the script.

Wait, also need to define the reset function properly.

Let me try to outline the full code:

<script>
const minDistance = 50;
const cellSize = minDistance / 2;
const width = 600;
const height = 600;
const canvas = document.querySelector('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');

let gridWidth = Math.ceil(width / cellSize);
let gridHeight = Math.ceil(height / cellSize);
let grid = Array.from({length: gridHeight}, () => 
  Array.from({length: gridWidth}, () => null)
);
let activeList = [];
let sampleCount = 0;

function addPoint(x, y) {
  const cellX = Math.floor(x / cellSize);
  const cellY = Math.floor(y / cellSize);
  grid[cellY][cellX] = {x, y};
  activeList.push({x, y});
  sampleCount++;
  ctx.fillRect(x - 0.5, y - 0.5, 1, 1); // draw a 1x1 pixel square, centered
}

function reset() {
  // Clear the grid
  grid.forEach(row => row.fill(null));
  activeList = [];
  sampleCount = 0;
  ctx.clearRect(0, 0, width, height);
  // Start with a random point
  const firstX = Math.random() * width;
  const firstY = Math.random() * height;
  addPoint(firstX, firstY);
}

function animate() {
  let stepCount = 0;
  while (activeList.length > 0 && stepCount < 10) {
    const index = Math.floor(Math.random() * activeList.length);
    const current = activeList[index];
    const currentX = current.x;
    const currentY = current.y;
    
    let found = false;
    for (let i = 0; i < 10; i++) {
      const angle = Math.random() * 2 * Math.PI;
      const radius = minDistance * (0.5 + Math.random() * 0.5);
      const dx = Math.cos(angle) * radius;
      const dy = Math.sin(angle) * radius;
      const candidateX = currentX + dx;
      const candidateY = currentY + dy;

      if (candidateX < 0 || candidateX >= width || candidateY < 0 || candidateY >= height) continue;

      const cellX = Math.floor(candidateX / cellSize);
      const cellY = Math.floor(candidateY / cellSize);

      let conflict = false;
      for (let ky = -1; ky <= 1; ky++) {
        for (let kx = -1; kx <= 1; kx++) {
          const neighborCellY = cellY + ky;
          const neighborCellX = cellX + kx;
          if (neighborCellY < 0 || neighborCellY >= gridHeight) continue;
          if (neighborCellX < 0 || neighborCellX >= gridWidth) continue;
          const neighborPoint = grid[neighborCellY][neighborCellX];
          if (neighborPoint) {
            const dx = candidateX - neighborPoint.x;
            const dy = candidateY - neighborPoint.y;
            if (dx*dx + dy*dy < minDistance * minDistance) {
              conflict = true;
              break;
            }
          }
        }
        if (conflict) break;
      }

      if (!conflict) {
        addPoint(candidateX, candidateY);
        found = true;
        break;
      }
    }

    if (!found) activeList.splice(index, 1);
    stepCount++;
  }

  if (activeList.length === 0) {
    reset();
  }

  ctx.fillText('Samples: ' + sampleCount, 10, 20);
  requestAnimationFrame(animate);
}

// Initialize and start
reset();
requestAnimationFrame(animate);
</script>

Wait, but in the addPoint function, after adding to the grid, the position is stored as an object {x, y}. So when checking neighborPoint, grid[neighborCellY][neighborCellX] is that object, so accessing neighborPoint.x and neighborPoint.y is okay.

Also, in the reset function, grid.forEach(...).fill(null) might not work as expected because Array.fill modifies the array in place. Wait, when using Array.from, each row is an array. So:

grid.forEach(row => row.fill(null));

This should reset each row to have all nulls.

Another possible issue: when adding the first point, the grid is initialized properly.

Also, in the animate function, after resetting, the next frame will start processing the new initial point.

Now, testing possible errors:

- The canvas element must be present in the HTML. So, the user must have a canvas tag in their HTML. Since the problem says to create the code, we can assume that the HTML includes a canvas element. But in the code above, the script is selecting it via document.querySelector('canvas'). So the user should have:

<canvas></canvas>

In their HTML.

Putting all together, the full HTML:

<!DOCTYPE html>
<html>
  <body>
    <canvas></canvas>
    <script>
    // The script code above
    </script>
  </body>
</html>

Now, in the code, the counter is drawn at (10,20), but initially, that might be covered by the first point, but since it's text, it should be on top.

Potential optimization: To prevent the text from being cleared, but since the canvas is cleared on reset, it's okay to redraw it each frame.

Another possible issue: when the grid is reset, the next time addPoint is called, the grid is properly set to nulls.

Testing the code:

The initial point is added via reset(). Then the animate loop processes it. Each step adds up to 10 points per frame (since stepCount <10).

The loop continues until the activeList is empty, then resets.

This should create a random pattern of points with at least minDistance between them, restarting periodically.

Now, possible edge cases:

- The first point is added, but no more points can be added (e.g., in a very small canvas). But with width=600 and minDistance=50, it should have enough room.

Testing on small canvas might cause it to reset quickly, but for 600 it should work.

Now, the problem says "Create a program that...", so the user expects the code to be in the form of a script, likely in HTML with canvas.

Thus, the final code would be as outlined.
deepseek-r1:32bERRBLANKFORMAT
Show code
```html
<!DOCTYPE html><html><body style="background:#1a1a1a;display:flex;justify-content:center;align-items:center;height:100vh;margin:0"><canvas id=c></canvas><script>
const c=document.getElementById('c'),w=window.innerWidth,h=window.innerHeight,radius=20,cellSize=radius*2,minDist=radius*2,grid=[],activeList=[],points=[];
let count=0;

function init(){
    c.width=w;
    c.height=h;
    grid.length=0;
    activeList.length=0;
    points.length=0;
    count=0;
}

function getIndex(x,y){
    return Math.floor(y/cellSize)+Math.floor(x/cellSize)*Math.ceil(h/cellSize);
}

function addPoint(x,y){
    const idx=getIndex(x,y);
    if(grid[idx])grid[idx].push({x:x,y:y});
    else grid[idx]=[ {x:x,y:y} ];
    activeList.push({x:x,y:y});
    points.push({x:x,y:y});
}

function isValid(x,y){
    let xMin=Math.max(0,Math.floor((x-minDist)/cellSize));
    let xMax=Math.min(Math.ceil(w/cellSize),Math.floor((x+minDist)/cellSize)+1);
    let yMin=Math.max(0,Math.floor((y-minDist)/cellSize));
    let yMax=Math.min(Math.ceil(h/cellSize),Math.floor((y+minDist)/cellSize)+1);
    
    for(let i=xMin;i<xMax;i++){
        for(let j=yMin;j<yMax;j++){
            const idx=j+i*Math.ceil(h/cellSize);
            if(grid[idx]){
                for(const p of grid[idx]){
                    const dx=x-p.x,dy=y-p.y;
                    if(Math.sqrt(dx*dx+dy*dy)<minDist)return false;
                }
            }
        }
    }
    return true;
}

function drawPoint(x,y){
    ctx.beginPath();
    ctx.arc(x,y,radius/4,0,2*Math.PI);
    ctx.fill();
}

function spawnPoints(){
    while(activeList.length>0&&count<1e6){
        const idx=Math.floor(Math.random()*activeList.length);
        const point=activeList[idx];
        const angle=Math.random()*Math.PI*2;
        const step=minDist/2;
        
        for(let i=0;i<32;i++){
            const candidate={
                x:point.x+step*Math.cos(angle+i*(Math.PI*2)/32),
                y:point.y+step*Math.sin(angle+i*(Math.PI*2)/32)
            };
            
            if(candidate.x>=0&&candidate.x<w&&candidate.y>=0&&candidate.y<h&&isValid(candidate.x,candidate.y)){
                addPoint(candidate.x,candidate.y);
                drawPoint(candidate.x,candidate.y);
                count++;
                break;
            }
        }
        
        activeList.splice(idx,1);
    }
    
    if(activeList.length>0){
        requestAnimationFrame(spawnPoints);
    }else{
        console.log('Generated',points.length,'points');
        setTimeout(init,500);
        init();
        const x=Math.random()*w;
        const y=Math.random()*h;
        addPoint(x,y);
        drawPoint(x,y);
        count++;
        spawnPoints();
    }
}

const ctx=c.getContext('2d');
ctx.fillStyle='#fff';
ctx.strokeStyle='#fff';

init();
c.width=w;
c.height=h;

function resizeCanvas(){
    c.width=window.innerWidth;
    c.height=window.innerHeight;
}

window.addEventListener('resize',resizeCanvas);

const x=Math.random()*w;
const y=Math.random()*h;
addPoint(x,y);
drawPoint(x,y);
count++;
spawnPoints();
</script></body></html>
```
Outside the Brain cluster — same task, same character budget, collected through their own tooling (response times not comparable)
Claude Opus 5frontier referenceOK
Show code
<!doctype html>
<html><head><meta charset="utf-8"><title>Poisson-disk sampling (Bridson)</title>
<style>
html,body{margin:0;height:100%;background:#070a12;overflow:hidden}
canvas{display:block;width:100vw;height:100vh}
#hud{position:fixed;left:12px;top:11px;font:13px ui-monospace,monospace;color:#cfe0ff;
background:rgba(6,10,20,.6);padding:5px 9px;border-radius:5px}
</style></head><body>
<canvas id="c"></canvas><div id="hud">samples 0</div>
<script>
const cv=document.getElementById('c'),g=cv.getContext('2d'),hud=document.getElementById('hud');
let W,H;
const R=14,K=30,CELL=R/Math.SQRT2;
let gw,gh,grid,active,count,hue,restarting=false;

function fit(){W=cv.width=innerWidth;H=cv.height=innerHeight}
fit();addEventListener('resize',()=>{fit();reset()});

function reset(){
  gw=Math.ceil(W/CELL);gh=Math.ceil(H/CELL);
  grid=new Int32Array(gw*gh).fill(-1);
  active=[];count=0;hue=Math.random()*360;
  g.fillStyle='#070a12';g.fillRect(0,0,W,H);
  add(W/2,H/2);
}

const pts=[];
function add(x,y){
  const i=pts.length;pts.push(x,y);
  grid[(y/CELL|0)*gw+(x/CELL|0)]=i;
  active.push(i);count++;
  const sh=(hue+count*.35)%360;
  g.fillStyle='hsl('+sh+',72%,62%)';
  g.beginPath();g.arc(x,y,2.2,0,6.2832);g.fill();
}

function ok(x,y){
  if(x<0||y<0||x>=W||y>=H)return false;
  const cx=x/CELL|0,cy=y/CELL|0;
  for(let j=Math.max(0,cy-2);j<=Math.min(gh-1,cy+2);j++)
    for(let i=Math.max(0,cx-2);i<=Math.min(gw-1,cx+2);i++){
      const s=grid[j*gw+i];
      if(s<0)continue;
      const dx=pts[s*2]-x,dy=pts[s*2+1]-y;
      if(dx*dx+dy*dy<R*R)return false;
    }
  return true;
}

function frame(){
  let budget=260;
  while(active.length&&budget-->0){
    const ai=Math.random()*active.length|0,idx=active[ai];
    const px=pts[idx*2],py=pts[idx*2+1];
    let placed=false;
    for(let n=0;n<K;n++){
      const a=Math.random()*6.2832,rad=R*(1+Math.random());
      const nx=px+Math.cos(a)*rad,ny=py+Math.sin(a)*rad;
      if(ok(nx,ny)){add(nx,ny);placed=true;break}
    }
    if(!placed)active.splice(ai,1);
  }

  hud.textContent='samples '+count+'  ·  active '+active.length
    +'  ·  r='+R+(active.length?'':'  · complete, restarting');

  if(!active.length&&!restarting){
    restarting=true;
    setTimeout(()=>{pts.length=0;reset();restarting=false},700);
  }
  requestAnimationFrame(frame);
}
reset();
requestAnimationFrame(frame);
</script></body></html>
GPT-5.5 (Codex)frontier referenceOKMINIFIED
Show code
<!doctype html><html><head><meta charset=utf-8><title>Poisson Disk</title><style>html,body{margin:0;height:100%;overflow:hidden;background:#07111f;color:#dbeafe;font:16px system-ui}canvas{display:block}#n{position:fixed;left:14px;top:10px;padding:6px 9px;background:#0008;border-radius:6px}</style></head><body><canvas id=c></canvas><div id=n></div><script>
let C=c.getContext("2d"),W,H,r=18,k=30,cs,g,gw,gh,a,p,fill,rest=0;
function R(){W=c.width=innerWidth;H=c.height=innerHeight;S()}
onresize=R;
function S(){cs=r/Math.SQRT2;gw=Math.ceil(W/cs);gh=Math.ceil(H/cs);g=Array(gw*gh).fill(-1);a=[];p=[];C.fillStyle="#07111f";C.fillRect(0,0,W,H);C.fillStyle="#39f";let x=Math.random()*W,y=Math.random()*H;add(x,y);rest=0}
function add(x,y){let i=p.length;p.push([x,y]);a.push(i);g[(x/cs|0)+(y/cs|0)*gw]=i;C.beginPath();C.arc(x,y,2.2,0,7);C.fill()}
function ok(x,y){if(x<0||y<0||x>=W||y>=H)return 0;let gx=x/cs|0,gy=y/cs|0;for(let j=gy-2;j<=gy+2;j++)for(let i=gx-2;i<=gx+2;i++)if(i>=0&&j>=0&&i<gw&&j<gh){let q=p[g[i+j*gw]];if(q&&((x-q[0])**2+(y-q[1])**2<r*r))return 0}return 1}
function step(){let n=0;while(a.length&&n<90){let m=Math.random()*a.length|0,s=p[a[m]],hit=0;for(let t=0;t<k;t++){let A=Math.random()*7,d=r*(1+Math.random()),x=s[0]+Math.cos(A)*d,y=s[1]+Math.sin(A)*d;if(ok(x,y)){add(x,y);hit=1;n++;break}}if(!hit)a.splice(m,1)}document.getElementById("n").textContent=p.length+" samples";if(!a.length){if(rest++>45)S()}requestAnimationFrame(step)}
R();step();
</script></body></html>
Claude Sonnet 5frontier referenceOK
Show code
<!DOCTYPE html><html><head><meta charset="utf8"><title>Poisson Disk</title><style>
body{margin:0;background:#101418;overflow:hidden}canvas{display:block}
#i{position:fixed;top:8px;left:8px;color:#fc8;font:14px monospace}
</style></head><body><canvas id="c"></canvas><div id="i"></div><script>
const cv=document.getElementById('c'),ctx=cv.getContext('2d');
function resize(){cv.width=innerWidth;cv.height=innerHeight}
resize();addEventListener('resize',resize);
let r,cellSize,gcols,grows,grid,samples,active,k=30,paused=false;
function init(){
  paused=false;
  ctx.fillStyle='#101418'; ctx.fillRect(0,0,cv.width,cv.height);
  r=8+Math.random()*8;
  cellSize=r/Math.SQRT2;
  gcols=Math.ceil(cv.width/cellSize);
  grows=Math.ceil(cv.height/cellSize);
  grid=new Array(gcols*grows).fill(-1);
  samples=[];
  active=[];
  const x0=cv.width/2, y0=cv.height/2;
  samples.push({x:x0,y:y0});
  active.push(0);
  grid[gridIdx(x0,y0)]=0;
}
function gridIdx(x,y){
  const gx=Math.floor(x/cellSize), gy=Math.floor(y/cellSize);
  return gy*gcols+gx;
}
function fits(x,y){
  if(x<0||x>=cv.width||y<0||y>=cv.height) return false;
  const gx=Math.floor(x/cellSize), gy=Math.floor(y/cellSize);
  for(let j=Math.max(0,gy-2); j<=Math.min(grows-1,gy+2); j++){
    for(let i=Math.max(0,gx-2); i<=Math.min(gcols-1,gx+2); i++){
      const idx=grid[j*gcols+i];
      if(idx>=0){
        const s=samples[idx];
        const dx=s.x-x, dy=s.y-y;
        if(dx*dx+dy*dy < r*r) return false;
      }
    }
  }
  return true;
}
function stepAlg(){
  let placed=0;
  const budget=40;
  while(active.length>0 && placed<budget){
    const ai=Math.floor(Math.random()*active.length);
    const pi=active[ai];
    const p=samples[pi];
    let found=false;
    for(let t=0;t<k;t++){
      const ang=Math.random()*Math.PI*2;
      const rad=r*(1+Math.random());
      const nx=p.x+Math.cos(ang)*rad, ny=p.y+Math.sin(ang)*rad;
      if(fits(nx,ny)){
        const ni=samples.length;
        samples.push({x:nx,y:ny});
        grid[gridIdx(nx,ny)]=ni;
        active.push(ni);
        drawPoint(nx,ny);
        found=true;placed++;
        break;
      }
    }
    if(!found){ active.splice(ai,1); }
  }
}
function drawPoint(x,y){
  ctx.fillStyle='hsl('+((x+y)*0.15%360)+',80%,65%)';
  ctx.beginPath();
  ctx.arc(x,y,r*0.42,0,Math.PI*2);
  ctx.fill();
}
init();
function loop(){
  if(!paused) stepAlg();
  ctx.fillStyle='rgba(16,20,24,0.55)';
  ctx.fillRect(0,0,220,44);
  ctx.fillStyle='#fc8'; ctx.font='14px monospace';
  ctx.fillText('samples: '+samples.length,10,20);
  ctx.fillText('active: '+active.length,10,38);
  if(!paused && active.length===0){
    paused=true;
    setTimeout(()=>{ init(); },900);
  }
  requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
</script></body></html>
Claude Haiku 4.5frontier referenceERRBLANKMINIFIED
Show code
<!DOCTYPE html><html><head><meta charset="utf-8"><style>body{margin:0;background:#000;overflow:hidden}#c{display:block}#i{position:absolute;top:5px;left:5px;color:#0f0;font-family:monospace;font-size:12px}</style></head><body><canvas id="c"></canvas><div id="i"></div><script>const c=document.getElementById('c'),ctx=c.getContext('2d'),i=document.getElementById('i');c.width=800;c.height=600;const W=800,H=600,r=20,gx=Math.ceil(W/r),gy=Math.ceil(H/r);let gr=Array(gx*gy).fill(null);let sp=[],ac=[];function a(x,y){let gxi=Math.floor(x/r),gyi=Math.floor(y/r);if(gxi<0||gxi>=gx||gyi<0||gyi>=gy)return true;for(let dy=-2;dy<=2;dy++){for(let dx=-2;dx<=2;dx++){let gi=(gyi+dy)*gx+(gxi+dx);if(gi>=0&&gi<gr.length&&gr[gi]){let p=gr[gi];if(Math.hypot(p.x-x,p.y-y)<r)return true}}}return false}let d=false;function dr(){if(!d){if(ac.length===0){if(sp.length===0){let p={x:Math.random()*W,y:Math.random()*H};if(!a(p.x,p.y)){sp.push(p);ac.push(p);let gi=Math.floor(p.y/r)*gx+Math.floor(p.x/r);gr[gi]=p}}}else{let pi=Math.floor(Math.random()*ac.length);let p=ac[pi];for(let j=0;j<10;j++){let a2=Math.random()*Math.PI*2;let d2=Math.random()*(2*r)+r;let nx=p.x+Math.cos(a2)*d2;let ny=p.y+Math.sin(a2)*d2;if(nx>=0&&nx<W&&ny>=0&&ny<H&&!a(nx,ny)){let np={x:nx,y:ny};sp.push(np);ac.push(np);let gi=Math.floor(ny/r)*gx+Math.floor(nx/r);gr[gi]=np;break}}ac.splice(pi,1)}}d=ac.length===0&&sp.length>0}ctx.fillStyle='#000';ctx.fillRect(0,0,W,H);ctx.fillStyle='#00f';for(let p of sp){ctx.fillRect(p.x-2,p.y-2,4,4)}i.textContent=`Samples: ${sp.length}`}setInterval(dr,30);</script></body></html>
Results at a glance— every model in this round with score, response time and status.

Who wrote what

ModelBlind scoreLatencyStatus
gemma4:26b ——harness
qwen3.5:9b —34.7 sOK
qwen3-coder:30b —18.8 sOK
mistral-small:24b ——DNF
llama3.1:8b —148.1 sOK
qwen3:14b —18.7 sOK
deepseek-r1:14b —110.9 sOK
qwen3:8b ——harness
command-r:35b —247.0 sOK
qwq:32b —240.9 sOK
deepseek-r1:32b —298.7 sOK