-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmap.lua
More file actions
155 lines (135 loc) · 4.48 KB
/
map.lua
File metadata and controls
155 lines (135 loc) · 4.48 KB
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
local args = {...}
local import_prefix = args[1]
if import_prefix then import_prefix = import_prefix:match("^(.-)[^%.]+$") end
if not import_prefix then local_prefix = args[1] end
local errormodule = require(import_prefix .. "error")
local utilmodule = load_module(import_prefix .. "util", true)
local classmodule = load_module(import_prefix .. "class", true)
Map = class(function(self, level)
self.__grid = {}
self.__width = level:getColumnCount()
self.__height = floor(level:getMapSize() / self.__width)
local x, y
for x = 1, self.__width do
self.__grid[x] = {}
for y = 1, self.__height do
local room = level:getRoomFromCoordinates(x, y)
self.__grid[x][y] = {
up = room:hasAccess("up"),
down = room:hasAccess("down"),
left = room:hasAccess("left"),
right = room:hasAccess("right")
}
if room:getAttribute("unreachable") or room:getAttribute("safezone") then
self.__grid[x][y].weight = -1
elseif room:getAttribute("trap") then
self.__grid[x][y].weight = 4
elseif room:getAttribute("monster") then
self.__grid[x][y].weight = 2
elseif room:getAttribute("redkey")
or room:getAttribute("reddoor") or room:getAttribute("reddoor_dir")
or room:getAttribute("graveyard") then
self.__grid[x][y].weight = 0
else
self.__grid[x][y].weight = 1
end
end
end
end)
--[[ Astar - an A* algorithm
Uses the A* algorithm to create a path from point (xbeg, ybeg) to (xend, yend).
Return nil or a table of {x: x, y: y} objects (representing the path)
]]
function Map:Astar(xbeg, ybeg, xend, yend)
-- Invalid coords?
if (xbeg <= 0) or (xbeg > self.__width)
or (xend <= 0) or (xend > self.__width)
or (ybeg <= 0) or (ybeg > self.__height)
or (yend <= 0) or (yend > self.__height) then
return nil
end
local x, y, path, node, nodes
nodes = {}
node = {}
path = {
--minCost = {val = inf, col = xbeg},
--minCost2 = {val = inf, col = 1},
}
for x = 1, self.__width do
node[x] = {}
path[x] = {
--minCost = {val = inf, line = 1}
}
for y = 1, self.__height do
path[x][y] = {
gcost = inf,
hcost = abs(x - xend) + abs(y - yend),
visited = false,
parent = nil
}
if (x == xend) and (y == yend) then
path[x][y].gcost = 0
--path[x].minCost = {val = path[x][y].hcost, line = y}
--path.minCost.val = path[x].minCost.val
end
node[x][y] = {
p = path[x][y],
g = self.__grid[x][y],
w = self.__grid[x][y].weight,
x = x, y = y
}
table.insert(nodes, node[x][y])
end
end
for x = 1, self.__width do
for y = 1, self.__height do
if y ~= 1 then node[x][y].up = node[x][y - 1]
else node[x][y].up = {p = {gcost = inf, hcost = inf}, g = {weight = 0}} end
if y ~= self.__height then node[x][y].down = node[x][y + 1]
else node[x][y].down = {p = {gcost = inf, hcost = inf}, g = {weight = 0}} end
if x ~= 1 then node[x][y].left = node[x - 1][y]
else node[x][y].left = {p = {gcost = inf, hcost = inf}, g = {weight = 0}} end
if x ~= self.__width then node[x][y].right = node[x + 1][y]
else node[x][y].right = {p = {gcost = inf, hcost = inf}, g = {weight = 0}} end
end
end
local gcost
table.sort(nodes, function(a, b) return a.p.gcost + a.p.hcost < b.p.gcost + b.p.hcost end)
while nodes[1].gcost ~= inf do
node = nodes[1]
x = node.x
y = node.y
if (x == xbeg) and (y == ybeg) then
local path = {{x = xbeg, y = ybeg}}
while node.parent do
node = node.parent
table.insert(path, {x = node.x, y = node.y})
end
return path
end
node.p.visited = true
-- xmin = path.minCost.val
-- xmin2 = path.minCost2.val
-- ymin = path[x].minCost.val
if node.g.up and (node.up.w >= 0) and (node.up.p.gcost > node.p.gcost + node.up.w) then
node.up.p.gcost = node.p.gcost + node.up.w
node.up.parent = node
end
if node.g.down and (node.down.w >= 0) and (node.down.p.gcost > node.p.gcost + node.down.w) then
node.down.p.gcost = node.p.gcost + node.down.w
node.down.parent = node
end
if node.g.left and (node.left.w >= 0) and (node.left.p.gcost > node.p.gcost + node.left.w) then
node.left.p.gcost = node.p.gcost + node.left.w
node.left.parent = node
end
if node.g.right and (node.right.w >= 0) and (node.right.p.gcost > node.p.gcost + node.right.w) then
node.right.p.gcost = node.p.gcost + node.right.w
node.right.parent = node
end
nodes[1] = nodes[#nodes]
table.remove(nodes)
table.sort(nodes, function(a, b) return a.p.gcost + a.p.hcost < b.p.gcost + b.p.hcost end)
end
return nil
end