#ifndef JUMP_POINT_SEARCH_H
#define JUMP_POINT_SEARCH_H

// Public domain Jump Point Search implementation by False.Genesis
// Very fast pathfinding for uniform cost grids.
// Supports incremental pathfinding.

// Please keep the following source information intact when you use this file in your own projects:
// This file originates from: https://github.com/fgenesis/jps
// Based on the paper http://users.cecs.anu.edu.au/~dharabor/data/papers/harabor-grastien-aaai11.pdf
// by Daniel Harabor & Alban Grastien.
// Jumper (https://github.com/Yonaba/Jumper) and PathFinding.js (https://github.com/qiao/PathFinding.js)
// served as reference for this implementation.
// If you use this, attribution would be nice, but is not necessary.

// ====== COMPILE CONFIG ======

// If this is defined, compare all jumps against recursive reference implementation (only if _DEBUG is defined)
//#define JPS_VERIFY

// If this is defined, use standard A* instead of JPS (e.g. if you want to compare performance in your scenario)
//#define JPS_ASTAR_ONLY

// If this is defined, disable the greedy direct-short-path check that avoids the large area scanning that JPS does.
// Does not change optimality of results when left enabled
//#define JPS_DISABLE_GREEDY

// ============================

// Usage:
/*
// Define a class that overloads `operator()(x, y) const`, returning a value that can be treated as boolean.
// You are responsible for bounds checking!
// You want your operator() to be as fast as possible, as it will be called a LOT.

struct MyGrid
{
	inline bool operator()(unsigned x, unsigned y) const
	{
		if(x < width && y < height) // Unsigned will wrap if < 0
			... return true if terrain at (x, y) is walkable.
	}
	unsigned width, height;
};

// Then you can retrieve a path:

MyGrid grid;
// ... set grid width, height, and whatever
unsigned step = 0; // set this to 1 if you want a detailed single-step path
                   // (e.g. if you plan to further mangle the path yourself),
                   // or any other higher value to output every Nth position.
JPS::PathVector path; // The resulting path will go here.


// Single-call interface:
bool found = JPS::findPath(path, grid, startx, starty, endx, endy, step);


// Alternatively, if you want more control:

JPS::Searcher<MyGrid> search(grid);
while(true)
{
	// ..stuff happening ...

	// build path incrementally from waypoints
	JPS::Position a, b, c, d = <...>; // set some waypoints
	search.findPath(path, a, b);
	search.findPath(path, b, c);
	search.findPath(path, c, d);

	// re-use existing pathfinder instance
	if(!search.findPath(path2, JPS::Pos(startx, starty), JPS::Pos(endx, endy), step))
	{
		// ...handle failure...
	}
	// ... more stuff happening ...

	// At convenient times, you can clean up accumulated nodes to reclaim memory.
	// This is never necessary for correct function, but performance will drop if too many cached nodes exist.
	if(mapWasReloaded)
		search.freeMemory();
}

// Further remarks about the super lazy single-call function can be found at the bottom of this file.

// -------------------------------
// --- Incremental pathfinding ---
// -------------------------------

First, call findPathInit(Position start, Position end).
Don't forget to check the return value, as it may return:
- NO_PATH if one or both of the points are obstructed
- EMPTY_PATH if the points are equal and not obstructed
- FOUND_PATH if the initial greedy heuristic could find a path quickly.
If it returns NEED_MORE_STEPS then the next part can start.

Repeatedly call findPathStep(int limit) until it returns NO_PATH or FOUND_PATH.
For consistency, you will want to ensure that the grid does not change between subsequent calls;
if the grid changes, parts of the path may go through a now obstructed area.
If limit is 0, it will perform the pathfinding in one go. Values > 0 abort the search
as soon as possible after the number of steps was exceeded, returning NEED_MORE_STEPS.
Use getStepsDone() after some test runs to find a good value for the limit.

Lastly, generate the actual path points from a successful run via findPathFinish(PathVector& path, unsigned step = 0).
Like described above, path points are appended, and granularity can be adjusted with the step parameter.
Returns false if the pathfinding did not finish or generating the path failed.

*/


