My personal thread: Clarification of certain game mechanics

This trick/cheat/whatever you call it is best on quick speed and negligible on marathon.
The trick/bug/cheat where culture is put in to hammers on culture border pop is indeed negligible, but the trick/bug/cheat which I am mentioning can be exploited heavily - each and every turn hammers can be put in to production and in money/beakers.
 
Oh, that a good recalling of CivIII building wealth in all cities while building normal stuff.

Yeah, keep it to yourself, that's better.
 
SYNOPSIS​

"We demand emancipation!" is the raging shrieks of the population for being under a Labor class civic that they deem unjust, oppressing or simply backward.
It increases the unhappiness level by several unhappiness points according to the following paramaters (ordered from the most direct to the most generalized one):
  1. A base number: I compared Warlords and BTS; I saw no difference in coding. Some people ranted BTS increased emancipation unhappiness along BTS, but that seems to be an unfounded rant. I don't know if Vanilla version have publicized the code...
  2. Number of AI's still alive : indeed more AI's mean smaller incrementation of unhappiness per AI; more AI does not eqal to higher over unhappiness.
  3. Number of cities per AI under Emancipation: that is some kind of weigh that small nations have less impact than large scaled empires.
  4. Population in human player cities: Bigger populations mean more rabbid citizens overall.

MATHEMATICAL APPROACH​

Consider a base number called iCivicPercentAnger=400.
That is defined in CIV4CivicInfos.xml.

In CvPlayer, we find the function that increases the percentage of unhappiness according to number of AI's under Emancipation over all possible AI's STILL ALIVE and that is weighted with their city counts.

%CivicAnger = 400*(Number of cities under Emancipation)/(Total Number of Cities in the world)

"Number of cities under Emancipation" is simply each AI under Emancipation and their weigh is their city counts.
"Total Number of Cities in the world" seems a pretty special parameter because it doesn't exclude barbarian cities in the count. Count them all if possible. And yes, that is possible to see barbarian cities during renaissance, especially if you play a Terra mapscript.

Now, to get the exact integer of unhappiness: Let it be named iUnhappiness.

iUnhappiness = [(%CivicAnger * (CityPopulation + Extra) )/ PERCENT_ANGER_DIVISOR]

CityPopulation is a common factor that affects many types of anger like motherland unhappiness, No military police anger, etc. That is why I consider that factor not proper to Emancipation, but a global factor in unhappiness.
PERCENT_ANGER_DIVISOR is some sort of constant defined in GlobalDefines.XML. Do not see beyond the fact it is worth 1000. That's it. :dunno:
Extra: I still need to define what it is. It can be some sort of additional parameter left for modders.
EDIT: Ok, I think I got the idea of what is that Extra parameter while browsing the code again. It seems to have to do with stacked unhappiness like from conscription, whipping, defying resolutions and stacking unhappy citizens.
Given the generality of that second formula for diverse forms of unhappiness, there is no extra for emancipation unhappiness.



SOURCE CODE​

Spoiler :

