Ghpstage
Deity
While its probably overly ambitious, being off work and bored for a while I thought about a pie in the sky idea I mentioned in Tachys game mechanics thread, that is figuring out how AI value everything in regards to trade. While parts have been ripped into before I don't think something of this scale has been done.
So, I thought, in order to not clog up Tachys thread anymore I may aswell make a thread specifically about it, hopefully roping in some people to help, perhaps by looking through code themselves, spotting my mistakes, testing, commenting on how to improve the presentation, suggesting where I should look next, or ways I can test. General comments, criticisms and related questions welcomed of course.
The stated purpose for this thread is to find and collect all the coding information needed to put numbers to trade deals, and hopefully explain just why the AI thinks corn for iron trades are a good deal if coming from an AI
If theres anything else of interest related to these I will probably have a look at those too.
Ideally this thread will eventually become a decent reference for trade matters.
Thread Layout
This thread is being made while much of the code-diving is being done rather than as a compilation of existing information, as a result the order of posting is going to reflect the order of functions I dive, which is likely to be illogical from a straight reading perspective. The plan is to link to other posts (not all from this thread or by me) where necessary to try and make it useable.
I know my presentation at this point is poor, part of this is because is due to it being a work in progress, but also partly due to me being pretty bad at that kind of thing. This should improve when I need to use this thread myself in order to test my claims, I will try to make a summary of useful points and equations at the start of each post when that section has run its course and i'm convinced of its validity.
I'm trying to colour code things for the most part, but I need to redo some things.
Red will be for the primary two functions that govern overall trade, Blue for individual component value functions, yellow for components of components, green for other functions of interest. But red unbolded text is also used for some notes.
Most of the code involved is found in either CvPlayerAI.cpp or CvTeamAI.cpp, some things cross into CvCityAI.cpp and other places, at some point i'll get around to sourcing each code extract.
By its very nature this is going to be extremely code heavy, if anyones going to find it useful it'll be the beancounter types. Perhaps some useful generalities useful to anybody will come out of this, but i'm not going to promise anything.
General Assumption of the Trade Table
As far as I know right now, the functions evaluate each side of the trade table from the Buyers perspective (as in both parties are 'buying' the others offer), giving a numerical value for each side.
There are two different minimum acceptable values to the AI, equal or greater than an AIs offer, and equal or greater than (1.1 * AIs offer).
offer =>AI Offer is the norm for tradings, while offer =>1.1 * AIs offer apprently only applies to resources/gpt trade renewals.
In general the human is going to give an AI more than the trade is worth, but fortunately the human does get some compensation for these unequal trades to AIs in the form of +diplo points for "fair trade", which has already been looked into by Tachywaxon link.
Tachy also covered the mechanics of another trade related diplo factor, "You have shared your technological discoveries with us"
The two parent functions governing all human-AI trades are;
Some, if not all of the others have been done by others in the past, unfortunately I have't been able to find them so i've had to redo the work myself.
Theres a couple of other related functions I may check out later if I get success with the main part, most to do with when the I does something based on the same value used in the tradeval functions. So far i'm thinking about these,
CvPlayerAI::AI_commerceWeight
This gives weights to the different types of commerce depending on AI strategy. It is called up in CvPlayerAI::AI_civicVal
CvPlayerAI::AI_doPeace
CvPlayerAI::AI_counterPropose
This is what the AI goes through when you click "What would make this deal work?" Its another huge function.
CvPlayerAI::AI_doReligion
Controls AI state religion changes
CvPlayerAI::AI_doCivics
Controls AI civic swaps
CvPlayerAI::AI_isFinancialTrouble
Defines when an AI is in Financial trouble
There are quite a few places where the code asks if the AI is running various strategies, for now at least i'm not going to touch that function with a barge pole, and if I ever do it'll get its own thread.
To Do list
Unlinked functions
Testing for everything other than gold, GPT, map and tech values
AI_cityTradeval - awaiting AI_bonusTradeval
AI_declareWarTradeVal - Waiting to know what EstimateEndTurn is
AI_religionTradeVal - need to figure out end of AI_bestReligion
AI_endWarVal - quite a few bits and pieces to finish off
Proofreading to see if the summaries match the post after editing
AI_stopTradingTradeVal - deal value calcs
AI_civicvalue
Yellow links list
Tidying everything up
So, I thought, in order to not clog up Tachys thread anymore I may aswell make a thread specifically about it, hopefully roping in some people to help, perhaps by looking through code themselves, spotting my mistakes, testing, commenting on how to improve the presentation, suggesting where I should look next, or ways I can test. General comments, criticisms and related questions welcomed of course.
The stated purpose for this thread is to find and collect all the coding information needed to put numbers to trade deals, and hopefully explain just why the AI thinks corn for iron trades are a good deal if coming from an AI

