mirror of
https://github.com/yairm210/Unciv.git
synced 2025-10-03 00:45:19 -04:00
Game can handle policies "disappearing" between mod versions
Added policy map to ruleset for simpler policy location
This commit is contained in:
parent
67bcc26ab7
commit
a8e0f270a0
@ -24,6 +24,7 @@ class UncivShowableException(missingMods: String) : Exception(missingMods)
|
||||
class GameInfo {
|
||||
@Transient
|
||||
lateinit var difficultyObject: Difficulty // Since this is static game-wide, and was taking a large part of nextTurn
|
||||
|
||||
@Transient
|
||||
lateinit var currentPlayerCiv: CivilizationInfo // this is called thousands of times, no reason to search for it with a find{} every time
|
||||
|
||||
@ -31,6 +32,7 @@ class GameInfo {
|
||||
* that is inconsistent with the saved game on the cloud */
|
||||
@Transient
|
||||
var isUpToDate = false
|
||||
|
||||
@Transient
|
||||
lateinit var ruleSet: Ruleset
|
||||
|
||||
@ -356,6 +358,9 @@ class GameInfo {
|
||||
for (tech in civinfo.tech.techsResearched.toList())
|
||||
if (!ruleSet.technologies.containsKey(tech))
|
||||
civinfo.tech.techsResearched.remove(tech)
|
||||
for (policy in civinfo.policies.adoptedPolicies.toList())
|
||||
if (!ruleSet.policies.containsKey(policy))
|
||||
civinfo.policies.adoptedPolicies.remove(policy)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,8 +65,7 @@ object NextTurnAutomation {
|
||||
if (TradeEvaluation().isTradeAcceptable(tradeLogic.currentTrade, civInfo, otherCiv)) {
|
||||
tradeLogic.acceptTrade()
|
||||
otherCiv.addNotification("[${civInfo.civName}] has accepted your trade request", Color.GOLD)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
otherCiv.addNotification("[${civInfo.civName}] has denied your trade request", Color.GOLD)
|
||||
}
|
||||
}
|
||||
@ -180,8 +179,7 @@ object NextTurnAutomation {
|
||||
private fun adoptPolicy(civInfo: CivilizationInfo) {
|
||||
while (civInfo.policies.canAdoptPolicy()) {
|
||||
|
||||
val adoptablePolicies = civInfo.gameInfo.ruleSet.policyBranches.values
|
||||
.flatMap { it.policies.union(listOf(it)) }
|
||||
val adoptablePolicies = civInfo.gameInfo.ruleSet.policies.values
|
||||
.filter { civInfo.policies.isAdoptable(it) }
|
||||
|
||||
// This can happen if the player is crazy enough to have the game continue forever and he disabled cultural victory
|
||||
@ -245,8 +243,10 @@ object NextTurnAutomation {
|
||||
// We should A. add some sort of timer (20? 30 turns?) between luxury trade requests if they're denied - see DeclinedLuxExchange
|
||||
// B. have a way for the AI to keep track of the "pending offers" - see DiplomacyManager.resourcesFromTrade
|
||||
|
||||
for (otherCiv in knownCivs.filter { it.isMajorCiv() && !it.isAtWarWith(civInfo)
|
||||
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedLuxExchange)}) {
|
||||
for (otherCiv in knownCivs.filter {
|
||||
it.isMajorCiv() && !it.isAtWarWith(civInfo)
|
||||
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedLuxExchange)
|
||||
}) {
|
||||
|
||||
val relationshipLevel = civInfo.getDiplomacyManager(otherCiv).relationshipLevel()
|
||||
if (relationshipLevel <= RelationshipLevel.Enemy)
|
||||
@ -263,11 +263,12 @@ object NextTurnAutomation {
|
||||
private fun offerDeclarationOfFriendship(civInfo: CivilizationInfo) {
|
||||
val civsThatWeCanDeclareFriendshipWith = civInfo.getKnownCivs()
|
||||
.asSequence()
|
||||
.filter { it.isMajorCiv() }
|
||||
.filter { !it.isAtWarWith(civInfo) }
|
||||
.filter { it.getDiplomacyManager(civInfo).relationshipLevel() > RelationshipLevel.Neutral }
|
||||
.filter { !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclarationOfFriendship) }
|
||||
.filter { !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.Denunceation) }
|
||||
.filter {
|
||||
it.isMajorCiv() && !it.isAtWarWith(civInfo)
|
||||
&& it.getDiplomacyManager(civInfo).relationshipLevel() > RelationshipLevel.Neutral
|
||||
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclarationOfFriendship)
|
||||
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.Denunceation)
|
||||
}
|
||||
.sortedByDescending { it.getDiplomacyManager(civInfo).relationshipLevel() }
|
||||
for (civ in civsThatWeCanDeclareFriendshipWith) {
|
||||
// Default setting is 5, this will be changed according to different civ.
|
||||
@ -281,8 +282,10 @@ object NextTurnAutomation {
|
||||
|
||||
val canSignResearchAgreementCiv = civInfo.getKnownCivs()
|
||||
.asSequence()
|
||||
.filter { civInfo.canSignResearchAgreementsWith(it)
|
||||
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedResearchAgreement) }
|
||||
.filter {
|
||||
civInfo.canSignResearchAgreementsWith(it)
|
||||
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedResearchAgreement)
|
||||
}
|
||||
.sortedByDescending { it.statsForNextTurn.science }
|
||||
|
||||
for (otherCiv in canSignResearchAgreementCiv) {
|
||||
@ -368,8 +371,10 @@ object NextTurnAutomation {
|
||||
|
||||
//evaluate war
|
||||
val enemyCivs = civInfo.getKnownCivs()
|
||||
.filterNot { it == civInfo || it.cities.isEmpty() || !civInfo.getDiplomacyManager(it).canDeclareWar()
|
||||
|| (it.cities.none { civInfo.exploredTiles.contains(it.location) }) }
|
||||
.filterNot {
|
||||
it == civInfo || it.cities.isEmpty() || !civInfo.getDiplomacyManager(it).canDeclareWar()
|
||||
|| (it.cities.none { civInfo.exploredTiles.contains(it.location) })
|
||||
}
|
||||
// If the AI declares war on a civ without knowing the location of any cities, it'll just keep amassing an army and not sending it anywhere,
|
||||
// and end up at a massive disadvantage
|
||||
|
||||
@ -521,7 +526,8 @@ object NextTurnAutomation {
|
||||
private fun onCitySettledNearBorders(civInfo: CivilizationInfo, otherCiv: CivilizationInfo) {
|
||||
val diplomacyManager = civInfo.getDiplomacyManager(otherCiv)
|
||||
when {
|
||||
diplomacyManager.hasFlag(DiplomacyFlags.IgnoreThemSettlingNearUs) -> {}
|
||||
diplomacyManager.hasFlag(DiplomacyFlags.IgnoreThemSettlingNearUs) -> {
|
||||
}
|
||||
diplomacyManager.hasFlag(DiplomacyFlags.AgreedToNotSettleNearUs) -> {
|
||||
otherCiv.popupAlerts.add(PopupAlert(AlertType.CitySettledNearOtherCivDespiteOurPromise, civInfo.civName))
|
||||
diplomacyManager.setFlag(DiplomacyFlags.IgnoreThemSettlingNearUs, 100)
|
||||
|
@ -1,10 +1,8 @@
|
||||
package com.unciv.logic.civilization
|
||||
|
||||
import com.unciv.Constants
|
||||
import com.unciv.models.ruleset.Policy
|
||||
import com.unciv.models.ruleset.UniqueMap
|
||||
import com.unciv.models.ruleset.UniqueTriggerActivation
|
||||
import com.unciv.models.ruleset.VictoryType
|
||||
import kotlin.math.min
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.roundToInt
|
||||
@ -12,10 +10,13 @@ import kotlin.math.roundToInt
|
||||
|
||||
class PolicyManager {
|
||||
|
||||
@Transient lateinit var civInfo: CivilizationInfo
|
||||
@Transient
|
||||
lateinit var civInfo: CivilizationInfo
|
||||
|
||||
// Needs to be separate from the actual adopted policies, so that
|
||||
// in different game versions, policies can have different effects
|
||||
@Transient internal val policyUniques = UniqueMap()
|
||||
@Transient
|
||||
internal val policyUniques = UniqueMap()
|
||||
|
||||
var freePolicies = 0
|
||||
var storedCulture = 0
|
||||
@ -38,7 +39,7 @@ class PolicyManager {
|
||||
return toReturn
|
||||
}
|
||||
|
||||
fun getPolicyByName(name:String): Policy = getAllPolicies().first { it.name==name }
|
||||
fun getPolicyByName(name: String): Policy = civInfo.gameInfo.ruleSet.policies[name]!!
|
||||
|
||||
fun setTransients() {
|
||||
for (policyName in adoptedPolicies)
|
||||
@ -50,9 +51,6 @@ class PolicyManager {
|
||||
policyUniques.addUnique(unique)
|
||||
}
|
||||
|
||||
private fun getAllPolicies() = civInfo.gameInfo.ruleSet.policyBranches.values.asSequence()
|
||||
.flatMap { it.policies.asSequence()+sequenceOf(it) }
|
||||
|
||||
fun startTurn() {
|
||||
tryAddLegalismBuildings()
|
||||
}
|
||||
@ -110,7 +108,7 @@ class PolicyManager {
|
||||
if (freePolicies == 0 && storedCulture < getCultureNeededForNextPolicy())
|
||||
return false
|
||||
|
||||
val hasAdoptablePolicies = getAllPolicies()
|
||||
val hasAdoptablePolicies = civInfo.gameInfo.ruleSet.policies.values
|
||||
.any { civInfo.policies.isAdoptable(it) }
|
||||
return hasAdoptablePolicies
|
||||
}
|
||||
@ -138,8 +136,6 @@ class PolicyManager {
|
||||
}
|
||||
}
|
||||
|
||||
val hasCapital = civInfo.cities.any { it.isCapital() }
|
||||
|
||||
for (unique in policy.uniqueObjects)
|
||||
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo)
|
||||
|
||||
@ -160,8 +156,10 @@ class PolicyManager {
|
||||
val candidateCities = civInfo.cities
|
||||
.sortedBy { it.turnAcquired }
|
||||
.subList(0, min(4, civInfo.cities.size))
|
||||
.filter { it.id !in legalismState
|
||||
&& it.cityConstructions.hasBuildableCultureBuilding() }
|
||||
.filter {
|
||||
it.id !in legalismState
|
||||
&& it.cityConstructions.hasBuildableCultureBuilding()
|
||||
}
|
||||
for (city in candidateCities) {
|
||||
val builtBuilding = city.cityConstructions.addCultureBuilding()
|
||||
legalismState[city.id] = builtBuilding!!
|
||||
|
@ -51,6 +51,7 @@ class Ruleset {
|
||||
val quests = LinkedHashMap<String, Quest>()
|
||||
val specialists = LinkedHashMap<String, Specialist>()
|
||||
val policyBranches = LinkedHashMap<String, PolicyBranch>()
|
||||
val policies = LinkedHashMap<String, Policy>()
|
||||
val difficulties = LinkedHashMap<String, Difficulty>()
|
||||
val mods = LinkedHashSet<String>()
|
||||
var modOptions = ModOptions()
|
||||
@ -74,6 +75,7 @@ class Ruleset {
|
||||
difficulties.putAll(ruleset.difficulties)
|
||||
nations.putAll(ruleset.nations)
|
||||
policyBranches.putAll(ruleset.policyBranches)
|
||||
policies.putAll(ruleset.policies)
|
||||
quests.putAll(ruleset.quests)
|
||||
specialists.putAll(ruleset.specialists)
|
||||
technologies.putAll(ruleset.technologies)
|
||||
@ -93,6 +95,7 @@ class Ruleset {
|
||||
difficulties.clear()
|
||||
nations.clear()
|
||||
policyBranches.clear()
|
||||
policies.clear()
|
||||
quests.clear()
|
||||
technologies.clear()
|
||||
buildings.clear()
|
||||
@ -159,9 +162,11 @@ class Ruleset {
|
||||
for (branch in policyBranches.values) {
|
||||
branch.requires = ArrayList()
|
||||
branch.branch = branch
|
||||
policies[branch.name] = branch
|
||||
for (policy in branch.policies) {
|
||||
policy.branch = branch
|
||||
if (policy.requires == null) policy.requires = arrayListOf(branch.name)
|
||||
policies[policy.name] = policy
|
||||
}
|
||||
branch.policies.last().name = branch.name + " Complete"
|
||||
}
|
||||
|
@ -25,15 +25,14 @@ class PolicyPickerScreen(val worldScreen: WorldScreen, civInfo: CivilizationInfo
|
||||
|
||||
rightSideButton.setText("{Adopt policy}\r\n(".tr() + policies.storedCulture + "/" + policies.getCultureNeededForNextPolicy() + ")")
|
||||
|
||||
if (viewingCiv.gameInfo.ruleSet.policyBranches.values.flatMap { it.policies }.all { it.name in policies.adoptedPolicies})
|
||||
if (viewingCiv.gameInfo.ruleSet.policies.values.all { it.name in policies.adoptedPolicies })
|
||||
rightSideButton.setText("All policies adopted".tr())
|
||||
|
||||
setDefaultCloseAction()
|
||||
if (policies.freePolicies > 0) {
|
||||
rightSideButton.setText("Adopt free policy".tr())
|
||||
if (policies.canAdoptPolicy()) closeButton.disable()
|
||||
}
|
||||
else onBackButtonClicked { UncivGame.Current.setWorldScreen() }
|
||||
} else onBackButtonClicked { UncivGame.Current.setWorldScreen() }
|
||||
|
||||
rightSideButton.onClick(UncivSound.Policy) {
|
||||
viewingCiv.policies.adopt(pickedPolicy!!)
|
||||
@ -42,8 +41,7 @@ class PolicyPickerScreen(val worldScreen: WorldScreen, civInfo: CivilizationInfo
|
||||
if (game.screen !is PolicyPickerScreen || !policies.canAdoptPolicy()) {
|
||||
game.setWorldScreen()
|
||||
dispose()
|
||||
}
|
||||
else game.setScreen(PolicyPickerScreen(worldScreen)) // update policies
|
||||
} else game.setScreen(PolicyPickerScreen(worldScreen)) // update policies
|
||||
}
|
||||
|
||||
if (!UncivGame.Current.worldScreen.canChangeState)
|
||||
|
Loading…
x
Reference in New Issue
Block a user