format and installer branches

This commit is contained in:
kepler155c@gmail.com
2018-01-24 17:39:38 -05:00
parent 1eea0d7cd8
commit 5a32fe208e
80 changed files with 10742 additions and 10156 deletions

View File

@@ -14,9 +14,9 @@
--
--[[
Notes:
This lighter implementation of binary heaps, based on :
https://github.com/Yonaba/Binary-Heaps
Notes:
This lighter implementation of binary heaps, based on :
https://github.com/Yonaba/Binary-Heaps
--]]
if (...) then

View File

@@ -9,16 +9,16 @@
--
if (...) then
local Node = {}
Node.__index = Node
local Node = {}
Node.__index = Node
function Node:new(x,y,z)
return setmetatable({x = x, y = y, z = z }, Node)
end
function Node:new(x,y,z)
return setmetatable({x = x, y = y, z = z }, Node)
end
-- Enables the use of operator '<' to compare nodes.
-- Will be used to sort a collection of nodes in a binary heap on the basis of their F-cost
function Node.__lt(A,B) return (A._f < B._f) end
-- Enables the use of operator '<' to compare nodes.
-- Will be used to sort a collection of nodes in a binary heap on the basis of their F-cost
function Node.__lt(A,B) return (A._f < B._f) end
function Node:getX() return self.x end
function Node:getY() return self.y end
@@ -33,7 +33,7 @@ if (...) then
return self
end
return setmetatable(Node,
return setmetatable(Node,
{__call = function(_,...)
return Node:new(...)
end}

View File

@@ -8,60 +8,60 @@
if (...) then
local t_remove = table.remove
local t_remove = table.remove
local Path = {}
Path.__index = Path
local Path = {}
Path.__index = Path
function Path:new()
return setmetatable({_nodes = {}}, Path)
end
function Path:new()
return setmetatable({_nodes = {}}, Path)
end
--- Iterates on each single `node` along a `path`. At each step of iteration,
-- returns the `node` plus a count value. Aliased as @{Path:nodes}
--- Iterates on each single `node` along a `path`. At each step of iteration,
-- returns the `node` plus a count value. Aliased as @{Path:nodes}
-- @usage
-- for node, count in p:iter() do
-- ...
-- end
function Path:nodes()
local i = 1
return function()
if self._nodes[i] then
i = i+1
return self._nodes[i-1],i-1
end
end
end
function Path:nodes()
local i = 1
return function()
if self._nodes[i] then
i = i+1
return self._nodes[i-1],i-1
end
end
end
--- `Path` compression modifier. Given a `path`, eliminates useless nodes to return a lighter `path`
-- consisting of straight moves. Does the opposite of @{Path:fill}
-- @class function
-- @treturn path self (the calling `path` itself, can be chained)
-- @see Path:fill
-- @usage p:filter()
function Path:filter()
local i = 2
local xi,yi,zi,dx,dy,dz, olddx, olddy, olddz
xi,yi,zi = self._nodes[i].x, self._nodes[i].y, self._nodes[i].z
dx, dy,dz = xi - self._nodes[i-1].x, yi-self._nodes[i-1].y, zi-self._nodes[i-1].z
while true do
olddx, olddy, olddz = dx, dy, dz
if self._nodes[i+1] then
i = i+1
xi, yi, zi = self._nodes[i].x, self._nodes[i].y, self._nodes[i].z
dx, dy, dz = xi - self._nodes[i-1].x, yi - self._nodes[i-1].y, zi - self._nodes[i-1].z
if olddx == dx and olddy == dy and olddz == dz then
t_remove(self._nodes, i-1)
i = i - 1
end
else break end
end
return self
end
--- `Path` compression modifier. Given a `path`, eliminates useless nodes to return a lighter `path`
-- consisting of straight moves. Does the opposite of @{Path:fill}
-- @class function
-- @treturn path self (the calling `path` itself, can be chained)
-- @see Path:fill
-- @usage p:filter()
function Path:filter()
local i = 2
local xi,yi,zi,dx,dy,dz, olddx, olddy, olddz
xi,yi,zi = self._nodes[i].x, self._nodes[i].y, self._nodes[i].z
dx, dy,dz = xi - self._nodes[i-1].x, yi-self._nodes[i-1].y, zi-self._nodes[i-1].z
while true do
olddx, olddy, olddz = dx, dy, dz
if self._nodes[i+1] then
i = i+1
xi, yi, zi = self._nodes[i].x, self._nodes[i].y, self._nodes[i].z
dx, dy, dz = xi - self._nodes[i-1].x, yi - self._nodes[i-1].y, zi - self._nodes[i-1].z
if olddx == dx and olddy == dy and olddz == dz then
t_remove(self._nodes, i-1)
i = i - 1
end
else break end
end
return self
end
return setmetatable(Path,
{__call = function(_,...)
return Path:new(...)
end
})
return setmetatable(Path,
{__call = function(_,...)
return Path:new(...)
end
})
end

View File

@@ -20,19 +20,19 @@ if (...) then
end
-- Extract a path from a given start/end position
local function traceBackPath(finder, node, startNode)
local path = Path:new()
path._grid = finder._grid
while true do
if node._parent then
t_insert(path._nodes,1,node)
node = node._parent
else
t_insert(path._nodes,1,startNode)
return path
end
end
end
local function traceBackPath(finder, node, startNode)
local path = Path:new()
path._grid = finder._grid
while true do
if node._parent then
t_insert(path._nodes,1,node)
node = node._parent
else
t_insert(path._nodes,1,startNode)
return path
end
end
end
-- Lookup for value in a table
local indexOf = function(t,v)
@@ -43,9 +43,9 @@ if (...) then
end
-- Is i out of range
local function outOfRange(i,low,up)
return (i< low or i > up)
end
local function outOfRange(i,low,up)
return (i< low or i > up)
end
return {
arraySize = arraySize,

View File

@@ -9,93 +9,93 @@
if (...) then
-- Dependencies
local _PATH = (...):gsub('%.grid$','')
local _PATH = (...):gsub('%.grid$','')
-- Local references
local Utils = require (_PATH .. '.core.utils')
local Node = require (_PATH .. '.core.node')
local Utils = require (_PATH .. '.core.utils')
local Node = require (_PATH .. '.core.node')
-- Local references
local setmetatable = setmetatable
-- Offsets for straights moves
local straightOffsets = {
{x = 1, y = 0, z = 0} --[[W]], {x = -1, y = 0, z = 0}, --[[E]]
{x = 0, y = 1, z = 0} --[[S]], {x = 0, y = -1, z = 0}, --[[N]]
{x = 0, y = 0, z = 1} --[[U]], {x = 0, y = -0, z = -1}, --[[D]]
}
-- Offsets for straights moves
local straightOffsets = {
{x = 1, y = 0, z = 0} --[[W]], {x = -1, y = 0, z = 0}, --[[E]]
{x = 0, y = 1, z = 0} --[[S]], {x = 0, y = -1, z = 0}, --[[N]]
{x = 0, y = 0, z = 1} --[[U]], {x = 0, y = -0, z = -1}, --[[D]]
}
local Grid = {}
Grid.__index = Grid
local Grid = {}
Grid.__index = Grid
function Grid:new(dim)
local newGrid = { }
newGrid._min_x, newGrid._max_x = dim.x, dim.ex
newGrid._min_y, newGrid._max_y = dim.y, dim.ey
newGrid._min_z, newGrid._max_z = dim.z, dim.ez
newGrid._nodes = { }
newGrid._width = (newGrid._max_x-newGrid._min_x)+1
newGrid._height = (newGrid._max_y-newGrid._min_y)+1
newGrid._length = (newGrid._max_z-newGrid._min_z)+1
return setmetatable(newGrid,Grid)
end
function Grid:new(dim)
local newGrid = { }
newGrid._min_x, newGrid._max_x = dim.x, dim.ex
newGrid._min_y, newGrid._max_y = dim.y, dim.ey
newGrid._min_z, newGrid._max_z = dim.z, dim.ez
newGrid._nodes = { }
newGrid._width = (newGrid._max_x-newGrid._min_x)+1
newGrid._height = (newGrid._max_y-newGrid._min_y)+1
newGrid._length = (newGrid._max_z-newGrid._min_z)+1
return setmetatable(newGrid,Grid)
end
function Grid:isWalkableAt(x, y, z)
local node = self:getNodeAt(x,y,z)
return node and node.walkable ~= 1
end
function Grid:isWalkableAt(x, y, z)
local node = self:getNodeAt(x,y,z)
return node and node.walkable ~= 1
end
function Grid:getWidth()
return self._width
end
function Grid:getWidth()
return self._width
end
function Grid:getHeight()
return self._height
end
function Grid:getHeight()
return self._height
end
function Grid:getNodes()
return self._nodes
end
function Grid:getNodes()
return self._nodes
end
function Grid:getBounds()
return self._min_x, self._min_y, self._min_z, self._max_x, self._max_y, self._max_z
end
--- Returns neighbours. The returned value is an array of __walkable__ nodes neighbouring a given `node`.
-- @treturn {node,...} an array of nodes neighbouring a given node
function Grid:getNeighbours(node)
--- Returns neighbours. The returned value is an array of __walkable__ nodes neighbouring a given `node`.
-- @treturn {node,...} an array of nodes neighbouring a given node
function Grid:getNeighbours(node)
local neighbours = {}
for i = 1,#straightOffsets do
local n = self:getNodeAt(
node.x + straightOffsets[i].x,
node.y + straightOffsets[i].y,
node.z + straightOffsets[i].z
)
if n and self:isWalkableAt(n.x, n.y, n.z) then
neighbours[#neighbours+1] = n
end
end
for i = 1,#straightOffsets do
local n = self:getNodeAt(
node.x + straightOffsets[i].x,
node.y + straightOffsets[i].y,
node.z + straightOffsets[i].z
)
if n and self:isWalkableAt(n.x, n.y, n.z) then
neighbours[#neighbours+1] = n
end
end
return neighbours
end
return neighbours
end
function Grid:getNodeAt(x,y,z)
if not x or not y or not z then return end
if Utils.outOfRange(x,self._min_x,self._max_x) then return end
if Utils.outOfRange(y,self._min_y,self._max_y) then return end
if Utils.outOfRange(z,self._min_z,self._max_z) then return end
if not x or not y or not z then return end
if Utils.outOfRange(x,self._min_x,self._max_x) then return end
if Utils.outOfRange(y,self._min_y,self._max_y) then return end
if Utils.outOfRange(z,self._min_z,self._max_z) then return end
-- inefficient
if not self._nodes[y] then self._nodes[y] = {} end
if not self._nodes[y][x] then self._nodes[y][x] = {} end
if not self._nodes[y][x][z] then self._nodes[y][x][z] = Node:new(x,y,z) end
return self._nodes[y][x][z]
end
-- inefficient
if not self._nodes[y] then self._nodes[y] = {} end
if not self._nodes[y][x] then self._nodes[y][x] = {} end
if not self._nodes[y][x][z] then self._nodes[y][x][z] = Node:new(x,y,z) end
return self._nodes[y][x][z]
end
return setmetatable(Grid,{
__call = function(self,...)
return self:new(...)
end
})
return setmetatable(Grid,{
__call = function(self,...)
return self:new(...)
end
})
end

View File

@@ -1,31 +1,16 @@
--[[
The following License applies to all files within the jumper directory.
The following License applies to all files within the jumper directory.
Note that this is only a partial copy of the full jumper code base. Also,
the code was modified to support 3D maps.
Note that this is only a partial copy of the full jumper code base. Also,
the code was modified to support 3D maps.
--]]
--[[
This work is under MIT-LICENSE
Copyright (c) 2012-2013 Roland Yonaba.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
-- https://opensource.org/licenses/MIT
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
--]]
local _VERSION = ""
@@ -33,87 +18,87 @@ local _RELEASEDATE = ""
if (...) then
-- Dependencies
local _PATH = (...):gsub('%.pathfinder$','')
-- Dependencies
local _PATH = (...):gsub('%.pathfinder$','')
local Utils = require (_PATH .. '.core.utils')
-- Internalization
local pairs = pairs
local assert = assert
local setmetatable = setmetatable
-- Internalization
local pairs = pairs
local assert = assert
local setmetatable = setmetatable
--- Finders (search algorithms implemented). Refers to the search algorithms actually implemented in Jumper.
-- <li>[A*](http://en.wikipedia.org/wiki/A*_search_algorithm)</li>
local Finders = {
['ASTAR'] = require (_PATH .. '.search.astar'),
}
local Finders = {
['ASTAR'] = require (_PATH .. '.search.astar'),
}
-- Will keep track of all nodes expanded during the search
-- to easily reset their properties for the next pathfinding call
local toClear = {}
-- Will keep track of all nodes expanded during the search
-- to easily reset their properties for the next pathfinding call
local toClear = {}
-- Performs a traceback from the goal node to the start node
-- Only happens when the path was found
-- Performs a traceback from the goal node to the start node
-- Only happens when the path was found
local Pathfinder = {}
Pathfinder.__index = Pathfinder
local Pathfinder = {}
Pathfinder.__index = Pathfinder
function Pathfinder:new(heuristic)
local newPathfinder = {}
setmetatable(newPathfinder, Pathfinder)
self._finder = Finders.ASTAR
self._heuristic = heuristic
return newPathfinder
end
function Pathfinder:new(heuristic)
local newPathfinder = {}
setmetatable(newPathfinder, Pathfinder)
self._finder = Finders.ASTAR
self._heuristic = heuristic
return newPathfinder
end
function Pathfinder:setGrid(grid)
self._grid = grid
return self
end
--- Calculates a `path`. Returns the `path` from start to end location
-- Both locations must exist on the collision map. The starting location can be unwalkable.
-- @treturn path a path (array of nodes) when found, otherwise nil
-- @usage local path = myFinder:getPath(1,1,5,5)
function Pathfinder:getPath(startX, startY, startZ, ih, endX, endY, endZ, oh)
self:reset()
local startNode = self._grid:getNodeAt(startX, startY, startZ)
local endNode = self._grid:getNodeAt(endX, endY, endZ)
if not startNode or not endNode then
return nil
end
startNode.heading = ih
endNode.heading = oh
assert(startNode, ('Invalid location [%d, %d, %d]'):format(startX, startY, startZ))
assert(endNode and self._grid:isWalkableAt(endX, endY, endZ),
('Invalid or unreachable location [%d, %d, %d]'):format(endX, endY, endZ))
local _endNode = self._finder(self, startNode, endNode, toClear)
if _endNode then
return Utils.traceBackPath(self, _endNode, startNode)
end
return nil
end
--- Resets the `pathfinder`. This function is called internally between
-- successive pathfinding calls, so you should not
-- use it explicitely, unless under specific circumstances.
-- @class function
-- @treturn pathfinder self (the calling `pathfinder` itself, can be chained)
-- @usage local path, len = myFinder:getPath(1,1,5,5)
function Pathfinder:reset()
for node in pairs(toClear) do node:reset() end
toClear = {}
function Pathfinder:setGrid(grid)
self._grid = grid
return self
end
-- Returns Pathfinder class
--- Calculates a `path`. Returns the `path` from start to end location
-- Both locations must exist on the collision map. The starting location can be unwalkable.
-- @treturn path a path (array of nodes) when found, otherwise nil
-- @usage local path = myFinder:getPath(1,1,5,5)
function Pathfinder:getPath(startX, startY, startZ, ih, endX, endY, endZ, oh)
self:reset()
local startNode = self._grid:getNodeAt(startX, startY, startZ)
local endNode = self._grid:getNodeAt(endX, endY, endZ)
if not startNode or not endNode then
return nil
end
startNode.heading = ih
endNode.heading = oh
assert(startNode, ('Invalid location [%d, %d, %d]'):format(startX, startY, startZ))
assert(endNode and self._grid:isWalkableAt(endX, endY, endZ),
('Invalid or unreachable location [%d, %d, %d]'):format(endX, endY, endZ))
local _endNode = self._finder(self, startNode, endNode, toClear)
if _endNode then
return Utils.traceBackPath(self, _endNode, startNode)
end
return nil
end
--- Resets the `pathfinder`. This function is called internally between
-- successive pathfinding calls, so you should not
-- use it explicitely, unless under specific circumstances.
-- @class function
-- @treturn pathfinder self (the calling `pathfinder` itself, can be chained)
-- @usage local path, len = myFinder:getPath(1,1,5,5)
function Pathfinder:reset()
for node in pairs(toClear) do node:reset() end
toClear = {}
return self
end
-- Returns Pathfinder class
Pathfinder._VERSION = _VERSION
Pathfinder._RELEASEDATE = _RELEASEDATE
return setmetatable(Pathfinder,{
__call = function(self,...)
return self:new(...)
end
})
return setmetatable(Pathfinder,{
__call = function(self,...)
return self:new(...)
end
})
end

View File

@@ -35,9 +35,9 @@ if (...) then
end
end
-- Calculates a path.
-- Returns the path from location `<startX, startY>` to location `<endX, endY>`.
return function (finder, startNode, endNode, toClear)
-- Calculates a path.
-- Returns the path from location `<startX, startY>` to location `<endX, endY>`.
return function (finder, startNode, endNode, toClear)
local openList = Heap()
startNode._g = 0
startNode._h = finder._heuristic(endNode, startNode)