Skip to content

Commit

Permalink
GOTTA, SWEEP SWEEP SWEEP!
Browse files Browse the repository at this point in the history
  • Loading branch information
RecursiveVision committed Jun 5, 2024
1 parent adbf669 commit 2f19860
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 124 deletions.
47 changes: 32 additions & 15 deletions (1) Community Patch/Core Files/Core Values/DiploApproachWeights.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,18 @@
-- WAR and HOSTILE approach scores are multiplied by whichever of these values is appropriate, and then divided by 100.
-- NOTE: Target Value is also affected by proximity!

-- Normal Target Value Multiplier (Major Civs)
-- Conquest Target Value Multiplier
-- Applied instead of the below values if the AI really wants to conquer this player AND has a good attack target.
INSERT INTO Defines (Name, Value) VALUES
('CONQUEST_WAR_MULTIPLIER_TARGET_CAKEWALK', 250),
('CONQUEST_WAR_MULTIPLIER_TARGET_SOFT', 200),
('CONQUEST_WAR_MULTIPLIER_TARGET_FAVORABLE', 150),
('CONQUEST_WAR_MULTIPLIER_TARGET_AVERAGE', 125),
('CONQUEST_WAR_MULTIPLIER_TARGET_DIFFICULT', 100),
('CONQUEST_WAR_MULTIPLIER_TARGET_BAD', 75),
('CONQUEST_WAR_MULTIPLIER_TARGET_IMPOSSIBLE', 50),

-- Normal Target Value Multiplier (Major Civs)
('MAJOR_WAR_MULTIPLIER_TARGET_CAKEWALK', 200),
('MAJOR_WAR_MULTIPLIER_TARGET_SOFT', 150),
('MAJOR_WAR_MULTIPLIER_TARGET_FAVORABLE', 125),
Expand All @@ -23,17 +33,6 @@ INSERT INTO Defines (Name, Value) SELECT 'MINOR_APPROACH_WAR_TARGET_DIFFICULT',
UPDATE Defines SET Value = 33 WHERE Name = 'MINOR_APPROACH_WAR_TARGET_BAD';
UPDATE Defines SET Value = 25 WHERE Name = 'MINOR_APPROACH_WAR_TARGET_IMPOSSIBLE';

-- Conquest Target Value Multiplier
-- Applied instead of the above values if the AI really wants to conquer this player AND has a good attack target.
INSERT INTO Defines (Name, Value) VALUES
('CONQUEST_WAR_MULTIPLIER_TARGET_CAKEWALK', 250),
('CONQUEST_WAR_MULTIPLIER_TARGET_SOFT', 200),
('CONQUEST_WAR_MULTIPLIER_TARGET_FAVORABLE', 150),
('CONQUEST_WAR_MULTIPLIER_TARGET_AVERAGE', 125),
('CONQUEST_WAR_MULTIPLIER_TARGET_DIFFICULT', 100),
('CONQUEST_WAR_MULTIPLIER_TARGET_BAD', 75),
('CONQUEST_WAR_MULTIPLIER_TARGET_IMPOSSIBLE', 50);


-- Proximity Multipliers to Approach Weights
-- These are only for MAJOR CIVS!
Expand Down Expand Up @@ -85,9 +84,9 @@ INSERT INTO Defines (Name, Value) SELECT 'APPROACH_SHIFT_PERCENT', 0.30;
UPDATE Defines SET Value = 5 WHERE Name = 'APPROACH_RANDOM_PERCENT';


-- C4DF Approach Values
INSERT INTO Defines (Name, Value) VALUES

-- C4DF Approach Values
-- Approach multipliers for having 2+ vassals
('APPROACH_WAR_TOO_MANY_VASSALS', 20), -- % increase to WAR and HOSTILE approaches per vassal
('APPROACH_GUARDED_TOO_MANY_VASSALS', 20), -- % increase to GUARDED and AFRAID approaches per vassal
Expand All @@ -100,13 +99,31 @@ INSERT INTO Defines (Name, Value) VALUES
-- Modifiers for agreeing to give a former vassal independence
('APPROACH_WAR_VASSAL_PEACEFULLY_REVOKED', -4), -- Adds x times the AI's War Bias to the War Approach
('APPROACH_FRIENDLY_VASSAL_PEACEFULLY_REVOKED', 5), -- Adds x times the AI's Friendly Bias to the Friendly Approach
('APPROACH_DECEPTIVE_VASSAL_PEACEFULLY_REVOKED', 2); -- Adds x times the AI's Deceptive Bias to the Deceptive Approach (not applied if master liberates vassal)
('APPROACH_DECEPTIVE_VASSAL_PEACEFULLY_REVOKED', 2), -- Adds x times the AI's Deceptive Bias to the Deceptive Approach (not applied if master liberates vassal)


