mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-30 23:41:03 -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 {
|
class GameInfo {
|
||||||
@Transient
|
@Transient
|
||||||
lateinit var difficultyObject: Difficulty // Since this is static game-wide, and was taking a large part of nextTurn
|
lateinit var difficultyObject: Difficulty // Since this is static game-wide, and was taking a large part of nextTurn
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
lateinit var currentPlayerCiv: CivilizationInfo // this is called thousands of times, no reason to search for it with a find{} every time
|
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 */
|
* that is inconsistent with the saved game on the cloud */
|
||||||
@Transient
|
@Transient
|
||||||
var isUpToDate = false
|
var isUpToDate = false
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
lateinit var ruleSet: Ruleset
|
lateinit var ruleSet: Ruleset
|
||||||
|
|
||||||
@ -356,6 +358,9 @@ class GameInfo {
|
|||||||
for (tech in civinfo.tech.techsResearched.toList())
|
for (tech in civinfo.tech.techsResearched.toList())
|
||||||
if (!ruleSet.technologies.containsKey(tech))
|
if (!ruleSet.technologies.containsKey(tech))
|
||||||
civinfo.tech.techsResearched.remove(tech)
|
civinfo.tech.techsResearched.remove(tech)
|
||||||
|
for (policy in civinfo.policies.adoptedPolicies.toList())
|
||||||
|
if (!ruleSet.policies.containsKey(policy))
|
||||||
|
civinfo.policies.adoptedPolicies.remove(policy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,8 +27,8 @@ object NextTurnAutomation {
|
|||||||
respondToPopupAlerts(civInfo)
|
respondToPopupAlerts(civInfo)
|
||||||
respondToTradeRequests(civInfo)
|
respondToTradeRequests(civInfo)
|
||||||
|
|
||||||
if(civInfo.isMajorCiv()) {
|
if (civInfo.isMajorCiv()) {
|
||||||
if(!civInfo.gameInfo.ruleSet.modOptions.uniques.contains(ModOptionsConstants.diplomaticRelationshipsCannotChange)) {
|
if (!civInfo.gameInfo.ruleSet.modOptions.uniques.contains(ModOptionsConstants.diplomaticRelationshipsCannotChange)) {
|
||||||
declareWar(civInfo)
|
declareWar(civInfo)
|
||||||
offerPeaceTreaty(civInfo)
|
offerPeaceTreaty(civInfo)
|
||||||
// offerDeclarationOfFriendship(civInfo)
|
// offerDeclarationOfFriendship(civInfo)
|
||||||
@ -52,7 +52,7 @@ object NextTurnAutomation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun respondToTradeRequests(civInfo: CivilizationInfo) {
|
private fun respondToTradeRequests(civInfo: CivilizationInfo) {
|
||||||
for(tradeRequest in civInfo.tradeRequests.toList()){
|
for (tradeRequest in civInfo.tradeRequests.toList()) {
|
||||||
val otherCiv = civInfo.gameInfo.getCivilization(tradeRequest.requestingCiv)
|
val otherCiv = civInfo.gameInfo.getCivilization(tradeRequest.requestingCiv)
|
||||||
val tradeLogic = TradeLogic(civInfo, otherCiv)
|
val tradeLogic = TradeLogic(civInfo, otherCiv)
|
||||||
tradeLogic.currentTrade.set(tradeRequest.trade)
|
tradeLogic.currentTrade.set(tradeRequest.trade)
|
||||||
@ -62,11 +62,10 @@ object NextTurnAutomation {
|
|||||||
* the same resource to ANOTHER civ in this turn. Complicated!
|
* the same resource to ANOTHER civ in this turn. Complicated!
|
||||||
*/
|
*/
|
||||||
civInfo.tradeRequests.remove(tradeRequest)
|
civInfo.tradeRequests.remove(tradeRequest)
|
||||||
if(TradeEvaluation().isTradeAcceptable(tradeLogic.currentTrade,civInfo,otherCiv)){
|
if (TradeEvaluation().isTradeAcceptable(tradeLogic.currentTrade, civInfo, otherCiv)) {
|
||||||
tradeLogic.acceptTrade()
|
tradeLogic.acceptTrade()
|
||||||
otherCiv.addNotification("[${civInfo.civName}] has accepted your trade request", Color.GOLD)
|
otherCiv.addNotification("[${civInfo.civName}] has accepted your trade request", Color.GOLD)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
otherCiv.addNotification("[${civInfo.civName}] has denied your trade request", Color.GOLD)
|
otherCiv.addNotification("[${civInfo.civName}] has denied your trade request", Color.GOLD)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,7 +73,7 @@ object NextTurnAutomation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun respondToPopupAlerts(civInfo: CivilizationInfo) {
|
private fun respondToPopupAlerts(civInfo: CivilizationInfo) {
|
||||||
for(popupAlert in civInfo.popupAlerts) {
|
for (popupAlert in civInfo.popupAlerts) {
|
||||||
if (popupAlert.type == AlertType.DemandToStopSettlingCitiesNear) { // we're called upon to make a decision
|
if (popupAlert.type == AlertType.DemandToStopSettlingCitiesNear) { // we're called upon to make a decision
|
||||||
val demandingCiv = civInfo.gameInfo.getCivilization(popupAlert.value)
|
val demandingCiv = civInfo.gameInfo.getCivilization(popupAlert.value)
|
||||||
val diploManager = civInfo.getDiplomacyManager(demandingCiv)
|
val diploManager = civInfo.getDiplomacyManager(demandingCiv)
|
||||||
@ -96,7 +95,7 @@ object NextTurnAutomation {
|
|||||||
civInfo.popupAlerts.clear() // AIs don't care about popups.
|
civInfo.popupAlerts.clear() // AIs don't care about popups.
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun tryGainInfluence(civInfo: CivilizationInfo, cityState:CivilizationInfo) {
|
private fun tryGainInfluence(civInfo: CivilizationInfo, cityState: CivilizationInfo) {
|
||||||
if (civInfo.gold < 250) return // save up
|
if (civInfo.gold < 250) return // save up
|
||||||
if (cityState.getDiplomacyManager(civInfo).influence < 20) {
|
if (cityState.getDiplomacyManager(civInfo).influence < 20) {
|
||||||
civInfo.giveGoldGift(cityState, 250)
|
civInfo.giveGoldGift(cityState, 250)
|
||||||
@ -180,8 +179,7 @@ object NextTurnAutomation {
|
|||||||
private fun adoptPolicy(civInfo: CivilizationInfo) {
|
private fun adoptPolicy(civInfo: CivilizationInfo) {
|
||||||
while (civInfo.policies.canAdoptPolicy()) {
|
while (civInfo.policies.canAdoptPolicy()) {
|
||||||
|
|
||||||
val adoptablePolicies = civInfo.gameInfo.ruleSet.policyBranches.values
|
val adoptablePolicies = civInfo.gameInfo.ruleSet.policies.values
|
||||||
.flatMap { it.policies.union(listOf(it)) }
|
|
||||||
.filter { civInfo.policies.isAdoptable(it) }
|
.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
|
// This can happen if the player is crazy enough to have the game continue forever and he disabled cultural victory
|
||||||
@ -209,7 +207,7 @@ object NextTurnAutomation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun potentialLuxuryTrades(civInfo:CivilizationInfo, otherCivInfo:CivilizationInfo): ArrayList<Trade> {
|
private fun potentialLuxuryTrades(civInfo: CivilizationInfo, otherCivInfo: CivilizationInfo): ArrayList<Trade> {
|
||||||
val tradeLogic = TradeLogic(civInfo, otherCivInfo)
|
val tradeLogic = TradeLogic(civInfo, otherCivInfo)
|
||||||
val ourTradableLuxuryResources = tradeLogic.ourAvailableOffers
|
val ourTradableLuxuryResources = tradeLogic.ourAvailableOffers
|
||||||
.filter { it.type == TradeType.Luxury_Resource && it.amount > 1 }
|
.filter { it.type == TradeType.Luxury_Resource && it.amount > 1 }
|
||||||
@ -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
|
// 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
|
// 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)
|
for (otherCiv in knownCivs.filter {
|
||||||
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedLuxExchange)}) {
|
it.isMajorCiv() && !it.isAtWarWith(civInfo)
|
||||||
|
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedLuxExchange)
|
||||||
|
}) {
|
||||||
|
|
||||||
val relationshipLevel = civInfo.getDiplomacyManager(otherCiv).relationshipLevel()
|
val relationshipLevel = civInfo.getDiplomacyManager(otherCiv).relationshipLevel()
|
||||||
if (relationshipLevel <= RelationshipLevel.Enemy)
|
if (relationshipLevel <= RelationshipLevel.Enemy)
|
||||||
@ -263,11 +263,12 @@ object NextTurnAutomation {
|
|||||||
private fun offerDeclarationOfFriendship(civInfo: CivilizationInfo) {
|
private fun offerDeclarationOfFriendship(civInfo: CivilizationInfo) {
|
||||||
val civsThatWeCanDeclareFriendshipWith = civInfo.getKnownCivs()
|
val civsThatWeCanDeclareFriendshipWith = civInfo.getKnownCivs()
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.filter { it.isMajorCiv() }
|
.filter {
|
||||||
.filter { !it.isAtWarWith(civInfo) }
|
it.isMajorCiv() && !it.isAtWarWith(civInfo)
|
||||||
.filter { it.getDiplomacyManager(civInfo).relationshipLevel() > RelationshipLevel.Neutral }
|
&& it.getDiplomacyManager(civInfo).relationshipLevel() > RelationshipLevel.Neutral
|
||||||
.filter { !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclarationOfFriendship) }
|
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclarationOfFriendship)
|
||||||
.filter { !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.Denunceation) }
|
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.Denunceation)
|
||||||
|
}
|
||||||
.sortedByDescending { it.getDiplomacyManager(civInfo).relationshipLevel() }
|
.sortedByDescending { it.getDiplomacyManager(civInfo).relationshipLevel() }
|
||||||
for (civ in civsThatWeCanDeclareFriendshipWith) {
|
for (civ in civsThatWeCanDeclareFriendshipWith) {
|
||||||
// Default setting is 5, this will be changed according to different civ.
|
// Default setting is 5, this will be changed according to different civ.
|
||||||
@ -281,8 +282,10 @@ object NextTurnAutomation {
|
|||||||
|
|
||||||
val canSignResearchAgreementCiv = civInfo.getKnownCivs()
|
val canSignResearchAgreementCiv = civInfo.getKnownCivs()
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.filter { civInfo.canSignResearchAgreementsWith(it)
|
.filter {
|
||||||
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedResearchAgreement) }
|
civInfo.canSignResearchAgreementsWith(it)
|
||||||
|
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedResearchAgreement)
|
||||||
|
}
|
||||||
.sortedByDescending { it.statsForNextTurn.science }
|
.sortedByDescending { it.statsForNextTurn.science }
|
||||||
|
|
||||||
for (otherCiv in canSignResearchAgreementCiv) {
|
for (otherCiv in canSignResearchAgreementCiv) {
|
||||||
@ -306,13 +309,13 @@ object NextTurnAutomation {
|
|||||||
.filterNot { it == civInfo || it.isBarbarian() || it.cities.isEmpty() }
|
.filterNot { it == civInfo || it.isBarbarian() || it.cities.isEmpty() }
|
||||||
.filter { !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedPeace) }
|
.filter { !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclinedPeace) }
|
||||||
// Don't allow AIs to offer peace to ity states allied with their enemies
|
// Don't allow AIs to offer peace to ity states allied with their enemies
|
||||||
.filterNot { it.isCityState() && it.getAllyCiv()!="" && civInfo.isAtWarWith(civInfo.gameInfo.getCivilization(it.getAllyCiv())) }
|
.filterNot { it.isCityState() && it.getAllyCiv() != "" && civInfo.isAtWarWith(civInfo.gameInfo.getCivilization(it.getAllyCiv())) }
|
||||||
|
|
||||||
for (enemy in enemiesCiv) {
|
for (enemy in enemiesCiv) {
|
||||||
val enemiesStrength = Automation.evaluteCombatStrength(enemy)
|
val enemiesStrength = Automation.evaluteCombatStrength(enemy)
|
||||||
|
|
||||||
// If we don't have an unobstructed path to the enemy, offer peace even though we can beat them
|
// If we don't have an unobstructed path to the enemy, offer peace even though we can beat them
|
||||||
val canReachEnemy = BFS(civInfo.getCapital().getCenterTile()){ it.canCivEnter(civInfo) }
|
val canReachEnemy = BFS(civInfo.getCapital().getCenterTile()) { it.canCivEnter(civInfo) }
|
||||||
canReachEnemy.stepToEnd()
|
canReachEnemy.stepToEnd()
|
||||||
|
|
||||||
if (enemy.cities.any { canReachEnemy.hasReachedTile(it.getCenterTile()) }
|
if (enemy.cities.any { canReachEnemy.hasReachedTile(it.getCenterTile()) }
|
||||||
@ -368,8 +371,10 @@ object NextTurnAutomation {
|
|||||||
|
|
||||||
//evaluate war
|
//evaluate war
|
||||||
val enemyCivs = civInfo.getKnownCivs()
|
val enemyCivs = civInfo.getKnownCivs()
|
||||||
.filterNot { it == civInfo || it.cities.isEmpty() || !civInfo.getDiplomacyManager(it).canDeclareWar()
|
.filterNot {
|
||||||
|| (it.cities.none { civInfo.exploredTiles.contains(it.location) }) }
|
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,
|
// 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
|
// and end up at a massive disadvantage
|
||||||
|
|
||||||
@ -383,7 +388,7 @@ object NextTurnAutomation {
|
|||||||
civInfo.getDiplomacyManager(civWithBestMotivationToAttack.first).declareWar()
|
civInfo.getDiplomacyManager(civWithBestMotivationToAttack.first).declareWar()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun motivationToAttack(civInfo:CivilizationInfo, otherCiv:CivilizationInfo): Int {
|
private fun motivationToAttack(civInfo: CivilizationInfo, otherCiv: CivilizationInfo): Int {
|
||||||
val ourCombatStrength = Automation.evaluteCombatStrength(civInfo).toFloat()
|
val ourCombatStrength = Automation.evaluteCombatStrength(civInfo).toFloat()
|
||||||
val theirCombatStrength = Automation.evaluteCombatStrength(otherCiv)
|
val theirCombatStrength = Automation.evaluteCombatStrength(otherCiv)
|
||||||
if (theirCombatStrength > ourCombatStrength) return 0
|
if (theirCombatStrength > ourCombatStrength) return 0
|
||||||
@ -417,13 +422,13 @@ object NextTurnAutomation {
|
|||||||
modifierMap["No land path"] = -10
|
modifierMap["No land path"] = -10
|
||||||
|
|
||||||
val diplomacyManager = civInfo.getDiplomacyManager(otherCiv)
|
val diplomacyManager = civInfo.getDiplomacyManager(otherCiv)
|
||||||
if(diplomacyManager.hasFlag(DiplomacyFlags.ResearchAgreement))
|
if (diplomacyManager.hasFlag(DiplomacyFlags.ResearchAgreement))
|
||||||
modifierMap["Research Agreement"] = -5
|
modifierMap["Research Agreement"] = -5
|
||||||
|
|
||||||
if(diplomacyManager.hasFlag(DiplomacyFlags.DeclarationOfFriendship))
|
if (diplomacyManager.hasFlag(DiplomacyFlags.DeclarationOfFriendship))
|
||||||
modifierMap["Declaration of Friendship"] = -10
|
modifierMap["Declaration of Friendship"] = -10
|
||||||
|
|
||||||
val relationshipModifier = when(diplomacyManager.relationshipLevel()){
|
val relationshipModifier = when (diplomacyManager.relationshipLevel()) {
|
||||||
RelationshipLevel.Unforgivable -> 10
|
RelationshipLevel.Unforgivable -> 10
|
||||||
RelationshipLevel.Enemy -> 5
|
RelationshipLevel.Enemy -> 5
|
||||||
RelationshipLevel.Ally -> -5 // this is so that ally + DoF is not too unbalanced -
|
RelationshipLevel.Ally -> -5 // this is so that ally + DoF is not too unbalanced -
|
||||||
@ -432,10 +437,10 @@ object NextTurnAutomation {
|
|||||||
}
|
}
|
||||||
modifierMap["Relationship"] = relationshipModifier
|
modifierMap["Relationship"] = relationshipModifier
|
||||||
|
|
||||||
if(diplomacyManager.resourcesFromTrade().any { it.amount > 0 })
|
if (diplomacyManager.resourcesFromTrade().any { it.amount > 0 })
|
||||||
modifierMap["Receiving trade resources"] = -5
|
modifierMap["Receiving trade resources"] = -5
|
||||||
|
|
||||||
if(theirCity.getTiles().none { it.neighbors.any { it.getOwner()==theirCity.civInfo && it.getCity() != theirCity } })
|
if (theirCity.getTiles().none { it.neighbors.any { it.getOwner() == theirCity.civInfo && it.getCity() != theirCity } })
|
||||||
modifierMap["Isolated city"] = 15
|
modifierMap["Isolated city"] = 15
|
||||||
|
|
||||||
return modifierMap.values.sum()
|
return modifierMap.values.sum()
|
||||||
@ -518,18 +523,19 @@ object NextTurnAutomation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onCitySettledNearBorders(civInfo: CivilizationInfo, otherCiv:CivilizationInfo){
|
private fun onCitySettledNearBorders(civInfo: CivilizationInfo, otherCiv: CivilizationInfo) {
|
||||||
val diplomacyManager = civInfo.getDiplomacyManager(otherCiv)
|
val diplomacyManager = civInfo.getDiplomacyManager(otherCiv)
|
||||||
when {
|
when {
|
||||||
diplomacyManager.hasFlag(DiplomacyFlags.IgnoreThemSettlingNearUs) -> {}
|
diplomacyManager.hasFlag(DiplomacyFlags.IgnoreThemSettlingNearUs) -> {
|
||||||
|
}
|
||||||
diplomacyManager.hasFlag(DiplomacyFlags.AgreedToNotSettleNearUs) -> {
|
diplomacyManager.hasFlag(DiplomacyFlags.AgreedToNotSettleNearUs) -> {
|
||||||
otherCiv.popupAlerts.add(PopupAlert(AlertType.CitySettledNearOtherCivDespiteOurPromise, civInfo.civName))
|
otherCiv.popupAlerts.add(PopupAlert(AlertType.CitySettledNearOtherCivDespiteOurPromise, civInfo.civName))
|
||||||
diplomacyManager.setFlag(DiplomacyFlags.IgnoreThemSettlingNearUs,100)
|
diplomacyManager.setFlag(DiplomacyFlags.IgnoreThemSettlingNearUs, 100)
|
||||||
diplomacyManager.setModifier(DiplomaticModifiers.BetrayedPromiseToNotSettleCitiesNearUs,-20f)
|
diplomacyManager.setModifier(DiplomaticModifiers.BetrayedPromiseToNotSettleCitiesNearUs, -20f)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val threatLevel = Automation.threatAssessment(civInfo,otherCiv)
|
val threatLevel = Automation.threatAssessment(civInfo, otherCiv)
|
||||||
if(threatLevel<ThreatLevel.High) // don't piss them off for no reason please.
|
if (threatLevel < ThreatLevel.High) // don't piss them off for no reason please.
|
||||||
otherCiv.popupAlerts.add(PopupAlert(AlertType.DemandToStopSettlingCitiesNear, civInfo.civName))
|
otherCiv.popupAlerts.add(PopupAlert(AlertType.DemandToStopSettlingCitiesNear, civInfo.civName))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -537,10 +543,10 @@ object NextTurnAutomation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getMinDistanceBetweenCities(civ1: CivilizationInfo, civ2: CivilizationInfo): Int {
|
fun getMinDistanceBetweenCities(civ1: CivilizationInfo, civ2: CivilizationInfo): Int {
|
||||||
return getClosestCities(civ1,civ2).aerialDistance
|
return getClosestCities(civ1, civ2).aerialDistance
|
||||||
}
|
}
|
||||||
|
|
||||||
data class CityDistance(val city1:CityInfo, val city2:CityInfo, val aerialDistance: Int)
|
data class CityDistance(val city1: CityInfo, val city2: CityInfo, val aerialDistance: Int)
|
||||||
|
|
||||||
fun getClosestCities(civ1: CivilizationInfo, civ2: CivilizationInfo): CityDistance {
|
fun getClosestCities(civ1: CivilizationInfo, civ2: CivilizationInfo): CityDistance {
|
||||||
val cityDistances = arrayListOf<CityDistance>()
|
val cityDistances = arrayListOf<CityDistance>()
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package com.unciv.logic.civilization
|
package com.unciv.logic.civilization
|
||||||
|
|
||||||
import com.unciv.Constants
|
|
||||||
import com.unciv.models.ruleset.Policy
|
import com.unciv.models.ruleset.Policy
|
||||||
import com.unciv.models.ruleset.UniqueMap
|
import com.unciv.models.ruleset.UniqueMap
|
||||||
import com.unciv.models.ruleset.UniqueTriggerActivation
|
import com.unciv.models.ruleset.UniqueTriggerActivation
|
||||||
import com.unciv.models.ruleset.VictoryType
|
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
@ -12,10 +10,13 @@ import kotlin.math.roundToInt
|
|||||||
|
|
||||||
class PolicyManager {
|
class PolicyManager {
|
||||||
|
|
||||||
@Transient lateinit var civInfo: CivilizationInfo
|
@Transient
|
||||||
|
lateinit var civInfo: CivilizationInfo
|
||||||
|
|
||||||
// Needs to be separate from the actual adopted policies, so that
|
// Needs to be separate from the actual adopted policies, so that
|
||||||
// in different game versions, policies can have different effects
|
// in different game versions, policies can have different effects
|
||||||
@Transient internal val policyUniques = UniqueMap()
|
@Transient
|
||||||
|
internal val policyUniques = UniqueMap()
|
||||||
|
|
||||||
var freePolicies = 0
|
var freePolicies = 0
|
||||||
var storedCulture = 0
|
var storedCulture = 0
|
||||||
@ -38,26 +39,23 @@ class PolicyManager {
|
|||||||
return toReturn
|
return toReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPolicyByName(name:String): Policy = getAllPolicies().first { it.name==name }
|
fun getPolicyByName(name: String): Policy = civInfo.gameInfo.ruleSet.policies[name]!!
|
||||||
|
|
||||||
fun setTransients() {
|
fun setTransients() {
|
||||||
for (policyName in adoptedPolicies)
|
for (policyName in adoptedPolicies)
|
||||||
addPolicyToTransients(getPolicyByName(policyName))
|
addPolicyToTransients(getPolicyByName(policyName))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addPolicyToTransients(policy: Policy){
|
fun addPolicyToTransients(policy: Policy) {
|
||||||
for(unique in policy.uniqueObjects)
|
for (unique in policy.uniqueObjects)
|
||||||
policyUniques.addUnique(unique)
|
policyUniques.addUnique(unique)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getAllPolicies() = civInfo.gameInfo.ruleSet.policyBranches.values.asSequence()
|
|
||||||
.flatMap { it.policies.asSequence()+sequenceOf(it) }
|
|
||||||
|
|
||||||
fun startTurn() {
|
fun startTurn() {
|
||||||
tryAddLegalismBuildings()
|
tryAddLegalismBuildings()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addCulture(culture: Int){
|
fun addCulture(culture: Int) {
|
||||||
val couldAdoptPolicyBefore = canAdoptPolicy()
|
val couldAdoptPolicyBefore = canAdoptPolicy()
|
||||||
storedCulture += culture
|
storedCulture += culture
|
||||||
if (!couldAdoptPolicyBefore && canAdoptPolicy())
|
if (!couldAdoptPolicyBefore && canAdoptPolicy())
|
||||||
@ -80,7 +78,7 @@ class PolicyManager {
|
|||||||
// Use "Culture cost of adopting new Policies reduced by [10]%" and "Each city founded increases culture cost of policies [33]% less than normal" instead
|
// Use "Culture cost of adopting new Policies reduced by [10]%" and "Each city founded increases culture cost of policies [33]% less than normal" instead
|
||||||
if (civInfo.hasUnique("Each city founded increases culture cost of policies 33% less than normal"))
|
if (civInfo.hasUnique("Each city founded increases culture cost of policies 33% less than normal"))
|
||||||
cityModifier *= (2 / 3f)
|
cityModifier *= (2 / 3f)
|
||||||
for(unique in civInfo.getMatchingUniques("Culture cost of adopting new Policies reduced by 10%"))
|
for (unique in civInfo.getMatchingUniques("Culture cost of adopting new Policies reduced by 10%"))
|
||||||
policyCultureCost *= 0.9
|
policyCultureCost *= 0.9
|
||||||
|
|
||||||
for (unique in civInfo.getMatchingUniques("Each city founded increases culture cost of policies []% less than normal"))
|
for (unique in civInfo.getMatchingUniques("Each city founded increases culture cost of policies []% less than normal"))
|
||||||
@ -99,7 +97,7 @@ class PolicyManager {
|
|||||||
fun isAdopted(policyName: String): Boolean = adoptedPolicies.contains(policyName)
|
fun isAdopted(policyName: String): Boolean = adoptedPolicies.contains(policyName)
|
||||||
|
|
||||||
fun isAdoptable(policy: Policy): Boolean {
|
fun isAdoptable(policy: Policy): Boolean {
|
||||||
if(isAdopted(policy.name)) return false
|
if (isAdopted(policy.name)) return false
|
||||||
if (policy.name.endsWith("Complete")) return false
|
if (policy.name.endsWith("Complete")) return false
|
||||||
if (!getAdoptedPolicies().containsAll(policy.requires!!)) return false
|
if (!getAdoptedPolicies().containsAll(policy.requires!!)) return false
|
||||||
if (civInfo.gameInfo.ruleSet.getEraNumber(policy.branch.era) > civInfo.getEraNumber()) return false
|
if (civInfo.gameInfo.ruleSet.getEraNumber(policy.branch.era) > civInfo.getEraNumber()) return false
|
||||||
@ -110,7 +108,7 @@ class PolicyManager {
|
|||||||
if (freePolicies == 0 && storedCulture < getCultureNeededForNextPolicy())
|
if (freePolicies == 0 && storedCulture < getCultureNeededForNextPolicy())
|
||||||
return false
|
return false
|
||||||
|
|
||||||
val hasAdoptablePolicies = getAllPolicies()
|
val hasAdoptablePolicies = civInfo.gameInfo.ruleSet.policies.values
|
||||||
.any { civInfo.policies.isAdoptable(it) }
|
.any { civInfo.policies.isAdoptable(it) }
|
||||||
return hasAdoptablePolicies
|
return hasAdoptablePolicies
|
||||||
}
|
}
|
||||||
@ -138,8 +136,6 @@ class PolicyManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val hasCapital = civInfo.cities.any { it.isCapital() }
|
|
||||||
|
|
||||||
for (unique in policy.uniqueObjects)
|
for (unique in policy.uniqueObjects)
|
||||||
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo)
|
UniqueTriggerActivation.triggerCivwideUnique(unique, civInfo)
|
||||||
|
|
||||||
@ -153,15 +149,17 @@ class PolicyManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun tryAddLegalismBuildings() {
|
fun tryAddLegalismBuildings() {
|
||||||
if(!civInfo.hasUnique("Immediately creates a cheapest available cultural building in each of your first 4 cities for free"))
|
if (!civInfo.hasUnique("Immediately creates a cheapest available cultural building in each of your first 4 cities for free"))
|
||||||
return
|
return
|
||||||
if(legalismState.size >= 4) return
|
if (legalismState.size >= 4) return
|
||||||
|
|
||||||
val candidateCities = civInfo.cities
|
val candidateCities = civInfo.cities
|
||||||
.sortedBy { it.turnAcquired }
|
.sortedBy { it.turnAcquired }
|
||||||
.subList(0, min(4, civInfo.cities.size))
|
.subList(0, min(4, civInfo.cities.size))
|
||||||
.filter { it.id !in legalismState
|
.filter {
|
||||||
&& it.cityConstructions.hasBuildableCultureBuilding() }
|
it.id !in legalismState
|
||||||
|
&& it.cityConstructions.hasBuildableCultureBuilding()
|
||||||
|
}
|
||||||
for (city in candidateCities) {
|
for (city in candidateCities) {
|
||||||
val builtBuilding = city.cityConstructions.addCultureBuilding()
|
val builtBuilding = city.cityConstructions.addCultureBuilding()
|
||||||
legalismState[city.id] = builtBuilding!!
|
legalismState[city.id] = builtBuilding!!
|
||||||
|
@ -51,6 +51,7 @@ class Ruleset {
|
|||||||
val quests = LinkedHashMap<String, Quest>()
|
val quests = LinkedHashMap<String, Quest>()
|
||||||
val specialists = LinkedHashMap<String, Specialist>()
|
val specialists = LinkedHashMap<String, Specialist>()
|
||||||
val policyBranches = LinkedHashMap<String, PolicyBranch>()
|
val policyBranches = LinkedHashMap<String, PolicyBranch>()
|
||||||
|
val policies = LinkedHashMap<String, Policy>()
|
||||||
val difficulties = LinkedHashMap<String, Difficulty>()
|
val difficulties = LinkedHashMap<String, Difficulty>()
|
||||||
val mods = LinkedHashSet<String>()
|
val mods = LinkedHashSet<String>()
|
||||||
var modOptions = ModOptions()
|
var modOptions = ModOptions()
|
||||||
@ -74,6 +75,7 @@ class Ruleset {
|
|||||||
difficulties.putAll(ruleset.difficulties)
|
difficulties.putAll(ruleset.difficulties)
|
||||||
nations.putAll(ruleset.nations)
|
nations.putAll(ruleset.nations)
|
||||||
policyBranches.putAll(ruleset.policyBranches)
|
policyBranches.putAll(ruleset.policyBranches)
|
||||||
|
policies.putAll(ruleset.policies)
|
||||||
quests.putAll(ruleset.quests)
|
quests.putAll(ruleset.quests)
|
||||||
specialists.putAll(ruleset.specialists)
|
specialists.putAll(ruleset.specialists)
|
||||||
technologies.putAll(ruleset.technologies)
|
technologies.putAll(ruleset.technologies)
|
||||||
@ -93,6 +95,7 @@ class Ruleset {
|
|||||||
difficulties.clear()
|
difficulties.clear()
|
||||||
nations.clear()
|
nations.clear()
|
||||||
policyBranches.clear()
|
policyBranches.clear()
|
||||||
|
policies.clear()
|
||||||
quests.clear()
|
quests.clear()
|
||||||
technologies.clear()
|
technologies.clear()
|
||||||
buildings.clear()
|
buildings.clear()
|
||||||
@ -159,9 +162,11 @@ class Ruleset {
|
|||||||
for (branch in policyBranches.values) {
|
for (branch in policyBranches.values) {
|
||||||
branch.requires = ArrayList()
|
branch.requires = ArrayList()
|
||||||
branch.branch = branch
|
branch.branch = branch
|
||||||
|
policies[branch.name] = branch
|
||||||
for (policy in branch.policies) {
|
for (policy in branch.policies) {
|
||||||
policy.branch = branch
|
policy.branch = branch
|
||||||
if (policy.requires == null) policy.requires = arrayListOf(branch.name)
|
if (policy.requires == null) policy.requires = arrayListOf(branch.name)
|
||||||
|
policies[policy.name] = policy
|
||||||
}
|
}
|
||||||
branch.policies.last().name = branch.name + " Complete"
|
branch.policies.last().name = branch.name + " Complete"
|
||||||
}
|
}
|
||||||
|
@ -25,28 +25,26 @@ class PolicyPickerScreen(val worldScreen: WorldScreen, civInfo: CivilizationInfo
|
|||||||
|
|
||||||
rightSideButton.setText("{Adopt policy}\r\n(".tr() + policies.storedCulture + "/" + policies.getCultureNeededForNextPolicy() + ")")
|
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())
|
rightSideButton.setText("All policies adopted".tr())
|
||||||
|
|
||||||
setDefaultCloseAction()
|
setDefaultCloseAction()
|
||||||
if (policies.freePolicies > 0) {
|
if (policies.freePolicies > 0) {
|
||||||
rightSideButton.setText("Adopt free policy".tr())
|
rightSideButton.setText("Adopt free policy".tr())
|
||||||
if (policies.canAdoptPolicy()) closeButton.disable()
|
if (policies.canAdoptPolicy()) closeButton.disable()
|
||||||
}
|
} else onBackButtonClicked { UncivGame.Current.setWorldScreen() }
|
||||||
else onBackButtonClicked { UncivGame.Current.setWorldScreen() }
|
|
||||||
|
|
||||||
rightSideButton.onClick(UncivSound.Policy) {
|
rightSideButton.onClick(UncivSound.Policy) {
|
||||||
viewingCiv.policies.adopt(pickedPolicy!!)
|
viewingCiv.policies.adopt(pickedPolicy!!)
|
||||||
|
|
||||||
// If we've moved to another screen in the meantime (great person pick, victory screen) ignore this
|
// If we've moved to another screen in the meantime (great person pick, victory screen) ignore this
|
||||||
if(game.screen !is PolicyPickerScreen || !policies.canAdoptPolicy()){
|
if (game.screen !is PolicyPickerScreen || !policies.canAdoptPolicy()) {
|
||||||
game.setWorldScreen()
|
game.setWorldScreen()
|
||||||
dispose()
|
dispose()
|
||||||
}
|
} else game.setScreen(PolicyPickerScreen(worldScreen)) // update policies
|
||||||
else game.setScreen(PolicyPickerScreen(worldScreen)) // update policies
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!UncivGame.Current.worldScreen.canChangeState)
|
if (!UncivGame.Current.worldScreen.canChangeState)
|
||||||
rightSideButton.disable()
|
rightSideButton.disable()
|
||||||
|
|
||||||
topTable.row().pad(30f)
|
topTable.row().pad(30f)
|
||||||
@ -107,7 +105,7 @@ class PolicyPickerScreen(val worldScreen: WorldScreen, civInfo: CivilizationInfo
|
|||||||
|
|
||||||
if (!policy.name.endsWith("Complete")) {
|
if (!policy.name.endsWith("Complete")) {
|
||||||
if (policy.requires!!.isNotEmpty())
|
if (policy.requires!!.isNotEmpty())
|
||||||
policyText += "Requires [" + policy.requires!!.joinToString { it.tr() }+"]"
|
policyText += "Requires [" + policy.requires!!.joinToString { it.tr() } + "]"
|
||||||
else
|
else
|
||||||
policyText += "{Unlocked at} {" + policy.branch.era + "}"
|
policyText += "{Unlocked at} {" + policy.branch.era + "}"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user