glest-source/source/glest_game/ai/path_finder.cpp
2018-05-06 00:01:36 +02:00

1876 lines
56 KiB
C++

// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Martiño Figueroa
//
// 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
// ==============================================================
#include "path_finder.h"
#include <algorithm>
#include "config.h"
#include "map.h"
#include "unit.h"
#include "unit_type.h"
#include "platform_common.h"
#include "command.h"
#include "faction.h"
#include "randomgen.h"
#include "leak_dumper.h"
using namespace std;
using namespace
Shared::Graphics;
using namespace
Shared::Util;
using namespace
Shared::PlatformCommon;
using
Shared::Util::RandomGen;
namespace
Glest {
namespace
Game {
// =====================================================
// class PathFinder
// =====================================================
// ===================== PUBLIC ========================
const int
PathFinder::maxFreeSearchRadius = 10;
int
PathFinder::pathFindNodesAbsoluteMax = 900;
int
PathFinder::pathFindNodesMax = 2000;
const int
PathFinder::pathFindBailoutRadius = 20;
const int
PathFinder::pathFindExtendRefreshForNodeCount = 25;
const int
PathFinder::pathFindExtendRefreshNodeCountMin = 40;
const int
PathFinder::pathFindExtendRefreshNodeCountMax = 40;
PathFinder::PathFinder() {
minorDebugPathfinder = false;
map = NULL;
}
int
PathFinder::getPathFindExtendRefreshNodeCount(FactionState & faction) {
//int refreshNodeCount = faction.random.randRange(PathFinder::pathFindExtendRefreshNodeCountMin,PathFinder::pathFindExtendRefreshNodeCountMax);
//return refreshNodeCount;
return PathFinder::pathFindExtendRefreshNodeCountMin;
}
PathFinder::PathFinder(const Map * map) {
minorDebugPathfinder = false;
map = NULL;
init(map);
}
void
PathFinder::init(const Map * map) {
for (int factionIndex = 0; factionIndex < GameConstants::maxPlayers;
++factionIndex) {
FactionState & faction = factions.getFactionState(factionIndex);
faction.nodePool.resize(pathFindNodesAbsoluteMax);
faction.useMaxNodeCount = PathFinder::pathFindNodesMax;
}
this->map = map;
}
void
PathFinder::init() {
minorDebugPathfinder = false;
map = NULL;
}
PathFinder::~PathFinder() {
for (int factionIndex = 0; factionIndex < GameConstants::maxPlayers;
++factionIndex) {
FactionState & faction = factions.getFactionState(factionIndex);
faction.nodePool.clear();
}
factions.clear();
map = NULL;
}
void
PathFinder::clearCaches() {
for (int factionIndex = 0; factionIndex < GameConstants::maxPlayers;
++factionIndex) {
static string
mutexOwnerId =
string(__FILE__) + string("_") + intToStr(__LINE__);
FactionState & faction = factions.getFactionState(factionIndex);
MutexSafeWrapper
safeMutex(faction.getMutexPreCache(), mutexOwnerId);
faction.precachedTravelState.clear();
faction.precachedPath.clear();
}
}
void
PathFinder::clearUnitPrecache(Unit * unit) {
if (unit != NULL && factions.size() > unit->getFactionIndex()) {
int
factionIndex = unit->getFactionIndex();
static string
mutexOwnerId =
string(__FILE__) + string("_") + intToStr(__LINE__);
FactionState & faction = factions.getFactionState(factionIndex);
MutexSafeWrapper
safeMutex(faction.getMutexPreCache(), mutexOwnerId);
faction.precachedTravelState[unit->getId()] = tsImpossible;
faction.precachedPath[unit->getId()].clear();
}
}
void
PathFinder::removeUnitPrecache(Unit * unit) {
if (unit != NULL && factions.size() > unit->getFactionIndex()) {
int
factionIndex = unit->getFactionIndex();
static string
mutexOwnerId =
string(__FILE__) + string("_") + intToStr(__LINE__);
FactionState & faction = factions.getFactionState(factionIndex);
MutexSafeWrapper
safeMutex(faction.getMutexPreCache(), mutexOwnerId);
if (faction.precachedTravelState.find(unit->getId()) !=
faction.precachedTravelState.end()) {
faction.precachedTravelState.erase(unit->getId());
}
if (faction.precachedPath.find(unit->getId()) !=
faction.precachedPath.end()) {
faction.precachedPath.erase(unit->getId());
}
}
}
TravelState
PathFinder::findPath(Unit * unit, const Vec2i & finalPos,
bool * wasStuck, int frameIndex) {
TravelState
ts = tsImpossible;
try {
int
factionIndex = unit->getFactionIndex();
FactionState & faction = factions.getFactionState(factionIndex);
static string
mutexOwnerId =
string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper
safeMutexPrecache(faction.getMutexPreCache(), mutexOwnerId);
if (map == NULL) {
throw
megaglest_runtime_error("map == NULL");
}
unit->setCurrentPathFinderDesiredFinalPos(finalPos);
if (frameIndex >= 0) {
clearUnitPrecache(unit);
}
if (unit->getFaction()->canUnitsPathfind() == true) {
unit->getFaction()->addUnitToPathfindingList(unit->getId());
} else {
if (SystemFlags::
getSystemSettingType(SystemFlags::debugWorldSynch).enabled ==
true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096, "canUnitsPathfind() == false");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).
c_str(), __LINE__, szBuf);
}
return tsBlocked;
}
if (SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).
enabled == true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"[findPath] unit->getPos() [%s] finalPos [%s]",
unit->getPos().getString().c_str(),
finalPos.getString().c_str());
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).
c_str(), __LINE__, szBuf);
}
//route cache
if (finalPos == unit->getPos()) {
if (frameIndex < 0) {
//if arrived
unit->setCurrSkill(scStop);
if (SystemFlags::
getSystemSettingType(SystemFlags::debugWorldSynch).
enabled == true) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"Unit finalPos [%s] == unit->getPos() [%s]",
finalPos.getString().c_str(),
unit->getPos().getString().c_str());
unit->
logSynchData(extractFileFromDirectoryPath(__FILE__).
c_str(), __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(false);
}
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"State: arrived#1 at pos: %s, command [%s]",
finalPos.getString().c_str(),
commandDesc.c_str());
unit->setCurrentUnitTitle(szBuf);
}
return tsArrived;
}
UnitPathInterface *
path = unit->getPath();
if (path->isEmpty() == false) {
UnitPathBasic *
basic_path = dynamic_cast <UnitPathBasic *>(path);
if (basic_path != NULL) {
//route cache
Vec2i
pos = basic_path->pop(frameIndex < 0);
if (map->canMove(unit, unit->getPos(), pos)) {
if (frameIndex < 0) {
if (SystemFlags::
getSystemSettingType(SystemFlags::
debugWorldSynch).enabled ==
true
&& SystemFlags::
getSystemSettingType(SystemFlags::
debugWorldSynchMax).
enabled == true) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"#1 map->canMove to pos [%s] from [%s]",
pos.getString().c_str(),
unit->getPos().getString().c_str());
unit->
logSynchData(extractFileFromDirectoryPath
(__FILE__).c_str(), __LINE__,
szBuf);
}
unit->setTargetPos(pos, frameIndex < 0);
if (SystemFlags::
getSystemSettingType(SystemFlags::
debugWorldSynch).enabled ==
true
&& SystemFlags::
getSystemSettingType(SystemFlags::
debugWorldSynchMax).
enabled == true) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"#2 map->canMove to pos [%s] from [%s]",
pos.getString().c_str(),
unit->getPos().getString().c_str());
unit->
logSynchData(extractFileFromDirectoryPath
(__FILE__).c_str(), __LINE__,
szBuf);
}
}
return tsMoving;
}
} else if (dynamic_cast <UnitPath *>(path) != NULL) {
UnitPath *
advPath = dynamic_cast <UnitPath *>(path);
//route cache
Vec2i
pos = advPath->peek();
if (map->canMove(unit, unit->getPos(), pos)) {
if (frameIndex < 0) {
advPath->pop();
unit->setTargetPos(pos, frameIndex < 0);
}
return tsMoving;
}
} else {
throw
megaglest_runtime_error
("unsupported or missing path finder detected!");
}
}
if (path->isStuck() == true &&
(unit->getLastStuckPos() == finalPos
|| path->getBlockCount() > 500)
&& unit->
isLastStuckFrameWithinCurrentFrameTolerance(frameIndex >= 0) ==
true) {
if (SystemFlags::
getSystemSettingType(SystemFlags::debugWorldSynch).enabled ==
true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"path->isStuck() == true unit->getLastStuckPos() [%s] finalPos [%s] path->getBlockCount() [%d]",
unit->getLastStuckPos().getString().c_str(),
finalPos.getString().c_str(),
path->getBlockCount());
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).
c_str(), __LINE__, szBuf);
}
return tsBlocked;
}
//route cache miss
int
maxNodeCount = -1;
if (unit->getUsePathfinderExtendedMaxNodes() == true) {
maxNodeCount = PathFinder::pathFindNodesAbsoluteMax;
if (SystemFlags::
getSystemSettingType(SystemFlags::debugWorldSynch).enabled ==
true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096, "maxNodeCount: %d", maxNodeCount);
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).
c_str(), __LINE__, szBuf);
}
}
bool
minorDebugPathfinderPerformance = false;
Chrono
chrono;
if (minorDebugPathfinderPerformance)
chrono.start();
uint32
searched_node_count = 0;
minorDebugPathfinder = false;
if (minorDebugPathfinder)
printf
("Legacy Pathfind Unit [%d - %s] from = %s to = %s frameIndex = %d\n",
unit->getId(), unit->getType()->getName(false).c_str(),
unit->getPos().getString().c_str(),
finalPos.getString().c_str(), frameIndex);
if (SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).
enabled == true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096, "calling aStar()");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).
c_str(), __LINE__, szBuf);
}
ts =
aStar(unit, finalPos, false, frameIndex, maxNodeCount,
&searched_node_count);
//post actions
switch (ts) {
case tsBlocked:
case tsArrived:
// The unit is stuck (not only blocked but unable to go anywhere for a while)
// We will try to bail out of the immediate area
if (ts == tsBlocked && unit->getInBailOutAttempt() == false &&
path->isStuck() == true) {
if (minorDebugPathfinder)
printf
("Pathfind Unit [%d - %s] START BAILOUT ATTEMPT frameIndex = %d\n",
unit->getId(),
unit->getType()->getName(false).c_str(), frameIndex);
if (SystemFlags::
getSystemSettingType(SystemFlags::debugWorldSynch).
enabled == true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"[attempting to BAIL OUT] finalPos [%s] ts [%d]",
finalPos.getString().c_str(), ts);
unit->
logSynchData(extractFileFromDirectoryPath(__FILE__).
c_str(), __LINE__, szBuf);
}
if (wasStuck != NULL) {
*wasStuck = true;
}
unit->setInBailOutAttempt(true);
bool
unitImmediatelyBlocked = false;
// First check if unit currently blocked all around them, if so don't try to pathfind
const Vec2i
unitPos = unit->getPos();
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) {
bool
canUnitMoveToCell =
map->aproxCanMove(unit, unitPos, pos);
if (canUnitMoveToCell == false) {
failureCount++;
}
cellCount++;
}
}
}
unitImmediatelyBlocked = (failureCount == cellCount);
if (unitImmediatelyBlocked == false) {
int
factionIndex = unit->getFactionIndex();
FactionState & faction =
factions.getFactionState(factionIndex);
//if(Thread::isCurrentThreadMainThread() == false) {
// throw megaglest_runtime_error("#2 Invalid access to FactionState random from outside main thread current id = " +
// intToStr(Thread::getCurrentThreadId()) + " main = " + intToStr(Thread::getMainThreadId()));
//}
int
tryRadius = faction.random.randRange(1, 2);
//int tryRadius = faction.random.IRandomX(1,2);
//int tryRadius = 1;
if (SystemFlags::
getSystemSettingType(SystemFlags::debugWorldSynch).
enabled == true) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"In astar bailout() tryRadius %d",
tryRadius);
if (frameIndex >= 0) {
unit->logSynchDataThreaded(__FILE__, __LINE__,
szBuf);
} else {
unit->logSynchData(__FILE__, __LINE__, szBuf);
}
}
// Try to bail out up to PathFinder::pathFindBailoutRadius cells away
if (tryRadius == 2) {
for (int bailoutX =
-PathFinder::pathFindBailoutRadius;
bailoutX <= PathFinder::pathFindBailoutRadius
&& ts == tsBlocked; ++bailoutX) {
for (int bailoutY =
-PathFinder::pathFindBailoutRadius;
bailoutY <= PathFinder::pathFindBailoutRadius
&& ts == tsBlocked; ++bailoutY) {
const Vec2i
newFinalPos =
finalPos + Vec2i(bailoutX, bailoutY);
bool
canUnitMove =
map->canMove(unit, unit->getPos(),
newFinalPos);
if (SystemFlags::
getSystemSettingType(SystemFlags::
debugWorldSynch).
enabled == true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"[attempting to BAIL OUT] finalPos [%s] newFinalPos [%s] ts [%d] canUnitMove [%d]",
finalPos.getString().c_str(),
newFinalPos.getString().
c_str(), ts, canUnitMove);
unit->
logSynchData
(extractFileFromDirectoryPath
(__FILE__).c_str(), __LINE__, szBuf);
}
if (canUnitMove) {
int
maxBailoutNodeCount =
(PathFinder::pathFindBailoutRadius * 2);
if (SystemFlags::
getSystemSettingType(SystemFlags::
debugWorldSynch).
enabled == true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"calling aStar()");
unit->
logSynchData
(extractFileFromDirectoryPath
(__FILE__).c_str(), __LINE__,
szBuf);
}
ts =
aStar(unit, newFinalPos, true,
frameIndex, maxBailoutNodeCount,
&searched_node_count);
}
}
}
} else {
for (int bailoutX = PathFinder::pathFindBailoutRadius;
bailoutX >= -PathFinder::pathFindBailoutRadius
&& ts == tsBlocked; --bailoutX) {
for (int bailoutY =
PathFinder::pathFindBailoutRadius;
bailoutY >=
-PathFinder::pathFindBailoutRadius
&& ts == tsBlocked; --bailoutY) {
const Vec2i
newFinalPos =
finalPos + Vec2i(bailoutX, bailoutY);
bool
canUnitMove =
map->canMove(unit, unit->getPos(),
newFinalPos);
if (SystemFlags::
getSystemSettingType(SystemFlags::
debugWorldSynch).
enabled == true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"[attempting to BAIL OUT] finalPos [%s] newFinalPos [%s] ts [%d] canUnitMove [%d]",
finalPos.getString().c_str(),
newFinalPos.getString().
c_str(), ts, canUnitMove);
unit->
logSynchData
(extractFileFromDirectoryPath
(__FILE__).c_str(), __LINE__, szBuf);
}
if (canUnitMove) {
int
maxBailoutNodeCount =
(PathFinder::pathFindBailoutRadius * 2);
if (SystemFlags::
getSystemSettingType(SystemFlags::
debugWorldSynch).
enabled == true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"calling aStar()");
unit->
logSynchData
(extractFileFromDirectoryPath
(__FILE__).c_str(), __LINE__,
szBuf);
}
ts =
aStar(unit, newFinalPos, true,
frameIndex, maxBailoutNodeCount,
&searched_node_count);
}
}
}
}
}
unit->setInBailOutAttempt(false);
if (ts == tsBlocked) {
unit->setLastStuckFrameToCurrentFrame();
unit->setLastStuckPos(finalPos);
}
}
if (ts == tsArrived || ts == tsBlocked) {
if (frameIndex < 0) {
unit->setCurrSkill(scStop);
}
}
break;
case tsMoving:
{
if (dynamic_cast <UnitPathBasic *>(path) != NULL) {
UnitPathBasic *
basicPath = dynamic_cast <UnitPathBasic *>(path);
Vec2i
pos;
if (frameIndex < 0 && basicPath != NULL) {
pos = basicPath->pop(frameIndex < 0);
} else {
if (faction.precachedPath[unit->getId()].size() <= 0) {
throw
megaglest_runtime_error
("factions[unit->getFactionIndex()].precachedPath[unit->getId()].size() <= 0!");
}
pos = faction.precachedPath[unit->getId()][0];
}
if (map->canMove(unit, unit->getPos(), pos)) {
if (frameIndex < 0) {
unit->setTargetPos(pos, frameIndex < 0);
}
} else {
if (frameIndex < 0) {
unit->setCurrSkill(scStop);
}
if (minorDebugPathfinderPerformance
&& chrono.getMillis() >= 1)
printf
("Unit [%d - %s] astar #2 took [%lld] msecs, ts = %d searched_node_count = %d.\n",
unit->getId(),
unit->getType()->getName(false).c_str(),
(long long int) chrono.getMillis(), ts,
searched_node_count);
if (SystemFlags::
getSystemSettingType(SystemFlags::debugWorldSynch).
enabled == true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096, "tsBlocked");
unit->
logSynchData(extractFileFromDirectoryPath
(__FILE__).c_str(), __LINE__,
szBuf);
}
return tsBlocked;
}
} else if (dynamic_cast <UnitPath *>(path) != NULL) {
UnitPath *
advPath = dynamic_cast <UnitPath *>(path);
Vec2i
pos = advPath->peek();
if (map->canMove(unit, unit->getPos(), pos)) {
if (frameIndex < 0) {
advPath->pop();
unit->setTargetPos(pos, frameIndex < 0);
}
} else {
if (frameIndex < 0) {
unit->setCurrSkill(scStop);
}
if (minorDebugPathfinder)
printf
("Pathfind Unit [%d - %s] INT BAILOUT ATTEMPT BLOCKED frameIndex = %d\n",
unit->getId(),
unit->getType()->getName(false).c_str(),
frameIndex);
if (minorDebugPathfinderPerformance
&& chrono.getMillis() >= 1)
printf
("Unit [%d - %s] astar #3 took [%lld] msecs, ts = %d searched_node_count = %d.\n",
unit->getId(),
unit->getType()->getName(false).c_str(),
(long long int) chrono.getMillis(), ts,
searched_node_count);
return tsBlocked;
}
} else {
throw
megaglest_runtime_error
("unsupported or missing path finder detected!");
}
}
break;
default:
break;
}
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(false).c_str(),
(long long int) chrono.getMillis(), ts, searched_node_count);
} catch (const exception & ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,
"In [%s::%s Line: %d] Error [%s]\n",
__FILE__, __FUNCTION__, __LINE__,
ex.what());
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d]\n", __FILE__,
__FUNCTION__, __LINE__);
throw
megaglest_runtime_error(ex.what());
} catch (...) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096, "In [%s::%s %d] UNKNOWN error\n", __FILE__,
__FUNCTION__, __LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError, szBuf);
throw
megaglest_runtime_error(szBuf);
}
return ts;
}
// ==================== PRIVATE ====================
//route a unit using A* algorithm
TravelState
PathFinder::aStar(Unit * unit, const Vec2i & targetPos, bool inBailout,
int frameIndex, int maxNodeCount,
uint32 * searched_node_count) {
TravelState
ts = tsImpossible;
try {
int
unitFactionIndex = unit->getFactionIndex();
int
factionIndex = unit->getFactionIndex();
FactionState & faction = factions.getFactionState(factionIndex);
if (SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).
enabled == true && frameIndex >= 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096, "In aStar()");
unit->logSynchDataThreaded(__FILE__, __LINE__, szBuf);
}
Chrono
chrono;
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
enabled)
chrono.start();
if (map == NULL) {
throw
megaglest_runtime_error("map == NULL");
}
if (maxNodeCount < 0) {
int
factionIndex = unit->getFactionIndex();
FactionState & faction = factions.getFactionState(factionIndex);
maxNodeCount = faction.useMaxNodeCount;
}
if (maxNodeCount >= 1
&& unit->getPathfindFailedConsecutiveFrameCount() >= 3) {
maxNodeCount = 200;
}
UnitPathInterface *
path = unit->getPath();
faction.nodePoolCount = 0;
faction.openNodesList.clear();
faction.openPosList.clear();
faction.closedNodesList.clear();
// check the pre-cache to see if we can re-use a cached path
if (frameIndex < 0) {
bool
foundPrecacheTravelState =
(faction.precachedTravelState.find(unit->getId()) !=
faction.precachedTravelState.end());
if (foundPrecacheTravelState == true) {
// if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
// char szBuf[8096]="";
// snprintf(szBuf,8096,"factions[unitFactionIndex].precachedTravelState[unit->getId()]: %d",faction.precachedTravelState[unit->getId()]);
// unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
// }
bool
foundPrecacheTravelStateIsMoving =
(faction.precachedTravelState[unit->getId()] == tsMoving);
if (foundPrecacheTravelStateIsMoving == true) {
bool
canMoveToCells = true;
Vec2i
lastPos = unit->getPos();
int
unitPrecachePathSize =
(int) faction.precachedPath[unit->getId()].size();
for (int i = 0; i < unitPrecachePathSize; i++) {
Vec2i
nodePos = faction.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 < unit->getPathFindRefreshCellCount() ||
(unitPrecachePathSize >=
pathFindExtendRefreshForNodeCount
&& i <
getPathFindExtendRefreshNodeCount(faction))) {
if (canUnitMoveSoon(unit, lastPos, nodePos) ==
false) {
canMoveToCells = false;
break;
}
lastPos = nodePos;
} else {
break;
}
}
if (canMoveToCells == true) {
path->clear();
//UnitPathBasic *basicPathFinder = dynamic_cast<UnitPathBasic *>(path);
int
unitPrecachePathSize =
(int) faction.precachedPath[unit->getId()].size();
for (int i = 0; i < unitPrecachePathSize; i++) {
Vec2i
nodePos =
faction.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() ||
(unitPrecachePathSize >=
pathFindExtendRefreshForNodeCount
&& i <
getPathFindExtendRefreshNodeCount(faction))) {
path->add(nodePos);
}
}
unit->setUsePathfinderExtendedMaxNodes(false);
if (SystemFlags::
getSystemSettingType(SystemFlags::
debugWorldSynch).enabled ==
true) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"return factions[unitFactionIndex].precachedTravelState[unit->getId()];");
unit->
logSynchData(extractFileFromDirectoryPath
(__FILE__).c_str(), __LINE__,
szBuf);
}
return faction.precachedTravelState[unit->getId()];
} else {
clearUnitPrecache(unit);
}
} else {
bool
foundPrecacheTravelStateIsBlocked =
(faction.precachedTravelState[unit->getId()] ==
tsBlocked);
if (foundPrecacheTravelStateIsBlocked == true) {
path->incBlockCount();
unit->setUsePathfinderExtendedMaxNodes(false);
// if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
// char szBuf[8096]="";
// snprintf(szBuf,8096,"return factions[unitFactionIndex].precachedTravelState[unit->getId()];");
// unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf);
// }
return faction.precachedTravelState[unit->getId()];
}
}
}
} else {
clearUnitPrecache(unit);
if (SystemFlags::
getSystemSettingType(SystemFlags::debugWorldSynch).enabled ==
true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096, "[clearUnitPrecache]");
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).
c_str(), __LINE__, szBuf);
}
}
const Vec2i
unitPos = unit->getPos();
const Vec2i
finalPos = computeNearestFreePos(unit, targetPos);
float
dist = unitPos.dist(finalPos);
faction.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",
extractFileFromDirectoryPath(__FILE__).
c_str(), __FUNCTION__, __LINE__,
chrono.getMillis());
//path find algorithm
//a) push starting pos into openNodes
Node *
firstNode = newNode(faction, maxNodeCount);
if (firstNode == NULL) {
throw
megaglest_runtime_error("firstNode == NULL");
}
firstNode->next = NULL;
firstNode->prev = NULL;
firstNode->pos = unitPos;
firstNode->heuristic = heuristic(unitPos, finalPos);
firstNode->exploredCell = true;
if (faction.openNodesList.find(firstNode->heuristic) ==
faction.openNodesList.end()) {
faction.openNodesList[firstNode->heuristic].clear();
}
faction.openNodesList[firstNode->heuristic].push_back(firstNode);
faction.openPosList[firstNode->pos] = true;
//b) loop
bool
pathFound = true;
bool
nodeLimitReached = false;
Node *
node = NULL;
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
enabled == true && chrono.getMillis() > 4)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s Line: %d] took msecs: %lld\n",
extractFileFromDirectoryPath(__FILE__).
c_str(), __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) {
bool
canUnitMoveToCell =
canUnitMoveSoon(unit, unitPos, pos);
if (canUnitMoveToCell == false) {
failureCount++;
}
cellCount++;
}
}
}
nodeLimitReached = (failureCount == cellCount);
pathFound = !nodeLimitReached;
if (SystemFlags::
getSystemSettingType(SystemFlags::debugWorldSynch).enabled ==
true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"nodeLimitReached: %d failureCount: %d cellCount: %d",
nodeLimitReached, failureCount, cellCount);
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).
c_str(), __LINE__, szBuf);
}
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",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__, unit->getId(),
unit->getFullName(false).c_str(),
unitPos.getString().c_str(),
finalPos.getString().c_str(), dist,
(long long int) chrono.getMillis(),
nodeLimitReached, failureCount);
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) {
bool
canUnitMoveToCell =
canUnitMoveSoon(unit, pos, finalPos);
if (canUnitMoveToCell == false) {
failureCount++;
}
cellCount++;
}
}
}
nodeLimitReached = (failureCount == cellCount);
pathFound = !nodeLimitReached;
if (SystemFlags::
getSystemSettingType(SystemFlags::debugWorldSynch).
enabled == true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"nodeLimitReached: %d failureCount: %d cellCount: %d",
nodeLimitReached, failureCount, cellCount);
unit->
logSynchData(extractFileFromDirectoryPath(__FILE__).
c_str(), __LINE__, szBuf);
}
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",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__, unit->getId(),
unit->getFullName(false).
c_str(),
unitPos.getString().c_str(),
finalPos.getString().c_str(),
dist,
(long long int) chrono.
getMillis(), nodeLimitReached,
failureCount);
}
} else {
if (SystemFlags::
getSystemSettingType(SystemFlags::debugWorldSynch).enabled ==
true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"inBailout: %d unitPos: [%s] finalPos [%s]",
inBailout, unitPos.getString().c_str(),
finalPos.getString().c_str());
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).
c_str(), __LINE__, szBuf);
}
}
//
// START
std::map < std::pair < Vec2i, Vec2i >, bool > canAddNode;
std::map < Vec2i, bool > closedNodes;
std::map < Vec2i, Vec2i > cameFrom;
cameFrom[unitPos] = Vec2i(-1, -1);
// Do the a-star base pathfind work if required
int
whileLoopCount = 0;
if (nodeLimitReached == false) {
if (SystemFlags::
getSystemSettingType(SystemFlags::debugWorldSynch).enabled ==
true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"Calling doAStarPathSearch nodeLimitReached: %d whileLoopCount: %d unitFactionIndex: %d pathFound: %d finalPos [%s] maxNodeCount: %d frameIndex: %d",
nodeLimitReached, whileLoopCount, unitFactionIndex,
pathFound, finalPos.getString().c_str(),
maxNodeCount, frameIndex);
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).
c_str(), __LINE__, szBuf);
}
doAStarPathSearch(nodeLimitReached, whileLoopCount,
unitFactionIndex, pathFound, node, finalPos,
closedNodes, cameFrom, canAddNode, unit,
maxNodeCount, frameIndex);
if (searched_node_count != NULL) {
*searched_node_count = whileLoopCount;
}
// Now see if the unit is eligible for pathfind max nodes boost?
if (nodeLimitReached == true) {
unit->incrementPathfindFailedConsecutiveFrameCount();
} else {
unit->resetPathfindFailedConsecutiveFrameCount();
}
if (SystemFlags::
getSystemSettingType(SystemFlags::debugWorldSynch).enabled ==
true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"Calling doAStarPathSearch nodeLimitReached: %d whileLoopCount: %d unitFactionIndex: %d pathFound: %d finalPos [%s] maxNodeCount: %d pathFindNodesAbsoluteMax: %d frameIndex: %d",
nodeLimitReached, whileLoopCount, unitFactionIndex,
pathFound, finalPos.getString().c_str(),
maxNodeCount, pathFindNodesAbsoluteMax, frameIndex);
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).
c_str(), __LINE__, szBuf);
}
if (nodeLimitReached == true
&& maxNodeCount != pathFindNodesAbsoluteMax) {
if (unit->
isLastPathfindFailedFrameWithinCurrentFrameTolerance() ==
true) {
if (frameIndex < 0) {
unit->setLastPathfindFailedFrameToCurrentFrame();
unit->setLastPathfindFailedPos(finalPos);
}
if (SystemFlags::
getSystemSettingType(SystemFlags::debugWorldSynch).
enabled == true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096, "calling aStar()");
unit->
logSynchData(extractFileFromDirectoryPath
(__FILE__).c_str(), __LINE__, szBuf);
}
return aStar(unit, targetPos, false, frameIndex,
pathFindNodesAbsoluteMax);
}
}
} else {
if (SystemFlags::
getSystemSettingType(SystemFlags::debugWorldSynch).enabled ==
true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096, "nodeLimitReached: %d",
nodeLimitReached);
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).
c_str(), __LINE__, szBuf);
}
}
Node *
lastNode = node;
//if consumed all nodes find best node (to avoid strange behaviour)
if (nodeLimitReached == true) {
if (faction.closedNodesList.empty() == false) {
float
bestHeuristic =
truncateDecimal <
float >(faction.closedNodesList.begin()->first, 6);
if (lastNode != NULL && bestHeuristic < lastNode->heuristic) {
lastNode =
faction.closedNodesList.begin()->second.front();
}
}
}
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
enabled == true && chrono.getMillis() > 4)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s Line: %d] took msecs: %lld\n",
extractFileFromDirectoryPath(__FILE__).
c_str(), __FUNCTION__, __LINE__,
chrono.getMillis());
//check results of path finding
ts = tsImpossible;
if (pathFound == false || lastNode == firstNode) {
if (minorDebugPathfinder)
printf
("Legacy Pathfind Unit [%d - %s] NOT FOUND PATH count = %d frameIndex = %d\n",
unit->getId(), unit->getType()->getName().c_str(),
whileLoopCount, frameIndex);
//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(false);
}
std::pair < Vec2i, int >
lastHarvest = unit->getLastHarvestResourceTarget();
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"State: blocked, cmd [%s] pos: [%s], dest pos: [%s], lastHarvest = [%s - %d], reason A= %d, B= %d, C= %d, D= %d, E= %d, F = %d",
commandDesc.c_str(),
unit->getPos().getString().c_str(),
targetPos.getString().c_str(),
lastHarvest.first.getString().c_str(),
lastHarvest.second, pathFound,
(lastNode == firstNode), path->getBlockCount(),
path->isBlocked(), nodeLimitReached,
path->isStuck());
unit->setCurrentUnitTitle(szBuf);
}
if (frameIndex < 0) {
unit->setUsePathfinderExtendedMaxNodes(false);
}
ts = tsBlocked;
if (frameIndex < 0) {
path->incBlockCount();
}
if (SystemFlags::
getSystemSettingType(SystemFlags::debugPerformance).
enabled == true && chrono.getMillis() > 4)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s Line: %d] took msecs: %lld\n",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__, chrono.getMillis());
} else {
if (minorDebugPathfinder)
printf
("Legacy Pathfind Unit [%d - %s] FOUND PATH count = %d frameIndex = %d\n",
unit->getId(), unit->getType()->getName().c_str(),
whileLoopCount, frameIndex);
//on the way
ts = tsMoving;
//build next pointers
Node *
currNode = lastNode;
while (currNode->prev != NULL) {
currNode->prev->next = currNode;
currNode = currNode->prev;
}
if (SystemFlags::
getSystemSettingType(SystemFlags::debugPerformance).
enabled == true && chrono.getMillis() > 4)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s Line: %d] took msecs: %lld\n",
extractFileFromDirectoryPath
(__FILE__).c_str(), __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);
currNode = firstNode;
for (int i = 0; currNode->next != NULL;
currNode = currNode->next, i++) {
Vec2i
nodePos = currNode->next->pos;
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) {
faction.precachedPath[unit->getId()].push_back(nodePos);
} else {
if (i < unit->getPathFindRefreshCellCount() ||
(whileLoopCount >= pathFindExtendRefreshForNodeCount
&& i < getPathFindExtendRefreshNodeCount(faction))) {
path->add(nodePos);
}
}
}
if (SystemFlags::
getSystemSettingType(SystemFlags::debugPerformance).
enabled == true && chrono.getMillis() > 4)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s Line: %d] took msecs: %lld\n",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__, chrono.getMillis());
if (SystemFlags::
getSystemSettingType(SystemFlags::debugWorldSynch).enabled ==
true
&& SystemFlags::getSystemSettingType(SystemFlags::
debugWorldSynchMax).
enabled == true) {
char
szBuf[8096] = "";
string
pathToTake = "";
if (frameIndex < 0) {
vector < Vec2i > pathQueue = path->getQueue();
for (unsigned int index = 0; index < pathQueue.size();
++index) {
Vec2i & pos = pathQueue[index];
if (pathToTake != "") {
pathToTake += ", ";
}
pathToTake += pos.getString();
}
} else {
for (unsigned int index = 0;
index <
faction.precachedPath[unit->getId()].size();
++index) {
Vec2i & pos =
faction.precachedPath[unit->getId()][index];
if (pathToTake != "") {
pathToTake += ", ";
}
pathToTake += pos.getString();
}
}
snprintf(szBuf, 8096, "Path for unit to take = %s",
pathToTake.c_str());
if (frameIndex < 0) {
unit->
logSynchData(extractFileFromDirectoryPath(__FILE__).
c_str(), __LINE__, szBuf);
} else {
unit->
logSynchDataThreaded(extractFileFromDirectoryPath
(__FILE__).c_str(), __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(false);
}
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"State: moving, cmd [%s] pos: %s dest pos: %s, Queue= %d",
commandDesc.c_str(),
unit->getPos().getString().c_str(),
targetPos.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",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__, chrono.getMillis());
}
faction.openNodesList.clear();
faction.openPosList.clear();
faction.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",
extractFileFromDirectoryPath(__FILE__).
c_str(), __FUNCTION__, __LINE__,
chrono.getMillis());
if (frameIndex >= 0) {
FactionState & faction = factions.getFactionState(factionIndex);
faction.precachedTravelState[unit->getId()] = ts;
} else {
if (SystemFlags::VERBOSE_MODE_ENABLED && chrono.getMillis() >= 5)
printf
("In [%s::%s Line: %d] astar took [%lld] msecs, ts = %d.\n",
extractFileFromDirectoryPath(__FILE__).c_str(),
__FUNCTION__, __LINE__, (long long int) chrono.getMillis(),
ts);
}
if (SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).
enabled == true && frameIndex < 0) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096, "return ts: %d", ts);
unit->logSynchData(extractFileFromDirectoryPath(__FILE__).
c_str(), __LINE__, szBuf);
}
} catch (const exception & ex) {
SystemFlags::OutputDebug(SystemFlags::debugError,
"In [%s::%s Line: %d] Error [%s]\n",
__FILE__, __FUNCTION__, __LINE__,
ex.what());
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d]\n", __FILE__,
__FUNCTION__, __LINE__);
throw
megaglest_runtime_error(ex.what());
} catch (...) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096, "In [%s::%s %d] UNKNOWN error\n", __FILE__,
__FUNCTION__, __LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError, szBuf);
throw
megaglest_runtime_error(szBuf);
}
return ts;
}
void
PathFinder::processNearestFreePos(const Vec2i & finalPos, int i, int j,
int size, Field field, int teamIndex,
Vec2i unitPos, Vec2i & nearestPos,
float &nearestDist) {
try {
Vec2i
currPos = finalPos + Vec2i(i, j);
if (map->isAproxFreeCells(currPos, size, field, teamIndex)) {
float
dist = currPos.dist(finalPos);
//if nearer from finalPos
if (dist < nearestDist) {
nearestPos = currPos;
nearestDist = dist;
}
//if the distance is the same compare distance to unit
else if (dist == nearestDist) {
if (currPos.dist(unitPos) < nearestPos.dist(unitPos)) {
nearestPos = currPos;
}
}
}
} catch (const exception & ex) {
SystemFlags::OutputDebug(SystemFlags::debugError,
"In [%s::%s Line: %d] Error [%s]\n",
__FILE__, __FUNCTION__, __LINE__,
ex.what());
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d]\n", __FILE__,
__FUNCTION__, __LINE__);
throw
megaglest_runtime_error(ex.what());
} catch (...) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096, "In [%s::%s %d] UNKNOWN error\n", __FILE__,
__FUNCTION__, __LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError, szBuf);
throw
megaglest_runtime_error(szBuf);
}
}
Vec2i
PathFinder::computeNearestFreePos(const Unit * unit,
const Vec2i & finalPos) {
Vec2i
nearestPos(0, 0);
try {
if (map == NULL) {
throw
megaglest_runtime_error("map == NULL");
}
//unit data
int
size = unit->getType()->getSize();
Field
field = unit->getCurrField();
int
teamIndex = unit->getTeam();
//if finalPos is free return it
if (map->isAproxFreeCells(finalPos, size, field, teamIndex)) {
return finalPos;
}
//find nearest pos
Vec2i
unitPos = unit->getPosNotThreadSafe();
nearestPos = unitPos;
float
nearestDist = unitPos.dist(finalPos);
for (int i = -maxFreeSearchRadius; i <= maxFreeSearchRadius; ++i) {
for (int j = -maxFreeSearchRadius; j <= maxFreeSearchRadius; ++j) {
processNearestFreePos(finalPos, i, j, size, field, teamIndex,
unitPos, nearestPos, nearestDist);
}
}
} catch (const exception & ex) {
SystemFlags::OutputDebug(SystemFlags::debugError,
"In [%s::%s Line: %d] Error [%s]\n",
__FILE__, __FUNCTION__, __LINE__,
ex.what());
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d]\n", __FILE__,
__FUNCTION__, __LINE__);
throw
megaglest_runtime_error(ex.what());
} catch (...) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096, "In [%s::%s %d] UNKNOWN error\n", __FILE__,
__FUNCTION__, __LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError, szBuf);
throw
megaglest_runtime_error(szBuf);
}
return nearestPos;
}
int
PathFinder::findNodeIndex(Node * node, Nodes & nodeList) {
int
index = -1;
if (node != NULL) {
for (unsigned int i = 0; i < nodeList.size(); ++i) {
Node *
curnode = nodeList[i];
if (node == curnode) {
index = i;
break;
}
}
}
return index;
}
int
PathFinder::findNodeIndex(Node * node, std::vector < Node > &nodeList) {
int
index = -1;
if (node != NULL) {
for (unsigned int i = 0; i < nodeList.size(); ++i) {
Node & curnode = nodeList[i];
if (node == &curnode) {
index = i;
break;
}
}
}
return index;
}
//bool PathFinder::unitCannotMove(Unit *unit) {
// bool unitImmediatelyBlocked = false;
//
// try {
// // First check if unit currently blocked all around them, if so don't try to pathfind
// const Vec2i unitPos = unit->getPos();
// 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) {
// bool canUnitMoveToCell = map->aproxCanMove(unit, unitPos, pos);
// if(canUnitMoveToCell == false) {
// failureCount++;
// }
// cellCount++;
// }
// }
// }
// unitImmediatelyBlocked = (failureCount == cellCount);
//
// }
// catch(const exception &ex) {
// //setRunningStatus(false);
//
// SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
// if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
//
// throw megaglest_runtime_error(ex.what());
// }
// catch(...) {
// char szBuf[8096]="";
// snprintf(szBuf,8096,"In [%s::%s %d] UNKNOWN error\n",__FILE__,__FUNCTION__,__LINE__);
// SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
// throw megaglest_runtime_error(szBuf);
// }
//
// return unitImmediatelyBlocked;
//}
void
PathFinder::saveGame(XmlNode * rootNode) {
std::map < string, string > mapTagReplacements;
XmlNode *
pathfinderNode = rootNode->addChild("PathFinder");
pathfinderNode->addAttribute("pathFindNodesMax",
intToStr(pathFindNodesMax),
mapTagReplacements);
pathfinderNode->addAttribute("pathFindNodesAbsoluteMax",
intToStr(pathFindNodesAbsoluteMax),
mapTagReplacements);
for (unsigned int i = 0; i < (unsigned int) factions.size(); ++i) {
FactionState & factionState = factions.getFactionState(i);
XmlNode *
factionsNode = pathfinderNode->addChild("factions");
for (unsigned int j = 0;
j < (unsigned int) factionState.nodePool.size(); ++j) {
Node *
curNode = &factionState.nodePool[j];
XmlNode *
nodePoolNode = factionsNode->addChild("nodePool");
nodePoolNode->addAttribute("pos", curNode->pos.getString(),
mapTagReplacements);
int
nextIdx =
findNodeIndex(curNode->next, factionState.nodePool);
nodePoolNode->addAttribute("next", intToStr(nextIdx),
mapTagReplacements);
int
prevIdx =
findNodeIndex(curNode->prev, factionState.nodePool);
nodePoolNode->addAttribute("prev", intToStr(prevIdx),
mapTagReplacements);
nodePoolNode->addAttribute("heuristic",
floatToStr(curNode->heuristic, 6),
mapTagReplacements);
nodePoolNode->addAttribute("exploredCell",
intToStr(curNode->exploredCell),
mapTagReplacements);
}
factionsNode->addAttribute("nodePoolCount",
intToStr(factionState.nodePoolCount),
mapTagReplacements);
factionsNode->addAttribute("random",
intToStr(factionState.random.
getLastNumber()),
mapTagReplacements);
factionsNode->addAttribute("useMaxNodeCount",
intToStr(factionState.useMaxNodeCount),
mapTagReplacements);
}
}
void
PathFinder::loadGame(const XmlNode * rootNode) {
const XmlNode *
pathfinderNode = rootNode->getChild("PathFinder");
vector < XmlNode * >factionsNodeList =
pathfinderNode->getChildList("factions");
for (unsigned int i = 0; i < (unsigned int) factionsNodeList.size();
++i) {
XmlNode *
factionsNode = factionsNodeList[i];
FactionState & factionState = factions.getFactionState(i);
vector < XmlNode * >nodePoolListNode =
factionsNode->getChildList("nodePool");
for (unsigned int j = 0;
j < (unsigned int) nodePoolListNode.size()
&& j < (unsigned int) pathFindNodesAbsoluteMax; ++j) {
XmlNode *
nodePoolNode = nodePoolListNode[j];
Node *
curNode = &factionState.nodePool[j];
curNode->pos =
Vec2i::strToVec2(nodePoolNode->getAttribute("pos")->
getValue());
int
nextNode =
nodePoolNode->getAttribute("next")->getIntValue();
if (nextNode >= 0) {
curNode->next = &factionState.nodePool[nextNode];
} else {
curNode->next = NULL;
}
int
prevNode =
nodePoolNode->getAttribute("prev")->getIntValue();
if (prevNode >= 0) {
curNode->prev = &factionState.nodePool[prevNode];
} else {
curNode->prev = NULL;
}
curNode->heuristic =
nodePoolNode->getAttribute("heuristic")->getFloatValue();
curNode->exploredCell =
nodePoolNode->getAttribute("exploredCell")->getIntValue() !=
0;
}
factionState.nodePoolCount =
factionsNode->getAttribute("nodePoolCount")->getIntValue();
factionState.random.setLastNumber(factionsNode->
getAttribute("random")->
getIntValue());
factionState.useMaxNodeCount = PathFinder::pathFindNodesMax;
}
}
}
} //end namespace