Overview › Code › R75
Code · blind round

R75 · Falling sand on a cell grid

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 falling sand as a cellular automaton on a 150x100 CELL GRID drawn on a <canvas>. Sand is poured in at the top; each step, every sand cell tries to move one cell down, otherwise one cell down-left or down-right, otherwise it rests. Work strictly cell by cell on the grid — no floating-point positions, no velocities. Show the number of resting cells and the step count. 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)
llama3.1:8bBLANKFORMAT
Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Falling Sand</title>
<style>body { margin: 0; }</style>
</head>
<body>
<canvas id="canvas"></canvas>

<script>
const canvas = document.getElementById('canvas');
canvas.width = 150;
canvas.height = 100;

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

let grid = new Array(150);
for (let i=0; i<150; i++) {
	grid[i] = new Array(100).fill(0);
}

function drawGrid() {
	ctx.fillStyle = 'black';
	for (let x=0; x<150; x++) {
		for (let y=0; y<100; y++) {
			if (grid[x][y] == 1) ctx.fillRect(x, y, 1, 1);
		}
	}
}

function updateGrid() {
	let resting = 0;
	for (let x=0; x<150; x++) {
		for (let y=0; y<100; y++) {
			if (grid[x][y] == 2) { // sand
				if (y < 99 && grid[x][y+1] != 1) grid[x][y+1] = 2;
				else if ((x > 0 && grid[x-1][y+1] != 1 && grid[x-1][y+1] != 2) || (x < 149 && grid[x+1][y+1] != 1 && grid[x+1][y+1] != 2)) {
					grid[x][y] = 3; // rest
					resting++;
				}
			} else if (grid[x][y] == 3) { // rest
				if ((x > 0 && grid[x-1][y] != 1 && grid[x-1][y] != 2) || (x < 149 && grid[x+1][y] != 1 && grid[x+1][y] != 2)) {
					grid[x][y] = 2;
				}
			} else if (grid[x][y] == 0) { // empty
				if (Math.random() < 0.05) { // pour in some sand
					grid[x][y] = 2;
				}
			}
		}
	}

	document.getElementById('resting').textContent = resting;

	drawGrid();
}

function animate() {
	updateGrid();
	requestAnimationFrame(animate);
}

const pouringButton = document.createElement('button');
pouringButton.textContent = 'Start';
document.body.appendChild(pouringButton);

canvas.addEventListener('click', function(e) {
	grid[e.clientX][e.clientY] = 2;
});

pouringButton.addEventListener('click', function() {
	animate();
});

drawGrid();
</script>

