- speed up the pathfinder a bit

This commit is contained in:
Mark Vejvoda 2012-04-21 03:42:25 +00:00
parent 12a76aec02
commit b8fb60b325
11 changed files with 179 additions and 204 deletions

View File

@ -1093,98 +1093,9 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
const bool tryJPSPathfinder = false;
while(nodeLimitReached == false) {
whileLoopCount++;
//b1) is open nodes is empty => failed to find the path
if(factions[unitFactionIndex].openNodesList.empty() == true) {
//printf("$$$$ Path for Unit [%d - %s] inBailout = %d BLOCKED\n",unit->getId(),unit->getFullName().c_str(),inBailout);
//printf("Path blocked\n");
pathFound= false;
break;
}
//b2) get the minimum heuristic node
//Nodes::iterator it = minHeuristic();
node = minHeuristicFastLookup(factions[unitFactionIndex]);
//printf("current node [%s]\n",node->pos.getString().c_str());
//b3) if minHeuristic is the finalNode, or the path is no more explored => path was found
if(node->pos == finalPos || node->exploredCell == false) {
//printf("Path found\n");
pathFound= true;
break;
}
if(tryJPSPathfinder == true) {
closedNodes[node->pos]=true;
}
//printf("$$$$ Path for Unit [%d - %s] node [%s] whileLoopCount = %d nodePoolCount = %d inBailout = %d\n",unit->getId(),unit->getFullName().c_str(), node->pos.getString().c_str(), whileLoopCount,factions[unitFactionIndex].nodePoolCount,inBailout);
//b4) move this node from closedNodes to openNodes
//add all succesors that are not in closedNodes or openNodes to openNodes
if(factions[unitFactionIndex].closedNodesList.find(node->heuristic) ==
factions[unitFactionIndex].closedNodesList.end()) {
factions[unitFactionIndex].closedNodesList[node->heuristic].clear();
}
factions[unitFactionIndex].closedNodesList[node->heuristic].push_back(node);
factions[unitFactionIndex].openPosList[node->pos] = true;
if(tryJPSPathfinder == true) {
astarJPS(cameFrom, node,finalPos, closedNodes,canAddNode, unit,
nodeLimitReached, maxNodeCount);
}
else {
int failureCount = 0;
int cellCount = 0;
int tryDirection = factions[unitFactionIndex].random.randRange(0,3);
if(tryDirection == 3) {
for(int i = 1; i >= -1 && nodeLimitReached == false; --i) {
for(int j = -1; j <= 1 && nodeLimitReached == false; ++j) {
if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false) {
failureCount++;
}
cellCount++;
}
}
}
else if(tryDirection == 2) {
for(int i = -1; i <= 1 && nodeLimitReached == false; ++i) {
for(int j = 1; j >= -1 && nodeLimitReached == false; --j) {
if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false) {
failureCount++;
}
cellCount++;
}
}
}
else if(tryDirection == 1) {
for(int i = -1; i <= 1 && nodeLimitReached == false; ++i) {
for(int j = -1; j <= 1 && nodeLimitReached == false; ++j) {
if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false) {
failureCount++;
}
cellCount++;
}
}
}
else {
for(int i = 1; i >= -1 && nodeLimitReached == false; --i) {
for(int j = 1; j >= -1 && nodeLimitReached == false; --j) {
if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false) {
failureCount++;
}
cellCount++;
}
}
}
}
} //while
doAStarPathSearch(nodeLimitReached, whileLoopCount, unitFactionIndex,
pathFound, node, finalPos, tryJPSPathfinder,
closedNodes, cameFrom, canAddNode, unit, maxNodeCount);
// Now see if the unit is eligble for pathfind max nodes boost?
if(nodeLimitReached == true && maxNodeCount != pathFindNodesAbsoluteMax) {

View File

@ -303,6 +303,87 @@ private:
return result;
}
inline void doAStarPathSearch(bool & nodeLimitReached, int & whileLoopCount,
int & unitFactionIndex, bool & pathFound, Node *& node, const Vec2i & finalPos,
const bool tryJPSPathfinder, std::map<Vec2i,bool> closedNodes,
std::map<Vec2i,Vec2i> cameFrom, std::map<std::pair<Vec2i,Vec2i> ,
bool> canAddNode, Unit *& unit, int & maxNodeCount) {
while(nodeLimitReached == false) {
whileLoopCount++;
if(factions[unitFactionIndex].openNodesList.empty() == true) {
pathFound = false;
break;
}
node = minHeuristicFastLookup(factions[unitFactionIndex]);
if(node->pos == finalPos || node->exploredCell == false) {
pathFound = true;
break;
}
if(tryJPSPathfinder == true) {
closedNodes[node->pos] = true;
}
if(factions[unitFactionIndex].closedNodesList.find(node->heuristic) == factions[unitFactionIndex].closedNodesList.end()) {
factions[unitFactionIndex].closedNodesList[node->heuristic].clear();
}
factions[unitFactionIndex].closedNodesList[node->heuristic].push_back(node);
factions[unitFactionIndex].openPosList[node->pos] = true;
if(tryJPSPathfinder == true) {
astarJPS(cameFrom, node, finalPos, closedNodes, canAddNode, unit, nodeLimitReached, maxNodeCount);
}
else {
int failureCount = 0;
int cellCount = 0;
int tryDirection = factions[unitFactionIndex].random.randRange(0, 3);
if(tryDirection == 3){
for(int i = 1;i >= -1 && nodeLimitReached == false;--i){
for(int j = -1;j <= 1 && nodeLimitReached == false;++j){
if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false){
failureCount++;
}
cellCount++;
}
}
}
else if(tryDirection == 2) {
for(int i = -1;i <= 1 && nodeLimitReached == false;++i){
for(int j = 1;j >= -1 && nodeLimitReached == false;--j){
if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false){
failureCount++;
}
cellCount++;
}
}
}
else if(tryDirection == 1) {
for(int i = -1;i <= 1 && nodeLimitReached == false;++i){
for(int j = -1;j <= 1 && nodeLimitReached == false;++j){
if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false){
failureCount++;
}
cellCount++;
}
}
}
else{
for(int i = 1;i >= -1 && nodeLimitReached == false;--i){
for(int j = 1;j >= -1 && nodeLimitReached == false;--j){
if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false){
failureCount++;
}
cellCount++;
}
}
}
}
}
}
};
}}//end namespace

