From 833760ab322a4b9cca55ef71655d2b4b348e27b6 Mon Sep 17 00:00:00 2001 From: Yair Morgenstern Date: Tue, 25 Sep 2018 22:03:53 +0300 Subject: [PATCH] Huge performance boost for time of "next turn" --- core/src/com/unciv/logic/GameInfo.kt | 1 - .../unciv/logic/automation/UnitAutomation.kt | 18 ++++++++++++------ core/src/com/unciv/logic/map/MapUnit.kt | 17 ++++++++++++----- core/src/com/unciv/logic/map/TileInfo.kt | 10 +++++++--- core/src/com/unciv/logic/map/TileMap.kt | 1 - core/src/com/unciv/logic/map/UnitPromotions.kt | 1 + .../com/unciv/models/gamebasics/Building.kt | 5 +++-- .../unciv/models/gamebasics/unit/BaseUnit.kt | 2 +- .../unciv/models/gamebasics/unit/UnitType.kt | 14 +++++++++++--- .../com/unciv/ui/worldscreen/WorldScreen.kt | 1 + 10 files changed, 48 insertions(+), 22 deletions(-) diff --git a/core/src/com/unciv/logic/GameInfo.kt b/core/src/com/unciv/logic/GameInfo.kt index abd63a0b60..eba7cfcf5e 100644 --- a/core/src/com/unciv/logic/GameInfo.kt +++ b/core/src/com/unciv/logic/GameInfo.kt @@ -23,7 +23,6 @@ class GameInfo { toReturn.civilizations.addAll(civilizations.map { it.clone() }) toReturn.notifications.addAll(notifications) toReturn.turns=turns - toReturn.setTransients() return toReturn } diff --git a/core/src/com/unciv/logic/automation/UnitAutomation.kt b/core/src/com/unciv/logic/automation/UnitAutomation.kt index 8ebc1fea0b..8097386f76 100644 --- a/core/src/com/unciv/logic/automation/UnitAutomation.kt +++ b/core/src/com/unciv/logic/automation/UnitAutomation.kt @@ -177,6 +177,7 @@ class UnitAutomation{ private fun tryHeadTowardsEnemyCity(unit: MapUnit): Boolean { if(unit.civInfo.cities.isEmpty()) return false + var enemyCities = unit.civInfo.gameInfo.civilizations.filter { unit.civInfo.isAtWarWith(it) } .flatMap { it.cities }.filter { it.location in unit.civInfo.exploredTiles }.map { it.getCenterTile() } if(unit.baseUnit().unitType.isRanged()) @@ -234,8 +235,9 @@ class UnitAutomation{ if(unit.baseUnit().unitType.isMelee()) return false // don't garrison melee units, they're not that good at it val reachableCitiesWithoutUnits = unit.civInfo.cities.filter { val centerTile = it.getCenterTile() - unit.canMoveTo(centerTile) - && unit.movementAlgs().canReach(centerTile) + centerTile.militaryUnit==null + && unit.canMoveTo(centerTile) + && unit.movementAlgs().canReach(centerTile) } fun cityThatNeedsDefendingInWartime(city: CityInfo): Boolean { @@ -249,6 +251,9 @@ class UnitAutomation{ if (!unit.civInfo.isAtWar()) { if (unit.getTile().isCityCenter()) return true // It's always good to have a unit in the city center, so if you haven't found anyone around to attack, forget it. if (reachableCitiesWithoutUnits.isNotEmpty()) { + val closestCity = reachableCitiesWithoutUnits.minBy { it.getCenterTile().arialDistanceTo(unit.currentTile) }!! + unit.movementAlgs().headTowards(closestCity.getCenterTile()) + return true } } else { if (unit.getTile().isCityCenter() && @@ -280,9 +285,6 @@ class UnitAutomation{ } else distanceToTiles = unitDistanceToTiles - val reachableTiles= distanceToTiles - .filter { unit.canMoveTo(it.key) } - for(tile in unit.currentTile.getTilesInDistance(5)) if(unit.canMoveTo(tile) && tile.position !in unit.civInfo.exploredTiles && unit.movementAlgs().canReach(tile)){ @@ -290,6 +292,10 @@ class UnitAutomation{ return } + + val reachableTiles= distanceToTiles + .filter { unit.canMoveTo(it.key) && unit.movementAlgs().canReach(it.key) } + val reachableTilesMaxWalkingDistance = reachableTiles.filter { it.value == unit.currentMovement } if (reachableTilesMaxWalkingDistance.any()) unit.moveToTile(reachableTilesMaxWalkingDistance.toList().getRandom().first) else if (reachableTiles.any()) unit.moveToTile(reachableTiles.toList().getRandom().first) @@ -305,7 +311,7 @@ class UnitAutomation{ } private fun automateSettlerActions(unit: MapUnit) { - if(unit.getTile().militaryUnit==null) return // Don;t move until you're accompanied by a military unit + if(unit.getTile().militaryUnit==null) return // Don't move until you're accompanied by a military unit // find best city location within 5 tiles val tilesNearCities = unit.civInfo.gameInfo.civilizations.flatMap { it.cities } diff --git a/core/src/com/unciv/logic/map/MapUnit.kt b/core/src/com/unciv/logic/map/MapUnit.kt index 1bc43e203d..776e4a9800 100644 --- a/core/src/com/unciv/logic/map/MapUnit.kt +++ b/core/src/com/unciv/logic/map/MapUnit.kt @@ -54,12 +54,18 @@ class MapUnit { return movementAlgs().getDistanceToTilesWithinTurn(tile.position,currentMovement) } - fun getUniques(): MutableList { - val abilities = mutableListOf() + @Transient var tempUniques: List = ArrayList() + + fun getUniques(): List { + return tempUniques + } + + fun updateUniques(){ + val uniques = ArrayList() val baseUnit = baseUnit() - if(baseUnit.uniques!=null) abilities.addAll(baseUnit.uniques!!) - abilities.addAll(promotions.promotions.map { GameBasics.UnitPromotions[it]!!.effect }) - return abilities + if(baseUnit.uniques!=null) uniques.addAll(baseUnit.uniques!!) + uniques.addAll(promotions.promotions.map { GameBasics.UnitPromotions[it]!!.effect }) + tempUniques = uniques } fun hasUnique(unique:String): Boolean { @@ -134,6 +140,7 @@ class MapUnit { fun setTransients(){ promotions.unit=this baseUnit=GameBasics.Units[name]!! + updateUniques() } fun doPreTurnAction() { val currentTile = getTile() diff --git a/core/src/com/unciv/logic/map/TileInfo.kt b/core/src/com/unciv/logic/map/TileInfo.kt index 1f1257e496..f7be87d495 100644 --- a/core/src/com/unciv/logic/map/TileInfo.kt +++ b/core/src/com/unciv/logic/map/TileInfo.kt @@ -47,12 +47,16 @@ open class TileInfo { } - fun getUnits()= listOf(militaryUnit,civilianUnit).filterNotNull() + fun getUnits(): List { + val list = ArrayList(2) + if(militaryUnit!=null) list.add(militaryUnit!!) + if(civilianUnit!=null) list.add(civilianUnit!!) + return list + // this used to be "return listOf(militaryUnit,civilianUnit).filterNotNull()" but profiling revealed that that took considerably longer + } fun getCity(): CityInfo? { return owningCity -// return tileMap.gameInfo.tilesToCities.get(this) - //return tileMap.gameInfo.civilizations.flatMap { it.cities }.firstOrNull{it.tiles.contains(position)} } val lastTerrain: Terrain diff --git a/core/src/com/unciv/logic/map/TileMap.kt b/core/src/com/unciv/logic/map/TileMap.kt index 02390a1489..6046a2be90 100644 --- a/core/src/com/unciv/logic/map/TileMap.kt +++ b/core/src/com/unciv/logic/map/TileMap.kt @@ -60,7 +60,6 @@ class TileMap { fun placeUnitNearTile(position: Vector2, unitName: String, civInfo: CivilizationInfo): MapUnit { val unit = GameBasics.Units[unitName]!!.getMapUnit() - val tilesInDistance = getTilesInDistance(position, 2) unit.assignOwner(civInfo) // both the civ name and actual civ need to be in here in order to calculate the canMoveTo...Darn diff --git a/core/src/com/unciv/logic/map/UnitPromotions.kt b/core/src/com/unciv/logic/map/UnitPromotions.kt index a97e1f01f1..7cfc3cacad 100644 --- a/core/src/com/unciv/logic/map/UnitPromotions.kt +++ b/core/src/com/unciv/logic/map/UnitPromotions.kt @@ -19,6 +19,7 @@ class UnitPromotions{ XP -= xpForNextPromotion() promotions.add(promotionName) numberOfPromotions++ + unit.updateUniques() } fun getAvailablePromotions(): List { diff --git a/core/src/com/unciv/models/gamebasics/Building.kt b/core/src/com/unciv/models/gamebasics/Building.kt index f99463a22f..052035f643 100644 --- a/core/src/com/unciv/models/gamebasics/Building.kt +++ b/core/src/com/unciv/models/gamebasics/Building.kt @@ -154,15 +154,16 @@ class Building : NamedStats(), IConstruction{ override fun isBuildable(construction: CityConstructions): Boolean { if (construction.isBuilt(name)) return false + val civInfo = construction.cityInfo.civInfo + if (uniqueTo!=null && uniqueTo!=civInfo.civName) return false + if (GameBasics.Buildings.values.any { it.uniqueTo==civInfo.civName && it.replaces==name }) return false if (requiredTech != null && !civInfo.tech.isResearched(requiredTech!!)) return false if (isWonder && requiredBuildingInAllCities==null && civInfo.gameInfo.civilizations.flatMap { it.cities }.any { it.cityConstructions.isBuilding(name) || it.cityConstructions.isBuilt(name) }) return false - if (uniqueTo!=null && uniqueTo!=civInfo.civName) return false - if (GameBasics.Buildings.values.any { it.uniqueTo==civInfo.civName && it.replaces==name }) return false if (requiredBuilding != null && !construction.isBuilt(requiredBuilding!!) && construction.getBuiltBuildings().none{it.replaces==requiredBuilding}) return false if (requiredBuildingInAllCities != null && civInfo.cities.any { !it.cityConstructions.isBuilt(requiredBuildingInAllCities!!) }) diff --git a/core/src/com/unciv/models/gamebasics/unit/BaseUnit.kt b/core/src/com/unciv/models/gamebasics/unit/BaseUnit.kt index 60d9f18f3e..ca9e6cf1bc 100644 --- a/core/src/com/unciv/models/gamebasics/unit/BaseUnit.kt +++ b/core/src/com/unciv/models/gamebasics/unit/BaseUnit.kt @@ -76,7 +76,7 @@ class BaseUnit : INamed, IConstruction, ICivilopedia { fun getMapUnit(): MapUnit { val unit = MapUnit() unit.name = name - unit.setTransients() // must be after setting name because it sets the bseUnit according to the name + unit.setTransients() // must be after setting name because it sets the baseUnit according to the name unit.currentMovement = unit.getMaxMovement().toFloat() // must be after setTransients because it relies on having the baseUnit set return unit } diff --git a/core/src/com/unciv/models/gamebasics/unit/UnitType.kt b/core/src/com/unciv/models/gamebasics/unit/UnitType.kt index ff9eac6390..9248e441d7 100644 --- a/core/src/com/unciv/models/gamebasics/unit/UnitType.kt +++ b/core/src/com/unciv/models/gamebasics/unit/UnitType.kt @@ -10,13 +10,21 @@ enum class UnitType{ Siege; fun isMelee(): Boolean { - return this in listOf(Melee, Mounted, Scout) + return this == Melee + || this == Mounted + || this == Scout } fun isRanged(): Boolean { - return this in listOf(Ranged, Siege) + return this == Ranged + || this == Siege } fun isLandUnit(): Boolean { - return this in listOf(Civilian, Melee, Mounted, Scout, Ranged, Siege) + return this == Civilian + || this == Melee + || this == Mounted + || this == Scout + || this == Ranged + || this == Siege } } \ No newline at end of file diff --git a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt index 67c8f6c8f3..20b20d1160 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt @@ -88,6 +88,7 @@ class WorldScreen : CameraStageBaseScreen() { // because that's guaranteed to stay the exact same and so we won't get any concurrent modification exceptions val gameClone = gameInfo.clone() + gameClone.setTransients() val cloneCivilization = gameClone.getPlayerCivilization() kotlin.concurrent.thread { civInfo.happiness = gameClone.getPlayerCivilization().getHappinessForNextTurn().values.sum().toInt()