00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef GRINNINGLIZARD_MICROPATHER_INCLUDED
00027 #define GRINNINGLIZARD_MICROPATHER_INCLUDED
00028
00029
00041 #include <vector>
00042 #include <float.h>
00043
00044 #ifdef _DEBUG
00045 #ifndef DEBUG
00046 #define DEBUG
00047 #endif
00048 #endif
00049
00050
00051 #if defined( _DEBUG )
00052 # if defined( _MSC_VER )
00053 # define MPASSERT( x ) if ( !(x)) { _asm { int 3 } }
00054 # else
00055 # include <assert.h>
00056 # define MPASSERT assert
00057 # endif
00058 #else
00059 # define MPASSERT( x ) {}
00060 #endif
00061
00062
00063 #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
00064 #include <stdlib.h>
00065 typedef uintptr_t MP_UPTR;
00066 #elif defined (__GNUC__) && (__GNUC__ >= 3 )
00067 #include <stdlib.h>
00068 typedef uintptr_t MP_UPTR;
00069 #else
00070
00071 typedef unsigned MP_UPTR;
00072 #endif
00073
00074
00075
00076 namespace micropather
00077 {
00084 struct StateCost
00085 {
00086 void* state;
00087 float cost;
00088 };
00089
00090
00105 class Graph
00106 {
00107 public:
00108 virtual ~Graph() {}
00109
00116 virtual float LeastCostEstimate( void* stateStart, void* stateEnd ) = 0;
00117
00124 virtual void AdjacentCost( void* state, std::vector< micropather::StateCost > *adjacent ) = 0;
00125
00131 virtual void PrintStateInfo( void* state ) = 0;
00132 };
00133
00134
00135 class PathNode;
00136
00137 struct NodeCost
00138 {
00139 PathNode* node;
00140 float cost;
00141 };
00142
00143
00144
00145
00146
00147
00148 class PathNode
00149 {
00150 public:
00151 void Init( unsigned _frame,
00152 void* _state,
00153 float _costFromStart,
00154 float _estToGoal,
00155 PathNode* _parent );
00156
00157 void Clear() {
00158 memset( this, 0, sizeof( PathNode ) );
00159 numAdjacent = -1;
00160 cacheIndex = -1;
00161 }
00162 void InitSentinel() {
00163 Clear();
00164 Init( 0, 0, FLT_MAX, FLT_MAX, 0 );
00165 prev = next = this;
00166 }
00167
00168 void *state;
00169 float costFromStart;
00170 float estToGoal;
00171 float totalCost;
00172 PathNode* parent;
00173 unsigned frame;
00174
00175
00176 int numAdjacent;
00177 int cacheIndex;
00178
00179 PathNode *child[2];
00180 PathNode *next, *prev;
00181
00182 bool inOpen;
00183 bool inClosed;
00184
00185 void Unlink() {
00186 next->prev = prev;
00187 prev->next = next;
00188 next = prev = 0;
00189 }
00190 void AddBefore( PathNode* addThis ) {
00191 addThis->next = this;
00192 addThis->prev = prev;
00193 prev->next = addThis;
00194 prev = addThis;
00195 }
00196 #ifdef DEBUG
00197 void CheckList()
00198 {
00199 MPASSERT( totalCost == FLT_MAX );
00200 for( PathNode* it = next; it != this; it=it->next ) {
00201 MPASSERT( it->prev == this || it->totalCost >= it->prev->totalCost );
00202 MPASSERT( it->totalCost <= it->next->totalCost );
00203 }
00204 }
00205 #endif
00206
00207 void CalcTotalCost() {
00208 if ( costFromStart < FLT_MAX && estToGoal < FLT_MAX )
00209 totalCost = costFromStart + estToGoal;
00210 else
00211 totalCost = FLT_MAX;
00212 }
00213
00214 private:
00215
00216 void operator=( const PathNode& );
00217 };
00218
00219
00220
00221 class PathNodePool
00222 {
00223 public:
00224 PathNodePool( unsigned allocate, unsigned typicalAdjacent );
00225 ~PathNodePool();
00226
00227
00228 void Clear();
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 PathNode* GetPathNode( unsigned frame,
00243 void* _state,
00244 float _costFromStart,
00245 float _estToGoal,
00246 PathNode* _parent );
00247
00248
00249 bool PushCache( const NodeCost* nodes, int nNodes, int* start );
00250
00251
00252
00253 void GetCache( int start, int nNodes, NodeCost* nodes ) {
00254 MPASSERT( start >= 0 && start < cacheCap );
00255 MPASSERT( nNodes > 0 );
00256 MPASSERT( start + nNodes <= cacheCap );
00257 memcpy( nodes, &cache[start], sizeof(NodeCost)*nNodes );
00258 }
00259
00260
00261
00262 void AllStates( unsigned frame, std::vector< void* >* stateVec );
00263
00264 private:
00265 struct Block
00266 {
00267 Block* nextBlock;
00268 PathNode pathNode[1];
00269 };
00270
00271 unsigned Hash( void* voidval );
00272 unsigned HashSize() const { return 1<<hashShift; }
00273 unsigned HashMask() const { return ((1<<hashShift)-1); }
00274 void AddPathNode( unsigned key, PathNode* p );
00275 Block* NewBlock();
00276 PathNode* Alloc();
00277
00278 PathNode** hashTable;
00279 Block* firstBlock;
00280 Block* blocks;
00281
00282 NodeCost* cache;
00283 int cacheCap;
00284 int cacheSize;
00285
00286 PathNode freeMemSentinel;
00287 unsigned allocate;
00288 unsigned nAllocated;
00289 unsigned nAvailable;
00290
00291 unsigned hashShift;
00292 unsigned totalCollide;
00293 };
00294
00295
00300 class MicroPather
00301 {
00302 friend class micropather::PathNode;
00303
00304 public:
00305 enum
00306 {
00307 SOLVED,
00308 NO_SOLUTION,
00309 START_END_SAME,
00310 };
00311
00333 MicroPather( Graph* graph, unsigned allocate = 250, unsigned typicalAdjacent=6 );
00334 ~MicroPather();
00335
00345 int Solve( void* startState, void* endState, std::vector< void* >* path, float* totalCost );
00346
00356 int SolveForNearStates( void* startState, std::vector< StateCost >* near, float maxCost );
00357
00361 void Reset();
00362
00367 MP_UPTR Checksum() { return checksum; }
00368
00369
00370 void StatesInPool( std::vector< void* >* stateVec );
00371
00372 private:
00373 MicroPather( const MicroPather& );
00374 void operator=( const MicroPather );
00375
00376 void GoalReached( PathNode* node, void* start, void* end, std::vector< void* > *path );
00377
00378 void GetNodeNeighbors( PathNode* node, std::vector< NodeCost >* neighborNode );
00379
00380 #ifdef DEBUG
00381
00382 #endif
00383
00384 PathNodePool pathNodePool;
00385 std::vector< StateCost > stateCostVec;
00386 std::vector< NodeCost > nodeCostVec;
00387
00388 Graph* graph;
00389 unsigned frame;
00390 MP_UPTR checksum;
00391
00392 };
00393 };
00394
00395 #endif
00396