<div id="resting"></div>
```
qwen3-coder:30bERRBLANKMINIFIED
Show code
<!DOCTYPE html>
<html><body><canvas id="sandCanvas" width="300" height="150"></canvas><script>const canvas=document.getElementById("sandCanvas");const ctx=canvas.getContext("2d");let W=15;let H=10;let CELL_SIZE=20;let GRID_W=150,GRID_H=100;// Scaling dimensions for the actual simulation logic
let grid = Array(GRID_H).fill(0).map(()=>Array(GRID_W).fill(0));let nextGrid=Array(GRID_H).fill(0).map(()=>Array(GRID_W).fill(0));let stepCount=0;function init() {for(let i=0;i<GRID_H;i++)grid[i]=Object.assign([...grid[i]]);for(let i=0;i<GRID_W;i++)grid[i].fill(0);stepCount=0;console.log("Simulation initialized.");}function draw() {ctx.clearRect(0,0,canvas.width,canvas.height);let scaleX=canvas.width/GRID_W;let scaleY=canvas.height/GRID_H;for(let y=0;y<GRID_H;y++)for(let x=0;x<GRID_W;x++)if(grid[y][x])ctx.fillStyle="#D2B48C";ctx.fillRect(x*scaleX,y*scaleY,scaleX-1,scaleY-1);function update() {nextGrid=Object.assign([...nextGrid]);for(let y=0;y<GRID_H;y++)for(let x=0;x<GRID_W;x++)if(grid[y][x]===1){let dy=y+1,dx=x;let target=[{dy:dy,dx:dx},{dy:y+1,dx:x-1},{dy:y+1,dx:x+1}];let moveTarget={r:-1,c:-1};for(const t of target){if(t.dy>=0&&t.dy<GRID_H&&t.dx>=0&&t.dx<GRID_W&&grid[t.dy][t.dx]===0){moveTarget={r:t.dy,c:t.dx};break;}}if(moveTarget.r>-1){nextGrid[moveTarget.r++][moveTarget.c++]++;}else{nextGrid[y][x]++;}}let restingCells=0;for(let y=0;y<GRID_H;y++)for(let x=0;x<GRID_W;x++)if(grid[y][x]===1&&nextGrid[y][x]===1)restingCells++;grid=Object.assign([...nextGrid]);nextGrid=Array(GRID_H).fill(0).map(()=>Array(GRID_W).fill(0));stepCount++;document.getElementById("status").innerHTML=`Step: ${stepCount}<br>Resting Cells: ${restingCells}`;requestAnimationFrame(loop);function loop() {draw();update();};init();window.onload=()=>{let status=document.createElement('div');status.id="status";status.style.position='absolute';status.style.top='10px';status.style.left='10px';document.body.appendChild(status);loop();}
</script></body></html>
deepseek-r1:14bERRBLANKFORMAT
Show code
```html
<!DOCTYPE html>
<html><body style="margin:0;overflow:hidden">
<canvas id=c width=600 height=400></canvas>
<script>
const c=document.getElementById('c'),ctx=c.getContext('2d');
const w=150,h=100,csize=4;
let grid=[];for(let y=0;y<h;++y)grid[y]=new Array(w).fill(0);
let step=0,resting=0,count=0;
function draw() {
  ctx.clearRect(0,0,w*csize,h*csize);
  for(let y=0;y<h;++y) {
    for(let x=0;x<w;++x) {
      if(grid[y][x]>0) {
        ctx.fillStyle=`rgb(${-~(Math.sin(y/csize)*127+128)},${-~(Math.sin((y+x)/csize*2.5)*127+128)},128)`; 
        ctx.fillRect(x*csize,y*csize,csize-1,csize-1);
      }
    }
  }
}
function update() {
  ++step;
  const newGrid=[[...grid[0]];for(let y=1;y<h;++y)newGrid[y]=new Array(w).fill(0)];
  let r=0;
  for(let y=0;y<h;++y) {
    for(let x=0;x<w;++x) {
      if(grid[y][x]===0) continue;
      const ny=y+1;if(ny>=h){newGrid[y][x]=grid[y][x];r++;continue;}
      if(newGrid[ny][x]<1 && grid[y][x]>0) {newGrid[ny][x]+=grid[y][x];continue;}
      if(newGrid[ny][x-1]===0 && newGrid[ny][x]>=1) {newGrid[ny][x-1]+=grid[y][x];continue;}
      if(newGrid[ny][x+1]===0 && newGrid[ny][x]==0) {newGrid[ny][x+1]+=grid[y][x];continue;}
      newGrid[y][x]=grid[y][x];r++;
    }
  }
  grid=newGrid;
  resting=r;count=++count%360;
}
function loop() {
  update();
  draw();
  if(resting===w*h) {grid=[];for(let y=0;y<h;++y)grid[y]=new Array(w).fill(0);step=0;resting=0;}
  requestAnimationFrame(loop);
}
loop();
</script>
</body></html>
```
qwen3.5:9bOKFORMAT
Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Falling Sand Simulation</title>
    <style>body { background: #111; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; } canvas { border: 2px solid #ccc; }</style>
</head>
<body>
    <canvas id="sandCanvas" width="300" height="500"></canvas>
    <script>
        const canvas = document.getElementById('sandCanvas');
        const ctx = canvas.getContext('2d');

        const COLS = 150;
        const ROWS = 100;
        const CELL_SIZE = 2; // Scale factor for visualization
        const GRID_WIDTH = Math.ceil(COLS * CELL_SIZE);
        const GRID_HEIGHT = Math.ceil(ROWS * CELL_SIZE);

        let grid = Array.from({ length: COLS }, () => new Array(ROWS).fill(0));
        let stepCount = 0;
        let restingCells = 0;
        let running = true;

        function initializeGrid() {
            grid = Array.from({ length: COLS }, () => new Array(ROWS).fill(0));
            stepCount = 0;
            restingCells = 0;
            for (let i = 0; i < COLS; i++) {
                if (Math.random() < 0.1) { // Random sand placement at start
                    grid[i][ROWS - 1] = 1;
                }
            }
        }

        function drawGrid() {
            ctx.clearRect(0, 0, GRID_WIDTH, GRID_HEIGHT);
            for (let x = 0; x < COLS; x++) {
                for (let y = 0; y < ROWS; y++) {
                    if (grid[x][y] === 1) {
                        ctx.fillStyle = '#FFD700'; // Sand color
                        ctx.fillRect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE);
                    }
                }
            }

            ctx.fillStyle = 'white';
            ctx.font = "14px Arial";
            ctx.fillText(`Step: ${stepCount} | Resting: ${restingCells}`, 10, 20);
        }

        function update() {
            let nextGrid = JSON.parse(JSON.stringify(grid));
            let newRestingCells = 0;
            let sandMoved = false;

            for (let x = 0; x < COLS; x++) {
                for (let y = ROWS - 1; y >= 0; y--) {
                    if (grid[x][y] === 1) {
                        let newX = x;
                        let newY = y - 1;

                        // Try falling down
                        if (newY >= 0 && nextGrid[x][newY] === 0) {
                            nextGrid[x][newY] = 1;
                            grid[x][y] = 0; // Clear old spot in original grid for the move logic below
                            sandMoved = true;
                        } else if (newY >= 0 && (x > 0 ? nextGrid[x - 1][y] === 0 : false) && (x < COLS - 1 ? nextGrid[x + 1][y] === 0 : false)) { // Try diagonal fallback
                            if (Math.random() < 0.5) {
                                newX = x - 1;
                            } else {
                                newX = x + 1;
                            }
                            newY = y;

                            if (nextGrid[newX][newY] === 0) {
                                nextGrid[newX][newY] = 1;
                                grid[x][y] = 0;
                                sandMoved = true;
                            } else {
                                // If diagonal spot is occupied in the temporary grid, it rests
                                nextGrid[x][y] = 1;
                                newRestingCells++;
                            }
                        } else {
                            // Rests if blocked or already at top edge
                            nextGrid[x][y] = 1;
                            newRestingCells++;
                        }
                    } else {
                        nextGrid[x][y] = grid[x][y]; // Keep empty spots empty
                    }
                }
            }

            grid = nextGrid;
            stepCount++;
            restingCells = newRestingCells;

            drawGrid();

            requestAnimationFrame(update);
        }

        initializeGrid();
        update();
    </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.
mistral-small:24bOKFORMAT
Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Falling Sand</title>
<style>
    body { display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: #f0f0f0; }
    canvas { border: 2px solid black; }
    #info { position: absolute; top: 10px; left: 10px; font-family: Arial, sans-serif; color: black; }
</style>
</head>
<body>
<canvas id="sandCanvas" width="600" height="400"></canvas>
<div id="info">Step: 0 | Resting: 0</div>
<script>
const canvas = document.getElementById('sandCanvas');
const ctx = canvas.getContext('2d');
const cellSize = 4;
const cols = 150;
const rows = 100;
const grid = Array.from({ length: rows }, () => Array(cols).fill(0));
let stepCount = 0;
let restingCells = 0;

function drawGrid() {
    for (let r = 0; r < rows; r++) {
        for (let c = 0; c < cols; c++) {
            ctx.fillStyle = grid[r][c] ? 'yellow' : 'white';
            ctx.fillRect(c * cellSize, r * cellSize, cellSize, cellSize);
        }
    }
}

function updateGrid() {
    const newGrid = Array.from({ length: rows }, () => Array(cols).fill(0));
    let restingCount = 0;
    for (let r = 0; r < rows; r++) {
        for (let c = 0; c < cols; c++) {
            if (grid[r][c]) {
                if (r === rows - 1) {
                    newGrid[r][c] = 1;
                    restingCount++;
                } else if (!newGrid[r + 1][c]) {
                    newGrid[r + 1][c] = 1;
                } else if (c > 0 && !newGrid[r + 1][c - 1]) {
                    newGrid[r + 1][c - 1] = 1;
                } else if (c < cols - 1 && !newGrid[r + 1][c + 1]) {
                    newGrid[r + 1][c + 1] = 1;
                } else {
                    newGrid[r][c] = 1;
                    restingCount++;
                }
            }
        }
    }
    grid.splice(0, rows, ...newGrid);
    return restingCount;
}

function pourSand() {
    if (Math.random() < 0.05) grid[0][Math.floor(Math.random() * cols)] = 1;
}

function animate() {
    stepCount++;
    restingCells += updateGrid();
    pourSand();
    drawGrid();
    document.getElementById('info').innerText = `Step: ${stepCount} | Resting: ${restingCells}`;
    if (restingCells >= cols * rows) restart();
    else requestAnimationFrame(animate);
}

function restart() {
    grid.fill(Array(cols).fill(0));
    stepCount = 0;
    restingCells = 0;
    animate();
}

requestAnimationFrame(animate);
</script>
</body>
</html>
```
qwen3:14bOKLIMFORMAT
Show code
```html
<!DOCTYPE html>
<html>
<head>
<title>Falling Sand Simulation</title>
<style>body { background: #000; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; }</style>
</head>
<body>
<canvas id="sandCanvas" width="300" height="600"></canvas>

<script>
    const canvas = document.getElementById('sandCanvas');
    const ctx = canvas.getContext('2d');

    // Grid dimensions (150 columns, 100 rows) - Note: Canvas size is fixed at 300x600 for visual scaling
    const COLS = 150;
    const ROWS = 100;
    const CELL_SIZE = 2; // Drawing scale factor
    const GRAVITY = 1;

    // State representation: 0 = Empty, 1 = Sand
    let grid = [];
    let stepCount = 0;

    function initializeGrid() {
        grid = Array(ROWS).fill(0).map(() => new Uint8Array(COLS));
        stepCount = 0;

        // Fill with some initial random sand for demonstration
        for (let r = 1; r < ROWS - 5; r++) {
            for (let c = Math.random() * COLS; c < Math.min(c + 2, COLS); c++) {
                if (Math.random() > 0.9) grid[r][c] = 1; // Sparse initial sand
            }
        }

        // Ensure the top corner starts with sand for continuous flow
        grid[0][30] = 1; 
    }

    function getSandCount(currentGrid) {
        let count = 0;
        for (let r = 0; r < ROWS; r++) {
            for (let c = 0; c < COLS; c++) {
                if (currentGrid[r][c] === 1) count++;
            }
        }
        return count;
    }

    function update() {
        const nextGrid = new Uint8Array(COLS).fill(0);
        let currentSandCount = 0;
        let nextSandCount = 0;
        let restingCells = 0;

        // Iterate bottom up, left to right (standard CA processing order)
        for (let r = ROWS - 1; r >= 0; r--) {
            for (let c = 0; c < COLS; c++) {
                if (grid[r][c] === 1) {
                    currentSandCount++;

                    // Try Down
                    const downR = r + GRAVITY;
                    const downC = c;
                    
                    if (downR < ROWS && grid[downR][downC] === 0) {
                        grid[downR][downC] = 1; // Move down
                        nextSandCount++;
                        continue;
                    }

                    // Try Down-Left or Down-Right if Down is blocked
                    const potentialMoves = [
                        { r: r + GRAVITY, c: c - 1 },
                        { r: r + GRAVITY, c: c + 1 }
                    ];

                    let moved = false;
                    for (const move of potentialMoves) {
                        const newR = move.r;
                        const newC = move.c;

                        if (newR < ROWS && newC >= 0 && newC < COLS && grid[newR][newC] === 0) {
                            grid[newR][newC] = 1; // Move diagonally
                            nextSandCount++;
                            moved = true;
                            break;
                        }
                    }

                    if (!moved) {
                        // Rests in place (This is the cell that stays at grid[r][c])
                        restingCells++;
                    }
                }
            }
        }
        
        // Fallback: If any cells were moved, they must be reset for the next frame.
        // Since we are modifying 'grid' directly in place (which is fine for this simple CA model), 
        // we don't need to copy the whole grid, just ensure boundaries are respected implicitly by logic.

        // We only count resting cells based on the successful updates within the loop structure.
        stepCount++;
    }

    function draw() {
        ctx.fillStyle = '#010A28'; // Dark background color
        ctx.fillRect(0, 0, canvas.width, canvas.height);

        for (let r = 0; r < ROWS; r++) {
            for (let c = 0; c < COLS; c++) {
                if (grid[r][c] === 1) {
                    ctx.fillStyle = '#ffaa00'; // Sand color
                    ctx.fillRect(c * CELL_SIZE, r * CELL_SIZE, CELL_SIZE, CELL_SIZE);
                }
            }
        }

        // Display stats
        const sandCount = getSandCount(grid);
        let statusText = `Step: ${stepCount} | Sand Cells: ${sandCount}`;
        ctx.fillStyle = '#FFFFFF';
        ctx.font = '16px monospace';
        ctx.fillText(`Status: Running`, 10, 20);

        // Draw info below canvas (simulated update for text output)
        const statusDisplay = document.createElement('div');
        statusDisplay.style.position = 'absolute';
        statusDisplay.style.top = 'calc(100vh - 50px)';
        statusDisplay.style.left = '0';
        statusDisplay.innerHTML = `<strong>Step: ${stepCount}</strong> | Sand Cells: ${sandCount}`;
        document.body.appendChild(statusDisplay);
    }

    function loop() {
        // Core simulation step
        update(); 
        draw();
        requestAnimationFrame(loop);
    }

    // Start the simulation
    initializeGrid();
    loop();
</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:35bOKFORMAT
Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Falling Sand Simulation</title>
    <style>
        body { margin: 0; }
        canvas { border: 1px solid black; }
    </style>
</head>
<body>
    <canvas id="game" width="450" height="300"></canvas>

    <script>
        const canvas = document.getElementById('game');
        const ctx = canvas.getContext('2d');

        let stepCount = 0;
        let restingCells = 0;
        const gridSizeX = 150;
        const gridSizeY = 100;
        let field = Array(gridSizeY).fill().map(() => Array(gridSizeX).fill(false));

        function drawCell(x, y) {
            ctx.fillStyle = 'rgba(247,239,154,0.8)'; // Sand color with some transparency
            ctx.fillRect(x * 3, y * 3, 3, 3);
        }

        function isCellEmpty(x, y) {
            return !field[y][x];
        }

        function setCellState(x, y, state) {
            field[y][x] = state;
        }

        function update() {
            restingCells = 0;
            for (let y = gridSizeY - 1; y >= 0; y--) {
                for (let x = 0; x < gridSizeX; x++) {
                    if (!field[y][x]) continue;

                    let newX = x;
                    let newY = y + 1;
                    if (isCellEmpty(newX, newY)) {
                        setCellState(x, y, false);
                        setCellState(newX, newY, true);
                    } else {
                        newX++;
                        newY++;
                        if (isCellEmpty(newX, newY)) {
                            setCellState(x, y, false);
                            setCellState(newX, newY, true);
                        } else {
                            restingCells++;
                        }
                    }
                }
            }

            stepCount++;
        }

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

            for (let y = 0; y < gridSizeY; y++) {
                for (let x = 0; x < gridSizeX; x++) {
                    if (field[y][x]) drawCell(x, y);
                }
            }

            ctx.fillStyle = 'rgba(255,255,255,0.8)'; // Text color with some transparency
            ctx.font = '16px sans-serif';
            ctx.textAlign = 'left';
            ctx.fillText(`Resting Cells: ${restingCells}`, 10, canvas.height - 10);
            ctx.fillText(`Step Count: ${stepCount}`, 250, canvas.height - 10);
        }

        function gameLoop() {
            update();
            draw();

            if (restingCells === gridSizeX * gridSizeY) {
                field = Array(gridSizeY).fill().map(() => Array(gridSizeX).fill(false)); // Reset the field
                stepCount = 0;
                restingCells = 0;

                for (let x = gridSizeX / 2 - 15; x <= gridSizeX / 2 + 15; x++) {
                    setCellState(x, 0, true); 
                }
            }

            requestAnimationFrame(gameLoop);
        }

        gameLoop();
    </script>
</body>
</html>
```
deepseek-r1:32bBLANKFORMAT
Show code
```html
<!DOCTYPE html>
<html>
<head>
    <title>Sand Simulation</title>
    <style>
        canvas{border:1px solid #000;display:block;margin:20px auto;background:#fff}
        body{background:#1a1a1a;color:#fff;font-family:sans-serif;text-align:center}
        #stats{position:absolute;top:20px;left:50%;transform:translateX(-50%)}
    </style>
</head>
<body>
    <canvas id="c"></canvas>
    <div id="stats">Resting: 0 | Steps: 0</div>
    <script>
        const canvas = document.getElementById('c'), ctx = canvas.getContext('2d');
        let w = 150, h = 100;
        canvas.width = w * 2; canvas.height = h * 2;
        ctx.scale(2, 2);
        const GRID_EMPTY = 0, GRID_FALLING = 1, GRID_RESTING = 2;
        
        let grid = new Array(w).fill().map(() => new Array(h).fill(GRID_EMPTY));
        let resting = 0, steps = 0, maxParticles = w * h / 3, particles = [];
        
        function init() {
            for(let x=5;x<w-5;x++)particles.push({x:x,y:0});
            resting = 0;
            steps = 0;
        }
        
        function updateGrid() {
            const newGrid = grid.map(c => [...c]);
            for(let y = h -1; y >=0; y--) {
                for(let x = 0; x <w;x++) {
                    if(grid[x][y] === GRID_FALLING) {
                        let below = y + 1;
                        if(below < h && grid[x][below] === GRID_EMPTY) {
                            newGrid[x][below] = GRID_FALLING;
                            newGrid[x][y] = GRID_EMPTY;
                        } else {
                            tryLeft: {
                                if(x >0 && y+1 <h && (grid[x-1][y+1] === GRID_EMPTY)) {
                                    newGrid[x-1][y+1] = GRID_FALLING;
                                    newGrid[x][y] = GRID_EMPTY;
                                    break tryLeft;
                                }
                            }
                            tryRight: {
                                if(x <w-1 && y+1 <h && (grid[x+1][y+1] === GRID_EMPTY)) {
                                    newGrid[x+1][y+1] = GRID_FALLING;
                                    newGrid[x][y] = GRID_EMPTY;
                                    break tryRight;
                                } else {
                                    if(newGrid[x][y] === GRID_FALLING) {
                                        newGrid[x][y] = GRID_RESTING;
                                        resting++;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            grid = newGrid;
        }
        
        function draw() {
            ctx.clearRect(0,0,w,h);
            for(let x=0;x<w;x++) {
                for(let y=0;y<h;y++) {
                    if(grid[x][y] === GRID_FALLING || grid[x][y] === GRID_RESTING) {
                        ctx.fillStyle = '#aaa';
                        ctx.fillRect(x,y,1,1);
                    }
                }
            }
            for(let p of particles) {
                ctx.fillStyle = '#c00';
                ctx.fillRect(p.x,p.y,1,1);
            }
        }
        
        function animate() {
            if(!particles.length && resting >= maxParticles/2) setTimeout(init, 2000);
            updateGrid();
            steps++;
            document.getElementById('stats').textContent = `Resting: ${resting} | Steps: ${steps}`;
            requestAnimationFrame(animate);
        }
        
        init();
        animate();
    </script>
</body>
</html>
```
qwq:32bSTAT
Show code
<think>

