Mods can handle situations where there is no military unit that is available for construction
This commit is contained in:
parent
95002bc69b
commit
23a57c711f
3 changed files with 21 additions and 23 deletions
|
@ -20,29 +20,25 @@ object Automation {
|
||||||
|
|
||||||
private fun rankStatsForCityWork(stats: Stats, city: CityInfo, foodWeight: Float = 1f): Float {
|
private fun rankStatsForCityWork(stats: Stats, city: CityInfo, foodWeight: Float = 1f): Float {
|
||||||
var rank = 0f
|
var rank = 0f
|
||||||
if(city.population.population < 5){
|
if (city.population.population < 5) {
|
||||||
// "small city" - we care more about food and less about global problems like gold science and culture
|
// "small city" - we care more about food and less about global problems like gold science and culture
|
||||||
rank += stats.food * 1.2f * foodWeight
|
rank += stats.food * 1.2f * foodWeight
|
||||||
rank += stats.production
|
rank += stats.production
|
||||||
rank += stats.science/2
|
rank += stats.science / 2
|
||||||
rank += stats.culture/2
|
rank += stats.culture / 2
|
||||||
rank += stats.gold / 5 // it's barely worth anything at this points
|
rank += stats.gold / 5 // it's barely worth anything at this points
|
||||||
}
|
} else {
|
||||||
else{
|
if (stats.food <= 2 || city.civInfo.getHappiness() > 5) rank += stats.food * 1.2f * foodWeight //food get more value to keep city growing
|
||||||
if (stats.food <= 2 || city.civInfo.getHappiness() > 5) rank += (stats.food * 1.2f * foodWeight) //food get more value to keep city growing
|
else rank += (2.4f + (stats.food - 2) / 2) * foodWeight // 1.2 point for each food up to 2, from there on half a point
|
||||||
else rank += ((2.4f + (stats.food - 2) / 2) * foodWeight) // 1.2 point for each food up to 2, from there on half a point
|
|
||||||
|
|
||||||
if (city.civInfo.gold < 0 && city.civInfo.statsForNextTurn.gold <= 0) rank += stats.gold // we have a global problem
|
if (city.civInfo.gold < 0 && city.civInfo.statsForNextTurn.gold <= 0) rank += stats.gold // we have a global problem
|
||||||
else rank += stats.gold / 3 // 3 gold is worse than 2 production
|
else rank += stats.gold / 3 // 3 gold is worse than 2 production
|
||||||
|
|
||||||
rank += stats.production
|
rank += stats.production
|
||||||
rank += stats.science
|
rank += stats.science
|
||||||
if (city.tiles.size < 12 || city.civInfo.victoryType() == VictoryType.Cultural){
|
if (city.tiles.size < 12 || city.civInfo.victoryType() == VictoryType.Cultural) {
|
||||||
rank += stats.culture
|
rank += stats.culture
|
||||||
}
|
} else rank += stats.culture / 2
|
||||||
else{
|
|
||||||
rank += stats.culture / 2
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return rank
|
return rank
|
||||||
}
|
}
|
||||||
|
@ -53,19 +49,20 @@ object Automation {
|
||||||
return rank
|
return rank
|
||||||
}
|
}
|
||||||
|
|
||||||
fun trainMilitaryUnit(city: CityInfo) {
|
fun tryTrainMilitaryUnit(city: CityInfo) {
|
||||||
val name = chooseMilitaryUnit(city)
|
val chosenUnitName = chooseMilitaryUnit(city)
|
||||||
city.cityConstructions.currentConstructionFromQueue = name
|
if (chosenUnitName != null)
|
||||||
|
city.cityConstructions.currentConstructionFromQueue = chosenUnitName
|
||||||
}
|
}
|
||||||
|
|
||||||
fun chooseMilitaryUnit(city: CityInfo) : String {
|
fun chooseMilitaryUnit(city: CityInfo) : String? {
|
||||||
var militaryUnits = city.cityConstructions.getConstructableUnits().filter { !it.unitType.isCivilian() }
|
var militaryUnits = city.cityConstructions.getConstructableUnits().filter { !it.unitType.isCivilian() }
|
||||||
if (militaryUnits.map { it.name }.contains(city.cityConstructions.currentConstructionFromQueue))
|
if (militaryUnits.map { it.name }.contains(city.cityConstructions.currentConstructionFromQueue))
|
||||||
return city.cityConstructions.currentConstructionFromQueue
|
return city.cityConstructions.currentConstructionFromQueue
|
||||||
|
|
||||||
// This is so that the AI doesn't use all its aluminum on units and have none left for spaceship parts
|
// This is so that the AI doesn't use all its aluminum on units and have none left for spaceship parts
|
||||||
val aluminum = city.civInfo.getCivResourcesByName()["Aluminum"]
|
val aluminum = city.civInfo.getCivResourcesByName()["Aluminum"]
|
||||||
if (aluminum!=null && aluminum < 2) // mods may have no aluminum
|
if (aluminum != null && aluminum < 2) // mods may have no aluminum
|
||||||
militaryUnits.filter { it.requiredResource != "Aluminum" }
|
militaryUnits.filter { it.requiredResource != "Aluminum" }
|
||||||
|
|
||||||
val findWaterConnectedCitiesAndEnemies = BFS(city.getCenterTile()) { it.isWater || it.isCityCenter() }
|
val findWaterConnectedCitiesAndEnemies = BFS(city.getCenterTile()) { it.isWater || it.isCityCenter() }
|
||||||
|
@ -81,8 +78,9 @@ object Automation {
|
||||||
&& militaryUnits.any { it.unitType == UnitType.Ranged }) // this is for city defence so get an archery unit if we can
|
&& militaryUnits.any { it.unitType == UnitType.Ranged }) // this is for city defence so get an archery unit if we can
|
||||||
chosenUnit = militaryUnits.filter { it.unitType == UnitType.Ranged }.maxBy { it.cost }!!
|
chosenUnit = militaryUnits.filter { it.unitType == UnitType.Ranged }.maxBy { it.cost }!!
|
||||||
else { // randomize type of unit and take the most expensive of its kind
|
else { // randomize type of unit and take the most expensive of its kind
|
||||||
val chosenUnitType = militaryUnits.map { it.unitType }.distinct().filterNot { it == UnitType.Scout }.toList().random()
|
val availableTypes = militaryUnits.map { it.unitType }.distinct().filterNot { it == UnitType.Scout }.toList()
|
||||||
chosenUnit = militaryUnits.filter { it.unitType == chosenUnitType }.maxBy { it.cost }!!
|
if (availableTypes.isEmpty()) return null
|
||||||
|
chosenUnit = militaryUnits.filter { it.unitType == availableTypes.random() }.maxBy { it.cost }!!
|
||||||
}
|
}
|
||||||
return chosenUnit.name
|
return chosenUnit.name
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,10 +96,11 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addMilitaryUnitChoice() {
|
private fun addMilitaryUnitChoice() {
|
||||||
if(!isAtWar && !cityIsOverAverageProduction) return // don't make any military units here. Infrastructure first!
|
if (!isAtWar && !cityIsOverAverageProduction) return // don't make any military units here. Infrastructure first!
|
||||||
if ((!isAtWar && civInfo.statsForNextTurn.gold > 0 && militaryUnits < cities * 2)
|
if ((!isAtWar && civInfo.statsForNextTurn.gold > 0 && militaryUnits < cities * 2)
|
||||||
|| (isAtWar && civInfo.gold > -50)) {
|
|| (isAtWar && civInfo.gold > -50)) {
|
||||||
val militaryUnit = Automation.chooseMilitaryUnit(cityInfo)
|
val militaryUnit = Automation.chooseMilitaryUnit(cityInfo)
|
||||||
|
if (militaryUnit == null) return
|
||||||
val unitsToCitiesRatio = cities.toFloat() / (militaryUnits + 1)
|
val unitsToCitiesRatio = cities.toFloat() / (militaryUnits + 1)
|
||||||
// most buildings and civ units contribute the the civ's growth, military units are anti-growth
|
// most buildings and civ units contribute the the civ's growth, military units are anti-growth
|
||||||
var modifier = sqrt(unitsToCitiesRatio) / 2
|
var modifier = sqrt(unitsToCitiesRatio) / 2
|
||||||
|
@ -107,7 +108,7 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){
|
||||||
else if (isAtWar) modifier *= unitsToCitiesRatio * 2
|
else if (isAtWar) modifier *= unitsToCitiesRatio * 2
|
||||||
if (!cityIsOverAverageProduction) modifier /= 5 // higher production cities will deal with this
|
if (!cityIsOverAverageProduction) modifier /= 5 // higher production cities will deal with this
|
||||||
|
|
||||||
val civilianUnit = cityInfo.getCenterTile().civilianUnit
|
val civilianUnit = cityInfo.getCenterTile().civilianUnit
|
||||||
if (civilianUnit != null && civilianUnit.hasUnique(Constants.settlerUnique)
|
if (civilianUnit != null && civilianUnit.hasUnique(Constants.settlerUnique)
|
||||||
&& cityInfo.getCenterTile().getTilesInDistance(5).none { it.militaryUnit?.civInfo == civInfo })
|
&& cityInfo.getCenterTile().getTilesInDistance(5).none { it.militaryUnit?.civInfo == civInfo })
|
||||||
modifier = 5f // there's a settler just sitting here, doing nothing - BAD
|
modifier = 5f // there's a settler just sitting here, doing nothing - BAD
|
||||||
|
|
|
@ -11,7 +11,6 @@ import com.unciv.logic.civilization.diplomacy.RelationshipLevel
|
||||||
import com.unciv.logic.map.BFS
|
import com.unciv.logic.map.BFS
|
||||||
import com.unciv.logic.map.MapUnit
|
import com.unciv.logic.map.MapUnit
|
||||||
import com.unciv.logic.trade.*
|
import com.unciv.logic.trade.*
|
||||||
import com.unciv.models.ruleset.ModOptions
|
|
||||||
import com.unciv.models.ruleset.ModOptionsConstants
|
import com.unciv.models.ruleset.ModOptionsConstants
|
||||||
import com.unciv.models.ruleset.VictoryType
|
import com.unciv.models.ruleset.VictoryType
|
||||||
import com.unciv.models.ruleset.tech.Technology
|
import com.unciv.models.ruleset.tech.Technology
|
||||||
|
@ -473,7 +472,7 @@ object NextTurnAutomation{
|
||||||
|
|
||||||
city.cityConstructions.chooseNextConstruction()
|
city.cityConstructions.chooseNextConstruction()
|
||||||
if (city.health < city.getMaxHealth())
|
if (city.health < city.getMaxHealth())
|
||||||
Automation.trainMilitaryUnit(city) // override previous decision if city is under attack
|
Automation.tryTrainMilitaryUnit(city) // override previous decision if city is under attack
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue