mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-08 23:08:35 +07:00
Performance improvements (#9265)
* UnitMovement#getDistanceToTilesWithinTurn hotspots
* Make fog busting less expensive
* Speed up tryHeadTowardsEncampment
* Reorder conditions in isGoodTileToExplore
* Reorder conditions in isGoodTileToExplore
* Revert "Speed up tryHeadTowardsEncampment"
This reverts commit d3841a233b
.
* Don't lookup twice.
This commit is contained in:
@ -27,13 +27,12 @@ object UnitAutomation {
|
||||
private const val CLOSE_ENEMY_TURNS_AWAY_LIMIT = 3f
|
||||
|
||||
private fun isGoodTileToExplore(unit: MapUnit, tile: Tile): Boolean {
|
||||
return unit.movement.canMoveTo(tile)
|
||||
&& (tile.getOwner() == null || !tile.getOwner()!!.isCityState())
|
||||
return (tile.getOwner() == null || !tile.getOwner()!!.isCityState())
|
||||
&& tile.neighbors.any { !unit.civ.hasExplored(it) }
|
||||
&& (!unit.civ.isCityState() || tile.neighbors.any { it.getOwner() == unit.civ }) // Don't want city-states exploring far outside their borders
|
||||
&& unit.getDamageFromTerrain(tile) <= 0 // Don't take unnecessary damage
|
||||
&& tile.getTilesInDistance(3) // don't walk in range of enemy units
|
||||
.none { tile_it -> containsEnemyMilitaryUnit(unit, tile_it)}
|
||||
&& tile.getTilesInDistance(3) .none { containsEnemyMilitaryUnit(unit, it) } // don't walk in range of enemy units
|
||||
&& unit.movement.canMoveTo(tile) // expensive, evaluate last
|
||||
&& unit.movement.canReach(tile) // expensive, evaluate last
|
||||
}
|
||||
|
||||
@ -78,6 +77,12 @@ object UnitAutomation {
|
||||
private fun tryFogBust(unit: MapUnit): Boolean {
|
||||
if (!Automation.afraidOfBarbarians(unit.civ)) return false // Not if we're not afraid
|
||||
|
||||
// If everything around this unit is visible, we can stop.
|
||||
// Calculations below are quite expensive especially in the late game.
|
||||
if (unit.currentTile.getTilesInDistance(5).any { !it.isVisible(unit.civ) }) {
|
||||
return false
|
||||
}
|
||||
|
||||
val reachableTilesThisTurn =
|
||||
unit.movement.getDistanceToTiles().keys.filter { isGoodTileForFogBusting(unit, it) }
|
||||
if (reachableTilesThisTurn.any()) {
|
||||
|
@ -163,6 +163,9 @@ class UnitMovement(val unit: MapUnit) {
|
||||
distanceToTiles[unitTile] = ParentTileAndTotalDistance(unitTile, unitTile, 0f)
|
||||
var tilesToCheck = listOf(unitTile)
|
||||
|
||||
val passThroughCache = HashMap<Tile, Boolean>() // Cache for canPassThrough
|
||||
val movementCostCache = HashMap<Pair<Tile, Tile>, Float>() // Cache for getMovementCostBetweenAdjacentTiles
|
||||
|
||||
while (tilesToCheck.isNotEmpty()) {
|
||||
val updatedTiles = ArrayList<Tile>()
|
||||
for (tileToCheck in tilesToCheck)
|
||||
@ -171,13 +174,17 @@ class UnitMovement(val unit: MapUnit) {
|
||||
var totalDistanceToTile: Float = when {
|
||||
!unit.civ.hasExplored(neighbor) ->
|
||||
distanceToTiles[tileToCheck]!!.totalDistance + 1f // If we don't know then we just guess it to be 1.
|
||||
!canPassThrough(neighbor) -> unitMovement // Can't go here.
|
||||
!passThroughCache.getOrPut(neighbor) { canPassThrough(neighbor) } -> unitMovement // Can't go here.
|
||||
// The reason that we don't just "return" is so that when calculating how to reach an enemy,
|
||||
// You need to assume his tile is reachable, otherwise all movement algorithms on reaching enemy
|
||||
// cities and units goes kaput.
|
||||
else -> {
|
||||
val distanceBetweenTiles = getMovementCostBetweenAdjacentTiles(tileToCheck, neighbor, unit.civ, considerZoneOfControl)
|
||||
distanceToTiles[tileToCheck]!!.totalDistance + distanceBetweenTiles
|
||||
val key = Pair(tileToCheck, neighbor)
|
||||
val movementCost =
|
||||
movementCostCache.getOrPut(key) {
|
||||
getMovementCostBetweenAdjacentTiles(tileToCheck, neighbor, unit.civ, considerZoneOfControl)
|
||||
}
|
||||
distanceToTiles[tileToCheck]!!.totalDistance + movementCost
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user