_James

A* Pathfinder for Tutorial

Jun 14th, 2016
3,516
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 2.85 KB | None | 0 0
  1. local nodes = workspace:WaitForChild("Nodes")
  2. local LIST  = nodes:GetChildren()
  3. local index = {}
  4.  
  5. local parent = {}
  6. local g_score = {}
  7. local f_score = {}
  8.  
  9. function round(n)
  10.     return math.floor(n + .5)
  11. end
  12.  
  13. function sort(list, index)
  14.     while true do
  15.         local p_index = round((index-1) / 2)
  16.         if p_index == 0 then return list end
  17.         if f_score[list[p_index]] > f_score[list[index]] then
  18.             list[p_index], list[index] = list[index], list[p_index]
  19.             index = p_index
  20.         else
  21.             return list
  22.         end
  23.     end
  24. end
  25.  
  26. function get_h(a, b)
  27.     if not (a and b) then return math.huge end
  28.     return (a.Position - b.Position).Magnitude
  29. end
  30.  
  31. function closest_node(coord)
  32.     local cap, output = math.huge
  33.     for _,v in ipairs(LIST)do
  34.         local dist = (v.Position - coord).Magnitude
  35.         if dist < cap then
  36.             output = v
  37.             cap = dist
  38.         end
  39.     end
  40.    
  41.     return output
  42. end
  43.  
  44. function a_star(a, b)
  45.     a = closest_node(a)
  46.     b = closest_node(b)
  47.    
  48.     local closed_list = {}
  49.     local open_list = {a}
  50.     local current
  51.    
  52.     parent  = {}
  53.     g_score  = {}
  54.     f_score  = {}
  55.    
  56.     g_score[a] = 0
  57.     f_score[a] = get_h(a, b)
  58.     parent[a] = a
  59.    
  60.     repeat
  61.         current = open_list[1]
  62.        
  63.         if current == b then
  64.             break
  65.         end
  66.        
  67.         table.remove(open_list, 1)
  68.         closed_list[current] = parent[current]
  69.        
  70.         for _,v in ipairs(current:GetChildren())do
  71.             local node = v.Value
  72.            
  73.             local h = get_h(node, b)
  74.             local g = g_score[current] + get_h(current, node)
  75.             local f = g + h
  76.            
  77.             if not parent[node] and not closed_list[node] then
  78.                 parent[node] = current
  79.                 f_score[node] = f
  80.                 g_score[node] = g
  81.                 table.insert(open_list, node)
  82.                 open_list = sort(open_list, #open_list)
  83.             end
  84.             if g < g_score[node] then
  85.                 parent[node] = current
  86.                 g_score[node] = g
  87.                 f_score[node] = f
  88.             end
  89.         end
  90.     until #open_list <= 0
  91.  
  92.     if #open_list <= 0 then
  93.         -- No path.
  94.         return {}, "No path"
  95.     end
  96.    
  97.     -- Retrace path.
  98.     local path = {current}
  99.     current = parent[current]
  100.     repeat
  101.         if current then
  102.             table.insert(path, current)
  103.             if parent[current] == current then
  104.                 break
  105.             end
  106.             current = parent[current]
  107.         end
  108.     until not current
  109.    
  110.     local output = {}
  111.     -- Reverse path.
  112.     for i = #path, 1, -1 do
  113.         table.insert(output, path[i].Position)
  114.     end
  115.     if current then
  116.         return output, "Success"
  117.     end
  118.     return {}, "Failure"
  119. end
  120.  
  121. return a_star
Advertisement
Add Comment
Please, Sign In to add comment