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:
WhoIsJohannes
2023-04-24 16:16:43 +02:00
committed by GitHub
parent 95ee35d301
commit 033957c738
2 changed files with 19 additions and 7 deletions

View File

@ -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()) {

View File

@ -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
}
}