perf: Civ.isBarbarian to lazy ("what could this possibly save", 100ms out of 30s)

This commit is contained in:
yairm210 2024-06-28 15:40:19 +03:00
parent 1dfa7e4677
commit 02737eb031
27 changed files with 57 additions and 55 deletions

View File

@ -257,7 +257,7 @@ class GameInfo : IsPartOfGameInfoSerialization, HasGameInfoSerializationVersion
val collator = GUI.getSettings().getCollatorFromLocale()
return civilizations.asSequence()
.filterNot {
it.isBarbarian() ||
it.isBarbarian ||
it.isSpectator() ||
!includeDefeated && it.isDefeated() ||
!includeCityStates && it.isCityState() ||

View File

@ -173,7 +173,7 @@ object GameStarter {
}
for (civInfo in gameInfo.civilizations) {
if (civInfo.isBarbarian()) continue
if (civInfo.isBarbarian) continue
for (tech in ruleset.technologies.values.filter { it.hasUnique(UniqueType.StartingTech) })
civInfo.addTechSilently(tech.name)
@ -204,7 +204,7 @@ object GameStarter {
}
private fun addCivPolicies(gameInfo: GameInfo, ruleset: Ruleset) {
for (civInfo in gameInfo.civilizations.filter { !it.isBarbarian() }) {
for (civInfo in gameInfo.civilizations.filter { !it.isBarbarian }) {
// generic start with policy unique
for (unique in civInfo.getMatchingUniques(UniqueType.StartsWithPolicy)) {
@ -228,7 +228,7 @@ object GameStarter {
val ruleSet = gameInfo.ruleset
val startingEra = gameInfo.gameParameters.startingEra
val era = ruleSet.eras[startingEra]!!
for (civInfo in gameInfo.civilizations.filter { !it.isBarbarian() && !it.isSpectator() }) {
for (civInfo in gameInfo.civilizations.filter { !it.isBarbarian && !it.isSpectator() }) {
civInfo.addGold((era.startingGold * gameInfo.speed.goldCostModifier).toInt())
civInfo.policies.addCulture((era.startingCulture * gameInfo.speed.cultureCostModifier).toInt())
}
@ -378,7 +378,7 @@ object GameStarter {
for (tile in tileMap.values) {
startScores[tile] = tile.stats.getTileStartScore(cityCenterMinStats)
}
val allCivs = gameInfo.civilizations.filter { !it.isBarbarian() }
val allCivs = gameInfo.civilizations.filter { !it.isBarbarian }
val landTilesInBigEnoughGroup = getCandidateLand(allCivs.size, tileMap, startScores)
// First we get start locations for the major civs, on the second pass the city states (without predetermined starts) can squeeze in wherever
@ -417,7 +417,7 @@ object GameStarter {
val startingEra = gameInfo.gameParameters.startingEra
val settlerLikeUnits = ruleset.units.filter { it.value.isCityFounder() }
for (civ in gameInfo.civilizations.filter { !it.isBarbarian() && !it.isSpectator() }) {
for (civ in gameInfo.civilizations.filter { !it.isBarbarian && !it.isSpectator() }) {
val startingLocation = startingLocations[civ]!!
removeAncientRuinsNearStartingLocation(startingLocation)

View File

@ -217,7 +217,7 @@ object Automation {
/** Determines whether [civInfo] should be allocating military to fending off barbarians */
fun afraidOfBarbarians(civInfo: Civilization): Boolean {
if (civInfo.isCityState() || civInfo.isBarbarian())
if (civInfo.isCityState() || civInfo.isBarbarian)
return false
if (civInfo.gameInfo.gameParameters.noBarbarians)

View File

@ -79,7 +79,7 @@ class BarbarianManager : IsPartOfGameInfoSerialization {
return
// Barbarians will only spawn in places that no one can see
val allViewableTiles = gameInfo.civilizations.asSequence().filterNot { it.isBarbarian() || it.isSpectator() }
val allViewableTiles = gameInfo.civilizations.asSequence().filterNot { it.isBarbarian || it.isSpectator() }
.flatMap { it.viewableTiles }.toHashSet()
val fogTiles = tileMap.values.filter { it.isLand && it !in allViewableTiles }
@ -98,7 +98,7 @@ class BarbarianManager : IsPartOfGameInfoSerialization {
if (campsToAdd <= 0) return
// Camps can't spawn within 7 tiles of each other or within 4 tiles of major civ capitals
val tooCloseToCapitals = gameInfo.civilizations.filterNot { it.isBarbarian() || it.isSpectator() || it.cities.isEmpty() || it.isCityState() || it.getCapital() == null }
val tooCloseToCapitals = gameInfo.civilizations.filterNot { it.isBarbarian || it.isSpectator() || it.cities.isEmpty() || it.isCityState() || it.getCapital() == null }
.flatMap { it.getCapital()!!.getCenterTile().getTilesInDistance(4) }.toSet()
val tooCloseToCamps = encampments
.flatMap { tileMap[it.position].getTilesInDistance(
@ -250,7 +250,7 @@ class Encampment() : IsPartOfGameInfoSerialization {
// if we don't make this into a separate list then the retain() will happen on the Tech keys,
// which effectively removes those techs from the game and causes all sorts of problems
val allResearchedTechs = gameInfo.ruleset.technologies.keys.toMutableList()
for (civ in gameInfo.civilizations.filter { !it.isBarbarian() && !it.isDefeated() }) {
for (civ in gameInfo.civilizations.filter { !it.isBarbarian && !it.isDefeated() }) {
allResearchedTechs.retainAll(civ.tech.techsResearched)
}
val barbarianCiv = gameInfo.getBarbarianCivilization()

View File

@ -296,7 +296,7 @@ object DiplomacyAutomation {
val enemiesCiv = civInfo.diplomacy.filter { it.value.diplomaticStatus == DiplomaticStatus.War }
.map { it.value.otherCiv() }
.filterNot {
it == civInfo || it.isBarbarian() || it.cities.isEmpty()
it == civInfo || it.isBarbarian || it.cities.isEmpty()
|| it.getDiplomacyManager(civInfo)!!.hasFlag(DiplomacyFlags.DeclaredWar)
|| civInfo.getDiplomacyManager(it)!!.hasFlag(DiplomacyFlags.DeclaredWar)
}.filter { !civInfo.getDiplomacyManager(it)!!.hasFlag(DiplomacyFlags.DeclinedPeace) }

View File

@ -33,7 +33,7 @@ object NextTurnAutomation {
/** Top-level AI turn task list */
fun automateCivMoves(civInfo: Civilization) {
if (civInfo.isBarbarian()) return BarbarianAutomation(civInfo).automate()
if (civInfo.isBarbarian) return BarbarianAutomation(civInfo).automate()
if (civInfo.isSpectator()) return // When there's a spectator in multiplayer games, it's processed automatically, but shouldn't be able to actually do anything
respondToPopupAlerts(civInfo)
@ -434,7 +434,7 @@ object NextTurnAutomation {
val ownMilitaryStrength = civInfo.getStatForRanking(RankingType.Force)
val sumOfEnemiesMilitaryStrength =
civInfo.gameInfo.civilizations
.filter { it != civInfo && !it.isBarbarian() && civInfo.isAtWarWith(it) }
.filter { it != civInfo && !it.isBarbarian && civInfo.isAtWarWith(it) }
.sumOf { it.getStatForRanking(RankingType.Force) }
val civHasSignificantlyWeakerMilitaryThanEnemies =
ownMilitaryStrength < sumOfEnemiesMilitaryStrength * 0.66f

View File

@ -167,7 +167,7 @@ object UnitAutomation {
}
fun automateUnitMoves(unit: MapUnit) {
check(!unit.civ.isBarbarian()) { "Barbarians is not allowed here." }
check(!unit.civ.isBarbarian) { "Barbarians is not allowed here." }
// Might die next turn - move!
if (unit.health <= unit.getDamageFromTerrain() && tryHealUnit(unit)) return

View File

@ -154,14 +154,14 @@ object Battle {
if (!captureMilitaryUnitSuccess) // capture creates a new unit, but `defender` still is the original, so this function would still show a kill message
postBattleNotifications(attacker, defender, attackedTile, attacker.getTile(), damageDealt)
if (defender.getCivInfo().isBarbarian() && attackedTile.improvement == Constants.barbarianEncampment)
if (defender.getCivInfo().isBarbarian && attackedTile.improvement == Constants.barbarianEncampment)
defender.getCivInfo().gameInfo.barbarians.campAttacked(attackedTile.position)
// This needs to come BEFORE the move-to-tile, because if we haven't conquered it we can't move there =)
if (defender.isDefeated() && defender is CityCombatant && attacker is MapUnitCombatant
&& attacker.isMelee() && !attacker.unit.hasUnique(UniqueType.CannotCaptureCities)) {
// Barbarians can't capture cities
if (attacker.unit.civ.isBarbarian()) {
if (attacker.unit.civ.isBarbarian) {
defender.takeDamage(-1) // Back to 2 HP
val ransom = min(200, defender.city.civ.gold)
defender.city.civ.addGold(-ransom)
@ -253,7 +253,7 @@ object Battle {
}
// CS friendship from killing barbarians
if (defeatedUnit.getCivInfo().isBarbarian() && !defeatedUnit.isCivilian() && civUnit.getCivInfo().isMajorCiv()) {
if (defeatedUnit.getCivInfo().isBarbarian && !defeatedUnit.isCivilian() && civUnit.getCivInfo().isMajorCiv()) {
for (cityState in defeatedUnit.getCivInfo().gameInfo.getAliveCityStates()) {
if (civUnit.getCivInfo().knows(cityState) && defeatedUnit.unit.threatensCiv(cityState)) {
cityState.cityStateFunctions.threateningBarbarianKilledBy(civUnit.getCivInfo())
@ -391,7 +391,7 @@ object Battle {
NotificationIcon.War to " was destroyed while attacking"
!defender.isDefeated() ->
NotificationIcon.War to " has attacked"
defender.isCity() && attacker.isMelee() && attacker.getCivInfo().isBarbarian() ->
defender.isCity() && attacker.isMelee() && attacker.getCivInfo().isBarbarian ->
NotificationIcon.War to " has raided"
defender.isCity() && attacker.isMelee() ->
NotificationIcon.War to " has captured"
@ -485,7 +485,7 @@ object Battle {
internal fun addXp(thisCombatant: ICombatant, amount: Int, otherCombatant: ICombatant) {
if (thisCombatant !is MapUnitCombatant) return
val civ = thisCombatant.getCivInfo()
val otherIsBarbarian = otherCombatant.getCivInfo().isBarbarian()
val otherIsBarbarian = otherCombatant.getCivInfo().isBarbarian
val promotions = thisCombatant.unit.promotions
val modConstants = civ.gameInfo.ruleset.modOptions.constants
@ -561,7 +561,7 @@ object Battle {
)
}
if (attackerCiv.isBarbarian() || attackerCiv.isOneCityChallenger()) {
if (attackerCiv.isBarbarian || attackerCiv.isOneCityChallenger()) {
city.destroyCity(true)
return
}

View File

@ -65,7 +65,7 @@ object BattleDamage {
}
}
if (enemy.getCivInfo().isBarbarian()) {
if (enemy.getCivInfo().isBarbarian) {
modifiers["Difficulty"] =
(civInfo.gameInfo.getDifficulty().barbarianBonus * 100).toInt()
}
@ -115,7 +115,7 @@ object BattleDamage {
val civInfo = combatant.getCivInfo()
val civResources = civInfo.getCivResourcesByName()
for (resource in combatant.unit.getResourceRequirementsPerTurn().keys)
if (civResources[resource]!! < 0 && !civInfo.isBarbarian())
if (civResources[resource]!! < 0 && !civInfo.isBarbarian)
modifiers["Missing resource"] = BattleConstants.MISSING_RESOURCES_MALUS
}

View File

@ -77,7 +77,7 @@ object BattleUnitCapture {
}
private fun unitCapturedFromEncampment(attacker: MapUnitCombatant, defender: MapUnitCombatant, attackedTile: Tile): Boolean {
if (!defender.getCivInfo().isBarbarian()) return false
if (!defender.getCivInfo().isBarbarian) return false
if (attackedTile.improvement != Constants.barbarianEncampment) return false
var unitCaptured = false
@ -154,9 +154,9 @@ object BattleUnitCapture {
capturedUnit.capturedBy(attacker.getCivInfo())
}
// Return captured civilian to its original owner?
defender.getCivInfo().isBarbarian()
defender.getCivInfo().isBarbarian
&& originalOwner != null
&& !originalOwner.isBarbarian()
&& !originalOwner.isBarbarian
&& attacker.getCivInfo() != originalOwner
&& attacker.getCivInfo().knows(originalOwner)
&& originalOwner.isAlive()
@ -205,7 +205,7 @@ object BattleUnitCapture {
*/
fun captureOrConvertToWorker(capturedUnit: MapUnit, capturingCiv: Civilization): Vector2? {
// Captured settlers are converted to workers unless captured by barbarians (so they can be returned later).
if (!capturedUnit.hasUnique(UniqueType.FoundCity) || capturingCiv.isBarbarian()) {
if (!capturedUnit.hasUnique(UniqueType.FoundCity) || capturingCiv.isBarbarian) {
capturedUnit.capturedBy(capturingCiv)
return capturedUnit.currentTile.position // if capturedBy has moved the unit, this is updated
}

View File

@ -39,7 +39,7 @@ object Nuke {
if (defenderCiv == null) return
// Allow nuking yourself! (Civ5 source: CvUnit::isNukeVictim)
if (defenderCiv == attackerCiv || defenderCiv.isDefeated()) return
if (defenderCiv.isBarbarian()) return
if (defenderCiv.isBarbarian) return
// Gleaned from Civ5 source - this disallows nuking unknown civs even in invisible tiles
// https://github.com/Gedemon/Civ5-DLL/blob/master/CvGameCoreDLL_Expansion1/CvUnit.cpp#L5056
// https://github.com/Gedemon/Civ5-DLL/blob/master/CvGameCoreDLL_Expansion1/CvTeam.cpp#L986
@ -205,7 +205,7 @@ object Nuke {
var damageModifierFromMissingResource = 1f
val civResources = attacker.getCivInfo().getCivResourcesByName()
for (resource in attacker.unit.getResourceRequirementsPerTurn().keys) {
if (civResources[resource]!! < 0 && !attacker.getCivInfo().isBarbarian())
if (civResources[resource]!! < 0 && !attacker.getCivInfo().isBarbarian)
damageModifierFromMissingResource *= 0.5f // I could not find a source for this number, but this felt about right
// - Original Civ5 does *not* reduce damage from missing resource, from source inspection
}

View File

@ -362,7 +362,7 @@ class Civilization : IsPartOfGameInfoSerialization {
fun isMajorCiv() = nation.isMajorCiv
fun isMinorCiv() = nation.isCityState || nation.isBarbarian
fun isCityState(): Boolean = nation.isCityState
fun isBarbarian() = nation.isBarbarian
val isBarbarian by lazy { nation.isBarbarian }
fun isSpectator() = nation.isSpectator
fun isAlive(): Boolean = !isDefeated()
@ -618,7 +618,7 @@ class Civilization : IsPartOfGameInfoSerialization {
* Otherwise, it stays 'alive' as long as it has cities (irrespective of settlers owned)
*/
fun isDefeated() = when {
isBarbarian() || isSpectator() -> false // Barbarians and voyeurs can't lose
isBarbarian || isSpectator() -> false // Barbarians and voyeurs can't lose
hasEverOwnedOriginalCapital -> cities.isEmpty()
else -> units.getCivUnitsSize() == 0
}

View File

@ -540,7 +540,7 @@ class CityStateFunctions(val civInfo: Civilization) {
fun getNumThreateningBarbarians(): Int {
if (civInfo.gameInfo.gameParameters.noBarbarians) return 0
val barbarianCiv = civInfo.gameInfo.civilizations.firstOrNull { it.isBarbarian() }
val barbarianCiv = civInfo.gameInfo.civilizations.firstOrNull { it.isBarbarian }
?: return 0
return barbarianCiv.units.getCivUnits().count { it.threatensCiv(civInfo) }
}

View File

@ -78,7 +78,7 @@ class DiplomacyFunctions(val civInfo: Civilization) {
fun isAtWarWith(otherCiv: Civilization): Boolean {
return when {
otherCiv == civInfo -> false
otherCiv.isBarbarian() || civInfo.isBarbarian() -> true
otherCiv.isBarbarian || civInfo.isBarbarian -> true
else -> {
val diplomacyManager = civInfo.diplomacy[otherCiv.civName]
?: return false // not encountered yet
@ -149,8 +149,8 @@ class DiplomacyFunctions(val civInfo: Civilization) {
*/
fun canPassThroughTiles(otherCiv: Civilization): Boolean {
if (otherCiv == civInfo) return true
if (otherCiv.isBarbarian()) return true
if (civInfo.isBarbarian() && civInfo.gameInfo.turns >= civInfo.gameInfo.difficultyObject.turnBarbariansCanEnterPlayerTiles)
if (otherCiv.isBarbarian) return true
if (civInfo.isBarbarian && civInfo.gameInfo.turns >= civInfo.gameInfo.difficultyObject.turnBarbariansCanEnterPlayerTiles)
return true
val diplomacyManager = civInfo.diplomacy[otherCiv.civName]
if (diplomacyManager != null && (diplomacyManager.hasOpenBorders || diplomacyManager.diplomaticStatus == DiplomaticStatus.War))

View File

@ -155,7 +155,7 @@ class TurnManager(val civInfo: Civilization) {
private fun updateRevolts() {
if (civInfo.gameInfo.civilizations.none { it.isBarbarian() }) {
if (civInfo.gameInfo.civilizations.none { it.isBarbarian }) {
// Can't spawn revolts without barbarians ¯\_(ツ)_/¯
return
}
@ -250,7 +250,7 @@ class TurnManager(val civInfo: Civilization) {
if (civInfo.isDefeated() || civInfo.isSpectator()) return // yes they do call this, best not update any further stuff
var nextTurnStats =
if (civInfo.isBarbarian())
if (civInfo.isBarbarian)
Stats()
else {
civInfo.updateStatsForNextTurn()
@ -271,7 +271,7 @@ class TurnManager(val civInfo: Civilization) {
}
// disband units until there are none left OR the gold values are normal
if (!civInfo.isBarbarian() && civInfo.gold <= -200 && nextTurnStats.gold.toInt() < 0) {
if (!civInfo.isBarbarian && civInfo.gold <= -200 && nextTurnStats.gold.toInt() < 0) {
do {
val militaryUnits = civInfo.units.getCivUnits().filter { it.isMilitary() } // New sequence as disband replaces unitList
val unitToDisband = militaryUnits.minByOrNull { it.baseUnit.cost }
@ -344,7 +344,7 @@ class TurnManager(val civInfo: Civilization) {
NextTurnAutomation.automateCivMoves(civInfo)
// Update barbarian camps
if (civInfo.isBarbarian() && !civInfo.gameInfo.gameParameters.noBarbarians)
if (civInfo.isBarbarian && !civInfo.gameInfo.gameParameters.noBarbarians)
civInfo.gameInfo.barbarians.updateEncampments()
}

View File

@ -38,7 +38,7 @@ class VictoryManager : IsPartOfGameInfoSerialization {
}
private fun getVotingCivs() = civInfo.gameInfo.civilizations.asSequence()
.filterNot { it.isBarbarian() || it.isSpectator() || it.isDefeated() }
.filterNot { it.isBarbarian || it.isSpectator() || it.isDefeated() }
/** Finds the Building and Owner of the United Nations (or whatever the Mod called it)
* - if it's built at all and only if the owner is alive

View File

@ -133,7 +133,7 @@ class CapitalConnectionsFinder(private val civInfo: Civilization) {
private fun canEnterBordersOf(otherCiv: Civilization): Boolean {
if (otherCiv == civInfo) return true // own borders are always open
if (otherCiv.isBarbarian() || civInfo.isBarbarian()) return false // barbarians blocks the routes
if (otherCiv.isBarbarian || civInfo.isBarbarian) return false // barbarians blocks the routes
val diplomacyManager = civInfo.diplomacy[otherCiv.civName]
?: return false // not encountered yet
if (otherCiv.isCityState() && diplomacyManager.diplomaticStatus != DiplomaticStatus.War) return true

View File

@ -119,10 +119,10 @@ class CivInfoTransientCache(val civInfo: Civilization) {
if (unitOwner != null) viewedCivs[unitOwner] = tile
}
if (!civInfo.isBarbarian()) {
if (!civInfo.isBarbarian) {
for (entry in viewedCivs) {
val metCiv = entry.key
if (metCiv == civInfo || metCiv.isBarbarian() || civInfo.diplomacy.containsKey(metCiv.civName)) continue
if (metCiv == civInfo || metCiv.isBarbarian || civInfo.diplomacy.containsKey(metCiv.civName)) continue
civInfo.diplomacyFunctions.makeCivilizationsMeet(metCiv)
if(!civInfo.isSpectator())
civInfo.addNotification("We have encountered [${metCiv.civName}]!",

View File

@ -546,7 +546,7 @@ class MapUnit : IsPartOfGameInfoSerialization {
private fun matchesSingleFilter(filter: String): Boolean {
return when (filter) {
Constants.wounded, "wounded units" -> health < 100
Constants.barbarians, "Barbarian" -> civ.isBarbarian()
Constants.barbarians, "Barbarian" -> civ.isBarbarian
"City-State" -> civ.isCityState()
Constants.embarked -> isEmbarked()
"Non-City" -> true
@ -858,7 +858,7 @@ class MapUnit : IsPartOfGameInfoSerialization {
if (civ.isMajorCiv() && tile.getTileImprovement()?.isAncientRuinsEquivalent() == true) {
getAncientRuinBonus(tile)
}
if (improvement == Constants.barbarianEncampment && !civ.isBarbarian())
if (improvement == Constants.barbarianEncampment && !civ.isBarbarian)
clearEncampment(tile)
// Check whether any civilians without military units are there.
// Keep in mind that putInTile(), which calls this method,

View File

@ -151,8 +151,8 @@ object MovementCost {
// these two tiles can perhaps be optimized. Using a hex-math-based "commonAdjacentTiles"
// function is surprisingly less efficient than the current neighbor-intersection approach.
// See #4085 for more details.
val tilesExertingZoneOfControl = getTilesExertingZoneOfControl(unit, from)
if (tilesExertingZoneOfControl.none { to.aerialDistanceTo(it) == 1 })
val tilesExertingZoneOfControl = getTilesExertingZoneOfControl(unit, from, to)
if (tilesExertingZoneOfControl.none())
return false
// Even though this is a very fast check, we perform it last. This is because very few units
@ -164,8 +164,9 @@ object MovementCost {
return true
}
private fun getTilesExertingZoneOfControl(unit: MapUnit, tile: Tile) = sequence {
for (neighbor in tile.neighbors) {
private fun getTilesExertingZoneOfControl(unit: MapUnit, from: Tile, to:Tile) = sequence {
for (neighbor in from.neighbors) {
if (neighbor !in to.neighbors) continue
if (neighbor.isCityCenter() && unit.civ.isAtWarWith(neighbor.getOwner()!!)) {
yield(neighbor)
}

View File

@ -829,7 +829,7 @@ object UniqueTriggerActivation {
UniqueType.OneTimeTriggerVoting -> {
return {
for (civ in civInfo.gameInfo.civilizations)
if (!civ.isBarbarian() && !civ.isSpectator())
if (!civ.isBarbarian && !civ.isSpectator())
civ.addFlag(
CivFlags.TurnsTillNextDiplomaticVote.name,
civInfo.getTurnsBetweenDiplomaticVotes()

View File

@ -225,7 +225,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
})
yield(RejectionReasonType.MaxNumberBuildable.toInstance())
if (!civ.isBarbarian()) { // Barbarians don't need resources
if (!civ.isBarbarian) { // Barbarians don't need resources
val civResources = Counter(civ.getCivResourcesByName()) + additionalResources
for ((resource, requiredAmount) in getResourceRequirementsPerTurn(StateForConditionals(civ))) {
val availableAmount = civResources[resource]

View File

@ -143,7 +143,7 @@ internal class ConsoleTileCommands: ConsoleCommandNode {
setBaseTerrain(tile, wonder.turnsInto ?: tile.baseTerrain)
for (civ in tile.tileMap.gameInfo.civilizations) {
if (wonder.name in civ.naturalWonders) continue
if (civ.isDefeated() || civ.isBarbarian() || civ.isSpectator()) continue
if (civ.isDefeated() || civ.isBarbarian || civ.isSpectator()) continue
if (!civ.hasExplored(tile)) continue
civ.cache.discoverNaturalWonders()
civ.updateStatsForNextTurn()

View File

@ -286,7 +286,7 @@ class GlobalPoliticsOverviewTable(
persistableData.includeCityStates && viewingPlayer.hideCityStateCount()
relevantCivsCount = if (hideCivsCount) "?"
else gameInfo.civilizations.count {
!it.isSpectator() && !it.isBarbarian() && (persistableData.includeCityStates || !it.isCityState())
!it.isSpectator() && !it.isBarbarian && (persistableData.includeCityStates || !it.isCityState())
}.toString()
undefeatedCivs = sequenceOf(viewingPlayer) +
viewingPlayer.diplomacyFunctions.getKnownCivsSorted(persistableData.includeCityStates)

View File

@ -171,7 +171,7 @@ class TechPolicyDiplomacyButtons(val worldScreen: WorldScreen) : Table(BaseScree
private fun updateDiplomacyButton(): Boolean {
return if (viewingCiv.isDefeated() || viewingCiv.isSpectator()
|| viewingCiv.getKnownCivs().filterNot { it == viewingCiv || it.isBarbarian() }.none()
|| viewingCiv.getKnownCivs().filterNot { it == viewingCiv || it.isBarbarian }.none()
) {
diplomacyButtonHolder.touchable = Touchable.disabled
diplomacyButtonHolder.actor = null

View File

@ -737,7 +737,7 @@ class WorldScreen(
if (!game.settings.showTutorials) return
displayTutorial(TutorialTrigger.SlowStart)
displayTutorial(TutorialTrigger.CityExpansion) { viewingCiv.cities.any { it.expansion.tilesClaimed() > 0 } }
displayTutorial(TutorialTrigger.BarbarianEncountered) { viewingCiv.viewableTiles.any { it.getUnits().any { unit -> unit.civ.isBarbarian() } } }
displayTutorial(TutorialTrigger.BarbarianEncountered) { viewingCiv.viewableTiles.any { it.getUnits().any { unit -> unit.civ.isBarbarian } } }
displayTutorial(TutorialTrigger.RoadsAndRailroads) { viewingCiv.cities.size > 2 }
displayTutorial(TutorialTrigger.Happiness) { viewingCiv.getHappiness() < 5 }
displayTutorial(TutorialTrigger.Unhappiness) { viewingCiv.getHappiness() < 0 }

View File

@ -195,7 +195,8 @@ class BattleTable(val worldScreen: WorldScreen) : Table() {
// from Battle.addXp(), check for can't gain more XP from Barbarians
val maxXPFromBarbarians = attacker.getCivInfo().gameInfo.ruleset.modOptions.constants.maxXPfromBarbarians
if (attacker is MapUnitCombatant && attacker.unit.promotions.totalXpProduced() >= maxXPFromBarbarians
&& defender.getCivInfo().isBarbarian()) {
&& defender.getCivInfo().isBarbarian
) {
add("Cannot gain more XP from Barbarians".toLabel(fontSize = 16).apply { wrap = true }).width(quarterScreen)
row()
}