OverviewCode › R88
Code · blind round

R88 · L-system tree growing in wind

blind round 4/8 local models answered

Answers below are anonymized and shuffled. Read, judge, pick a favourite — then scroll down and reveal the models.

The field: deepseek-r1:14b · gemma4:26b · llama3.1:8b · mistral-small:24b · qwen3-coder:30b · qwen3:14b · qwen3:8b · qwen3.5:9b — listed alphabetically, which is not the order of the cards below.

2 of the 8 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. Which ones, and why, is spelled out in the reveal.

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 grows a fractal tree from an L-system on a <canvas>: expand a rewriting rule over several generations, then draw the branch structure so the tree appears branch by branch rather than all at once, and once it is complete let it sway in a wind that changes strength over time. Show the generation depth and the number of branches. 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 — blind

Local models (Brain cluster) — identical prompt, anonymized order
MODEL Adeepseek-r1:14bERRBLANKFORMAT
Show code
```html
<!DOCTYPE html>
<html><head><style>canvas{position:fixed; margin:0 auto;top:50vh;left:50%;transform:translate(-50%, -50%)}.info{position:fixed;top:20px;right:20px;color:#fff;font-family:sans-serif}</style></head><body>
<canvas id=c width=600 height=800></canvas>
<div class="info" id=i>Gen: 0, Branches: 0</div>
<script>
let c=document.getElementById('c'), ctx=c.getContext('2d'), w=c.width, h=c.height;
let depth=5, branches=0, angle=90, len=100, wind=0;
function generateLSys(depth){return depth>0 ? generateLSys(depth-1).replace(/X/g,Y+X).replace(/F/g,F+F) : 'X';}
function parse(s){return s.split('').map(c=>c=='+'?{t:'angle',val:2}:c=='-'?{t:'angle',val:-2}:c=='Y'?{t:'store'}:{t:'line',x:1}))}
function draw(cmds,x,y,a,l){cmds.forEach(c=>{
  ctx.save();
  if(c.t=='line'){ctx.beginPath();ctx.moveTo(x,y);let nx=x+l*Math.cos(a), ny=y+l*Math.sin(a);ctx.lineTo(nx,ny);ctx.strokeStyle='#fff';ctx.lineWidth=2;ctx.stroke();}
  else if(c.t=='angle') a +=c.val * Math.PI/180;
});
}
function animate(){
  ctx.fillStyle='rgba(0,0,0,.3)';ctx.fillRect(0,0,w,h);
  let s=generateLSys(depth), cmds=parse(s.split('')));
  branches=cmds.filter(c=>c.t=='line').length;
  ctx.translate(w/2,h/4);angle=Math.PI/2;len=150;
  cmds.forEach((cmd,i)=>{if(i%3==0)ctx.beginPath();draw(cmd,i?0:0,0,angle,len)});
  wind=(Date.now()/100)%360;
  cmds.forEach(c=>c.t=='line' && c.x && (len=80/(c.x+2)));
  cmds.forEach((cmd,i)=>{if(cmd.t=='line') {let d=i%4; ctx.translate(w/2,h/4);}});
  document.getElementById('i').textContent=`Gen: ${depth}, Branches: ${branches}`;
  requestAnimationFrame(animate);
}
ctx.fillStyle='#000';animate();
</script>
</body></html>
```
MODEL Bqwen3:14bOKLIMFORMAT
Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>L-System Fractal Tree</title>
    <style>body {margin:0;overflow:hidden;background:#111;}canvas {display:block;}</style>
</head>
<body>
<canvas id="treeCanvas"></canvas>
<script>
(function() {
    const canvas = document.getElementById('treeCanvas');
    const ctx = canvas.getContext('2d');
    let W, H;

    // System State Variables
    let currentGeneration = 0;
    let maxGenerations = 6;
    let lSystemRules = {};
    let axiom = "";
    let sequence = "";
    let branchCount = 0;
    let isDrawingPhase = true;
    let drawingStep = 0;
    let currentBranch = []; // Stores segment information for the next draw step

    // Wind Simulation Variables (for stabilization after growth)
    let windStrength = 0.1;
    let timeOffset = Math.random() * 2 * Math.PI;
    const WIND_SPEED = 0.03;

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

    // --- L-System Setup and Generation ---

    function setupLSystem() {
        lSystemRules = {
            'F': 'FF+[+F-F-F]-[-F-F]', // A common fractal rule (e.g., Bush/Dragon)
        };
        axiom = "F";
        maxGenerations = 6;
        currentGeneration = 0;

        sequence = axiom;
        for (let i = 0; i < maxGenerations; i++) {
            let nextSequence = "";
            for (const char of sequence) {
                nextSequence += lSystemRules[char] || char;
            }
            sequence = nextSequence;
            currentGeneration++;
        }
    }

    function parseSequence(seq) {
        branchCount = 0;
        let stack = [];
        const segments = []; // Stores the path for drawing: [{x, y}, angle, length]

        // Start position (bottom center)
        let x = W / 2;
        let y = H - 50;
        let currentAngle = Math.PI * (-Math.PI / 16); // Pointing up slightly

        for (const char of seq) {
            if (char === 'F') {
                // Move forward and record segment
                let newX = x + Math.cos(currentAngle) * 2;
                let newY = y - Math.sin(currentAngle) * 2; // Y is inverted for canvas
                segments.push({ start: {x, y}, end: {x: newX, y: newY}, angle: currentAngle });
                x = newX;
                y = newY;
            } else if (char === '+') {
                currentAngle += Math.PI / 6; // Turn right
            } else if (char === '-') {
                currentAngle -= Math.PI / 6; // Turn left
            } else if (char === '[') {
                // Push state: [x, y, angle]
                stack.push({ x: x, y: y, a: currentAngle });
            } else if (char === ']') {
                // Pop state
                const state = stack.pop();
                if (state) {
                    x = state.x;
                    y = state.y;
                    currentAngle = state.a;
                }
            }
        }
        return segments;
    }

    // --- Drawing and Animation Logic ---

    let pathSegments = []; // The full list of segment data

    function drawTree(segments) {
        ctx.clearRect(0, 0, W, H);
        ctx.save();
        ctx.strokeStyle = '#532c18';
        ctx.lineCap = 'round';
        let currentDepth = 0;

        for (const segment of segments) {
            // Draw the segment
            ctx.beginPath();
            ctx.moveTo(segment.start.x, segment.start.y);
            ctx.lineTo(segment.end.x, segment.end.y);
            ctx.stroke();

            // Simple depth scaling/color change (optional)
        }
        ctx.restore();
    }


    function stepAnimation() {
        if (!isDrawingPhase && drawingStep === 0) {
            // Phase 2: Wind Simulation (Continuous animation)
            animationLoop(true);
            return;
        }

        if (drawingStep < pathSegments.length) {
            // Phase 1: Step-by-step Drawing
            const segment = pathSegments[drawingStep];

            // Calculate current wind influence (Sine wave based on time/progress)
            const t = performance.now() / 500;
            let swayFactor = Math.sin(t * WIND_SPEED + timeOffset);
            let adjustedAngle = segment.angle + swayFactor * 0.1;

            // Apply wind deviation to the drawing path (only noticeable on later, thinner branches)
            let startX = segment.start.x;
            let startY = segment.start.y;
            let endX = segment.end.x + Math.cos(adjustedAngle - segment.angle) * 5 * swayFactor;
            let endY = segment.end.y - Math.sin(adjustedAngle - segment.angle) * 5 * swayFactor;

            // Redraw the canvas, drawing only up to the current step
            ctx.clearRect(0, 0, W, H);
            ctx.save();
            ctx.strokeStyle = '#532c18';
            ctx.lineCap = 'round';

            for (let i = 0; i <= drawingStep; i++) {
                const s = pathSegments[i];
                // Re-simulate the winding effect for previous steps slightly, making it look continuous
                ctx.beginPath();
                ctx.moveTo(s.start.x, s.start.y);
                ctx.lineTo(s.end.x * (1 + 0.05 * Math.sin((i / pathSegments.length) * 2)) , s.end.y);
                ctx.stroke();
            }
            ctx.restore();

            drawingStep++;
        } else {
            // Phase End: Drawing Complete, transition to wind phase
            isDrawingPhase = false;
            drawingStep = 0; // Reset step counter for continuous loop
            animationLoop(true);
            return;
        }

        requestAnimationFrame(stepAnimation);
    }

    function animationLoop(continuous) {
        ctx.clearRect(0, 0, W, H);
        if (!isDrawingPhase && continuous) {
             // Wind simulation redraw logic (re-draw the full path with wind effect)
            ctx.save();
            ctx.strokeStyle = '#532c18';
            ctx.lineCap = 'round';

            const t = performance.now() / 500;
            let currentX = W/2;
            let currentY = H-50;
            let stack = [];
            let angle = Math.PI * (-Math.PI / 16);

            // Re-execute the parsing logic to draw the full tree structure every frame, applying wind deviation
            for (const char of sequence) {
                if (char === 'F') {
                    let sinAngle = Math.sin(angle + t * WIND_SPEED * 0.5);
                    let cosAngle = Math.cos(angle + t * WIND_SPEED * 0.5);

                    let newX = currentX + cosAngle * 2;
                    let newY = currentY - sinAngle * 2;

                    ctx.beginPath();
                    ctx.moveTo(currentX, currentY);
                    ctx.lineTo(newX, newY);
                    ctx.stroke();

                    currentX = newX;
                    currentY = newY;
                } else if (char === '+') {
                    angle += Math.PI / 6;
                } else if (char === '-') {
                    angle -= Math.PI / 6;
                } else if (char === '[') {
                    stack.push({ x: currentX, y: currentY, a: angle });
                } else if (char === ']') {
                    const state = stack.pop();
                    if (state) {
                        currentX = state.x;
                        currentY = state.y;
                        angle = state.a;
                    }
                }
            }

        }
        requestAnimationFrame(() => animationLoop(continuous));
    }


    function startSystem() {
        // 1. Setup L-system and generate sequence
        setupLSystem();

        // 2. Parse the sequence into drawable segments (for step-by-step drawing)
        pathSegments = parseSequence(sequence);

        // 3. Start Animation
        isDrawingPhase = true;
        drawingStep = 0;
        requestAnimationFrame(stepAnimation);
    }

    startSystem();
})();
</script>
</body>
</html>
```
MODEL Cqwen3-coder:30bERRBLANKFORMAT
Show code
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>LSystem Tree Growth</title>
    <style>body{margin:0;overflow:hidden;background:#111}canvas{display:block}</style>
</head>
<body>
<canvas id="treeCanvas"></canvas>
<script>
const canvas = document.getElementById('treeCanvas');
const ctx = canvas.getContext('2d');

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

let state = {
    maxGenerations: 8,
    currentGeneration: 0,
    systemRules: [],
    axiom: "",
    string: ""
};

function initLSystem() {
    // Basic rules for a fractal tree structure (e.g., Plant/Bush)
    state.systemRules = ["F", "FF+", "F-[-F+F]+[-F-F]"]; 
    state.axiom = "F";
    state.string = state.axiom;
}

function generateNextString() {
    let newString = "";
    for (let char of state.string) {
        if (char === 'F') { // Simple rule: F expands to a sequence
            newString += state.systemRules[0]; 
        } else if (char === '+' || char === '-' || char === '[' || char === ']') {
             // Pass through drawing characters
            newString += char;
        } else {
            newString += char;
        }
    }
    state.string = newString;
}

function drawTree(str, isWindPhase) {
    ctx.clearRect(0, 0);
    ctx.save();
    ctx.translate(canvas.width / 2, canvas.height);
    ctx.rotate(Math.PI / 2); // Start pointing up

    // Wind variable (time-dependent offset)
    let windOffset = isWindPhase ? Math.sin(Date.now() * 0.001) * 0.3 : 0;

    const stack = [];
    let x = 0;
    let y = 0;
    ctx.strokeStyle = '#4CAF50';
    ctx.lineWidth = 1;

    for (let i = 0; i < str.length; i++) {
        let char = str[i];

        if (char === 'F') {
            // Calculate current drawing position considering wind
            const effectiveX = x + Math.sin(y * 0.1) * windOffset;
            const effectiveY = y;

            ctx.beginPath();
            ctx.moveTo(effectiveX, effectiveY);
            let newY = effectiveY - 1; // Step down by 1 unit
            
            // Draw the segment
            ctx.lineTo(effectiveX + Math.sin((effectiveY - newY) * 0.1) * windOffset * 0.5, effectiveY - 1);
            ctx.stroke();

            x = effectiveX;
            y -= 1; // Move down (or up in canvas coords due to initial rotation)
        } else if (char === '+') {
            const angleChange = Math.PI / 4;
            ctx.rotate(angleChange);
        } else if (char === '-') {
            const angleChange = -Math.PI / 4;
            ctx.rotate(angleChange);
        } else if (char === '[') {
            stack.push({ x: x, y: y, rotation: ctx.getTransform().a }); // Save state 
        } else if (char === ']') {
            const saved = stack.pop();
            if (saved) {
                ctx.setTransform(1, 0, 0, 1, saved.x, saved.y);
                // Restore previous rotation and position
                ctx.rotate(0); 
                ctx.translate(canvas.width / 2, canvas.height);
            }
        } else {
            continue;
        }
    }
    ctx.restore();
}

function updateStats() {
    const depth = state.currentGeneration;
    const branches = Math.max(1, parseInt(state.string.split(/[\+\-]/).join('').length) / 20); // Rough estimate
    document.title = `Gen: ${depth}/${state.maxGenerations} | Branches: ${branches}`;
}

function loop(time) {
    if (state.currentGeneration <= state.maxGenerations) {
        // --- GROWTH PHASE ---
        const currentString = state.string;
        drawTree(currentString, false); 
        updateStats();

        if (state.currentGeneration < state.maxGenerations) {
            generateNextString();
            state.currentGeneration++;
            requestAnimationFrame(loop);
        } else {
            // --- WIND PHASE (Complete) ---
            console.log("Growth Complete. Entering Wind Phase.");
            state.isGrowing = false; 
            animateWind(time);
        }
    } else {
        // Keep running wind animation if it was already in progress
        if (!state.isGrowing && typeof animateWind === 'function') {
             requestAnimationFrame(loop);
        }
    }
}

let lastTime = 0;
const WIND_SPEED = 0.0015;

function animateWind(time) {
    // Redraw the tree structure using a continuous time input for wind offset
    drawTree(state.string, true); 
    requestAnimationFrame(() => {
        setTimeout(() => requestAnimationFrame(animateWind), 16); // ~60 FPS loop
    });
}

document.addEventListener('DOMContentLoaded', () => {
    initLSystem();
    // Start the process by setting current state and calling the loop
    state.isGrowing = true;
    requestAnimationFrame(loop);
});
</script>
</body>
</html>
```
MODEL Dqwen3:8bDNF
No usable answer reached the harness (ERR). Counted as a did-not-finish.
MODEL Ellama3.1:8bDNF
No usable answer reached the harness (TIMEOUT). Counted as a did-not-finish.
No usable answer reached the harness (TIMEOUT). Counted as a did-not-finish.
MODEL Gqwen3.5:9bERRBLANKLIMFORMAT
Show code
```html
<!DOCTYPE html>
<html><head><title>L-System Tree</title></head><style>body{margin:0;overflow:hidden;background:#111}{canvas{display:block}}#status{position:absolute;top:10px;left:10px;color:#ccc;font-family:monospace;padding:5px;background:#000b1133;border-radius:5px}</style><body><canvas id="treeCanvas"></canvas><div id="status">Generating...</div><script>
const canvas = document.getElementById('treeCanvas');
const ctx = canvas.getContext('2d');
let W, H;
function resize() {W=canvas.width=window.innerWidth;H=canvas.height=window.innerHeight;ctx.fillStyle='#000';ctx.fillRect(0,0,W,H); }
window.addEventListener('resize',resize);
resize();

const L_RULES = ['F', 'FF+[+F%-]']; // A classic fractal rule
let currentString = '';
let generation = 0;
let maxGenerations = 6;
let branchesDrawn = 0;
let isBuilding = true;
let animationTime = 0;

struct State {
    x: number, y: number, angle: number, length: number, stack: string[]
}

function initializeSystem() {
    currentString = L_RULES[0];
    generation = 0;
    branchesDrawn = 0;
    isBuilding = true;
    animationTime = 0;
    document.getElementById('status').innerHTML = `Generation: ${generation}/6 | Branches: 0`;
}

function expand() {
    if (generation >= maxGenerations) return false;
    currentString = "";
    for (const char of currentString) {
        if (char === 'F') { // Simple rewrite for this example
            currentString += L_RULES[1].replace(/[+%-]/g, '').split('').join(''); 
        } else if (L_RULES.includes(char)) {
             currentString = char;
        }
    }
    generation++;
    document.getElementById('status').innerHTML = `Generation: ${generation}/${maxGenerations} | Branches: ${branchesDrawn}`;

    if (generation < maxGenerations) {
        requestAnimationFrame(buildTree);
    } else {
        setTimeout(() => {
            isBuilding = false;
            document.getElementById('status').innerHTML = `Complete! Total Generations: ${generation}. Swaying...`;
            animateWind();
        }, 100);
    }
    return true;
}

function drawBranch(s) {
    const state = [];
    let p = { x: W/2, y: H-50 };
    let angle = -Math.PI / 2;
    state.push({...p, angle, length: 1}); // Initial state (root)

    for (let i = 0; i < s.length; i++) {
        const char = s[i];
        if (char === 'F') {
            const nextP = { x: p.x + Math.cos(angle) * p.length, y: p.y + Math.sin(angle) * p.length };
            p = nextP;
            ctx.strokeStyle = '#1a3300';
            ctx.lineWidth = 2;
            ctx.beginPath();
            ctx.moveTo(state[state.length - 1].x, state[state.length - 1].y);
            ctx.lineTo(p.x, p.y);
            ctx.stroke();

        } else if (char === '+') {
            // Increase angle (right)
            angle += Math.PI / 4;
        } else if (char === '-') {
            // Decrease angle (left)
            angle -= Math.PI / 4;
        } else if (char === '[') {
            state.push({...p, angle: angle, length: p.length}); // Push state
        } else if (char === ']') {
            const lastState = state.pop();
            p = {...lastState};
            angle = lastState.angle;
            // Recalculate position based on the popped state's origin
            state[state.length - 1].x = p.x + Math.cos(angle) * 0.5; // Simple correction for segment start
            state[state.length - 1].y = p.y + Math.sin(angle) * 0.5;

        } else if (char === '|') { 
             // This character is used as a marker for new segments/branches, handled by structure instead of simple append
        }
    }
}

let segments_in_progress = [];

function buildTree() {
    if (!isBuilding) return;

    const chars = currentString.split('');
    segments_in_progress = []; 

    // Simplified interpretation focusing on segment drawing logic rather than complex stack traversal for size constraints
    // We iterate through the string and store potential branches
    let p = { x: W/2, y: H-50 };
    let angle = -Math.PI / 2;
    const segments = [];

    for (let i = 0; i < chars.length; i++) {
        const char = chars[i];
        if (char === 'F') {
            segments.push({x: p.x, y: p.y, length: 10}); // Store start point and basic segment data
            p.x += Math.cos(angle) * 10;
            p.y += Math.sin(angle) * 10;
        } else if (char === '+') {
            angle += Math.PI / 4;
        } else if (char === '-') {
            angle -= Math.PI / 4;
        } else if (char === '[') {
             // In a real L-system, this would push the full state. Here we just track depth for branch counting.
             segments_in_progress.push(true);
        } else if (char === ']') {
             segments_in_progress.pop();
        }
    }

    if (!segments[0]) { // Initial draw phase needs to happen once per generation step
         ctx.clearRect(0, 0, W, H);
         ctx.save();
         // Simple drawing of the current state's path (approximation)
         let x = W/2; let y = H-50; let a = -Math.PI / 2;
         ctx.strokeStyle = '#1a3300';
         ctx.lineWidth = 4 * (generation > 0 ? 0.8 : 1);
         ctx.beginPath();
         ctx.moveTo(x, y);

         for(let i=0; i<chars.length; i++){
             const char = chars[i];
             if(char === 'F'){
                 x += Math.cos(a) * 10;
                 y += Math.sin(a) * 10;
                 ctx.lineTo(x, y);
             } else if (char === '+') { a += Math.PI/4; } 
             else if (char === '-') { a -= Math.PI/4; }
         }
         ctx.stroke();
    }

    // Increment branches drawn based on the complexity of the current structure
    branchesDrawn = Math.min(100 + generation * 5, 300);
}


function animateWind() {
    let t = animationTime;
    const windStrength = 0.02 + 0.01 * Math.sin(t / 400);

    ctx.clearRect(0, 0, W, H);
    ctx.save();
    ctx.translate(W/2, H - 150); // Base anchor point
    ctx.rotate(-Math.PI / 2); // Start pointing up

    // Recursive function to draw and apply wind physics
    function drawAndSway(segment, angleOffset, scale) {
        if (scale < 0.1) return;

        const length = segment.length * scale;
        ctx.strokeStyle = `rgba(26, 51, 0, ${scale*0.8 + 0.2})`;
        ctx.lineWidth = Math.max(1, 3 * scale);
        
        // Apply wind influence (horizontal force proportional to time and scale)
        const swayX = length * Math.sin(angleOffset * 0.5 + t / 400 * windStrength);
        const swayY = length * Math.cos(angleOffset * 0.5 + t / 400 * windStrength);

        ctx.beginPath();
        ctx.moveTo(0, 0);
        ctx.lineTo(swayX, swayY);
        ctx.stroke();

        // Recursive calls (simplified tree branching structure)
        if (segment.branches && segment.branches.length > 0) {
            for (let i = 0; i < segment.branches.length; i++) {
                const b = segment.branches[i];
                drawAndSway(b, angleOffset + b.angle * scale / Math.max(1, scale), scale * 0.6);
            }
        }
    }

    // Since we don't store the full tree structure for physics in this size-constrained version, 
    // we just draw a simplified visualization based on generation count.
    const simSegments = [];
    for(let i=0; i<generation; i++){
        simSegments.push({length: Math.pow(10, -i*0.2), branches: Array(Math.min(5, 3+i)).fill({})});
    }

    drawAndSway(simSegments[0] || {length: 10}, 0, 1);
    ctx.restore();


    animationTime += 16; // Assuming ~60fps frame rate
    requestAnimationFrame(animateWind);
}


function run() {
    initializeSystem();
    // Step-by-step building animation loop
    const buildTree = () => {
        if (generation < maxGenerations) {
            buildTree();
        } else {
            setTimeout(() => {
                isBuilding = false;
                animateWind();
            }, 100);
        }
    };
    requestAnimationFrame(buildTree);
}

run();
</script></body></html>
```
MODEL Hgemma4:26bDNF
No usable answer reached the harness (TIMEOUT). Counted as a did-not-finish.
Reveal the models— compare the answers first, then open. Names, blind scores and latencies are hidden until you do.

Who wrote what

Blind labelModelBlind scoreLatencyStatus
MODEL A deepseek-r1:14b 15.6 sOK
MODEL B qwen3:14b 35.0 sOK
MODEL C qwen3-coder:30b 23.7 sOK
MODEL D qwen3:8b harness
MODEL E llama3.1:8b DNF
MODEL F mistral-small:24b DNF
MODEL G qwen3.5:9b 68.4 sOK
MODEL H gemma4:26b harness