merlin11188

3D A* Algorithm

Nov 27th, 2011
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.43 KB | None | 0 0
  1. -- 3D pathfinding :D
  2. function pathFind(map) -- Map is a 3-dimensional matrix with uniform width, height, and length (a rectangular prism)
  3.     local height, width, length = 0, 0, 0
  4.     local start, finish, open, closed, order, current = {}, {}, {}, {}, {}, {}
  5.     -- Format: open[x .. "-" .. y .. "-" .. z] = {{x, y, z}, ParentNode, fCost}
  6.     for i, v in pairs(map) do
  7.         width = width + 1
  8.         for j, k in pairs(v) do
  9.             if width == 1 then
  10.                 height = height + 1
  11.             end
  12.             for l, z in pairs(k) do
  13.                 if height == 1 then
  14.                     length = length + 1
  15.                 end
  16.                 if z == 2 then
  17.                     start = {l, j, i}
  18.                 elseif z == 3 then
  19.                     finish = {l, j, i}
  20.                 end
  21.             end
  22.         end
  23.     end
  24.    
  25.     local function getPrCost(Node, ParentNode)
  26.         if not ParentNode then return 0 end
  27.         if Node[1] - ParentNode[1] == 0 or Node[2] - ParentNode[2] == 0 or Node[3] - ParentNode[3] == 0 then
  28.             return 10
  29.         elseif math.abs(Node[1] - ParentNode[1]) == 1 and math.abs(Node[2] - ParentNode[2]) == 1 and math.abs(Node[3] - ParentNode[3]) == 1 then
  30.             return 17
  31.         else
  32.             return 14
  33.         end
  34.     end
  35.  
  36.     local function getSeCost(Node)
  37.         return (math.abs(Node[1] - finish[1]) + math.abs(Node[2] - finish[2]) + math.abs(Node[3] - finish[3])) * 10
  38.     end
  39.        
  40.     local function getSurroundingNodes(Node, ParentCost)
  41.         local x, y, z = Node[1], Node[2], Node[3]
  42.         for i = -1, 1 do
  43.             for j = -1, 1 do
  44.                 for n = -1, 1 do
  45.                     if x + i > length or z + n > width or y + j > height or x + i <= 0 or y + j <= 0 or z + n <= 0 or (map[z + n][y + j][x + i] and map[z + n][y + j][x +i] == 1) or closed[x + i .. "-" .. y + j .. "-" .. z + n] then
  46.                         open[x + i .. "-" .. y + j .. "-" .. z + n] = nil
  47.                         closed[x + i .. "-" .. y + j .. "-" .. z + n] = true
  48.                     elseif open[x + i .. "-" .. y + j .. "-" .. z + n] then
  49.                         if ParentCost + getPrCost({x + i, y + j, z + n}, Node) < getPrCost({x + i, y + j, z + n}, open[x + i .. "-" .. y + j .. "-" .. z + n][2]) then
  50.                             open[x + i .. "-" .. y + j .. "-" .. z + n] = {{x + i, y + j, z + n}, Node, getPrCost({x + i, y + j, z + n}, Node) + getSeCost({x + i, y + j, z + n})}
  51.                         end
  52.                     else
  53.                         open[x + i .. "-" .. y + j .. "-" .. z + n] = {{x + i, y + j, z + n}, Node, getPrCost({x + i, y + j, z + n}, Node) + getSeCost({x + i, y + j, z + n})}
  54.                     end
  55.                 end
  56.             end
  57.         end
  58.     end
  59.    
  60.     current = start
  61.     while (true) do
  62.         if current[1] == start[1] and current[2] == start[2] and current[3] == start[3] then
  63.             localCost = 0
  64.         else
  65.             local localCost = getPrCost(current, open[current[1] .. "-" .. current[2] .. "-" .. current[3]][2])
  66.         end
  67.         open[current[1] .. "-" .. current[2] .. "-" .. current[3]] = nil
  68.         closed[current[1] .. "-" .. current[2] .. "-" .. current[3]] = true
  69.         if current[1] == finish[1] and current[2] == finish[2] and current[3] == finish[3] then print("Search complete.") return order end
  70.         getSurroundingNodes(current, localCost)
  71.         local closest, lowest
  72.         for i, v in pairs(open) do
  73.             if not closest or v[3] < lowest then
  74.                 closest = v[1]
  75.                 lowest = v[3]
  76.             end
  77.         end
  78.         if not closest then print("No path.") return {} end
  79.         table.insert(order, {closest[1], closest[2], closest[3]})
  80.         current = closest
  81.     end
  82. end
  83.  
  84. local order = pathFind  {
  85.     { -- z 1
  86.         {2, 0, 0}, -- y
  87.         {1, 1, 0},
  88.         {0, 0, 0}
  89.     }, {
  90.         {1, 1, 1},
  91.         {1, 1, 1},
  92.         {0, 1, 1}
  93.     }, {
  94.         {3, 0, 0},
  95.         {1, 1, 0},
  96.         {0, 0, 0}
  97.     }
  98. }
  99.  
  100. -- Display the path to the output
  101. for i, v in pairs(order) do
  102.     print("{" .. v[1] .. ", " .. v[2] .. ", " .. v[3] .. "}")
  103. end
Advertisement
Add Comment
Please, Sign In to add comment