mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-28 14:24:43 -04:00
Resolved #11200 - Add AI for land-based nukes
This commit is contained in:
parent
e6a132a9d7
commit
a0f710b885
@ -1,6 +1,7 @@
|
|||||||
package com.unciv.logic.automation.unit
|
package com.unciv.logic.automation.unit
|
||||||
|
|
||||||
import com.unciv.logic.battle.AirInterception
|
import com.unciv.logic.battle.AirInterception
|
||||||
|
import com.unciv.logic.battle.Battle
|
||||||
import com.unciv.logic.battle.MapUnitCombatant
|
import com.unciv.logic.battle.MapUnitCombatant
|
||||||
import com.unciv.logic.battle.Nuke
|
import com.unciv.logic.battle.Nuke
|
||||||
import com.unciv.logic.battle.TargetHelper
|
import com.unciv.logic.battle.TargetHelper
|
||||||
@ -25,17 +26,17 @@ object AirUnitAutomation {
|
|||||||
val friendlyUsedFighterCount = friendlyAirUnitsInRange.count { it.health >= 50 && !it.canAttack() }
|
val friendlyUsedFighterCount = friendlyAirUnitsInRange.count { it.health >= 50 && !it.canAttack() }
|
||||||
|
|
||||||
// We need to be on standby in case they attack
|
// We need to be on standby in case they attack
|
||||||
if (friendlyUnusedFighterCount < enemyFighters) return
|
if (friendlyUnusedFighterCount < enemyFighters) return
|
||||||
|
|
||||||
if (friendlyUsedFighterCount <= enemyFighters) {
|
if (friendlyUsedFighterCount <= enemyFighters) {
|
||||||
fun airSweepDamagePercentBonus(): Int {
|
fun airSweepDamagePercentBonus(): Int {
|
||||||
return unit.getMatchingUniques(UniqueType.StrengthWhenAirsweep)
|
return unit.getMatchingUniques(UniqueType.StrengthWhenAirsweep)
|
||||||
.sumOf { it.params[0].toInt() }
|
.sumOf { it.params[0].toInt() }
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are outnumbered, don't heal after attacking and don't have an Air Sweep bonus
|
// If we are outnumbered, don't heal after attacking and don't have an Air Sweep bonus
|
||||||
// Then we shouldn't speed the air battle by killing our fighters, instead, focus on defending
|
// Then we shouldn't speed the air battle by killing our fighters, instead, focus on defending
|
||||||
if (friendlyUsedFighterCount + friendlyUnusedFighterCount < enemyFighters
|
if (friendlyUsedFighterCount + friendlyUnusedFighterCount < enemyFighters
|
||||||
&& !unit.hasUnique(UniqueType.HealsEvenAfterAction)
|
&& !unit.hasUnique(UniqueType.HealsEvenAfterAction)
|
||||||
&& airSweepDamagePercentBonus() <= 0) {
|
&& airSweepDamagePercentBonus() <= 0) {
|
||||||
return
|
return
|
||||||
@ -47,7 +48,7 @@ object AirUnitAutomation {
|
|||||||
if (unit.health < 80) {
|
if (unit.health < 80) {
|
||||||
return // Wait and heal up, no point in moving closer to battle if we aren't healed
|
return // Wait and heal up, no point in moving closer to battle if we aren't healed
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BattleHelper.tryAttackNearbyEnemy(unit)) return
|
if (BattleHelper.tryAttackNearbyEnemy(unit)) return
|
||||||
|
|
||||||
if (tryRelocateToCitiesWithEnemyNearBy(unit)) return
|
if (tryRelocateToCitiesWithEnemyNearBy(unit)) return
|
||||||
@ -79,8 +80,8 @@ object AirUnitAutomation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun tryAirSweep(unit: MapUnit, tilesWithEnemyUnitsInRange: List<Tile>):Boolean {
|
private fun tryAirSweep(unit: MapUnit, tilesWithEnemyUnitsInRange: List<Tile>):Boolean {
|
||||||
val targetTile = tilesWithEnemyUnitsInRange.filter {
|
val targetTile = tilesWithEnemyUnitsInRange.filter {
|
||||||
tile -> tile.getUnits().any { it.civ.isAtWarWith(unit.civ)
|
tile -> tile.getUnits().any { it.civ.isAtWarWith(unit.civ)
|
||||||
|| (tile.isCityCenter() && tile.getCity()!!.civ.isAtWarWith(unit.civ)) }
|
|| (tile.isCityCenter() && tile.getCity()!!.civ.isAtWarWith(unit.civ)) }
|
||||||
}.minByOrNull { it.aerialDistanceTo(unit.getTile()) } ?: return false
|
}.minByOrNull { it.aerialDistanceTo(unit.getTile()) } ?: return false
|
||||||
AirInterception.airSweep(MapUnitCombatant(unit),targetTile)
|
AirInterception.airSweep(MapUnitCombatant(unit),targetTile)
|
||||||
@ -124,20 +125,22 @@ object AirUnitAutomation {
|
|||||||
fun automateNukes(unit: MapUnit) {
|
fun automateNukes(unit: MapUnit) {
|
||||||
if (!unit.civ.isAtWar()) return
|
if (!unit.civ.isAtWar()) return
|
||||||
// We should *Almost* never want to nuke our own city, so don't consider it
|
// We should *Almost* never want to nuke our own city, so don't consider it
|
||||||
val tilesInRange = unit.currentTile.getTilesInDistanceRange(2..unit.getRange())
|
if (unit.type.isAirUnit()) {
|
||||||
var highestTileNukeValue = 0
|
val tilesInRange = unit.currentTile.getTilesInDistanceRange(2..unit.getRange())
|
||||||
var tileToNuke: Tile? = null
|
val highestTileNukeValue = tilesInRange.map { it to getNukeLocationValue(unit, it) }
|
||||||
tilesInRange.forEach {
|
.maxByOrNull { it.second }
|
||||||
val value = getNukeLocationValue(unit, it)
|
if (highestTileNukeValue != null && highestTileNukeValue.second > 0)
|
||||||
if (value > highestTileNukeValue) {
|
Nuke.NUKE(MapUnitCombatant(unit), highestTileNukeValue.first)
|
||||||
highestTileNukeValue = value
|
|
||||||
tileToNuke = it
|
tryRelocateMissileToNearbyAttackableCities(unit)
|
||||||
}
|
} else {
|
||||||
|
val attackableTiles = TargetHelper.getAttackableEnemies(unit, unit.movement.getDistanceToTiles())
|
||||||
|
val highestTileNukeValue = attackableTiles.map { it to getNukeLocationValue(unit, it.tileToAttack) }
|
||||||
|
.maxByOrNull { it.second }
|
||||||
|
if (highestTileNukeValue != null && highestTileNukeValue.second > 0)
|
||||||
|
Battle.moveAndAttack(MapUnitCombatant(unit), highestTileNukeValue.first)
|
||||||
|
HeadTowardsEnemyCityAutomation.tryHeadTowardsEnemyCity(unit)
|
||||||
}
|
}
|
||||||
if (highestTileNukeValue > 0) {
|
|
||||||
Nuke.NUKE(MapUnitCombatant(unit), tileToNuke!!)
|
|
||||||
}
|
|
||||||
tryRelocateMissileToNearbyAttackableCities(unit)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -173,7 +176,7 @@ object AirUnitAutomation {
|
|||||||
if (targetUnit.isInvisible(civ)) continue
|
if (targetUnit.isInvisible(civ)) continue
|
||||||
// If we are nuking a unit at ground zero, it is more likely to be destroyed
|
// If we are nuking a unit at ground zero, it is more likely to be destroyed
|
||||||
val tileExplosionValue = if (targetTile == tile) 80 else 50
|
val tileExplosionValue = if (targetTile == tile) 80 else 50
|
||||||
|
|
||||||
if (targetUnit.isMilitary()) {
|
if (targetUnit.isMilitary()) {
|
||||||
explosionValue += if (targetTile == tile) evaluateCivValue(targetUnit.civ, -200, tileExplosionValue)
|
explosionValue += if (targetTile == tile) evaluateCivValue(targetUnit.civ, -200, tileExplosionValue)
|
||||||
else evaluateCivValue(targetUnit.civ, -150, 50)
|
else evaluateCivValue(targetUnit.civ, -150, 50)
|
||||||
|
@ -194,14 +194,15 @@ object UnitAutomation {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note that not all nukes have to be air units
|
||||||
|
if (unit.baseUnit.isNuclearWeapon()) {
|
||||||
|
return AirUnitAutomation.automateNukes(unit)
|
||||||
|
}
|
||||||
|
|
||||||
if (unit.baseUnit.isAirUnit()) {
|
if (unit.baseUnit.isAirUnit()) {
|
||||||
if (unit.canIntercept())
|
if (unit.canIntercept())
|
||||||
return AirUnitAutomation.automateFighter(unit)
|
return AirUnitAutomation.automateFighter(unit)
|
||||||
|
|
||||||
// Note that not all nukes have to be air units
|
|
||||||
if (unit.baseUnit.isNuclearWeapon())
|
|
||||||
return AirUnitAutomation.automateNukes(unit)
|
|
||||||
|
|
||||||
if (unit.hasUnique(UniqueType.SelfDestructs))
|
if (unit.hasUnique(UniqueType.SelfDestructs))
|
||||||
return AirUnitAutomation.automateMissile(unit)
|
return AirUnitAutomation.automateMissile(unit)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user