Cache 'library' helper classes of CivilizationInfo (#6363)

This commit is contained in:
SomeTroglodyte 2022-03-17 21:22:54 +01:00 committed by GitHub
parent c117860d6f
commit c80db524b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 36 additions and 27 deletions

View File

@ -13,7 +13,6 @@ import java.util.*
import kotlin.collections.HashMap import kotlin.collections.HashMap
import kotlin.collections.HashSet import kotlin.collections.HashSet
import kotlin.collections.LinkedHashMap import kotlin.collections.LinkedHashMap
import kotlin.math.max
import kotlin.math.min import kotlin.math.min
import kotlin.math.pow import kotlin.math.pow
@ -487,12 +486,12 @@ class CityStateFunctions(val civInfo: CivilizationInfo) {
if (diplomacy.diplomaticStatus == DiplomaticStatus.War) return // No reward for enemies if (diplomacy.diplomaticStatus == DiplomaticStatus.War) return // No reward for enemies
diplomacy.addInfluence(12f) diplomacy.addInfluence(12f)
if (diplomacy.hasFlag(DiplomacyFlags.AngerFreeIntrusion)) if (diplomacy.hasFlag(DiplomacyFlags.AngerFreeIntrusion))
diplomacy.setFlag(DiplomacyFlags.AngerFreeIntrusion, diplomacy.getFlag(DiplomacyFlags.AngerFreeIntrusion) + 5) diplomacy.setFlag(DiplomacyFlags.AngerFreeIntrusion, diplomacy.getFlag(DiplomacyFlags.AngerFreeIntrusion) + 5)
else else
diplomacy.setFlag(DiplomacyFlags.AngerFreeIntrusion, 5) diplomacy.setFlag(DiplomacyFlags.AngerFreeIntrusion, 5)
otherCiv.addNotification("[${civInfo.civName}] is grateful that you killed a Barbarian that was threatening them!", otherCiv.addNotification("[${civInfo.civName}] is grateful that you killed a Barbarian that was threatening them!",
DiplomacyAction(civInfo.civName), civInfo.civName) DiplomacyAction(civInfo.civName), civInfo.civName)
} }
@ -645,13 +644,13 @@ class CityStateFunctions(val civInfo: CivilizationInfo) {
) { ) {
thirdCiv.addNotification( thirdCiv.addNotification(
"[${civInfo.civName}] is being attacked by [${attacker.civName}] and asks all major civilizations to help them out by gifting them military units.", "[${civInfo.civName}] is being attacked by [${attacker.civName}] and asks all major civilizations to help them out by gifting them military units.",
civInfo.getCapital().location, civInfo.getCapital().location,
civInfo.civName, civInfo.civName,
"OtherIcons/Present", "OtherIcons/Present",
) )
} }
} }
fun getCityStateResourcesForAlly(): ResourceSupplyList { fun getCityStateResourcesForAlly(): ResourceSupplyList {
val newDetailedCivResources = ResourceSupplyList() val newDetailedCivResources = ResourceSupplyList()
for (city in civInfo.cities) { for (city in civInfo.cities) {

View File

@ -144,7 +144,6 @@ class CivInfoTransientUpdater(val civInfo: CivilizationInfo) {
civInfo.hasUnique(UniqueType.EnemyLandUnitsSpendExtraMovement) civInfo.hasUnique(UniqueType.EnemyLandUnitsSpendExtraMovement)
} }
fun updateCitiesConnectedToCapital(initialSetup: Boolean = false) { fun updateCitiesConnectedToCapital(initialSetup: Boolean = false) {
if (civInfo.cities.isEmpty()) return // eg barbarians if (civInfo.cities.isEmpty()) return // eg barbarians
@ -173,7 +172,7 @@ class CivInfoTransientUpdater(val civInfo: CivilizationInfo) {
for (unique in civInfo.getMatchingUniques(UniqueType.CityStateResources)) for (unique in civInfo.getMatchingUniques(UniqueType.CityStateResources))
resourceBonusPercentage += unique.params[0].toFloat() / 100 resourceBonusPercentage += unique.params[0].toFloat() / 100
for (cityStateAlly in civInfo.getKnownCivs().filter { it.getAllyCiv() == civInfo.civName }) { for (cityStateAlly in civInfo.getKnownCivs().filter { it.getAllyCiv() == civInfo.civName }) {
for (resource in CityStateFunctions(cityStateAlly).getCityStateResourcesForAlly()) { for (resource in cityStateAlly.cityStateFunctions.getCityStateResourcesForAlly()) {
newDetailedCivResources.add( newDetailedCivResources.add(
resource.apply { amount = (amount * resourceBonusPercentage).toInt() } resource.apply { amount = (amount * resourceBonusPercentage).toInt() }
) )

View File

@ -188,7 +188,7 @@ class CivilizationInfo {
* *
* @property attackingUnit Name key of [BaseUnit] type that performed the attack, or null (E.G. for city bombardments). * @property attackingUnit Name key of [BaseUnit] type that performed the attack, or null (E.G. for city bombardments).
* @property source Position of the tile from which the attack was made. * @property source Position of the tile from which the attack was made.
* @property target Position of the tile targetted by the attack. * @property target Position of the tile targeted by the attack.
* @see [MapUnit.UnitMovementMemory], [attacksSinceTurnStart] * @see [MapUnit.UnitMovementMemory], [attacksSinceTurnStart]
*/ */
class HistoricalAttackMemory() { class HistoricalAttackMemory() {
@ -280,6 +280,7 @@ class CivilizationInfo {
fun getDiplomacyManager(civName: String) = diplomacy[civName]!! fun getDiplomacyManager(civName: String) = diplomacy[civName]!!
fun getProximity(civInfo: CivilizationInfo) = getProximity(civInfo.civName) fun getProximity(civInfo: CivilizationInfo) = getProximity(civInfo.civName)
@Suppress("MemberVisibilityCanBePrivate") // same visibility for overloads
fun getProximity(civName: String) = proximity[civName] ?: Proximity.None fun getProximity(civName: String) = proximity[civName] ?: Proximity.None
/** Returns only undefeated civs, aka the ones we care about */ /** Returns only undefeated civs, aka the ones we care about */
@ -303,7 +304,10 @@ class CivilizationInfo {
var cityStateUniqueUnit: String? = null // Unique unit for militaristic city state. Might still be null if there are no appropriate units var cityStateUniqueUnit: String? = null // Unique unit for militaristic city state. Might still be null if there are no appropriate units
fun isMajorCiv() = nation.isMajorCiv() fun isMajorCiv() = nation.isMajorCiv()
fun isAlive(): Boolean = !isDefeated() fun isAlive(): Boolean = !isDefeated()
@Suppress("unused") //TODO remove if future use unlikely, including DiplomacyFlags.EverBeenFriends and 2 DiplomacyManager methods - see #3183
fun hasEverBeenFriendWith(otherCiv: CivilizationInfo): Boolean = getDiplomacyManager(otherCiv).everBeenFriends() fun hasEverBeenFriendWith(otherCiv: CivilizationInfo): Boolean = getDiplomacyManager(otherCiv).everBeenFriends()
fun hasMetCivTerritory(otherCiv: CivilizationInfo): Boolean = otherCiv.getCivTerritory().any { it in exploredTiles } fun hasMetCivTerritory(otherCiv: CivilizationInfo): Boolean = otherCiv.getCivTerritory().any { it in exploredTiles }
fun getCompletedPolicyBranchesCount(): Int = policies.adoptedPolicies.count { Policy.isBranchCompleteByName(it) } fun getCompletedPolicyBranchesCount(): Int = policies.adoptedPolicies.count { Policy.isBranchCompleteByName(it) }
private fun getCivTerritory() = cities.asSequence().flatMap { it.tiles.asSequence() } private fun getCivTerritory() = cities.asSequence().flatMap { it.tiles.asSequence() }
@ -317,8 +321,13 @@ class CivilizationInfo {
else VictoryType.Neutral else VictoryType.Neutral
} }
fun stats() = CivInfoStats(this) @Transient
fun transients() = CivInfoTransientUpdater(this) private val civInfoStats = CivInfoStats(this)
fun stats() = civInfoStats
@Transient
private val civInfoTransientUpdater = CivInfoTransientUpdater(this)
fun transients() = civInfoTransientUpdater
fun updateStatsForNextTurn() { fun updateStatsForNextTurn() {
happinessForNextTurn = stats().getHappinessBreakdown().values.sum().roundToInt() happinessForNextTurn = stats().getHappinessBreakdown().values.sum().roundToInt()
@ -650,7 +659,7 @@ class CivilizationInfo {
fun isMinorCivAggressor() = numMinorCivsAttacked >= 2 fun isMinorCivAggressor() = numMinorCivsAttacked >= 2
fun isMinorCivWarmonger() = numMinorCivsAttacked >= 4 fun isMinorCivWarmonger() = numMinorCivsAttacked >= 4
fun isLongCountActive(): Boolean { private fun isLongCountActive(): Boolean {
val unique = getMatchingUniques(UniqueType.MayanGainGreatPerson).firstOrNull() val unique = getMatchingUniques(UniqueType.MayanGainGreatPerson).firstOrNull()
?: return false ?: return false
return tech.isResearched(unique.params[1]) return tech.isResearched(unique.params[1])
@ -1011,10 +1020,8 @@ class CivilizationInfo {
return score return score
} }
private fun getTurnsBeforeRevolt(): Int { private fun getTurnsBeforeRevolt() =
val score = ((4 + Random().nextInt(3)) * max(gameInfo.gameParameters.gameSpeed.modifier, 1f)).toInt() ((4 + Random().nextInt(3)) * max(gameInfo.gameParameters.gameSpeed.modifier, 1f)).toInt()
return score
}
/** Modify gold by a given amount making sure it does neither overflow nor underflow. /** Modify gold by a given amount making sure it does neither overflow nor underflow.
* @param delta the amount to add (can be negative) * @param delta the amount to add (can be negative)

View File

@ -82,7 +82,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo): BaseScreen() {
val relationLevel = civ.getDiplomacyManager(viewingCiv).relationshipLevel() val relationLevel = civ.getDiplomacyManager(viewingCiv).relationshipLevel()
val relationshipIcon = if (civ.isCityState() && relationLevel == RelationshipLevel.Ally) val relationshipIcon = if (civ.isCityState() && relationLevel == RelationshipLevel.Ally)
ImageGetter.getImage("OtherIcons/Star") ImageGetter.getImage("OtherIcons/Star")
.surroundWithCircle(size = 30f, color = relationLevel.color).apply { .surroundWithCircle(size = 30f, color = relationLevel.color).apply {
actor.color = Color.GOLD actor.color = Color.GOLD
} }
else else
@ -146,8 +146,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo): BaseScreen() {
if (otherCiv.detailedCivResources.any { it.resource.resourceType != ResourceType.Bonus }) { if (otherCiv.detailedCivResources.any { it.resource.resourceType != ResourceType.Bonus }) {
val resourcesTable = Table() val resourcesTable = Table()
resourcesTable.add("{Resources}: ".toLabel()).padRight(10f) resourcesTable.add("{Resources}: ".toLabel()).padRight(10f)
val cityStateResources = CityStateFunctions(otherCiv) val cityStateResources = otherCiv.cityStateFunctions.getCityStateResourcesForAlly()
.getCityStateResourcesForAlly()
for (supplyList in cityStateResources) { for (supplyList in cityStateResources) {
if (supplyList.resource.resourceType == ResourceType.Bonus) if (supplyList.resource.resourceType == ResourceType.Bonus)
continue continue
@ -374,7 +373,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo): BaseScreen() {
diplomacyTable.addSeparator() diplomacyTable.addSeparator()
diplomacyTable.add(getQuestTable(assignedQuest)).row() diplomacyTable.add(getQuestTable(assignedQuest)).row()
} }
for (target in otherCiv.getKnownCivs().filter { otherCiv.questManager.warWithMajorActive(it) }) { for (target in otherCiv.getKnownCivs().filter { otherCiv.questManager.warWithMajorActive(it) }) {
diplomacyTable.addSeparator() diplomacyTable.addSeparator()
diplomacyTable.add(getWarWithMajorTable(target, otherCiv)).row() diplomacyTable.add(getWarWithMajorTable(target, otherCiv)).row()
@ -580,7 +579,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo): BaseScreen() {
private fun getWarWithMajorTable(target: CivilizationInfo, otherCiv: CivilizationInfo): Table { private fun getWarWithMajorTable(target: CivilizationInfo, otherCiv: CivilizationInfo): Table {
val warTable = Table() val warTable = Table()
warTable.defaults().pad(10f) warTable.defaults().pad(10f)
val title = "War against [${target.civName}]" val title = "War against [${target.civName}]"
val description = "We need you to help us defend against [${target.civName}]. Killing [${otherCiv.questManager.unitsToKill(target)}] of their military units would slow their offensive." val description = "We need you to help us defend against [${target.civName}]. Killing [${otherCiv.questManager.unitsToKill(target)}] of their military units would slow their offensive."
val progress = if (viewingCiv.knows(target)) "Currently you have killed [${otherCiv.questManager.unitsKilledSoFar(target, viewingCiv)}] of their military units." val progress = if (viewingCiv.knows(target)) "Currently you have killed [${otherCiv.questManager.unitsKilledSoFar(target, viewingCiv)}] of their military units."
@ -591,7 +590,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo): BaseScreen() {
.width(stage.width / 2).row() .width(stage.width / 2).row()
warTable.add(progress.toLabel().apply { wrap = true; setAlignment(Align.center) }) warTable.add(progress.toLabel().apply { wrap = true; setAlignment(Align.center) })
.width(stage.width / 2).row() .width(stage.width / 2).row()
return warTable return warTable
} }

View File

@ -16,15 +16,20 @@ import com.unciv.Constants
* @param fontSize Text size for [String.toLabel]. * @param fontSize Text size for [String.toLabel].
* @param fontColor Text colour for [String.toLabel]. * @param fontColor Text colour for [String.toLabel].
*/ */
class IconTextButton(text: String, val icon: Actor? = null, fontSize: Int = Constants.defaultFontSize, fontColor: Color = Color.WHITE): Button(BaseScreen.skin) { class IconTextButton(
val button = Button(BaseScreen.skin) text: String,
val icon: Actor? = null,
fontSize: Int = Constants.defaultFontSize,
fontColor: Color = Color.WHITE
): Button(BaseScreen.skin) {
/** [Label] instance produced by and with content and formatting as specified to [String.toLabel]. */ /** [Label] instance produced by and with content and formatting as specified to [String.toLabel]. */
val label = text.toLabel(fontColor, fontSize) val label = text.toLabel(fontColor, fontSize)
/** Table cell containing the [icon] if any, or `null`. */ /** Table cell containing the [icon] if any, or `null`. */
val iconCell: Cell<Actor>? = if (icon != null) { val iconCell: Cell<Actor>? =
if (icon != null) {
val size = fontSize.toFloat() val size = fontSize.toFloat()
icon.setSize(size,size) icon.setSize(size,size)
icon.setOrigin(Align.center) icon.setOrigin(Align.center)
add(icon).size(size).padRight(size / 3) add(icon).size(size).padRight(size / 3)
} else null } else null
/** Table cell instance containing the [label]. */ /** Table cell instance containing the [label]. */