[Into the code] Is the AI willing to negociate peace ?

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 :
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 :)
 
Thanks for the clarification, this explains quite a lot.
Still I'd prefer it if a rule was added that prevents T from resetting once the AI has lost a significant amount of cities (~5).
Granted it would still be a relatively bad deal to make peace just after losing a city but if the AI is to simulate humans it should at some point acknowledge that taking a bad deal is a better option than continuing to fight a war where they are losing a lot of territory.
 
I just had a game where I had a 100 warscore over Poland, but they wouldn't let it go. I was trying to figure out why they wouldn't give it up, maybe they thought they could get that their capital back, even though I pushed them back time and time again.
 
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.

Thanks for the very thorough explanation.

I just had a game where I was in a long, inconclusive war with the Inca, who were halfway around the world. They were ranked #1 in military, me #8. I had killed about 4 stray units, and lost none. No cities had been attacked. The Inca eventually asked for a white peace. I said No, and took their capital with my fleet in about 4 turns. Just before I took it, they were willing to only give me a white peace. I asked for peace immediately after taking it, since I could never have held it... and the Inca agreed!

My conclusion here is that their calculations placed no greater value on their capital than they would have on their smallest city.
 
Thanks for the clarification, this explains quite a lot.
Still I'd prefer it if a rule was added that prevents T from resetting once the AI has lost a significant amount of cities (~5).
Granted it would still be a relatively bad deal to make peace just after losing a city but if the AI is to simulate humans it should at some point acknowledge that taking a bad deal is a better option than continuing to fight a war where they are losing a lot of territory.

I have always had an issue with how the AI acts just after a city as been taken. A human player might cut their losses and agree to peace right away before more cities are lost.

The current setup often has the AI delaying peace until the human is almost ready to take an additional city, at that point the value of peace decreases for the attacking human. If they take another city the cycle starts again.
 
I have always had an issue with how the AI acts just after a city as been taken. A human player might cut their losses and agree to peace right away before more cities are lost.

The current setup often has the AI delaying peace until the human is almost ready to take an additional city, at that point the value of peace decreases for the attacking human. If they take another city the cycle starts again.
So don't take another city?
 
Exploitability aside, right now the problem (at least to me) is that making war is no fun at all. It happens so often that I make war, I crush them, destroy their army, their economy (warscore 100) and they still don't want to peace out.

I'll even bomb down one or two of their cities to nothing and have a cavalry within range to take them .... they won't peace out unless I fully surround that city with melee units.

Not only is it a dumb all-or-nothing wa to wage war, it's very counterintuitive.

I absolutely love Vox Populi: it finally made Civ V into something good for me. It made me want to play again. But everytime in the game I'm in a situation where I want to end a war, I find myself wanting to play less and less, because of the annoying mechanics.

I have come to the point where I avoid war at all costs and that can't be the solution. It's a pity this one little thing to me ruins what is otherwise simply the best mod in Civ V.
 
Exploitability aside, right now the problem (at least to me) is that making war is no fun at all. It happens so often that I make war, I crush them, destroy their army, their economy (warscore 100) and they still don't want to peace out.

I'll even bomb down one or two of their cities to nothing and have a cavalry within range to take them .... they won't peace out unless I fully surround that city with melee units.

Not only is it a dumb all-or-nothing wa to wage war, it's very counterintuitive.

I absolutely love Vox Populi: it finally made Civ V into something good for me. It made me want to play again. But everytime in the game I'm in a situation where I want to end a war, I find myself wanting to play less and less, because of the annoying mechanics.

I have come to the point where I avoid war at all costs and that can't be the solution. It's a pity this one little thing to me ruins what is otherwise simply the best mod in Civ V.

Have you tried brokering for peace? I've found that AIs will sometimes be willing to pay for me to stop, and when you are at 75 or higher warscore, the enemy AI doesn't get a say in the matter any more.
 
I am in an all game war into riflemen at the moment with 3 civs.

