Fix Denunceation typo, reorg compatibility code (#5156)

* Fix Denunceation typo, reorg compatibility code

* Fix Denunceation typo - lint
This commit is contained in:
SomeTroglodyte 2021-09-09 20:29:13 +02:00 committed by GitHub
parent cbd3c2910e
commit f1f4def7f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 207 additions and 154 deletions

View File

@ -0,0 +1,131 @@
package com.unciv.logic
import com.unciv.logic.city.CityConstructions
import com.unciv.logic.city.PerpetualConstruction
import com.unciv.logic.civilization.TechManager
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
import com.unciv.logic.civilization.diplomacy.DiplomacyManager
import com.unciv.models.ruleset.Ruleset
/**
* Container for all temporarily used code managing transitions from deprecated elements to their replacements.
*
* Please place ***all*** such code here and call it _only_ from [GameInfo.setTransients].
* Functions are allowed to remain once no longer used if you think they might serve as template for
* similar usecases in the future. Please comment sufficiently :)
*/
@Suppress("unused") // as mentioned above
object BackwardCompatibility {
/**
* Mods can change, leading to things on the map that are no longer defined in the mod.
* This function removes them so the game doesn't crash when it tries to access them.
*/
fun GameInfo.removeMissingModReferences() {
for (tile in tileMap.values) {
for (terrainFeature in tile.terrainFeatures.filter{ !ruleSet.terrains.containsKey(it) })
tile.terrainFeatures.remove(terrainFeature)
if (tile.resource != null && !ruleSet.tileResources.containsKey(tile.resource!!))
tile.resource = null
if (tile.improvement != null && !ruleSet.tileImprovements.containsKey(tile.improvement!!))
tile.improvement = null
for (unit in tile.getUnits()) {
if (!ruleSet.units.containsKey(unit.name)) tile.removeUnit(unit)
for (promotion in unit.promotions.promotions.toList())
if (!ruleSet.unitPromotions.containsKey(promotion))
unit.promotions.promotions.remove(promotion)
}
}
for (city in civilizations.asSequence().flatMap { it.cities.asSequence() }) {
for (building in city.cityConstructions.builtBuildings.toHashSet())
if (!ruleSet.buildings.containsKey(building))
city.cityConstructions.builtBuildings.remove(building)
fun isInvalidConstruction(construction: String) =
!ruleSet.buildings.containsKey(construction)
&& !ruleSet.units.containsKey(construction)
&& !PerpetualConstruction.perpetualConstructionsMap.containsKey(construction)
// Remove invalid buildings or units from the queue - don't just check buildings and units because it might be a special construction as well
for (construction in city.cityConstructions.constructionQueue.toList()) {
if (isInvalidConstruction(construction))
city.cityConstructions.constructionQueue.remove(construction)
}
// And from being in progress
for (construction in city.cityConstructions.inProgressConstructions.keys.toList())
if (isInvalidConstruction(construction))
city.cityConstructions.inProgressConstructions.remove(construction)
}
for (civInfo in civilizations) {
for (tech in civInfo.tech.techsResearched.toList())
if (!ruleSet.technologies.containsKey(tech))
civInfo.tech.techsResearched.remove(tech)
}
}
/**
* Replaces all occurrences of [oldBuildingName] in [cityConstructions] with [newBuildingName]
* if the former is not contained in the ruleset.
*/
private fun changeBuildingNameIfNotInRuleset(
ruleSet: Ruleset,
cityConstructions: CityConstructions,
oldBuildingName: String,
newBuildingName: String
) {
if (ruleSet.buildings.containsKey(oldBuildingName))
return
// Replace in built buildings
if (cityConstructions.builtBuildings.contains(oldBuildingName)) {
cityConstructions.builtBuildings.remove(oldBuildingName)
cityConstructions.builtBuildings.add(newBuildingName)
}
// Replace in construction queue
if (!cityConstructions.builtBuildings.contains(newBuildingName) && !cityConstructions.constructionQueue.contains(newBuildingName))
cityConstructions.constructionQueue = cityConstructions.constructionQueue
.map { if (it == oldBuildingName) newBuildingName else it }
.toMutableList()
else
cityConstructions.constructionQueue.remove(oldBuildingName)
// Replace in in-progress constructions
if (cityConstructions.inProgressConstructions.containsKey(oldBuildingName)) {
if (!cityConstructions.builtBuildings.contains(newBuildingName) && !cityConstructions.inProgressConstructions.containsKey(newBuildingName))
cityConstructions.inProgressConstructions[newBuildingName] = cityConstructions.inProgressConstructions[oldBuildingName]!!
cityConstructions.inProgressConstructions.remove(oldBuildingName)
}
}
/** Replace a changed tech name */
private fun TechManager.replaceUpdatedTechName(oldTechName: String, newTechName: String) {
if (oldTechName in techsResearched) {
techsResearched.remove(oldTechName)
techsResearched.add(newTechName)
}
val index = techsToResearch.indexOf(oldTechName)
if (index >= 0) {
techsToResearch[index] = newTechName
}
if (oldTechName in techsInProgress) {
techsInProgress[newTechName] = researchOfTech(oldTechName)
techsInProgress.remove(oldTechName)
}
}
/** Replace a deprecated DiplomacyFlags instance */
fun GameInfo.replaceDiplomacyFlag(old: DiplomacyFlags, new: DiplomacyFlags) {
fun DiplomacyManager.replaceFlag() {
if (hasFlag(old)) {
val value = getFlag(old)
removeFlag(old)
setFlag(new, value)
}
}
civilizations.flatMap { civ -> civ.diplomacy.values }.forEach { it.replaceFlag() }
}
}

View File

@ -2,10 +2,11 @@ package com.unciv.logic
import com.unciv.Constants import com.unciv.Constants
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.logic.BackwardCompatibility.removeMissingModReferences
import com.unciv.logic.BackwardCompatibility.replaceDiplomacyFlag
import com.unciv.logic.automation.NextTurnAutomation import com.unciv.logic.automation.NextTurnAutomation
import com.unciv.logic.city.CityConstructions
import com.unciv.logic.city.PerpetualConstruction
import com.unciv.logic.civilization.* import com.unciv.logic.civilization.*
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileInfo
import com.unciv.logic.map.TileMap import com.unciv.logic.map.TileMap
import com.unciv.models.Religion import com.unciv.models.Religion
@ -18,20 +19,7 @@ import java.util.*
class UncivShowableException(missingMods: String) : Exception(missingMods) class UncivShowableException(missingMods: String) : Exception(missingMods)
class GameInfo { class GameInfo {
@Transient //region Fields - Serialized
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
/** This is used in multiplayer games, where I may have a saved game state on my phone
* that is inconsistent with the saved game on the cloud */
@Transient
var isUpToDate = false
@Transient
lateinit var ruleSet: Ruleset
var civilizations = mutableListOf<CivilizationInfo>() var civilizations = mutableListOf<CivilizationInfo>()
var religions: HashMap<String, Religion> = hashMapOf() var religions: HashMap<String, Religion> = hashMapOf()
var difficulty = "Chieftain" // difficulty is game-wide, think what would happen if 2 human players could play on different difficulties? var difficulty = "Chieftain" // difficulty is game-wide, think what would happen if 2 human players could play on different difficulties?
@ -54,15 +42,36 @@ class GameInfo {
@Volatile @Volatile
var customSaveLocation: String? = null var customSaveLocation: String? = null
//endregion
//region Fields - Transient
@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
/** This is used in multiplayer games, where I may have a saved game state on my phone
* that is inconsistent with the saved game on the cloud */
@Transient
var isUpToDate = false
@Transient
lateinit var ruleSet: Ruleset
/** Simulate until any player wins, /** Simulate until any player wins,
* or turns exceeds indicated number * or turns exceeds indicated number
* Does not update World View until finished. * Does not update World View until finished.
* Should be set manually on each new game start. * Should be set manually on each new game start.
*/ */
@Transient
var simulateMaxTurns: Int = 1000 var simulateMaxTurns: Int = 1000
@Transient
var simulateUntilWin = false var simulateUntilWin = false
//region pure functions //endregion
//region Pure functions
fun clone(): GameInfo { fun clone(): GameInfo {
val toReturn = GameInfo() val toReturn = GameInfo()
toReturn.tileMap = tileMap.clone() toReturn.tileMap = tileMap.clone()
@ -103,7 +112,14 @@ class GameInfo {
fun getCities() = civilizations.asSequence().flatMap { it.cities } fun getCities() = civilizations.asSequence().flatMap { it.cities }
fun getAliveCityStates() = civilizations.filter { it.isAlive() && it.isCityState() } fun getAliveCityStates() = civilizations.filter { it.isAlive() && it.isCityState() }
fun getAliveMajorCivs() = civilizations.filter { it.isAlive() && it.isMajorCiv() } fun getAliveMajorCivs() = civilizations.filter { it.isAlive() && it.isMajorCiv() }
fun hasReligionEnabled() =
// Temporary function to check whether religion should be used for this game
(gameParameters.religionEnabled || ruleSet.hasReligion())
&& (ruleSet.eras.isEmpty() || !ruleSet.eras[gameParameters.startingEra]!!.hasUnique("Starting in this era disables religion"))
//endregion //endregion
//region State changing functions
fun nextTurn() { fun nextTurn() {
val previousHumanPlayer = getCurrentPlayerCivilization() val previousHumanPlayer = getCurrentPlayerCivilization()
@ -236,7 +252,7 @@ class GameInfo {
return tile return tile
} }
fun placeBarbarianUnit(tileToPlace: TileInfo) { private fun placeBarbarianUnit(tileToPlace: TileInfo) {
// if we don't make this into a separate list then the retain() will happen on the Tech keys, // 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 // which effectively removes those techs from the game and causes all sorts of problems
val allResearchedTechs = ruleSet.technologies.keys.toMutableList() val allResearchedTechs = ruleSet.technologies.keys.toMutableList()
@ -252,10 +268,9 @@ class GameInfo {
val landUnits = unitList.filter { it.isLandUnit() } val landUnits = unitList.filter { it.isLandUnit() }
val waterUnits = unitList.filter { it.isWaterUnit() } val waterUnits = unitList.filter { it.isWaterUnit() }
val unit: String val unit: String = if (waterUnits.isNotEmpty() && tileToPlace.isCoastalTile() && Random().nextBoolean())
if (waterUnits.isNotEmpty() && tileToPlace.isCoastalTile() && Random().nextBoolean()) waterUnits.random().name
unit = waterUnits.random().name else landUnits.random().name
else unit = landUnits.random().name
tileMap.placeUnitNearTile(tileToPlace.position, unit, getBarbarianCivilization()) tileMap.placeUnitNearTile(tileToPlace.position, unit, getBarbarianCivilization())
} }
@ -264,7 +279,7 @@ class GameInfo {
* [CivilizationInfo.addNotification][Add a notification] to every civilization that have * [CivilizationInfo.addNotification][Add a notification] to every civilization that have
* adopted Honor policy and have explored the [tile] where the Barbarian Encampment has spawned. * adopted Honor policy and have explored the [tile] where the Barbarian Encampment has spawned.
*/ */
fun notifyCivsOfBarbarianEncampment(tile: TileInfo) { private fun notifyCivsOfBarbarianEncampment(tile: TileInfo) {
civilizations.filter { civilizations.filter {
it.hasUnique("Notified of new Barbarian encampments") it.hasUnique("Notified of new Barbarian encampments")
&& it.exploredTiles.contains(tile.position) && it.exploredTiles.contains(tile.position)
@ -289,6 +304,8 @@ class GameInfo {
removeMissingModReferences() removeMissingModReferences()
replaceDiplomacyFlag(DiplomacyFlags.Denunceation, DiplomacyFlags.Denunciation)
for (baseUnit in ruleSet.units.values) for (baseUnit in ruleSet.units.values)
baseUnit.ruleset = ruleSet baseUnit.ruleset = ruleSet
@ -296,14 +313,14 @@ class GameInfo {
// the nation of their civilization when setting transients // the nation of their civilization when setting transients
for (civInfo in civilizations) civInfo.gameInfo = this for (civInfo in civilizations) civInfo.gameInfo = this
for (civInfo in civilizations) civInfo.setNationTransient() for (civInfo in civilizations) civInfo.setNationTransient()
tileMap.setTransients(ruleSet) tileMap.setTransients(ruleSet)
if (currentPlayer == "") currentPlayer = civilizations.first { it.isPlayerCivilization() }.civName if (currentPlayer == "") currentPlayer = civilizations.first { it.isPlayerCivilization() }.civName
currentPlayerCiv = getCivilization(currentPlayer) currentPlayerCiv = getCivilization(currentPlayer)
difficultyObject = ruleSet.difficulties[difficulty]!! difficultyObject = ruleSet.difficulties[difficulty]!!
for (religion in religions.values) religion.setTransients(this) for (religion in religions.values) religion.setTransients(this)
for (civInfo in civilizations) civInfo.setTransients() for (civInfo in civilizations) civInfo.setTransients()
@ -338,105 +355,7 @@ class GameInfo {
} }
} }
//endregion
// Mods can change, leading to things on the map that are no longer defined in the mod.
// So we remove them so the game doesn't crash when it tries to access them.
private fun removeMissingModReferences() {
for (tile in tileMap.values) {
for (terrainFeature in tile.terrainFeatures.filter{ !ruleSet.terrains.containsKey(it) })
tile.terrainFeatures.remove(terrainFeature)
if (tile.resource != null && !ruleSet.tileResources.containsKey(tile.resource!!))
tile.resource = null
if (tile.improvement != null && !ruleSet.tileImprovements.containsKey(tile.improvement!!))
tile.improvement = null
for (unit in tile.getUnits()) {
if (!ruleSet.units.containsKey(unit.name)) tile.removeUnit(unit)
for (promotion in unit.promotions.promotions.toList())
if (!ruleSet.unitPromotions.containsKey(promotion))
unit.promotions.promotions.remove(promotion)
}
}
for (city in civilizations.asSequence().flatMap { it.cities.asSequence() }) {
for (building in city.cityConstructions.builtBuildings.toHashSet())
if (!ruleSet.buildings.containsKey(building))
city.cityConstructions.builtBuildings.remove(building)
fun isInvalidConstruction(construction: String) =
!ruleSet.buildings.containsKey(construction)
&& !ruleSet.units.containsKey(construction)
&& !PerpetualConstruction.perpetualConstructionsMap.containsKey(construction)
// Remove invalid buildings or units from the queue - don't just check buildings and units because it might be a special construction as well
for (construction in city.cityConstructions.constructionQueue.toList()) {
if (isInvalidConstruction(construction))
city.cityConstructions.constructionQueue.remove(construction)
}
// And from being in progress
for (construction in city.cityConstructions.inProgressConstructions.keys.toList())
if (isInvalidConstruction(construction))
city.cityConstructions.inProgressConstructions.remove(construction)
}
for (civinfo in civilizations) {
for (tech in civinfo.tech.techsResearched.toList())
if (!ruleSet.technologies.containsKey(tech))
civinfo.tech.techsResearched.remove(tech)
}
}
/**
* Replaces all occurrences of [oldBuildingName] in [cityConstructions] with [newBuildingName]
* if the former is not contained in the ruleset.
* This function can be used for backwards compatibility with older save files when a building
* name is changed.
*/
@Suppress("unused") // it's OK if there's no deprecation currently needing this
private fun changeBuildingNameIfNotInRuleset(cityConstructions: CityConstructions, oldBuildingName: String, newBuildingName: String) {
if (ruleSet.buildings.containsKey(oldBuildingName))
return
// Replace in built buildings
if (cityConstructions.builtBuildings.contains(oldBuildingName)) {
cityConstructions.builtBuildings.remove(oldBuildingName)
cityConstructions.builtBuildings.add(newBuildingName)
}
// Replace in construction queue
if (!cityConstructions.builtBuildings.contains(newBuildingName) && !cityConstructions.constructionQueue.contains(newBuildingName))
cityConstructions.constructionQueue = cityConstructions.constructionQueue.map{ if (it == oldBuildingName) newBuildingName else it }.toMutableList()
else
cityConstructions.constructionQueue.remove(oldBuildingName)
// Replace in in-progress constructions
if (cityConstructions.inProgressConstructions.containsKey(oldBuildingName)) {
if (!cityConstructions.builtBuildings.contains(newBuildingName) && !cityConstructions.inProgressConstructions.containsKey(newBuildingName))
cityConstructions.inProgressConstructions[newBuildingName] = cityConstructions.inProgressConstructions[oldBuildingName]!!
cityConstructions.inProgressConstructions.remove(oldBuildingName)
}
}
/** Replace a changed tech name, only temporarily used for breaking ruleset updates */
private fun TechManager.replaceUpdatedTechName(oldTechName: String, newTechName: String) {
if (oldTechName in techsResearched) {
techsResearched.remove(oldTechName)
techsResearched.add(newTechName)
}
val index = techsToResearch.indexOf(oldTechName)
if (index >= 0) {
techsToResearch[index] = newTechName
}
if (oldTechName in techsInProgress) {
techsInProgress[newTechName] = researchOfTech(oldTechName)
techsInProgress.remove(oldTechName)
}
}
fun hasReligionEnabled() =
// Temporary function to check whether religion should be used for this game
(gameParameters.religionEnabled || ruleSet.hasReligion())
&& (ruleSet.eras.isEmpty() || !ruleSet.eras[gameParameters.startingEra]!!.hasUnique("Starting in this era disables religion"))
} }
// reduced variant only for load preview // reduced variant only for load preview

View File

@ -63,7 +63,7 @@ object NextTurnAutomation {
// Can only be done now, as the prophet first has to decide to found/enhance a religion // Can only be done now, as the prophet first has to decide to found/enhance a religion
chooseReligiousBeliefs(civInfo) chooseReligiousBeliefs(civInfo)
} }
reassignWorkedTiles(civInfo) // second most expensive reassignWorkedTiles(civInfo) // second most expensive
trainSettler(civInfo) trainSettler(civInfo)
tryVoteForDiplomaticVictory(civInfo) tryVoteForDiplomaticVictory(civInfo)
@ -103,7 +103,7 @@ object NextTurnAutomation {
val requestingCiv = civInfo.gameInfo.getCivilization(popupAlert.value) val requestingCiv = civInfo.gameInfo.getCivilization(popupAlert.value)
val diploManager = civInfo.getDiplomacyManager(requestingCiv) val diploManager = civInfo.getDiplomacyManager(requestingCiv)
if (diploManager.relationshipLevel() > RelationshipLevel.Neutral if (diploManager.relationshipLevel() > RelationshipLevel.Neutral
&& !diploManager.otherCivDiplomacy().hasFlag(DiplomacyFlags.Denunceation)) { && !diploManager.otherCivDiplomacy().hasFlag(DiplomacyFlags.Denunciation)) {
diploManager.signDeclarationOfFriendship() diploManager.signDeclarationOfFriendship()
requestingCiv.addNotification("We have signed a Declaration of Friendship with [${civInfo.civName}]!", NotificationIcon.Diplomacy, civInfo.civName) requestingCiv.addNotification("We have signed a Declaration of Friendship with [${civInfo.civName}]!", NotificationIcon.Diplomacy, civInfo.civName)
} else requestingCiv.addNotification("[${civInfo.civName}] has denied our Declaration of Friendship!", NotificationIcon.Diplomacy, civInfo.civName) } else requestingCiv.addNotification("[${civInfo.civName}] has denied our Declaration of Friendship!", NotificationIcon.Diplomacy, civInfo.civName)
@ -206,8 +206,9 @@ object NextTurnAutomation {
} }
// Bonus for luxury resources we can get from them // Bonus for luxury resources we can get from them
value += cityState.detailedCivResources.count { it.resource.resourceType == ResourceType.Luxury value += cityState.detailedCivResources.count {
&& it.resource !in civInfo.detailedCivResources.map { it.resource } it.resource.resourceType == ResourceType.Luxury
&& it.resource !in civInfo.detailedCivResources.map { supply -> supply.resource }
} }
return value return value
@ -298,13 +299,13 @@ object NextTurnAutomation {
civInfo.policies.adopt(policyToAdopt) civInfo.policies.adopt(policyToAdopt)
} }
} }
private fun chooseReligiousBeliefs(civInfo: CivilizationInfo) { private fun chooseReligiousBeliefs(civInfo: CivilizationInfo) {
choosePantheon(civInfo) choosePantheon(civInfo)
foundReligion(civInfo) foundReligion(civInfo)
enhanceReligion(civInfo) enhanceReligion(civInfo)
} }
private fun choosePantheon(civInfo: CivilizationInfo) { private fun choosePantheon(civInfo: CivilizationInfo) {
if (!civInfo.religionManager.canFoundPantheon()) return if (!civInfo.religionManager.canFoundPantheon()) return
// So looking through the source code of the base game available online, // So looking through the source code of the base game available online,
@ -319,7 +320,7 @@ object NextTurnAutomation {
val chosenPantheon = availablePantheons.random() // Why calculate stuff? val chosenPantheon = availablePantheons.random() // Why calculate stuff?
civInfo.religionManager.choosePantheonBelief(chosenPantheon) civInfo.religionManager.choosePantheonBelief(chosenPantheon)
} }
private fun foundReligion(civInfo: CivilizationInfo) { private fun foundReligion(civInfo: CivilizationInfo) {
if (civInfo.religionManager.religionState != ReligionState.FoundingReligion) return if (civInfo.religionManager.religionState != ReligionState.FoundingReligion) return
val religionIcon = civInfo.gameInfo.ruleSet.religions val religionIcon = civInfo.gameInfo.ruleSet.religions
@ -329,7 +330,7 @@ object NextTurnAutomation {
val chosenBeliefs = chooseBeliefs(civInfo, civInfo.religionManager.getBeliefsToChooseAtFounding()).toList() val chosenBeliefs = chooseBeliefs(civInfo, civInfo.religionManager.getBeliefsToChooseAtFounding()).toList()
civInfo.religionManager.chooseBeliefs(religionIcon, religionIcon, chosenBeliefs) civInfo.religionManager.chooseBeliefs(religionIcon, religionIcon, chosenBeliefs)
} }
private fun enhanceReligion(civInfo: CivilizationInfo) { private fun enhanceReligion(civInfo: CivilizationInfo) {
civInfo.religionManager.chooseBeliefs( civInfo.religionManager.chooseBeliefs(
null, null,
@ -337,11 +338,11 @@ object NextTurnAutomation {
chooseBeliefs(civInfo, civInfo.religionManager.getBeliefsToChooseAtEnhancing()).toList() chooseBeliefs(civInfo, civInfo.religionManager.getBeliefsToChooseAtEnhancing()).toList()
) )
} }
private fun chooseBeliefs(civInfo: CivilizationInfo, beliefContainer: BeliefContainer): HashSet<Belief> { private fun chooseBeliefs(civInfo: CivilizationInfo, beliefContainer: BeliefContainer): HashSet<Belief> {
val chosenBeliefs = hashSetOf<Belief>() val chosenBeliefs = hashSetOf<Belief>()
// The 'continues' should never be reached, but just in case I'd rather have AI have a // The `continue`s should never be reached, but just in case I'd rather have the AI have a
// belief less than make the game crash. The 'continue's should only be reached whenever // belief less than make the game crash. The `continue`s should only be reached whenever
// there are not enough beliefs to choose, but there should be, as otherwise we could // there are not enough beliefs to choose, but there should be, as otherwise we could
// not have used a great prophet to found/enhance our religion. // not have used a great prophet to found/enhance our religion.
for (counter in 0 until beliefContainer.pantheonBeliefCount) for (counter in 0 until beliefContainer.pantheonBeliefCount)
@ -362,7 +363,7 @@ object NextTurnAutomation {
) )
return chosenBeliefs return chosenBeliefs
} }
private fun chooseBeliefOfType(civInfo: CivilizationInfo, beliefType: BeliefType, additionalBeliefsToExclude: HashSet<Belief> = hashSetOf()): Belief? { private fun chooseBeliefOfType(civInfo: CivilizationInfo, beliefType: BeliefType, additionalBeliefsToExclude: HashSet<Belief> = hashSetOf()): Belief? {
return civInfo.gameInfo.ruleSet.beliefs return civInfo.gameInfo.ruleSet.beliefs
.filter { .filter {
@ -436,7 +437,7 @@ object NextTurnAutomation {
it.isMajorCiv() && !it.isAtWarWith(civInfo) it.isMajorCiv() && !it.isAtWarWith(civInfo)
&& it.getDiplomacyManager(civInfo).relationshipLevel() > RelationshipLevel.Neutral && it.getDiplomacyManager(civInfo).relationshipLevel() > RelationshipLevel.Neutral
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclarationOfFriendship) && !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.DeclarationOfFriendship)
&& !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.Denunceation) && !civInfo.getDiplomacyManager(it).hasFlag(DiplomacyFlags.Denunciation)
} }
.sortedByDescending { it.getDiplomacyManager(civInfo).relationshipLevel() } .sortedByDescending { it.getDiplomacyManager(civInfo).relationshipLevel() }
for (civ in civsThatWeCanDeclareFriendshipWith) { for (civ in civsThatWeCanDeclareFriendshipWith) {
@ -682,20 +683,20 @@ object NextTurnAutomation {
private fun tryVoteForDiplomaticVictory(civInfo: CivilizationInfo) { private fun tryVoteForDiplomaticVictory(civInfo: CivilizationInfo) {
if (!civInfo.mayVoteForDiplomaticVictory()) return if (!civInfo.mayVoteForDiplomaticVictory()) return
val chosenCiv: String? = if (civInfo.isMajorCiv()) { val chosenCiv: String? = if (civInfo.isMajorCiv()) {
val knownMajorCivs = civInfo.getKnownCivs().filter { it.isMajorCiv() } val knownMajorCivs = civInfo.getKnownCivs().filter { it.isMajorCiv() }
val highestOpinion = knownMajorCivs val highestOpinion = knownMajorCivs
.maxOfOrNull { .maxOfOrNull {
civInfo.getDiplomacyManager(it).opinionOfOtherCiv() civInfo.getDiplomacyManager(it).opinionOfOtherCiv()
} }
if (highestOpinion == null) null if (highestOpinion == null) null
else knownMajorCivs.filter { civInfo.getDiplomacyManager(it).opinionOfOtherCiv() == highestOpinion}.random().civName else knownMajorCivs.filter { civInfo.getDiplomacyManager(it).opinionOfOtherCiv() == highestOpinion}.random().civName
} else { } else {
civInfo.getAllyCiv() civInfo.getAllyCiv()
} }
civInfo.diplomaticVoteForCiv(chosenCiv) civInfo.diplomaticVoteForCiv(chosenCiv)
} }
@ -742,4 +743,4 @@ object NextTurnAutomation {
return cityDistances.minByOrNull { it.aerialDistance }!! return cityDistances.minByOrNull { it.aerialDistance }!!
} }
} }

View File

@ -32,6 +32,7 @@ enum class DiplomacyFlags {
DeclaredWar, DeclaredWar,
DeclarationOfFriendship, DeclarationOfFriendship,
ResearchAgreement, ResearchAgreement,
@Deprecated("Deprecated after 3.16.13", ReplaceWith("Denunciation"))
Denunceation, Denunceation,
BorderConflict, BorderConflict,
SettledCitiesNearUs, SettledCitiesNearUs,
@ -43,7 +44,8 @@ enum class DiplomacyFlags {
NotifiedAfraid, NotifiedAfraid,
RecentlyPledgedProtection, RecentlyPledgedProtection,
RecentlyWithdrewProtection, RecentlyWithdrewProtection,
AngerFreeIntrusion AngerFreeIntrusion,
Denunciation
} }
enum class DiplomaticModifiers { enum class DiplomaticModifiers {
@ -107,7 +109,7 @@ class DiplomacyManager() {
get() = if (civInfo.isAtWarWith(otherCiv())) MINIMUM_INFLUENCE else field get() = if (civInfo.isAtWarWith(otherCiv())) MINIMUM_INFLUENCE else field
/** Total of each turn Science during Research Agreement */ /** Total of each turn Science during Research Agreement */
var totalOfScienceDuringRA = 0 private var totalOfScienceDuringRA = 0
fun clone(): DiplomacyManager { fun clone(): DiplomacyManager {
val toReturn = DiplomacyManager() val toReturn = DiplomacyManager()
@ -188,6 +190,7 @@ class DiplomacyManager() {
return 0 return 0
} }
@Suppress("unused") //todo Finish original intent or remove
fun matchesCityStateRelationshipFilter(filter: String): Boolean { fun matchesCityStateRelationshipFilter(filter: String): Boolean {
val relationshipLevel = relationshipLevel() val relationshipLevel = relationshipLevel()
return when (filter) { return when (filter) {
@ -210,7 +213,7 @@ class DiplomacyManager() {
} }
// To be run from City-State DiplomacyManager, which holds the influence. Resting point for every major civ can be different. // To be run from City-State DiplomacyManager, which holds the influence. Resting point for every major civ can be different.
fun getCityStateInfluenceRestingPoint(): Float { private fun getCityStateInfluenceRestingPoint(): Float {
var restingPoint = 0f var restingPoint = 0f
for (unique in otherCiv().getMatchingUniques("Resting point for Influence with City-States is increased by []")) for (unique in otherCiv().getMatchingUniques("Resting point for Influence with City-States is increased by []"))
@ -287,7 +290,7 @@ class DiplomacyManager() {
return goldPerTurnForUs return goldPerTurnForUs
} }
fun scienceFromResearchAgreement() { private fun scienceFromResearchAgreement() {
// https://forums.civfanatics.com/resources/research-agreements-bnw.25568/ // https://forums.civfanatics.com/resources/research-agreements-bnw.25568/
val scienceFromResearchAgreement = min(totalOfScienceDuringRA, otherCivDiplomacy().totalOfScienceDuringRA) val scienceFromResearchAgreement = min(totalOfScienceDuringRA, otherCivDiplomacy().totalOfScienceDuringRA)
civInfo.tech.scienceFromResearchAgreements += scienceFromResearchAgreement civInfo.tech.scienceFromResearchAgreements += scienceFromResearchAgreement
@ -696,16 +699,16 @@ class DiplomacyManager() {
diplomaticModifiers[modifier.name] = amount diplomaticModifiers[modifier.name] = amount
} }
fun getModifier(modifier: DiplomaticModifiers): Float { private fun getModifier(modifier: DiplomaticModifiers): Float {
if (!hasModifier(modifier)) return 0f if (!hasModifier(modifier)) return 0f
return diplomaticModifiers[modifier.name]!! return diplomaticModifiers[modifier.name]!!
} }
fun removeModifier(modifier: DiplomaticModifiers) = diplomaticModifiers.remove(modifier.name) private fun removeModifier(modifier: DiplomaticModifiers) = diplomaticModifiers.remove(modifier.name)
fun hasModifier(modifier: DiplomaticModifiers) = diplomaticModifiers.containsKey(modifier.name) fun hasModifier(modifier: DiplomaticModifiers) = diplomaticModifiers.containsKey(modifier.name)
/** @param amount always positive, so you don't need to think about it */ /** @param amount always positive, so you don't need to think about it */
fun revertToZero(modifier: DiplomaticModifiers, amount: Float) { private fun revertToZero(modifier: DiplomaticModifiers, amount: Float) {
if (!hasModifier(modifier)) return if (!hasModifier(modifier)) return
val currentAmount = getModifier(modifier) val currentAmount = getModifier(modifier)
if (currentAmount > 0) addModifier(modifier, -amount) if (currentAmount > 0) addModifier(modifier, -amount)
@ -728,7 +731,7 @@ class DiplomacyManager() {
} }
} }
fun setFriendshipBasedModifier() { private fun setFriendshipBasedModifier() {
removeModifier(DiplomaticModifiers.DeclaredFriendshipWithOurAllies) removeModifier(DiplomaticModifiers.DeclaredFriendshipWithOurAllies)
removeModifier(DiplomaticModifiers.DeclaredFriendshipWithOurEnemies) removeModifier(DiplomaticModifiers.DeclaredFriendshipWithOurEnemies)
for (thirdCiv in getCommonKnownCivs() for (thirdCiv in getCommonKnownCivs()
@ -747,8 +750,8 @@ class DiplomacyManager() {
fun denounce() { fun denounce() {
setModifier(DiplomaticModifiers.Denunciation, -35f) setModifier(DiplomaticModifiers.Denunciation, -35f)
otherCivDiplomacy().setModifier(DiplomaticModifiers.Denunciation, -35f) otherCivDiplomacy().setModifier(DiplomaticModifiers.Denunciation, -35f)
setFlag(DiplomacyFlags.Denunceation, 30) setFlag(DiplomacyFlags.Denunciation, 30)
otherCivDiplomacy().setFlag(DiplomacyFlags.Denunceation, 30) otherCivDiplomacy().setFlag(DiplomacyFlags.Denunciation, 30)
otherCiv().addNotification("[${civInfo.civName}] has denounced us!", NotificationIcon.Diplomacy, civInfo.civName) otherCiv().addNotification("[${civInfo.civName}] has denounced us!", NotificationIcon.Diplomacy, civInfo.civName)

View File

@ -16,7 +16,6 @@ import com.unciv.logic.civilization.diplomacy.RelationshipLevel
import com.unciv.logic.trade.TradeLogic import com.unciv.logic.trade.TradeLogic
import com.unciv.logic.trade.TradeOffer import com.unciv.logic.trade.TradeOffer
import com.unciv.logic.trade.TradeType import com.unciv.logic.trade.TradeType
import com.unciv.models.ruleset.Era
import com.unciv.models.ruleset.ModOptionsConstants import com.unciv.models.ruleset.ModOptionsConstants
import com.unciv.models.ruleset.Quest import com.unciv.models.ruleset.Quest
import com.unciv.models.ruleset.tile.ResourceType import com.unciv.models.ruleset.tile.ResourceType
@ -593,7 +592,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
diplomacyTable.add(researchAgreementButton).row() diplomacyTable.add(researchAgreementButton).row()
} }
if (!diplomacyManager.hasFlag(DiplomacyFlags.Denunceation) if (!diplomacyManager.hasFlag(DiplomacyFlags.Denunciation)
&& !diplomacyManager.hasFlag(DiplomacyFlags.DeclarationOfFriendship) && !diplomacyManager.hasFlag(DiplomacyFlags.DeclarationOfFriendship)
) { ) {
val denounceButton = "Denounce ([30] turns)".toTextButton() val denounceButton = "Denounce ([30] turns)".toTextButton()