- 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 "faction.h"
|
||||
#include "randomgen.h"
|
||||
#include "fast_path_finder.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace std;
|
||||
|
@ -87,9 +86,6 @@ void PathFinder::init(const Map *map) {
|
|||
PathFinder::~PathFinder() {
|
||||
for(int i = 0; i < GameConstants::maxPlayers; ++i) {
|
||||
factions[i].nodePool.clear();
|
||||
|
||||
releaseFastAstar(factions[i].fa);
|
||||
factions[i].fa = NULL;
|
||||
}
|
||||
factions.clear();
|
||||
map=NULL;
|
||||
|
@ -229,18 +225,9 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
|
|||
|
||||
uint32 searched_node_count = 0;
|
||||
minorDebugPathfinder = false;
|
||||
//bool enableFastPathfinder = Config::getInstance().getBool("EnableFastPathFinder","false");
|
||||
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);
|
||||
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 = aStarFast(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);
|
||||
}
|
||||
ts = aStar(unit, finalPos, false, frameIndex, maxNodeCount,&searched_node_count);
|
||||
|
||||
//post actions
|
||||
switch(ts) {
|
||||
|
@ -317,12 +304,7 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
|
|||
|
||||
int maxBailoutNodeCount = (PathFinder::pathFindBailoutRadius * 2);
|
||||
|
||||
if(enableFastPathfinder == true) {
|
||||
ts= aStarFast(unit, newFinalPos, true, frameIndex, maxBailoutNodeCount,&searched_node_count);
|
||||
}
|
||||
else {
|
||||
ts= aStar(unit, newFinalPos, true, frameIndex, maxBailoutNodeCount,&searched_node_count);
|
||||
}
|
||||
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());
|
||||
int maxBailoutNodeCount = (PathFinder::pathFindBailoutRadius * 2);
|
||||
|
||||
if(enableFastPathfinder == true) {
|
||||
ts= aStarFast(unit, newFinalPos, true, frameIndex, maxBailoutNodeCount,&searched_node_count);
|
||||
}
|
||||
else {
|
||||
ts= aStar(unit, newFinalPos, true, frameIndex, maxBailoutNodeCount,&searched_node_count);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
//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);
|
||||
|
||||
return ts;
|
||||
|
@ -436,511 +412,6 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
|
|||
|
||||
// ==================== 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 result = false;
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "skill_type.h"
|
||||
#include "map.h"
|
||||
#include "unit.h"
|
||||
#include "fast_path_finder.h"
|
||||
|
||||
//#include <tr1/unordered_map>
|
||||
//using namespace std::tr1;
|
||||
|
||||
|
@ -114,8 +114,6 @@ public:
|
|||
//mapFromToNodeList.clear();
|
||||
//lastFromToNodeListFrame = -100;
|
||||
badCellList.clear();
|
||||
|
||||
fa = createFastAstar();
|
||||
}
|
||||
~FactionState() {
|
||||
//fa = NULL;
|
||||
|
@ -135,8 +133,6 @@ public:
|
|||
//std::map<int, std::map<Vec2i,std::map<Vec2i, bool> > > mapFromToNodeList;
|
||||
|
||||
std::map<int,std::map<Field,BadUnitNodeList> > badCellList;
|
||||
|
||||
FastAstar *fa;
|
||||
};
|
||||
typedef vector<FactionState> FactionStateList;
|
||||
|
||||
|
@ -173,7 +169,6 @@ public:
|
|||
void loadGame(const XmlNode *rootNode);
|
||||
|
||||
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);
|
||||
//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
|
||||
// =====================================================
|
||||
|
||||
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 ========================
|
||||
|
||||
const int Map::cellScale= 2;
|
||||
|
@ -423,7 +287,6 @@ const int Map::mapScale= 2;
|
|||
Map::Map() {
|
||||
cells= NULL;
|
||||
surfaceCells= NULL;
|
||||
cellNodes=NULL;
|
||||
startLocations= NULL;
|
||||
|
||||
title="";
|
||||
|
@ -446,8 +309,6 @@ Map::~Map() {
|
|||
cells = NULL;
|
||||
delete [] surfaceCells;
|
||||
surfaceCells = NULL;
|
||||
delete [] cellNodes;
|
||||
cellNodes = NULL;
|
||||
delete [] startLocations;
|
||||
startLocations = NULL;
|
||||
}
|
||||
|
@ -545,14 +406,6 @@ Checksum Map::load(const string &path, TechTree *techTree, Tileset *tileset) {
|
|||
|
||||
//cells
|
||||
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()];
|
||||
|
||||
//read heightmap
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "selection.h"
|
||||
#include <cassert>
|
||||
#include "unit_type.h"
|
||||
#include "fast_path_finder.h"
|
||||
#include "command.h"
|
||||
#include "checksum.h"
|
||||
#include "leak_dumper.h"
|
||||
|
@ -204,47 +203,6 @@ public:
|
|||
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 {
|
||||
public:
|
||||
static const int cellScale; //number of cells per surfaceCell
|
||||
|
@ -263,7 +221,6 @@ private:
|
|||
int maxPlayers;
|
||||
Cell *cells;
|
||||
SurfaceCell *surfaceCells;
|
||||
FastAINode *cellNodes;
|
||||
Vec2i *startLocations;
|
||||
Checksum checksumValue;
|
||||
float maxMapHeight;
|
||||
|
@ -306,30 +263,6 @@ public:
|
|||
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 {
|
||||
return (w * h);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue