oneshotlm
Compare all models on this prompt →

Mandelbrot explorer · gpt-oss-safeguard-20b

Render the Mandelbrot set with a smooth color gradient on a full-screen canvas, with click-and-drag to pan and mouse-wheel to zoom.

⛨ sandboxed Open in new tab ↗
transcript · 4 messages
user

Render the Mandelbrot set with a smooth color gradient on a full-screen canvas, with click-and-drag to pan and mouse-wheel to zoom.

assistant
thinking
We need to produce a single file index.html that implements a Mandelbrot set renderer in JavaScript with a smooth gradient, full-screen canvas, interactive pan via click-drag, zoom via mouse wheel. No external resources. All CSS and JS inline. We need to write the file. Also ensure that we use correct HTML, CSS, JS. Let's design.

Goal: create canvas covering whole screen. Use requestAnimationFrame to render. Use a simple iterative calculation with maximum iterations. For smooth coloring, use normalized iteration count: use log of the escape count. We'll implement a color function: convert a value [0,1] to color via HSV to RGB mapping or using a gradient. We'll choose a simple palette: e.g., mapping to hues: 240 to 0 degrees (blue to red). Use formula: let t = Math.log(iter + 3 - Math.log(Math.log2(zabs)))/Math.log(maxIter); but simpler: use smooth iteration: iter + 1 - Math.log(Math.log(zabs)) / Math.log(2); but to keep simple. Use zabs = abs(z). We'll implement.

Interactivity: track mouse down, move, up for pan. Use transform: map screen coordinates to complex plane using center and scale. Start with center = [0,0] and scale = 4 (i.e., view width of 4). Then zoom in by scaling factor. Mouse wheel: change scale multiplicatively.

Implementation steps:

- HTML: <html><head> <style> body, canvas full-screen. </style></head> <body><canvas id="mandelbrot"></canvas> <script> ... </script></body></html>

In JS: get canvas, set size to window.innerWidth/Height; resize handler to adjust.

Define variables: centerX, centerY, scale; zoomFactor. For click drag: store isDragging, lastX, lastY. On mousedown: set isDragging true; store initial mouse pos. On mousemove if isDragging: compute delta, adjust center accordingly: centerX -= deltaX * scale / canvas.width; centerY -= deltaY * scale / canvas.height. On mouseup: set isDragging false. On wheel: event.preventDefault(); scale *= Math.pow(0.9, event.deltaY > 0 ? 1 : -1); or using scale *= Math.exp(event.deltaY * -0.001). Also update center to keep zoom around cursor? For simplicity, keep center fixed when scrolling? But better to zoom towards cursor. We can compute point under mouse: const rect = canvas.getBoundingClientRect(); const mx = (e.clientX - rect.left) / canvas.width; const my = (e.clientY - rect.top) / canvas.height; convert to complex coordinate: const x = centerX + (mx - 0.5) * scale; const y = centerY + (my - 0.5) * scale. Then adjust scale: newScale = scale * factor; Then adjust center to keep that point same after zoom: centerX = x - (mx - 0.5) * newScale; centerY = y - (my - 0.5) * newScale; but might be simpler.

Render loop: For each pixel, compute real/imag; iterate: z = 0; for iter < maxIter and abs(z) <= 2; compute z = z^2 + c. For smooth: if abs(z) > 2, compute mu = iter + 1 - Math.log(Math.log2(zabs)); let t = mu / maxIter. color = getColor(t); else t = 0. For color mapping, we can use HSL: hue = t * 360; saturation 1; lightness 0.5; convert to rgb via hslToRgb. We'll write function hslToRgb.

We need to set pixel data via ImageData. For performance, use typed array. Use for loops.

Potential performance: for large canvas may be heavy; but okay.

Let's produce code.

Also, add a small debounce for resize.

Ok let's write index.html content.

We'll produce it via write tool.
write index.html (3598 bytes)
toolResult

Successfully wrote 3598 bytes to index.html

assistant
thinking
We need to create index.html with Mandelbrot set and interaction. The code above is already written. Need to verify no external resources. It's fine. Might want to improve performance? But requirement just to build single file. Ensure it works. Let's run tests? Not possible here. The code seems okay. Let's provide final.