In CvPlayer.cpp
Code:
int CvPlayer::getCivicPercentAnger(CivicTypes eCivic, bool bIgnore) const
{
	int iCount;
	int iPossibleCount;
	int iI;

	if (GC.getCivicInfo(eCivic).getCivicPercentAnger() == 0)
	{
		return 0;
	}

	if (!bIgnore && (getCivics((CivicOptionTypes)(GC.getCivicInfo(eCivic).getCivicOptionType())) == eCivic))
	{
		return 0;
	}

	iCount = 0;
	iPossibleCount = 0;

	for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
	{
		if (GET_PLAYER((PlayerTypes)iI).isAlive())
		{
			if (GET_PLAYER((PlayerTypes)iI).getTeam() != getTeam())
			{
				if (GET_PLAYER((PlayerTypes)iI).getCivics((CivicOptionTypes)(GC.getCivicInfo(eCivic).getCivicOptionType())) == eCivic)
				{
					iCount += GET_PLAYER((PlayerTypes)iI).getNumCities();
				}

				iPossibleCount += GET_PLAYER((PlayerTypes)iI).getNumCities();
			}
		}
	}

	if (iPossibleCount == 0)
	{
		return 0;
	}

	return ((GC.getCivicInfo(eCivic).getCivicPercentAnger() * iCount) / iPossibleCount);
}
In CvCity.cpp
Code:
int CvCity::unhappyLevel(int iExtra) const
{
	int iAngerPercent;
	int iUnhappiness;
	int iI;

	iUnhappiness = 0;

	if (!isNoUnhappiness())
	{
		iAngerPercent = 0;

		for (iI = 0; iI < GC.getNumCivicInfos(); iI++)
		{
			iAngerPercent += GET_PLAYER(getOwnerINLINE()).getCivicPercentAnger((CivicTypes)iI);
		}

		iUnhappiness = ((iAngerPercent * (getPopulation() + iExtra)) / GC.getPERCENT_ANGER_DIVISOR());

		iUnhappiness -= std::min(0, getLargestCityHappiness());
		iUnhappiness -= std::min(0, getMilitaryHappiness());
		iUnhappiness -= std::min(0, getCurrentStateReligionHappiness());
		iUnhappiness -= std::min(0, getBuildingBadHappiness());
		iUnhappiness -= std::min(0, getExtraBuildingBadHappiness());
		iUnhappiness -= std::min(0, getFeatureBadHappiness());
		iUnhappiness -= std::min(0, getBonusBadHappiness());
		iUnhappiness -= std::min(0, getReligionBadHappiness());
		iUnhappiness -= std::min(0, getCommerceHappiness());
		iUnhappiness -= std::min(0, area()->getBuildingHappiness(getOwnerINLINE()));
		iUnhappiness -= std::min(0, GET_PLAYER(getOwnerINLINE()).getBuildingHappiness());
		iUnhappiness -= std::min(0, (getExtraHappiness() + GET_PLAYER(getOwnerINLINE()).getExtraHappiness()));
		iUnhappiness -= std::min(0, GC.getHandicapInfo(getHandicapType()).getHappyBonus());
		iUnhappiness += std::max(0, getVassalUnhappiness());
		iUnhappiness += std::max(0, getEspionageHappinessCounter());
	}

	return std::max(0, iUnhappiness);
}
In globalDefines.xml
Code:
<Define>
		<DefineName>PERCENT_ANGER_DIVISOR</DefineName>
		<iDefineIntVal>1000</iDefineIntVal>
	</Define>
