Each unit now saves its viewable tiles, which gives in certain situations a whopping 10% performance improvement! Whoa!

This commit is contained in:
Yair Morgenstern 2019-05-29 22:58:20 +03:00
parent b9cf40487f
commit 16d8c16dfe
7 changed files with 28 additions and 9 deletions

View File

@ -174,7 +174,11 @@ class GameInfo {
}
}
for (civInfo in civilizations) civInfo.setTransients()
for (civInfo in civilizations) {
civInfo.setTransients()
for(unit in civInfo.getCivUnits())
unit.updateViewableTiles() // this needs to be done after all the units are assigned to their civs and all other transients are set
}
for (civInfo in civilizations){
for (cityInfo in civInfo.cities) cityInfo.cityStats.update()
}

View File

@ -253,5 +253,6 @@ class Battle(val gameInfo:GameInfo) {
capturedUnit.civInfo.removeUnit(capturedUnit)
capturedUnit.assignOwner(attacker.getCivInfo())
capturedUnit.updateViewableTiles()
}
}

View File

@ -329,11 +329,11 @@ class CivilizationInfo {
fun updateViewableTiles() {
val newViewableTiles = HashSet<TileInfo>()
newViewableTiles.addAll(cities.flatMap { it.getTiles() }.flatMap { it.neighbors }) // tiles adjacent to city tiles
newViewableTiles.addAll(getCivUnits().flatMap { it.getViewableTiles()})
newViewableTiles.addAll(getCivUnits().flatMap { it.viewableTiles})
viewableTiles = newViewableTiles // to avoid concurrent modification problems
val newViewableInvisibleTiles = HashSet<TileInfo>()
newViewableInvisibleTiles.addAll(getCivUnits().filter {it.hasUnique("Can attack submarines")}.flatMap {it.getViewableTiles()})
newViewableInvisibleTiles.addAll(getCivUnits().filter {it.hasUnique("Can attack submarines")}.flatMap {it.viewableTiles})
viewableInvisibleUnitsTiles = newViewableInvisibleTiles
// updating the viewable tiles also affects the explored tiles, obvs

View File

@ -23,6 +23,11 @@ class MapUnit {
@Transient lateinit var baseUnit: BaseUnit
@Transient internal lateinit var currentTile :TileInfo
// This is saved per each unit because if we need to recalculate viewable tiles every time a unit moves,
// and we need to go over ALL the units, that's a lot of time spent on updating information we should already know!
// About 10% of total NextTurn performance time, at the time of this change!
@Transient var viewableTiles = listOf<TileInfo>()
// These are for performance improvements to getMovementCostBetweenAdjacentTiles,
// a major component of getDistanceToTilesWithinTurn,
// which in turn is a component of getShortestPath and canReach
@ -122,7 +127,8 @@ class MapUnit {
return getUniques().contains(unique)
}
fun getViewableTiles(): MutableList<TileInfo> {
// we need to map all the places that this could change: Unit changes locations, owners, gets promotion?
fun updateViewableTiles() {
var visibilityRange = 2
visibilityRange += getUniques().count{it=="+1 Visibility Range"}
if(hasUnique("Limited Visibility")) visibilityRange-=1
@ -133,7 +139,9 @@ class MapUnit {
visibilityRange += 1
val tile = getTile()
if (tile.baseTerrain == Constants.hill && type.isLandUnit()) visibilityRange += 1
return tile.getViewableTiles(visibilityRange, type.isWaterUnit())
viewableTiles = tile.getViewableTiles(visibilityRange, type.isWaterUnit())
civInfo.updateViewableTiles() // for the civ
}
fun isFortified(): Boolean {
@ -450,7 +458,8 @@ class MapUnit {
currentTile = tile
if(tile.improvement=="Ancient ruins" && !civInfo.isBarbarianCivilization())
getAncientRuinBonus()
civInfo.updateViewableTiles()
updateViewableTiles()
}
fun disband(){

View File

@ -56,6 +56,7 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
for (tileToCheck in tilesToCheck)
for (neighbor in tileToCheck.neighbors) {
var totalDistanceToTile:Float
if (!unit.canPassThrough(neighbor))
totalDistanceToTile = unitMovement // Can't go here.
// The reason that we don't just "return" is so that when calculating how to reach an enemy,
@ -67,11 +68,14 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
totalDistanceToTile = distanceToTiles[tileToCheck]!! + distanceBetweenTiles
}
if (!distanceToTiles.containsKey(neighbor) || distanceToTiles[neighbor]!! > totalDistanceToTile) {
if (totalDistanceToTile < unitMovement)
if (!distanceToTiles.containsKey(neighbor) || distanceToTiles[neighbor]!! > totalDistanceToTile) { // this is the new best path
if (totalDistanceToTile < unitMovement) // We can still keep moving from here!
updatedTiles += neighbor
else
totalDistanceToTile = unitMovement
// In Civ V, you can always travel between adjacent tiles, even if you don't technically
// have enough movement points - it simple depletes what you have
distanceToTiles[neighbor] = totalDistanceToTile
}
}

View File

@ -28,7 +28,7 @@ class UnitPromotions{
else promotions.add(promotionName)
unit.updateUniques()
unit.civInfo.updateViewableTiles() // some promotions give the unit bonus sight
unit.updateViewableTiles() // some promotions/uniques give the unit bonus sight
}
fun getAvailablePromotions(): List<Promotion> {

View File

@ -102,6 +102,7 @@ class UnitActions {
newunit.promotions.addPromotion(promotion,true)
newunit.updateUniques()
newunit.updateViewableTiles()
newunit.currentMovement = 0f
worldScreen.shouldUpdate = true
}.sound("upgrade")