Here is the complete `index.html` that renders the Mandelbrot set with a smooth color gradient, supports click‑drag panning, and mouse‑wheel zooming. All CSS and JavaScript are embedded inline, with no external dependencies. ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Mandelbrot Explorer</title> <style> html, body { margin:0; height:100%; overflow:hidden; } canvas { display:block; width:100%; height:100%; } </style> </head> <body> <canvas id="mandelbrot"></canvas> <script> const canvas = document.getElementById('mandelbrot'); const ctx = canvas.getContext('2d'); let width, height; // Resize to fill viewport function resize(){ width = canvas.width = window.innerWidth; height = canvas.height = window.innerHeight; render(); } window.addEventListener('resize', resize); // Mandelbrot view parameters let centerX = -0.5, centerY = 0; let scale = 4; // View width in complex plane units const maxIter = 200; // Max iterations for escape time // Interaction state let isDragging = false; let dragStartX = 0, dragStartY = 0; let dragCenterX = 0, dragCenterY = 0; // Mouse drag to pan canvas.addEventListener('mousedown', e => { isDragging = true; dragStartX = e.clientX; dragStartY = e.clientY; dragCenterX = centerX; dragCenterY = centerY; }); canvas.addEventListener('mousemove', e => { if (!isDragging) return; const dx = e.clientX - dragStartX; const dy = e.clientY - dragStartY; centerX = dragCenterX - dx * scale / width; centerY = dragCenterY - dy * scale / height; render(); }); canvas.addEventListener('mouseup', () => { isDragging = false; }); canvas.addEventListener('mouseleave', () => { isDragging = false; }); // Mouse wheel to zoom, centered on cursor canvas.addEventListener('wheel', e => { e.preventDefault(); const rect = canvas.getBoundingClientRect(); const mx = (e.clientX - rect.left) / width; const my = (e.clientY - rect.top) / height; const zoom = Math.exp(-e.deltaY * 0.001); // smooth zoom factor // Recenter to keep pointer stable const x = centerX + (mx - 0.5) * scale; const y = centerY + (my - 0.5) * scale; centerX = x - (mx - 0.5) * scale * zoom; centerY = y - (my - 0.5) * scale * zoom; scale *= zoom; render(); }); // Convert HSL to RGB string function hslToRgb(h, s, l) { h = h % 360; if (h < 0) h += 360; h /= 360; const q = l < 0.5 ? l * (1 + s) : l + s - l * s; const p = 2 * l - q; const hueToRgb = t => { if (t < 0) t += 1; if (t > 1) t -= 1; if (t * 6 < 1) return p + (q - p) * 6 * t; if (t * 2 < 1) return q; if (t * 3 < 2) return p + (q - p) * (2 / 3 - t) * 6; return p; }; const r = hueToRgb(h + 1 / 3); const g = hueToRgb(h); const b = hueToRgb(h - 1 / 3); return `rgb(${Math.floor(r * 255)},${Math.floor(g * 255)},${Math.floor(b * 255)})`; } // Map normalized iteration count to color function colorValue(t) { // t in [0,1] => blue (240°) to red (0°) const hue = 240 * (1 - t); return hslToRgb(hue, 1, 0.5); } // Render the Mandelbrot set to the canvas function render() { const imgData = ctx.createImageData(width, height); const data = imgData.data; for (let py = 0; py < height; py++) { const imag = centerY + (py - height / 2) * scale / height; for (let px = 0; px < width; px++) { const real = centerX + (px - width / 2) * scale / width; let zr = 0, zi = 0, iter = 0; while (iter < maxIter && zr * zr + zi * zi <= 4) { const temp = zr * zr - zi * zi + real; zi = 2 * zr * zi + imag; zr = temp; iter++; } let t; if (iter === maxIter) { t = 0; // Inside set – black } else { // Smooth coloring const mod = Math.log(Math.log(zr * zr + zi * zi) / Math.log(4)) / Math.log(2); t = (iter + 1 - mod) / maxIter; } const color = colorValue(t); const [r, g, b] = color.match(/\d+/g).map(Number); const idx = (py * width + px) * 4; data[idx] = r; data[idx + 1] = g; data[idx + 2] = b; data[idx + 3] = 255; // alpha } } ctx.putImageData(imgData, 0, 0); } resize(); // Initial render </script> </body> </html> ``` Save this as `index.html` in your working directory, and it will open in any browser to display an interactive Mandelbrot explorer.

TAKE IT TO CODE

A single self-contained HTML file — copy it and open in any browser, or reuse the prompt with your own pi-agent run.

RUN

modelgpt-oss-safeguard-20b
vendorOpenAI
harnesspi-agent
generated2026-08-01

EVALUATION

3/5 partial

Mandelbrot renders with gradient; drag pans and wheel zooms, but colors are flat blue/green with little smooth gradient variety.

Vision grade · anthropic/claude-sonnet-5

MEASUREMENTS

Raw readings from the capture, not a verdict — the grade above is the only judgement. Percentages are how much of the screen changed; the measure under-reports sparse motion on a dark background.

idle motion0.0%
on click0.0%
on drag14.6%
on wheel6.8%
on enter + space0.0%
on arrow keys0.0%
on w/a/s/d0.0%
frame spread11.2 / 255
console errors0
js errors none

METRICS

runtime6.8s
tokens in3.8k
tokens out3.6k
cached2.0k
cost / run$0.0013