From 21da13ab81ef4bbe22f752a042ed89ff9d463901 Mon Sep 17 00:00:00 2001 From: RecursiveVision <66801010+RecursiveVision@users.noreply.github.com> Date: Sat, 7 Dec 2024 17:14:59 -0500 Subject: [PATCH] Fix a very nasty diplomacy bug More assert fixes in Diplo AI --- CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp | 44 ++++++++++++++-------- CvGameCoreDLL_Expansion2/CvMilitaryAI.cpp | 31 +++++++-------- 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp b/CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp index f2773066b6..79453dc916 100644 --- a/CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp +++ b/CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp @@ -3618,6 +3618,10 @@ void CvDiplomacyAI::SetCivApproach(PlayerTypes ePlayer, CivApproachTypes eApproa // Planning war? Pick a surface approach to disguise our war plans. if (eApproach == CIV_APPROACH_WAR) { + // No surface approaches for City-States! + if (ePlayer >= MAX_MAJOR_CIVS) + return; + // If we're targeting them for a demand, cancel that if (bResetAttackOperations && GetDemandTargetPlayer() == ePlayer) SetDemandTargetPlayer(NO_PLAYER); @@ -3709,7 +3713,8 @@ void CvDiplomacyAI::SetCivApproach(PlayerTypes ePlayer, CivApproachTypes eApproa } } - SetCachedSurfaceApproach(ePlayer, -1); + if (ePlayer < MAX_MAJOR_CIVS) + SetCachedSurfaceApproach(ePlayer, -1); } /// What is our Strategic Diplomatic Approach towards this Major Civ? @@ -7205,6 +7210,9 @@ void CvDiplomacyAI::SetPlayerEverCapturedCapital(PlayerTypes ePlayer, bool bValu /// Returns if this player's original capital was captured by ePlayer bool CvDiplomacyAI::IsCapitalCapturedBy(PlayerTypes ePlayer, bool bCurrently, bool bTeammates, bool bCheckEver) const { + if (GET_PLAYER(ePlayer).isMinorCiv()) + bCurrently = true; + if (!bCurrently && (IsPlayerCapturedCapital(ePlayer) || (bCheckEver && IsPlayerEverCapturedCapital(ePlayer)))) return true; @@ -7266,6 +7274,9 @@ void CvDiplomacyAI::SetPlayerEverCapturedHolyCity(PlayerTypes ePlayer, bool bVal /// Returns if this player's Holy City was captured by ePlayer bool CvDiplomacyAI::IsHolyCityCapturedBy(PlayerTypes ePlayer, bool bCurrently, bool bTeammates, bool bCheckEver) const { + if (GET_PLAYER(ePlayer).isMinorCiv()) + bCurrently = true; + if (!bCurrently && (IsPlayerCapturedHolyCity(ePlayer) || (bCheckEver && IsPlayerEverCapturedHolyCity(ePlayer)))) return true; @@ -12475,12 +12486,15 @@ int CvDiplomacyAI::CountAggressiveMilitaryScore(PlayerTypes ePlayer, bool bHalve CvTeam& kTeam = GET_TEAM(kPlayer.getTeam()); TeamTypes eOurTeam = GetTeam(); - // Don't be frightened of vassals, they can't declare war on their own. - if (kPlayer.IsVassalOfSomeone() && !IsAtWar(ePlayer)) - return 0; + if (!IsAtWar(ePlayer)) + { + // Don't be frightened of City-States or vassals, they can't declare war on their own. + if (kPlayer.isMinorCiv() || kPlayer.IsVassalOfSomeone()) + return 0; + } // Vassals count units for the purposes of determining deterrence against independence - if (!IsVassal(ePlayer)) + if (kPlayer.isMajorCiv() && !IsVassal(ePlayer)) { // We're allowing them Open Borders? We shouldn't care. if (GET_TEAM(GetTeam()).IsAllowsOpenBordersToTeam(kPlayer.getTeam())) @@ -12756,7 +12770,7 @@ void CvDiplomacyAI::DoUpdatePlotBuyingAggressivePostures() vector vPlayersToReevaluate; // Loop through all (known) Players - for (int iPlayerLoop = 0; iPlayerLoop < MAX_CIV_PLAYERS; iPlayerLoop++) + for (int iPlayerLoop = 0; iPlayerLoop < MAX_MAJOR_CIVS; iPlayerLoop++) { PlayerTypes ePlayer = (PlayerTypes) iPlayerLoop; @@ -13604,7 +13618,7 @@ void CvDiplomacyAI::DoUpdateSaneDiplomaticTargets() } // No new wars! Exception for endgame aggression and players who captured our key cities. - if (bNoNewWars && !IsEndgameAggressiveTo(ePlayer) && !IsCapitalCapturedBy(ePlayer, true, false) && !IsHolyCityCapturedBy(ePlayer, true, false)) + if (bNoNewWars && !IsCapitalCapturedBy(ePlayer, true, false) && !IsHolyCityCapturedBy(ePlayer, true, false) && (!GET_PLAYER(ePlayer).isMajorCiv() || !IsEndgameAggressiveTo(ePlayer))) { SetSaneDiplomaticTarget(ePlayer, false); continue; @@ -51700,17 +51714,17 @@ void CvDiplomacyAI::LogStatus() LogMilitaryStrength(strOutBuf, eLoopPlayer); LogTargetValue(strOutBuf, eLoopPlayer); LogMilitaryAggressivePosture(strOutBuf, eLoopPlayer); - LogWarmongerThreat(strOutBuf, eLoopPlayer); - - LogPlotBuyingAggressivePosture(strOutBuf, eLoopPlayer); LogLandDispute(strOutBuf, eLoopPlayer); - LogVictoryDispute(strOutBuf, eLoopPlayer); - LogWonderDispute(strOutBuf, eLoopPlayer); - LogMinorCivDispute(strOutBuf, eLoopPlayer); - // Other Player's Estimated Grand Strategy - if(!GET_PLAYER(eLoopPlayer).isMinorCiv()) + if (!GET_PLAYER(eLoopPlayer).isMinorCiv()) { + LogWarmongerThreat(strOutBuf, eLoopPlayer); + LogPlotBuyingAggressivePosture(strOutBuf, eLoopPlayer); + LogVictoryDispute(strOutBuf, eLoopPlayer); + LogWonderDispute(strOutBuf, eLoopPlayer); + LogMinorCivDispute(strOutBuf, eLoopPlayer); + + // Other Player's Estimated Grand Strategy AIGrandStrategyTypes eGrandStrategy = GetPlayer()->GetGrandStrategyAI()->GetGuessOtherPlayerActiveGrandStrategy(eLoopPlayer); CvAIGrandStrategyXMLEntry* pEntry = eGrandStrategy != NO_AIGRANDSTRATEGY ? GC.getAIGrandStrategyInfo(eGrandStrategy) : NULL; diff --git a/CvGameCoreDLL_Expansion2/CvMilitaryAI.cpp b/CvGameCoreDLL_Expansion2/CvMilitaryAI.cpp index 1bd3325d9e..571d1f2562 100644 --- a/CvGameCoreDLL_Expansion2/CvMilitaryAI.cpp +++ b/CvGameCoreDLL_Expansion2/CvMilitaryAI.cpp @@ -2145,33 +2145,32 @@ void CvMilitaryAI::UpdateMilitaryStrategies() void CvMilitaryAI::DoNuke(PlayerTypes ePlayer) { + // if we need to nuke the Barbarians, we've already lost this game 10x over + if (ePlayer == BARBARIAN_PLAYER) + return; + bool bLaunchNuke = false; StrengthTypes eMilitaryStrength = m_pPlayer->GetDiplomacyAI()->GetRawMilitaryStrengthComparedToUs(ePlayer); WarStateTypes eCurrentWarState = m_pPlayer->GetDiplomacyAI()->GetWarState(ePlayer); - // only evaluate nukes when we have nukes and we've declared war on someone + // only evaluate nukes when we have nukes if (m_pPlayer->getNumNukeUnits() > 0) { - // they nuked us, so we can nuke them. - if (m_pPlayer->GetDiplomacyAI()->GetNumTimesNuked(ePlayer) > 0) - { - bLaunchNuke = true; - } - // if we already nuked them, uhhh, keep it up! - else if (GET_PLAYER(ePlayer).GetDiplomacyAI()->GetNumTimesNuked(m_pPlayer->GetID()) > 0) - { - bLaunchNuke = true; - } // if we will surely lose this war anyway, we might as well nuke them! - else if (eMilitaryStrength == STRENGTH_IMMENSE || eCurrentWarState == WAR_STATE_NEARLY_DEFEATED) + if (eMilitaryStrength == STRENGTH_IMMENSE || eCurrentWarState == WAR_STATE_NEARLY_DEFEATED) { bLaunchNuke = true; } - else + else if (GET_PLAYER(ePlayer).isMajorCiv()) { - bool bRollForNuke = false; - if (GET_PLAYER(ePlayer).isMajorCiv()) + // if one of us has already nuked the other...well, I'll keep the trend going! + if (m_pPlayer->GetDiplomacyAI()->GetNumTimesNuked(ePlayer) > 0 || GET_PLAYER(ePlayer).GetDiplomacyAI()->GetNumTimesNuked(m_pPlayer->GetID()) > 0) + { + bLaunchNuke = true; + } + else { + bool bRollForNuke = false; CivOpinionTypes eCivOpinion = m_pPlayer->GetDiplomacyAI()->GetCivOpinion(ePlayer); if (eMilitaryStrength == STRENGTH_POWERFUL || eCurrentWarState <= WAR_STATE_TROUBLED) { @@ -2204,9 +2203,7 @@ void CvMilitaryAI::DoNuke(PlayerTypes ePlayer) } if (bLaunchNuke) - { RequestNukeAttack(ePlayer); - } } void CvMilitaryAI::SetupInstantDefenses(PlayerTypes ePlayer)