Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- 3D pathfinding :D
- function pathFind(map) -- Map is a 3-dimensional matrix with uniform width, height, and length (a rectangular prism)
- local height, width, length = 0, 0, 0
- local start, finish, open, closed, order, current = {}, {}, {}, {}, {}, {}
- -- Format: open[x .. "-" .. y .. "-" .. z] = {{x, y, z}, ParentNode, fCost}
- for i, v in pairs(map) do
- width = width + 1
- for j, k in pairs(v) do
- if width == 1 then
- height = height + 1
- end
- for l, z in pairs(k) do
- if height == 1 then
- length = length + 1
- end
- if z == 2 then
- start = {l, j, i}
- elseif z == 3 then
- finish = {l, j, i}
- end
- end
- end
- end
- local function getPrCost(Node, ParentNode)
- if not ParentNode then return 0 end
- if Node[1] - ParentNode[1] == 0 or Node[2] - ParentNode[2] == 0 or Node[3] - ParentNode[3] == 0 then
- return 10
- elseif math.abs(Node[1] - ParentNode[1]) == 1 and math.abs(Node[2] - ParentNode[2]) == 1 and math.abs(Node[3] - ParentNode[3]) == 1 then
- return 17
- else
- return 14
- end
- end
- local function getSeCost(Node)
- return (math.abs(Node[1] - finish[1]) + math.abs(Node[2] - finish[2]) + math.abs(Node[3] - finish[3])) * 10
- end
- local function getSurroundingNodes(Node, ParentCost)
- local x, y, z = Node[1], Node[2], Node[3]
- for i = -1, 1 do
- for j = -1, 1 do
- for n = -1, 1 do
- if x + i > length or z + n > width or y + j > height or x + i <= 0 or y + j <= 0 or z + n <= 0 or (map[z + n][y + j][x + i] and map[z + n][y + j][x +i] == 1) or closed[x + i .. "-" .. y + j .. "-" .. z + n] then
- open[x + i .. "-" .. y + j .. "-" .. z + n] = nil
- closed[x + i .. "-" .. y + j .. "-" .. z + n] = true
- elseif open[x + i .. "-" .. y + j .. "-" .. z + n] then
- if ParentCost + getPrCost({x + i, y + j, z + n}, Node) < getPrCost({x + i, y + j, z + n}, open[x + i .. "-" .. y + j .. "-" .. z + n][2]) then
- open[x + i .. "-" .. y + j .. "-" .. z + n] = {{x + i, y + j, z + n}, Node, getPrCost({x + i, y + j, z + n}, Node) + getSeCost({x + i, y + j, z + n})}
- end
- else
- open[x + i .. "-" .. y + j .. "-" .. z + n] = {{x + i, y + j, z + n}, Node, getPrCost({x + i, y + j, z + n}, Node) + getSeCost({x + i, y + j, z + n})}
- end
- end
- end
- end
- end
- current = start
- while (true) do
- if current[1] == start[1] and current[2] == start[2] and current[3] == start[3] then
- localCost = 0
- else
- local localCost = getPrCost(current, open[current[1] .. "-" .. current[2] .. "-" .. current[3]][2])
- end
- open[current[1] .. "-" .. current[2] .. "-" .. current[3]] = nil
- closed[current[1] .. "-" .. current[2] .. "-" .. current[3]] = true
- if current[1] == finish[1] and current[2] == finish[2] and current[3] == finish[3] then print("Search complete.") return order end
- getSurroundingNodes(current, localCost)
- local closest, lowest
- for i, v in pairs(open) do
- if not closest or v[3] < lowest then
- closest = v[1]
- lowest = v[3]
- end
- end
- if not closest then print("No path.") return {} end
- table.insert(order, {closest[1], closest[2], closest[3]})
- current = closest
- end
- end
- local order = pathFind {
- { -- z 1
- {2, 0, 0}, -- y
- {1, 1, 0},
- {0, 0, 0}
- }, {
- {1, 1, 1},
- {1, 1, 1},
- {0, 1, 1}
- }, {
- {3, 0, 0},
- {1, 1, 0},
- {0, 0, 0}
- }
- }
- -- Display the path to the output
- for i, v in pairs(order) do
- print("{" .. v[1] .. ", " .. v[2] .. ", " .. v[3] .. "}")
- end
Advertisement
Add Comment
Please, Sign In to add comment