calculatePathDistanceToPlot function

OrionVeteran

Deity
Joined
Dec 25, 2003
Messages
2,443
Location
Newport News VA
The calculatePathDistance function in CvPlot.cpp requires a starting (source) water plot to calculate distances to other water plots. Since city plots are considered land plots, the function will fail if the source plot is a city and your are trying to find a specific water plot. However, it will work just fine searching for a surrounding land plot. To search for land, the source plot must be land. To search for water, the source plot must be water. There have been many times when I needed to search for a water plot that is a few plots away from a city.

The work around is to loop through the adjacent plots around a coastal city and select the first water plot and then make the adjacent water plot the source plot in the calculatePathDistance function. I would much prefer to have the calculation be made from the city instead of an adjacent water plot. Reason: The adjacent water plot is not centered in the city and thus I could miss my target plot on the other side of the city.

My Goal: I want the calculation to search for water plots to work from a city (land) plot.

Question: Is there a way to modify the function below to eliminate the need for the source plot to be water, when searching for water plots?

Spoiler :

Code:
int CvPlot::calculatePathDistanceToPlot( TeamTypes eTeam, CvPlot* pTargetPlot )
{
	PROFILE_FUNC();

	FAssert(eTeam != NO_TEAM);

	if( pTargetPlot->area() != area() )
	{
		return false;
	}

	// Imitate instatiation of irrigated finder, pIrrigatedFinder
	// Can't mimic step finder initialization because it requires creation from the exe
	std::vector<TeamTypes> teamVec;
	teamVec.push_back(eTeam);
	teamVec.push_back(NO_TEAM);
	FAStar* pTeamStepFinder = gDLL->getFAStarIFace()->create();
	gDLL->getFAStarIFace()->Initialize(pTeamStepFinder, GC.getMapINLINE().getGridWidthINLINE(), GC.getMapINLINE().getGridHeightINLINE(), GC.getMapINLINE().isWrapXINLINE(), GC.getMapINLINE().isWrapYINLINE(), stepDestValid, stepHeuristic, stepCost, teamStepValid, stepAdd, NULL, NULL);
	gDLL->getFAStarIFace()->SetData(pTeamStepFinder, &teamVec);
	FAStarNode* pNode;

	int iPathDistance = -1;
	gDLL->getFAStarIFace()->GeneratePath(pTeamStepFinder, getX_INLINE(), getY_INLINE(), pTargetPlot->getX_INLINE(), pTargetPlot->getY_INLINE(), false, 0, true);

	pNode = gDLL->getFAStarIFace()->GetLastNode(&GC.getStepFinder());

	if (pNode != NULL)
	{
		iPathDistance = pNode->m_iData1;
	}

	gDLL->getFAStarIFace()->destroy(pTeamStepFinder);

	return iPathDistance;
}
 
I believe I have listed the wrong function in my previous post. Here is the correct function, which is located in the CvMap.cpp file. This is the function that needs to be modified. Sorry for the confusion.

Spoiler :

Code:
int CvMap::calculatePathDistance(CvPlot *pSource, CvPlot *pDest)
{
	FAStarNode* pNode;

	if (pSource == NULL || pDest == NULL)
	{
		return -1;
	}

	if (gDLL->getFAStarIFace()->GeneratePath(&GC.getStepFinder(), pSource->getX_INLINE(), pSource->getY_INLINE(), pDest->getX_INLINE(), pDest->getY_INLINE(), false, 0, true))
	{
		pNode = gDLL->getFAStarIFace()->GetLastNode(&GC.getStepFinder());

		if (pNode != NULL)
		{
			return pNode->m_iData1;
		}
	}

	return -1; // no passable path exists
}
 
I suspect it's stopping on stepDestValid and stepValid in CvGameCoreUtils.cpp. You can make your own exception to the "must be same area" rule. Make a new define like you see e.g. MOVE_MAX_MOVES and MOVE_SAFE_TERRITORY in CvDefines.h.

Make sure GeneratePath is called with your new define when you need it to. Then have stepDestValid and stepValid not check that the areas are the same when your define is active. See the other defines if you don't understand how to make it work.

If you want to make sure the city is next to the water area then use CvPlot::isAdjacentToArea before trying to generate a path.
 
Back
Top Bottom