From e9d29ab7d5209d5eb07717421a67f1bf215fd930 Mon Sep 17 00:00:00 2001 From: RecursiveVision <66801010+RecursiveVision@users.noreply.github.com> Date: Wed, 10 Jul 2024 00:10:39 -0400 Subject: [PATCH] Make AI teammates less annoying --- CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp | 55 +++++++++++++++---- .../CvEspionageClasses.cpp | 21 ++++++- CvGameCoreDLL_Expansion2/CvHomelandAI.cpp | 2 +- CvGameCoreDLL_Expansion2/CvPlayerAI.cpp | 6 +- .../CvReligionClasses.cpp | 54 ++++++++++++++++-- CvGameCoreDLL_Expansion2/CvReligionClasses.h | 3 +- 6 files changed, 119 insertions(+), 22 deletions(-) diff --git a/CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp b/CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp index d0faba39d7..e8a3c4a0e2 100644 --- a/CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp +++ b/CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp @@ -18420,22 +18420,39 @@ void CvDiplomacyAI::SelectBestApproachTowardsMajorCiv(PlayerTypes ePlayer, bool // Someone else's? else if (!bIgnoreReligionDifferences) { + // Who controls the Holy City? + PlayerTypes eController = NO_PLAYER; const CvReligion* pReligion = GC.getGame().GetGameReligions()->GetReligion(eTheirStateReligion, NO_PLAYER); + if (MOD_BALANCE_VP) + { + if (pReligion) + { + CvCity* pHolyCity = pReligion->GetHolyCity(); + if (pHolyCity != NULL) + { + eController = pHolyCity->getOwner(); + } + } + } + else + { + eController = pReligion->m_eFounder; + } - // If the religion's founder is our teammate, don't apply a penalty if that teammate is still alive. - if (!IsTeammate((PlayerTypes)pReligion->m_eFounder) || GET_PLAYER((PlayerTypes)pReligion->m_eFounder).getNumCities() <= 0) + // If the religion's controller is our teammate, don't apply a penalty. + if (eController == NO_PLAYER || IsTeammate(eController)) { bDifferentReligions = true; - // If the religion's founder is THEIR teammate, treat it like a state religion. - if (pTheirDiplo->IsTeammate((PlayerTypes)pReligion->m_eFounder) && GET_PLAYER((PlayerTypes)pReligion->m_eFounder).getNumCities() > 0) + // If the religion's founder is THEIR teammate, treat it like an opposing state religion. + if (eController != NO_PLAYER && pTheirDiplo->IsTeammate(eController)) { vApproachScores[CIV_APPROACH_WAR] += (vApproachBias[CIV_APPROACH_WAR] * 2) + iReligiosityScore; vApproachScores[CIV_APPROACH_DECEPTIVE] += (vApproachBias[CIV_APPROACH_DECEPTIVE] * 2) + iReligiosityScore; vApproachScores[CIV_APPROACH_GUARDED] += (vApproachBias[CIV_APPROACH_GUARDED] * 2) + iReligiosityScore; // If it's the World Religion and their teammate controls its Holy City, we should work against them - if (GC.getGame().GetGameLeagues()->GetReligionSpreadStrengthModifier((PlayerTypes)pReligion->m_eFounder, eTheirStateReligion) > 0) + if (GC.getGame().GetGameLeagues()->GetReligionSpreadStrengthModifier(eController, eTheirStateReligion) > 0) { vApproachScores[CIV_APPROACH_WAR] += (vApproachBias[CIV_APPROACH_WAR] * 2) + iReligiosityScore; vApproachScores[CIV_APPROACH_HOSTILE] += (vApproachBias[CIV_APPROACH_HOSTILE] * 2) + iReligiosityScore; @@ -44195,7 +44212,7 @@ bool CvDiplomacyAI::IsPlayerOpposingReligion(PlayerTypes ePlayer) const return false; if (eOurReligion != eTheirReligion) - return true; + return CvReligionAIHelpers::PassesTeammateReligionCheck(eTheirReligion, GetID(), false); return false; } @@ -47796,16 +47813,30 @@ int CvDiplomacyAI::GetReligionScore(PlayerTypes ePlayer) // Someone else's? else { + PlayerTypes eController = NO_PLAYER; const CvReligion* pReligion = GC.getGame().GetGameReligions()->GetReligion(eTheirStateReligion, NO_PLAYER); - if (!pReligion) - return 0; + if (MOD_BALANCE_VP) + { + if (pReligion) + { + CvCity* pHolyCity = pReligion->GetHolyCity(); + if (pHolyCity != NULL) + { + eController = pHolyCity->getOwner(); + } + } + } + else + { + eController = pReligion->m_eFounder; + } - // If the religion's founder is our teammate, don't apply a penalty if that teammate is still alive. - if (IsTeammate((PlayerTypes)pReligion->m_eFounder) && GET_PLAYER((PlayerTypes)pReligion->m_eFounder).getNumCities() > 0) + // If the religion's founder is our teammate, don't apply a penalty. + if (eController != NO_PLAYER && IsTeammate(eController)) return 0; - // If the religion's founder is THEIR teammate, treat it like a state religion. - if (GET_PLAYER(ePlayer).GetDiplomacyAI()->IsTeammate((PlayerTypes)pReligion->m_eFounder) && GET_PLAYER((PlayerTypes)pReligion->m_eFounder).getNumCities() > 0) + // If the religion's founder is THEIR teammate, treat it like an opposing state religion. + if (eController != NO_PLAYER && GET_PLAYER(ePlayer).GetDiplomacyAI()->IsTeammate(eController)) { iOpinionWeight = /*5*/ GD_INT_GET(OPINION_WEIGHT_DIFFERENT_OWNED_RELIGIONS) * iEraMod; diff --git a/CvGameCoreDLL_Expansion2/CvEspionageClasses.cpp b/CvGameCoreDLL_Expansion2/CvEspionageClasses.cpp index 8e89eca8ef..517ea746ea 100644 --- a/CvGameCoreDLL_Expansion2/CvEspionageClasses.cpp +++ b/CvGameCoreDLL_Expansion2/CvEspionageClasses.cpp @@ -9296,6 +9296,11 @@ std::vector CvEspionageAI::BuildMinorCityList(bool bLogAllChoice if (pMinorCapital->IsRazing()) continue; + // Don't mess with our teammates' allies. + PlayerTypes eAlly = pMinorCivAI->GetAlly(); + if (eAlly != NO_PLAYER && pDiploAI->IsTeammate(eAlly)) + continue; + //Is there a proposal (not resolution) involving a Sphere of Influence or Open Door? CvLeague* pLeague = GC.getGame().GetGameLeagues()->GetActiveLeague(); bool bBlockingProposal = false; @@ -9449,7 +9454,6 @@ std::vector CvEspionageAI::BuildMinorCityList(bool bLogAllChoice } // Influence status - PlayerTypes eAlly = pMinorCivAI->GetAlly(); bool bAllied = eAlly == m_pPlayer->GetID(); int iAllyInfluence = (eAlly != NO_PLAYER) ? pMinorCivAI->GetFriendshipLevelWithMajor(eAlly) : 0; int iOurInfluence = pMinorCivAI->GetFriendshipLevelWithMajor(m_pPlayer->GetID()); @@ -9794,6 +9798,21 @@ void CvEspionageAI::EvaluateMinorCivSpies(void) } } + // Don't mess with our teammates' allies. + PlayerTypes eAlly = pMinorCivAI->GetAlly(); + if (eAlly != NO_PLAYER && eAlly != m_pPlayer->GetID() && GET_PLAYER(eAlly).getTeam() == m_pPlayer->getTeam()) + { + CvEspionageSpy* pSpy = &(pEspionage->m_aSpyList[ui]); + pSpy->m_bEvaluateReassignment = true; + if (GC.getLogging()) + { + CvString strMsg; + strMsg.Format("Re-eval: teammate is minor civ ally, %d,", ui); + strMsg += GetLocalizedText(pCity->getNameKey()); + pEspionage->LogEspionageMsg(strMsg); + } + } + //Is there a proposal (not resolution) involving a Sphere of Influence or Open Door? CvLeague* pLeague = GC.getGame().GetGameLeagues()->GetActiveLeague(); if (pLeague != NULL) diff --git a/CvGameCoreDLL_Expansion2/CvHomelandAI.cpp b/CvGameCoreDLL_Expansion2/CvHomelandAI.cpp index ee98b2b5fd..48963d7b6c 100644 --- a/CvGameCoreDLL_Expansion2/CvHomelandAI.cpp +++ b/CvGameCoreDLL_Expansion2/CvHomelandAI.cpp @@ -4522,7 +4522,7 @@ void CvHomelandAI::ExecuteInquisitorMoves() { vBurnedTargets.push_back( make_pair(pUnit->GetID(),pTarget->plot()->GetPlotIndex())); - if (pUnit->CanRemoveHeresy(pTarget->plot()) && CvReligionAIHelpers::ShouldRemoveHeresy(pTarget,pUnit->GetReligionData()->GetReligion())) + if (pUnit->CanRemoveHeresy(pTarget->plot()) && CvReligionAIHelpers::ShouldRemoveHeresy(pTarget,pUnit->GetReligionData()->GetReligion(),m_pPlayer->GetID())) { if (iTargetTurns == 0) { diff --git a/CvGameCoreDLL_Expansion2/CvPlayerAI.cpp b/CvGameCoreDLL_Expansion2/CvPlayerAI.cpp index d9797d18df..61e3e06d26 100644 --- a/CvGameCoreDLL_Expansion2/CvPlayerAI.cpp +++ b/CvGameCoreDLL_Expansion2/CvPlayerAI.cpp @@ -2500,6 +2500,11 @@ int CvPlayerAI::ScoreCityForMessenger(CvCity* pCity, CvUnit* pUnit) if (pMinorCivAI->IsQuestInfluenceDisabled(GetID())) return 0; + // Don't compete with our teammates for Influence. + PlayerTypes eAlliedPlayer = pMinorCivAI->GetAlly(); + if (eAlliedPlayer != NO_PLAYER && eAlliedPlayer != GetID() && GET_PLAYER(eAlliedPlayer).getTeam() == getTeam() && GET_PLAYER(eAlliedPlayer).getNumCities() > 0) + return 0; + // They captured one of our cities? Do not raise influence; we want to recapture. if (GetNumOurCitiesOwnedBy(kMinor.GetID()) > 0) return 0; @@ -2730,7 +2735,6 @@ int CvPlayerAI::ScoreCityForMessenger(CvCity* pCity, CvUnit* pUnit) // ************************** int iFriendshipWithMinor = pMinorCivAI->GetBaseFriendshipWithMajor(GetID()); - PlayerTypes eAlliedPlayer = pMinorCivAI->GetAlly(); int iHighestInfluence = 0; // Loop through other players to see if we can pass them in influence diff --git a/CvGameCoreDLL_Expansion2/CvReligionClasses.cpp b/CvGameCoreDLL_Expansion2/CvReligionClasses.cpp index 9225a05ac6..dbd4c41dce 100644 --- a/CvGameCoreDLL_Expansion2/CvReligionClasses.cpp +++ b/CvGameCoreDLL_Expansion2/CvReligionClasses.cpp @@ -6393,7 +6393,7 @@ CvCity *CvReligionAI::ChooseProphetConversionCity(CvUnit* pUnit, int* piTurns) c int iHeretics = pLoopCity->GetCityReligions()->GetFollowersOtherReligions(eReligion,true) + pLoopCity->GetCityReligions()->GetNumFollowers(NO_RELIGION); int iDistanceToHolyCity = plotDistance(pLoopCity->getX(), pLoopCity->getY(), pHolyCity->getX(), pHolyCity->getY()); - if (eMajorityReligion == eReligion) + if (eMajorityReligion == eReligion || !CvReligionAIHelpers::PassesTeammateReligionCheck(eMajorityReligion, m_pPlayer->GetID(), true)) continue; else { @@ -6478,6 +6478,9 @@ CvCity *CvReligionAI::ChooseProphetConversionCity(CvUnit* pUnit, int* piTurns) c if (eMajorityReligion == eReligion) continue; + if (!CvReligionAIHelpers::PassesTeammateReligionCheck(eMajorityReligion, m_pPlayer->GetID(), false)) + continue; + int iOurPressure = max(1,pCR->GetPressurePerTurn(eReligion)); int iMajorityPressure = pCR->GetPressurePerTurn(eMajorityReligion); int iDistanceToHolyCity = plotDistance(pLoopCity->getX(), pLoopCity->getY(), pHolyCity->getX(), pHolyCity->getY()); @@ -10796,7 +10799,11 @@ int CvReligionAI::ScoreCityForMissionary(CvCity* pCity, CvUnit* pUnit, ReligionT } } - if (pCity->GetCityReligions()->GetReligiousMajority() <= RELIGION_PANTHEON) + ReligionTypes eMajorityReligion = pCity->GetCityReligions()->GetReligiousMajority(); + if (!CvReligionAIHelpers::PassesTeammateReligionCheck(eMajorityReligion, m_pPlayer->GetID(), pCity->getOwner() == m_pPlayer->GetID())) + return 0; + + if (eMajorityReligion <= RELIGION_PANTHEON) { //fifty percent bonus if not religion at the moment iScore *= 3; @@ -10866,7 +10873,7 @@ int CvReligionAI::ScoreCityForInquisitorOffensive(CvCity* pCity, CvUnit* pUnit, //Inquisitors are more expensive than Missionaries, so don't be overly zealous here //Looking to remove heresy? - if (CvReligionAIHelpers::ShouldRemoveHeresy(pCity,eMyReligion)) + if (CvReligionAIHelpers::ShouldRemoveHeresy(pCity,eMyReligion,m_pPlayer->GetID())) { // How much impact would using the inquistor have? let's ignore resilience here ... int iNumOtherFollowers = pCity->GetCityReligions()->GetFollowersOtherReligions(eMyReligion); @@ -10912,7 +10919,7 @@ int CvReligionAI::ScoreCityForInquisitorDefensive(CvCity* pCity, CvUnit* pUnit, return 0; //sometimes we need more active measures - if (CvReligionAIHelpers::ShouldRemoveHeresy(pCity,eMyReligion)) + if (CvReligionAIHelpers::ShouldRemoveHeresy(pCity,eMyReligion,m_pPlayer->GetID())) return 0; //see how much we want to defend passively here @@ -11661,7 +11668,7 @@ bool CvReligionAIHelpers::DoesUnitPassFaithPurchaseCheck(CvPlayer &kPlayer, Unit return bRtnValue; } -bool CvReligionAIHelpers::ShouldRemoveHeresy(CvCity* pCity, ReligionTypes eTrueReligion) +bool CvReligionAIHelpers::ShouldRemoveHeresy(CvCity* pCity, ReligionTypes eTrueReligion, PlayerTypes ePlayer) { ReligionTypes eMajorityReligion = pCity->GetCityReligions()->GetReligiousMajority(); if (eMajorityReligion == NO_RELIGION) @@ -11669,10 +11676,15 @@ bool CvReligionAIHelpers::ShouldRemoveHeresy(CvCity* pCity, ReligionTypes eTrueR ReligionTypes eMostPowerfulReligion = pCity->GetCityReligions()->GetReligionByAccumulatedPressure(0); if (eMostPowerfulReligion <= RELIGION_PANTHEON) return false; + if (!CvReligionAIHelpers::PassesTeammateReligionCheck(eMostPowerfulReligion, ePlayer, true)) + return false; if (eMostPowerfulReligion != eTrueReligion) return true; ReligionTypes eRunnerUpReligion = pCity->GetCityReligions()->GetReligionByAccumulatedPressure(1); + if (!CvReligionAIHelpers::PassesTeammateReligionCheck(eRunnerUpReligion, ePlayer, true)) + return false; + int iPPT1 = pCity->GetCityReligions()->GetPressurePerTurn(eTrueReligion); int iPPT2 = pCity->GetCityReligions()->GetPressurePerTurn(eRunnerUpReligion); //want a missionary if we are losing ground @@ -11684,11 +11696,41 @@ bool CvReligionAIHelpers::ShouldRemoveHeresy(CvCity* pCity, ReligionTypes eTrueR //never waste an inquisitor on a pantheon city, use a missionary instead return false; } - else if (eMajorityReligion != eTrueReligion) + else if (eMajorityReligion != eTrueReligion && CvReligionAIHelpers::PassesTeammateReligionCheck(eMajorityReligion, ePlayer, true)) { //the easy case return true; } return false; +} + +/// Avoid competing with our teammates' religions. +bool CvReligionAIHelpers::PassesTeammateReligionCheck(ReligionTypes eReligion, PlayerTypes ePlayer, bool bMustBeHuman) +{ + PlayerTypes eController = NO_PLAYER; + const CvReligion* pReligion = GC.getGame().GetGameReligions()->GetReligion(eReligion, NO_PLAYER); + if (MOD_BALANCE_VP) + { + if (pReligion) + { + CvCity* pHolyCity = pReligion->GetHolyCity(); + if (pHolyCity != NULL) + { + eController = pHolyCity->getOwner(); + } + } + } + else + { + eController = pReligion->m_eFounder; + } + + if (eController == NO_PLAYER || eController == ePlayer) + return true; + + if (bMustBeHuman && !GET_PLAYER(eController).isHuman()) + return true; + + return GET_PLAYER(eController).getTeam() != GET_PLAYER(ePlayer).getTeam(); } \ No newline at end of file diff --git a/CvGameCoreDLL_Expansion2/CvReligionClasses.h b/CvGameCoreDLL_Expansion2/CvReligionClasses.h index 27ae0f234a..a1cb0e7953 100644 --- a/CvGameCoreDLL_Expansion2/CvReligionClasses.h +++ b/CvGameCoreDLL_Expansion2/CvReligionClasses.h @@ -597,7 +597,8 @@ namespace CvReligionAIHelpers CvCity *GetBestCityFaithUnitPurchase(CvPlayer &kPlayer, UnitTypes eUnit, ReligionTypes eReligion); CvCity *GetBestCityFaithBuildingPurchase(CvPlayer &kPlayer, BuildingTypes eBuilding, ReligionTypes eReligion); bool DoesUnitPassFaithPurchaseCheck(CvPlayer &kPlayer, UnitTypes eUnit); - bool ShouldRemoveHeresy(CvCity* pCity, ReligionTypes eTrueReligion); + bool ShouldRemoveHeresy(CvCity* pCity, ReligionTypes eTrueReligion, PlayerTypes ePlayer); + bool PassesTeammateReligionCheck(ReligionTypes eReligion, PlayerTypes ePlayer, bool bMustBeHuman); } #endif //CIV5_RELIGION_CLASSES_H \ No newline at end of file