mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-26 05:14:32 -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 {
|
||||
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
|
||||
}
|
||||
|
@ -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())
|
||||
|
@ -145,6 +145,8 @@ class CityInfo {
|
||||
|
||||
private var flagsCountdown = HashMap<String, Int>()
|
||||
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user