opus/sys/modules/opus/jumper/search/astar.lua

78 lines
2.2 KiB
Lua
Raw Normal View History

2016-12-11 19:24:52 +00:00
-- Astar algorithm
-- This actual implementation of A-star is based on
-- [Nash A. & al. pseudocode](http://aigamedev.com/open/tutorials/theta-star-any-angle-paths/)
if (...) then
-- Internalization
local huge = math.huge
-- Dependancies
local _PATH = (...):match('(.+)%.search.astar$')
local Heap = require (_PATH.. '.core.bheap')
-- Updates G-cost
2017-10-26 22:56:55 +00:00
local function computeCost(node, neighbour, heuristic)
2016-12-11 19:24:52 +00:00
local mCost, heading = heuristic(neighbour, node) -- Heuristics.EUCLIDIAN(neighbour, node)
if node._g + mCost < neighbour._g then
neighbour._parent = node
neighbour._g = node._g + mCost
2017-10-28 00:24:48 +00:00
neighbour.heading = heading
2016-12-11 19:24:52 +00:00
end
end
-- Updates vertex node-neighbour
2017-10-26 22:56:55 +00:00
local function updateVertex(openList, node, neighbour, endNode, heuristic)
2016-12-11 19:24:52 +00:00
local oldG = neighbour._g
2017-10-26 22:56:55 +00:00
computeCost(node, neighbour, heuristic)
2016-12-11 19:24:52 +00:00
if neighbour._g < oldG then
2017-10-26 22:56:55 +00:00
if neighbour._opened then neighbour._opened = false end
neighbour._h = heuristic(endNode, neighbour)
neighbour._f = neighbour._g + neighbour._h
openList:push(neighbour)
neighbour._opened = true
2016-12-11 19:24:52 +00:00
end
end
2018-01-24 22:39:38 +00:00
-- Calculates a path.
-- Returns the path from location `<startX, startY>` to location `<endX, endY>`.
return function (finder, startNode, endNode, toClear)
2016-12-11 19:24:52 +00:00
local openList = Heap()
startNode._g = 0
2017-10-26 22:56:55 +00:00
startNode._h = finder._heuristic(endNode, startNode)
2016-12-11 19:24:52 +00:00
startNode._f = startNode._g + startNode._h
openList:push(startNode)
toClear[startNode] = true
startNode._opened = true
while not openList:empty() do
local node = openList:pop()
node._closed = true
if node == endNode then return node end
2017-10-26 22:56:55 +00:00
local neighbours = finder._grid:getNeighbours(node)
2016-12-11 19:24:52 +00:00
for i = 1,#neighbours do
local neighbour = neighbours[i]
if not neighbour._closed then
toClear[neighbour] = true
if not neighbour._opened then
neighbour._g = huge
2017-10-26 22:56:55 +00:00
neighbour._parent = nil
2016-12-11 19:24:52 +00:00
end
2017-10-26 22:56:55 +00:00
updateVertex(openList, node, neighbour, endNode, finder._heuristic)
end
2016-12-11 19:24:52 +00:00
end
--[[
2017-10-28 00:24:48 +00:00
printf('x:%d y:%d z:%d g:%d', node.x, node.y, node.z, node._g)
2016-12-11 19:24:52 +00:00
for i = 1,#neighbours do
local n = neighbours[i]
2017-10-28 00:24:48 +00:00
printf('x:%d y:%d z:%d f:%f g:%f h:%d', n.x, n.y, n.z, n._f, n._g, n.heading or -1)
2016-12-11 19:24:52 +00:00
end
--]]
end
2017-10-26 22:56:55 +00:00
return nil
2016-12-11 19:24:52 +00:00
end
end