Performance: nation type booleans are all lazy vals, to avoid unnecessary string comparisons

These were so numerous that they were popping up in the CPU profiler which is just unacceptable
This commit is contained in:
Yair Morgenstern 2023-04-03 10:45:19 +03:00
parent f50b88c9a5
commit bfb869f64f
14 changed files with 76 additions and 79 deletions

View File

@ -229,7 +229,7 @@ object GameStarter {
availableCivNames.addAll(gameSetupInfo.gameParameters.randomNationsPool.shuffled())
} else
// CityState or Spectator civs are not available for Random pick
availableCivNames.addAll(ruleset.nations.filter { it.value.isMajorCiv() }.keys.shuffled())
availableCivNames.addAll(ruleset.nations.filter { it.value.isMajorCiv }.keys.shuffled())
availableCivNames.removeAll(newGameParameters.players.map { it.chosenCiv }.toSet())
@ -294,7 +294,7 @@ object GameStarter {
// and then all the other City-States in a random order! Because the sortedBy function is stable!
availableCityStatesNames.addAll( ruleset.nations
.filter {
it.value.isCityState() &&
it.value.isCityState &&
!it.value.hasUnique(UniqueType.CityStateDeprecated)
}.keys
.shuffled()

View File

@ -182,7 +182,7 @@ class CityFounder {
// names are taken from the rest of the major nations in the rule set
val absentMajorNations: Sequence<Nation> =
foundingCiv.gameInfo.ruleset.nations.values.asSequence().filter { nation ->
nation.isMajorCiv() && nation !in aliveMajorNations
nation.isMajorCiv && nation !in aliveMajorNations
}
newCityNames =
absentMajorNations.flatMap { nation ->

View File

@ -320,11 +320,11 @@ class Civilization : IsPartOfGameInfoSerialization {
fun isOneCityChallenger() = playerType == PlayerType.Human && gameInfo.gameParameters.oneCityChallenge
fun isCurrentPlayer() = gameInfo.currentPlayerCiv == this
fun isMajorCiv() = nation.isMajorCiv()
fun isMinorCiv() = nation.isCityState() || nation.isBarbarian()
fun isCityState(): Boolean = nation.isCityState()
fun isBarbarian() = nation.isBarbarian()
fun isSpectator() = nation.isSpectator()
fun isMajorCiv() = nation.isMajorCiv
fun isMinorCiv() = nation.isCityState || nation.isBarbarian
fun isCityState(): Boolean = nation.isCityState
fun isBarbarian() = nation.isBarbarian
fun isSpectator() = nation.isSpectator
fun isAlive(): Boolean = !isDefeated()
@delegate:Transient

View File

@ -144,17 +144,17 @@ class MapGenerator(val ruleset: Ruleset, private val coroutineScope: CoroutineSc
if (civilizations.isNotEmpty()) {
val regions = MapRegions(ruleset)
runAndMeasure("generateRegions") {
regions.generateRegions(map, civilizations.count { ruleset.nations[it.civName]!!.isMajorCiv() })
regions.generateRegions(map, civilizations.count { ruleset.nations[it.civName]!!.isMajorCiv })
}
runAndMeasure("assignRegions") {
regions.assignRegions(map, civilizations.filter { ruleset.nations[it.civName]!!.isMajorCiv() }, gameParameters)
regions.assignRegions(map, civilizations.filter { ruleset.nations[it.civName]!!.isMajorCiv }, gameParameters)
}
// Natural wonders need to go before most resources since there is a minimum distance
runAndMeasure("NaturalWonderGenerator") {
NaturalWonderGenerator(ruleset, randomness).spawnNaturalWonders(map)
}
runAndMeasure("placeResourcesAndMinorCivs") {
regions.placeResourcesAndMinorCivs(map, civilizations.filter { ruleset.nations[it.civName]!!.isCityState() })
regions.placeResourcesAndMinorCivs(map, civilizations.filter { ruleset.nations[it.civName]!!.isCityState })
}
} else {
runAndMeasure("NaturalWonderGenerator") {

View File

@ -1124,7 +1124,7 @@ class MapRegions (val ruleset: Ruleset){
// Second place one (1) luxury at minor civ start locations
// Check only ones that got a start location
for (startLocation in tileMap.startingLocationsByNation
.filterKeys { ruleset.nations[it]!!.isCityState() }.map { it.value.first() }) {
.filterKeys { ruleset.nations[it]!!.isCityState }.map { it.value.first() }) {
val region = regions.firstOrNull { startLocation in it.tiles }
val tilesToCheck = startLocation.getTilesInDistanceRange(1..2)
// 75% probability that we first attempt to place a "city state" luxury, then a random or regional one
@ -1315,7 +1315,7 @@ class MapRegions (val ruleset: Ruleset){
if (modernOptions.any())
for (cityStateLocation in tileMap.startingLocationsByNation
.filterKeys { ruleset.nations[it]!!.isCityState() }.values.map { it.first() }) {
.filterKeys { ruleset.nations[it]!!.isCityState }.values.map { it.first() }) {
val resourceToPlace = modernOptions.random()
totalPlaced[resourceToPlace] =
totalPlaced[resourceToPlace]!! + tryAddingResourceToTiles(resourceToPlace, 1, cityStateLocation.getTilesInDistanceRange(1..3))

View File

@ -68,7 +68,7 @@ class RulesetValidator(val ruleset: Ruleset) {
}
for (nation in ruleset.nations.values) {
if (nation.cities.isEmpty() && !nation.isSpectator() && !nation.isBarbarian()) {
if (nation.cities.isEmpty() && !nation.isSpectator && !nation.isBarbarian) {
lines += "${nation.name} can settle cities, but has no city names!"
}

View File

@ -9,15 +9,15 @@ import com.unciv.models.ruleset.unique.UniqueTarget
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.translations.squareBraceRegex
import com.unciv.models.translations.tr
import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen.Companion.showReligionInCivilopedia
import com.unciv.ui.screens.civilopediascreen.FormattedLine
import com.unciv.ui.components.Fonts
import com.unciv.ui.components.extensions.colorFromRGB
import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen.Companion.showReligionInCivilopedia
import com.unciv.ui.screens.civilopediascreen.FormattedLine
import kotlin.math.pow
class Nation : RulesetObject() {
var leaderName = ""
fun getLeaderDisplayName() = if (isCityState()) name
fun getLeaderDisplayName() = if (isCityState) name
else "[$leaderName] of [$name]"
val style = ""
@ -61,10 +61,10 @@ import kotlin.math.pow
fun getInnerColor(): Color = innerColorObject
fun isCityState() = cityStateType != null
fun isMajorCiv() = !isBarbarian() && !isCityState() && !isSpectator()
fun isBarbarian() = name == Constants.barbarians
fun isSpectator() = name == Constants.spectator
val isCityState by lazy { cityStateType != null }
val isMajorCiv by lazy { !isBarbarian && !isCityState && !isSpectator }
val isBarbarian by lazy { name == Constants.barbarians }
val isSpectator by lazy { name == Constants.spectator }
// This is its own transient because we'll need to check this for every tile-to-tile movement which is harsh
@Transient
@ -89,13 +89,13 @@ import kotlin.math.pow
override fun makeLink() = "Nation/$name"
override fun getSortGroup(ruleset: Ruleset) = when {
isCityState() -> 1
isBarbarian() -> 9
isCityState -> 1
isBarbarian -> 9
else -> 0
}
override fun getCivilopediaTextLines(ruleset: Ruleset): List<FormattedLine> {
if (isCityState()) return getCityStateInfo(ruleset)
if (isCityState) return getCityStateInfo(ruleset)
val textList = ArrayList<FormattedLine>()
@ -300,8 +300,8 @@ import kotlin.math.pow
return when (filter) {
"All" -> true
name -> true
"Major" -> isMajorCiv()
"CityState" -> isCityState()
"Major" -> isMajorCiv
"CityState" -> isCityState
else -> uniques.contains(filter)
}
}

View File

@ -13,16 +13,16 @@ import com.unciv.models.helpers.MapArrowType
import com.unciv.models.helpers.MiscArrowTypes
import com.unciv.models.helpers.TintedMapArrow
import com.unciv.models.helpers.UnitMovementMemoryType
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.components.extensions.center
import com.unciv.ui.components.extensions.centerX
import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.extensions.toPrettyString
import com.unciv.ui.components.tilegroups.CityTileGroup
import com.unciv.ui.components.tilegroups.TileGroup
import com.unciv.ui.components.tilegroups.TileSetStrings
import com.unciv.ui.components.tilegroups.WorldTileGroup
import com.unciv.ui.components.tilegroups.YieldGroup
import com.unciv.ui.components.extensions.center
import com.unciv.ui.components.extensions.centerX
import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.extensions.toPrettyString
import com.unciv.ui.images.ImageGetter
import com.unciv.utils.DebugUtils
import kotlin.math.atan2
import kotlin.math.min
@ -219,7 +219,7 @@ class TileLayerMisc(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, si
.filter { tile() in it.value }
.filter { it.key in tilemap.ruleset!!.nations } // Ignore missing nations
.map { it.key to tilemap.ruleset!!.nations[it.key]!! }
.sortedWith(compareBy({ it.second.isCityState() }, { it.first }))
.sortedWith(compareBy({ it.second.isCityState }, { it.first }))
.toList()
if (nations.isEmpty()) return

View File

@ -217,7 +217,7 @@ class PortraitNation(name: String, size: Float) : Portrait(Type.Nation, name, si
override fun getDefaultImage(): Image {
val nation = ruleset.nations[imageName]
val isCityState = nation != null && nation.isCityState()
val isCityState = nation != null && nation.isCityState
val pathCityState = "NationIcons/CityState"
return when {

View File

@ -17,17 +17,17 @@ import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.ruleset.unit.UnitType
import com.unciv.models.stats.INamed
import com.unciv.models.translations.tr
import com.unciv.ui.images.IconTextButton
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.components.Fonts
import com.unciv.ui.components.KeyCharAndCode
import com.unciv.ui.screens.basescreen.RecreateOnResize
import com.unciv.ui.components.UncivTooltip.Companion.addTooltip
import com.unciv.ui.components.extensions.colorFromRGB
import com.unciv.ui.components.extensions.onClick
import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.extensions.toTextButton
import com.unciv.ui.images.IconTextButton
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.basescreen.RecreateOnResize
import com.unciv.ui.components.AutoScrollPane as ScrollPane
/** Screen displaying the Civilopedia
@ -217,7 +217,7 @@ class CivilopediaScreen(
CivilopediaCategories.Improvement -> ruleset.tileImprovements.values
CivilopediaCategories.Unit -> ruleset.units.values
CivilopediaCategories.UnitType -> UnitType.getCivilopediaIterator(ruleset)
CivilopediaCategories.Nation -> ruleset.nations.values.filter { !it.isSpectator() }
CivilopediaCategories.Nation -> ruleset.nations.values.filter { !it.isSpectator }
CivilopediaCategories.Technology -> ruleset.technologies.values
CivilopediaCategories.Promotion -> ruleset.unitPromotions.values
CivilopediaCategories.Policy -> ruleset.policies.values

View File

@ -18,18 +18,18 @@ import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.translations.tr
import com.unciv.ui.audio.MusicMood
import com.unciv.ui.audio.MusicTrackChooserFlags
import com.unciv.ui.screens.civilopediascreen.FormattedLine
import com.unciv.ui.screens.civilopediascreen.MarkupRenderer
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.mapeditorscreen.tabs.MapEditorEditTab
import com.unciv.ui.screens.mapeditorscreen.tabs.MapEditorEditTab.BrushHandlerType
import com.unciv.ui.components.tilegroups.TileGroup
import com.unciv.ui.components.tilegroups.TileSetStrings
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.components.TabbedPager
import com.unciv.ui.components.extensions.center
import com.unciv.ui.components.extensions.onClick
import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.tilegroups.TileGroup
import com.unciv.ui.components.tilegroups.TileSetStrings
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.civilopediascreen.FormattedLine
import com.unciv.ui.screens.civilopediascreen.MarkupRenderer
import com.unciv.ui.screens.mapeditorscreen.tabs.MapEditorEditTab
import com.unciv.ui.screens.mapeditorscreen.tabs.MapEditorEditTab.BrushHandlerType
internal interface IMapEditorEditSubTabs {
fun isDisabled(): Boolean
@ -301,7 +301,7 @@ class MapEditorEditStartsTab(
private fun allowedNations() = ruleset.nations.values.asSequence()
.filter { it.name !in disallowNations }
private fun getNations() = allowedNations()
.sortedWith(compareBy<Nation>{ it.isCityState() }.thenBy(collator) { it.name.tr() })
.sortedWith(compareBy<Nation>{ it.isCityState }.thenBy(collator) { it.name.tr() })
.map { FormattedLine("[${it.name}] starting location", it.name, "Nation/${it.name}", size = 24) }
.toList()

View File

@ -14,13 +14,6 @@ import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.nation.Nation
import com.unciv.models.stats.Stats
import com.unciv.models.translations.tr
import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen
import com.unciv.ui.screens.civilopediascreen.FormattedLine
import com.unciv.ui.screens.civilopediascreen.FormattedLine.IconDisplay
import com.unciv.ui.screens.civilopediascreen.MarkupRenderer
import com.unciv.ui.screens.mapeditorscreen.MapEditorScreen
import com.unciv.ui.popups.ToastPopup
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.components.ExpanderTab
import com.unciv.ui.components.TabbedPager
import com.unciv.ui.components.WrappableLabel
@ -29,6 +22,13 @@ import com.unciv.ui.components.extensions.darken
import com.unciv.ui.components.extensions.onClick
import com.unciv.ui.components.extensions.pad
import com.unciv.ui.components.extensions.toTextButton
import com.unciv.ui.popups.ToastPopup
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.civilopediascreen.CivilopediaScreen
import com.unciv.ui.screens.civilopediascreen.FormattedLine
import com.unciv.ui.screens.civilopediascreen.FormattedLine.IconDisplay
import com.unciv.ui.screens.civilopediascreen.MarkupRenderer
import com.unciv.ui.screens.mapeditorscreen.MapEditorScreen
class MapEditorViewTab(
private val editorScreen: MapEditorScreen
@ -235,11 +235,11 @@ class MapEditorViewTab(
startingLocationsByNation.asSequence()
.filter { tile == null || tile in it.value }
.mapNotNull { ruleset!!.nations[it.key] }
.sortedWith(compareBy<Nation>{ it.isCityState() }.thenBy(collator) { it.name.tr() })
.sortedWith(compareBy<Nation>{ it.isCityState }.thenBy(collator) { it.name.tr() })
private fun TileMap.getStartingLocationSummary() =
startingLocationsByNation.asSequence()
.mapNotNull { if (it.key in ruleset!!.nations) ruleset!!.nations[it.key]!! to it.value.size else null }
.sortedWith(compareBy<Pair<Nation,Int>>{ it.first.isCityState() }.thenBy(collator) { it.first.name.tr() })
.sortedWith(compareBy<Pair<Nation,Int>>{ it.first.isCityState }.thenBy(collator) { it.first.name.tr() })
.map { it.first.name to it.second }
}

View File

@ -1,10 +1,8 @@
package com.unciv.ui.screens.newgamescreen
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.utils.Align
import com.unciv.UncivGame
@ -15,12 +13,7 @@ import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.translations.tr
import com.unciv.ui.audio.MusicMood
import com.unciv.ui.audio.MusicTrackChooserFlags
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.screens.multiplayerscreens.MultiplayerHelpers
import com.unciv.ui.popups.Popup
import com.unciv.ui.popups.ToastPopup
import com.unciv.ui.components.AutoScrollPane
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.components.ExpanderTab
import com.unciv.ui.components.KeyCharAndCode
import com.unciv.ui.components.UncivSlider
@ -33,6 +26,11 @@ import com.unciv.ui.components.extensions.toCheckBox
import com.unciv.ui.components.extensions.toImageButton
import com.unciv.ui.components.extensions.toLabel
import com.unciv.ui.components.extensions.toTextButton
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.popups.Popup
import com.unciv.ui.popups.ToastPopup
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.multiplayerscreens.MultiplayerHelpers
class GameOptionsTable(
private val previousScreen: IPreviousScreen,
@ -207,12 +205,11 @@ class GameOptionsTable(
}
private fun numberOfPlayable() = ruleset.nations.values.count {
it.isMajorCiv()
it.isMajorCiv
}
private fun numberOfCityStates() = ruleset.nations.values.count {
it.isCityState()
&& !it.hasUnique(UniqueType.CityStateDeprecated)
it.isCityState && !it.hasUnique(UniqueType.CityStateDeprecated)
}
private fun Table.addNoStartBiasCheckbox() =
@ -434,7 +431,7 @@ class GameOptionsTable(
var desiredCiv = ""
if (gameParameters.mods.contains(mod)) {
val modNations = RulesetCache[mod]?.nations?.values?.filter { it.isMajorCiv() }
val modNations = RulesetCache[mod]?.nations?.values?.filter { it.isMajorCiv }
if (modNations != null && modNations.any())
desiredCiv = modNations.random().name
@ -481,7 +478,7 @@ private class RandomNationPickerPopup(
init {
val sortedNations = previousScreen.ruleset.nations.values
.filter { it.isMajorCiv() }
.filter { it.isMajorCiv }
.sortedWith(compareBy(UncivGame.Current.settings.getCollatorFromLocale()) { it.name.tr() })
allNationTables = ArrayList(
sortedNations.map { NationTable(it, civBlocksWidth, 0f) } // no need for min height

View File

@ -12,21 +12,21 @@ import com.unciv.logic.civilization.PlayerType
import com.unciv.logic.multiplayer.FriendList
import com.unciv.models.metadata.GameParameters
import com.unciv.models.metadata.Player
import com.unciv.models.ruleset.nation.Nation
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.nation.Nation
import com.unciv.models.translations.tr
import com.unciv.ui.audio.MusicMood
import com.unciv.ui.audio.MusicTrackChooserFlags
import com.unciv.ui.components.KeyCharAndCode
import com.unciv.ui.components.UncivTextField
import com.unciv.ui.components.extensions.*
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.popups.Popup
import com.unciv.ui.screens.basescreen.BaseScreen
import com.unciv.ui.screens.multiplayerscreens.FriendPickerList
import com.unciv.ui.screens.pickerscreens.PickerPane
import com.unciv.ui.screens.pickerscreens.PickerScreen
import com.unciv.ui.popups.Popup
import com.unciv.ui.components.UncivTextField
import com.unciv.ui.components.KeyCharAndCode
import com.unciv.ui.components.extensions.*
import com.unciv.ui.screens.basescreen.BaseScreen
import java.util.UUID
import java.util.*
import com.unciv.ui.components.AutoScrollPane as ScrollPane
/**
@ -82,7 +82,7 @@ class PlayerPickerTable(
for (player in gameParameters.players) {
playerListTable.add(getPlayerTable(player)).width(civBlocksWidth).padBottom(20f).row()
}
if (!locked && gameParameters.players.size < gameBasics.nations.values.count { it.isMajorCiv() }) {
if (!locked && gameParameters.players.size < gameBasics.nations.values.count { it.isMajorCiv }) {
val addPlayerButton = "+".toLabel(Color.BLACK, 30)
.apply { this.setAlignment(Align.center) }
.surroundWithCircle(50f)
@ -110,7 +110,7 @@ class PlayerPickerTable(
*/
private fun reassignRemovedModReferences() {
for (player in gameParameters.players) {
if (!previousScreen.ruleset.nations.containsKey(player.chosenCiv) || previousScreen.ruleset.nations[player.chosenCiv]!!.isCityState())
if (!previousScreen.ruleset.nations.containsKey(player.chosenCiv) || previousScreen.ruleset.nations[player.chosenCiv]!!.isCityState)
player.chosenCiv = Constants.random
}
}
@ -263,7 +263,7 @@ class PlayerPickerTable(
*/
internal fun getAvailablePlayerCivs(dontSkipNation: String? = null) =
previousScreen.ruleset.nations.values.asSequence()
.filter { it.isMajorCiv() }
.filter { it.isMajorCiv }
.filter { it.name == dontSkipNation || gameParameters.players.none { player -> player.chosenCiv == it.name } }
/**
@ -375,7 +375,7 @@ private class NationPickerPopup(
var currentY = 0f
for (nation in nations) {
// only humans can spectate, sorry robots
if (player.playerType == PlayerType.AI && nation.isSpectator())
if (player.playerType == PlayerType.AI && nation.isSpectator)
continue
if (player.chosenCiv == nation.name)
nationListScrollY = currentY