When choosing military units, 'carrying' units are only chosen if they provide needed 'slots' for carrying units. (#5436)

This commit is contained in:
Yair Morgenstern 2021-10-09 20:59:58 +03:00 committed by GitHub
parent 1df454368a
commit 1132042949
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 3 deletions

View File

@ -4,10 +4,12 @@ import com.unciv.logic.city.CityInfo
import com.unciv.logic.city.INonPerpetualConstruction import com.unciv.logic.city.INonPerpetualConstruction
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.BFS import com.unciv.logic.map.BFS
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileInfo
import com.unciv.models.ruleset.Building import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.VictoryType import com.unciv.models.ruleset.VictoryType
import com.unciv.models.ruleset.tile.ResourceType import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.ruleset.unit.BaseUnit import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.stats.Stats import com.unciv.models.stats.Stats
import com.unciv.ui.victoryscreen.RankingType import com.unciv.ui.victoryscreen.RankingType
@ -59,6 +61,26 @@ object Automation {
city.cityConstructions.currentConstructionFromQueue = chosenUnitName city.cityConstructions.currentConstructionFromQueue = chosenUnitName
} }
fun providesUnneededCarryingSlots(baseUnit: BaseUnit, civInfo: CivilizationInfo): Boolean {
// Simplified, will not work for crazy mods with more than one carrying filter for a unit
val carryUnique = baseUnit.getMatchingUniques(UniqueType.CarryAirUnits).first()
val carryFilter = carryUnique.params[1]
fun getCarryAmount(mapUnit: MapUnit): Int {
val mapUnitCarryUnique =
mapUnit.getMatchingUniques(UniqueType.CarryAirUnits).firstOrNull() ?: return 0
if (mapUnitCarryUnique.params[1] != carryFilter) return 0 //Carries a different type of unit
return mapUnitCarryUnique.params[0].toInt() +
mapUnit.getMatchingUniques(UniqueType.CarryExtraAirUnits)
.filter { it.params[1] == carryFilter }.sumOf { it.params[0].toInt() }
}
val totalCarriableUnits =
civInfo.getCivUnits().count { it.matchesFilter(carryFilter) }
val totalCarryingSlots = civInfo.getCivUnits().sumOf { getCarryAmount(it) }
return totalCarriableUnits < totalCarryingSlots
}
fun chooseMilitaryUnit(city: CityInfo): String? { fun chooseMilitaryUnit(city: CityInfo): String? {
var militaryUnits = var militaryUnits =
city.cityConstructions.getConstructableUnits().filter { !it.isCivilian() } city.cityConstructions.getConstructableUnits().filter { !it.isCivilian() }
@ -67,7 +89,6 @@ object Automation {
.contains(city.cityConstructions.currentConstructionFromQueue)) .contains(city.cityConstructions.currentConstructionFromQueue))
return city.cityConstructions.currentConstructionFromQueue return city.cityConstructions.currentConstructionFromQueue
val findWaterConnectedCitiesAndEnemies = val findWaterConnectedCitiesAndEnemies =
BFS(city.getCenterTile()) { it.isWater || it.isCityCenter() } BFS(city.getCenterTile()) { it.isWater || it.isCityCenter() }
findWaterConnectedCitiesAndEnemies.stepToEnd() findWaterConnectedCitiesAndEnemies.stepToEnd()
@ -77,8 +98,15 @@ object Automation {
}) // there is absolutely no reason for you to make water units on this body of water. }) // there is absolutely no reason for you to make water units on this body of water.
militaryUnits = militaryUnits.filter { !it.isWaterUnit() } militaryUnits = militaryUnits.filter { !it.isWaterUnit() }
val carryingUnits = militaryUnits.filter { it.hasUnique(UniqueType.CarryAirUnits) }.toList()
for (unit in carryingUnits)
if (providesUnneededCarryingSlots(unit, city.civInfo))
militaryUnits = militaryUnits.filterNot { it == unit }
val chosenUnit: BaseUnit val chosenUnit: BaseUnit
if (!city.civInfo.isAtWar() if (!city.civInfo.isAtWar()
&& city.civInfo.cities.any { it.getCenterTile().militaryUnit == null } && city.civInfo.cities.any { it.getCenterTile().militaryUnit == null }
&& militaryUnits.any { it.isRanged() } // this is for city defence so get a ranged unit if we can && militaryUnits.any { it.isRanged() } // this is for city defence so get a ranged unit if we can
) { ) {

View File

@ -966,7 +966,7 @@ class MapUnit {
fun canTransport(unit: MapUnit): Boolean { fun canTransport(unit: MapUnit): Boolean {
if (owner != unit.owner) return false if (owner != unit.owner) return false
if (!isTransportTypeOf(unit)) return false if (!isTransportTypeOf(unit)) return false
if (unit.getMatchingUniques("Cannot be carried by [] units").any{matchesFilter(it.params[0])}) return false if (unit.getMatchingUniques(UniqueType.CannotBeCarriedBy).any{matchesFilter(it.params[0])}) return false
if (currentTile.airUnits.count { it.isTransported } >= carryCapacity(unit)) return false if (currentTile.airUnits.count { it.isTransported } >= carryCapacity(unit)) return false
return true return true
} }