/// How close to one of our cities must a newly-settled city be in order to trigger our aggression?
int CvDiplomacyAI::GetExpansionBickerRange() const
{
if (GetPlayer()->isHuman() || GetPlayer()->GetPlayerTraits()->IsExpansionist() || GetBoldness() >= 8)
return /*7*/ GD_INT_GET(EXPANSION_BICKER_RANGE_HIGH);
if (GetBoldness() >= 4)
return /*6*/ GD_INT_GET(EXPANSION_BICKER_RANGE_MEDIUM);
return /*5*/ GD_INT_GET(EXPANSION_BICKER_RANGE_LOW);
}
/// Updates how pissy the AI is about other players settling too near them
/// Also tests whether other players have broken any expansion or land buying promises since last turn
void CvDiplomacyAI::DoExpansionBickering()
{
if (GetPlayer()->isHuman())
return;
int iLoop = 0;
int iLoop2 = 0;
int iGameTurn = GC.getGame().getGameTurn();
int iExpansionBickerRange = GetExpansionBickerRange();
for (int iPlayerLoop = 0; iPlayerLoop < MAX_MAJOR_CIVS; iPlayerLoop++)
{
PlayerTypes ePlayer = (PlayerTypes) iPlayerLoop;
if (!IsPlayerValid(ePlayer))
continue;
// No point in updating this while at war
if (IsAtWar(ePlayer))
continue;
// Test to see if a land buying promise was broken
if (GetNumTurnsBorderPromise(ePlayer) > 0)
{
AggressivePostureTypes eOldPosture = GetBorderPromisePosture(ePlayer);
if (GetPlotBuyingAggressivePosture(ePlayer) > eOldPosture)
SetBorderPromiseState(ePlayer, PROMISE_STATE_BROKEN);
}
// Don't bother checking further if they ignored/broke a promise, if bicker range is 0, or if they're our master.
if (GetExpansionPromiseState(ePlayer) >= PROMISE_STATE_IGNORED || iExpansionBickerRange <= 0 || IsVassal(ePlayer))
{
SetAngryAboutExpansion(ePlayer, false);
continue;
}
// If they haven't expanded or if it's been too long for us to complain about their expansion, forget about it.
if (GET_PLAYER(ePlayer).getNumCities() <= 1 || GET_PLAYER(ePlayer).GetNumCitiesFounded() == 0 || GET_PLAYER(ePlayer).GetTurnsSinceSettledLastCity() >= /*30*/ GD_INT_GET(EXPANSION_BICKER_TIMEOUT))
{
SetAngryAboutExpansion(ePlayer, false);
continue;
}
CvCity* pTheirCapital = GET_PLAYER(ePlayer).getCapitalCity();
if (!pTheirCapital || !pTheirCapital->plot())
continue;
bool bFoundOne = false;
for (CvCity* pLoopCity = GET_PLAYER(ePlayer).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER(ePlayer).nextCity(&iLoop))
{
CvPlot* pCityPlot = pLoopCity->plot();
if (!pCityPlot)
continue;
// Ignore their capital
if (pLoopCity->IsOriginalCapitalForPlayer(ePlayer))
continue;
// If this city already existed last time we got mad, don't get mad again over it
// This flag also excludes City-States purchased by Venice/Austria
if (pLoopCity->IsIgnoredForExpansionBickering(GetID()))
continue;
// Can we actually see this city? No cheating!
if (!pCityPlot->isRevealed(GetTeam()))
continue;
// Only count settled cities, not conquered ones
if (GET_PLAYER(pLoopCity->getOriginalOwner()).getTeam() != GET_PLAYER(ePlayer).getTeam())
continue;
// Must have founded the city recently
int iTurnFounded = pLoopCity->getGameTurnFounded();
if (iGameTurn - iTurnFounded >= /*30*/ GD_INT_GET(EXPANSION_BICKER_TIMEOUT))
continue;
// Must be close to one of our cities
if (GetPlayer()->GetCityDistanceInPlots(pCityPlot) > iExpansionBickerRange)
continue;
int iDistanceFromTheirCapital = plotDistance(*pCityPlot, *pTheirCapital->plot());
// Check to see if any of our cities within range of them were founded earlier than theirs was
for (CvCity* pOurLoopCity = GetPlayer()->firstCity(&iLoop2); pOurLoopCity != NULL; pOurLoopCity = GetPlayer()->nextCity(&iLoop2))
{
CvPlot* pOurCityPlot = pOurLoopCity->plot();
if (!pOurCityPlot)
continue;
// If we acquired our city after they founded theirs, they're not being aggressive
int iGameTurnAcquired = pOurLoopCity->getGameTurnAcquired();
if (iGameTurnAcquired > iTurnFounded)
continue;
else if (iGameTurnAcquired == iTurnFounded)
{
// If they're earlier in the player order, they're not being aggressive, they just got there first!
if ((int)ePlayer < (int)GetID())
continue;
}
// Must be on same land area
if (pCityPlot->getLandmass() != pOurCityPlot->getLandmass())
continue;
// Is this city near them?
int iDistanceBetweenUs = plotDistance(*pCityPlot, *pOurCityPlot);
if (iDistanceBetweenUs > iExpansionBickerRange)
continue;
// If their city is closer to (or equidistant from) their own capital, it's within their sphere of influence - ignore it
if (iDistanceFromTheirCapital <= iDistanceBetweenUs)
continue;
// We've got a reason to be mad!
bFoundOne = true;
break;
}
if (bFoundOne)
break;
}
// AI is pissed!
if (bFoundOne)
{
if (GetNumTurnsExpansionPromise(ePlayer) > 0) // Call this function, because expansion bickering occurs before TestOpinionModifiers()
{
SetExpansionPromiseState(ePlayer, PROMISE_STATE_BROKEN); // You broke the promise you made!
// Flag all of their cities as ignored for future bickering
for (CvCity* pLoopCity = GET_PLAYER(ePlayer).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER(ePlayer).nextCity(&iLoop))
{
pLoopCity->SetIgnoredForExpansionBickering(GetID(), true);
}
}
else
SetAngryAboutExpansion(ePlayer, true); // Let's give them a piece of our mind!
}
else
SetAngryAboutExpansion(ePlayer, false);
}
}