View File

@ -62,12 +62,12 @@ public:
Command(const CommandType *ct, const Vec2i &pos, const UnitType *unitType, CardinalDir facing);
//get
const CommandType *getCommandType() const {return commandType;}
Vec2i getPos() const {return pos;}
Vec2i getOriginalPos() const {return originalPos;}
Unit* getUnit() const {return unitRef.getUnit();}
const UnitType* getUnitType() const {return unitType;}
CardinalDir getFacing() const {return facing;}
inline const CommandType *getCommandType() const {return commandType;}
inline Vec2i getPos() const {return pos;}
inline Vec2i getOriginalPos() const {return originalPos;}
inline Unit* getUnit() const {return unitRef.getUnit();}
inline const UnitType* getUnitType() const {return unitType;}
inline CardinalDir getFacing() const {return facing;}
//Priority: commands of higher priority will cancel commands of lower priority
virtual int getPriority();
@ -80,15 +80,14 @@ public:
void setUnit(Unit *unit);
void setStateType(CommandStateType value) { stateType = value; }
CommandStateType getStateType() const { return stateType; }
inline void setStateType(CommandStateType value) { stateType = value; }
inline CommandStateType getStateType() const { return stateType; }
void setStateValue(int value) { stateValue = value; }
int getStateValue() const { return stateValue; }
inline void setStateValue(int value) { stateValue = value; }
inline int getStateValue() const { return stateValue; }
void setUnitCommandGroupId(int value) { unitCommandGroupId = value; }
int getUnitCommandGroupId() const { return unitCommandGroupId; }
inline void setUnitCommandGroupId(int value) { unitCommandGroupId = value; }
inline int getUnitCommandGroupId() const { return unitCommandGroupId; }
std::string toString() const;

View File

