oneshotlm
Compare all models on this prompt →

Maze generator & solver · nex-n2-pro

Generate a random maze with the recursive-backtracker algorithm on a canvas, then animate an A-star or BFS solver finding the path from start to finish.

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

Generate a random maze with the recursive-backtracker algorithm on a canvas, then animate an A-star or BFS solver finding the path from start to finish.

assistant
thinking
We need answer to user. Need create single-page web app index.html in current directory. Need use tools. Need inspect cwd maybe. Need generate file. We need ensure no external resources. Single-page with canvas maze recursive backtracker and animate A* or BFS solver. Need maybe include controls? User asks generate random maze and animate solver. We can make nice app. Need write index.html. Need maybe current directory /tmp/ws. Let's inspect?
bash {"command":"pwd && ls -la","timeout":1000}
toolResult

/tmp/ws total 0 drwxr-sr-x. 2 node node 6 Aug 1 20:19 . drwxrwsrwx. 3 root node 16 Aug 1 20:19 ..

assistant
thinking
Need write index.html. Need craft self-contained. Requirements: random maze with recursive-backtracker algorithm on canvas, animate A-star or BFS solver finding path. Need maybe buttons Generate, Solve, speed, dimensions. Need robust.

Need think design. We need single file with CSS and JS inline. No external. Use canvas. Maze generated via recursive backtracker. Animate BFS maybe. Need include start/finish. Need path. Need maybe status.

Need ensure code works. Let's design.

