Showing preview only (256K chars total). Download the full file or copy to clipboard to get everything.
Repository: Yonaba/Jumper
Branch: master
Commit: 441176b33536
Files: 45
Total size: 242.0 KB
Directory structure:
gitextract_lrl520tn/
├── .gitignore
├── LICENSE.txt
├── README.md
├── docs/
│ ├── examples/
│ │ ├── annotatedpathing.lua.html
│ │ ├── customheuristics.lua.html
│ │ ├── makeclearance.lua.html
│ │ └── simpleexample.lua.html
│ ├── index.html
│ └── modules/
│ ├── core.bheap.html
│ ├── core.heuristics.html
│ ├── core.node.html
│ ├── core.path.html
│ ├── grid.html
│ └── pathfinder.html
├── examples/
│ ├── annotatedPathing.lua
│ ├── customHeuristics.lua
│ ├── makeClearance.lua
│ └── simpleExample.lua
├── jumper/
│ ├── core/
│ │ ├── assert.lua
│ │ ├── bheap.lua
│ │ ├── heuristics.lua
│ │ ├── lookuptable.lua
│ │ ├── node.lua
│ │ ├── path.lua
│ │ └── utils.lua
│ ├── grid.lua
│ ├── pathfinder.lua
│ └── search/
│ ├── astar.lua
│ ├── bfs.lua
│ ├── dfs.lua
│ ├── dijkstra.lua
│ ├── jps.lua
│ └── thetastar.lua
├── rockspecs/
│ ├── jumper-1.6-2.rockspec
│ ├── jumper-1.6.3-1.rockspec
│ ├── jumper-1.7.0-1.rockspec
│ ├── jumper-1.8.0.rockspec
│ └── jumper-1.8.1-1.rockspec
├── specs/
│ ├── bheap_specs.lua
│ ├── grid_specs.lua
│ ├── heuristics_specs.lua
│ ├── node_specs.lua
│ ├── path_specs.lua
│ └── pathfinder_specs.lua
└── version_history.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.yml
*.ld
*.bat
tsc
test*
ldoc*
telescope*
hkl
debug*
profiler*
================================================
FILE: LICENSE.txt
================================================
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:
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.
================================================
FILE: README.md
================================================
Jumper
======
[](https://gitter.im/Yonaba/Jumper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[](http://travis-ci.org/Yonaba/Jumper)
__Jumper__ is a pathfinding library designed for grid-based games. It aims to be __fast__ and __lightweight__.
It features a wide range of search algorithms, built within a clean interface with
chaining features which makes it __very friendly and easy to use__.<br/>
__Jumper__ is written in pure [Lua][]. Thus, it is not __framework-related__ and can be used in any project embedding [Lua][] code.
## Installation
The current repository can be retrieved locally on your computer via:
### Bash
```bash
git clone git://github.com/Yonaba/Jumper.git
````
### Download (latest)
* __Development version__: [zip](http://github.com/Yonaba/Jumper/zipball/master) | [tar.gz](http://github.com/Yonaba/Jumper/tarball/master) ( __please do not use this!__ )
* __Latest stable release (1.8.1)__: [zip](http://github.com/Yonaba/Jumper/archive/jumper-1.8.1-1.zip) | [tar.gz](http://github.com/Yonaba/Jumper/archive/jumper-1.8.1-1.tar.gz) ( __Recommended!__ )
* __All stable releases__: [tags](http://github.com/Yonaba/Jumper/tags)
### LuaRocks
```bash
luarocks install jumper
````
### MoonRocks
```bash
luarocks install --server=http://rocks.moonscript.org/manifests/Yonaba jumper
````
## Installing Jumper
Copy the contents of the folder named [jumper](http://github.com/Yonaba/Jumper/blob/master/jumper) and its contents and place it inside your projet. Use *require* function to import any module of the library.
## A Simple Example of Use
Here is a simple example explaining how to use Jumper:
```lua
-- Usage Example
-- First, set a collision map
local map = {
{0,1,0,1,0},
{0,1,0,1,0},
{0,1,1,1,0},
{0,0,0,0,0},
}
-- Value for walkable tiles
local walkable = 0
-- Library setup
local Grid = require ("jumper.grid") -- The grid class
local Pathfinder = require ("jumper.pathfinder") -- The pathfinder class
-- Creates a grid object
local grid = Grid(map)
-- Creates a pathfinder object using Jump Point Search
local myFinder = Pathfinder(grid, 'JPS', walkable)
-- Define start and goal locations coordinates
local startx, starty = 1,1
local endx, endy = 5,1
-- Calculates the path, and its length
local path = myFinder:getPath(startx, starty, endx, endy)
if path then
print(('Path found! Length: %.2f'):format(path:getLength()))
for node, count in path:nodes() do
print(('Step: %d - x: %d - y: %d'):format(count, node:getX(), node:getY()))
end
end
--> Output:
--> Path found! Length: 8.83
--> Step: 1 - x: 1 - y: 1
--> Step: 2 - x: 1 - y: 3
--> Step: 3 - x: 2 - y: 4
--> Step: 4 - x: 4 - y: 4
--> Step: 5 - x: 5 - y: 3
--> Step: 6 - x: 5 - y: 1
````
## Specs
Specs tests have been included.<br/>
You can run them using [Telescope](http://github.com/norman/telescope) with the following command
from the [root](http://github.com/Yonaba/Jumper/blob/master/jumper) folder:
```
tsc -f specs/*
```
## Credits and Thanks
* [Daniel Harabor][], [Alban Grastien][] : for the [Jump Point Search](http://harablog.wordpress.com/2011/09/07/jump-point-search/) algorithm.<br/>
* [XueXiao Xu][], [Nathan Witmer][]: for the [JavaScript port][] of the algorithm.<br/>
* [Steve Donovan](http://github.com/stevedonovan): for the awesome documentation generator tool [LDoc](http://github.com/stevedonovan/ldoc/).
* [Srdjan Markovic](http://github.com/srdjan-m), for his tremendous feedback.
## License
This work is under [MIT-LICENSE][]<br/>
Copyright (c) 2012-2013 Roland Yonaba.
> Permission is hereby granted, free of charge, to any person obtaining a copy<br/>
> of this software and associated documentation files (the "Software"), to deal<br/>
> in the Software without restriction, including without limitation the rights<br/>
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell<br/>
> copies of the Software, and to permit persons to whom the Software is<br/>
> furnished to do so, subject to the following conditions:<br/>
><br/>
> The above copyright notice and this permission notice shall be included in<br/>
> all copies or substantial portions of the Software.<br/>
><br/>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br/>
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br/>
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE<br/>
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br/>
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,<br/>
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN<br/>
> THE SOFTWARE.
[Jump Point Search]: http://harablog.wordpress.com/2011/09/07/jump-point-search/
[Lua]: http://lua.org
[L�ve]: http://love2d.org
[L�ve2d]: http://love2d.org
[L�ve 0.8.0 Framework]: http://love2d.org
[Dragon Age : Origins]: http://dragonage.bioware.com
[Moving AI]: http://movingai.com
[Nathan Witmer]: http://github.com/aniero
[XueXiao Xu]: http://github.com/qiao
[JavaScript port]: http://github.com/qiao/PathFinding.js
[Alban Grastien]: http://www.grastien.net/ban/
[Daniel Harabor]: http://users.cecs.anu.edu.au/~dharabor/home.html
[the algorithm and the technical papers]: http://users.cecs.anu.edu.au/~dharabor/data/papers/harabor-grastien-aaai11.pdf
[MIT-LICENSE]: http://www.opensource.org/licenses/mit-license.php
[heuristics.lua]: http://github.com/Yonaba/Jumper/blob/master/Jumper/core/heuristics.lua
[](https://bitdeli.com/free "Bitdeli Badge")
[](http://githalytics.com/Yonaba/Jumper)
================================================
FILE: docs/examples/annotatedpathing.lua.html
================================================
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Jumper documentation</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Jumper</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Examples</h2>
<ul>
<li><strong>annotatedpathing.lua</strong></li>
<li><a href="../examples/customheuristics.lua.html">customheuristics.lua</a></li>
<li><a href="../examples/makeclearance.lua.html">makeclearance.lua</a></li>
<li><a href="../examples/simpleexample.lua.html">simpleexample.lua</a></li>
</ul>
<h2>Modules</h2>
<ul>
<li><a href="../modules/core.bheap.html">core.bheap</a></li>
<li><a href="../modules/core.heuristics.html">core.heuristics</a></li>
<li><a href="../modules/core.node.html">core.node</a></li>
<li><a href="../modules/core.path.html">core.path</a></li>
<li><a href="../modules/grid.html">grid</a></li>
<li><a href="../modules/pathfinder.html">pathfinder</a></li>
</ul>
</div>
<div id="content">
<h1>Example <code>annotatedpathing.lua</code></h1>
<pre>
<span class="comment">-- Tests sample for clearance metrics calculation
</span><span class="comment">-- See Figure 10 at http://aigamedev.com/open/tutorial/clearance-based-pathfinding/
</span><span class="comment">-- Jump Point Search still has some flaws with clearance based pathfinding
</span>
<span class="keyword">local</span> Grid = <span class="global">require</span> <span class="string">'jumper.grid'</span>
<span class="keyword">local</span> PF = <span class="global">require</span> <span class="string">'jumper.pathfinder'</span>
<span class="keyword">local</span> map = {
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">2</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">2</span>,<span class="number">0</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">2</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">2</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">2</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>}
}
<span class="keyword">local</span> grid = Grid(map)
<span class="keyword">local</span> walkable = <span class="keyword">function</span>(v) <span class="keyword">return</span> v~=<span class="number">2</span> <span class="keyword">end</span>
<span class="keyword">local</span> finder = PF(grid, <span class="string">'ASTAR'</span>,walkable)
finder:annotateGrid()
<span class="keyword">local</span> finderNames = PF:getFinders()
<span class="keyword">local</span> sx, sy = <span class="number">1</span>,<span class="number">1</span>
<span class="keyword">local</span> ex, ey = <span class="number">9</span>,<span class="number">9</span>
<span class="keyword">local</span> agent_size = <span class="number">2</span>
<span class="keyword">for</span> i = <span class="number">1</span>,#finderNames <span class="keyword">do</span>
finder:setFinder(finderNames[i])
<span class="keyword">local</span> path = finder:getPath(sx, sy, ex, ey, agent_size)
<span class="global">print</span>((<span class="string">'Algorithm used: %s - Path %s'</span>)
:format(finder:getFinder(), path <span class="keyword">and</span> <span class="string">'found'</span> <span class="keyword">or</span> <span class="string">'not found'</span>))
<span class="keyword">if</span> path <span class="keyword">then</span>
<span class="keyword">for</span> node, count <span class="keyword">in</span> path:nodes() <span class="keyword">do</span>
<span class="global">print</span>((<span class="string">' Step %d. (%d,%d)'</span>)
:format(count, node:getPos()))
<span class="keyword">end</span>
<span class="keyword">end</span>
<span class="keyword">end</span></pre>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.2</a></i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>
================================================
FILE: docs/examples/customheuristics.lua.html
================================================
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Jumper documentation</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Jumper</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Examples</h2>
<ul>
<li><a href="../examples/annotatedpathing.lua.html">annotatedpathing.lua</a></li>
<li><strong>customheuristics.lua</strong></li>
<li><a href="../examples/makeclearance.lua.html">makeclearance.lua</a></li>
<li><a href="../examples/simpleexample.lua.html">simpleexample.lua</a></li>
</ul>
<h2>Modules</h2>
<ul>
<li><a href="../modules/core.bheap.html">core.bheap</a></li>
<li><a href="../modules/core.heuristics.html">core.heuristics</a></li>
<li><a href="../modules/core.node.html">core.node</a></li>
<li><a href="../modules/core.path.html">core.path</a></li>
<li><a href="../modules/grid.html">grid</a></li>
<li><a href="../modules/pathfinder.html">pathfinder</a></li>
</ul>
</div>
<div id="content">
<h1>Example <code>customheuristics.lua</code></h1>
<pre>
<span class="comment">--- Example of use for Heuristics
</span>
<span class="keyword">local</span> Grid = <span class="global">require</span> (<span class="string">"jumper.grid"</span>)
<span class="keyword">local</span> Pathfinder = <span class="global">require</span> (<span class="string">"jumper.pathfinder"</span>)
<span class="keyword">local</span> map = {
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>},
}
<span class="keyword">local</span> walkable = <span class="number">0</span>
<span class="keyword">local</span> grid = Grid(map)
<span class="keyword">local</span> myFinder = Pathfinder(grid, <span class="string">'ASTAR'</span>, walkable)
<span class="comment">-- Use Euclidian heuristic to evaluate distance
</span>myFinder:setHeuristic(<span class="string">'EUCLIDIAN'</span>)
myFinder:setHeuristic(<span class="string">'DIAGONAL'</span>)
myFinder:setHeuristic(<span class="string">'MANHATTAN'</span>)
<span class="comment">-- Custom
</span><span class="keyword">local</span> h = <span class="keyword">function</span>(nodeA, nodeB)
<span class="keyword">return</span> (<span class="number">0.1</span> * (<span class="global">math</span>.abs(nodeA:getX() - nodeB:getX()))
+ <span class="number">0.9</span> * (<span class="global">math</span>.abs(nodeA:getY() - nodeB:getY())))
<span class="keyword">end</span>
myFinder:setHeuristic(h)
<span class="keyword">local</span> p = myFinder:getPath(<span class="number">1</span>,<span class="number">1</span>, <span class="number">6</span>,<span class="number">5</span>)
<span class="keyword">for</span> node, count <span class="keyword">in</span> p:nodes() <span class="keyword">do</span>
<span class="global">print</span>((<span class="string">'%d. Node(%d,%d)'</span>):format(count, node:getX(), node:getY()))
<span class="keyword">end</span>
<span class="global">print</span>((<span class="string">'Path length: %.2f'</span>):format(p:getLength()))
<span class="comment">-- etc ...
</span></pre>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.2</a></i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>
================================================
FILE: docs/examples/makeclearance.lua.html
================================================
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Jumper documentation</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Jumper</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Examples</h2>
<ul>
<li><a href="../examples/annotatedpathing.lua.html">annotatedpathing.lua</a></li>
<li><a href="../examples/customheuristics.lua.html">customheuristics.lua</a></li>
<li><strong>makeclearance.lua</strong></li>
<li><a href="../examples/simpleexample.lua.html">simpleexample.lua</a></li>
</ul>
<h2>Modules</h2>
<ul>
<li><a href="../modules/core.bheap.html">core.bheap</a></li>
<li><a href="../modules/core.heuristics.html">core.heuristics</a></li>
<li><a href="../modules/core.node.html">core.node</a></li>
<li><a href="../modules/core.path.html">core.path</a></li>
<li><a href="../modules/grid.html">grid</a></li>
<li><a href="../modules/pathfinder.html">pathfinder</a></li>
</ul>
</div>
<div id="content">
<h1>Example <code>makeclearance.lua</code></h1>
<pre>
<span class="comment">-- Tests sample for clearance metrics calculation
</span><span class="comment">-- See Figure 10 at http://aigamedev.com/open/tutorial/clearance-based-pathfinding/
</span><span class="keyword">local</span> Grid = <span class="global">require</span> <span class="string">'jumper.grid'</span>
<span class="keyword">local</span> PF = <span class="global">require</span> <span class="string">'jumper.pathfinder'</span>
<span class="keyword">local</span> map = {
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">2</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">2</span>,<span class="number">0</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">2</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">2</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">2</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>}
}
<span class="keyword">local</span> grid = Grid(map)
<span class="keyword">local</span> walkable = <span class="keyword">function</span>(v) <span class="keyword">return</span> v~=<span class="number">2</span> <span class="keyword">end</span>
<span class="keyword">local</span> finder = PF(grid, <span class="string">'ASTAR'</span>,walkable)
finder:annotateGrid()
<span class="keyword">for</span> y = <span class="number">1</span>, #map <span class="keyword">do</span>
<span class="keyword">local</span> s = <span class="string">''</span>
<span class="keyword">for</span> x = <span class="number">1</span>, #map[y] <span class="keyword">do</span>
<span class="keyword">local</span> node = grid:getNodeAt(x,y)
s = (s .. <span class="string">' '</span> .. node:getClearance(walkable))
<span class="keyword">end</span>
<span class="global">print</span>(s)
<span class="keyword">end</span>
<span class="comment">-- Expected output
</span><span class="comment">-- 6 6 5 5 4 4 4 3 2 1
</span><span class="comment">-- 6 5 5 4 4 3 3 3 2 1
</span><span class="comment">-- 6 5 4 4 3 3 2 2 2 1
</span><span class="comment">-- 6 5 4 3 3 2 2 1 1 1
</span><span class="comment">-- 6 5 4 3 2 2 1 1 0 1
</span><span class="comment">-- 5 5 4 3 2 1 1 0 1 1
</span><span class="comment">-- 4 4 4 3 2 1 0 2 1 0
</span><span class="comment">-- 3 3 3 3 3 3 3 2 1 0
</span><span class="comment">-- 2 2 2 2 2 2 2 2 2 1
</span><span class="comment">-- 1 1 1 1 1 1 1 1 1 1
</span></pre>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.2</a></i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>
================================================
FILE: docs/examples/simpleexample.lua.html
================================================
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Jumper documentation</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Jumper</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Examples</h2>
<ul>
<li><a href="../examples/annotatedpathing.lua.html">annotatedpathing.lua</a></li>
<li><a href="../examples/customheuristics.lua.html">customheuristics.lua</a></li>
<li><a href="../examples/makeclearance.lua.html">makeclearance.lua</a></li>
<li><strong>simpleexample.lua</strong></li>
</ul>
<h2>Modules</h2>
<ul>
<li><a href="../modules/core.bheap.html">core.bheap</a></li>
<li><a href="../modules/core.heuristics.html">core.heuristics</a></li>
<li><a href="../modules/core.node.html">core.node</a></li>
<li><a href="../modules/core.path.html">core.path</a></li>
<li><a href="../modules/grid.html">grid</a></li>
<li><a href="../modules/pathfinder.html">pathfinder</a></li>
</ul>
</div>
<div id="content">
<h1>Example <code>simpleexample.lua</code></h1>
<pre>
<span class="comment">--- Very minimal usage example for Jumper
</span>
<span class="comment">-- Set up a collision map
</span><span class="keyword">local</span> map = {
{<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">1</span>,<span class="number">0</span>},
{<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>},
}
<span class="comment">-- Value for walkable tiles
</span><span class="keyword">local</span> walkable = <span class="number">0</span>
<span class="comment">-- Library setup
</span><span class="comment">-- Calls the grid class
</span><span class="keyword">local</span> Grid = <span class="global">require</span> (<span class="string">"jumper.grid"</span>)
<span class="comment">-- Calls the pathfinder class
</span><span class="keyword">local</span> Pathfinder = <span class="global">require</span> (<span class="string">"jumper.pathfinder"</span>)
<span class="comment">-- Creates a grid object
</span><span class="keyword">local</span> grid = Grid(map)
<span class="comment">-- Creates a pathfinder object using Jump Point Search algorithm
</span><span class="keyword">local</span> myFinder = Pathfinder(grid, <span class="string">'JPS'</span>, walkable)
<span class="comment">-- Define start and goal locations coordinates
</span><span class="keyword">local</span> startx, starty = <span class="number">1</span>,<span class="number">1</span>
<span class="keyword">local</span> endx, endy = <span class="number">5</span>,<span class="number">1</span>
<span class="comment">-- Calculates the path, and its length
</span><span class="keyword">local</span> path = myFinder:getPath(startx, starty, endx, endy)
<span class="comment">-- Pretty-printing the results
</span><span class="keyword">if</span> path <span class="keyword">then</span>
<span class="global">print</span>((<span class="string">'Path found! Length: %.2f'</span>):format(path:getLength()))
<span class="keyword">for</span> node, count <span class="keyword">in</span> path:nodes() <span class="keyword">do</span>
<span class="global">print</span>((<span class="string">'Step: %d - x: %d - y: %d'</span>):format(count, node:getX(), node:getY()))
<span class="keyword">end</span>
<span class="keyword">end</span></pre>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.2</a></i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>
================================================
FILE: docs/index.html
================================================
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Jumper documentation</title>
<link rel="stylesheet" href="ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Jumper</h1>
<h2>Modules</h2>
<ul>
<li><a href="modules/core.bheap.html">core.bheap</a></li>
<li><a href="modules/core.heuristics.html">core.heuristics</a></li>
<li><a href="modules/core.node.html">core.node</a></li>
<li><a href="modules/core.path.html">core.path</a></li>
<li><a href="modules/grid.html">grid</a></li>
<li><a href="modules/pathfinder.html">pathfinder</a></li>
</ul>
<h2>Examples</h2>
<ul>
<li><a href="examples/annotatedpathing.lua.html">annotatedpathing.lua</a></li>
<li><a href="examples/customheuristics.lua.html">customheuristics.lua</a></li>
<li><a href="examples/makeclearance.lua.html">makeclearance.lua</a></li>
<li><a href="examples/simpleexample.lua.html">simpleexample.lua</a></li>
</ul>
</div>
<div id="content">
<h2>
<h2>Fast and lightweight pathfinding library for grid based games</h2>
</h2>
<h2>Modules</h2>
<table class="module_list">
<tr>
<td class="name" nowrap><a href="modules/core.bheap.html">core.bheap</a></td>
<td class="summary">A light implementation of Binary heaps data structure.</td>
</tr>
<tr>
<td class="name" nowrap><a href="modules/core.heuristics.html">core.heuristics</a></td>
<td class="summary">Heuristic functions for search algorithms.</td>
</tr>
<tr>
<td class="name" nowrap><a href="modules/core.node.html">core.node</a></td>
<td class="summary">The Node class.</td>
</tr>
<tr>
<td class="name" nowrap><a href="modules/core.path.html">core.path</a></td>
<td class="summary">The Path class.</td>
</tr>
<tr>
<td class="name" nowrap><a href="modules/grid.html">grid</a></td>
<td class="summary">The Grid class.</td>
</tr>
<tr>
<td class="name" nowrap><a href="modules/pathfinder.html">pathfinder</a></td>
<td class="summary">The Pathfinder class</td>
</tr>
</table>
<h2>Examples</h2>
<table class="module_list">
<tr>
<td class="name" nowrap><a href="examples/annotatedpathing.lua.html">annotatedpathing.lua</a></td>
<td class="summary"></td>
</tr>
<tr>
<td class="name" nowrap><a href="examples/customheuristics.lua.html">customheuristics.lua</a></td>
<td class="summary"></td>
</tr>
<tr>
<td class="name" nowrap><a href="examples/makeclearance.lua.html">makeclearance.lua</a></td>
<td class="summary"></td>
</tr>
<tr>
<td class="name" nowrap><a href="examples/simpleexample.lua.html">simpleexample.lua</a></td>
<td class="summary"></td>
</tr>
</table>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.2</a></i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>
================================================
FILE: docs/modules/core.bheap.html
================================================
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Jumper documentation</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Jumper</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Class_heap_">Class heap </a></li>
</ul>
<h2>Modules</h2>
<ul>
<li><strong>core.bheap</strong></li>
<li><a href="../modules/core.heuristics.html">core.heuristics</a></li>
<li><a href="../modules/core.node.html">core.node</a></li>
<li><a href="../modules/core.path.html">core.path</a></li>
<li><a href="../modules/grid.html">grid</a></li>
<li><a href="../modules/pathfinder.html">pathfinder</a></li>
</ul>
<h2>Examples</h2>
<ul>
<li><a href="../examples/annotatedpathing.lua.html">annotatedpathing.lua</a></li>
<li><a href="../examples/customheuristics.lua.html">customheuristics.lua</a></li>
<li><a href="../examples/makeclearance.lua.html">makeclearance.lua</a></li>
<li><a href="../examples/simpleexample.lua.html">simpleexample.lua</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>core.bheap</code></h1>
<p>A light implementation of Binary heaps data structure.</p>
<p> While running a search, some search algorithms (Astar, Dijkstra, Jump Point Search) have to maintains
a list of nodes called <strong>open list</strong>. Retrieve from this list the lowest cost node can be quite slow,
as it normally requires to skim through the full set of nodes stored in this list. This becomes a real
problem especially when dozens of nodes are being processed (on large maps). </p>
<p> The current module implements a <a href="http://www.policyalmanac.org/games/binaryHeaps.htm">binary heap</a>
data structure, from which the search algorithm will instantiate an open list, and cache the nodes being
examined during a search. As such, retrieving the lower-cost node is faster and globally makes the search end
up quickly.</p>
<p> This module is internally used by the library on purpose.
It should normally not be used explicitely, yet it remains fully accessible.</p>
<h2><a href="#Class_heap_">Class heap </a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#heap:empty">heap:empty ()</a></td>
<td class="summary">Checks if a <a href="../modules/core.bheap.html#Class_heap">heap</a> is empty</td>
</tr>
<tr>
<td class="name" nowrap><a href="#heap:clear">heap:clear ()</a></td>
<td class="summary">Clears the <a href="../modules/core.bheap.html#Class_heap">heap</a> (removes all items queued in the heap)</td>
</tr>
<tr>
<td class="name" nowrap><a href="#heap:push">heap:push (item)</a></td>
<td class="summary">Adds a new item in the <a href="../modules/core.bheap.html#Class_heap">heap</a> </td>
</tr>
<tr>
<td class="name" nowrap><a href="#heap:pop">heap:pop ()</a></td>
<td class="summary">Pops from the <a href="../modules/core.bheap.html#Class_heap">heap</a> .</td>
</tr>
<tr>
<td class="name" nowrap><a href="#heap:heapify">heap:heapify ( [item])</a></td>
<td class="summary">Restores the <a href="../modules/core.bheap.html#Class_heap">heap</a> property.</td>
</tr>
</table>
<br/>
<br/>
<h2><a name="Class_heap_"></a>Class heap </h2>
The <a href="../modules/core.bheap.html#Class_heap">heap</a> class.<br/>
This class is callable.
<em>Therefore,</em> <code>heap(...)</code> <em>is used to instantiate new heaps</em>.
<dl class="function">
<dt>
<a name = "heap:empty"></a>
<strong>heap:empty ()</strong>
</dt>
<dd>
Checks if a <a href="../modules/core.bheap.html#Class_heap">heap</a> is empty
<h3>Usage:</h3>
<ul>
<pre class="example">
if myHeap:empty() then
print('Heap is empty!')
end</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">bool</a></span>
<strong>true</strong> of no item is queued in the heap, <strong>false</strong> otherwise
</ol>
</dd>
<dt>
<a name = "heap:clear"></a>
<strong>heap:clear ()</strong>
</dt>
<dd>
Clears the <a href="../modules/core.bheap.html#Class_heap">heap</a> (removes all items queued in the heap)
<h3>Usage:</h3>
<ul>
<pre class="example">myHeap:clear()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/core.bheap.html#Class_heap">heap</a></span>
self (the calling <a href="../modules/core.bheap.html#Class_heap">heap</a> itself, can be chained)
</ol>
</dd>
<dt>
<a name = "heap:push"></a>
<strong>heap:push (item)</strong>
</dt>
<dd>
Adds a new item in the <a href="../modules/core.bheap.html#Class_heap">heap</a>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">item</span>
<span class="types"><span class="type">value</span></span>
a new value to be queued in the heap</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
myHeap:push(1)
-- or, with chaining
myHeap:push(1):push(2):push(4)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/core.bheap.html#Class_heap">heap</a></span>
self (the calling <a href="../modules/core.bheap.html#Class_heap">heap</a> itself, can be chained)
</ol>
</dd>
<dt>
<a name = "heap:pop"></a>
<strong>heap:pop ()</strong>
</dt>
<dd>
Pops from the <a href="../modules/core.bheap.html#Class_heap">heap</a> .
Removes and returns the lowest cost item (with respect to the comparison function being used) from the <a href="../modules/core.bheap.html#Class_heap">heap</a> .
<h3>Usage:</h3>
<ul>
<pre class="example">
while not myHeap:empty() do
local lowestValue = myHeap:pop()
...
end</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">value</span></span>
a value previously pushed into the heap
</ol>
</dd>
<dt>
<a name = "heap:heapify"></a>
<strong>heap:heapify ( [item])</strong>
</dt>
<dd>
Restores the <a href="../modules/core.bheap.html#Class_heap">heap</a> property.
Reorders the <a href="../modules/core.bheap.html#Class_heap">heap</a> with respect to the comparison function being used.
When given argument <strong>item</strong> (a value existing in the <a href="../modules/core.bheap.html#Class_heap">heap</a> ), will sort from that very item in the <a href="../modules/core.bheap.html#Class_heap">heap</a> .
Otherwise, the whole <a href="../modules/core.bheap.html#Class_heap">heap</a> will be cheacked.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">item</span>
<span class="types"><span class="type">value</span></span>
the modified value</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">myHeap:heapify()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/core.bheap.html#Class_heap">heap</a></span>
self (the calling <a href="../modules/core.bheap.html#Class_heap">heap</a> itself, can be chained)
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.2</a></i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>
================================================
FILE: docs/modules/core.heuristics.html
================================================
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Jumper documentation</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Jumper</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Functions">Functions</a></li>
</ul>
<h2>Modules</h2>
<ul>
<li><a href="../modules/core.bheap.html">core.bheap</a></li>
<li><strong>core.heuristics</strong></li>
<li><a href="../modules/core.node.html">core.node</a></li>
<li><a href="../modules/core.path.html">core.path</a></li>
<li><a href="../modules/grid.html">grid</a></li>
<li><a href="../modules/pathfinder.html">pathfinder</a></li>
</ul>
<h2>Examples</h2>
<ul>
<li><a href="../examples/annotatedpathing.lua.html">annotatedpathing.lua</a></li>
<li><a href="../examples/customheuristics.lua.html">customheuristics.lua</a></li>
<li><a href="../examples/makeclearance.lua.html">makeclearance.lua</a></li>
<li><a href="../examples/simpleexample.lua.html">simpleexample.lua</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>core.heuristics</code></h1>
<p>Heuristic functions for search algorithms.</p>
<p> A <a href="http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html">distance heuristic</a>
provides an <em>estimate of the optimal distance cost</em> from a given location to a target.
As such, it guides the pathfinder to the goal, helping it to decide which route is the best.</p>
<p> This script holds the definition of some built-in heuristics available through jumper.</p>
<p> Distance functions are internally used by the <a href="../modules/pathfinder.html#">pathfinder</a> to evaluate the optimal path
from the start location to the goal. These functions share the same prototype:</p>
<pre><code> local function myHeuristic(nodeA, nodeB)
-- function body
end
</code></pre>
<p> Jumper features some built-in distance heuristics, namely <code>MANHATTAN</code>, <code>EUCLIDIAN</code>, <code>DIAGONAL</code>, <code>CARDINTCARD</code>.
You can also supply your own heuristic function, following the same template as above.</p>
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Heuristics.MANHATTAN">Heuristics.MANHATTAN (nodeA, nodeB)</a></td>
<td class="summary">Manhattan distance.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Heuristics.EUCLIDIAN">Heuristics.EUCLIDIAN (nodeA, nodeB)</a></td>
<td class="summary">Euclidian distance.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Heuristics.DIAGONAL">Heuristics.DIAGONAL (nodeA, nodeB)</a></td>
<td class="summary">Diagonal distance.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Heuristics.CARDINTCARD">Heuristics.CARDINTCARD (nodeA, nodeB)</a></td>
<td class="summary">Cardinal/Intercardinal distance.</td>
</tr>
</table>
<br/>
<br/>
<h2><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "Heuristics.MANHATTAN"></a>
<strong>Heuristics.MANHATTAN (nodeA, nodeB)</strong>
</dt>
<dd>
Manhattan distance.
<br/>This heuristic is the default one being used by the <a href="../modules/pathfinder.html#">pathfinder</a> object.
<br/>Evaluates as <code>distance = |dx|+|dy|</code>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">nodeA</span>
<span class="types"><a class="type" href="../modules/core.node.html">node</a></span>
a node</li>
<li><span class="parameter">nodeB</span>
<span class="types"><a class="type" href="../modules/core.node.html">node</a></span>
another node</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
-- First method
pathfinder:setHeuristic('MANHATTAN')
-- Second method
local Distance = require ('jumper.core.heuristics')
pathfinder:setHeuristic(Distance.MANHATTAN)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">number</span></span>
the distance from <strong>nodeA</strong> to <strong>nodeB</strong>
</ol>
</dd>
<dt>
<a name = "Heuristics.EUCLIDIAN"></a>
<strong>Heuristics.EUCLIDIAN (nodeA, nodeB)</strong>
</dt>
<dd>
Euclidian distance.
<br/>Evaluates as <code>distance = squareRoot(dx<em>dx+dy</em>dy)</code>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">nodeA</span>
<span class="types"><a class="type" href="../modules/core.node.html">node</a></span>
a node</li>
<li><span class="parameter">nodeB</span>
<span class="types"><a class="type" href="../modules/core.node.html">node</a></span>
another node</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
-- First method
pathfinder:setHeuristic('EUCLIDIAN')
-- Second method
local Distance = require ('jumper.core.heuristics')
pathfinder:setHeuristic(Distance.EUCLIDIAN) </pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">number</span></span>
the distance from <strong>nodeA</strong> to <strong>nodeB</strong>
</ol>
</dd>
<dt>
<a name = "Heuristics.DIAGONAL"></a>
<strong>Heuristics.DIAGONAL (nodeA, nodeB)</strong>
</dt>
<dd>
Diagonal distance.
<br/>Evaluates as <code>distance = max(|dx|, abs|dy|)</code>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">nodeA</span>
<span class="types"><a class="type" href="../modules/core.node.html">node</a></span>
a node</li>
<li><span class="parameter">nodeB</span>
<span class="types"><a class="type" href="../modules/core.node.html">node</a></span>
another node</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
-- First method
pathfinder:setHeuristic('DIAGONAL')
-- Second method
local Distance = require ('jumper.core.heuristics')
pathfinder:setHeuristic(Distance.DIAGONAL)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">number</span></span>
the distance from <strong>nodeA</strong> to <strong>nodeB</strong>
</ol>
</dd>
<dt>
<a name = "Heuristics.CARDINTCARD"></a>
<strong>Heuristics.CARDINTCARD (nodeA, nodeB)</strong>
</dt>
<dd>
Cardinal/Intercardinal distance.
<br/>Evaluates as <code>distance = min(dx, dy)*squareRoot(2) + max(dx, dy) - min(dx, dy)</code>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">nodeA</span>
<span class="types"><a class="type" href="../modules/core.node.html">node</a></span>
a node</li>
<li><span class="parameter">nodeB</span>
<span class="types"><a class="type" href="../modules/core.node.html">node</a></span>
another node</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
-- First method
pathfinder:setHeuristic('CARDINTCARD')
-- Second method
local Distance = require ('jumper.core.heuristics')
pathfinder:setHeuristic(Distance.CARDINTCARD)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">number</span></span>
the distance from <strong>nodeA</strong> to <strong>nodeB</strong>
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.2</a></i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>
================================================
FILE: docs/modules/core.node.html
================================================
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Jumper documentation</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Jumper</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Class_Node_">Class Node </a></li>
</ul>
<h2>Modules</h2>
<ul>
<li><a href="../modules/core.bheap.html">core.bheap</a></li>
<li><a href="../modules/core.heuristics.html">core.heuristics</a></li>
<li><strong>core.node</strong></li>
<li><a href="../modules/core.path.html">core.path</a></li>
<li><a href="../modules/grid.html">grid</a></li>
<li><a href="../modules/pathfinder.html">pathfinder</a></li>
</ul>
<h2>Examples</h2>
<ul>
<li><a href="../examples/annotatedpathing.lua.html">annotatedpathing.lua</a></li>
<li><a href="../examples/customheuristics.lua.html">customheuristics.lua</a></li>
<li><a href="../examples/makeclearance.lua.html">makeclearance.lua</a></li>
<li><a href="../examples/simpleexample.lua.html">simpleexample.lua</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>core.node</code></h1>
<p>The Node class.</p>
<p> The <a href="../modules/core.node.html">node</a> represents a cell (or a tile) on a collision map. Basically, for each single cell (tile)
in the collision map passed-in upon initialization, a <a href="../modules/core.node.html">node</a> object will be generated
and then cached within the <a href="../modules/grid.html#">grid</a> .</p>
<p> In the following implementation, nodes can be compared using the <code><</code> operator. The comparison is
made with regards of their <code>f</code> cost. From a given node being examined, the <a href="../modules/pathfinder.html#">pathfinder</a> will expand the search
to the next neighbouring node having the lowest <code>f</code> cost. See <a href="../modules/core.bheap.html#">core.bheap</a> for more details.
</p>
<h2><a href="#Class_Node_">Class Node </a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Node:new">Node:new (x, y)</a></td>
<td class="summary">Inits a new <a href="../modules/core.node.html">node</a> </td>
</tr>
<tr>
<td class="name" nowrap><a href="#Node:getX">Node:getX ()</a></td>
<td class="summary">Returns x-coordinate of a <a href="../modules/core.node.html">node</a> </td>
</tr>
<tr>
<td class="name" nowrap><a href="#Node:getY">Node:getY ()</a></td>
<td class="summary">Returns y-coordinate of a <a href="../modules/core.node.html">node</a> </td>
</tr>
<tr>
<td class="name" nowrap><a href="#Node:getPos">Node:getPos ()</a></td>
<td class="summary">Returns x and y coordinates of a <a href="../modules/core.node.html">node</a> </td>
</tr>
<tr>
<td class="name" nowrap><a href="#Node:getClearance">Node:getClearance (walkable)</a></td>
<td class="summary">Returns the amount of true <a href="http://aigamedev.com/open/tutorial/clearance-based-pathfinding/#TheTrueClearanceMetric">clearance</a>
for a given <a href="../modules/core.node.html">node</a> </td>
</tr>
<tr>
<td class="name" nowrap><a href="#Node:removeClearance">Node:removeClearance (walkable)</a></td>
<td class="summary">Removes the clearance value for a given walkable.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Node:reset">Node:reset ()</a></td>
<td class="summary">Clears temporary cached attributes of a <a href="../modules/core.node.html">node</a> .</td>
</tr>
</table>
<br/>
<br/>
<h2><a name="Class_Node_"></a>Class Node </h2>
The <a href="../modules/core.node.html#Class_Node">Node</a> class.<br/>
This class is callable.
Therefore,_ <code>Node(...)</code> <em>acts as a shortcut to</em> <code>Node:new(...)</code>.
<dl class="function">
<dt>
<a name = "Node:new"></a>
<strong>Node:new (x, y)</strong>
</dt>
<dd>
Inits a new <a href="../modules/core.node.html">node</a>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">x</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the x-coordinate of the node on the collision map</li>
<li><span class="parameter">y</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the y-coordinate of the node on the collision map</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">local node = Node(3,4)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/core.node.html">node</a></span>
a new <a href="../modules/core.node.html">node</a>
</ol>
</dd>
<dt>
<a name = "Node:getX"></a>
<strong>Node:getX ()</strong>
</dt>
<dd>
Returns x-coordinate of a <a href="../modules/core.node.html">node</a>
<h3>Usage:</h3>
<ul>
<pre class="example">local x = node:getX()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">number</span></span>
the x-coordinate of the <a href="../modules/core.node.html">node</a>
</ol>
</dd>
<dt>
<a name = "Node:getY"></a>
<strong>Node:getY ()</strong>
</dt>
<dd>
Returns y-coordinate of a <a href="../modules/core.node.html">node</a>
<h3>Usage:</h3>
<ul>
<pre class="example">local y = node:getY()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">number</span></span>
the y-coordinate of the <a href="../modules/core.node.html">node</a>
</ol>
</dd>
<dt>
<a name = "Node:getPos"></a>
<strong>Node:getPos ()</strong>
</dt>
<dd>
Returns x and y coordinates of a <a href="../modules/core.node.html">node</a>
<h3>Usage:</h3>
<ul>
<pre class="example">local x, y = node:getPos()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<li>
<span class="types"><span class="type">number</span></span>
the x-coordinate of the <a href="../modules/core.node.html">node</a> </li>
<li>
<span class="types"><span class="type">number</span></span>
the y-coordinate of the <a href="../modules/core.node.html">node</a> </li>
</ol>
</dd>
<dt>
<a name = "Node:getClearance"></a>
<strong>Node:getClearance (walkable)</strong>
</dt>
<dd>
Returns the amount of true <a href="http://aigamedev.com/open/tutorial/clearance-based-pathfinding/#TheTrueClearanceMetric">clearance</a>
for a given <a href="../modules/core.node.html">node</a>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">walkable</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a>, <a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a> or <a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">func</a></span>
the value for walkable locations in the collision map array.</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
-- Assuming walkable was 0
local clearance = node:getClearance(0) </pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the clearance of the <a href="../modules/core.node.html">node</a>
</ol>
</dd>
<dt>
<a name = "Node:removeClearance"></a>
<strong>Node:removeClearance (walkable)</strong>
</dt>
<dd>
Removes the clearance value for a given walkable.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">walkable</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a>, <a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a> or <a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">func</a></span>
the value for walkable locations in the collision map array.</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
-- Assuming walkable is defined
node:removeClearance(walkable) </pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/core.node.html">node</a></span>
self (the calling <a href="../modules/core.node.html">node</a> itself, can be chained)
</ol>
</dd>
<dt>
<a name = "Node:reset"></a>
<strong>Node:reset ()</strong>
</dt>
<dd>
Clears temporary cached attributes of a <a href="../modules/core.node.html">node</a> .
Deletes the attributes cached within a given node after a pathfinding call.
This function is internally used by the search algorithms, so you should not use it explicitely.
<h3>Usage:</h3>
<ul>
<pre class="example">
local thisNode = Node(1,2)
thisNode:reset()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/core.node.html">node</a></span>
self (the calling <a href="../modules/core.node.html">node</a> itself, can be chained)
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.2</a></i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>
================================================
FILE: docs/modules/core.path.html
================================================
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Jumper documentation</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Jumper</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Class_Path_">Class Path </a></li>
</ul>
<h2>Modules</h2>
<ul>
<li><a href="../modules/core.bheap.html">core.bheap</a></li>
<li><a href="../modules/core.heuristics.html">core.heuristics</a></li>
<li><a href="../modules/core.node.html">core.node</a></li>
<li><strong>core.path</strong></li>
<li><a href="../modules/grid.html">grid</a></li>
<li><a href="../modules/pathfinder.html">pathfinder</a></li>
</ul>
<h2>Examples</h2>
<ul>
<li><a href="../examples/annotatedpathing.lua.html">annotatedpathing.lua</a></li>
<li><a href="../examples/customheuristics.lua.html">customheuristics.lua</a></li>
<li><a href="../examples/makeclearance.lua.html">makeclearance.lua</a></li>
<li><a href="../examples/simpleexample.lua.html">simpleexample.lua</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>core.path</code></h1>
<p>The Path class.</p>
<p> The <a href="../modules/core.path.html">path</a> class is a structure which represents a path (ordered set of nodes) from a start location to a goal.
An instance from this class would be a result of a request addressed to <code>Pathfinder:getPath</code>.</p>
<p> This module is internally used by the library on purpose.
It should normally not be used explicitely, yet it remains fully accessible.</p>
<h2><a href="#Class_Path_">Class Path </a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Path:new">Path:new ()</a></td>
<td class="summary">Inits a new <a href="../modules/core.path.html">path</a> .</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Path:iter">Path:iter ()</a></td>
<td class="summary">Iterates on each single <a href="../modules/core.node.html">node</a> along a <a href="../modules/core.path.html">path</a> .</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Path:nodes">Path:nodes ()</a></td>
<td class="summary">Iterates on each single <a href="../modules/core.node.html">node</a> along a <a href="../modules/core.path.html">path</a> .</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Path:getLength">Path:getLength ()</a></td>
<td class="summary">Evaluates the <a href="../modules/core.path.html">path</a> length</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Path:addNode">Path:addNode (node [, index])</a></td>
<td class="summary">Counts the number of steps.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Path:fill">Path:fill ()</a></td>
<td class="summary"><a href="../modules/core.path.html#Class_Path">Path</a> filling modifier.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Path:filter">Path:filter ()</a></td>
<td class="summary"><a href="../modules/core.path.html#Class_Path">Path</a> compression modifier.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Path:clone">Path:clone ()</a></td>
<td class="summary">Clones a <a href="../modules/core.path.html">path</a> .</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Path:isEqualTo">Path:isEqualTo (p2)</a></td>
<td class="summary">Checks if a <a href="../modules/core.path.html">path</a> is equal to another.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Path:reverse">Path:reverse ()</a></td>
<td class="summary">Reverses a <a href="../modules/core.path.html">path</a> .</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Path:append">Path:append (p)</a></td>
<td class="summary">Appends a given <a href="../modules/core.path.html">path</a> to self.</td>
</tr>
</table>
<br/>
<br/>
<h2><a name="Class_Path_"></a>Class Path </h2>
The <a href="../modules/core.path.html#Class_Path">Path</a> class.<br/>
This class is callable.
Therefore, <em><code>Path(...)</code></em> acts as a shortcut to <em><code>Path:new(...)</code></em>.
<dl class="function">
<dt>
<a name = "Path:new"></a>
<strong>Path:new ()</strong>
</dt>
<dd>
Inits a new <a href="../modules/core.path.html">path</a> .
<h3>Usage:</h3>
<ul>
<pre class="example">local p = Path()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/core.path.html">path</a></span>
a <a href="../modules/core.path.html">path</a>
</ol>
</dd>
<dt>
<a name = "Path:iter"></a>
<strong>Path:iter ()</strong>
</dt>
<dd>
Iterates on each single <a href="../modules/core.node.html">node</a> along a <a href="../modules/core.path.html">path</a> . At each step of iteration,
returns the <a href="../modules/core.node.html">node</a> plus a count value. Aliased as <a href="../modules/core.path.html#Path:nodes">Path:nodes</a>
<h3>Usage:</h3>
<ul>
<pre class="example">
for node, count in p:iter() do
...
end</pre>
</ul>
<h3>Returns:</h3>
<ol>
<li>
<span class="types"><a class="type" href="../modules/core.node.html">node</a></span>
a <a href="../modules/core.node.html">node</a> </li>
<li>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the count for the number of nodes</li>
</ol>
<h3>see also:</h3>
<ul>
<a href="../modules/core.path.html#Path:nodes">Path:nodes</a>
</ul>
</dd>
<dt>
<a name = "Path:nodes"></a>
<strong>Path:nodes ()</strong>
</dt>
<dd>
Iterates on each single <a href="../modules/core.node.html">node</a> along a <a href="../modules/core.path.html">path</a> . At each step of iteration,
returns a <a href="../modules/core.node.html">node</a> plus a count value. Alias for <a href="../modules/core.path.html#Path:iter">Path:iter</a>
<h3>Usage:</h3>
<ul>
<pre class="example">
for node, count in p:nodes() do
...
end </pre>
</ul>
<h3>Returns:</h3>
<ol>
<li>
<span class="types"><a class="type" href="../modules/core.node.html">node</a></span>
a <a href="../modules/core.node.html">node</a> </li>
<li>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the count for the number of nodes</li>
</ol>
<h3>see also:</h3>
<ul>
<a href="../modules/core.path.html#Path:iter">Path:iter</a>
</ul>
</dd>
<dt>
<a name = "Path:getLength"></a>
<strong>Path:getLength ()</strong>
</dt>
<dd>
Evaluates the <a href="../modules/core.path.html">path</a> length
<h3>Usage:</h3>
<ul>
<pre class="example">local len = p:getLength()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">number</span></span>
the <a href="../modules/core.path.html">path</a> length
</ol>
</dd>
<dt>
<a name = "Path:addNode"></a>
<strong>Path:addNode (node [, index])</strong>
</dt>
<dd>
Counts the number of steps.
Returns the number of waypoints (nodes) in the current path.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">node</span>
<span class="types"><a class="type" href="../modules/core.node.html">node</a></span>
a node to be added to the path</li>
<li><span class="parameter">index</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the index at which the node will be inserted. If omitted, the node will be appended after the last node in the path.</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">local nSteps = p:countSteps()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/core.path.html">path</a></span>
self (the calling <a href="../modules/core.path.html">path</a> itself, can be chained)
</ol>
</dd>
<dt>
<a name = "Path:fill"></a>
<strong>Path:fill ()</strong>
</dt>
<dd>
<a href="../modules/core.path.html#Class_Path">Path</a> filling modifier. Interpolates between non contiguous nodes along a <a href="../modules/core.path.html">path</a>
to build a fully continuous <a href="../modules/core.path.html">path</a> . This maybe useful when using search algorithms such as Jump Point Search.
Does the opposite of <a href="../modules/core.path.html#Path:filter">Path:filter</a>
<h3>Usage:</h3>
<ul>
<pre class="example">p:fill()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/core.path.html">path</a></span>
self (the calling <a href="../modules/core.path.html">path</a> itself, can be chained)
</ol>
<h3>see also:</h3>
<ul>
<a href="../modules/core.path.html#Path:filter">Path:filter</a>
</ul>
</dd>
<dt>
<a name = "Path:filter"></a>
<strong>Path:filter ()</strong>
</dt>
<dd>
<a href="../modules/core.path.html#Class_Path">Path</a> compression modifier. Given a <a href="../modules/core.path.html">path</a> , eliminates useless nodes to return a lighter <a href="../modules/core.path.html">path</a> <br/>
consisting of straight moves. Does the opposite of <a href="../modules/core.path.html#Path:fill">Path:fill</a>
<h3>Usage:</h3>
<ul>
<pre class="example">p:filter()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/core.path.html">path</a></span>
self (the calling <a href="../modules/core.path.html">path</a> itself, can be chained)
</ol>
<h3>see also:</h3>
<ul>
<a href="../modules/core.path.html#Path:fill">Path:fill</a>
</ul>
</dd>
<dt>
<a name = "Path:clone"></a>
<strong>Path:clone ()</strong>
</dt>
<dd>
Clones a <a href="../modules/core.path.html">path</a> .
<h3>Usage:</h3>
<ul>
<pre class="example">local p = path:clone()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/core.path.html">path</a></span>
a <a href="../modules/core.path.html">path</a>
</ol>
</dd>
<dt>
<a name = "Path:isEqualTo"></a>
<strong>Path:isEqualTo (p2)</strong>
</dt>
<dd>
Checks if a <a href="../modules/core.path.html">path</a> is equal to another. It also supports <em>filtered paths</em> (see <a href="../modules/core.path.html#Path:filter">Path:filter</a>).
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">p2</span>
<span class="types"><a class="type" href="../modules/core.path.html">path</a></span>
a path</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">print(myPath:isEqualTo(anotherPath))</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">boolean</a></span>
a boolean
</ol>
</dd>
<dt>
<a name = "Path:reverse"></a>
<strong>Path:reverse ()</strong>
</dt>
<dd>
Reverses a <a href="../modules/core.path.html">path</a> .
<h3>Usage:</h3>
<ul>
<pre class="example">myPath:reverse()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/core.path.html">path</a></span>
self (the calling <a href="../modules/core.path.html">path</a> itself, can be chained)
</ol>
</dd>
<dt>
<a name = "Path:append"></a>
<strong>Path:append (p)</strong>
</dt>
<dd>
Appends a given <a href="../modules/core.path.html">path</a> to self.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">p</span>
<span class="types"><a class="type" href="../modules/core.path.html">path</a></span>
a path</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">myPath:append(anotherPath)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/core.path.html">path</a></span>
self (the calling <a href="../modules/core.path.html">path</a> itself, can be chained)
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.2</a></i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>
================================================
FILE: docs/modules/grid.html
================================================
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Jumper documentation</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Jumper</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Class_Grid_">Class Grid </a></li>
</ul>
<h2>Modules</h2>
<ul>
<li><a href="../modules/core.bheap.html">core.bheap</a></li>
<li><a href="../modules/core.heuristics.html">core.heuristics</a></li>
<li><a href="../modules/core.node.html">core.node</a></li>
<li><a href="../modules/core.path.html">core.path</a></li>
<li><strong>grid</strong></li>
<li><a href="../modules/pathfinder.html">pathfinder</a></li>
</ul>
<h2>Examples</h2>
<ul>
<li><a href="../examples/annotatedpathing.lua.html">annotatedpathing.lua</a></li>
<li><a href="../examples/customheuristics.lua.html">customheuristics.lua</a></li>
<li><a href="../examples/makeclearance.lua.html">makeclearance.lua</a></li>
<li><a href="../examples/simpleexample.lua.html">simpleexample.lua</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>grid</code></h1>
<p>The Grid class.</p>
<p> Implementation of the <a href="../modules/grid.html#">grid</a> class.
The <a href="../modules/grid.html#">grid</a> is a implicit graph which represents the 2D
world map layout on which the <a href="../modules/pathfinder.html#">pathfinder</a> object will run.
During a search, the <a href="../modules/pathfinder.html#">pathfinder</a> object needs to save some critical values. These values are cached within each <code>node</code>
object, and the whole set of nodes are tight inside the <a href="../modules/grid.html#">grid</a> object itself.</p>
<h2><a href="#Class_Grid_">Class Grid </a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Grid:new">Grid:new (map [, cacheNodeAtRuntime])</a></td>
<td class="summary">Inits a new <a href="../modules/grid.html#">grid</a> </td>
</tr>
<tr>
<td class="name" nowrap><a href="#Grid:isWalkableAt">Grid:isWalkableAt (x, y [, walkable [, clearance]])</a></td>
<td class="summary">Checks if <code>node</code> at [x,y] is <strong>walkable</strong>.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Grid:getWidth">Grid:getWidth ()</a></td>
<td class="summary">Returns the <a href="../modules/grid.html#">grid</a> width.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Grid:getHeight">Grid:getHeight ()</a></td>
<td class="summary">Returns the <a href="../modules/grid.html#">grid</a> height.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Grid:getMap">Grid:getMap ()</a></td>
<td class="summary">Returns the collision map.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Grid:getNodes">Grid:getNodes ()</a></td>
<td class="summary">Returns the set of nodes.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Grid:getBounds">Grid:getBounds ()</a></td>
<td class="summary">Returns the <a href="../modules/grid.html#">grid</a> bounds.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Grid:getNeighbours">Grid:getNeighbours (node [, walkable [, allowDiagonal [, tunnel [, clearance]]]])</a></td>
<td class="summary">Returns neighbours.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Grid:iter">Grid:iter ( [lx [, ly [, ex [, ey]]]])</a></td>
<td class="summary">Grid iterator.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Grid:around">Grid:around (node [, radius])</a></td>
<td class="summary">Grid iterator.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Grid:each">Grid:each (f [, ...])</a></td>
<td class="summary">Each transformation.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Grid:eachRange">Grid:eachRange (lx, ly, ex, ey, f [, ...])</a></td>
<td class="summary">Each (in range) transformation.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Grid:imap">Grid:imap (f [, ...])</a></td>
<td class="summary">Map transformation.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Grid:imapRange">Grid:imapRange (lx, ly, ex, ey, f [, ...])</a></td>
<td class="summary">Map in range transformation.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Grid:getNodeAt">Grid:getNodeAt (x, y)</a></td>
<td class="summary">Returns the <code>node</code> at location [x,y].</td>
</tr>
</table>
<br/>
<br/>
<h2><a name="Class_Grid_"></a>Class Grid </h2>
The <a href="../modules/grid.html#Class_Grid">Grid</a> class.<br/>
This class is callable.
Therefore,_ <code>Grid(...)</code> <em>acts as a shortcut to</em> <code>Grid:new(...)</code>.
<dl class="function">
<dt>
<a name = "Grid:new"></a>
<strong>Grid:new (map [, cacheNodeAtRuntime])</strong>
</dt>
<dd>
Inits a new <a href="../modules/grid.html#">grid</a>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">map</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.5">table</a> or <a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
A collision map - (2D array) with consecutive indices (starting at 0 or 1)
or a <a href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a> with line-break chars (<code>\n</code> or <code>\r</code>) as row delimiters.</li>
<li><span class="parameter">cacheNodeAtRuntime</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">bool</a></span>
When <strong>true</strong>, returns an empty <a href="../modules/grid.html#">grid</a> instance, so that
later on, indexing a non-cached <code>node</code> will cause it to be created and cache within the <a href="../modules/grid.html#">grid</a> on purpose (i.e, when needed).
This is a <strong>memory-safe</strong> option, in case your dealing with some tight memory constraints.
Defaults to <strong>false</strong> when omitted.</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
-- A simple 3x3 grid
local myGrid = Grid:new({{0,0,0},{0,0,0},{0,0,0}})
-- A memory-safe 3x3 grid
myGrid = Grid('000\n000\n000', true)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/grid.html#">grid</a></span>
a new <a href="../modules/grid.html#">grid</a> instance
</ol>
</dd>
<dt>
<a name = "Grid:isWalkableAt"></a>
<strong>Grid:isWalkableAt (x, y [, walkable [, clearance]])</strong>
</dt>
<dd>
Checks if <code>node</code> at [x,y] is <strong>walkable</strong>.
Will check if <code>node</code> at location [x,y] both <em>exists</em> on the collision map and <em>is walkable</em>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">x</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the x-location of the node</li>
<li><span class="parameter">y</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the y-location of the node</li>
<li><span class="parameter">walkable</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a>, <a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a> or <a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">func</a></span>
the value for walkable locations in the collision map array (see <a href="../modules/grid.html#Grid:new">Grid:new</a>).
Defaults to <strong>false</strong> when omitted.
If this parameter is a function, it should be prototyped as <strong>f(value)</strong> and return a <a href="http://www.lua.org/manual/5.1/manual.html#2.2">boolean</a> :
<strong>true</strong> when value matches a <strong>walkable</strong> <code>node</code>, <strong>false</strong> otherwise. If this parameter is not given
while location [x,y] <strong>is valid</strong>, this actual function returns <strong>true</strong>.</li>
<li><span class="parameter">clearance</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the amount of clearance needed. Defaults to 1 (normal clearance) when not given.</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
-- Always true
print(myGrid:isWalkableAt(2,3))
-- True if node at [2,3] collision map value is 0
print(myGrid:isWalkableAt(2,3,0))
-- True if node at [2,3] collision map value is 0 and has a clearance higher or equal to 2
print(myGrid:isWalkableAt(2,3,0,2))
</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">bool</a></span>
<strong>true</strong> if <code>node</code> exists and is <strong>walkable</strong>, <strong>false</strong> otherwise
</ol>
</dd>
<dt>
<a name = "Grid:getWidth"></a>
<strong>Grid:getWidth ()</strong>
</dt>
<dd>
Returns the <a href="../modules/grid.html#">grid</a> width.
<h3>Usage:</h3>
<ul>
<pre class="example">print(myGrid:getWidth())</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the <a href="../modules/grid.html#">grid</a> width
</ol>
</dd>
<dt>
<a name = "Grid:getHeight"></a>
<strong>Grid:getHeight ()</strong>
</dt>
<dd>
Returns the <a href="../modules/grid.html#">grid</a> height.
<h3>Usage:</h3>
<ul>
<pre class="example">print(myGrid:getHeight())</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the <a href="../modules/grid.html#">grid</a> height
</ol>
</dd>
<dt>
<a name = "Grid:getMap"></a>
<strong>Grid:getMap ()</strong>
</dt>
<dd>
Returns the collision map.
<h3>Usage:</h3>
<ul>
<pre class="example">local map = myGrid:getMap()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">map</span></span>
the collision map (see <a href="../modules/grid.html#Grid:new">Grid:new</a>)
</ol>
</dd>
<dt>
<a name = "Grid:getNodes"></a>
<strong>Grid:getNodes ()</strong>
</dt>
<dd>
Returns the set of nodes.
<h3>Usage:</h3>
<ul>
<pre class="example">local nodes = myGrid:getNodes()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">{{node,...},...}</span></span>
an array of nodes
</ol>
</dd>
<dt>
<a name = "Grid:getBounds"></a>
<strong>Grid:getBounds ()</strong>
</dt>
<dd>
Returns the <a href="../modules/grid.html#">grid</a> bounds. Returned values corresponds to the upper-left
and lower-right coordinates (in tile units) of the actual <a href="../modules/grid.html#">grid</a> instance.
<h3>Usage:</h3>
<ul>
<pre class="example">local left_x, left_y, right_x, right_y = myGrid:getBounds()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<li>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the upper-left corner x-coordinate</li>
<li>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the upper-left corner y-coordinate</li>
<li>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the lower-right corner x-coordinate</li>
<li>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the lower-right corner y-coordinate</li>
</ol>
</dd>
<dt>
<a name = "Grid:getNeighbours"></a>
<strong>Grid:getNeighbours (node [, walkable [, allowDiagonal [, tunnel [, clearance]]]])</strong>
</dt>
<dd>
Returns neighbours. The returned value is an array of <strong>walkable</strong> nodes neighbouring a given <code>node</code>.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">node</span>
<span class="types"><span class="type">node</span></span>
a given <code>node</code></li>
<li><span class="parameter">walkable</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a>, <a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a> or <a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">func</a></span>
the value for walkable locations in the collision map array (see <a href="../modules/grid.html#Grid:new">Grid:new</a>).
Defaults to <strong>false</strong> when omitted.</li>
<li><span class="parameter">allowDiagonal</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">bool</a></span>
when <strong>true</strong>, allows adjacent nodes are included (8-neighbours).
Defaults to <strong>false</strong> when omitted.</li>
<li><span class="parameter">tunnel</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">bool</a></span>
When <strong>true</strong>, allows the <a href="../modules/pathfinder.html#">pathfinder</a> to tunnel through walls when heading diagonally.</li>
<li><span class="parameter">clearance</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
When given, will prune for the neighbours set all nodes having a clearance value lower than the passed-in value
Defaults to <strong>false</strong> when omitted.</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
local aNode = myGrid:getNodeAt(5,6)
local neighbours = myGrid:getNeighbours(aNode, 0, true)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">{node,...}</span></span>
an array of nodes neighbouring a given node
</ol>
</dd>
<dt>
<a name = "Grid:iter"></a>
<strong>Grid:iter ( [lx [, ly [, ex [, ey]]]])</strong>
</dt>
<dd>
Grid iterator. Iterates on every single node
in the <a href="../modules/grid.html#">grid</a> . Passing <strong>lx, ly, ex, ey</strong> arguments will iterate
only on nodes inside the bounding-rectangle delimited by those given coordinates.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">lx</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the leftmost x-coordinate of the rectangle. Default to the <a href="../modules/grid.html#">grid</a> leftmost x-coordinate (see <a href="../modules/grid.html#Grid:getBounds">Grid:getBounds</a>).</li>
<li><span class="parameter">ly</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the topmost y-coordinate of the rectangle. Default to the <a href="../modules/grid.html#">grid</a> topmost y-coordinate (see <a href="../modules/grid.html#Grid:getBounds">Grid:getBounds</a>).</li>
<li><span class="parameter">ex</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the rightmost x-coordinate of the rectangle. Default to the <a href="../modules/grid.html#">grid</a> rightmost x-coordinate (see <a href="../modules/grid.html#Grid:getBounds">Grid:getBounds</a>).</li>
<li><span class="parameter">ey</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the bottom-most y-coordinate of the rectangle. Default to the <a href="../modules/grid.html#">grid</a> bottom-most y-coordinate (see <a href="../modules/grid.html#Grid:getBounds">Grid:getBounds</a>).</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
for node, count in myGrid:iter() do
print(node:getX(), node:getY(), count)
end</pre>
</ul>
<h3>Returns:</h3>
<ol>
<li>
<span class="types"><span class="type">node</span></span>
a <code>node</code> on the collision map, upon each iteration step</li>
<li>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the iteration count</li>
</ol>
</dd>
<dt>
<a name = "Grid:around"></a>
<strong>Grid:around (node [, radius])</strong>
</dt>
<dd>
Grid iterator. Iterates on each node along the outline (border) of a squared area
centered on the given node.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">node</span>
<span class="types"><span class="type">node</span></span>
a given <code>node</code></li>
<li><span class="parameter">radius</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the area radius (half-length). Defaults to <strong>1</strong> when not given.</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
for node in myGrid:around(node, 2) do
...
end</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">node</span></span>
a <code>node</code> at each iteration step
</ol>
</dd>
<dt>
<a name = "Grid:each"></a>
<strong>Grid:each (f [, ...])</strong>
</dt>
<dd>
Each transformation. Calls the given function on each <code>node</code> in the <a href="../modules/grid.html#">grid</a> ,
passing the <code>node</code> as the first argument to function <strong>f</strong>.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">f</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">func</a></span>
a function prototyped as <strong>f(node,...)</strong></li>
<li><span class="parameter">...</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.5">vararg</a></span>
args to be passed to function <strong>f</strong></li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
local function printNode(node)
print(node:getX(), node:getY())
end
myGrid:each(printNode)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/grid.html#">grid</a></span>
self (the calling <a href="../modules/grid.html#">grid</a> itself, can be chained)
</ol>
</dd>
<dt>
<a name = "Grid:eachRange"></a>
<strong>Grid:eachRange (lx, ly, ex, ey, f [, ...])</strong>
</dt>
<dd>
Each (in range) transformation. Calls a function on each <code>node</code> in the range of a rectangle of cells,
passing the <code>node</code> as the first argument to function <strong>f</strong>.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">lx</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the leftmost x-coordinate coordinate of the rectangle</li>
<li><span class="parameter">ly</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the topmost y-coordinate of the rectangle</li>
<li><span class="parameter">ex</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the rightmost x-coordinate of the rectangle</li>
<li><span class="parameter">ey</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the bottom-most y-coordinate of the rectangle</li>
<li><span class="parameter">f</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">func</a></span>
a function prototyped as <strong>f(node,...)</strong></li>
<li><span class="parameter">...</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.5">vararg</a></span>
args to be passed to function <strong>f</strong></li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
local function printNode(node)
print(node:getX(), node:getY())
end
myGrid:eachRange(1,1,8,8,printNode)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/grid.html#">grid</a></span>
self (the calling <a href="../modules/grid.html#">grid</a> itself, can be chained)
</ol>
</dd>
<dt>
<a name = "Grid:imap"></a>
<strong>Grid:imap (f [, ...])</strong>
</dt>
<dd>
Map transformation.
Calls function <strong>f(node,...)</strong> on each <code>node</code> in a given range, passing the <code>node</code> as the first arg to function <strong>f</strong> and replaces
it with the returned value. Therefore, the function should return a <code>node</code>.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">f</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">func</a></span>
a function prototyped as <strong>f(node,...)</strong></li>
<li><span class="parameter">...</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.5">vararg</a></span>
args to be passed to function <strong>f</strong></li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
local function nothing(node)
return node
end
myGrid:imap(nothing)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/grid.html#">grid</a></span>
self (the calling <a href="../modules/grid.html#">grid</a> itself, can be chained)
</ol>
</dd>
<dt>
<a name = "Grid:imapRange"></a>
<strong>Grid:imapRange (lx, ly, ex, ey, f [, ...])</strong>
</dt>
<dd>
Map in range transformation.
Calls function <strong>f(node,...)</strong> on each <code>node</code> in a rectangle range, passing the <code>node</code> as the first argument to the function and replaces
it with the returned value. Therefore, the function should return a <code>node</code>.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">lx</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the leftmost x-coordinate coordinate of the rectangle</li>
<li><span class="parameter">ly</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the topmost y-coordinate of the rectangle</li>
<li><span class="parameter">ex</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the rightmost x-coordinate of the rectangle</li>
<li><span class="parameter">ey</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the bottom-most y-coordinate of the rectangle</li>
<li><span class="parameter">f</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">func</a></span>
a function prototyped as <strong>f(node,...)</strong></li>
<li><span class="parameter">...</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.5">vararg</a></span>
args to be passed to function <strong>f</strong></li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
local function nothing(node)
return node
end
myGrid:imap(1,1,6,6,nothing)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/grid.html#">grid</a></span>
self (the calling <a href="../modules/grid.html#">grid</a> itself, can be chained)
</ol>
</dd>
<dt>
<a name = "Grid:getNodeAt"></a>
<strong>Grid:getNodeAt (x, y)</strong>
</dt>
<dd>
Returns the <code>node</code> at location [x,y].
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">x</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the x-coordinate coordinate</li>
<li><span class="parameter">y</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the y-coordinate coordinate</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">local aNode = myGrid:getNodeAt(2,2)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">node</span></span>
a <code>node</code>
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.2</a></i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>
================================================
FILE: docs/modules/pathfinder.html
================================================
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Jumper documentation</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Jumper</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Finders">Finders</a></li>
<li><a href="#Modes">Modes</a></li>
<li><a href="#Class_Pathfinder_">Class Pathfinder </a></li>
</ul>
<h2>Modules</h2>
<ul>
<li><a href="../modules/core.bheap.html">core.bheap</a></li>
<li><a href="../modules/core.heuristics.html">core.heuristics</a></li>
<li><a href="../modules/core.node.html">core.node</a></li>
<li><a href="../modules/core.path.html">core.path</a></li>
<li><a href="../modules/grid.html">grid</a></li>
<li><strong>pathfinder</strong></li>
</ul>
<h2>Examples</h2>
<ul>
<li><a href="../examples/annotatedpathing.lua.html">annotatedpathing.lua</a></li>
<li><a href="../examples/customheuristics.lua.html">customheuristics.lua</a></li>
<li><a href="../examples/makeclearance.lua.html">makeclearance.lua</a></li>
<li><a href="../examples/simpleexample.lua.html">simpleexample.lua</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>pathfinder</code></h1>
<p>The Pathfinder class</p>
<p>
</p>
<h2><a href="#Finders">Finders</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Finders">Finders</a></td>
<td class="summary">Finders (search algorithms implemented).</td>
</tr>
</table>
<h2><a href="#Modes">Modes</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Modes">Modes</a></td>
<td class="summary">Search modes.</td>
</tr>
</table>
<h2><a href="#Class_Pathfinder_">Class Pathfinder </a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Pathfinder:new">Pathfinder:new (grid [, finderName [, walkable]])</a></td>
<td class="summary">Inits a new <a href="../modules/pathfinder.html#">pathfinder</a> </td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:annotateGrid">Pathfinder:annotateGrid ()</a></td>
<td class="summary">Evaluates <a href="http://aigamedev.com/open/tutorial/clearance-based-pathfinding/#TheTrueClearanceMetric">clearance</a>
for the whole <a href="../modules/grid.html#">grid</a> .</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:clearAnnotations">Pathfinder:clearAnnotations ()</a></td>
<td class="summary">Removes <a href="http://aigamedev.com/open/tutorial/clearance-based-pathfinding/#TheTrueClearanceMetric">clearance</a>values.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:setGrid">Pathfinder:setGrid (grid)</a></td>
<td class="summary">Sets the <a href="../modules/grid.html#">grid</a> .</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:getGrid">Pathfinder:getGrid ()</a></td>
<td class="summary">Returns the <a href="../modules/grid.html#">grid</a> .</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:setWalkable">Pathfinder:setWalkable (walkable)</a></td>
<td class="summary">Sets the <strong>walkable</strong> value or function.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:getWalkable">Pathfinder:getWalkable ()</a></td>
<td class="summary">Gets the <strong>walkable</strong> value or function.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:setFinder">Pathfinder:setFinder (finderName)</a></td>
<td class="summary">Defines the <code>finder</code>.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:getFinder">Pathfinder:getFinder ()</a></td>
<td class="summary">Returns the name of the <code>finder</code> being used.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:getFinders">Pathfinder:getFinders ()</a></td>
<td class="summary">Returns the list of all available finders names.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:setHeuristic">Pathfinder:setHeuristic (heuristic)</a></td>
<td class="summary">Sets a heuristic.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:getHeuristic">Pathfinder:getHeuristic ()</a></td>
<td class="summary">Returns the <code>heuristic</code> used.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:getHeuristics">Pathfinder:getHeuristics ()</a></td>
<td class="summary">Gets the list of all available <code>heuristics</code>.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:setMode">Pathfinder:setMode (mode)</a></td>
<td class="summary">Defines the search <code>mode</code>.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:getMode">Pathfinder:getMode ()</a></td>
<td class="summary">Returns the search mode.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:getModes">Pathfinder:getModes ()</a></td>
<td class="summary">Gets the list of all available search modes.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:setTunnelling">Pathfinder:setTunnelling (bool)</a></td>
<td class="summary">Enables tunnelling.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:getTunnelling">Pathfinder:getTunnelling ()</a></td>
<td class="summary">Returns tunnelling feature state.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:getPath">Pathfinder:getPath (startX, startY, endX, endY, clearance)</a></td>
<td class="summary">Calculates a <code>path</code>.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pathfinder:reset">Pathfinder:reset ()</a></td>
<td class="summary">Resets the <a href="../modules/pathfinder.html#">pathfinder</a> .</td>
</tr>
</table>
<br/>
<br/>
<h2><a name="Finders"></a>Finders</h2>
<dl class="function">
<dt>
<a name = "Finders"></a>
<strong>Finders</strong>
</dt>
<dd>
Finders (search algorithms implemented). Refers to the search algorithms actually implemented in Jumper.</p>
<p> <li><a href="http://en.wikipedia.org/wiki/A*_search_algorithm">A*</a></li>
<li><a href="http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm">Dijkstra</a></li>
<li><a href="http://aigamedev.com/open/tutorials/theta-star-any-angle-paths/">Theta Astar</a></li>
<li><a href="http://en.wikipedia.org/wiki/Breadth-first_search">BFS</a></li>
<li><a href="http://en.wikipedia.org/wiki/Depth-first_search">DFS</a></li>
<li><a href="http://harablog.wordpress.com/2011/09/07/jump-point-search/">JPS</a></li>
<h3>see also:</h3>
<ul>
<a href="../modules/pathfinder.html#Pathfinder:getFinders">Pathfinder:getFinders</a>
</ul>
</dd>
</dl>
<h2><a name="Modes"></a>Modes</h2>
<dl class="function">
<dt>
<a name = "Modes"></a>
<strong>Modes</strong>
</dt>
<dd>
Search modes. Refers to the search modes. In ORTHOGONAL mode, 4-directions are only possible when moving,
including North, East, West, South. In DIAGONAL mode, 8-directions are possible when moving,
including North, East, West, South and adjacent directions.</p>
<p> <li>ORTHOGNAL</li>
<li>DIAGONAL</li>
<h3>see also:</h3>
<ul>
<a href="../modules/pathfinder.html#Pathfinder:getModes">Pathfinder:getModes</a>
</ul>
</dd>
</dl>
<h2><a name="Class_Pathfinder_"></a>Class Pathfinder </h2>
The <a href="../modules/pathfinder.html#Class_Pathfinder">Pathfinder</a> class.<br/>
This class is callable.
Therefore,_ <code>Pathfinder(...)</code> <em>acts as a shortcut to</em> <code>Pathfinder:new(...)</code>.
<dl class="function">
<dt>
<a name = "Pathfinder:new"></a>
<strong>Pathfinder:new (grid [, finderName [, walkable]])</strong>
</dt>
<dd>
Inits a new <a href="../modules/pathfinder.html#">pathfinder</a>
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">grid</span>
<span class="types"><a class="type" href="../modules/grid.html#">grid</a></span>
a <a href="../modules/grid.html#">grid</a> </li>
<li><span class="parameter">finderName</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
the name of the <code>Finder</code> (search algorithm) to be used for search.
Defaults to <code>ASTAR</code> when not given (see <a href="../modules/pathfinder.html#Pathfinder:getFinders">Pathfinder:getFinders</a>).</li>
<li><span class="parameter">walkable</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a>, <a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a> or <a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">func</a></span>
the value for <strong>walkable</strong> nodes.
If this parameter is a function, it should be prototyped as <strong>f(value)</strong>, returning a boolean:
<strong>true</strong> when value matches a <strong>walkable</strong> <code>node</code>, <strong>false</strong> otherwise.</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
-- Example one
local finder = Pathfinder:new(myGrid, 'ASTAR', 0)
-- Example two
local function walkable(value)
return value > 0
end
local finder = Pathfinder(myGrid, 'JPS', walkable)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/pathfinder.html#">pathfinder</a></span>
a new <a href="../modules/pathfinder.html#">pathfinder</a> instance
</ol>
</dd>
<dt>
<a name = "Pathfinder:annotateGrid"></a>
<strong>Pathfinder:annotateGrid ()</strong>
</dt>
<dd>
Evaluates <a href="http://aigamedev.com/open/tutorial/clearance-based-pathfinding/#TheTrueClearanceMetric">clearance</a>
for the whole <a href="../modules/grid.html#">grid</a> . It should be called only once, unless the collision map or the
<strong>walkable</strong> attribute changes. The clearance values are calculated and cached within the grid nodes.
<h3>Usage:</h3>
<ul>
<pre class="example">myFinder:annotateGrid()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/pathfinder.html#">pathfinder</a></span>
self (the calling <a href="../modules/pathfinder.html#">pathfinder</a> itself, can be chained)
</ol>
</dd>
<dt>
<a name = "Pathfinder:clearAnnotations"></a>
<strong>Pathfinder:clearAnnotations ()</strong>
</dt>
<dd>
Removes <a href="http://aigamedev.com/open/tutorial/clearance-based-pathfinding/#TheTrueClearanceMetric">clearance</a>values.
Clears cached clearance values for the current <strong>walkable</strong>.
<h3>Usage:</h3>
<ul>
<pre class="example">myFinder:clearAnnotations()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/pathfinder.html#">pathfinder</a></span>
self (the calling <a href="../modules/pathfinder.html#">pathfinder</a> itself, can be chained)
</ol>
</dd>
<dt>
<a name = "Pathfinder:setGrid"></a>
<strong>Pathfinder:setGrid (grid)</strong>
</dt>
<dd>
Sets the <a href="../modules/grid.html#">grid</a> . Defines the given <a href="../modules/grid.html#">grid</a> as the one on which the <a href="../modules/pathfinder.html#">pathfinder</a> will perform the search.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">grid</span>
<span class="types"><a class="type" href="../modules/grid.html#">grid</a></span>
a <a href="../modules/grid.html#">grid</a> </li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">myFinder:setGrid(myGrid)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/pathfinder.html#">pathfinder</a></span>
self (the calling <a href="../modules/pathfinder.html#">pathfinder</a> itself, can be chained)
</ol>
</dd>
<dt>
<a name = "Pathfinder:getGrid"></a>
<strong>Pathfinder:getGrid ()</strong>
</dt>
<dd>
Returns the <a href="../modules/grid.html#">grid</a> . This is a reference to the actual <a href="../modules/grid.html#">grid</a> used by the <a href="../modules/pathfinder.html#">pathfinder</a> .
<h3>Usage:</h3>
<ul>
<pre class="example">local myGrid = myFinder:getGrid()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/grid.html#">grid</a></span>
the <a href="../modules/grid.html#">grid</a>
</ol>
</dd>
<dt>
<a name = "Pathfinder:setWalkable"></a>
<strong>Pathfinder:setWalkable (walkable)</strong>
</dt>
<dd>
Sets the <strong>walkable</strong> value or function.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">walkable</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a>, <a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a> or <a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">func</a></span>
the value for walkable nodes.</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
-- Value '0' is walkable
myFinder:setWalkable(0)
-- Any value greater than 0 is walkable
myFinder:setWalkable(function(n)
return n>0
end</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/pathfinder.html#">pathfinder</a></span>
self (the calling <a href="../modules/pathfinder.html#">pathfinder</a> itself, can be chained)
</ol>
</dd>
<dt>
<a name = "Pathfinder:getWalkable"></a>
<strong>Pathfinder:getWalkable ()</strong>
</dt>
<dd>
Gets the <strong>walkable</strong> value or function.
<h3>Usage:</h3>
<ul>
<pre class="example">local walkable = myFinder:getWalkable()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a>, <a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a> or <a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">func</a></span>
the <code>walkable</code> value or function
</ol>
</dd>
<dt>
<a name = "Pathfinder:setFinder"></a>
<strong>Pathfinder:setFinder (finderName)</strong>
</dt>
<dd>
Defines the <code>finder</code>. It refers to the search algorithm used by the <a href="../modules/pathfinder.html#">pathfinder</a> .
Default finder is <code>ASTAR</code>. Use <a href="../modules/pathfinder.html#Pathfinder:getFinders">Pathfinder:getFinders</a> to get the list of available finders.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">finderName</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
the name of the <code>finder</code> to be used for further searches.</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">
--To use Breadth-First-Search
myFinder:setFinder('BFS')</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/pathfinder.html#">pathfinder</a></span>
self (the calling <a href="../modules/pathfinder.html#">pathfinder</a> itself, can be chained)
</ol>
<h3>see also:</h3>
<ul>
<a href="../modules/pathfinder.html#Pathfinder:getFinders">Pathfinder:getFinders</a>
</ul>
</dd>
<dt>
<a name = "Pathfinder:getFinder"></a>
<strong>Pathfinder:getFinder ()</strong>
</dt>
<dd>
Returns the name of the <code>finder</code> being used.
<h3>Usage:</h3>
<ul>
<pre class="example">local finderName = myFinder:getFinder()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
the name of the <code>finder</code> to be used for further searches.
</ol>
</dd>
<dt>
<a name = "Pathfinder:getFinders"></a>
<strong>Pathfinder:getFinders ()</strong>
</dt>
<dd>
Returns the list of all available finders names.
<h3>Usage:</h3>
<ul>
<pre class="example">
local finders = myFinder:getFinders()
for i, finderName in ipairs(finders) do
print(i, finderName)
end</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">{string,...}</span></span>
array of built-in finders names.
</ol>
</dd>
<dt>
<a name = "Pathfinder:setHeuristic"></a>
<strong>Pathfinder:setHeuristic (heuristic)</strong>
</dt>
<dd>
Sets a heuristic. This is a function internally used by the <a href="../modules/pathfinder.html#">pathfinder</a> to find the optimal path during a search.
Use <a href="../modules/pathfinder.html#Pathfinder:getHeuristics">Pathfinder:getHeuristics</a> to get the list of all available <code>heuristics</code>. One can also define
his own <code>heuristic</code> function.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">heuristic</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">func</a> or <a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
<code>heuristic</code> function, prototyped as <strong>f(dx,dy)</strong> or as a <a href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a> .</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">myFinder:setHeuristic('MANHATTAN')</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/pathfinder.html#">pathfinder</a></span>
self (the calling <a href="../modules/pathfinder.html#">pathfinder</a> itself, can be chained)
</ol>
<h3>see also:</h3>
<ul>
<li><a href="../modules/pathfinder.html#Pathfinder:getHeuristics">Pathfinder:getHeuristics</a></li>
<li><a href="../modules/core.heuristics.html#">core.heuristics</a></li>
</ul>
</dd>
<dt>
<a name = "Pathfinder:getHeuristic"></a>
<strong>Pathfinder:getHeuristic ()</strong>
</dt>
<dd>
Returns the <code>heuristic</code> used. Returns the function itself.
<h3>Usage:</h3>
<ul>
<pre class="example">local h = myFinder:getHeuristic()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">func</a></span>
the <code>heuristic</code> function being used by the <a href="../modules/pathfinder.html#">pathfinder</a>
</ol>
<h3>see also:</h3>
<ul>
<a href="../modules/core.heuristics.html#">core.heuristics</a>
</ul>
</dd>
<dt>
<a name = "Pathfinder:getHeuristics"></a>
<strong>Pathfinder:getHeuristics ()</strong>
</dt>
<dd>
Gets the list of all available <code>heuristics</code>.
<h3>Usage:</h3>
<ul>
<pre class="example">
local heur = myFinder:getHeuristic()
for i, heuristicName in ipairs(heur) do
...
end</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">{string,...}</span></span>
array of heuristic names.
</ol>
<h3>see also:</h3>
<ul>
<a href="../modules/core.heuristics.html#">core.heuristics</a>
</ul>
</dd>
<dt>
<a name = "Pathfinder:setMode"></a>
<strong>Pathfinder:setMode (mode)</strong>
</dt>
<dd>
Defines the search <code>mode</code>.
The default search mode is the <code>DIAGONAL</code> mode, which implies 8-possible directions when moving (north, south, east, west and diagonals).
In <code>ORTHOGONAL</code> mode, only 4-directions are allowed (north, south, east and west).
Use <a href="../modules/pathfinder.html#Pathfinder:getModes">Pathfinder:getModes</a> to get the list of all available search modes.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">mode</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
the new search <code>mode</code>.</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">myFinder:setMode('ORTHOGNAL')</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/pathfinder.html#">pathfinder</a></span>
self (the calling <a href="../modules/pathfinder.html#">pathfinder</a> itself, can be chained)
</ol>
<h3>see also:</h3>
<ul>
<li><a href="../modules/pathfinder.html#Pathfinder:getModes">Pathfinder:getModes</a></li>
<li><a href="../modules/pathfinder.html#Modes">Modes</a></li>
</ul>
</dd>
<dt>
<a name = "Pathfinder:getMode"></a>
<strong>Pathfinder:getMode ()</strong>
</dt>
<dd>
Returns the search mode.
<h3>Usage:</h3>
<ul>
<pre class="example">local mode = myFinder:getMode()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
the current search mode
</ol>
<h3>see also:</h3>
<ul>
<a href="../modules/pathfinder.html#Modes">Modes</a>
</ul>
</dd>
<dt>
<a name = "Pathfinder:getModes"></a>
<strong>Pathfinder:getModes ()</strong>
</dt>
<dd>
Gets the list of all available search modes.
<h3>Usage:</h3>
<ul>
<pre class="example"> local modes = myFinder:getModes()
for modeName in ipairs(modes) do
...
end</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">{string,...}</span></span>
array of search modes.
</ol>
<h3>see also:</h3>
<ul>
<a href="../modules/pathfinder.html#Modes">Modes</a>
</ul>
</dd>
<dt>
<a name = "Pathfinder:setTunnelling"></a>
<strong>Pathfinder:setTunnelling (bool)</strong>
</dt>
<dd>
Enables tunnelling. Defines the ability for the <a href="../modules/pathfinder.html#">pathfinder</a> to tunnel through walls when heading diagonally.
This feature <strong>is not compatible</strong> with Jump Point Search algorithm (i.e. enabling it will not affect Jump Point Search)
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">bool</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">bool</a></span>
a boolean</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">myFinder:setTunnelling(true)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/pathfinder.html#">pathfinder</a></span>
self (the calling <a href="../modules/pathfinder.html#">pathfinder</a> itself, can be chained)
</ol>
</dd>
<dt>
<a name = "Pathfinder:getTunnelling"></a>
<strong>Pathfinder:getTunnelling ()</strong>
</dt>
<dd>
Returns tunnelling feature state.
<h3>Usage:</h3>
<ul>
<pre class="example">local isTunnellingEnabled = myFinder:getTunnelling()</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">bool</a></span>
tunnelling feature actual state
</ol>
</dd>
<dt>
<a name = "Pathfinder:getPath"></a>
<strong>Pathfinder:getPath (startX, startY, endX, endY, clearance)</strong>
</dt>
<dd>
Calculates a <code>path</code>. Returns the <code>path</code> from location <strong>[startX, startY]</strong> to location <strong>[endX, endY]</strong>.
Both locations must exist on the collision map. The starting location can be unwalkable.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">startX</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the x-coordinate for the starting location</li>
<li><span class="parameter">startY</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the y-coordinate for the starting location</li>
<li><span class="parameter">endX</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the x-coordinate for the goal location</li>
<li><span class="parameter">endY</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the y-coordinate for the goal location</li>
<li><span class="parameter">clearance</span>
<span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#2.2">int</a></span>
the amount of clearance (i.e the pathing agent size) to consider</li>
</ul>
<h3>Usage:</h3>
<ul>
<pre class="example">local path = myFinder:getPath(1,1,5,5)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">path</span></span>
a path (array of nodes) when found, otherwise nil
</ol>
</dd>
<dt>
<a name = "Pathfinder:reset"></a>
<strong>Pathfinder:reset ()</strong>
</dt>
<dd>
Resets the <a href="../modules/pathfinder.html#">pathfinder</a> . This function is called internally between successive pathfinding calls, so you should not
use it explicitely, unless under specific circumstances.
<h3>Usage:</h3>
<ul>
<pre class="example">local path, len = myFinder:getPath(1,1,5,5)</pre>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../modules/pathfinder.html#">pathfinder</a></span>
self (the calling <a href="../modules/pathfinder.html#">pathfinder</a> itself, can be chained)
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.2</a></i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>
================================================
FILE: examples/annotatedPathing.lua
================================================
-- Tests sample for clearance metrics calculation
-- See Figure 10 at http://aigamedev.com/open/tutorial/clearance-based-pathfinding/
-- Jump Point Search still has some flaws with clearance based pathfinding
local Grid = require 'jumper.grid'
local PF = require 'jumper.pathfinder'
local map = {
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,1,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,1,0,0,0,0,0,0},
{0,0,1,0,0,0,0,0,2,0},
{0,0,1,1,1,0,0,2,0,0},
{0,0,0,1,1,0,2,0,0,2},
{0,0,0,0,1,0,0,0,0,2},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0}
}
local grid = Grid(map)
local walkable = function(v) return v~=2 end
local finder = PF(grid, 'ASTAR',walkable)
finder:annotateGrid()
local finderNames = PF:getFinders()
local sx, sy = 1,1
local ex, ey = 9,9
local agent_size = 2
for i = 1,#finderNames do
finder:setFinder(finderNames[i])
local path = finder:getPath(sx, sy, ex, ey, agent_size)
print(('Algorithm used: %s - Path %s')
:format(finder:getFinder(), path and 'found' or 'not found'))
if path then
for node, count in path:nodes() do
print((' Step %d. (%d,%d)')
:format(count, node:getPos()))
end
end
end
================================================
FILE: examples/customHeuristics.lua
================================================
--- Example of use for Heuristics
local Grid = require ("jumper.grid")
local Pathfinder = require ("jumper.pathfinder")
local map = {
{0,0,0,0,0,0},
{0,0,0,0,0,0},
{0,1,1,1,1,0},
{0,0,0,0,0,0},
{0,0,0,0,0,0},
}
local walkable = 0
local grid = Grid(map)
local myFinder = Pathfinder(grid, 'ASTAR', walkable)
-- Use Euclidian heuristic to evaluate distance
myFinder:setHeuristic('EUCLIDIAN')
myFinder:setHeuristic('DIAGONAL')
myFinder:setHeuristic('MANHATTAN')
-- Custom
local h = function(nodeA, nodeB)
return (0.1 * (math.abs(nodeA:getX() - nodeB:getX()))
+ 0.9 * (math.abs(nodeA:getY() - nodeB:getY())))
end
myFinder:setHeuristic(h)
local p = myFinder:getPath(1,1, 6,5)
for node, count in p:nodes() do
print(('%d. Node(%d,%d)'):format(count, node:getX(), node:getY()))
end
print(('Path length: %.2f'):format(p:getLength()))
-- etc ...
================================================
FILE: examples/makeClearance.lua
================================================
-- Tests sample for clearance metrics calculation
-- See Figure 10 at http://aigamedev.com/open/tutorial/clearance-based-pathfinding/
local Grid = require 'jumper.grid'
local PF = require 'jumper.pathfinder'
local map = {
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,1,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,1,0,0,0,0,0,0},
{0,0,1,0,0,0,0,0,2,0},
{0,0,1,1,1,0,0,2,0,0},
{0,0,0,1,1,0,2,0,0,2},
{0,0,0,0,1,0,0,0,0,2},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0}
}
local grid = Grid(map)
local walkable = function(v) return v~=2 end
local finder = PF(grid, 'ASTAR',walkable)
finder:annotateGrid()
for y = 1, #map do
local s = ''
for x = 1, #map[y] do
local node = grid:getNodeAt(x,y)
s = (s .. ' ' .. node:getClearance(walkable))
end
print(s)
end
-- Expected output
-- 6 6 5 5 4 4 4 3 2 1
-- 6 5 5 4 4 3 3 3 2 1
-- 6 5 4 4 3 3 2 2 2 1
-- 6 5 4 3 3 2 2 1 1 1
-- 6 5 4 3 2 2 1 1 0 1
-- 5 5 4 3 2 1 1 0 1 1
-- 4 4 4 3 2 1 0 2 1 0
-- 3 3 3 3 3 3 3 2 1 0
-- 2 2 2 2 2 2 2 2 2 1
-- 1 1 1 1 1 1 1 1 1 1
================================================
FILE: examples/simpleExample.lua
================================================
--- Very minimal usage example for Jumper
-- Set up a collision map
local map = {
{0,1,0,1,0},
{0,1,0,1,0},
{0,1,1,1,0},
{0,0,0,0,0},
}
-- Value for walkable tiles
local walkable = 0
-- Library setup
-- Calls the grid class
local Grid = require ("jumper.grid")
-- Calls the pathfinder class
local Pathfinder = require ("jumper.pathfinder")
-- Creates a grid object
local grid = Grid(map)
-- Creates a pathfinder object using Jump Point Search algorithm
local myFinder = Pathfinder(grid, 'JPS', walkable)
-- Define start and goal locations coordinates
local startx, starty = 1,1
local endx, endy = 5,1
-- Calculates the path, and its length
local path = myFinder:getPath(startx, starty, endx, endy)
-- Pretty-printing the results
if path then
print(('Path found! Length: %.2f'):format(path:getLength()))
for node, count in path:nodes() do
print(('Step: %d - x: %d - y: %d'):format(count, node:getX(), node:getY()))
end
end
================================================
FILE: jumper/core/assert.lua
================================================
-- Various assertion function for API methods argument-checking
if (...) then
-- Dependancies
local _PATH = (...):gsub('%.core.assert$','')
local Utils = require (_PATH .. '.core.utils')
-- Local references
local lua_type = type
local floor = math.floor
local concat = table.concat
local next = next
local pairs = pairs
local getmetatable = getmetatable
-- Is I an integer ?
local function isInteger(i)
return lua_type(i) ==('number') and (floor(i)==i)
end
-- Override lua_type to return integers
local function type(v)
return isInteger(v) and 'int' or lua_type(v)
end
-- Does the given array contents match a predicate type ?
local function arrayContentsMatch(t,...)
local n_count = Utils.arraySize(t)
if n_count < 1 then return false end
local init_count = t[0] and 0 or 1
local n_count = (t[0] and n_count-1 or n_count)
local types = {...}
if types then types = concat(types) end
for i=init_count,n_count,1 do
if not t[i] then return false end
if types then
if not types:match(type(t[i])) then return false end
end
end
return true
end
-- Checks if arg is a valid array map
local function isMap(m)
if not arrayContentsMatch(m, 'table') then return false end
local lsize = Utils.arraySize(m[next(m)])
for k,v in pairs(m) do
if not arrayContentsMatch(m[k], 'string', 'int') then return false end
if Utils.arraySize(v)~=lsize then return false end
end
return true
end
-- Checks if s is a valid string map
local function isStringMap(s)
if lua_type(s) ~= 'string' then return false end
local w
for row in s:gmatch('[^\n\r]+') do
if not row then return false end
w = w or #row
if w ~= #row then return false end
end
return true
end
-- Does instance derive straight from class
local function derives(instance, class)
return getmetatable(instance) == class
end
-- Does instance inherits from class
local function inherits(instance, class)
return (getmetatable(getmetatable(instance)) == class)
end
-- Is arg a boolean
local function isBoolean(b)
return (b==true or b==false)
end
-- Is arg nil ?
local function isNil(n)
return (n==nil)
end
local function matchType(value, types)
return types:match(type(value))
end
return {
arrayContentsMatch = arrayContentsMatch,
derives = derives,
inherits = inherits,
isInteger = isInteger,
isBool = isBoolean,
isMap = isMap,
isStrMap = isStringMap,
isOutOfRange = isOutOfRange,
isNil = isNil,
type = type,
matchType = matchType
}
end
================================================
FILE: jumper/core/bheap.lua
================================================
--- A light implementation of Binary heaps data structure.
-- While running a search, some search algorithms (Astar, Dijkstra, Jump Point Search) have to maintains
-- a list of nodes called __open list__. Retrieve from this list the lowest cost node can be quite slow,
-- as it normally requires to skim through the full set of nodes stored in this list. This becomes a real
-- problem especially when dozens of nodes are being processed (on large maps).
--
-- The current module implements a <a href="http://www.policyalmanac.org/games/binaryHeaps.htm">binary heap</a>
-- data structure, from which the search algorithm will instantiate an open list, and cache the nodes being
-- examined during a search. As such, retrieving the lower-cost node is faster and globally makes the search end
-- up quickly.
--
-- This module is internally used by the library on purpose.
-- It should normally not be used explicitely, yet it remains fully accessible.
--
--[[
Notes:
This lighter implementation of binary heaps, based on :
https://github.com/Yonaba/Binary-Heaps
--]]
if (...) then
-- Dependency
local Utils = require((...):gsub('%.bheap$','.utils'))
-- Local reference
local floor = math.floor
-- Default comparison function
local function f_min(a,b) return a < b end
-- Percolates up
local function percolate_up(heap, index)
if index == 1 then return end
local pIndex
if index <= 1 then return end
if index%2 == 0 then
pIndex = index/2
else pIndex = (index-1)/2
end
if not heap._sort(heap._heap[pIndex], heap._heap[index]) then
heap._heap[pIndex], heap._heap[index] =
heap._heap[index], heap._heap[pIndex]
percolate_up(heap, pIndex)
end
end
-- Percolates down
local function percolate_down(heap,index)
local lfIndex,rtIndex,minIndex
lfIndex = 2*index
rtIndex = lfIndex + 1
if rtIndex > heap._size then
if lfIndex > heap._size then return
else minIndex = lfIndex end
else
if heap._sort(heap._heap[lfIndex],heap._heap[rtIndex]) then
minIndex = lfIndex
else
minIndex = rtIndex
end
end
if not heap._sort(heap._heap[index],heap._heap[minIndex]) then
heap._heap[index],heap._heap[minIndex] = heap._heap[minIndex],heap._heap[index]
percolate_down(heap,minIndex)
end
end
-- Produces a new heap
local function newHeap(template,comp)
return setmetatable({_heap = {},
_sort = comp or f_min, _size = 0},
template)
end
--- The `heap` class.<br/>
-- This class is callable.
-- _Therefore,_ <code>heap(...)</code> _is used to instantiate new heaps_.
-- @type heap
local heap = setmetatable({},
{__call = function(self,...)
return newHeap(self,...)
end})
heap.__index = heap
--- Checks if a `heap` is empty
-- @class function
-- @treturn bool __true__ of no item is queued in the heap, __false__ otherwise
-- @usage
-- if myHeap:empty() then
-- print('Heap is empty!')
-- end
function heap:empty()
return (self._size==0)
end
--- Clears the `heap` (removes all items queued in the heap)
-- @class function
-- @treturn heap self (the calling `heap` itself, can be chained)
-- @usage myHeap:clear()
function heap:clear()
self._heap = {}
self._size = 0
self._sort = self._sort or f_min
return self
end
--- Adds a new item in the `heap`
-- @class function
-- @tparam value item a new value to be queued in the heap
-- @treturn heap self (the calling `heap` itself, can be chained)
-- @usage
-- myHeap:push(1)
-- -- or, with chaining
-- myHeap:push(1):push(2):push(4)
function heap:push(item)
if item then
self._size = self._size + 1
self._heap[self._size] = item
percolate_up(self, self._size)
end
return self
end
--- Pops from the `heap`.
-- Removes and returns the lowest cost item (with respect to the comparison function being used) from the `heap`.
-- @class function
-- @treturn value a value previously pushed into the heap
-- @usage
-- while not myHeap:empty() do
-- local lowestValue = myHeap:pop()
-- ...
-- end
function heap:pop()
local root
if self._size > 0 then
root = self._heap[1]
self._heap[1] = self._heap[self._size]
self._heap[self._size] = nil
self._size = self._size-1
if self._size>1 then
percolate_down(self, 1)
end
end
return root
end
--- Restores the `heap` property.
-- Reorders the `heap` with respect to the comparison function being used.
-- When given argument __item__ (a value existing in the `heap`), will sort from that very item in the `heap`.
-- Otherwise, the whole `heap` will be cheacked.
-- @class function
-- @tparam[opt] value item the modified value
-- @treturn heap self (the calling `heap` itself, can be chained)
-- @usage myHeap:heapify()
function heap:heapify(item)
if self._size == 0 then return end
if item then
local i = Utils.indexOf(self._heap,item)
if i then
percolate_down(self, i)
percolate_up(self, i)
end
return
end
for i = floor(self._size/2),1,-1 do
percolate_down(self,i)
end
return self
end
return heap
end
================================================
FILE: jumper/core/heuristics.lua
================================================
--- Heuristic functions for search algorithms.
-- A <a href="http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html">distance heuristic</a>
-- provides an *estimate of the optimal distance cost* from a given location to a target.
-- As such, it guides the pathfinder to the goal, helping it to decide which route is the best.
--
-- This script holds the definition of some built-in heuristics available through jumper.
--
-- Distance functions are internally used by the `pathfinder` to evaluate the optimal path
-- from the start location to the goal. These functions share the same prototype:
-- local function myHeuristic(nodeA, nodeB)
-- -- function body
-- end
-- Jumper features some built-in distance heuristics, namely `MANHATTAN`, `EUCLIDIAN`, `DIAGONAL`, `CARDINTCARD`.
-- You can also supply your own heuristic function, following the same template as above.
local abs = math.abs
local sqrt = math.sqrt
local sqrt2 = sqrt(2)
local max, min = math.max, math.min
local Heuristics = {}
--- Manhattan distance.
-- <br/>This heuristic is the default one being used by the `pathfinder` object.
-- <br/>Evaluates as <code>distance = |dx|+|dy|</code>
-- @class function
-- @tparam node nodeA a node
-- @tparam node nodeB another node
-- @treturn number the distance from __nodeA__ to __nodeB__
-- @usage
-- -- First method
-- pathfinder:setHeuristic('MANHATTAN')
-- -- Second method
-- local Distance = require ('jumper.core.heuristics')
-- pathfinder:setHeuristic(Distance.MANHATTAN)
function Heuristics.MANHATTAN(nodeA, nodeB)
local dx = abs(nodeA._x - nodeB._x)
local dy = abs(nodeA._y - nodeB._y)
return (dx + dy)
end
--- Euclidian distance.
-- <br/>Evaluates as <code>distance = squareRoot(dx*dx+dy*dy)</code>
-- @class function
-- @tparam node nodeA a node
-- @tparam node nodeB another node
-- @treturn number the distance from __nodeA__ to __nodeB__
-- @usage
-- -- First method
-- pathfinder:setHeuristic('EUCLIDIAN')
-- -- Second method
-- local Distance = require ('jumper.core.heuristics')
-- pathfinder:setHeuristic(Distance.EUCLIDIAN)
function Heuristics.EUCLIDIAN(nodeA, nodeB)
local dx = nodeA._x - nodeB._x
local dy = nodeA._y - nodeB._y
return sqrt(dx*dx+dy*dy)
end
--- Diagonal distance.
-- <br/>Evaluates as <code>distance = max(|dx|, abs|dy|)</code>
-- @class function
-- @tparam node nodeA a node
-- @tparam node nodeB another node
-- @treturn number the distance from __nodeA__ to __nodeB__
-- @usage
-- -- First method
-- pathfinder:setHeuristic('DIAGONAL')
-- -- Second method
-- local Distance = require ('jumper.core.heuristics')
-- pathfinder:setHeuristic(Distance.DIAGONAL)
function Heuristics.DIAGONAL(nodeA, nodeB)
local dx = abs(nodeA._x - nodeB._x)
local dy = abs(nodeA._y - nodeB._y)
return max(dx,dy)
end
--- Cardinal/Intercardinal distance.
-- <br/>Evaluates as <code>distance = min(dx, dy)*squareRoot(2) + max(dx, dy) - min(dx, dy)</code>
-- @class function
-- @tparam node nodeA a node
-- @tparam node nodeB another node
-- @treturn number the distance from __nodeA__ to __nodeB__
-- @usage
-- -- First method
-- pathfinder:setHeuristic('CARDINTCARD')
-- -- Second method
-- local Distance = require ('jumper.core.heuristics')
-- pathfinder:setHeuristic(Distance.CARDINTCARD)
function Heuristics.CARDINTCARD(nodeA, nodeB)
local dx = abs(nodeA._x - nodeB._x)
local dy = abs(nodeA._y - nodeB._y)
return min(dx,dy) * sqrt2 + max(dx,dy) - min(dx,dy)
end
return Heuristics
================================================
FILE: jumper/core/lookuptable.lua
================================================
local addNode(self, node, nextNode, ed)
if not self._pathDB[node] then self._pathDB[node] = {} end
self._pathDB[node][ed] = (nextNode == ed and node or nextNode)
end
-- Path lookupTable
local lookupTable = {}
lookupTable.__index = lookupTable
function lookupTable:new()
local lut = {_pathDB = {}}
return setmetatable(lut, lookupTable)
end
function lookupTable:addPath(path)
local st, ed = path._nodes[1], path._nodes[#path._nodes]
for node, count in path:nodes() do
local nextNode = path._nodes[count+1]
if nextNode then addNode(self, node, nextNode, ed) end
end
end
function lookupTable:hasPath(nodeA, nodeB)
local found
found = self._pathDB[nodeA] and self._path[nodeA][nodeB]
if found then return true, true end
found = self._pathDB[nodeB] and self._path[nodeB][nodeA]
if found then return true, false end
return false
end
return lookupTable
================================================
FILE: jumper/core/node.lua
================================================
--- The Node class.
-- The `node` represents a cell (or a tile) on a collision map. Basically, for each single cell (tile)
-- in the collision map passed-in upon initialization, a `node` object will be generated
-- and then cached within the `grid`.
--
-- In the following implementation, nodes can be compared using the `<` operator. The comparison is
-- made with regards of their `f` cost. From a given node being examined, the `pathfinder` will expand the search
-- to the next neighbouring node having the lowest `f` cost. See `core.bheap` for more details.
--
if (...) then
local assert = assert
--- The `Node` class.<br/>
-- This class is callable.
-- Therefore,_ <code>Node(...)</code> _acts as a shortcut to_ <code>Node:new(...)</code>.
-- @type Node
local Node = {}
Node.__index = Node
--- Inits a new `node`
-- @class function
-- @tparam int x the x-coordinate of the node on the collision map
-- @tparam int y the y-coordinate of the node on the collision map
-- @treturn node a new `node`
-- @usage local node = Node(3,4)
function Node:new(x,y)
return setmetatable({_x = x, _y = y, _clearance = {}}, 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
--- Returns x-coordinate of a `node`
-- @class function
-- @treturn number the x-coordinate of the `node`
-- @usage local x = node:getX()
function Node:getX() return self._x end
--- Returns y-coordinate of a `node`
-- @class function
-- @treturn number the y-coordinate of the `node`
-- @usage local y = node:getY()
function Node:getY() return self._y end
--- Returns x and y coordinates of a `node`
-- @class function
-- @treturn number the x-coordinate of the `node`
-- @treturn number the y-coordinate of the `node`
-- @usage local x, y = node:getPos()
function Node:getPos() return self._x, self._y end
--- Returns the amount of true [clearance](http://aigamedev.com/open/tutorial/clearance-based-pathfinding/#TheTrueClearanceMetric)
-- for a given `node`
-- @class function
-- @tparam string|int|func walkable the value for walkable locations in the collision map array.
-- @treturn int the clearance of the `node`
-- @usage
-- -- Assuming walkable was 0
-- local clearance = node:getClearance(0)
function Node:getClearance(walkable)
return self._clearance[walkable]
end
--- Removes the clearance value for a given walkable.
-- @class function
-- @tparam string|int|func walkable the value for walkable locations in the collision map array.
-- @treturn node self (the calling `node` itself, can be chained)
-- @usage
-- -- Assuming walkable is defined
-- node:removeClearance(walkable)
function Node:removeClearance(walkable)
self._clearance[walkable] = nil
return self
end
--- Clears temporary cached attributes of a `node`.
-- Deletes the attributes cached within a given node after a pathfinding call.
-- This function is internally used by the search algorithms, so you should not use it explicitely.
-- @class function
-- @treturn node self (the calling `node` itself, can be chained)
-- @usage
-- local thisNode = Node(1,2)
-- thisNode:reset()
function Node:reset()
self._g, self._h, self._f = nil, nil, nil
self._opened, self._closed, self._parent = nil, nil, nil
return self
end
return setmetatable(Node,
{__call = function(self,...)
return Node:new(...)
end}
)
end
================================================
FILE: jumper/core/path.lua
================================================
--- The Path class.
-- The `path` class is a structure which represents a path (ordered set of nodes) from a start location to a goal.
-- An instance from this class would be a result of a request addressed to `Pathfinder:getPath`.
--
-- This module is internally used by the library on purpose.
-- It should normally not be used explicitely, yet it remains fully accessible.
--
if (...) then
-- Dependencies
local _PATH = (...):match('(.+)%.path$')
local Heuristic = require (_PATH .. '.heuristics')
-- Local references
local abs, max = math.abs, math.max
local t_insert, t_remove = table.insert, table.remove
--- The `Path` class.<br/>
-- This class is callable.
-- Therefore, <em><code>Path(...)</code></em> acts as a shortcut to <em><code>Path:new(...)</code></em>.
-- @type Path
local Path = {}
Path.__index = Path
--- Inits a new `path`.
-- @class function
-- @treturn path a `path`
-- @usage local p = Path()
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}
-- @class function
-- @treturn node a `node`
-- @treturn int the count for the number of nodes
-- @see Path:nodes
-- @usage
-- for node, count in p:iter() do
-- ...
-- end
function Path:iter()
local i,pathLen = 1,#self._nodes
return function()
if self._nodes[i] then
i = i+1
return self._nodes[i-1],i-1
end
end
end
--- Iterates on each single `node` along a `path`. At each step of iteration,
-- returns a `node` plus a count value. Alias for @{Path:iter}
-- @class function
-- @name Path:nodes
-- @treturn node a `node`
-- @treturn int the count for the number of nodes
-- @see Path:iter
-- @usage
-- for node, count in p:nodes() do
-- ...
-- end
Path.nodes = Path.iter
--- Evaluates the `path` length
-- @class function
-- @treturn number the `path` length
-- @usage local len = p:getLength()
function Path:getLength()
local len = 0
for i = 2,#self._nodes do
len = len + Heuristic.EUCLIDIAN(self._nodes[i], self._nodes[i-1])
end
return len
end
--- Counts the number of steps.
-- Returns the number of waypoints (nodes) in the current path.
-- @class function
-- @tparam node node a node to be added to the path
-- @tparam[opt] int index the index at which the node will be inserted. If omitted, the node will be appended after the last node in the path.
-- @treturn path self (the calling `path` itself, can be chained)
-- @usage local nSteps = p:countSteps()
function Path:addNode(node, index)
index = index or #self._nodes+1
t_insert(self._nodes, index, node)
return self
end
--- `Path` filling modifier. Interpolates between non contiguous nodes along a `path`
-- to build a fully continuous `path`. This maybe useful when using search algorithms such as Jump Point Search.
-- Does the opposite of @{Path:filter}
-- @class function
-- @treturn path self (the calling `path` itself, can be chained)
-- @see Path:filter
-- @usage p:fill()
function Path:fill()
local i = 2
local xi,yi,dx,dy
local N = #self._nodes
local incrX, incrY
while true do
xi,yi = self._nodes[i]._x,self._nodes[i]._y
dx,dy = xi-self._nodes[i-1]._x,yi-self._nodes[i-1]._y
if (abs(dx) > 1 or abs(dy) > 1) then
incrX = dx/max(abs(dx),1)
incrY = dy/max(abs(dy),1)
t_insert(self._nodes, i, self._grid:getNodeAt(self._nodes[i-1]._x + incrX, self._nodes[i-1]._y +incrY))
N = N+1
else i=i+1
end
if i>N then 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,dx,dy, olddx, olddy
xi,yi = self._nodes[i]._x, self._nodes[i]._y
dx, dy = xi - self._nodes[i-1]._x, yi-self._nodes[i-1]._y
while true do
olddx, olddy = dx, dy
if self._nodes[i+1] then
i = i+1
xi, yi = self._nodes[i]._x, self._nodes[i]._y
dx, dy = xi - self._nodes[i-1]._x, yi - self._nodes[i-1]._y
if olddx == dx and olddy == dy then
t_remove(self._nodes, i-1)
i = i - 1
end
else break end
end
return self
end
--- Clones a `path`.
-- @class function
-- @treturn path a `path`
-- @usage local p = path:clone()
function Path:clone()
local p = Path:new()
for node in self:nodes() do p:addNode(node) end
return p
end
--- Checks if a `path` is equal to another. It also supports *filtered paths* (see @{Path:filter}).
-- @class function
-- @tparam path p2 a path
-- @treturn boolean a boolean
-- @usage print(myPath:isEqualTo(anotherPath))
function Path:isEqualTo(p2)
local p1 = self:clone():filter()
local p2 = p2:clone():filter()
for node, count in p1:nodes() do
if not p2._nodes[count] then return false end
local n = p2._nodes[count]
if n._x~=node._x or n._y~=node._y then return false end
end
return true
end
--- Reverses a `path`.
-- @class function
-- @treturn path self (the calling `path` itself, can be chained)
-- @usage myPath:reverse()
function Path:reverse()
local _nodes = {}
for i = #self._nodes,1,-1 do
_nodes[#_nodes+1] = self._nodes[i]
end
self._nodes = _nodes
return self
end
--- Appends a given `path` to self.
-- @class function
-- @tparam path p a path
-- @treturn path self (the calling `path` itself, can be chained)
-- @usage myPath:append(anotherPath)
function Path:append(p)
for node in p:nodes() do self:addNode(node) end
return self
end
return setmetatable(Path,
{__call = function(self,...)
return Path:new(...)
end
})
end
================================================
FILE: jumper/core/utils.lua
================================================
-- Various utilities for Jumper top-level modules
if (...) then
-- Dependencies
local _PATH = (...):gsub('%.utils$','')
local Path = require (_PATH .. '.path')
local Node = require (_PATH .. '.node')
-- Local references
local pairs = pairs
local type = type
local t_insert = table.insert
local assert = assert
local coroutine = coroutine
-- Raw array items count
local function arraySize(t)
local count = 0
for k,v in pairs(t) do
count = count+1
end
return count
end
-- Parses a string map and builds an array map
local function stringMapToArray(str)
local map = {}
local w, h
for line in str:gmatch('[^\n\r]+') do
if line then
w = not w and #line or w
assert(#line == w, 'Error parsing map, rows must have the same size!')
h = (h or 0) + 1
map[h] = {}
for char in line:gmatch('.') do
map[h][#map[h]+1] = char
end
end
end
return map
end
-- Collects and returns the keys of a given array
local function getKeys(t)
local keys = {}
for k,v in pairs(t) do keys[#keys+1] = k end
return keys
end
-- Calculates the bounds of a 2d array
local function getArrayBounds(map)
local min_x, max_x
local min_y, max_y
for y in pairs(map) do
min_y = not min_y and y or (y<min_y and y or min_y)
max_y = not max_y and y or (y>max_y and y or max_y)
for x in pairs(map[y]) do
min_x = not min_x and x or (x<min_x and x or min_x)
max_x = not max_x and x or (x>max_x and x or max_x)
end
end
return min_x,max_x,min_y,max_y
end
-- Converts an array to a set of nodes
local function arrayToNodes(map)
local min_x, max_x
local min_y, max_y
local nodes = {}
for y in pairs(map) do
min_y = not min_y and y or (y<min_y and y or min_y)
max_y = not max_y and y or (y>max_y and y or max_y)
nodes[y] = {}
for x in pairs(map[y]) do
min_x = not min_x and x or (x<min_x and x or min_x)
max_x = not max_x and x or (x>max_x and x or max_x)
nodes[y][x] = Node:new(x,y)
end
end
return nodes,
(min_x or 0), (max_x or 0),
(min_y or 0), (max_y or 0)
end
-- Iterator, wrapped within a coroutine
-- Iterates around a given position following the outline of a square
local function around()
local iterf = function(x0, y0, s)
local x, y = x0-s, y0-s
coroutine.yield(x, y)
repeat
x = x + 1
coroutine.yield(x,y)
until x == x0+s
repeat
y = y + 1
coroutine.yield(x,y)
until y == y0 + s
repeat
x = x - 1
coroutine.yield(x, y)
until x == x0-s
repeat
y = y - 1
coroutine.yield(x,y)
until y == y0-s+1
end
return coroutine.create(iterf)
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
-- Lookup for value in a table
local indexOf = function(t,v)
for i = 1,#t do
if t[i] == v then return i end
end
return nil
end
-- Is i out of range
local function outOfRange(i,low,up)
return (i< low or i > up)
end
return {
arraySize = arraySize,
getKeys = getKeys,
indexOf = indexOf,
outOfRange = outOfRange,
getArrayBounds = getArrayBounds,
arrayToNodes = arrayToNodes,
strToMap = stringMapToArray,
around = around,
drAround = drAround,
traceBackPath = traceBackPath
}
end
================================================
FILE: jumper/grid.lua
================================================
--- The Grid class.
-- Implementation of the `grid` class.
-- The `grid` is a implicit graph which represents the 2D
-- world map layout on which the `pathfinder` object will run.
-- During a search, the `pathfinder` object needs to save some critical values. These values are cached within each `node`
-- object, and the whole set of nodes are tight inside the `grid` object itself.
if (...) then
-- Dependencies
local _PATH = (...):gsub('%.grid$','')
-- Local references
local Utils = require (_PATH .. '.core.utils')
local Assert = require (_PATH .. '.core.assert')
local Node = require (_PATH .. '.core.node')
-- Local references
local pairs = pairs
local assert = assert
local next = next
local setmetatable = setmetatable
local floor = math.floor
local coroutine = coroutine
-- Offsets for straights moves
local straightOffsets = {
{x = 1, y = 0} --[[W]], {x = -1, y = 0}, --[[E]]
{x = 0, y = 1} --[[S]], {x = 0, y = -1}, --[[N]]
}
-- Offsets for diagonal moves
local diagonalOffsets = {
{x = -1, y = -1} --[[NW]], {x = 1, y = -1}, --[[NE]]
{x = -1, y = 1} --[[SW]], {x = 1, y = 1}, --[[SE]]
}
--- The `Grid` class.<br/>
-- This class is callable.
-- Therefore,_ <code>Grid(...)</code> _acts as a shortcut to_ <code>Grid:new(...)</code>.
-- @type Grid
local Grid = {}
Grid.__index = Grid
-- Specialized grids
local PreProcessGrid = setmetatable({},Grid)
local PostProcessGrid = setmetatable({},Grid)
PreProcessGrid.__index = PreProcessGrid
PostProcessGrid.__index = PostProcessGrid
PreProcessGrid.__call = function (self,x,y)
return self:getNodeAt(x,y)
end
PostProcessGrid.__call = function (self,x,y,create)
if create then return self:getNodeAt(x,y) end
return self._nodes[y] and self._nodes[y][x]
end
--- Inits a new `grid`
-- @class function
-- @tparam table|string map A collision map - (2D array) with consecutive indices (starting at 0 or 1)
-- or a `string` with line-break chars (<code>\n</code> or <code>\r</code>) as row delimiters.
-- @tparam[opt] bool cacheNodeAtRuntime When __true__, returns an empty `grid` instance, so that
-- later on, indexing a non-cached `node` will cause it to be created and cache within the `grid` on purpose (i.e, when needed).
-- This is a __memory-safe__ option, in case your dealing with some tight memory constraints.
-- Defaults to __false__ when omitted.
-- @treturn grid a new `grid` instance
-- @usage
-- -- A simple 3x3 grid
-- local myGrid = Grid:new({{0,0,0},{0,0,0},{0,0,0}})
--
-- -- A memory-safe 3x3 grid
-- myGrid = Grid('000\n000\n000', true)
function Grid:new(map, cacheNodeAtRuntime)
if type(map) == 'string' then
assert(Assert.isStrMap(map), 'Wrong argument #1. Not a valid string map')
map = Utils.strToMap(map)
end
assert(Assert.isMap(map),('Bad argument #1. Not a valid map'))
assert(Assert.isBool(cacheNodeAtRuntime) or Assert.isNil(cacheNodeAtRuntime),
('Bad argument #2. Expected \'boolean\', got %s.'):format(type(cacheNodeAtRuntime)))
if cacheNodeAtRuntime then
return PostProcessGrid:new(map,walkable)
end
return PreProcessGrid:new(map,walkable)
end
--- Checks if `node` at [x,y] is __walkable__.
-- Will check if `node` at location [x,y] both *exists* on the collision map and *is walkable*
-- @class function
-- @tparam int x the x-location of the node
-- @tparam int y the y-location of the node
-- @tparam[opt] string|int|func walkable the value for walkable locations in the collision map array (see @{Grid:new}).
-- Defaults to __false__ when omitted.
-- If this parameter is a function, it should be prototyped as __f(value)__ and return a `boolean`:
-- __true__ when value matches a __walkable__ `node`, __false__ otherwise. If this parameter is not given
-- while location [x,y] __is valid__, this actual function returns __true__.
-- @tparam[optchain] int clearance the amount of clearance needed. Defaults to 1 (normal clearance) when not given.
-- @treturn bool __true__ if `node` exists and is __walkable__, __false__ otherwise
-- @usage
-- -- Always true
-- print(myGrid:isWalkableAt(2,3))
--
-- -- True if node at [2,3] collision map value is 0
-- print(myGrid:isWalkableAt(2,3,0))
--
-- -- True if node at [2,3] collision map value is 0 and has a clearance higher or equal to 2
-- print(myGrid:isWalkableAt(2,3,0,2))
--
function Grid:isWalkableAt(x, y, walkable, clearance)
local nodeValue = self._map[y] and self._map[y][x]
if nodeValue then
if not walkable then return true end
else
return false
end
local hasEnoughClearance = not clearance and true or false
if not hasEnoughClearance then
if not self._isAnnotated[walkable] then return false end
local node = self:getNodeAt(x,y)
local nodeClearance = node:getClearance(walkable)
hasEnoughClearance = (nodeClearance >= clearance)
end
if self._eval then
return walkable(nodeValue) and hasEnoughClearance
end
return ((nodeValue == walkable) and hasEnoughClearance)
end
--- Returns the `grid` width.
-- @class function
-- @treturn int the `grid` width
-- @usage print(myGrid:getWidth())
function Grid:getWidth()
return self._width
end
--- Returns the `grid` height.
-- @class function
-- @treturn int the `grid` height
-- @usage print(myGrid:getHeight())
function Grid:getHeight()
return self._height
end
--- Returns the collision map.
-- @class function
-- @treturn map the collision map (see @{Grid:new})
-- @usage local map = myGrid:getMap()
function Grid:getMap()
return self._map
end
--- Returns the set of nodes.
-- @class function
-- @treturn {{node,...},...} an array of nodes
-- @usage local nodes = myGrid:getNodes()
function Grid:getNodes()
return self._nodes
end
--- Returns the `grid` bounds. Returned values corresponds to the upper-left
-- and lower-right coordinates (in tile units) of the actual `grid` instance.
-- @class function
-- @treturn int the upper-left corner x-coordinate
-- @treturn int the upper-left corner y-coordinate
-- @treturn int the lower-right corner x-coordinate
-- @treturn int the lower-right corner y-coordinate
-- @usage local left_x, left_y, right_x, right_y = myGrid:getBounds()
function Grid:getBounds()
return self._min_x, self._min_y,self._max_x, self._max_y
end
--- Returns neighbours. The returned value is an array of __walkable__ nodes neighbouring a given `node`.
-- @class function
-- @tparam node node a given `node`
-- @tparam[opt] string|int|func walkable the value for walkable locations in the collision map array (see @{Grid:new}).
-- Defaults to __false__ when omitted.
-- @tparam[optchain] bool allowDiagonal when __true__, allows adjacent nodes are included (8-neighbours).
-- Defaults to __false__ when omitted.
-- @tparam[optchain] bool tunnel When __true__, allows the `pathfinder` to tunnel through walls when heading diagonally.
-- @tparam[optchain] int clearance When given, will prune for the neighbours set all nodes having a clearance value lower than the passed-in value
-- Defaults to __false__ when omitted.
-- @treturn {node,...} an array of nodes neighbouring a given node
-- @usage
-- local aNode = myGrid:getNodeAt(5,6)
-- local neighbours = myGrid:getNeighbours(aNode, 0, true)
function Grid:getNeighbours(node, walkable, allowDiagonal, tunnel, clearance)
local neighbours = {}
for i = 1,#straightOffsets do
local n = self:getNodeAt(
node._x + straightOffsets[i].x,
node._y + straightOffsets[i].y
)
if n and self:isWalkableAt(n._x, n._y, walkable, clearance) then
neighbours[#neighbours+1] = n
end
end
if not allowDiagonal then return neighbours end
tunnel = not not tunnel
for i = 1,#diagonalOffsets do
local n = self:getNodeAt(
node._x + diagonalOffsets[i].x,
node._y + diagonalOffsets[i].y
)
if n and self:isWalkableAt(n._x, n._y, walkable, clearance) then
if tunnel then
neighbours[#neighbours+1] = n
else
local skipThisNode = false
local n1 = self:getNodeAt(node._x+diagonalOffsets[i].x, node._y)
local n2 = self:getNodeAt(node._x, node._y+diagonalOffsets[i].y)
if ((n1 and n2) and not self:isWalkableAt(n1._x, n1._y, walkable, clearance) and not self:isWalkableAt(n2._x, n2._y, walkable, clearance)) then
skipThisNode = true
end
if not skipThisNode then neighbours[#neighbours+1] = n end
end
end
end
return neighbours
end
--- Grid iterator. Iterates on every single node
-- in the `grid`. Passing __lx, ly, ex, ey__ arguments will iterate
-- only on nodes inside the bounding-rectangle delimited by those given coordinates.
-- @class function
-- @tparam[opt] int lx the leftmost x-coordinate of the rectangle. Default to the `grid` leftmost x-coordinate (see @{Grid:getBounds}).
-- @tparam[optchain] int ly the topmost y-coordinate of the rectangle. Default to the `grid` topmost y-coordinate (see @{Grid:getBounds}).
-- @tparam[optchain] int ex the rightmost x-coordinate of the rectangle. Default to the `grid` rightmost x-coordinate (see @{Grid:getBounds}).
-- @tparam[optchain] int ey the bottom-most y-coordinate of the rectangle. Default to the `grid` bottom-most y-coordinate (see @{Grid:getBounds}).
-- @treturn node a `node` on the collision map, upon each iteration step
-- @treturn int the iteration count
-- @usage
-- for node, count in myGrid:iter() do
-- print(node:getX(), node:getY(), count)
-- end
function Grid:iter(lx,ly,ex,ey)
local min_x = lx or self._min_x
local min_y = ly or self._min_y
local max_x = ex or self._max_x
local max_y = ey or self._max_y
local x, y
y = min_y
return function()
x = not x and min_x or x+1
if x > max_x then
x = min_x
y = y+1
end
if y > max_y then
y = nil
end
return self._nodes[y] and self._nodes[y][x] or self:getNodeAt(x,y)
end
end
--- Grid iterator. Iterates on each node along the outline (border) of a squared area
-- centered on the given node.
-- @tparam node node a given `node`
-- @tparam[opt] int radius the area radius (half-length). Defaults to __1__ when not given.
-- @treturn node a `node` at each iteration step
-- @usage
-- for node in myGrid:around(node, 2) do
-- ...
-- end
function Grid:around(node, radius)
local x, y = node._x, node._y
radius = radius or 1
local _around = Utils.around()
local _nodes = {}
repeat
local state, x, y = coroutine.resume(_around,x,y,radius)
local nodeAt = state and self:getNodeAt(x, y)
if nodeAt then _nodes[#_nodes+1] = nodeAt end
until (not state)
local _i = 0
return function()
_i = _i+1
return _nodes[_i]
end
end
--- Each transformation. Calls the given function on each `node` in the `grid`,
-- passing the `node` as the first argument to function __f__.
-- @class function
-- @tparam func f a function prototyped as __f(node,...)__
-- @tparam[opt] vararg ... args to be passed to function __f__
-- @treturn grid self (the calling `grid` itself, can be chained)
-- @usage
-- local function printNode(node)
-- print(node:getX(), node:getY())
-- end
-- myGrid:each(printNode)
function Grid:each(f,...)
for node in self:iter() do f(node,...) end
return self
end
--- Each (in range) transformation. Calls a function on each `node` in the range of a rectangle of cells,
-- passing the `node` as the first argument to function __f__.
-- @class function
-- @tparam int lx the leftmost x-coordinate coordinate of the rectangle
-- @tparam int ly the topmost y-coordinate of the rectangle
-- @tparam int ex the rightmost x-coordinate of the rectangle
-- @tparam int ey the bottom-most y-coordinate of the rectangle
-- @tparam func f a function prototyped as __f(node,...)__
-- @tparam[opt] vararg ... args to be passed to function __f__
-- @treturn grid self (the calling `grid` itself, can be chained)
-- @usage
-- local function printNode(node)
-- print(node:getX(), node:getY())
-- end
-- myGrid:eachRange(1,1,8,8,printNode)
function Grid:eachRange(lx,ly,ex,ey,f,...)
for node in self:iter(lx,ly,ex,ey) do f(node,...) end
return self
end
--- Map transformation.
-- Calls function __f(node,...)__ on each `node` in a given range, passing the `node` as the first arg to function __f__ and replaces
-- it with the returned value. Therefore, the function should return a `node`.
-- @class function
-- @tparam func f a function prototyped as __f(node,...)__
-- @tparam[opt] vararg ... args to be passed to function __f__
-- @treturn grid self (the calling `grid` itself, can be chained)
-- @usage
-- local function nothing(node)
-- return node
-- end
-- myGrid:imap(nothing)
function Grid:imap(f,...)
for node in self:iter() do
node = f(node,...)
end
return self
end
--- Map in range transformation.
-- Calls function __f(node,...)__ on each `node` in a rectangle range, passing the `node` as the first argument to the function and replaces
-- it with the returned value. Therefore, the function should return a `node`.
-- @class function
-- @tparam int lx the leftmost x-coordinate coordinate of the rectangle
-- @tparam int ly the topmost y-coordinate of the rectangle
-- @tparam int ex the rightmost x-coordinate of the rectangle
-- @tparam int ey the bottom-most y-coordinate of the rectangle
-- @tparam func f a function prototyped as __f(node,...)__
-- @tparam[opt] vararg ... args to be passed to function __f__
-- @treturn grid self (the calling `grid` itself, can be chained)
-- @usage
-- local function nothing(node)
-- return node
-- end
-- myGrid:imap(1,1,6,6,nothing)
function Grid:imapRange(lx,ly,ex,ey,f,...)
for node in self:iter(lx,ly,ex,ey) do
node = f(node,...)
end
return self
end
-- Specialized grids
-- Inits a preprocessed grid
function PreProcessGrid:new(map)
local newGrid = {}
newGrid._map = map
newGrid._nodes, newGrid._min_x, newGrid._max_x, newGrid._min_y, newGrid._max_y = Utils.arrayToNodes(newGrid._map)
newGrid._width = (newGrid._max_x-newGrid._min_x)+1
newGrid._height = (newGrid._max_y-newGrid._min_y)+1
newGrid._isAnnotated = {}
return setmetatable(newGrid,PreProcessGrid)
end
-- Inits a postprocessed grid
function PostProcessGrid:new(map)
local newGrid = {}
newGrid._map = map
newGrid._nodes = {}
newGrid._min_x, newGrid._max_x, newGrid._min_y, newGrid._max_y = Utils.getArrayBounds(newGrid._map)
newGrid._width = (newGrid._max_x-newGrid._min_x)+1
newGrid._height = (newGrid._max_y-newGrid._min_y)+1
newGrid._isAnnotated = {}
return setmetatable(newGrid,PostProcessGrid)
end
--- Returns the `node` at location [x,y].
-- @class function
-- @name Grid:getNodeAt
-- @tparam int x the x-coordinate coordinate
-- @tparam int y the y-coordinate coordinate
-- @treturn node a `node`
-- @usage local aNode = myGrid:getNodeAt(2,2)
-- Gets the node at location <x,y> on a preprocessed grid
function PreProcessGrid:getNodeAt(x,y)
return self._nodes[y] and self._nodes[y][x] or nil
end
-- Gets the node at location <x,y> on a postprocessed grid
function PostProcessGrid:getNodeAt(x,y)
if not x or not y 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 not self._nodes[y] then self._nodes[y] = {} end
if not self._nodes[y][x] then self._nodes[y][x] = Node:new(x,y) end
return self._nodes[y][x]
end
return setmetatable(Grid,{
__call = function(self,...)
return self:new(...)
end
})
end
================================================
FILE: jumper/pathfinder.lua
================================================
--- The Pathfinder class
--
-- Implementation of the `pathfinder` class.
local _VERSION = ""
local _RELEASEDATE = ""
if (...) then
-- Dependencies
local _PATH = (...):gsub('%.pathfinder$','')
local Utils = require (_PATH .. '.core.utils')
local Assert = require (_PATH .. '.core.assert')
local Heap = require (_PATH .. '.core.bheap')
local Heuristic = require (_PATH .. '.core.heuristics')
local Grid = require (_PATH .. '.grid')
local Path = require (_PATH .. '.core.path')
-- Internalization
local t_insert, t_remove = table.insert, table.remove
local floor = math.floor
local pairs = pairs
local assert = assert
local type = type
local setmetatable, getmetatable = setmetatable, getmetatable
--- Finders (search algorithms implemented). Refers to the search algorithms actually implemented in Jumper.
--
-- <li>[A*](http://en.wikipedia.org/wiki/A*_search_algorithm)</li>
-- <li>[Dijkstra](http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm)</li>
-- <li>[Theta Astar](http://aigamedev.com/open/tutorials/theta-star-any-angle-paths/)</li>
-- <li>[BFS](http://en.wikipedia.org/wiki/Breadth-first_search)</li>
-- <li>[DFS](http://en.wikipedia.org/wiki/Depth-first_search)</li>
-- <li>[JPS](http://harablog.wordpress.com/2011/09/07/jump-point-search/)</li>
-- @finder Finders
-- @see Pathfinder:getFinders
local Finders = {
['ASTAR'] = require (_PATH .. '.search.astar'),
['DIJKSTRA'] = require (_PATH .. '.search.dijkstra'),
['THETASTAR'] = require (_PATH .. '.search.thetastar'),
['BFS'] = require (_PATH .. '.search.bfs'),
['DFS'] = require (_PATH .. '.search.dfs'),
['JPS'] = require (_PATH .. '.search.jps')
}
-- Will keep track of all nodes expanded during the search
-- to easily reset their properties for the next pathfinding call
local toClear = {}
--- Search modes. Refers to the search modes. In ORTHOGONAL mode, 4-directions are only possible when moving,
-- including North, East, West, South. In DIAGONAL mode, 8-directions are possible when moving,
-- including North, East, West, South and adjacent directions.
--
-- <li>ORTHOGONAL</li>
-- <li>DIAGONAL</li>
-- @mode Modes
-- @see Pathfinder:getModes
local searchModes = {['DIAGONAL'] = true, ['ORTHOGONAL'] = true}
-- Performs a traceback from the goal node to the start node
-- Only happens when the path was found
--- The `Pathfinder` class.<br/>
-- This class is callable.
-- Therefore,_ <code>Pathfinder(...)</code> _acts as a shortcut to_ <code>Pathfinder:new(...)</code>.
-- @type Pathfinder
local Pathfinder = {}
Pathfinder.__index = Pathfinder
--- Inits a new `pathfinder`
-- @class function
-- @tparam grid grid a `grid`
-- @tparam[opt] string finderName the name of the `Finder` (search algorithm) to be used for search.
-- Defaults to `ASTAR` when not given (see @{Pathfinder:getFinders}).
-- @tparam[optchain] string|int|func walkable the value for __walkable__ nodes.
-- If this parameter is a function, it should be prototyped as __f(value)__, returning a boolean:
-- __true__ when value matches a __walkable__ `node`, __false__ otherwise.
-- @treturn pathfinder a new `pathfinder` instance
-- @usage
-- -- Example one
-- local finder = Pathfinder:new(myGrid, 'ASTAR', 0)
--
-- -- Example two
-- local function walkable(value)
-- return value > 0
-- end
-- local finder = Pathfinder(myGrid, 'JPS', walkable)
function Pathfinder:new(grid, finderName, walkable)
local newPathfinder = {}
setmetatable(newPathfinder, Pathfinder)
newPathfinder:setGrid(grid)
newPathfinder:setFinder(finderName)
newPathfinder:setWalkable(walkable)
newPathfinder:setMode('DIAGONAL')
newPathfinder:setHeuristic('MANHATTAN')
newPathfinder:setTunnelling(false)
return newPathfinder
end
--- Evaluates [clearance](http://aigamedev.com/open/tutorial/clearance-based-pathfinding/#TheTrueClearanceMetric)
-- for the whole `grid`. It should be called only once, unless the collision map or the
-- __walkable__ attribute changes. The clearance values are calculated and cached within the grid nodes.
-- @class function
-- @treturn pathfinder self (the calling `pathfinder` itself, can be chained)
-- @usage myFinder:annotateGrid()
function Pathfinder:annotateGrid()
assert(self._walkable, 'Finder must implement a walkable value')
for x=self._grid._max_x,self._grid._min_x,-1 do
for y=self._grid._max_y,self._grid._min_y,-1 do
local node = self._grid:getNodeAt(x,y)
if self._grid:isWalkableAt(x,y,self._walkable) then
local nr = self._grid:getNodeAt(node._x+1, node._y)
local nrd = self._grid:getNodeAt(node._x+1, node._y+1)
local nd = self._grid:getNodeAt(node._x, node._y+1)
if nr and nrd and nd then
local m = nrd._clearance[self._walkable] or 0
m = (nd._clearance[self._walkable] or 0)<m and (nd._clearance[self._walkable] or 0) or m
m = (nr._clearance[self._walkable] or 0)<m and (nr._clearance[self._walkable] or 0) or m
node._clearance[self._walkable] = m+1
else
node._clearance[self._walkable] = 1
end
else node._clearance[self._walkable] = 0
end
end
end
self._grid._isAnnotated[self._walkable] = true
return self
end
--- Removes [clearance](http://aigamedev.com/open/tutorial/clearance-based-pathfinding/#TheTrueClearanceMetric)values.
-- Clears cached clearance values for the current __walkable__.
-- @class function
-- @treturn pathfinder self (the calling `pathfinder` itself, can be chained)
-- @usage myFinder:clearAnnotations()
function Pathfinder:clearAnnotations()
assert(self._walkable, 'Finder must implement a walkable value')
for node in self._grid:iter() do
node:removeClearance(self._walkable)
end
self._grid._isAnnotated[self._walkable] = false
return self
end
--- Sets the `grid`. Defines the given `grid` as the one on which the `pathfinder` will perform the search.
-- @class function
-- @tparam grid grid a `grid`
-- @treturn pathfinder self (the calling `pathfinder` itself, can be chained)
-- @usage myFinder:setGrid(myGrid)
function Pathfinder:setGrid(grid)
assert(Assert.inherits(grid, Grid), 'Wrong argument #1. Expected a \'grid\' object')
self._grid = grid
self._grid._eval = self._walkable and type(self._walkable) == 'function'
return self
end
--- Returns the `grid`. This is a reference to the actual `grid` used by the `pathfinder`.
-- @class function
-- @treturn grid the `grid`
-- @usage local myGrid = myFinder:getGrid()
function Pathfinder:getGrid()
return self._grid
end
--- Sets the __walkable__ value or function.
-- @class function
-- @tparam string|int|func walkable the value for walkable nodes.
-- @treturn pathfinder self (the calling `pathfinder` itself, can be chained)
-- @usage
-- -- Value '0' is walkable
-- myFinder:setWalkable(0)
--
-- -- Any value greater than 0 is walkable
-- myFinder:setWalkable(function(n)
-- return n>0
-- end
function Pathfinder:setWalkable(walkable)
assert(Assert.matchType(walkable,'stringintfunctionnil'),
('Wrong argument #1. Expected \'string\', \'number\' or \'function\', got %s.'):format(type(walkable)))
self._walkable = walkable
self._grid._eval = type(self._walkable) == 'function'
return self
end
--- Gets the __walkable__ value or function.
-- @class function
-- @treturn string|int|func the `walkable` value or function
-- @usage local walkable = myFinder:getWalkable()
function Pathfinder:getWalkable()
return self._walkable
end
--- Defines the `finder`. It refers to the search algorithm used by the `pathfinder`.
-- Default finder is `ASTAR`. Use @{Pathfinder:getFinders} to get the list of available finders.
-- @class function
-- @tparam string finderName the name of the `finder` to be used for further searches.
-- @treturn pathfinder self (the calling `pathfinder` itself, can be chained)
-- @usage
-- --To use Breadth-First-Search
-- myFinder:setFinder('BFS')
-- @see Pathfinder:getFinders
function Pathfinder:setFinder(finderName)
if not finderName then
if not self._finder then
finderName = 'ASTAR'
else return
end
end
assert(Finders[finderName],'Not a valid finder name!')
self._finder = finderName
return self
end
--- Returns the name of the `finder` being used.
-- @class function
-- @treturn string the name of the `finder` to be used for further searches.
-- @usage local finderName = myFinder:getFinder()
function Pathfinder:getFinder()
return self._finder
end
--- Returns the list of all available finders names.
-- @class function
-- @treturn {string,...} array of built-in finders names.
-- @usage
-- local finders = myFinder:getFinders()
-- for i, finderName in ipairs(finders) do
-- print(i, finderName)
-- end
function Pathfinder:getFinders()
return Utils.getKeys(Finders)
end
--- Sets a heuristic. This is a function internally used by the `pathfinder` to find the optimal path during a search.
-- Use @{Pathfinder:getHeuristics} to get the list of all available `heuristics`. One can also define
-- his own `heuristic` function.
-- @class function
-- @tparam func|string heuristic `heuristic` function, prototyped as __f(dx,dy)__ or as a `string`.
-- @treturn pathfinder self (the calling `pathfinder` itself, can be chained)
-- @see Pathfinder:getHeuristics
-- @see core.heuristics
-- @usage myFinder:setHeuristic('MANHATTAN')
function Pathfinder:setHeuristic(heuristic)
assert(Heuristic[heuristic] or (type(heuristic) == 'function'),'Not a valid heuristic!')
self._heuristic = Heuristic[heuristic] or heuristic
return self
end
--- Returns the `heuristic` used. Returns the function itself.
-- @class function
-- @treturn func the `heuristic` function being used by the `pathfinder`
-- @see core.heuristics
-- @usage local h = myFinder:getHeuristic()
function Pathfinder:getHeuristic()
return self._heuristic
end
--- Gets the list of all available `heuristics`.
-- @class function
-- @treturn {string,...} array of heuristic names.
-- @see core.heuristics
-- @usage
-- local heur = myFinder:getHeuristic()
-- for i, heuristicName in ipairs(heur) do
-- ...
-- end
function Pathfinder:getHeuristics()
return Utils.getKeys(Heuristic)
end
--- Defines the search `mode`.
-- The default search mode is the `DIAGONAL` mode, which implies 8-possible directions when moving (north, south, east, west and diagonals).
-- In `ORTHOGONAL` mode, only 4-directions are allowed (north, south, east and west).
-- Use @{Pathfinder:getModes} to get the list of all available search modes.
-- @class function
-- @tparam string mode the new search `mode`.
-- @treturn pathfinder self (the calling `pathfinder` itself, can be chained)
-- @see Pathfinder:getModes
-- @see Modes
-- @usage myFinder:setMode('ORTHOGONAL')
function Pathfinder:setMode(mode)
assert(searchModes[mode],'Invalid mode')
self._allowDiagonal = (mode == 'DIAGONAL')
return self
end
--- Returns the search mode.
-- @class function
-- @treturn string the current search mode
-- @see Modes
-- @usage local mode = myFinder:getMode()
function Pathfinder:getMode()
return (self._allowDiagonal and 'DIAGONAL' or 'ORTHOGONAL')
end
--- Gets the list of all available search modes.
-- @class function
-- @treturn {string,...} array of search modes.
-- @see Modes
-- @usage local modes = myFinder:getModes()
-- for modeName in ipairs(modes) do
-- ...
-- end
function Pathfinder:getModes()
return Utils.getKeys(searchModes)
end
--- Enables tunnelling. Defines the ability for the `pathfinder` to tunnel through walls when heading diagonally.
-- This feature __is not compatible__ with Jump Point Search algorithm (i.e. enabling it will not affect Jump Point Search)
-- @class function
-- @tparam bool bool a boolean
-- @treturn pathfinder self (the calling `pathfinder` itself, can be chained)
-- @usage myFinder:setTunnelling(true)
function Pathfinder:setTunnelling(bool)
assert(Assert.isBool(bool), ('Wrong argument #1. Expected boolean, got %s'):format(type(bool)))
self._tunnel = bool
return self
end
--- Returns tunnelling feature state.
-- @class function
-- @treturn bool tunnelling feature actual state
-- @usage local isTunnellingEnabled = myFinder:getTunnelling()
function Pathfinder:getTunnelling()
return self._tunnel
end
--- Calculates a `path`. Returns the `path` from location __[startX, startY]__ to location __[endX, endY]__.
-- Both locations must exist on the collision map. The starting location can be unwalkable.
-- @class function
-- @tparam int startX the x-coordinate for the starting location
-- @tparam int startY the y-coordinate for the starting location
-- @tparam int endX the x-coordinate for the goal location
-- @tparam int endY the y-coordinate for the goal location
-- @tparam int clearance the amount of clearance (i.e the pathing agent size) to consider
-- @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, endX, endY, clearance)
self:reset()
local startNode = self._grid:getNodeAt(startX, startY)
local endNode = self._grid:getNodeAt(endX, endY)
assert(startNode, ('Invalid location [%d, %d]'):format(startX, startY))
assert(endNode and self._grid:isWalkableAt(endX, endY),
('Invalid or unreachable location [%d, %d]'):format(endX, endY))
local _endNode = Finders[self._finder](self, startNode, endNode, clearance, 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
})
end
================================================
FILE: jumper/search/astar.lua
================================================
-- 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 ipairs = ipairs
local huge = math.huge
-- Dependancies
local _PATH = (...):match('(.+)%.search.astar$')
local Heuristics = require (_PATH .. '.core.heuristics')
local Heap = require (_PATH.. '.core.bheap')
-- Updates G-cost
local function computeCost(node, neighbour, finder, clearance)
local mCost = Heuristics.EUCLIDIAN(neighbour, node)
if node._g + mCost < neighbour._g then
neighbour._parent = node
neighbour._g = node._g + mCost
end
end
-- Updates vertex node-neighbour
local function updateVertex(finder, openList, node, neighbour, endNode, clearance, heuristic, overrideCostEval)
local oldG = neighbour._g
local cmpCost = overrideCostEval or computeCost
cmpCost(node, neighbour, finder, clearance)
if neighbour._g < oldG then
local nClearance = neighbour._clearance[finder._walkable]
local pushThisNode = clearance and nClearance and (nClearance >= clearance)
if (clearance and pushThisNode) or (not clearance) then
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
end
end
end
-- Calculates a path.
-- Returns the path from location `<startX, startY>` to location `<endX, endY>`.
return function (finder, startNode, endNode, clearance, toClear, overrideHeuristic, overrideCostEval)
local heuristic = overrideHeuristic or finder._heuristic
local openList = Heap()
startNode._g = 0
startNode._h = heuristic(endNode, startNode)
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
local neighbours = finder._grid:getNeighbours(node, finder._walkable, finder._allowDiagonal, finder._tunnel)
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
neighbour._parent = nil
end
updateVertex(finder, openList, node, neighbour, endNode, clearance, heuristic, overrideCostEval)
end
end
end
return nil
end
end
================================================
FILE: jumper/search/bfs.lua
================================================
-- Breadth-First search algorithm
if (...) then
-- Internalization
local t_remove = table.remove
local function breadth_first_search(finder, openList, node, endNode, clearance, toClear)
local neighbours = finder._grid:getNeighbours(node, finder._walkable, finder._allowDiagonal, finder._tunnel)
for i = 1,#neighbours do
local neighbour = neighbours[i]
if not neighbour._closed and not neighbour._opened then
local nClearance = neighbour._clearance[finder._walkable]
local pushThisNode = clearance and nClearance and (nClearance >= clearance)
if (clearance and pushThisNode) or (not clearance) then
openList[#openList+1] = neighbour
neighbour._opened = true
neighbour._parent = node
toClear[neighbour] = true
end
end
end
end
-- Calculates a path.
-- Returns the path from location `<startX, startY>` to location `<endX, endY>`.
return function (finder, startNode, endNode, clearance, toClear)
local openList = {} -- We'll use a FIFO queue (simple array)
openList[1] = startNode
startNode._opened = true
toClear[startNode] = true
local node
while (#openList > 0) do
node = openList[1]
t_remove(openList,1)
node._closed = true
if node == endNode then return node end
breadth_first_search(finder, openList, node, endNode, clearance, toClear)
end
return nil
end
end
================================================
FILE: jumper/search/dfs.lua
================================================
-- Depth-First search algorithm.
if (...) then
-- Internalization
local t_remove = table.remove
local function depth_first_search(finder, openList, node, endNode, clearance, toClear)
local neighbours = finder._grid:getNeighbours(node, finder._walkable, finder._allowDiagonal, finder._tunnel)
for i = 1,#neighbours do
local neighbour = neighbours[i]
if (not neighbour._closed and not neighbour._opened) then
local nClearance = neighbour._clearance[finder._walkable]
local pushThisNode = clearance and nClearance and (nClearance >= clearance)
if (clearance and pushThisNode) or (not clearance) then
openList[#openList+1] = neighbour
neighbour._opened = true
neighbour._parent = node
toClear[neighbour] = true
end
end
end
end
-- Calculates a path.
-- Returns the path from location `<startX, startY>` to location `<endX, endY>`.
return function (finder, startNode, endNode, clearance, toClear)
local openList = {} -- We'll use a LIFO queue (simple array)
openList[1] = startNode
startNode._opened = true
toClear[startNode] = true
local node
while (#openList > 0) do
node = openList[#openList]
t_remove(openList)
node._closed = true
if node == endNode then return node end
depth_first_search(finder, openList, node, endNode, clearance, toClear)
end
return nil
end
end
================================================
FILE: jumper/search/dijkstra.lua
================================================
-- Dijkstra algorithm (Uses Astar implementation)
if (...) then
local astar_search = require ((...):gsub('%.dijkstra$','.astar'))
-- Dijkstra is similar to aStar, with no heuristic
local dijkstraHeuristic = function() return 0 end
-- Calculates a path.
-- Returns the path from location `<startX, startY>` to location `<endX, endY>`.
return function (finder, startNode, endNode, clearance, toClear)
return astar_search(finder, startNode, endNode, clearance, toClear, dijkstraHeuristic)
end
end
================================================
FILE: jumper/search/jps.lua
================================================
-- Jump Point search algorithm
if (...) then
-- Dependancies
local _PATH = (...):match('(.+)%.search.jps$')
local Heuristics = require (_PATH .. '.core.heuristics')
local Heap = require (_PATH.. '.core.bheap')
-- Internalization
local max, abs = math.max, math.abs
-- Local helpers, these routines will stay private
-- As they are internally used by the public interface
-- Resets properties of nodes expanded during a search
-- This is a lot faster than resetting all nodes
-- between consecutive pathfinding requests
--[[
Looks for the neighbours of a given node.
Returns its natural neighbours plus forced neighbours when the given
node has no parent (generally occurs with the starting node).
Otherwise, based on the direction of move from the parent, returns
neighbours while pruning directions which will lead to symmetric paths.
In case diagonal moves are forbidden, when the given node has no
parent, we return straight neighbours (up, down, left and right).
Otherwise, we add left and right node (perpendicular to the direction
of move) in the neighbours list.
--]]
local function findNeighbours(finder, node, clearance)
if node._parent then
local neighbours = {}
local x,y = node._x, node._y
-- Node have a parent, we will prune some neighbours
-- Gets the direction of move
local dx = (x-node._parent._x)/max(abs(x-node._parent._x),1)
local dy = (y-node._parent._y)/max(abs(y-node._parent._y),1)
-- Diagonal move case
if dx~=0 and dy~=0 then
local walkY, walkX
-- Natural neighbours
if finder._grid:isWalkableAt(x,y+dy,finder._walkable, clearance) then
neighbours[#neighbours+1] = finder._grid:getNodeAt(x,y+dy)
walkY = true
end
if finder._grid:isWalkableAt(x+dx,y,finder._walkable, clearance) then
neighbours[#neighbours+1] = finder._grid:getNodeAt(x+dx,y)
walkX = true
end
if walkX or walkY then
neighbours[#neighbours+1] = finder._grid:getNodeAt(x+dx,y+dy)
end
-- Forced neighbours
if (not finder._grid:isWalkableAt(x-dx,y,finder._walkable, clearance)) and walkY then
neighbours[#neighbours+1] = finder._grid:getNodeAt(x-dx,y+dy)
end
if (not finder._grid:isWalkableAt(x,y-dy,finder._walkable, clearance)) and walkX then
neighbours[#neighbours+1] = finder._grid:getNodeAt(x+dx,y-dy)
end
else
-- Move along Y-axis case
if dx==0 then
local walkY
if finder._grid:isWalkableAt(x,y+dy,finder._walkable, clearance) then
neighbours[#neighbours+1] = finder._grid:getNodeAt(x,y+dy)
-- Forced neighbours are left and right ahead along Y
if (not finder._grid:isWalkableAt(x+1,y,finder._walkable, clearance)) then
neighbours[#neighbours+1] = finder._grid:getNodeAt(x+1,y+dy)
end
if (not finder._grid:isWalkableAt(x-1,y,finder._walkable, clearance)) then
neighbours[#neighbours+1] = finder._grid:getNodeAt(x-1,y+dy)
end
end
-- In case diagonal moves are forbidden : Needs to be optimized
if not finder._allowDiagonal then
if finder._grid:isWalkableAt(x+1,y,finder._walkable, clearance) then
neighbours[#neighbours+1] = finder._grid:getNodeAt(x+1,y)
end
if finder._grid:isWalkableAt(x-1,y,finder._walkable, clearance)
then neighbours[#neighbours+1] = finder._grid:getNodeAt(x-1,y)
end
end
else
-- Move along X-axis case
if finder._grid:isWalkableAt(x+dx,y,finder._walkable, clearance) then
neighbours[#neighbours+1] = finder._grid:getNodeAt(x+dx,y)
-- Forced neighbours are up and down ahead along X
if (not finder._grid:isWalkableAt(x,y+1,finder._walkable, clearance)) then
neighbours[#neighbours+1] = finder._grid:getNodeAt(x+dx,y+1)
end
if (not finder._grid:isWalkableAt(x,y-1,finder._walkable, clearance)) then
neighbours[#neighbours+1] = finder._grid:getNodeAt(x+dx,y-1)
end
end
-- : In case diagonal moves are forbidden
if not finder._allowDiagonal then
if finder._grid:isWalkableAt(x,y+1,finder._walkable, clearance) then
neighbours[#neighbours+1] = finder._grid:getNodeAt(x,y+1)
end
if finder._grid:isWalkableAt(x,y-1,finder._walkable, clearance) then
neighbours[#neighbours+1] = finder._grid:getNodeAt(x,y-1)
end
end
end
end
return neighbours
end
-- Node do not have parent, we return all neighbouring nodes
return finder._grid:getNeighbours(node, finder._walkable, finder._allowDiagonal, finder._tunnel, clearance)
end
--[[
Searches for a jump point (or a turning point) in a specific direction.
This is a generic translation of the algorithm 2 in the paper:
http://users.cecs.anu.edu.au/~dharabor/data/papers/harabor-grastien-aaai11.pdf
The current expanded node is a jump point if near a forced node
In case diagonal moves are forbidden, when lateral nodes (perpendicular to
the direction of moves are walkable, we force them to be turning points in other
to perform a straight move.
--]]
local function jump(finder, node, parent, endNode, clearance)
if not node then return end
local x,y = node._x, node._y
local dx, dy = x - parent._x,y - parent._y
-- If the node to be examined is unwalkable, return nil
if not finder._grid:isWalkableAt(x,y,finder._walkable, clearance) then return end
-- If the node to be examined is the endNode, return this node
if node == endNode then return node end
-- Diagonal search case
if dx~=0 and dy~=0 then
-- Current node is a jump point if one of his leftside/rightside neighbours ahead is forced
if (finder
gitextract_lrl520tn/ ├── .gitignore ├── LICENSE.txt ├── README.md ├── docs/ │ ├── examples/ │ │ ├── annotatedpathing.lua.html │ │ ├── customheuristics.lua.html │ │ ├── makeclearance.lua.html │ │ └── simpleexample.lua.html │ ├── index.html │ └── modules/ │ ├── core.bheap.html │ ├── core.heuristics.html │ ├── core.node.html │ ├── core.path.html │ ├── grid.html │ └── pathfinder.html ├── examples/ │ ├── annotatedPathing.lua │ ├── customHeuristics.lua │ ├── makeClearance.lua │ └── simpleExample.lua ├── jumper/ │ ├── core/ │ │ ├── assert.lua │ │ ├── bheap.lua │ │ ├── heuristics.lua │ │ ├── lookuptable.lua │ │ ├── node.lua │ │ ├── path.lua │ │ └── utils.lua │ ├── grid.lua │ ├── pathfinder.lua │ └── search/ │ ├── astar.lua │ ├── bfs.lua │ ├── dfs.lua │ ├── dijkstra.lua │ ├── jps.lua │ └── thetastar.lua ├── rockspecs/ │ ├── jumper-1.6-2.rockspec │ ├── jumper-1.6.3-1.rockspec │ ├── jumper-1.7.0-1.rockspec │ ├── jumper-1.8.0.rockspec │ └── jumper-1.8.1-1.rockspec ├── specs/ │ ├── bheap_specs.lua │ ├── grid_specs.lua │ ├── heuristics_specs.lua │ ├── node_specs.lua │ ├── path_specs.lua │ └── pathfinder_specs.lua └── version_history.md
Condensed preview — 45 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (267K chars).
[
{
"path": ".gitignore",
"chars": 64,
"preview": "*.yml\n*.ld\n*.bat\ntsc\ntest*\nldoc*\ntelescope*\nhkl\ndebug*\nprofiler*"
},
{
"path": "LICENSE.txt",
"chars": 1062,
"preview": "Copyright (c) 2012-2013 Roland Yonaba\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of t"
},
{
"path": "README.md",
"chars": 5935,
"preview": "Jumper\n======\n\n[](https://g"
},
{
"path": "docs/examples/annotatedpathing.lua.html",
"chars": 6953,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html>\n"
},
{
"path": "docs/examples/customheuristics.lua.html",
"chars": 4528,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html>\n"
},
{
"path": "docs/examples/makeclearance.lua.html",
"chars": 6680,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html>\n"
},
{
"path": "docs/examples/simpleexample.lua.html",
"chars": 4361,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html>\n"
},
{
"path": "docs/index.html",
"chars": 3198,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html>\n"
},
{
"path": "docs/modules/core.bheap.html",
"chars": 7888,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html>\n"
},
{
"path": "docs/modules/core.heuristics.html",
"chars": 7900,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html>\n"
},
{
"path": "docs/modules/core.node.html",
"chars": 9830,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html>\n"
},
{
"path": "docs/modules/core.path.html",
"chars": 13072,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html>\n"
},
{
"path": "docs/modules/grid.html",
"chars": 25978,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html>\n"
},
{
"path": "docs/modules/pathfinder.html",
"chars": 26767,
"preview": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html>\n"
},
{
"path": "examples/annotatedPathing.lua",
"chars": 1123,
"preview": "-- Tests sample for clearance metrics calculation\n-- See Figure 10 at http://aigamedev.com/open/tutorial/clearance-based"
},
{
"path": "examples/customHeuristics.lua",
"chars": 862,
"preview": "--- Example of use for Heuristics\n\nlocal Grid = require (\"jumper.grid\")\nlocal Pathfinder = require (\"jumper.pathfinder\")"
},
{
"path": "examples/makeClearance.lua",
"chars": 1016,
"preview": "-- Tests sample for clearance metrics calculation\n-- See Figure 10 at http://aigamedev.com/open/tutorial/clearance-based"
},
{
"path": "examples/simpleExample.lua",
"chars": 940,
"preview": "--- Very minimal usage example for Jumper\n\n-- Set up a collision map\nlocal map = {\n\t{0,1,0,1,0},\n\t{0,1,0,1,0},\n\t{0,1,1,1"
},
{
"path": "jumper/core/assert.lua",
"chars": 2565,
"preview": "-- Various assertion function for API methods argument-checking\n\nif (...) then\n\t\n\t-- Dependancies\n\tlocal _PATH = (...):g"
},
{
"path": "jumper/core/bheap.lua",
"chars": 5040,
"preview": "--- A light implementation of Binary heaps data structure.\n-- While running a search, some search algorithms (Astar, Dij"
},
{
"path": "jumper/core/heuristics.lua",
"chars": 3588,
"preview": "--- Heuristic functions for search algorithms.\n-- A <a href=\"http://theory.stanford.edu/~amitp/GameProgramming/Heuristic"
},
{
"path": "jumper/core/lookuptable.lua",
"chars": 866,
"preview": "local addNode(self, node, nextNode, ed)\n\tif not self._pathDB[node] then self._pathDB[node] = {} end\n\tself._pathDB[node]["
},
{
"path": "jumper/core/node.lua",
"chars": 3550,
"preview": "--- The Node class.\n-- The `node` represents a cell (or a tile) on a collision map. Basically, for each single cell (til"
},
{
"path": "jumper/core/path.lua",
"chars": 6046,
"preview": "--- The Path class.\n-- The `path` class is a structure which represents a path (ordered set of nodes) from a start locat"
},
{
"path": "jumper/core/utils.lua",
"chars": 3675,
"preview": "-- Various utilities for Jumper top-level modules\n\nif (...) then\n\n\t-- Dependencies\n\tlocal _PATH = (...):gsub('%.utils$',"
},
{
"path": "jumper/grid.lua",
"chars": 15843,
"preview": "--- The Grid class.\n-- Implementation of the `grid` class.\n-- The `grid` is a implicit graph which represents the 2D\n-- "
},
{
"path": "jumper/pathfinder.lua",
"chars": 14513,
"preview": "--- The Pathfinder class\n\n--\n-- Implementation of the `pathfinder` class.\n\nlocal _VERSION = \"\"\nlocal _RELEASEDATE = \"\"\n\n"
},
{
"path": "jumper/search/astar.lua",
"chars": 2527,
"preview": "-- Astar algorithm\n-- This actual implementation of A-star is based on\n-- [Nash A. & al. pseudocode](http://aigamedev.co"
},
{
"path": "jumper/search/bfs.lua",
"chars": 1419,
"preview": "-- Breadth-First search algorithm\n\nif (...) then\n -- Internalization\n local t_remove = table.remove\n\n local function "
},
{
"path": "jumper/search/dfs.lua",
"chars": 1418,
"preview": "-- Depth-First search algorithm.\n\nif (...) then\n -- Internalization\n local t_remove = table.remove\n\n local function d"
},
{
"path": "jumper/search/dijkstra.lua",
"chars": 515,
"preview": "-- Dijkstra algorithm (Uses Astar implementation)\n\nif (...) then\n\n local astar_search = require ((...):gsub('%.dijkstra"
},
{
"path": "jumper/search/jps.lua",
"chars": 11461,
"preview": "-- Jump Point search algorithm\n\nif (...) then\n\n -- Dependancies\n local _PATH = (...):match('(.+)%.search.jps$')\n loca"
},
{
"path": "jumper/search/thetastar.lua",
"chars": 2031,
"preview": "-- ThetaStar implementation\n-- See: http://aigamedev.com/open/tutorials/theta-star-any-angle-paths for reference\n\nif (.."
},
{
"path": "rockspecs/jumper-1.6-2.rockspec",
"chars": 1005,
"preview": "package = \"jumper\"\nversion = \"1.6-2\"\nsource = {\n url = \"https://github.com/Yonaba/Jumper/archive/jumper-1.6-2.tar.gz\","
},
{
"path": "rockspecs/jumper-1.6.3-1.rockspec",
"chars": 1011,
"preview": "package = \"jumper\"\nversion = \"1.6.3-1\"\nsource = {\n url = \"https://github.com/Yonaba/Jumper/archive/jumper-1.6.3-1.tar."
},
{
"path": "rockspecs/jumper-1.7.0-1.rockspec",
"chars": 1254,
"preview": "package = \"jumper\"\nversion = \"1.7.0-1\"\nsource = {\n url = \"https://github.com/Yonaba/Jumper/archive/jumper-1.7.0-1.tar."
},
{
"path": "rockspecs/jumper-1.8.0.rockspec",
"chars": 1448,
"preview": "package = \"jumper\"\nversion = \"1.8.0\"\nsource = {\n url = \"https://github.com/Yonaba/Jumper/archive/jumper-1.8.0.tar.gz\","
},
{
"path": "rockspecs/jumper-1.8.1-1.rockspec",
"chars": 1462,
"preview": "package = \"jumper\"\nversion = \"1.8.1-1\"\nsource = {\n url = \"https://github.com/Yonaba/Jumper/archive/jumper-1.8.1-1.tar."
},
{
"path": "specs/bheap_specs.lua",
"chars": 3212,
"preview": "context('Module BHeap', function()\t\n\tlocal BHeap \n\t\n\tbefore(function()\n\t\tBHeap = require ('jumper.core.bheap')\n\tend)\n\t\n\t"
},
{
"path": "specs/grid_specs.lua",
"chars": 12544,
"preview": "context('Module Grid', function()\n\tlocal Grid, Node\n\t\n\tbefore(function()\n\t\tGrid = require ('jumper.grid')\n\t\tNode = requi"
},
{
"path": "specs/heuristics_specs.lua",
"chars": 2928,
"preview": "context('Module Heuristics', function()\n\tlocal H, Node\n\t\n\tbefore(function()\n\t\tH = require ('jumper.core.heuristics')\n\t\tN"
},
{
"path": "specs/node_specs.lua",
"chars": 989,
"preview": "context('Module Node', function()\n\tlocal Node\n\t\n\tbefore(function()\n\t\tNode = require ('jumper.core.node')\n end)\n\t\n cont"
},
{
"path": "specs/path_specs.lua",
"chars": 2599,
"preview": "context('Module Path', function()\n\tlocal Path, Node\n\t\n\tbefore(function()\n\t\tPath = require ('jumper.core.path')\n\t\tNode = "
},
{
"path": "specs/pathfinder_specs.lua",
"chars": 9938,
"preview": "context('Module Pathfinder', function()\n\tlocal PF, H, Grid, Path, map, grid\n\t\n\tbefore(function()\n\t\tPF = require ('jumper"
},
{
"path": "version_history.md",
"chars": 6167,
"preview": "#Version history#\n\n##1.8.1 (03/01/2013)\n* Added optionnal `tunneling` feature (not fully compatible with `Jump Point Sea"
}
]
About this extraction
This page contains the full source code of the Yonaba/Jumper GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 45 files (242.0 KB), approximately 76.3k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.