-- Approach Trade Value Modifiers
-- Change the AI's trade prices based on their surface approach towards another player.
-- WAR is possible as a surface approach, but the trade modifier for peace deals is always 100 for sanity, so there's no define for it.

-- The AI is buying from the other player
('APPROACH_HOSTILE_BUYING_PRICE_MODIFIER', 50),
('APPROACH_GUARDED_BUYING_PRICE_MODIFIER', 80),
('APPROACH_AFRAID_BUYING_PRICE_MODIFIER', 125),
('APPROACH_NEUTRAL_BUYING_PRICE_MODIFIER', 100),
('APPROACH_FRIENDLY_BUYING_PRICE_MODIFIER', 125),

-- The AI is selling to the other player
('APPROACH_HOSTILE_SELLING_PRICE_MODIFIER', 200),
('APPROACH_GUARDED_SELLING_PRICE_MODIFIER', 125),
('APPROACH_AFRAID_SELLING_PRICE_MODIFIER', 80),
('APPROACH_NEUTRAL_SELLING_PRICE_MODIFIER', 100),
('APPROACH_FRIENDLY_SELLING_PRICE_MODIFIER', 80),


-- "Close To Victory" Thresholds
-- A player who has completed x% of the progress towards a specific victory condition is considered "close to" that victory.
-- Affects AI calculations and (if Endgame Aggression isn't disabled for that player) triggers the Endgame Aggression boost to approach.
INSERT INTO Defines (Name, Value) VALUES
('CLOSE_TO_DOMINATION_VICTORY_THRESHOLD', 50),
('CLOSE_TO_DIPLOMATIC_VICTORY_THRESHOLD', 55),
('CLOSE_TO_SCIENCE_VICTORY_THRESHOLD', 80),
Expand Down
2 changes: 1 addition & 1 deletion CvGameCoreDLL_Expansion2/CvCity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16226,7 +16226,7 @@ void CvCity::processBuilding(BuildingTypes eBuilding, int iChange, bool bFirst,
if ((pBuildingInfo->GetYieldFromBirthRetroactive(eYield) > 0))
{
int iVal = getPopulation() * pBuildingInfo->GetYieldFromBirthRetroactive(eYield);
GET_PLAYER(getOwner()).doInstantYield(INSTANT_YIELD_TYPE_BIRTH_RETROACTIVE, false, NO_GREATPERSON, eBuilding, iVal, false, NO_PLAYER, NULL, false, this, false, true, false, eYield);
GET_PLAYER(getOwner()).doInstantYield(INSTANT_YIELD_TYPE_BIRTH_RETROACTIVE, false, NO_GREATPERSON, eBuilding, iVal, false, NO_PLAYER, NULL, false, this, false, false, false, eYield);
}
if ((pBuildingInfo->GetYieldFromUnitProduction(eYield) > 0))
{
Expand Down
1 change: 0 additions & 1 deletion CvGameCoreDLL_Expansion2/CvDealAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1120,7 +1120,6 @@ int CvDealAI::GetTradeItemValue(TradeableItems eItem, bool bFromMe, PlayerTypes
// Don't offer the item in AI-AI deals or in AI offers to humans.
// If a human has asked for this item, return the sell price we'd be willing to accept.
iItemValue = (!bHumanInvolved || bIsAIOffer) ? INT_MAX : iMinAcceptableSellPrice;

}
else
{
Expand Down
178 changes: 96 additions & 82 deletions CvGameCoreDLL_Expansion2/CvDiplomacyAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3661,67 +3661,17 @@ void CvDiplomacyAI::SetCivApproach(PlayerTypes ePlayer, CivApproachTypes eApproa
}

m_aeCivApproach[ePlayer] = eApproach;
}

/// What is our Strategic Diplomatic Approach towards this Major Civ?
CivApproachTypes CvDiplomacyAI::GetCivStrategicApproach(PlayerTypes ePlayer) const
{
if (ePlayer < 0 || ePlayer >= MAX_MAJOR_CIVS) return NO_CIV_APPROACH;
return (CivApproachTypes) m_aeCivStrategicApproach[ePlayer];
}

void CvDiplomacyAI::SetCivStrategicApproach(PlayerTypes ePlayer, CivApproachTypes eApproach)
{
if (ePlayer < 0 || ePlayer >= MAX_MAJOR_CIVS) return;
if (eApproach < 0 || eApproach >= NUM_CIV_APPROACHES) return;
m_aeCivStrategicApproach[ePlayer] = eApproach;
}

/// What is our cached surface-level approach towards ePlayer? This is used to stay consistent during war plans.
CivApproachTypes CvDiplomacyAI::GetCachedSurfaceApproach(PlayerTypes ePlayer) const
{
if (ePlayer < 0 || ePlayer >= MAX_MAJOR_CIVS) return NO_CIV_APPROACH;
return (CivApproachTypes) m_aeCachedSurfaceApproach[ePlayer];
}

void CvDiplomacyAI::SetCachedSurfaceApproach(PlayerTypes ePlayer, CivApproachTypes eApproach)
{
if (ePlayer < 0 || ePlayer >= MAX_MAJOR_CIVS) return;
if (eApproach < NO_CIV_APPROACH || eApproach >= NUM_CIV_APPROACHES) return;
m_aeCachedSurfaceApproach[ePlayer] = eApproach;
}

/// What is our surface-level approach towards ePlayer (i.e. how we are acting towards them right now)?
CivApproachTypes CvDiplomacyAI::GetSurfaceApproach(PlayerTypes ePlayer) const
{
if (ePlayer < 0 || ePlayer >= MAX_PLAYERS) return NO_CIV_APPROACH;

if (IsAtWar(ePlayer) || GET_PLAYER(ePlayer).isBarbarian())
return CIV_APPROACH_WAR;

if (GET_PLAYER(ePlayer).isMinorCiv())
return GetCivApproach(ePlayer);

// Always friendly if we have a Declaration of Friendship
if (IsDoFAccepted(ePlayer))
return CIV_APPROACH_FRIENDLY;

CivApproachTypes eRealApproach = GetCivApproach(ePlayer);

// Display NEUTRAL if human approach is invalid
if (GetPlayer()->isHuman())
// Planning war? Pick a surface approach to disguise our war plans.
if (eApproach == CIV_APPROACH_WAR)
{
if ((!IsAtWar(ePlayer) && eRealApproach == CIV_APPROACH_WAR) || eRealApproach == CIV_APPROACH_DECEPTIVE || eRealApproach == CIV_APPROACH_AFRAID)
// We don't need a surface approach while *at* war. Approaches are updated in DoWeMadePeaceWithSomeone(), so there's no need to store one for later.
if (IsAtWar(ePlayer))
{
return CIV_APPROACH_NEUTRAL;
SetCachedSurfaceApproach(ePlayer, NO_CIV_APPROACH);
return;
}

return eRealApproach;
}

// Pick a surface approach to disguise our war plans (this approach is cached to prevent erratic behavior)
if (eRealApproach == CIV_APPROACH_WAR)
{
CivApproachTypes eSurfaceApproach = NO_CIV_APPROACH;
CivApproachTypes eCurrentSurfaceApproach = GetCachedSurfaceApproach(ePlayer);

Expand All @@ -3745,7 +3695,7 @@ CivApproachTypes CvDiplomacyAI::GetSurfaceApproach(PlayerTypes ePlayer) const
eSurfaceApproach = CIV_APPROACH_GUARDED;
}
}
if (eSurfaceApproach == CIV_APPROACH_FRIENDLY)
else if (eSurfaceApproach == CIV_APPROACH_FRIENDLY)
{
if (IsDenouncedPlayer(ePlayer) || IsDenouncedByPlayer(ePlayer) || IsUntrustworthy(ePlayer))
{
Expand All @@ -3754,7 +3704,7 @@ CivApproachTypes CvDiplomacyAI::GetSurfaceApproach(PlayerTypes ePlayer) const
}

GetPlayer()->GetDiplomacyAI()->SetCachedSurfaceApproach(ePlayer, eSurfaceApproach);
return eSurfaceApproach;
return;
}
else
{
Expand All @@ -3773,71 +3723,135 @@ CivApproachTypes CvDiplomacyAI::GetSurfaceApproach(PlayerTypes ePlayer) const
if (eSurfaceApproach == CIV_APPROACH_AFRAID)
{
GetPlayer()->GetDiplomacyAI()->SetCachedSurfaceApproach(ePlayer, CIV_APPROACH_GUARDED);
return CIV_APPROACH_GUARDED;
return;
}

// Deceptive = Friendly
if (eSurfaceApproach == CIV_APPROACH_DECEPTIVE)
else if (eSurfaceApproach == CIV_APPROACH_DECEPTIVE)
{
GetPlayer()->GetDiplomacyAI()->SetCachedSurfaceApproach(ePlayer, CIV_APPROACH_FRIENDLY);
return CIV_APPROACH_FRIENDLY;
return;
}

GetPlayer()->GetDiplomacyAI()->SetCachedSurfaceApproach(ePlayer, eSurfaceApproach);
return eSurfaceApproach;
return;
}
}

SetCachedSurfaceApproach(ePlayer, NO_CIV_APPROACH);
}

/// What is our Strategic Diplomatic Approach towards this Major Civ?
CivApproachTypes CvDiplomacyAI::GetCivStrategicApproach(PlayerTypes ePlayer) const
{
if (ePlayer < 0 || ePlayer >= MAX_MAJOR_CIVS) return NO_CIV_APPROACH;
return (CivApproachTypes) m_aeCivStrategicApproach[ePlayer];
}

void CvDiplomacyAI::SetCivStrategicApproach(PlayerTypes ePlayer, CivApproachTypes eApproach)
{
if (ePlayer < 0 || ePlayer >= MAX_MAJOR_CIVS) return;
if (eApproach < 0 || eApproach >= NUM_CIV_APPROACHES) return;
m_aeCivStrategicApproach[ePlayer] = eApproach;
}

/// What is our cached surface-level approach towards ePlayer? This is used to stay consistent during war plans.
CivApproachTypes CvDiplomacyAI::GetCachedSurfaceApproach(PlayerTypes ePlayer) const
{
if (ePlayer < 0 || ePlayer >= MAX_MAJOR_CIVS) return NO_CIV_APPROACH;
return (CivApproachTypes) m_aeCachedSurfaceApproach[ePlayer];
}

void CvDiplomacyAI::SetCachedSurfaceApproach(PlayerTypes ePlayer, CivApproachTypes eApproach)
{
if (ePlayer < 0 || ePlayer >= MAX_MAJOR_CIVS) return;
if (eApproach < NO_CIV_APPROACH || eApproach >= NUM_CIV_APPROACHES) return;
m_aeCachedSurfaceApproach[ePlayer] = eApproach;
}

/// What is our surface-level approach towards ePlayer (i.e. how we are acting towards them right now)?
CivApproachTypes CvDiplomacyAI::GetSurfaceApproach(PlayerTypes ePlayer) const
{
if (ePlayer < 0 || ePlayer >= MAX_PLAYERS) return NO_CIV_APPROACH;

if (IsAtWar(ePlayer) || GET_PLAYER(ePlayer).isBarbarian())
return CIV_APPROACH_WAR;

if (GET_PLAYER(ePlayer).isMinorCiv())
return GetCivApproach(ePlayer);

// Always friendly if we have a Declaration of Friendship
if (IsDoFAccepted(ePlayer))
return CIV_APPROACH_FRIENDLY;

CivApproachTypes eRealApproach = GetCivApproach(ePlayer);

// Display NEUTRAL if human approach is invalid
if (GetPlayer()->isHuman())
{
if ((!IsAtWar(ePlayer) && eRealApproach == CIV_APPROACH_WAR) || eRealApproach == CIV_APPROACH_DECEPTIVE || eRealApproach == CIV_APPROACH_AFRAID)
{
return CIV_APPROACH_NEUTRAL;
}

return eRealApproach;
}

// Use a surface approach to disguise our war plans (this approach is cached to prevent erratic behavior)
if (eRealApproach == CIV_APPROACH_WAR)
{
return GetCachedSurfaceApproach(ePlayer);
}
// Deceptive = Friendly
else if (eRealApproach == CIV_APPROACH_DECEPTIVE)
{
GetPlayer()->GetDiplomacyAI()->SetCachedSurfaceApproach(ePlayer, NO_CIV_APPROACH);
return CIV_APPROACH_FRIENDLY;
}

GetPlayer()->GetDiplomacyAI()->SetCachedSurfaceApproach(ePlayer, NO_CIV_APPROACH);
return eRealApproach;
}


/// How is trade deal valuation modified based on our surface-lavel approach towards ePlayer?
/// How is trade deal valuation modified based on our surface-level approach towards ePlayer?
int CvDiplomacyAI::GetSurfaceApproachDealModifier(PlayerTypes ePlayer, bool bFromMe) const
{
if (ePlayer < 0 || ePlayer >= MAX_PLAYERS) return -1;
if (bFromMe)
{
//How much is OUR stuff worth?
// How much is OUR stuff worth?
switch (GetSurfaceApproach(ePlayer))
{
case CIV_APPROACH_FRIENDLY:
return 80;
return /*80*/ GD_INT_GET(APPROACH_FRIENDLY_SELLING_PRICE_MODIFIER);
case CIV_APPROACH_AFRAID:
return 80;
return /*80*/ GD_INT_GET(APPROACH_AFRAID_SELLING_PRICE_MODIFIER);
case CIV_APPROACH_NEUTRAL:
return 100;
case NO_CIV_APPROACH:
return /*100*/ GD_INT_GET(APPROACH_NEUTRAL_SELLING_PRICE_MODIFIER);
case CIV_APPROACH_GUARDED:
return 125;
return /*125*/ GD_INT_GET(APPROACH_GUARDED_SELLING_PRICE_MODIFIER);
case CIV_APPROACH_HOSTILE:
return 200;
return /*200*/ GD_INT_GET(APPROACH_HOSTILE_SELLING_PRICE_MODIFIER);
default:
return 100;
return 100; // Peace deals should always be evaluated fairly for sanity
}
}
else
{
switch (GetPlayer()->GetDiplomacyAI()->GetSurfaceApproach(ePlayer))
{
case CIV_APPROACH_FRIENDLY:
return 125;
return /*125*/ GD_INT_GET(APPROACH_FRIENDLY_BUYING_PRICE_MODIFIER);
case CIV_APPROACH_AFRAID:
return 125;
return /*125*/ GD_INT_GET(APPROACH_AFRAID_BUYING_PRICE_MODIFIER);
case CIV_APPROACH_NEUTRAL:
return 100;
case NO_CIV_APPROACH:
return /*100*/ GD_INT_GET(APPROACH_NEUTRAL_BUYING_PRICE_MODIFIER);
case CIV_APPROACH_GUARDED:
return 80;
return /*80*/ GD_INT_GET(APPROACH_GUARDED_BUYING_PRICE_MODIFIER);
case CIV_APPROACH_HOSTILE:
return 50;
return /*50*/ GD_INT_GET(APPROACH_HOSTILE_BUYING_PRICE_MODIFIER);
default:
return 100;
return 100; // Peace deals should always be evaluated fairly for sanity
}
}
}
Expand Down Expand Up @@ -4304,8 +4318,6 @@ void CvDiplomacyAI::SetDoFAccepted(PlayerTypes ePlayer, bool bValue)

if (bValue != IsDoFAccepted(ePlayer))
{
m_pPlayer->recomputeGreatPeopleModifiers();

// Someone made a DoF, send out notifications to everyone
if (bValue)
{
Expand Down Expand Up @@ -4415,6 +4427,8 @@ void CvDiplomacyAI::SetDoFAccepted(PlayerTypes ePlayer, bool bValue)
{
SetDoFAcceptedTurn(ePlayer, -1);
}

m_pPlayer->recomputeGreatPeopleModifiers();
}
}

Expand Down Expand Up @@ -5215,7 +5229,7 @@ void CvDiplomacyAI::SetStateAllWars(StateAllWars eState)
}

