Diplomacy AI Development

3. This option was specifically removed by Gazebo a while back as the AI couldn't make use of it. I too want it added but at the moment the AI has no capability of handling it.

Is there a way I can enable this like some config file editing or some modmod? Honestly, I would be fine if this only existed for the human too.
 
Recursive, I'm still seeing a lot of early DoWs (turn 60-90) where my neighbour China bribed faraway Carthage, Poland and Babylon to DoW me. And even later on, around t110, when China was losing a war against Russia (having just lost a city and its capital being attacked), China still decided to spend money on bribing Poland to DoW me, even though I was at peace with China, instead of using it to bolster its defense. So perhaps that's something to be looked at, maybe code it more emphatically that if one of the AIs cities is being attacked or has been conquered, it won't bribe for DoWs except against civs that it is at war with and/or lost a city to?
 
just wanted to quickly add that even though I've made a couple of posts critical of the current build, I'm thrilled Vox Populi exists and I appreciate you guys considering the input of an obviously casual player.

I consider all feedback regardless of the source, I like making people happy and whether someone plays casually or is an expert they may have a good point.

Obviously, I am still a mere human, and I'm more likely to respond well if criticism is presented constructively (as opposed to some of the angry incoherent ranting I've seen).
 
This reminds me of an idea I had. It would be enacted through the UN/world Congress, "peacekeeping forces", where each member would lose gold, and forces are sent to one side of a war. Most likely it would only be for CS wars. So if someone declares war on a CS you can enact the resolution and the CS would gain troops. People complain about not being able to protect CS, and this would help that. Also it seems easier for AI logic, vote yes if you like the CS or CS ally, no if you like the offender or don't like the CS or CS ally.

Instead of receiving units, it could be a large combat modifier for City-States instead.
 
Here is a thought regarding non-lasting friendships. I don't have this issue in my games (Emperor, Large, Fractal, 13/22) -- many friendships last throughout the game other than of course those with civs close in proximity (sooner or later there will be border disputes, which is a good thing). However, I play Vox with Tech Trading turned off and with Research Agreements turned on. So, there is actually some incentive for friendships (RA's) or at least to not go to war with someone with whom you have a RA. I find the current Diplomacy to be excellent imho (especially after the bribed wars was recently fixed) as a result.
 
I like how now there's a sense of "historic" friendships and "historic" enemies. In my current game I've practically been friends with the same people and enemies with the same people all game from ancient to modern times.

The only exception is where I've become aggressive myself. I warned you to stop spending spies, Napoleon. We'll settle this on the battlefield, old friend. Au revoir.
 
