ScummVM API documentation
micropather.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 /*
23 
24 This is a lightly modified version of MicroPather, from
25 github.com/leethomason/MicroPather. Modifications were made to fit with
26 ScummVM coding style and APIs.
27 
28 The original copyright message is:
29 
30 -------
31 
32 Copyright (c) 2000-2013 Lee Thomason (www.grinninglizard.com)
33 Micropather
34 
35 This software is provided 'as-is', without any express or implied
36 warranty. In no event will the authors be held liable for any
37 damages arising from the use of this software.
38 
39 Permission is granted to anyone to use this software for any
40 purpose, including commercial applications, and to alter it and
41 redistribute it freely, subject to the following restrictions:
42 
43 1. The origin of this software must not be misrepresented; you must
44 not claim that you wrote the original software. If you use this
45 software in a product, an acknowledgment in the product documentation
46 would be appreciated but is not required.
47 
48 2. Altered source versions must be plainly marked as such, and
49 must not be misrepresented as being the original software.
50 
51 3. This notice may not be removed or altered from any source
52 distribution.
53 */
54 
55 
56 #ifndef TETRAEDGE_TE_MICROPATHER
57 #define TETRAEDGE_TE_MICROPATHER
58 
59 #include "common/array.h"
60 #include "common/util.h"
61 #include "common/types.h"
62 #include "math/utils.h"
63 
64 
73 namespace Tetraedge
74 {
75 
76 namespace micropather
77 {
78 
79  typedef uintptr MP_UPTR;
80 
87  struct StateCost
88  {
89  void* state;
90  float cost;
91  };
92 
93 
108  class Graph
109  {
110  public:
111  virtual ~Graph() {}
112 
119  virtual float LeastCostEstimate( void* stateStart, void* stateEnd ) = 0;
120 
127  virtual void AdjacentCost( void* state, Common::Array< micropather::StateCost > *adjacent ) = 0;
128 
134  virtual void PrintStateInfo( void* state ) = 0;
135  };
136 
137 
138  class PathNode;
139 
140  struct NodeCost
141  {
142  PathNode* node;
143  float cost;
144  };
145 
146 
147  /*
148  Every state (void*) is represented by a PathNode in MicroPather. There
149  can only be one PathNode for a given state.
150  */
151  class PathNode
152  {
153  public:
154  void Init( unsigned _frame,
155  void* _state,
156  float _costFromStart,
157  float _estToGoal,
158  PathNode* _parent );
159 
160  void Clear();
161  void InitSentinel() {
162  Clear();
163  Init( 0, 0, FLT_MAX, FLT_MAX, 0 );
164  prev = next = this;
165  }
166 
167  void *state; // the client state
168  float costFromStart; // exact
169  float estToGoal; // estimated
170  float totalCost; // could be a function, but save some math.
171  PathNode* parent; // the parent is used to reconstruct the path
172  unsigned frame; // unique id for this path, so the solver can distinguish
173  // correct from stale values
174 
175  int numAdjacent; // -1 is unknown & needs to be queried
176  int cacheIndex; // position in cache
177 
178  PathNode *child[2]; // Binary search in the hash table. [left, right]
179  PathNode *next, *prev; // used by open queue
180 
181  bool inOpen;
182  bool inClosed;
183 
184  void Unlink() {
185  next->prev = prev;
186  prev->next = next;
187  next = prev = 0;
188  }
189  void AddBefore( PathNode* addThis ) {
190  addThis->next = this;
191  addThis->prev = prev;
192  prev->next = addThis;
193  prev = addThis;
194  }
195 #ifdef TETRAEDGE_MICROPATHER_DEBUG
196  void CheckList()
197  {
198  MPASSERT( totalCost == FLT_MAX );
199  for( PathNode* it = next; it != this; it=it->next ) {
200  MPASSERT( it->prev == this || it->totalCost >= it->prev->totalCost );
201  MPASSERT( it->totalCost <= it->next->totalCost );
202  }
203  }
204 #endif
205 
206  void CalcTotalCost() {
207  if ( costFromStart < FLT_MAX && estToGoal < FLT_MAX )
208  totalCost = costFromStart + estToGoal;
209  else
210  totalCost = FLT_MAX;
211  }
212 
213  private:
214 
215  void operator=( const PathNode& );
216  };
217 
218 
219  /* Memory manager for the PathNodes. */
221  {
222  public:
223  PathNodePool( unsigned allocate, unsigned typicalAdjacent );
224  ~PathNodePool();
225 
226  // Free all the memory except the first block. Resets all memory.
227  void Clear();
228 
229  // Essentially:
230  // pNode = Find();
231  // if ( !pNode )
232  // pNode = New();
233  //
234  // Get the PathNode associated with this state. If the PathNode already
235  // exists (allocated and is on the current frame), it will be returned.
236  // Else a new PathNode is allocated and returned. The returned object
237  // is always fully initialized.
238  //
239  // NOTE: if the pathNode exists (and is current) all the initialization
240  // parameters are ignored.
241  PathNode* GetPathNode( unsigned frame,
242  void* _state,
243  float _costFromStart,
244  float _estToGoal,
245  PathNode* _parent );
246 
247  // Get a pathnode that is already in the pool.
248  PathNode* FetchPathNode( void* state );
249 
250  // Store stuff in cache
251  bool PushCache( const NodeCost* nodes, int nNodes, int* start );
252 
253  // Get neighbors from the cache
254  // Note - always access this with an offset. Can get re-allocated.
255  void GetCache( int start, int nNodes, NodeCost* nodes );
256 
257  // Return all the allocated states. Useful for visuallizing what
258  // the pather is doing.
259  void AllStates( unsigned frame, Common::Array< void* >* stateVec );
260 
261  private:
262  struct Block
263  {
264  Block* nextBlock;
265  PathNode pathNode[1];
266  };
267 
268  unsigned Hash( void* voidval );
269  unsigned HashSize() const { return 1<<hashShift; }
270  unsigned HashMask() const { return ((1<<hashShift)-1); }
271  void AddPathNode( unsigned key, PathNode* p );
272  Block* NewBlock();
273  PathNode* Alloc();
274 
275  PathNode** hashTable;
276  Block* firstBlock;
277  Block* blocks;
278 
279  NodeCost* cache;
280  int cacheCap;
281  int cacheSize;
282 
283  PathNode freeMemSentinel;
284  unsigned allocate; // how big a block of pathnodes to allocate at once
285  unsigned nAllocated; // number of pathnodes allocated (from Alloc())
286  unsigned nAvailable; // number available for allocation
287 
288  unsigned hashShift;
289  unsigned totalCollide;
290  };
291 
292 
293  /* Used to cache results of paths. Much, much faster
294  to return an existing solution than to calculate
295  a new one. A post on this is here: http://grinninglizard.com/altera/programming/a-path-caching-2/
296  */
297  class PathCache
298  {
299  public:
300  struct Item {
301  // The key:
302  void* start;
303  void* end;
304 
305  bool KeyEqual( const Item& item ) const { return start == item.start && end == item.end; }
306  bool Empty() const { return start == 0 && end == 0; }
307 
308  // Data:
309  void* next;
310  float cost; // from 'start' to 'next'. FLT_MAX if unsolveable.
311 
312  unsigned Hash() const {
313  const unsigned char *p = (const unsigned char *)(&start);
314  uint h = 2166136261U;
315 
316  for( unsigned i=0; i<sizeof(void*)*2; ++i, ++p ) {
317  h ^= *p;
318  h *= 16777619;
319  }
320  return h;
321  }
322  };
323 
324  PathCache( int itemsToAllocate );
325  ~PathCache();
326 
327  void Reset();
328  void Add( const Common::Array< void* >& path, const Common::Array< float >& cost );
329  void AddNoSolution( void* end, void* states[], int count );
330  int Solve( void* startState, void* endState, Common::Array< void* >* path, float* totalCost );
331 
332  int AllocatedBytes() const { return allocated * sizeof(Item); }
333  int UsedBytes() const { return nItems * sizeof(Item); }
334 
335  int hit;
336  int miss;
337 
338  private:
339  void AddItem( const Item& item );
340  const Item* Find( void* start, void* end );
341 
342  Item* mem;
343  int allocated;
344  int nItems;
345  };
346 
347  struct CacheData {
348  CacheData() { reset(); }
349 
350  int nBytesAllocated;
351  int nBytesUsed;
352  float memoryFraction;
353 
354  int hit;
355  int miss;
356  float hitFraction;
357 
358  void reset() {
359  nBytesAllocated = 0;
360  nBytesUsed = 0;
361  memoryFraction = 0;
362 
363  hit = 0;
364  miss = 0;
365  hitFraction = 0;
366  }
367  };
368 
374  {
375  friend class micropather::PathNode;
376 
377  public:
378  enum
379  {
380  SOLVED,
381  NO_SOLUTION,
382  START_END_SAME,
383 
384  // internal
385  NOT_CACHED
386  };
387 
411  MicroPather( Graph* graph, unsigned allocate = 250, unsigned typicalAdjacent=6, bool cache=true );
412  ~MicroPather();
413 
423  int Solve( void* startState, void* endState, Common::Array< void* >* path, float* totalCost );
424 
434  int SolveForNearStates( void* startState, Common::Array< StateCost >* near, float maxCost );
435 
439  void Reset();
440 
441  // Debugging function to return all states that were used by the last "solve"
442  void StatesInPool( Common::Array< void* >* stateVec );
443  void GetCacheData( CacheData* data );
444 
445  private:
446  MicroPather( const MicroPather& ); // undefined and unsupported
447  void operator=( const MicroPather ); // undefined and unsupported
448 
449  void GoalReached( PathNode* node, void* start, void* end, Common::Array< void* > *path );
450 
451  void GetNodeNeighbors( PathNode* node, Common::Array< NodeCost >* neighborNode );
452 
453 #ifdef TETRAEDGE_MICROPATHER_DEBUG
454  void DumpStats();
455 #endif
456 
457  PathNodePool pathNodePool;
458  Common::Array< StateCost > stateCostVec; // local to Solve, but put here to reduce memory allocation
459  Common::Array< NodeCost > nodeCostVec; // local to Solve, but put here to reduce memory allocation
460  Common::Array< float > costVec;
461 
462  Graph* graph;
463  unsigned frame; // incremented with every solve, used to determine if cached data needs to be refreshed
464  PathCache* pathCache;
465  };
466 
467 } // namespace micropather
468 
469 } // namespace Tetraedge
470 
471 #endif // TETRAEDGE_TE_MICROPATHER
472 
Definition: detection.h:27
Definition: micropather.h:373
Definition: array.h:52
float cost
The cost to the state. Use FLT_MAX for infinite cost.
Definition: micropather.h:90
Definition: micropather.h:220
Definition: micropather.h:87
Definition: micropather.h:151
void * state
The state as a void*.
Definition: micropather.h:89
Definition: micropather.h:300
Definition: micropather.h:347
Definition: micropather.h:297
Definition: micropather.h:140
Definition: micropather.h:108