In CIV4CivicInfos.xml
Code:
<CivicInfo>
			<CivicOptionType>CIVICOPTION_LABOR</CivicOptionType>
			<Type>CIVIC_EMANCIPATION</Type>
			<Description>TXT_KEY_CIVIC_EMANCIPATION</Description>
			<Civilopedia>TXT_KEY_CIVIC_EMANCIPATION_PEDIA</Civilopedia>
			<Strategy>TXT_KEY_CIVIC_EMANCIPATION_STRATEGY</Strategy>
			<Button>,Art/Interface/Buttons/Civics/Emancipation.dds,Art/Interface/Buttons/Civics_Civilizations_Religions_Atlas.dds,6,1</Button>
			<TechPrereq>TECH_DEMOCRACY</TechPrereq>
			<iAnarchyLength>1</iAnarchyLength>
			<Upkeep>UPKEEP_LOW</Upkeep>
			<iAIWeight>0</iAIWeight>
			<iGreatPeopleRateModifier>0</iGreatPeopleRateModifier>
			<iStateReligionGreatPeopleRateModifier>0</iStateReligionGreatPeopleRateModifier>
			<iDistanceMaintenanceModifier>0</iDistanceMaintenanceModifier>
			<iNumCitiesMaintenanceModifier>0</iNumCitiesMaintenanceModifier>
			<iExtraHealth>0</iExtraHealth>
			<iFreeExperience>0</iFreeExperience>
			<iWorkerSpeedModifier>0</iWorkerSpeedModifier>
			<iImprovementUpgradeRateModifier>100</iImprovementUpgradeRateModifier>
			<iMilitaryProductionModifier>0</iMilitaryProductionModifier>
			<iBaseFreeUnits>0</iBaseFreeUnits>
			<iBaseFreeMilitaryUnits>0</iBaseFreeMilitaryUnits>
			<iFreeUnitsPopulationPercent>0</iFreeUnitsPopulationPercent>
			<iFreeMilitaryUnitsPopulationPercent>0</iFreeMilitaryUnitsPopulationPercent>
			<iGoldPerUnit>0</iGoldPerUnit>
			<iGoldPerMilitaryUnit>0</iGoldPerMilitaryUnit>
			<iHappyPerMilitaryUnit>0</iHappyPerMilitaryUnit>
			<bMilitaryFoodProduction>0</bMilitaryFoodProduction>
			<iMaxConscript>0</iMaxConscript>
			<bNoUnhealthyPopulation>0</bNoUnhealthyPopulation>
			<bBuildingOnlyHealthy>0</bBuildingOnlyHealthy>
			<iLargestCityHappiness>0</iLargestCityHappiness>
			<iWarWearinessModifier>0</iWarWearinessModifier>
			<iFreeSpecialist>0</iFreeSpecialist>
			<iTradeRoutes>0</iTradeRoutes>
			<bNoForeignTrade>0</bNoForeignTrade>
			<iCivicPercentAnger>400</iCivicPercentAnger>
			<bStateReligion>0</bStateReligion>
			<bNoNonStateReligionSpread>0</bNoNonStateReligionSpread>
			<iStateReligionHappiness>0</iStateReligionHappiness>
			<iNonStateReligionHappiness>0</iNonStateReligionHappiness>
			<iStateReligionUnitProductionModifier>0</iStateReligionUnitProductionModifier>
			<iStateReligionBuildingProductionModifier>0</iStateReligionBuildingProductionModifier>
			<iStateReligionFreeExperience>0</iStateReligionFreeExperience>
			<YieldModifiers/>
			<CapitalYieldModifiers/>
			<TradeYieldModifiers/>
			<CommerceModifiers/>
			<CapitalCommerceModifiers/>
			<SpecialistExtraCommerces/>
			<Hurrys/>
			<SpecialBuildingNotRequireds/>
			<SpecialistValids/>
			<BuildingHappinessChanges/>
			<FeatureHappinessChanges/>
			<ImprovementYieldChanges/>
			<WeLoveTheKing/>
		</CivicInfo>
 
Finally, I got the mother lode. I finally resolved that matter by myself. :)

SYNOPSIS

As many people already deduced well, here are the factors that goad some AI's to be generous:

  1. Every AI out of 52 has an attitude theshold. That is :<NoGiveHelpAttitudeThreshold>ATTITUDE_CAUTIOUS</NoGiveHelpAttitudeThreshold> . According to the code, the AI has to be PLEASED (or >CAUTIOUS) to be in the mood for generosity.
  2. Position in the scoreboard is indeed again an indicator. Your position (or team position) has to be a rank lower than the half alive civs number. It has nothing to do with being the dead last!
  3. The contact for the gift is indeed randomized and is leader dependant: CONTACT_GIVE_HELP is the magical number that rules the contact for freebee. For instance, if CONTACT_GIVE_HELP=50 and the RNG gives 0 (out of 0 to 49 of values), the contact is made. Indeed, bigger is CONTACT_GIVE_HELP, less frequent are the contacts for gifts. Most are either 50 to 100. Some are at 250, 500 and 1000. BUT there is one noticeable unfriendly one with CONTACT_GIVE_HELP=10000. GUESS WHO?
  4. What kind of tech can we get for free? Sadly, that is completely randomized. No prediction can be done. Can we get any techs from what the donor got? Nope. That is because a check is done before the tech roulette: it checks if that tech is tradable and checks possible denials (e.g. WDWTSTA, WFYABTA, We have our reasons, etc.). Don't expect super nice gifts that outrage AI reasoning in refusing such techs in normal trading!
  5. Did you know there was an equivalent for resources?!

