Fixed city state tests

This commit is contained in:
Yair Morgenstern 2022-11-22 00:13:05 +02:00
parent e83e733104
commit 5ba8e05079
8 changed files with 45 additions and 57 deletions

View File

@ -2,7 +2,6 @@ package com.unciv.logic.city
import com.unciv.Constants import com.unciv.Constants
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
import com.unciv.logic.map.RoadStatus import com.unciv.logic.map.RoadStatus
import com.unciv.models.Counter import com.unciv.models.Counter
import com.unciv.models.ruleset.Building import com.unciv.models.ruleset.Building
@ -138,32 +137,6 @@ class CityStats(val cityInfo: CityInfo) {
statPercentBonusTree.addStats(building.getStatPercentageBonuses(cityInfo, localUniqueCache), "Buildings", building.name) statPercentBonusTree.addStats(building.getStatPercentageBonuses(cityInfo, localUniqueCache), "Buildings", building.name)
} }
private fun getStatsFromCityStates(): Stats {
val stats = Stats()
for (otherCiv in cityInfo.civInfo.getKnownCivs()) {
val relationshipLevel = otherCiv.getDiplomacyManager(cityInfo.civInfo).relationshipLevel()
if (otherCiv.isCityState() && relationshipLevel >= RelationshipLevel.Friend) {
val eraInfo = cityInfo.civInfo.getEra()
for (bonus in eraInfo.getCityStateBonuses(otherCiv.cityStateType, relationshipLevel, UniqueType.CityStateStatsPerCity)) {
if (cityInfo.matchesFilter(bonus.params[1])
&& bonus.conditionalsApply(otherCiv, cityInfo)
) stats.add(bonus.stats)
}
}
}
for (unique in cityInfo.civInfo.getMatchingUniques(UniqueType.BonusStatsFromCityStates)) {
stats[Stat.valueOf(unique.params[1])] *= unique.params[0].toPercent()
}
return stats
}
private fun getStatPercentBonusesFromPuppetCity(): Stats { private fun getStatPercentBonusesFromPuppetCity(): Stats {
val stats = Stats() val stats = Stats()
if (cityInfo.isPuppet) { if (cityInfo.isPuppet) {
@ -216,8 +189,15 @@ class CityStats(val cityInfo: CityInfo) {
private fun getStatsFromUniquesBySource(): StatTreeNode { private fun getStatsFromUniquesBySource(): StatTreeNode {
val sourceToStats = StatTreeNode() val sourceToStats = StatTreeNode()
val cityStateStatsMultipliers = cityInfo.civInfo.getMatchingUniques(UniqueType.BonusStatsFromCityStates).toList()
fun addUniqueStats(unique:Unique) { fun addUniqueStats(unique:Unique) {
sourceToStats.addStats(unique.stats, getSourceNameForUnique(unique), unique.sourceObjectName ?: "") val stats = unique.stats.clone()
if (unique.sourceObjectType==UniqueTarget.CityState)
for (multiplierUnique in cityStateStatsMultipliers)
stats[Stat.valueOf(multiplierUnique.params[1])] *= multiplierUnique.params[0].toPercent()
sourceToStats.addStats(stats, getSourceNameForUnique(unique), unique.sourceObjectName ?: "")
} }
for (unique in cityInfo.getMatchingUniques(UniqueType.StatsPerCity)) for (unique in cityInfo.getMatchingUniques(UniqueType.StatsPerCity))
@ -236,6 +216,7 @@ class CityStats(val cityInfo: CityInfo) {
addUniqueStats(unique) addUniqueStats(unique)
return sourceToStats return sourceToStats
} }
@ -246,6 +227,7 @@ class CityStats(val cityInfo: CityInfo) {
UniqueTarget.Wonder -> "Wonders" UniqueTarget.Wonder -> "Wonders"
UniqueTarget.Building -> "Buildings" UniqueTarget.Building -> "Buildings"
UniqueTarget.Policy -> "Policies" UniqueTarget.Policy -> "Policies"
UniqueTarget.CityState -> Constants.cityStates
else -> unique.sourceObjectType.name else -> unique.sourceObjectType.name
} }
} }
@ -444,7 +426,6 @@ class CityStats(val cityInfo: CityInfo) {
getStatsFromSpecialists(cityInfo.population.getNewSpecialists()) getStatsFromSpecialists(cityInfo.population.getNewSpecialists())
newBaseStatList["Trade routes"] = getStatsFromTradeRoute() newBaseStatList["Trade routes"] = getStatsFromTradeRoute()
newBaseStatTree.children["Buildings"] = statsFromBuildings newBaseStatTree.children["Buildings"] = statsFromBuildings
newBaseStatList[Constants.cityStates] = getStatsFromCityStates()
for ((source, stats) in newBaseStatList) for ((source, stats) in newBaseStatList)
newBaseStatTree.addStats(stats, source) newBaseStatTree.addStats(stats, source)

View File

@ -6,6 +6,7 @@ import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
import com.unciv.logic.civilization.diplomacy.RelationshipLevel import com.unciv.logic.civilization.diplomacy.RelationshipLevel
import com.unciv.models.ruleset.CityStateType
import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.tile.ResourceSupplyList import com.unciv.models.ruleset.tile.ResourceSupplyList
import com.unciv.models.ruleset.unique.StateForConditionals import com.unciv.models.ruleset.unique.StateForConditionals
@ -419,8 +420,7 @@ class CityStateFunctions(val civInfo: CivilizationInfo) {
fun canGiveStat(statType: Stat): Boolean { fun canGiveStat(statType: Stat): Boolean {
if (!civInfo.isCityState()) if (!civInfo.isCityState())
return false return false
val eraInfo = civInfo.getEra() for (bonus in getCityStateBonuses(civInfo.cityStateType, RelationshipLevel.Ally)) {
for (bonus in eraInfo.getCityStateBonuses(civInfo.cityStateType, RelationshipLevel.Ally)) {
if (bonus.stats[statType] > 0 || (bonus.isOfType(UniqueType.CityStateHappiness) && statType == Stat.Happiness)) if (bonus.stats[statType] > 0 || (bonus.isOfType(UniqueType.CityStateHappiness) && statType == Stat.Happiness))
return true return true
} }
@ -650,10 +650,20 @@ class CityStateFunctions(val civInfo: CivilizationInfo) {
stateForConditionals: StateForConditionals stateForConditionals: StateForConditionals
):Sequence<Unique> { ):Sequence<Unique> {
if (civInfo.isCityState()) return emptySequence() if (civInfo.isCityState()) return emptySequence()
val era = civInfo.getEra()
return civInfo.getKnownCivs().asSequence().filter { it.isCityState() } return civInfo.getKnownCivs().asSequence().filter { it.isCityState() }
.flatMap { era.getCityStateBonuses(it.cityStateType, civInfo.getDiplomacyManager(it).relationshipLevel(), uniqueType) } .flatMap { getCityStateBonuses(it.cityStateType, it.getDiplomacyManager(civInfo).relationshipLevel(), uniqueType) }
.filter { it.conditionalsApply(stateForConditionals) } .filter { it.conditionalsApply(stateForConditionals) }
} }
fun getCityStateBonuses(cityStateType: CityStateType, relationshipLevel: RelationshipLevel, uniqueType:UniqueType?=null): Sequence<Unique> {
val cityStateUniqueMap = when (relationshipLevel) {
RelationshipLevel.Ally -> cityStateType.allyBonusUniqueMap
RelationshipLevel.Friend -> cityStateType.friendBonusUniqueMap
else -> null
} ?: return emptySequence()
return if (uniqueType == null) cityStateUniqueMap.getAllUniques()
else cityStateUniqueMap.getUniques(uniqueType)
}
} }

View File

@ -149,9 +149,8 @@ class CivInfoStats(val civInfo: CivilizationInfo) {
val relationshipLevel = otherCiv.getDiplomacyManager(civInfo.civName).relationshipLevel() val relationshipLevel = otherCiv.getDiplomacyManager(civInfo.civName).relationshipLevel()
if (otherCiv.isCityState() && relationshipLevel >= RelationshipLevel.Friend) { if (otherCiv.isCityState() && relationshipLevel >= RelationshipLevel.Friend) {
val cityStateBonus = Stats() val cityStateBonus = Stats()
val eraInfo = civInfo.getEra()
for (bonus in eraInfo.getCityStateBonuses(otherCiv.cityStateType, relationshipLevel, UniqueType.CityStateStatsPerTurn)) { for (bonus in civInfo.cityStateFunctions.getCityStateBonuses(otherCiv.cityStateType, relationshipLevel, UniqueType.CityStateStatsPerTurn)) {
cityStateBonus.add(bonus.stats) cityStateBonus.add(bonus.stats)
} }
@ -314,8 +313,7 @@ class CivInfoStats(val civInfo: CivilizationInfo) {
val relationshipLevel = otherCiv.getDiplomacyManager(civInfo).relationshipLevel() val relationshipLevel = otherCiv.getDiplomacyManager(civInfo).relationshipLevel()
if (!otherCiv.isCityState() || relationshipLevel < RelationshipLevel.Friend) continue if (!otherCiv.isCityState() || relationshipLevel < RelationshipLevel.Friend) continue
val eraInfo = civInfo.getEra() for (bonus in civInfo.cityStateFunctions.getCityStateBonuses(otherCiv.cityStateType, relationshipLevel)) {
for (bonus in eraInfo.getCityStateBonuses(otherCiv.cityStateType, relationshipLevel)) {
if (!bonus.conditionalsApply(otherCiv)) continue if (!bonus.conditionalsApply(otherCiv)) continue
if (bonus.isOfType(UniqueType.CityStateHappiness)) if (bonus.isOfType(UniqueType.CityStateHappiness))
cityStatesHappiness += bonus.params[0].toFloat() cityStatesHappiness += bonus.params[0].toFloat()

View File

@ -610,8 +610,6 @@ class DiplomacyManager() : IsPartOfGameInfoSerialization {
if (!otherCiv().isCityState()) return if (!otherCiv().isCityState()) return
val eraInfo = civInfo.getEra()
if (relationshipLevel() < RelationshipLevel.Friend) { if (relationshipLevel() < RelationshipLevel.Friend) {
if (hasFlag(DiplomacyFlags.ProvideMilitaryUnit)) if (hasFlag(DiplomacyFlags.ProvideMilitaryUnit))
removeFlag(DiplomacyFlags.ProvideMilitaryUnit) removeFlag(DiplomacyFlags.ProvideMilitaryUnit)
@ -620,7 +618,7 @@ class DiplomacyManager() : IsPartOfGameInfoSerialization {
val variance = listOf(-1, 0, 1).random() val variance = listOf(-1, 0, 1).random()
val provideMilitaryUnitUniques = eraInfo.getCityStateBonuses(otherCiv().cityStateType, relationshipLevel(), UniqueType.CityStateMilitaryUnits) val provideMilitaryUnitUniques = civInfo.cityStateFunctions.getCityStateBonuses(otherCiv().cityStateType, relationshipLevel(), UniqueType.CityStateMilitaryUnits)
.filter { it.conditionalsApply(civInfo) }.toList() .filter { it.conditionalsApply(civInfo) }.toList()
if (provideMilitaryUnitUniques.isEmpty()) removeFlag(DiplomacyFlags.ProvideMilitaryUnit) if (provideMilitaryUnitUniques.isEmpty()) removeFlag(DiplomacyFlags.ProvideMilitaryUnit)

View File

@ -1,9 +1,7 @@
package com.unciv.models.ruleset package com.unciv.models.ruleset
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.unciv.logic.civilization.diplomacy.RelationshipLevel
import com.unciv.models.ruleset.unique.StateForConditionals import com.unciv.models.ruleset.unique.StateForConditionals
import com.unciv.models.ruleset.unique.Unique
import com.unciv.models.ruleset.unique.UniqueTarget import com.unciv.models.ruleset.unique.UniqueTarget
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.ui.civilopedia.FormattedLine import com.unciv.ui.civilopedia.FormattedLine
@ -81,16 +79,6 @@ class Era : RulesetObject() {
}.map { it.first }.distinct() }.map { it.first }.distinct()
} }
fun getCityStateBonuses(cityStateType: CityStateType, relationshipLevel: RelationshipLevel, uniqueType:UniqueType?=null): Sequence<Unique> {
val cityStateUniqueMap = when (relationshipLevel) {
RelationshipLevel.Ally -> cityStateType.allyBonusUniqueMap
RelationshipLevel.Friend -> cityStateType.friendBonusUniqueMap
else -> null
} ?: return emptySequence()
return if (uniqueType == null) cityStateUniqueMap.getAllUniques()
else cityStateUniqueMap.getUniques(uniqueType)
}
fun getStartingUnits(): List<String> { fun getStartingUnits(): List<String> {
val startingUnits = mutableListOf<String>() val startingUnits = mutableListOf<String>()
repeat(startingSettlerCount) { startingUnits.add(startingSettlerUnit) } repeat(startingSettlerCount) { startingUnits.add(startingSettlerUnit) }

View File

@ -253,7 +253,6 @@ class RulesetValidator(val ruleset: Ruleset) {
allDifficultiesStartingUnits.addAll(difficulty.playerBonusStartingUnits) allDifficultiesStartingUnits.addAll(difficulty.playerBonusStartingUnits)
} }
val rulesetHasCityStates = ruleset.nations.values.any { it.isCityState() }
for (era in ruleset.eras.values) { for (era in ruleset.eras.values) {
for (wonder in era.startingObsoleteWonders) for (wonder in era.startingObsoleteWonders)
if (wonder !in ruleset.buildings) if (wonder !in ruleset.buildings)
@ -298,6 +297,9 @@ class RulesetValidator(val ruleset: Ruleset) {
for (nation in ruleset.nations.values) { for (nation in ruleset.nations.values) {
checkUniques(nation, lines, rulesetSpecific, tryFixUnknownUniques) checkUniques(nation, lines, rulesetSpecific, tryFixUnknownUniques)
if (nation.cityStateType!=null && nation.cityStateType !in ruleset.cityStateTypes)
lines += "${nation.name} is of city-state type ${nation.cityStateType} which does not exist!"
if (nation.favoredReligion != null && nation.favoredReligion !in ruleset.religions) if (nation.favoredReligion != null && nation.favoredReligion !in ruleset.religions)
lines += "${nation.name} has ${nation.favoredReligion} as their favored religion, which does not exist!" lines += "${nation.name} has ${nation.favoredReligion} as their favored religion, which does not exist!"
} }

View File

@ -232,6 +232,19 @@ enum class UniqueParameterType(
parameterText != "All" && getErrorSeverity(parameterText, ruleset) == null parameterText != "All" && getErrorSeverity(parameterText, ruleset) == null
}, },
/** [UniqueType.PercentProductionConstructions], [UniqueType.PercentProductionConstructionsCities] */
@Deprecated("as of 3.17.10 - removed 3.18.5")
ConstructionFilter("constructionFilter", "Spaceship Part") {
override fun getErrorSeverity(
parameterText: String,
ruleset: Ruleset
): UniqueType.UniqueComplianceErrorSeverity? {
if (BuildingFilter.getErrorSeverity(parameterText, ruleset) == null) return null
if (BaseUnitFilter.getErrorSeverity(parameterText, ruleset) == null) return null
return UniqueType.UniqueComplianceErrorSeverity.WarningOnly
}
},
/** Implemented by [PopulationManager.getPopulationFilterAmount][com.unciv.logic.city.PopulationManager.getPopulationFilterAmount] */ /** Implemented by [PopulationManager.getPopulationFilterAmount][com.unciv.logic.city.PopulationManager.getPopulationFilterAmount] */
PopulationFilter("populationFilter", "Followers of this Religion", null, "Population Filters") { PopulationFilter("populationFilter", "Followers of this Religion", null, "Population Filters") {
private val knownValues = setOf("Population", "Specialists", "Unemployed", "Followers of the Majority Religion", "Followers of this Religion") private val knownValues = setOf("Population", "Specialists", "Unemployed", "Followers of the Majority Religion", "Followers of this Religion")

View File

@ -246,15 +246,13 @@ class DiplomacyScreen(
} }
diplomacyTable.row().padTop(15f) diplomacyTable.row().padTop(15f)
val eraInfo = viewingCiv.getEra()
var friendBonusText = "{When Friends:}\n".tr() var friendBonusText = "{When Friends:}\n".tr()
val friendBonusObjects = eraInfo.getCityStateBonuses(otherCiv.cityStateType, RelationshipLevel.Friend) val friendBonusObjects = viewingCiv.cityStateFunctions.getCityStateBonuses(otherCiv.cityStateType, RelationshipLevel.Friend)
val friendBonusStrings = getAdjustedBonuses(friendBonusObjects) val friendBonusStrings = getAdjustedBonuses(friendBonusObjects)
friendBonusText += friendBonusStrings.joinToString(separator = "\n") { it.tr() } friendBonusText += friendBonusStrings.joinToString(separator = "\n") { it.tr() }
var allyBonusText = "{When Allies:}\n".tr() var allyBonusText = "{When Allies:}\n".tr()
val allyBonusObjects = eraInfo.getCityStateBonuses(otherCiv.cityStateType, RelationshipLevel.Ally) val allyBonusObjects = viewingCiv.cityStateFunctions.getCityStateBonuses(otherCiv.cityStateType, RelationshipLevel.Ally)
val allyBonusStrings = getAdjustedBonuses(allyBonusObjects) val allyBonusStrings = getAdjustedBonuses(allyBonusObjects)
allyBonusText += allyBonusStrings.joinToString(separator = "\n") { it.tr() } allyBonusText += allyBonusStrings.joinToString(separator = "\n") { it.tr() }