Alright, let's tackle this problem. The user wants an HTML file that simulates falling sand using a cellular automaton on a 150x100 grid. The key points are:

- It needs to be self-contained, so all code has to be in one HTML file.
- The grid is 150 cells wide and 100 tall.
- Sand pours from the top, and each step, each sand cell tries to move down, then down-left or down-right if down is blocked, otherwise rests.
- Show resting cells count and step count.
- Use requestAnimationFrame for smooth animation.
- No user input, starts immediately, restarts when finished with a new random instance.
- No external libraries, no comments needed. Strictly under 120 lines.

First, I need to structure the HTML file. It should include a canvas element and a script. The canvas will be used to draw the grid, and the script will handle the cellular automaton logic.

Let me think about the grid. Since it's 150x100, I can represent it as a 2D array. Each cell can have a state: 0 (empty), 1 (moving sand), 2 (resting sand). Wait, but the problem says "each step, every sand cell tries to move one cell down, otherwise down-left or down-right, otherwise rests". So maybe each sand particle is processed each step, checking movement options.

But the user specifies "work strictly cell by cell on the grid". So perhaps each cell can hold a state indicating if it's sand and if it's moving. Maybe an array of arrays where each cell is 0 (empty), 1 (moving sand), 2 (resting sand). The algorithm will process each cell in each step, trying to move down first.

