mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-30 15:30:43 -04:00
AI considers liberating city-states from other civilizations (#7157)
* AI will consider liberating a city state on conquest * Factor in current civ happiness for liberation consideration * Refactor foundingCiv check into function
This commit is contained in:
parent
4fb2ad8fab
commit
623b84ea30
@ -299,8 +299,6 @@ object NextTurnAutomation {
|
|||||||
|
|
||||||
private fun valueCityStateAlliance(civInfo: CivilizationInfo, cityState: CivilizationInfo): Int {
|
private fun valueCityStateAlliance(civInfo: CivilizationInfo, cityState: CivilizationInfo): Int {
|
||||||
var value = 0
|
var value = 0
|
||||||
if (!cityState.isAlive() || cityState.cities.isEmpty() || civInfo.cities.isEmpty())
|
|
||||||
return value
|
|
||||||
|
|
||||||
if (civInfo.wantsToFocusOn(Victory.Focus.Culture) && cityState.canGiveStat(Stat.Culture)) {
|
if (civInfo.wantsToFocusOn(Victory.Focus.Culture) && cityState.canGiveStat(Stat.Culture)) {
|
||||||
value += 10
|
value += 10
|
||||||
@ -310,24 +308,33 @@ object NextTurnAutomation {
|
|||||||
value += 10
|
value += 10
|
||||||
}
|
}
|
||||||
else if (civInfo.wantsToFocusOn(Victory.Focus.Military)) {
|
else if (civInfo.wantsToFocusOn(Victory.Focus.Military)) {
|
||||||
|
if (!cityState.isAlive())
|
||||||
|
value -= 5
|
||||||
|
else {
|
||||||
// Don't ally close city-states, conquer them instead
|
// Don't ally close city-states, conquer them instead
|
||||||
val distance = getMinDistanceBetweenCities(civInfo, cityState)
|
val distance = getMinDistanceBetweenCities(civInfo, cityState)
|
||||||
if (distance < 20)
|
if (distance < 20)
|
||||||
value -= (20 - distance) / 4
|
value -= (20 - distance) / 4
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (civInfo.wantsToFocusOn(Victory.Focus.CityStates)) {
|
else if (civInfo.wantsToFocusOn(Victory.Focus.CityStates)) {
|
||||||
value += 5 // Generally be friendly
|
value += 5 // Generally be friendly
|
||||||
}
|
}
|
||||||
if (civInfo.gold < 100) {
|
|
||||||
// Consider bullying for cash
|
|
||||||
value -= 5
|
|
||||||
}
|
|
||||||
if (civInfo.getHappiness() < 5 && cityState.canGiveStat(Stat.Happiness)) {
|
if (civInfo.getHappiness() < 5 && cityState.canGiveStat(Stat.Happiness)) {
|
||||||
value += 10 - civInfo.getHappiness()
|
value += 10 - civInfo.getHappiness()
|
||||||
}
|
}
|
||||||
if (civInfo.getHappiness() > 5 && cityState.canGiveStat(Stat.Food)) {
|
if (civInfo.getHappiness() > 5 && cityState.canGiveStat(Stat.Food)) {
|
||||||
value += 5
|
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) {
|
if (cityState.getAllyCiv() != null && cityState.getAllyCiv() != civInfo.civName) {
|
||||||
// easier not to compete if a third civ has this locked down
|
// easier not to compete if a third civ has this locked down
|
||||||
val thirdCivInfluence = cityState.getDiplomacyManager(cityState.getAllyCiv()!!).getInfluence().toInt()
|
val thirdCivInfluence = cityState.getDiplomacyManager(cityState.getAllyCiv()!!).getInfluence().toInt()
|
||||||
@ -936,6 +943,31 @@ object NextTurnAutomation {
|
|||||||
diplomacyManager.removeFlag(DiplomacyFlags.SettledCitiesNearUs)
|
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 {
|
fun getMinDistanceBetweenCities(civ1: CivilizationInfo, civ2: CivilizationInfo): Int {
|
||||||
return getClosestCities(civ1, civ2).aerialDistance
|
return getClosestCities(civ1, civ2).aerialDistance
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.unciv.logic.battle
|
|||||||
import com.badlogic.gdx.math.Vector2
|
import com.badlogic.gdx.math.Vector2
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
|
import com.unciv.logic.automation.NextTurnAutomation
|
||||||
import com.unciv.logic.city.CityInfo
|
import com.unciv.logic.city.CityInfo
|
||||||
import com.unciv.logic.civilization.AlertType
|
import com.unciv.logic.civilization.AlertType
|
||||||
import com.unciv.logic.civilization.CivilizationInfo
|
import com.unciv.logic.civilization.CivilizationInfo
|
||||||
@ -540,15 +541,7 @@ object Battle {
|
|||||||
// we're not taking our former capital
|
// we're not taking our former capital
|
||||||
attackerCiv.popupAlerts.add(PopupAlert(AlertType.CityConquered, city.id))
|
attackerCiv.popupAlerts.add(PopupAlert(AlertType.CityConquered, city.id))
|
||||||
} else {
|
} else {
|
||||||
// ideally here we would do some AI thinking for liberation vs. razing
|
NextTurnAutomation.onConquerCity(attackerCiv, city)
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attackerCiv.isPlayerCivilization())
|
if (attackerCiv.isPlayerCivilization())
|
||||||
|
@ -145,6 +145,8 @@ class CityInfo {
|
|||||||
|
|
||||||
private var flagsCountdown = HashMap<String, Int>()
|
private var flagsCountdown = HashMap<String, Int>()
|
||||||
|
|
||||||
|
fun hasDiplomaticMarriage(): Boolean = foundingCiv == ""
|
||||||
|
|
||||||
constructor() // for json parsing, we need to have a default constructor
|
constructor() // for json parsing, we need to have a default constructor
|
||||||
constructor(civInfo: CivilizationInfo, cityLocation: Vector2) { // new city!
|
constructor(civInfo: CivilizationInfo, cityLocation: Vector2) { // new city!
|
||||||
this.civInfo = civInfo
|
this.civInfo = civInfo
|
||||||
|
Loading…
x
Reference in New Issue
Block a user