URBAN LEGENDS TO SHOOT DOWN

  • Being the last dead person is not a necessary condition.
  • Differences in number of techs between you and AI has nothing to do with it. So beelining or not doesn't change directly the odd of freebee techs. What makes more common is the fact of beelining makes the player to ignore some filler techs.
  • Receiving a gift is not without consequences. Yes, you don't get any Worst Enemy negmods, but you get one more tech in the count of WFYABTA. Think twice accepting the poison gift like Archery that may forbid you later to tech trade fission!


SOURCE CODE

Spoiler :


In CvPlayerAI.cpp:
Code:
if (GET_PLAYER((PlayerTypes)iI).getTeam() != getTeam() && GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).isVassal(getTeam()))
							{
								iBestValue = 0;
								eBestGiveTech = NO_TECH;

								for (iJ = 0; iJ < GC.getNumTechInfos(); iJ++)
								{
									if (GET_TEAM(getTeam()).AI_techTrade((TechTypes)iJ, GET_PLAYER((PlayerTypes)iI).getTeam()) == NO_DENIAL)
									{
										setTradeItem(&item, TRADE_TECHNOLOGIES, iJ);

										if (canTradeItem(((PlayerTypes)iI), item, true))
										{
											iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "AI Vassal Tech gift"));

											if (iValue > iBestValue)
											{
												iBestValue = iValue;
												eBestGiveTech = ((TechTypes)iJ);
											}
										}
									}
								}
In CvPlayer.cpp:
Code:
bool CvPlayer::canTradeItem(PlayerTypes eWhoTo, TradeData item, bool bTestDenial) const
{
	CvCity *pOurCapitalCity;

	if (bTestDenial)
	{
		if (getTradeDenial(eWhoTo, item) != NO_DENIAL)
		{
			return false;
		}
	}

CIV4LeaderHeadInfos.xml:
Code:
<ContactType>CONTACT_GIVE_HELP</ContactType>

CIV4LeaderHeadInfos.xml -> Toku	:				<iContactRand>10000</iContactRand>
Code:
<NoGiveHelpAttitudeThreshold>ATTITUDE_CAUTIOUS</NoGiveHelpAttitudeThreshold>

In CvTeam.cpp :
Code:
int CvTeam::getAssets() const
{
	int iCount;
	int iI;

	iCount = 0;

	for (iI = 0; iI < MAX_PLAYERS; iI++)
	{
		if (GET_PLAYER((PlayerTypes)iI).isAlive())
		{
			if (GET_PLAYER((PlayerTypes)iI).getTeam() == getID())
			{
				iCount += GET_PLAYER((PlayerTypes)iI).getAssets();
			}
		}
	}

	return iCount;
}
 
Tachy,

Please avoid using the Lime (Lime) font, because it has poor contrast on both normal background and QUOTE/SPOILER background. As a result of poor contrast, it is almost as hard to read as the Yellow font.

Sun Tzu Wu
 
I have a question about a game mechanic, that I hope is ok to ask here. I found this in SGOTM 11 Plastic Ducks' thread regarding peace vassaling Saladin on another continent:
5) Master's power should be enough: about 1.5 x Vassal's power if Master is a land target; 3 x Vassal's power if not. (Unfulfilled. We are not Saladin's land target.)

Why we are not Saladin's land target? Because we don't have 3 cities on his continent. (Another condition to be a land target is to have 8 adjacent tiles on the border, which we do have) So building another city would make the vassaling happen. Of course, it's the best way to win the game at the moment.

In a recent Noble's Club on an Archipelago map, I capitulated an AI after kicking it off my mainland via war. It immediately capitulated along with its colony. But by kicking it off the large land mass we shared together, didn't I fail the 'land target' requirement? My power rating was only twice the AI's.

