Massive performance improvement thanks to:

* not mapping out the uniques every tile
* saving tech uniques and units uniques specific to movement between tiles
This commit is contained in:
Yair Morgenstern 2018-12-17 21:33:07 +02:00
parent 30734c7287
commit 2923dc80c9
7 changed files with 60 additions and 19 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -21,7 +21,7 @@ android {
applicationId "com.unciv.game"
minSdkVersion 14
targetSdkVersion 28
versionCode 181
versionCode 182
versionName "2.11.0"
}

View file

@ -21,7 +21,7 @@ class UnCivGame : Game() {
val viewEntireMapForDebug = false
// For when you need to test something in an advanced game and don't have time to faff around
val superchargedForDebug = true
val superchargedForDebug = false
lateinit var worldScreen: WorldScreen

View file

@ -12,6 +12,12 @@ import java.util.*
class TechManager {
@Transient lateinit var civInfo: CivilizationInfo
@Transient var researchedTechnologies=ArrayList<Technology>()
@Transient private var researchedTechUniques=ArrayList<String>()
// MapUnit.canPassThrough is the most called function in the game, and having these extremey specific booleans is or way of improving the time cost
@Transient var unitsCanEmbark=false
@Transient var embarkedUnitsCanEnterOcean=false
var freeTechs = 0
var techsResearched = HashSet<String>()
@ -56,7 +62,7 @@ class TechManager {
return GameBasics.Technologies[TechName]!!.prerequisites.all { isResearched(it) }
}
fun getUniques() = researchedTechnologies.flatMap { it.uniques }
fun getUniques() = researchedTechUniques
//endregion
@ -103,7 +109,11 @@ class TechManager {
techsResearched.add(techName)
// this is to avoid concurrent modification problems
researchedTechnologies = researchedTechnologies.withItem(GameBasics.Technologies[techName]!!)
val newTech = GameBasics.Technologies[techName]!!
researchedTechnologies = researchedTechnologies.withItem(newTech)
for(unique in newTech.uniques)
researchedTechUniques = researchedTechUniques.withItem(unique)
updateTransientBooleans()
civInfo.addNotification("Research of [$techName] has completed!", null, Color.BLUE)
@ -144,7 +154,13 @@ class TechManager {
techsToResearch.remove("Mass Media")
researchedTechnologies.addAll(techsResearched.map { GameBasics.Technologies[it]!! })
researchedTechUniques.addAll(researchedTechnologies.flatMap { it.uniques })
updateTransientBooleans()
}
}
fun updateTransientBooleans(){
if(researchedTechUniques.contains("Enables embarkation for land units")) unitsCanEmbark=true
if(researchedTechUniques.contains("Enables embarked units to enter ocean tiles")) embarkedUnitsCanEnterOcean=true
}
}

View file

@ -19,6 +19,13 @@ class MapUnit {
@Transient lateinit var baseUnit: BaseUnit
@Transient internal lateinit var currentTile :TileInfo
// These are for performance improvements to getMovementCostBetweenAdjacentTiles,
// a major component of getDistanceToTilesWithinTurn,
// which in turn is a component of getShortestPath and canReach
@Transient var ignoresTerrainCost = false
@Transient var roughTerrainPenalty = false
@Transient var doubleMovementInCoast = false
lateinit var owner: String
lateinit var name: String
var currentMovement: Float = 0f
@ -81,6 +88,10 @@ class MapUnit {
uniques.addAll(baseUnit.uniques)
uniques.addAll(promotions.promotions.map { GameBasics.UnitPromotions[it]!!.effect })
tempUniques = uniques
if("Ignores terrain cost" in uniques) ignoresTerrainCost=true
if("Rough terrain penalty" in uniques) roughTerrainPenalty=true
if("Double movement in coast" in uniques) doubleMovementInCoast=true
}
fun hasUnique(unique:String): Boolean {
@ -116,23 +127,26 @@ class MapUnit {
return "$name - $owner"
}
// This is the most called function in the entire game,
// so multiple callees of this function have been optimized,
// because optimization on this function results in massive benefits!
fun canPassThrough(tile: TileInfo):Boolean{
val tileOwner = tile.getOwner()
if(tile.getBaseTerrain().impassable) return false
val isOcean = tile.baseTerrain == "Ocean" // profiling showed that 3.5% of all nextTurn time is taken up by string equals in this function =|
if(tile.isWater() && type.isLandUnit()){
val techUniques = civInfo.tech.getUniques()
if(!techUniques.contains("Enables embarkation for land units"))
return false
if(isOcean && !techUniques.contains("Enables embarked units to enter ocean tiles"))
return false
}
if(tile.isLand() && type.isWaterUnit())
return false
val isOcean = tile.baseTerrain == "Ocean"
if(tile.isWater() && type.isLandUnit()){
if(!civInfo.tech.unitsCanEmbark) return false
if(isOcean && !civInfo.tech.embarkedUnitsCanEnterOcean)
return false
}
if(isOcean && baseUnit.uniques.contains("Cannot enter ocean tiles")) return false
if(isOcean && baseUnit.uniques.contains("Cannot enter ocean tiles until Astronomy")
&& !civInfo.tech.isResearched("Astronomy"))
return false
if(isOcean && baseUnit.uniques.contains("Cannot enter ocean tiles")) return false
if(tileOwner!=null && tileOwner.civName!=owner
&& (tile.isCityCenter() || !civInfo.canEnterTiles(tileOwner))) return false
return true

View file

@ -92,8 +92,19 @@ class TileMap {
fun getViewableTiles(position: Vector2, sightDistance: Int): MutableList<TileInfo> {
val viewableTiles = getTilesInDistance(position, 1).toMutableList()
for (i in 1..sightDistance) { // in each layer,
getTilesAtDistance(position, i).filterTo(viewableTiles) // take only tiles which have a visible neighbor, which is lower than the tile
{ tile -> tile.neighbors.any{viewableTiles.contains(it) && (it.getHeight() ==0 || it.getHeight() < tile.getHeight())} }
// This is so we don't use tiles in the same distance to "see over",
// that is to say, the "viewableTiles.contains(it) check will return false for neighbors from the same distance
val tilesToAddInDistanceI = ArrayList<TileInfo>()
for (tile in getTilesAtDistance(position, i)) { // for each tile in that layer,
val tileHeight = tile.getHeight()
val containsViewableNeighborThatCanSeeOver = tile.neighbors.any {
val neighborHeight = it.getHeight()
viewableTiles.contains(it) && (neighborHeight == 0 || neighborHeight < tileHeight)
}
if (containsViewableNeighborThatCanSeeOver) tilesToAddInDistanceI.add(tile)
}
viewableTiles.addAll(tilesToAddInDistanceI)
}
return viewableTiles

View file

@ -19,13 +19,13 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
if (unit.civInfo.tech.getUniques().contains("Improves movement speed on roads")) return 1 / 3f
else return 1 / 2f
}
if (unit.hasUnique("Ignores terrain cost")) return 1f
if (unit.ignoresTerrainCost) return 1f
if (unit.hasUnique("Rough terrain penalty")
if (unit.roughTerrainPenalty
&& (to.baseTerrain == "Hill" || to.terrainFeature == "Forest" || to.terrainFeature == "Jungle"))
return 4f
if(unit.hasUnique("Double movement in coast") && to.baseTerrain=="Coast")
if(unit.doubleMovementInCoast && to.baseTerrain=="Coast")
return 1/2f
return to.getLastTerrain().movementCost.toFloat() // no road