#include <stdlib.h>
#include <algorithm>
#include <vector>
#include <cmath>

#include <map>

#ifdef _DEBUG
#include <cassert>
#define JPS_ASSERT(cond) assert(cond)
#else
#define JPS_ASSERT(cond)
#endif


namespace JPS {

enum Result
{
	NO_PATH,
	FOUND_PATH,
	NEED_MORE_STEPS,
	EMPTY_PATH
};

struct Position
{
	unsigned x, y;

	inline bool operator==(const Position& p) const
	{
		return x == p.x && y == p.y;
	}
	inline bool operator!=(const Position& p) const
	{
		return x != p.x || y != p.y;
	}

	// for sorting
	inline bool operator<(const Position& p) const
	{
		return y < p.y || (y == p.y && x < p.x);
	}

	inline bool isValid() const { return x != unsigned(-1); }
};

typedef std::vector<Position> PathVector;

// ctor function to keep Position a real POD struct.
inline static Position Pos(unsigned x, unsigned y)
{
	Position p;
	p.x = x;
	p.y = y;
	return p;
}

namespace Internal {

static const Position npos = Pos(-1, -1);

class Node
{
public:
	Node(const Position& p) : f(0), g(0), pos(p), parent(0), flags(0) {}
	unsigned f, g;
	const Position pos;
	const Node *parent;

	inline void setOpen() { flags |= 1; }
	inline void setClosed() { flags |= 2; }
	inline unsigned isOpen() const { return flags & 1; }
	inline unsigned isClosed() const { return flags & 2; }
	inline void clearState() { f = 0; g = 0, parent = 0; flags = 0; }

private:
	unsigned flags;

	bool operator==(const Node& o); // not implemented, nodes should not be compared
};
} // end namespace Internal

namespace Heuristic
{
	inline unsigned Manhattan(const Internal::Node *a, const Internal::Node *b)
	{
		return abs(int(a->pos.x - b->pos.x)) + abs(int(a->pos.y - b->pos.y));
	}

