- added logic to delay AI player from path finding more than 10 units per frame (we make him think he is blocked and he will retry another frame)

This commit is contained in:
Mark Vejvoda 2012-03-31 19:50:45 +00:00
parent 45ff24dbd7
commit 2f885406e0
6 changed files with 354 additions and 183 deletions

View File

@ -107,9 +107,18 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu
if(map == NULL) {
throw runtime_error("map == NULL");
}
if(frameIndex >= 0) {
clearUnitPrecache(unit);
}
else {
if(unit->getFaction()->canUnitsPathfind() == true) {
unit->getFaction()->addUnitToPathfindingList(unit->getId());
}
else {
return tsBlocked;
}
}
// if(frameIndex != factions[unit->getFactionIndex()].lastFromToNodeListFrame) {
// if(factions[unit->getFactionIndex()].mapFromToNodeList.size() > 0) {
@ -650,6 +659,138 @@ Vec2i PathFinder::jump(Vec2i dest, direction dir, Vec2i start,std::vector<Vec2i>
}
void PathFinder::astarJPS(std::map<Vec2i,Vec2i> cameFrom, Node *& node,
const Vec2i & finalPos, std::map<Vec2i,bool> closedNodes,
std::map<std::pair<Vec2i,Vec2i> ,bool> canAddNode, Unit *& unit,
bool & nodeLimitReached, int & maxNodeCount) {
Vec2i cameFromPos(-1, -1);
if(cameFrom.find(node->pos) != cameFrom.end()) {
cameFromPos = cameFrom[node->pos];
}
direction from = directionWeCameFrom(node->pos, cameFromPos);
directionset dirs = forcedNeighbours(node->pos, from) | naturalNeighbours(from);
bool canAddEntirePath = false;
bool foundQuickRoute = false;
for (int dir = nextDirectionInSet(&dirs); dir != NO_DIRECTION; dir = nextDirectionInSet(&dirs)) {
//for (int dir = 0; dir < 8; dir++) {
std::vector<Vec2i> path;
Vec2i newNode = jump(finalPos, dir, node->pos,path,(int)node->pos.dist(finalPos));
//Vec2i newNode = adjustInDirection(node->pos, dir);
//printf("examine node from [%u][%u] - current node [%s] next possible node [%s]\n",from,dirs,node->pos.getString().c_str(),newNode.getString().c_str());
//coord_t newCoord = getCoord (bounds, newNode);
// this'll also bail out if jump() returned -1
if (!contained(newNode))
continue;
if(closedNodes.find(newNode) != closedNodes.end())
continue;
//if(factions[unit->getFactionIndex()].closedNodesList.find(node->heuristic) == factions[unit->getFactionIndex()].closedNodesList.end()) {
//addToOpenSet (&astar, newNode, node);
//printf("JPS #2 node->pos [%s] newNode [%s] path.size() [%d] pos [%s]\n",node->pos.getString().c_str(),newNode.getString().c_str(),(int)path.size(),path[0].getString().c_str());
Vec2i newPath = path[0];
//bool canUnitMoveToCell = map->aproxCanMove(unit, node->pos, newPath);
//bool posOpen = (openPos(newPath, factions[unit->getFactionIndex()]) == false);
//bool isFreeCell = map->isFreeCell(newPath,unit->getType()->getField());
if(canAddNode.find(make_pair(node->pos,newPath)) == canAddNode.end()) {
Node *newNode=NULL;
if(addToOpenSet(unit, node, finalPos, newPath, nodeLimitReached, maxNodeCount,&newNode,false) == true) {
//cameFrom = node->pos;
cameFrom[newPath]=node->pos;
foundQuickRoute = true;
if(path.size() > 1 && path[path.size()-1] == finalPos) {
canAddEntirePath = true;
for(unsigned int x = 1; x < path.size(); ++x) {
Vec2i futureNode = path[x];
bool canUnitMoveToCell = map->aproxCanMoveSoon(unit, newNode->pos, futureNode);
if(canUnitMoveToCell != true || openPos(futureNode, factions[unit->getFactionIndex()]) == true) {
canAddEntirePath = false;
canAddNode[make_pair(node->pos,futureNode)]=false;
//printf("COULD NOT ADD ENTIRE PATH! canUnitMoveToCell = %d\n",canUnitMoveToCell);
break;
}
}
if(canAddEntirePath == true) {
//printf("add node - ENTIRE PATH!\n");
for(unsigned int x = 1; x < path.size(); ++x) {
Vec2i futureNode = path[x];
Node *newNode2=NULL;
addToOpenSet(unit, newNode, finalPos, futureNode, nodeLimitReached, maxNodeCount,&newNode2, true);
newNode=newNode2;
}
//Node *result = factions[unit->getFactionIndex()].openNodesList.begin()->second[0];
//if(result->pos == finalPos || result->exploredCell == false) {
// printf("Will break out of pathfinding now!\n");
//}
}
}
//printf("add node - current node [%s] next possible node [%s] canUnitMoveToCell [%d] posOpen [%d] isFreeCell [%d]\n",node->pos.getString().c_str(),newPath.getString().c_str(),canUnitMoveToCell,posOpen,isFreeCell);
}
else {
//printf("COULD NOT add node - current node [%s] next possible node [%s] canUnitMoveToCell [%d] posOpen [%d] isFreeCell [%d]\n",node->pos.getString().c_str(),newPath.getString().c_str(),canUnitMoveToCell,posOpen,isFreeCell);
canAddNode[make_pair(node->pos,newPath)]=false;
}
}
//if(canAddEntirePath == true) {
// break;
//}
}
if(foundQuickRoute == false) {
for (int dir = 0; dir < 8; dir++) {
Vec2i newNode = adjustInDirection(node->pos, dir);
//printf("examine node from [%u][%u] - current node [%s] next possible node [%s]\n",from,dirs,node->pos.getString().c_str(),newNode.getString().c_str());
//coord_t newCoord = getCoord (bounds, newNode);
// this'll also bail out if jump() returned -1
if (!contained(newNode))
continue;
if(closedNodes.find(newNode) != closedNodes.end())
continue;
//if(factions[unit->getFactionIndex()].closedNodesList.find(node->heuristic) == factions[unit->getFactionIndex()].closedNodesList.end()) {
//addToOpenSet (&astar, newNode, node);
//printf("JPS #3 node->pos [%s] newNode [%s]\n",node->pos.getString().c_str(),newNode.getString().c_str());
Vec2i newPath = newNode;
//bool canUnitMoveToCell = map->aproxCanMove(unit, node->pos, newPath);
//bool posOpen = (openPos(newPath, factions[unit->getFactionIndex()]) == false);
//bool isFreeCell = map->isFreeCell(newPath,unit->getType()->getField());
if(canAddNode.find(make_pair(node->pos,newPath)) == canAddNode.end()) {
Node *newNode=NULL;
if(addToOpenSet(unit, node, finalPos, newPath, nodeLimitReached, maxNodeCount,&newNode, false) == true) {
//cameFrom = node->pos;
cameFrom[newPath]=node->pos;
foundQuickRoute = true;
//printf("#2 add node - current node [%s] next possible node [%s] canUnitMoveToCell [%d] posOpen [%d] isFreeCell [%d]\n",node->pos.getString().c_str(),newPath.getString().c_str(),canUnitMoveToCell,posOpen,isFreeCell);
}
else {
//printf("#2 COULD NOT add node - current node [%s] next possible node [%s] canUnitMoveToCell [%d] posOpen [%d] isFreeCell [%d]\n",node->pos.getString().c_str(),newPath.getString().c_str(),canUnitMoveToCell,posOpen,isFreeCell);
canAddNode[make_pair(node->pos,newPath)]=false;
}
}
}
}
}
//route a unit using A* algorithm
TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout,
int frameIndex, int maxNodeCount) {
@ -668,29 +809,31 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
maxNodeCount = factions[unit->getFactionIndex()].useMaxNodeCount;
}
UnitPathInterface *path= unit->getPath();
int unitFactionIndex = unit->getFactionIndex();
factions[unit->getFactionIndex()].nodePoolCount= 0;
factions[unit->getFactionIndex()].openNodesList.clear();
factions[unit->getFactionIndex()].openPosList.clear();
factions[unit->getFactionIndex()].closedNodesList.clear();
factions[unitFactionIndex].nodePoolCount= 0;
factions[unitFactionIndex].openNodesList.clear();
factions[unitFactionIndex].openPosList.clear();
factions[unitFactionIndex].closedNodesList.clear();
TravelState ts = tsImpossible;
// check the pre-cache to see if we can re-use a cached path
if(frameIndex < 0) {
if(factions[unit->getFactionIndex()].precachedTravelState.find(unit->getId()) != factions[unit->getFactionIndex()].precachedTravelState.end()) {
if(factions[unit->getFactionIndex()].precachedTravelState[unit->getId()] == tsMoving) {
if(factions[unitFactionIndex].precachedTravelState.find(unit->getId()) != factions[unitFactionIndex].precachedTravelState.end()) {
if(factions[unitFactionIndex].precachedTravelState[unit->getId()] == tsMoving) {
bool canMoveToCells = true;
Vec2i lastPos = unit->getPos();
for(int i=0; i < factions[unit->getFactionIndex()].precachedPath[unit->getId()].size(); i++) {
Vec2i nodePos = factions[unit->getFactionIndex()].precachedPath[unit->getId()][i];
for(int i=0; i < factions[unitFactionIndex].precachedPath[unit->getId()].size(); i++) {
Vec2i nodePos = factions[unitFactionIndex].precachedPath[unit->getId()][i];
if(map->isInside(nodePos) == false || map->isInsideSurface(map->toSurfCoords(nodePos)) == false) {
throw runtime_error("Pathfinder invalid node path position = " + nodePos.getString() + " i = " + intToStr(i));
}
if(i < pathFindRefresh ||
(factions[unit->getFactionIndex()].precachedPath[unit->getId()].size() >= pathFindExtendRefreshForNodeCount &&
i < getPathFindExtendRefreshNodeCount(unit->getFactionIndex()))) {
(factions[unitFactionIndex].precachedPath[unit->getId()].size() >= pathFindExtendRefreshForNodeCount &&
i < getPathFindExtendRefreshNodeCount(unitFactionIndex))) {
//!!! Test MV
if(map->aproxCanMoveSoon(unit, lastPos, nodePos) == false) {
canMoveToCells = false;
@ -707,15 +850,15 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
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];
for(int i=0; i < factions[unitFactionIndex].precachedPath[unit->getId()].size(); i++) {
Vec2i nodePos = factions[unitFactionIndex].precachedPath[unit->getId()][i];
if(map->isInside(nodePos) == false || map->isInsideSurface(map->toSurfCoords(nodePos)) == false) {
throw runtime_error("Pathfinder invalid node path position = " + nodePos.getString() + " i = " + intToStr(i));
}
if(i < pathFindRefresh ||
(factions[unit->getFactionIndex()].precachedPath[unit->getId()].size() >= pathFindExtendRefreshForNodeCount &&
i < getPathFindExtendRefreshNodeCount(unit->getFactionIndex()))) {
(factions[unitFactionIndex].precachedPath[unit->getId()].size() >= pathFindExtendRefreshForNodeCount &&
i < getPathFindExtendRefreshNodeCount(unitFactionIndex))) {
path->add(nodePos);
}
//else if(tryLastPathCache == false) {
@ -728,16 +871,16 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
}
}
unit->setUsePathfinderExtendedMaxNodes(false);
return factions[unit->getFactionIndex()].precachedTravelState[unit->getId()];
return factions[unitFactionIndex].precachedTravelState[unit->getId()];
}
else {
clearUnitPrecache(unit);
}
}
else if(factions[unit->getFactionIndex()].precachedTravelState[unit->getId()] == tsBlocked) {
else if(factions[unitFactionIndex].precachedTravelState[unit->getId()] == tsBlocked) {
path->incBlockCount();
unit->setUsePathfinderExtendedMaxNodes(false);
return factions[unit->getFactionIndex()].precachedTravelState[unit->getId()];
return factions[unitFactionIndex].precachedTravelState[unit->getId()];
}
}
}
@ -749,7 +892,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
const Vec2i finalPos= computeNearestFreePos(unit, targetPos);
float dist= unitPos.dist(finalPos);
factions[unit->getFactionIndex()].useMaxNodeCount = PathFinder::pathFindNodesMax;
factions[unitFactionIndex].useMaxNodeCount = PathFinder::pathFindNodesMax;
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
@ -789,7 +932,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
}
if(frameIndex >= 0) {
factions[unit->getFactionIndex()].precachedPath[unit->getId()].push_back(cachedPath[k]);
factions[unitFactionIndex].precachedPath[unit->getId()].push_back(cachedPath[k]);
}
else {
if(pathCount < pathFindRefresh) {
@ -805,7 +948,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[4096]="";
sprintf(szBuf,"[Setting new path for unit] openNodesList.size() [%lu] openPosList.size() [%lu] finalPos [%s] targetPos [%s] inBailout [%d] ts [%d]",
factions[unit->getFactionIndex()].openNodesList.size(),factions[unit->getFactionIndex()].openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts);
factions[unitFactionIndex].openNodesList.size(),factions[unitFactionIndex].openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts);
unit->logSynchData(__FILE__,__LINE__,szBuf);
}
@ -844,7 +987,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
}
if(frameIndex >= 0) {
factions[unit->getFactionIndex()].precachedPath[unit->getId()].push_back(cachedPath[k]);
factions[unitFactionIndex].precachedPath[unit->getId()].push_back(cachedPath[k]);
}
else {
if(pathCount < pathFindRefresh) {
@ -860,7 +1003,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[4096]="";
sprintf(szBuf,"[Setting new path for unit] openNodesList.size() [%lu] openPosList.size() [%lu] finalPos [%s] targetPos [%s] inBailout [%d] ts [%d]",
factions[unit->getFactionIndex()].openNodesList.size(),factions[unit->getFactionIndex()].openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts);
factions[unitFactionIndex].openNodesList.size(),factions[unitFactionIndex].openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts);
unit->logSynchData(__FILE__,__LINE__,szBuf);
}
@ -896,7 +1039,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
//path find algorithm
//a) push starting pos into openNodes
Node *firstNode= newNode(factions[unit->getFactionIndex()],maxNodeCount);
Node *firstNode= newNode(factions[unitFactionIndex],maxNodeCount);
assert(firstNode != NULL);
if(firstNode == NULL) {
throw runtime_error("firstNode == NULL");
@ -907,11 +1050,11 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
firstNode->pos= unitPos;
firstNode->heuristic= heuristic(unitPos, finalPos);
firstNode->exploredCell= true;
if(factions[unit->getFactionIndex()].openNodesList.find(firstNode->heuristic) == factions[unit->getFactionIndex()].openNodesList.end()) {
factions[unit->getFactionIndex()].openNodesList[firstNode->heuristic].clear();
if(factions[unitFactionIndex].openNodesList.find(firstNode->heuristic) == factions[unitFactionIndex].openNodesList.end()) {
factions[unitFactionIndex].openNodesList[firstNode->heuristic].clear();
}
factions[unit->getFactionIndex()].openNodesList[firstNode->heuristic].push_back(firstNode);
factions[unit->getFactionIndex()].openPosList[firstNode->pos] = true;
factions[unitFactionIndex].openNodesList[firstNode->heuristic].push_back(firstNode);
factions[unitFactionIndex].openPosList[firstNode->pos] = true;
//b) loop
bool pathFound = true;
@ -987,6 +1130,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
//cameFrom[unitPos] = unit->getPos();
// Do the a-star base pathfind work if required
int whileLoopCount = 0;
if(nodeLimitReached == false) {
//printf("\n\n\n====== START AStar-JPS Pathfinder start [%s] end [%s]\n",unitPos.getString().c_str(),finalPos.getString().c_str());
@ -997,7 +1141,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
whileLoopCount++;
//b1) is open nodes is empty => failed to find the path
if(factions[unit->getFactionIndex()].openNodesList.empty() == true) {
if(factions[unitFactionIndex].openNodesList.empty() == true) {
//printf("$$$$ Path for Unit [%d - %s] inBailout = %d BLOCKED\n",unit->getId(),unit->getFullName().c_str(),inBailout);
//printf("Path blocked\n");
pathFound= false;
@ -1006,7 +1150,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
//b2) get the minimum heuristic node
//Nodes::iterator it = minHeuristic();
node = minHeuristicFastLookup(factions[unit->getFactionIndex()]);
node = minHeuristicFastLookup(factions[unitFactionIndex]);
//printf("current node [%s]\n",node->pos.getString().c_str());
//b3) if minHeuristic is the finalNode, or the path is no more explored => path was found
@ -1016,156 +1160,30 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
break;
}
if(tryJPSPathfinder) {
if(tryJPSPathfinder == true) {
closedNodes[node->pos]=true;
}
//printf("$$$$ Path for Unit [%d - %s] node [%s] whileLoopCount = %d nodePoolCount = %d inBailout = %d\n",unit->getId(),unit->getFullName().c_str(), node->pos.getString().c_str(), whileLoopCount,factions[unit->getFactionIndex()].nodePoolCount,inBailout);
//printf("$$$$ Path for Unit [%d - %s] node [%s] whileLoopCount = %d nodePoolCount = %d inBailout = %d\n",unit->getId(),unit->getFullName().c_str(), node->pos.getString().c_str(), whileLoopCount,factions[unitFactionIndex].nodePoolCount,inBailout);
//b4) move this node from closedNodes to openNodes
//add all succesors that are not in closedNodes or openNodes to openNodes
if(factions[unit->getFactionIndex()].closedNodesList.find(node->heuristic) == factions[unit->getFactionIndex()].closedNodesList.end()) {
factions[unit->getFactionIndex()].closedNodesList[node->heuristic].clear();
if(factions[unitFactionIndex].closedNodesList.find(node->heuristic) ==
factions[unitFactionIndex].closedNodesList.end()) {
factions[unitFactionIndex].closedNodesList[node->heuristic].clear();
}
factions[unit->getFactionIndex()].closedNodesList[node->heuristic].push_back(node);
factions[unit->getFactionIndex()].openPosList[node->pos] = true;
factions[unitFactionIndex].closedNodesList[node->heuristic].push_back(node);
factions[unitFactionIndex].openPosList[node->pos] = true;
if(tryJPSPathfinder) {
Vec2i cameFromPos(-1,-1);
if(cameFrom.find(node->pos) != cameFrom.end()) {
cameFromPos = cameFrom[node->pos];
}
direction from = directionWeCameFrom(node->pos,cameFromPos);
directionset dirs = forcedNeighbours(node->pos, from) | naturalNeighbours(from);
//printf("JPS #1 node->pos [%s] from = %u dirs = %u\n",node->pos.getString().c_str(),from,dirs);
bool canAddEntirePath = false;
bool foundQuickRoute = false;
for (int dir = nextDirectionInSet(&dirs); dir != NO_DIRECTION; dir = nextDirectionInSet(&dirs)) {
//for (int dir = 0; dir < 8; dir++) {
std::vector<Vec2i> path;
Vec2i newNode = jump(finalPos, dir, node->pos,path,(int)node->pos.dist(finalPos));
//Vec2i newNode = adjustInDirection(node->pos, dir);
//printf("examine node from [%u][%u] - current node [%s] next possible node [%s]\n",from,dirs,node->pos.getString().c_str(),newNode.getString().c_str());
//coord_t newCoord = getCoord (bounds, newNode);
// this'll also bail out if jump() returned -1
if (!contained(newNode))
continue;
if(closedNodes.find(newNode) != closedNodes.end())
continue;
//if(factions[unit->getFactionIndex()].closedNodesList.find(node->heuristic) == factions[unit->getFactionIndex()].closedNodesList.end()) {
//addToOpenSet (&astar, newNode, node);
//printf("JPS #2 node->pos [%s] newNode [%s] path.size() [%d] pos [%s]\n",node->pos.getString().c_str(),newNode.getString().c_str(),(int)path.size(),path[0].getString().c_str());
Vec2i newPath = path[0];
//bool canUnitMoveToCell = map->aproxCanMove(unit, node->pos, newPath);
//bool posOpen = (openPos(newPath, factions[unit->getFactionIndex()]) == false);
//bool isFreeCell = map->isFreeCell(newPath,unit->getType()->getField());
if(canAddNode.find(make_pair(node->pos,newPath)) == canAddNode.end()) {
Node *newNode=NULL;
if(addToOpenSet(unit, node, finalPos, newPath, nodeLimitReached, maxNodeCount,&newNode,false) == true) {
//cameFrom = node->pos;
cameFrom[newPath]=node->pos;
foundQuickRoute = true;
if(path.size() > 1 && path[path.size()-1] == finalPos) {
canAddEntirePath = true;
for(unsigned int x = 1; x < path.size(); ++x) {
Vec2i futureNode = path[x];
bool canUnitMoveToCell = map->aproxCanMoveSoon(unit, newNode->pos, futureNode);
if(canUnitMoveToCell != true || openPos(futureNode, factions[unit->getFactionIndex()]) == true) {
canAddEntirePath = false;
canAddNode[make_pair(node->pos,futureNode)]=false;
//printf("COULD NOT ADD ENTIRE PATH! canUnitMoveToCell = %d\n",canUnitMoveToCell);
break;
}
}
if(canAddEntirePath == true) {
//printf("add node - ENTIRE PATH!\n");
for(unsigned int x = 1; x < path.size(); ++x) {
Vec2i futureNode = path[x];
Node *newNode2=NULL;
addToOpenSet(unit, newNode, finalPos, futureNode, nodeLimitReached, maxNodeCount,&newNode2, true);
newNode=newNode2;
}
//Node *result = factions[unit->getFactionIndex()].openNodesList.begin()->second[0];
//if(result->pos == finalPos || result->exploredCell == false) {
// printf("Will break out of pathfinding now!\n");
//}
}
}
//printf("add node - current node [%s] next possible node [%s] canUnitMoveToCell [%d] posOpen [%d] isFreeCell [%d]\n",node->pos.getString().c_str(),newPath.getString().c_str(),canUnitMoveToCell,posOpen,isFreeCell);
}
else {
//printf("COULD NOT add node - current node [%s] next possible node [%s] canUnitMoveToCell [%d] posOpen [%d] isFreeCell [%d]\n",node->pos.getString().c_str(),newPath.getString().c_str(),canUnitMoveToCell,posOpen,isFreeCell);
canAddNode[make_pair(node->pos,newPath)]=false;
}
}
//if(canAddEntirePath == true) {
// break;
//}
}
if(foundQuickRoute == false) {
for (int dir = 0; dir < 8; dir++) {
Vec2i newNode = adjustInDirection(node->pos, dir);
//printf("examine node from [%u][%u] - current node [%s] next possible node [%s]\n",from,dirs,node->pos.getString().c_str(),newNode.getString().c_str());
//coord_t newCoord = getCoord (bounds, newNode);
// this'll also bail out if jump() returned -1
if (!contained(newNode))
continue;
if(closedNodes.find(newNode) != closedNodes.end())
continue;
//if(factions[unit->getFactionIndex()].closedNodesList.find(node->heuristic) == factions[unit->getFactionIndex()].closedNodesList.end()) {
//addToOpenSet (&astar, newNode, node);
//printf("JPS #3 node->pos [%s] newNode [%s]\n",node->pos.getString().c_str(),newNode.getString().c_str());
Vec2i newPath = newNode;
//bool canUnitMoveToCell = map->aproxCanMove(unit, node->pos, newPath);
//bool posOpen = (openPos(newPath, factions[unit->getFactionIndex()]) == false);
//bool isFreeCell = map->isFreeCell(newPath,unit->getType()->getField());
if(canAddNode.find(make_pair(node->pos,newPath)) == canAddNode.end()) {
Node *newNode=NULL;
if(addToOpenSet(unit, node, finalPos, newPath, nodeLimitReached, maxNodeCount,&newNode, false) == true) {
//cameFrom = node->pos;
cameFrom[newPath]=node->pos;
foundQuickRoute = true;
//printf("#2 add node - current node [%s] next possible node [%s] canUnitMoveToCell [%d] posOpen [%d] isFreeCell [%d]\n",node->pos.getString().c_str(),newPath.getString().c_str(),canUnitMoveToCell,posOpen,isFreeCell);
}
else {
//printf("#2 COULD NOT add node - current node [%s] next possible node [%s] canUnitMoveToCell [%d] posOpen [%d] isFreeCell [%d]\n",node->pos.getString().c_str(),newPath.getString().c_str(),canUnitMoveToCell,posOpen,isFreeCell);
canAddNode[make_pair(node->pos,newPath)]=false;
}
}
}
}
if(tryJPSPathfinder == true) {
astarJPS(cameFrom, node,finalPos, closedNodes,canAddNode, unit,
nodeLimitReached, maxNodeCount);
}
else {
int failureCount = 0;
int cellCount = 0;
int failureCount = 0;
int cellCount = 0;
int tryDirection = factions[unit->getFactionIndex()].random.randRange(0,3);
int tryDirection = factions[unitFactionIndex].random.randRange(0,3);
if(tryDirection == 3) {
for(int i = 1; i >= -1 && nodeLimitReached == false; --i) {
for(int j = -1; j <= 1 && nodeLimitReached == false; ++j) {
@ -1229,19 +1247,19 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
}
}
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(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[unitFactionIndex].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,factions[unit->getFactionIndex()].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[unitFactionIndex].nodePoolCount);
}
Node *lastNode= node;
//if consumed all nodes find best node (to avoid strange behaviour)
if(nodeLimitReached == true) {
if(factions[unit->getFactionIndex()].closedNodesList.size() > 0) {
float bestHeuristic = factions[unit->getFactionIndex()].closedNodesList.begin()->first;
if(factions[unitFactionIndex].closedNodesList.size() > 0) {
float bestHeuristic = factions[unitFactionIndex].closedNodesList.begin()->first;
if(bestHeuristic < lastNode->heuristic) {
lastNode= factions[unit->getFactionIndex()].closedNodesList.begin()->second[0];
lastNode= factions[unitFactionIndex].closedNodesList.begin()->second[0];
}
}
}
@ -1278,7 +1296,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[4096]="";
sprintf(szBuf,"[path for unit BLOCKED] openNodesList.size() [%lu] openPosList.size() [%lu] finalPos [%s] targetPos [%s] inBailout [%d] ts [%d]",
factions[unit->getFactionIndex()].openNodesList.size(),factions[unit->getFactionIndex()].openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts);
factions[unitFactionIndex].openNodesList.size(),factions[unitFactionIndex].openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts);
unit->logSynchData(__FILE__,__LINE__,szBuf);
}
@ -1327,12 +1345,12 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
//printf("nodePos [%s]\n",nodePos.getString().c_str());
if(frameIndex >= 0) {
factions[unit->getFactionIndex()].precachedPath[unit->getId()].push_back(nodePos);
factions[unitFactionIndex].precachedPath[unit->getId()].push_back(nodePos);
}
else {
if(i < pathFindRefresh ||
(whileLoopCount >= pathFindExtendRefreshForNodeCount &&
i < getPathFindExtendRefreshNodeCount(unit->getFactionIndex()))) {
i < getPathFindExtendRefreshNodeCount(unitFactionIndex))) {
path->add(nodePos);
}
//else if(tryLastPathCache == false) {
@ -1351,7 +1369,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout
if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) {
char szBuf[4096]="";
sprintf(szBuf,"[Setting new path for unit] openNodesList.size() [%lu] openPosList.size() [%lu] finalPos [%s] targetPos [%s] inBailout [%d] ts [%d]",
factions[unit->getFactionIndex()].openNodesList.size(),factions[unit->getFactionIndex()].openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts);
factions[unitFactionIndex].openNodesList.size(),factions[unitFactionIndex].openPosList.size(),finalPos.getString().c_str(),targetPos.getString().c_str(),inBailout,ts);
unit->logSynchData(__FILE__,__LINE__,szBuf);
string pathToTake = "";
@ -1381,14 +1399,14 @@ 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());
}
factions[unit->getFactionIndex()].openNodesList.clear();
factions[unit->getFactionIndex()].openPosList.clear();
factions[unit->getFactionIndex()].closedNodesList.clear();
factions[unitFactionIndex].openNodesList.clear();
factions[unitFactionIndex].openPosList.clear();
factions[unitFactionIndex].closedNodesList.clear();
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [END OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
if(frameIndex >= 0) {
factions[unit->getFactionIndex()].precachedTravelState[unit->getId()] = ts;
factions[unitFactionIndex].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);

View File

@ -138,6 +138,11 @@ private:
int getPathFindExtendRefreshNodeCount(int factionIndex);
void astarJPS(std::map<Vec2i,Vec2i> cameFrom, Node *& node,
const Vec2i & finalPos, std::map<Vec2i,bool> closedNodes,
std::map<std::pair<Vec2i,Vec2i> ,bool> canAddNode, Unit *& unit,
bool & nodeLimitReached, int & maxNodeCount);
bool contained(Vec2i c);
direction directionOfMove(Vec2i to, Vec2i from) const;
direction directionWeCameFrom(Vec2i node, Vec2i nodeFrom) const;

View File

@ -456,6 +456,46 @@ int Faction::getAIBehaviorStaticOverideValue(AIBehaviorStaticValueCategory type)
return factionType->getAIBehaviorStaticOverideValue(type);
}
void Faction::addUnitToMovingList(int unitId) {
unitsMovingList[unitId] = getWorld()->getFrameCount();
}
void Faction::removeUnitFromMovingList(int unitId) {
unitsMovingList.erase(unitId);
}
int Faction::getUnitMovingListCount() {
return unitsMovingList.size();
}
void Faction::addUnitToPathfindingList(int unitId) {
unitsPathfindingList[unitId] = getWorld()->getFrameCount();
}
void Faction::removeUnitFromPathfindingList(int unitId) {
unitsPathfindingList.erase(unitId);
}
int Faction::getUnitPathfindingListCount() {
return unitsPathfindingList.size();
}
void Faction::clearUnitsPathfinding() {
unitsPathfindingList.clear();
}
bool Faction::canUnitsPathfind() {
bool result = true;
if(control == ctCpuEasy || control == ctCpu ||
control == ctCpuUltra || control == ctCpuMega) {
//printf("AI player for faction index: %d (%s) current pathfinding: %d\n",index,factionType->getName().c_str(),getUnitPathfindingListCount());
const int MAX_UNITS_PATHFINDING_PER_FRAME = 10;
result = (getUnitPathfindingListCount() <= MAX_UNITS_PATHFINDING_PER_FRAME);
if(result == false) {
//printf("WARNING limited AI player for faction index: %d (%s) current pathfinding: %d\n",index,factionType->getName().c_str(),getUnitPathfindingListCount());
}
}
return result;
}
Unit * Faction::getUnit(int i) const {
Unit *result = units[i];
@ -1924,6 +1964,21 @@ void Faction::saveGame(XmlNode *rootNode) {
// set<int> livingUnits;
// set<Unit*> livingUnitsp;
for(std::map<int,int>::iterator iterMap = unitsMovingList.begin();
iterMap != unitsMovingList.end(); ++iterMap) {
XmlNode *unitsMovingListNode = factionNode->addChild("unitsMovingList");
unitsMovingListNode->addAttribute("key",intToStr(iterMap->first), mapTagReplacements);
unitsMovingListNode->addAttribute("value",intToStr(iterMap->second), mapTagReplacements);
}
for(std::map<int,int>::iterator iterMap = unitsPathfindingList.begin();
iterMap != unitsPathfindingList.end(); ++iterMap) {
XmlNode *unitsPathfindingListNode = factionNode->addChild("unitsPathfindingList");
unitsPathfindingListNode->addAttribute("key",intToStr(iterMap->first), mapTagReplacements);
unitsPathfindingListNode->addAttribute("value",intToStr(iterMap->second), mapTagReplacements);
}
}
void Faction::loadGame(const XmlNode *rootNode, int factionIndex,GameSettings *settings,World *world) {
@ -2007,8 +2062,69 @@ void Faction::loadGame(const XmlNode *rootNode, int factionIndex,GameSettings *s
thisFaction = factionNode->getAttribute("thisFaction")->getIntValue();
// bool factionDisconnectHandled;
// for(std::map<Vec2i,int>::iterator iterMap = cacheResourceTargetList.begin();
// iterMap != cacheResourceTargetList.end(); ++iterMap) {
// XmlNode *cacheResourceTargetListNode = factionNode->addChild("cacheResourceTargetList");
//
// cacheResourceTargetListNode->addAttribute("key",iterMap->first.getString(), mapTagReplacements);
// cacheResourceTargetListNode->addAttribute("value",intToStr(iterMap->second), mapTagReplacements);
// }
// // std::map<Vec2i,bool> cachedCloseResourceTargetLookupList;
// for(std::map<Vec2i,bool>::iterator iterMap = cachedCloseResourceTargetLookupList.begin();
// iterMap != cachedCloseResourceTargetLookupList.end(); ++iterMap) {
// XmlNode *cachedCloseResourceTargetLookupListNode = factionNode->addChild("cachedCloseResourceTargetLookupList");
//
// cachedCloseResourceTargetLookupListNode->addAttribute("key",iterMap->first.getString(), mapTagReplacements);
// cachedCloseResourceTargetLookupListNode->addAttribute("value",intToStr(iterMap->second), mapTagReplacements);
// }
vector<XmlNode *> cacheResourceTargetListNodeList = factionNode->getChildList("cacheResourceTargetList");
for(unsigned int i = 0; i < cacheResourceTargetListNodeList.size(); ++i) {
XmlNode *cacheResourceTargetListNode = cacheResourceTargetListNodeList[i];
Vec2i vec = Vec2i::strToVec2(cacheResourceTargetListNode->getAttribute("key")->getValue());
cacheResourceTargetList[vec] = cacheResourceTargetListNode->getAttribute("value")->getIntValue();
}
vector<XmlNode *> cachedCloseResourceTargetLookupListNodeList = factionNode->getChildList("cachedCloseResourceTargetLookupList");
for(unsigned int i = 0; i < cachedCloseResourceTargetLookupListNodeList.size(); ++i) {
XmlNode *cachedCloseResourceTargetLookupListNode = cachedCloseResourceTargetLookupListNodeList[i];
Vec2i vec = Vec2i::strToVec2(cachedCloseResourceTargetLookupListNode->getAttribute("key")->getValue());
cachedCloseResourceTargetLookupList[vec] = cachedCloseResourceTargetLookupListNode->getAttribute("value")->getIntValue();
}
// RandomGen random;
random.setLastNumber(factionNode->getAttribute("random")->getIntValue());
// for(std::map<int,int>::iterator iterMap = unitsMovingList.begin();
// iterMap != unitsMovingList.end(); ++iterMap) {
// XmlNode *unitsMovingListNode = factionNode->addChild("unitsMovingList");
//
// unitsMovingListNode->addAttribute("key",intToStr(iterMap->first), mapTagReplacements);
// unitsMovingListNode->addAttribute("value",intToStr(iterMap->second), mapTagReplacements);
// }
//
// for(std::map<int,int>::iterator iterMap = unitsPathfindingList.begin();
// iterMap != unitsPathfindingList.end(); ++iterMap) {
// XmlNode *unitsPathfindingListNode = factionNode->addChild("unitsPathfindingList");
//
// unitsPathfindingListNode->addAttribute("key",intToStr(iterMap->first), mapTagReplacements);
// unitsPathfindingListNode->addAttribute("value",intToStr(iterMap->second), mapTagReplacements);
// }
vector<XmlNode *> unitsMovingListNodeList = factionNode->getChildList("unitsMovingList");
for(unsigned int i = 0; i < unitsMovingListNodeList.size(); ++i) {
XmlNode *unitsMovingListNode = unitsMovingListNodeList[i];
int unitId = unitsMovingListNode->getAttribute("key")->getIntValue();
unitsMovingList[unitId] = unitsMovingListNode->getAttribute("value")->getIntValue();
}
vector<XmlNode *> unitsPathfindingListNodeList = factionNode->getChildList("unitsPathfindingList");
for(unsigned int i = 0; i < unitsPathfindingListNodeList.size(); ++i) {
XmlNode *unitsPathfindingListNode = unitsPathfindingListNodeList[i];
int unitId = unitsPathfindingListNode->getAttribute("key")->getIntValue();
unitsPathfindingList[unitId] = unitsPathfindingListNode->getAttribute("value")->getIntValue();
}
}
}

View File

@ -141,6 +141,9 @@ private:
set<int> livingUnits;
set<Unit*> livingUnitsp;
std::map<int,int> unitsMovingList;
std::map<int,int> unitsPathfindingList;
TechTree *techTree;
const XmlNode *loadWorldNode;
@ -155,6 +158,17 @@ public:
void deleteLivingUnits(int id) { livingUnits.erase(id); }
void deleteLivingUnitsp(Unit *unit) { livingUnitsp.erase(unit); }
//std::map<int,int> unitsMovingList;
void addUnitToMovingList(int unitId);
void removeUnitFromMovingList(int unitId);
int getUnitMovingListCount();
void addUnitToPathfindingList(int unitId);
void removeUnitFromPathfindingList(int unitId);
int getUnitPathfindingListCount();
void clearUnitsPathfinding();
bool canUnitsPathfind();
void init(
FactionType *factionType, ControlType control, TechTree *techTree, Game *game,
int factionIndex, int teamIndex, int startLocationIndex, bool thisFaction,

View File

@ -932,9 +932,18 @@ void Unit::setCurrSkill(const SkillType *currSkill) {
throw runtime_error(szBuf);
}
if(this->currSkill->getClass() == scMove &&
currSkill->getClass() != scMove) {
faction->removeUnitFromMovingList(this->getId());
}
else if(this->currSkill->getClass() != scMove &&
currSkill->getClass() == scMove) {
faction->addUnitToMovingList(this->getId());
}
changedActiveCommand = false;
if(currSkill->getClass() != this->currSkill->getClass() ||
currSkill->getName() != this->currSkill->getName()) {
if( currSkill->getClass() != this->currSkill->getClass() ||
currSkill->getName() != this->currSkill->getName()) {
animProgress= 0;
lastAnimProgress= 0;

View File

@ -392,6 +392,15 @@ void World::updateAllFactionUnits() {
// }
// }
// Clear pathfinder list restrictions
for(int i = 0; i < factionCount; ++i) {
Faction *faction = getFaction(i);
if(faction == NULL) {
throw runtime_error("faction == NULL");
}
faction->clearUnitsPathfinding();
}
// Signal the faction threads to do any pre-processing
for(int i = 0; i < factionCount; ++i) {
Faction *faction = getFaction(i);