mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-29 06:51:30 -04:00
Construction choices are now more standardized and easier to understand
Construction choice depends on how much work is left towards construction and not initial cost
This commit is contained in:
parent
34a3b614b0
commit
4001526aea
@ -74,7 +74,7 @@ class Automation {
|
|||||||
|
|
||||||
val civUnits = cityInfo.civInfo.getCivUnits()
|
val civUnits = cityInfo.civInfo.getCivUnits()
|
||||||
val militaryUnits = civUnits.filter { !it.type.isCivilian()}.size
|
val militaryUnits = civUnits.filter { !it.type.isCivilian()}.size
|
||||||
val workers = civUnits.filter { it.name == CityConstructions.Worker }.size
|
val workers = civUnits.filter { it.name == CityConstructions.Worker }.size.toFloat()
|
||||||
val cities = cityInfo.civInfo.cities.size
|
val cities = cityInfo.civInfo.cities.size
|
||||||
val canBuildWorkboat = cityInfo.cityConstructions.getConstructableUnits().map { it.name }.contains("Work Boats")
|
val canBuildWorkboat = cityInfo.cityConstructions.getConstructableUnits().map { it.name }.contains("Work Boats")
|
||||||
&& !cityInfo.getTiles().any { it.civilianUnit?.name == "Work Boats" }
|
&& !cityInfo.getTiles().any { it.civilianUnit?.name == "Work Boats" }
|
||||||
@ -82,18 +82,21 @@ class Automation {
|
|||||||
&& cityInfo.getTiles().any { it.isWater() && it.hasViewableResource(cityInfo.civInfo) && it.improvement == null }
|
&& cityInfo.getTiles().any { it.isWater() && it.hasViewableResource(cityInfo.civInfo) && it.improvement == null }
|
||||||
|
|
||||||
val isAtWar = cityInfo.civInfo.isAtWar()
|
val isAtWar = cityInfo.civInfo.isAtWar()
|
||||||
val cityProduction = cityInfo.cityStats.currentCityStats.production
|
|
||||||
|
|
||||||
var buildingValues = HashMap<String, Float>()
|
data class ConstructionChoice(val choice:String, var choiceModifier:Float){
|
||||||
|
val remainingWork:Int = getRemainingWork(choice)
|
||||||
|
}
|
||||||
|
|
||||||
|
val relativeCostEffectiveness = ArrayList<ConstructionChoice>()
|
||||||
|
|
||||||
//Food buildings : Granary and lighthouse and hospital
|
//Food buildings : Granary and lighthouse and hospital
|
||||||
val foodBuilding = buildableNotWonders.filter { it.food>0
|
val foodBuilding = buildableNotWonders.filter { it.food>0
|
||||||
|| (it.resourceBonusStats!=null && it.resourceBonusStats!!.food>0) }
|
|| (it.resourceBonusStats!=null && it.resourceBonusStats!!.food>0) }
|
||||||
.minBy{ it.cost }
|
.minBy{ it.cost }
|
||||||
if (foodBuilding!=null) {
|
if (foodBuilding!=null) {
|
||||||
buildingValues[foodBuilding.name] = foodBuilding.cost / cityProduction
|
val choice = ConstructionChoice(foodBuilding.name,1f)
|
||||||
if (cityInfo.population.population < foodBuilding.food + 5) {
|
if (cityInfo.population.population < foodBuilding.food + 5) choice.choiceModifier=2f
|
||||||
buildingValues[foodBuilding.name] = buildingValues[foodBuilding.name]!! / 2.0f
|
relativeCostEffectiveness.add(choice)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Production buildings : Workshop, factory
|
//Production buildings : Workshop, factory
|
||||||
@ -101,7 +104,7 @@ class Automation {
|
|||||||
|| (it.resourceBonusStats!=null && it.resourceBonusStats!!.production>0) }
|
|| (it.resourceBonusStats!=null && it.resourceBonusStats!!.production>0) }
|
||||||
.minBy{it.cost}
|
.minBy{it.cost}
|
||||||
if (productionBuilding!=null) {
|
if (productionBuilding!=null) {
|
||||||
buildingValues[productionBuilding.name] = productionBuilding.cost / cityProduction / 1.5f
|
relativeCostEffectiveness.add(ConstructionChoice(productionBuilding.name, 1.5f))
|
||||||
}
|
}
|
||||||
|
|
||||||
//Gold buildings : Market, bank
|
//Gold buildings : Market, bank
|
||||||
@ -109,10 +112,11 @@ class Automation {
|
|||||||
|| (it.resourceBonusStats!=null && it.resourceBonusStats!!.gold>0) }
|
|| (it.resourceBonusStats!=null && it.resourceBonusStats!!.gold>0) }
|
||||||
.minBy{it.cost}
|
.minBy{it.cost}
|
||||||
if (goldBuilding!=null) {
|
if (goldBuilding!=null) {
|
||||||
buildingValues[goldBuilding.name] = goldBuilding.cost / cityProduction / 1.2f
|
val choice = ConstructionChoice(goldBuilding.name,1.2f)
|
||||||
if (cityInfo.civInfo.getStatsForNextTurn().gold<0) {
|
if (cityInfo.civInfo.getStatsForNextTurn().gold<0) {
|
||||||
buildingValues[goldBuilding.name] = buildingValues[goldBuilding.name]!! / 3.0f
|
choice.choiceModifier=3f
|
||||||
}
|
}
|
||||||
|
relativeCostEffectiveness.add(choice)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Happiness
|
//Happiness
|
||||||
@ -120,17 +124,17 @@ class Automation {
|
|||||||
|| (it.resourceBonusStats!=null && it.resourceBonusStats!!.happiness>0) }
|
|| (it.resourceBonusStats!=null && it.resourceBonusStats!!.happiness>0) }
|
||||||
.minBy{it.cost}
|
.minBy{it.cost}
|
||||||
if (happinessBuilding!=null) {
|
if (happinessBuilding!=null) {
|
||||||
buildingValues[happinessBuilding.name] = happinessBuilding.cost / cityProduction
|
val choice = ConstructionChoice(happinessBuilding.name,1f)
|
||||||
if (cityInfo.civInfo.happiness < 0) {
|
if (cityInfo.civInfo.happiness > 5) choice.choiceModifier = 1/2f // less desperate
|
||||||
buildingValues[happinessBuilding.name] = buildingValues[happinessBuilding.name]!! / 3.0f
|
if (cityInfo.civInfo.happiness < 0) choice.choiceModifier = 3f // more desperate
|
||||||
}
|
relativeCostEffectiveness.add(choice)
|
||||||
}
|
}
|
||||||
|
|
||||||
//War buildings
|
//War buildings
|
||||||
val wartimeBuildings = buildableNotWonders.filter { it.xpForNewUnits>0 || it.cityStrength>0 }
|
val wartimeBuilding = buildableNotWonders.filter { it.xpForNewUnits>0 || it.cityStrength>0 }
|
||||||
.minBy { it.cost }
|
.minBy { it.cost }
|
||||||
if (wartimeBuildings!=null) {
|
if (wartimeBuilding!=null) {
|
||||||
buildingValues[wartimeBuildings.name] = wartimeBuildings.cost / cityProduction
|
relativeCostEffectiveness.add(ConstructionChoice(wartimeBuilding.name,1f))
|
||||||
}
|
}
|
||||||
|
|
||||||
//Wonders
|
//Wonders
|
||||||
@ -138,38 +142,47 @@ class Automation {
|
|||||||
val citiesBuildingWonders = cityInfo.civInfo.cities
|
val citiesBuildingWonders = cityInfo.civInfo.cities
|
||||||
.count { it.cityConstructions.isBuildingWonder() }
|
.count { it.cityConstructions.isBuildingWonder() }
|
||||||
val wonder = buildableWonders.getRandom()
|
val wonder = buildableWonders.getRandom()
|
||||||
buildingValues[wonder.name] = wonder.cost / cityProduction * (citiesBuildingWonders + 1) / 5.0f
|
relativeCostEffectiveness.add(ConstructionChoice(wonder.name,3f / (citiesBuildingWonders + 1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
//other buildings
|
//other buildings
|
||||||
val other = buildableNotWonders.minBy{it.cost}
|
val other = buildableNotWonders.minBy{it.cost}
|
||||||
if (other!=null) {
|
if (other!=null) {
|
||||||
buildingValues[other.name] = other.cost / cityProduction * 1.2f
|
relativeCostEffectiveness.add(ConstructionChoice(other.name,1.2f))
|
||||||
}
|
}
|
||||||
|
|
||||||
//worker
|
//worker
|
||||||
if (workers<(cities+1)/2) {
|
if (workers < cities) {
|
||||||
buildingValues[CityConstructions.Worker] =
|
relativeCostEffectiveness.add(ConstructionChoice(CityConstructions.Worker,workers/(cities+1)))
|
||||||
buildableUnits.first{ it.name == CityConstructions.Worker }.cost / cityProduction *
|
|
||||||
(workers/(cities+1))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Work boat
|
//Work boat
|
||||||
if (needWorkboat) {
|
if (needWorkboat) {
|
||||||
buildingValues["Work Boats"] =
|
relativeCostEffectiveness.add(ConstructionChoice("Work Boats",1.5f))
|
||||||
buildableUnits.first{ it.name == "Work Boats" }.cost / cityProduction * 1.5f
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Army
|
//Army
|
||||||
val militaryUnit = chooseCombatUnit(cityInfo)
|
val militaryUnit = chooseCombatUnit(cityInfo)
|
||||||
buildingValues[militaryUnit] =
|
val unitsToCitiesRatio = militaryUnits / cities.toFloat()
|
||||||
buildableUnits.first{ it.name == militaryUnit }.cost / cityProduction * 1.5f * militaryUnits / (cities+1)
|
// most buildings and civ units contribute the the civ's growth, military units are anti-growth
|
||||||
|
val militaryChoice = ConstructionChoice(militaryUnit,unitsToCitiesRatio/5)
|
||||||
if (isAtWar) {
|
if (isAtWar) {
|
||||||
buildingValues[militaryUnit] = buildingValues[militaryUnit]!! / 3.0f
|
militaryChoice.choiceModifier=unitsToCitiesRatio
|
||||||
}
|
}
|
||||||
|
relativeCostEffectiveness.add(militaryChoice)
|
||||||
|
|
||||||
val name = buildingValues.minBy{it.value}!!.key
|
val production = cityInfo.cityStats.currentCityStats.production
|
||||||
currentConstruction = name
|
|
||||||
|
// Nobody can plan 30 turns ahead, I don't care how cost-efficient you are.
|
||||||
|
|
||||||
|
val theChosenOne:String
|
||||||
|
if(relativeCostEffectiveness.any { it.remainingWork < production*30 }) { // it's possible that this is a new city and EVERYTHING is way expensive.
|
||||||
|
relativeCostEffectiveness.removeAll { it.remainingWork >= production * 30 }
|
||||||
|
theChosenOne = relativeCostEffectiveness.minBy { it.remainingWork/it.choiceModifier }!!.choice
|
||||||
|
}
|
||||||
|
else theChosenOne = relativeCostEffectiveness.minBy { it.remainingWork }!!.choice // ignore modifiers, go for the cheapest.
|
||||||
|
|
||||||
|
currentConstruction = theChosenOne
|
||||||
cityInfo.civInfo.addNotification("Work has started on [$currentConstruction]", cityInfo.location, Color.BROWN)
|
cityInfo.civInfo.addNotification("Work has started on [$currentConstruction]", cityInfo.location, Color.BROWN)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,10 +105,11 @@ class CityConstructions {
|
|||||||
else return 0
|
else return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fun turnsToConstruction(constructionName: String): Int {
|
fun getRemainingWork(constructionName: String) = getConstruction(constructionName)
|
||||||
val productionCost = getConstruction(constructionName).getProductionCost(cityInfo.civInfo.policies.adoptedPolicies)
|
.getProductionCost(cityInfo.civInfo.policies.adoptedPolicies) - getWorkDone(constructionName)
|
||||||
|
|
||||||
val workLeft = (productionCost - getWorkDone(constructionName)).toFloat() // needs to be float so that we get the cieling properly ;)
|
fun turnsToConstruction(constructionName: String): Int {
|
||||||
|
val workLeft = getRemainingWork(constructionName)
|
||||||
|
|
||||||
val cityStats = cityInfo.cityStats.currentCityStats
|
val cityStats = cityInfo.cityStats.currentCityStats
|
||||||
var production = Math.round(cityStats.production)
|
var production = Math.round(cityStats.production)
|
||||||
@ -149,7 +150,7 @@ class CityConstructions {
|
|||||||
if (!construction.isBuildable(this)) {
|
if (!construction.isBuildable(this)) {
|
||||||
// We can't build this building anymore! (Wonder has been built / resource is gone / etc.)
|
// We can't build this building anymore! (Wonder has been built / resource is gone / etc.)
|
||||||
cityInfo.civInfo.addNotification("[${cityInfo.name}] Cannot continue work on [$saveCurrentConstruction]", cityInfo.location, Color.BROWN)
|
cityInfo.civInfo.addNotification("[${cityInfo.name}] Cannot continue work on [$saveCurrentConstruction]", cityInfo.location, Color.BROWN)
|
||||||
Automation().chooseNextConstruction(this)
|
chooseNextConstruction()
|
||||||
} else
|
} else
|
||||||
currentConstruction = saveCurrentConstruction
|
currentConstruction = saveCurrentConstruction
|
||||||
|
|
||||||
@ -169,7 +170,7 @@ class CityConstructions {
|
|||||||
cityInfo.civInfo.addNotification("[$currentConstruction] has been built in [" + cityInfo.name + "]", cityInfo.location, Color.BROWN)
|
cityInfo.civInfo.addNotification("[$currentConstruction] has been built in [" + cityInfo.name + "]", cityInfo.location, Color.BROWN)
|
||||||
|
|
||||||
currentConstruction = ""
|
currentConstruction = ""
|
||||||
Automation().chooseNextConstruction(this)
|
chooseNextConstruction()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addBuilding(buildingName:String){
|
fun addBuilding(buildingName:String){
|
||||||
@ -189,7 +190,7 @@ class CityConstructions {
|
|||||||
getConstruction(buildingName).postBuildEvent(this)
|
getConstruction(buildingName).postBuildEvent(this)
|
||||||
if (currentConstruction == buildingName) {
|
if (currentConstruction == buildingName) {
|
||||||
currentConstruction=""
|
currentConstruction=""
|
||||||
Automation().chooseNextConstruction(this)
|
chooseNextConstruction()
|
||||||
}
|
}
|
||||||
cityInfo.cityStats.update()
|
cityInfo.cityStats.update()
|
||||||
}
|
}
|
||||||
@ -200,7 +201,7 @@ class CityConstructions {
|
|||||||
addBuilding(cultureBuildingToBuild)
|
addBuilding(cultureBuildingToBuild)
|
||||||
if (currentConstruction == cultureBuildingToBuild) {
|
if (currentConstruction == cultureBuildingToBuild) {
|
||||||
currentConstruction=""
|
currentConstruction=""
|
||||||
Automation().chooseNextConstruction(this)
|
chooseNextConstruction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user