- attempt to see if threaded pathfinding will work and if it improves performance

This commit is contained in:
Mark Vejvoda 2011-03-18 03:53:06 +00:00
parent e65f588045
commit 07f56669b7
12 changed files with 1054 additions and 524 deletions

View File

@ -45,12 +45,19 @@ const int PathFinder::pathFindBailoutRadius = 20;
PathFinder::PathFinder() {
nodePool.clear();
for(int i = 0; i < GameConstants::maxPlayers; ++i) {
factions.push_back(FactionState());
}
//nodePool.clear();
map=NULL;
}
PathFinder::PathFinder(const Map *map) {
nodePool.clear();
for(int i = 0; i < GameConstants::maxPlayers; ++i) {
factions.push_back(FactionState());
}
//nodePool.clear();
map=NULL;
init(map);
@ -58,22 +65,35 @@ PathFinder::PathFinder(const Map *map) {
void PathFinder::init(const Map *map) {
PathFinder::pathFindNodesMax = Config::getInstance().getInt("MaxPathfinderNodeCount",intToStr(PathFinder::pathFindNodesMax).c_str());
nodePool.resize(pathFindNodesMax);
useMaxNodeCount = PathFinder::pathFindNodesMax;
for(int i = 0; i < GameConstants::maxPlayers; ++i) {
factions[i].nodePool.resize(pathFindNodesMax);
factions[i].useMaxNodeCount = PathFinder::pathFindNodesMax;
}
this->map= map;
}
PathFinder::~PathFinder(){
nodePool.clear();
PathFinder::~PathFinder() {
for(int i = 0; i < GameConstants::maxPlayers; ++i) {
factions[i].nodePool.clear();
}
map=NULL;
}
TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStuck) {
void PathFinder::clearUnitPrecache(Unit *unit) {
factions[unit->getFactionIndex()].precachedTravelState[unit->getId()] = tsImpossible;
factions[unit->getFactionIndex()].precachedPath[unit->getId()].clear();
}
TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStuck, int frameIndex) {
//printf("PathFinder::findPath...\n");
if(map == NULL) {
throw runtime_error("map == NULL");
}
if(frameIndex >= 0) {
clearUnitPrecache(unit);
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) {
char szBuf[4096]="";
@ -83,11 +103,11 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
}
//route cache
UnitPathInterface *path= unit->getPath();
if(finalPos == unit->getPos()) {
//if arrived
unit->setCurrSkill(scStop);
if(frameIndex < 0) {
//if arrived
unit->setCurrSkill(scStop);
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) {
string commandDesc = "none";
Command *command= unit->getCurrCommand();
@ -102,36 +122,39 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
//unit->getFaction()->addCachedPath(finalPos,unit);
return tsArrived;
}
else {
if(path->isEmpty() == false) {
if(dynamic_cast<UnitPathBasic *>(path) != NULL) {
//route cache
UnitPathBasic *basicPath = dynamic_cast<UnitPathBasic *>(path);
Vec2i pos= basicPath->pop();
//if(map->canMove(unit, unit->getPos(), pos, &lookupCacheCanMove)) {
if(map->canMove(unit, unit->getPos(), pos)) {
UnitPathInterface *path= unit->getPath();
if(path->isEmpty() == false) {
if(dynamic_cast<UnitPathBasic *>(path) != NULL) {
//route cache
UnitPathBasic *basicPath = dynamic_cast<UnitPathBasic *>(path);
Vec2i pos= basicPath->pop(frameIndex < 0);
if(map->canMove(unit, unit->getPos(), pos)) {
if(frameIndex < 0) {
unit->setTargetPos(pos);
unit->addCurrentTargetPathTakenCell(finalPos,pos);
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, &lookupCacheCanMove)) {
if(map->canMove(unit, unit->getPos(), pos)) {
advPath->pop();
unit->setTargetPos(pos);
return tsMoving;
}
}
else {
throw runtime_error("unsupported or missing path finder detected!");
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);
}
return tsMoving;
}
}
else {
throw runtime_error("unsupported or missing path finder detected!");
}
}
TravelState ts = tsImpossible;
//std::vector<Vec2i> cachedPath = unit->getFaction()->findCachedPath(finalPos, unit);
@ -144,10 +167,10 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
//}
//else {
//route cache miss
ts = aStar(unit, finalPos, false);
ts = aStar(unit, finalPos, false, frameIndex);
//}
if(ts == tsBlocked) {
//if(ts == tsBlocked) {
//std::vector<Vec2i> cachedPath = unit->getFaction()->findCachedPath(finalPos, unit);
//if(cachedPath.size() > 0) {
// path->clear();
@ -158,16 +181,16 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
// ts = tsMoving;
// unit->addCurrentTargetPathTakenCell(Vec2i(-1),Vec2i(-1));
//}
}
//}
//post actions
switch(ts) {
case tsBlocked:
case tsArrived:
if(ts == tsArrived) {
//if(ts == tsArrived) {
//unit->getFaction()->addCachedPath(finalPos,unit);
}
//}
// 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
@ -224,7 +247,7 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
if(useBailoutRadius == true) {
//int tryRadius = random.randRange(-PathFinder::pathFindBailoutRadius, PathFinder::pathFindBailoutRadius);
int tryRadius = random.randRange(0,1);
int tryRadius = factions[unit->getFactionIndex()].random.randRange(0,1);
//printf("#4 BAILOUT test unitid [%d] useBailoutRadius [%d] tryRadius [%d]\n",unit->getId(),useBailoutRadius,tryRadius);
@ -243,7 +266,7 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
}
if(canUnitMove) {
ts= aStar(unit, newFinalPos, true);
ts= aStar(unit, newFinalPos, true, frameIndex);
}
}
}
@ -262,7 +285,7 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
}
if(canUnitMove) {
ts= aStar(unit, newFinalPos, true);
ts= aStar(unit, newFinalPos, true, frameIndex);
}
}
}
@ -271,35 +294,50 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
unit->setInBailOutAttempt(false);
}
if(ts == tsArrived || ts == tsBlocked) {
unit->setCurrSkill(scStop);
if(frameIndex < 0) {
unit->setCurrSkill(scStop);
}
}
break;
case tsMoving:
{
if(dynamic_cast<UnitPathBasic *>(path) != NULL) {
UnitPathBasic *basicPath = dynamic_cast<UnitPathBasic *>(path);
Vec2i pos= basicPath->pop();
Vec2i pos;
if(frameIndex < 0) {
pos = basicPath->pop(frameIndex < 0);
}
else {
pos = factions[unit->getFactionIndex()].precachedPath[unit->getId()][0];
}
//if(map->canMove(unit, unit->getPos(), pos, &lookupCacheCanMove)) {
if(map->canMove(unit, unit->getPos(), pos)) {
unit->setTargetPos(pos);
unit->addCurrentTargetPathTakenCell(finalPos,pos);
if(frameIndex < 0) {
unit->setTargetPos(pos);
unit->addCurrentTargetPathTakenCell(finalPos,pos);
}
}
else {
unit->setCurrSkill(scStop);
if(frameIndex < 0) {
unit->setCurrSkill(scStop);
}
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, &lookupCacheCanMove)) {
if(map->canMove(unit, unit->getPos(), pos)) {
advPath->pop();
unit->setTargetPos(pos);
if(frameIndex < 0) {
advPath->pop();
unit->setTargetPos(pos);
}
}
else {
unit->setCurrSkill(scStop);
if(frameIndex < 0) {
unit->setCurrSkill(scStop);
}
return tsBlocked;
}
}
@ -319,20 +357,20 @@ bool PathFinder::processNode(Unit *unit, Node *node,const Vec2i finalPos, int i,
bool result = false;
Vec2i sucPos= node->pos + Vec2i(i, j);
bool canUnitMoveToCell = map->aproxCanMove(unit, node->pos, sucPos);
if(openPos(sucPos) == false && canUnitMoveToCell == true) {
if(openPos(sucPos, factions[unit->getFactionIndex()]) == false && canUnitMoveToCell == true) {
//if node is not open and canMove then generate another node
Node *sucNode= newNode();
Node *sucNode= newNode(factions[unit->getFactionIndex()]);
if(sucNode != NULL) {
sucNode->pos= sucPos;
sucNode->heuristic= heuristic(sucNode->pos, finalPos);
sucNode->prev= node;
sucNode->next= NULL;
sucNode->exploredCell= map->getSurfaceCell(Map::toSurfCoords(sucPos))->isExplored(unit->getTeam());
if(openNodesList.find(sucNode->heuristic) == openNodesList.end()) {
openNodesList[sucNode->heuristic].clear();
if(factions[unit->getFactionIndex()].openNodesList.find(sucNode->heuristic) == factions[unit->getFactionIndex()].openNodesList.end()) {
factions[unit->getFactionIndex()].openNodesList[sucNode->heuristic].clear();
}
openNodesList[sucNode->heuristic].push_back(sucNode);
openPosList[sucNode->pos] = true;
factions[unit->getFactionIndex()].openNodesList[sucNode->heuristic].push_back(sucNode);
factions[unit->getFactionIndex()].openPosList[sucNode->pos] = true;
result = true;
}
@ -344,7 +382,8 @@ bool PathFinder::processNode(Unit *unit, Node *node,const Vec2i finalPos, int i,
}
//route a unit using A* algorithm
TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout) {
TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout,
int frameIndex) {
//printf("PathFinder::aStar...\n");
Chrono chrono;
@ -354,18 +393,78 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
throw runtime_error("map == NULL");
}
nodePoolCount= 0;
openNodesList.clear();
openPosList.clear();
closedNodesList.clear();
UnitPathInterface *path= unit->getPath();
factions[unit->getFactionIndex()].nodePoolCount= 0;
factions[unit->getFactionIndex()].openNodesList.clear();
factions[unit->getFactionIndex()].openPosList.clear();
factions[unit->getFactionIndex()].closedNodesList.clear();
TravelState ts = tsImpossible;
if(frameIndex < 0) {
if(factions[unit->getFactionIndex()].precachedTravelState.find(unit->getId()) != factions[unit->getFactionIndex()].precachedTravelState.end()) {
if(factions[unit->getFactionIndex()].precachedTravelState[unit->getId()] == tsMoving) {
bool canMoveToCells = true;
Vec2i lastPos = unit->getPos();
for(int i=0; i < factions[unit->getFactionIndex()].precachedPath[unit->getId()].size(); i++) {
Vec2i nodePos = factions[unit->getFactionIndex()].precachedPath[unit->getId()][i];
if(map->isInside(nodePos) == false || map->isInsideSurface(map->toSurfCoords(nodePos)) == false) {
throw runtime_error("Pathfinder invalid node path position = " + nodePos.getString() + " i = " + intToStr(i));
}
if(i < pathFindRefresh) {
if(map->aproxCanMove(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[unit->getFactionIndex()].precachedPath[unit->getId()].size(); i++) {
Vec2i nodePos = factions[unit->getFactionIndex()].precachedPath[unit->getId()][i];
if(map->isInside(nodePos) == false || map->isInsideSurface(map->toSurfCoords(nodePos)) == false) {
throw runtime_error("Pathfinder invalid node path position = " + nodePos.getString() + " i = " + intToStr(i));
}
if(i < pathFindRefresh) {
path->add(nodePos);
}
else {
break;
}
}
return factions[unit->getFactionIndex()].precachedTravelState[unit->getId()];
}
else {
clearUnitPrecache(unit);
}
}
else if(factions[unit->getFactionIndex()].precachedTravelState[unit->getId()] == tsBlocked) {
path->incBlockCount();
return factions[unit->getFactionIndex()].precachedTravelState[unit->getId()];
}
}
}
else {
clearUnitPrecache(unit);
}
const Vec2i unitPos = unit->getPos();
const Vec2i finalPos= computeNearestFreePos(unit, targetPos);
float dist= unitPos.dist(finalPos);
useMaxNodeCount = PathFinder::pathFindNodesMax;
factions[unit->getFactionIndex()].useMaxNodeCount = PathFinder::pathFindNodesMax;
// if(dist <= 10) {
// useMaxNodeCount = (int)dist * 20;
// if(useMaxNodeCount <= 0) {
@ -375,7 +474,6 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
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());
UnitPathInterface *path= unit->getPath();
// Check the previous path find cache for the unit to see if its good to
// use
const bool showConsoleDebugInfo = Config::getInstance().getBool("EnablePathfinderDistanceOutput","false");
@ -422,7 +520,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) {
char szBuf[4096]="";
sprintf(szBuf,"[Setting new path for unit] openNodesList.size() [%lu] openPosList.size() [%lu] finalPos [%s] targetPos [%s] inBailout [%d] ts [%d]",
openNodesList.size(),openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts);
factions[unit->getFactionIndex()].openNodesList.size(),factions[unit->getFactionIndex()].openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts);
unit->logSynchData(__FILE__,__LINE__,szBuf);
}
@ -470,7 +568,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) {
char szBuf[4096]="";
sprintf(szBuf,"[Setting new path for unit] openNodesList.size() [%lu] openPosList.size() [%lu] finalPos [%s] targetPos [%s] inBailout [%d] ts [%d]",
openNodesList.size(),openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts);
factions[unit->getFactionIndex()].openNodesList.size(),factions[unit->getFactionIndex()].openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts);
unit->logSynchData(__FILE__,__LINE__,szBuf);
}
@ -506,7 +604,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
//path find algorithm
//a) push starting pos into openNodes
Node *firstNode= newNode();
Node *firstNode= newNode(factions[unit->getFactionIndex()]);
assert(firstNode != NULL);
if(firstNode == NULL) {
throw runtime_error("firstNode == NULL");
@ -517,11 +615,11 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
firstNode->pos= unitPos;
firstNode->heuristic= heuristic(unitPos, finalPos);
firstNode->exploredCell= true;
if(openNodesList.find(firstNode->heuristic) == openNodesList.end()) {
openNodesList[firstNode->heuristic].clear();
if(factions[unit->getFactionIndex()].openNodesList.find(firstNode->heuristic) == factions[unit->getFactionIndex()].openNodesList.end()) {
factions[unit->getFactionIndex()].openNodesList[firstNode->heuristic].clear();
}
openNodesList[firstNode->heuristic].push_back(firstNode);
openPosList[firstNode->pos] = true;
factions[unit->getFactionIndex()].openNodesList[firstNode->heuristic].push_back(firstNode);
factions[unit->getFactionIndex()].openPosList[firstNode->pos] = true;
//b) loop
bool pathFound = true;
@ -592,14 +690,14 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
whileLoopCount++;
//b1) is open nodes is empty => failed to find the path
if(openNodesList.empty() == true) {
if(factions[unit->getFactionIndex()].openNodesList.empty() == true) {
pathFound= false;
break;
}
//b2) get the minimum heuristic node
//Nodes::iterator it = minHeuristic();
node = minHeuristicFastLookup();
node = minHeuristicFastLookup(factions[unit->getFactionIndex()]);
//b3) if minHeuristic is the finalNode, or the path is no more explored => path was found
if(node->pos == finalPos || node->exploredCell == false) {
@ -609,16 +707,16 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
//b4) move this node from closedNodes to openNodes
//add all succesors that are not in closedNodes or openNodes to openNodes
if(closedNodesList.find(node->heuristic) == closedNodesList.end()) {
closedNodesList[node->heuristic].clear();
if(factions[unit->getFactionIndex()].closedNodesList.find(node->heuristic) == factions[unit->getFactionIndex()].closedNodesList.end()) {
factions[unit->getFactionIndex()].closedNodesList[node->heuristic].clear();
}
closedNodesList[node->heuristic].push_back(node);
openPosList[node->pos] = true;
factions[unit->getFactionIndex()].closedNodesList[node->heuristic].push_back(node);
factions[unit->getFactionIndex()].openPosList[node->pos] = true;
int failureCount = 0;
int cellCount = 0;
int tryDirection = random.randRange(0,3);
int tryDirection = factions[unit->getFactionIndex()].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) {
@ -673,19 +771,19 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
}
} //while
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld nodeLimitReached = %d whileLoopCount = %d nodePoolCount = %d\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),nodeLimitReached,whileLoopCount,nodePoolCount);
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld nodeLimitReached = %d whileLoopCount = %d nodePoolCount = %d\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),nodeLimitReached,whileLoopCount,factions[unit->getFactionIndex()].nodePoolCount);
if(showConsoleDebugInfo && chrono.getMillis() > 2) {
printf("Distance for unit [%d - %s] from [%s] to [%s] is %.2f took msecs: %lld nodeLimitReached = %d whileLoopCount = %d nodePoolCount = %d\n",unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),nodeLimitReached,whileLoopCount,nodePoolCount);
printf("Distance for unit [%d - %s] from [%s] to [%s] is %.2f took msecs: %lld nodeLimitReached = %d whileLoopCount = %d nodePoolCount = %d\n",unit->getId(),unit->getFullName().c_str(), unitPos.getString().c_str(), finalPos.getString().c_str(), dist,(long long int)chrono.getMillis(),nodeLimitReached,whileLoopCount,factions[unit->getFactionIndex()].nodePoolCount);
}
Node *lastNode= node;
//if consumed all nodes find best node (to avoid strange behaviour)
if(nodeLimitReached == true) {
if(closedNodesList.size() > 0) {
float bestHeuristic = closedNodesList.begin()->first;
if(factions[unit->getFactionIndex()].closedNodesList.size() > 0) {
float bestHeuristic = factions[unit->getFactionIndex()].closedNodesList.begin()->first;
if(bestHeuristic < lastNode->heuristic) {
lastNode= closedNodesList.begin()->second[0];
lastNode= factions[unit->getFactionIndex()].closedNodesList.begin()->second[0];
}
}
}
@ -712,12 +810,14 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
}
ts= tsBlocked;
path->incBlockCount();
if(frameIndex < 0) {
path->incBlockCount();
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) {
char szBuf[4096]="";
sprintf(szBuf,"[path for unit BLOCKED] openNodesList.size() [%lu] openPosList.size() [%lu] finalPos [%s] targetPos [%s] inBailout [%d] ts [%d]",
openNodesList.size(),openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts);
factions[unit->getFactionIndex()].openNodesList.size(),factions[unit->getFactionIndex()].openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts);
unit->logSynchData(__FILE__,__LINE__,szBuf);
}
@ -737,7 +837,10 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
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
path->clear();
if(frameIndex < 0) {
path->clear();
}
UnitPathBasic *basicPathFinder = dynamic_cast<UnitPathBasic *>(path);
currNode= firstNode;
@ -747,15 +850,20 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
throw runtime_error("Pathfinder invalid node path position = " + nodePos.getString() + " i = " + intToStr(i));
}
if(i < pathFindRefresh) {
path->add(nodePos);
}
else if(tryLastPathCache == false) {
break;
if(frameIndex >= 0) {
factions[unit->getFactionIndex()].precachedPath[unit->getId()].push_back(nodePos);
}
else {
if(i < pathFindRefresh) {
path->add(nodePos);
}
else if(tryLastPathCache == false) {
break;
}
if(tryLastPathCache == true && basicPathFinder) {
basicPathFinder->addToLastPathCache(nodePos);
if(tryLastPathCache == true && basicPathFinder) {
basicPathFinder->addToLastPathCache(nodePos);
}
}
}
@ -764,7 +872,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) {
char szBuf[4096]="";
sprintf(szBuf,"[Setting new path for unit] openNodesList.size() [%lu] openPosList.size() [%lu] finalPos [%s] targetPos [%s] inBailout [%d] ts [%d]",
openNodesList.size(),openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts);
factions[unit->getFactionIndex()].openNodesList.size(),factions[unit->getFactionIndex()].openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts);
unit->logSynchData(__FILE__,__LINE__,szBuf);
string pathToTake = "";
@ -794,20 +902,27 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
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());
}
openNodesList.clear();
openPosList.clear();
closedNodesList.clear();
factions[unit->getFactionIndex()].openNodesList.clear();
factions[unit->getFactionIndex()].openPosList.clear();
factions[unit->getFactionIndex()].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[unit->getFactionIndex()].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",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis(),ts);
}
return ts;
}
PathFinder::Node *PathFinder::newNode() {
if(nodePoolCount < nodePool.size() && nodePoolCount < useMaxNodeCount) {
Node *node= &nodePool[nodePoolCount];
PathFinder::Node *PathFinder::newNode(FactionState &faction) {
if( faction.nodePoolCount < faction.nodePool.size() &&
faction.nodePoolCount < faction.useMaxNodeCount) {
Node *node= &(faction.nodePool[faction.nodePoolCount]);
node->clear();
nodePoolCount++;
faction.nodePoolCount++;
return node;
}
return NULL;
@ -864,22 +979,22 @@ float PathFinder::heuristic(const Vec2i &pos, const Vec2i &finalPos) {
return pos.dist(finalPos);
}
PathFinder::Node * PathFinder::minHeuristicFastLookup() {
assert(openNodesList.empty() == false);
if(openNodesList.empty() == true) {
PathFinder::Node * PathFinder::minHeuristicFastLookup(FactionState &faction) {
assert(faction.openNodesList.empty() == false);
if(faction.openNodesList.empty() == true) {
throw runtime_error("openNodesList.empty() == true");
}
Node *result = openNodesList.begin()->second[0];
openNodesList.begin()->second.erase(openNodesList.begin()->second.begin());
if(openNodesList.begin()->second.size() == 0) {
openNodesList.erase(openNodesList.begin());
Node *result = faction.openNodesList.begin()->second[0];
faction.openNodesList.begin()->second.erase(faction.openNodesList.begin()->second.begin());
if(faction.openNodesList.begin()->second.size() == 0) {
faction.openNodesList.erase(faction.openNodesList.begin());
}
return result;
}
bool PathFinder::openPos(const Vec2i &sucPos) {
if(openPosList.find(sucPos) == openPosList.end()) {
bool PathFinder::openPos(const Vec2i &sucPos, FactionState &faction) {
if(faction.openPosList.find(sucPos) == faction.openPosList.end()) {
return false;
}
return true;

View File

@ -57,38 +57,59 @@ public:
};
typedef vector<Node*> Nodes;
class FactionState {
public:
FactionState() {
openPosList.clear();
openNodesList.clear();
closedNodesList.clear();
nodePool.clear();
nodePoolCount = 0;
useMaxNodeCount = 0;
precachedTravelState.clear();
precachedPath.clear();
}
std::map<Vec2i, bool> openPosList;
std::map<float, Nodes> openNodesList;
std::map<float, Nodes> closedNodesList;
std::vector<Node> nodePool;
int nodePoolCount;
RandomGen random;
int useMaxNodeCount;
std::map<int,TravelState> precachedTravelState;
std::map<int,std::vector<Vec2i> > precachedPath;
};
typedef vector<FactionState> FactionStateList;
public:
static const int maxFreeSearchRadius;
static int pathFindNodesMax;
static const int pathFindRefresh;
static const int pathFindBailoutRadius;
private:
std::map<Vec2i, bool> openPosList;
std::map<float, Nodes> openNodesList;
std::map<float, Nodes> closedNodesList;
std::vector<Node> nodePool;
int nodePoolCount;
static int pathFindNodesMax;
FactionStateList factions;
const Map *map;
RandomGen random;
int useMaxNodeCount;
public:
PathFinder();
PathFinder(const Map *map);
~PathFinder();
void init(const Map *map);
TravelState findPath(Unit *unit, const Vec2i &finalPos, bool *wasStuck=NULL);
TravelState findPath(Unit *unit, const Vec2i &finalPos, bool *wasStuck=NULL,int frameIndex=-1);
void clearUnitPrecache(Unit *unit);
private:
TravelState aStar(Unit *unit, const Vec2i &finalPos, bool inBailout);
Node *newNode();
TravelState aStar(Unit *unit, const Vec2i &finalPos, bool inBailout, int frameIndex);
Node *newNode(FactionState &faction);
Vec2i computeNearestFreePos(const Unit *unit, const Vec2i &targetPos);
float heuristic(const Vec2i &pos, const Vec2i &finalPos);
bool openPos(const Vec2i &sucPos);
bool openPos(const Vec2i &sucPos,FactionState &faction);
Node * minHeuristicFastLookup();
Node * minHeuristicFastLookup(FactionState &faction);
bool processNode(Unit *unit, Node *node,const Vec2i finalPos, int i, int j, bool &nodeLimitReached);
void processNearestFreePos(const Vec2i &finalPos, int i, int j, int size, Field field, int teamIndex,Vec2i unitPos, Vec2i &nearestPos, float &nearestDist);

View File

@ -26,7 +26,164 @@
using namespace Shared::Util;
namespace Glest{ namespace Game{
namespace Glest { namespace Game {
// =====================================================
// class FactionThread
// =====================================================
FactionThread::FactionThread(Faction *faction) : BaseThread() {
this->faction = faction;
}
void FactionThread::setQuitStatus(bool value) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d value = %d\n",__FILE__,__FUNCTION__,__LINE__,value);
BaseThread::setQuitStatus(value);
if(value == true) {
signalPathfinder(-1);
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
}
void FactionThread::signalPathfinder(int frameIndex) {
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] event = %p\n",__FILE__,__FUNCTION__,__LINE__,event);
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] frameIndex = %d this = %p\n",__FILE__,__FUNCTION__,__LINE__,frameIndex, this);
if(frameIndex >= 0) {
static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper safeMutex(&triggerIdMutex,mutexOwnerId);
this->frameIndex.first = frameIndex;
this->frameIndex.second = false;
safeMutex.ReleaseLock();
}
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
semTaskSignalled.signal();
}
void FactionThread::setTaskCompleted(int frameIndex) {
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] frameIndex = %d this = %p\n",__FILE__,__FUNCTION__,__LINE__,frameIndex, this);
if(frameIndex >= 0) {
static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper safeMutex(&triggerIdMutex,mutexOwnerId);
if(this->frameIndex.first == frameIndex) {
this->frameIndex.second = true;
}
safeMutex.ReleaseLock();
}
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
}
bool FactionThread::canShutdown(bool deleteSelfIfShutdownDelayed) {
bool ret = (getExecutingTask() == false);
if(ret == false && deleteSelfIfShutdownDelayed == true) {
setDeleteSelfOnExecutionDone(deleteSelfIfShutdownDelayed);
signalQuit();
}
return ret;
}
bool FactionThread::isSignalPathfinderCompleted(int frameIndex) {
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] slotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,slotIndex);
if(getRunningStatus() == false) {
return true;
}
static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper safeMutex(&triggerIdMutex,mutexOwnerId);
//bool result = (event != NULL ? event->eventCompleted : true);
bool result = (this->frameIndex.first == frameIndex && this->frameIndex.second == true);
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] worker thread this = %p, this->frameIndex.first = %d, this->frameIndex.second = %d\n",__FILE__,__FUNCTION__,__LINE__,this,this->frameIndex.first,this->frameIndex.second);
safeMutex.ReleaseLock();
//if(result == false) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] slotIndex = %d, result = %d\n",__FILE__,__FUNCTION__,__LINE__,slotIndex,result);
return result;
}
void FactionThread::execute() {
RunningStatusSafeWrapper runningStatus(this);
try {
//setRunningStatus(true);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] ****************** STARTING worker thread this = %p\n",__FILE__,__FUNCTION__,__LINE__,this);
unsigned int idx = 0;
for(;this->faction != NULL;) {
if(getQuitStatus() == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
semTaskSignalled.waitTillSignalled();
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
if(getQuitStatus() == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper safeMutex(&triggerIdMutex,mutexOwnerId);
bool executeTask = (frameIndex.first >= 0);
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] frameIndex = %d this = %p executeTask = %d\n",__FILE__,__FUNCTION__,__LINE__,frameIndex.first, this, executeTask);
safeMutex.ReleaseLock();
if(executeTask == true) {
ExecutingTaskSafeWrapper safeExecutingTaskMutex(this);
//this->slotInterface->slotUpdateTask(&eventCopy);
World *world = faction->getWorld();
int unitCount = faction->getUnitCount();
for(int j = 0; j < unitCount; ++j) {
Unit *unit = faction->getUnit(j);
if(unit == NULL) {
throw runtime_error("unit == NULL");
}
bool update = unit->needToUpdate();
if(update == true) {
world->getUnitUpdater()->updateUnitCommand(unit,frameIndex.first);
}
}
setTaskCompleted(frameIndex.first);
}
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
if(getQuitStatus() == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] ****************** ENDING worker thread this = %p\n",__FILE__,__FUNCTION__,__LINE__,this);
}
catch(const exception &ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw runtime_error(ex.what());
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
//setRunningStatus(false);
}
// =====================================================
// class Faction
@ -37,6 +194,7 @@ Faction::Faction() {
//lastResourceTargettListPurge = 0;
cachingDisabled=false;
factionDisconnectHandled=false;
workerThread = NULL;
}
Faction::~Faction() {
@ -50,11 +208,33 @@ Faction::~Faction() {
//texture->end();
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(workerThread != NULL) {
workerThread->signalQuit();
if(workerThread->shutdownAndWait() == true) {
delete workerThread;
}
workerThread = NULL;
}
//delete texture;
texture = NULL;
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void Faction::signalWorkerThread(int frameIndex) {
if(workerThread != NULL) {
workerThread->signalPathfinder(frameIndex);
}
}
bool Faction::isWorkerThreadSignalCompleted(int frameIndex) {
if(workerThread != NULL) {
return workerThread->isSignalPathfinderCompleted(frameIndex);
}
return true;
}
void Faction::init(
FactionType *factionType, ControlType control, TechTree *techTree, Game *game,
int factionIndex, int teamIndex, int startLocationIndex, bool thisFaction, bool giveResources)
@ -84,11 +264,33 @@ void Faction::init(
string data_path = getGameReadWritePath(GameConstants::path_data_CacheLookupKey);
texture->load(data_path + "data/core/faction_textures/faction"+intToStr(startLocationIndex)+".tga");
if(Config::getInstance().getBool("EnableFactionWorkerThreads","true") == true) {
if(workerThread != NULL) {
workerThread->signalQuit();
if(workerThread->shutdownAndWait() == true) {
delete workerThread;
}
workerThread = NULL;
}
this->workerThread = new FactionThread(this);
this->workerThread->setUniqueID(__FILE__);
this->workerThread->start();
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void Faction::end(){
void Faction::end() {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(workerThread != NULL) {
workerThread->signalQuit();
if(workerThread->shutdownAndWait() == true) {
delete workerThread;
}
workerThread = NULL;
}
deleteValues(units.begin(), units.end());
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}

View File

@ -20,12 +20,14 @@
#include "resource.h"
#include "game_constants.h"
#include "command_type.h"
#include "base_thread.h"
#include "leak_dumper.h"
using std::map;
using std::vector;
using Shared::Graphics::Texture2D;
using namespace Shared::PlatformCommon;
namespace Glest{ namespace Game{
@ -39,6 +41,7 @@ class UnitType;
class Game;
class ScriptManager;
class World;
class Faction;
// =====================================================
// class Faction
@ -54,6 +57,25 @@ public:
vector<std::pair<vector<Vec2i>, int> > pathQueue;
};
class FactionThread : public BaseThread {
protected:
Faction *faction;
Semaphore semTaskSignalled;
Mutex triggerIdMutex;
std::pair<int,bool> frameIndex;
virtual void setQuitStatus(bool value);
virtual void setTaskCompleted(int frameIndex);
virtual bool canShutdown(bool deleteSelfIfShutdownDelayed=false);
public:
FactionThread(Faction *faction);
virtual void execute();
void signalPathfinder(int frameIndex);
bool isSignalPathfinderCompleted(int frameIndex);
};
class Faction {
private:
typedef vector<Resource> Resources;
@ -98,6 +120,8 @@ private:
// update of the faction
//std::map<int,std::map<Field, std::map<Vec2i,std::map<Vec2i, > > > localCacheForUnitCellMovement;
FactionThread *workerThread;
public:
Faction();
~Faction();
@ -186,7 +210,11 @@ public:
void deletePixels();
World * getWorld() { return world; }
int getFrameCount();
void signalWorkerThread(int frameIndex);
bool isWorkerThreadSignalCompleted(int frameIndex);
std::string toString() const;
private:

View File

@ -101,12 +101,14 @@ void UnitPathBasic::addToLastPathCache(const Vec2i &path) {
lastPathCacheQueue.push_back(path);
}
Vec2i UnitPathBasic::pop() {
Vec2i UnitPathBasic::pop(bool removeFrontPos) {
if(pathQueue.size() <= 0) {
throw runtime_error("pathQueue.size() = " + intToStr(pathQueue.size()));
}
Vec2i p= pathQueue.front();
pathQueue.erase(pathQueue.begin());
if(removeFrontPos == true) {
pathQueue.erase(pathQueue.begin());
}
return p;
}
std::string UnitPathBasic::toString() const {
@ -1105,6 +1107,60 @@ const CommandType *Unit::computeCommandType(const Vec2i &pos, const Unit *target
return commandType;
}
bool Unit::needToUpdate() {
assert(progress <= 1.f);
if(currSkill == NULL) {
char szBuf[4096]="";
sprintf(szBuf,"In [%s::%s Line: %d] ERROR: currSkill == NULL, Unit = [%s]\n",__FILE__,__FUNCTION__,__LINE__,this->toString().c_str());
throw runtime_error(szBuf);
}
//speed
int speed = currSkill->getTotalSpeed(&totalUpgrade);
//speed modifier
float diagonalFactor= 1.f;
float heightFactor= 1.f;
if(currSkill->getClass() == scMove) {
//if moving in diagonal move slower
Vec2i dest= pos-lastPos;
if(abs(dest.x) + abs(dest.y) == 2) {
diagonalFactor= 0.71f;
}
//if movig to an higher cell move slower else move faster
float heightDiff= map->getCell(pos)->getHeight() - map->getCell(targetPos)->getHeight();
heightFactor= clamp(1.f + heightDiff / 5.f, 0.2f, 5.f);
}
//update progresses
float newProgress = progress;
const Game *game = Renderer::getInstance().getGame();
newProgress += (speed * diagonalFactor * heightFactor) / (speedDivider * game->getWorld()->getUpdateFps(this->getFactionIndex()));
//checks
bool return_value = false;
//checks
if(newProgress >= 1.f) {
if(currSkill->getClass() != scDie) {
newProgress= 0.f;
return_value = true;
}
else {
newProgress= 1.f;
int newDeadCount = deadCount;
newDeadCount++;
if(newDeadCount >= maxDeadCount) {
return_value = false;
}
}
}
return return_value;
}
bool Unit::update() {
assert(progress<=1.f);

View File

@ -147,7 +147,7 @@ public:
virtual void incBlockCount();
virtual void add(const Vec2i &path);
void addToLastPathCache(const Vec2i &path);
Vec2i pop();
Vec2i pop(bool removeFrontPos=true);
virtual int getBlockCount() const { return blockCount; }
virtual int getQueueCount() const { return pathQueue.size(); }
@ -494,6 +494,7 @@ public:
void logSynchData(string file,int line,string source="");
std::string toString() const;
bool needToUpdate();
private:
float computeHeight(const Vec2i &pos) const;

View File

@ -88,8 +88,8 @@ StopCommandType::StopCommandType(){
clicks= cOne;
}
void StopCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{
unitUpdater->updateStop(unit);
void StopCommandType::update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const {
unitUpdater->updateStop(unit, frameIndex);
}
string StopCommandType::getDesc(const TotalUpgrade *totalUpgrade) const{
@ -131,8 +131,8 @@ MoveCommandType::MoveCommandType(){
clicks= cTwo;
}
void MoveCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{
unitUpdater->updateMove(unit);
void MoveCommandType::update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const {
unitUpdater->updateMove(unit, frameIndex);
}
void MoveCommandType::load(int id, const XmlNode *n, const string &dir,
@ -180,8 +180,8 @@ AttackCommandType::AttackCommandType(){
clicks= cTwo;
}
void AttackCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{
unitUpdater->updateAttack(unit);
void AttackCommandType::update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const {
unitUpdater->updateAttack(unit, frameIndex);
}
void AttackCommandType::load(int id, const XmlNode *n, const string &dir,
@ -272,8 +272,8 @@ AttackStoppedCommandType::AttackStoppedCommandType(){
clicks= cOne;
}
void AttackStoppedCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{
unitUpdater->updateAttackStopped(unit);
void AttackStoppedCommandType::update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const {
unitUpdater->updateAttackStopped(unit, frameIndex);
}
void AttackStoppedCommandType::load(int id, const XmlNode *n, const string &dir,
@ -359,8 +359,8 @@ BuildCommandType::~BuildCommandType() {
deleteValues(startSounds.getSounds().begin(), startSounds.getSounds().end());
}
void BuildCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{
unitUpdater->updateBuild(unit);
void BuildCommandType::update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const {
unitUpdater->updateBuild(unit, frameIndex);
}
void BuildCommandType::load(int id, const XmlNode *n, const string &dir,
@ -457,8 +457,8 @@ HarvestCommandType::HarvestCommandType(){
clicks= cTwo;
}
void HarvestCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{
unitUpdater->updateHarvest(unit);
void HarvestCommandType::update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const {
unitUpdater->updateHarvest(unit, frameIndex);
}
void HarvestCommandType::load(int id, const XmlNode *n, const string &dir,
@ -538,8 +538,8 @@ RepairCommandType::RepairCommandType(){
RepairCommandType::~RepairCommandType(){
}
void RepairCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{
unitUpdater->updateRepair(unit);
void RepairCommandType::update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const {
unitUpdater->updateRepair(unit, frameIndex);
}
void RepairCommandType::load(int id, const XmlNode *n, const string &dir,
@ -615,8 +615,8 @@ ProduceCommandType::ProduceCommandType(){
clicks= cOne;
}
void ProduceCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{
unitUpdater->updateProduce(unit);
void ProduceCommandType::update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const {
unitUpdater->updateProduce(unit, frameIndex);
}
void ProduceCommandType::load(int id, const XmlNode *n, const string &dir,
@ -680,8 +680,8 @@ UpgradeCommandType::UpgradeCommandType(){
clicks= cOne;
}
void UpgradeCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{
unitUpdater->updateUpgrade(unit);
void UpgradeCommandType::update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const {
unitUpdater->updateUpgrade(unit, frameIndex);
}
void UpgradeCommandType::load(int id, const XmlNode *n, const string &dir,
@ -737,8 +737,8 @@ MorphCommandType::MorphCommandType(){
clicks= cOne;
}
void MorphCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{
unitUpdater->updateMorph(unit);
void MorphCommandType::update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const {
unitUpdater->updateMorph(unit, frameIndex);
}
void MorphCommandType::load(int id, const XmlNode *n, const string &dir,

View File

@ -21,7 +21,7 @@
#include "sound_container.h"
#include "leak_dumper.h"
namespace Glest{ namespace Game{
namespace Glest { namespace Game {
using Shared::Util::MultiFactory;
@ -31,7 +31,7 @@ class UnitType;
class TechTree;
class FactionType;
enum CommandClass{
enum CommandClass {
ccStop,
ccMove,
ccAttack,
@ -47,7 +47,7 @@ enum CommandClass{
ccNull
};
enum Clicks{
enum Clicks {
cOne,
cTwo
};
@ -80,7 +80,7 @@ public:
clicks = cOne;
id = -1;
}
virtual void update(UnitUpdater *unitUpdater, Unit *unit) const= 0;
virtual void update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const= 0;
virtual void load(int id, const XmlNode *n, const string &dir,
const TechTree *tt, const FactionType *ft, const UnitType &ut,
std::map<string,int> &loadedFileList);
@ -109,13 +109,13 @@ public:
// class StopCommandType
// ===============================
class StopCommandType: public CommandType{
class StopCommandType: public CommandType {
private:
const StopSkillType* stopSkillType;
public:
StopCommandType();
virtual void update(UnitUpdater *unitUpdater, Unit *unit) const;
virtual void update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const;
virtual void load(int id, const XmlNode *n, const string &dir, const TechTree *tt,
const FactionType *ft, const UnitType &ut, std::map<string,int> &loadedFileList);
virtual string getDesc(const TotalUpgrade *totalUpgrade) const;
@ -131,13 +131,13 @@ public:
// class MoveCommandType
// ===============================
class MoveCommandType: public CommandType{
class MoveCommandType: public CommandType {
private:
const MoveSkillType *moveSkillType;
public:
MoveCommandType();
virtual void update(UnitUpdater *unitUpdater, Unit *unit) const;
virtual void update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const;
virtual void load(int id, const XmlNode *n, const string &dir,
const TechTree *tt, const FactionType *ft, const UnitType &ut,
std::map<string,int> &loadedFileList);
@ -153,14 +153,14 @@ public:
// class AttackCommandType
// ===============================
class AttackCommandType: public CommandType{
class AttackCommandType: public CommandType {
private:
const MoveSkillType* moveSkillType;
const AttackSkillType* attackSkillType;
public:
AttackCommandType();
virtual void update(UnitUpdater *unitUpdater, Unit *unit) const;
virtual void update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const;
virtual void load(int id, const XmlNode *n, const string &dir,
const TechTree *tt, const FactionType *ft, const UnitType &ut,
std::map<string,int> &loadedFileList);
@ -177,14 +177,14 @@ public:
// class AttackStoppedCommandType
// =======================================
class AttackStoppedCommandType: public CommandType{
class AttackStoppedCommandType: public CommandType {
private:
const StopSkillType* stopSkillType;
const AttackSkillType* attackSkillType;
public:
AttackStoppedCommandType();
virtual void update(UnitUpdater *unitUpdater, Unit *unit) const;
virtual void update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const;
virtual void load(int id, const XmlNode *n, const string &dir,
const TechTree *tt, const FactionType *ft, const UnitType &ut,
std::map<string,int> &loadedFileList);
@ -201,7 +201,7 @@ public:
// class BuildCommandType
// ===============================
class BuildCommandType: public CommandType{
class BuildCommandType: public CommandType {
private:
const MoveSkillType* moveSkillType;
const BuildSkillType* buildSkillType;
@ -212,7 +212,7 @@ private:
public:
BuildCommandType();
~BuildCommandType();
virtual void update(UnitUpdater *unitUpdater, Unit *unit) const;
virtual void update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const;
virtual void load(int id, const XmlNode *n, const string &dir,
const TechTree *tt, const FactionType *ft, const UnitType &ut,
std::map<string,int> &loadedFileList);
@ -233,7 +233,7 @@ public:
// class HarvestCommandType
// ===============================
class HarvestCommandType: public CommandType{
class HarvestCommandType: public CommandType {
private:
const MoveSkillType *moveSkillType;
const MoveSkillType *moveLoadedSkillType;
@ -245,7 +245,7 @@ private:
public:
HarvestCommandType();
virtual void update(UnitUpdater *unitUpdater, Unit *unit) const;
virtual void update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const;
virtual void load(int id, const XmlNode *n, const string &dir,
const TechTree *tt, const FactionType *ft, const UnitType &ut,
std::map<string,int> &loadedFileList);
@ -270,7 +270,7 @@ public:
// class RepairCommandType
// ===============================
class RepairCommandType: public CommandType{
class RepairCommandType: public CommandType {
private:
const MoveSkillType* moveSkillType;
const RepairSkillType* repairSkillType;
@ -279,7 +279,7 @@ private:
public:
RepairCommandType();
~RepairCommandType();
virtual void update(UnitUpdater *unitUpdater, Unit *unit) const;
virtual void update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const;
virtual void load(int id, const XmlNode *n, const string &dir,
const TechTree *tt, const FactionType *ft, const UnitType &ut,
std::map<string,int> &loadedFileList);
@ -301,14 +301,14 @@ public:
// class ProduceCommandType
// ===============================
class ProduceCommandType: public CommandType{
class ProduceCommandType: public CommandType {
private:
const ProduceSkillType* produceSkillType;
const UnitType *producedUnit;
public:
ProduceCommandType();
virtual void update(UnitUpdater *unitUpdater, Unit *unit) const;
virtual void update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const;
virtual void load(int id, const XmlNode *n, const string &dir,
const TechTree *tt, const FactionType *ft, const UnitType &ut,
std::map<string,int> &loadedFileList);
@ -328,14 +328,14 @@ public:
// class UpgradeCommandType
// ===============================
class UpgradeCommandType: public CommandType{
class UpgradeCommandType: public CommandType {
private:
const UpgradeSkillType* upgradeSkillType;
const UpgradeType* producedUpgrade;
public:
UpgradeCommandType();
virtual void update(UnitUpdater *unitUpdater, Unit *unit) const;
virtual void update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const;
virtual void load(int id, const XmlNode *n, const string &dir,
const TechTree *tt, const FactionType *ft, const UnitType &ut,
std::map<string,int> &loadedFileList);
@ -354,7 +354,7 @@ public:
// class MorphCommandType
// ===============================
class MorphCommandType: public CommandType{
class MorphCommandType: public CommandType {
private:
const MorphSkillType* morphSkillType;
const UnitType* morphUnit;
@ -362,7 +362,7 @@ private:
public:
MorphCommandType();
virtual void update(UnitUpdater *unitUpdater, Unit *unit) const;
virtual void update(UnitUpdater *unitUpdater, Unit *unit, int frameIndex) const;
virtual void load(int id, const XmlNode *n, const string &dir,
const TechTree *tt, const FactionType *ft, const UnitType &ut,
std::map<string,int> &loadedFileList);

File diff suppressed because it is too large Load Diff

View File

@ -100,17 +100,17 @@ public:
void updateUnit(Unit *unit);
//update commands
void updateUnitCommand(Unit *unit);
void updateStop(Unit *unit);
void updateMove(Unit *unit);
void updateAttack(Unit *unit);
void updateAttackStopped(Unit *unit);
void updateBuild(Unit *unit);
void updateHarvest(Unit *unit);
void updateRepair(Unit *unit);
void updateProduce(Unit *unit);
void updateUpgrade(Unit *unit);
void updateMorph(Unit *unit);
void updateUnitCommand(Unit *unit, int frameIndex);
void updateStop(Unit *unit, int frameIndex);
void updateMove(Unit *unit, int frameIndex);
void updateAttack(Unit *unit, int frameIndex);
void updateAttackStopped(Unit *unit, int frameIndex);
void updateBuild(Unit *unit, int frameIndex);
void updateHarvest(Unit *unit, int frameIndex);
void updateRepair(Unit *unit, int frameIndex);
void updateProduce(Unit *unit, int frameIndex);
void updateUpgrade(Unit *unit, int frameIndex);
void updateMorph(Unit *unit, int frameIndex);
private:
//attack
@ -133,6 +133,7 @@ private:
const CommandType *commandType,
int originalValue,int newValue);
void clearUnitPrecache(Unit *unit);
};
// =====================================================

View File

@ -271,8 +271,44 @@ Checksum World::loadScenario(const string &path, Checksum *checksum) {
void World::updateAllFactionUnits() {
scriptManager->onTimerTriggerEvent();
//units
// Signal the faction threads to do any pre-processing
int factionCount = getFactionCount();
for(int i = 0; i < factionCount; ++i) {
Faction *faction = getFaction(i);
if(faction == NULL) {
throw runtime_error("faction == NULL");
}
faction->signalWorkerThread(frameCount);
}
bool workThreadsFinished = false;
Chrono chrono;
chrono.start();
for(;chrono.getMillis() < 10000;) {
workThreadsFinished = true;
for(int i = 0; i < factionCount; ++i) {
Faction *faction = getFaction(i);
if(faction == NULL) {
throw runtime_error("faction == NULL");
}
if(faction->isWorkerThreadSignalCompleted(frameCount) == false) {
workThreadsFinished = false;
break;
}
}
if(workThreadsFinished == false) {
sleep(0);
}
else {
break;
}
}
if(SystemFlags::VERBOSE_MODE_ENABLED && chrono.getMillis() >= 10) printf("In [%s::%s Line: %d] *** Faction thread preprocessing took [%lld] msecs for %d factions for frameCount = %d.\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis(),factionCount,frameCount);
//units
for(int i = 0; i < factionCount; ++i) {
Faction *faction = getFaction(i);
if(faction == NULL) {
@ -290,6 +326,8 @@ void World::updateAllFactionUnits() {
unitUpdater.updateUnit(unit);
}
}
if(SystemFlags::VERBOSE_MODE_ENABLED && chrono.getMillis() >= 20) printf("In [%s::%s Line: %d] *** Faction MAIN thread processing took [%lld] msecs for %d factions for frameCount = %d.\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis(),factionCount,frameCount);
}
void World::underTakeDeadFactionUnits() {

View File

@ -231,6 +231,8 @@ public:
void exploreCells(const Vec2i &newPos, int sightRange, int teamIndex);
bool showWorldForPlayer(int factionIndex) const;
UnitUpdater * getUnitUpdater() { return &unitUpdater; }
private:
void initCells(bool fogOfWar);