HTML:
<!DOCTYPE html>
<html lang="en">
<head> meta, title. CSS body dark, container, canvas. controls.
<body>
<header h1 Maze Solver
<div class panel: canvas id mazeCanvas; status, progress.
<div controls: Generate, Solve, speed slider, size slider, maybe algorithm select BFS/A*
<script>
(() => {
const canvas = document.getElementById('mazeCanvas'), ctx = canvas.getContext('2d');
const cellSize default 22, cols 31 rows 21; Need odd? recursive backtracker can grid cells and walls between. We'll represent cells as x,y with walls [top,right,bottom,left]. Canvas dimensions = cols*cellSize, rows*cellSize. Generate maze:
function createMaze(cols, rows) {
 cells array rows*cols objects {x,y,walls:[true,true,true,true], visited:false}
 stack [cell0], visited count
 while stack length:
 current visited true
 unvisited neighbors in dirs
 if unvisited.length: choose random, remove walls current and next, push next
 else stack.pop()
 return cells
}
Need animate generation? User says generate random maze, not necessarily animate. Could show final. But perhaps animate? They ask "Generate random maze ... on a canvas, then animate solver". Could generate instantly. Maybe "Generate" button.

BFS solver:
start index 0, end index cols*rows -1. open queue [start]. visited set, parent Map. While queue not empty:
 dequeue idx, add to explored list. If end break. For each dir if no wall and not visited: mark visited, parent, enqueue.
Need animate BFS:
function solveBFS(maze, cols, rows) {
 let queue=[0], visited=new Set([0]), parent=new Map(), explored=[], done=false
 function step() {
   if queue.length ===0 { done=true; if end visited reconstruct}
   else {
      const idx = queue.shift()
      explored.push(idx)
      if idx === end { done=true; path = reconstruct }
      else for dirs...
   }
   draw(explored, path, queue)
   if !done requestAnimationFrame(step) or setTimeout based speed
 }
}
Need animate BFS cells. But if step too fast, use setTimeout. Use speed slider maybe 1-50 ms. Need display status.

Path reconstruction:
let path=[]; cur=end; while cur!==undefined; path.push(cur); cur=parent.get(cur); if cur==start? parent start undefined. Reverse.
draw:
clear background
draw visited/explored cells maybe light blue
draw queue frontier maybe yellow
draw path orange
draw walls.
Draw walls by for each cell draw line for each wall. Need avoid duplicate okay. Use lineWidth 2.
Start and finish squares green/red.
Need canvas high DPI scaling? We can set canvas.width = cols*cellSize*dpr? Simpler with CSS size. Need crisp. Use resizeCanvas function:
function setupCanvas() {
 const dpr=window.devicePixelRatio||1;
 canvas.width = cols*cellSize*dpr;
 canvas.height = rows*cellSize*dpr;
 canvas.style.width = `${cols*cellSize}px`;
 canvas.style.height = `${rows*cellSize}px`;
 ctx.setTransform(dpr,0,0,dpr,0,0);
}
draw uses CSS coordinate.

Controls:
Generate button: stop animation, generate maze, draw, status.
Solve button: if no maze generate. reset solved? solve.
New Maze button maybe Generate.
Size slider:
<input id="size" type="range" min="8" max="45" value="25">
Actually for cols/rows use same? Could choose "maze size" sets square cells. Maybe rows = cols? But canvas could be square. Need maybe odd? With grid cells no issue. But start to finish diagonal. Use square maybe 25. Canvas 550. Max 45 = 990 px maybe okay. We can set cell size fixed 18. Better:
size slider 8-45 value 25 => square grid. cellSize slider 8-28 value 18. Canvas width maybe 45*18=810. Good.
Algorithm select BFS/A*.
Speed slider 1-80 maybe delay.
Need if resize generate new maze automatically? Could update label and maybe generate. Simpler on size change generate.
Need maybe show "BFS" default. But user asked A-star or BFS. We can implement BFS and A*? Nice. But maybe no need. Yet implement algorithm select with BFS and A*. A* with Manhattan heuristic. Need animate A* perhaps. It may be more interesting. But BFS guarantee shortest in unweighted. A* more efficient. Need implement both maybe.

Need "random maze" recursive backtracker. Need "animate solver finding path from start to finish". We'll include BFS/A*.

Need code robust.

Potential issue A* in maze with perfect maze. Use priority queue. Implement min-heap or array sorted. For small grid fine. Need f, g, cameFrom, openSet, closedSet.
Pseudo:
function solveAStar() {
 const start=0, end=cols*rows-1;
 const open = [{idx:start, f:manhattan(start,end)}]; openSet = new Set([start]);
 const cameFrom = new Map();
 const g = new Map([[start,0]]);
 const closed = new Set();
 const explored = [];
 const path = [];
 let done=false;
 function step() {
   if (open.length === 0) { done=true; status='No path found'; draw; return; }
   open.sort((a,b)=>a.f-b.f || a.idx-b.idx);
   const current = open.shift(); const currentIdx=current.idx;
   if (!openSet.has(currentIdx)) continue; openSet.delete(currentIdx); closed.add(currentIdx); explored.push(currentIdx);
   if (currentIdx === end) { path = reconstruct(cameFrom,end); done=true; draw; status='Path found'; return; }
   for dirs if passable:
      const neighbor = ...
      if closed.has(neighbor) continue;
      const tentativeG = (g.get(currentIdx)||Infinity)+1;
      if (!openSet.has(neighbor) || tentativeG < (g.get(neighbor)||Infinity)) {
          cameFrom.set(neighbor,currentIdx);
          g.set(neighbor,tentativeG);
          const h = manhattan(neighbor,end);
          const f = tentativeG+h;
          if (!openSet.has(neighbor)) { open.push({idx:neighbor,f}); openSet.add(neighbor); } else { update f in open; }
      }
   draw(... open list, path)
   schedule
 }
}
Need A* if neighbor already in open with lower g update f. Use open.findIndex.
BFS:
function solveBFS() {
 queue = [0], visited = new Set([0]), parent = new Map(), explored = [], path = [];
 function step() {
   if queue.length===0: done true status no path; draw; return
   const current=queue.shift(); explored.push(current);
   if current===end: path=reconstruct(parent,end); done=true; status; draw; return
   for dirs:
      if !wall and !visited:
         visited.add(n); parent.set(n,current); queue.push(n)
   draw(explored, path, queue)
   schedule
 }
}
Need scheduling with speed. Avoid requestAnimationFrame? Use setTimeout. Need stop on generate. Have solverTimer.
function clearTimer() { if solverTimer) clearTimeout; }
function schedule() { if (!state.done) solverTimer=setTimeout(step, Number(speed.value));}
Need state object:
let cols=25, rows=25, cells=[], cellSize=18, start=0, end=0, isSolving=false, solved=false, explored=[], path=[], frontier=[];
Need draw receives optional.

Need wall removal:
const dirs = [
 {dx:0,dy:-1,wall:0,opposite:2,label:'top'},
 {dx:1,dy:0,wall:1,opposite:3},
 {dx:0,dy:1,wall:2,opposite:0},
 {dx:-1,dy:0,wall:3,opposite:1},
];
function removeWalls(a,b) { const dx=b.x-a.x; if dx===1 {a.walls[1]=false; b.walls[3]=false;} else if dx===-1 {a.walls[3]=false; b.walls[1]=false;} ... }
Need index = x + y*cols.

Draw:
function drawMaze(options={}) {
 ctx.clearRect(0,0,width,height);
 ctx.fillStyle = '#0b1020'; fillRect
 // visited/explored:
 for idx of explored: drawCell(idx, 'rgba(96,165,250,.45)');
 for idx of frontier: drawCell(idx, 'rgba(250,204,21,.35)');
 for idx of path: drawCell(idx, 'rgba(251,146,60,.75)');
 // cells maybe unvisited fill dark
 // walls:
 ctx.strokeStyle='#e2e8f0'; ctx.lineWidth=2; ctx.beginPath();
 for each cell:
   const x=cell.x*cellSize, y=cell.y*cellSize;
   if cell.walls[0] moveTo x,y lineTo x+cellSize,y...
 etc
 ctx.stroke()
 // start finish:
 draw rounded? Use fillRect with margin.
 // maybe current cell in generation? no.
}
Need drawCell fillRect with margin 1.
Need start/finish maybe after walls. Use fillRect margin.

Need status:
statusEl.textContent = 'Maze ready. Press Solve.'
progressEl maybe "Explored X / N". Need update.
Need controls:
<label>Size <input id=size type=range...><span id=sizeValue>25×25</span></label>
<label>Cell <input id=cellSize...><span id=cellValue>18px</span></label>
<label>Speed <input id=speed type=range min=5 max=120 value=45><span id=speedValue>45 ms</span></label>
<select id=algorithm><option value=bfs>BFS</option><option value=astar>A*</option></select>
<button id=generate>Generate maze</button><button id=solve>Solve</button><button id=reset>Solve view?</button maybe not.
Need "Generate" and "Solve".
Need if solve button while solving disabled.
Need keyboard? maybe not.

Need maybe "recursive backtracker" visible? maybe in subtitle.
Need ensure "random maze with recursive-backtracker algorithm on a canvas" Could include "Recursive backtracker" in UI.

Need maybe animate generation too? It says generate random maze with algorithm on canvas, then animate solver. It doesn't say generation must animate. But maybe more impressive to animate generation? However "then animate solver" means after generation. We can include generate animation? But "then animate solver" maybe okay. If generation animation plus solver maybe more complex. We can perhaps make generate instant but show maze. Could animate generation using recursive backtracker? User specifically algorithm, not necessarily animate. But maybe "Generate a random maze..." Maybe no need. But if we do animate generation, then after complete solve. However "then animate solver" maybe expects solver animation. We can include "Animate generation" checkbox? But not needed.

Need maybe if user opens file, it auto-generates and maybe auto-solves? The wording "Generate ... then animate ..." Could maybe auto-generate and start solving. But user can click. To satisfy, maybe on load generate random maze and start BFS automatically after small delay? But if they want see generation, yes. We can generate on load and solve automatically? The app can have buttons. The user asked to generate and animate solver; likely final artifact should demonstrate automatically. We can auto-generate and solve on load. But if page loads and animation runs, okay. Include "Generate" and "Solve" controls. Maybe auto start after 500ms. Good.

Need be careful with speed. Default speed 35ms, grid 25x25 => BFS 625 steps, 22s. Too long. Need default speed maybe 8ms or 12ms. But user can adjust. If auto-solve, default speed should be maybe 18ms -> 11s. Could be okay. But maybe "animate" should be visible. Default grid 21x21, cell 22 -> 441 steps, speed 25ms -> 11s. Hmm.
Maybe default size 21x21, cell 24, speed 12ms -> 5s. Good.
Set size range 8-45, default 21, cell 12-32 default 22, speed 0-100? slider min 0 max 120 value 18.
If auto-solve after generate, BFS 441 cells, 18ms = 8s. Good.

Need maybe A* path shorter maybe less explored. BFS explores all reachable (perfect maze all) until finish? BFS stops at finish so explores maybe large area. A* maybe fewer. Good.

Need implement "Generate" cancels solver and new random. "Solve" cancels current solver and starts. "Pause"? Could include pause/resume. Not necessary.

Need maybe "BFS/A*" both. If A* default? BFS simpler. User says A-star or BFS. We can default A* maybe. But BFS guarantee shortest and simpler. Maybe default BFS. UI algorithm select.

Need ensure no external resources. Good.

Need maybe use canvas accessible? Could add aria-label.

Need code exact. Need maybe use <script> strict. Let's write file.
write /tmp/ws/index.html (22848 bytes)
toolResult

Successfully wrote 22848 bytes to /tmp/ws/index.html

assistant
thinking
Need verify file present maybe maybe use bash ls. Need maybe check HTML syntax? Could use grep? Need maybe no external resources. Need maybe test with node? Browser only. Could run maybe python http? But not needed. Need maybe inspect maybe there is issue with canvas.roundRect not supported in older browsers? Modern. Could avoid if want. But okay. However maybe ctx.roundRect not supported in some. Most modern. Could implement fallback? Since fully sandboxed. Better robust. We can replace drawMarker with manual roundedRect function? Since user likely modern. But for compatibility, implement custom rounded rect. The file uses ctx.roundRect; not all browsers. Could be okay but maybe avoid. We can edit. Also maybe canvas.width/height set in CSS coordinate. ctx.setTransform(dpr...). But draw uses canvas.width? clearRect with canvas.width in transformed coordinates? Wait important: after ctx.setTransform(dpr,...), canvas.width is physical pixels, but coordinate system is CSS pixels. clearRect(0,0,canvas.width,canvas.height) will clear dpr*physical area, more than enough. fillRect etc okay. But in draw, clearRect uses canvas.width and height, not cols*cellSize; after transform, clearRect clears dpr*physical area. Fine. But if canvas.width = cols*cellSize*dpr, then clearRect clears 2x area. Fine.

Potential issue regenerate on size input fires many times, generating on each input. Fine.

Potential issue auto start solving while generateBtn disabled? generateMaze sets generating? In regenerate: setStatus, generateMaze; generateMaze resets solved and draw, then regenerate set status ready. setTimeout startSolving. Good.

Potential issue stopSolving status uses "Stopped..." false but dot removed. Fine.

Potential issue A* frontier duplicates if update openList with lower f but openSet already has. Good.

Potential issue BFS finalPath includes start/finish. Good.

Potential issue A* currentEntry may be stale if openList contains duplicate? updateOpenList prevents duplicates. Good.

Potential issue A* openSet and openList: if openSet has current, shift; if current stale not in openSet skip. But openList only one per open set. Good.

Potential issue BFS explores current before checking if finish. It pushes finish to explored then final path. Good.

Potential issue cellSize slider regenerate on every input; if solver running, regenerate doesn't stop solving? It calls clearSolverTimer and solving=false but doesn't reset solveBtn disabled? It does. Good. But if A* step scheduled already? clear. Good.

Potential issue sizeInput input while solve running: regenerate -> solving false; startSolving auto? no.

Potential issue updateLabels called before size etc defined? yes after.

Potential issue if algorithmSelect disabled while solving and size input? disabled no.

Potential issue finalPath drawn over walls, but walls drawn after path, so path is under walls? Wait draw order: fills explored/frontier/path, then draws walls on top, then markers. So path is visible in cells but walls overlay. Good.

Potential issue A* final path may not be shortest? In perfect maze, A* with Manhattan admissible. Good.

Potential issue "recursive-backtracker" hyphen? Text says recursive-backtracker. Good.

Need maybe maybe use "recursive backtracking" in subtitle. Fine.

Need maybe maybe user only asked "Generate..." not ask for explanation. We can final concise: created index.html. But maybe need mention features. Need ensure index.html present. Could run ls.
bash {"command":"ls -l /tmp/ws/index.html","timeout":1000}
toolResult

-rw-r--r--. 1 node node 22860 Aug 1 20:21 /tmp/ws/index.html

assistant
thinking

Created `/tmp/ws/index.html`. It’s a self-contained single-page canvas app with: - Random maze generation using recursive backtracking - Animated BFS solver by default - Optional A* solver - Generate / Solve / Stop controls - Adjustable maze size, cell size, and animation speed - No external resources, CDNs, or network requests

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

modelnex-n2-pro
vendorNex AGI
harnesspi-agent
generated2026-08-01

EVALUATION

4/5 working

Maze generation and BFS solving animate automatically; solved path shown, but click/drag/wheel/arrow/wasd don't trigger new maze or resolve.

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 motion11.2%
on click0.0%
on drag0.0%
on wheel0.0%
on enter + space27.8%
on arrow keys0.0%
on w/a/s/d0.0%
frame spread38.6 / 255
console errors0
js errors none

METRICS

runtime81.3s
tokens in11k
tokens out11k
cached18k
cost / run$0.0143