If theres anything else of interest related to these I will probably have a look at those too.
Ideally this thread will eventually become a decent reference for trade matters.
Thread Layout
This thread is being made while much of the code-diving is being done rather than as a compilation of existing information, as a result the order of posting is going to reflect the order of functions I dive, which is likely to be illogical from a straight reading perspective. The plan is to link to other posts (not all from this thread or by me) where necessary to try and make it useable.
I know my presentation at this point is poor, part of this is because is due to it being a work in progress, but also partly due to me being pretty bad at that kind of thing. This should improve when I need to use this thread myself in order to test my claims, I will try to make a summary of useful points and equations at the start of each post when that section has run its course and i'm convinced of its validity.
I'm trying to colour code things for the most part, but I need to redo some things.
Red will be for the primary two functions that govern overall trade, Blue for individual component value functions, yellow for components of components, green for other functions of interest. But red unbolded text is also used for some notes.
Most of the code involved is found in either CvPlayerAI.cpp or CvTeamAI.cpp, some things cross into CvCityAI.cpp and other places, at some point i'll get around to sourcing each code extract.
By its very nature this is going to be extremely code heavy, if anyones going to find it useful it'll be the beancounter types. Perhaps some useful generalities useful to anybody will come out of this, but i'm not going to promise anything.
General Assumption of the Trade Table
As far as I know right now, the functions evaluate each side of the trade table from the Buyers perspective (as in both parties are 'buying' the others offer), giving a numerical value for each side.
There are two different minimum acceptable values to the AI, equal or greater than an AIs offer, and equal or greater than (1.1 * AIs offer).
offer =>AI Offer is the norm for tradings, while offer =>1.1 * AIs offer apprently only applies to resources/gpt trade renewals.
In general the human is going to give an AI more than the trade is worth, but fortunately the human does get some compensation for these unequal trades to AIs in the form of +diplo points for "fair trade", which has already been looked into by Tachywaxon link.
Tachy also covered the mechanics of another trade related diplo factor, "You have shared your technological discoveries with us"
The two parent functions governing all human-AI trades are;
CvPlayerAI::AI_considerOffer
Which is ultimately where the AI decides what trades with a human are acceptable, it also governs values for tribute and begging deals
CvPlayerAI::AI_dealVal
This is the utimate value function, all it does is add up the total value of everything on offer, the only part that acts slightly differently is AI_goldTradeValuePercent which is divided by 100 (giving 2 or 3) before being added. I'll spoiler the code for completion below,
Which is ultimately where the AI decides what trades with a human are acceptable, it also governs values for tribute and begging deals
CvPlayerAI::AI_dealVal
This is the utimate value function, all it does is add up the total value of everything on offer, the only part that acts slightly differently is AI_goldTradeValuePercent which is divided by 100 (giving 2 or 3) before being added. I'll spoiler the code for completion below,
Spoiler :
Code:
int CvPlayerAI::AI_dealVal(PlayerTypes ePlayer, const CLinkList<TradeData>* pList, bool bIgnoreAnnual, int iChange) const
{
CLLNode<TradeData>* pNode;
CvCity* pCity;
int iValue;
FAssertMsg(ePlayer != getID(), "shouldn't call this function on ourselves");
iValue = 0;
if (atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
{
iValue += GET_TEAM(getTeam()).AI_endWarVal(GET_PLAYER(ePlayer).getTeam());
}
for (pNode = pList->head(); pNode; pNode = pList->next(pNode))
{
FAssertMsg(!(pNode->m_data.m_bHidden), "(pNode->m_data.m_bHidden) did not return false as expected");
switch (pNode->m_data.m_eItemType)
{
case TRADE_TECHNOLOGIES:
iValue += GET_TEAM(getTeam()).AI_techTradeVal((TechTypes)(pNode->m_data.m_iData), GET_PLAYER(ePlayer).getTeam());
break;
case TRADE_RESOURCES:
if (!bIgnoreAnnual)
{
iValue += AI_bonusTradeVal(((BonusTypes)(pNode->m_data.m_iData)), ePlayer, iChange);
}
break;
case TRADE_CITIES:
pCity = GET_PLAYER(ePlayer).getCity(pNode->m_data.m_iData);
if (pCity != NULL)
{
iValue += AI_cityTradeVal(pCity);
}
break;
case TRADE_GOLD:
iValue += (pNode->m_data.m_iData * AI_goldTradeValuePercent()) / 100;
break;
case TRADE_GOLD_PER_TURN:
if (!bIgnoreAnnual)
{
iValue += AI_goldPerTurnTradeVal(pNode->m_data.m_iData);
}
break;
case TRADE_MAPS:
iValue += GET_TEAM(getTeam()).AI_mapTradeVal(GET_PLAYER(ePlayer).getTeam());
break;
case TRADE_SURRENDER:
if (!bIgnoreAnnual)
{
iValue += GET_TEAM(getTeam()).AI_surrenderTradeVal(GET_PLAYER(ePlayer).getTeam());
}
break;
case TRADE_VASSAL:
if (!bIgnoreAnnual)
{
iValue += GET_TEAM(getTeam()).AI_vassalTradeVal(GET_PLAYER(ePlayer).getTeam());
}
break;
case TRADE_OPEN_BORDERS:
iValue += GET_TEAM(getTeam()).AI_openBordersTradeVal(GET_PLAYER(ePlayer).getTeam());
break;
case TRADE_DEFENSIVE_PACT:
iValue += GET_TEAM(getTeam()).AI_defensivePactTradeVal(GET_PLAYER(ePlayer).getTeam());
break;
case TRADE_PEACE:
iValue += GET_TEAM(getTeam()).AI_makePeaceTradeVal(((TeamTypes)(pNode->m_data.m_iData)), GET_PLAYER(ePlayer).getTeam());
break;
case TRADE_WAR:
iValue += GET_TEAM(getTeam()).AI_declareWarTradeVal(((TeamTypes)(pNode->m_data.m_iData)), GET_PLAYER(ePlayer).getTeam());
break;
case TRADE_EMBARGO:
iValue += AI_stopTradingTradeVal(((TeamTypes)(pNode->m_data.m_iData)), ePlayer);
break;
case TRADE_CIVIC:
iValue += AI_civicTradeVal(((CivicTypes)(pNode->m_data.m_iData)), ePlayer);
break;
case TRADE_RELIGION:
iValue += AI_religionTradeVal(((ReligionTypes)(pNode->m_data.m_iData)), ePlayer);
break;
}
}
return iValue;
}
AI_techTradeVal
AI_bonusTradeVal
AI_cityTradeVal
AI_goldTradeValuePercent
AI_goldPerTurnTradeVal
AI_mapTradeVal
AI_makePeaceTradeVal
AI_declareWarTradeVal
AI_stopTradingTradeVal
AI_civicTradeVal
AI_religionTradeVal
AI_endWarVal
The four below are also in the dealval function, for trade table purposes we already know that you cannot trade anything for them in any way shape or form so their value must be equal. Open Borders and Defensive Pacts do have small values, (total city count of both teams for Open Borders, multiply that by 3 for Defensive Pacts) that could hypothetically trip diplomatic thresholds, but for reasonable use they are so small as to be safely ignored.
Strangely AI_Vassaltradeval may aswell not exist at all, as it just calls up AI_surrenderTradeVal which is 0....
This may be worth knowing in its own right, as it means that capitulating an AI doesn't eat into your war spoils.
AI_surrenderTradeVal
AI_vassalTradeVal
AI_openBordersTradeVal
AI_defensivePactTradeVal
AI_bonusTradeVal
AI_cityTradeVal
AI_goldTradeValuePercent
AI_goldPerTurnTradeVal
AI_mapTradeVal
AI_makePeaceTradeVal
AI_declareWarTradeVal
AI_stopTradingTradeVal
AI_civicTradeVal
AI_religionTradeVal
AI_endWarVal
The four below are also in the dealval function, for trade table purposes we already know that you cannot trade anything for them in any way shape or form so their value must be equal. Open Borders and Defensive Pacts do have small values, (total city count of both teams for Open Borders, multiply that by 3 for Defensive Pacts) that could hypothetically trip diplomatic thresholds, but for reasonable use they are so small as to be safely ignored.
Strangely AI_Vassaltradeval may aswell not exist at all, as it just calls up AI_surrenderTradeVal which is 0....
This may be worth knowing in its own right, as it means that capitulating an AI doesn't eat into your war spoils.
AI_surrenderTradeVal
AI_vassalTradeVal
AI_openBordersTradeVal
AI_defensivePactTradeVal
Some, if not all of the others have been done by others in the past, unfortunately I have't been able to find them so i've had to redo the work myself.
Theres a couple of other related functions I may check out later if I get success with the main part, most to do with when the I does something based on the same value used in the tradeval functions. So far i'm thinking about these,
CvPlayerAI::AI_commerceWeight
This gives weights to the different types of commerce depending on AI strategy. It is called up in CvPlayerAI::AI_civicVal
CvPlayerAI::AI_doPeace
CvPlayerAI::AI_counterPropose
This is what the AI goes through when you click "What would make this deal work?" Its another huge function.
CvPlayerAI::AI_doReligion
Controls AI state religion changes
CvPlayerAI::AI_doCivics
Controls AI civic swaps
CvPlayerAI::AI_isFinancialTrouble
Defines when an AI is in Financial trouble
There are quite a few places where the code asks if the AI is running various strategies, for now at least i'm not going to touch that function with a barge pole, and if I ever do it'll get its own thread.
To Do list
Unlinked functions
Testing for everything other than gold, GPT, map and tech values
AI_cityTradeval - awaiting AI_bonusTradeval
AI_declareWarTradeVal - Waiting to know what EstimateEndTurn is
AI_religionTradeVal - need to figure out end of AI_bestReligion
AI_endWarVal - quite a few bits and pieces to finish off
Proofreading to see if the summaries match the post after editing
AI_stopTradingTradeVal - deal value calcs
AI_civicvalue
Yellow links list
Tidying everything up