diff --git a/android/assets/jsons/translations/template.properties b/android/assets/jsons/translations/template.properties index bccf541b29..6425276d03 100644 --- a/android/assets/jsons/translations/template.properties +++ b/android/assets/jsons/translations/template.properties @@ -1379,6 +1379,8 @@ You have been defeated. Your civilization has been overwhelmed by its many foes. One more turn...! = Destroy [civName] = Capture [cityName] = +Destroy ? * [civName] = +Capture ? * [cityName] = Our status = Global status = Rankings = @@ -1604,6 +1606,7 @@ Minimal Faith required for\nthe next [Great Prophet]: = Religions to be founded: [amount] = Available religion symbols = Number of civilizations * [amount] + [amount2] = +Estimated Number of civilizations * [amount] + [amount2] = Religions already founded = Available founder beliefs = Available follower beliefs = diff --git a/core/src/com/unciv/logic/civilization/Civilization.kt b/core/src/com/unciv/logic/civilization/Civilization.kt index a252108fba..f3440767ff 100644 --- a/core/src/com/unciv/logic/civilization/Civilization.kt +++ b/core/src/com/unciv/logic/civilization/Civilization.kt @@ -32,6 +32,7 @@ import com.unciv.logic.map.mapunit.MapUnit import com.unciv.logic.map.tile.Tile import com.unciv.logic.trade.TradeRequest import com.unciv.models.Counter +import com.unciv.models.metadata.GameParameters // Kdoc only import com.unciv.models.ruleset.Building import com.unciv.models.ruleset.Policy import com.unciv.models.ruleset.Victory @@ -53,7 +54,6 @@ import com.unciv.models.stats.Stats import com.unciv.models.translations.tr import com.unciv.ui.components.extensions.toPercent import com.unciv.ui.screens.victoryscreen.RankingType -import java.util.* import kotlin.math.max import kotlin.math.min import kotlin.math.roundToInt @@ -795,8 +795,7 @@ class Civilization : IsPartOfGameInfoSerialization { city.cityConstructions.addBuilding(city.capitalCityIndicator()) city.isBeingRazed = false // stop razing the new capital if it was being razed } - if (oldCapital != null) - oldCapital.cityConstructions.removeBuilding(oldCapital.capitalCityIndicator()) + oldCapital?.cityConstructions?.removeBuilding(oldCapital.capitalCityIndicator()) } fun moveCapitalToNextLargest() { @@ -814,6 +813,20 @@ class Civilization : IsPartOfGameInfoSerialization { fun getAllyCiv() = allyCivName fun setAllyCiv(newAllyName: String?) { allyCivName = newAllyName } + /** Determine if this civ (typically as human player) is allowed to know how many major civs there are + * + * Can only be `true` if [GameParameters.randomNumberOfPlayers] is `true`, but in that case + * we try to see if the player _could_ be certain with a modicum of cleverness... + */ + fun hideCivCount(): Boolean { + if (!gameInfo.gameParameters.randomNumberOfPlayers) return false + val knownCivs = 1 + getKnownCivs().count { it.isMajorCiv() } + if (knownCivs >= gameInfo.gameParameters.maxNumberOfPlayers) return false + if (hasUnique(UniqueType.OneTimeRevealEntireMap)) return false + // Other ideas? viewableTiles.size == gameInfo.tileMap.tileList.size seems not quite useful... + return true + } + fun asPreview() = CivilizationInfoPreview(this) } diff --git a/core/src/com/unciv/logic/civilization/managers/ReligionManager.kt b/core/src/com/unciv/logic/civilization/managers/ReligionManager.kt index fd92dcb07c..03063d9c3b 100644 --- a/core/src/com/unciv/logic/civilization/managers/ReligionManager.kt +++ b/core/src/com/unciv/logic/civilization/managers/ReligionManager.kt @@ -217,11 +217,25 @@ class ReligionManager : IsPartOfGameInfoSerialization { fun remainingFoundableReligionsBreakdown() = sequence { val gameInfo = civInfo.gameInfo val ruleset = gameInfo.ruleset + yield("Available religion symbols" to ruleset.religions.size) + val multiplier = ruleset.modOptions.constants.religionLimitMultiplier val base = ruleset.modOptions.constants.religionLimitBase val civCount = gameInfo.civilizations.count { it.isMajorCiv() } - yield("Available religion symbols" to ruleset.religions.size) - yield("Number of civilizations * [$multiplier] + [$base]" to base + (civCount * multiplier).toInt()) + val hideCivCount = civInfo.hideCivCount() + if (hideCivCount) { + val knownCivs = 1 + civInfo.getKnownCivs().count { it.isMajorCiv() } + val estimatedCivCount = ( + gameInfo.gameParameters.minNumberOfPlayers.coerceAtLeast(knownCivs) + + gameInfo.gameParameters.maxNumberOfPlayers - 1 + ) / 2 + 1 + val civsAndBase = base + (estimatedCivCount * multiplier).toInt() + yield("Estimated number of civilizations * [$multiplier] + [$base]" to civsAndBase) + } else { + val civsAndBase = base + (civCount * multiplier).toInt() + yield("Number of civilizations * [$multiplier] + [$base]" to civsAndBase) + } + yield("Religions already founded" to foundedReligionsCount()) yield("Available founder beliefs" to numberOfBeliefsAvailable(BeliefType.Founder)) yield("Available follower beliefs" to numberOfBeliefsAvailable(BeliefType.Follower)) diff --git a/core/src/com/unciv/models/ruleset/Victory.kt b/core/src/com/unciv/models/ruleset/Victory.kt index 8a007bc711..1152cc0fb0 100644 --- a/core/src/com/unciv/models/ruleset/Victory.kt +++ b/core/src/com/unciv/models/ruleset/Victory.kt @@ -73,7 +73,7 @@ class Milestone(val uniqueDescription: String, private val parentVictory: Victor val type: MilestoneType? = MilestoneType.values().firstOrNull { uniqueDescription.getPlaceholderText() == it.text.getPlaceholderText() } val params = uniqueDescription.getPlaceholderParameters() - fun getIncompleteSpaceshipParts(civInfo: Civilization): Counter { + private fun getIncompleteSpaceshipParts(civInfo: Civilization): Counter { val incompleteSpaceshipParts = parentVictory.requiredSpaceshipPartsAsCounter.clone() incompleteSpaceshipParts.remove(civInfo.victoryManager.currentsSpaceshipParts) return incompleteSpaceshipParts @@ -136,14 +136,20 @@ class Milestone(val uniqueDescription: String, private val parentVictory: Victor val amountDone = if (completed) amountToDo else civInfo.originalMajorCapitalsOwned() - "{$uniqueDescription} ($amountDone/$amountToDo)" + if (civInfo.hideCivCount()) + "{$uniqueDescription} ($amountDone/?)" + else + "{$uniqueDescription} ($amountDone/$amountToDo)" } MilestoneType.DestroyAllPlayers -> { val amountToDo = civInfo.gameInfo.civilizations.count { it.isMajorCiv() } - 1 // Don't count yourself val amountDone = if (completed) amountToDo - else amountToDo - (civInfo.gameInfo.getAliveMajorCivs().filter { it != civInfo }.size) - "{$uniqueDescription} ($amountDone/$amountToDo)" + else amountToDo - (civInfo.gameInfo.getAliveMajorCivs().count { it != civInfo }) + if (civInfo.hideCivCount()) + "{$uniqueDescription} ($amountDone/?)" + else + "{$uniqueDescription} ($amountDone/$amountToDo)" } MilestoneType.AddedSSPartsInCapital -> { val completeSpaceshipParts = civInfo.victoryManager.currentsSpaceshipParts @@ -185,8 +191,10 @@ class Milestone(val uniqueDescription: String, private val parentVictory: Victor val buttons = mutableListOf(headerButton) when (type) { // No extra buttons necessary + null, MilestoneType.BuiltBuilding, MilestoneType.BuildingBuiltGlobally, MilestoneType.ScoreAfterTimeOut, MilestoneType.WinDiplomaticVote -> {} + MilestoneType.AddedSSPartsInCapital -> { val completedSpaceshipParts = civInfo.victoryManager.currentsSpaceshipParts val incompleteSpaceshipParts = getIncompleteSpaceshipParts(civInfo) @@ -204,23 +212,30 @@ class Milestone(val uniqueDescription: String, private val parentVictory: Victor } MilestoneType.DestroyAllPlayers -> { - val majorCivs = civInfo.gameInfo.civilizations.filter { it.isMajorCiv() && it != civInfo } - for (civ in majorCivs) { + val hideCivCount = civInfo.hideCivCount() + for (civ in civInfo.gameInfo.civilizations) { + if (civ == civInfo || !civ.isMajorCiv()) continue + if (hideCivCount && !civInfo.knows(civ)) continue val milestoneText = - if (civInfo.knows(civ) || !civ.isAlive()) "Destroy [${civ.civName}]" + if (civInfo.knows(civ) || civ.isDefeated()) "Destroy [${civ.civName}]" else "Destroy [${Constants.unknownNationName}]" - buttons.add(getMilestoneButton(milestoneText, !civ.isAlive())) + buttons.add(getMilestoneButton(milestoneText, civ.isDefeated())) } + if (hideCivCount) buttons.add(getMilestoneButton("Destroy ? * [${Constants.unknownNationName}]", false)) } MilestoneType.CaptureAllCapitals -> { + val hideCivCount = civInfo.hideCivCount() val originalCapitals = civInfo.gameInfo.getCities().filter { it.isOriginalCapital } for (city in originalCapitals) { + val isKnown = civInfo.hasExplored(city.getCenterTile()) + if (hideCivCount && !isKnown) continue val milestoneText = - if (civInfo.hasExplored(city.getCenterTile())) "Capture [${city.name}]" + if (isKnown) "Capture [${city.name}]" else "Capture [${Constants.unknownCityName}]" buttons.add(getMilestoneButton(milestoneText, city.civ == civInfo)) } + if (hideCivCount) buttons.add(getMilestoneButton("Capture ? * [${Constants.unknownCityName}]", false)) } MilestoneType.CompletePolicyBranches -> { @@ -229,6 +244,7 @@ class Milestone(val uniqueDescription: String, private val parentVictory: Victor buttons.add(getMilestoneButton(finisher, civInfo.policies.isAdopted(finisher))) } } + MilestoneType.WorldReligion -> { val majorCivs = civInfo.gameInfo.civilizations.filter { it.isMajorCiv() && it.isAlive() } val civReligion = civInfo.religionManager.religion @@ -242,7 +258,6 @@ class Milestone(val uniqueDescription: String, private val parentVictory: Victor buttons.add(getMilestoneButton(milestoneText, milestoneMet)) } } - null -> {} } return buttons } diff --git a/core/src/com/unciv/ui/screens/overviewscreen/ReligionOverviewTable.kt b/core/src/com/unciv/ui/screens/overviewscreen/ReligionOverviewTable.kt index 860fef25b2..b52ef069e2 100644 --- a/core/src/com/unciv/ui/screens/overviewscreen/ReligionOverviewTable.kt +++ b/core/src/com/unciv/ui/screens/overviewscreen/ReligionOverviewTable.kt @@ -68,34 +68,37 @@ class ReligionOverviewTab( private fun Table.addCivSpecificStats() { // This is not Civ-specific, but -oh well- still fits - val remaining = viewingPlayer.religionManager.remainingFoundableReligions() val minWidth = max(religionButtonLabel.prefWidth, overviewScreen.stage.width / 3) - val headerText = "Religions to be founded: [$remaining]" + val manager = viewingPlayer.religionManager + val headerText = + if (viewingPlayer.hideCivCount()) "Religions to be founded: [?]" + else "Religions to be founded: [${manager.remainingFoundableReligions()}]" val religionCountExpander = ExpanderTab( headerText, fontSize = 18, headerPad = 5f, - startsOutOpened = false, defaultPad = 0f, expanderWidth = minWidth + startsOutOpened = false, defaultPad = 0f, expanderWidth = minWidth, + onChange = { overviewScreen.resizePage(this@ReligionOverviewTab) } ) { it.defaults().padTop(10f) - for ((text, num) in viewingPlayer.religionManager.remainingFoundableReligionsBreakdown()) { + for ((text, num) in manager.remainingFoundableReligionsBreakdown()) { it.add(text.toLabel()) it.add(num.toString().toLabel(alignment = Align.right)).right().row() } } add(religionCountExpander).colspan(2).growX().row() - if (viewingPlayer.religionManager.canGenerateProphet()) { + if (manager.canGenerateProphet()) { add("Minimal Faith required for\nthe next [great prophet equivalent]:" - .fillPlaceholders(viewingPlayer.religionManager.getGreatProphetEquivalent()!!) + .fillPlaceholders(manager.getGreatProphetEquivalent()!!) .toLabel() ) add( - (viewingPlayer.religionManager.faithForNextGreatProphet() + 1) + (manager.faithForNextGreatProphet() + 1) .toLabel() ).right().row() } add("Religious status:".toLabel()).left() - add(viewingPlayer.religionManager.religionState.toString().toLabel()).right().row() + add(manager.religionState.toString().toLabel()).right().row() } private fun loadReligionButtons() {