Advertisement
WarPie90

Maze solver Simba 2.0 - ffast

Jul 16th, 2024 (edited)
601
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 4.68 KB | None | 0 0
  1. program MazeSolver;
  2. {.$I SRL/OSR.simba}
  3. {$R-}
  4.  
  5.  
  6. // home brewed search structure for the heuristic BFS lookup
  7. // maintains order. High cost of insertion O(n).
  8. type
  9.   TPathStruct = record
  10.     node: TPoint;
  11.     hdist: single;
  12.     rdist: single;
  13.   end;
  14.  
  15.   TSearchArray = record
  16.     lo, hi: Int32;
  17.     data: array of TPathStruct;
  18.   end;
  19.  
  20.  
  21. procedure TSearchArray.Init(sz: Int32);
  22. begin
  23.   SetLength(Self.data, sz);
  24.  
  25.   Self.hi := -1;
  26.   Self.lo := 0;
  27. end;
  28.  
  29. // find the current value or the closest value in the array.
  30. // Time complexity: O(log n)
  31. function TSearchArray.SearchClosest(value: single): Int32;
  32. var
  33.   l, h: Int32;
  34. begin
  35.   l := Self.Lo;
  36.   h := Self.Hi;
  37.  
  38.   while l <= h do
  39.   begin
  40.     Result := (l + h) div 2;
  41.     if Self.Data[Result].hdist < value then
  42.       h := Result - 1
  43.     else if Self.Data[Result].hdist > value then
  44.       l := Result + 1
  45.     else
  46.       Exit(Result);
  47.   end;
  48. end;
  49.  
  50. // Insert the a value into it's correct position by searching.
  51. // Time complexity: O(n)
  52. // For this usage we are looking at time complexity in range of
  53. // average O(log n)
  54. function TSearchArray.Insert(_node:TPoint; _hdist, _rdist: single): Int32;
  55. var
  56.   idx,i: Int32;
  57. begin
  58.   if (Self.hi = -1) or (Self.Data[Self.hi].hdist >= _hdist) then
  59.     idx := self.hi + 1
  60.   else if (Self.hi >= 5) and (_hdist <= Self.Data[Self.hi-5].hdist) then
  61.   begin
  62.     for idx := self.hi+1 downto Self.hi-5 do
  63.     begin
  64.       Self.data[idx] := Self.data[idx-1];
  65.       if Self.data[idx].hdist >= _hdist then break;
  66.     end;
  67.   end else begin
  68.     idx := Self.SearchClosest(_hdist);
  69.     if Self.Data[idx].hdist > _hdist then Inc(idx);
  70.  
  71.     if (self.hi+1-idx) > 0 then
  72.       Move(Self.data[idx], Self.data[idx+1], (self.hi+1-idx)*(SizeOf(TPathStruct)));
  73.   end;
  74.  
  75.   with Self.data[idx] do
  76.   begin
  77.     hdist := _hdist;
  78.     rdist := _rdist;
  79.     node  := _node;
  80.   end;
  81.  
  82.   Inc(Self.hi);
  83. end;
  84.  
  85. // Pop the largest or smallest value depending on insertion order
  86. // Time complexity: O(1)
  87. procedure TSearchArray.Pop(out _node:TPoint; out _hdist, _rdist: single);
  88. begin
  89.   with self.data[self.hi] do
  90.   begin
  91.     _node  := node;
  92.     _hdist := hdist;
  93.     _rdist := rdist;
  94.   end;
  95.  
  96.   Dec(Self.Hi);
  97. end;
  98.  
  99. function TSearchArray.AsString(): String;
  100. var
  101.   tmp: array of TPathStruct;
  102. begin
  103.   tmp := self.data;
  104.   SetLength(tmp, self.hi+1);
  105.   Result := ToString(tmp);
  106. end;
  107.  
  108.  
  109. function SolveMaze(Start, Stop: TPoint; Img: TImage): TPointArray;
  110. var
  111.   score,hdist,score1: single;
  112.   i,w,h: Int32;
  113.   arr: TSearchArray;
  114.   map: TSingleMatrix;
  115.   p,q: TPoint;
  116.   bmp: TImage;
  117.   adj: TPointArray = [[-1,0],[1,0],[0,-1],[0,1],[1,-1],[1,1],[-1,-1],[-1,1]];
  118.   t: Double;
  119. begin
  120.   arr.Init(img.Width * img.Height);
  121.   arr.Insert(start, Sqr(start.x-stop.x)+Sqr(start.y-stop.y), 0);
  122.  
  123.   w := img.Width - 1;
  124.   h := img.Height - 1;
  125.   map.SetSize(w+1, h+1);
  126.  
  127.   SetLength(adj, 4);
  128.   // heuristical forward search for goal
  129.   while (arr.hi >= 0) do
  130.   begin
  131.     arr.Pop(p, hdist, score); //inline for higher performance
  132.     if (p = stop) then break;
  133.     for q in adj do
  134.       with q do
  135.       begin
  136.         x += p.x;
  137.         y += p.y;
  138.         if img.InImage(x,y) and (img.Pixel[x,y] = $FFFFFF)  then
  139.         begin
  140.           img.Pixel[x,y] := $666666;
  141.           arr.Insert(q, score + Sqr(x-stop.x)+Sqr(y-stop.y), score+1);
  142.           map[y,x] := score+1; //<--- for simple backtrace
  143.         end;
  144.       end;
  145.   end;
  146.  
  147.   // backtrace towards 0 distance from stop using the distance map
  148.   score := map[stop.y,stop.x];
  149.   Result += p; //pre-allocate result size for another boost SetLen(res, Ceil(score))
  150.   while score > 1 do
  151.   begin
  152.     for q in adj do
  153.     begin
  154.       q.x += p.x;
  155.       q.y += p.y;
  156.       if img.InImage(q.x,q.y) and
  157.       (map[q.y, q.x] < score) and (map[q.y, q.x] > 0) then
  158.       begin
  159.         score := map[q.y, q.x];
  160.         p := q;
  161.       end;
  162.     end;
  163.     Result += p;
  164.   end;
  165.   Result += start;
  166. end;
  167.  
  168.  
  169. var
  170.   start := Point(5,0); stop  := Point(635,480);
  171.   //stop := Point(428,510); start := Point(83,2);
  172.  
  173.   img, im2: TImage;
  174.   TPA,white,black,path1,path2: TPointArray;
  175.   t:Double;
  176. begin
  177.   img := TImage.Create('images\maze.png');
  178.   //Swap(start,stop);
  179.  
  180.   for 0 to 100 do
  181.   begin
  182.     img.Free();
  183.     img := TImage.Create('images\maze.png');
  184.  
  185.     t := PerformanceTimer;
  186.     begin
  187.       black := img.FindColor(0,1);
  188.       img.DrawColor := 0;
  189.       img.DrawTPA(black.Grow(2));
  190.       path1 := SolveMaze(start, stop, img);
  191.     end;
  192.     WriteLn(PerformanceTimer - t, 'ms');
  193.   end;
  194.   WriteLn('Length: ', Length(path1));
  195.  
  196.   img.Fill($FFFFFF);
  197.   img.DrawColor := 0;
  198.   img.DrawTPA(black);
  199.  
  200.   img.DrawColor := $FF00FF;
  201.   img.DrawTPA(path1.Grow(1));
  202.  
  203.   img.Show();
  204.   img.Free();
  205. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement