示例#1
0
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;
}
示例#2
0
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;
}