diff --git a/android/assets/jsons/Civ V - Vanilla/Techs.json b/android/assets/jsons/Civ V - Vanilla/Techs.json index 1124cbdbff..88f69eddf2 100644 --- a/android/assets/jsons/Civ V - Vanilla/Techs.json +++ b/android/assets/jsons/Civ V - Vanilla/Techs.json @@ -612,7 +612,7 @@ "name": "Future Tech", "row": 5, "prerequisites": ["Nanotechnology","Particle Physics","Satellites"], - "uniques": ["Who knows what the future holds?"], + "uniques": ["Who knows what the future holds?", "Can be continually researched"], "quote": "'I think we agree, the past is over.' - George W. Bush" } ] diff --git a/core/src/com/unciv/logic/automation/NextTurnAutomation.kt b/core/src/com/unciv/logic/automation/NextTurnAutomation.kt index eb9ddcee81..14bdd12f34 100644 --- a/core/src/com/unciv/logic/automation/NextTurnAutomation.kt +++ b/core/src/com/unciv/logic/automation/NextTurnAutomation.kt @@ -14,7 +14,6 @@ import com.unciv.logic.trade.* import com.unciv.models.ruleset.VictoryType import com.unciv.models.ruleset.tech.Technology import com.unciv.models.translations.tr -import java.lang.reflect.Modifier import kotlin.math.min object NextTurnAutomation{ @@ -153,27 +152,24 @@ object NextTurnAutomation{ private fun chooseTechToResearch(civInfo: CivilizationInfo) { if (civInfo.tech.techsToResearch.isEmpty()) { val researchableTechs = civInfo.gameInfo.ruleSet.technologies.values - .filter { !civInfo.tech.isResearched(it.name) && civInfo.tech.canBeResearched(it.name) } + .filter { civInfo.tech.canBeResearched(it.name) } val techsGroups = researchableTechs.groupBy { it.cost } val costs = techsGroups.keys.sorted() - val tech: Technology - if (researchableTechs.isEmpty()) { // no non-researched techs available, go for future tech - civInfo.tech.techsToResearch.add(Constants.futureTech) - return - } + if (researchableTechs.isEmpty()) return - val techsCheapest = techsGroups[costs[0]]!! + val cheapestTechs = techsGroups[costs[0]]!! //Do not consider advanced techs if only one tech left in cheapest groupe - if (techsCheapest.size == 1 || costs.size == 1) { - tech = techsCheapest.random() + val techToResearch: Technology + if (cheapestTechs.size == 1 || costs.size == 1) { + techToResearch = cheapestTechs.random() } else { //Choose randomly between cheapest and second cheapest groupe val techsAdvanced = techsGroups[costs[1]]!! - tech = (techsCheapest + techsAdvanced).random() + techToResearch = (cheapestTechs + techsAdvanced).random() } - civInfo.tech.techsToResearch.add(tech.name) + civInfo.tech.techsToResearch.add(techToResearch.name) } } diff --git a/core/src/com/unciv/logic/civilization/TechManager.kt b/core/src/com/unciv/logic/civilization/TechManager.kt index 8a7639bbab..c2a2739c8f 100644 --- a/core/src/com/unciv/logic/civilization/TechManager.kt +++ b/core/src/com/unciv/logic/civilization/TechManager.kt @@ -60,8 +60,10 @@ class TechManager { if (civInfo.isPlayerCivilization()) techCost *= civInfo.getDifficulty().researchCostModifier techCost *= civInfo.gameInfo.gameParameters.gameSpeed.modifier - val techsResearchedKnownCivs = civInfo.getKnownCivs().count { it.isMajorCiv() && it.tech.isResearched(techName) } - val undefeatedCivs = civInfo.gameInfo.civilizations.count { it.isMajorCiv() && !it.isDefeated() } + val techsResearchedKnownCivs = civInfo.getKnownCivs() + .count { it.isMajorCiv() && it.tech.isResearched(techName) } + val undefeatedCivs = civInfo.gameInfo.civilizations + .count { it.isMajorCiv() && !it.isDefeated() } // https://forums.civfanatics.com/threads/the-mechanics-of-overflow-inflation.517970/ techCost /= 1 + techsResearchedKnownCivs / undefeatedCivs.toFloat() * 0.3f // http://www.civclub.net/bbs/forum.php?mod=viewthread&tid=123976 @@ -96,10 +98,13 @@ class TechManager { return max(1, ceil(remainingScienceToTech(techName).toDouble() / civInfo.statsForNextTurn.science).toInt()) } - fun isResearched(TechName: String): Boolean = techsResearched.contains(TechName) + fun isResearched(techName: String): Boolean = techsResearched.contains(techName) - fun canBeResearched(TechName: String): Boolean { - return getRuleset().technologies[TechName]!!.prerequisites.all { isResearched(it) } + fun canBeResearched(techName: String): Boolean { + val tech = getRuleset().technologies[techName]!! + if (isResearched(tech.name) && !tech.isContinuallyResearchable()) + return false + return tech.prerequisites.all { isResearched(it) } } fun getTechUniques() = researchedTechUniques @@ -116,7 +121,7 @@ class TechManager { val techToCheck = checkPrerequisites.pop() // future tech can have been researched even when we're researching it, // so...if we skip it we'll end up with 0 techs in the "required techs", which will mean that we don't have anything to research. Yeah. - if (techToCheck.name != Constants.futureTech && + if (!techToCheck.isContinuallyResearchable() && (isResearched(techToCheck.name) || prerequisites.contains(techToCheck))) continue //no need to add or check prerequisites for (prerequisite in techToCheck.prerequisites) @@ -204,8 +209,6 @@ class TechManager { } fun addTechnology(techName: String) { - if (techName != Constants.futureTech) - techsToResearch.remove(techName) techsInProgress.remove(techName) val previousEra = civInfo.getEra() @@ -213,6 +216,8 @@ class TechManager { // this is to avoid concurrent modification problems val newTech = getRuleset().technologies[techName]!! + if (!newTech.isContinuallyResearchable()) + techsToResearch.remove(techName) researchedTechnologies = researchedTechnologies.withItem(newTech) for (unique in newTech.uniques) researchedTechUniques = researchedTechUniques.withItem(unique) @@ -325,4 +330,8 @@ class TechManager { return if (canBuildRailroad) RoadStatus.Railroad else RoadStatus.Road } + + fun canResearchTech(): Boolean { + return getRuleset().technologies.values.any { canBeResearched(it.name) } + } } \ No newline at end of file diff --git a/core/src/com/unciv/models/ruleset/tech/Technology.kt b/core/src/com/unciv/models/ruleset/tech/Technology.kt index 7693e09b94..98de11fa6d 100644 --- a/core/src/com/unciv/models/ruleset/tech/Technology.kt +++ b/core/src/com/unciv/models/ruleset/tech/Technology.kt @@ -18,7 +18,7 @@ class Technology { var column: TechColumn? = null // The column that this tech is in the tech tree var row: Int = 0 - var quote="" + var quote = "" fun getDescription(ruleset: Ruleset): String { val lineList = ArrayList() // more readable than StringBuilder, with same performance for our use-case @@ -81,12 +81,12 @@ class Technology { return enabledBuildings } - fun getEnabledUnits(civInfo:CivilizationInfo): List { + fun getEnabledUnits(civInfo: CivilizationInfo): List { var enabledUnits = civInfo.gameInfo.ruleSet.units.values.filter { it.requiredTech == name && (it.uniqueTo == null || it.uniqueTo == civInfo.civName) } - val replacedUnits = civInfo.gameInfo.ruleSet.units.values.filter { it.uniqueTo==civInfo.civName } + val replacedUnits = civInfo.gameInfo.ruleSet.units.values.filter { it.uniqueTo == civInfo.civName } .mapNotNull { it.replaces } enabledUnits = enabledUnits.filter { it.name !in replacedUnits } @@ -96,9 +96,9 @@ class Technology { return enabledUnits } - override fun toString(): String { - return name - } + override fun toString() = name fun era(): String = column!!.era + + fun isContinuallyResearchable() = uniques.contains("Can be continually researched") } diff --git a/core/src/com/unciv/ui/pickerscreens/TechPickerScreen.kt b/core/src/com/unciv/ui/pickerscreens/TechPickerScreen.kt index ed4ca420d7..24852ed41e 100644 --- a/core/src/com/unciv/ui/pickerscreens/TechPickerScreen.kt +++ b/core/src/com/unciv/ui/pickerscreens/TechPickerScreen.kt @@ -26,7 +26,7 @@ class TechPickerScreen(internal val civInfo: CivilizationInfo, centerOnTech: Tec // All these are to counter performance problems when updating buttons for all techs. private var researchableTechs = civInfo.gameInfo.ruleSet.technologies.keys - .filter { civTech.canBeResearched(it) && !civTech.isResearched(it) }.toHashSet() + .filter { civTech.canBeResearched(it) }.toHashSet() private val currentTechColor = colorFromRGB(7,46,43) private val researchedTechColor = colorFromRGB(133,112,39) @@ -170,7 +170,7 @@ class TechPickerScreen(internal val civInfo: CivilizationInfo, centerOnTech: Tec prerequisiteCoords.x, prerequisiteCoords.y, 2f) val lineColor = when { - civTech.isResearched(tech.name) && tech.name != Constants.futureTech -> researchedTechColor + civTech.isResearched(tech.name) && !tech.isContinuallyResearchable() -> researchedTechColor civTech.isResearched(prerequisite) -> researchableTechColor else -> Color.GRAY } @@ -210,7 +210,7 @@ class TechPickerScreen(internal val civInfo: CivilizationInfo, centerOnTech: Tec civInfo.tech.addTechnology(tech.name) } - if (civTech.isResearched(tech.name) && tech.name != Constants.futureTech) { + if (civTech.isResearched(tech.name) && !tech.isContinuallyResearchable()) { rightSideButton.setText("Pick a tech".tr()) rightSideButton.disable() setButtonsInfo() @@ -242,8 +242,7 @@ class TechPickerScreen(internal val civInfo: CivilizationInfo, centerOnTech: Tec private fun selectTechnologyForFreeTech(tech: Technology) { - if (researchableTechs.contains(tech.name) || - (tech.name==Constants.futureTech && civTech.canBeResearched(tech.name))) { + if (researchableTechs.contains(tech.name)) { pick("Pick [${selectedTech!!.name}] as free tech".tr()) } else { rightSideButton.setText("Pick a free tech".tr()) diff --git a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt index ca793fcd88..d604ade9b7 100644 --- a/core/src/com/unciv/ui/worldscreen/WorldScreen.kt +++ b/core/src/com/unciv/ui/worldscreen/WorldScreen.kt @@ -439,11 +439,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() { techButtonHolder.isVisible = viewingCiv.cities.isNotEmpty() techButtonHolder.clearChildren() - val researchableTechs = viewingCiv.gameInfo.ruleSet.technologies.values.filter { !viewingCiv.tech.isResearched(it.name) && viewingCiv.tech.canBeResearched(it.name) } - if (viewingCiv.tech.currentTechnology() == null && researchableTechs.isEmpty()) - viewingCiv.tech.techsToResearch.add(Constants.futureTech) - - if (viewingCiv.tech.currentTechnology() == null) { + if (viewingCiv.tech.currentTechnology() == null && viewingCiv.tech.canResearchTech()) { val buttonPic = Table() buttonPic.background = ImageGetter.getRoundedEdgeTableBackground(colorFromRGB(7, 46, 43)) buttonPic.defaults().pad(20f)