Code to determine if a player can reach another landmass?

Tholal

Emperor
Joined
May 19, 2009
Messages
1,676
I'm looking for some C++ code that would help me determine if a player can reach another landmass (IE, is it just one space away and we have boats? Or is it across Ocean, in which case we need to check that we can make units that can cross Ocean tiles). I thought there would be something like this already in the DLL but I cant seem to find anything along these lines.

Basically, the issue is that AI players will sometimes start Warplans against other players that they can't reach due to Ocean tiles being in the way (and the AI lacks the ability to cross Oceans). This is counter-productive for the AI and I would like to fix it.
 
You are likely looking for something like gDLL->getFAStarIFace()->GeneratePath(). This is tricky stuff as the most interesting part takes place inside the exe and I haven't been able to find any documentation on it.

The best I can do is give you code, which I wrote and is known to work. It is written for Medieval Conquest (a colonization mod, but it should work in BTS too). The goal is to check if two plots are connected by road.

Code:
if (gDLL->getFAStarIFace()->GeneratePath(&GC.getRouteFinder(), pLastPlot->getX_INLINE(), pLastPlot->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), false, (0x40 & eTeam), true))
This is true if pLastPlot and pLoopPlot are connected.

The code it calls is:
Spoiler :
Code:
// Nightinggale note:
// This function has been expanded to solve more tasks than the vanilla one
// It exists in two modes:
//
//  1:
//    iInfo set to playerID
//    vanilla behavior (something about AI checking route quality between cities)
//
//  2:
//    iInfo is set to TeamTypes + 0x40 (64)
//    tells if there is a road (of any quality) between start and end plots
//    Used to detect plotgroup splitting
int routeValid(FAStarNode* parent, FAStarNode* node, int data, const void* pointer, FAStar* finder)
{
	CvPlot* pNewPlot;
	PlayerTypes ePlayer;

	if (parent == NULL)
	{
		return TRUE;
	}

	pNewPlot = GC.getMapINLINE().plotSorenINLINE(node->m_iX, node->m_iY);

	/// PlotGroup - start - Nightinggale
	int iInfo = gDLL->getFAStarIFace()->GetInfo(finder);

	if (iInfo & 0x40)
	{
		[COLOR="Red"]return pNewPlot->isTradeNetwork((TeamTypes)(iInfo & 0x3f));[/COLOR]
	}
	
	//ePlayer = ((PlayerTypes)(gDLL->getFAStarIFace()->GetInfo(finder)));
	ePlayer = ((PlayerTypes)(iInfo));
	/// PlotGroup - end - Nightinggale

	if (!(pNewPlot->isOwned()) || (pNewPlot->getTeam() == GET_PLAYER(ePlayer).getTeam()))
	{
		if (pNewPlot->getRouteType() == GET_PLAYER(ePlayer).getBestRoute(pNewPlot))
		{
			return TRUE;
		}
	}

	return FALSE;
}
You should be able to do something similar. The interesting line is marked in red. It should be true if the civ can pass and false if it can't. You then write a function, which checks if plot is water, impassable, owned by player with/without open borders etc.

There is a bit of bit magic as I didn't manage to add more arguments (I don't think it's possible). Because of this iInfo is both team and mode selector and as such needs to be split.

Look at CvMap::setup() to see which pathfinding functions you have available. The 4th last argument is a pointer to a function in CvGameCoreUtils.cpp.

Come to think of it, maybe you can use one of the existing pathfinding functions without modifying it. I would advice you to take a closer look at all of them before starting any coding.

Warning: pathfinding might have to go through a lot of data meaning it will likely slow down the game if you write code to make hundreds of checks every turn. My profiling experience tells me that pathfinding is a major part of totally time used by the AI. I can't remember precisely offhand, but I recall something about more than 1/3 of total time spent on AI actions. It was on a big map, but still it is something to keep in mind.
 
Back
Top Bottom