//	-----------------------------------------------------------------------------------------------
int CvDistanceMap::GetClosestFeatureOwner(const CvPlot& plot)
{
	if (m_bDirty)
		Update();

	if (m_bArrayAllocated)
		return UNPACK_OWNER( m_vClosestFeature[ GC.getMap().plotNum( plot.getX(), plot.getY() ) ] );

	return -1;
}
Ejemplo n.º 2
0
/// Updates the lookup table
void CvDistanceMapTurns::Update()
{
	//performance optimization, reduce pathfinding range
	int iMaxTurns = GC.getGame().getElapsedGameTurns() == 0 ? 7 : 12;
	int iVeryFar = iMaxTurns * 6;

	const CvMap& map = GC.getMap();
	int nPlots = map.numPlots();

	m_vDistance = std::vector<int>(nPlots, iVeryFar);
	m_vClosestFeature = std::vector<int>(nPlots,0);
	m_bArrayAllocated = true;
		
	for (int i = 0; i < MAX_PLAYERS; i++)
	{
		//if we have a set player, ignore all others
		if (m_ePlayer!=NO_PLAYER && m_ePlayer!=i)
			continue;

		// for each city
		CvPlayer& thisPlayer = GET_PLAYER((PlayerTypes)i);
		int iCityIndex = 0;
		for(CvCity* pLoopCity = thisPlayer.firstCity(&iCityIndex); pLoopCity != NULL; pLoopCity = thisPlayer.nextCity(&iCityIndex))
		{
			//slow update only for plots close to the city
			ReachablePlots turnsFromCity;
			SPathFinderUserData data(m_ePlayer, PT_GENERIC_REACHABLE_PLOTS, -1, iMaxTurns);
			turnsFromCity = GC.GetStepFinder().GetPlotsInReach(pLoopCity->plot(), data);

			for (ReachablePlots::iterator it = turnsFromCity.begin(); it != turnsFromCity.end(); ++it)
			{
				int iTurns = it->iTurns;
				bool bUpdate = (iTurns < m_vDistance[it->iPlotIndex]);
					
				//in case of equal distance, take care not to prefer the player with the lower ID
				if (iTurns == m_vDistance[it->iPlotIndex])
				{
					PlayerTypes currentOwner = (PlayerTypes)UNPACK_OWNER(m_vClosestFeature[it->iPlotIndex]);
					CvCity* pCurrentCity = GET_PLAYER(currentOwner).getCity(UNPACK_ID(m_vClosestFeature[it->iPlotIndex]));
					//it can happen that there is no current city if the plot has never been updated because it's very remote
					bUpdate = (pCurrentCity==NULL) || (pCurrentCity->getGameTurnFounded() > pLoopCity->getGameTurnFounded());
				}

				if (bUpdate)
				{
					m_vDistance[it->iPlotIndex] = iTurns;
					m_vClosestFeature[it->iPlotIndex] = PACK(pLoopCity->getOwner(), pLoopCity->GetID());
				}
			}
		}
	}

	m_bDirty = false;
}
/// Updates the danger plots values to reflect threats across the map
void CvDistanceMap::Update()
{
	const CvMap& map = GC.getMap();
	int nPlots = map.numPlots();

	m_vDistance = std::vector<int>(nPlots,INT_MAX);
	m_vClosestFeature = std::vector<int>(nPlots,0);
	m_bArrayAllocated = true;
		
	// since we know there are very few cities compared to the number of plots,
	// we don't need to do the full distance transform

	for (int i = 0; i < MAX_PLAYERS; i++)
	{
		if (m_ePlayer!=NO_PLAYER && m_ePlayer!=i)
			continue;

		// for each city
		CvPlayer& thisPlayer = GET_PLAYER((PlayerTypes)i);
		int iCityIndex = 0;
		for(CvCity* pLoopCity = thisPlayer.firstCity(&iCityIndex); pLoopCity != NULL; pLoopCity = thisPlayer.nextCity(&iCityIndex))
		{
			CvPlot* pCityPlot = pLoopCity->plot();

			for (int iPlotIndex=0; iPlotIndex<nPlots; iPlotIndex++)
			{
				CvPlot* pPlot = map.plotByIndexUnchecked(iPlotIndex);
				if (pPlot)
				{
					int iDistance = plotDistance( pCityPlot->getX(),pCityPlot->getY(),pPlot->getX(),pPlot->getY() );

					bool bUpdate = (iDistance < m_vDistance[iPlotIndex]);
					
					//in case of equal distance, take care not to prefer the player with the lower ID
					if (iDistance == m_vDistance[iPlotIndex]) 
					{
						PlayerTypes currentOwner = (PlayerTypes) UNPACK_OWNER(m_vClosestFeature[iPlotIndex]);
						CvCity* pCurrentCity = GET_PLAYER(currentOwner).getCity( UNPACK_ID(m_vClosestFeature[iPlotIndex]) );
						bUpdate = (pCurrentCity->getGameTurnFounded() > pLoopCity->getGameTurnFounded());
					}

					if (bUpdate)
					{
						m_vDistance[iPlotIndex] = iDistance;
						m_vClosestFeature[iPlotIndex] = PACK(pLoopCity->getOwner(), pLoopCity->GetID());
					}
				}
			}
		}
	}

	m_bDirty = false;
}