Fixed settler automation performance problem - now actually viable for phone use

All kinds of other small performance-boosting bits and bobs
This commit is contained in:
Yair Morgenstern 2018-04-26 23:43:36 +03:00
parent f4af9f7d80
commit 8268c0c561
13 changed files with 31 additions and 30 deletions

View File

@ -22,22 +22,22 @@ class Automation {
var rank = 0.0f
if (stats.food <= 2) rank += stats.food
else rank += (2 + (stats.food - 2) / 2f) // 1 point for each food up to 2, from there on half a point
rank += (stats.gold / 2)
rank += stats.gold / 2
rank += stats.production
rank += stats.science
rank += stats.culture
if (tile.improvement == null) rank += 0.5f // improvement potential!
if (tile.resource != null) rank += 1.0f
if (tile.hasViewableResource(civInfo)) rank += 1.0f
return rank
}
fun rankTileAsCityCenter(tileInfo: TileInfo, civInfo: CivilizationInfo): Float {
fun rankTileAsCityCenter(tileInfo: TileInfo, civInfo: CivilizationInfo, nearbyTileRankings: Map<TileInfo, Float>): Float {
val bestTilesFromOuterLayer = tileInfo.tileMap.getTilesAtDistance(tileInfo.position,2)
.sortedByDescending { rankTile(it,civInfo) }.take(2)
.sortedByDescending { nearbyTileRankings[it] }.take(2)
val top5Tiles = tileInfo.neighbors.union(bestTilesFromOuterLayer)
.sortedByDescending { rankTile(it,civInfo) }
.sortedByDescending { nearbyTileRankings[it] }
.take(5)
return top5Tiles.map { rankTile(it,civInfo) }.sum()
return top5Tiles.map { nearbyTileRankings[it]!! }.sum()
}
fun automateCivMoves(civInfo: CivilizationInfo) {
@ -113,7 +113,7 @@ class Automation {
// if there is an attackable unit in the vicinity, attack!
val attackableTiles = unit.civInfo.getViewableTiles()
.filter { it.unit != null && it.unit!!.owner != unit.civInfo.civName && !it.isCityCenter }.toHashSet()
.filter { it.unit != null && it.unit!!.owner != unit.civInfo.civName && !it.isCityCenter() }.toHashSet()
val distanceToTiles = unit.getDistanceToTiles()
val unitTileToAttack = distanceToTiles.keys.firstOrNull { attackableTiles.contains(it) }
@ -170,10 +170,12 @@ class Automation {
// find best city location within 5 tiles
val tilesNearCities = unit.civInfo.gameInfo.civilizations.flatMap { it.cities }
.flatMap { it.getCenterTile().getTilesInDistance(2) }
// This is to improve performance - instead of ranking each tile in the area up to 19 times, do it once.
val nearbyTileRankings = unit.getTile().getTilesInDistance(7).associateBy ( {it},{rankTile(it,unit.civInfo) })
val bestCityLocation = unit.getTile().getTilesInDistance(5)
.minus(tilesNearCities)
.sortedByDescending { rankTileAsCityCenter(it, unit.civInfo) }
.first()
.maxBy { rankTileAsCityCenter(it, unit.civInfo, nearbyTileRankings) }!!
if (unit.getTile() == bestCityLocation)
UnitActions().getUnitActions(unit, UnCivGame.Current.worldScreen!!).first { it.name == "Found city" }.action()

View File

@ -30,8 +30,8 @@ public class WorkerAutomation(){
.filter {
(it.unit == null || it == currentTile)
&& it.improvement == null
&& (it.getCity()==null || it.getCity()!!.civInfo == civInfo) // don't work tiles belonging to another civ
&& it.canBuildImprovement(chooseImprovement(it), civInfo)
&& {val city=it.getCity(); city==null || it.getCity()?.civInfo == civInfo}() // don't work tiles belonging to another civ
&& UnitMovementAlgorithms(currentTile.tileMap) // the tile is actually reachable - more difficult than it seems!
.getShortestPath(currentTile.position, it.position, 2f, 2, civInfo).isNotEmpty()
}

View File

@ -9,7 +9,7 @@ class CityExpansionManager {
var cultureStored: Int = 0
fun reset() {
cityInfo.tiles = ArrayList(cityInfo.getCenterTile().getTilesInDistance(1).map { it.position })
cityInfo.tiles = cityInfo.getCenterTile().getTilesInDistance(1).map { it.position }.toHashSet()
}
// This one has conflicting sources -

View File

@ -23,8 +23,8 @@ class CityInfo {
var expansion = CityExpansionManager()
var cityStats = CityStats()
var tiles = ArrayList<Vector2>()
var workedTiles = ArrayList<Vector2>()
var tiles = HashSet<Vector2>()
var workedTiles = HashSet<Vector2>()
internal val tileMap: TileMap
@ -42,7 +42,7 @@ class CityInfo {
for (tileInfo in getTilesInRange().filter { it.resource != null }) {
val resource = tileInfo.tileResource
if (resource.improvement == tileInfo.improvement || tileInfo.isCityCenter)
if (resource.improvement == tileInfo.improvement || tileInfo.isCityCenter())
cityResources.add(resource, 1)
}

View File

@ -74,7 +74,7 @@ class CivilizationInfo {
private fun getTransportationUpkeep(): Int {
var transportationUpkeep = 0
for (it in gameInfo.tileMap.values.filterNot { it.isCityCenter }) {
for (it in gameInfo.tileMap.values.filterNot { it.isCityCenter() }) {
when(it.roadStatus) {
RoadStatus.Road -> transportationUpkeep += 1
RoadStatus.Railroad -> transportationUpkeep += 2

View File

@ -62,7 +62,7 @@ class TechManager {
.filter { it.resource == revealedResource.name && civInfo == it.getOwner() }) {
val closestCityTile = tileInfo.getTilesInDistance(4)
.firstOrNull { it.isCityCenter }
.firstOrNull { it.isCityCenter() }
if (closestCityTile != null) {
civInfo.addNotification(
revealedResource.name + " revealed near " + closestCityTile.getCity()!!.name, tileInfo.position)

View File

@ -113,7 +113,7 @@ class MapUnit {
private fun heal(){
val tile = getTile()
health += when{
tile.isCityCenter -> 20
tile.isCityCenter() -> 20
tile.getOwner()?.civName == owner -> 15 // home territory
tile.getOwner() == null -> 10 // no man's land (neutral)
else -> 5 // enemy territory

View File

@ -32,8 +32,7 @@ class TileInfo {
val tileResource: TileResource
get() = if (resource == null) throw Exception("No resource exists for this tile!") else GameBasics.TileResources[resource!!]!!
val isCityCenter: Boolean
get() = getCity() != null && position == getCity()!!.location
fun isCityCenter(): Boolean = getCity()?.location == position
val tileImprovement: TileImprovement?
get() = if (improvement == null) null else GameBasics.TileImprovements[improvement!!]
@ -101,7 +100,7 @@ class TileInfo {
stats.add(improvement) // again, for the double effect
}
if (isCityCenter) {
if (isCityCenter()) {
if (stats.food < 2) stats.food = 2f
if (stats.production < 1) stats.production = 1f
}
@ -118,7 +117,7 @@ class TileInfo {
}
fun canBuildImprovement(improvement: TileImprovement, civInfo: CivilizationInfo): Boolean {
if (isCityCenter || improvement.name == this.improvement) return false
if (isCityCenter() || improvement.name == this.improvement) return false
val topTerrain = if (terrainFeature == null) getBaseTerrain() else getTerrainFeature()
if (improvement.techRequired != null && !civInfo.tech.isResearched(improvement.techRequired!!)) return false
if (improvement.terrainsCanBeBuiltOn.contains(topTerrain!!.name)) return true
@ -141,14 +140,14 @@ class TileInfo {
override fun toString(): String {
val SB = StringBuilder()
if (isCityCenter) {
if (isCityCenter()) {
val city = getCity()!!
SB.appendln(city.name+ ",\r\n" + city.cityConstructions.getProductionForTileInfo())
}
SB.appendln(this.baseTerrain)
if (terrainFeature != null) SB.appendln(terrainFeature!!)
if (hasViewableResource(tileMap.gameInfo.getPlayerCivilization())) SB.appendln(resource!!)
if (roadStatus !== RoadStatus.None && !isCityCenter) SB.appendln(roadStatus)
if (roadStatus !== RoadStatus.None && !isCityCenter()) SB.appendln(roadStatus)
if (improvement != null) SB.appendln(improvement!!)
if (improvementInProgress != null) SB.appendln("$improvementInProgress in ${this.turnsToImprovement} turns")
if (unit != null && UnCivGame.Current.gameInfo.getPlayerCivilization().getViewableTiles().contains(this)){

View File

@ -16,7 +16,7 @@ class UnitMovementAlgorithms(val tileMap: TileMap){
val updatedTiles = ArrayList<TileInfo>()
for (tileToCheck in tilesToCheck)
for (maybeUpdatedTile in tileToCheck.neighbors) {
if(maybeUpdatedTile.getOwner() != null && maybeUpdatedTile.getOwner() != civInfo && maybeUpdatedTile.isCityCenter)
if(maybeUpdatedTile.getOwner() != null && maybeUpdatedTile.getOwner() != civInfo && maybeUpdatedTile.isCityCenter())
continue // Enemy city, can't move through it!
var distanceBetweenTiles = maybeUpdatedTile.lastTerrain.movementCost.toFloat() // no road

View File

@ -163,7 +163,7 @@ class CityScreen(internal val city: CityInfo) : CameraStageBaseScreen() {
if (tileInfo.getCity()!=city) {
group.setColor(0f, 0f, 0f, 0.3f)
group.yieldGroup.isVisible = false
} else if (!tileInfo.isCityCenter) {
} else if (!tileInfo.isCityCenter()) {
group.addPopulationIcon()
group.populationImage!!.addClickListener {
if (!tileInfo.isWorked() && cityInfo.population.getFreePopulation() > 0)

View File

@ -55,7 +55,7 @@ class WorldTileGroup(tileInfo: TileInfo) : TileGroup(tileInfo) {
if (tileInfo.isWorked() && city!!.civInfo.isPlayerCivilization() && populationImage == null)
addPopulationIcon()
if (city != null && tileInfo.isCityCenter) {
if (city != null && tileInfo.isCityCenter()) {
if (cityButton == null) {
cityButton = Table()
cityButton!!.background = ImageGetter.getDrawable("skin/civTableBackground.png")

View File

@ -31,7 +31,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
val selectedTile = worldScreen.tileMapHolder.selectedTile!!
val defender: ICombatant
if (attacker.getCivilization().exploredTiles.contains(selectedTile.position)
&& selectedTile.isCityCenter && selectedTile.getOwner() != worldScreen.civInfo)
&& selectedTile.isCityCenter() && selectedTile.getOwner() != worldScreen.civInfo)
defender = CityCombatant(selectedTile.getCity()!!)
else if (selectedTile.unit != null
&& selectedTile.unit!!.owner != worldScreen.civInfo.civName // enemy unit on selected tile,

View File

@ -66,7 +66,7 @@ class UnitActions {
worldScreen.update()
},
unit.currentMovement != 0f &&
!tile.getTilesInDistance(2).any { it.isCityCenter })
!tile.getTilesInDistance(2).any { it.isCityCenter() })
}
if (unit.name == "Worker") {
@ -76,7 +76,7 @@ class UnitActions {
actionList += UnitAction(improvementButtonText,
{ worldScreen.game.screen = ImprovementPickerScreen(tile) },
unit.currentMovement != 0f &&
!tile.isCityCenter || GameBasics.TileImprovements.values.any { tile.canBuildImprovement(it, unit.civInfo) })
!tile.isCityCenter() || GameBasics.TileImprovements.values.any { tile.canBuildImprovement(it, unit.civInfo) })
if("automation" == unit.action){
actionList += UnitAction("Stop automation",
@ -123,7 +123,7 @@ class UnitActions {
tile.unit = null // destroy!
},
unit.currentMovement != 0f &&
tile.isCityCenter &&
tile.isCityCenter() &&
tile.getCity()!!.cityConstructions.getCurrentConstruction() is Building &&
(tile.getCity()!!.cityConstructions.getCurrentConstruction() as Building).isWonder)