forked from clowerweb/Lib-Pico8
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pathfinding.lua
78 lines (67 loc) · 2.07 KB
/
pathfinding.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
-- will contain functions for
-- various forms of pathfinding,
-- such as distance-based (see
-- distance.lua), and A*
-- for now it's only breath-first path finding
-- Contributors: sulai
---
-- Breadth-first path finding.
-- Example usage
-- targets = find_path_breadth(startx, starty, 10,
-- function(cx,cy)
-- -- make the path finder step on tiles with index>16 only
-- return mget(cx,cy)>16
-- end,
-- function(tx,ty)
-- -- accept tile index 20 as targets
-- return mget(tx,ty)==20
-- end)
-- -- now use the result of the path finding
-- for t in all(targets) do
-- mset(t.x, t.y, 0)
-- end
--
-- @param x coordinate to start path finding at
-- @param y coordinate to start path finding at
-- @param limit stop if this amount of targets were found
-- @param accept_child callback method (x,y), return true if you accept this child
-- @param accept_target callback method (x,y), return true if you accept this as target
-- @return a table of coordinates matching what ever is defined in the callbacks.
-- The result might look something like this
-- {{x=...,y=...},...}
function find_path_breadth(x, y, limit, accept_child, accept_target)
local targets = {} -- list od coordinates {x}{y} as result of this function
local visited = {}
local stack = {}
local read = 0
local write = 0
write=write + 1 stack[write] = {x,y} -- push
visited[x..","..y] = true
local dir={{x=-1,y=0},{x=1,y=0},{x=0,y=-1},{x=0,y=1} }
while write > read do
-- pull currently visited node
read=read + 1 local coord = stack[read] -- pull
local vx = coord[1]
local vy = coord[2]
-- position matching all criteria?
if accept_target(vx,vy) then
add(targets,{x=vx, y=vy })
if #targets==limit then
return targets
end
end
-- go visit neighboars
for d in all(dir) do
-- child position
local cx = (vx+d.x)%48 -- map wrap
local cy = (vy+d.y)%48
if not visited[cx..","..cy] then
visited[cx..","..cy]=true
if accept_child(cx,cy) then
write=write + 1 stack[write] = { cx, cy } -- push
end
end
end
end
return targets
end