So, will the mechanics I quoted from that SGOTM not apply during war capitulations? And also, will an AI capitulate to a Civ across the oceans if it meets the power requirements even if neither Civ has Astronomy? I had a situation where I was beating up a Civ on Hemispheres with Shaka on the other continent, no one had Astro and I was really worried about my target throwing himself at Shaka to save itself. Was that fear justified?

Thanks for your time and really love the info you are gathering here, Tachywaxon! :)
 
So, will the mechanics I quoted from that SGOTM not apply during war capitulations? And also, will an AI capitulate to a Civ across the oceans if it meets the power requirements even if neither Civ has Astronomy?

http://forums.civfanatics.com/showthread.php?p=10739358#post10739358
A pretty thorough coverage of the code dealing with AI surrender trades.

War capitulations have different standards than peacevassaling. What really matters is war success and relative power (plus you must reduce them to <50% of your pop or land).
 
@ Coanda

Thanks a lot for that link. That's a lot of excellent info and answers a lot of things I wondered about the mechanic.

What about war capitulations? Are they weighted in anyway towards AIs being more willing to cap to other AIs vs. the player like tech-trades? For instance, AIs always seem to have an easier time capitulating some one like Sitting Bull as opposed to me. I always seem to need to burn half his empire to ashes first. On the other hand, I actually saw Brennus cap SB at tech parity after just taking one city. Mao capped to Frederick in a recent game with neither side even inflicting casualties. (I was between the two AIs and didn't see troops move through my borders.)
 
No problem about asking in-game mechanics here. It's all about it.

SB has an increased resilience against losses and thus capitulate harder.
I don't think it's weighted towards the AI. It's weighted towards who has done the most damages in a dogpiling war.
 
You also need to remember that Capping IS RNG based. You can have a everything in a war, killed their stack, took 6 cites, and if the AI rolls a lets cap to the AI who hasn't done anything, or even moved units roll they will give in to them, and not you.
 
Dear Tachywaxon,

I have a vague question with limited practical application for a real game. So I thought you might be able to answer :D

How does the AI determine the limit at which to accede to a request ("Could you spare X for a friend?"), and does this differ from the formula used to determine the point at which it should give in to a demand?

My gut feeling is that certain demands succeed where a polite request will fail, at least when you have become powerful enough. For example, it often seems very difficult to successfully request a mid-/late-game technology from an ally, whereas it is entirely possible to bully one of your vassals into giving the same technology away.

In a similar vein, does the AI alter it's opinion regarding the generosity of a gift as the game progresses? 30 gold in 2000 BC is much more valuable than 30 gold in 2000 AD. But it often seems that you can beg Meditation in 2000 BC, whereas you have no chance of getting (e.g.) Medicine in 2000 AD.

Many thanks for indulging me.
 
Phew, I feared it was some hard question I can't take.
Right now, I'm working vassal refusal to give in resources after the first demand. Sure is hard to find the exact mechanics. Found the interface button mechanics for instance but can't actually see what pushes the AI to cancel the vassal deal.

Let me see for that thing.
I'm leaning towards CvPlayerAI::AI_considerDeal() thingy.
 
In fact, I'm a bit tight of time now. I'll use instead the POWAAA of bookmarking: This!

I'll return of that subject if something wasn't answered.
 
Right now, I'm working vassal refusal to give in resources after the first demand. Sure is hard to find the exact mechanics. Found the interface button mechanics for instance but can't actually see what pushes the AI to cancel the vassal deal.

Let me see for that thing.
I'm leaning towards CvPlayerAI::AI_considerDeal() thingy.

Oh my! I can't believe I did not see that. :eek:
Yay! :rotfl::w00t::bounce:
I got the answer right under my nose and I didn't see that.

Interesting how it is tied to Doshin's question.
Ah, the satisfaction of another mystery solved.
 
The link Tachywaxon provided answers both your questions. It is also the source I will use to answer your questions. EDIT: I believe there may be another article that better explains this topic, but I'm pressed for time to look for it right now. I realize now that I'm using additional info from that article to answer your questions.

How does the AI determine the limit at which to accede to a request ("Could you spare X for a friend?"), and does this differ from the formula used to determine the point at which it should give in to a demand?

My gut feeling is that certain demands succeed where a polite request will fail, at least when you have become powerful enough. For example, it often seems very difficult to successfully request a mid-/late-game technology from an ally, whereas it is entirely possible to bully one of your vassals into giving the same technology away.

It doesn't matter whether the player begs (target AI is Pleased or higher) or demands (target AI is Cautious or lower) something from an AI regarding success of the beg/demand. On the other hand, the Demand will suffer a Diplomacy hit whereas the Beg never does, thus it is better to beg if one cares about diplomacy.

In a similar vein, does the AI alter it's opinion regarding the generosity of a gift as the game progresses? 30 gold in 2000 BC is much more valuable than 30 gold in 2000 AD. But it often seems that you can beg Meditation in 2000 BC, whereas you have no chance of getting (e.g.) Medicine in 2000 AD.

The maximum size of a successful beg/demand is bounded by a linear function which is a limit on the sum of all begs/demands made. The referenced article describes this function better than I can. If no begs/demands have been made versus a particular AI, that AI will accommodate a significantly larger beg/demand than an AI that has agreed to one or more begs/demands already. The size of technologies increases faster than a linear function, so only small technologies in early Eras and obsolete technologies in later Eras can ever be successfully begged/demanded. In practice, it is much easier to beg/demand a linearly increasing amount of Wealth than a Technology or a Technology that has been nearly completely researched. I have done both quite successfully in my games.

Sun Tzu Wu
 
Oedali's article was the strongest to my knowledge. Anyways, I have the code on access if I want see it on a deeper perspective.
 
Oedali's article was the strongest to my knowledge. Anyways, I have the code on access if I want see it on a deeper perspective.

I agree. I had to reread his article in full to convince myself. Only another code perusal may shed more light on this topic.

Sun Tzu Wu
 
Thanks both. I'm a little pushed for time now, but a brief skim read has already taught me something (no distinction exists between Pleased or Friendly attitudes in terms of beg success).
 
In XML serie of <tag>values</tag> (CIV4LeaderHeadInfos.xml), there is indeed a location for how many techs trigger a particular attitude modifier called TXT_KEY_MEMORY_TRADED_TECH_TO_US ("You have shared your technological discoveries with us.").

In Civ4 game, there are two types of attitude: those who are eternal and those affected by some decay process.
The second category has two values: decay odd and some attitude indicator (which is finally processed in the SDK, that is C++/header files in CvGameCoreDLL folder).

In CIV4LeaderHeadInfos:

Decay:

Spoiler :
Code:
<MemoryDecay>
					<MemoryType>MEMORY_TRADED_TECH_TO_US</MemoryType>
					<iMemoryRand>100</iMemoryRand>
				</MemoryDecay>

Attitude Indicator:

Spoiler :
Code:
<MemoryAttitudePercent>
					<MemoryType>MEMORY_TRADED_TECH_TO_US</MemoryType>
					<iMemoryAttitudePercent>5,10,15</iMemoryAttitudePercent>
				</MemoryAttitudePercent>


All leaders have same memory capacity; no one forgets faster than others.
But some leaders are more sensitive to other player propensity (and I said player, because AI-AI works too; not human exclusive) to freely share their discoveries.

Here's the list:

Spoiler :
Code:
LEADERS     <iMemoryAttitudePercent>

ALEXANDER 	10             
ASOKA       	 5              
AUGUSTUS	        10
BISMARCK   	 5
BOUDICA     	15
BRENNUS    	10
CATHERINE  	15
CHARLEMAGNE	10
CHURCHILL  	10
CYRUS        	10
DARIUS       	10
DE_GAULLE  	10
ELIZABETH  	15
ROOSEVELT  	10
FREDERICK  	15
GANDHI      	5
GENGHIS_KHAN 	10
GILGAMESH  	15
HAMMURABI 	10
HANNIBAL   	15
HATSHEPSUT	10
HUAYNA_CAPAC	10
ISABELLA    	5
JOAO          	15
JULIUS_CAESAR 	10
JUSTINIAN  	15
KUBLAI_KHAN	15
LINCOLN     	15
LOUIS_XIV  	10
MANSA_MUSA	20
MAO_ZEDONG	5
MEHMED     	10
MONTEZUMA    	15
NAPOLEON  	10
PACAL        	10
PERICLES    	10
PETER        	20
QIN_SHI_HUANG	10
RAGNAR      	5
RAMESSES   	10
SALADIN     	10
SHAKA        	5
SITTING_BULL	5
STALIN       	5
SULEIMAN    	5
SURYAVARMAN	5
TOKUGAWA   	5
VICTORIA	        5
WANGKON   	5
WASHINGTON	5
WILLEM      	5
ZARA_YAQOB	5

Now how to process those numbers in an actual number of received techs (point of view of the tech receiver).

In CvPlayerAI.cpp:

Spoiler :
Code:
int CvPlayerAI::AI_getAttitudeVal(PlayerTypes ePlayer, bool bForced) const
{
	PROFILE_FUNC();

	int iRankDifference;
	int iAttitude;
	int iI;

	FAssertMsg(ePlayer != getID(), "shouldn't call this function on ourselves");

	if (bForced)
	{
		if (getTeam() == GET_PLAYER(ePlayer).getTeam() || (GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()) && !GET_TEAM(getTeam()).isCapitulated()))
		{
			return 100;
		}

		if (isBarbarian() || GET_PLAYER(ePlayer).isBarbarian())
		{
			return -100;
		}
	}

	iAttitude = GC.getLeaderHeadInfo(getPersonalityType()).getBaseAttitude();

	iAttitude += GC.getHandicapInfo(GET_PLAYER(ePlayer).getHandicapType()).getAttitudeChange();

//	if (GC.getGameINLINE().isOption(GAMEOPTION_AGGRESSIVE_AI))
//	{
//		if (GET_PLAYER(ePlayer).isHuman())
//		{
//			iAttitude -= 2;
//		}
//	}

	if (!(GET_PLAYER(ePlayer).isHuman()))
	{
		iAttitude += (4 - abs(AI_getPeaceWeight() - GET_PLAYER(ePlayer).AI_getPeaceWeight()));
		iAttitude += std::min(GC.getLeaderHeadInfo(getPersonalityType()).getWarmongerRespect(), GC.getLeaderHeadInfo(GET_PLAYER(ePlayer).getPersonalityType()).getWarmongerRespect());
	}

	iAttitude -= std::max(0, (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getNumMembers() - GET_TEAM(getTeam()).getNumMembers()));

	iRankDifference = (GC.getGameINLINE().getPlayerRank(getID()) - GC.getGameINLINE().getPlayerRank(ePlayer));

	if (iRankDifference > 0)
	{
		iAttitude += ((GC.getLeaderHeadInfo(getPersonalityType()).getWorseRankDifferenceAttitudeChange() * iRankDifference) / (GC.getGameINLINE().countCivPlayersEverAlive() + 1));
	}
	else
	{
		iAttitude += ((GC.getLeaderHeadInfo(getPersonalityType()).getBetterRankDifferenceAttitudeChange() * -(iRankDifference)) / (GC.getGameINLINE().countCivPlayersEverAlive() + 1));
	}

	if ((GC.getGameINLINE().getPlayerRank(getID()) >= (GC.getGameINLINE().countCivPlayersEverAlive() / 2)) &&
		  (GC.getGameINLINE().getPlayerRank(ePlayer) >= (GC.getGameINLINE().countCivPlayersEverAlive() / 2)))
	{
		iAttitude++;
	}

	if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).AI_getWarSuccess(getTeam()) > GET_TEAM(getTeam()).AI_getWarSuccess(GET_PLAYER(ePlayer).getTeam()))
	{
		iAttitude += GC.getLeaderHeadInfo(getPersonalityType()).getLostWarAttitudeChange();
	}

	iAttitude += AI_getCloseBordersAttitude(ePlayer);
	iAttitude += AI_getWarAttitude(ePlayer);
	iAttitude += AI_getPeaceAttitude(ePlayer);
	iAttitude += AI_getSameReligionAttitude(ePlayer);
	iAttitude += AI_getDifferentReligionAttitude(ePlayer);
	iAttitude += AI_getBonusTradeAttitude(ePlayer);
	iAttitude += AI_getOpenBordersAttitude(ePlayer);
	iAttitude += AI_getDefensivePactAttitude(ePlayer);
	iAttitude += AI_getRivalDefensivePactAttitude(ePlayer);
	iAttitude += AI_getRivalVassalAttitude(ePlayer);
	iAttitude += AI_getShareWarAttitude(ePlayer);
	iAttitude += AI_getFavoriteCivicAttitude(ePlayer);
	iAttitude += AI_getTradeAttitude(ePlayer);
	iAttitude += AI_getRivalTradeAttitude(ePlayer);

	for (iI = 0; iI < NUM_MEMORY_TYPES; iI++)
	{
		iAttitude += AI_getMemoryAttitude(ePlayer, ((MemoryTypes)iI));
	}

	iAttitude += AI_getColonyAttitude(ePlayer);
	iAttitude += AI_getAttitudeExtra(ePlayer);

	return range(iAttitude, -100, 100);
}

