Skip to content

Commit

Permalink
TechDebt: Made getDiplomacyManger() nullable (#11771)
Browse files Browse the repository at this point in the history
* Made getDiplomacyManager nullable and added getDiplomacyMangerOrMeet

* Fixed AI Automation having problems when playing as a oneCityChallenger civ
  • Loading branch information
tuvus authored Jun 16, 2024
1 parent c5d3bfc commit bbea083
Show file tree
Hide file tree
Showing 48 changed files with 300 additions and 305 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ object DeclareWarPlanEvaluator {
* @return The movtivation of the plan. If it is > 0 then we can declare the war.
*/
fun evaluateTeamWarPlan(civInfo: Civilization, target: Civilization, teamCiv: Civilization, givenMotivation: Int?): Int {
val teamCivDiplo = civInfo.getDiplomacyManager(teamCiv)!!
if (civInfo.getPersonality()[PersonalityValue.DeclareWar] == 0f) return -1000
if (civInfo.getDiplomacyManager(teamCiv).isRelationshipLevelLT(RelationshipLevel.Neutral)) return -1000
if (teamCivDiplo.isRelationshipLevelLT(RelationshipLevel.Neutral)) return -1000

var motivation = givenMotivation
?: MotivationToAttackAutomation.hasAtLeastMotivationToAttack(civInfo, target, 0)

if (civInfo.getDiplomacyManager(teamCiv).isRelationshipLevelEQ(RelationshipLevel.Neutral)) motivation -= 5
if (teamCivDiplo.isRelationshipLevelEQ(RelationshipLevel.Neutral)) motivation -= 5
// Make sure that they can actually help us with the target
if (!teamCiv.threatManager.getNeighboringCivilizations().contains(target)) {
motivation -= 40
Expand Down Expand Up @@ -70,13 +71,13 @@ object DeclareWarPlanEvaluator {
* @return The movtivation of the plan. If it is > 0 then we can declare the war.
*/
fun evaluateJoinWarPlan(civInfo: Civilization, target: Civilization, civToJoin: Civilization, givenMotivation: Int?): Int {
val thirdCivDiplo = civInfo.getDiplomacyManager(civToJoin)!!
if (civInfo.getPersonality()[PersonalityValue.DeclareWar] == 0f) return -1000
if (civInfo.getDiplomacyManager(civToJoin).isRelationshipLevelLE(RelationshipLevel.Favorable)) return -1000
if (thirdCivDiplo.isRelationshipLevelLE(RelationshipLevel.Favorable)) return -1000

var motivation = givenMotivation
?: MotivationToAttackAutomation.hasAtLeastMotivationToAttack(civInfo, target, 0)
// We need to be able to trust the thirdCiv at least somewhat
val thirdCivDiplo = civInfo.getDiplomacyManager(civToJoin)
if (thirdCivDiplo.diplomaticStatus != DiplomaticStatus.DefensivePact &&
thirdCivDiplo.opinionOfOtherCiv() + motivation * 2 < 80) {
motivation -= 80 - (thirdCivDiplo.opinionOfOtherCiv() + motivation * 2).toInt()
Expand Down Expand Up @@ -116,7 +117,7 @@ object DeclareWarPlanEvaluator {
* @return The movtivation of the plan. If it is > 0 then we can declare the war.
*/
fun evaluateJoinOurWarPlan(civInfo: Civilization, target: Civilization, civToJoin: Civilization, givenMotivation: Int?): Int {
if (civInfo.getDiplomacyManager(civToJoin).isRelationshipLevelLT(RelationshipLevel.Favorable)) return -1000
if (civInfo.getDiplomacyManager(civToJoin)!!.isRelationshipLevelLT(RelationshipLevel.Favorable)) return -1000
var motivation = givenMotivation ?: 0
if (!civToJoin.threatManager.getNeighboringCivilizations().contains(target)) {
motivation -= 50
Expand Down Expand Up @@ -146,7 +147,7 @@ object DeclareWarPlanEvaluator {
val motivation = givenMotivation
?: MotivationToAttackAutomation.hasAtLeastMotivationToAttack(civInfo, target, 0)

val diploManager = civInfo.getDiplomacyManager(target)
val diploManager = civInfo.getDiplomacyManager(target)!!

if (diploManager.hasFlag(DiplomacyFlags.WaryOf) && diploManager.getFlag(DiplomacyFlags.WaryOf) < 0) {
val turnsToPlan = (10 - (motivation / 10)).coerceAtLeast(3)
Expand All @@ -168,7 +169,7 @@ object DeclareWarPlanEvaluator {

// TODO: We use negative values in WaryOf for now so that we aren't adding any extra fields to the save file
// This will very likely change in the future and we will want to build upon it
val diploManager = civInfo.getDiplomacyManager(target)
val diploManager = civInfo.getDiplomacyManager(target)!!
if (diploManager.hasFlag(DiplomacyFlags.WaryOf)) return 0

return motivation - 15
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ object DeclareWarTargetAutomation {
* Together we are stronger and are more likely to take down bigger threats.
*/
private fun tryTeamWar(civInfo: Civilization, target: Civilization, motivation: Int): Boolean {
val potentialAllies = civInfo.getDiplomacyManager(target).getCommonKnownCivs()
val potentialAllies = civInfo.getDiplomacyManager(target)!!.getCommonKnownCivs()
.filter {
it.isMajorCiv()
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedJoinWarOffer)
&& civInfo.getDiplomacyManager(it).isRelationshipLevelGE(RelationshipLevel.Neutral)
&& !civInfo.getDiplomacyManager(it)!!.hasFlag(DiplomacyFlags.DeclinedJoinWarOffer)
&& civInfo.getDiplomacyManager(it)!!.isRelationshipLevelGE(RelationshipLevel.Neutral)
&& !it.isAtWarWith(target)
}.sortedByDescending { it.getStatForRanking(RankingType.Force) }

Expand All @@ -75,11 +75,11 @@ object DeclareWarTargetAutomation {
* The next safest aproach is to join an existing war on the side of an ally that is already at war with [target].
*/
private fun tryJoinWar(civInfo: Civilization, target: Civilization, motivation: Int): Boolean {
val potentialAllies = civInfo.getDiplomacyManager(target).getCommonKnownCivs()
val potentialAllies = civInfo.getDiplomacyManager(target)!!.getCommonKnownCivs()
.filter {
it.isMajorCiv()
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedJoinWarOffer)
&& civInfo.getDiplomacyManager(it).isRelationshipLevelGE(RelationshipLevel.Favorable)
&& !civInfo.getDiplomacyManager(it)!!.hasFlag(DiplomacyFlags.DeclinedJoinWarOffer)
&& civInfo.getDiplomacyManager(it)!!.isRelationshipLevelGE(RelationshipLevel.Favorable)
&& it.isAtWarWith(target)
} // Must be a civ not already at war with them
.sortedByDescending { it.getStatForRanking(RankingType.Force) }
Expand All @@ -104,7 +104,7 @@ object DeclareWarTargetAutomation {
*/
private fun declareWar(civInfo: Civilization, target: Civilization, motivation: Int): Boolean {
if (DeclareWarPlanEvaluator.evaluateDeclareWarPlan(civInfo, target, motivation) > 0) {
civInfo.getDiplomacyManager(target).declareWar()
civInfo.getDiplomacyManager(target)!!.declareWar()
return true
}
return false
Expand All @@ -116,7 +116,7 @@ object DeclareWarTargetAutomation {
private fun prepareWar(civInfo: Civilization, target: Civilization, motivation: Int): Boolean {
// TODO: We use negative values in WaryOf for now so that we aren't adding any extra fields to the save file
// This will very likely change in the future and we will want to build upon it
val diploManager = civInfo.getDiplomacyManager(target)
val diploManager = civInfo.getDiplomacyManager(target)!!
if (DeclareWarPlanEvaluator.evaluateStartPreparingWarPlan(civInfo, target, motivation) > 0) {
diploManager.setFlag(DiplomacyFlags.WaryOf, -1)
return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ object DiplomacyAutomation {
val civsThatWeCanDeclareFriendshipWith = civInfo.getKnownCivs()
.filter {
civInfo.diplomacyFunctions.canSignDeclarationOfFriendshipWith(it)
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedDeclarationOfFriendship)
&& !civInfo.getDiplomacyManager(it)!!.hasFlag(DiplomacyFlags.DeclinedDeclarationOfFriendship)
}
.sortedByDescending { it.getDiplomacyManager(civInfo).relationshipLevel() }.toList()
.sortedByDescending { it.getDiplomacyManager(civInfo)!!.relationshipLevel() }.toList()
for (otherCiv in civsThatWeCanDeclareFriendshipWith) {
// Default setting is 2, this will be changed according to different civ.
if ((1..10).random() <= 2 && wantsToSignDeclarationOfFrienship(civInfo, otherCiv)) {
Expand All @@ -40,7 +40,7 @@ object DiplomacyAutomation {
}

internal fun wantsToSignDeclarationOfFrienship(civInfo: Civilization, otherCiv: Civilization): Boolean {
val diploManager = civInfo.getDiplomacyManager(otherCiv)
val diploManager = civInfo.getDiplomacyManager(otherCiv)!!
if (diploManager.hasFlag(DiplomacyFlags.DeclinedDeclarationOfFriendship)) return false
// Shortcut, if it is below favorable then don't consider it
if (diploManager.isRelationshipLevelLT(RelationshipLevel.Favorable)) return false
Expand Down Expand Up @@ -93,7 +93,7 @@ object DiplomacyAutomation {
// If they are the only non-friendly civ near us then they are the only civ to attack and expand into
if (civInfo.threatManager.getNeighboringCivilizations().none {
it.isMajorCiv() && it != otherCiv
&& civInfo.getDiplomacyManager(it).isRelationshipLevelLT(RelationshipLevel.Favorable)
&& civInfo.getDiplomacyManager(it)!!.isRelationshipLevelLT(RelationshipLevel.Favorable)
})
motivation -= 20

Expand All @@ -108,10 +108,10 @@ object DiplomacyAutomation {
.filter {
it.isMajorCiv() && !civInfo.isAtWarWith(it)
&& it.hasUnique(UniqueType.EnablesOpenBorders)
&& !civInfo.getDiplomacyManager(it).hasOpenBorders
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedOpenBorders)
&& !civInfo.getDiplomacyManager(it)!!.hasOpenBorders
&& !civInfo.getDiplomacyManager(it)!!.hasFlag(DiplomacyFlags.DeclinedOpenBorders)
&& !isTradeBeingOffered(civInfo, it, Constants.openBorders)
}.sortedByDescending { it.getDiplomacyManager(civInfo).relationshipLevel() }.toList()
}.sortedByDescending { it.getDiplomacyManager(civInfo)!!.relationshipLevel() }.toList()

for (otherCiv in civsThatWeCanOpenBordersWith) {
// Default setting is 3, this will be changed according to different civ.
Expand All @@ -124,13 +124,13 @@ object DiplomacyAutomation {
otherCiv.tradeRequests.add(TradeRequest(civInfo.civName, tradeLogic.currentTrade.reverse()))
} else {
// Remember this for a few turns to save computation power
civInfo.getDiplomacyManager(otherCiv).setFlag(DiplomacyFlags.DeclinedOpenBorders, 5)
civInfo.getDiplomacyManager(otherCiv)!!.setFlag(DiplomacyFlags.DeclinedOpenBorders, 5)
}
}
}

fun wantsToOpenBorders(civInfo: Civilization, otherCiv: Civilization): Boolean {
val diploManager = civInfo.getDiplomacyManager(otherCiv)
val diploManager = civInfo.getDiplomacyManager(otherCiv)!!
if (diploManager.hasFlag(DiplomacyFlags.DeclinedOpenBorders)) return false
if (diploManager.isRelationshipLevelLT(RelationshipLevel.Favorable)) return false
// Don't accept if they are at war with our friends, they might use our land to attack them
Expand All @@ -150,7 +150,7 @@ object DiplomacyAutomation {
val canSignResearchAgreementCiv = civInfo.getKnownCivs()
.filter {
civInfo.diplomacyFunctions.canSignResearchAgreementsWith(it)
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedResearchAgreement)
&& !civInfo.getDiplomacyManager(it)!!.hasFlag(DiplomacyFlags.DeclinedResearchAgreement)
&& !isTradeBeingOffered(civInfo, it, Constants.researchAgreement)
}
.sortedByDescending { it.stats.statsForNextTurn.science }
Expand All @@ -173,8 +173,8 @@ object DiplomacyAutomation {
val canSignDefensivePactCiv = civInfo.getKnownCivs()
.filter {
civInfo.diplomacyFunctions.canSignDefensivePactWith(it)
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedDefensivePact)
&& civInfo.getDiplomacyManager(it).opinionOfOtherCiv() < 70f
&& !civInfo.getDiplomacyManager(it)!!.hasFlag(DiplomacyFlags.DeclinedDefensivePact)
&& civInfo.getDiplomacyManager(it)!!.opinionOfOtherCiv() < 70f
&& !isTradeBeingOffered(civInfo, it, Constants.defensivePact)
}

Expand All @@ -190,33 +190,32 @@ object DiplomacyAutomation {
otherCiv.tradeRequests.add(TradeRequest(civInfo.civName, tradeLogic.currentTrade.reverse()))
} else {
// Remember this for a few turns to save computation power
civInfo.getDiplomacyManager(otherCiv).setFlag(DiplomacyFlags.DeclinedDefensivePact, 5)
civInfo.getDiplomacyManager(otherCiv)!!.setFlag(DiplomacyFlags.DeclinedDefensivePact, 5)
}
}
}

fun wantsToSignDefensivePact(civInfo: Civilization, otherCiv: Civilization): Boolean {
val diploManager = civInfo.getDiplomacyManager(otherCiv)
val diploManager = civInfo.getDiplomacyManager(otherCiv)!!
if (diploManager.hasFlag(DiplomacyFlags.DeclinedDefensivePact)) return false
if (diploManager.opinionOfOtherCiv() < 60f) return false
val commonknownCivs = diploManager.getCommonKnownCivs()
// If they have bad relations with any of our friends, don't consider it
for (thirdCiv in commonknownCivs) {
if (civInfo.getDiplomacyManager(thirdCiv).hasFlag(DiplomacyFlags.DeclarationOfFriendship)
&& thirdCiv.getDiplomacyManager(otherCiv).isRelationshipLevelLT(RelationshipLevel.Favorable))
// If they have bad relations with any of our friends, don't consider it
if (civInfo.getDiplomacyManager(thirdCiv)!!.hasFlag(DiplomacyFlags.DeclarationOfFriendship)
&& thirdCiv.getDiplomacyManager(otherCiv)!!.isRelationshipLevelLT(RelationshipLevel.Favorable))
return false
}
// If they have bad relations with any of our friends, don't consider it
for (thirdCiv in commonknownCivs) {
if (otherCiv.getDiplomacyManager(thirdCiv).hasFlag(DiplomacyFlags.DeclarationOfFriendship)
&& thirdCiv.getDiplomacyManager(civInfo).isRelationshipLevelLT(RelationshipLevel.Neutral))

// If they have bad relations with any of our friends, don't consider it
if (otherCiv.getDiplomacyManager(thirdCiv)!!.hasFlag(DiplomacyFlags.DeclarationOfFriendship)
&& thirdCiv.getDiplomacyManager(civInfo)!!.isRelationshipLevelLT(RelationshipLevel.Neutral))
return false
}

val defensivePacts = civInfo.diplomacy.count { it.value.hasFlag(DiplomacyFlags.DefensivePact) }
val otherCivNonOverlappingDefensivePacts = otherCiv.diplomacy.values.count {
it.hasFlag(DiplomacyFlags.DefensivePact)
&& (!it.otherCiv().knows(civInfo) || !it.otherCiv().getDiplomacyManager(civInfo).hasFlag(DiplomacyFlags.DefensivePact))
&& it.otherCiv().getDiplomacyManager(civInfo)?.hasFlag(DiplomacyFlags.DefensivePact) != true
}
val allCivs = civInfo.gameInfo.civilizations.count { it.isMajorCiv() } - 1 // Don't include us
val deadCivs = civInfo.gameInfo.civilizations.count { it.isMajorCiv() && !it.isAlive() }
Expand Down Expand Up @@ -263,7 +262,7 @@ object DiplomacyAutomation {
//evaluate war
val targetCivs = civInfo.getKnownCivs()
.filterNot {
it == civInfo || it.cities.isEmpty() || !civInfo.getDiplomacyManager(it).canDeclareWar()
it == civInfo || it.cities.isEmpty() || !civInfo.getDiplomacyManager(it)!!.canDeclareWar()
|| it.cities.none { city -> civInfo.hasExplored(city.getCenterTile()) }
}
// If the AI declares war on a civ without knowing the location of any cities,
Expand All @@ -285,9 +284,9 @@ object DiplomacyAutomation {
.map { it.value.otherCiv() }
.filterNot {
it == civInfo || it.isBarbarian() || it.cities.isEmpty()
|| it.getDiplomacyManager(civInfo).hasFlag(DiplomacyFlags.DeclaredWar)
|| civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclaredWar)
}.filter { !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedPeace) }
|| it.getDiplomacyManager(civInfo)!!.hasFlag(DiplomacyFlags.DeclaredWar)
|| civInfo.getDiplomacyManager(it)!!.hasFlag(DiplomacyFlags.DeclaredWar)
}.filter { !civInfo.getDiplomacyManager(it)!!.hasFlag(DiplomacyFlags.DeclinedPeace) }
// Don't allow AIs to offer peace to city states allied with their enemies
.filterNot { it.isCityState() && it.getAllyCiv() != null && civInfo.isAtWarWith(civInfo.gameInfo.getCivilization(it.getAllyCiv()!!)) }
// ignore civs that we have already offered peace this turn as a counteroffer to another civ's peace offer
Expand Down Expand Up @@ -341,8 +340,8 @@ object DiplomacyAutomation {
val potentialAllies = enemyCiv.threatManager.getNeighboringCivilizations()
.filter {
civInfo.knows(it) && !it.isAtWarWith(enemyCiv)
&& civInfo.getDiplomacyManager(it).isRelationshipLevelGE(RelationshipLevel.Friend)
&& !it.getDiplomacyManager(civInfo).hasFlag(DiplomacyFlags.DeclinedJoinWarOffer) }
&& civInfo.getDiplomacyManager(it)!!.isRelationshipLevelGE(RelationshipLevel.Friend)
&& !it.getDiplomacyManager(civInfo)!!.hasFlag(DiplomacyFlags.DeclinedJoinWarOffer) }
.sortedByDescending { it.getStatForRanking(RankingType.Force) }
val civToAsk = potentialAllies.firstOrNull {
DeclareWarPlanEvaluator.evaluateJoinOurWarPlan(civInfo, enemyCiv, it, null) > 0 } ?: continue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ object MotivationToAttackAutomation {
modifiers.add(Pair("Their allies", getDefensivePactAlliesScore(targetCiv, civInfo, baseForce, ourCombatStrength)))

if (civInfo.threatManager.getNeighboringCivilizations().none { it != targetCiv && it.isMajorCiv()
&& civInfo.getDiplomacyManager(it).isRelationshipLevelLT(RelationshipLevel.Friend) })
&& civInfo.getDiplomacyManager(it)!!.isRelationshipLevelLT(RelationshipLevel.Friend) })
modifiers.add(Pair("No other threats", 10))

if (targetCiv.isMajorCiv()) {
Expand All @@ -70,7 +70,7 @@ object MotivationToAttackAutomation {
}))
if (minTargetCityDistance < 6) modifiers.add(Pair("Close cities", 5))

val diplomacyManager = civInfo.getDiplomacyManager(targetCiv)
val diplomacyManager = civInfo.getDiplomacyManager(targetCiv)!!

if (diplomacyManager.hasFlag(DiplomacyFlags.ResearchAgreement))
modifiers.add(Pair("Research Agreement", -5))
Expand Down Expand Up @@ -165,12 +165,12 @@ object MotivationToAttackAutomation {
/** If they are at war with our allies, then we should join in */
private fun getAlliedWarMotivation(civInfo: Civilization, otherCiv: Civilization): Int {
var alliedWarMotivation = 0
for (thirdCiv in civInfo.getDiplomacyManager(otherCiv).getCommonKnownCivs()) {
for (thirdCiv in civInfo.getDiplomacyManager(otherCiv)!!.getCommonKnownCivs()) {
val thirdCivDiploManager = civInfo.getDiplomacyManager(thirdCiv)
if (thirdCivDiploManager.isRelationshipLevelGE(RelationshipLevel.Friend)
if (thirdCivDiploManager!!.isRelationshipLevelGE(RelationshipLevel.Friend)
&& thirdCiv.isAtWarWith(otherCiv)
) {
if (thirdCiv.getDiplomacyManager(otherCiv).hasFlag(DiplomacyFlags.Denunciation))
if (thirdCiv.getDiplomacyManager(otherCiv)!!.hasFlag(DiplomacyFlags.Denunciation))
alliedWarMotivation += 2
alliedWarMotivation += if (thirdCivDiploManager.hasFlag(DiplomacyFlags.DefensivePact)) 15
else if (thirdCivDiploManager.isRelationshipLevelGT(RelationshipLevel.Friend)) 5
Expand Down
Loading

0 comments on commit bbea083

Please sign in to comment.