/// Human making a demand of the AI
DemandResponseTypes CvDealAI::DoHumanDemand(CvDeal* pDeal)
{
DemandResponseTypes eResponse = NO_DEMAND_RESPONSE_TYPE;
PlayerTypes eFromPlayer = pDeal->GetOtherPlayer(GetPlayer()->GetID()); // Playing it safe, should be OK to use pDeal->GetFromPlayer() but code was using GetActivePlayer so maybe the From field wasn't always the human (although in my testing it was fine!)
PlayerTypes eMyPlayer = GetPlayer()->GetID();
int iValueWillingToGiveUp = 0;
CvDiplomacyAI* pDiploAI = GET_PLAYER(eMyPlayer).GetDiplomacyAI();
#if defined(MOD_DIPLOMACY_CIV4_FEATURES)
MajorCivApproachTypes eApproach = pDiploAI->GetMajorCivApproach(eFromPlayer, /*bHideTrueFeelings*/ true);
StrengthTypes eMilitaryStrength = pDiploAI->GetPlayerMilitaryStrengthComparedToUs(eFromPlayer);
StrengthTypes eEconomicStrength = pDiploAI->GetPlayerEconomicStrengthComparedToUs(eFromPlayer);
AggressivePostureTypes eMilitaryPosture = pDiploAI->GetMilitaryAggressivePosture(eFromPlayer);
PlayerProximityTypes eProximity = GET_PLAYER(eMyPlayer).GetProximityToPlayer(eFromPlayer);
// If we're friends with the demanding player, it's actually a Request for Help. Let's evaluate in a separate function and come back here
if(MOD_DIPLOMACY_CIV4_FEATURES && pDiploAI->IsDoFAccepted(eFromPlayer))
{
eResponse = GetRequestForHelpResponse(pDeal);
}
else
{
#endif
// Too soon for another demand?
if(pDiploAI->IsDemandTooSoon(eFromPlayer))
eResponse = DEMAND_RESPONSE_REFUSE_TOO_SOON;
// Not too soon for a demand
else
{
bool bWeak = false;
bool bHostile = false;
// Initial odds of giving in to ANY demand are based on the player's boldness (which is also tied to the player's likelihood of going for world conquest)
int iOddsOfGivingIn = (10 - pDiploAI->GetBoldness()) * 10;
// Unforgivable: AI will never give in
if (pDiploAI->GetMajorCivOpinion(eFromPlayer) == MAJOR_CIV_OPINION_UNFORGIVABLE)
{
bHostile = true;
iOddsOfGivingIn -= 25;
}
// Hostile: AI will never give in
if (eApproach == MAJOR_CIV_APPROACH_HOSTILE)
{
bHostile = true;
iOddsOfGivingIn -= 25;
}
// They are very far away and have no units near us (from what we can tell): AI will never give in
if (eProximity <= PLAYER_PROXIMITY_FAR && eMilitaryPosture == AGGRESSIVE_POSTURE_NONE)
{
bWeak = true;
iOddsOfGivingIn -= 25;
}
// Our military is stronger: AI will never give in
if (eMilitaryStrength < STRENGTH_AVERAGE && eEconomicStrength < STRENGTH_AVERAGE)
{
bWeak = true;
iOddsOfGivingIn -= 25;
}
iValueWillingToGiveUp = 0;
#if defined(MOD_DIPLOMACY_CIV4_FEATURES)
//Vassals give in to demands more often, and give more away.
if(MOD_DIPLOMACY_CIV4_FEATURES)
{
TeamTypes eMasterTeam = GET_TEAM(GET_PLAYER(eMyPlayer).getTeam()).GetMaster();
if(eMasterTeam == GET_PLAYER(eFromPlayer).getTeam())
{
iOddsOfGivingIn += 100;
iValueWillingToGiveUp += 500;
}
}
switch(pDiploAI->GetWarmongerThreat(eFromPlayer))
{
case THREAT_NONE:
{
iOddsOfGivingIn -= 10;
break;
}
case THREAT_MINOR:
{
iOddsOfGivingIn -= 5;
break;
}
case THREAT_MAJOR:
{
iOddsOfGivingIn += 10;
break;
}
case THREAT_CRITICAL:
{
iOddsOfGivingIn += 25;
break;
}
}
switch (pDiploAI->GetMilitaryAggressivePosture(eFromPlayer))
{
case AGGRESSIVE_POSTURE_NONE:
{
iOddsOfGivingIn -= 10;
break;
}
case AGGRESSIVE_POSTURE_LOW:
{
iOddsOfGivingIn -= 5;
break;
}
case AGGRESSIVE_POSTURE_MEDIUM:
{
iOddsOfGivingIn += 10;
break;
}
case AGGRESSIVE_POSTURE_HIGH:
{
iOddsOfGivingIn += 25;
break;
}
case AGGRESSIVE_POSTURE_INCREDIBLE:
{
iOddsOfGivingIn += 50;
break;
}
}
#endif
// If we're afraid we're more likely to give in
if(eApproach == MAJOR_CIV_APPROACH_AFRAID)
{
iOddsOfGivingIn += 50;
iValueWillingToGiveUp += 200;
}
// Not afraid
else
{
// How strong are they compared to us?
switch(eMilitaryStrength)
{
case STRENGTH_PATHETIC:
iOddsOfGivingIn += -50;
iValueWillingToGiveUp += 5;
break;
case STRENGTH_WEAK:
iOddsOfGivingIn += -50;
iValueWillingToGiveUp += 10;
break;
case STRENGTH_POOR:
iOddsOfGivingIn += -25;
iValueWillingToGiveUp += 20;
break;
case STRENGTH_AVERAGE:
iOddsOfGivingIn += 0;
iValueWillingToGiveUp += 40;
break;
case STRENGTH_STRONG:
iOddsOfGivingIn += 15;
iValueWillingToGiveUp += 60;
break;
case STRENGTH_POWERFUL:
iOddsOfGivingIn += 25;
iValueWillingToGiveUp += 80;
break;
case STRENGTH_IMMENSE:
iOddsOfGivingIn += 50;
iValueWillingToGiveUp += 100;
break;
default:
break;
}
switch (eEconomicStrength)
{
case STRENGTH_PATHETIC:
iOddsOfGivingIn += -50;
iValueWillingToGiveUp += 5;
break;
case STRENGTH_WEAK:
iOddsOfGivingIn += -50;
iValueWillingToGiveUp += 10;
break;
case STRENGTH_POOR:
iOddsOfGivingIn += -25;
iValueWillingToGiveUp += 25;
break;
case STRENGTH_AVERAGE:
iOddsOfGivingIn += 0;
iValueWillingToGiveUp += 40;
break;
case STRENGTH_STRONG:
iOddsOfGivingIn += 15;
iValueWillingToGiveUp += 60;
break;
case STRENGTH_POWERFUL:
iOddsOfGivingIn += 25;
iValueWillingToGiveUp += 80;
break;
case STRENGTH_IMMENSE:
iOddsOfGivingIn += 50;
iValueWillingToGiveUp += 100;
break;
default:
break;
}
}
// IMPORTANT NOTE: This APPEARS to be very bad for multiplayer, but the only changes made to the game state are the fact that the human
// made a demand, and if the deal went through. These are both sent over the network later in this function.
int iRand = GC.getGame().getSmallFakeRandNum(100, iValueWillingToGiveUp);
// Are they going to say no matter what?
if (iRand > iOddsOfGivingIn)
{
if (bHostile)
eResponse = DEMAND_RESPONSE_REFUSE_HOSTILE;
else if (bWeak)
eResponse = DEMAND_RESPONSE_REFUSE_WEAK;
else
eResponse = DEMAND_RESPONSE_REFUSE_TOO_MUCH;
}
#if defined(MOD_DIPLOMACY_CIV4_FEATURES)
}
#endif
}
// Possibility exists that the AI will accept
if(eResponse == NO_DEAL_RESPONSE_TYPE)
{
int iValueDemanded = 0;
int iGPT = GetPlayer()->GetTreasury()->CalculateBaseNetGold();
int iTempGold;
int iModdedGoldValue;
// Loop through items in this deal
TradedItemList::iterator it;
for(it = pDeal->m_TradedItems.begin(); it != pDeal->m_TradedItems.end(); ++it)
{
// Item from this AI
if(it->m_eFromPlayer == eMyPlayer)
{
switch(it->m_eItemType)
{
// Gold
case TRADE_ITEM_GOLD:
{
iTempGold = it->m_iData1;
if (iGPT > 0)
iModdedGoldValue = iTempGold * 5 / iGPT;
else
iModdedGoldValue = 0;
iValueDemanded += max(iTempGold, iModdedGoldValue);
break;
}
// GPT
case TRADE_ITEM_GOLD_PER_TURN:
{
iValueDemanded += (it->m_iData1 * it->m_iDuration * 50 / 100);
break;
}
// Resources
case TRADE_ITEM_RESOURCES:
{
ResourceTypes eResource = (ResourceTypes) it->m_iData1;
ResourceUsageTypes eUsage = GC.getResourceInfo(eResource)->getResourceUsage();
if(eUsage == RESOURCEUSAGE_LUXURY)
iValueDemanded += 100;
else if(eUsage == RESOURCEUSAGE_STRATEGIC)
iValueDemanded += (25 * it->m_iData2);
break;
}
// Open Borders
case TRADE_ITEM_OPEN_BORDERS:
{
iValueDemanded += 25;
break;
}
case TRADE_ITEM_CITIES:
case TRADE_ITEM_DEFENSIVE_PACT:
case TRADE_ITEM_RESEARCH_AGREEMENT:
{
eResponse = DEMAND_RESPONSE_REFUSE_TOO_MUCH;
break;
}
case TRADE_ITEM_PERMANENT_ALLIANCE:
case TRADE_ITEM_THIRD_PARTY_PEACE:
case TRADE_ITEM_THIRD_PARTY_WAR:
case TRADE_ITEM_THIRD_PARTY_EMBARGO:
default:
iValueDemanded += 75;
break;
}
}
}
if (iValueDemanded == 0)
eResponse = DEMAND_RESPONSE_REFUSE_WEAK;
// No illegal items in the demand
else if (eResponse == NO_DEAL_RESPONSE_TYPE)
{
if(iValueDemanded <= iValueWillingToGiveUp)
eResponse = DEMAND_RESPONSE_ACCEPT;
else
eResponse = DEMAND_RESPONSE_REFUSE_TOO_MUCH;
}
}
// Have to sent AI response through the network - it affects AI behavior
#if defined(MOD_DIPLOMACY_CIV4_FEATURES)
if(MOD_DIPLOMACY_CIV4_FEATURES && pDiploAI->IsDoFAccepted(eFromPlayer))
{
GC.getGame().DoFromUIDiploEvent(FROM_UI_DIPLO_EVENT_HUMAN_REQUEST, eMyPlayer, /*iData1*/ eResponse, -1);
}
else
{
#endif
GC.getGame().DoFromUIDiploEvent(FROM_UI_DIPLO_EVENT_HUMAN_DEMAND, eMyPlayer, /*iData1*/ eResponse, -1);
#if defined(MOD_DIPLOMACY_CIV4_FEATURES)
}
#endif
// Demand agreed to
#if defined(MOD_DIPLOMACY_CIV4_FEATURES)
if(eResponse == DEMAND_RESPONSE_ACCEPT || (MOD_DIPLOMACY_CIV4_FEATURES && eResponse == DEMAND_RESPONSE_GIFT_ACCEPT))
#else
if(eResponse == DEMAND_RESPONSE_ACCEPT)
#endif
{
CvDeal kDeal = *pDeal;
//gDLL->sendNetDealAccepted(eFromPlayer, GetPlayer()->GetID(), kDeal, -1, -1, -1);
GC.GetEngineUserInterface()->SetDealInTransit(true);
auto_ptr<ICvDeal1> pDllDeal = GC.WrapDealPointer(&kDeal);
gDLL->sendNetDemandAccepted(eFromPlayer, GetPlayer()->GetID(), pDllDeal.get());
}
return eResponse;
}