Huge performance boost for time of "next turn"

This commit is contained in:
Yair Morgenstern 2018-09-25 22:03:53 +03:00
parent d22da73636
commit 833760ab32
10 changed files with 48 additions and 22 deletions

View File

@ -23,7 +23,6 @@ class GameInfo {
toReturn.civilizations.addAll(civilizations.map { it.clone() })
toReturn.notifications.addAll(notifications)
toReturn.turns=turns
toReturn.setTransients()
return toReturn
}

View File

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

View File

@ -54,12 +54,18 @@ class MapUnit {
return movementAlgs().getDistanceToTilesWithinTurn(tile.position,currentMovement)
}
fun getUniques(): MutableList<String> {
val abilities = mutableListOf<String>()
@Transient var tempUniques: List<String> = ArrayList()
fun getUniques(): List<String> {
return tempUniques
}
fun updateUniques(){
val uniques = ArrayList<String>()
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()

View File

@ -47,12 +47,16 @@ open class TileInfo {
}
fun getUnits()= listOf(militaryUnit,civilianUnit).filterNotNull()
fun getUnits(): List<MapUnit> {
val list = ArrayList<MapUnit>(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

View File

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

View File

@ -19,6 +19,7 @@ class UnitPromotions{
XP -= xpForNextPromotion()
promotions.add(promotionName)
numberOfPromotions++
unit.updateUniques()
}
fun getAvailablePromotions(): List<Promotion> {

View File

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

View File

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

View File

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

View File

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