micropather.h

00001 /*
00002 Copyright (c) 2000-2009 Lee Thomason (www.grinninglizard.com)
00003 Grinning Lizard Utilities.
00004 
00005 This software is provided 'as-is', without any express or implied 
00006 warranty. In no event will the authors be held liable for any 
00007 damages arising from the use of this software.
00008 
00009 Permission is granted to anyone to use this software for any 
00010 purpose, including commercial applications, and to alter it and 
00011 redistribute it freely, subject to the following restrictions:
00012 
00013 1. The origin of this software must not be misrepresented; you must 
00014 not claim that you wrote the original software. If you use this 
00015 software in a product, an acknowledgment in the product documentation 
00016 would be appreciated but is not required.
00017 
00018 2. Altered source versions must be plainly marked as such, and 
00019 must not be misrepresented as being the original software.
00020 
00021 3. This notice may not be removed or altered from any source 
00022 distribution.
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     // Assume not 64 bit pointers. Get a new compiler.
00071     typedef unsigned MP_UPTR;
00072 #endif
00073 
00074 //#define MICROPATHER_STRESS
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         Every state (void*) is represented by a PathNode in MicroPather. There
00146         can only be one PathNode for a given state.
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;            // the client state
00169         float costFromStart;    // exact
00170         float estToGoal;        // estimated
00171         float totalCost;        // could be a function, but save some math.
00172         PathNode* parent;       // the parent is used to reconstruct the path
00173         unsigned frame;         // unique id for this path, so the solver can distinguish
00174                                 // correct from stale values
00175 
00176         int numAdjacent;        // -1  is unknown & needs to be queried
00177         int cacheIndex;         // position in cache
00178 
00179         PathNode *child[2];     // Binary search in the hash table. [left, right]
00180         PathNode *next, *prev;  // used by open queue
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     /* Memory manager for the PathNodes. */
00221     class PathNodePool
00222     {
00223     public:
00224         PathNodePool( unsigned allocate, unsigned typicalAdjacent );
00225         ~PathNodePool();
00226 
00227         // Free all the memory except the first block. Resets all memory.
00228         void Clear();
00229 
00230         // Essentially:
00231         // pNode = Find();
00232         // if ( !pNode )
00233         //      pNode = New();
00234         //
00235         // Get the PathNode associated with this state. If the PathNode already
00236         // exists (allocated and is on the current frame), it will be returned. 
00237         // Else a new PathNode is allocated and returned. The returned object
00238         // is always fully initialized.
00239         //
00240         // NOTE: if the pathNode exists (and is current) all the initialization
00241         //       parameters are ignored.
00242         PathNode* GetPathNode(      unsigned frame,
00243                                     void* _state,
00244                                     float _costFromStart, 
00245                                     float _estToGoal, 
00246                                     PathNode* _parent );
00247 
00248         // Store stuff in cache
00249         bool PushCache( const NodeCost* nodes, int nNodes, int* start );
00250 
00251         // Get neighbors from the cache
00252         // Note - always access this with an offset. Can get re-allocated.
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         // Return all the allocated states. Useful for visuallizing what
00261         // the pather is doing.
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;               // how big a block of pathnodes to allocate at once
00288         unsigned    nAllocated;             // number of pathnodes allocated (from Alloc())
00289         unsigned    nAvailable;             // number available for allocation
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         // Debugging function to return all states that were used by the last "solve" 
00370         void StatesInPool( std::vector< void* >* stateVec );
00371 
00372       private:
00373         MicroPather( const MicroPather& );  // undefined and unsupported
00374         void operator=( const MicroPather ); // undefined and unsupported
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         //void DumpStats();
00382         #endif
00383 
00384         PathNodePool                pathNodePool;
00385         std::vector< StateCost >    stateCostVec;   // local to Solve, but put here to reduce memory allocation
00386         std::vector< NodeCost >     nodeCostVec;    // local to Solve, but put here to reduce memory allocation
00387 
00388         Graph* graph;
00389         unsigned frame;                     // incremented with every solve, used to determine if cached data needs to be refreshed
00390         MP_UPTR checksum;                       // the checksum of the last successful "Solve".
00391         
00392     };
00393 };  // namespace grinliz
00394 
00395 #endif
00396 

Generated on Sun Dec 6 09:25:42 2009 for MicroPather by  doxygen 1.5.1-p1