mirror of
https://github.com/yairm210/Unciv.git
synced 2025-01-05 21:11:35 +07:00
Performance: Cache uniques when choosing best tiles to settle/create improvements on
Resuse cache between cities for choosing best improvement for worker to pick (but not between workers...YET) Alternate title: MOAR CACHES EVERYWHERE
This commit is contained in:
parent
f8ccefd10c
commit
ad7397ecc9
@ -362,11 +362,12 @@ object Automation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ranks a tile for any purpose except the expansion algorithm of cities
|
// 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
|
if (tile == null) return 0f
|
||||||
val tileOwner = tile.getOwner()
|
val tileOwner = tile.getOwner()
|
||||||
if (tileOwner != null && tileOwner != civInfo) return 0f // Already belongs to another civilization, useless to us
|
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)
|
var rank = rankStatsValue(stats, civInfo)
|
||||||
if (tile.improvement == null) rank += 0.5f // improvement potential!
|
if (tile.improvement == null) rank += 0.5f // improvement potential!
|
||||||
if (tile.isPillaged()) rank += 0.6f
|
if (tile.isPillaged()) rank += 0.6f
|
||||||
|
@ -7,6 +7,7 @@ import com.unciv.logic.map.mapunit.MapUnit
|
|||||||
import com.unciv.logic.map.tile.Tile
|
import com.unciv.logic.map.tile.Tile
|
||||||
import com.unciv.models.ruleset.tile.ResourceType
|
import com.unciv.models.ruleset.tile.ResourceType
|
||||||
import com.unciv.models.ruleset.tile.TileResource
|
import com.unciv.models.ruleset.tile.TileResource
|
||||||
|
import com.unciv.models.ruleset.unique.LocalUniqueCache
|
||||||
|
|
||||||
object CityLocationTileRanker {
|
object CityLocationTileRanker {
|
||||||
fun getBestTilesToFoundCity(unit: MapUnit): Sequence<Pair<Tile, Float>> {
|
fun getBestTilesToFoundCity(unit: MapUnit): Sequence<Pair<Tile, Float>> {
|
||||||
@ -93,14 +94,15 @@ object CityLocationTileRanker {
|
|||||||
tile: Tile,
|
tile: Tile,
|
||||||
civ: Civilization
|
civ: Civilization
|
||||||
): Map<Tile, Float> {
|
): Map<Tile, Float> {
|
||||||
|
val uniqueCache = LocalUniqueCache()
|
||||||
return tile.getTilesInDistance(7)
|
return tile.getTilesInDistance(7)
|
||||||
.filter { canUseTileForRanking(it, civ) }
|
.filter { canUseTileForRanking(it, civ) }
|
||||||
.associateBy({ it }, { Automation.rankTile(it, civ) })
|
.associateBy({ it }, { Automation.rankTile(it, civ, uniqueCache) })
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getLuxuryResourcesInCivArea(civ: Civilization): Sequence<TileResource> {
|
private fun getLuxuryResourcesInCivArea(civ: Civilization): Sequence<TileResource> {
|
||||||
return civ.cities.asSequence()
|
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 }
|
.map { it.tileResource }.filter { it.resourceType == ResourceType.Luxury }
|
||||||
.distinct()
|
.distinct()
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import com.unciv.logic.map.tile.Tile
|
|||||||
import com.unciv.models.UnitAction
|
import com.unciv.models.UnitAction
|
||||||
import com.unciv.models.UnitActionType
|
import com.unciv.models.UnitActionType
|
||||||
import com.unciv.models.ruleset.Building
|
import com.unciv.models.ruleset.Building
|
||||||
|
import com.unciv.models.ruleset.unique.LocalUniqueCache
|
||||||
import com.unciv.models.ruleset.unique.UniqueType
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
import com.unciv.models.stats.Stat
|
import com.unciv.models.stats.Stat
|
||||||
import com.unciv.ui.screens.worldscreen.unit.actions.UnitActions
|
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!
|
// if we got here, we're pretty close, start looking!
|
||||||
|
val localUniqueCache = LocalUniqueCache()
|
||||||
val chosenTile = applicableTiles.sortedByDescending {
|
val chosenTile = applicableTiles.sortedByDescending {
|
||||||
Automation.rankTile(
|
Automation.rankTile(
|
||||||
it,
|
it,
|
||||||
unit.civ
|
unit.civ,
|
||||||
|
localUniqueCache
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.firstOrNull { unit.movement.canReach(it) }
|
.firstOrNull { unit.movement.canReach(it) }
|
||||||
@ -500,7 +503,7 @@ object SpecificUnitAutomation {
|
|||||||
val tilesInRange = unit.currentTile.getTilesInDistanceRange(2..unit.getRange())
|
val tilesInRange = unit.currentTile.getTilesInDistanceRange(2..unit.getRange())
|
||||||
var highestTileNukeValue = 0
|
var highestTileNukeValue = 0
|
||||||
var tileToNuke: Tile? = null
|
var tileToNuke: Tile? = null
|
||||||
tilesInRange.forEach {
|
tilesInRange.forEach {
|
||||||
val value = getNukeLocationValue(unit, it)
|
val value = getNukeLocationValue(unit, it)
|
||||||
if (value > highestTileNukeValue) {
|
if (value > highestTileNukeValue) {
|
||||||
highestTileNukeValue = value
|
highestTileNukeValue = value
|
||||||
@ -524,15 +527,15 @@ object SpecificUnitAutomation {
|
|||||||
val tilesInBlastRadius = tile.getTilesInDistance(blastRadius)
|
val tilesInBlastRadius = tile.getTilesInDistance(blastRadius)
|
||||||
val civsInBlastRadius = tilesInBlastRadius.mapNotNull { it.getOwner() } +
|
val civsInBlastRadius = tilesInBlastRadius.mapNotNull { it.getOwner() } +
|
||||||
tilesInBlastRadius.mapNotNull { it.getFirstUnit()?.civ }
|
tilesInBlastRadius.mapNotNull { it.getFirstUnit()?.civ }
|
||||||
|
|
||||||
// Don't nuke if it means we will be declaring war on someone!
|
// Don't nuke if it means we will be declaring war on someone!
|
||||||
if (civsInBlastRadius.any { it != civ && !it.isAtWarWith(civ) }) return -100000
|
if (civsInBlastRadius.any { it != civ && !it.isAtWarWith(civ) }) return -100000
|
||||||
// If there are no enemies to hit, don't nuke
|
// If there are no enemies to hit, don't nuke
|
||||||
if (!civsInBlastRadius.any { it.isAtWarWith(civ) }) return -100000
|
if (!civsInBlastRadius.any { it.isAtWarWith(civ) }) return -100000
|
||||||
|
|
||||||
// Launching a Nuke uses resources, therefore don't launch it by default
|
// Launching a Nuke uses resources, therefore don't launch it by default
|
||||||
var explosionValue = -500
|
var explosionValue = -500
|
||||||
|
|
||||||
// Returns either ourValue or thierValue depending on if the input Civ matches the Nuke's Civ
|
// 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 {
|
fun evaluateCivValue(targetCiv: Civilization, ourValue: Int, theirValue: Int): Int {
|
||||||
if (targetCiv == civ) // We are nuking something that we own!
|
if (targetCiv == civ) // We are nuking something that we own!
|
||||||
@ -548,8 +551,8 @@ object SpecificUnitAutomation {
|
|||||||
explosionValue += evaluateCivValue(targetTile.civilianUnit?.civ!!, -100, 25)
|
explosionValue += evaluateCivValue(targetTile.civilianUnit?.civ!!, -100, 25)
|
||||||
}
|
}
|
||||||
// Never nuke our own Civ, don't nuke single enemy civs as well
|
// Never nuke our own Civ, don't nuke single enemy civs as well
|
||||||
if (targetTile.isCityCenter()
|
if (targetTile.isCityCenter()
|
||||||
&& !(targetTile.getCity()!!.health <= 50f
|
&& !(targetTile.getCity()!!.health <= 50f
|
||||||
&& targetTile.neighbors.any {it.militaryUnit?.civ == civ})) // Prefer not to nuke cities that we are about to take
|
&& 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)
|
explosionValue += evaluateCivValue(targetTile.getCity()?.civ!!, -100000, 250)
|
||||||
else if (targetTile.owningCity != null) {
|
else if (targetTile.owningCity != null) {
|
||||||
|
@ -390,14 +390,10 @@ class WorkerAutomation(
|
|||||||
}
|
}
|
||||||
if (potentialTileImprovements.isEmpty()) return null
|
if (potentialTileImprovements.isEmpty()) return null
|
||||||
|
|
||||||
val cityUniqueCaches = HashMap<City, LocalUniqueCache>()
|
val localUniqueCache = LocalUniqueCache()
|
||||||
fun getImprovementRanking(improvementName: String): Float {
|
fun getImprovementRanking(improvementName: String): Float {
|
||||||
val improvement = ruleSet.tileImprovements[improvementName]!!
|
val improvement = ruleSet.tileImprovements[improvementName]!!
|
||||||
val city = tile.getCity()
|
val stats = tile.stats.getStatDiffForImprovement(improvement, civInfo, tile.getCity(), localUniqueCache)
|
||||||
val cache =
|
|
||||||
if (city == null) LocalUniqueCache(false)
|
|
||||||
else cityUniqueCaches.getOrPut(city) { LocalUniqueCache() }
|
|
||||||
val stats = tile.stats.getStatDiffForImprovement(improvement, civInfo, tile.getCity(), cache)
|
|
||||||
return Automation.rankStatsValue(stats, unit.civ)
|
return Automation.rankStatsValue(stats, unit.civ)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,10 +169,10 @@ class ImprovementPickerScreen(
|
|||||||
//Warn when the current improvement will increase a stat for the tile,
|
//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
|
// but the tile is outside of the range (> 3 tiles from city center) that can be
|
||||||
// worked by a city's population
|
// 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.name.startsWith(Constants.remove)
|
||||||
&& !improvement.isRoad()
|
|
||||||
&& tile.owningCity != null
|
|
||||||
&& !tile.owningCity!!.getWorkableTiles().contains(tile)
|
&& !tile.owningCity!!.getWorkableTiles().contains(tile)
|
||||||
)
|
)
|
||||||
labelText += "\n" + "Not in city work range".tr()
|
labelText += "\n" + "Not in city work range".tr()
|
||||||
|
Loading…
Reference in New Issue
Block a user