diff --git a/core/src/com/unciv/logic/automation/Automation.kt b/core/src/com/unciv/logic/automation/Automation.kt index 97bcbb1292..f662bb2d61 100644 --- a/core/src/com/unciv/logic/automation/Automation.kt +++ b/core/src/com/unciv/logic/automation/Automation.kt @@ -362,11 +362,12 @@ object Automation { } // Ranks a tile for any purpose except the expansion algorithm of cities - internal fun rankTile(tile: Tile?, civInfo: Civilization): Float { + internal fun rankTile(tile: Tile?, civInfo: Civilization, + localUniqueCache: LocalUniqueCache): Float { if (tile == null) return 0f val tileOwner = tile.getOwner() if (tileOwner != null && tileOwner != civInfo) return 0f // Already belongs to another civilization, useless to us - val stats = tile.stats.getTileStats(null, civInfo) + val stats = tile.stats.getTileStats(null, civInfo, localUniqueCache) var rank = rankStatsValue(stats, civInfo) if (tile.improvement == null) rank += 0.5f // improvement potential! if (tile.isPillaged()) rank += 0.6f diff --git a/core/src/com/unciv/logic/automation/unit/CityLocationTileRanker.kt b/core/src/com/unciv/logic/automation/unit/CityLocationTileRanker.kt index 32bef7ab90..8fcca203c5 100644 --- a/core/src/com/unciv/logic/automation/unit/CityLocationTileRanker.kt +++ b/core/src/com/unciv/logic/automation/unit/CityLocationTileRanker.kt @@ -7,6 +7,7 @@ import com.unciv.logic.map.mapunit.MapUnit import com.unciv.logic.map.tile.Tile import com.unciv.models.ruleset.tile.ResourceType import com.unciv.models.ruleset.tile.TileResource +import com.unciv.models.ruleset.unique.LocalUniqueCache object CityLocationTileRanker { fun getBestTilesToFoundCity(unit: MapUnit): Sequence> { @@ -93,14 +94,15 @@ object CityLocationTileRanker { tile: Tile, civ: Civilization ): Map { + val uniqueCache = LocalUniqueCache() return tile.getTilesInDistance(7) .filter { canUseTileForRanking(it, civ) } - .associateBy({ it }, { Automation.rankTile(it, civ) }) + .associateBy({ it }, { Automation.rankTile(it, civ, uniqueCache) }) } private fun getLuxuryResourcesInCivArea(civ: Civilization): Sequence { return civ.cities.asSequence() - .flatMap { it.getTiles().asSequence() }.filter { it.resource != null } + .flatMap { it.getTiles() }.filter { it.resource != null } .map { it.tileResource }.filter { it.resourceType == ResourceType.Luxury } .distinct() } diff --git a/core/src/com/unciv/logic/automation/unit/SpecificUnitAutomation.kt b/core/src/com/unciv/logic/automation/unit/SpecificUnitAutomation.kt index e93d23b9dc..d8c7d57e92 100644 --- a/core/src/com/unciv/logic/automation/unit/SpecificUnitAutomation.kt +++ b/core/src/com/unciv/logic/automation/unit/SpecificUnitAutomation.kt @@ -14,6 +14,7 @@ import com.unciv.logic.map.tile.Tile import com.unciv.models.UnitAction import com.unciv.models.UnitActionType import com.unciv.models.ruleset.Building +import com.unciv.models.ruleset.unique.LocalUniqueCache import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.stats.Stat import com.unciv.ui.screens.worldscreen.unit.actions.UnitActions @@ -199,10 +200,12 @@ object SpecificUnitAutomation { } // if we got here, we're pretty close, start looking! + val localUniqueCache = LocalUniqueCache() val chosenTile = applicableTiles.sortedByDescending { Automation.rankTile( it, - unit.civ + unit.civ, + localUniqueCache ) } .firstOrNull { unit.movement.canReach(it) } @@ -500,7 +503,7 @@ object SpecificUnitAutomation { val tilesInRange = unit.currentTile.getTilesInDistanceRange(2..unit.getRange()) var highestTileNukeValue = 0 var tileToNuke: Tile? = null - tilesInRange.forEach { + tilesInRange.forEach { val value = getNukeLocationValue(unit, it) if (value > highestTileNukeValue) { highestTileNukeValue = value @@ -524,15 +527,15 @@ object SpecificUnitAutomation { val tilesInBlastRadius = tile.getTilesInDistance(blastRadius) val civsInBlastRadius = tilesInBlastRadius.mapNotNull { it.getOwner() } + tilesInBlastRadius.mapNotNull { it.getFirstUnit()?.civ } - + // Don't nuke if it means we will be declaring war on someone! if (civsInBlastRadius.any { it != civ && !it.isAtWarWith(civ) }) return -100000 // If there are no enemies to hit, don't nuke if (!civsInBlastRadius.any { it.isAtWarWith(civ) }) return -100000 - + // Launching a Nuke uses resources, therefore don't launch it by default var explosionValue = -500 - + // Returns either ourValue or thierValue depending on if the input Civ matches the Nuke's Civ fun evaluateCivValue(targetCiv: Civilization, ourValue: Int, theirValue: Int): Int { if (targetCiv == civ) // We are nuking something that we own! @@ -548,8 +551,8 @@ object SpecificUnitAutomation { explosionValue += evaluateCivValue(targetTile.civilianUnit?.civ!!, -100, 25) } // Never nuke our own Civ, don't nuke single enemy civs as well - if (targetTile.isCityCenter() - && !(targetTile.getCity()!!.health <= 50f + if (targetTile.isCityCenter() + && !(targetTile.getCity()!!.health <= 50f && targetTile.neighbors.any {it.militaryUnit?.civ == civ})) // Prefer not to nuke cities that we are about to take explosionValue += evaluateCivValue(targetTile.getCity()?.civ!!, -100000, 250) else if (targetTile.owningCity != null) { diff --git a/core/src/com/unciv/logic/automation/unit/WorkerAutomation.kt b/core/src/com/unciv/logic/automation/unit/WorkerAutomation.kt index 57ea33be25..3e60e8277c 100644 --- a/core/src/com/unciv/logic/automation/unit/WorkerAutomation.kt +++ b/core/src/com/unciv/logic/automation/unit/WorkerAutomation.kt @@ -390,14 +390,10 @@ class WorkerAutomation( } if (potentialTileImprovements.isEmpty()) return null - val cityUniqueCaches = HashMap() + val localUniqueCache = LocalUniqueCache() fun getImprovementRanking(improvementName: String): Float { val improvement = ruleSet.tileImprovements[improvementName]!! - val city = tile.getCity() - val cache = - if (city == null) LocalUniqueCache(false) - else cityUniqueCaches.getOrPut(city) { LocalUniqueCache() } - val stats = tile.stats.getStatDiffForImprovement(improvement, civInfo, tile.getCity(), cache) + val stats = tile.stats.getStatDiffForImprovement(improvement, civInfo, tile.getCity(), localUniqueCache) return Automation.rankStatsValue(stats, unit.civ) } diff --git a/core/src/com/unciv/ui/screens/pickerscreens/ImprovementPickerScreen.kt b/core/src/com/unciv/ui/screens/pickerscreens/ImprovementPickerScreen.kt index 070fb00d1a..7264285a40 100644 --- a/core/src/com/unciv/ui/screens/pickerscreens/ImprovementPickerScreen.kt +++ b/core/src/com/unciv/ui/screens/pickerscreens/ImprovementPickerScreen.kt @@ -169,10 +169,10 @@ class ImprovementPickerScreen( //Warn when the current improvement will increase a stat for the tile, // but the tile is outside of the range (> 3 tiles from city center) that can be // worked by a city's population - if (stats.values.any { it > 0f } + if (tile.owningCity != null + && !improvement.isRoad() + && stats.values.any { it > 0f } && !improvement.name.startsWith(Constants.remove) - && !improvement.isRoad() - && tile.owningCity != null && !tile.owningCity!!.getWorkableTiles().contains(tile) ) labelText += "\n" + "Not in city work range".tr()