Maze Makers: Modified Cylog Maze Program for Tabbs Feature lazarus / 39-Graphics ---------------------------------------------------------------------- Boleeman · 2025-12-23 09:40 Now looking at Lazes Maze Sample Program. Works well at quickly creating large mazes, but the pathfinding for the solution is incredibly slow. Previously: Depth First Search Maze Maker Hooray. Finally I have made a maze maker. Kinda found it really difficult to follow the logic, but eventually worked it out. Uses an agent (Ellipse) to work out the maze path. Enjoy. ---------------------------------------------------------------------- avra · 2025-12-23 11:08 Congratulations!  Here are some more mazes for your inspiration with different geometries, shapes and algorithms. I intentionally left some with solution path, debug info, and false entrances shown. ---------------------------------------------------------------------- Dzandaa · 2025-12-23 11:45 Hi Eddie, Welcome back to Graphics and Lazarus Here is a maze I wrote in 2024 for fun, fixed size Merry Christmas and happy new-year to all the fans of Lazarus. B-> ---------------------------------------------------------------------- Boleeman · 2025-12-23 22:40 After recently installing the new version of Bgrabmp I noticed bgragames at https://github.com/bgrabitmap/bgragames After installing the bgragames package I compiled the sample maze game from the folder bgragames\test\game_maze. It's a ball bouncing maze, with the ball controlled by either the mouse or the arrow keys. ---------------------------------------------------------------------- Thaddy · 2025-12-25 15:21 At least the image is not a maze, since a maze has a solution. Actually at least two: always go left or always go right with only one exit given one entry. Let's see what AI does, CoPilot (basically ChatGTP) and DeepSeek: Copilot:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program MazeCopilot; {$mode objfpc}{$H+} uses  SysUtils; type  TDirection = (dirUp, dirRight, dirDown, dirLeft);  TCell = record    Visited: Boolean;    WallTop: Boolean;    WallRight: Boolean;    WallBottom: Boolean;    WallLeft: Boolean;  end;   TMaze = array of array of TCell; const  MazeWidth  = 25;  // number of cells horizontally  MazeHeight = 15;  // number of cells vertically var  Maze: TMaze; function InBounds(x, y: Integer): Boolean;begin  Result := (x >= 0) and (x < MazeWidth) and (y >= 0) and (y < MazeHeight);end; procedure InitMaze;var  x, y: Integer;begin  SetLength(Maze, MazeWidth, MazeHeight);  for x := 0 to MazeWidth - 1 do    for y := 0 to MazeHeight - 1 do    begin      Maze[x, y].Visited    := False;      Maze[x, y].WallTop    := True;      Maze[x, y].WallRight  := True;      Maze[x, y].WallBottom := True;      Maze[x, y].WallLeft   := True;    end;end; procedure RemoveWall(x, y: Integer; dir: TDirection);begin  case dir of    dirUp:      begin      Maze[x, y].WallTop := False;        if y > 0 then          Maze[x, y - 1].WallBottom := False;      end;    dirRight:      begin        Maze[x, y].WallRight := False;        if x < MazeWidth - 1 then        Maze[x + 1, y].WallLeft := False;      end;    dirDown:      begin      Maze[x, y].WallBottom := False;        if y < MazeHeight - 1 then          Maze[x, y + 1].WallTop := False;      end;    dirLeft:    begin        Maze[x, y].WallLeft := False;        if x > 0 then        Maze[x - 1, y].WallRight := False;      end;  end;end; procedure ShuffleDirections(var dirs: array of TDirection);var  i, j: Integer;  tmp: TDirection;begin  for i := High(dirs) downto Low(dirs) + 1 do  begin    j := Random(i + 1);    tmp       := dirs[i];    dirs[i]   := dirs[j];    dirs[j]   := tmp;  end;end; procedure CarveFrom(x, y: Integer);var  dirs: array[0..3] of TDirection;  i, nx, ny: Integer;begin  Maze[x, y].Visited := True;   dirs[0] := dirUp;  dirs[1] := dirRight;  dirs[2] := dirDown;  dirs[3] := dirLeft;  ShuffleDirections(dirs);   for i := 0 to 3 do  begin    nx := x;    ny := y;    case dirs[i] of      dirUp:    Dec(ny);      dirRight: Inc(nx);      dirDown:  Inc(ny);      dirLeft:  Dec(nx);    end;     if InBounds(nx, ny) and (not Maze[nx, ny].Visited) then    begin      RemoveWall(x, y, dirs[i]);      CarveFrom(nx, ny);    end;  end;end; procedure MakeEntranceAndExit;var  startX, endX: Integer;begin  // choose entrance at random on top row  startX := Random(MazeWidth);  Maze[startX, 0].WallTop := False;   // choose exit at random on bottom row  endX := Random(MazeWidth);  Maze[endX, MazeHeight - 1].WallBottom := False;end; procedure PrintMaze;var  x, y: Integer;begin  // top border  Write('##');  for x := 0 to MazeWidth - 1 do    if Maze[x, 0].WallTop then      Write('##')    else      Write('# ');  Writeln('#');   // each row  for y := 0 to MazeHeight - 1 do  begin    // left border    if Maze[0, y].WallLeft then      Write('#')    else      Write(' ');     // cells with vertical walls  for x := 0 to MazeWidth - 1 do    begin      Write(' ');      if Maze[x, y].WallRight then        Write('#')      else        Write(' ');    end;    Writeln;     // bottom walls for this row    Write('#');    for x := 0 to MazeWidth - 1 do    begin      if Maze[x, y].WallBottom then        Write('##')      else        Write('# ');  end;    Writeln;  end;end; begin  Randomize;  InitMaze;  CarveFrom(0, 0);       // start carving at top-left (arbitrary)  MakeEntranceAndExit;   // open one entrance & one exit  PrintMaze;end.DeepSeek:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program MazeDeepseek;{$mode objfpc}{$H+}uses  SysUtils, Crt; const  WIDTH = 21;   // Must be odd  HEIGHT = 21;  // Must be odd  WALL = '#';  PATH = ' ';  START = 'S';  EXIT_CELL = 'E'; type  TMaze = array[0..HEIGHT-1, 0..WIDTH-1] of Char;  TPoint = record    X, Y: Integer;  end; var  Maze: TMaze;  StartPos, ExitPos: TPoint; procedure InitializeMaze(var Maze: TMaze);var  X, Y: Integer;begin  for Y := 0 to HEIGHT - 1 do    for X := 0 to WIDTH - 1 do      Maze[Y, X] := WALL;end; function IsInBounds(X, Y: Integer): Boolean;begin  Result := (X >= 0) and (X < WIDTH) and (Y >= 0) and (Y < HEIGHT);end; procedure CarvePassages(var Maze: TMaze; X, Y: Integer);type  TDirection = (dirUp, dirRight, dirDown, dirLeft);  TDirArray = array[TDirection] of Integer;const  DX: TDirArray = (0, 1, 0, -1);  DY: TDirArray = (-1, 0, 1, 0);var  Directions: array[0..3] of TDirection;  Dir: TDirection;  NextX, NextX2, NextY: Integer;  I, J: Integer;begin  // Randomize directions  Directions[0] := dirUp;  Directions[1] := dirRight;  Directions[2] := dirDown;  Directions[3] := dirLeft;    // Shuffle directions using Fisher-Yates shuffle  for I := 3 downto 1 do  begin    J := Random(I + 1);    Dir := Directions[I];    Directions[I] := Directions[J];    Directions[J] := Dir;  end;    // Try each direction  for I := 0 to 3 do  begin    Dir := Directions[I];    NextX := X + DX[Dir] * 2;    NextY := Y + DY[Dir] * 2;        if IsInBounds(NextX, NextY) and (Maze[NextY, NextX] = WALL) then    begin      // Carve path to next cell      Maze[NextY, NextX] := PATH;      Maze[Y + DY[Dir], X + DX[Dir]] := PATH;          // Recursively carve from the new cell      CarvePassages(Maze, NextX, NextY);    end;  end;end; procedure GenerateMaze(var Maze: TMaze; var StartPos, ExitPos: TPoint);var  StartX, StartY: Integer;  ExitSide: Integer;begin  Randomize;  InitializeMaze(Maze);    // Start from a random odd cell (to ensure we're in grid alignment)  repeat    StartX := Random(WIDTH div 2) * 2 + 1;    StartY := Random(HEIGHT div 2) * 2 + 1;  until IsInBounds(StartX, StartY);    // Carve starting cell  Maze[StartY, StartX] := START;  StartPos.X := StartX;  StartPos.Y := StartY;    // Generate the maze  CarvePassages(Maze, StartX, StartY);    // Find an exit position (on the border)  ExitSide := Random(4);  case ExitSide of    0: // Top      begin        ExitPos.X := Random(WIDTH div 2) * 2 + 1;        ExitPos.Y := 0;      end;    1: // Right      begin        ExitPos.X := WIDTH - 1;        ExitPos.Y := Random(HEIGHT div 2) * 2 + 1;      end;    2: // Bottom    begin        ExitPos.X := Random(WIDTH div 2) * 2 + 1;        ExitPos.Y := HEIGHT - 1;      end;    3: // Left      begin        ExitPos.X := 0;        ExitPos.Y := Random(HEIGHT div 2) * 2 + 1;    end;  end;    // Ensure exit path is open  Maze[ExitPos.Y, ExitPos.X] := EXIT_CELL;end; procedure PrintMaze(const Maze: TMaze);var  X, Y: Integer;begin  ClrScr;  WriteLn('Maze (', WIDTH, 'x', HEIGHT, '):');  WriteLn('Start = S, Exit = E');  WriteLn;    for Y := 0 to HEIGHT - 1 do  begin    for X := 0 to WIDTH - 1 do    begin      TextColor(White);      case Maze[Y, X] of        START: TextColor(LightGreen);        EXIT_CELL: TextColor(LightRed);        PATH: TextColor(White);        WALL: TextColor(Blue);      end;      Write(Maze[Y, X]);    end;    WriteLn;  end;  TextColor(White);  WriteLn;end; procedure SaveMazeToFile(const Maze: TMaze; const Filename: string);var  F: TextFile;  X, Y: Integer;begin  AssignFile(F, Filename);  try    Rewrite(F);    WriteLn(F, 'Maze generated by FreePascal Maze Generator');    WriteLn(F, 'Dimensions: ', WIDTH, 'x', HEIGHT);    WriteLn(F);        for Y := 0 to HEIGHT - 1 do    begin      for X := 0 to WIDTH - 1 do        Write(F, Maze[Y, X]);      WriteLn(F);    end;        CloseFile(F);    WriteLn('Maze saved to ', Filename);  except    on E: Exception do      WriteLn('Error saving maze: ', E.Message);  end;end; function VerifyMazeProperties(const Maze: TMaze): Boolean;var  X, Y: Integer;  PathCount, WallCount: Integer;begin  PathCount := 0;  WallCount := 0;    for Y := 0 to HEIGHT - 1 do    for X := 0 to WIDTH - 1 do      if Maze[Y, X] in [PATH, START, EXIT_CELL] then        Inc(PathCount)    else if Maze[Y, X] = WALL then        Inc(WallCount);    WriteLn('Maze Statistics:');  WriteLn('  Total cells: ', WIDTH * HEIGHT);  WriteLn('  Path cells: ', PathCount);  WriteLn('  Wall cells: ', WallCount);  WriteLn('  Fill percentage: ', (WallCount * 100) div (WIDTH * HEIGHT), '%');    Result := (PathCount > 0) and (WallCount > 0);end; procedure AddMorePaths(var Maze: TMaze; Percentage: Integer);var  X, Y, I: Integer;  MaxPaths: Integer;begin  // Add additional paths to create some dead ends and branches  MaxPaths := (WIDTH * HEIGHT * Percentage) div 100;    for I := 1 to MaxPaths do  begin    X := Random(WIDTH - 2) + 1;    Y := Random(HEIGHT - 2) + 1;        // Only convert if it's a wall and has at least 2 neighboring paths    if Maze[Y, X] = WALL then    begin      // Check if this would create a reasonable path    if ((Maze[Y-1, X] = PATH) and (Maze[Y+1, X] = PATH)) or         ((Maze[Y, X-1] = PATH) and (Maze[Y, X+1] = PATH)) then        Maze[Y, X] := PATH;    end;  end;end; begin  WriteLn('FreePascal Maze Generator');  WriteLn('==========================');  WriteLn;    // Generate the maze  GenerateMaze(Maze, StartPos, ExitPos);    // Optional: Add some extra paths to make it more interesting  AddMorePaths(Maze, 5); // Add 5% more paths    // Display the maze  PrintMaze(Maze);    // Verify maze properties  if VerifyMazeProperties(Maze) then    WriteLn('Maze verification: PASSED')  else    WriteLn('Maze verification: FAILED');    WriteLn;  WriteLn('Start position: (', StartPos.X, ', ', StartPos.Y, ')');  WriteLn('Exit position: (', ExitPos.X, ', ', ExitPos.Y, ')');  WriteLn;    // Save to file  SaveMazeToFile(Maze, 'maze.txt');    WriteLn;  WriteLn('Press any key to exit...');  ReadKey;end.Both generate almost correct true Mazes. I like the DeepSeek version best since the code is a bit more elegant and has only two exits. (It should have just one) https://en.wikipedia.org/wiki/Maze Merry Christmas! ---------------------------------------------------------------------- Boleeman · 2025-12-26 07:17 Interesting AI maze designs. Thanks Thaddy for those mazes. ---------------------------------------------------------------------- Thaddy · 2025-12-26 09:48 Reminds me of my UCSD Pascal times back in the early 80's. Generating a maze was part of the CS curriculum. I am sure the above AI examples are way better than mine. ---------------------------------------------------------------------- Boleeman · 2025-12-26 23:31 "Reminds me of my UCSD Pascal times back in the early 80's" Unis made us do all sorts of tasks. I did a Bachelor of Science. Corpsman had a Labyrinth maze maker as well. Can't see the start and the finish? Has a text like appear on a TStringGrid and a Fill mode. ---------------------------------------------------------------------- Thaddy · 2025-12-27 14:47 Here's another one. Was testing/adding Claude AI. It succeeded second time after I pointed out its first solution could create unsolvable mazes:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program MazeClaude; uses  SysUtils; const  WIDTH = 21;   // Must be odd  HEIGHT = 21;  // Must be odd type  TMaze = array[0..HEIGHT-1, 0..WIDTH-1] of Char;  TPoint = record    x, y: Integer;  end;  TQueue = array[0..WIDTH*HEIGHT-1] of TPoint; var  maze: TMaze;  visited: array[0..HEIGHT-1, 0..WIDTH-1] of Boolean; procedure InitMaze;var  i, j: Integer;begin  for i := 0 to HEIGHT-1 do    for j := 0 to WIDTH-1 do    begin      maze[i][j] := '#';      visited[i][j] := False;    end;end; procedure PrintMaze;var  i, j: Integer;begin  for i := 0 to HEIGHT-1 do  begin    for j := 0 to WIDTH-1 do      Write(maze[i][j]);    WriteLn;  end;end; function IsValid(x, y: Integer): Boolean;begin  IsValid := (x >= 0) and (x < WIDTH) and (y >= 0) and (y < HEIGHT);end; procedure Shuffle(var arr: array of TPoint; count: Integer);var  i, j: Integer;  temp: TPoint;begin  for i := count-1 downto 1 do  begin    j := Random(i + 1);    temp := arr[i];  arr[i] := arr[j];    arr[j] := temp;  end;end; procedure CarveMaze(x, y: Integer);var  dirs: array[0..3] of TPoint;  i, nx, ny, wx, wy: Integer;begin  visited[y][x] := True;  maze[y][x] := ' ';    // Four directions: right, down, left, up  dirs[0].x := 2; dirs[0].y := 0;  dirs[1].x := 0; dirs[1].y := 2;  dirs[2].x := -2; dirs[2].y := 0;  dirs[3].x := 0; dirs[3].y := -2;    Shuffle(dirs, 4);    for i := 0 to 3 do  begin    nx := x + dirs[i].x;    ny := y + dirs[i].y;        if IsValid(nx, ny) and not visited[ny][nx] then    begin      // Carve wall between current and next cell      wx := x + dirs[i].x div 2;    wy := y + dirs[i].y div 2;      maze[wy][wx] := ' ';            CarveMaze(nx, ny);    end;  end;end; procedure AddEntranceExit;begin  // Entrance at top  maze[0][1] := ' ';  // Exit at bottom  maze[HEIGHT-1][WIDTH-2] := ' ';end; function ValidateMaze: Boolean;var  queue: TQueue;  qHead, qTail: Integer;  current: TPoint;  checkVisited: array[0..HEIGHT-1, 0..WIDTH-1] of Boolean;  i, j, nx, ny: Integer;  dx: array[0..3] of Integer;  dy: array[0..3] of Integer;  found: Boolean;begin  // Initialize visited array  for i := 0 to HEIGHT-1 do    for j := 0 to WIDTH-1 do      checkVisited[i][j] := False;    // BFS from entrance (1, 0) to exit (WIDTH-2, HEIGHT-1)  dx[0] := 1; dx[1] := 0; dx[2] := -1; dx[3] := 0;  dy[0] := 0; dy[1] := 1; dy[2] := 0; dy[3] := -1;    qHead := 0;  qTail := 0;    // Start from entrance  queue[qTail].x := 1;  queue[qTail].y := 0;  Inc(qTail);  checkVisited[0][1] := True;    found := False;    while qHead < qTail do  begin    current := queue[qHead];    Inc(qHead);      // Check if we reached the exit    if (current.x = WIDTH-2) and (current.y = HEIGHT-1) then    begin      found := True;      Break;  end;        // Explore neighbors    for i := 0 to 3 do    begin      nx := current.x + dx[i];      ny := current.y + dy[i];            if IsValid(nx, ny) and (maze[ny][nx] = ' ') and not checkVisited[ny][nx] then      begin        checkVisited[ny][nx] := True;        queue[qTail].x := nx;        queue[qTail].y := ny;        Inc(qTail);      end;    end;  end;    ValidateMaze := found;end; var  attempts: Integer;  valid: Boolean; begin  Randomize;    attempts := 0;  valid := False;    while not valid do  begin    Inc(attempts);        InitMaze;    CarveMaze(1, 1);    AddEntranceExit;        valid := ValidateMaze;        if not valid then      WriteLn('Attempt ', attempts, ': Invalid maze, regenerating...');  end;    WriteLn('Valid maze generated after ', attempts, ' attempt(s)!');  WriteLn('Perfect Maze (always-left/always-right solvable):');  WriteLn;  PrintMaze;    WriteLn;  WriteLn('Press Enter to exit...');  ReadLn;end.Quite neat, but it took two attempts. ---------------------------------------------------------------------- TBMan · 2025-12-27 15:30 From the other view point, years ago I had created a way to manually create and save simple text mazes to disk. To use the mazes I created "bugs" that had string "genes",  NSEWSEWNE, for example (but much longer). The "bug" would start at the defined beginning and used it's "genes" to determine which way to go. When it could not progress along a direction anymore,  the next gene was used, etc, etc. If it ran out of genes it before it solved the maze it "died."   I would make hundreds of these "bugs" and send them through the maze. From a "generation" of bugs I would take the bugs that progressed the farthest in the maze and pair them up with others and merge their genes. Finally, I would then introduce a few random mutations to the bugs genes and then use these bugs to create the next generation.  Over a few generations every "bug" would eventually solve the maze. ---------------------------------------------------------------------- Boleeman · 2026-01-03 11:21 Hi All. I was trying to add a save to png to the Lararus lazes program, but somehow I could not work out the correct sizing of the png. The png is oversizing to the full client size instead of just the maze size. Anyone have a clue on how to get the correct size? ---------------------------------------------------------------------- Phoenix · 2026-01-03 12:22 First of all, thank you for all your graphics programs, and Happy New Year! Try this modification: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TfrmMain1.SavePng();var  Png2: TPortableNetworkGraphic;  DstRect,SrcRect: TRect;  offsetX,offsetY: Integer;begin  if not assigned(MazePainter) then   Exit;   Png2 := TPortableNetworkGraphic.Create;  try    Png2.Width := MazePainter.Width+1;    Png2.Height := MazePainter.Height+1;    Png2.Canvas.FillRect(0, 0, Png2.Width, Png2.Height);     offsetX:= (pbMaze.ClientWidth - MazePainter.Width) div 2;    offsetY:= (pbMaze.ClientHeight - MazePainter.Height) div 2;     DstRect := types.Rect(0,0,Png2.Width,Png2.Height);    SrcRect := types.Rect(offsetX,offsetY, offsetX + Png2.Width, offsetY + Png2.Height);    Png2.Canvas.CopyRect(DstRect, pbMaze.Canvas, SrcRect);    if SaveDialog1.Execute then      Png2.SaveToFile(SaveDialog1.FileName);  finally    Png2.Free;  end;end; probably improvable but here it works ---------------------------------------------------------------------- Boleeman · 2026-01-03 22:10 Thank you Phoenix for your kind words and for the save to correct png size snippet. The original Laze Maze Wiki code had a small error (mentioned in another post). I didn't fully understand the MazePaintercode and the MazeMetrics.MazeWidth and  MazeMetrics.MazeHeight sizing code.  Also looked at Rect(pOffsetX,pOffsetY,pOffsetX+Width+1,pOffsetY+Height+1), bmp.Canvas, Rect(0,0,Width+1,Height+1)) I tried every combination, but kept going round in circles. Looking at your snippet I now see offset relationship for the correct region needed: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     offsetX:= (pbMaze.ClientWidth - MazePainter.Width) div 2;    offsetY:= (pbMaze.ClientHeight - MazePainter.Height) div 2;     DstRect := types.Rect(0,0,Png2.Width,Png2.Height);    SrcRect := types.Rect(offsetX,offsetY, offsetX + Png2.Width, offsetY + Png2.Height); It's nice to be appreciated (I felt like I was spamming the Graphics forum with my Graphics programs so I stopped uploading for a while). Many thanks Phoenix and Happy New Year to you as well. ---------------------------------------------------------------------- Boleeman · 2026-01-03 22:52 With Phoenix's save png snippet I can now save large mazes correctly, but I noticed having the red squares for the solution path is making the solution harder to read. Perhaps the red squares need to be a continuous thin red 3 pixel line showing the solution path? I modified the Max limits and now can make huge mazes (almost instantly) but the path finding is quite awkwardly slow. ---------------------------------------------------------------------- TBMan · 2026-01-03 23:38 Quote from: Boleeman on January 03, 2026, 11:10:22 pm. . . (I felt like I was spamming the Graphics forum with my Graphics programs so I stopped uploading for a while). . . . Keep posting, I enjoy reading your stuff. ---------------------------------------------------------------------- Boleeman · 2026-01-04 00:39 "I honestly thought I was being a massive Graphics forum spammer and had a perception that I was being a bit of a pain, being too responsive to the "Post" button." Thanks for your kind words TBMan and Phoenix. ---------------------------------------------------------------------- Boleeman · 2026-01-04 02:55 Two posts before this one you can download the modified Max limits Laze source. With the Laze Mazes program I experimented by changing the scaling slide Max limits and was pleasantly surprised that the maze creation was quite fast (almost instantaneous). The solution path finding was quite slow (took about 12 minutes to solve). I was watching it work and sometimes it made some obvious wrong pathway choices (I could see the correct pathway but the program needlessly went down obvious dead ends and then backed up to the correct path). I wondered if a different (more efficient) pathfinding method could be implemented for these larger mazes? The maze creation is quite fast but the solution finding is extremely slow. I have a JavaScript Maze Generator (found on GitHub) that can make large mazes fast and it also solves them just as fast. Something like this is needed for the Lazarus pathfinder mechanism. Lastly looking at the extreme sized Lazes maze, sometimes there is a vertical bias, sometimes horizontal and sometimes zigzag. So at very large sizes the Lazes program seems to have a mixture of all 3 biases. At the CSharp Helper Website ( http://www.csharphelper.com/howtos/howto_weighted_maze.html )  Rod Stephens made a maze with topographic features that uses a random spanning tree algorithm to make biased mazes with vertical, horizontal, age, zigzag and straight biased modes. I've known Rod for a long time and admire his CSharp skills (although my CSharp suck but I was getting a bit better at it). I had gotten a lot better at doing Lazarus Graphics programming). Rod has certainly made a lot of interesting programs. ---------------------------------------------------------------------- Boleeman · 2026-01-14 10:48 Cylog's LazMaze V3 Found it on SourceForge and compiled it to 64Bits (was 32Bit). Can left click for start and right click for end positions when doing the pathfinding. Not sure how to toggle (hide/show) the solution without creating a new maze? ---------------------------------------------------------------------- Thaddy · 2026-01-14 13:51 Maze solutions - in a true maze - are easy. Always go left or always go right. Do not mix. For the shortest way, there is technically no direct answer without knowing the solution beforehand. (That would be Dijkstra's). I already gave you that answer? And yes, while the left/right paradigm always hold, maze solutions are otherwise computationally expensive (and fun). But solving a maze isn't: always left or always right. Without prior knowledge you can't compute Dijkstra's shortest path. ---------------------------------------------------------------------- speter · 2026-01-14 21:43 You may like to have a look at this thread; it includes a recursive (maze) pathfinder. cheers S. ---------------------------------------------------------------------- Boleeman · 2026-01-15 04:12 Thanks. Actually I thought of just copying the maze to a temporary bmp (where it can remain untouched until New Maze button is clicked) and then different solutions can be found by clicking in different regions of the original canvas of the maze. speter, I will look at your standard recursive pathing algorithm code as well. Thanks Thaddy and speter. ---------------------------------------------------------------------- Boleeman · 2026-01-15 06:20 And the updated Cylog Lazmaze maker. Tabbed to play around with solution (in order to get more difficult path finds). Left and right mouse click to set the starting point and the end point of the path finder. Also added a Save to Png feature that saves both mazes with given sub- names. Enjoy. ---------------------------------------------------------------------- Boleeman · 2026-01-18 07:51 Recently came across an article about using CSharp to make "Mazed Progress Bars". https://www.codeproject.com/articles/The-Amazing-ProgressBar- Control#comments-section The progress bars kinda LOOK COOL. Also working on a Cretan Labytinth (uses 1 line only and threads it).  Not a maze but makes amazingly tight paths. Nice!