However, I play Vox with Tech Trading turned off and with Research Agreements turned on. So, there is actually some incentive for friendships (RA's) or at least to not go to war with someone with whom you have a RA. I find the current Diplomacy to be excellent imho (especially after the bribed wars was recently fixed) as a result.
I've been doing this over the last few months as well with similar results. There's been a couple times in prior versions that saw questionable behaviour in terms of civs backstabbing me with low turns remaining on a RA, but everything has been great for the most part.
 
How are War score and Peace Deal Max Value related, if at all? I have a 100 war score against Ottomans, but only a 131 value max peace deal, which seems awefully low.

Spoiler :

upload_2021-1-8_0-27-19.png

 
How are War score and Peace Deal Max Value related, if at all? I have a 100 war score against Ottomans, but only a 131 value max peace deal, which seems awefully low.


AI performs this calculation and then sets "max value" to -1x the deal value of the calculation for them.

Code:
/// Add appropriate items to pDeal based on what type of PeaceTreaty eTreaty is
void CvDealAI::DoAddItemsToDealForPeaceTreaty(PlayerTypes eOtherPlayer, CvDeal* pDeal, PeaceTreatyTypes eTreaty, bool bMeSurrendering)
{
   if(eTreaty < PEACE_TREATY_ARMISTICE)
   {
       return;
   }
   int iDuration = GC.getGame().GetDealDuration();

   PlayerTypes eLosingPlayer = bMeSurrendering ? GetPlayer()->GetID() : eOtherPlayer;
   CvPlayer* pLosingPlayer = &GET_PLAYER(eLosingPlayer);
   PlayerTypes eWinningPlayer = bMeSurrendering ? eOtherPlayer : GetPlayer()->GetID();
   pDeal->SetSurrenderingPlayer(eLosingPlayer);
   int iWarScore = pLosingPlayer->GetDiplomacyAI()->GetWarScore(eWinningPlayer);
#if defined(MOD_DIPLOMACY_CIV4_FEATURES)
   bool bBecomeMyVassal = pLosingPlayer->GetDiplomacyAI()->IsVassalageAcceptable(eWinningPlayer, true);
   bool bRevokeMyVassals = false;
   // Reduce war score if losing player wants to become winning player's vassal
   if(MOD_DIPLOMACY_CIV4_FEATURES && bBecomeMyVassal)
   {
       iWarScore /= 2;
   }
   // Is losing player willing to revoke his vassals?
   if(MOD_DIPLOMACY_CIV4_FEATURES && iWarScore <= -85 && GET_TEAM(pLosingPlayer->getTeam()).GetNumVassals() > 0)
   {
       //If we're willing to do this, give less below.
       bRevokeMyVassals = true;
       iWarScore /= max(2, GET_TEAM(pLosingPlayer->getTeam()).GetNumVassals());
   }
   if(iWarScore < 0)
   {
       iWarScore *= -1;
   }
#endif

   //strategic warscore adjustment
   if (!pLosingPlayer->HasCityInDanger(false,0))
       iWarScore = max(0, iWarScore - 10);

   int iPercentGoldToGive = iWarScore;
   int iPercentGPTToGive = (iWarScore / 2);
   bool bGiveUpCities = (iWarScore > 60);
   int iPercentCitiesGiveUp = (iWarScore / 5);
   bool bGiveUpStratResources = (iWarScore > 35);
   bool bGiveUpLuxuryResources = (iWarScore > 15);
   int iGiveUpLuxResources = iWarScore;
   int iGiveUpStratResources = (iWarScore / 4);

   pDeal->AddPeaceTreaty(eWinningPlayer, GC.getGame().getGameSpeedInfo().getPeaceDealDuration());
   pDeal->AddPeaceTreaty(eLosingPlayer, GC.getGame().getGameSpeedInfo().getPeaceDealDuration());
   DoAddPlayersAlliesToTreaty(eOtherPlayer, pDeal);

   CvCity* pLoopCity;
   int iCityLoop;
   // If the player only has one city then we can't get any more from him
   if (bGiveUpCities && iPercentCitiesGiveUp > 0 && pLosingPlayer->getNumCities() > 1)
   {
       int iTotalCityValue = 0;

       // Create vector of the losing players' Cities so we can see which are the closest to the winner
       CvWeightedVector<int> viCityValue;

       // Loop through all of the loser's Cities, looking only at valid ones.
       for(pLoopCity = pLosingPlayer->firstCity(&iCityLoop); pLoopCity != NULL; pLoopCity = pLosingPlayer->nextCity(&iCityLoop))
       {
           //do this from the winner's perspective!
           int iCurrentCityValue = GetCityValueForBuyer(pLoopCity, eLosingPlayer, eWinningPlayer, true);
           if (iCurrentCityValue == INT_MAX)
               continue;

           //add up total city value of the loser (before danger and damage adjustment)
           iTotalCityValue += iCurrentCityValue;

           //Remember for later
           viCityValue.push_back(pLoopCity->GetID(), iCurrentCityValue);
       }

       // Sort the vector based on distance from winner's capital
       viCityValue.SortItems();
       int iSortedCityID;

       // Determine the value of Cities to be given up
       int iCityValueToSurrender = iTotalCityValue * iPercentCitiesGiveUp / 100;
       // Loop through sorted Cities and add them to the deal if they're under the amount to give up
       // Start from the back of the list, because that's where the cheapest cities are
       for(int iSortedCityIndex = viCityValue.size() - 1; iSortedCityIndex > -1 ; iSortedCityIndex--)
       {
           iSortedCityID = viCityValue.GetElement(iSortedCityIndex);
           pLoopCity = pLosingPlayer->getCity(iSortedCityID);

           int iCurrentCityValue = GetCityValueForBuyer(pLoopCity, eLosingPlayer, eWinningPlayer, true);
           if (iCurrentCityValue == INT_MAX)
               continue;

           // City is worth less than what is left to be added to the deal, so add it
           if (iCurrentCityValue < iCityValueToSurrender && iCurrentCityValue > 0)
           {
               pDeal->AddCityTrade(eLosingPlayer, iSortedCityID);
               iCityValueToSurrender -= iCurrentCityValue;

               //Frontline cities count more than they're worth. Ideally they should satisfy the winner?
               iCityValueToSurrender -= (pLoopCity->getDamage() * 10);
               if (pLosingPlayer->GetPlotDanger(pLoopCity) > GC.getCITY_HIT_POINTS_HEALED_PER_TURN())
                   iCityValueToSurrender -= iCurrentCityValue / 10;
           }
       }
   }
   // Gold
   int iGold = 0;
   if (iPercentGoldToGive > 0)
   {
       iGold = pDeal->GetGoldAvailable(eLosingPlayer, TRADE_ITEM_GOLD);
       iGold = iGold * iPercentGoldToGive / 100;
       if(iGold > 0)
       {
           pDeal->AddGoldTrade(eLosingPlayer, iGold);
       }
   }

   // Gold per turn
   int iGPT = 0;
   if (iPercentGPTToGive > 0)
   {
       iGPT = pLosingPlayer->calculateGoldRate();
       int iGPTToGive = ((iGPT * iPercentGPTToGive) / 100);

       if (iGPTToGive >= iGPT-2)
       {
           iGPTToGive -= 2;
       }

       if (iGPTToGive > 0)
       {
           pDeal->AddGoldPerTurnTrade(eLosingPlayer, iGPTToGive, iDuration);
       }
   }

   // precalculate, it's expensive
   int iCurrentNetGoldOfReceivingPlayer = GET_PLAYER(eOtherPlayer).GetTreasury()->CalculateBaseNetGold();

   // Luxury Resources
   if(bGiveUpLuxuryResources && iGiveUpLuxResources > 0)
   {
       ResourceUsageTypes eUsage;
       ResourceTypes eResource;
       int iResourceQuantity = 1;
       int iTotalResourceValue = 0;
       CvWeightedVector<int> viResourceValue;
       for(int iResourceLoop = 0; iResourceLoop < GC.getNumResourceInfos(); iResourceLoop++)
       {
           eResource = (ResourceTypes) iResourceLoop;

           const CvResourceInfo* pkResourceInfo = GC.getResourceInfo(eResource);
           if (pkResourceInfo == NULL)
               continue;

           eUsage = pkResourceInfo->getResourceUsage();

           // Can't trade bonus Resources
           if (eUsage != RESOURCEUSAGE_LUXURY)
           {
               continue;
           }

           iResourceQuantity = pLosingPlayer->getNumResourceAvailable(eResource, false);

           // Don't bother looking at this Resource if the other player doesn't even have any of it
           if (iResourceQuantity == 0)
           {
               continue;
           }
       
           // Can only get 1 copy of a Luxury
           if (eUsage == RESOURCEUSAGE_LUXURY)
           {
               iResourceQuantity = 1;
           }

           int iCurrentResourceValue = GetResourceValue(eResource, iResourceQuantity, GC.getGame().GetDealDuration(), true, eOtherPlayer, iCurrentNetGoldOfReceivingPlayer);

           if(iCurrentResourceValue == INT_MAX)
               continue;

           if(iCurrentResourceValue > 0)
           {
               // Get total city value of the loser
               iTotalResourceValue += iCurrentResourceValue;
               viResourceValue.push_back(eResource, iCurrentResourceValue);
           }
       }
       
       // Determine the value of Cities to be given up
       int iResourceValueToSurrender = (iTotalResourceValue * iGiveUpLuxResources) / 100;

       // Sort the vector based on value
       viResourceValue.SortItems();
       if(viResourceValue.size() > 0)
       {
           // Loop through sorted Cities and add them to the deal if they're under the amount to give up - start from the back of the list, because that's where the CLOSEST cities are
           for(int iSortedResourceIndex =  0; iSortedResourceIndex < viResourceValue.size(); iSortedResourceIndex++)
           {
               ResourceTypes eResourceList = (ResourceTypes)viResourceValue.GetElement(iSortedResourceIndex);

               int iCurrentResourceValue = GetResourceValue(eResourceList, 1,  GC.getGame().GetDealDuration(), true, eOtherPlayer, iCurrentNetGoldOfReceivingPlayer);

               if(iCurrentResourceValue == INT_MAX)
                   continue;

               // City is worth less than what is left to be added to the deal, so add it
               if(iCurrentResourceValue <= iResourceValueToSurrender && iCurrentResourceValue > 0)
               {
                   pDeal->AddResourceTrade(eLosingPlayer, eResourceList, 1, GC.getGame().GetDealDuration());
                   iResourceValueToSurrender -= iCurrentResourceValue;
               }
           }
       }
   }
   // Strategic Resources
   if(bGiveUpStratResources && iGiveUpStratResources > 0)
   {
       ResourceUsageTypes eUsage;
       ResourceTypes eResource;
       int iResourceQuantity = 1;
       int iTotalResourceValue = 0;
       CvWeightedVector<int> viResourceValue;
       for(int iResourceLoop = 0; iResourceLoop < GC.getNumResourceInfos(); iResourceLoop++)
       {
           eResource = (ResourceTypes) iResourceLoop;

           const CvResourceInfo* pkResourceInfo = GC.getResourceInfo(eResource);
           if (pkResourceInfo == NULL)
               continue;

           eUsage = pkResourceInfo->getResourceUsage();

           // Can't trade bonus Resources
           if (eUsage != RESOURCEUSAGE_STRATEGIC)
           {
               continue;
           }

           iResourceQuantity = pLosingPlayer->getNumResourceAvailable(eResource, false);

           // Don't bother looking at this Resource if the other player doesn't even have any of it
           if (iResourceQuantity == 0)
           {
               continue;
           }
       
           if (iResourceQuantity > 3)
           {
               iResourceQuantity = 3;
           }

           int iCurrentResourceValue = GetResourceValue(eResource, iResourceQuantity, GC.getGame().GetDealDuration(), true, eOtherPlayer, iCurrentNetGoldOfReceivingPlayer);

           if(iCurrentResourceValue == INT_MAX)
               continue;

           if(iCurrentResourceValue > 0)
           {
               // Get total city value of the loser
               iTotalResourceValue += iCurrentResourceValue;
               viResourceValue.push_back(eResource, iCurrentResourceValue);
           }
       }
       
       // Determine the value of Cities to be given up
       int iResourceValueToSurrender = (iTotalResourceValue * iGiveUpStratResources) / 100;

       // Sort the vector based on distance from winner's capital
       viResourceValue.SortItems();
       if(viResourceValue.size() > 0)
       {
           // Loop through sorted Cities and add them to the deal if they're under the amount to give up - start from the back of the list, because that's where the CLOSEST cities are
           for(int iSortedResourceIndex =  0; iSortedResourceIndex < viResourceValue.size(); iSortedResourceIndex++)
           {
               ResourceTypes eResourceList = (ResourceTypes)viResourceValue.GetElement(iSortedResourceIndex);               
               iResourceQuantity = pLosingPlayer->getNumResourceAvailable(eResourceList, false);
               if (iResourceQuantity > 3)
               {
                   iResourceQuantity = 3;
               }
               int iCurrentResourceValue = GetResourceValue(eResourceList, iResourceQuantity, GC.getGame().GetDealDuration(), true, eOtherPlayer, iCurrentNetGoldOfReceivingPlayer);

               if(iCurrentResourceValue == INT_MAX)
                   continue;

               // City is worth less than what is left to be added to the deal, so add it
               if(iCurrentResourceValue < iResourceValueToSurrender && iCurrentResourceValue > 0)
               {
                   pDeal->AddResourceTrade(eLosingPlayer, eResourceList, iResourceQuantity, GC.getGame().GetDealDuration());
                   iResourceValueToSurrender -= iCurrentResourceValue;
               }
           }
       }
   }
#if defined(MOD_DIPLOMACY_CIV4_FEATURES)
   if(MOD_DIPLOMACY_CIV4_FEATURES && bBecomeMyVassal)
   {
       pDeal->AddVassalageTrade(eLosingPlayer);
   }
   if(MOD_DIPLOMACY_CIV4_FEATURES && bRevokeMyVassals)
   {
       pDeal->AddRevokeVassalageTrade(eLosingPlayer);
   }

#endif
}
 
Been the case for more than just this new patch, they don't really seem to care unless you straight up touch borders
 
Yup. Settle in the location they were about to settle in the next turn? +10 we have no contested borders. it really should
Include territory they would like to settle.
 
Been playing on the 1/9 patch, really liking the new AI. Haven't a chance to try the 1/15 patch with the new aggressiveness, but so far the AI is the best it's been. The "friendlier" AI is more unpredictable in a lot of ways now, since it's now not guaranteed that all civs will start to attack you once you start winning. Also really liking how long-lasting alliances form and aren't necessarily going to result in being backstabbed eventually. I'll have to play the newer patch and see how AI aggressiveness is (could stand to be ramped up a bit). Warmongering is in a good place now, you can capture cities and every civ won't immediately hate you; wars don't feel like a binary "defensive only" or "if I capture one city I may as well capture all of them" now. City trading is nice, it opens up a lot more strategic opportunities. I was pleasantly surprised by having some interesting city trades proposed. You can also liberate city states without going to war, which is nice. I think it's been stated before, but the AI values strategic resources way higher than they should during trades.

I did notice some strange things though: doing certain actions can make other civs hostile to you permanently, but especially having religious differences. After resurrecting two different civs (albeit, keeping their capital cities), they immediately became hostile because of "religious differences." One civ (America) hadn't even founded a religion either. It could have been because I held their capital (though I captured it from a different civ), but that didn't appear in their list of grievances. Unless this is a bug, having certain actions make other civs permanently hostile doesn't feel like a good mechanic. Having the penalty decay over a long while would be fine.

Other than that, the AI is in a really good spot now.
 
Been playing on the 1/9 patch, really liking the new AI. Haven't a chance to try the 1/15 patch with the new aggressiveness, but so far the AI is the best it's been. The "friendlier" AI is more unpredictable in a lot of ways now, since it's now not guaranteed that all civs will start to attack you once you start winning. Also really liking how long-lasting alliances form and aren't necessarily going to result in being backstabbed eventually. I'll have to play the newer patch and see how AI aggressiveness is (could stand to be ramped up a bit). Warmongering is in a good place now, you can capture cities and every civ won't immediately hate you; wars don't feel like a binary "defensive only" or "if I capture one city I may as well capture all of them" now. City trading is nice, it opens up a lot more strategic opportunities. I was pleasantly surprised by having some interesting city trades proposed. You can also liberate city states without going to war, which is nice. I think it's been stated before, but the AI values strategic resources way higher than they should during trades.

I did notice some strange things though: doing certain actions can make other civs hostile to you permanently, but especially having religious differences. After resurrecting two different civs (albeit, keeping their capital cities), they immediately became hostile because of "religious differences." One civ (America) hadn't even founded a religion either. It could have been because I held their capital (though I captured it from a different civ), but that didn't appear in their list of grievances. Unless this is a bug, having certain actions make other civs permanently hostile doesn't feel like a good mechanic. Having the penalty decay over a long while would be fine.

Other than that, the AI is in a really good spot now.

-160 to opinion if you own a civ's original capital, plus you're marked as untrustworthy which makes them hostile. It isn't religious differences...

If you return it you should get a diplo bonus now. This functions as intended, only capitulated vassals will disregard you owning their capital/Holy City.

Odd that it didn't appear in the list though, could you post a bug report with a savegame/screenshots?

Thanks for the feedback!
 
Here are the screenshots, not sure if these are bugs though. If they are, I'll make a bug report:

Here's Theodora, voluntary vassal, didn't capture capital (but converted her civ to my religion). Been hostile ever since (the negative modifiers for the WC and territorial disputes are recent).

20210115184058_1.jpg

Next we have Montezuma, whom I resurrected from another civ. Held onto their capital city, but the positive modifiers outweigh the negative. Also, the message the AI gave me was "religious differences."

20210115184133_1.jpg

Finally, here's Greece. Captured their original capital, but haven't had any problems with them since.

20210115184235_1.jpg

They only difference is that Greece was a forced vassal whereas the Byzantines and Aztecs were voluntary vassals. Not sure if that's what's driving the different opinions here and is the intended behavior.
 
Here are the screenshots, not sure if these are bugs though. If they are, I'll make a bug report:

Here's Theodora, voluntary vassal, didn't capture capital (but converted her civ to my religion). Been hostile ever since (the negative modifiers for the WC and territorial disputes are recent).

View attachment 581693
Next we have Montezuma, whom I resurrected from another civ. Held onto their capital city, but the positive modifiers outweigh the negative. Also, the message the AI gave me was "religious differences."

View attachment 581694
Finally, here's Greece. Captured their original capital, but haven't had any problems with them since.

View attachment 581695
They only difference is that Greece was a forced vassal whereas the Byzantines and Aztecs were voluntary vassals. Not sure if that's what's driving the different opinions here and is the intended behavior.

Yeah, there is some unintended behavior here. Bug report with savegame/mod list would be appreciated.
 
@Recursive, how come the Celts don't have a penalty to our diplomacy because of differing ideologies? Everyone else does, are there things that nullify it?

Spoiler :

upload_2021-1-20_0-41-10.png

 
I guess it's unintended with the religious opinion change on Celts.

Why's your map all empty?
 
Back
Top Bottom