diff --git a/core/src/com/unciv/logic/automation/NextTurnAutomation.kt b/core/src/com/unciv/logic/automation/NextTurnAutomation.kt index 460f47239a..4893ec5c31 100644 --- a/core/src/com/unciv/logic/automation/NextTurnAutomation.kt +++ b/core/src/com/unciv/logic/automation/NextTurnAutomation.kt @@ -299,8 +299,6 @@ object NextTurnAutomation { private fun valueCityStateAlliance(civInfo: CivilizationInfo, cityState: CivilizationInfo): Int { var value = 0 - if (!cityState.isAlive() || cityState.cities.isEmpty() || civInfo.cities.isEmpty()) - return value if (civInfo.wantsToFocusOn(Victory.Focus.Culture) && cityState.canGiveStat(Stat.Culture)) { value += 10 @@ -310,24 +308,33 @@ object NextTurnAutomation { value += 10 } else if (civInfo.wantsToFocusOn(Victory.Focus.Military)) { - // Don't ally close city-states, conquer them instead - val distance = getMinDistanceBetweenCities(civInfo, cityState) - if (distance < 20) - value -= (20 - distance) / 4 + if (!cityState.isAlive()) + value -= 5 + else { + // Don't ally close city-states, conquer them instead + val distance = getMinDistanceBetweenCities(civInfo, cityState) + if (distance < 20) + value -= (20 - distance) / 4 + } } else if (civInfo.wantsToFocusOn(Victory.Focus.CityStates)) { value += 5 // Generally be friendly } - if (civInfo.gold < 100) { - // Consider bullying for cash - value -= 5 - } if (civInfo.getHappiness() < 5 && cityState.canGiveStat(Stat.Happiness)) { value += 10 - civInfo.getHappiness() } if (civInfo.getHappiness() > 5 && cityState.canGiveStat(Stat.Food)) { value += 5 } + + if (!cityState.isAlive() || cityState.cities.isEmpty() || civInfo.cities.isEmpty()) + return value + + if (civInfo.gold < 100) { + // Consider bullying for cash + value -= 5 + } + if (cityState.getAllyCiv() != null && cityState.getAllyCiv() != civInfo.civName) { // easier not to compete if a third civ has this locked down val thirdCivInfluence = cityState.getDiplomacyManager(cityState.getAllyCiv()!!).getInfluence().toInt() @@ -936,6 +943,31 @@ object NextTurnAutomation { diplomacyManager.removeFlag(DiplomacyFlags.SettledCitiesNearUs) } + /** Handle decision making after city conquest, namely whether the AI should liberate, puppet, + * or raze a city */ + fun onConquerCity(civInfo: CivilizationInfo, city: CityInfo) { + if (!city.hasDiplomaticMarriage()) { + val foundingCiv = civInfo.gameInfo.getCivilization(city.foundingCiv) + var valueAlliance = valueCityStateAlliance(civInfo, foundingCiv) + if (civInfo.getHappiness() < 0) + valueAlliance -= civInfo.getHappiness() // put extra weight on liberating if unhappy + if (foundingCiv.isCityState() && city.civInfo != civInfo && foundingCiv != civInfo + && !civInfo.isAtWarWith(foundingCiv) + && valueAlliance > 0) { + city.liberateCity(civInfo) + return + } + } + + city.puppetCity(civInfo) + if ((city.population.population < 4 || civInfo.isCityState()) + && city.foundingCiv != civInfo.civName && city.canBeDestroyed(justCaptured = true)) { + // raze if attacker is a city state + city.annexCity() + city.isBeingRazed = true + } + } + fun getMinDistanceBetweenCities(civ1: CivilizationInfo, civ2: CivilizationInfo): Int { return getClosestCities(civ1, civ2).aerialDistance } diff --git a/core/src/com/unciv/logic/battle/Battle.kt b/core/src/com/unciv/logic/battle/Battle.kt index 6553880a3c..c0e5da85e7 100644 --- a/core/src/com/unciv/logic/battle/Battle.kt +++ b/core/src/com/unciv/logic/battle/Battle.kt @@ -3,6 +3,7 @@ package com.unciv.logic.battle import com.badlogic.gdx.math.Vector2 import com.unciv.Constants import com.unciv.UncivGame +import com.unciv.logic.automation.NextTurnAutomation import com.unciv.logic.city.CityInfo import com.unciv.logic.civilization.AlertType import com.unciv.logic.civilization.CivilizationInfo @@ -540,15 +541,7 @@ object Battle { // we're not taking our former capital attackerCiv.popupAlerts.add(PopupAlert(AlertType.CityConquered, city.id)) } else { - // ideally here we would do some AI thinking for liberation vs. razing - // e.g., valueCityStateAlliance() > 0 to determine if we should liberate a city-state - city.puppetCity(attackerCiv) - if ((city.population.population < 4 || attackerCiv.isCityState()) - && city.canBeDestroyed(justCaptured = true)) { - // raze if attacker is a city state - city.annexCity() - city.isBeingRazed = true - } + NextTurnAutomation.onConquerCity(attackerCiv, city) } if (attackerCiv.isPlayerCivilization()) diff --git a/core/src/com/unciv/logic/city/CityInfo.kt b/core/src/com/unciv/logic/city/CityInfo.kt index 33356bc26a..df7a8ab558 100644 --- a/core/src/com/unciv/logic/city/CityInfo.kt +++ b/core/src/com/unciv/logic/city/CityInfo.kt @@ -145,6 +145,8 @@ class CityInfo { private var flagsCountdown = HashMap() + fun hasDiplomaticMarriage(): Boolean = foundingCiv == "" + constructor() // for json parsing, we need to have a default constructor constructor(civInfo: CivilizationInfo, cityLocation: Vector2) { // new city! this.civInfo = civInfo