kremnev8

A star algorithm

Dec 7th, 2015
162
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.64 KB | None | 0 0
  1. --[[
  2. A* algorithm for LUA
  3. Ported to LUA by Altair
  4. 21 septembre 2006
  5. --]]
  6.  
  7. local AStar = {}
  8.  
  9. function AStar.CalcMoves(mapmat, px, py, tx, ty)    -- Based on some code of LMelior but made it work and improved way beyond his code, still thx LMelior!
  10. --[[ PRE:
  11. mapmat is a 2d array
  12. px is the player's current x
  13. py is the player's current y
  14. tx is the target x
  15. ty is the target y
  16. Note: all the x and y are the x and y to be used in the table.
  17. By this I mean, if the table is 3 by 2, the x can be 1,2,3 and the y can be 1 or 2.
  18. --]]
  19.  
  20. --[[ POST:
  21. closedlist is a list with the checked nodes.
  22. It will return nil if all the available nodes have been checked but the target hasn't been found.
  23. --]]
  24.  
  25.     -- variables
  26.     local openlist={}                               -- Initialize table to store possible moves
  27.     local closedlist={}                     -- Initialize table to store checked gridsquares
  28.     local listk=1                                   -- List counter
  29.         local closedk=0                                 -- Closedlist counter
  30.     local tempH=math.abs(px-tx)+math.abs(py-ty)
  31.     local tempG=0
  32.     openlist[1]={x=px, y=py, g=0, h=tempH, f=0+tempH ,par=1}    -- Make starting point in list
  33.     local xsize=table.getn(mapmat[1])               -- horizontal map size
  34.     local ysize=table.getn(mapmat)                  -- vertical map size
  35.     local curbase={}                        -- Current square from which to check possible moves
  36.     local basis=1                           -- Index of current base
  37.  
  38.     -- Growing loop
  39.     while listk>0 do
  40.  
  41.             -- Get the lowest f of the openlist
  42.             local lowestF=openlist[listk].f
  43.             basis=listk
  44.         for k=listk,1,-1 do
  45.             if openlist[k].f<lowestF then
  46.                lowestF=openlist[k].f
  47.                        basis=k
  48.                 end
  49.         end
  50.  
  51.         closedk=closedk+1
  52.         table.insert(closedlist,closedk,openlist[basis])
  53.  
  54.         curbase=closedlist[closedk]              -- define current base from which to grow list
  55.  
  56.         local rightOK=true
  57.         local leftOK=true                            -- Booleans defining if they're OK to add
  58.         local downOK=true                            -- (must be reset for each while loop)
  59.         local upOK=true
  60.  
  61.         -- Look through closedlist
  62.         if closedk>0 then
  63.             for k=1,closedk do
  64.             if closedlist[k].x==curbase.x+1 and closedlist[k].y==curbase.y then
  65.                 rightOK=false
  66.             end
  67.             if closedlist[k].x==curbase.x-1 and closedlist[k].y==curbase.y then
  68.                 leftOK=false
  69.             end
  70.             if closedlist[k].x==curbase.x and closedlist[k].y==curbase.y+1 then
  71.                 downOK=false
  72.             end
  73.             if closedlist[k].x==curbase.x and closedlist[k].y==curbase.y-1 then
  74.                 upOK=false
  75.             end
  76.             end
  77.         end
  78.        
  79.         -- Check if next points are on the map and within moving distance
  80.         if curbase.x+1>xsize then
  81.             rightOK=false
  82.         end
  83.         if curbase.x-1<1 then
  84.             leftOK=false
  85.         end
  86.         if curbase.y+1>ysize then
  87.             downOK=false
  88.         end
  89.         if curbase.y-1<1 then
  90.             upOK=false
  91.         end
  92.  
  93.         -- If it IS on the map, check map for obstacles
  94.         --(Lua returns an error if you try to access a table position that doesn't exist, so you can't combine it with above)
  95.         if curbase.x+1<=xsize and mapmat[curbase.y][curbase.x+1]~=0 then
  96.             rightOK=false
  97.         end
  98.         if curbase.x-1>=1 and mapmat[curbase.y][curbase.x-1]~=0 then
  99.             leftOK=false
  100.         end
  101.         if curbase.y+1<=ysize and mapmat[curbase.y+1][curbase.x]~=0 then
  102.             downOK=false
  103.         end
  104.         if curbase.y-1>=1 and mapmat[curbase.y-1][curbase.x]~=0 then
  105.             upOK=false
  106.         end
  107.        
  108.         -- check if the move from the current base is shorter then from the former parrent
  109.         tempG=curbase.g+1
  110.         for k=1,listk do
  111.             if rightOK and openlist[k].x==curbase.x+1 and openlist[k].y==curbase.y and openlist[k].g>tempG then
  112.             tempH=math.abs((curbase.x+1)-tx)+math.abs(curbase.y-ty)
  113.             table.insert(openlist,k,{x=curbase.x+1, y=curbase.y, g=tempG, h=tempH, f=tempG+tempH, par=closedk})
  114.             rightOK=false
  115.             end
  116.        
  117.             if leftOK and openlist[k].x==curbase.x-1 and openlist[k].y==curbase.y and openlist[k].g>tempG then
  118.             tempH=math.abs((curbase.x-1)-tx)+math.abs(curbase.y-ty)
  119.             table.insert(openlist,k,{x=curbase.x-1, y=curbase.y, g=tempG, h=tempH, f=tempG+tempH, par=closedk})
  120.             leftOK=false
  121.             end
  122.  
  123.             if downOK and openlist[k].x==curbase.x and openlist[k].y==curbase.y+1 and openlist[k].g>tempG then
  124.             tempH=math.abs((curbase.x)-tx)+math.abs(curbase.y+1-ty)
  125.             table.insert(openlist,k,{x=curbase.x, y=curbase.y+1, g=tempG, h=tempH, f=tempG+tempH, par=closedk})
  126.             downOK=false
  127.             end
  128.  
  129.             if upOK and openlist[k].x==curbase.x and openlist[k].y==curbase.y-1 and openlist[k].g>tempG then
  130.             tempH=math.abs((curbase.x)-tx)+math.abs(curbase.y-1-ty)
  131.             table.insert(openlist,k,{x=curbase.x, y=curbase.y-1, g=tempG, h=tempH, f=tempG+tempH, par=closedk})
  132.             upOK=false
  133.             end
  134.         end
  135.  
  136.         -- Add points to openlist
  137.         -- Add point to the right of current base point
  138.         if rightOK then
  139.             listk=listk+1
  140.             tempH=math.abs((curbase.x+1)-tx)+math.abs(curbase.y-ty)
  141.             table.insert(openlist,listk,{x=curbase.x+1, y=curbase.y, g=tempG, h=tempH, f=tempG+tempH, par=closedk})
  142.         end
  143.  
  144.         -- Add point to the left of current base point
  145.         if leftOK then
  146.             listk=listk+1
  147.             tempH=math.abs((curbase.x-1)-tx)+math.abs(curbase.y-ty)
  148.             table.insert(openlist,listk,{x=curbase.x-1, y=curbase.y, g=tempG, h=tempH, f=tempG+tempH, par=closedk})
  149.         end
  150.  
  151.         -- Add point on the top of current base point
  152.         if downOK then
  153.             listk=listk+1
  154.             tempH=math.abs(curbase.x-tx)+math.abs((curbase.y+1)-ty)
  155.             table.insert(openlist,listk,{x=curbase.x, y=curbase.y+1, g=tempG, h=tempH, f=tempG+tempH, par=closedk})
  156.         end
  157.  
  158.         -- Add point on the bottom of current base point
  159.         if upOK then
  160.             listk=listk+1
  161.             tempH=math.abs(curbase.x-tx)+math.abs((curbase.y-1)-ty)
  162.             table.insert(openlist,listk,{x=curbase.x, y=curbase.y-1, g=tempG, h=tempH, f=tempG+tempH, par=closedk})
  163.         end
  164.  
  165.         table.remove(openlist,basis)
  166.         listk=listk-1
  167.  
  168.                 if closedlist[closedk].x==tx and closedlist[closedk].y==ty then
  169.                    return closedlist
  170.                 end
  171.     end
  172.  
  173.     return nil
  174. end
  175.  
  176. function AStar.CalcPath(closedlist)
  177. --[[ PRE:
  178. closedlist is a list with the checked nodes.
  179. OR nil if all the available nodes have been checked but the target hasn't been found.
  180. --]]
  181.  
  182. --[[ POST:
  183. path is a list with all the x and y coords of the nodes of the path to the target.
  184. OR nil if closedlist==nil
  185. --]]
  186.  
  187.     if closedlist==nil then
  188.        return nil
  189.     end
  190.      local path={}
  191.      local pathIndex={}
  192.      local last=table.getn(closedlist)
  193.      table.insert(pathIndex,1,last)
  194.  
  195.      local i=1
  196.      while pathIndex[i]>1 do
  197.         i=i+1
  198.         table.insert(pathIndex,i,closedlist[pathIndex[i-1]].par)
  199.      end
  200.  
  201.      for n=table.getn(pathIndex),1,-1 do
  202.          table.insert(path,{x=closedlist[pathIndex[n]].x, y=closedlist[pathIndex[n]].y})
  203.      end
  204.  
  205.      closedlist=nil
  206.      return path
  207. end
  208.  
  209. return AStar
Advertisement
Add Comment
Please, Sign In to add comment