AI Attitude Explained

ori

Repair Guy
Retired Moderator
Joined
Dec 17, 2005
Messages
16,561
Location
Baden-Württemberg, Germany
This is a parse of the way the Game determines an AIs attitude towards other players. The attitude is calculated as iAttitudeVal and is set to +100 for team members and -100 for Barbarians.

For all other cases the following 25 items are calculated and added to determine iAttitudeVal (see next post).

For this guide the following sources are used if no other source is given:
CvPlayerAI.cpp from the SDK (note: this is the Vanilla version - there is a 26th item for having a Vassal in Warlords which is visible).
CivIVLeaderHeadInfos.xml (a spreadsheet of this is available here.

In the posts below the following terms are used:

US for the current AI

THEM for the Player towards whom the iAttitudeVal is calculated

Rank as defined in CvGame.cpp is 0 for the highest scoring Civilization and (TotalNumberOfPlayers - 1) for the lowest scoring Civilization.

RankDifference = US Rank - THEM Rank
 
Code:
Item 1 (not visible)
US iBaseAttitude

Code:
Item 2 (not visible)
THEM iAttitudeChange

Code:
Item 3 (not visible)
If AggressiveAI option is ON AND THEM is Human:
-2

Code:
Item 4 (not visible)
If THEM is NOT Human:
+(4 – abs(US Peace Weight – THEM PeaceWeight))

Code:
Item 5 (not visible)
If THEM is NOT Human:
+ the lower of US iWarmongerRespect or THEM iWarmongerRespect

Code:
Item 6 (not visible)
- the higher of 0 or (THEM number of Team members – US number of Team members)

Code:
Item 7 (not visible)
if THEM is higher ranking:
+(RankDifference*iWorseRankDifferenceAttitudeChange/(NumberOfPlayersEverAlive+1))

Code:
Item 8 (not visible)
if THEM is lower ranking:
+((-RankDifference)*iBetterRankDifferenceAttitudeChange/(NumberOfPlayersEverAlive+1))

Code:
Item 9 (not visible)
if US rank >= NumberOfPlayersEverAlive/2 AND THEM rank >= NumberOfPlayersEverAlive/2
+1

Code:
Item 10 (not visible)
if THEM WarSuccess > US WarSuccess:
+iLostWarAttitudeChange

Code:
Item 11 (visible)
CloseBordersAttitude

Code:
Item 12 (visible)
WarAttitude

Code:
Item 13 (visible)
PeaceAttitude

Code:
Item 14 (visible)
SameReligionAttitude

Code:
Item 15 (visible)
DifferentReligionAttitude

Code:
Item 16 (visible)
BonusTradeAttitude

Code:
Item 17 (visible)
OpenBordersAttitude

Code:
Item 18 (visible)
DefensivePactAttitude

Code:
Item 19 (visible)
RivalDefensivePactAttitude

Code:
Item 20 (visible)
ShareWarAttitude

Code:
Item 21 (visible)
FavoriteCivicAttitude

Code:
Item 22 (visible)
TradeAttitude

Code:
Item 23 (visible)
RivalTradeAttitude

Code:
Item 24 (visible)
MemoryAttitude

Code:
Item 25 (visible)
AttitudeExtra

All Items are added and the total Attitude is returned as iAttitudeVal and used for subsequent decisions.
 
The following attitudes are set for the calculated Attitude Values from above:

Code:
Friendly:
iAttitudeVal >= +10

Pleased:
iAttitudeVal >= +3

Cautious:
if no other Attitude rule is fulfilled

Annoyed:
iAttitudeVal <= -3

Furious:
iAttitudeVal <= -10
 
Notes:

Item 2:
source: CIV4HandicapInfo.xml = +2 on Settler, +1 on Warlord, 0 on Chieftain, -1 on Noble and above​

Item 4:
abs means that the result of (US Peace Weight &#8211; THEM PeaceWeight) is always a positive value
PeaceWeight = iBasePeaceWeight + (0 to iPeaceWeightRand) as shown by Seven05 - This is the only case were a Random Number is used directly to determine an Attitude Value.

Item 10:
WarSuccess seems to be the number of Units killed (source: CvUnit.cpp)​

Item 25:
This is reserved for scenarios or mods which want to control relations between certain civilizations​

Diplomacy vote (Diplomatic Victory):
An AI will always vote itself. If this is not a choice it will vote for a team member. If this is not a choice it will vote for the Player towards whom the iAttitudeVal is highest if iAttitudeVal is greater than +7. If both players are tied it will abstain. If both players are at or below iAttitudeVal of +7 it will abstain.​

Worst Enemy:
An AIs has a worst enemy if there is atleast one other Player towards whom its attitude is worse than Cautious. The worst enemy is defined as the one with the lowest iAttitudeVal (source: CvTeamAI.cpp).​
 
A note on rank (items 7-9):
Lower rank means higher score. The best in score is rank 0.
So item 7 means (IWorseRankDifference is <=0 in the xml): not liking people scoring higher.
Item 8 (iRankDifference is<0): liking people scoring lower.
Item 9: the underdogs give each other a +1.
 
A note on rank (items 7-9):
Lower rank means higher score. The best in score is rank 0.
So item 7 means (IWorseRankDifference is <=0 in the xml): not liking people scoring higher.
Item 8 (iRankDifference is<0): liking people scoring lower.
Item 9: the underdogs give each other a +1.

This was confusing me, actually - since if you look at the way this works - if you trade a lower scoring civ techs so that it moves to a score above yours they actually like you less. This means that a low rank number is indeed linked to a low score and that the iBetterRankDifference is applied if you score higher than the AI (see also Iustus' post for the BetterAI mod).

The CvGame.cpp defines rank like this:

Code:
for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
    {
        iBestScore = MIN_INT;
        eBestPlayer = NO_PLAYER;

        for (iJ = 0; iJ < MAX_CIV_PLAYERS; iJ++)
        {
            if (!abPlayerScored[iJ])
            {
                iScore = GET_PLAYER((PlayerTypes)iJ).calculateScore(false);

                if (iScore >= iBestScore)
                {
                    iBestScore = iScore;
                    eBestPlayer = (PlayerTypes)iJ;
                }
            }
        }

        abPlayerScored[eBestPlayer] = true;

        setRankPlayer(iI, eBestPlayer);
        setPlayerRank(eBestPlayer, iI);

if I understand this correctly (and this is in line with the above observation) - then the game sets rank 0 for the lowest score and then looks for higher scoring players and sets them at 1, 2 etc. so that the highest scoring player has the highest iPlayerRank.

They definitely like a high scoring Player better than a low scoring one (which encourages them to bully the weaker players).
 
Well, I looked up the rank calculation you quoted before I posted :).

The inner loop gets the highest score not already scored. So for the outer loop (ii) 0, it's the highest score overall.

Edit:
I looked up the Iustus post. It's unlikely that this could come from better-worse rank, as the ranks are pretty similar (and it needs a lot difference for Saladin to even give a 1 change). But what could have happened is that Saladin fell out of the group of underdogs by passing somebody not even known to any of the two.
 
Well, I looked up the rank calculation you quoted before I posted :).

The inner loop gets the highest score not already scored. So for the outer loop (ii) 0, it's the highest score overall.

Edit:
I looked up the Iustus post. It's unlikely that this could come from better-worse rank, as the ranks are pretty similar (and it needs a lot difference for Saladin to even give a 1 change). But what could have happened is that Saladin fell out of the group of underdogs by passing somebody not even known to any of the two.

:confused: I am still confused - but you sure seem to be right, I just did a quick test on an old save and gave the underdog a couple hundred more population points in Worldbuilder so that he went to No.1 and sure enough he went from pleased to friendly... So it basically means that:

iBetterRankDifference is applied when the AI scores better than the other player.
iWorseRankDifference is applied when the AI scores worse than the other player.
 
Now all we need is someone to put together a UI mod that performs all these calculations for you and displays the results in the foreign advisor screen.

1....2....3.....Not It!
 
Ori, do you know how rounding of numbers work?

Thanks,

TDK

Referring to items 7 and 8 (worse or betterrank calculations):

I am not even sure if the game rounds those values at this point. But if it uses integers I would expect it to do the mathematically correct thing and round up at .5 and down below this.
 
Code:
Item 6 (not visible)
- the higher of 0 or (THEM number of Team members &#8211; US number of Team members)
Code:
Item 23 (visible) RivalTradeAttitude
What are "Team members" anyway?
And what sort of text do we see when there's a RivalTradeAttitude value on the screen?
 
What are "Team members" anyway?

In single player games: either team members you have specified in custom game (by choosing the same team number) or Permanent Alliance partners. In Multiplayer Games usually team members assigned at the start...

And what sort of text do we see when there's a RivalTradeAttitude value on the screen?

"You have traded with our worst enemy"
 
You may, or may not, want to note that the attitude value used in trading is Team to Team attitude, not player to player attitude. (This may be true in other circumstances as well - I've not investigated thoroughly).

This got touched on a bit in another thread
 
Now all we need is someone to put together a UI mod that performs all these calculations for you and displays the results in the foreign advisor screen.

1....2....3.....Not It!
I did. Although I left out Items 4 & 5, since I disabled those. With Better AI the AI doesn't need those bonuses anymore. And Item 3 since the Better AI team disabled that one.

I am not even sure if the game rounds those values at this point. But if it uses integers I would expect it to do the mathematically correct thing and round up at .5 and down below this.
Suprisingly not. C++ like most programming languages rounds integer calculations down. That means that values of -1 or 1 for iWorseRankDifferenceAttitudeChange and iBetterRankDifferenceAttitudeChange are completely meaningless.

Consider iBetterRankDifferenceAttitudeChange in a game with 10 civs. The biggest rank difference is 9. iBetterRankDifferenceAttitudeChange then gets multiplied by 9 divided by 11, 11 being the civs ever alive plus 1. Obviously resulting in a number between 0 and 1 and thus 0.

The same goes for iWorseRankDifferenceAttitudeChange since negative numbers get rounded up. Or better: the remainder is discarded.

I'm sure this is unintended and as such a bug. Hardly a gamebreaking one though.



In this game I'm the number one and Alex is 7. A rankdifference of 6 which is the threshold for an iWorseRankDifferenceAttitudeChange guy of -2 like Alex and indeed he shows a "We think you are getting too big for your own good.", which is the translation I made for Item 7.



Wang Kon however who has an iWorseRankDifferenceAttitudeChange of -1 apparently doesn't mind my rank while being the lowest in score with the exception of dead Ramesses.

 
Suprisingly not. C++ like most programming languages rounds integer calculations down. That means that values of -1 or 1 for iWorseRankDifferenceAttitudeChange and iBetterRankDifferenceAttitudeChange are completely meaningless.

:crazyeye: Thanks, good to know that a lot of these values are essentially meaningless - but then one could mod this by simply increasing all those values by 1...

You may, or may not, want to note that the attitude value used in trading is Team to Team attitude, not player to player attitude. (This may be true in other circumstances as well - I've not investigated thoroughly).

This got touched on a bit in another thread

Yes, I noticed this in your thread, but since this here was about how the AI calculates its Attitude and not what it actually does with it ;) I didn't bother to include it here. But now that I am at it I can as well start :) (this is from a quick search through the SDK - so there might and probably will be mistakes and things overlooked)

There are only four instances were the AI uses the Attitude Value (i.e. the integer value):
Diplomacy Vote
Determine Worst Enemy
Determine which city to nuke
Become Vassal while at Peace

For all other instances either PlayerAttitude or TeamAttitude (i.e. Friendly, Pleased etc.) are used. PlayerAttitude is the attitude of on AI player towards another player, TeamAttitude is the attitude of one AITeam towards another Team.

Spoiler TeamAttitude explained by VoiceOfUnreason :

A close reading of my first post would catch that the function involved in trading is a team function (CvTeamAI) rather than a player function (CvPlayerAI). Therefore, the attitude referenced in redding out the techs is not your trading partner's attitude toward you (which is what is displayed on the trade screen), but instead your trading partner's team's attitude toward your team.

For these purposes, her team is her and all of her permanent allies. Your team is you, your permanent allies, and your vassals.

Furthermore, the value that is used is the average attitude of these relationships. Note that attitude means Friendly, Pleased, etc. not +10 or +20 or whatever the net of the plusses and minuses is.

And as usual, the averaging is done with integer division, which rounds down on any excuse to do so. Thus, for her team to have a friendly attitude toward yours, it is necessary that every permanent ally on that team have a friendly attitude toward all of your allies and your vassals.

From what I can tell, the attitude of her vassals doesn't come into play at all. I didn't have enough time this morning to establish whether her attitude toward your ally's vassal matters at all.

When I've had a chance to satisfy myself that I have the details of this undertood, I'll update the first post so that the close reading I mentioned earlier is no longer essential.

Edit: to clarify, vassals aren't essential. You could run into the same problem with no vassals if the ally of your trade partner didn't share her high opinion of you.


The instances in which PlayerAttitude are used are:

Civic Trade - ask an AI to change Civic(s)

Religion Trade - ask an AI to convert Religion

Trade City - ask an AI to trade a city (Note: that does not mean it will trade it, it just is not readened out ;) )

Give Help - ask an AI to give help

Demand Tribute - AI demands tribute

UseSpy - all Spy actions against a player


UseNuke - the AI decides which city to Nuke depending on attitude :crazyeye:

The Instances in which TeamAttitude are used are:


Stop Trading - trade stop trading

IsFriend - for you Declared War on a friend memory and for you nuked a friend memory

StartWar - for decision to start a war

Tech Trade - for tech trading decisions

Map Trade - for map trading

Trade Peace - (broker Peace between 2 AIs)
Trade War - (broker War between 2 AIs)
Open Borders - explains itself ;)

Defensive Pact - dito

Permanent Alliance - dito

Worst Enemy - who is my worst enemy?

NoWarAtttude - (NoWar threshold)
DiploVote - which team to vote for?

Vassal - (Peace)
 
Some of these reasons I've never even seen before in my games. How big do you have to be before you get "we are worried that you are becoming too big"? I tried continuing the game after domination victory, and I still don't get that modifier.
 
Top Bottom