Fix submodules tf
This commit is contained in:
parent
35e307e1af
commit
fa0ba8d86b
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -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
|
||||
|
1
external/MicroPather
vendored
Submodule
1
external/MicroPather
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 33a3b8403f1bc3937c9d364fe6c3977169bee3b5
|
113
external/MicroPather/MakefileSpeed
vendored
113
external/MicroPather/MakefileSpeed
vendored
@ -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
|
BIN
external/MicroPather/demo0.gif
vendored
BIN
external/MicroPather/demo0.gif
vendored
Binary file not shown.
Before Width: | Height: | Size: 4.1 KiB |
BIN
external/MicroPather/demo0.png
vendored
BIN
external/MicroPather/demo0.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 34 KiB |
305
external/MicroPather/dungeon.cpp
vendored
305
external/MicroPather/dungeon.cpp
vendored
@ -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 <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#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<void*> 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<MAPY; ++j ) {
|
||||
// Copy in the line.
|
||||
memcpy( buf, &gMap[MAPX*j], MAPX+1 );
|
||||
buf[MAPX]=0;
|
||||
|
||||
#ifdef USE_PATHER
|
||||
unsigned k;
|
||||
// Wildly inefficient demo code.
|
||||
unsigned size = path.size();
|
||||
for( k=0; k<size; ++k ) {
|
||||
int x, y;
|
||||
NodeToXY( path[k], &x, &y );
|
||||
if ( y == j )
|
||||
buf[x] = '0' + k%10;
|
||||
}
|
||||
if ( showConsidered )
|
||||
{
|
||||
for( k=0; k<stateVec.size(); ++k ) {
|
||||
int x, y;
|
||||
NodeToXY( stateVec[k], &x, &y );
|
||||
if ( y == j )
|
||||
buf[x] = 'x';
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Insert the player
|
||||
if ( j==playerY )
|
||||
buf[playerX] = 'i';
|
||||
|
||||
printf( "%d%s\n", j%10, buf );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_PATHER
|
||||
|
||||
void NodeToXY( void* node, int* x, int* y )
|
||||
{
|
||||
intptr_t index = (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 );
|
||||
|
||||
/* Compute the minimum path cost using distance measurement. It is possible
|
||||
to compute the exact minimum path using the fact that you can move only
|
||||
on a straight line or on a diagonal, and this will yield a better result.
|
||||
*/
|
||||
int dx = xStart - xEnd;
|
||||
int dy = yStart - yEnd;
|
||||
return (float) sqrt( (double)(dx*dx) + (double)(dy*dy) );
|
||||
}
|
||||
|
||||
virtual void AdjacentCost( void* node, micropather::MPVector< StateCost > *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;
|
||||
}
|
1078
external/MicroPather/micropather.cpp
vendored
1078
external/MicroPather/micropather.cpp
vendored
File diff suppressed because it is too large
Load Diff
509
external/MicroPather/micropather.h
vendored
509
external/MicroPather/micropather.h
vendored
@ -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 <vector>
|
||||
# define MP_VECTOR std::vector
|
||||
#endif
|
||||
#include <float.h>
|
||||
|
||||
#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 <android/log.h>
|
||||
# define MPASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
|
||||
# else
|
||||
# include <assert.h>
|
||||
# define MPASSERT assert
|
||||
# endif
|
||||
# else
|
||||
# define MPASSERT( x ) {}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
|
||||
#include <stdlib.h>
|
||||
typedef uintptr_t MP_UPTR;
|
||||
#elif defined (__GNUC__) && (__GNUC__ >= 3 )
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
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 <typename T>
|
||||
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<m_size );
|
||||
return m_buf[i];
|
||||
}
|
||||
const T& operator[](unsigned i) const { MPASSERT( i>=0 && i<m_size );
|
||||
return m_buf[i];
|
||||
}
|
||||
void push_back( const T& t ) { capacity( m_size+1 );
|
||||
m_buf[m_size++] = t;
|
||||
}
|
||||
unsigned size() const { return m_size; }
|
||||
|
||||
private:
|
||||
void capacity( unsigned cap ) {
|
||||
if ( m_allocated < cap ) {
|
||||
unsigned newAllocated = cap * 3/2 + 16;
|
||||
T* newBuf = new T[newAllocated];
|
||||
MPASSERT( m_size <= m_allocated );
|
||||
MPASSERT( m_size < newAllocated );
|
||||
memcpy( newBuf, m_buf, sizeof(T)*m_size );
|
||||
delete [] m_buf;
|
||||
m_buf = newBuf;
|
||||
m_allocated = newAllocated;
|
||||
}
|
||||
}
|
||||
unsigned m_allocated;
|
||||
unsigned m_size;
|
||||
T* m_buf;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
Used to pass the cost of states from the cliet application to MicroPather. This
|
||||
structure is copied in a vector.
|
||||
|
||||
@sa AdjacentCost
|
||||
*/
|
||||
struct StateCost
|
||||
{
|
||||
void* state; ///< The state as a void*
|
||||
float cost; ///< The cost to the state. Use FLT_MAX for infinite cost.
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
A pure abstract class used to define a set of callbacks.
|
||||
The client application inherits from
|
||||
this class, and the methods will be called when MicroPather::Solve() is invoked.
|
||||
|
||||
The notion of a "state" is very important. It must have the following properties:
|
||||
- Unique
|
||||
- Unchanging (unless MicroPather::Reset() is called)
|
||||
|
||||
If the client application represents states as objects, then the state is usually
|
||||
just the object cast to a void*. If the client application sees states as numerical
|
||||
values, (x,y) for example, then state is an encoding of these values. MicroPather
|
||||
never interprets or modifies the value of state.
|
||||
*/
|
||||
class Graph
|
||||
{
|
||||
public:
|
||||
virtual ~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;
|
||||
};
|
||||
|
||||
|
||||
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<<hashShift; }
|
||||
unsigned HashMask() const { return ((1<<hashShift)-1); }
|
||||
void AddPathNode( unsigned key, PathNode* p );
|
||||
Block* NewBlock();
|
||||
PathNode* Alloc();
|
||||
|
||||
PathNode** hashTable;
|
||||
Block* firstBlock;
|
||||
Block* blocks;
|
||||
|
||||
NodeCost* cache;
|
||||
int cacheCap;
|
||||
int cacheSize;
|
||||
|
||||
PathNode freeMemSentinel;
|
||||
unsigned allocate; // how big a block of pathnodes to allocate at once
|
||||
unsigned nAllocated; // number of pathnodes allocated (from Alloc())
|
||||
unsigned nAvailable; // number available for allocation
|
||||
|
||||
unsigned hashShift;
|
||||
unsigned totalCollide;
|
||||
};
|
||||
|
||||
|
||||
/* Used to cache results of paths. Much, much faster
|
||||
to return an existing solution than to calculate
|
||||
a new one. A post on this is here: http://grinninglizard.com/altera/programming/a-path-caching-2/
|
||||
*/
|
||||
class PathCache
|
||||
{
|
||||
public:
|
||||
struct Item {
|
||||
// The key:
|
||||
void* start;
|
||||
void* end;
|
||||
|
||||
bool KeyEqual( const Item& item ) const { return start == item.start && end == item.end; }
|
||||
bool Empty() const { return start == 0 && end == 0; }
|
||||
|
||||
// Data:
|
||||
void* next;
|
||||
float cost; // from 'start' to 'next'. FLT_MAX if unsolveable.
|
||||
|
||||
unsigned Hash() const {
|
||||
const unsigned char *p = (const unsigned char *)(&start);
|
||||
unsigned int h = 2166136261U;
|
||||
|
||||
for( unsigned i=0; i<sizeof(void*)*2; ++i, ++p ) {
|
||||
h ^= *p;
|
||||
h *= 16777619;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
PathCache( int itemsToAllocate );
|
||||
~PathCache();
|
||||
|
||||
void Reset();
|
||||
void Add( const MP_VECTOR< void* >& 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
|
||||
|
181
external/MicroPather/readme.md
vendored
181
external/MicroPather/readme.md
vendored
@ -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</p>
|
||||
2. Implement the Graph interface</p>
|
||||
3. Call the Solver</p>
|
||||
|
||||
*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
|
||||
|
BIN
external/MicroPather/reset0.gif
vendored
BIN
external/MicroPather/reset0.gif
vendored
Binary file not shown.
Before Width: | Height: | Size: 2.9 KiB |
54
external/MicroPather/setversion.py
vendored
54
external/MicroPather/setversion.py
vendored
@ -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 )
|
||||
|
||||
|
339
external/MicroPather/speed.cpp
vendored
339
external/MicroPather/speed.cpp
vendored
@ -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 <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
|
||||
#include "micropather.h"
|
||||
using namespace micropather;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <Windows.h>
|
||||
// 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<std::chrono::high_resolution_clock> TimePoint;
|
||||
|
||||
inline TimePoint FastTime()
|
||||
{
|
||||
return std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
inline int64_t Nanoseconds(TimePoint start, TimePoint end)
|
||||
{
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(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<void*> 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<maxDir; ++i ) {
|
||||
int nx = x + dx[i];
|
||||
int ny = y + dy[i];
|
||||
|
||||
int pass = Passable( nx, ny );
|
||||
if ( pass > 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; i<NUM_TEST; ++i )
|
||||
{
|
||||
if ( reset )
|
||||
dungeon.aStar->Reset();
|
||||
|
||||
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<NUM_TEST; ++i )
|
||||
{
|
||||
int idx = 0;
|
||||
if ( resultArray[i] == MicroPather::SOLVED ) {
|
||||
if ( costArray[i] < shortPath ) {
|
||||
idx = SHORT_PATH;
|
||||
}
|
||||
else if ( costArray[i] < medPath ) {
|
||||
idx = MED_PATH;
|
||||
}
|
||||
else {
|
||||
idx = LONG_PATH;
|
||||
}
|
||||
}
|
||||
else if ( resultArray[i] == MicroPather::NO_SOLUTION ) {
|
||||
int startState = indexArray[i];
|
||||
int endState = indexArray[ (i==(NUM_TEST-1)) ? 0 : i+1];
|
||||
int startX, startY, endX, endY;
|
||||
dungeon.NodeToXY( (void*)startState, &startX, &startY );
|
||||
dungeon.NodeToXY( (void*)endState, &endX, &endY );
|
||||
|
||||
int distance = abs( startX - endX ) + abs( startY - endY );
|
||||
|
||||
if ( distance < shortPath ) {
|
||||
idx = FAIL_SHORT;
|
||||
}
|
||||
else {
|
||||
idx = FAIL_LONG;
|
||||
}
|
||||
}
|
||||
count[idx] += 1;
|
||||
time[idx] += timeArray[i];
|
||||
}
|
||||
|
||||
printf( "Average of %d runs. Reset=%s. Dir=%d.\n",
|
||||
NUM_TEST, reset ? "true" : "false", numDir );
|
||||
printf( "short(%4d) = %7.2f\n", count[0], double(time[0]) / count[0] * 0.001 );
|
||||
printf( "med (%4d) = %7.2f\n", count[1], double(time[1]) / count[1] * 0.001 );
|
||||
printf( "long (%4d) = %7.2f\n", count[2], double(time[2]) / count[2] * 0.001 );
|
||||
printf( "fail short (%4d) = %7.2f\n", count[3], double(time[3]) / count[3] * 0.001 );
|
||||
printf( "fail long (%4d) = %7.2f\n", count[4], double(time[4]) / count[4] * 0.001 );
|
||||
|
||||
int64_t totalTime = 0;
|
||||
int totalCount = 0;
|
||||
for( int k=0; k<5; ++k ) {
|
||||
totalTime += time[k];
|
||||
totalCount += count[k];
|
||||
}
|
||||
printf( "Average = %7.2f\n", double(totalTime) / totalCount * 0.001 );
|
||||
compositeScore += totalTime / totalCount;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
printf( "Composite average = %7.2f\n", double(compositeScore) / 4 * 0.001);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
30
external/MicroPather/speed.txt
vendored
30
external/MicroPather/speed.txt
vendored
@ -1,30 +0,0 @@
|
||||
SpeedTest binaryHash=false list=false debug=false
|
||||
Average of 389 runs. Reset=false. Dir=4.
|
||||
short( 85, cutoff=22.0)= 31
|
||||
med ( 119, cutoff=45.0)= 121
|
||||
long ( 146) = 354
|
||||
fail ( 13) short = 406
|
||||
fail ( 26) long = 469
|
||||
Average = 276
|
||||
Average of 389 runs. Reset=true. Dir=4.
|
||||
short( 85, cutoff=22.0)= 26
|
||||
med ( 119, cutoff=45.0)= 102
|
||||
long ( 146) = 325
|
||||
fail ( 13) short = 432
|
||||
fail ( 26) long = 495
|
||||
Average = 276
|
||||
Average of 389 runs. Reset=false. Dir=8.
|
||||
short( 113, cutoff=22.0)= 27
|
||||
med ( 124, cutoff=45.0)= 103
|
||||
long ( 113) = 268
|
||||
fail ( 13) short = 452
|
||||
fail ( 26) long = 503
|
||||
Average = 270
|
||||
Average of 389 runs. Reset=true. Dir=8.
|
||||
short( 113, cutoff=22.0)= 38
|
||||
med ( 124, cutoff=45.0)= 157
|
||||
long ( 113) = 430
|
||||
fail ( 13) short = 675
|
||||
fail ( 26) long = 688
|
||||
Average = 397
|
||||
Composite average = 305
|
26
external/MicroPather/visstudio/micropather.sln
vendored
26
external/MicroPather/visstudio/micropather.sln
vendored
@ -1,26 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual C++ Express 2010
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "micropather", "micropather.vcxproj", "{C36D6BFA-8F57-483C-83FB-5BBBDF3F4036}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "speed", "speed.vcxproj", "{6E0FBADD-648B-4FAF-93DB-29830058D935}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C36D6BFA-8F57-483C-83FB-5BBBDF3F4036}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{C36D6BFA-8F57-483C-83FB-5BBBDF3F4036}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{C36D6BFA-8F57-483C-83FB-5BBBDF3F4036}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{C36D6BFA-8F57-483C-83FB-5BBBDF3F4036}.Release|Win32.Build.0 = Release|Win32
|
||||
{6E0FBADD-648B-4FAF-93DB-29830058D935}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6E0FBADD-648B-4FAF-93DB-29830058D935}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6E0FBADD-648B-4FAF-93DB-29830058D935}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6E0FBADD-648B-4FAF-93DB-29830058D935}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
140
external/MicroPather/visstudio/micropather.vcxproj
vendored
140
external/MicroPather/visstudio/micropather.vcxproj
vendored
@ -1,140 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\dungeon.cpp" />
|
||||
<ClCompile Include="..\micropather.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\micropather.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{C36D6BFA-8F57-483C-83FB-5BBBDF3F4036}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Midl>
|
||||
<TypeLibraryName>.\Debug/micropather.tlb</TypeLibraryName>
|
||||
<HeaderFileName>
|
||||
</HeaderFileName>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PrecompiledHeaderOutputFile>.\Debug/micropather.pch</PrecompiledHeaderOutputFile>
|
||||
<AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
|
||||
<ObjectFileName>.\Debug/</ObjectFileName>
|
||||
<ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
|
||||
<BrowseInformation>true</BrowseInformation>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0409</Culture>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<OutputFile>.\Debug/micropather.exe</OutputFile>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>.\Debug/micropather.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
<Bscmake>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>.\Debug/micropather.bsc</OutputFile>
|
||||
</Bscmake>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Midl>
|
||||
<TypeLibraryName>.\Release/micropather.tlb</TypeLibraryName>
|
||||
<HeaderFileName>
|
||||
</HeaderFileName>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeaderOutputFile>.\Release/micropather.pch</PrecompiledHeaderOutputFile>
|
||||
<AssemblerListingLocation>.\Release/</AssemblerListingLocation>
|
||||
<ObjectFileName>.\Release/</ObjectFileName>
|
||||
<ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0409</Culture>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<OutputFile>.\Release/micropather.exe</OutputFile>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<ProgramDatabaseFile>.\Release/micropather.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
<Bscmake>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>.\Release/micropather.bsc</OutputFile>
|
||||
</Bscmake>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
142
external/MicroPather/visstudio/speed.vcxproj
vendored
142
external/MicroPather/visstudio/speed.vcxproj
vendored
@ -1,142 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\micropather.cpp" />
|
||||
<ClCompile Include="..\speed.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\micropather.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{6E0FBADD-648B-4FAF-93DB-29830058D935}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\speed___Win32_Release\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\speed___Win32_Release\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\speed___Win32_Debug\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\speed___Win32_Debug\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Midl>
|
||||
<TypeLibraryName>.\speed___Win32_Release/speed.tlb</TypeLibraryName>
|
||||
<HeaderFileName>
|
||||
</HeaderFileName>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeaderOutputFile>.\speed___Win32_Release/speed.pch</PrecompiledHeaderOutputFile>
|
||||
<AssemblerListingLocation>.\speed___Win32_Release/</AssemblerListingLocation>
|
||||
<ObjectFileName>.\speed___Win32_Release/</ObjectFileName>
|
||||
<ProgramDataBaseFileName>.\speed___Win32_Release/</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0409</Culture>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<OutputFile>.\speed___Win32_Release/speed.exe</OutputFile>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>.\speed___Win32_Release/speed.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
<Bscmake>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>.\speed___Win32_Release/speed.bsc</OutputFile>
|
||||
</Bscmake>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Midl>
|
||||
<TypeLibraryName>.\speed___Win32_Debug/speed.tlb</TypeLibraryName>
|
||||
<HeaderFileName>
|
||||
</HeaderFileName>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PrecompiledHeaderOutputFile>.\speed___Win32_Debug/speed.pch</PrecompiledHeaderOutputFile>
|
||||
<AssemblerListingLocation>.\speed___Win32_Debug/</AssemblerListingLocation>
|
||||
<ObjectFileName>.\speed___Win32_Debug/</ObjectFileName>
|
||||
<ProgramDataBaseFileName>.\speed___Win32_Debug/</ProgramDataBaseFileName>
|
||||
<BrowseInformation>true</BrowseInformation>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Culture>0x0409</Culture>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<OutputFile>.\speed___Win32_Debug/speed.exe</OutputFile>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>.\speed___Win32_Debug/speed.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
<Bscmake>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<OutputFile>.\speed___Win32_Debug/speed.bsc</OutputFile>
|
||||
</Bscmake>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
1
include/TF2_NavFile_Reader
Submodule
1
include/TF2_NavFile_Reader
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit d20b162b0f5803414b0229180441137e7abf7f4f
|
@ -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}")
|
@ -1,267 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "nav.h"
|
||||
#include <fstream>
|
||||
|
||||
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<CNavPlace> m_places;
|
||||
bool m_hasUnnamedAreas;
|
||||
std::vector<CNavArea> m_areas;
|
||||
bool m_isOK = false;
|
||||
};
|
@ -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
|
@ -1,53 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.hpp"
|
||||
#include <vector>
|
||||
namespace nav {
|
||||
struct singleNode {
|
||||
typedef singleNode ThisClass;
|
||||
int id{-1};
|
||||
Vector pos;
|
||||
std::vector<singleNode *> children;
|
||||
|
||||
inline void addChildren(singleNode *node) {
|
||||
children.push_back(node);
|
||||
}
|
||||
|
||||
inline std::vector<singleNode *> FindPath(singleNode *goal) {
|
||||
std::vector<singleNode *> 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;
|
||||
}
|
||||
};
|
||||
}
|
@ -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<NavConnect> m_connections;
|
||||
std::vector<HidingSpot> m_hidingSpots;
|
||||
std::vector<SpotEncounter> 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<AreaBindInfo> 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<SpotOrder>
|
||||
spots; // list of spots to look at, in order of occurrence
|
||||
};
|
Reference in New Issue
Block a user