@ -497,16 +497,6 @@ bool Faction::canUnitsPathfind() {
return result;
}
Unit * Faction::getUnit(int i) const {
Unit *result = units[i];
return result;
}
int Faction::getUnitCount() const {
int result = units.size();
return result;
}
void Faction::signalWorkerThread(int frameIndex) {
if(workerThread != NULL) {
workerThread->signalPathfinder(frameIndex);

View File

@ -210,9 +210,15 @@ public:
void setPersonalityType(FactionPersonalityType pType) { overridePersonalityType=pType; }
int getAIBehaviorStaticOverideValue(AIBehaviorStaticValueCategory type) const;
Unit *getUnit(int i) const;
int getUnitCount() const;
Mutex * getUnitMutex() {return unitsMutex;}
inline Unit *getUnit(int i) const {
Unit *result = units[i];
return result;
}
inline int getUnitCount() const {
int result = units.size();
return result;
}
inline Mutex * getUnitMutex() {return unitsMutex;}
inline const UpgradeManager *getUpgradeManager() const {return &upgradeManager;}
inline const Texture2D *getTexture() const {return texture;}

View File

@ -10,7 +10,7 @@
// ==============================================================
#define NOMINMAX
#include "faction.h"
#include <cassert>
#include "unit.h"
#include "unit_particle_type.h"
@ -593,14 +593,6 @@ void Unit::setModelFacing(CardinalDir value) {
// ====================================== get ======================================
int Unit::getFactionIndex() const{
return faction->getIndex();
}
int Unit::getTeam() const{
return faction->getTeam();
}
Vec2i Unit::getCenteredPos() const {
if(type == NULL) {
char szBuf[4096]="";
@ -1266,14 +1258,6 @@ Command *Unit::getCurrrentCommandThreadSafe() {
return NULL;
}
//return current command, assert that there is always one command
Command *Unit::getCurrCommand() const {
if(commands.empty() == false) {
return commands.front();
}
return NULL;
}
void Unit::replaceCurrCommand(Command *cmd) {
static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper safeMutex(mutexCommands,mutexOwnerId);
@ -3309,35 +3293,6 @@ void Unit::removeBadHarvestPos(const Vec2i &value) {
cleanupOldBadHarvestPos();
}
bool Unit::isBadHarvestPos(const Vec2i &value, bool checkPeerUnits) const {
bool result = false;
if(badHarvestPosList.empty() == true) {
return result;
}
std::map<Vec2i,int>::const_iterator iter = badHarvestPosList.find(value);
if(iter != badHarvestPosList.end()) {
result = true;
}
else if(checkPeerUnits == true) {
// Check if any other units of similar type have this position tagged
// as bad?
for(int i = 0; i < this->getFaction()->getUnitCount(); ++i) {
Unit *peerUnit = this->getFaction()->getUnit(i);
if( peerUnit != NULL && peerUnit->getId() != this->getId() &&
peerUnit->getType()->hasCommandClass(ccHarvest) == true &&
peerUnit->getType()->getSize() <= this->getType()->getSize()) {
if(peerUnit->isBadHarvestPos(value,false) == true) {
result = true;
break;
}
}
}
}
return result;
}
void Unit::cleanupOldBadHarvestPos() {
const int cleanupInterval = (GameConstants::updateFps * 5);
bool needToCleanup = (getFrameCount() % cleanupInterval == 0);

View File

@ -23,6 +23,7 @@
#include "game_constants.h"
#include "platform_common.h"
#include <vector>
#include "faction.h"
#include "leak_dumper.h"
//#define LEAK_CHECK_UNITS
@ -40,7 +41,7 @@ using Shared::PlatformCommon::Chrono;
using Shared::PlatformCommon::ValueCheckerVault;
class Map;
class Faction;
//class Faction;
class Unit;
class Command;
class SkillType;
@ -459,8 +460,12 @@ public:
inline float getAnimProgress() const {return animProgress;}
inline float getHightlight() const {return highlight;}
inline int getProgress2() const {return progress2;}
int getFactionIndex() const;
int getTeam() const;
inline int getFactionIndex() const {
return faction->getIndex();
}
inline int getTeam() const {
return faction->getTeam();
}
inline int getHp() const {return hp;}
inline int getEp() const {return ep;}
int getProductionPercent() const;
@ -544,7 +549,12 @@ public:
//command related
bool anyCommand(bool validateCommandtype=false) const;
Command *getCurrCommand() const;
inline Command *getCurrCommand() const {
if(commands.empty() == false) {
return commands.front();
}
return NULL;
}
void replaceCurrCommand(Command *cmd);
int getCountOfProducedUnits(const UnitType *ut) const;
unsigned int getCommandSize() const;
@ -612,7 +622,34 @@ public:
//void setBadHarvestPosList(std::vector<std::pair<Vec2i,Chrono> > value) { badHarvestPosList = value; }
void addBadHarvestPos(const Vec2i &value);
void removeBadHarvestPos(const Vec2i &value);
bool isBadHarvestPos(const Vec2i &value,bool checkPeerUnits=true) const;
inline bool isBadHarvestPos(const Vec2i &value,bool checkPeerUnits=true) const {
bool result = false;
if(badHarvestPosList.empty() == true) {
return result;
}
std::map<Vec2i,int>::const_iterator iter = badHarvestPosList.find(value);
if(iter != badHarvestPosList.end()) {
result = true;
}
else if(checkPeerUnits == true) {
// Check if any other units of similar type have this position tagged
// as bad?
for(int i = 0; i < this->getFaction()->getUnitCount(); ++i) {
Unit *peerUnit = this->getFaction()->getUnit(i);
if( peerUnit != NULL && peerUnit->getId() != this->getId() &&
peerUnit->getType()->hasCommandClass(ccHarvest) == true &&
peerUnit->getType()->getSize() <= this->getType()->getSize()) {
if(peerUnit->isBadHarvestPos(value,false) == true) {
result = true;
break;
}
}
}
}
return result;
}
void cleanupOldBadHarvestPos();
void setLastHarvestResourceTarget(const Vec2i *pos);

View File

@ -888,10 +888,6 @@ bool UnitType::hasCommandType(const CommandType *commandType) const {
return false;
}
bool UnitType::hasCommandClass(CommandClass commandClass) const {
return firstCommandTypeOfClass[commandClass]!=NULL;
}
bool UnitType::hasSkillType(const SkillType *skillType) const {
assert(skillType!=NULL);
for(int i=0; i<skillTypes.size(); ++i) {

View File

@ -218,7 +218,9 @@ public:
//has
bool hasCommandType(const CommandType *commandType) const;
bool hasCommandClass(CommandClass commandClass) const;
inline bool hasCommandClass(CommandClass commandClass) const {
return firstCommandTypeOfClass[commandClass]!=NULL;
}
bool hasSkillType(const SkillType *skillType) const;
bool hasSkillClass(SkillClass skillClass) const;
inline bool hasCellMap() const {return cellMap!=NULL;}

View File

@ -690,15 +690,6 @@ bool Map::isFreeCell(const Vec2i &pos, Field field) const {
(field!=fLand || getDeepSubmerged(getCell(pos)) == false);
}
bool Map::isFreeCellOrMightBeFreeSoon(Vec2i originPos, const Vec2i &pos, Field field) const {
return
isInside(pos) &&
isInsideSurface(toSurfCoords(pos)) &&
getCell(pos)->isFreeOrMightBeFreeSoon(originPos,pos,field) &&
(field==fAir || getSurfaceCell(toSurfCoords(pos))->isFree()) &&
(field!=fLand || getDeepSubmerged(getCell(pos)) == false);
}
bool Map::isFreeCellOrHasUnit(const Vec2i &pos, Field field, const Unit *unit) const {
if(isInside(pos) && isInsideSurface(toSurfCoords(pos))) {
if(unit->getCurrField() != field) {
@ -753,25 +744,6 @@ bool Map::isAproxFreeCell(const Vec2i &pos, Field field, int teamIndex) const {
return false;
}
bool Map::isAproxFreeCellOrMightBeFreeSoon(Vec2i originPos,const Vec2i &pos, Field field, int teamIndex) const {
if(isInside(pos) && isInsideSurface(toSurfCoords(pos))) {
const SurfaceCell *sc= getSurfaceCell(toSurfCoords(pos));
if(sc->isVisible(teamIndex)) {
return isFreeCellOrMightBeFreeSoon(originPos, pos, field);
}
else if(sc->isExplored(teamIndex)) {
return field==fLand? sc->isFree() && !getDeepSubmerged(getCell(pos)): true;
}
else {
return true;
}
}
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
return false;
}
bool Map::isFreeCells(const Vec2i & pos, int size, Field field) const {
for(int i=pos.x; i<pos.x+size; ++i) {
for(int j=pos.y; j<pos.y+size; ++j) {

View File

@ -342,8 +342,34 @@ public:
inline static Vec2i toUnitCoords(const Vec2i &surfPos) {return surfPos * cellScale;}
static string getMapPath(const string &mapName, string scenarioDir="", bool errorOnNotFound=true);
bool isFreeCellOrMightBeFreeSoon(Vec2i originPos, const Vec2i &pos, Field field) const;
bool isAproxFreeCellOrMightBeFreeSoon(Vec2i originPos,const Vec2i &pos, Field field, int teamIndex) const;
inline bool isFreeCellOrMightBeFreeSoon(Vec2i originPos, const Vec2i &pos, Field field) const {
return
isInside(pos) &&
isInsideSurface(toSurfCoords(pos)) &&
getCell(pos)->isFreeOrMightBeFreeSoon(originPos,pos,field) &&
(field==fAir || getSurfaceCell(toSurfCoords(pos))->isFree()) &&
(field!=fLand || getDeepSubmerged(getCell(pos)) == false);
}
inline bool isAproxFreeCellOrMightBeFreeSoon(Vec2i originPos,const Vec2i &pos, Field field, int teamIndex) const {
if(isInside(pos) && isInsideSurface(toSurfCoords(pos))) {
const SurfaceCell *sc= getSurfaceCell(toSurfCoords(pos));
if(sc->isVisible(teamIndex)) {
return isFreeCellOrMightBeFreeSoon(originPos, pos, field);
}
else if(sc->isExplored(teamIndex)) {
return field==fLand? sc->isFree() && !getDeepSubmerged(getCell(pos)): true;
}
else {
return true;
}
}
//printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__);
return false;
}
bool aproxCanMoveSoon(const Unit *unit, const Vec2i &pos1, const Vec2i &pos2) const;
string getMapFile() const { return mapFile; }