The very part that interests us is:

Code:
for (iI = 0; iI < NUM_MEMORY_TYPES; iI++)
	{
		iAttitude += AI_getMemoryAttitude(ePlayer, ((MemoryTypes)iI));
	}

Basically making some enumeration of memory types, and #26 is the concerned one.

Becomes
Code:
iAttitude += AI_getMemoryAttitude(TechReceiver, ((MEMORY_TRADED_TECH_TO_US)26));

And bit farther in CvPlayerAI...

we have our definition for AI_getMemoryAttitude:

Code:
int CvPlayerAI::AI_getMemoryAttitude(PlayerTypes ePlayer, MemoryTypes eMemory) const
{
	return ((AI_getMemoryCount(ePlayer, eMemory) * GC.getLeaderHeadInfo(getPersonalityType()).getMemoryAttitudePercent(eMemory)) / 100);
}

Basically that in understandable formula:

iAttitude= [#TechsReceived*<iMemoryAttitudePercent> / 100]

[] meaning you have to round down after the calculus.

For instance, for Cathy, let's take instances of 7, 14 and 20 given techs.

7 techs:
iAttitude = [7*15/100] = [1.05]=1
14 techs:
iAttitude = [14*15/100] = [2.1]=2
20 techs:
iAttitude = [20*15/100] = [3]=3

And that is why for those with <iMemoryAttitudePercent> as 15, for getting diplo modifiers up to +3, it goes 7,7,6 techs.

Important thing to remember, those with <iMemoryAttitudePercent> as 5 need 20 techs for +1, those with <iMemoryAttitudePercent> as 10 need 10 techs +1 modifier and those with <iMemoryAttitudePercent> as 15 need 7,7,6 techs for +1,+2,+3 modifier.

Trivia

  • Interestingly, I was thinking that was better in CvTeamAI.cpp because tech trading is a matter of teams more of individuals. Now come the thought, if you trade a tech to a team, the other partner automatically receives the tech. Does it have a tech count for both or just the leader you traded/gave the tech? Food for thought.
  • The decay process is defined in CvPlayerAI::AI_doCounter() ; nothing particular but basic Soren Johnson's RNG that rolls a number from 0 to 100 (for 101 possible values?). If rolling 0, then the count decreases by one. That RNG is processed each turn. And it is worth for each leader as roughly 1% per turn of Alzheimer.
  • Most code parts are trifles. Mostly for me. ;)
 
Top Bottom