The steps per frame: since it's a cellular automaton, each frame (animation frame) might represent a step. But for smoother animation, perhaps multiple steps per frame? Or each animation frame corresponds to one step. Hmm, the problem says "smooth requestAnimationFrame animation", so probably each frame is a step. But maybe steps are processed each frame, but need to ensure it's fast enough.

The simulation steps:

1. For each cell in the grid, check if it's sand (moving or resting). Wait, moving sand needs to move first. Maybe first, in each step, we process all the moving sand cells to see where they can go.

Alternatively, perhaps we process each cell from top to bottom, left to right. For each cell, if it's sand (assuming moving), check the cell below. If that's empty, move it down and mark as resting? Or maybe:

The algorithm per step:

Loop through each cell in the grid. For each cell that is sand (moving), check if it can move down. If yes, move down and mark as moving again (since maybe next step it can go further). Wait, maybe better to process in a way that movement is determined, then updated in a new grid to prevent race conditions.

Wait, handling cellular automata often requires a buffer to avoid overwriting cells that are being processed. Because if you process a cell and move it, then the next cell below might be processed before the movement is complete. So perhaps we need a temporary buffer to store the next state of each cell.

So here's a possible approach:

- Create a 2D array grid, and a temporary buffer array (same size) to store the next state.

- Each step:

   - Initialize buffer to all zeros (or copy the grid?)

   - For each cell (r, c) in grid:

      - If cell is sand (either moving or resting?), Wait, perhaps moving sand is in a separate state. Maybe:

         - 0: empty

         - 1: moving sand (needs to move this step)

         - 2: resting (can't move)

      But how does a sand particle transition between states? Let's think:

      When sand is poured initially, it starts as moving (state 1). Then, in each step, check if it can move down. If yes, mark the cell below as moving, and current as empty? Or use the buffer approach.

Wait, perhaps the process is:

For each step:

1. Create a buffer array to hold the next state.

2. For each row from bottom to top, and each column, process the cell:

   If the current cell is sand (state 1):

      Check the cell below (row+1). If it's empty (0), then in the buffer, set the cell below to 1 (moving), and the current to 0.

      If the cell below is blocked (2 or 1), then check diagonals (down-left: row+1, col-1 and down-right: row+1, col+1). If either of those is empty (0), choose one randomly? Or alternately, check left first then right. Wait the problem says "otherwise one cell down-left or down-right". It says "otherwise" meaning if down is blocked, then try down-left or down-right. So maybe first check down, then if blocked, try down-left or down-right (both options?), and if either is available, choose one? But the problem says "otherwise one cell down-left or down-right, otherwise it rests". So if down is blocked, then check left and right directions. If either is available, it can move there; if both are blocked, then it rests (becomes 2).

Wait the exact wording:

"each step, every sand cell tries to move one cell down, otherwise one cell down-left or down-right, otherwise it rests."

So the priority is:

1. Move down if possible (to row+1, same column).

2. If not, try down-left (row+1, column-1) and down-right (row+1, column+1). Wait, the problem says "otherwise one cell down-left or down-right". Maybe it can choose either of the two if possible? Or does it check both and pick one?

Hmm, the problem says "otherwise one cell down-left or down-right", perhaps the sand can move to either if possible. But how to choose between them? Maybe check left first, then right. So first check down-left, if possible, else down-right.

Alternatively, pick a random direction between the two if both are blocked? Wait, no: the problem says "otherwise it rests". So if neither down-left nor down-right are possible, then it can't move and becomes resting.

So the algorithm for a sand cell (state 1) at position (r,c):

- Check if r+1 < rows (within grid). If grid[r+1][c] is 0, then move down to r+1, c, becomes moving again.

Wait, no. Because moving sand is trying to move each step. Once it can't move down, it tries the diagonals.

Wait, the process is: Each sand cell in this step first tries to move down. If it can, then it does so (so in the next step, it will again try to move down again). If it can't, then it tries to move down-left or down-right. If neither is possible, then it stops and becomes resting (state 2).

But how do we track this in the grid?

Perhaps:

- The buffer is used to store the next state of each cell.

- For each cell (r,c) in the grid, if it's moving sand (1):

   Check if the cell below (r+1,c) is empty (0):

   - If yes, then in the buffer, set (r
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 lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Falling Sand</title>
<style>
html,body{margin:0;height:100%;background:#111;color:#eee;font:16px system-ui,sans-serif;display:grid;place-items:center}
main{display:grid;gap:12px;justify-items:center}
canvas{width:min(96vw,900px);height:auto;image-rendering:pixelated;background:#050505;border:1px solid #333}
#hud{display:flex;gap:24px}
</style>
</head>
<body>
<main>
<canvas id="c" width="900" height="600"></canvas>
<div id="hud"><span>Resting: <b id="r">0</b></span><span>Steps: <b id="s">0</b></span></div>
</main>
<script>
const W=150,H=100,N=W*H,cell=6,c=document.getElementById("c"),x=c.getContext("2d"),R=document.getElementById("r"),S=document.getElementById("s");
let g,n,rest,steps,source,left,last;
function reset(){
 g=new Uint8Array(N);n=new Uint8Array(N);rest=0;steps=0;left=9000+Math.random()*5000|0;last=performance.now();source=60+Math.random()*30|0;
}
function pour(){
 for(let i=0;i<6&&left>0;i++){
  let p=source+(Math.random()*13|0)-6;
  if(p>=0&&p<W&&!g[p]){g[p]=1;left--}
 }
}
function tick(){
 n.fill(0);rest=0;let moving=0;
 for(let y=H-1;y>=0;y--)for(let x0=0;x0<W;x0++){
  let i=y*W+x0;if(!g[i])continue;
  if(y<H-1&&!g[i+W]&&!n[i+W]){n[i+W]=1;moving++;continue}
  let d=Math.random()<.5?-1:1,a=i+W+d,b=i+W-d;
  if(y<H-1&&x0+d>=0&&x0+d<W&&!g[a]&&!n[a]){n[a]=1;moving++;continue}
  if(y<H-1&&x0-d>=0&&x0-d<W&&!g[b]&&!n[b]){n[b]=1;moving++;continue}
  n[i]=1;rest++;
 }
 let t=g;g=n;n=t;steps++;
 if(left<=0&&!moving)reset();
}
function draw(){
 x.fillStyle="#050505";x.fillRect(0,0,c.width,c.height);x.fillStyle="#d7a64a";
 for(let i=0;i<N;i++)if(g[i])x.fillRect(i%W*cell,(i/W|0)*cell,cell,cell);
 R.textContent=rest;S.textContent=steps;
}
function frame(now){
 for(let k=0;k<Math.min(5,(now-last)/16);k++){pour();tick();last+=16}
 draw();requestAnimationFrame(frame);
}
reset();requestAnimationFrame(frame);
</script>
</body>
</html>
Claude Sonnet 5frontier referenceOK
Show code
<!doctype html>
<html><head><meta charset="utf-8"><title>Falling Sand Grid</title>
<style>html,body{margin:0;background:#101014;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 COLS=150,ROWS=100,CS=6,OX=20,OY=20;
let grid,shade,stepCount,pourX,restCount;
function rnd(n){return Math.floor(Math.random()*n)}
function init(){
  grid=new Uint8Array(COLS*ROWS);
  shade=new Uint8Array(COLS*ROWS);
  stepCount=0;restCount=0;
  pourX=30+rnd(COLS-60);
}
init();
function canMove(x,y){
  const below=grid[(y+1)*COLS+x];
  if(below===0)return true;
  const l=x>0?grid[(y+1)*COLS+x-1]:1;
  const r=x<COLS-1?grid[(y+1)*COLS+x+1]:1;
  return l===0||r===0;
}
function step(){
  for(let y=ROWS-2;y>=0;y--){
    const dir=Math.random()<0.5?1:-1;
    let xs=[];
    for(let x=0;x<COLS;x++)xs.push(x);
    if(dir<0)xs.reverse();
    for(const x of xs){
      const idx=y*COLS+x;
      if(grid[idx]!==1)continue;
      const below=(y+1)*COLS+x;
      if(grid[below]===0){grid[below]=1;shade[below]=shade[idx];grid[idx]=0;continue;}
      const canL=x>0&&grid[(y+1)*COLS+x-1]===0;
      const canR=x<COLS-1&&grid[(y+1)*COLS+x+1]===0;
      if(canL&&canR){
        const t=Math.random()<0.5?-1:1;
        grid[(y+1)*COLS+x+t]=1;shade[(y+1)*COLS+x+t]=shade[idx];grid[idx]=0;
      }else if(canL){grid[(y+1)*COLS+x-1]=1;shade[(y+1)*COLS+x-1]=shade[idx];grid[idx]=0;}
      else if(canR){grid[(y+1)*COLS+x+1]=1;shade[(y+1)*COLS+x+1]=shade[idx];grid[idx]=0;}
    }
  }
  for(let k=0;k<3;k++){
    const px=Math.max(0,Math.min(COLS-1,pourX+rnd(5)-2));
    if(grid[px]===0){grid[px]=1;shade[px]=rnd(3);}
  }
  stepCount++;
  restCount=0;
  for(let y=0;y<ROWS;y++)for(let x=0;x<COLS;x++){
    const idx=y*COLS+x;
    if(grid[idx]===1&&!canMove(x,y))restCount++;
  }
  if(restCount>COLS*ROWS*0.75)init();
}
const shadeCols=['#d9b25c','#c79a3f','#e8c878'];
function draw(){
  ctx.fillStyle='#101014';ctx.fillRect(0,0,cv.width,cv.height);
  ctx.strokeStyle='#456';ctx.strokeRect(OX,OY,COLS*CS,ROWS*CS);
  for(let y=0;y<ROWS;y++)for(let x=0;x<COLS;x++){
    const idx=y*COLS+x;
    if(grid[idx]===1){
      ctx.fillStyle=shadeCols[shade[idx]];
      ctx.fillRect(OX+x*CS,OY+y*CS,CS,CS);
    }
  }
  ctx.fillStyle='#eef';ctx.font='16px monospace';ctx.textAlign='left';
  ctx.fillText('Falling Sand - Cellular Automaton (150x100 grid)',OX,OY+ROWS*CS+28);
  ctx.font='13px monospace';ctx.fillStyle='#9cf';
  ctx.fillText('Resting cells: '+restCount,OX,OY+ROWS*CS+50);
  ctx.fillText('Step: '+stepCount,OX,OY+ROWS*CS+70);
}
function loop(){
  step();
  draw();
  requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
</script>
</body></html>
Claude Haiku 4.5frontier referenceOK
Show code
<!DOCTYPE html><html><head><title>r75</title></head><body><canvas id="c"></canvas><script>
let c=document.getElementById('c'),x=c.getContext('2d');c.width=800;c.height=600;
let W=150,H=100,g=Array(H).fill(0).map(()=>Array(W).fill(0));
let rest=0,step=0;
function draw(){
  x.fillStyle="#fff";x.fillRect(0,0,800,600);
  let s=Math.floor(750/W);
  // Pour sand
  if(Math.random()>0.7){g[0][Math.floor(Math.random()*W)]=1;}
  // Update
  let ng=Array(H).fill(0).map(()=>Array(W).fill(0));
  for(let i=0;i<H;i++)for(let j=0;j<W;j++){ng[i][j]=g[i][j];}
  for(let i=H-2;i>=0;i--){for(let j=0;j<W;j++){
    if(g[i][j]){
      if(i+1<H&&!g[i+1][j]){ng[i][j]=0;ng[i+1][j]=1;}
      else if(i+1<H&&j>0&&!g[i+1][j-1]){ng[i][j]=0;ng[i+1][j-1]=1;}
      else if(i+1<H&&j+1<W&&!g[i+1][j+1]){ng[i][j]=0;ng[i+1][j+1]=1;}
    }
  }}
  g=ng;
  // Count rest
  rest=0;
  for(let i=0;i<H;i++)for(let j=0;j<W;j++){if(g[i][j]&&(i===H-1||(i+1<H&&g[i+1][j])))rest++;}
  // Draw
  for(let i=0;i<H;i++)for(let j=0;j<W;j++){
    if(g[i][j]){x.fillStyle="#d4a574";x.fillRect(j*s,i*s,s,s);}
  }
  step++;
  x.fillStyle="#000";x.font="14px mono";x.fillText("Resting:"+rest+" Step:"+step,500,50);
  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
llama3.1:8b —9.1 sOK
qwen3-coder:30b —17.5 sOK
deepseek-r1:14b —167.8 sOK
qwen3.5:9b —18.3 sOK
gemma4:26b ——harness
mistral-small:24b —101.1 sOK
qwen3:14b —22.7 sOK
qwen3:8b ——harness
command-r:35b —131.0 sOK
deepseek-r1:32b —150.2 sOK
qwq:32b —150.1 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>Falling Sand — Cellular Automaton</title>
<style>
*{box-sizing:border-box}
body{margin:0;min-height:100vh;display:flex;align-items:center;justify-content:center;padding:1.2rem;
background:radial-gradient(1200px 700px at 50% -10%,#141a26,#080a10 70%);color:#e7ebf3;
font:16px/1.5 ui-sans-serif,system-ui,"Segoe UI",Roboto,sans-serif}
.wrap{width:min(980px,100%)}
h1{margin:0 0 .25rem;font-size:clamp(1.05rem,2.6vw,1.5rem);font-weight:650;letter-spacing:.01em}
p.sub{margin:0 0 1rem;color:#8b95a8;font-size:.85rem}
.stats{display:flex;flex-wrap:wrap;gap:.6rem;margin-bottom:.75rem}
.stat{flex:1 1 120px;background:#121722;border:1px solid #232a39;border-radius:12px;padding:.5rem .75rem}
.k{display:block;font-size:.66rem;letter-spacing:.14em;text-transform:uppercase;color:#7d879b}
.v{font:600 1.2rem/1.25 ui-monospace,SFMono-Regular,Menlo,monospace;color:#f3f6fb;font-variant-numeric:tabular-nums}
canvas{display:block;width:100%;aspect-ratio:3/2;background:#05070b;border:1px solid #232a39;
border-radius:12px;image-rendering:pixelated;box-shadow:0 18px 50px -22px #000}
</style>
</head>
<body>
<div class="wrap">
<h1>Falling Sand · 150 × 100 cell automaton</h1>
<p class="sub">Every step each grain moves one cell down, else down-left or down-right, else it rests.</p>
<div class="stats">
<div class="stat"><span class="k">Step</span><span class="v" id="eS">0</span></div>
<div class="stat"><span class="k">Resting cells</span><span class="v" id="eR">0</span></div>
<div class="stat"><span class="k">Grains</span><span class="v" id="eG">0</span></div>
<div class="stat"><span class="k">Run</span><span class="v" id="eN">0</span></div>
</div>
<canvas id="c" width="150" height="100"></canvas>
</div>
<script>
const W=150,H=100,N=W*H;
const cv=document.getElementById("c"),ctx=cv.getContext("2d");
const img=ctx.createImageData(W,H),buf=new Uint32Array(img.data.buffer);
const eS=document.getElementById("eS"),eR=document.getElementById("eR"),
      eG=document.getElementById("eG"),eN=document.getElementById("eN");
const grid=new Uint8Array(N),shade=new Uint8Array(N),rest=new Uint8Array(N),pal=new Uint32Array(256);
const BG=0xff0b0705;
let step=0,total=0,resting=0,run=0,src=[],emit=1,cap=0,idle=0,mov=0;
function hsl(h,s,l){s/=100;l/=100;const k=n=>(n+h/30)%12,a=s*Math.min(l,1-l),
 f=n=>Math.round(255*(l-a*Math.max(-1,Math.min(k(n)-3,9-k(n),1))));return[f(0),f(8),f(4)];}
function px(h,s,l){const c=hsl(h,s,l);return 4278190080|(c[2]<<16)|(c[1]<<8)|c[0];}
function reset(){
 grid.fill(0);shade.fill(0);rest.fill(0);
 step=0;total=0;resting=0;idle=0;run++;
 const hue=Math.random()*360;
 for(let i=0;i<256;i++)pal[i]=px((hue+i/11-11+360)%360,58+i/15,32+i/6.5);
 mov=px(hue,95,80);
 const k=1+(Math.random()*3|0);src=[];
 for(let i=0;i<k;i++)src.push(14+(((W-28)*(k===1?0.5:i/(k-1)))|0));
 emit=1+(Math.random()*3|0);
 cap=2400+(Math.random()*3400|0);
}
function tick(){
 if(total<cap)for(const x of src)for(let i=0;i<emit;i++){
  const p=Math.max(0,Math.min(W-1,x+(Math.random()*3|0)-1));
  if(!grid[p]){grid[p]=1;shade[p]=Math.random()*256|0;total++;}
 }
 const dir=step&1;
 for(let y=H-2;y>=0;y--)for(let i=0;i<W;i++){
  const x=dir?i:W-1-i,p=y*W+x,b=p+W;
  if(!grid[p])continue;
  let t=-1;
  if(!grid[b])t=b;
  else{
   const dl=x>0&&!grid[b-1],dr=x<W-1&&!grid[b+1];
   if(dl&&dr)t=Math.random()<0.5?b-1:b+1;else if(dl)t=b-1;else if(dr)t=b+1;
  }
  if(t>=0){grid[t]=1;shade[t]=shade[p];grid[p]=0;shade[p]=0;}
 }
 step++;
 let cnt=0;
 for(let p=0;p<N;p++){
  rest[p]=0;
  if(!grid[p])continue;
  const y=(p/W)|0,x=p-y*W,b=p+W;
  if(y===H-1||(grid[b]&&(x===0||grid[b-1])&&(x===W-1||grid[b+1]))){rest[p]=1;cnt++;}
 }
 resting=cnt;
 let blocked=true;
 for(const x of src)if(!grid[x])blocked=false;
 if(blocked)idle+=3;
 else if(total>=cap&&resting===total)idle+=2;
 else idle=0;
 if(idle>110)reset();
}
function draw(){
 buf.fill(BG);
 for(let p=0;p<N;p++)if(grid[p])buf[p]=rest[p]?pal[shade[p]]:mov;
 ctx.putImageData(img,0,0);
 eS.textContent=step.toLocaleString();
 eR.textContent=resting.toLocaleString();
 eG.textContent=total.toLocaleString();
 eN.textContent=run;
}
let last=0,acc=0;
function frame(t){
 requestAnimationFrame(frame);
 if(!last)last=t;
 acc+=Math.min(120,t-last);last=t;
 let k=0;
 while(acc>=16.6&&k<4){tick();acc-=16.6;k++;}
 draw();
}
reset();requestAnimationFrame(frame);
</script>
</body>
</html>