	inline unsigned Euclidean(const Internal::Node *a, const Internal::Node *b)
	{
		float fx = float(int(a->pos.x - b->pos.x));
		float fy = float(int(a->pos.y - b->pos.y));
		return unsigned(int(sqrtf(fx*fx + fy*fy)));
	}
} // end namespace heuristic

namespace Internal {

typedef std::vector<Node*> NodeVector;

class OpenList
{
public:
	inline void push(Node *node)
	{
		JPS_ASSERT(node);
		nodes.push_back(node);
		std::push_heap(nodes.begin(), nodes.end(), _compare);
	}
	inline Node *pop()
	{
		std::pop_heap(nodes.begin(), nodes.end(), _compare);
		Node *node = nodes.back();
		nodes.pop_back();
		return node;
	}
	inline bool empty() const
	{
		return nodes.empty();
	}
	inline void clear()
	{
		nodes.clear();
	}
	inline void fixup()
	{
		std::make_heap(nodes.begin(), nodes.end(), _compare);
	}

protected:
	static inline bool _compare(const Node *a, const Node *b)
	{
		return a->f > b->f;
	}
	NodeVector nodes;
};

template <typename GRID> class Searcher
{
public:
	Searcher(const GRID& g)
		: grid(g), endNode(NULL), skip(1), stepsRemain(0), stepsDone(0)
	{}

	// single-call
	bool findPath(PathVector& path, Position start, Position end, unsigned step);

	// incremental pathfinding
	Result findPathInit(Position start, Position end);
	Result findPathStep(int limit);
	bool findPathFinish(PathVector& path, unsigned step);

	// misc
	void freeMemory();
	inline void setSkip(int s) { skip = std::max(1, s); }
	inline size_t getStepsDone() const { return stepsDone; }
	inline size_t getNodesExpanded() const { return nodegrid.size(); }

private:

	typedef std::map<Position, Node> NodeGrid;

	const GRID& grid;
	Node *endNode;
	int skip;
	int stepsRemain;
	size_t stepsDone;
	OpenList open;

	NodeGrid nodegrid;

	Node *getNode(const Position& pos);
	void identifySuccessors(const Node *n);
	bool generatePath(PathVector& path, unsigned step) const;
#ifndef JPS_DISABLE_GREEDY
	bool findPathGreedy(Node *start);
#endif
	
#ifdef JPS_ASTAR_ONLY
	unsigned findNeighborsAStar(const Node *n, Position *wptr);
#else
	unsigned findNeighbors(const Node *n, Position *wptr) const;
	Position jumpP(const Position& p, const Position& src);
	Position jumpD(Position p, int dx, int dy);
	Position jumpX(Position p, int dx);
	Position jumpY(Position p, int dy);
#endif
#ifdef JPS_VERIFY
	Position jumpPRec(const Position& p, const Position& src) const;
#endif
};

template <typename GRID> inline Node *Searcher<GRID>::getNode(const Position& pos)
{
	JPS_ASSERT(grid(pos.x, pos.y));
	return &nodegrid.insert(std::make_pair(pos, Node(pos))).first->second;
}

#ifndef JPS_ASTAR_ONLY
template <typename GRID> Position Searcher<GRID>::jumpP(const Position &p, const Position& src)
{
	JPS_ASSERT(grid(p.x, p.y));

	int dx = int(p.x - src.x);
	int dy = int(p.y - src.y);
	JPS_ASSERT(dx || dy);

	if(dx && dy)
		return jumpD(p, dx, dy);
	else if(dx)
		return jumpX(p, dx);
	else if(dy)
		return jumpY(p, dy);

	// not reached
	JPS_ASSERT(false);
	return npos;
}

template <typename GRID> Position Searcher<GRID>::jumpD(Position p, int dx, int dy)
{
	JPS_ASSERT(grid(p.x, p.y));
	JPS_ASSERT(dx && dy);

	const Position& endpos = endNode->pos;
	int steps = 0;

	while(true)
	{
		if(p == endpos)
			break;

		++steps;
		const unsigned x = p.x;
		const unsigned y = p.y;

		if( (grid(x-dx, y+dy) && !grid(x-dx, y)) || (grid(x+dx, y-dy) && !grid(x, y-dy)) )
			break;

		const bool gdx = grid(x+dx, y);
		const bool gdy = grid(x, y+dy);

		if(gdx && jumpX(Pos(x+dx, y), dx).isValid())
			break;

		if(gdy && jumpY(Pos(x, y+dy), dy).isValid())
			break;

		if((gdx || gdy) && grid(x+dx, y+dy))
		{
			p.x += dx;
			p.y += dy;
		}
		else
		{
			p = npos;
			break;
		}
	}
	stepsDone += (unsigned)steps;
	stepsRemain -= steps;
	return p;
}

template <typename GRID> inline Position Searcher<GRID>::jumpX(Position p, int dx)
{
	JPS_ASSERT(dx);
	JPS_ASSERT(grid(p.x, p.y));

	const unsigned y = p.y;
	const Position& endpos = endNode->pos;
	const int skip = this->skip;
	int steps = 0;

	unsigned a = ~((!!grid(p.x, y+skip)) | ((!!grid(p.x, y-skip)) << 1));

	while(true)
	{
		const unsigned xx = p.x + dx;
		const unsigned b = (!!grid(xx, y+skip)) | ((!!grid(xx, y-skip)) << 1);

		if((b & a) || p == endpos)
			break;
		if(!grid(xx, y))
		{
			p = npos;
			break;
		}

		p.x += dx;
		a = ~b;
		++steps;
	}

	stepsDone += (unsigned)steps;
	stepsRemain -= steps;
	return p;
}

template <typename GRID> inline Position Searcher<GRID>::jumpY(Position p, int dy)
{
	JPS_ASSERT(dy);
	JPS_ASSERT(grid(p.x, p.y));

	const unsigned x = p.x;
	const Position& endpos = endNode->pos;
	const int skip = this->skip;
	int steps = 0;

	unsigned a = ~((!!grid(x+skip, p.y)) | ((!!grid(x-skip, p.y)) << 1));

	while(true)
	{
		const unsigned yy = p.y + dy;
		const unsigned b = (!!grid(x+skip, yy)) | ((!!grid(x-skip, yy)) << 1);

		if((a & b) || p == endpos)
			break;
		if(!grid(x, yy))
		{
			p = npos;
			break;
		}

		p.y += dy;
		a = ~b;
	}

	stepsDone += (unsigned)steps;
	stepsRemain -= steps;
	return p;
}
#endif // JPS_ASTAR_ONLY

#ifdef JPS_VERIFY
// Recursive reference implementation -- for comparison only
template <typename GRID> Position Searcher<GRID>::jumpPRec(const Position& p, const Position& src) const
{
	unsigned x = p.x;
	unsigned y = p.y;
	if(!grid(x, y))
		return npos;
	if(p == endNode->pos)
		return p;

	int dx = int(x - src.x);
	int dy = int(y - src.y);
	JPS_ASSERT(dx || dy);

	if(dx && dy)
	{
		if( (grid(x-dx, y+dy) && !grid(x-dx, y)) || (grid(x+dx, y-dy) && !grid(x, y-dy)) )
			return p;
	}
	else if(dx)
	{
		if( (grid(x+dx, y+skip) && !grid(x, y+skip)) || (grid(x+dx, y-skip) && !grid(x, y-skip)) )
			return p;
	}
	else if(dy)
	{
		if( (grid(x+skip, y+dy) && !grid(x+skip, y)) || (grid(x-skip, y+dy) && !grid(x-skip, y)) )
			return p;
	}

	if(dx && dy)
	{
		if(jumpPRec(Pos(x+dx, y), p).isValid())
			return p;
		if(jumpPRec(Pos(x, y+dy), p).isValid())
			return p;
	}

	if(grid(x+dx, y) || grid(x, y+dy))
		return jumpPRec(Pos(x+dx, y+dy), p);

	return npos;
}
#endif // JPS_VERIFY

#define JPS_CHECKGRID(dx, dy) (grid(x+(dx), y+(dy)))
#define JPS_ADDPOS(dx, dy) 	do { *w++ = Pos(x+(dx), y+(dy)); } while(0)
#define JPS_ADDPOS_CHECK(dx, dy) do { if(JPS_CHECKGRID(dx, dy)) JPS_ADDPOS(dx, dy); } while(0)
#define JPS_ADDPOS_NO_TUNNEL(dx, dy) do { if(grid(x+(dx),y) || grid(x,y+(dy))) JPS_ADDPOS_CHECK(dx, dy); } while(0)

#ifndef JPS_ASTAR_ONLY
template <typename GRID> unsigned Searcher<GRID>::findNeighbors(const Node *n, Position *wptr) const
{
	Position *w = wptr;
	const unsigned x = n->pos.x;
	const unsigned y = n->pos.y;
	const int skip = this->skip;

	if(!n->parent)
	{
		// straight moves
		JPS_ADDPOS_CHECK(-skip, 0);
		JPS_ADDPOS_CHECK(0, -skip);
		JPS_ADDPOS_CHECK(0, skip);
		JPS_ADDPOS_CHECK(skip, 0);

		// diagonal moves + prevent tunneling
		JPS_ADDPOS_NO_TUNNEL(-skip, -skip);
		JPS_ADDPOS_NO_TUNNEL(-skip, skip);
		JPS_ADDPOS_NO_TUNNEL(skip, -skip);
		JPS_ADDPOS_NO_TUNNEL(skip, skip);

		return unsigned(w - wptr);
	}

	// jump directions (both -1, 0, or 1)
	int dx = int(x - n->parent->pos.x);
	dx /= std::max(abs(dx), 1);
	dx *= skip;
	int dy = int(y - n->parent->pos.y);
	dy /= std::max(abs(dy), 1);
	dy *= skip;

	if(dx && dy)
	{
		// diagonal
		// natural neighbors
		bool walkX = false;
		bool walkY = false;
		if((walkX = grid(x+dx, y)))
			*w++ = Pos(x+dx, y);
		if((walkY = grid(x, y+dy)))
			*w++ = Pos(x, y+dy);

		if(walkX || walkY)
			JPS_ADDPOS_CHECK(dx, dy);

		// forced neighbors
		if(walkY && !JPS_CHECKGRID(-dx,0))
			JPS_ADDPOS_CHECK(-dx, dy);

		if(walkX && !JPS_CHECKGRID(0,-dy))
			JPS_ADDPOS_CHECK(dx, -dy);
	}
	else if(dx)
	{
		// along X axis
		if(JPS_CHECKGRID(dx, 0))
		{
			JPS_ADDPOS(dx, 0);

			 // Forced neighbors (+ prevent tunneling)
			if(!JPS_CHECKGRID(0, skip))
				JPS_ADDPOS_CHECK(dx, skip);
			if(!JPS_CHECKGRID(0,-skip))
				JPS_ADDPOS_CHECK(dx,-skip);
		}


	}
	else if(dy)
	{
		// along Y axis
		if(JPS_CHECKGRID(0, dy))
		{
			JPS_ADDPOS(0, dy);

			// Forced neighbors (+ prevent tunneling)
			if(!JPS_CHECKGRID(skip, 0))
				JPS_ADDPOS_CHECK(skip, dy);
			if(!JPS_CHECKGRID(-skip, 0))
				JPS_ADDPOS_CHECK(-skip,dy);
		}
	}

	return unsigned(w - wptr);
}

#else
//-------------- Plain old A* search ----------------
template <typename GRID> unsigned Searcher<GRID>::findNeighborsAStar(const Node *n, Position *wptr)
{
	Position *w = wptr;
	const int x = n->pos.x;
	const int y = n->pos.y;
	const int d = skip;
	JPS_ADDPOS_NO_TUNNEL(-d, -d);
	JPS_ADDPOS_CHECK    ( 0, -d);
	JPS_ADDPOS_NO_TUNNEL(+d, -d);
	JPS_ADDPOS_CHECK    (-d,  0);
	JPS_ADDPOS_CHECK    (+d,  0);
	JPS_ADDPOS_NO_TUNNEL(-d, +d);
	JPS_ADDPOS_CHECK    ( 0, +d);
	JPS_ADDPOS_NO_TUNNEL(+d, +d);
	stepsDone += 8;
	return unsigned(w - wptr);
}
#endif // JPS_ASTAR_ONLY
//-------------------------------------------------
#undef JPS_ADDPOS
#undef JPS_ADDPOS_CHECK
#undef JPS_ADDPOS_NO_TUNNEL
#undef JPS_CHECKGRID


template <typename GRID> void Searcher<GRID>::identifySuccessors(const Node *n)
{
	Position buf[8];
#ifdef JPS_ASTAR_ONLY
	const int num = findNeighborsAStar(n, &buf[0]);
#else
	const int num = findNeighbors(n, &buf[0]);
#endif
	for(int i = num-1; i >= 0; --i)
	{
		// Invariant: A node is only a valid neighbor if the corresponding grid position is walkable (asserted in jumpP)
#ifdef JPS_ASTAR_ONLY
		Position jp = buf[i];
#else
		Position jp = jumpP(buf[i], n->pos);
	#ifdef JPS_VERIFY
		JPS_ASSERT(jp == jumpPRec(buf[i], n->pos));
	#endif
		if(!jp.isValid())
			continue;
#endif
		// Now that the grid position is definitely a valid jump point, we have to create the actual node.
		Node *jn = getNode(jp);
		JPS_ASSERT(jn && jn != n);
		if(!jn->isClosed())
		{
			unsigned extraG = Heuristic::Euclidean(jn, n);
			unsigned newG = n->g + extraG;
			if(!jn->isOpen() || newG < jn->g)
			{
				jn->g = newG;
				jn->f = jn->g + Heuristic::Manhattan(jn, endNode);
				jn->parent = n;
				if(!jn->isOpen())
				{
					open.push(jn);
					jn->setOpen();
				}
				else
					open.fixup();
			}
		}
	}
}

template <typename GRID> bool Searcher<GRID>::generatePath(PathVector& path, unsigned step) const
{
	if(!endNode)
		return false;
	size_t offset = path.size();
	if(step)
	{
		const Node *next = endNode;
		const Node *prev = endNode->parent;
		if(!prev)
			return false;
		do
		{
			const unsigned x = next->pos.x, y = next->pos.y;
			int dx = int(prev->pos.x - x);
			int dy = int(prev->pos.y - y);
			JPS_ASSERT(!dx || !dy || abs(dx) == abs(dy)); // known to be straight, if diagonal
			const int steps = std::max(abs(dx), abs(dy));
			dx /= std::max(abs(dx), 1);
			dy /= std::max(abs(dy), 1);
			dx *= int(step);
			dy *= int(step);
			int dxa = 0, dya = 0;
			for(int i = 0; i < steps; i += step)
			{
				path.push_back(Pos(x+dxa, y+dya));
				dxa += dx;
				dya += dy;
			}
			next = prev;
			prev = prev->parent;
		}
		while (prev);
	}
	else
	{
		const Node *next = endNode;
		if(!next->parent)
			return false;
		do
		{
			JPS_ASSERT(next != next->parent);
			path.push_back(next->pos);
			next = next->parent;
		}
		while (next->parent);
	}
	std::reverse(path.begin() + offset, path.end());
	return true;
}

template <typename GRID> bool Searcher<GRID>::findPath(PathVector& path, Position start, Position end, unsigned step)
{
	Result res = findPathInit(start, end);

	// If this is true, the resulting path is empty (findPathFinish() would fail, so this needs to be checked before)
	if(res == EMPTY_PATH)
		return true;

	while(true)
	{
		switch(res)
		{
			case NEED_MORE_STEPS:
				res = findPathStep(0);
				break; // the switch

			case FOUND_PATH:
				return findPathFinish(path, step);

			case NO_PATH:
			default:
				return false;
		}
	}
}

template <typename GRID> Result Searcher<GRID>::findPathInit(Position start, Position end)
{
	for(NodeGrid::iterator it = nodegrid.begin(); it != nodegrid.end(); ++it)
		it->second.clearState();
	open.clear();
	endNode = NULL;
	stepsDone = 0;

	// If skip is > 1, make sure the points are aligned so that the search will always hit them
	start.x = (start.x / skip) * skip;
	start.y = (start.y / skip) * skip;
	end.x = (end.x / skip) * skip;
	end.y = (end.y / skip) * skip;

	if(start == end)
	{
		// There is only a path if this single position is walkable.
		// But since the starting position is omitted, there is nothing to do here.
		return grid(end.x, end.y) ? EMPTY_PATH : NO_PATH;
	}

	// If start or end point are obstructed, don't even start
	if(!grid(start.x, start.y) || !grid(end.x, end.y))
		return NO_PATH;

	endNode = getNode(end);
	Node *startNode = getNode(start);
	JPS_ASSERT(startNode && endNode);

#ifndef JPS_DISABLE_GREEDY
	// Try the quick way out first
	if(findPathGreedy(startNode))
		return FOUND_PATH;
#endif

	open.push(startNode);

	return NEED_MORE_STEPS;
}

template <typename GRID> Result Searcher<GRID>::findPathStep(int limit)
{
	stepsRemain = limit;
	do
	{
		if(open.empty())
			return NO_PATH;
		Node *n = open.pop();
		n->setClosed();
		if(n == endNode)
			return FOUND_PATH;
		identifySuccessors(n);
	}
	while(stepsRemain >= 0);
	return NEED_MORE_STEPS;
}

template<typename GRID> bool Searcher<GRID>::findPathFinish(PathVector& path, unsigned step)
{
	return generatePath(path, step);
}

#ifndef JPS_DISABLE_GREEDY
template<typename GRID> bool Searcher<GRID>::findPathGreedy(Node *n)
{
	Position midpos = npos;
	int x = n->pos.x;
	int y = n->pos.y;
	int ex = endNode->pos.x;
	int ey = endNode->pos.y;

	JPS_ASSERT(x != ex || y != ey); // must not be called when start==end
	JPS_ASSERT(n != endNode);

	const int skip = this->skip;

	int dx = int(ex - x);
	int dy = int(ey - y);
	const int adx = abs(dx);
	const int ady = abs(dy);
	dx /= std::max(adx, 1);
	dy /= std::max(ady, 1);
	dx *= skip;
	dy *= skip;

	// go diagonally first
	if(x != ex && y != ey)
	{
		JPS_ASSERT(dx && dy);
		const int minlen = (int)std::min(adx, ady);
		const int tx = x + dx * minlen;
		for( ; x != tx; )
		{
			if(grid(x, y) && (grid(x+dx, y) || grid(x, y+dy))) // prevent tunneling as well
			{
				x += dx;
				y += dy;
			}
			else
				return false;
		}

		if(!grid(x, y))
			return false;

		midpos = Pos(x, y);
	}

	// at this point, we're aligned to at least one axis
	JPS_ASSERT(x == ex || y == ey);

	if(!(x == ex && y == ey))
	{
		while(x != ex)
			if(!grid(x += dx, y))
				return false;

		while(y != ey)
			if(!grid(x, y += dy))
				return false;

		JPS_ASSERT(x == ex && y == ey);
	}

	if(midpos.isValid())
	{
		Node *mid = getNode(midpos);
		JPS_ASSERT(mid && mid != n);
		mid->parent = n;
		if(mid != endNode)
			endNode->parent = mid;
	}
	else
		endNode->parent = n;

	return true;
}
#endif

template<typename GRID> void Searcher<GRID>::freeMemory()
{
	NodeGrid v;
	nodegrid.swap(v);
	endNode = NULL;
	open.clear();
	// other containers known to be empty.
}

} // end namespace Internal

using Internal::Searcher;

// Single-call convenience function
//
// path: If the function returns true, the path is stored in this vector.
//       The path does NOT contain the starting position, i.e. if start and end are the same,
//       the resulting path has no elements.
//       The vector does not have to be empty. The function does not clear it;
//       instead, the new path positions are appended at the end.
//       This allows building a path incrementally.
//
// grid: expected to overload operator()(x, y), return true if position is walkable, false if not.
//
// step: If 0, only return waypoints.
//       If 1, create exhaustive step-by-step path.
//       If N, put in one position for N blocks travelled, or when a waypoint is hit.
//       All returned points are guaranteed to be on a straight line (vertically, horizontally, or diagonally),
//       and there is no obstruction between any two consecutive points.
//       Note that this parameter does NOT influence the pathfinding in any way;
//       it only controls the coarseness of the output path.
//
// skip: If you know your map data well enough, this can be set to > 1 to speed up pathfinding even more.
//       Warning: Start and end positions will be rounded down to the nearest <skip>-aligned position,
//       so make sure to give appropriate positions so they do not end up in a wall.
//       This will also skip through walls if they are less than <skip> blocks thick at any reachable position.
template <typename GRID> bool findPath(PathVector& path, const GRID& grid, unsigned startx, unsigned starty, unsigned endx, unsigned endy,
                                       unsigned step = 0, int skip = 0, // optional params
                                       size_t *stepsDone = NULL, size_t *nodesExpanded = NULL // for information
                                       )
{
	Searcher<GRID> search(grid);
	search.setSkip(skip);
	bool found = search.findPath(path, Pos(startx, starty), Pos(endx, endy), step);
	if(stepsDone)
		*stepsDone = search.getStepsDone();
	if(nodesExpanded)
		*nodesExpanded = search.getNodesExpanded();
	return found;
}



} // end namespace JPS


#endif
