From 1da5410324fe52970dd5dff7ccc358f15f1a5b3b Mon Sep 17 00:00:00 2001 From: yairm210 Date: Wed, 26 Jun 2024 18:38:02 +0300 Subject: [PATCH] Religion beliefs are private, uniques are cached --- .../civilization/ReligionAutomation.kt | 8 ++- core/src/com/unciv/logic/city/City.kt | 4 +- .../city/managers/CityReligionManager.kt | 4 +- .../unciv/logic/civilization/Civilization.kt | 7 +-- .../civilization/managers/ReligionManager.kt | 14 +---- .../transients/CivInfoStatsForNextTurn.kt | 32 ++++++------ core/src/com/unciv/models/Religion.kt | 51 ++++++++++++------- .../diplomacy/DiplomacyManagerTests.kt | 4 +- .../com/unciv/uniques/GlobalUniquesTests.kt | 8 +-- tests/src/com/unciv/uniques/ResourceTests.kt | 2 +- 10 files changed, 67 insertions(+), 67 deletions(-) diff --git a/core/src/com/unciv/logic/automation/civilization/ReligionAutomation.kt b/core/src/com/unciv/logic/automation/civilization/ReligionAutomation.kt index 0095b41104..61a81d11ba 100644 --- a/core/src/com/unciv/logic/automation/civilization/ReligionAutomation.kt +++ b/core/src/com/unciv/logic/automation/civilization/ReligionAutomation.kt @@ -339,16 +339,14 @@ object ReligionAutomation { else 1f UniqueType.BuyUnitsForAmountStat, UniqueType.BuyBuildingsForAmountStat -> if (civInfo.religionManager.religion != null - && civInfo.religionManager.religion!!.getFollowerUniques() - .any { it.type == unique.type } + && civInfo.religionManager.religion!!.followerBeliefUniqueMap.getUniques(unique.type).any() ) 0f // This is something completely different from the original, but I have no idea // what happens over there else civInfo.stats.statsForNextTurn[Stat.valueOf(unique.params[2])] * 5f / unique.params[1].toFloat() UniqueType.BuyUnitsWithStat, UniqueType.BuyBuildingsWithStat -> if (civInfo.religionManager.religion != null - && civInfo.religionManager.religion!!.getFollowerUniques() - .any { it.type == unique.type } + && civInfo.religionManager.religion!!.followerBeliefUniqueMap.getUniques(unique.type).any() ) 0f // This is something completely different from the original, but I have no idea // what happens over there @@ -473,7 +471,7 @@ object ReligionAutomation { && it.getMatchingUniques(UniqueType.OnlyAvailable, StateForConditionals.IgnoreConditionals) .none { unique -> !unique.conditionalsApply(civInfo) } } - .maxByOrNull { ReligionAutomation.rateBelief(civInfo, it) } + .maxByOrNull { rateBelief(civInfo, it) } } diff --git a/core/src/com/unciv/logic/city/City.kt b/core/src/com/unciv/logic/city/City.kt index e6dc57d223..ac3a9a7a3a 100644 --- a/core/src/com/unciv/logic/city/City.kt +++ b/core/src/com/unciv/logic/city/City.kt @@ -482,7 +482,7 @@ class City : IsPartOfGameInfoSerialization, INamed { getLocalMatchingUniques(uniqueType, stateForConditionals) else ( cityConstructions.builtBuildingUniqueMap.getUniques(uniqueType) - + religion.getUniques().filter { it.type == uniqueType } + + religion.getUniques(uniqueType) ).filter { !it.isTimedTriggerable && it.conditionalsApply(stateForConditionals) }.flatMap { it.getMultiplied(stateForConditionals) } @@ -491,7 +491,7 @@ class City : IsPartOfGameInfoSerialization, INamed { // Uniques special to this city fun getLocalMatchingUniques(uniqueType: UniqueType, stateForConditionals: StateForConditionals = StateForConditionals(this)): Sequence { val uniques = cityConstructions.builtBuildingUniqueMap.getUniques(uniqueType).filter { it.isLocalEffect } + - religion.getUniques().filter { it.type == uniqueType } + religion.getUniques(uniqueType) return if (uniques.any()) uniques.filter { !it.isTimedTriggerable && it.conditionalsApply(stateForConditionals) } .flatMap { it.getMultiplied(stateForConditionals) } else uniques diff --git a/core/src/com/unciv/logic/city/managers/CityReligionManager.kt b/core/src/com/unciv/logic/city/managers/CityReligionManager.kt index 46e24cfce6..9149888c0f 100644 --- a/core/src/com/unciv/logic/city/managers/CityReligionManager.kt +++ b/core/src/com/unciv/logic/city/managers/CityReligionManager.kt @@ -57,9 +57,9 @@ class CityReligionManager : IsPartOfGameInfoSerialization { getAffectedBySurroundingCities() } - fun getUniques(): Sequence { + fun getUniques(uniqueType: UniqueType): Sequence { val majorityReligion = getMajorityReligion() ?: return sequenceOf() - return majorityReligion.getFollowerUniques() + return majorityReligion.followerBeliefUniqueMap.getUniques(uniqueType) } diff --git a/core/src/com/unciv/logic/civilization/Civilization.kt b/core/src/com/unciv/logic/civilization/Civilization.kt index b9f9894f83..9545f9b1b2 100644 --- a/core/src/com/unciv/logic/civilization/Civilization.kt +++ b/core/src/com/unciv/logic/civilization/Civilization.kt @@ -514,8 +514,7 @@ class Civilization : IsPartOfGameInfoSerialization { yieldAll(getEra().getMatchingUniques(uniqueType, stateForConditionals)) yieldAll(cityStateFunctions.getUniquesProvidedByCityStates(uniqueType, stateForConditionals)) if (religionManager.religion != null) - yieldAll(religionManager.religion!!.getFounderUniques() - .filter { !it.isTimedTriggerable && it.type == uniqueType && it.conditionalsApply(stateForConditionals) }) + yieldAll(religionManager.religion!!.founderBeliefUniqueMap.getMatchingUniques(uniqueType, stateForConditionals)) yieldAll(getCivResourceSupply().asSequence() .filter { it.amount > 0 } @@ -534,9 +533,7 @@ class Civilization : IsPartOfGameInfoSerialization { .flatMap { city -> city.cityConstructions.builtBuildingUniqueMap.getTriggeredUniques(trigger, stateForConditionals) } ) if (religionManager.religion != null) - yieldAll(religionManager.religion!!.getFounderUniques() - .filter { unique -> unique.conditionals.any { it.type == trigger } - && unique.conditionalsApply(stateForConditionals) }) + yieldAll(religionManager.religion!!.founderBeliefUniqueMap.getMatchingUniques(trigger, stateForConditionals)) yieldAll(policies.policyUniques.getTriggeredUniques(trigger, stateForConditionals)) yieldAll(tech.techUniques.getTriggeredUniques(trigger, stateForConditionals)) yieldAll(getEra().uniqueMap.getTriggeredUniques (trigger, stateForConditionals)) diff --git a/core/src/com/unciv/logic/civilization/managers/ReligionManager.kt b/core/src/com/unciv/logic/civilization/managers/ReligionManager.kt index e212c19676..d5d2466139 100644 --- a/core/src/com/unciv/logic/civilization/managers/ReligionManager.kt +++ b/core/src/com/unciv/logic/civilization/managers/ReligionManager.kt @@ -375,16 +375,7 @@ class ReligionManager : IsPartOfGameInfoSerialization { if (religionState == ReligionState.None) foundPantheon(beliefs[0].name, useFreeBeliefs) // makes religion non-null // add beliefs (religion exists at this point) - religion!!.followerBeliefs.addAll( - beliefs - .filter { it.type == BeliefType.Pantheon || it.type == BeliefType.Follower } - .map { it.name } - ) - religion!!.founderBeliefs.addAll( - beliefs - .filter { it.type == BeliefType.Founder || it.type == BeliefType.Enhancer } - .map { it.name } - ) + religion!!.addBeliefs(beliefs) when (religionState) { ReligionState.None -> { @@ -423,8 +414,7 @@ class ReligionManager : IsPartOfGameInfoSerialization { val newReligion = Religion(name, civInfo.gameInfo, civInfo.civName) newReligion.displayName = displayName if (religion != null) { - newReligion.followerBeliefs.addAll(religion!!.followerBeliefs) - newReligion.founderBeliefs.addAll(religion!!.founderBeliefs) + newReligion.addBeliefs(religion!!.getAllBeliefsOrdered().asIterable()) } religion = newReligion diff --git a/core/src/com/unciv/logic/civilization/transients/CivInfoStatsForNextTurn.kt b/core/src/com/unciv/logic/civilization/transients/CivInfoStatsForNextTurn.kt index bb06d71270..7d9af70ea6 100644 --- a/core/src/com/unciv/logic/civilization/transients/CivInfoStatsForNextTurn.kt +++ b/core/src/com/unciv/logic/civilization/transients/CivInfoStatsForNextTurn.kt @@ -284,21 +284,23 @@ class CivInfoStatsForNextTurn(val civInfo: Civilization) { private fun getGlobalStatsFromUniques():StatMap { val statMap = StatMap() if (civInfo.religionManager.religion != null) { - for (unique in civInfo.religionManager.religion!!.getFounderUniques()) { - if (unique.type == UniqueType.StatsFromGlobalCitiesFollowingReligion) { - statMap.add( - "Religion", - unique.stats * civInfo.religionManager.numberOfCitiesFollowingThisReligion() - ) - } - if (unique.type == UniqueType.StatsFromGlobalFollowers) - statMap.add( - "Religion", - unique.stats * civInfo.religionManager.numberOfFollowersFollowingThisReligion( - unique.params[2] - ).toFloat() / unique.params[1].toFloat() - ) - } + for (unique in civInfo.religionManager.religion!!.founderBeliefUniqueMap.getMatchingUniques( + UniqueType.StatsFromGlobalCitiesFollowingReligion, StateForConditionals(civInfo) + )) + statMap.add( + "Religion", + unique.stats * civInfo.religionManager.numberOfCitiesFollowingThisReligion() + ) + + for (unique in civInfo.religionManager.religion!!.founderBeliefUniqueMap.getMatchingUniques( + UniqueType.StatsFromGlobalFollowers, StateForConditionals(civInfo) + )) + statMap.add( + "Religion", + unique.stats * civInfo.religionManager.numberOfFollowersFollowingThisReligion( + unique.params[2] + ).toFloat() / unique.params[1].toFloat() + ) } for (unique in civInfo.getMatchingUniques(UniqueType.StatsPerPolicies)) { diff --git a/core/src/com/unciv/models/Religion.kt b/core/src/com/unciv/models/Religion.kt index 3cf5ff7481..3b8643d204 100644 --- a/core/src/com/unciv/models/Religion.kt +++ b/core/src/com/unciv/models/Religion.kt @@ -4,7 +4,7 @@ import com.unciv.logic.GameInfo import com.unciv.logic.IsPartOfGameInfoSerialization import com.unciv.models.ruleset.Belief import com.unciv.models.ruleset.BeliefType -import com.unciv.models.ruleset.unique.Unique +import com.unciv.models.ruleset.unique.UniqueMap import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.stats.INamed @@ -15,8 +15,13 @@ class Religion() : INamed, IsPartOfGameInfoSerialization { var displayName: String? = null lateinit var foundingCivName: String - var founderBeliefs: HashSet = hashSetOf() - var followerBeliefs: HashSet = hashSetOf() + private var founderBeliefs: HashSet = hashSetOf() + private var followerBeliefs: HashSet = hashSetOf() + + @Transient + var founderBeliefUniqueMap = UniqueMap() + @Transient + var followerBeliefUniqueMap = UniqueMap() @Transient lateinit var gameInfo: GameInfo @@ -42,6 +47,23 @@ class Religion() : INamed, IsPartOfGameInfoSerialization { fun setTransients(gameInfo: GameInfo) { this.gameInfo = gameInfo + updateUniqueMaps() + } + + private fun updateUniqueMaps(){ + followerBeliefUniqueMap = UniqueMap(mapToExistingBeliefs(followerBeliefs).flatMap { it.uniqueObjects }) + founderBeliefUniqueMap = UniqueMap(mapToExistingBeliefs(founderBeliefs).flatMap { it.uniqueObjects }) + } + + fun addBeliefs(beliefs: Iterable){ + for (belief in beliefs){ + when (belief.type){ + BeliefType.Founder, BeliefType.Enhancer -> founderBeliefs.add(belief.name) + BeliefType.Pantheon, BeliefType.Follower -> followerBeliefs.add(belief.name) + else -> continue // 'None' and 'Any' are not valid for beliefs, they're used for internal purposes + } + } + updateUniqueMaps() } fun getIconName() = @@ -52,9 +74,9 @@ class Religion() : INamed, IsPartOfGameInfoSerialization { if (displayName != null) displayName!! else name - private fun mapToExistingBeliefs(beliefs: HashSet): List { + private fun mapToExistingBeliefs(beliefs: Set): Sequence { val rulesetBeliefs = gameInfo.ruleset.beliefs - return beliefs.mapNotNull { + return beliefs.asSequence().mapNotNull { if (it !in rulesetBeliefs) null else rulesetBeliefs[it]!! } @@ -62,7 +84,7 @@ class Religion() : INamed, IsPartOfGameInfoSerialization { fun getBeliefs(beliefType: BeliefType): Sequence { if (beliefType == BeliefType.Any) - return mapToExistingBeliefs((founderBeliefs + followerBeliefs).toHashSet()).asSequence() + return mapToExistingBeliefs((founderBeliefs + followerBeliefs).toHashSet()) val beliefs = when { @@ -72,25 +94,16 @@ class Religion() : INamed, IsPartOfGameInfoSerialization { } return mapToExistingBeliefs(beliefs) - .asSequence() .filter { it.type == beliefType } } fun getAllBeliefsOrdered(): Sequence { - return mapToExistingBeliefs(followerBeliefs).asSequence().filter { it.type == BeliefType.Pantheon } + - mapToExistingBeliefs(founderBeliefs).asSequence().filter { it.type == BeliefType.Founder } + - mapToExistingBeliefs(followerBeliefs).asSequence().filter { it.type == BeliefType.Follower } + - mapToExistingBeliefs(founderBeliefs).asSequence().filter { it.type == BeliefType.Enhancer } + return mapToExistingBeliefs(followerBeliefs).filter { it.type == BeliefType.Pantheon } + + mapToExistingBeliefs(founderBeliefs).filter { it.type == BeliefType.Founder } + + mapToExistingBeliefs(followerBeliefs).filter { it.type == BeliefType.Follower } + + mapToExistingBeliefs(founderBeliefs).filter { it.type == BeliefType.Enhancer } } - private fun getUniquesOfBeliefs(beliefs: HashSet): Sequence { - return mapToExistingBeliefs(beliefs).asSequence().flatMap { it.uniqueObjects } - } - - fun getFollowerUniques() = getUniquesOfBeliefs(followerBeliefs) - - fun getFounderUniques() = getUniquesOfBeliefs(founderBeliefs) - fun hasBelief(belief: String) = followerBeliefs.contains(belief) || founderBeliefs.contains(belief) fun isPantheon() = getBeliefs(BeliefType.Pantheon).any() && !isMajorReligion() diff --git a/tests/src/com/unciv/logic/civilization/diplomacy/DiplomacyManagerTests.kt b/tests/src/com/unciv/logic/civilization/diplomacy/DiplomacyManagerTests.kt index b69840f48c..683ee7f1ac 100644 --- a/tests/src/com/unciv/logic/civilization/diplomacy/DiplomacyManagerTests.kt +++ b/tests/src/com/unciv/logic/civilization/diplomacy/DiplomacyManagerTests.kt @@ -299,7 +299,7 @@ class DiplomacyManagerTests { val religion = testGame.addReligion(a) val belief = testGame.createBelief(BeliefType.Founder, "[+1 Food] from every [Shrine]") - religion.founderBeliefs.add(belief.name) + religion.addBeliefs(listOf(belief)) cityStateCapital.religion.addPressure(religion.name, 1000) cityState.getDiplomacyManager(a)!!.addInfluence(30f) @@ -340,7 +340,7 @@ class DiplomacyManagerTests { val religion = testGame.addReligion(a) val belief = testGame.createBelief(BeliefType.Founder, "[+1 Food] from every [Shrine]") - religion.founderBeliefs.add(belief.name) + religion.addBeliefs(listOf(belief)) cityStateCapital.religion.addPressure(religion.name, 1000) cityState.getDiplomacyManager(a)!!.addInfluence(-30f) diff --git a/tests/src/com/unciv/uniques/GlobalUniquesTests.kt b/tests/src/com/unciv/uniques/GlobalUniquesTests.kt index 7ced76fad9..3a3ab64a72 100644 --- a/tests/src/com/unciv/uniques/GlobalUniquesTests.kt +++ b/tests/src/com/unciv/uniques/GlobalUniquesTests.kt @@ -220,7 +220,7 @@ class GlobalUniquesTests { val civ1 = game.addCiv() val religion = game.addReligion(civ1) val belief = game.createBelief(BeliefType.Founder, "[+30 Science] for each global city following this religion") - religion.founderBeliefs.add(belief.name) + religion.addBeliefs(listOf(belief)) val civ2 = game.addCiv() val tile = game.getTile(Vector2.Zero) val cityOfCiv2 = game.addCity(civ2, tile, initialPopulation = 1) // Need someone to be converted @@ -238,7 +238,7 @@ class GlobalUniquesTests { val civ1 = game.addCiv() val religion = game.addReligion(civ1) val belief = game.createBelief(BeliefType.Founder, "[+42 Happiness] for each global city following this religion") - religion.founderBeliefs.add(belief.name) + religion.addBeliefs(listOf(belief)) val civ2 = game.addCiv() val tile = game.getTile(Vector2.Zero) val cityOfCiv2 = game.addCity(civ2, tile, initialPopulation = 1) // Need someone to be converted @@ -256,7 +256,7 @@ class GlobalUniquesTests { val civ1 = game.addCiv() val religion = game.addReligion(civ1) val belief = game.createBelief(BeliefType.Founder, "[+30 Science] from every [3] global followers [in all cities]") - religion.founderBeliefs.add(belief.name) + religion.addBeliefs(listOf(belief)) val civ2 = game.addCiv() val tile = game.getTile(Vector2.Zero) val cityOfCiv2 = game.addCity(civ2, tile, initialPopulation = 9) // Need people to be converted @@ -350,7 +350,7 @@ class GlobalUniquesTests { val city = game.addCity(civInfo, game.getTile(Vector2.Zero), true, 1) val religion = game.addReligion(civInfo) val belief = game.createBelief(BeliefType.Follower, "[+10]% [Faith] from every follower, up to [42]%") - religion.followerBeliefs.add(belief.name) + religion.addBeliefs(listOf(belief)) city.religion.addPressure(religion.name, 1000000000) diff --git a/tests/src/com/unciv/uniques/ResourceTests.kt b/tests/src/com/unciv/uniques/ResourceTests.kt index db6dd66180..153372b46e 100644 --- a/tests/src/com/unciv/uniques/ResourceTests.kt +++ b/tests/src/com/unciv/uniques/ResourceTests.kt @@ -240,7 +240,7 @@ class ResourceTests { // given val religion = game.addReligion(civInfo) val belief = game.createBelief(BeliefType.Follower, "Provides [1] [Iron]") - religion.followerBeliefs.add(belief.name) + religion.addBeliefs(listOf(belief)) city.population.setPopulation(1) city.religion.addPressure(religion.name, 1000) val otherCity = civInfo.addCity(Vector2(2f,2f)) // NOT religionized