1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

Civ Illustrated #1 (Know Your Enemy)

Discussion in 'Civ4 Strategy Articles' started by Kaitzilla, Oct 23, 2012.

  1. Sun Tzu Wu

    Sun Tzu Wu Chieftain Supporter

    Joined:
    Mar 26, 2007
    Messages:
    7,920
    I have completed testing for the first 13 AIs. They give +1, +2 and +3 after giving them 20 Technologies each:

    Code:
    +2 20/2=10 Alexander
    +1 20/1=20 Asoka  
    +2 20/2=10 Augustus
    +1 20/1=20 Bismarck
    +3 20/3=07 Boudica
    +2 20/2=10 Brennus
    +3 20/3=07 Catherine
    +2 20/2=10 Charlemagne
    +2 20/2=10 Churchill
    +2 20/2=10 Cyrus
    +2 20/2=10 Darius I
    +2 20/2=10 De Gaulle
    +3 20/3=07 Elizabeth
    
    Notice that Boudica, Catherine and Elizabeth will provide +1 after 7 Techs, +2 after 14 Techs and +3 after 20 Techs. So ignoring the AI's less than perfect memory, the +3 bonus applies after giving just 20 Techs. Thus 7 = ceiling[20/3] and 14 = ceiling[20*2/3].

    Notice that Alexander, Augustus, Brennus, Charlemagne, Churchill, Cyrus, Darius I and De Gaulle will provide +1 after 10 Techs and +2 after 20 Techs. So ignoring the AI's less than perfect memory, the +2 bonus applies after giving 20 Techs.

    Notice that Asoka and Bismarck will provide +1 only after 20 Techs. So ignoring the AI's less than perfect memory, the +1 bonus applies only after giving 20 Techs.

    I have attached two game save files. First one is a turn 1 save where the player was given Mediaevil Era Technologies and all AIs had all their starting Technologies removed to make it easier to verify that each AI was given exactly the same number of Techs. The second save is a turn 3 save after each AI was given the 19 Technologies they possess over the previous 2 turns. You can verify the above results from either save; in the latter one, 19 technology trades are completed for you and the 20th trade should answer the question of how big this bonus is after giving 20 technologies. Every AI will increase their bonus with the 20th technology, ignoring their imperfect memory which should be excellent after just 2 turns.

    Enjoy! I'll complete the remaining 3 games as soon as I am able. BTW, I foolishly started this first test game with Tribal Villages on, but Boudica popped Technology from a Hut, so I reloaded and manually removed all Huts. I won't make that mistake with the remaining 3 games.

    Sun Tzu Wu
     
  2. Manco Capac

    Manco Capac Friday,13 June,I Collapse

    Joined:
    Mar 1, 2010
    Messages:
    8,051
    Good research Sun Tzu Wu. Given you enthusiasm, I'll look into the code about it.
    I definitely think if it wasn't defined in XML files as an individual value, it is because that mechanics use another unrelated XML value. I happen to see this for resource demands at vassals.
     
  3. UnforcedError

    UnforcedError Settler

    Joined:
    May 1, 2012
    Messages:
    3,298
    Gender:
    Female
    Location:
    Budapest, Hungary
    Thanks a lot, that was really informative :goodjob:
     
  4. Kaitzilla

    Kaitzilla Lord Croissant

    Joined:
    Jun 21, 2008
    Messages:
    8,121
    Gender:
    Male
    Location:
    America!
    I double checked and Gandhi was an ok choice to illustrate the clashing of "Worst Enemy" mechanic vs. attitute thresholds at Annoyed and Furious. Mansa might be a better example since he is more consistent in regards to using the Annoyed threshold throughout the entire example but Gandhi was chosen because he was the most extreme. Trading techs with Gandhi at Furious is rather quite hard since you need another AI whom he hates even more.
     
  5. Kaitzilla

    Kaitzilla Lord Croissant

    Joined:
    Jun 21, 2008
    Messages:
    8,121
    Gender:
    Male
    Location:
    America!
    :dance:[party]:banana: You are absolutely right Sun Tzu Wu! The guide will be fixed as soon as possible later today. Finding the +3 bonus at 20 tech trades is also quite appreciated. No idea why the AI gives +1/+2/+3 at 7/14/20 techs instead of 7/14/21. That is so strange. :crazyeye:

    For testing it is worthwhile to turn on "no tech brokering" as it allows unlimited tech trades to occur without having to press next turn. Corners were cut a little to maintain sanity for 52 AI's by giving the AI's techs in batches of 5 during testing so very sorry for the mistake! :sad:

    Thanks for helping fix this :goodjob:
     
  6. Manco Capac

    Manco Capac Friday,13 June,I Collapse

    Joined:
    Mar 1, 2010
    Messages:
    8,051
    Hey guys. Don't do unnecessary testings. I finally found it. The mechanics. Will post.
     
  7. Manco Capac

    Manco Capac Friday,13 June,I Collapse

    Joined:
    Mar 1, 2010
    Messages:
    8,051
    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. ;)
     
  8. Kaitzilla

    Kaitzilla Lord Croissant

    Joined:
    Jun 21, 2008
    Messages:
    8,121
    Gender:
    Male
    Location:
    America!
    :love:
     
  9. Sun Tzu Wu

    Sun Tzu Wu Chieftain Supporter

    Joined:
    Mar 26, 2007
    Messages:
    7,920
    My list matched yours until:


    SULEIMAN 10
    SURYAVARMAN 10
    TOKUGAWA 5
    VICTORIA 10
    WANGKON 10
    WASHINGTON 10
    WILLEM 15
    ZARA_YAQOB 10

    My list was based on the MEMORY_TRADED_TECH_TO_US row in a BtS 3.13 spreadsheet. I'm not sure whether these values were correct for 3.13, but I know that I gave Zara Yaqob a few more than 10 technologies long ago and never got +1 for sharing technologies, so I'm sure the spreadsheet maker got 7 of 8 wrong.

    The raw 3.19 CIV4LeaderHeadsInfo.xml was easy enough to read until I got to Suleiman. There seem to be trivial bugs there in the XML that bother a human reader. I finally downloaded an eval copy of xmlspy and was finally able to verify your values quoted above as correct.

    How did you create that list so easily?

    Thanks for producing the list. I ended up verifying it with my raw 3.19 CIV4LeaderHeadsInfo.xml with the last eight via xmlspy. So I'd agree that no further testing is needed, except ...

    We have seen three Leaders (Boudica, Catherine and Elizabeth) get to +3 via 20 technology trades. Is there a limit to how big this bonus can go?

    @Kaitzilla: Thanks for the testing tip of using "no tech brokering". That would eliminate the slim chance of an AI forgetting about one tech trade in the range of 2t that I was using.

    Sun Tzu Wu
     
  10. Manco Capac

    Manco Capac Friday,13 June,I Collapse

    Joined:
    Mar 1, 2010
    Messages:
    8,051
    Comments in blue. BTW, I can't confirm with citations of other works because no one worked on
    "You have shared your technological discoveries with us." before. It's original work.
     
  11. Sun Tzu Wu

    Sun Tzu Wu Chieftain Supporter

    Joined:
    Mar 26, 2007
    Messages:
    7,920
    I couldn't find MEMORY_TRADED_TECH_TO_US in DanF5771's spreadsheet.

    Thank you very much for your explanation!

    Sun Tzu Wu
     
  12. Manco Capac

    Manco Capac Friday,13 June,I Collapse

    Joined:
    Mar 1, 2010
    Messages:
    8,051
    It's because he cut the MEMORY part given he organized in sections.

    Give a try on TRADED_TECH_TO_US.
     
  13. Sun Tzu Wu

    Sun Tzu Wu Chieftain Supporter

    Joined:
    Mar 26, 2007
    Messages:
    7,920
    OK, that worked great. Thanks!

    DanF5771's Spreadsheet is now just over an year old (2012/10/19). That is likely to be the most up to date spread sheet on CIV4LeaderHeadInfo.xml and stay up to date.

    I'm looking for a more versatile XML viewer than xmlspy. One that is perpetually free. The grid view of xmlspy was ok, but ackward to use; in 30 days the eval license expires too.

    Sun Tzu Wu
     
  14. Manco Capac

    Manco Capac Friday,13 June,I Collapse

    Joined:
    Mar 1, 2010
    Messages:
    8,051
    I'm not really a know-it-all (in fact I'm a know-it-null) in applications but I simply use Notepad++. That app is free source.
    Before I was simply using simple notepad (roughest terrain).

    BTW, funny how Kakumeika team looks so much of a highly bureaucratic team. Numbers, proofs, spreadsheets, etc.

    BTW2: Don't forget to put your thread score. I did.
     
  15. Sun Tzu Wu

    Sun Tzu Wu Chieftain Supporter

    Joined:
    Mar 26, 2007
    Messages:
    7,920
    Don't be too modest. Your code diving skills are becoming legendary!

    notepad++ is a great application; I use it daily.

    Agreed, Kakumeika is a highly technical, micromanaging team.

    "thread score?" :lol: A microbrew is in order when ours goes past 5000. You will beat me no doubt. Or did you mean team thread score?

    Sun Tzu Wu
     
  16. Sun Tzu Wu

    Sun Tzu Wu Chieftain Supporter

    Joined:
    Mar 26, 2007
    Messages:
    7,920
    I continued my test game trading more technologies to Elizabeth, until she received 60 techs and became +9 "shared your technological discoveries with us." See the attached save game file with 59 technologies traded (given) to her. Give her one more. There are plenty more technologies to trade away too, including Future Tech <n> where n is huge! In any case, +9 should be more than enough to get Friendly with her. In fact, she said something about sacrificing 50 Warriors in honor of our friendship.

    This verifies, in a practical sense, your code analysis that there is no limit to this bonus, other than Research rate (Beat the the AI to every technology and one can realistically give every such technology away, especially with well timed Great Person bulbs).

    Sun Tzu Wu
     
  17. Manco Capac

    Manco Capac Friday,13 June,I Collapse

    Joined:
    Mar 1, 2010
    Messages:
    8,051
    Finally, I was able to mostly gather about capitulee resource demands.
    That always was a random part for me as I never knew how the AI would react. Sometimes, I got automatic war state in ridiculous situations (like the AI being far weaker than me).

    Thus, this XML value (and following explanations) have a real strategic value in CIV4 gaming.

    ========================================================

    SYNOPSIS

    Two types of vassals exist: peacevassals and capitulee. While peacevassals have an automatic mechanics that force the AI to be FRIENDLY with you (even without enough attitude modifier), capitulee won't be necessary pleased with you as master. Both types enable disabled WFYABTA, many disabled reddened diplo items and right to demands single resources for free along other kind of bonuses/maluses.

    Depending of the leader that has capitulated, if you have the right attitude, you can ask as many resources without risk at all of breaking the vassal treaty.
    Indeed, under vassality, asking resources for free is some kind of animal intimidation fight: if one thinks have no chance, it flees. Otherwise it attacks.
    Here the vassal revolts and enter war state when (s)he deemed the demand(s) was abusive.

    It turns out that resource demands are either free-revolt if correct attitude or is under the same rules as a normal demand you do to a non-capitulee AI, but with war as result of refusal.

    First demand is not protected from revolt and the vassal treaty can be broken even in the 10 first turns after capitulation. If there was some rumors of the first resource demand was free of dangers, it is often because on how long you knew/met the AI until deciding to capitulate him/her. This boost the chance of a granted first free resource. But once the first grant done, the magnitude of the second grant is reset to zero and you have to wait a certain number of turns before it worth a resource.

    ANALYSIS

    It all starts with CvPlayerAI.cpp (the SDK files that deal with individual AI leader behaviours)::AI_doDiplo().

    For a willing to talk vassal, here's the code:

    Spoiler :
    Code:
    if (GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).isVassal(getTeam()))
    								{
    									iBestValue = 0;
    									eBestGiveBonus = NO_BONUS;
    
    									for (iJ = 0; iJ < GC.getNumBonusInfos(); iJ++)
    									{
    										if (GET_PLAYER((PlayerTypes)iI).getNumTradeableBonuses((BonusTypes)iJ) > 0 && getNumAvailableBonuses((BonusTypes)iJ) == 0)
    										{
    											iValue = AI_bonusTradeVal((BonusTypes)iJ, (PlayerTypes)iI, 1);
    
    											if (iValue > iBestValue)
    											{
    												iBestValue = iValue;
    												eBestGiveBonus = ((BonusTypes)iJ);
    											}
    										}
    									}
    
    									if (eBestGiveBonus != NO_BONUS)
    									{
    										theirList.clear();
    										ourList.clear();
    
    										setTradeItem(&item, TRADE_RESOURCES, eBestGiveBonus);
    										theirList.insertAtEnd(item);
    
    										if (GET_PLAYER((PlayerTypes)iI).isHuman())
    										{
    											if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
    											{
    												CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_VASSAL_GRANT_TRIBUTE, getID(), eBestGiveBonus);
    												if (pInfo)
    												{
    													gDLL->getInterfaceIFace()->addPopup(pInfo, (PlayerTypes)iI);
    													abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
    												}
    											}
    										}
    										else
    										{
    											GC.getGameINLINE().implementDeal(getID(), ((PlayerTypes)iI), &ourList, &theirList);
    										}
    									}
    								}
    								


    It is basically how a code block on vassal-master trade of resources, with both side to offer or only one side (master) asking. Here is our part:

    Spoiler :
    Code:
    if (GET_PLAYER((PlayerTypes)iI).isHuman())
    										{
    											if (!(abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()]))
    											{
    												CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_VASSAL_GRANT_TRIBUTE, getID(), eBestGiveBonus);
    												if (pInfo)
    												{
    													gDLL->getInterfaceIFace()->addPopup(pInfo, (PlayerTypes)iI);
    													abContacted[GET_PLAYER((PlayerTypes)iI).getTeam()] = true;
    												}
    											}
    										}


    First, demanding resources is excusive to human player! That means no one should ever see some war between AI vassal-AI master due to some resource denial.
    BUTTONPOPUP_VASSAL_GRANT_TRIBUTE is some kind of action made by the human player and let's see it in details in CvDLLButtomPopup.ccp.

    That's almost the core of the subject:

    Spoiler :
    Code:
    case BUTTONPOPUP_VASSAL_DEMAND_TRIBUTE:
                    if (pPopupReturn->getButtonClicked() < GC.getNumBonusInfos())
                    {
                            PlayerTypes eVassal = (PlayerTypes)info.getData1();
                            if (GET_PLAYER(eVassal).isHuman())
                            {
                                    CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_VASSAL_GRANT_TRIBUTE, GC.getGameINLINE().getActivePlayer(), pPopupReturn->getButtonClicked());
                                    if (NULL != pInfo)
                                    {
                                            gDLL->sendPopup(eVassal, pInfo);
                                    }
                            }
                            else
                            {
                                    TradeData item;
                                    setTradeItem(&item, TRADE_RESOURCES, pPopupReturn->getButtonClicked());
    
                                    CLinkList<TradeData> ourList;
                                    CLinkList<TradeData> theirList;
                                    theirList.insertAtEnd(item);
    
                                    if (GET_PLAYER(eVassal).AI_considerOffer(GC.getGameINLINE().getActivePlayer(), &ourList, &theirList))
                                    {
                                            gDLL->sendImplementDealMessage(eVassal, &ourList, &theirList);
    
                                            CvWString szBuffer = gDLL->getText("TXT_KEY_VASSAL_GRANT_TRIBUTE_ACCEPTED", GET_PLAYER(eVassal).getNameKey(), GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getNameKey(), GC.getBonusInfo((BonusTypes)pPopupReturn->getButtonClicked()).getTextKeyWide());
                                            gDLL->getInterfaceIFace()->addMessage(GC.getGameINLINE().getActivePlayer(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer);
                                    }
                                    else
                                    {
                                            gDLL->sendChangeWar(GET_PLAYER(eVassal).getTeam(), true);
                                    }
                            }
                    }
                    break;


    Let cut the fat of uninteresting:
    Spoiler :
    Code:
    if (GET_PLAYER(eVassal).AI_considerOffer(GC.getGameINLINE().getActivePlayer(), &ourList, &theirList))
                                    {
                                            gDLL->sendImplementDealMessage(eVassal, &ourList, &theirList);
    
                                            CvWString szBuffer = gDLL->getText("TXT_KEY_VASSAL_GRANT_TRIBUTE_ACCEPTED", GET_PLAYER(eVassal).getNameKey(), GET_PLAYER(GC.getGameINLINE().getActivePlayer()).getNameKey(), GC.getBonusInfo((BonusTypes)pPopupReturn->getButtonClicked()).getTextKeyWide());
                                            gDLL->getInterfaceIFace()->addMessage(GC.getGameINLINE().getActivePlayer(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer);
                                    }
                                    else
                                    {
                                            gDLL->sendChangeWar(GET_PLAYER(eVassal).getTeam(), true);
                                    }


    Basically, it goes like this: if the AI (via AI_considerOffer() function) finds your demand reasonable, that function is returning true and the capitulee simply return a grumble plus the resource.
    But if AI_considerOffer() returns false, then war is triggered. I haven't find the exact link between sending info a war and the actual war triggering, but I don't really care.
    sendChangeWar() function is prolly obvious.

    Here the code anyways:

    Spoiler :
    Code:
    void CvMessageControl::sendChangeWar(TeamTypes eRivalTeam, bool bWar)
    {
    	if (NO_PLAYER != GC.getGameINLINE().getActivePlayer())
    	{
    		gDLL->sendMessageData(new CvNetChangeWar(GC.getGameINLINE().getActivePlayer(), eRivalTeam, bWar));
    	}
    }


    Now where lies the acceptance of bullying from the capitulee lies in AI_considerOffer().
    Yes, the same place as begging/demands functions.

    Now the core of the subject (with fat cut):

    Spoiler :
    Code:
    int iOurValue = GET_PLAYER(ePlayer).AI_dealVal(getID(), pOurList, false, iChange);
    	int iTheirValue = AI_dealVal(ePlayer, pTheirList, false, iChange);
    
    	if (iOurValue > 0 && 0 == pTheirList->getLength() && 0 == iTheirValue)
    	{
    		if (GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()) && CvDeal::isVassalTributeDeal(pOurList))
    		{
    			if (AI_getAttitude(ePlayer, false) <= GC.getLeaderHeadInfo(getPersonalityType()).getif()
    				&& GET_TEAM(getTeam()).getAtWarCount(true) == 0
    				&& GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getDefensivePactCount() == 0)
    			{
    				iOurValue *= (GET_TEAM(getTeam()).getPower(false) + 10);
    				iOurValue /= (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getPower(false) + 10);
    			}
    			else
    			{
    				return true;
    			}
    		}
    		else
    		{
    			if (AI_getAttitude(ePlayer) < ATTITUDE_PLEASED)
    			{
    				if (GET_TEAM(getTeam()).getPower(false) > ((GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getPower(false) * 4) / 3))
    				{
    					return false;
    				}
    			}
    
    			if (AI_getMemoryCount(ePlayer, MEMORY_MADE_DEMAND_RECENT) > 0)
    			{
    				return false;
    			}
    		}

    Basically for a player that is vassal and has the vassal treaty in their balance (i.e. a capitulee or peacevassal),
    if the vassal attitude is lower or equal to <VassalRefuseAttitudeThreshold> (an XML value in CIV4LeaderHeadInfos.xml and the same used for peacevassal!!!!) AND not already at war (well duh!) AND the master does not have some defensive pact, then comes some calculi equivalent to normal demands.
    BUT if you have at least one defensive pact, or have better relationship than <VassalRefuseAttitudeThreshold> , then resources are always granted!!!!
    Peacevassals have an automatic FRIENDLY stance mechanics just to avoid refusal btw.

    Now we now the ensured paths to get free-risk demands, let's see demands that are tied some many calculi and possibly I won't end this work being too heavy.

    First, the AI ponders the demand via AI_dealVal() function:

    Code:
    iOurValue = GET_PLAYER(ePlayer).AI_dealVal(getID(), pOurList, false, iChange);
    In CvPlayerAI::AI_dealVal(), hereunder the case for resources valuing:

    Code:
    case TRADE_RESOURCES:
    			if (!bIgnoreAnnual)
    			{
    				iValue += AI_bonusTradeVal(((BonusTypes)(pNode->m_data.m_iData)), ePlayer, iChange);
    			}
    			break;
    Thenb AI_bonusTradeVal is a simple function (where one can see vassals see their worth halved; for peacevassals only it seems, weird...), but it calls a big big and big function that gives the value of resources (AI_bonusVal). Despite I already unraveled this big scumbag function in the past for another reason, I won't display its ugliness for now unless begged.

    At least, let show AI_bonusTradeVal():

    Spoiler :
    Code:
    int CvPlayerAI::AI_bonusTradeVal(BonusTypes eBonus, PlayerTypes ePlayer, int iChange) const
    {
    	int iValue;
    
    	FAssertMsg(ePlayer != getID(), "shouldn't call this function on ourselves");
    
    	iValue = AI_bonusVal(eBonus, iChange);
    
    	iValue *= ((std::min(getNumCities(), GET_PLAYER(ePlayer).getNumCities()) + 3) * 30);
    	iValue /= 100;
    
    	iValue *= std::max(0, (GC.getBonusInfo(eBonus).getAITradeModifier() + 100));
    	iValue /= 100;
    
    	if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isVassal(getTeam()) && !GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isCapitulated())
    	{
    		iValue /= 2;
    	}
    
    	return (iValue * GC.getDefineINT("PEACE_TREATY_LENGTH"));
    }
    


    To come back on iOurValue, then it is processed to a power inflating factor. Basically the power of the team (master+vassal(s)) over the power of the master power (I think).

    I'll stop there. I need to rethink. I'm confusing things I think.

    //cut
     
  18. Manco Capac

    Manco Capac Friday,13 June,I Collapse

    Joined:
    Mar 1, 2010
    Messages:
    8,051
    No need for Kaku is have score. :lol:

    I meant Civ Illustrated thread (mainly Kaitzilla's work). I did give my score. Perhaps, that will attract newcoming players. You see, some people judge by score. :sad:
     
  19. Manco Capac

    Manco Capac Friday,13 June,I Collapse

    Joined:
    Mar 1, 2010
    Messages:
    8,051
    You clearly haven't seen monsters in Civ4 - Creation & Customization. There are possibly bigger monsters than DanF. There's not only SDK (C++, header files, etc.). There's python and other stuff to know.

    Most of them have possible actual courses that backs them in their modding while I am working from scratch.

    One thing I want to do is to use python to create events (just like events you see in the blackish tab in the upper middle screen; e.g. wonders) when functions are called. That would help me greatly in how to decipher functions. DanF can do this (I saw a screen with this) but he never mentioned anywhere how to do it).
     
  20. Manco Capac

    Manco Capac Friday,13 June,I Collapse

    Joined:
    Mar 1, 2010
    Messages:
    8,051
    @Kaitzilla

    Let's test our friendship. (Irony of my latest work)

    I demand you to add close border XML values, <VassalRefuseAttitudeThreshold> (that is adding a line below "Will possibly peace vassal to human player: Friendly" about demanding resources from vassal for same attitude is risk-free) and corrections for "shared your technological discoveries with us".

    If refused, we enter a war state of eternal râleries... :groucho:
     

Share This Page