From 075a5c70c77bd2a88c3d7aecadac2976385852bd Mon Sep 17 00:00:00 2001 From: yairm210 Date: Thu, 11 Jul 2024 13:23:44 +0300 Subject: [PATCH] Unified AI and Human gold purchase logic --- .../civilization/UseGoldAutomation.kt | 14 ++++++------- .../com/unciv/logic/city/CityConstructions.kt | 16 ++++++++++++++- .../com/unciv/models/ruleset/IConstruction.kt | 1 - .../cityscreen/CityConstructionsTable.kt | 20 +++---------------- 4 files changed, 24 insertions(+), 27 deletions(-) diff --git a/core/src/com/unciv/logic/automation/civilization/UseGoldAutomation.kt b/core/src/com/unciv/logic/automation/civilization/UseGoldAutomation.kt index 4c5702baa8..ddab6fae02 100644 --- a/core/src/com/unciv/logic/automation/civilization/UseGoldAutomation.kt +++ b/core/src/com/unciv/logic/automation/civilization/UseGoldAutomation.kt @@ -5,13 +5,11 @@ import com.unciv.logic.civilization.Civilization import com.unciv.logic.map.BFS import com.unciv.logic.map.tile.Tile import com.unciv.models.ruleset.INonPerpetualConstruction -import com.unciv.models.ruleset.PerpetualConstruction import com.unciv.models.ruleset.Victory import com.unciv.models.ruleset.tile.ResourceType import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.stats.Stat -import java.util.SortedMap -import java.util.TreeMap +import java.util.* object UseGoldAutomation { @@ -23,11 +21,11 @@ object UseGoldAutomation { for (city in civ.cities.sortedByDescending { it.population.population }) { val construction = city.cityConstructions.getCurrentConstruction() - if (construction is PerpetualConstruction) continue - if ((construction as INonPerpetualConstruction).canBePurchasedWithStat(city, Stat.Gold) - && city.civ.gold / 3 >= construction.getStatBuyCost(city, Stat.Gold)!!) { - city.cityConstructions.purchaseConstruction(construction, 0, true) - } + if (construction !is INonPerpetualConstruction) continue + val statBuyCost = construction.getStatBuyCost(city, Stat.Gold) ?: continue + if (!city.cityConstructions.isConstructionPurchaseAllowed(construction, Stat.Gold, statBuyCost)) continue + if (civ.gold < statBuyCost / 3) continue + city.cityConstructions.purchaseConstruction(construction, 0, true) } maybeBuyCityTiles(civ) diff --git a/core/src/com/unciv/logic/city/CityConstructions.kt b/core/src/com/unciv/logic/city/CityConstructions.kt index 8a573237d7..0cc63c93b9 100644 --- a/core/src/com/unciv/logic/city/CityConstructions.kt +++ b/core/src/com/unciv/logic/city/CityConstructions.kt @@ -155,7 +155,7 @@ class CityConstructions : IsPartOfGameInfoSerialization { if (buildable) lines += (if (currentProgress == 0) "" else "$currentProgress/") + "$cost${Fonts.production} $turnsToConstruction${Fonts.turn}" - val otherStats = Stat.values().filter { + val otherStats = Stat.entries.filter { (it != Stat.Gold || !buildable) && // Don't show rush cost for consistency construction.canBePurchasedWithStat(city, it) }.joinToString(" / ") { "${construction.getStatBuyCost(city, it)}${it.character}" } @@ -698,6 +698,20 @@ class CityConstructions : IsPartOfGameInfoSerialization { return true } + + /** This tests whether the buy button should be _enabled_ */ + fun isConstructionPurchaseAllowed(construction: INonPerpetualConstruction, stat: Stat, constructionBuyCost: Int): Boolean { + return when { + city.isPuppet && !city.getMatchingUniques(UniqueType.MayBuyConstructionsInPuppets).any() -> false + city.isInResistance() -> false + !construction.isPurchasable(city.cityConstructions) -> false // checks via 'rejection reason' + construction is BaseUnit && !city.canPlaceNewUnit(construction) -> false + city.civ.gameInfo.gameParameters.godMode -> true + constructionBuyCost == 0 -> true + else -> city.getStatReserve(stat) >= constructionBuyCost + } + } + private fun removeCurrentConstruction() = removeFromQueue(0, true) fun chooseNextConstruction() { diff --git a/core/src/com/unciv/models/ruleset/IConstruction.kt b/core/src/com/unciv/models/ruleset/IConstruction.kt index 43d20b124f..6dca939c31 100644 --- a/core/src/com/unciv/models/ruleset/IConstruction.kt +++ b/core/src/com/unciv/models/ruleset/IConstruction.kt @@ -67,7 +67,6 @@ interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques { } fun canBePurchasedWithAnyStat(city: City): Boolean { - return statsUsableToBuy.any { canBePurchasedWithStat(city, it) } } diff --git a/core/src/com/unciv/ui/screens/cityscreen/CityConstructionsTable.kt b/core/src/com/unciv/ui/screens/cityscreen/CityConstructionsTable.kt index 9ca112ae94..a822f36d13 100644 --- a/core/src/com/unciv/ui/screens/cityscreen/CityConstructionsTable.kt +++ b/core/src/com/unciv/ui/screens/cityscreen/CityConstructionsTable.kt @@ -644,7 +644,8 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { button.disable() buyButtonOnClick(construction, stat) } - button.isEnabled = isConstructionPurchaseAllowed(construction, stat, constructionBuyCost) + button.isEnabled = cityScreen.canCityBeChanged() && + city.cityConstructions.isConstructionPurchaseAllowed(construction, stat, constructionBuyCost) preferredBuyStat = stat // Not very intelligent, but the least common currency "wins" } @@ -679,7 +680,7 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { if (!isConstructionPurchaseShown(construction, stat)) return val city = cityScreen.city val constructionStatBuyCost = construction.getStatBuyCost(city, stat)!! - if (!isConstructionPurchaseAllowed(construction, stat, constructionStatBuyCost)) return + if (!city.cityConstructions.isConstructionPurchaseAllowed(construction, stat, constructionStatBuyCost)) return cityScreen.closeAllPopups() ConfirmBuyPopup(construction, stat,constructionStatBuyCost, tile) @@ -728,21 +729,6 @@ class CityConstructionsTable(private val cityScreen: CityScreen) { return construction.canBePurchasedWithStat(city, stat) } - /** This tests whether the buy button should be _enabled_ */ - private fun isConstructionPurchaseAllowed(construction: INonPerpetualConstruction, stat: Stat, constructionBuyCost: Int): Boolean { - val city = cityScreen.city - return when { - city.isPuppet && !city.getMatchingUniques(UniqueType.MayBuyConstructionsInPuppets).any() -> false - !cityScreen.canChangeState -> false - city.isInResistance() -> false - !construction.isPurchasable(city.cityConstructions) -> false // checks via 'rejection reason' - construction is BaseUnit && !city.canPlaceNewUnit(construction) -> false - city.civ.gameInfo.gameParameters.godMode -> true - constructionBuyCost == 0 -> true - else -> city.getStatReserve(stat) >= constructionBuyCost - } - } - /** Called only by askToBuyConstruction's Yes answer - not to be confused with [CityConstructions.purchaseConstruction] * @param tile supports [UniqueType.CreatesOneImprovement] */