mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-16 18:59:15 +07:00
Fix: automated units would advance towards enemies they can't attack without dying (#1529)
* Fix: units would advance towards enemies they can't attack without dying * Code quality
This commit is contained in:
@ -14,6 +14,9 @@ import com.unciv.models.ruleset.unit.UnitType
|
||||
import com.unciv.ui.worldscreen.unit.UnitAction
|
||||
import com.unciv.ui.worldscreen.unit.UnitActions
|
||||
|
||||
const val CLOSE_TURNS_AWAY_LIMIT = 3f
|
||||
const val CLOSE_TILES_AWAY_LIMIT = 5
|
||||
|
||||
class UnitAutomation{
|
||||
|
||||
fun automateUnitMoves(unit: MapUnit) {
|
||||
@ -80,7 +83,7 @@ class UnitAutomation{
|
||||
|
||||
if (unit.health < 80 && tryHealUnit(unit, unitDistanceToTiles)) return
|
||||
|
||||
// find the closest enemy unit that we know of within 5 spaces and advance towards it
|
||||
// move towards the closest reasonably attackable enemy unit within 3 turns of movement (and 5 tiles range)
|
||||
if (tryAdvanceTowardsCloseEnemy(unit)) return
|
||||
|
||||
if (unit.health < 100 && tryHealUnit(unit, unitDistanceToTiles)) return
|
||||
@ -195,9 +198,13 @@ class UnitAutomation{
|
||||
|
||||
class AttackableTile(val tileToAttackFrom:TileInfo, val tileToAttack:TileInfo)
|
||||
|
||||
fun getAttackableEnemies(unit: MapUnit, unitDistanceToTiles: PathsToTilesWithinTurn): ArrayList<AttackableTile> {
|
||||
val tilesWithEnemies = unit.civInfo.viewableTiles
|
||||
.filter { containsAttackableEnemy(it, MapUnitCombatant(unit)) }
|
||||
fun getAttackableEnemies(
|
||||
unit: MapUnit,
|
||||
unitDistanceToTiles: PathsToTilesWithinTurn,
|
||||
tilesToCheck: List<TileInfo>? = null
|
||||
): ArrayList<AttackableTile> {
|
||||
val tilesWithEnemies = (tilesToCheck ?: unit.civInfo.viewableTiles)
|
||||
.filter { containsAttackableEnemy(it, MapUnitCombatant(unit)) }
|
||||
|
||||
val rangeOfAttack = unit.getRange()
|
||||
|
||||
@ -238,17 +245,32 @@ class UnitAutomation{
|
||||
.filter { containsAttackableEnemy(it, CityCombatant(city)) }
|
||||
}
|
||||
|
||||
/** Move towards the closest attackable enemy of the [unit].
|
||||
*
|
||||
* Limited by [CLOSE_TURNS_AWAY_LIMIT] and [CLOSE_TILES_AWAY_LIMIT].
|
||||
* Tiles attack from which would result in instant death of the [unit] are ignored. */
|
||||
private fun tryAdvanceTowardsCloseEnemy(unit: MapUnit): Boolean {
|
||||
// this can be sped up if we check each layer separately
|
||||
var closeEnemies = unit.getTile().getTilesInDistance(5)
|
||||
.filter{ containsAttackableEnemy(it, MapUnitCombatant(unit)) && unit.movement.canReach(it)}
|
||||
if(unit.type.isRanged())
|
||||
closeEnemies = closeEnemies.filterNot { it.isCityCenter() && it.getCity()!!.health==1 }
|
||||
val unitDistanceToTiles = unit.movement.getDistanceToTilesWithinTurn(
|
||||
unit.getTile().position,
|
||||
unit.getMaxMovement() * CLOSE_TURNS_AWAY_LIMIT
|
||||
)
|
||||
var closeEnemies = getAttackableEnemies(
|
||||
unit,
|
||||
unitDistanceToTiles,
|
||||
tilesToCheck = unit.getTile().getTilesInDistance(CLOSE_TILES_AWAY_LIMIT)
|
||||
).filter {
|
||||
BattleDamage().calculateDamageToAttacker(MapUnitCombatant(unit),
|
||||
Battle(unit.civInfo.gameInfo).getMapCombatantOfTile(it.tileToAttack)!!) < unit.health
|
||||
}
|
||||
|
||||
val closestEnemy = closeEnemies.minBy { it.arialDistanceTo(unit.getTile()) }
|
||||
if(unit.type.isRanged())
|
||||
closeEnemies = closeEnemies.filterNot { it.tileToAttack.isCityCenter() && it.tileToAttack.getCity()!!.health==1 }
|
||||
|
||||
val closestEnemy = closeEnemies.minBy { it.tileToAttack.arialDistanceTo(unit.getTile()) }
|
||||
|
||||
if (closestEnemy != null) {
|
||||
unit.movement.headTowards(closestEnemy)
|
||||
unit.movement.headTowards(closestEnemy.tileToAttack)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
Reference in New Issue
Block a user