- removed deprecated 'fast' pathfinder that wasn't fast enough and is not going to be used
This commit is contained in:
parent
d91e72a825
commit
871b6c4a6e
|
@ -1,403 +0,0 @@
|
||||||
// ==============================================================
|
|
||||||
// This file is part of Glest (www.glest.org)
|
|
||||||
//
|
|
||||||
// Copyright (C) 2012 Mark Vejvoda
|
|
||||||
//
|
|
||||||
// You can redistribute this code and/or modify it under
|
|
||||||
// the terms of the GNU General Public License as published
|
|
||||||
// by the Free Software Foundation; either version 2 of the
|
|
||||||
// License, or (at your option) any later version
|
|
||||||
// ==============================================================
|
|
||||||
|
|
||||||
#ifndef __INTRUSIVE_HASH_SET_HPP__
|
|
||||||
#define __INTRUSIVE_HASH_SET_HPP__
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
#include <inttypes.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <memory.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
This is base class for values that can be
|
|
||||||
stored in intrusive hashset.
|
|
||||||
|
|
||||||
*/
|
|
||||||
struct IntrHashSetNodeBase{
|
|
||||||
IntrHashSetNodeBase* ihsNextNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Values must be allocated in (some kind of) a heap.
|
|
||||||
Not stack.
|
|
||||||
Values are also nodes in a hash table,
|
|
||||||
so deleting values that is in hash is bad thing to do.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
class TRAITS MUST implement following static members:
|
|
||||||
|
|
||||||
bool TRAITS::isEqual(const T* a,const T* b);
|
|
||||||
uint32_t TRAITS::getHashCode(const T* a);
|
|
||||||
*/
|
|
||||||
|
|
||||||
template <class T,class TRAITS>
|
|
||||||
class IntrHashSet{
|
|
||||||
protected:
|
|
||||||
typedef T Node;
|
|
||||||
// copy constructor is protected
|
|
||||||
// values CANNOT be copied since
|
|
||||||
// they are allocated outside of this container!
|
|
||||||
IntrHashSet(const IntrHashSet&);
|
|
||||||
public:
|
|
||||||
// default constructor
|
|
||||||
// preAlloc values CANNOT be zero!
|
|
||||||
IntrHashSet(int preAlloc=128)
|
|
||||||
{
|
|
||||||
hash=new Node*[preAlloc];
|
|
||||||
memset(hash,0,sizeof(Node*)*preAlloc);
|
|
||||||
hashSize=preAlloc;
|
|
||||||
collisionsCount=0;
|
|
||||||
}
|
|
||||||
//destructor
|
|
||||||
~IntrHashSet()
|
|
||||||
{
|
|
||||||
if(hash)
|
|
||||||
{
|
|
||||||
delete [] hash;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//just empties container without deleting values!
|
|
||||||
void Clear()
|
|
||||||
{
|
|
||||||
collisionsCount=0;
|
|
||||||
memset(hash,0,sizeof(Node*)*hashSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
//insert allocated value
|
|
||||||
void Insert(T* value)
|
|
||||||
{
|
|
||||||
if(collisionsCount>hashSize/2)
|
|
||||||
{
|
|
||||||
Rehash();
|
|
||||||
}
|
|
||||||
uint32_t hidx=getIndex(value);
|
|
||||||
Node*& nodePtr=hash[hidx];
|
|
||||||
collisionsCount+=nodePtr!=0?1:0;
|
|
||||||
value->ihsNextNode=nodePtr;
|
|
||||||
nodePtr=value;
|
|
||||||
}
|
|
||||||
|
|
||||||
//iterator
|
|
||||||
//can be used to iterate over all values of hash
|
|
||||||
//and also returned by find method and can be
|
|
||||||
//use to delete value from hash faster
|
|
||||||
class ConstIterator{
|
|
||||||
public:
|
|
||||||
ConstIterator(const IntrHashSet* argHash):node(0),parent(0),index(0),hash(argHash){}
|
|
||||||
ConstIterator(const IntrHashSet& argHash):node(0),parent(0),index(0),hash(&argHash){}
|
|
||||||
|
|
||||||
const T* Get()const
|
|
||||||
{
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Found()const
|
|
||||||
{
|
|
||||||
return node!=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Rewind()
|
|
||||||
{
|
|
||||||
index=0;
|
|
||||||
node=0;
|
|
||||||
parent=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Next()
|
|
||||||
{
|
|
||||||
if(index>=hash->hashSize)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(index==0 && node==0 && parent==0)
|
|
||||||
{
|
|
||||||
parent=&hash->hash;
|
|
||||||
node=*parent;
|
|
||||||
if(node)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while(node==0)
|
|
||||||
{
|
|
||||||
index++;
|
|
||||||
if(index>=hash->hashSize)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
parent=hash->hash+index;
|
|
||||||
node=*parent;
|
|
||||||
if(node)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(*parent!=node)
|
|
||||||
{
|
|
||||||
parent=(Node**)&(*parent)->ihsNextNode;
|
|
||||||
}
|
|
||||||
node=(Node*)node->ihsNextNode;
|
|
||||||
if(node)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return Next();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
ConstIterator(const IntrHashSet* argHash,uint32_t argIndex,const Node* argNode,const Node*const* argParent):
|
|
||||||
node(argNode),parent(argParent),index(argIndex),hash(argHash){}
|
|
||||||
const Node* node;
|
|
||||||
const Node*const* parent;
|
|
||||||
uint32_t index;
|
|
||||||
const IntrHashSet* hash;
|
|
||||||
friend class IntrHashSet;
|
|
||||||
};
|
|
||||||
|
|
||||||
//mutable version of iterator
|
|
||||||
//however it's not good idea to modify key part of stored value
|
|
||||||
class Iterator{
|
|
||||||
public:
|
|
||||||
Iterator(IntrHashSet* argHash):node(0),parent(0),index(0),hash(argHash){}
|
|
||||||
Iterator(IntrHashSet& argHash):node(0),parent(0),index(0),hash(&argHash){}
|
|
||||||
|
|
||||||
T* Get()
|
|
||||||
{
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Found()const
|
|
||||||
{
|
|
||||||
return node!=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Rewind()
|
|
||||||
{
|
|
||||||
index=0;
|
|
||||||
node=0;
|
|
||||||
parent=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Next()
|
|
||||||
{
|
|
||||||
if(index>=hash->hashSize)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(index==0 && node==0 && parent==0)
|
|
||||||
{
|
|
||||||
parent=hash->hash;
|
|
||||||
node=*parent;
|
|
||||||
if(node)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while(node==0)
|
|
||||||
{
|
|
||||||
index++;
|
|
||||||
if(index>=hash->hashSize)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
parent=hash->hash+index;
|
|
||||||
node=*parent;
|
|
||||||
if(node)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(*parent!=node)
|
|
||||||
{
|
|
||||||
parent=(Node**)&(*parent)->ihsNextNode;
|
|
||||||
}
|
|
||||||
node=(Node*)node->ihsNextNode;
|
|
||||||
if(node)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return Next();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Iterator(IntrHashSet* argHash,uint32_t argIndex,Node* argNode,Node** argParent):
|
|
||||||
node(argNode),parent(argParent),index(argIndex),hash(argHash){}
|
|
||||||
Node* node;
|
|
||||||
Node** parent;
|
|
||||||
uint32_t index;
|
|
||||||
IntrHashSet* hash;
|
|
||||||
friend class IntrHashSet;
|
|
||||||
};
|
|
||||||
|
|
||||||
//constant version of find
|
|
||||||
//returned iterator can be used to obtain found value
|
|
||||||
//or delete it from hashet
|
|
||||||
|
|
||||||
ConstIterator Find(const T& value)const
|
|
||||||
{
|
|
||||||
uint32_t hidx=getIndex(&value);
|
|
||||||
Node*const* nodePtr=&hash[hidx];
|
|
||||||
if(!*nodePtr)return ConstIterator(0);
|
|
||||||
if(TRAITS::isEqual((*nodePtr),&value))
|
|
||||||
{
|
|
||||||
return ConstIterator(this,hidx,*nodePtr,nodePtr);
|
|
||||||
}
|
|
||||||
Node*const* parentPtr=nodePtr;
|
|
||||||
Node* node=(Node*)(*nodePtr)->ihsNextNode;
|
|
||||||
while(node)
|
|
||||||
{
|
|
||||||
if(TRAITS::isEqual(node,&value))
|
|
||||||
{
|
|
||||||
return ConstIterator(this,hidx,node,parentPtr);
|
|
||||||
}
|
|
||||||
parentPtr=nodePtr;
|
|
||||||
nodePtr=(Node**)&node->ihsNextNode;
|
|
||||||
node=(Node*)node->ihsNextNode;
|
|
||||||
}
|
|
||||||
return ConstIterator(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//non constant version of find
|
|
||||||
Iterator Find(const T& value)
|
|
||||||
{
|
|
||||||
uint32_t hidx=getIndex(&value);
|
|
||||||
Node** nodePtr=&hash[hidx];
|
|
||||||
if(!*nodePtr)return Iterator(0);
|
|
||||||
if(TRAITS::isEqual((*nodePtr),&value))
|
|
||||||
{
|
|
||||||
return Iterator(this,hidx,*nodePtr,nodePtr);
|
|
||||||
}
|
|
||||||
Node** parentPtr=nodePtr;
|
|
||||||
Node* node=(Node*)(*nodePtr)->ihsNextNode;
|
|
||||||
while(node)
|
|
||||||
{
|
|
||||||
if(TRAITS::isEqual(node,&value))
|
|
||||||
{
|
|
||||||
return Iterator(this,hidx,node,parentPtr);
|
|
||||||
}
|
|
||||||
parentPtr=nodePtr;
|
|
||||||
nodePtr=(Node**)&node->ihsNextNode;
|
|
||||||
node=(Node*)node->ihsNextNode;
|
|
||||||
}
|
|
||||||
return Iterator(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//delete element from hashset 'by value'
|
|
||||||
//actual value IS NOT DEALLOCATED
|
|
||||||
//and should be deallocated separately
|
|
||||||
void Delete(const T& value)
|
|
||||||
{
|
|
||||||
uint32_t hidx=getIndex(&value);
|
|
||||||
Node** nodePtr=hash+hidx;
|
|
||||||
if(TRAITS::isEqual((*nodePtr),&value))
|
|
||||||
{
|
|
||||||
Node* node=*nodePtr;
|
|
||||||
*nodePtr=(Node*)node->ihsNextNode;
|
|
||||||
if(*nodePtr)
|
|
||||||
{
|
|
||||||
collisionsCount--;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Node* parentPtr=*nodePtr;
|
|
||||||
Node* node=(Node*)(*nodePtr)->ihsNextNode;
|
|
||||||
while(node)
|
|
||||||
{
|
|
||||||
if(TRAITS::isEqual(node,&value))
|
|
||||||
{
|
|
||||||
parentPtr->ihsNextNode=node->ihsNextNode;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
parentPtr=node;
|
|
||||||
node=(Node*)node->ihsNextNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//delete element by iterator returned from Find
|
|
||||||
//or used for iteration.
|
|
||||||
//iterator used for Delete is no longer valid
|
|
||||||
//for iteration, however element it refer to
|
|
||||||
//is still here and Get is still valid after Delete.
|
|
||||||
//actuall value also IS NOT DEALLOCATED!
|
|
||||||
|
|
||||||
void Delete(const Iterator& hi)
|
|
||||||
{
|
|
||||||
Node** parentPtr=(Node**)hi.parent;
|
|
||||||
Node* node=(Node*)hi.node;
|
|
||||||
if(!node)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(*parentPtr==node)
|
|
||||||
{
|
|
||||||
*parentPtr=(Node*)node->ihsNextNode;
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
(*parentPtr)->ihsNextNode=node->ihsNextNode;
|
|
||||||
}
|
|
||||||
if(*parentPtr)
|
|
||||||
{
|
|
||||||
collisionsCount--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// get index of a bucket in a hash table
|
|
||||||
uint32_t getIndex(const T* value)const
|
|
||||||
{
|
|
||||||
uint32_t hashCode=TRAITS::getHashCode(value);
|
|
||||||
return hashCode%hashSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// increase hash table size if there are
|
|
||||||
// too much collisions
|
|
||||||
void Rehash()
|
|
||||||
{
|
|
||||||
Node** oldHash=hash;
|
|
||||||
Node** oldHashEnd=hash+hashSize;
|
|
||||||
hashSize*=2;
|
|
||||||
hash=new Node*[hashSize];
|
|
||||||
memset(hash,0,sizeof(Node*)*hashSize);
|
|
||||||
collisionsCount=0;
|
|
||||||
for(Node** it=oldHash;it!=oldHashEnd;it++)
|
|
||||||
{
|
|
||||||
Node* node=*it;
|
|
||||||
Node* nextNode;
|
|
||||||
while(node)
|
|
||||||
{
|
|
||||||
uint32_t hidx=getIndex(node);
|
|
||||||
Node** nodePtr=hash+hidx;
|
|
||||||
if(*nodePtr)
|
|
||||||
{
|
|
||||||
collisionsCount++;
|
|
||||||
}
|
|
||||||
nextNode=(Node*)node->ihsNextNode;
|
|
||||||
node->ihsNextNode=*nodePtr;
|
|
||||||
*nodePtr=node;
|
|
||||||
node=nextNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// hash table itself
|
|
||||||
Node** hash;
|
|
||||||
// size of hash table
|
|
||||||
size_t hashSize;
|
|
||||||
// number of collisions
|
|
||||||
int collisionsCount;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,546 +0,0 @@
|
||||||
// ==============================================================
|
|
||||||
// This file is part of Glest (www.glest.org)
|
|
||||||
//
|
|
||||||
// Copyright (C) 2012 Mark Vejvoda
|
|
||||||
//
|
|
||||||
// You can redistribute this code and/or modify it under
|
|
||||||
// the terms of the GNU General Public License as published
|
|
||||||
// by the Free Software Foundation; either version 2 of the
|
|
||||||
// License, or (at your option) any later version
|
|
||||||
// ==============================================================
|
|
||||||
|
|
||||||
#ifndef __INTRUSIVE_HEAP_HASH_SET_HPP__
|
|
||||||
#define __INTRUSIVE_HEAP_HASH_SET_HPP__
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
#include <inttypes.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "IntrHashSet.hpp"
|
|
||||||
|
|
||||||
/*
|
|
||||||
Here is temlate class Intrusive Heap/HashSet.
|
|
||||||
Actuall values are stored in this container,
|
|
||||||
no copying is performed, so all values should
|
|
||||||
be allocated in a heap or in a storage with
|
|
||||||
lifetime as long as lifetime of container.
|
|
||||||
Values are also used as nodes of container,
|
|
||||||
so no value can be stored in two containers
|
|
||||||
of this kind simultaneously.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
This is what should be done with duplicate
|
|
||||||
from hash point of view values.
|
|
||||||
*/
|
|
||||||
enum HHDuplicatePolicy{
|
|
||||||
hhdpReplaceOld, //replace old value. old values is not deallocated!
|
|
||||||
hhdpKeepOld, //container is not modified in this case.
|
|
||||||
hhdpInsertDuplicate //duplicates are stored in container
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
TRAITS class MUST implement following static members:
|
|
||||||
for heap - this is something like operator< or operator>
|
|
||||||
bool TRAITS::Compare(const T* a,const T* b);
|
|
||||||
for hash
|
|
||||||
bool TRAITS::isEqual(const T* a,const T* b);
|
|
||||||
uint32_t TRAITS::getHashCode(const T& a);
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
This is base class for values stored in a intrusive heap hash
|
|
||||||
*/
|
|
||||||
struct IntrHeapHashNodeBase:public IntrHashSetNodeBase{
|
|
||||||
int ihhNodeIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T,class TRAITS,HHDuplicatePolicy policy=hhdpReplaceOld>
|
|
||||||
class IntrHeapHash{
|
|
||||||
public:
|
|
||||||
//default constructor
|
|
||||||
//preAlloc value cannot be 0!
|
|
||||||
IntrHeapHash(int preAlloc=128)
|
|
||||||
{
|
|
||||||
hash=new Node*[preAlloc];
|
|
||||||
memset(hash,0,preAlloc*sizeof(Node*));
|
|
||||||
hashSize=preAlloc;
|
|
||||||
heap=new Node*[preAlloc];
|
|
||||||
memset(heap,0,preAlloc*sizeof(Node*));
|
|
||||||
heapSize=0;
|
|
||||||
heapAlloc=preAlloc;
|
|
||||||
collisionsCount=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//guess what? destructor!
|
|
||||||
~IntrHeapHash()
|
|
||||||
{
|
|
||||||
delete [] hash;
|
|
||||||
delete [] heap;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear content container
|
|
||||||
// values are not deallocated!
|
|
||||||
void Clear()
|
|
||||||
{
|
|
||||||
memset(hash,0,hashSize*sizeof(Node*));
|
|
||||||
heapSize=0;
|
|
||||||
collisionsCount=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//insert new value into container
|
|
||||||
//return value is equal to inserted value for all policies if no duplicate detected
|
|
||||||
//in case of duplicate for keep old policy 0 is returned
|
|
||||||
//in case of duplicate for replace old policy old value is returned
|
|
||||||
T* Insert(T* value)
|
|
||||||
{
|
|
||||||
if(collisionsCount>hashSize/2)
|
|
||||||
{
|
|
||||||
Rehash();
|
|
||||||
}
|
|
||||||
uint32_t hidx=getIndex(value);
|
|
||||||
Node*& node=hash[hidx];
|
|
||||||
T* rv=value;
|
|
||||||
if(policy==hhdpReplaceOld || policy==hhdpKeepOld)
|
|
||||||
{
|
|
||||||
Node* ptr=FindHashNode(node,*value);
|
|
||||||
if(ptr)
|
|
||||||
{
|
|
||||||
if(policy==hhdpKeepOld)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
DeleteHashNode(hash+hidx,ptr);
|
|
||||||
rv=ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
value->ihhNodeIndex=heapSize;
|
|
||||||
if(node)
|
|
||||||
{
|
|
||||||
collisionsCount++;
|
|
||||||
}
|
|
||||||
value->ihsNextNode=node;
|
|
||||||
node=value;
|
|
||||||
if(heapSize==heapAlloc)
|
|
||||||
{
|
|
||||||
heapAlloc*=2;
|
|
||||||
Node** newHeap=new Node*[heapAlloc];
|
|
||||||
memcpy(newHeap,heap,heapSize*sizeof(Node*));
|
|
||||||
delete [] heap;
|
|
||||||
heap=newHeap;
|
|
||||||
}
|
|
||||||
heap[heapSize++]=value;
|
|
||||||
HeapPush();
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
// value at the head of heap
|
|
||||||
const T* getHead()const
|
|
||||||
{
|
|
||||||
return *heap;
|
|
||||||
}
|
|
||||||
|
|
||||||
// same as previous but non const
|
|
||||||
T* getHead()
|
|
||||||
{
|
|
||||||
return **heap;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get and remove head value of heap
|
|
||||||
T* Pop()
|
|
||||||
{
|
|
||||||
T* rv=*heap;
|
|
||||||
uint32_t hidx=getIndex(rv);
|
|
||||||
DeleteHashNode(&hash[hidx],rv);
|
|
||||||
HeapSwap(heap,heap+heapSize-1);
|
|
||||||
heapSize--;
|
|
||||||
HeapPop();
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
//find value in hash
|
|
||||||
//const version
|
|
||||||
const T* Find(const T& value)const
|
|
||||||
{
|
|
||||||
uint32_t hidx=getIndex(&value);
|
|
||||||
Node* ptr=hash[hidx];
|
|
||||||
while(ptr)
|
|
||||||
{
|
|
||||||
if(TRAITS::isEqual(ptr,&value))
|
|
||||||
{
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
ptr=(Node*)ptr->ihsNextNode;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//find value in hash
|
|
||||||
//non const version
|
|
||||||
//it's not good idea to modify key value of hash or key value of heap however
|
|
||||||
T* Find(const T& value)
|
|
||||||
{
|
|
||||||
uint32_t hidx=getIndex(&value);
|
|
||||||
Node* ptr=hash[hidx];
|
|
||||||
while(ptr)
|
|
||||||
{
|
|
||||||
if(TRAITS::isEqual(ptr,&value))
|
|
||||||
{
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
ptr=(Node*)ptr->ihsNextNode;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//get from hash all values equal to given
|
|
||||||
void GetAll(const T& value,std::vector<T*>& values)const
|
|
||||||
{
|
|
||||||
uint32_t hidx=getIndex(&value);
|
|
||||||
Node* ptr=hash[hidx];
|
|
||||||
while(ptr)
|
|
||||||
{
|
|
||||||
if(TRAITS::isEqual(ptr,&value))
|
|
||||||
{
|
|
||||||
values.push_back(ptr);
|
|
||||||
}
|
|
||||||
ptr=(Node*)ptr->ihsNextNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//delete value from hash
|
|
||||||
//deleted object returned
|
|
||||||
T* Delete(const T& value)
|
|
||||||
{
|
|
||||||
uint32_t hidx=getIndex(&value);
|
|
||||||
int idx=DeleteHashNode(hash+hidx,value);
|
|
||||||
if(idx==-1)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(idx==heapSize-1)
|
|
||||||
{
|
|
||||||
heapSize--;
|
|
||||||
return heap[heapSize];
|
|
||||||
}
|
|
||||||
HeapSwap(heap+idx,heap+heapSize-1);
|
|
||||||
heapSize--;
|
|
||||||
HeapFix(idx);
|
|
||||||
return heap[heapSize];
|
|
||||||
}
|
|
||||||
|
|
||||||
//delete all values equal to given
|
|
||||||
void DeleteAll(const T& value)
|
|
||||||
{
|
|
||||||
uint32_t hidx=getIndex(&value);
|
|
||||||
Node** nodePtr=hash+hidx;
|
|
||||||
while(*nodePtr)
|
|
||||||
{
|
|
||||||
int idx=DeleteHashNode(nodePtr,value);
|
|
||||||
if(idx==-1)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(idx==heapSize-1)
|
|
||||||
{
|
|
||||||
heapSize--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
HeapSwap(heap+idx,heap+heapSize-1);
|
|
||||||
heapSize--;
|
|
||||||
HeapFix(idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//get number of elements in container
|
|
||||||
size_t getSize()const
|
|
||||||
{
|
|
||||||
return heapSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
//check if container is empty
|
|
||||||
bool isEmpty()const
|
|
||||||
{
|
|
||||||
return heapSize==0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//iterator
|
|
||||||
//can/should be used like this:
|
|
||||||
//for(IHHTypeDef::Iterator it(ihh);it.Next();)
|
|
||||||
//{
|
|
||||||
// dosomething(it.Get())
|
|
||||||
//}
|
|
||||||
class Iterator{
|
|
||||||
public:
|
|
||||||
Iterator(const IntrHeapHash& argHH)
|
|
||||||
{
|
|
||||||
begin=argHH.heap;
|
|
||||||
current=0;
|
|
||||||
end=argHH.heap+argHH.heapSize;
|
|
||||||
}
|
|
||||||
bool Next()
|
|
||||||
{
|
|
||||||
if(current==0)
|
|
||||||
{
|
|
||||||
current=begin;
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
current++;
|
|
||||||
}
|
|
||||||
return current!=end;
|
|
||||||
}
|
|
||||||
T* Get()
|
|
||||||
{
|
|
||||||
if(current)
|
|
||||||
{
|
|
||||||
return *current;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
void Rewind()
|
|
||||||
{
|
|
||||||
current=begin;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
typename IntrHeapHash::Node **begin,**current,**end;
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
//protected copy constructor
|
|
||||||
//values cannot be copied as well as container
|
|
||||||
IntrHeapHash(const IntrHeapHash&);
|
|
||||||
|
|
||||||
//typedef for convenience
|
|
||||||
typedef T Node;
|
|
||||||
//heap array
|
|
||||||
Node** heap;
|
|
||||||
//hash table
|
|
||||||
Node** hash;
|
|
||||||
//size of hash table
|
|
||||||
size_t hashSize;
|
|
||||||
//used size of heap
|
|
||||||
size_t heapSize;
|
|
||||||
//allocated size of heap
|
|
||||||
size_t heapAlloc;
|
|
||||||
|
|
||||||
//count of collisions in hash
|
|
||||||
int collisionsCount;
|
|
||||||
|
|
||||||
//get index of value in hash table
|
|
||||||
uint32_t getIndex(const T* value)const
|
|
||||||
{
|
|
||||||
uint32_t hashCode=TRAITS::getHashCode(value);
|
|
||||||
return hashCode%hashSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
//resize hash table when
|
|
||||||
//collisions count is too big
|
|
||||||
void Rehash()
|
|
||||||
{
|
|
||||||
Node** oldHash=hash;
|
|
||||||
Node** oldHashEnd=oldHash+hashSize;
|
|
||||||
hashSize*=2;
|
|
||||||
hash=new Node*[hashSize];
|
|
||||||
memset(hash,0,hashSize*sizeof(Node*));
|
|
||||||
collisionsCount=0;
|
|
||||||
for(Node** it=oldHash;it!=oldHashEnd;it++)
|
|
||||||
{
|
|
||||||
Node* nodePtr=*it;
|
|
||||||
while(nodePtr)
|
|
||||||
{
|
|
||||||
uint32_t hidx=getIndex(nodePtr);
|
|
||||||
Node*& hnode=hash[hidx];
|
|
||||||
if(hnode)
|
|
||||||
{
|
|
||||||
collisionsCount++;
|
|
||||||
}
|
|
||||||
Node* next=(Node*)nodePtr->ihsNextNode;
|
|
||||||
nodePtr->ihsNextNode=hnode;
|
|
||||||
hnode=nodePtr;
|
|
||||||
nodePtr=next;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//find and delete hash node from bucket by ptr
|
|
||||||
void DeleteHashNode(Node** nodeBasePtr,Node* nodePtr)
|
|
||||||
{
|
|
||||||
if(*nodeBasePtr==nodePtr)
|
|
||||||
{
|
|
||||||
*nodeBasePtr=(Node*)nodePtr->ihsNextNode;
|
|
||||||
if(*nodeBasePtr)
|
|
||||||
{
|
|
||||||
collisionsCount--;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Node* parentPtr=*nodeBasePtr;
|
|
||||||
Node* iterPtr=(Node*)parentPtr->ihsNextNode;
|
|
||||||
while(iterPtr)
|
|
||||||
{
|
|
||||||
if(iterPtr==nodePtr)
|
|
||||||
{
|
|
||||||
parentPtr->ihsNextNode=nodePtr->ihsNextNode;
|
|
||||||
collisionsCount--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
parentPtr=iterPtr;
|
|
||||||
iterPtr=(Node*)iterPtr->ihsNextNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//find and delete hash node from bucked by value
|
|
||||||
//heap index returned
|
|
||||||
int DeleteHashNode(Node** nodePtr,const T& data)
|
|
||||||
{
|
|
||||||
if(!*nodePtr)return -1;
|
|
||||||
if(TRAITS::isEqual(*nodePtr,&data))
|
|
||||||
{
|
|
||||||
int rv=(*nodePtr)->ihhNodeIndex;
|
|
||||||
*nodePtr=(Node*)(*nodePtr)->ihsNextNode;
|
|
||||||
if(*nodePtr)
|
|
||||||
{
|
|
||||||
collisionsCount--;
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
Node* parentPtr=*nodePtr;
|
|
||||||
Node* node=(Node*)(*nodePtr)->ihsNextNode;
|
|
||||||
while(node)
|
|
||||||
{
|
|
||||||
if(TRAITS::isEqual(node,&data))
|
|
||||||
{
|
|
||||||
parentPtr->ihsNextNode=node->ihsNextNode;
|
|
||||||
collisionsCount--;
|
|
||||||
return node->ihhNodeIndex;
|
|
||||||
}
|
|
||||||
parentPtr=node;
|
|
||||||
node=(Node*)node->ihsNextNode;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//find hash node in a bucked by value
|
|
||||||
Node* FindHashNode(Node* nodePtr,const T& data)
|
|
||||||
{
|
|
||||||
while(nodePtr)
|
|
||||||
{
|
|
||||||
if(TRAITS::isEqual(nodePtr,&data))
|
|
||||||
{
|
|
||||||
return nodePtr;
|
|
||||||
}
|
|
||||||
nodePtr=(Node*)nodePtr->ihsNextNode;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//float up tail element
|
|
||||||
void HeapPush(int didx=-1)
|
|
||||||
{
|
|
||||||
int idx=didx==-1?heapSize-1:didx;
|
|
||||||
int pidx;
|
|
||||||
Node** b=heap;
|
|
||||||
Node** i=b+idx;
|
|
||||||
Node** pi;
|
|
||||||
Node* ptr=*i;
|
|
||||||
while(idx)
|
|
||||||
{
|
|
||||||
pidx=(idx-1)/2;
|
|
||||||
pi=b+pidx;
|
|
||||||
if(TRAITS::Compare(ptr,(*pi)))
|
|
||||||
{
|
|
||||||
*i=*pi;
|
|
||||||
(*i)->ihhNodeIndex=idx;
|
|
||||||
i=pi;
|
|
||||||
idx=pidx;
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*i=ptr;
|
|
||||||
ptr->ihhNodeIndex=idx;
|
|
||||||
}
|
|
||||||
//drow down element from head
|
|
||||||
void HeapPop(int idx=0)
|
|
||||||
{
|
|
||||||
if(heapSize<=1)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Node **i,**b,**i1,**i2;
|
|
||||||
int cidx1,cidx2;
|
|
||||||
b=heap;
|
|
||||||
i=b+idx;
|
|
||||||
Node* ptr=*i;
|
|
||||||
while(idx<heapSize)
|
|
||||||
{
|
|
||||||
cidx1=idx*2+1;
|
|
||||||
cidx2=idx*2+2;
|
|
||||||
if(cidx1>=heapSize)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i1=b+cidx1;
|
|
||||||
i2=b+cidx2;
|
|
||||||
if(cidx2>=heapSize || TRAITS::Compare((*i1),(*i2)))
|
|
||||||
{
|
|
||||||
if(!TRAITS::Compare(ptr,(*i1)))
|
|
||||||
{
|
|
||||||
*i=*i1;
|
|
||||||
(*i)->ihhNodeIndex=idx;
|
|
||||||
idx=cidx1;
|
|
||||||
i=i1;
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
if(!TRAITS::Compare(ptr,(*i2)))
|
|
||||||
{
|
|
||||||
*i=*i2;
|
|
||||||
(*i)->ihhNodeIndex=idx;
|
|
||||||
idx=cidx2;
|
|
||||||
i=i2;
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*i=ptr;
|
|
||||||
ptr->ihhNodeIndex=idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
//either drow down or float up element at middle
|
|
||||||
void HeapFix(int idx)
|
|
||||||
{
|
|
||||||
int pidx=(idx-1)/2;
|
|
||||||
if(TRAITS::Compare(heap[idx],heap[pidx]))
|
|
||||||
{
|
|
||||||
HeapPush(idx);
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
HeapPop(idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//swap two element fixing indeces
|
|
||||||
void HeapSwap(Node** i1,Node** i2)
|
|
||||||
{
|
|
||||||
int idx1=(*i1)->ihhNodeIndex;
|
|
||||||
int idx2=(*i2)->ihhNodeIndex;
|
|
||||||
Node* ptr=*i1;
|
|
||||||
*i1=*i2;
|
|
||||||
(*i1)->ihhNodeIndex=idx1;
|
|
||||||
(*i2)=ptr;
|
|
||||||
(*i2)->ihhNodeIndex=idx2;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,155 +0,0 @@
|
||||||
/*!
|
|
||||||
// ==============================================================
|
|
||||||
// This file is part of Glest (www.glest.org)
|
|
||||||
//
|
|
||||||
// Copyright (C) 2012 Mark Vejvoda
|
|
||||||
//
|
|
||||||
// You can redistribute this code and/or modify it under
|
|
||||||
// the terms of the GNU General Public License as published
|
|
||||||
// by the Free Software Foundation; either version 2 of the
|
|
||||||
// License, or (at your option) any later version
|
|
||||||
// ==============================================================
|
|
||||||
|
|
||||||
** Copyright (c) 2007 by John W. Ratcliff mailto:jratcliff@infiniplex.net
|
|
||||||
**
|
|
||||||
** Portions of this source has been released with the PhysXViewer application, as well as
|
|
||||||
** Rocket, CreateDynamics, ODF, and as a number of sample code snippets.
|
|
||||||
**
|
|
||||||
** If you find this code useful or you are feeling particularily generous I would
|
|
||||||
** ask that you please go to http://www.amillionpixels.us and make a donation
|
|
||||||
** to Troy DeMolay.
|
|
||||||
**
|
|
||||||
** DeMolay is a youth group for young men between the ages of 12 and 21.
|
|
||||||
** It teaches strong moral principles, as well as leadership skills and
|
|
||||||
** public speaking. The donations page uses the 'pay for pixels' paradigm
|
|
||||||
** where, in this case, a pixel is only a single penny. Donations can be
|
|
||||||
** made for as small as $4 or as high as a $100 block. Each person who donates
|
|
||||||
** will get a link to their own site as well as acknowledgement on the
|
|
||||||
** donations blog located here http://www.amillionpixels.blogspot.com/
|
|
||||||
**
|
|
||||||
** If you wish to contact me you can use the following methods:
|
|
||||||
**
|
|
||||||
** Skype Phone: 636-486-4040 (let it ring a long time while it goes through switches)
|
|
||||||
** Skype ID: jratcliff63367
|
|
||||||
** Yahoo: jratcliff63367
|
|
||||||
** AOL: jratcliff1961
|
|
||||||
** email: jratcliff@infiniplex.net
|
|
||||||
|
|
||||||
A* Algorithm Implementation using STL is
|
|
||||||
Copyright (C)2001-2005 Justin Heyes-Jones
|
|
||||||
|
|
||||||
FixedSizeAllocator class
|
|
||||||
Copyright 2001 Justin Heyes-Jones
|
|
||||||
|
|
||||||
This class is a constant time O(1) memory manager for objects of
|
|
||||||
a specified type. The type is specified using a template class.
|
|
||||||
|
|
||||||
Memory is allocated from a fixed size buffer which you can specify in the
|
|
||||||
class constructor or use the default.
|
|
||||||
|
|
||||||
Using GetFirst and GetNext it is possible to iterate through the elements
|
|
||||||
one by one, and this would be the most common use for the class.
|
|
||||||
|
|
||||||
I would suggest using this class when you want O(1) add and delete
|
|
||||||
and you don't do much searching, which would be O(n). Structures such as binary
|
|
||||||
trees can be used instead to get O(logn) access time.
|
|
||||||
|
|
||||||
**
|
|
||||||
** The MIT license:
|
|
||||||
**
|
|
||||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
** of this software and associated documentation files (the "Software"), to deal
|
|
||||||
** in the Software without restriction, including without limitation the rights
|
|
||||||
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
** copies of the Software, and to permit persons to whom the Software is furnished
|
|
||||||
** to do so, subject to the following conditions:
|
|
||||||
**
|
|
||||||
** The above copyright notice and this permission notice shall be included in all
|
|
||||||
** copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||||
** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FAST_ASTAR_H
|
|
||||||
|
|
||||||
#define FAST_ASTAR_H
|
|
||||||
|
|
||||||
//*** IMPORTANT : READ ME FIRST !!
|
|
||||||
//***
|
|
||||||
//*** This source code simply provides a C++ wrapper for the AStar Algorithm Implementation in STL written by Justin Heyes-Jones
|
|
||||||
//*** There is nothing wrong with Justin's code in any way, except that he uses templates. My personal programming style is
|
|
||||||
//*** to use virtual interfaces and the PIMPLE paradigm to hide the details of the implementation.
|
|
||||||
//***
|
|
||||||
//*** To use my wrapper you simply have your own path node inherit the pure virtual interface 'AI_Node' and implement the
|
|
||||||
//*** following four methods.
|
|
||||||
//***
|
|
||||||
//***
|
|
||||||
//** virtual float getDistance(const AI_Node *node) = 0; // Return the distance between two nodes
|
|
||||||
//** virtual float getCost(void) = 0; // return the relative 'cost' of a node. Default should be 1.
|
|
||||||
//** virtual unsigned int getEdgeCount(void) const = 0; // Return the number of edges in a node.
|
|
||||||
//** virtual AI_Node * getEdge(int index) const = 0; // Return a pointer to the node a particular edge is connected to.
|
|
||||||
//**
|
|
||||||
//** That's all there is to it.
|
|
||||||
//**
|
|
||||||
//** Here is an example usage:
|
|
||||||
//**
|
|
||||||
//** FastAstar *fa = createFastAstar();
|
|
||||||
//** astarStartSearch(fq,fromNode,toNode);
|
|
||||||
//** for (int i=0; i<10000; i++)
|
|
||||||
//** {
|
|
||||||
//** bool finished = astarSearchStep(fa);
|
|
||||||
//** if ( finished ) break;
|
|
||||||
//** }
|
|
||||||
//**
|
|
||||||
//** unsigned int count;
|
|
||||||
//** AI_Node **solution = getSolution(fa,count);
|
|
||||||
//**
|
|
||||||
//** ... do something you want with the answer
|
|
||||||
//**
|
|
||||||
//** releaseFastAstar(fa);
|
|
||||||
//**
|
|
||||||
//*******************************
|
|
||||||
#include "data_types.h"
|
|
||||||
|
|
||||||
using namespace Shared::Platform;
|
|
||||||
|
|
||||||
class AI_Node
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual float getDistance(const AI_Node *node,void *userData) = 0;
|
|
||||||
virtual float getCost(void *userData) = 0;
|
|
||||||
virtual unsigned int getEdgeCount(void *userData) const = 0;
|
|
||||||
virtual AI_Node * getEdge(int index,void *userData) const = 0;
|
|
||||||
virtual int32 getHashCode() const = 0;
|
|
||||||
|
|
||||||
virtual ~AI_Node() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
enum SearchState {
|
|
||||||
SEARCH_STATE_NOT_INITIALISED,
|
|
||||||
SEARCH_STATE_SEARCHING,
|
|
||||||
SEARCH_STATE_SUCCEEDED,
|
|
||||||
SEARCH_STATE_FAILED,
|
|
||||||
SEARCH_STATE_OUT_OF_MEMORY,
|
|
||||||
SEARCH_STATE_INVALID
|
|
||||||
};
|
|
||||||
|
|
||||||
class FastAstar;
|
|
||||||
|
|
||||||
FastAstar * createFastAstar(void); // Create an instance of the FastAstar utility.
|
|
||||||
void astarStartSearch(FastAstar *astar,AI_Node *from,AI_Node *to, void *userData); // start a search.
|
|
||||||
|
|
||||||
bool astarSearchStep(FastAstar *astar,unsigned int &searchCount); // step the A star algorithm one time. Return true if the search is completed.
|
|
||||||
SearchState getLastSearchState(FastAstar *astar);
|
|
||||||
|
|
||||||
AI_Node ** getSolution(FastAstar *astar,unsigned int &count); // retrieve the solution. If this returns a null pointer and count of zero, it means no solution could be found.
|
|
||||||
void releaseFastAstar(FastAstar *astar); // Release the intance of the FastAstar utility.
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "faction.h"
|
#include "faction.h"
|
||||||
#include "randomgen.h"
|
#include "randomgen.h"
|
||||||
#include "fast_path_finder.h"
|
|
||||||
#include "leak_dumper.h"
|
#include "leak_dumper.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -87,9 +86,6 @@ void PathFinder::init(const Map *map) {
|
||||||
PathFinder::~PathFinder() {
|
PathFinder::~PathFinder() {
|
||||||
for(int i = 0; i < GameConstants::maxPlayers; ++i) {
|
for(int i = 0; i < GameConstants::maxPlayers; ++i) {
|
||||||
factions[i].nodePool.clear();
|
factions[i].nodePool.clear();
|
||||||
|
|
||||||
releaseFastAstar(factions[i].fa);
|
|
||||||
factions[i].fa = NULL;
|
|
||||||
}
|
}
|
||||||
factions.clear();
|
factions.clear();
|
||||||
map=NULL;
|
map=NULL;
|
||||||
|
@ -229,18 +225,9 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
|
||||||
|
|
||||||
uint32 searched_node_count = 0;
|
uint32 searched_node_count = 0;
|
||||||
minorDebugPathfinder = false;
|
minorDebugPathfinder = false;
|
||||||
//bool enableFastPathfinder = Config::getInstance().getBool("EnableFastPathFinder","false");
|
if(minorDebugPathfinder) printf("Legacy Pathfind Unit [%d - %s] from = %s to = %s frameIndex = %d\n",unit->getId(),unit->getType()->getName().c_str(),unit->getPos().getString().c_str(),finalPos.getString().c_str(),frameIndex);
|
||||||
bool enableFastPathfinder = false;
|
|
||||||
if(enableFastPathfinder == true) {
|
|
||||||
if(minorDebugPathfinder) printf("Fast Pathfind Unit [%d - %s] from = %s to = %s frameIndex = %d\n",unit->getId(),unit->getType()->getName().c_str(),unit->getPos().getString().c_str(),finalPos.getString().c_str(),frameIndex);
|
|
||||||
|
|
||||||
ts = aStarFast(unit, finalPos, false, frameIndex, maxNodeCount,&searched_node_count);
|
ts = aStar(unit, finalPos, false, frameIndex, maxNodeCount,&searched_node_count);
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(minorDebugPathfinder) printf("Legacy Pathfind Unit [%d - %s] from = %s to = %s frameIndex = %d\n",unit->getId(),unit->getType()->getName().c_str(),unit->getPos().getString().c_str(),finalPos.getString().c_str(),frameIndex);
|
|
||||||
|
|
||||||
ts = aStar(unit, finalPos, false, frameIndex, maxNodeCount,&searched_node_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
//post actions
|
//post actions
|
||||||
switch(ts) {
|
switch(ts) {
|
||||||
|
@ -317,12 +304,7 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
|
||||||
|
|
||||||
int maxBailoutNodeCount = (PathFinder::pathFindBailoutRadius * 2);
|
int maxBailoutNodeCount = (PathFinder::pathFindBailoutRadius * 2);
|
||||||
|
|
||||||
if(enableFastPathfinder == true) {
|
ts= aStar(unit, newFinalPos, true, frameIndex, maxBailoutNodeCount,&searched_node_count);
|
||||||
ts= aStarFast(unit, newFinalPos, true, frameIndex, maxBailoutNodeCount,&searched_node_count);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ts= aStar(unit, newFinalPos, true, frameIndex, maxBailoutNodeCount,&searched_node_count);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -344,12 +326,7 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
|
||||||
//printf("$$$$ Unit BAILOUT(1) ASTAR ATTEMPT for [%d - %s] newFinalPos = [%s]\n",unit->getId(),unit->getFullName().c_str(),newFinalPos.getString().c_str());
|
//printf("$$$$ Unit BAILOUT(1) ASTAR ATTEMPT for [%d - %s] newFinalPos = [%s]\n",unit->getId(),unit->getFullName().c_str(),newFinalPos.getString().c_str());
|
||||||
int maxBailoutNodeCount = (PathFinder::pathFindBailoutRadius * 2);
|
int maxBailoutNodeCount = (PathFinder::pathFindBailoutRadius * 2);
|
||||||
|
|
||||||
if(enableFastPathfinder == true) {
|
ts= aStar(unit, newFinalPos, true, frameIndex, maxBailoutNodeCount,&searched_node_count);
|
||||||
ts= aStarFast(unit, newFinalPos, true, frameIndex, maxBailoutNodeCount,&searched_node_count);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ts= aStar(unit, newFinalPos, true, frameIndex, maxBailoutNodeCount,&searched_node_count);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -428,7 +405,6 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() >= 1) printf("In [%s::%s Line: %d] fastastar took [%lld] msecs, ts = %d nodeSearchCount = %d.\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis(),ts,nodeSearchCount);
|
|
||||||
if(minorDebugPathfinderPerformance && chrono.getMillis() >= 1) printf("Unit [%d - %s] astar took [%lld] msecs, ts = %d searched_node_count = %d.\n",unit->getId(),unit->getType()->getName().c_str(),(long long int)chrono.getMillis(),ts,searched_node_count);
|
if(minorDebugPathfinderPerformance && chrono.getMillis() >= 1) printf("Unit [%d - %s] astar took [%lld] msecs, ts = %d searched_node_count = %d.\n",unit->getId(),unit->getType()->getName().c_str(),(long long int)chrono.getMillis(),ts,searched_node_count);
|
||||||
|
|
||||||
return ts;
|
return ts;
|
||||||
|
@ -436,511 +412,6 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
|
||||||
|
|
||||||
// ==================== PRIVATE ====================
|
// ==================== PRIVATE ====================
|
||||||
|
|
||||||
TravelState PathFinder::aStarFast(Unit *unit, Vec2i finalPos, bool inBailout, int frameIndex, int maxNodeCount,uint32 *searched_node_count) {
|
|
||||||
TravelState ts = tsImpossible;
|
|
||||||
|
|
||||||
Chrono chrono;
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
|
|
||||||
|
|
||||||
if(maxNodeCount < 0) {
|
|
||||||
maxNodeCount = factions[unit->getFactionIndex()].useMaxNodeCount;
|
|
||||||
|
|
||||||
//printf("AStar set maxNodeCount = %d\n",maxNodeCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(maxNodeCount >= 1 && unit->getPathfindFailedConsecutiveFrameCount() >= 3) {
|
|
||||||
//int orgmaxNodeCount = maxNodeCount;
|
|
||||||
maxNodeCount = 200;
|
|
||||||
//printf("AStar maxpath cut for unit [%d - %s] to %d [orig: %d] [unit->getPathfindFailedConsecutiveFrameCount(): %d]\n",unit->getId(),unit->getFullName().c_str(), maxNodeCount,orgmaxNodeCount,unit->getPathfindFailedConsecutiveFrameCount());
|
|
||||||
}
|
|
||||||
|
|
||||||
UnitPathInterface *path= unit->getPath();
|
|
||||||
int unitFactionIndex = unit->getFactionIndex();
|
|
||||||
//factions[unitFactionIndex].nodePoolCount= 0;
|
|
||||||
//factions[unitFactionIndex].openNodesList.clear();
|
|
||||||
//factions[unitFactionIndex].openPosList.clear();
|
|
||||||
//factions[unitFactionIndex].closedNodesList.clear();
|
|
||||||
|
|
||||||
if(frameIndex >= 0) {
|
|
||||||
clearUnitPrecache(unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check the pre-cache to see if we can re-use a cached path
|
|
||||||
if(frameIndex < 0) {
|
|
||||||
if(factions[unitFactionIndex].precachedTravelState.find(unit->getId()) != factions[unitFactionIndex].precachedTravelState.end()) {
|
|
||||||
if(factions[unitFactionIndex].precachedTravelState[unit->getId()] == tsMoving) {
|
|
||||||
bool canMoveToCells = true;
|
|
||||||
|
|
||||||
Vec2i lastPos = unit->getPos();
|
|
||||||
for(int i=0; i < factions[unitFactionIndex].precachedPath[unit->getId()].size(); i++) {
|
|
||||||
Vec2i nodePos = factions[unitFactionIndex].precachedPath[unit->getId()][i];
|
|
||||||
if(map->isInside(nodePos) == false || map->isInsideSurface(map->toSurfCoords(nodePos)) == false) {
|
|
||||||
throw megaglest_runtime_error("Pathfinder invalid node path position = " + nodePos.getString() + " i = " + intToStr(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
//if(i < pathFindRefresh ||
|
|
||||||
if(i < unit->getPathFindRefreshCellCount() ||
|
|
||||||
(factions[unitFactionIndex].precachedPath[unit->getId()].size() >= pathFindExtendRefreshForNodeCount &&
|
|
||||||
i < getPathFindExtendRefreshNodeCount(unitFactionIndex))) {
|
|
||||||
//!!! Test MV
|
|
||||||
if(canUnitMoveSoon(unit, lastPos, nodePos) == false) {
|
|
||||||
canMoveToCells = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
lastPos = nodePos;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(canMoveToCells == true) {
|
|
||||||
path->clear();
|
|
||||||
UnitPathBasic *basicPathFinder = dynamic_cast<UnitPathBasic *>(path);
|
|
||||||
|
|
||||||
for(int i=0; i < factions[unitFactionIndex].precachedPath[unit->getId()].size(); i++) {
|
|
||||||
Vec2i nodePos = factions[unitFactionIndex].precachedPath[unit->getId()][i];
|
|
||||||
if(map->isInside(nodePos) == false || map->isInsideSurface(map->toSurfCoords(nodePos)) == false) {
|
|
||||||
throw megaglest_runtime_error("Pathfinder invalid node path position = " + nodePos.getString() + " i = " + intToStr(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
//if(i < pathFindRefresh ||
|
|
||||||
if(i < unit->getPathFindRefreshCellCount() ||
|
|
||||||
(factions[unitFactionIndex].precachedPath[unit->getId()].size() >= pathFindExtendRefreshForNodeCount &&
|
|
||||||
i < getPathFindExtendRefreshNodeCount(unitFactionIndex))) {
|
|
||||||
path->add(nodePos);
|
|
||||||
}
|
|
||||||
//else if(tryLastPathCache == false) {
|
|
||||||
// break;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//if(tryLastPathCache == true && basicPathFinder) {
|
|
||||||
if(basicPathFinder) {
|
|
||||||
basicPathFinder->addToLastPathCache(nodePos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unit->setUsePathfinderExtendedMaxNodes(false);
|
|
||||||
return factions[unitFactionIndex].precachedTravelState[unit->getId()];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
clearUnitPrecache(unit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(factions[unitFactionIndex].precachedTravelState[unit->getId()] == tsBlocked) {
|
|
||||||
path->incBlockCount();
|
|
||||||
unit->setUsePathfinderExtendedMaxNodes(false);
|
|
||||||
return factions[unitFactionIndex].precachedTravelState[unit->getId()];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
clearUnitPrecache(unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vec2i unitPos = unit->getPos();
|
|
||||||
finalPos= computeNearestFreePos(unit, finalPos);
|
|
||||||
|
|
||||||
float dist= unitPos.dist(finalPos);
|
|
||||||
factions[unitFactionIndex].useMaxNodeCount = PathFinder::pathFindNodesMax;
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
|
||||||
|
|
||||||
// Check the previous path find cache for the unit to see if its good to
|
|
||||||
// use
|
|
||||||
const bool showConsoleDebugInfo = Config::getInstance().getBool("EnablePathfinderDistanceOutput","false");
|
|
||||||
const bool tryLastPathCache = Config::getInstance().getBool("EnablePathfinderCache","false");
|
|
||||||
|
|
||||||
if(showConsoleDebugInfo || tryLastPathCache) {
|
|
||||||
if(showConsoleDebugInfo && dist > 60) printf("Distance from [%d - %s] to destination is %.2f tryLastPathCache = %d\n",unit->getId(),unit->getFullName().c_str(), dist,tryLastPathCache);
|
|
||||||
|
|
||||||
if(tryLastPathCache == true && path != NULL) {
|
|
||||||
UnitPathBasic *basicPathFinder = dynamic_cast<UnitPathBasic *>(path);
|
|
||||||
if(basicPathFinder != NULL && basicPathFinder->getLastPathCacheQueueCount() > 0) {
|
|
||||||
vector<Vec2i> cachedPath= basicPathFinder->getLastPathCacheQueue();
|
|
||||||
for(int i = 0; i < cachedPath.size(); ++i) {
|
|
||||||
Vec2i &pos1 = cachedPath[i];
|
|
||||||
// Looking to find if the unit is in one of the cells in the cached path
|
|
||||||
if(unitPos == pos1) {
|
|
||||||
// Now see if we can re-use this path to get to the final destination
|
|
||||||
for(int j = i+1; j < cachedPath.size(); ++j) {
|
|
||||||
Vec2i &pos2 = cachedPath[j];
|
|
||||||
bool canUnitMoveToCell = map->aproxCanMove(unit, pos1, pos2);
|
|
||||||
if(canUnitMoveToCell == true) {
|
|
||||||
if(pos2 == finalPos) {
|
|
||||||
//on the way
|
|
||||||
ts= tsMoving;
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
|
||||||
|
|
||||||
//store path
|
|
||||||
if(frameIndex < 0) {
|
|
||||||
basicPathFinder->clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
int pathCount=0;
|
|
||||||
for(int k=i+1; k <= j; k++) {
|
|
||||||
if(k >= cachedPath.size()) {
|
|
||||||
throw megaglest_runtime_error("k >= cachedPath.size() k = " + intToStr(k) + " cachedPath.size() = " + intToStr(cachedPath.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(frameIndex >= 0) {
|
|
||||||
factions[unitFactionIndex].precachedPath[unit->getId()].push_back(cachedPath[k]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//if(pathCount < pathFindRefresh) {
|
|
||||||
if(pathCount < unit->getPathFindRefreshCellCount()) {
|
|
||||||
basicPathFinder->add(cachedPath[k]);
|
|
||||||
}
|
|
||||||
basicPathFinder->addToLastPathCache(cachedPath[k]);
|
|
||||||
}
|
|
||||||
pathCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
|
|
||||||
char szBuf[4096]="";
|
|
||||||
sprintf(szBuf,"[Setting new path for unit] openNodesList.size() [%lu] openPosList.size() [%lu] finalPos [%s] inBailout [%d] ts [%d]",
|
|
||||||
factions[unitFactionIndex].openNodesList.size(),factions[unitFactionIndex].openPosList.size(),finalPos.getString().c_str(),inBailout,ts);
|
|
||||||
unit->logSynchData(__FILE__,__LINE__,szBuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) {
|
|
||||||
string commandDesc = "none";
|
|
||||||
Command *command= unit->getCurrCommand();
|
|
||||||
if(command != NULL && command->getCommandType() != NULL) {
|
|
||||||
commandDesc = command->getCommandType()->toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
char szBuf[1024]="";
|
|
||||||
sprintf(szBuf,"State: moving, cmd [%s] pos: %s Queue= %d",commandDesc.c_str(),unit->getPos().getString().c_str(), path->getQueueCount());
|
|
||||||
unit->setCurrentUnitTitle(szBuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
|
||||||
|
|
||||||
unit->setUsePathfinderExtendedMaxNodes(false);
|
|
||||||
return ts;
|
|
||||||
}
|
|
||||||
//else if(j - i > pathFindRefresh) {
|
|
||||||
else if(j - i > unit->getPathFindRefreshCellCount()) {
|
|
||||||
//on the way
|
|
||||||
ts= tsMoving;
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
|
||||||
|
|
||||||
//store path
|
|
||||||
if(frameIndex < 0) {
|
|
||||||
basicPathFinder->clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
int pathCount=0;
|
|
||||||
for(int k=i+1; k < cachedPath.size(); k++) {
|
|
||||||
if(k >= cachedPath.size()) {
|
|
||||||
throw megaglest_runtime_error("#2 k >= cachedPath.size() k = " + intToStr(k) + " cachedPath.size() = " + intToStr(cachedPath.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(frameIndex >= 0) {
|
|
||||||
factions[unitFactionIndex].precachedPath[unit->getId()].push_back(cachedPath[k]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//if(pathCount < pathFindRefresh) {
|
|
||||||
if(pathCount < unit->getPathFindRefreshCellCount()) {
|
|
||||||
basicPathFinder->add(cachedPath[k]);
|
|
||||||
}
|
|
||||||
basicPathFinder->addToLastPathCache(cachedPath[k]);
|
|
||||||
}
|
|
||||||
pathCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
|
|
||||||
char szBuf[4096]="";
|
|
||||||
sprintf(szBuf,"[Setting new path for unit] openNodesList.size() [%lu] openPosList.size() [%lu] finalPos [%s] inBailout [%d] ts [%d]",
|
|
||||||
factions[unitFactionIndex].openNodesList.size(),factions[unitFactionIndex].openPosList.size(),finalPos.getString().c_str(),inBailout,ts);
|
|
||||||
unit->logSynchData(__FILE__,__LINE__,szBuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) {
|
|
||||||
string commandDesc = "none";
|
|
||||||
Command *command= unit->getCurrCommand();
|
|
||||||
if(command != NULL && command->getCommandType() != NULL) {
|
|
||||||
commandDesc = command->getCommandType()->toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
char szBuf[1024]="";
|
|
||||||
sprintf(szBuf,"State: moving, cmd [%s] pos: %s Queue= %d",commandDesc.c_str(),unit->getPos().getString().c_str(), path->getQueueCount());
|
|
||||||
unit->setCurrentUnitTitle(szBuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
|
||||||
|
|
||||||
unit->setUsePathfinderExtendedMaxNodes(false);
|
|
||||||
return ts;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pos1 = pos2;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//path find algorithm
|
|
||||||
|
|
||||||
//b) loop
|
|
||||||
bool pathFound = true;
|
|
||||||
bool nodeLimitReached = false;
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
|
||||||
|
|
||||||
// First check if unit currently blocked all around them, if so don't try to pathfind
|
|
||||||
if(inBailout == false && unitPos != finalPos) {
|
|
||||||
int failureCount = 0;
|
|
||||||
int cellCount = 0;
|
|
||||||
|
|
||||||
for(int i = -1; i <= 1; ++i) {
|
|
||||||
for(int j = -1; j <= 1; ++j) {
|
|
||||||
Vec2i pos = unitPos + Vec2i(i, j);
|
|
||||||
if(pos != unitPos) {
|
|
||||||
//!!! Test MV
|
|
||||||
bool canUnitMoveToCell = canUnitMoveSoon(unit, unitPos, pos);
|
|
||||||
if(canUnitMoveToCell == false) {
|
|
||||||
failureCount++;
|
|
||||||
}
|
|
||||||
cellCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nodeLimitReached = (failureCount == cellCount);
|
|
||||||
pathFound = !nodeLimitReached;
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] **Check if dest blocked, distance for unit [%d - %s] from [%s] to [%s] is %.2f took msecs: %lld nodeLimitReached = %d, failureCount = %d\n",__FILE__,__FUNCTION__,__LINE__,unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),nodeLimitReached,failureCount);
|
|
||||||
if(showConsoleDebugInfo && nodeLimitReached) {
|
|
||||||
printf("**Check if src blocked [%d - %d], unit [%d - %s] from [%s] to [%s] distance %.2f took msecs: %lld nodeLimitReached = %d, failureCount = %d [%d]\n",
|
|
||||||
nodeLimitReached, inBailout, unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),nodeLimitReached,failureCount,cellCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(nodeLimitReached == false) {
|
|
||||||
// First check if final destination blocked
|
|
||||||
failureCount = 0;
|
|
||||||
cellCount = 0;
|
|
||||||
|
|
||||||
for(int i = -1; i <= 1; ++i) {
|
|
||||||
for(int j = -1; j <= 1; ++j) {
|
|
||||||
Vec2i pos = finalPos + Vec2i(i, j);
|
|
||||||
if(pos != finalPos) {
|
|
||||||
//!!! Test MV
|
|
||||||
bool canUnitMoveToCell = canUnitMoveSoon(unit, pos, finalPos);
|
|
||||||
if(canUnitMoveToCell == false) {
|
|
||||||
failureCount++;
|
|
||||||
}
|
|
||||||
cellCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nodeLimitReached = (failureCount == cellCount);
|
|
||||||
pathFound = !nodeLimitReached;
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] **Check if dest blocked, distance for unit [%d - %s] from [%s] to [%s] is %.2f took msecs: %lld nodeLimitReached = %d, failureCount = %d\n",__FILE__,__FUNCTION__,__LINE__,unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),nodeLimitReached,failureCount);
|
|
||||||
if(showConsoleDebugInfo && nodeLimitReached) {
|
|
||||||
printf("**Check if dest blocked [%d - %d], unit [%d - %s] from [%s] to [%s] distance %.2f took msecs: %lld nodeLimitReached = %d, failureCount = %d [%d]\n",
|
|
||||||
nodeLimitReached, inBailout, unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),nodeLimitReached,failureCount,cellCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
|
|
||||||
//finalPos= computeNearestFreePos(unit, finalPos);
|
|
||||||
|
|
||||||
FastAINodeCache nodeCache(unit);
|
|
||||||
// Start of New Fast AStar
|
|
||||||
FastAINode *fromNode = map->getCellNode(unit->getPos());
|
|
||||||
FastAINode *toNode = map->getCellNode(finalPos);
|
|
||||||
//FastAstar *fa = createFastAstar();
|
|
||||||
FastAstar *fa = factions[unitFactionIndex].fa;
|
|
||||||
astarStartSearch(fa,fromNode,toNode, &nodeCache);
|
|
||||||
|
|
||||||
pathFound = false;
|
|
||||||
unsigned int nodeSearchCount=0;
|
|
||||||
unsigned int count=0;
|
|
||||||
AI_Node **solution = NULL;
|
|
||||||
if(nodeLimitReached == false) {
|
|
||||||
for(nodeSearchCount=0; pathFound == false && nodeSearchCount < maxNodeCount; ++nodeSearchCount) {
|
|
||||||
unsigned int search_count=0;
|
|
||||||
pathFound = astarSearchStep(fa,search_count);
|
|
||||||
//printf("Fast Pathfind Unit [%d - %s] finished = %d search_count = %d i = %d\n",unit->getId(),unit->getType()->getName().c_str(),finished,search_count,i);
|
|
||||||
}
|
|
||||||
|
|
||||||
solution = getSolution(fa,count);
|
|
||||||
}
|
|
||||||
if(searched_node_count != NULL) {
|
|
||||||
*searched_node_count = nodeSearchCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(count <= 1 || getLastSearchState(fa) != SEARCH_STATE_SUCCEEDED) {
|
|
||||||
if(minorDebugPathfinder) printf("Fast Pathfind Unit [%d - %s] NOT FOUND PATH frameIndex = %d nodeSearchCount = %d\n",unit->getId(),unit->getType()->getName().c_str(),frameIndex,nodeSearchCount);
|
|
||||||
|
|
||||||
//blocked
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) {
|
|
||||||
string commandDesc = "none";
|
|
||||||
Command *command= unit->getCurrCommand();
|
|
||||||
if(command != NULL && command->getCommandType() != NULL) {
|
|
||||||
commandDesc = command->getCommandType()->toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<Vec2i,int> lastHarvest = unit->getLastHarvestResourceTarget();
|
|
||||||
|
|
||||||
char szBuf[4096]="";
|
|
||||||
sprintf(szBuf,"State: blocked, cmd [%s] pos: [%s], lastHarvest = [%s - %d], reason C= %d, D= %d, F = %d",
|
|
||||||
commandDesc.c_str(),unit->getPos().getString().c_str(), lastHarvest.first.getString().c_str(),lastHarvest.second, path->getBlockCount(), path->isBlocked(), path->isStuck());
|
|
||||||
unit->setCurrentUnitTitle(szBuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(frameIndex < 0) {
|
|
||||||
unit->setUsePathfinderExtendedMaxNodes(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ts= tsBlocked;
|
|
||||||
if(frameIndex < 0) {
|
|
||||||
path->incBlockCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
|
|
||||||
char szBuf[4096]="";
|
|
||||||
sprintf(szBuf,"[path for unit BLOCKED] openNodesList.size() [%lu] openPosList.size() [%lu] finalPos [%s] ts [%d]",
|
|
||||||
factions[unitFactionIndex].openNodesList.size(),factions[unitFactionIndex].openPosList.size(),finalPos.getString().c_str(),ts);
|
|
||||||
unit->logSynchData(__FILE__,__LINE__,szBuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
|
||||||
|
|
||||||
unit->setLastStuckFrameToCurrentFrame();
|
|
||||||
unit->setLastStuckPos(finalPos);
|
|
||||||
|
|
||||||
// Now see if the unit is eligble for pathfind max nodes boost?
|
|
||||||
if(nodeSearchCount >= maxNodeCount) {
|
|
||||||
unit->incrementPathfindFailedConsecutiveFrameCount();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
unit->resetPathfindFailedConsecutiveFrameCount();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(minorDebugPathfinder) printf("Fast Pathfind Unit [%d - %s] FOUND PATH count = %d frameIndex = %d nodeSearchCount = %d\n",unit->getId(),unit->getType()->getName().c_str(),count,frameIndex,nodeSearchCount);
|
|
||||||
|
|
||||||
ts= tsMoving;
|
|
||||||
|
|
||||||
UnitPathInterface *path= unit->getPath();
|
|
||||||
|
|
||||||
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
|
||||||
if(frameIndex < 0) {
|
|
||||||
if(maxNodeCount == pathFindNodesAbsoluteMax) {
|
|
||||||
unit->setUsePathfinderExtendedMaxNodes(true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
unit->setUsePathfinderExtendedMaxNodes(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//store path
|
|
||||||
if(frameIndex < 0) {
|
|
||||||
path->clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
UnitPathBasic *basicPathFinder = dynamic_cast<UnitPathBasic *>(path);
|
|
||||||
|
|
||||||
for(int i=0; i < count; ++i) {
|
|
||||||
FastAINode *node = dynamic_cast<FastAINode *>(solution[i]);
|
|
||||||
const Vec2i &nodePos = node->getPos();
|
|
||||||
if(nodePos != unit->getPos()) {
|
|
||||||
if(map->isInside(nodePos) == false || map->isInsideSurface(map->toSurfCoords(nodePos)) == false) {
|
|
||||||
throw megaglest_runtime_error("Pathfinder invalid node path position = " + nodePos.getString() + " i = " + intToStr(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
//if(minorDebugPathfinder) printf("nodePos [%s]\n",nodePos.getString().c_str());
|
|
||||||
|
|
||||||
if(frameIndex >= 0) {
|
|
||||||
factions[unitFactionIndex].precachedPath[unit->getId()].push_back(nodePos);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//if(i < pathFindRefresh ||
|
|
||||||
if(i < unit->getPathFindRefreshCellCount() ||
|
|
||||||
(nodeSearchCount >= pathFindExtendRefreshForNodeCount &&
|
|
||||||
i < getPathFindExtendRefreshNodeCount(unitFactionIndex))) {
|
|
||||||
path->add(nodePos);
|
|
||||||
}
|
|
||||||
else if(tryLastPathCache == false) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//if(tryLastPathCache == true && basicPathFinder) {
|
|
||||||
if(basicPathFinder) {
|
|
||||||
basicPathFinder->addToLastPathCache(nodePos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
|
|
||||||
char szBuf[4096]="";
|
|
||||||
sprintf(szBuf,"[Setting new path for unit] openNodesList.size() [%lu] openPosList.size() [%lu] finalPos [%s] ts [%d]",
|
|
||||||
factions[unitFactionIndex].openNodesList.size(),factions[unitFactionIndex].openPosList.size(),finalPos.getString().c_str(),ts);
|
|
||||||
unit->logSynchData(__FILE__,__LINE__,szBuf);
|
|
||||||
|
|
||||||
string pathToTake = "";
|
|
||||||
for(int i = 0; i < path->getQueueCount(); ++i) {
|
|
||||||
Vec2i &pos = path->getQueue()[i];
|
|
||||||
if(pathToTake != "") {
|
|
||||||
pathToTake += ", ";
|
|
||||||
}
|
|
||||||
pathToTake += pos.getString();
|
|
||||||
}
|
|
||||||
unit->logSynchData(__FILE__,__LINE__,szBuf);
|
|
||||||
sprintf(szBuf,"Path for unit to take = %s",pathToTake.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) {
|
|
||||||
string commandDesc = "none";
|
|
||||||
Command *command= unit->getCurrCommand();
|
|
||||||
if(command != NULL && command->getCommandType() != NULL) {
|
|
||||||
commandDesc = command->getCommandType()->toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
char szBuf[1024]="";
|
|
||||||
sprintf(szBuf,"State: moving, cmd [%s] pos: %s, Queue= %d",commandDesc.c_str(),unit->getPos().getString().c_str(), path->getQueueCount());
|
|
||||||
unit->setCurrentUnitTitle(szBuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
|
||||||
}
|
|
||||||
//releaseFastAstar(fa);
|
|
||||||
|
|
||||||
// End of New Fast AStar
|
|
||||||
|
|
||||||
//factions[unitFactionIndex].openNodesList.clear();
|
|
||||||
//factions[unitFactionIndex].openPosList.clear();
|
|
||||||
//factions[unitFactionIndex].closedNodesList.clear();
|
|
||||||
|
|
||||||
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [END OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
|
|
||||||
|
|
||||||
if(frameIndex >= 0) {
|
|
||||||
factions[unitFactionIndex].precachedTravelState[unit->getId()] = ts;
|
|
||||||
}
|
|
||||||
//else {
|
|
||||||
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() >= 1) printf("In [%s::%s Line: %d] fastastar took [%lld] msecs, ts = %d nodeSearchCount = %d.\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis(),ts,nodeSearchCount);
|
|
||||||
//if(chrono.getMillis() >= 1) printf("In [%s::%s Line: %d] fastastar took [%lld] msecs, ts = %d nodeSearchCount = %d.\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis(),ts,nodeSearchCount);
|
|
||||||
//}
|
|
||||||
|
|
||||||
return ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PathFinder::addToOpenSet(Unit *unit, Node *node,const Vec2i finalPos, Vec2i sucPos, bool &nodeLimitReached,int maxNodeCount,Node **newNodeAdded, bool bypassChecks) {
|
bool PathFinder::addToOpenSet(Unit *unit, Node *node,const Vec2i finalPos, Vec2i sucPos, bool &nodeLimitReached,int maxNodeCount,Node **newNodeAdded, bool bypassChecks) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "skill_type.h"
|
#include "skill_type.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
#include "fast_path_finder.h"
|
|
||||||
//#include <tr1/unordered_map>
|
//#include <tr1/unordered_map>
|
||||||
//using namespace std::tr1;
|
//using namespace std::tr1;
|
||||||
|
|
||||||
|
@ -114,8 +114,6 @@ public:
|
||||||
//mapFromToNodeList.clear();
|
//mapFromToNodeList.clear();
|
||||||
//lastFromToNodeListFrame = -100;
|
//lastFromToNodeListFrame = -100;
|
||||||
badCellList.clear();
|
badCellList.clear();
|
||||||
|
|
||||||
fa = createFastAstar();
|
|
||||||
}
|
}
|
||||||
~FactionState() {
|
~FactionState() {
|
||||||
//fa = NULL;
|
//fa = NULL;
|
||||||
|
@ -135,8 +133,6 @@ public:
|
||||||
//std::map<int, std::map<Vec2i,std::map<Vec2i, bool> > > mapFromToNodeList;
|
//std::map<int, std::map<Vec2i,std::map<Vec2i, bool> > > mapFromToNodeList;
|
||||||
|
|
||||||
std::map<int,std::map<Field,BadUnitNodeList> > badCellList;
|
std::map<int,std::map<Field,BadUnitNodeList> > badCellList;
|
||||||
|
|
||||||
FastAstar *fa;
|
|
||||||
};
|
};
|
||||||
typedef vector<FactionState> FactionStateList;
|
typedef vector<FactionState> FactionStateList;
|
||||||
|
|
||||||
|
@ -173,7 +169,6 @@ public:
|
||||||
void loadGame(const XmlNode *rootNode);
|
void loadGame(const XmlNode *rootNode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TravelState aStarFast(Unit *unit, Vec2i finalPos, bool inBailout, int frameIndex, int maxNodeCount=-1,uint32 *searched_node_count=NULL);
|
|
||||||
TravelState aStar(Unit *unit, const Vec2i &finalPos, bool inBailout, int frameIndex, int maxNodeCount=-1,uint32 *searched_node_count=NULL);
|
TravelState aStar(Unit *unit, const Vec2i &finalPos, bool inBailout, int frameIndex, int maxNodeCount=-1,uint32 *searched_node_count=NULL);
|
||||||
//Node *newNode(FactionState &faction,int maxNodeCount);
|
//Node *newNode(FactionState &faction,int maxNodeCount);
|
||||||
inline static Node *newNode(FactionState &faction, int maxNodeCount) {
|
inline static Node *newNode(FactionState &faction, int maxNodeCount) {
|
||||||
|
|
|
@ -279,142 +279,6 @@ void SurfaceCell::loadGame(const XmlNode *rootNode, int index, World *world) {
|
||||||
// class Map
|
// class Map
|
||||||
// =====================================================
|
// =====================================================
|
||||||
|
|
||||||
FastAINode * FastAINode::getNodeForEdgeIndex(int index,void *userData) const {
|
|
||||||
FastAINode *resultNode = NULL;
|
|
||||||
switch(index) {
|
|
||||||
case 0: // north
|
|
||||||
resultNode = map->getCellNode(pos.x,pos.y-1,false);
|
|
||||||
break;
|
|
||||||
case 1: // north east
|
|
||||||
resultNode = map->getCellNode(pos.x+1,pos.y-1,false);
|
|
||||||
break;
|
|
||||||
case 2: // east
|
|
||||||
resultNode = map->getCellNode(pos.x+1,pos.y,false);
|
|
||||||
break;
|
|
||||||
case 3: // south east
|
|
||||||
resultNode = map->getCellNode(pos.x+1,pos.y+1,false);
|
|
||||||
break;
|
|
||||||
case 4: // south
|
|
||||||
resultNode = map->getCellNode(pos.x,pos.y+1,false);
|
|
||||||
break;
|
|
||||||
case 5: // south west
|
|
||||||
resultNode = map->getCellNode(pos.x-1,pos.y+1,false);
|
|
||||||
break;
|
|
||||||
case 6: // west
|
|
||||||
resultNode = map->getCellNode(pos.x-1,pos.y,false);
|
|
||||||
break;
|
|
||||||
case 7: // north west
|
|
||||||
resultNode = map->getCellNode(pos.x-1,pos.y-1,false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
bool checkCellObjects = true;
|
|
||||||
if(checkCellObjects == true && resultNode != NULL) {
|
|
||||||
FastAINodeCache *nodeCache = (FastAINodeCache *)userData;
|
|
||||||
std::map<Vec2i,std::map<Vec2i,bool> >::const_iterator iterFind = nodeCache->cachedCanMoveSoonList.find(pos);
|
|
||||||
if(iterFind != nodeCache->cachedCanMoveSoonList.end() &&
|
|
||||||
iterFind->second.find(resultNode->getPos()) != iterFind->second.end()) {
|
|
||||||
const std::map<Vec2i,bool> &mapCache2 = iterFind->second;
|
|
||||||
std::map<Vec2i,bool>::const_iterator iterFind2 = mapCache2.find(resultNode->getPos());
|
|
||||||
|
|
||||||
if(iterFind2->second == false) {
|
|
||||||
resultNode = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const Vec2i &nodePos = resultNode->getPos();
|
|
||||||
|
|
||||||
if(resultNode->getPos() != nodeCache->unit->getCurrentPathFinderDesiredFinalPos()) {
|
|
||||||
if(map->aproxCanMoveSoon(nodeCache->unit, pos, resultNode->getPos()) == false) {
|
|
||||||
resultNode = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeCache->cachedCanMoveSoonList[pos][nodePos] = (resultNode != NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resultNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
float FastAINode::getDistance(const AI_Node *node,void *userData) {
|
|
||||||
return pos.dist(dynamic_cast<const FastAINode *>(node)->pos);
|
|
||||||
}
|
|
||||||
float FastAINode::getCost(void *userData) {
|
|
||||||
float result = 1.0f;
|
|
||||||
|
|
||||||
// FastAINodeCache *nodeCache = (FastAINodeCache *)userData;
|
|
||||||
// if(map->aproxCanMoveSoon(nodeCache->unit, pos, pos) == false) {
|
|
||||||
// result = 100000;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// bool checkCellObjects = true;
|
|
||||||
// if(checkCellObjects == true) {
|
|
||||||
// FastAINode *resultNode = map->getCellNode(pos,false);
|
|
||||||
// if(resultNode != NULL) {
|
|
||||||
// FastAINodeCache *nodeCache = (FastAINodeCache *)userData;
|
|
||||||
// std::map<Vec2i,std::map<Vec2i,bool> >::const_iterator iterFind = nodeCache->cachedCanMoveSoonList.find(pos);
|
|
||||||
// if(iterFind != nodeCache->cachedCanMoveSoonList.end() &&
|
|
||||||
// iterFind->second.find(resultNode->getPos()) != iterFind->second.end()) {
|
|
||||||
// const std::map<Vec2i,bool> &mapCache2 = iterFind->second;
|
|
||||||
// std::map<Vec2i,bool>::const_iterator iterFind2 = mapCache2.find(resultNode->getPos());
|
|
||||||
//
|
|
||||||
// if(iterFind2->second == false) {
|
|
||||||
// resultNode = NULL;
|
|
||||||
// result = 9999999;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// const Vec2i &nodePos = resultNode->getPos();
|
|
||||||
//
|
|
||||||
// if(resultNode->getPos() != nodeCache->unit->getCurrentPathFinderDesiredFinalPos()) {
|
|
||||||
// if(map->aproxCanMoveSoon(nodeCache->unit, pos, resultNode->getPos()) == false) {
|
|
||||||
// resultNode = NULL;
|
|
||||||
// result = 9999999;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// nodeCache->cachedCanMoveSoonList[pos][nodePos] = (resultNode != NULL);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int FastAINode::getEdgeCount(void *userData) const {
|
|
||||||
unsigned int result = 0;
|
|
||||||
for(unsigned int index = 0; index < NODE_EDGE_COUNT; ++index) {
|
|
||||||
FastAINode *resultNode = getNodeForEdgeIndex(index,userData);
|
|
||||||
if(resultNode != NULL) {
|
|
||||||
result++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
AI_Node * FastAINode::getEdge(int index,void *userData) const {
|
|
||||||
FastAINode *result = NULL;
|
|
||||||
|
|
||||||
unsigned int edgeCount = getEdgeCount(userData);
|
|
||||||
if(edgeCount < NODE_EDGE_COUNT) {
|
|
||||||
int edgeIndex = -1;
|
|
||||||
|
|
||||||
for(unsigned int index2 = 0; index2 < NODE_EDGE_COUNT; ++index2) {
|
|
||||||
result = getNodeForEdgeIndex(index2,userData);
|
|
||||||
if(result != NULL) {
|
|
||||||
edgeIndex++;
|
|
||||||
|
|
||||||
if(edgeIndex == index) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = NULL;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = getNodeForEdgeIndex(index,userData);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ===================== PUBLIC ========================
|
// ===================== PUBLIC ========================
|
||||||
|
|
||||||
const int Map::cellScale= 2;
|
const int Map::cellScale= 2;
|
||||||
|
@ -423,7 +287,6 @@ const int Map::mapScale= 2;
|
||||||
Map::Map() {
|
Map::Map() {
|
||||||
cells= NULL;
|
cells= NULL;
|
||||||
surfaceCells= NULL;
|
surfaceCells= NULL;
|
||||||
cellNodes=NULL;
|
|
||||||
startLocations= NULL;
|
startLocations= NULL;
|
||||||
|
|
||||||
title="";
|
title="";
|
||||||
|
@ -446,8 +309,6 @@ Map::~Map() {
|
||||||
cells = NULL;
|
cells = NULL;
|
||||||
delete [] surfaceCells;
|
delete [] surfaceCells;
|
||||||
surfaceCells = NULL;
|
surfaceCells = NULL;
|
||||||
delete [] cellNodes;
|
|
||||||
cellNodes = NULL;
|
|
||||||
delete [] startLocations;
|
delete [] startLocations;
|
||||||
startLocations = NULL;
|
startLocations = NULL;
|
||||||
}
|
}
|
||||||
|
@ -545,14 +406,6 @@ Checksum Map::load(const string &path, TechTree *techTree, Tileset *tileset) {
|
||||||
|
|
||||||
//cells
|
//cells
|
||||||
cells= new Cell[getCellArraySize()];
|
cells= new Cell[getCellArraySize()];
|
||||||
cellNodes = new FastAINode[getCellArraySize()];
|
|
||||||
for(unsigned int x = 0; x < w; ++x) {
|
|
||||||
for(unsigned int y = 0; y < h; ++y) {
|
|
||||||
int arrayIndex = y * w + x;
|
|
||||||
FastAINode &cellNode = cellNodes[arrayIndex];
|
|
||||||
cellNode.setData(Vec2i(x,y),this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
surfaceCells= new SurfaceCell[getSurfaceCellArraySize()];
|
surfaceCells= new SurfaceCell[getSurfaceCellArraySize()];
|
||||||
|
|
||||||
//read heightmap
|
//read heightmap
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "selection.h"
|
#include "selection.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "unit_type.h"
|
#include "unit_type.h"
|
||||||
#include "fast_path_finder.h"
|
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "checksum.h"
|
#include "checksum.h"
|
||||||
#include "leak_dumper.h"
|
#include "leak_dumper.h"
|
||||||
|
@ -204,47 +203,6 @@ public:
|
||||||
std::map<Vec2i,std::map<Vec2i,bool> > cachedCanMoveSoonList;
|
std::map<Vec2i,std::map<Vec2i,bool> > cachedCanMoveSoonList;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FastAINode : public AI_Node {
|
|
||||||
protected:
|
|
||||||
Vec2i pos;
|
|
||||||
const Map *map;
|
|
||||||
int32 hashCode;
|
|
||||||
static const int NODE_EDGE_COUNT = 8;
|
|
||||||
|
|
||||||
FastAINode * getNodeForEdgeIndex(int index,void *userData) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
FastAINode() {
|
|
||||||
this->map = NULL;
|
|
||||||
hashCode=0;
|
|
||||||
}
|
|
||||||
FastAINode(Vec2i &pos,const Map *map) {
|
|
||||||
this->pos = pos;
|
|
||||||
this->map = map;
|
|
||||||
Checksum result;
|
|
||||||
result.addInt(pos.x);
|
|
||||||
result.addInt(pos.y);
|
|
||||||
hashCode = result.getSum();
|
|
||||||
}
|
|
||||||
virtual ~FastAINode() {}
|
|
||||||
void setData(Vec2i pos, const Map *map) {
|
|
||||||
this->pos = pos;
|
|
||||||
this->map = map;
|
|
||||||
Checksum result;
|
|
||||||
result.addInt(pos.x);
|
|
||||||
result.addInt(pos.y);
|
|
||||||
hashCode = result.getSum();
|
|
||||||
}
|
|
||||||
inline const Vec2i & getPos() const { return pos; }
|
|
||||||
|
|
||||||
virtual float getDistance(const AI_Node *node, void *userData);
|
|
||||||
virtual float getCost(void *userData);
|
|
||||||
virtual unsigned int getEdgeCount(void *userData) const;
|
|
||||||
virtual AI_Node * getEdge(int index, void *userData) const;
|
|
||||||
inline virtual int32 getHashCode() const { return hashCode; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class Map {
|
class Map {
|
||||||
public:
|
public:
|
||||||
static const int cellScale; //number of cells per surfaceCell
|
static const int cellScale; //number of cells per surfaceCell
|
||||||
|
@ -263,7 +221,6 @@ private:
|
||||||
int maxPlayers;
|
int maxPlayers;
|
||||||
Cell *cells;
|
Cell *cells;
|
||||||
SurfaceCell *surfaceCells;
|
SurfaceCell *surfaceCells;
|
||||||
FastAINode *cellNodes;
|
|
||||||
Vec2i *startLocations;
|
Vec2i *startLocations;
|
||||||
Checksum checksumValue;
|
Checksum checksumValue;
|
||||||
float maxMapHeight;
|
float maxMapHeight;
|
||||||
|
@ -306,30 +263,6 @@ public:
|
||||||
return getCell(pos.x, pos.y);
|
return getCell(pos.x, pos.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
//get
|
|
||||||
inline FastAINode *getCellNode(Vec2i pos, bool errorOnInvalid=true) const {
|
|
||||||
return getCellNode(pos.x, pos.y, errorOnInvalid);
|
|
||||||
}
|
|
||||||
inline FastAINode *getCellNode(int x, int y, bool errorOnInvalid=true) const {
|
|
||||||
int arrayIndex = y * w + x;
|
|
||||||
if(arrayIndex < 0 || arrayIndex >= getCellArraySize()) {
|
|
||||||
if(errorOnInvalid == false) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
//abort();
|
|
||||||
throw megaglest_runtime_error("arrayIndex >= getCellArraySize(), arrayIndex = " + intToStr(arrayIndex) + " w = " + intToStr(w) + " h = " + intToStr(h));
|
|
||||||
}
|
|
||||||
else if(cellNodes == NULL) {
|
|
||||||
if(errorOnInvalid == false) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw megaglest_runtime_error("cellNodes == NULL");
|
|
||||||
}
|
|
||||||
|
|
||||||
return &cellNodes[arrayIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int getCellArraySize() const {
|
inline int getCellArraySize() const {
|
||||||
return (w * h);
|
return (w * h);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user