diff --git a/core/src/com/unciv/logic/automation/Automation.kt b/core/src/com/unciv/logic/automation/Automation.kt index b9a914e36d..8bc6d4f0b5 100644 --- a/core/src/com/unciv/logic/automation/Automation.kt +++ b/core/src/com/unciv/logic/automation/Automation.kt @@ -101,7 +101,7 @@ class Automation { chosenUnit = militaryUnits.filter { it.unitType== UnitType.Ranged }.maxBy { it.cost }!! else{ // randomize type of unit and take the most expensive of its kind - val chosenUnitType = militaryUnits.map { it.unitType }.distinct().filterNot{it==UnitType.Scout}.random() + val chosenUnitType = militaryUnits.map { it.unitType }.distinct().filterNot{it==UnitType.Scout}.toList().random() chosenUnit = militaryUnits.filter { it.unitType==chosenUnitType }.maxBy { it.cost }!! } return chosenUnit.name diff --git a/core/src/com/unciv/logic/automation/ConstructionAutomation.kt b/core/src/com/unciv/logic/automation/ConstructionAutomation.kt index b6db33b0a1..ce3b334782 100644 --- a/core/src/com/unciv/logic/automation/ConstructionAutomation.kt +++ b/core/src/com/unciv/logic/automation/ConstructionAutomation.kt @@ -18,8 +18,10 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ val cityInfo = cityConstructions.cityInfo val civInfo = cityInfo.civInfo - val buildableNotWonders = cityConstructions.getBuildableBuildings().filterNot { it.isWonder || it.isNationalWonder } - val buildableWonders = cityConstructions.getBuildableBuildings().filter { it.isWonder || it.isNationalWonder } + val buildableNotWonders = cityConstructions.getBuildableBuildings() + .filterNot { it.isWonder || it.isNationalWonder } + val buildableWonders = cityConstructions.getBuildableBuildings() + .filter { it.isWonder || it.isNationalWonder } val civUnits = civInfo.getCivUnits() val militaryUnits = civUnits.filter { !it.type.isCivilian()}.size @@ -118,6 +120,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ private fun addWorkerChoice() { if(civInfo.getIdleUnits().any { it.name==Constants.worker && it.action== Constants.unitActionAutomation}) return // If we have automated workers who have no work to do then it's silly to construct new workers. + val citiesCountedTowardsWorkers = min(5, cities) // above 5 cities, extra cities won't make us want more workers if (workers < citiesCountedTowardsWorkers * 0.6f && civUnits.none { it.name==Constants.worker && it.isIdle() }) { var modifier = citiesCountedTowardsWorkers / (workers + 0.1f) @@ -127,7 +130,8 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ } private fun addCultureBuildingChoice() { - val cultureBuilding = buildableNotWonders.filter { it.isStatRelated(Stat.Culture) }.minBy { it.cost } + val cultureBuilding = buildableNotWonders + .filter { it.isStatRelated(Stat.Culture) }.minBy { it.cost } if (cultureBuilding != null) { var modifier = 0.5f if(cityInfo.cityStats.currentCityStats.culture==0f) // It won't grow if we don't help it @@ -149,7 +153,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ } private fun addWondersChoice() { - if (buildableWonders.isNotEmpty()) { + if (buildableWonders.any()) { fun getWonderPriority(wonder: Building): Float { if (preferredVictoryType == VictoryType.Cultural && wonder.name in listOf("Sistine Chapel", "Eiffel Tower", "Cristo Redentor", "Neuschwanstein", "Sydney Opera House")) @@ -167,21 +171,20 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ return 1f } - val wondersByPriority = buildableWonders - .sortedByDescending { getWonderPriority(it) } - val wonder = wondersByPriority.first() + val highestPriorityWonder = buildableWonders + .maxBy { getWonderPriority(it) }!! val citiesBuildingWonders = civInfo.cities .count { it.cityConstructions.isBuildingWonder() } - var modifier = 2f * getWonderPriority(wonder) / (citiesBuildingWonders + 1) + var modifier = 2f * getWonderPriority(highestPriorityWonder) / (citiesBuildingWonders + 1) if (!cityIsOverAverageProduction) modifier /= 5 // higher production cities will deal with this - addChoice(relativeCostEffectiveness, wonder.name, modifier) + addChoice(relativeCostEffectiveness, highestPriorityWonder.name, modifier) } } private fun addUnitTrainingBuildingChoice() { - val unitTrainingBuilding = buildableNotWonders.filter { it.xpForNewUnits > 0 } - .minBy { it.cost } + val unitTrainingBuilding = buildableNotWonders.asSequence() + .filter { it.xpForNewUnits > 0 }.minBy { it.cost } if (unitTrainingBuilding != null && (preferredVictoryType != VictoryType.Cultural || isAtWar)) { var modifier = if (cityIsOverAverageProduction) 0.5f else 0.1f // You shouldn't be cranking out units anytime soon if (isAtWar) modifier *= 2 @@ -192,8 +195,8 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ } private fun addDefenceBuildingChoice() { - val defensiveBuilding = buildableNotWonders.filter { it.cityStrength > 0 } - .minBy { it.cost } + val defensiveBuilding = buildableNotWonders.asSequence() + .filter { it.cityStrength > 0 }.minBy { it.cost } if (defensiveBuilding != null && (isAtWar || preferredVictoryType != VictoryType.Cultural)) { var modifier = 0.2f if (isAtWar) modifier = 0.5f @@ -208,7 +211,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ } private fun addHappinessBuildingChoice() { - val happinessBuilding = buildableNotWonders + val happinessBuilding = buildableNotWonders.asSequence() .filter { it.isStatRelated(Stat.Happiness) || it.uniques.contains("Remove extra unhappiness from annexed cities") } .minBy { it.cost } @@ -222,7 +225,8 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ } private fun addScienceBuildingChoice() { - val scienceBuilding = buildableNotWonders.filter { it.isStatRelated(Stat.Science) || it.name=="Library" } // only stat related in unique + val scienceBuilding = buildableNotWonders.asSequence() + .filter { it.isStatRelated(Stat.Science) || it.name=="Library" } // only stat related in unique .minBy { it.cost } if (scienceBuilding != null) { var modifier = 1.1f @@ -233,7 +237,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ } private fun addGoldBuildingChoice() { - val goldBuilding = buildableNotWonders.filter { it.isStatRelated(Stat.Gold) } + val goldBuilding = buildableNotWonders.asSequence().filter { it.isStatRelated(Stat.Gold) } .minBy { it.cost } if (goldBuilding != null) { val modifier = if (civInfo.statsForNextTurn.gold < 0) 3f else 1.2f @@ -244,7 +248,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ private fun addProductionBuildingChoice() { val hasWaterResource = cityInfo.tilesInRange .any { it.isWater && it.resource!=null && it.position in cityInfo.tiles } - val productionBuilding = buildableNotWonders + val productionBuilding = buildableNotWonders.asSequence() .filter { it.isStatRelated(Stat.Production) || (hasWaterResource && (it.uniques.contains("+1 production and gold from all sea resources worked by the city") || it.uniques.contains("+1 production from all sea resources worked by the city")) ) @@ -256,7 +260,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ } private fun addFoodBuildingChoice() { - val foodBuilding = buildableNotWonders.filter { it.isStatRelated(Stat.Food) + val foodBuilding = buildableNotWonders.asSequence().filter { it.isStatRelated(Stat.Food) || it.getBaseBuilding(civInfo.gameInfo.ruleSet).name == "Aqueduct" || it.getBaseBuilding(civInfo.gameInfo.ruleSet).name == "Medical Lab"} // only stat related in unique .minBy { it.cost } if (foodBuilding != null) { diff --git a/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt b/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt index 3da84501f5..6f42efb2b2 100644 --- a/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt +++ b/core/src/com/unciv/logic/automation/SpecificUnitAutomation.kt @@ -19,7 +19,7 @@ class SpecificUnitAutomation{ } fun automateWorkBoats(unit: MapUnit) { - val seaResourcesInCities = unit.civInfo.cities.flatMap { city -> city.getWorkableTiles() } + val seaResourcesInCities = unit.civInfo.cities.asSequence().flatMap { city -> city.getWorkableTiles() } .filter { hasWorkableSeaResource(it, unit.civInfo) && (unit.movement.canMoveTo(it) || unit.currentTile == it) } val closestReachableResource = seaResourcesInCities.sortedBy { it.arialDistanceTo(unit.currentTile) } .firstOrNull { unit.movement.canReach(it) } diff --git a/core/src/com/unciv/logic/city/CityConstructions.kt b/core/src/com/unciv/logic/city/CityConstructions.kt index c44a1bf174..bb94d58633 100644 --- a/core/src/com/unciv/logic/city/CityConstructions.kt +++ b/core/src/com/unciv/logic/city/CityConstructions.kt @@ -6,8 +6,8 @@ import com.unciv.logic.automation.ConstructionAutomation import com.unciv.logic.civilization.AlertType import com.unciv.logic.civilization.PopupAlert import com.unciv.models.ruleset.Building -import com.unciv.models.translations.tr import com.unciv.models.stats.Stats +import com.unciv.models.translations.tr import com.unciv.ui.utils.withItem import com.unciv.ui.utils.withoutItem import java.util.* @@ -33,11 +33,11 @@ class CityConstructions { return toReturn } - internal fun getBuildableBuildings(): List = cityInfo.getRuleset().buildings.values - .filter { it.isBuildable(this) } + internal fun getBuildableBuildings(): Sequence = cityInfo.getRuleset().buildings.values + .asSequence().filter { it.isBuildable(this) } fun getConstructableUnits() = cityInfo.getRuleset().units.values - .filter { it.isBuildable(this) } + .asSequence().filter { it.isBuildable(this) } fun getStats(): Stats { val stats = Stats() @@ -109,7 +109,7 @@ class CityConstructions { throw NotBuildingOrUnitException("$constructionName is not a building or a unit!") } - internal fun getBuiltBuildings(): List = builtBuildingObjects + internal fun getBuiltBuildings(): Sequence = builtBuildingObjects.asSequence() fun containsBuildingOrEquivalent(building: String): Boolean = isBuilt(building) || getBuiltBuildings().any{it.replaces==building} diff --git a/core/src/com/unciv/logic/city/CityInfo.kt b/core/src/com/unciv/logic/city/CityInfo.kt index e2933096c2..7be3b0537f 100644 --- a/core/src/com/unciv/logic/city/CityInfo.kt +++ b/core/src/com/unciv/logic/city/CityInfo.kt @@ -116,7 +116,7 @@ class CityInfo { fun getCenterTile(): TileInfo = centerTileInfo - fun getTiles(): List = tiles.map { tileMap[it] } + fun getTiles(): Sequence = tiles.asSequence().map { tileMap[it] } fun getWorkableTiles() = getTiles().filter { it in tilesInRange } fun isCapital() = cityConstructions.isBuilt("Palace") @@ -192,7 +192,7 @@ class CityInfo { return 0 } - fun getBuildingUniques(): List = cityConstructions.getBuiltBuildings().flatMap { it.uniques } + fun getBuildingUniques(): Sequence = cityConstructions.getBuiltBuildings().flatMap { it.uniques.asSequence() } fun containsBuildingUnique(unique:String) = cityConstructions.getBuiltBuildings().any { it.uniques.contains(unique) } fun getGreatPersonMap():HashMap{ diff --git a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt index 296a30aa5d..73b9dea146 100644 --- a/core/src/com/unciv/logic/civilization/CivilizationInfo.kt +++ b/core/src/com/unciv/logic/civilization/CivilizationInfo.kt @@ -492,7 +492,7 @@ class CivilizationInfo { val city = NextTurnAutomation().getClosestCities(this, otherCiv).city1 val militaryUnit = city.cityConstructions.getConstructableUnits() .filter { !it.unitType.isCivilian() && it.unitType.isLandUnit() } - .random() + .toList().random() placeUnitNearTile(city.location, militaryUnit.name) addNotification("[${otherCiv.civName}] gave us a [${militaryUnit.name}] as gift near [${city.name}]!", null, Color.GREEN) }