Moi Magnus
Emperor
- Joined
- Mar 1, 2015
- Messages
- 1,868
In this "guide", I will go trought the code and try to explain the way the AI chose to negociate or not.
Here is the code :
Translation of the code into english :
In order to accept negociation, the AI start by doing the following simple tests :
Then, it will evaluate the war.
It will compute the value :
War_state + War_projection + City_danger + Others
and compare it to 4.
If the value is lesser or equal to 4, then no negotiations. If it is greater, the AI agree to negotiate.
What is the WantPeaceCounter ?
Each turn, the AI check each of its war, and either increase this counter by 1, either reset it to 0.
There is two situations :
Situation 1 : The AI want your head.
In this situation, the counter will most likely be irrelevant.
In order to increase the counter, the AI must not be in a coop war, it must also be loosing the war according to War_projection, be already willing to negociate (so passing all the tests, including having more than 4 points as described before), and either having war weariness problems, either being a peacefull AI, either having a negative war score.
In every other cases, the counter is reset to 0.
Situation 2 : The AI don't want your head.
The counter is increased if the War_state is bad for the AI, and reset to 0 when it is neutral or good.
Interpretation :
The AI will never peace out if it think it can take a city easily.
If no cities are about to fall or under siege, and the AI has no war weariness problems, then you have to wait up to 28 turns after a city capture to be able to negociate.
This value is reduced by 4 turns for each AI city under siege, and by 4 other turns for each AI city about to fall.
This value is reduced 8 turns if the AI is losing or neutral in a long term point of vue.
This value is reduced by 8 turns if the AI is losing in a short term point of vue.
Moreover, if the AI is losing in a short term point of vue, and do not hate you, this value is divided by 5 (i.e reduced by 4 additional turns each turns).
So you can technicaly peace out just after capturing a city. You just need to be wining on short term and long term, and puting under siege 3 other cities.
Have a good day
Here is the code :
Spoiler :
Code:
/// Need some special rules for humans so that the AI isn't exploited
bool CvDiplomacyAI::IsWillingToMakePeaceWithHuman(PlayerTypes ePlayer)
{
CvPlayer& kHumanPlayer = GET_PLAYER(ePlayer);
if (kHumanPlayer.isHuman())
{
#if defined(MOD_CONFIG_GAME_IN_XML)
if(GetPlayerNumTurnsAtWar(ePlayer) < GD_INT_GET(WAR_MAJOR_MINIMUM_TURNS))
{
return false;
}
#else
bool bWillMakePeace = GetPlayerNumTurnsAtWar(ePlayer) >= 5;
#endif
//don't give up if we're about to score!
if (kHumanPlayer.HasCityAboutToBeConquered() && !m_pPlayer->HasCityAboutToBeConquered())
{
return false;
}
if(!GET_TEAM(m_pPlayer->getTeam()).canChangeWarPeace(kHumanPlayer.getTeam()))
{
return false;
}
// If either of us are locked in, then we're not willing to make peace (this prevents weird greetings and stuff) - we use > 1 because it'll get decremented after it appears the human make peace again
if(GET_TEAM(GetPlayer()->getTeam()).GetNumTurnsLockedIntoWar(kHumanPlayer.getTeam()) > 1)
return false;
if(GET_TEAM(kHumanPlayer.getTeam()).GetNumTurnsLockedIntoWar(GetPlayer()->getTeam()) > 1)
return false;
#if defined(MOD_DIPLOMACY_CIV4_FEATURES)
if (MOD_DIPLOMACY_CIV4_FEATURES)
{
// If either of us are locked in war because of a Vassal agreement, then we're not willing to make peace
if(GET_TEAM(GetPlayer()->getTeam()).IsVassalLockedIntoWar(kHumanPlayer.getTeam()) == true)
return false;
if(GET_TEAM(kHumanPlayer.getTeam()).IsVassalLockedIntoWar(GetPlayer()->getTeam()) == true)
return false;
TeamTypes eMasterTeam = GET_TEAM(m_pPlayer->getTeam()).GetMaster();
if(eMasterTeam != NO_TEAM)
{
if(GET_TEAM(eMasterTeam).isAtWar(GET_PLAYER(ePlayer).getTeam()))
{
return false;
}
}
//We don't want peace with vassals.
if(GET_TEAM(GET_PLAYER(ePlayer).getTeam()).IsVassalOfSomeone())
{
return false;
}
}
#endif
#if defined(MOD_BALANCE_CORE)
int iRequestPeaceTurnThreshold = /*4*/ GC.getREQUEST_PEACE_TURN_THRESHOLD();
int iWantPeace = 0;
CvCity* pLoopCity;
int iOurDanger = 0;
int iThierDanger = 0;
int iLoop;
for(pLoopCity = m_pPlayer->firstCity(&iLoop); pLoopCity != NULL; pLoopCity = m_pPlayer->nextCity(&iLoop))
{
if(pLoopCity == NULL)
continue;
if(pLoopCity->isUnderSiege())
{
iOurDanger++;
}
if(pLoopCity->isInDangerOfFalling())
{
iOurDanger++;
}
}
for(pLoopCity = GET_PLAYER(ePlayer).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER(ePlayer).nextCity(&iLoop))
{
if(pLoopCity == NULL)
continue;
if(pLoopCity->isUnderSiege())
{
iThierDanger++;
}
if(pLoopCity->isInDangerOfFalling())
{
iThierDanger++;
}
}
iWantPeace += iOurDanger;
iWantPeace += (iThierDanger * -1);
if(GetPlayerNumTurnsSinceCityCapture(ePlayer) > 1)
{
iWantPeace += (GetPlayerNumTurnsSinceCityCapture(ePlayer) / 4);
}
if(m_pPlayer->GetCulture()->GetWarWeariness() > 0 && m_pPlayer->IsEmpireUnhappy())
{
iWantPeace += (m_pPlayer->GetCulture()->GetWarWeariness() / 10);
}
if(GetWarProjection(ePlayer) >= WAR_PROJECTION_GOOD)
{
iWantPeace--;
}
else if(GetWarProjection(ePlayer) <= WAR_PROJECTION_UNKNOWN)
{
iWantPeace++;
}
if(GetWarState(ePlayer) <= WAR_STATE_STALEMATE)
{
iWantPeace++;
}
else if(GetWarState(ePlayer) >= WAR_STATE_CALM)
{
iWantPeace--;
}
iWantPeace += GetWantPeaceCounter(ePlayer);
if(iWantPeace > iRequestPeaceTurnThreshold)
{
return true;
}
else
{
return false;
}
#else
return bWillMakePeace;
#endif
}
return true;
}
Code:
/// Updates what the Goal of war is with all Players
void CvDiplomacyAI::DoUpdateWarGoals()
{
// Are we going for World conquest? If so, then we want to fight our wars to the death
bool bWorldConquest = false;
if(IsGoingForWorldConquest())
{
bWorldConquest = true;
}
int iWarGoalValue;
WarGoalTypes eWarGoal;
//PlayerTypes eLoopOtherPlayer;
//int iOtherPlayerLoop;
bool bHigherUpsWantWar;
bool bIsMinor;
WarProjectionTypes eProjection;
// Loop through all (known) Players
PlayerTypes eLoopPlayer;
for(int iPlayerLoop = 0; iPlayerLoop < MAX_CIV_PLAYERS; iPlayerLoop++)
{
eLoopPlayer = (PlayerTypes) iPlayerLoop;
if(IsPlayerValid(eLoopPlayer))
{
eWarGoal = NO_WAR_GOAL_TYPE;
if(GET_TEAM(GetTeam()).isAtWar(GET_PLAYER(eLoopPlayer).getTeam()))
{
bIsMinor = (GET_PLAYER(eLoopPlayer).isMinorCiv());
iWarGoalValue = 0;
bHigherUpsWantWar = false;
// Higher ups want war with this Minor Civ
if(bIsMinor)
bHigherUpsWantWar = GetMinorCivApproach(eLoopPlayer) == MINOR_CIV_APPROACH_CONQUEST;
// Higher ups want war with this Major Civ
else
bHigherUpsWantWar = GetMajorCivApproach(eLoopPlayer, /*bHideTrueFeelings*/ false) == MAJOR_CIV_APPROACH_WAR;
#if defined(MOD_DIPLOMACY_CIV4_FEATURES)
//Vassals will never want peace with a player if their master is at war with a player.
if(MOD_DIPLOMACY_CIV4_FEATURES)
{
if(GET_TEAM(m_pPlayer->getTeam()).IsVassalOfSomeone())
{
TeamTypes eMasterTeam = GET_TEAM(m_pPlayer->getTeam()).GetMaster();
if(eMasterTeam != NO_TEAM)
{
if(GET_TEAM(eMasterTeam).isAtWar(GET_PLAYER(eLoopPlayer).getTeam()))
{
bHigherUpsWantWar = true;
}
}
}
}
#endif
eProjection = GetWarProjection(eLoopPlayer);
//////////////////////////////
// Higher ups want war, figure out what kind we're waging
if(bHigherUpsWantWar)
{
// Minor Civs
if(bIsMinor)
// If we're going for the conquest victory, conquest is our goal with minors
if(bWorldConquest)
eWarGoal = WAR_GOAL_CONQUEST;
else
eWarGoal = WAR_GOAL_DAMAGE;
// Major Civs - depends on how things are going
else
{
// Default goal is Damage
eWarGoal = WAR_GOAL_DAMAGE;
// If we're locked into a coop war, we're out for conquest
if(IsLockedIntoCoopWar(eLoopPlayer))
eWarGoal = WAR_GOAL_CONQUEST;
// If we think the war will go well, we can aim for conquest, which means we will not make peace
#if defined(MOD_BALANCE_CORE)
if(eProjection > WAR_PROJECTION_UNKNOWN)
#else
if(eProjection >= WAR_PROJECTION_UNKNOWN)
#endif
{
// If they're unforgivable we're out to destroy them, no less
if(GetMajorCivOpinion(eLoopPlayer) == MAJOR_CIV_OPINION_UNFORGIVABLE)
eWarGoal = WAR_GOAL_CONQUEST;
// Out for world conquest?
else if(bWorldConquest)
eWarGoal = WAR_GOAL_CONQUEST;
}
#if defined(MOD_BALANCE_CORE)
// Let's consider peace if we've been fighting for a long time.
else if(GetPlayerNumTurnsAtWar(eLoopPlayer) > GD_INT_GET(WAR_MAJOR_MINIMUM_TURNS))
{
if( GET_TEAM(m_pPlayer->getTeam()).canChangeWarPeace(GET_PLAYER(eLoopPlayer).getTeam()))
{
if(GET_PLAYER(eLoopPlayer).isHuman())
{
bool bWillConsiderPeace = IsWillingToMakePeaceWithHuman(eLoopPlayer);
if(bWillConsiderPeace)
{
if(GetPlayer()->GetCulture()->GetWarWeariness() > 0 && GetPlayer()->IsEmpireUnhappy())
{
eWarGoal = WAR_GOAL_PEACE;
}
else if(GetDiploBalance() > 7)
{
eWarGoal = WAR_GOAL_PEACE;
}
else
{
//If we aren't winning at this point, let's end the fight.
int iWarScore = GetWarScore(eLoopPlayer);
if(iWarScore < 0)
{
eWarGoal = WAR_GOAL_PEACE;
}
}
}
}
else
{
bool bWillConsiderPeace = IsWantsPeaceWithPlayer(eLoopPlayer);
if(bWillConsiderPeace)
{
if(GetPlayer()->GetCulture()->GetWarWeariness() > 0 && GetPlayer()->IsEmpireUnhappy())
{
eWarGoal = WAR_GOAL_PEACE;
}
else if(GetDiploBalance() > 8)
{
eWarGoal = WAR_GOAL_PEACE;
}
else
{
//If we aren't winning at this point, let's end the fight.
int iWarScore = GetWarScore(eLoopPlayer);
if(iWarScore < 0)
{
eWarGoal = WAR_GOAL_PEACE;
}
}
}
}
}
}
#endif
}
}
//////////////////////////////
// Higher ups don't want to be at war, figure out how bad things are
else
{
// If we're about to cause some mayhem then hold off on the peace stuff for a bit - not against Minors though
if(!bIsMinor && GetStateAllWars() != STATE_ALL_WARS_LOSING)
{
//why make peace when we're winning?
if (GetWarState(eLoopPlayer) == WAR_STATE_NEARLY_WON)
eWarGoal = WAR_GOAL_CONQUEST;
#if defined(MOD_BALANCE_CORE)
else if(GetWarState(eLoopPlayer) <= WAR_STATE_DEFENSIVE)
eWarGoal = WAR_GOAL_PEACE;
#endif
else
eWarGoal = WAR_GOAL_DAMAGE;
}
// War isn't decisively in our favor, so we'll make peace if possible
else
{
eWarGoal = WAR_GOAL_PEACE;
}
}
}
// Getting ready to attack
else if(GetWarGoal(eLoopPlayer) == WAR_GOAL_PREPARE)
eWarGoal = WAR_GOAL_PREPARE;
// Getting ready to make a forceful demand
else if(GetWarGoal(eLoopPlayer) == WAR_GOAL_DEMAND)
eWarGoal = WAR_GOAL_DEMAND;
// Update the counter for how long we've wanted peace for (used to determine when to ask for peace)
if(eWarGoal == WAR_GOAL_PEACE)
ChangeWantPeaceCounter(eLoopPlayer, 1);
else
SetWantPeaceCounter(eLoopPlayer, 0);
// Set the War Goal
SetWarGoal(eLoopPlayer, eWarGoal);
}
}
}
Translation of the code into english :
In order to accept negociation, the AI start by doing the following simple tests :
- If the war began less than 5 turn ago, peace is forbidden so no negociations.
- If the peace is forbidden by something (agreement, vassal, ...), no negociations.
- If the AI is about to capture a city, no negociations.
Then, it will evaluate the war.
It will compute the value :
War_state + War_projection + City_danger + Others
and compare it to 4.
If the value is lesser or equal to 4, then no negotiations. If it is greater, the AI agree to negotiate.
- War_state = +1 or -1, depending of the short-term state of the war. If the AI is loosing the war, its value is +1, if the AI is wining the war (or neutral), its value is -1.
- War_projection = +1 or -1, depending of the long-term state of the war. If the AI think it will lose the war (or neutral), its value is +1, if the AI think it will win the war, its value is -1.
- City_danger = Number of AI cities under siege + Number of AI cities about to fall - Number of Human cities under siege - Number of Human cities about to fall.
- Others = T/4 + W/10 + WPC. Were T is the number of turns since the last city capture, W is the war weariness penalty if the AI's empire is unhappy, and WPC is the WantPeaceCounter, which is usually equal to 0.
What is the WantPeaceCounter ?
Each turn, the AI check each of its war, and either increase this counter by 1, either reset it to 0.
There is two situations :
Situation 1 : The AI want your head.
In this situation, the counter will most likely be irrelevant.
In order to increase the counter, the AI must not be in a coop war, it must also be loosing the war according to War_projection, be already willing to negociate (so passing all the tests, including having more than 4 points as described before), and either having war weariness problems, either being a peacefull AI, either having a negative war score.
In every other cases, the counter is reset to 0.
Situation 2 : The AI don't want your head.
The counter is increased if the War_state is bad for the AI, and reset to 0 when it is neutral or good.
Interpretation :
The AI will never peace out if it think it can take a city easily.
If no cities are about to fall or under siege, and the AI has no war weariness problems, then you have to wait up to 28 turns after a city capture to be able to negociate.
This value is reduced by 4 turns for each AI city under siege, and by 4 other turns for each AI city about to fall.
This value is reduced 8 turns if the AI is losing or neutral in a long term point of vue.
This value is reduced by 8 turns if the AI is losing in a short term point of vue.
Moreover, if the AI is losing in a short term point of vue, and do not hate you, this value is divided by 5 (i.e reduced by 4 additional turns each turns).
So you can technicaly peace out just after capturing a city. You just need to be wining on short term and long term, and puting under siege 3 other cities.
Have a good day
