mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-16 02:40:41 +07:00
Construction automation optimization (#7504)
This commit is contained in:

committed by
GitHub

parent
0e0e245365
commit
772e7faf54
@ -137,7 +137,7 @@ object Automation {
|
|||||||
val currentChoice = city.cityConstructions.getCurrentConstruction()
|
val currentChoice = city.cityConstructions.getCurrentConstruction()
|
||||||
if (currentChoice is BaseUnit && !currentChoice.isCivilian()) return city.cityConstructions.currentConstructionFromQueue
|
if (currentChoice is BaseUnit && !currentChoice.isCivilian()) return city.cityConstructions.currentConstructionFromQueue
|
||||||
|
|
||||||
var militaryUnits = city.getRuleset().units.values.asSequence()
|
var militaryUnits = city.getRuleset().units.values
|
||||||
.filter { !it.isCivilian() }
|
.filter { !it.isCivilian() }
|
||||||
.filter { allowSpendingResource(city.civInfo, it) }
|
.filter { allowSpendingResource(city.civInfo, it) }
|
||||||
|
|
||||||
@ -154,14 +154,14 @@ object Automation {
|
|||||||
val carryingOnlyUnits = militaryUnits.filter {
|
val carryingOnlyUnits = militaryUnits.filter {
|
||||||
it.hasUnique(UniqueType.CarryAirUnits)
|
it.hasUnique(UniqueType.CarryAirUnits)
|
||||||
&& it.hasUnique(UniqueType.CannotAttack)
|
&& it.hasUnique(UniqueType.CannotAttack)
|
||||||
}.toList()
|
}
|
||||||
|
|
||||||
for (unit in carryingOnlyUnits)
|
for (unit in carryingOnlyUnits)
|
||||||
if (providesUnneededCarryingSlots(unit, city.civInfo))
|
if (providesUnneededCarryingSlots(unit, city.civInfo))
|
||||||
militaryUnits = militaryUnits.filterNot { it == unit }
|
militaryUnits = militaryUnits.filterNot { it == unit }
|
||||||
|
|
||||||
// Only now do we filter out the constructable units because that's a heavier check
|
// Only now do we filter out the constructable units because that's a heavier check
|
||||||
militaryUnits = militaryUnits.filter { it.isBuildable(city.cityConstructions) }.toList().asSequence() // gather once because we have a .any afterwards
|
militaryUnits = militaryUnits.filter { it.isBuildable(city.cityConstructions) } // gather once because we have a .any afterwards
|
||||||
|
|
||||||
val chosenUnit: BaseUnit
|
val chosenUnit: BaseUnit
|
||||||
if (!city.civInfo.isAtWar()
|
if (!city.civInfo.isAtWar()
|
||||||
@ -183,7 +183,7 @@ object Automation {
|
|||||||
}
|
}
|
||||||
// Check the maximum force evaluation for the shortlist so we can prune useless ones (ie scouts)
|
// Check the maximum force evaluation for the shortlist so we can prune useless ones (ie scouts)
|
||||||
val bestForce = bestUnitsForType.maxOf { it.getForceEvaluation() }
|
val bestForce = bestUnitsForType.maxOf { it.getForceEvaluation() }
|
||||||
chosenUnit = bestUnitsForType.filter { it.uniqueTo != null || it.getForceEvaluation() > bestForce / 3 }.toList().random()
|
chosenUnit = bestUnitsForType.filter { it.uniqueTo != null || it.getForceEvaluation() > bestForce / 3 }.random()
|
||||||
}
|
}
|
||||||
return chosenUnit.name
|
return chosenUnit.name
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
package com.unciv.logic.automation
|
package com.unciv.logic.automation
|
||||||
|
|
||||||
import com.unciv.UncivGame
|
|
||||||
import com.unciv.logic.city.CityConstructions
|
import com.unciv.logic.city.CityConstructions
|
||||||
|
import com.unciv.logic.city.INonPerpetualConstruction
|
||||||
import com.unciv.logic.city.PerpetualConstruction
|
import com.unciv.logic.city.PerpetualConstruction
|
||||||
import com.unciv.logic.civilization.CityAction
|
import com.unciv.logic.civilization.CityAction
|
||||||
import com.unciv.logic.civilization.NotificationIcon
|
import com.unciv.logic.civilization.NotificationIcon
|
||||||
import com.unciv.logic.civilization.PlayerType
|
|
||||||
import com.unciv.logic.map.BFS
|
import com.unciv.logic.map.BFS
|
||||||
import com.unciv.models.ruleset.Building
|
import com.unciv.models.ruleset.Building
|
||||||
import com.unciv.models.ruleset.MilestoneType
|
import com.unciv.models.ruleset.MilestoneType
|
||||||
@ -22,13 +21,11 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
private val cityInfo = cityConstructions.cityInfo
|
private val cityInfo = cityConstructions.cityInfo
|
||||||
private val civInfo = cityInfo.civInfo
|
private val civInfo = cityInfo.civInfo
|
||||||
|
|
||||||
private val buildableBuildings = cityConstructions.getBuildableBuildings().toList()
|
private val buildings = cityInfo.getRuleset().buildings.values
|
||||||
private val buildableNotWonders = buildableBuildings
|
private val nonWonders = buildings.filterNot { it.isAnyWonder() }
|
||||||
.filterNot { it.isAnyWonder() }
|
private val wonders = buildings.filter { it.isAnyWonder() }
|
||||||
private val buildableWonders = buildableBuildings
|
|
||||||
.filter { it.isAnyWonder() }
|
|
||||||
|
|
||||||
private val buildableUnits = cityConstructions.getConstructableUnits()
|
private val units = cityInfo.getRuleset().units.values
|
||||||
|
|
||||||
private val civUnits = civInfo.getCivUnits()
|
private val civUnits = civInfo.getCivUnits()
|
||||||
private val militaryUnits = civUnits.count { it.baseUnit.isMilitary() }
|
private val militaryUnits = civUnits.count { it.baseUnit.isMilitary() }
|
||||||
@ -58,6 +55,10 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
choices.add(ConstructionChoice(choice, choiceModifier, cityConstructions.getRemainingWork(choice)))
|
choices.add(ConstructionChoice(choice, choiceModifier, cityConstructions.getRemainingWork(choice)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Collection<INonPerpetualConstruction>.isBuildable(): Collection<INonPerpetualConstruction> {
|
||||||
|
return this.filter { it.isBuildable(cityConstructions) }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun chooseNextConstruction() {
|
fun chooseNextConstruction() {
|
||||||
if (cityConstructions.getCurrentConstruction() !is PerpetualConstruction) return // don't want to be stuck on these forever
|
if (cityConstructions.getCurrentConstruction() !is PerpetualConstruction) return // don't want to be stuck on these forever
|
||||||
@ -140,11 +141,11 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addWorkBoatChoice() {
|
private fun addWorkBoatChoice() {
|
||||||
val buildableWorkboatUnits = buildableUnits
|
val buildableWorkboatUnits = units
|
||||||
.filter {
|
.filter {
|
||||||
it.hasUnique(UniqueType.CreateWaterImprovements)
|
it.hasUnique(UniqueType.CreateWaterImprovements)
|
||||||
&& Automation.allowAutomatedConstruction(civInfo, cityInfo, it)
|
&& Automation.allowAutomatedConstruction(civInfo, cityInfo, it)
|
||||||
}
|
}.isBuildable()
|
||||||
val alreadyHasWorkBoat = buildableWorkboatUnits.any()
|
val alreadyHasWorkBoat = buildableWorkboatUnits.any()
|
||||||
&& !cityInfo.getTiles().any {
|
&& !cityInfo.getTiles().any {
|
||||||
it.civilianUnit?.hasUnique(UniqueType.CreateWaterImprovements) == true
|
it.civilianUnit?.hasUnique(UniqueType.CreateWaterImprovements) == true
|
||||||
@ -172,11 +173,11 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addWorkerChoice() {
|
private fun addWorkerChoice() {
|
||||||
val workerEquivalents = buildableUnits
|
val workerEquivalents = units
|
||||||
.filter {
|
.filter {
|
||||||
it.hasUnique(UniqueType.BuildImprovements)
|
it.hasUnique(UniqueType.BuildImprovements)
|
||||||
&& Automation.allowAutomatedConstruction(civInfo, cityInfo, it)
|
&& Automation.allowAutomatedConstruction(civInfo, cityInfo, it)
|
||||||
}
|
}.isBuildable()
|
||||||
if (workerEquivalents.none()) return // for mods with no worker units
|
if (workerEquivalents.none()) return // for mods with no worker units
|
||||||
|
|
||||||
if (workers < cities) {
|
if (workers < cities) {
|
||||||
@ -187,9 +188,10 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addCultureBuildingChoice() {
|
private fun addCultureBuildingChoice() {
|
||||||
val cultureBuilding = buildableNotWonders
|
val cultureBuilding = nonWonders
|
||||||
.filter { it.isStatRelated(Stat.Culture)
|
.filter { it.isStatRelated(Stat.Culture)
|
||||||
&& Automation.allowAutomatedConstruction(civInfo, cityInfo, it) }.minByOrNull { it.cost }
|
&& Automation.allowAutomatedConstruction(civInfo, cityInfo, it) }
|
||||||
|
.isBuildable().minByOrNull { it.cost }
|
||||||
if (cultureBuilding != null) {
|
if (cultureBuilding != null) {
|
||||||
var modifier = 0.5f
|
var modifier = 0.5f
|
||||||
if (cityInfo.cityStats.currentCityStats.culture == 0f) // It won't grow if we don't help it
|
if (cityInfo.cityStats.currentCityStats.culture == 0f) // It won't grow if we don't help it
|
||||||
@ -200,16 +202,17 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addSpaceshipPartChoice() {
|
private fun addSpaceshipPartChoice() {
|
||||||
val spaceshipPart = (buildableNotWonders + buildableUnits).firstOrNull { it.name in spaceshipParts }
|
val spaceshipPart = (nonWonders + units).filter { it.name in spaceshipParts }.isBuildable()
|
||||||
if (spaceshipPart != null) {
|
if (spaceshipPart.isNotEmpty()) {
|
||||||
val modifier = 2f
|
val modifier = 2f
|
||||||
addChoice(relativeCostEffectiveness, spaceshipPart.name, modifier)
|
addChoice(relativeCostEffectiveness, spaceshipPart.first().name, modifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addOtherBuildingChoice() {
|
private fun addOtherBuildingChoice() {
|
||||||
val otherBuilding = buildableNotWonders
|
val otherBuilding = nonWonders
|
||||||
.filter { Automation.allowAutomatedConstruction(civInfo, cityInfo, it) }.minByOrNull { it.cost }
|
.filter { Automation.allowAutomatedConstruction(civInfo, cityInfo, it) }
|
||||||
|
.isBuildable().minByOrNull { it.cost }
|
||||||
if (otherBuilding != null) {
|
if (otherBuilding != null) {
|
||||||
val modifier = 0.6f
|
val modifier = 0.6f
|
||||||
addChoice(relativeCostEffectiveness, otherBuilding.name, modifier)
|
addChoice(relativeCostEffectiveness, otherBuilding.name, modifier)
|
||||||
@ -246,25 +249,26 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addWondersChoice() {
|
private fun addWondersChoice() {
|
||||||
if (!buildableWonders.any()) return
|
if (!wonders.any()) return
|
||||||
|
|
||||||
val highestPriorityWonder = buildableWonders
|
val highestPriorityWonder = wonders
|
||||||
.filter { Automation.allowAutomatedConstruction(civInfo, cityInfo, it) }
|
.filter { Automation.allowAutomatedConstruction(civInfo, cityInfo, it) }
|
||||||
.maxByOrNull { getWonderPriority(it) }
|
.isBuildable().maxByOrNull { getWonderPriority(it as Building) }
|
||||||
?: return
|
?: return
|
||||||
|
|
||||||
val citiesBuildingWonders = civInfo.cities
|
val citiesBuildingWonders = civInfo.cities
|
||||||
.count { it.cityConstructions.isBuildingWonder() }
|
.count { it.cityConstructions.isBuildingWonder() }
|
||||||
|
|
||||||
var modifier = 2f * getWonderPriority(highestPriorityWonder) / (citiesBuildingWonders + 1)
|
var modifier = 2f * getWonderPriority(highestPriorityWonder as Building) / (citiesBuildingWonders + 1)
|
||||||
if (!cityIsOverAverageProduction) modifier /= 5 // higher production cities will deal with this
|
if (!cityIsOverAverageProduction) modifier /= 5 // higher production cities will deal with this
|
||||||
addChoice(relativeCostEffectiveness, highestPriorityWonder.name, modifier)
|
addChoice(relativeCostEffectiveness, highestPriorityWonder.name, modifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addUnitTrainingBuildingChoice() {
|
private fun addUnitTrainingBuildingChoice() {
|
||||||
val unitTrainingBuilding = buildableNotWonders.asSequence()
|
val unitTrainingBuilding = nonWonders
|
||||||
.filter { it.hasUnique(UniqueType.UnitStartingExperience)
|
.filter { it.hasUnique(UniqueType.UnitStartingExperience)
|
||||||
&& Automation.allowAutomatedConstruction(civInfo, cityInfo, it) }.minByOrNull { it.cost }
|
&& Automation.allowAutomatedConstruction(civInfo, cityInfo, it) }
|
||||||
|
.isBuildable().minByOrNull { it.cost }
|
||||||
if (unitTrainingBuilding != null && (!civInfo.wantsToFocusOn(Victory.Focus.Culture) || isAtWar)) {
|
if (unitTrainingBuilding != null && (!civInfo.wantsToFocusOn(Victory.Focus.Culture) || isAtWar)) {
|
||||||
var modifier = if (cityIsOverAverageProduction) 0.5f else 0.1f // You shouldn't be cranking out units anytime soon
|
var modifier = if (cityIsOverAverageProduction) 0.5f else 0.1f // You shouldn't be cranking out units anytime soon
|
||||||
if (isAtWar) modifier *= 2
|
if (isAtWar) modifier *= 2
|
||||||
@ -275,17 +279,17 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addDefenceBuildingChoice() {
|
private fun addDefenceBuildingChoice() {
|
||||||
val defensiveBuilding = buildableNotWonders.asSequence()
|
val defensiveBuilding = nonWonders
|
||||||
.filter { it.cityStrength > 0
|
.filter { it.cityStrength > 0
|
||||||
&& Automation.allowAutomatedConstruction(civInfo, cityInfo, it)}.minByOrNull { it.cost }
|
&& Automation.allowAutomatedConstruction(civInfo, cityInfo, it)}
|
||||||
|
.isBuildable().minByOrNull { it.cost }
|
||||||
if (defensiveBuilding != null && (isAtWar || !civInfo.wantsToFocusOn(Victory.Focus.Culture))) {
|
if (defensiveBuilding != null && (isAtWar || !civInfo.wantsToFocusOn(Victory.Focus.Culture))) {
|
||||||
var modifier = 0.2f
|
var modifier = 0.2f
|
||||||
if (isAtWar) modifier = 0.5f
|
if (isAtWar) modifier = 0.5f
|
||||||
|
|
||||||
// If this city is the closest city to another civ, that makes it a likely candidate for attack
|
// If this city is the closest city to another civ, that makes it a likely candidate for attack
|
||||||
if (civInfo.getKnownCivs()
|
if (civInfo.getKnownCivs()
|
||||||
.map { NextTurnAutomation.getClosestCities(civInfo, it) }
|
.mapNotNull { NextTurnAutomation.getClosestCities(civInfo, it) }
|
||||||
.filterNotNull()
|
|
||||||
.any { it.city1 == cityInfo })
|
.any { it.city1 == cityInfo })
|
||||||
modifier *= 1.5f
|
modifier *= 1.5f
|
||||||
|
|
||||||
@ -294,11 +298,11 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addHappinessBuildingChoice() {
|
private fun addHappinessBuildingChoice() {
|
||||||
val happinessBuilding = buildableNotWonders.asSequence()
|
val happinessBuilding = nonWonders
|
||||||
.filter { (it.isStatRelated(Stat.Happiness)
|
.filter { (it.isStatRelated(Stat.Happiness)
|
||||||
|| it.uniques.contains("Remove extra unhappiness from annexed cities"))
|
|| it.uniques.contains("Remove extra unhappiness from annexed cities"))
|
||||||
&& Automation.allowAutomatedConstruction(civInfo, cityInfo, it) }
|
&& Automation.allowAutomatedConstruction(civInfo, cityInfo, it) }
|
||||||
.minByOrNull { it.cost }
|
.isBuildable().minByOrNull { it.cost }
|
||||||
if (happinessBuilding != null) {
|
if (happinessBuilding != null) {
|
||||||
var modifier = 1f
|
var modifier = 1f
|
||||||
val civHappiness = civInfo.getHappiness()
|
val civHappiness = civInfo.getHappiness()
|
||||||
@ -310,10 +314,10 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
|
|
||||||
private fun addScienceBuildingChoice() {
|
private fun addScienceBuildingChoice() {
|
||||||
if (allTechsAreResearched) return
|
if (allTechsAreResearched) return
|
||||||
val scienceBuilding = buildableNotWonders.asSequence()
|
val scienceBuilding = nonWonders
|
||||||
.filter { it.isStatRelated(Stat.Science)
|
.filter { it.isStatRelated(Stat.Science)
|
||||||
&& Automation.allowAutomatedConstruction(civInfo, cityInfo, it) }
|
&& Automation.allowAutomatedConstruction(civInfo, cityInfo, it) }
|
||||||
.minByOrNull { it.cost }
|
.isBuildable().minByOrNull { it.cost }
|
||||||
if (scienceBuilding != null) {
|
if (scienceBuilding != null) {
|
||||||
var modifier = 1.1f
|
var modifier = 1.1f
|
||||||
if (civInfo.wantsToFocusOn(Victory.Focus.Science))
|
if (civInfo.wantsToFocusOn(Victory.Focus.Science))
|
||||||
@ -323,9 +327,9 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addGoldBuildingChoice() {
|
private fun addGoldBuildingChoice() {
|
||||||
val goldBuilding = buildableNotWonders.asSequence().filter { it.isStatRelated(Stat.Gold)
|
val goldBuilding = nonWonders.filter { it.isStatRelated(Stat.Gold)
|
||||||
&& Automation.allowAutomatedConstruction(civInfo, cityInfo, it) }
|
&& Automation.allowAutomatedConstruction(civInfo, cityInfo, it) }
|
||||||
.minByOrNull { it.cost }
|
.isBuildable().minByOrNull { it.cost }
|
||||||
if (goldBuilding != null) {
|
if (goldBuilding != null) {
|
||||||
val modifier = if (civInfo.statsForNextTurn.gold < 0) 3f else 1.2f
|
val modifier = if (civInfo.statsForNextTurn.gold < 0) 3f else 1.2f
|
||||||
addChoice(relativeCostEffectiveness, goldBuilding.name, modifier)
|
addChoice(relativeCostEffectiveness, goldBuilding.name, modifier)
|
||||||
@ -333,9 +337,9 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addProductionBuildingChoice() {
|
private fun addProductionBuildingChoice() {
|
||||||
val productionBuilding = buildableNotWonders.asSequence()
|
val productionBuilding = nonWonders
|
||||||
.filter { it.isStatRelated(Stat.Production) && Automation.allowAutomatedConstruction(civInfo, cityInfo, it) }
|
.filter { it.isStatRelated(Stat.Production) && Automation.allowAutomatedConstruction(civInfo, cityInfo, it) }
|
||||||
.minByOrNull { it.cost }
|
.isBuildable().minByOrNull { it.cost }
|
||||||
if (productionBuilding != null) {
|
if (productionBuilding != null) {
|
||||||
addChoice(relativeCostEffectiveness, productionBuilding.name, 1.5f)
|
addChoice(relativeCostEffectiveness, productionBuilding.name, 1.5f)
|
||||||
}
|
}
|
||||||
@ -343,12 +347,12 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
|
|
||||||
private fun addFoodBuildingChoice() {
|
private fun addFoodBuildingChoice() {
|
||||||
val conditionalState = StateForConditionals(civInfo, cityInfo)
|
val conditionalState = StateForConditionals(civInfo, cityInfo)
|
||||||
val foodBuilding = buildableNotWonders.asSequence()
|
val foodBuilding = nonWonders
|
||||||
.filter {
|
.filter {
|
||||||
(it.isStatRelated(Stat.Food)
|
(it.isStatRelated(Stat.Food)
|
||||||
|| it.hasUnique(UniqueType.CarryOverFood, conditionalState)
|
|| it.hasUnique(UniqueType.CarryOverFood, conditionalState)
|
||||||
) && Automation.allowAutomatedConstruction(civInfo, cityInfo, it)
|
) && Automation.allowAutomatedConstruction(civInfo, cityInfo, it)
|
||||||
}.minByOrNull { it.cost }
|
}.isBuildable().minByOrNull { it.cost }
|
||||||
if (foodBuilding != null) {
|
if (foodBuilding != null) {
|
||||||
var modifier = 1f
|
var modifier = 1f
|
||||||
if (cityInfo.population.population < 5) modifier = 1.3f
|
if (cityInfo.population.population < 5) modifier = 1.3f
|
||||||
@ -370,12 +374,12 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
|
|
||||||
// The performance of the regular getMatchingUniques is better, since it only tries to find one unique,
|
// The performance of the regular getMatchingUniques is better, since it only tries to find one unique,
|
||||||
// while the canBePurchasedWithStat tries (at time of writing) *6* different uniques.
|
// while the canBePurchasedWithStat tries (at time of writing) *6* different uniques.
|
||||||
val missionary = buildableUnits
|
val missionary = units
|
||||||
.firstOrNull { it -> it.getMatchingUniques("Can [] [] times").any { it.params[0] == "Spread Religion"}
|
.firstOrNull { it -> it.getMatchingUniques("Can [] [] times").any { it.params[0] == "Spread Religion"}
|
||||||
&& it.canBePurchasedWithStat(cityInfo, Stat.Faith) }
|
&& it.canBePurchasedWithStat(cityInfo, Stat.Faith) }
|
||||||
|
|
||||||
|
|
||||||
val inquisitor = buildableUnits
|
val inquisitor = units
|
||||||
.firstOrNull { it.hasUnique("Prevents spreading of religion to the city it is next to")
|
.firstOrNull { it.hasUnique("Prevents spreading of religion to the city it is next to")
|
||||||
&& it.canBePurchasedWithStat(cityInfo, Stat.Faith) }
|
&& it.canBePurchasedWithStat(cityInfo, Stat.Faith) }
|
||||||
|
|
||||||
@ -395,8 +399,8 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
|||||||
|
|
||||||
val buildMissionary = possibleSpreadReligionTargets.toList().size.toFloat() / 15 + modifier
|
val buildMissionary = possibleSpreadReligionTargets.toList().size.toFloat() / 15 + modifier
|
||||||
|
|
||||||
if (buildMissionary > buildInquisitor && missionary != null) faithConstruction.add(missionary)
|
if (buildMissionary > buildInquisitor && missionary != null && missionary.isBuildable(cityConstructions)) faithConstruction.add(missionary)
|
||||||
else if(inquisitor != null) faithConstruction.add(inquisitor)
|
else if (inquisitor != null && inquisitor.isBuildable(cityConstructions)) faithConstruction.add(inquisitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ interface IConstruction : INamed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques {
|
interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques {
|
||||||
|
var cost: Int
|
||||||
val hurryCostModifier: Int
|
val hurryCostModifier: Int
|
||||||
var requiredTech: String?
|
var requiredTech: String?
|
||||||
|
|
||||||
|
@ -31,8 +31,8 @@ import kotlin.math.pow
|
|||||||
class Building : RulesetStatsObject(), INonPerpetualConstruction {
|
class Building : RulesetStatsObject(), INonPerpetualConstruction {
|
||||||
|
|
||||||
override var requiredTech: String? = null
|
override var requiredTech: String? = null
|
||||||
|
override var cost: Int = 0
|
||||||
|
|
||||||
var cost: Int = 0
|
|
||||||
var maintenance = 0
|
var maintenance = 0
|
||||||
private var percentStatBonus: Stats? = null
|
private var percentStatBonus: Stats? = null
|
||||||
var specialistSlots: Counter<String> = Counter()
|
var specialistSlots: Counter<String> = Counter()
|
||||||
@ -181,7 +181,6 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
|
|||||||
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)): Stats {
|
localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)): Stats {
|
||||||
// Calls the clone function of the NamedStats this class is derived from, not a clone function of this class
|
// Calls the clone function of the NamedStats this class is derived from, not a clone function of this class
|
||||||
val stats = cloneStats()
|
val stats = cloneStats()
|
||||||
val civInfo = city.civInfo
|
|
||||||
|
|
||||||
for (unique in localUniqueCache.get("StatsFromObject", city.getMatchingUniques(UniqueType.StatsFromObject))) {
|
for (unique in localUniqueCache.get("StatsFromObject", city.getMatchingUniques(UniqueType.StatsFromObject))) {
|
||||||
if (!matchesFilter(unique.params[1])) continue
|
if (!matchesFilter(unique.params[1])) continue
|
||||||
|
@ -28,7 +28,7 @@ import kotlin.math.pow
|
|||||||
in contrast to MapUnit, which is a specific unit of a certain type that appears on the map */
|
in contrast to MapUnit, which is a specific unit of a certain type that appears on the map */
|
||||||
class BaseUnit : RulesetObject(), INonPerpetualConstruction {
|
class BaseUnit : RulesetObject(), INonPerpetualConstruction {
|
||||||
|
|
||||||
var cost: Int = 0
|
override var cost: Int = 0
|
||||||
override var hurryCostModifier: Int = 0
|
override var hurryCostModifier: Int = 0
|
||||||
var movement: Int = 0
|
var movement: Int = 0
|
||||||
var strength: Int = 0
|
var strength: Int = 0
|
||||||
|
Reference in New Issue
Block a user