diff --git a/.gitmodules b/.gitmodules
index d42c10d6..18405cfe 100755
--- a/.gitmodules
+++ b/.gitmodules
@@ -20,5 +20,5 @@
path = include/TF2_NavFile_Reader
url = https://github.com/nullworks/TF2_NavFile_Reader.git
[submodule "external/MicroPather"]
- path = src/MicroPather
- url = https://github.com/leethomason/MicroPather.git
+ path = external/MicroPather
+ url = https://github.com/leethomason/MicroPather
diff --git a/external/MicroPather b/external/MicroPather
new file mode 160000
index 00000000..33a3b840
--- /dev/null
+++ b/external/MicroPather
@@ -0,0 +1 @@
+Subproject commit 33a3b8403f1bc3937c9d364fe6c3977169bee3b5
diff --git a/external/MicroPather/MakefileSpeed b/external/MicroPather/MakefileSpeed
deleted file mode 100755
index a0ffd4a4..00000000
--- a/external/MicroPather/MakefileSpeed
+++ /dev/null
@@ -1,113 +0,0 @@
-#****************************************************************************
-#
-# Makefile for Micropather test.
-# Lee Thomason
-# www.grinninglizard.com
-#
-# This is a GNU make (gmake) makefile
-#****************************************************************************
-
-# DEBUG can be set to YES to include debugging info, or NO otherwise
-DEBUG := NO
-
-# PROFILE can be set to YES to include profiling info, or NO otherwise
-PROFILE := NO
-
-#****************************************************************************
-
-CC := gcc
-CXX := g++
-LD := g++
-AR := ar rc
-RANLIB := ranlib
-
-DEBUG_CFLAGS := -Wall -Wno-format -g -DDEBUG -std=c++11
-RELEASE_CFLAGS := -Wall -Wno-unknown-pragmas -Wno-format -O3 -std=c++11
-
-LIBS :=
-
-DEBUG_CXXFLAGS := ${DEBUG_CFLAGS}
-RELEASE_CXXFLAGS := ${RELEASE_CFLAGS}
-
-DEBUG_LDFLAGS := -g
-RELEASE_LDFLAGS :=
-
-ifeq (YES, ${DEBUG})
- CFLAGS := ${DEBUG_CFLAGS}
- CXXFLAGS := ${DEBUG_CXXFLAGS}
- LDFLAGS := ${DEBUG_LDFLAGS}
-else
- CFLAGS := ${RELEASE_CFLAGS}
- CXXFLAGS := ${RELEASE_CXXFLAGS}
- LDFLAGS := ${RELEASE_LDFLAGS}
-endif
-
-ifeq (YES, ${PROFILE})
- CFLAGS := ${CFLAGS} -pg -O3
- CXXFLAGS := ${CXXFLAGS} -pg -O3
- LDFLAGS := ${LDFLAGS} -pg
-endif
-
-#****************************************************************************
-# Preprocessor directives
-#****************************************************************************
-
-
-#****************************************************************************
-# Include paths
-#****************************************************************************
-
-#INCS := -I/usr/include/g++-2 -I/usr/local/include
-INCS :=
-
-
-#****************************************************************************
-# Makefile code common to all platforms
-#****************************************************************************
-
-CFLAGS := ${CFLAGS} ${DEFS}
-CXXFLAGS := ${CXXFLAGS} ${DEFS}
-
-#****************************************************************************
-# Targets of the build
-#****************************************************************************
-
-OUTPUT := speed
-
-all: ${OUTPUT}
-
-
-#****************************************************************************
-# Source files
-#****************************************************************************
-
-SRCS := micropather.cpp speed.cpp
-
-# Add on the sources for libraries
-SRCS := ${SRCS}
-
-OBJS := $(addsuffix .o,$(basename ${SRCS}))
-
-#****************************************************************************
-# Output
-#****************************************************************************
-
-${OUTPUT}: ${OBJS}
- ${LD} -o $@ ${LDFLAGS} ${OBJS} ${LIBS} ${EXTRA_LIBS}
-
-#****************************************************************************
-# common rules
-#****************************************************************************
-
-# Rules for compiling source files to object files
-%.o : %.cpp
- ${CXX} -c ${CXXFLAGS} ${INCS} $< -o $@
-
-%.o : %.c
- ${CC} -c ${CFLAGS} ${INCS} $< -o $@
-
-clean:
- -rm -f core ${OBJS} ${OUTPUT}
-
-micropather.o: micropather.h
-speed.o: micropather.h
diff --git a/external/MicroPather/demo0.gif b/external/MicroPather/demo0.gif
deleted file mode 100755
index 74bd087e..00000000
Binary files a/external/MicroPather/demo0.gif and /dev/null differ
diff --git a/external/MicroPather/demo0.png b/external/MicroPather/demo0.png
deleted file mode 100755
index 79e6e48e..00000000
Binary files a/external/MicroPather/demo0.png and /dev/null differ
diff --git a/external/MicroPather/dungeon.cpp b/external/MicroPather/dungeon.cpp
deleted file mode 100755
index 53f59d3a..00000000
--- a/external/MicroPather/dungeon.cpp
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
-Copyright (c) 2000-2012 Lee Thomason (www.grinninglizard.com)
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any
-damages arising from the use of this software.
-
-Permission is granted to anyone to use this software for any
-purpose, including commercial applications, and to alter it and
-redistribute it freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must
-not claim that you wrote the original software. If you use this
-software in a product, an acknowledgment in the product documentation
-would be appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and
-must not be misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
-distribution.
-*/
-
-
-#define USE_PATHER
-
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#ifdef USE_PATHER
-
-#include "micropather.h"
-using namespace micropather;
-#endif
-
-
-const int MAPX = 30;
-const int MAPY = 10;
-const char gMap[MAPX*MAPY+1] =
- //"012345678901234567890123456789"
- " | | |"
- " | |----+ | +"
- "---+ +---DD-+ +--+--+ "
- " | +-- +"
- " +----+ +---+ "
- "---+ + D D | "
- " | | +----+ +----+ +--+"
- " D | | | "
- " | +-------+ +-+ |--+ "
- "---+ | +";
-
-class Dungeon
-#ifdef USE_PATHER
- : public Graph
-#endif
-{
- private:
- Dungeon( const Dungeon& );
- void operator=( const Dungeon& );
-
- int playerX, playerY;
- MPVector path;
- bool doorsOpen;
- bool showConsidered;
-
- MicroPather* pather;
-
- public:
- Dungeon() : playerX( 0 ), playerY( 0 ), doorsOpen( false ), showConsidered( false ), pather( 0 )
- {
- pather = new MicroPather( this, 20 ); // Use a very small memory block to stress the pather
- }
-
- virtual ~Dungeon() {
- delete pather;
- }
-
- int X() { return playerX; }
- int Y() { return playerY; }
-
- void ClearPath()
- {
- #ifdef USE_PATHER
- path.resize( 0 );
- #endif
- }
-
- void ToggleTouched() { showConsidered = !showConsidered;
- pather->Reset();
- }
-
- void ToggleDoor()
- {
- doorsOpen = !doorsOpen;
-
- #ifdef USE_PATHER
- pather->Reset();
-
- #endif
- }
-
- int Passable( int nx, int ny )
- {
- if ( nx >= 0 && nx < MAPX
- && ny >= 0 && ny < MAPY )
- {
- int index = ny*MAPX+nx;
- char c = gMap[ index ];
- if ( c == ' ' )
- return 1;
- else if ( c == 'D' )
- return 2;
- }
- return 0;
- }
-
- int SetPos( int nx, int ny )
- {
- int result = 0;
- if ( Passable( nx, ny ) == 1 )
- {
- #ifdef USE_PATHER
- float totalCost;
- if ( showConsidered )
- pather->Reset();
-
- result = pather->Solve( XYToNode( playerX, playerY ), XYToNode( nx, ny ), &path, &totalCost );
-
- if ( result == MicroPather::SOLVED ) {
- playerX = nx;
- playerY = ny;
- }
- printf( "Pather returned %d\n", result );
-
- #else
- playerX = nx;
- playerY = ny;
- #endif
- }
- return result;
- }
-
- void Print()
- {
- char buf[ MAPX+1 ];
-
- MPVector< void* > stateVec;
-
- if ( showConsidered )
- pather->StatesInPool( &stateVec );
- printf( " doors %s\n", doorsOpen ? "open" : "closed" );
- printf( " 0 10 20\n" );
- printf( " 012345678901234567890123456789\n" );
- for( int j=0; j *neighbors )
- {
- int x, y;
- const int dx[8] = { 1, 1, 0, -1, -1, -1, 0, 1 };
- const int dy[8] = { 0, 1, 1, 1, 0, -1, -1, -1 };
- const float cost[8] = { 1.0f, 1.41f, 1.0f, 1.41f, 1.0f, 1.41f, 1.0f, 1.41f };
-
- NodeToXY( node, &x, &y );
-
- for( int i=0; i<8; ++i ) {
- int nx = x + dx[i];
- int ny = y + dy[i];
-
- int pass = Passable( nx, ny );
- if ( pass > 0 ) {
- if ( pass == 1 || doorsOpen )
- {
- // Normal floor
- StateCost nodeCost = { XYToNode( nx, ny ), cost[i] };
- neighbors->push_back( nodeCost );
- }
- else
- {
- // Normal floor
- StateCost nodeCost = { XYToNode( nx, ny ), FLT_MAX };
- neighbors->push_back( nodeCost );
- }
- }
- }
- }
-
- virtual void PrintStateInfo( void* node )
- {
- int x, y;
- NodeToXY( node, &x, &y );
- printf( "(%d,%d)", x, y );
- }
-
-#endif
-};
-
-int main( int /*argc*/, const char** /*argv*/ )
-{
- Dungeon dungeon;
- bool done = false;
- char buf[ 256 ];
-
- while ( !done ) {
- dungeon.Print();
- printf( "\n# # to move, q to quit, r to redraw, d to toggle doors, t for touched\n" );
- //gets( buf );
- //printf( "\n" );
-
- std::cin.getline( buf, 256 );
-
- if ( *buf )
- {
- if ( buf[0] == 'q' ) {
- done = true;
- }
- else if ( buf[0] == 'd' ) {
- dungeon.ToggleDoor();
- dungeon.ClearPath();
- }
- else if ( buf[0] == 't' ) {
- dungeon.ToggleTouched();
- }
- else if ( buf[0] == 'r' ) {
- dungeon.ClearPath();
- }
- else if ( isdigit( buf[0] ) ) {
- int x, y;
- sscanf( buf, "%d %d", &x, &y ); // sleazy, I know
- dungeon.SetPos( x, y );
- }
- }
- else
- {
- dungeon.ClearPath();
- }
- }
- return 0;
-}
diff --git a/external/MicroPather/micropather.cpp b/external/MicroPather/micropather.cpp
deleted file mode 100755
index dbc1db8b..00000000
--- a/external/MicroPather/micropather.cpp
+++ /dev/null
@@ -1,1078 +0,0 @@
-/*
-Copyright (c) 2000-2009 Lee Thomason (www.grinninglizard.com)
-
-Grinning Lizard Utilities.
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any
-damages arising from the use of this software.
-
-Permission is granted to anyone to use this software for any
-purpose, including commercial applications, and to alter it and
-redistribute it freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must
-not claim that you wrote the original software. If you use this
-software in a product, an acknowledgment in the product documentation
-would be appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and
-must not be misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
-distribution.
-*/
-
-#ifdef _MSC_VER
-#pragma warning( disable : 4786 ) // Debugger truncating names.
-#pragma warning( disable : 4530 ) // Exception handler isn't used
-#endif
-
-#include
-#include
-
-//#define DEBUG_PATH
-//#define DEBUG_PATH_DEEP
-//#define TRACK_COLLISION
-//#define DEBUG_CACHING
-
-#ifdef DEBUG_CACHING
-#include "../grinliz/gldebug.h"
-#endif
-
-#include "micropather.h"
-
-using namespace micropather;
-
-class OpenQueue
-{
- public:
- OpenQueue( Graph* _graph )
- {
- graph = _graph;
- sentinel = (PathNode*) sentinelMem;
- sentinel->InitSentinel();
- #ifdef DEBUG
- sentinel->CheckList();
- #endif
- }
- ~OpenQueue() {}
-
- void Push( PathNode* pNode );
- PathNode* Pop();
- void Update( PathNode* pNode );
-
- bool Empty() { return sentinel->next == sentinel; }
-
- private:
- OpenQueue( const OpenQueue& ); // undefined and unsupported
- void operator=( const OpenQueue& );
-
- PathNode* sentinel;
- int sentinelMem[ ( sizeof( PathNode ) + sizeof( int ) ) / sizeof( int ) ];
- Graph* graph; // for debugging
-};
-
-
-void OpenQueue::Push( PathNode* pNode )
-{
-
- MPASSERT( pNode->inOpen == 0 );
- MPASSERT( pNode->inClosed == 0 );
-
-#ifdef DEBUG_PATH_DEEP
- printf( "Open Push: " );
- graph->PrintStateInfo( pNode->state );
- printf( " total=%.1f\n", pNode->totalCost );
-#endif
-
- // Add sorted. Lowest to highest cost path. Note that the sentinel has
- // a value of FLT_MAX, so it should always be sorted in.
- MPASSERT( pNode->totalCost < FLT_MAX );
- PathNode* iter = sentinel->next;
- while ( true )
- {
- if ( pNode->totalCost < iter->totalCost ) {
- iter->AddBefore( pNode );
- pNode->inOpen = 1;
- break;
- }
- iter = iter->next;
- }
- MPASSERT( pNode->inOpen ); // make sure this was actually added.
-#ifdef DEBUG
- sentinel->CheckList();
-#endif
-}
-
-PathNode* OpenQueue::Pop()
-{
- MPASSERT( sentinel->next != sentinel );
- PathNode* pNode = sentinel->next;
- pNode->Unlink();
-#ifdef DEBUG
- sentinel->CheckList();
-#endif
-
- MPASSERT( pNode->inClosed == 0 );
- MPASSERT( pNode->inOpen == 1 );
- pNode->inOpen = 0;
-
-#ifdef DEBUG_PATH_DEEP
- printf( "Open Pop: " );
- graph->PrintStateInfo( pNode->state );
- printf( " total=%.1f\n", pNode->totalCost );
-#endif
-
- return pNode;
-}
-
-void OpenQueue::Update( PathNode* pNode )
-{
-#ifdef DEBUG_PATH_DEEP
- printf( "Open Update: " );
- graph->PrintStateInfo( pNode->state );
- printf( " total=%.1f\n", pNode->totalCost );
-#endif
-
- MPASSERT( pNode->inOpen );
-
- // If the node now cost less than the one before it,
- // move it to the front of the list.
- if ( pNode->prev != sentinel && pNode->totalCost < pNode->prev->totalCost ) {
- pNode->Unlink();
- sentinel->next->AddBefore( pNode );
- }
-
- // If the node is too high, move to the right.
- if ( pNode->totalCost > pNode->next->totalCost ) {
- PathNode* it = pNode->next;
- pNode->Unlink();
-
- while ( pNode->totalCost > it->totalCost )
- it = it->next;
-
- it->AddBefore( pNode );
-#ifdef DEBUG
- sentinel->CheckList();
-#endif
- }
-}
-
-
-class ClosedSet
-{
- public:
- ClosedSet( Graph* _graph ) { this->graph = _graph; }
- ~ClosedSet() {}
-
- void Add( PathNode* pNode )
- {
- #ifdef DEBUG_PATH_DEEP
- printf( "Closed add: " );
- graph->PrintStateInfo( pNode->state );
- printf( " total=%.1f\n", pNode->totalCost );
- #endif
- #ifdef DEBUG
- MPASSERT( pNode->inClosed == 0 );
- MPASSERT( pNode->inOpen == 0 );
- #endif
- pNode->inClosed = 1;
- }
-
- void Remove( PathNode* pNode )
- {
- #ifdef DEBUG_PATH_DEEP
- printf( "Closed remove: " );
- graph->PrintStateInfo( pNode->state );
- printf( " total=%.1f\n", pNode->totalCost );
- #endif
- MPASSERT( pNode->inClosed == 1 );
- MPASSERT( pNode->inOpen == 0 );
-
- pNode->inClosed = 0;
- }
-
- private:
- ClosedSet( const ClosedSet& );
- void operator=( const ClosedSet& );
- Graph* graph;
-};
-
-
-PathNodePool::PathNodePool( unsigned _allocate, unsigned _typicalAdjacent )
- : firstBlock( 0 ),
- blocks( 0 ),
-#if defined( MICROPATHER_STRESS )
- allocate( 32 ),
-#else
- allocate( _allocate ),
-#endif
- nAllocated( 0 ),
- nAvailable( 0 )
-{
- freeMemSentinel.InitSentinel();
-
- cacheCap = allocate * _typicalAdjacent;
- cacheSize = 0;
- cache = (NodeCost*)malloc(cacheCap * sizeof(NodeCost));
-
- // Want the behavior that if the actual number of states is specified, the cache
- // will be at least that big.
- hashShift = 3; // 8 (only useful for stress testing)
-#if !defined( MICROPATHER_STRESS )
- while( HashSize() < allocate )
- ++hashShift;
-#endif
- hashTable = (PathNode**)calloc( HashSize(), sizeof(PathNode*) );
-
- blocks = firstBlock = NewBlock();
-// printf( "HashSize=%d allocate=%d\n", HashSize(), allocate );
- totalCollide = 0;
-}
-
-
-PathNodePool::~PathNodePool()
-{
- Clear();
- free( firstBlock );
- free( cache );
- free( hashTable );
-#ifdef TRACK_COLLISION
- printf( "Total collide=%d HashSize=%d HashShift=%d\n", totalCollide, HashSize(), hashShift );
-#endif
-}
-
-
-bool PathNodePool::PushCache( const NodeCost* nodes, int nNodes, int* start ) {
- *start = -1;
- if ( nNodes+cacheSize <= cacheCap ) {
- for( int i=0; i= 0 && start < cacheCap );
- MPASSERT( nNodes > 0 );
- MPASSERT( start + nNodes <= cacheCap );
- memcpy( nodes, &cache[start], sizeof(NodeCost)*nNodes );
-}
-
-
-void PathNodePool::Clear()
-{
-#ifdef TRACK_COLLISION
- // Collision tracking code.
- int collide=0;
- for( unsigned i=0; ichild[0] || hashTable[i]->child[1]) )
- ++collide;
- }
- //printf( "PathNodePool %d/%d collision=%d %.1f%%\n", nAllocated, HashSize(), collide, 100.0f*(float)collide/(float)HashSize() );
- totalCollide += collide;
-#endif
-
- Block* b = blocks;
- while( b ) {
- Block* temp = b->nextBlock;
- if ( b != firstBlock ) {
- free( b );
- }
- b = temp;
- }
- blocks = firstBlock; // Don't delete the first block (we always need at least that much memory.)
-
- // Set up for new allocations (but don't do work we don't need to. Reset/Clear can be called frequently.)
- if ( nAllocated > 0 ) {
- freeMemSentinel.next = &freeMemSentinel;
- freeMemSentinel.prev = &freeMemSentinel;
-
- memset( hashTable, 0, sizeof(PathNode*)*HashSize() );
- for( unsigned i=0; ipathNode[i] );
- }
- }
- nAvailable = allocate;
- nAllocated = 0;
- cacheSize = 0;
-}
-
-
-PathNodePool::Block* PathNodePool::NewBlock()
-{
- Block* block = (Block*) calloc( 1, sizeof(Block) + sizeof(PathNode)*(allocate-1) );
- block->nextBlock = 0;
-
- nAvailable += allocate;
- for( unsigned i=0; ipathNode[i] );
- }
- return block;
-}
-
-
-unsigned PathNodePool::Hash( void* voidval )
-{
- /*
- Spent quite some time on this, and the result isn't quite satifactory. The
- input set is the size of a void*, and is generally (x,y) pairs or memory pointers.
-
- FNV resulting in about 45k collisions in a (large) test and some other approaches
- about the same.
-
- Simple folding reduces collisions to about 38k - big improvement. However, that may
- be an artifact of the (x,y) pairs being well distributed. And for either the x,y case
- or the pointer case, there are probably very poor hash table sizes that cause "overlaps"
- and grouping. (An x,y encoding with a hashShift of 8 is begging for trouble.)
-
- The best tested results are simple folding, but that seems to beg for a pathelogical case.
- FNV-1a was the next best choice, without obvious pathelogical holes.
-
- Finally settled on h%HashMask(). Simple, but doesn't have the obvious collision cases of folding.
- */
- /*
- // Time: 567
- // FNV-1a
- // http://isthe.com/chongo/tech/comp/fnv/
- // public domain.
- MP_UPTR val = (MP_UPTR)(voidval);
- const unsigned char *p = (unsigned char *)(&val);
- unsigned int h = 2166136261;
-
- for( size_t i=0; i>hashShift) ^ (h>>(hashShift*2)) ^ (h>>(hashShift*3)) ) & HashMask();
- */
- /*
- // Time: 526
- MP_UPTR h = (MP_UPTR)(voidval);
- return ( h ^ (h>>hashShift) ^ (h>>(hashShift*2)) ^ (h>>(hashShift*3)) ) & HashMask();
- */
-
- // Time: 512
- // The HashMask() is used as the divisor. h%1024 has lots of common
- // repetitions, but h%1023 will move things out more.
- MP_UPTR h = (MP_UPTR)(voidval);
- return h % HashMask();
-}
-
-
-
-PathNode* PathNodePool::Alloc()
-{
- if ( freeMemSentinel.next == &freeMemSentinel ) {
- MPASSERT( nAvailable == 0 );
-
- Block* b = NewBlock();
- b->nextBlock = blocks;
- blocks = b;
- MPASSERT( freeMemSentinel.next != &freeMemSentinel );
- }
- PathNode* pathNode = freeMemSentinel.next;
- pathNode->Unlink();
-
- ++nAllocated;
- MPASSERT( nAvailable > 0 );
- --nAvailable;
- return pathNode;
-}
-
-
-void PathNodePool::AddPathNode( unsigned key, PathNode* root )
-{
- if ( hashTable[key] ) {
- PathNode* p = hashTable[key];
- while( true ) {
- int dir = (root->state < p->state) ? 0 : 1;
- if ( p->child[dir] ) {
- p = p->child[dir];
- }
- else {
- p->child[dir] = root;
- break;
- }
- }
- }
- else {
- hashTable[key] = root;
- }
-}
-
-
-PathNode* PathNodePool::FetchPathNode( void* state )
-{
- unsigned key = Hash( state );
-
- PathNode* root = hashTable[key];
- while( root ) {
- if ( root->state == state ) {
- break;
- }
- root = ( state < root->state ) ? root->child[0] : root->child[1];
- }
- MPASSERT( root );
- return root;
-}
-
-
-PathNode* PathNodePool::GetPathNode( unsigned frame, void* _state, float _costFromStart, float _estToGoal, PathNode* _parent )
-{
- unsigned key = Hash( _state );
-
- PathNode* root = hashTable[key];
- while( root ) {
- if ( root->state == _state ) {
- if ( root->frame == frame ) // This is the correct state and correct frame.
- break;
- // Correct state, wrong frame.
- root->Init( frame, _state, _costFromStart, _estToGoal, _parent );
- break;
- }
- root = ( _state < root->state ) ? root->child[0] : root->child[1];
- }
- if ( !root ) {
- // allocate new one
- root = Alloc();
- root->Clear();
- root->Init( frame, _state, _costFromStart, _estToGoal, _parent );
- AddPathNode( key, root );
- }
- return root;
-}
-
-
-void PathNode::Init( unsigned _frame,
- void* _state,
- float _costFromStart,
- float _estToGoal,
- PathNode* _parent )
-{
- state = _state;
- costFromStart = _costFromStart;
- estToGoal = _estToGoal;
- CalcTotalCost();
- parent = _parent;
- frame = _frame;
- inOpen = 0;
- inClosed = 0;
-}
-
-
-void PathNode::Clear()
-{
- memset( this, 0, sizeof( PathNode ) );
- numAdjacent = -1;
- cacheIndex = -1;
-}
-
-MicroPather::MicroPather( Graph* _graph, unsigned allocate, unsigned typicalAdjacent, bool cache )
- : pathNodePool( allocate, typicalAdjacent ),
- graph( _graph ),
- frame( 0 )
-{
- MPASSERT( allocate );
- MPASSERT( typicalAdjacent );
- pathCache = 0;
- if ( cache ) {
- pathCache = new PathCache( allocate*4 ); // untuned arbitrary constant
- }
-}
-
-
-MicroPather::~MicroPather()
-{
- delete pathCache;
-}
-
-
-void MicroPather::Reset()
-{
- pathNodePool.Clear();
- if ( pathCache ) {
- pathCache->Reset();
- }
- frame = 0;
-}
-
-
-void MicroPather::GoalReached( PathNode* node, void* start, void* end, MP_VECTOR< void* > *_path )
-{
- MP_VECTOR< void* >& path = *_path;
- path.clear();
-
- // We have reached the goal.
- // How long is the path? Used to allocate the vector which is returned.
- int count = 1;
- PathNode* it = node;
- while( it->parent )
- {
- ++count;
- it = it->parent;
- }
-
- // Now that the path has a known length, allocate
- // and fill the vector that will be returned.
- if ( count < 3 )
- {
- // Handle the short, special case.
- path.resize(2);
- path[0] = start;
- path[1] = end;
- }
- else
- {
- path.resize(count);
-
- path[0] = start;
- path[count-1] = end;
- count-=2;
- it = node->parent;
-
- while ( it->parent )
- {
- path[count] = it->state;
- it = it->parent;
- --count;
- }
- }
-
- if ( pathCache ) {
- costVec.clear();
-
- PathNode* pn0 = pathNodePool.FetchPathNode( path[0] );
- PathNode* pn1 = 0;
- for( unsigned i=0; iAdd( path, costVec );
- }
-
- #ifdef DEBUG_PATH
- printf( "Path: " );
- int counter=0;
- #endif
- for ( unsigned k=0; kPrintStateInfo( path[k] );
- printf( " " );
- ++counter;
- if ( counter == 8 )
- {
- printf( "\n" );
- counter = 0;
- }
- #endif
- }
- #ifdef DEBUG_PATH
- printf( "Cost=%.1f Checksum %d\n", node->costFromStart, checksum );
- #endif
-}
-
-
-void MicroPather::GetNodeNeighbors( PathNode* node, MP_VECTOR< NodeCost >* pNodeCost )
-{
- if ( node->numAdjacent == 0 ) {
- // it has no neighbors.
- pNodeCost->resize( 0 );
- }
- else if ( node->cacheIndex < 0 )
- {
- // Not in the cache. Either the first time or just didn't fit. We don't know
- // the number of neighbors and need to call back to the client.
- stateCostVec.resize( 0 );
- graph->AdjacentCost( node->state, &stateCostVec );
-
- #ifdef DEBUG
- {
- // If this assert fires, you have passed a state
- // as its own neighbor state. This is impossible --
- // bad things will happen.
- for ( unsigned i=0; istate );
- }
- #endif
-
- pNodeCost->resize( stateCostVec.size() );
- node->numAdjacent = stateCostVec.size();
-
- if ( node->numAdjacent > 0 ) {
- // Now convert to pathNodes.
- // Note that the microsoft std library is actually pretty slow.
- // Move things to temp vars to help.
- const unsigned stateCostVecSize = stateCostVec.size();
- const StateCost* stateCostVecPtr = &stateCostVec[0];
- NodeCost* pNodeCostPtr = &(*pNodeCost)[0];
-
- for( unsigned i=0; isize() > 0 && pathNodePool.PushCache( pNodeCostPtr, pNodeCost->size(), &start ) ) {
- node->cacheIndex = start;
- }
- }
- }
- else {
- // In the cache!
- pNodeCost->resize( node->numAdjacent );
- NodeCost* pNodeCostPtr = &(*pNodeCost)[0];
- pathNodePool.GetCache( node->cacheIndex, node->numAdjacent, pNodeCostPtr );
-
- // A node is uninitialized (even if memory is allocated) if it is from a previous frame.
- // Check for that, and Init() as necessary.
- for( int i=0; inumAdjacent; ++i ) {
- PathNode* pNode = pNodeCostPtr[i].node;
- if ( pNode->frame != frame ) {
- pNode->Init( frame, pNode->state, FLT_MAX, FLT_MAX, 0 );
- }
- }
- }
-}
-
-
-#ifdef DEBUG
-/*
-void MicroPather::DumpStats()
-{
- int hashTableEntries = 0;
- for( int i=0; i* stateVec )
-{
- stateVec->clear();
- pathNodePool.AllStates( frame, stateVec );
-}
-
-
-void PathNodePool::AllStates( unsigned frame, MP_VECTOR< void* >* stateVec )
-{
- for ( Block* b=blocks; b; b=b->nextBlock )
- {
- for( unsigned i=0; ipathNode[i].frame == frame )
- stateVec->push_back( b->pathNode[i].state );
- }
- }
-}
-
-
-PathCache::PathCache( int _allocated )
-{
- mem = new Item[_allocated];
- memset( mem, 0, sizeof(*mem)*_allocated );
- allocated = _allocated;
- nItems = 0;
- hit = 0;
- miss = 0;
-}
-
-
-PathCache::~PathCache()
-{
- delete [] mem;
-}
-
-
-void PathCache::Reset()
-{
- if ( nItems ) {
- memset( mem, 0, sizeof(*mem)*allocated );
- nItems = 0;
- hit = 0;
- miss = 0;
- }
-}
-
-
-void PathCache::Add( const MP_VECTOR< void* >& path, const MP_VECTOR< float >& cost )
-{
- if ( nItems + (int)path.size() > allocated*3/4 ) {
- return;
- }
-
- for( unsigned i=0; ib->c->d
- // Huge memory saving to only store 3 paths to 'd'
- // Can put more in cache with also adding path to b, c, & d
- // But uses much more memory. Experiment with this commented
- // in and out and how to set.
-
- void* end = path[path.size()-1];
- Item item = { path[i], end, path[i+1], cost[i] };
- AddItem( item );
- }
-}
-
-
-void PathCache::AddNoSolution( void* end, void* states[], int count )
-{
- if ( count + nItems > allocated*3/4 ) {
- return;
- }
-
- for( int i=0; i* path, float* totalCost )
-{
- const Item* item = Find( start, end );
- if ( item ) {
- if ( item->cost == FLT_MAX ) {
- ++hit;
- return MicroPather::NO_SOLUTION;
- }
-
- path->clear();
- path->push_back( start );
- *totalCost = 0;
-
- for ( ;start != end; start=item->next, item=Find(start, end) ) {
- MPASSERT( item );
- *totalCost += item->cost;
- path->push_back( item->next );
- }
- ++hit;
- return MicroPather::SOLVED;
- }
- ++miss;
- return MicroPather::NOT_CACHED;
-}
-
-
-void PathCache::AddItem( const Item& item )
-{
- MPASSERT( allocated );
- unsigned index = item.Hash() % allocated;
- while( true ) {
- if ( mem[index].Empty() ) {
- mem[index] = item;
- ++nItems;
-#ifdef DEBUG_CACHING
- GLOUTPUT(( "Add: start=%x next=%x end=%x\n", item.start, item.next, item.end ));
-#endif
- break;
- }
- else if ( mem[index].KeyEqual( item ) ) {
- MPASSERT( (mem[index].next && item.next) || (mem[index].next==0 && item.next == 0) );
- // do nothing; in cache
- break;
- }
- ++index;
- if ( index == allocated )
- index = 0;
- }
-}
-
-
-const PathCache::Item* PathCache::Find( void* start, void* end )
-{
- MPASSERT( allocated );
- Item fake = { start, end, 0, 0 };
- unsigned index = fake.Hash() % allocated;
- while( true ) {
- if ( mem[index].Empty() ) {
- return 0;
- }
- if ( mem[index].KeyEqual( fake )) {
- return mem + index;
- }
- ++index;
- if ( index == allocated )
- index = 0;
- }
-}
-
-
-void MicroPather::GetCacheData( CacheData* data )
-{
- memset( data, 0, sizeof(*data) );
-
- if ( pathCache ) {
- data->nBytesAllocated = pathCache->AllocatedBytes();
- data->nBytesUsed = pathCache->UsedBytes();
- data->memoryFraction = (float)( (double)data->nBytesUsed / (double)data->nBytesAllocated );
-
- data->hit = pathCache->hit;
- data->miss = pathCache->miss;
- if ( data->hit + data->miss ) {
- data->hitFraction = (float)( (double)(data->hit) / (double)(data->hit + data->miss) );
- }
- else {
- data->hitFraction = 0;
- }
- }
-}
-
-
-
-int MicroPather::Solve( void* startNode, void* endNode, MP_VECTOR< void* >* path, float* cost )
-{
- // Important to clear() in case the caller doesn't check the return code. There
- // can easily be a left over path from a previous call.
- path->clear();
-
- #ifdef DEBUG_PATH
- printf( "Path: " );
- graph->PrintStateInfo( startNode );
- printf( " --> " );
- graph->PrintStateInfo( endNode );
- printf( " min cost=%f\n", graph->LeastCostEstimate( startNode, endNode ) );
- #endif
-
- *cost = 0.0f;
-
- if ( startNode == endNode )
- return START_END_SAME;
-
- if ( pathCache ) {
- int cacheResult = pathCache->Solve( startNode, endNode, path, cost );
- if ( cacheResult == SOLVED || cacheResult == NO_SOLUTION ) {
- #ifdef DEBUG_CACHING
- GLOUTPUT(( "PathCache hit. result=%s\n", cacheResult == SOLVED ? "solved" : "no_solution" ));
- #endif
- return cacheResult;
- }
- #ifdef DEBUG_CACHING
- GLOUTPUT(( "PathCache miss\n" ));
- #endif
- }
-
- ++frame;
-
- OpenQueue open( graph );
- ClosedSet closed( graph );
-
- PathNode* newPathNode = pathNodePool.GetPathNode( frame,
- startNode,
- 0,
- graph->LeastCostEstimate( startNode, endNode ),
- 0 );
-
- open.Push( newPathNode );
- stateCostVec.resize(0);
- nodeCostVec.resize(0);
-
- while ( !open.Empty() )
- {
- PathNode* node = open.Pop();
-
- if ( node->state == endNode )
- {
- GoalReached( node, startNode, endNode, path );
- *cost = node->costFromStart;
- #ifdef DEBUG_PATH
- DumpStats();
- #endif
- return SOLVED;
- }
- else
- {
- closed.Add( node );
-
- // We have not reached the goal - add the neighbors.
- GetNodeNeighbors( node, &nodeCostVec );
-
- for( int i=0; inumAdjacent; ++i )
- {
- // Not actually a neighbor, but useful. Filter out infinite cost.
- if ( nodeCostVec[i].cost == FLT_MAX ) {
- continue;
- }
- PathNode* child = nodeCostVec[i].node;
- float newCost = node->costFromStart + nodeCostVec[i].cost;
-
- PathNode* inOpen = child->inOpen ? child : 0;
- PathNode* inClosed = child->inClosed ? child : 0;
- PathNode* inEither = (PathNode*)( ((MP_UPTR)inOpen) | ((MP_UPTR)inClosed) );
-
- MPASSERT( inEither != node );
- MPASSERT( !( inOpen && inClosed ) );
-
- if ( inEither ) {
- if ( newCost < child->costFromStart ) {
- child->parent = node;
- child->costFromStart = newCost;
- child->estToGoal = graph->LeastCostEstimate( child->state, endNode );
- child->CalcTotalCost();
- if ( inOpen ) {
- open.Update( child );
- }
- }
- }
- else {
- child->parent = node;
- child->costFromStart = newCost;
- child->estToGoal = graph->LeastCostEstimate( child->state, endNode ),
- child->CalcTotalCost();
-
- MPASSERT( !child->inOpen && !child->inClosed );
- open.Push( child );
- }
- }
- }
- }
- #ifdef DEBUG_PATH
- DumpStats();
- #endif
- if ( pathCache ) {
- // Could add a bunch more with a little tracking.
- pathCache->AddNoSolution( endNode, &startNode, 1 );
- }
- return NO_SOLUTION;
-}
-
-
-int MicroPather::SolveForNearStates( void* startState, MP_VECTOR< StateCost >* near, float maxCost )
-{
- /* http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
-
- 1 function Dijkstra(Graph, source):
- 2 for each vertex v in Graph: // Initializations
- 3 dist[v] := infinity // Unknown distance function from source to v
- 4 previous[v] := undefined // Previous node in optimal path from source
- 5 dist[source] := 0 // Distance from source to source
- 6 Q := the set of all nodes in Graph
- // All nodes in the graph are unoptimized - thus are in Q
- 7 while Q is not empty: // The main loop
- 8 u := vertex in Q with smallest dist[]
- 9 if dist[u] = infinity:
- 10 break // all remaining vertices are inaccessible from source
- 11 remove u from Q
- 12 for each neighbor v of u: // where v has not yet been removed from Q.
- 13 alt := dist[u] + dist_between(u, v)
- 14 if alt < dist[v]: // Relax (u,v,a)
- 15 dist[v] := alt
- 16 previous[v] := u
- 17 return dist[]
- */
-
- ++frame;
-
- OpenQueue open( graph ); // nodes to look at
- ClosedSet closed( graph );
-
- nodeCostVec.resize(0);
- stateCostVec.resize(0);
-
- PathNode closedSentinel;
- closedSentinel.Clear();
- closedSentinel.Init( frame, 0, FLT_MAX, FLT_MAX, 0 );
- closedSentinel.next = closedSentinel.prev = &closedSentinel;
-
- PathNode* newPathNode = pathNodePool.GetPathNode( frame, startState, 0, 0, 0 );
- open.Push( newPathNode );
-
- while ( !open.Empty() )
- {
- PathNode* node = open.Pop(); // smallest dist
- closed.Add( node ); // add to the things we've looked at
- closedSentinel.AddBefore( node );
-
- if ( node->totalCost > maxCost )
- continue; // Too far away to ever get here.
-
- GetNodeNeighbors( node, &nodeCostVec );
-
- for( int i=0; inumAdjacent; ++i )
- {
- MPASSERT( node->costFromStart < FLT_MAX );
- float newCost = node->costFromStart + nodeCostVec[i].cost;
-
- PathNode* inOpen = nodeCostVec[i].node->inOpen ? nodeCostVec[i].node : 0;
- PathNode* inClosed = nodeCostVec[i].node->inClosed ? nodeCostVec[i].node : 0;
- MPASSERT( !( inOpen && inClosed ) );
- PathNode* inEither = inOpen ? inOpen : inClosed;
- MPASSERT( inEither != node );
-
- if ( inEither && inEither->costFromStart <= newCost ) {
- continue; // Do nothing. This path is not better than existing.
- }
- // Groovy. We have new information or improved information.
- PathNode* child = nodeCostVec[i].node;
- MPASSERT( child->state != newPathNode->state ); // should never re-process the parent.
-
- child->parent = node;
- child->costFromStart = newCost;
- child->estToGoal = 0;
- child->totalCost = child->costFromStart;
-
- if ( inOpen ) {
- open.Update( inOpen );
- }
- else if ( !inClosed ) {
- open.Push( child );
- }
- }
- }
- near->clear();
-
- for( PathNode* pNode=closedSentinel.next; pNode != &closedSentinel; pNode=pNode->next ) {
- if ( pNode->totalCost <= maxCost ) {
- StateCost sc;
- sc.cost = pNode->totalCost;
- sc.state = pNode->state;
-
- near->push_back( sc );
- }
- }
-#ifdef DEBUG
- for( unsigned i=0; isize(); ++i ) {
- for( unsigned k=i+1; ksize(); ++k ) {
- MPASSERT( (*near)[i].state != (*near)[k].state );
- }
- }
-#endif
-
- return SOLVED;
-}
-
-
-
-
diff --git a/external/MicroPather/micropather.h b/external/MicroPather/micropather.h
deleted file mode 100755
index 1c63414d..00000000
--- a/external/MicroPather/micropather.h
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
-Copyright (c) 2000-2013 Lee Thomason (www.grinninglizard.com)
-Micropather
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any
-damages arising from the use of this software.
-
-Permission is granted to anyone to use this software for any
-purpose, including commercial applications, and to alter it and
-redistribute it freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must
-not claim that you wrote the original software. If you use this
-software in a product, an acknowledgment in the product documentation
-would be appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and
-must not be misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
-distribution.
-*/
-
-
-#ifndef GRINNINGLIZARD_MICROPATHER_INCLUDED
-#define GRINNINGLIZARD_MICROPATHER_INCLUDED
-
-
-/** @mainpage MicroPather
-
- MicroPather is a path finder and A* solver (astar or a-star) written in platform independent
- C++ that can be easily integrated into existing code. MicroPather focuses on being a path
- finding engine for video games but is a generic A* solver. MicroPather is open source, with
- a license suitable for open source or commercial use.
-*/
-
-// This probably works to remove, but isn't currently tested in STL mode.
-#define GRINLIZ_NO_STL
-
-#ifdef GRINLIZ_NO_STL
-# define MP_VECTOR micropather::MPVector
-#else
-# include
-# define MP_VECTOR std::vector
-#endif
-#include
-
-#ifdef _DEBUG
- #ifndef DEBUG
- #define DEBUG
- #endif
-#endif
-
-
-#if defined(DEBUG)
-# if defined(_MSC_VER)
-# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
-# define MPASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
-# elif defined (ANDROID_NDK)
-# include
-# define MPASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
-# else
-# include
-# define MPASSERT assert
-# endif
-# else
-# define MPASSERT( x ) {}
-#endif
-
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
- #include
- typedef uintptr_t MP_UPTR;
-#elif defined (__GNUC__) && (__GNUC__ >= 3 )
- #include
- #include
- typedef uintptr_t MP_UPTR;
-#else
- // Assume not 64 bit pointers. Get a new compiler.
- typedef unsigned MP_UPTR;
-#endif
-
-namespace micropather
-{
-#ifdef GRINLIZ_NO_STL
-
- /* WARNING: vector partial replacement. Does everything needed to replace std::vector
- for micropather, but only works on Plain Old Data types. Doesn't call copy/construct/destruct
- correctly for general use.
- */
- template
- class MPVector {
- public:
- MPVector() : m_allocated( 0 ), m_size( 0 ), m_buf ( 0 ) {}
- ~MPVector() { delete [] m_buf; }
-
- void clear() { m_size = 0; } // see warning above
- void resize( unsigned s ) { capacity( s );
- m_size = s;
- }
- T& operator[](unsigned i) { MPASSERT( i>=0 && i=0 && i *adjacent ) = 0;
-
- /**
- This function is only used in DEBUG mode - it dumps output to stdout. Since void*
- aren't really human readable, normally you print out some concise info (like "(1,2)")
- without an ending newline.
- */
- virtual void PrintStateInfo( void* state ) = 0;
- };
-
-
- class PathNode;
-
- struct NodeCost
- {
- PathNode* node;
- float cost;
- };
-
-
- /*
- Every state (void*) is represented by a PathNode in MicroPather. There
- can only be one PathNode for a given state.
- */
- class PathNode
- {
- public:
- void Init( unsigned _frame,
- void* _state,
- float _costFromStart,
- float _estToGoal,
- PathNode* _parent );
-
- void Clear();
- void InitSentinel() {
- Clear();
- Init( 0, 0, FLT_MAX, FLT_MAX, 0 );
- prev = next = this;
- }
-
- void *state; // the client state
- float costFromStart; // exact
- float estToGoal; // estimated
- float totalCost; // could be a function, but save some math.
- PathNode* parent; // the parent is used to reconstruct the path
- unsigned frame; // unique id for this path, so the solver can distinguish
- // correct from stale values
-
- int numAdjacent; // -1 is unknown & needs to be queried
- int cacheIndex; // position in cache
-
- PathNode *child[2]; // Binary search in the hash table. [left, right]
- PathNode *next, *prev; // used by open queue
-
- bool inOpen;
- bool inClosed;
-
- void Unlink() {
- next->prev = prev;
- prev->next = next;
- next = prev = 0;
- }
- void AddBefore( PathNode* addThis ) {
- addThis->next = this;
- addThis->prev = prev;
- prev->next = addThis;
- prev = addThis;
- }
- #ifdef DEBUG
- void CheckList()
- {
- MPASSERT( totalCost == FLT_MAX );
- for( PathNode* it = next; it != this; it=it->next ) {
- MPASSERT( it->prev == this || it->totalCost >= it->prev->totalCost );
- MPASSERT( it->totalCost <= it->next->totalCost );
- }
- }
- #endif
-
- void CalcTotalCost() {
- if ( costFromStart < FLT_MAX && estToGoal < FLT_MAX )
- totalCost = costFromStart + estToGoal;
- else
- totalCost = FLT_MAX;
- }
-
- private:
-
- void operator=( const PathNode& );
- };
-
-
- /* Memory manager for the PathNodes. */
- class PathNodePool
- {
- public:
- PathNodePool( unsigned allocate, unsigned typicalAdjacent );
- ~PathNodePool();
-
- // Free all the memory except the first block. Resets all memory.
- void Clear();
-
- // Essentially:
- // pNode = Find();
- // if ( !pNode )
- // pNode = New();
- //
- // Get the PathNode associated with this state. If the PathNode already
- // exists (allocated and is on the current frame), it will be returned.
- // Else a new PathNode is allocated and returned. The returned object
- // is always fully initialized.
- //
- // NOTE: if the pathNode exists (and is current) all the initialization
- // parameters are ignored.
- PathNode* GetPathNode( unsigned frame,
- void* _state,
- float _costFromStart,
- float _estToGoal,
- PathNode* _parent );
-
- // Get a pathnode that is already in the pool.
- PathNode* FetchPathNode( void* state );
-
- // Store stuff in cache
- bool PushCache( const NodeCost* nodes, int nNodes, int* start );
-
- // Get neighbors from the cache
- // Note - always access this with an offset. Can get re-allocated.
- void GetCache( int start, int nNodes, NodeCost* nodes );
-
- // Return all the allocated states. Useful for visuallizing what
- // the pather is doing.
- void AllStates( unsigned frame, MP_VECTOR< void* >* stateVec );
-
- private:
- struct Block
- {
- Block* nextBlock;
- PathNode pathNode[1];
- };
-
- unsigned Hash( void* voidval );
- unsigned HashSize() const { return 1<& path, const MP_VECTOR< float >& cost );
- void AddNoSolution( void* end, void* states[], int count );
- int Solve( void* startState, void* endState, MP_VECTOR< void* >* path, float* totalCost );
-
- int AllocatedBytes() const { return allocated * sizeof(Item); }
- int UsedBytes() const { return nItems * sizeof(Item); }
-
- int hit;
- int miss;
-
- private:
- void AddItem( const Item& item );
- const Item* Find( void* start, void* end );
-
- Item* mem;
- int allocated;
- int nItems;
- };
-
- struct CacheData {
- CacheData() : nBytesAllocated(0), nBytesUsed(0), memoryFraction(0), hit(0), miss(0), hitFraction(0) {}
- int nBytesAllocated;
- int nBytesUsed;
- float memoryFraction;
-
- int hit;
- int miss;
- float hitFraction;
- };
-
- /**
- Create a MicroPather object to solve for a best path. Detailed usage notes are
- on the main page.
- */
- class MicroPather
- {
- friend class micropather::PathNode;
-
- public:
- enum
- {
- SOLVED,
- NO_SOLUTION,
- START_END_SAME,
-
- // internal
- NOT_CACHED
- };
-
- /**
- Construct the pather, passing a pointer to the object that implements
- the Graph callbacks.
-
- @param graph The "map" that implements the Graph callbacks.
- @param allocate How many states should be internally allocated at a time. This
- can be hard to get correct. The higher the value, the more memory
- MicroPather will use.
- - If you have a small map (a few thousand states?) it may make sense
- to pass in the maximum value. This will cache everything, and MicroPather
- will only need one main memory allocation. For a chess board, allocate
- would be set to 8x8 (64)
- - If your map is large, something like 1/4 the number of possible
- states is good.
- - If your state space is huge, use a multiple (5-10x) of the normal
- path. "Occasionally" call Reset() to free unused memory.
- @param typicalAdjacent Used to determine cache size. The typical number of adjacent states
- to a given state. (On a chessboard, 8.) Higher values use a little
- more memory.
- @param cache Turn on path caching. Uses more memory (yet again) but at a huge speed
- advantage if you may call the pather with the same path or sub-path, which
- is common for pathing over maps in games.
- */
- MicroPather( Graph* graph, unsigned allocate = 250, unsigned typicalAdjacent=6, bool cache=true );
- ~MicroPather();
-
- /**
- Solve for the path from start to end.
-
- @param startState Input, the starting state for the path.
- @param endState Input, the ending state for the path.
- @param path Output, a vector of states that define the path. Empty if not found.
- @param totalCost Output, the cost of the path, if found.
- @return Success or failure, expressed as SOLVED, NO_SOLUTION, or START_END_SAME.
- */
- int Solve( void* startState, void* endState, MP_VECTOR< void* >* path, float* totalCost );
-
- /**
- Find all the states within a given cost from startState.
-
- @param startState Input, the starting state for the path.
- @param near All the states within 'maxCost' of 'startState', and cost to that state.
- @param maxCost Input, the maximum cost that will be returned. (Higher values return
- larger 'near' sets and take more time to compute.)
- @return Success or failure, expressed as SOLVED or NO_SOLUTION.
- */
- int SolveForNearStates( void* startState, MP_VECTOR< StateCost >* near, float maxCost );
-
- /** Should be called whenever the cost between states or the connection between states changes.
- Also frees overhead memory used by MicroPather, and calling will free excess memory.
- */
- void Reset();
-
- // Debugging function to return all states that were used by the last "solve"
- void StatesInPool( MP_VECTOR< void* >* stateVec );
- void GetCacheData( CacheData* data );
-
- private:
- MicroPather( const MicroPather& ); // undefined and unsupported
- void operator=( const MicroPather ); // undefined and unsupported
-
- void GoalReached( PathNode* node, void* start, void* end, MP_VECTOR< void* > *path );
-
- void GetNodeNeighbors( PathNode* node, MP_VECTOR< NodeCost >* neighborNode );
-
- #ifdef DEBUG
- //void DumpStats();
- #endif
-
- PathNodePool pathNodePool;
- MP_VECTOR< StateCost > stateCostVec; // local to Solve, but put here to reduce memory allocation
- MP_VECTOR< NodeCost > nodeCostVec; // local to Solve, but put here to reduce memory allocation
- MP_VECTOR< float > costVec;
-
- Graph* graph;
- unsigned frame; // incremented with every solve, used to determine if cached data needs to be refreshed
- PathCache* pathCache;
- };
-}; // namespace grinliz
-
-#endif
-
diff --git a/external/MicroPather/readme.md b/external/MicroPather/readme.md
deleted file mode 100755
index 6c09c96d..00000000
--- a/external/MicroPather/readme.md
+++ /dev/null
@@ -1,181 +0,0 @@
-MicroPather
-===========
-
-MicroPather is a path finder and A* solver (astar or a-star) written in platform
-independent C++ that can be easily integrated into existing code. MicroPather
-focuses on being a path finding engine for video games but is a generic A* solver.
-MicroPather is open source, with a license suitable for open source or commercial
-use.
-
-The goals of MicroPather are:
-* Easy integration into games and other software
-* Easy to use and simple interface
-* Fast enough
-
-Demo
-----
-
-MicroPather comes with a demo application - dungeon.cpp - to show off pathing.
-It's ASCII art dungeon exploring at its finest.
-
-The demo shows an ASCII art dungeon. You can move around by typing a new location, and it will
-print the path to that location. In the screen shot above, the path starts in
-the upper left corner, and steps to the 'i' at about the middle of
-the screen avoiding ASCII walls on the way. The numbers show the path from 0
-to 9 then back to 0.
-
-You can even open and close the doors to change possible paths. 'd' at the command prompt.
-
-A Windows Visual C++ 2010 project file and a Linux Makefile are provided. Building it
-for another environment is trivial: just compile dungeon.cpp, micropather.h, and
-micropather.cpp to a command line app in your environment.
-
-About A*
---------
-In video games, the pathfinding problem comes up in many modern games. What
-is the shortest distance from point A to point B? Humans are good at that problem
-- you pathfind naturally almost every time you move - but tricky to express
-as a computer algorithm. A* is the workhorse technique to solve pathing. It
-is directed, meaning that it is optimized to find a solution quickly rather
-than by brute force, but it will never fail to find a solution if there is one.
-
-A* is much more universal that just pathfinding. A* and MicroPather could be
-used to find the solution to general state problems, for example it could be
-used to solve for a rubiks cube puzzle.
-
-Terminology
------------
-
-The *Graph* is the search space. For the pathfinding problem,
-this is your Map. It can be any kind of map: squares like the dungeon example,
-polygonal, 3D, hexagons, etc.
-
-In pathfinding, a *State* is just a position on the Map. In
-the demo, the player starts at State (0,0). Adjacent states are very important,
-as you might image. If something is at state (1,1) in the dungeon example,
-it has 8 adjacent states (0,1), (2,1) etc. it can move to. Why State instead
-of location or node? The terminology comes from the more general application.
-The states of a cube puzzle aren't locations, for example.
-
-States are separated by *Cost*. For simple pathfinding in
-the dungeon, the *Cost* is simply distance. The cost from state
-(0,0) to (1,0) is 1.0, and the cost from (0,0) to (1,1) is sqrt(2), about
-1.4. *Cost* is challenging and interesting because it can be
-distance, time, or difficulty.
-* using distance as the cost will give the shortest length path
-* using traversal time as the cost will give the fastest path
-* using difficulty as the cost will give the easiest path
-etc.
-
-More info: http://www-cs-students.stanford.edu/~amitp/gameprog.html#paths
-
-Integrating MicroPather Into Your Code
---------------------------------------
-Nothing could by simpler! Or at least that's the goal. More importantly, none
-of your game data structures need to change to use MicroPather. The steps, in
-brief, are:
-
-1. Include MicroPather files
-2. Implement the Graph interface
-3. Call the Solver
-
-*Include files*
-
-There are only 2 files for micropather: micropather.cpp and micropather.h.
-So there's no build, no make, just add the 2 files to your project. That's it.
-They are standard C++ and don't require exceptions or RTTI. (I know, a bunch
-of you like exceptions and RTTI. But it does make it less portable and slightly
-slower to use them.)
-
-Assuming you build a debug version of your project with _DEBUG or DEBUG (and
-everyone does) MicroPather will run extra checking in these modes.
-
-*Implement Graph Interface*
-
-You have some class called Game, or Map, or World, that organizes and stores
-your game map. This object (we'll call it Map) needs to inherit from the abstract
-class Graph:
-
- class Map : public Graph
-
-Graph is pure abstract, so your map class won't be changed by it (except for
-possibly gaining a vtable), or have strange conflicts.
-Before getting to the methods of Graph, lets think states, as in:
-
- void Foo( void* state )
-
-The state pointer is provided by you, the game programmer. What it is? It is
-a unique id for a state. For something like a 3D terrain map, like Lilith3D
-uses, the states are pointers to a map structure, a 'QuadNode' in
-this case. So the state would simply be:
-
- void* state = (void*) quadNode;
-
-On the other hand, the Dungeon example doesn't have an object per map location,
-just an x and y. It then uses:
-
- void* state = (void*)( y * MAPX + x );
-
-The state can be anything you want, as long as it is unique and you can convert
-to it and from it.
-
-Now, the methods of Graph.
-
- /**
- Return the least possible cost between 2 states. For example, if your pathfinding
- is based on distance, this is simply the straight distance between 2 points on the
- map. If you pathfinding is based on minimum time, it is the minimal travel time
- between 2 points given the best possible terrain.
- */
- virtual float LeastCostEstimate( void* stateStart, void* stateEnd ) = 0;
-
- /**
- Return the exact cost from the given state to all its neighboring states. This
- may be called multiple times, or cached by the solver. It *must* return the same
- exact values for every call to MicroPather::Solve(). It should generally be a simple,
- fast function with no callbacks into the pather.
- */
- virtual void AdjacentCost( void* state, MP_VECTOR< micropather::StateCost > *adjacent ) = 0;
-
- /**
- This function is only used in DEBUG mode - it dumps output to stdout. Since void*
- aren't really human readable, normally you print out some concise info (like "(1,2)")
- without an ending newline.
- */
- virtual void PrintStateInfo( void* state ) = 0;
-
-*Call the Solver*
-
- MicroPather* pather = new MicroPather( myGraph ); // Although you really should set the default params for your game.
-
- micropather::MPVector< void* > path;
- float totalCost = 0;
- int result = pather->Solve( startState, endState, &path, &totalCost );
-
-That's it. Given the start state and the end state, the sequence of states
-from start to end will be written to the vector.
-
-MicroPather does a lot of caching. You want to create one and keep in around.
-It will cache lots of information about your graph, and get faster as it is
-called. However, for caching to work, the connections between states and the
-costs of those connections must stay the same. (Else the cache information will
-be invalid.) If costs between connections does change, be sure to call Reset().
-
- pather->Reset();
-
-Reset() is a fast call if it doesn't need to do anything.
-
-Future Improvements and Social Coding
--------------------------------------
-
-I really like getting patches, improvements, and performance enhancements.
-Some guidelines:
-* Pull requests are the best way to send a change.
-* The "ease of use" goal is important to this project. It can be sped up by
- deeper integration into the client code (all states must subclass the State
- object, for example) but that dramatically reduces usability.
-
-Thanks for checking out MicroPather!
-
-Lee Thomason
-
\ No newline at end of file
diff --git a/external/MicroPather/reset0.gif b/external/MicroPather/reset0.gif
deleted file mode 100755
index 42e74168..00000000
Binary files a/external/MicroPather/reset0.gif and /dev/null differ
diff --git a/external/MicroPather/setversion.py b/external/MicroPather/setversion.py
deleted file mode 100755
index 4697063b..00000000
--- a/external/MicroPather/setversion.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# Python program to set the version.
-##############################################
-
-
-def fileProcess( name, lineFunction ):
- filestream = open( name, 'r' )
- if filestream.closed:
- print( "file " + name + " not open." )
- return
-
- output = ""
- print( "--- Processing " + name + " ---------" )
- while 1:
- line = filestream.readline()
- if not line: break
- output += lineFunction( line )
- filestream.close()
-
- if not output: return # basic error checking
-
- print( "Writing file " + name )
- filestream = open( name, "w" );
- filestream.write( output );
- filestream.close()
-
-
-def echoInput( line ):
- return line
-
-
-import sys
-major = input( "Major: " )
-minor = input( "Minor: " )
-build = input( "Build: " )
-
-print "Version: " + `major` + "." + `minor` + "." + `build`
-
-#### Write the buildlilith #####
-
-def buildlinuxRule( line ):
-
- i = line.rfind( "_" )
-
- if i >= 4 and line[i] == "_" and line[i-2] == "_" and line[i-4] == "_":
- # This is ghetto. Should really use regular expressions.
- i -= 4
- print "buildmicro instance found"
- return line[0:i] + "_" + `major` + "_" + `minor` + "_" + `build` + line[i+6:]
- else:
- return line
-
-fileProcess( "buildmicro", buildlinuxRule )
-
-
diff --git a/external/MicroPather/speed.cpp b/external/MicroPather/speed.cpp
deleted file mode 100755
index 2c7c312e..00000000
--- a/external/MicroPather/speed.cpp
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
-Copyright (c) 2000-2012 Lee Thomason (www.grinninglizard.com)
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any
-damages arising from the use of this software.
-
-Permission is granted to anyone to use this software for any
-purpose, including commercial applications, and to alter it and
-redistribute it freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must
-not claim that you wrote the original software. If you use this
-software in a product, an acknowledgment in the product documentation
-would be appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and
-must not be misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source
-distribution.
-*/
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#include "micropather.h"
-using namespace micropather;
-
-#ifdef _MSC_VER
-#include
-// The std::chronos high resolution clocks are no where near accurate enough on Windows 10.
-// Many calls come back at 0 time.
-typedef uint64_t TimePoint;
-
-inline uint64_t FastTime()
-{
- uint64_t t;
- QueryPerformanceCounter((LARGE_INTEGER*)&t);
- return t;
-}
-
-inline int64_t Nanoseconds(TimePoint start, TimePoint end)
-{
- uint64_t freq;
- QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
- return (end - start) * 1000 * 1000 * 1000 / freq;
-}
-#else
-typedef std::chrono::time_point TimePoint;
-
-inline TimePoint FastTime()
-{
- return std::chrono::high_resolution_clock::now();
-}
-
-inline int64_t Nanoseconds(TimePoint start, TimePoint end)
-{
- return std::chrono::duration_cast(end - start).count();
-}
-#endif
-
-
-const int MAPX = 90;
-const int MAPY = 20;
-const char gMap[MAPX*MAPY+1] =
- //"012345678901234567890123456789"
- " | | | | || | | | |"
- " | |----+ | + | ||---+ | + | |----+ | +"
- "---+ +--- -+ +--+--+ ---+ +--- -+| +--+--+ ---+ +--- -+ +--+--+ "
- " | +-- + | || +-- + | +-- +"
- " +----+ +---+ || +---+ +----+ +---+ "
- "---+ + + + | ---+ + | 2---+ + + + | "
- " | | +----+ +----+ +--+ | | || +----+ +--+322| | +----+ +----+ +--+"
- " | | | | || | | 222232 | | | "
- " | +-------+ +-+ |------------------+| +-+ |--+ 2223| +-------+ +-+ |--+ "
- "---+ | || | 222+---+ | +"
- " | | | || 22233| | | |"
- " | |----+ ++ ||---+3333| 22+ | |----+ | +"
- "---+ +--- -+ +--+-------------------||22223+--+--+ ---+ +--- -+ +--+--+ "
- " | +-- + | 22223333 +-- + | +-- +"
- " +----+ +---+ +---+| +---+ 222 +----+ +---+ "
- "---+ + + + | ---+ + + +| |222---+ + + + | "
- " | | +----+ +----+ +--+ | | +---+| 22+----+ +--+233|2| +----+ +----+ +--+"
- " | | | | ||2222| | 2223333| | | "
- " | +-------+ +-+ |--+ | +------++ +-+ |--+ |2+-------+ +-+ |--+ "
- "---+ | +---+ || | +---+ | ";
-
-class Dungeon : public Graph
-{
- public:
- MPVector path;
- MicroPather* aStar;
- int maxDir;
-
- Dungeon() {
- aStar = new MicroPather( this, MAPX*MAPY, 6 );
- maxDir = 4;
- }
-
- virtual ~Dungeon() {
- delete aStar;
- }
-
- int Passable( int nx, int ny )
- {
- if ( nx >= 0 && nx < MAPX
- && ny >= 0 && ny < MAPY )
- {
- int index = ny*MAPX+nx;
- char c = gMap[ index ];
- if ( c == ' ' )
- return 1;
- else if ( c >= '1' && c <= '9' ) {
- int val = c-'0';
- MPASSERT( val > 0 );
- return val;
- }
- }
- return 0;
- }
-
- void NodeToXY( void* node, int* x, int* y )
- {
- int index = (int)((intptr_t)node);
- *y = index / MAPX;
- *x = index - *y * MAPX;
- }
-
- void* XYToNode( int x, int y )
- {
- return (void*) ( y*MAPX + x );
- }
-
-
- virtual float LeastCostEstimate( void* nodeStart, void* nodeEnd )
- {
- int xStart, yStart, xEnd, yEnd;
- NodeToXY( nodeStart, &xStart, &yStart );
- NodeToXY( nodeEnd, &xEnd, &yEnd );
-
- int dx = xStart - xEnd;
- int dy = yStart - yEnd;
- return (float) sqrt( (double)(dx*dx) + (double)(dy*dy) );
- }
-
- virtual void AdjacentCost( void* node, MPVector< StateCost > *neighbors )
- {
- int x, y;
- // E N W S NE NW SW SE
- const int dx[8] = { 1, 0, -1, 0, 1, -1, -1, 1 };
- const int dy[8] = { 0, -1, 0, 1, -1, -1, 1, 1 };
- const float cost[8] = { 1.0f, 1.0f, 1.0f, 1.0f,
- 1.41f, 1.41f, 1.41f, 1.41f };
-
- NodeToXY( node, &x, &y );
-
- for( int i=0; i 0 ) {
- // Normal floor
- StateCost nodeCost = { XYToNode( nx, ny ), cost[i] * (float)(pass) };
- neighbors->push_back( nodeCost );
- }
- }
- }
-
- virtual void PrintStateInfo( void* node )
- {
- int x, y;
- NodeToXY( node, &x, &y );
- printf( "(%2d,%2d)", x, y );
- }
-
-};
-
-
-int main( int argc, const char* argv[] )
-{
- Dungeon dungeon;
-
- const int NUM_TEST = 389;
-
- int indexArray[ NUM_TEST ]; // a bunch of locations to go from-to
- float costArray[ NUM_TEST ];
- int64_t timeArray[ NUM_TEST ];
- int resultArray[ NUM_TEST ];
-
- bool useBinaryHash = false;
- bool useList = false;
- bool debug = false;
-
- #ifdef DEBUG
- debug = true;
- #endif
- #ifdef USE_BINARY_HASH
- useBinaryHash = true;
- #endif
- #ifdef USE_LIST
- useList = true;
- #endif
-
- printf( "SpeedTest binaryHash=%s list=%s debug=%s\n",
- useBinaryHash ? "true" : "false",
- useList ? "true" : "false",
- debug ? "true" : "false" );
-
- // Set up the test locations, making sure they
- // are all valid.
- for (int i = 0; i < NUM_TEST; ++i) {
- indexArray[i] = (MAPX*MAPY) * i / NUM_TEST;
- costArray[i] = 0.0f;
-
- int y = indexArray[i] / MAPX;
- int x = indexArray[i] - MAPX*y;
- while (!dungeon.Passable(x, y)) {
- indexArray[i] += 1;
- y = indexArray[i] / MAPX;
- x = indexArray[i] - MAPX*y;
- }
- }
- // Randomize the locations.
- for (int i = 0; i < NUM_TEST; ++i)
- {
- int swapWith = rand() % NUM_TEST;
- int temp = indexArray[i];
- indexArray[i] = indexArray[swapWith];
- indexArray[swapWith] = temp;
- }
-
- int64_t compositeScore = 0;
- for ( int numDir=4; numDir<=8; numDir+=4 )
- {
- dungeon.maxDir = numDir;
- dungeon.aStar->Reset();
-
- static const int SHORT_PATH = 0;
- static const int MED_PATH = 1;
- static const int LONG_PATH = 2;
- static const int FAIL_SHORT = 3;
- static const int FAIL_LONG = 4;
-
- for( int reset=0; reset<=1; ++reset )
- {
- TimePoint clockStart = FastTime();
- for( int i=0; iReset();
-
- int startState = indexArray[i];
- int endState = indexArray[ (i==(NUM_TEST-1)) ? 0 : i+1];
-
- TimePoint start = FastTime();
- resultArray[i] = dungeon.aStar->Solve( (void*)startState, (void*)endState, &dungeon.path, &costArray[i] );
- TimePoint end = FastTime();
-
- timeArray[i] = Nanoseconds(start, end);
- MPASSERT(timeArray[i]);
- }
- TimePoint clockEnd = FastTime();
-
- #ifndef PROFILING_RUN
- // -------- Results ------------ //
- const float shortPath = (float)(MAPX / 4);
- const float medPath = (float)(MAPX / 2 );
-
- int count[5] = { 0 }; // short, med, long, fail short, fail long
- int64_t time[5] = { 0 };
-
- for(int i=0; i
-
-
-
- Debug
- Win32
-
-
- Release
- Win32
-
-
-
-
-
-
-
-
-
-
- {C36D6BFA-8F57-483C-83FB-5BBBDF3F4036}
-
-
-
- Application
- false
- MultiByte
- v120
-
-
- Application
- false
- MultiByte
- v120
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.40219.1
- .\Debug\
- .\Debug\
- true
- .\Release\
- .\Release\
- false
-
-
-
- .\Debug/micropather.tlb
-
-
-
-
- Disabled
- WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
- true
- EnableFastChecks
- MultiThreadedDebug
- .\Debug/micropather.pch
- .\Debug/
- .\Debug/
- .\Debug/
- true
- Level3
- true
- EditAndContinue
-
-
- _DEBUG;%(PreprocessorDefinitions)
- 0x0409
-
-
- .\Debug/micropather.exe
- true
- true
- .\Debug/micropather.pdb
- Console
- false
-
-
- MachineX86
-
-
- true
- .\Debug/micropather.bsc
-
-
-
-
- .\Release/micropather.tlb
-
-
-
-
- MaxSpeed
- OnlyExplicitInline
- WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
- true
- MultiThreaded
- true
- .\Release/micropather.pch
- .\Release/
- .\Release/
- .\Release/
- Level3
- true
-
-
- NDEBUG;%(PreprocessorDefinitions)
- 0x0409
-
-
- .\Release/micropather.exe
- true
- .\Release/micropather.pdb
- Console
- false
-
-
- MachineX86
-
-
- true
- .\Release/micropather.bsc
-
-
-
-
-
-
\ No newline at end of file
diff --git a/external/MicroPather/visstudio/speed.vcxproj b/external/MicroPather/visstudio/speed.vcxproj
deleted file mode 100755
index 273fc814..00000000
--- a/external/MicroPather/visstudio/speed.vcxproj
+++ /dev/null
@@ -1,142 +0,0 @@
-
-
-
-
- Debug
- Win32
-
-
- Release
- Win32
-
-
-
-
-
-
-
-
-
-
- {6E0FBADD-648B-4FAF-93DB-29830058D935}
-
-
-
- Application
- false
- MultiByte
- v120
-
-
- Application
- false
- MultiByte
- v120
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.40219.1
- .\speed___Win32_Release\
- .\speed___Win32_Release\
- false
- .\speed___Win32_Debug\
- .\speed___Win32_Debug\
- true
-
-
-
- .\speed___Win32_Release/speed.tlb
-
-
-
-
- MaxSpeed
- OnlyExplicitInline
- WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
- true
- MultiThreaded
- true
- .\speed___Win32_Release/speed.pch
- .\speed___Win32_Release/
- .\speed___Win32_Release/
- .\speed___Win32_Release/
- Level3
- true
- ProgramDatabase
-
-
- NDEBUG;%(PreprocessorDefinitions)
- 0x0409
-
-
- .\speed___Win32_Release/speed.exe
- true
- true
- .\speed___Win32_Release/speed.pdb
- Console
- false
-
-
- MachineX86
-
-
- true
- .\speed___Win32_Release/speed.bsc
-
-
-
-
- .\speed___Win32_Debug/speed.tlb
-
-
-
-
- Disabled
- WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
- true
- EnableFastChecks
- MultiThreadedDebug
- .\speed___Win32_Debug/speed.pch
- .\speed___Win32_Debug/
- .\speed___Win32_Debug/
- .\speed___Win32_Debug/
- true
- Level3
- true
- EditAndContinue
-
-
- _DEBUG;%(PreprocessorDefinitions)
- 0x0409
-
-
- .\speed___Win32_Debug/speed.exe
- true
- true
- .\speed___Win32_Debug/speed.pdb
- Console
- false
-
-
- MachineX86
-
-
- true
- .\speed___Win32_Debug/speed.bsc
-
-
-
-
-
-
\ No newline at end of file
diff --git a/include/TF2_NavFile_Reader b/include/TF2_NavFile_Reader
new file mode 160000
index 00000000..d20b162b
--- /dev/null
+++ b/include/TF2_NavFile_Reader
@@ -0,0 +1 @@
+Subproject commit d20b162b0f5803414b0229180441137e7abf7f4f
diff --git a/include/TF2_NavFile_Reader/CMakeLists.txt b/include/TF2_NavFile_Reader/CMakeLists.txt
deleted file mode 100644
index 051f2c35..00000000
--- a/include/TF2_NavFile_Reader/CMakeLists.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-target_sources(cathook PRIVATE
- "${CMAKE_CURRENT_LIST_DIR}/astar.h"
- "${CMAKE_CURRENT_LIST_DIR}/CNavFile.h"
- "${CMAKE_CURRENT_LIST_DIR}/nav.h")
-
-target_include_directories(cathook PRIVATE "${CMAKE_CURRENT_LIST_DIR}")
diff --git a/include/TF2_NavFile_Reader/CNavFile.h b/include/TF2_NavFile_Reader/CNavFile.h
deleted file mode 100755
index 5f8a8b9d..00000000
--- a/include/TF2_NavFile_Reader/CNavFile.h
+++ /dev/null
@@ -1,267 +0,0 @@
-#pragma once
-
-#include "nav.h"
-#include
-
-class CNavFile
-{
-public:
- // Intended to use with engine->GetLevelName() or mapname from server_spawn
- // GameEvent Change it if you get the nav file from elsewhere
- CNavFile(const char *szLevelname)
- {
- if (!szLevelname)
- return;
-
- m_mapName = std::string("tf/");
- std::string map(szLevelname);
-
- if (map.find("maps/") == std::string::npos)
- m_mapName.append("maps/");
-
- m_mapName.append(szLevelname);
- int dotpos = m_mapName.find('.');
- m_mapName = m_mapName.substr(0, dotpos);
- m_mapName.append(".nav");
-
- std::ifstream fs(m_mapName, std::ios::binary);
-
- if (!fs.is_open())
- {
- //.nav file does not exist
- return;
- }
-
- uint32_t magic;
- fs.read((char *) &magic, sizeof(uint32_t));
-
- if (magic != 0xFEEDFACE)
- {
- // Wrong magic number
- return;
- }
-
- uint32_t version;
- fs.read((char *) &version, sizeof(uint32_t));
-
- if (version < 16) // 16 is latest for TF2
- {
- // Version is too old
- return;
- }
-
- uint32_t subVersion;
- fs.read((char *) &subVersion, sizeof(uint32_t));
-
- if (subVersion != 2) // 2 for TF2
- {
- // Not TF2 nav file
- return;
- }
-
- // We do not really need to check the size
- uint32_t bspSize;
- fs.read((char *) &bspSize, sizeof(uint32_t));
- fs.read((char *) &m_isAnalized, sizeof(unsigned char));
- uint16_t placeCount;
- fs.read((char *) &placeCount, sizeof(uint16_t));
-
- // TF2 does not use places, but in case they exist
- uint16_t len;
- for (int i = 0; i < placeCount; i++)
- {
- fs.read((char *) &len, sizeof(uint16_t));
-
- CNavPlace place;
-
- fs.read((char *) &place.m_name, len);
-
- m_places.push_back(place);
- }
-
- fs.read((char *) &m_hasUnnamedAreas, sizeof(unsigned char));
-
- uint32_t areaCount;
- fs.read((char *) &areaCount, sizeof(uint32_t));
-
- for (size_t i = 0; i < areaCount; i++)
- {
- CNavArea area;
- fs.read((char *) &area.m_id, sizeof(uint32_t));
- fs.read((char *) &area.m_attributeFlags, sizeof(uint32_t));
- fs.read((char *) &area.m_nwCorner, sizeof(Vector));
- fs.read((char *) &area.m_seCorner, sizeof(Vector));
- fs.read((char *) &area.m_neY, sizeof(float));
- fs.read((char *) &area.m_swY, sizeof(float));
-
- area.m_center[0] = (area.m_nwCorner[0] + area.m_seCorner[0]) / 2.0f;
- area.m_center[1] = (area.m_nwCorner[1] + area.m_seCorner[1]) / 2.0f;
- area.m_center[2] = (area.m_nwCorner[2] + area.m_seCorner[2]) / 2.0f;
-
- if ((area.m_seCorner.x - area.m_nwCorner.x) > 0.0f &&
- (area.m_seCorner.y - area.m_nwCorner.y) > 0.0f)
- {
- area.m_invDxCorners =
- 1.0f / (area.m_seCorner.x - area.m_nwCorner.x);
- area.m_invDzCorners =
- 1.0f / (area.m_seCorner.z - area.m_nwCorner.z);
- }
- else
- area.m_invDxCorners = area.m_invDzCorners = 0.0f;
-
- // Change the tolerance if you wish
- area.m_minZ = min(area.m_seCorner.z, area.m_nwCorner.z) - 18.f;
- area.m_maxZ = max(area.m_seCorner.z, area.m_nwCorner.z) + 18.f;
-
- for (int dir = 0; dir < NUM_DIRECTIONS; dir++)
- {
- uint32_t connectionCount;
- fs.read((char *) &connectionCount, sizeof(uint32_t));
-
- for (size_t j = 0; j < connectionCount; j++)
- {
- NavConnect connect;
-
- fs.read((char *) &connect.id, sizeof(uint32_t));
-
- // Connection to the same area?
- if (connect.id == area.m_id)
- continue;
-
- // Note: If connection directions matter to you, uncomment
- // this
- area.m_connections /*[dir]*/.push_back(connect);
- }
- }
-
- uint8_t hidingSpotCount;
- fs.read((char *) &hidingSpotCount, sizeof(uint8_t));
-
- for (size_t j = 0; j < hidingSpotCount; j++)
- {
- HidingSpot spot;
- fs.read((char *) &spot.m_id, sizeof(uint32_t));
- fs.read((char *) &spot.m_pos, sizeof(Vector));
- fs.read((char *) &spot.m_flags, sizeof(unsigned char));
-
- area.m_hidingSpots.push_back(spot);
- }
-
- fs.read((char *) &area.m_encounterSpotCount, sizeof(uint32_t));
-
- for (size_t j = 0; j < area.m_encounterSpotCount; j++)
- {
- SpotEncounter spot;
- fs.read((char *) &spot.from.id, sizeof(uint32_t));
- fs.read((char *) &spot.fromDir, sizeof(unsigned char));
- fs.read((char *) &spot.to.id, sizeof(uint32_t));
- fs.read((char *) &spot.toDir, sizeof(unsigned char));
-
- unsigned char spotcount;
- fs.read((char *) &spotcount, sizeof(unsigned char));
-
- for (int s = 0; s < spotcount; ++s)
- {
- SpotOrder order;
- fs.read((char *) &order.id, sizeof(uint32_t));
- fs.read((char *) &order.t, sizeof(unsigned char));
- spot.spots.push_back(order);
- }
-
- area.m_spotEncounters.push_back(spot);
- }
-
- fs.read((char *) &area.m_indexType, sizeof(uint16_t));
-
- // TF2 does not use ladders either
- for (int dir = 0; dir < NUM_LADDER_DIRECTIONS; dir++)
- {
- uint32_t laddercount;
- fs.read((char *) &laddercount, sizeof(uint32_t));
-
- for (size_t j = 0; j < laddercount; j++)
- {
- int temp;
- fs.read((char *) &temp, sizeof(uint32_t));
- }
- }
-
- for (int j = 0; j < MAX_NAV_TEAMS; j++)
- fs.read((char *) &area.m_earliestOccupyTime[j], sizeof(float));
-
- for (int j = 0; j < NUM_CORNERS; ++j)
- fs.read((char *) &area.m_lightIntensity[j], sizeof(float));
-
- fs.read((char *) &area.m_visibleAreaCount, sizeof(uint32_t));
-
- for (size_t j = 0; j < area.m_visibleAreaCount; ++j)
- {
- AreaBindInfo info;
- fs.read((char *) &info.id, sizeof(uint32_t));
- fs.read((char *) &info.attributes, sizeof(unsigned char));
-
- area.m_potentiallyVisibleAreas.push_back(info);
- }
-
- fs.read((char *) &area.m_inheritVisibilityFrom, sizeof(uint32_t));
-
- // Unknown 4 bytes
- uint32_t unk;
- fs.read((char *) &unk, sizeof(uint32_t));
-
- m_areas.push_back(area);
- }
-
- fs.close();
-
- // Fill connection for every area with their area ptrs instead of IDs
- // This will come in handy in path finding
-
- for (auto it = m_areas.begin(); it != m_areas.end(); it++)
- {
- CNavArea &area = *it;
-
- for (auto it2 = area.m_connections.begin();
- it2 != area.m_connections.end(); it2++)
- {
- NavConnect &connection = *it2;
-
- for (auto it3 = m_areas.begin(); it3 != m_areas.end(); it3++)
- {
- CNavArea &connectedarea = *it3;
-
- if (connection.id == connectedarea.m_id)
- {
- connection.area = &connectedarea;
- }
- }
- }
-
- // Fill potentially visible areas as well
- for (auto it2 = area.m_potentiallyVisibleAreas.begin();
- it2 != area.m_potentiallyVisibleAreas.end(); it2++)
- {
- AreaBindInfo &bindinfo = *it2;
-
- for (auto it3 = m_areas.begin(); it3 != m_areas.end(); it3++)
- {
- CNavArea &boundarea = *it3;
-
- if (bindinfo.id == boundarea.m_id)
- {
- bindinfo.area = &boundarea;
- }
- }
- }
- }
-
- m_isOK = true;
- }
-
- std::string m_mapName;
- bool m_isAnalized;
- std::vector m_places;
- bool m_hasUnnamedAreas;
- std::vector m_areas;
- bool m_isOK = false;
-};
diff --git a/include/TF2_NavFile_Reader/README.md b/include/TF2_NavFile_Reader/README.md
deleted file mode 100755
index ae1cabc1..00000000
--- a/include/TF2_NavFile_Reader/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-TF2 NavFile Reader
-
-How to use:
-
-1.) Include CNavFile.h
-
-2.) Instantiate CNavFile, map name argument in
-constructor is intended to work with level name from engine->GetLevelName() or with "mapname" string from "server_spawn" GameEvent
-
-3.) Check if m_isOK -> no errors while reading
-
-4.) Done!
-
-License: http://www.wtfpl.net/txt/copying/
-Credits: Source Engine SDK by Valve -> cool and good header files
diff --git a/include/TF2_NavFile_Reader/astar.h b/include/TF2_NavFile_Reader/astar.h
deleted file mode 100755
index 2a12acc6..00000000
--- a/include/TF2_NavFile_Reader/astar.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#pragma once
-
-#include "common.hpp"
-#include
-namespace nav {
- struct singleNode {
- typedef singleNode ThisClass;
- int id{-1};
- Vector pos;
- std::vector children;
-
- inline void addChildren(singleNode *node) {
- children.push_back(node);
- }
-
- inline std::vector FindPath(singleNode *goal) {
- std::vector ret;
- singleNode *node = nullptr;
- singleNode *target = this;
- for (int i = 0; i < 100; i++) {
- float bestscr = 99999999.0f;
- if (node) {
- if (node->id == goal->id)
- break;
- ret.push_back(node);
- }
- for (auto child : target->children) {
- bool rett = false;
- for (auto sub : ret) {
- if (sub->id == child->id) {
- rett = true;
- break;
- }
- }
- if (rett)
- continue;
- if (child->id == goal->id) {
- ret.push_back(child);
- node = child;
- target = child;
- break;
- }
- if (child->pos.DistTo(goal->pos) < bestscr) {
- bestscr = child->pos.DistTo(goal->pos);
- node = child;
- target = child;
- }
- }
- }
- return ret;
- }
- };
-}
\ No newline at end of file
diff --git a/include/TF2_NavFile_Reader/nav.h b/include/TF2_NavFile_Reader/nav.h
deleted file mode 100755
index e39213b8..00000000
--- a/include/TF2_NavFile_Reader/nav.h
+++ /dev/null
@@ -1,272 +0,0 @@
-#pragma once
-
-#include "common.hpp"
-
-struct SpotEncounter;
-
-class CNavPlace
-{
-public:
- char m_name[256];
-};
-
-enum NavDirType
-{
- NORTH = 0,
- EAST = 1,
- SOUTH = 2,
- WEST = 3,
-
- NUM_DIRECTIONS
-};
-
-enum
-{
- MAX_NAV_TEAMS = 2
-};
-
-/**
- * A HidingSpot is a good place for a bot to crouch and wait for enemies
- */
-class HidingSpot
-{
-public:
- enum
- {
- IN_COVER = 0x01, // in a corner with good hard cover nearby
- GOOD_SNIPER_SPOT = 0x02, // had at least one decent sniping corridor
- IDEAL_SNIPER_SPOT =
- 0x04, // can see either very far, or a large area, or both
- EXPOSED = 0x08 // spot in the open, usually on a ledge or cliff
- };
-
- bool HasGoodCover(void) const
- {
- return (m_flags & IN_COVER) ? true : false;
- } // return true if hiding spot in in cover
- bool IsGoodSniperSpot(void) const
- {
- return (m_flags & GOOD_SNIPER_SPOT) ? true : false;
- }
- bool IsIdealSniperSpot(void) const
- {
- return (m_flags & IDEAL_SNIPER_SPOT) ? true : false;
- }
- bool IsExposed(void) const
- {
- return (m_flags & EXPOSED) ? true : false;
- }
-
- Vector m_pos; // world coordinates of the spot
- unsigned int m_id; // this spot's unique ID
- unsigned char m_flags; // bit flags
-};
-
-class CNavArea;
-struct SpotEncounter;
-struct NavConnect;
-
-struct AreaBindInfo
-{
- union {
- CNavArea *area;
- unsigned int id = 0;
- };
-
- unsigned char attributes; // VisibilityType
-};
-
-enum NavAttributeType
-{
- NAV_MESH_INVALID = 0,
- NAV_MESH_CROUCH = 0x0000001, // must crouch to use this node/area
- NAV_MESH_JUMP = 0x0000002, // must jump to traverse this area (only used
- // during generation)
- NAV_MESH_PRECISE =
- 0x0000004, // do not adjust for obstacles, just move along area
- NAV_MESH_NO_JUMP = 0x0000008, // inhibit discontinuity jumping
- NAV_MESH_STOP = 0x0000010, // must stop when entering this area
- NAV_MESH_RUN = 0x0000020, // must run to traverse this area
- NAV_MESH_WALK = 0x0000040, // must walk to traverse this area
- NAV_MESH_AVOID =
- 0x0000080, // avoid this area unless alternatives are too dangerous
- NAV_MESH_TRANSIENT = 0x0000100, // area may become blocked, and should be
- // periodically checked
- NAV_MESH_DONT_HIDE =
- 0x0000200, // area should not be considered for hiding spot generation
- NAV_MESH_STAND = 0x0000400, // bots hiding in this area should stand
- NAV_MESH_NO_HOSTAGES = 0x0000800, // hostages shouldn't use this area
- NAV_MESH_STAIRS = 0x0001000, // this area represents stairs, do not attempt
- // to climb or jump them - just walk up
- NAV_MESH_NO_MERGE = 0x0002000, // don't merge this area with adjacent areas
- NAV_MESH_OBSTACLE_TOP =
- 0x0004000, // this nav area is the climb point on the tip of an obstacle
- NAV_MESH_CLIFF = 0x0008000, // this nav area is adjacent to a drop of at
- // least CliffHeight
-
- NAV_MESH_FIRST_CUSTOM = 0x00010000, // apps may define custom app-specific
- // bits starting with this value
- NAV_MESH_LAST_CUSTOM =
- 0x04000000, // apps must not define custom app-specific bits higher than
- // with this value
-
- NAV_MESH_HAS_ELEVATOR = 0x40000000, // area is in an elevator's path
- NAV_MESH_NAV_BLOCKER =
- 0x80000000, // area is blocked by nav blocker ( Alas, needed to hijack a
- // bit in the attributes to get within a cache line
- // [7/24/2008 tom])
-};
-
-enum NavTraverseType
-{
- // NOTE: First 4 directions MUST match NavDirType
- GO_NORTH = 0,
- GO_EAST,
- GO_SOUTH,
- GO_WEST,
-
- GO_LADDER_UP,
- GO_LADDER_DOWN,
- GO_JUMP,
- GO_ELEVATOR_UP,
- GO_ELEVATOR_DOWN,
-
- NUM_TRAVERSE_TYPES
-};
-
-enum NavCornerType
-{
- NORTH_WEST = 0,
- NORTH_EAST = 1,
- SOUTH_EAST = 2,
- SOUTH_WEST = 3,
-
- NUM_CORNERS
-};
-
-enum NavRelativeDirType
-{
- FORWARD = 0,
- RIGHT,
- BACKWARD,
- LEFT,
- UP,
- DOWN,
-
- NUM_RELATIVE_DIRECTIONS
-};
-
-enum LadderDirectionType
-{
- LADDER_UP = 0,
- LADDER_DOWN,
-
- NUM_LADDER_DIRECTIONS
-};
-
-class CNavArea
-{
-public:
- uint32_t m_id;
- int32_t m_attributeFlags;
- Vector m_nwCorner;
- Vector m_seCorner;
- Vector m_center;
- float m_invDzCorners;
- float m_invDxCorners;
- float m_neY;
- float m_swY;
- float m_minZ;
- float m_maxZ;
- std::vector m_connections;
- std::vector m_hidingSpots;
- std::vector m_spotEncounters;
- uint32_t m_encounterSpotCount;
- uint16_t m_indexType;
- float m_earliestOccupyTime[MAX_NAV_TEAMS];
- float m_lightIntensity[NUM_CORNERS];
- uint32_t m_visibleAreaCount;
- uint32_t m_inheritVisibilityFrom;
- std::vector m_potentiallyVisibleAreas;
-
- // Check if the given point is overlapping the area
- // @return True if 'pos' is within 2D extents of area.
- bool IsOverlapping(const Vector &vecPos, float flTolerance = 0)
- {
- if (vecPos.x + flTolerance < this->m_nwCorner.x)
- return false;
-
- if (vecPos.x - flTolerance > this->m_seCorner.x)
- return false;
-
- if (vecPos.y + flTolerance < this->m_nwCorner.y)
- return false;
-
- if (vecPos.y - flTolerance > this->m_seCorner.y)
- return false;
-
- return true;
- }
-
- // Check if the point is within the 3D bounds of this area
- bool Contains(Vector &vecPoint)
- {
- if (!IsOverlapping(vecPoint))
- return false;
-
- if (vecPoint.z > m_maxZ)
- return false;
-
- if (vecPoint.z < m_minZ)
- return false;
-
- return true;
- }
-};
-
-struct NavConnect
-{
- NavConnect()
- {
- id = 0;
- length = -1;
- }
-
- union {
- unsigned int id;
- CNavArea *area;
- };
-
- mutable float length;
-
- bool operator==(const NavConnect &other) const
- {
- return (area == other.area) ? true : false;
- }
-};
-
-struct SpotOrder
-{
- float t; // parametric distance along ray where this spot first has LOS to
- // our path
-
- union {
- HidingSpot *spot; // the spot to look at
- unsigned int id; // spot ID for save/load
- };
-};
-
-/**
- * This struct stores possible path segments thru a CNavArea, and the dangerous
- * spots to look at as we traverse that path segment.
- */
-struct SpotEncounter
-{
- NavConnect from;
- NavDirType fromDir;
- NavConnect to;
- NavDirType toDir;
- // Ray path; // the path segment
- std::vector
- spots; // list of spots to look at, in order of occurrence
-};