Advertisement
GeeItSomeLaldy

BFS Pico 8

Jul 20th, 2021
985
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 23.25 KB | None | 0 0
  1. pico-8 cartridge // http://www.pico-8.com
  2. version 32
  3. __lua__
  4. -- pico-8 bfs search using map flags
  5. -- david mcquillan @geeitsomelaldy
  6. grid = {}
  7. path = nil
  8. cost_values = nil
  9. cycles = 0
  10. cursor_x,cursor_y = 1,1
  11. point = {{0,0},{0,0}}
  12. index = 1
  13. grid_size = {0,0,32,32}
  14. function _init()
  15.     grid = build_pathfinding_grid(unpack(grid_size))
  16. end
  17.  
  18. function _update60()
  19.     if btnp(0) then
  20.     cursor_x -= 1  
  21.     end
  22.     if btnp(1) then
  23.      cursor_x += 1  
  24.     end
  25.     if btnp(2) then
  26.     cursor_y -= 1  
  27.     end
  28.     if btnp(3) then
  29.     cursor_y += 1  
  30.     end
  31.     if(btnp(4)) then
  32.         point[index] = {cursor_x,cursor_y}
  33.         if(index == 1)
  34.         then
  35.             index = 2
  36.         else
  37.             path,cost_values,cycles = grid:get_path_to(point[1],point[2])
  38.             index = 1
  39.         end
  40.     end
  41.     if(btnp(5)) then
  42.         point[2] = {cursor_x,cursor_y}
  43.         path,cost_values,cycles = grid:get_path_to(point[1],point[2])
  44.         index = 1  
  45.     end
  46. end
  47. function _draw()
  48.         draw_grid()
  49.     camera(0,0)
  50.     po(stat(7) .. " fps",2,38)
  51.     if(cost_values != nil) then
  52.         po(cycles .. " cycles",2,47)
  53.     end
  54.     if(path != nil) then
  55.         po("#path = " .. #path,2,54,9)
  56.     end
  57.     pset(point[1][1]+1,point[1][2]+1,9)
  58.     pset(point[2][1]+1,point[2][2]+1,9)
  59.  
  60.    
  61.     camera(mid(-32,cursor_x*8 -64,128),mid(0,cursor_y*8-64,128))
  62.     spr(3,cursor_x*8,cursor_y*8)
  63.     spr(4,point[1][1]*8,point[1][2]*8)
  64.     spr(5,point[2][1]*8,point[2][2]*8)
  65.  
  66. end
  67. function po(t,x,y,c1,c2)
  68.     print(t,x+1,y+1,c2 or 0)
  69.     print(t,x+1,y-1,c2 or 0)
  70.     print(t,x-1,y+1,c2 or 0)
  71.     print(t,x-1,y-1,c2 or 0)
  72.     print(t,x+1,y,c2 or 0)
  73.     print(t,x-1,y,c2 or 0)
  74.     print(t,x,y+1,c2 or 0)
  75.     print(t,x,y-1,c2 or 0)
  76.     print(t,x,y,c1 or 7)
  77. end
  78. function draw_grid()
  79.     cls(0)
  80.     camera(mid(-32,cursor_x*8 -64,128),mid(0,cursor_y*8-64,128))
  81.     map(grid_size[1],grid_size[2],0,0,grid_size[3],grid_size[4])
  82.     if(path != nil) then
  83.         for  pi = 2, #path do        
  84.             line(path[pi][1]*8 +4,path[pi][2]*8 +4,path[pi-1][1]*8 +4,path[pi-1][2]*8 +4,2)
  85.         end  
  86.         for  pi = 1, #path do        
  87.             print(cost_values[path[pi]],path[pi][1]*8,path[pi][2]*8,7)
  88.         end  
  89.     end
  90.     camera(0,0)
  91.     for ix = 1,#grid do
  92.         for iy = 1,#grid[ix] do
  93.             pset(ix,iy,grid[ix][iy] and 11 or 8)
  94.         end
  95.     end
  96.     if(cost_values != nil) then
  97.         for k,v in pairs(cost_values) do
  98.             pset(k[1]+1,k[2]+1,3)
  99.         end  
  100.     end
  101.     if(path != nil) then
  102.         for  pi = 1, #path do
  103.             pset(path[pi][1]+1,path[pi][2]+1,2)
  104.         end
  105.     end
  106.      
  107. end
  108. -->8
  109. --astar
  110. function build_pathfinding_grid(mx,my,mw,mh)
  111.     local grid = {}
  112.     for ix = mx,mx+mw-1 do
  113.         local row = {}
  114.         for iy = my,my+mh-1 do
  115.             local m = mget(ix,iy)
  116.             local issolid = fget(m,solid)
  117.             add(row,not(issolid))
  118.         end
  119.         add(grid,row)
  120.     end
  121.     local get_path = function(came_from,endnode)
  122.         local path = {}
  123.         add(path,endnode)
  124.         local next = came_from[endnode]
  125.         while(next != nil) do
  126.             add(path,next)
  127.             next = came_from[next]
  128.         end
  129.         return path
  130.     end
  131.     local ref={}
  132.     grid.get_node_reference = function(self,x,y) -- cache references to nodes so we're passing around objects, not strings
  133.         if(ref[x] == nil) ref[x] = {}
  134.         if(ref[x][y] == nil) ref[x][y] = {x,y}
  135.         return ref[x][y]
  136.     end
  137.     grid.is_node = function(self, x,y)
  138.         return self[x+1] and self[x+1][y+1]
  139.     end
  140.     grid.get_neighbours = function(self,point)
  141.         local neighbours = {}
  142.         if(self:is_node(point[1],point[2]+1)) add(neighbours,self:get_node_reference(point[1]  ,point[2]+1))
  143.         if(self:is_node(point[1],point[2]-1)) add(neighbours,self:get_node_reference(point[1]  ,point[2]-1))
  144.         if(self:is_node(point[1]+1,point[2])) add(neighbours,self:get_node_reference(point[1]+1,point[2]  ))
  145.         if(self:is_node(point[1]-1,point[2])) add(neighbours,self:get_node_reference(point[1]-1,point[2]  ))
  146.         return neighbours
  147.     end
  148.     grid.get_path_to = function(self,p1,p2)
  149.         if(self:is_node(p1[1],p1[2]) and self:is_node(p2[1],p2[2])) then
  150.             return self:find_nearest(p1[1],p1[2],{p2})
  151.         end
  152.         return nil
  153.     end
  154.     grid.find_nearest = function(self, sx,sy, destinations)
  155.         local start = self:get_node_reference(sx,sy)
  156.         local frontier = {start}
  157.         local came_from = {}
  158.         local cost_so_far = {}
  159.         local current = nil
  160.         came_from[start] = nil
  161.         cost_so_far[start] = 0
  162.         local f = 0
  163.         while #frontier > 0 do
  164.             current = queue_get(frontier)
  165.             local neighbours = self:get_neighbours(current)
  166.             for ni = 1,#neighbours do
  167.                 local n = neighbours[ni]
  168.                 if(cost_so_far[n] == nil) then
  169.                     add(frontier,n)
  170.                     came_from[n] = current
  171.                     cost_so_far[n] = cost_so_far[current] + 1
  172.                     f+=1
  173.                     if(f > 1000) then --timeout check
  174.                         return nil
  175.                     end
  176.                     if(contains_comp(destinations, function(v,i,a)
  177.                         return v[1] == n[1] and v[2] == n[2]
  178.                     end)) then
  179.                         return get_path(came_from,n),cost_so_far,f
  180.                     end
  181.                 end
  182.             end
  183.         end
  184.         return nil
  185.     end
  186.    
  187.     return grid
  188. end
  189.  
  190. function queue_get(q)  
  191.     local r = q[1]
  192.     del(q,r)
  193.     return r
  194. end
  195. function contains_comp(arr,comp)
  196.     for ri = 1,#arr do
  197.    
  198.         if comp(arr[ri],ri,arr) then
  199.             return true
  200.         end
  201.     end
  202.     return false
  203. end
  204. function index_of(arr,item)
  205.     for ri = 1,#arr do
  206.    
  207.         if arr[ri] == item then
  208.             return ri
  209.         end
  210.     end
  211.     return -1
  212. end
  213. function fully_unpack(table,p)
  214.     local s = ""
  215.     local tabs = p or ""
  216.     for k,v in pairs(table) do
  217.         if( type(k) == "table" ) then
  218.             k = fully_unpack(k)
  219.         end
  220.         if( type(v) == "table" ) then
  221.             s ..= tabs .."["..k.."] = {\n".. fully_unpack(v,tabs .. "\t")..tabs.."\n},\n"
  222.         else
  223.         s ..= tabs .."["..k.."] = "..v..",\n"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement