Mods can handle situations where there is no military unit that is available for construction

This commit is contained in:
Yair Morgenstern 2020-09-04 16:11:48 +03:00
parent 95002bc69b
commit 23a57c711f
3 changed files with 21 additions and 23 deletions

View file

@ -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
} }

View file

@ -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

View file

@ -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
} }
} }