1. On border. Declared war on after a move your troops notice. Taken a major city from, haven't taken any more cities sitting in a defensive position killing units. around 40-50 war score, no peace. Took the major city around 200 turns ago.

2. On Border, have taken 2 capitals (they had taken someone else) and another 3-4 cities maybe. 100 war score. Not taking any more. No peace yet.

3. 1 Civ in between us on all sides, but sending units with open borders. Killing all their units like knife through butter. Very low war score, no peace in sight as I have to kill through another civ to be able to get to their cities.


Does it log the detail about why a Civ won't call peace? I could look in the logs and see why this is.

It isn't particularly interesting to be at war all game, even though I do have enough military to be absolutely fine from it. It just isn't textured... in the sense that there's nothing else in the game but war.
 
Into Modern era, after a long time of taking almost all their cities, and waiting so many turns after, they finally asked for peace. Just crazy long time, but oh well.
 
I may be a little off topic but what about the strange behavior of another Civ (usually one that is doing very well) asking for peace on behalf of a losing Civ?
The losing Civ is unwilling to neg peace (10 turns) when I tried but immediately that turn, another Civ offered me a sweet carrot (9GPT and 2 iron!) to sign a peace treaty (15 turns).
Why would bystander Civs make such a bad deal to begin with?
 
I may be a little off topic but what about the strange behavior of another Civ (usually one that is doing very well) asking for peace on behalf of a losing Civ?
The losing Civ is unwilling to neg peace (10 turns) when I tried but immediately that turn, another Civ offered me a sweet carrot (9GPT and 2 iron!) to sign a peace treaty (15 turns).
Why would bystander Civs make such a bad deal to begin with?

It does seem like kind of an odd mechanic but yeah, can't say no to the money, and it's a nice way of getting something more from your warscore since since oftentimes the civ you're at war with won't have the money to pay you properly.

Pity it only works if you have positive warscore, so you can't use it against the Civs on another continent who declare war and then refuse peace forever just to get on your nerves and mess up your city-state relations (I guess it does allow them to conquer your city-state allies with less penalty, not sure if the AI recognizes that though).
 
I may be a little off topic but what about the strange behavior of another Civ (usually one that is doing very well) asking for peace on behalf of a losing Civ?
The losing Civ is unwilling to neg peace (10 turns) when I tried but immediately that turn, another Civ offered me a sweet carrot (9GPT and 2 iron!) to sign a peace treaty (15 turns).
Why would bystander Civs make such a bad deal to begin with?

Because it's not a bad deal to them. You don't necessarily know what their long game is.
 
Because it's not a bad deal to them. You don't necessarily know what their long game is.

Well, it is possible that I may be ruining some form of trade agreements by conquering the cities with the resources being traded. The minds of the AIs are alien to me :lol:
 
Ten turns where your units aren't gaining EXP and where you're not conquering more cities are good turns if you're threatening to snowball. Ten turns can be the difference between having Knights instead of Horsemen, for instance, and that's potentially the difference between the game having 8 civs remaining instead of 7.
 
I think so too.
Even neighboring Shaka, Montezuma, and Gengis Khan (and Korea, who was first to declare war on me), I can manage to only have one war at a time :D
 
So I was at war with Venice and its Greek vassal. I'd liberated all the venetian puppeted city states, and rolled through most of Greece. Down to its last city and without any greek reinforcements available, Venice still refused to consider peace. I had four artillery units and an atom bomb waiting to obliterate Venice... Why didn't it surrender?

The war had been going on for much more than 10 turns, as Greece was immense and inbetween me and Venice, which, even though I played England, I couldn't take since it was built on a lake my navy had no access to.






On a side note, I kind of had a D-Day style invasion of Greece with naval shore bombardment and troop landings which felt really awesome

One of my city state allies had also expanded to include a Greek city weakened by my fleet, on top of another city founded by the Dutch whom I then vassalized. Interesting game.
 
Back
Top Bottom