Skip to content

Commit

Permalink
Make AI teammates less annoying
Browse files Browse the repository at this point in the history
  • Loading branch information
RecursiveVision committed Jul 10, 2024
1 parent 698db40 commit e9d29ab
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 22 deletions.
55 changes: 43 additions & 12 deletions CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;

Expand Down
21 changes: 20 additions & 1 deletion CvGameCoreDLL_Expansion2/CvEspionageClasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9296,6 +9296,11 @@ std::vector<ScoreCityEntry> 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;
Expand Down Expand Up @@ -9449,7 +9454,6 @@ std::vector<ScoreCityEntry> 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());
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion CvGameCoreDLL_Expansion2/CvHomelandAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
6 changes: 5 additions & 1 deletion CvGameCoreDLL_Expansion2/CvPlayerAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
54 changes: 48 additions & 6 deletions CvGameCoreDLL_Expansion2/CvReligionClasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -11661,18 +11668,23 @@ 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)
{
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
Expand All @@ -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();
}
3 changes: 2 additions & 1 deletion CvGameCoreDLL_Expansion2/CvReligionClasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit e9d29ab

Please sign in to comment.