/// How much progress (or lack thereof) have we made in this war?
/// (to be) Used by the AI to determine whether they should continue or stop.
/// Used by the AI to determine whether they should continue or stop.
int CvDiplomacyAI::GetWarProgressScore(PlayerTypes ePlayer) const
{
if (ePlayer < 0 || ePlayer >= MAX_CIV_PLAYERS) return 0;
Expand Down
2 changes: 1 addition & 1 deletion CvGameCoreDLL_Expansion2/CvGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ void CvGame::setInitialItems(CvGameInitialItemsOverrides& kInitialItemOverrides)
m_iEarliestBarbarianReleaseTurn = max(0, GC.getGame().randRangeInclusive(iBarbReleaseTurn - iPlusMinus, iBarbReleaseTurn + iPlusMinus, CvSeeder::fromRaw(0x07f63322)));
}
else
m_iEarliestBarbarianReleaseTurn = max(0, getHandicapInfo().getEarliestBarbarianReleaseTurn() + GC.getGame().randRangeInclusive(0, /*15*/ max(1, GD_INT_GET(AI_TACTICAL_BARBARIAN_RELEASE_VARIATION)), CvSeeder::fromRaw(0x4602dd5b)));
m_iEarliestBarbarianReleaseTurn = max(0, getHandicapInfo().getEarliestBarbarianReleaseTurn() + GC.getGame().randRangeInclusive(0, /*15*/ GD_INT_GET(AI_TACTICAL_BARBARIAN_RELEASE_VARIATION), CvSeeder::fromRaw(0x4602dd5b)));

UpdateGameEra();
// What route type forms an industrial connection
Expand Down
Loading

0 comments on commit 2f19860

Please sign in to comment.