float CPathFinder::FindBestPath(F3Vec& posPath, float3& startPos, float myMaxRange, F3Vec& possibleTargets) { ai->math->TimerStart(); path.clear(); // make a list with the points that will count as end nodes float totalcost = 0.0f; const unsigned int radius = int(myMaxRange / (8 * resmodifier)); int offsetSize = 0; std::vector<std::pair<int, int> > offsets; std::vector<int> xend; std::vector<void*> endNodes; endNodes.reserve(possibleTargets.size() * radius * 10); { const unsigned int DoubleRadius = radius * 2; const unsigned int SquareRadius = radius * radius; xend.resize(DoubleRadius + 1); offsets.resize(DoubleRadius * 5); for (size_t a = 0; a < DoubleRadius + 1; a++) { const float z = (int) (a - radius); const float floatsqrradius = SquareRadius; xend[a] = int(sqrt(floatsqrradius - z * z)); } offsets[0].first = 0; offsets[0].second = 0; size_t index = 1; size_t index2 = 1; for (size_t a = 1; a < radius + 1; a++) { int endPosIdx = xend[a]; int startPosIdx = xend[a - 1]; while (startPosIdx <= endPosIdx) { assert(index < offsets.size()); offsets[index].first = startPosIdx; offsets[index].second = a; startPosIdx++; index++; } startPosIdx--; } index2 = index; for (size_t a = 0; a < index2 - 2; a++) { assert(index < offsets.size()); assert(a < offsets.size()); offsets[index].first = offsets[a].first; offsets[index].second = DoubleRadius - (offsets[a].second); index++; } index2 = index; for (size_t a = 0; a < index2; a++) { assert(index < offsets.size()); assert(a < offsets.size()); offsets[index].first = -(offsets[a].first); offsets[index].second = offsets[a].second; index++; } for (size_t a = 0; a < index; a++) { assert(a < offsets.size()); offsets[a].first = offsets[a].first; // ?? offsets[a].second = offsets[a].second - radius; } offsetSize = index; } for (unsigned i = 0; i < possibleTargets.size(); i++) { float3& f = possibleTargets[i]; int x, y; // TODO: make the circle here ai->math->F3MapBound(f); Node2XY(Pos2Node(f), &x, &y); for (int j = 0; j < offsetSize; j++) { const int sx = x + offsets[j].first; const int sy = y + offsets[j].second; if (sx >= 0 && sx < PathMapXSize && sy >= 0 && sy < PathMapYSize) { endNodes.push_back(XY2Node(sx, sy)); } } } ai->math->F3MapBound(startPos); if (micropather->FindBestPathToAnyGivenPoint(Pos2Node(startPos), endNodes, &path, &totalcost) == MicroPather::SOLVED) { posPath.reserve(path.size()); for (unsigned i = 0; i < path.size(); i++) { int x, y; Node2XY(path[i], &x, &y); float3 mypos = Node2Pos(path[i]); mypos.y = ai->cb->GetElevation(mypos.x, mypos.z); posPath.push_back(mypos); } } return totalcost; }
void CPathFinder::CreateDefenseMatrix() { int enemyStartUnitIDs[255] = {-1}; float3 enemyStartPositions[255] = {ZeroVector}; const int range = std::max(1.0f, sqrtf(float(PathMapXSize * PathMapYSize)) / THREATRES / 3); const int rangeSq = range * range; const int maskWidth = (2 * range + 1); std::vector<float> costMask(maskWidth * maskWidth); for (int x = 0; x < maskWidth; x++) { for (int y = 0; y < maskWidth; y++) { const int index = y * maskWidth + x; const int distSq = (x - range) * (x - range) + (y - range) * (y - range); if (distSq <= rangeSq) { costMask[index] = ((distSq - rangeSq) * (distSq - rangeSq)) / (rangeSq * 2); } else { costMask[index] = 0.0f; } } } ai->dm->ChokeMapsByMovetype.resize(NumOfMoveTypes); for (int m = 0; m < NumOfMoveTypes;m++) { const int numEnemies = ai->ccb->GetEnemyUnits(enemyStartUnitIDs); for (int i = 0; i < numEnemies; i++) { enemyStartPositions[i] = ai->ccb->GetUnitPos(enemyStartUnitIDs[i]); } const float3& myPos = ai->cb->GetUnitPos(ai->uh->AllUnitsByCat[CAT_BUILDER].front()); const int reruns = 35; ai->dm->ChokeMapsByMovetype[m].resize(totalcells); micropather->SetMapData(MoveArrays[m], &ai->dm->ChokeMapsByMovetype[m][0], PathMapXSize, PathMapYSize); for (int i = 0; i < totalcells; i++) { ai->dm->ChokeMapsByMovetype[m][i] = 1; } // HACK: // for each enemy start-unit, find a path to its position <N> times // for each found path, deposit cost-crumbs at every second waypoint // regions where many paths overlap indicate choke-points if (numEnemies > 0 && m == PATHTOUSE) { for (int r = 0; r < reruns; r++) { for (int startPosIdx = 0; startPosIdx < numEnemies; startPosIdx++) { void* startPos = Pos2Node(enemyStartPositions[startPosIdx]); void* goalPos = Pos2Node(myPos); if (micropather->Solve(startPos, goalPos, &path, &totalcost) != MicroPather::SOLVED) { continue; } for (int i = 12; i < int(path.size() - 12); i++) { if ((i % 2) == 0) { continue; } int x, y; Node2XY(path[i], &x, &y); for (int myx = -range; myx <= range; myx++) { const int actualx = x + myx; if (actualx < 0 || actualx >= PathMapXSize) { continue; } for (int myy = -range; myy <= range; myy++) { const int actualy = y + myy; const int cmIndex = actualy * PathMapXSize + actualx; if (actualy < 0 || actualy >= PathMapYSize) { continue; } ai->dm->ChokeMapsByMovetype[m][cmIndex] += costMask[(myy + range) * maskWidth + (myx + range)]; } } } } } } } }
float CPathFinder::FindBestPath(vector<float3> *posPath, float3 *startPos, float myMaxRange, vector<float3> *possibleTargets) { ////L("FindBestPath Started"); ////L("startPos: x: " << startPos->x << ", z: " << startPos->z); ai->math->TimerStart(); float totalcost; ClearPath(); // Make a list with the points that will count as end nodes. static vector<void*> endNodes; int radius = int(myMaxRange / (8 *resmodifier)); int offsetSize = 0; endNodes.resize(0); endNodes.reserve(possibleTargets->size() * radius * 10); ////L("possibleTargets->size(): " << possibleTargets->size()); pair<int, int> * offsets; { ////L("radius: " << radius); int DoubleRadius = radius * 2; int SquareRadius = radius * radius; //used to speed up loops so no recalculation needed int * xend = new int[DoubleRadius+1]; ////L("1"); for (int a=0;a<DoubleRadius+1;a++){ float z=a-radius; float floatsqrradius = SquareRadius; xend[a]=int(sqrt(floatsqrradius-z*z)); } ////L("2"); offsets = new pair<int, int>[DoubleRadius*5]; int index = 0; int startPos = 0; ////L("3"); offsets[index].first = 0; ////L("offsets[index].first: " << offsets[index].first); offsets[index].second = 0; ////L("offsets[index].second: " << offsets[index].second); index++; for (int a=1;a<radius+1;a++){ ////L("a: " << a); int endPos = xend[a]; int startPos = xend[a-1]; ////L("endPos: " << endPos); while(startPos <= endPos) { ////L("startPos: " << startPos); offsets[index].first = startPos; ////L("offsets[index].first: " << offsets[index].first); offsets[index].second = a; ////L("offsets[index].second: " << offsets[index].second); startPos++; index++; } startPos--; } int index2 = index; for (int a=0;a<index2-2;a++) { offsets[index].first = offsets[a].first; ////L("offsets[index].first: " << offsets[index].first); offsets[index].second = DoubleRadius - ( offsets[a].second); ////L("offsets[index].second: " << offsets[index].second); index++; } index2 = index; ////L("3.7"); for (int a=0;a<index2;a++) { offsets[index].first = - ( offsets[a].first); ////L("offsets[index].first: " << offsets[index].first); offsets[index].second = offsets[a].second; ////L("offsets[index].second: " << offsets[index].second); index++; } for (int a=0;a<index;a++) { offsets[a].first = offsets[a].first;// + radius; ////L("offsets[index].first: " << offsets[a].first); offsets[a].second = offsets[a].second - radius; ////L("offsets[index].second: " << offsets[a].second); } offsetSize = index; delete [] xend; } for(unsigned i = 0; i < possibleTargets->size(); i++) { float3 f = (*possibleTargets)[i]; int x, y; ////L("Added: x: " << f.x << ", z: " << f.z); // TODO: Make the circle here: ai->math->F3MapBound(&f); void * node = Pos2Node(f); Node2XY(node, &x, &y); for(int j = 0; j < offsetSize; j++) { int sx = x + offsets[j].first; int sy = y + offsets[j].second; if(sx >= 0 && sx < PathMapXSize && sy >= 0 && sy < PathMapYSize) endNodes.push_back(XY2Node(sx, sy)); } ////L("node: " << ((int) node) << ", x: " << x << ", y: " << y); //endNodes.push_back(node); } ai->math->F3MapBound(startPos); ////L("endNodes.size(): " << endNodes.size()); delete [] offsets; if(micropather->FindBestPathToAnyGivenPoint( Pos2Node(*startPos), endNodes, &path, &totalcost) == MicroPather::SOLVED) { // Solved ////L("attack solution solved! Path size = " << path.size()); posPath->reserve(path.size()); for(unsigned i = 0; i < path.size(); i++) { ////L("adding path point"); int x, y; Node2XY(path[i], &x, &y); ////L("node: " << ((int) path[i]) << ". x: " << x << ", y: " << y); float3 mypos = Node2Pos(path[i]); ////L("mypos: x: " << mypos.x << ", z: " << mypos.z); mypos.y = ai->cb->GetElevation(mypos.x, mypos.z); posPath->push_back(mypos); } //char c[500]; //sprintf(c,"Time Taken: %f Total Cost %i",ai->math->TimerSecs(), int(totalcost)); ////L(c); } else //L("FindBestPath: path failed!"); return totalcost; }
void CPathFinder::CreateDefenseMatrix(){ ////L("Starting pathing"); ai->math->TimerStart(); int enemycomms[16]; float3 enemyposes[16]; ai->dm->ChokeMapsByMovetype.resize(NumOfMoveTypes); //ai->debug->MakeBWTGA(SlopeMap,PathMapXSize,PathMapYSize,string("SlopeMap")); //ai->debug->MakeBWTGA(TestMoveArray,PathMapXSize,PathMapYSize,string("Plane Move Array")); int Range = int(sqrtf(float(PathMapXSize*PathMapYSize))/ THREATRES / 3); int squarerange = Range*Range; int maskwidth = (2*Range+1); float* costmask = new float[maskwidth*maskwidth]; for (int x = 0; x < maskwidth; x++){ for (int y = 0; y < maskwidth; y++){ int distance = (x - Range)*(x - Range) + (y - Range)*(y - Range); if(distance <= squarerange){ costmask[y * maskwidth + x] = (distance - squarerange)*(distance - squarerange)/squarerange * 2; } else{ costmask[y * maskwidth + x] = 0; } } } //ai->debug->MakeBWTGA(costmask,maskwidth,maskwidth,string("CostMask")); for(int m = 0; m < NumOfMoveTypes;m++){ int numberofenemyplayers = ai->cheat->GetEnemyUnits(enemycomms); for(int i = 0; i < numberofenemyplayers; i++){ //L("Enemy comm: " << enemycomms[i]); enemyposes[i] = ai->cheat->GetUnitPos(enemycomms[i]); } float3 mypos = ai->cb->GetUnitPos(ai->uh->AllUnitsByCat[CAT_BUILDER]->front()); int reruns = 35; ai->dm->ChokeMapsByMovetype[m] = new float [totalcells]; char k [10]; itoa (m,k,10); micropather->SetMapData(MoveArrays[m], ai->dm->ChokeMapsByMovetype[m], PathMapXSize, PathMapYSize); double pathCostSum = 0; for(int i = 0; i < totalcells; i++) { ai->dm->ChokeMapsByMovetype[m][i] = 1; } int runcounter = 0; if(numberofenemyplayers > 0 && m == PATHTOUSE){ // HACK for(int r = 0; r < reruns; r++){ ////L("reruns: " << r); for(int startpos = 0; startpos < numberofenemyplayers; startpos++){ if(micropather->Solve(Pos2Node(enemyposes[startpos]), Pos2Node(mypos), &path, &totalcost) == MicroPather::SOLVED){ for(int i = 12; i < int(path.size()-12); i++){ if(i%2){ int x,y; Node2XY(path[i],&x,&y); /*float3 pos1 = Node2Pos(path[i-1]); float3 pos2 = Node2Pos(path[i]); pos1.y = 100 + ai->cb->GetElevation(pos1.x ,pos1.z); pos2.y = 100 + ai->cb->GetElevation(pos2.x ,pos2.z); //L("Line: " << pos1.x << "," << pos1.z << ", pos2: " << pos2.x << "," << pos2.z); //ai->cb->CreateLineFigure(pos1,pos2,10,1,100000000,457);*/ for (int myx = -Range; myx <= Range; myx++){ int actualx = x + myx; if (actualx >= 0 && actualx < PathMapXSize){ for (int myy = -Range; myy <= Range; myy++){ int actualy = y + myy; if (actualy >= 0 && actualy < PathMapYSize){ ai->dm->ChokeMapsByMovetype[m][actualy * PathMapXSize + actualx] += costmask[(myy+Range) * maskwidth + (myx+Range)]; } } } } } //SlopeMap[y*PathMapXSize+x] += 30; } runcounter++; } ////L("Enemy Pos " << startpos << " Cost: " << totalcost); pathCostSum += totalcost; ////L("Time Taken: " << clock() - timetaken); } } ////L("pathCostSum: " << pathCostSum); ////L("paths calculated, resmodifier: " << resmodifier ); char k [10]; itoa (m,k,10); //ai->debug->MakeBWTGA(ai->dm->ChokeMapsByMovetype[m],PathMapXSize,PathMapYSize,string("ChokePoint Array for Movetype ") + string(k)); /*float maxvalue = 0.1; for(int i = 0; i < totalcells; i++) { if(chokemap[i] > maxvalue) maxvalue = chokemap[i]; } for(int i = 0; i < totalcells; i++) { chokemap[i] /= maxvalue; }*/ //Radius debug /*int radius = 2; void * startNode = XY2Node(xvector[0],zvector[0]); void * senterNode = XY2Node(xvector[1],zvector[1]); float3 senterPos = Node2Pos(senterNode); float3 distPos = Node2Pos(XY2Node(radius,radius)); for(int i = 0; i < 20; i++) { float dx1 = sin(i * 3.1415 / 10) * distPos.x; float dy1 = cos(i * 3.1415 / 10) * distPos.z; float dx2 = sin((i + 1) * 3.1415 / 10) * distPos.x; float dy2 = cos((i + 1) * 3.1415 / 10) * distPos.z; float3 pos1 = senterPos + float3(dx1,0,dy1); pos1.y = 100 + ai->cb->GetElevation(pos1.x, pos1.z); float3 pos2 = senterPos + float3(dx2,0,dy2); pos2.y = 100 + ai->cb->GetElevation(pos2.x, pos2.z); ////L("Line: " << pos1.x << "," << pos1.z << ", pos2: " << pos2.x << "," << pos2.z); //ai->cb->CreateLineFigure(pos1,pos2,20,0,100000000,456); } micropather->FindBestPathToPointOnRadius(startNode, senterNode, &path, &totalcost, radius); //L("totalcost: " << totalcost << ", path.size(): " << path.size()); for(int i = 1; i < path.size(); i++) { float3 pos1 = Node2Pos(path[i-1]); float3 pos2 = Node2Pos(path[i]); pos1.y = 100 + ai->cb->GetElevation(pos1.x ,pos1.z); pos2.y = 100 + ai->cb->GetElevation(pos2.x ,pos2.z); ////L("Line: " << pos1.x << "," << pos1.z << ", pos2: " << pos2.x << "," << pos2.z); //ai->cb->CreateLineFigure(pos1,pos2,10,1,100000000,457); }*/ } } delete [] costmask; char c[500]; sprintf(c,"Time Taken to create chokepoints: %f",ai->math->TimerSecs()); ai->cb->SendTextMsg(c,0); //L(c); }
float CPathFinder::FindBestPath(vector<float3>* posPath, float3* startPos, float myMaxRange, vector<float3>* possibleTargets) { ai->math->TimerStart(); float totalcost; ClearPath(); // make a list with the points that will count as end nodes static vector<void*> endNodes; int radius = int(myMaxRange / (8 * resmodifier)); int offsetSize = 0; endNodes.resize(0); endNodes.reserve(possibleTargets->size() * radius * 10); pair<int, int>* offsets; { // L("radius: " << radius); int DoubleRadius = radius * 2; // used to speed up loops so no recalculation needed int SquareRadius = radius * radius; int* xend = new int[DoubleRadius + 1]; for (int a = 0; a < DoubleRadius + 1; a++) { float z = a - radius; float floatsqrradius = SquareRadius; xend[a] = int(sqrt(floatsqrradius - z * z)); } offsets = new pair<int, int>[DoubleRadius * 5]; int index = 0; offsets[index].first = 0; offsets[index].second = 0; index++; for (int a = 1; a < radius + 1; a++) { // L("a: " << a); int endPos = xend[a]; int startPos = xend[a - 1]; while (startPos <= endPos) { offsets[index].first = startPos; offsets[index].second = a; startPos++; index++; } startPos--; } int index2 = index; for (int a = 0; a < index2 - 2; a++) { offsets[index].first = offsets[a].first; offsets[index].second = DoubleRadius - ( offsets[a].second); index++; } index2 = index; for (int a = 0; a < index2; a++) { offsets[index].first = -( offsets[a].first); offsets[index].second = offsets[a].second; index++; } for (int a = 0; a < index; a++) { offsets[a].first = offsets[a].first; offsets[a].second = offsets[a].second - radius; } offsetSize = index; delete[] xend; } for (unsigned i = 0; i < possibleTargets->size(); i++) { float3 f = (*possibleTargets)[i]; int x, y; // L("Added: x: " << f.x << ", z: " << f.z); // TODO: make the circle here ai->math->F3MapBound(&f); void * node = Pos2Node(f); Node2XY(node, &x, &y); for (int j = 0; j < offsetSize; j++) { int sx = x + offsets[j].first; int sy = y + offsets[j].second ; if (sx >= 0 && sx < PathMapXSize && sy >= 0 && sy < PathMapYSize) endNodes.push_back(XY2Node(sx, sy)); } } ai->math->F3MapBound(startPos); delete[] offsets; if (micropather->FindBestPathToAnyGivenPoint(Pos2Node(*startPos), endNodes, &path, &totalcost) == MicroPather::SOLVED) { posPath->reserve(path.size()); for (unsigned i = 0; i < path.size(); i++) { int x, y; Node2XY(path[i], &x, &y); float3 mypos = Node2Pos(path[i]); mypos.y = ai->cb->GetElevation(mypos.x, mypos.z); posPath->push_back(mypos); } } return totalcost; }
void CPathFinder::CreateDefenseMatrix() { int enemycomms[16]; float3 enemyposes[16]; ai->dm->ChokeMapsByMovetype.resize(NumOfMoveTypes); int Range = int(sqrtf(float(PathMapXSize * PathMapYSize)) / THREATRES / 3); int squarerange = Range * Range; int maskwidth = (2 * Range + 1); float* costmask = new float[maskwidth * maskwidth]; for (int x = 0; x < maskwidth; x++) { for (int y = 0; y < maskwidth; y++) { int distance = (x - Range) * (x - Range) + (y - Range) * (y - Range); if (distance <= squarerange) { costmask[y * maskwidth + x] = (distance - squarerange) * (distance - squarerange) / squarerange * 2; } else { costmask[y * maskwidth + x] = 0; } } } for (int m = 0; m < NumOfMoveTypes;m++) { int numberofenemyplayers = ai->cheat->GetEnemyUnits(enemycomms); for (int i = 0; i < numberofenemyplayers; i++) { enemyposes[i] = ai->cheat->GetUnitPos(enemycomms[i]); } float3 mypos = ai->cb->GetUnitPos(ai->uh->AllUnitsByCat[CAT_BUILDER].front()); ai->dm->ChokeMapsByMovetype[m].resize(totalcells); int reruns = 35; char k[10]; itoa(m, k, 10); micropather->SetMapData(MoveArrays[m], &ai->dm->ChokeMapsByMovetype[m][0], PathMapXSize, PathMapYSize); double pathCostSum = 0.0; for (int i = 0; i < totalcells; i++) { ai->dm->ChokeMapsByMovetype[m][i] = 1; } int runcounter = 0; // HACK if (numberofenemyplayers > 0 && m == PATHTOUSE) { for (int r = 0; r < reruns; r++) { for (int startpos = 0; startpos < numberofenemyplayers; startpos++) { if (micropather->Solve(Pos2Node(enemyposes[startpos]), Pos2Node(mypos), &path, &totalcost) == MicroPather::SOLVED) { for (int i = 12; i < int(path.size() - 12); i++) { if (i % 2) { int x, y; Node2XY(path[i], &x, &y); for (int myx = -Range; myx <= Range; myx++) { int actualx = x + myx; if (actualx >= 0 && actualx < PathMapXSize) { for (int myy = -Range; myy <= Range; myy++) { int actualy = y + myy; if (actualy >= 0 && actualy < PathMapYSize){ ai->dm->ChokeMapsByMovetype[m][actualy * PathMapXSize + actualx] += costmask[(myy + Range) * maskwidth + (myx+Range)]; } } } } } } runcounter++; } pathCostSum += totalcost; } } } } delete[] costmask; }