mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-22 05:41:11 +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.UnitAction
|
||||||
import com.unciv.ui.worldscreen.unit.UnitActions
|
import com.unciv.ui.worldscreen.unit.UnitActions
|
||||||
|
|
||||||
|
const val CLOSE_TURNS_AWAY_LIMIT = 3f
|
||||||
|
const val CLOSE_TILES_AWAY_LIMIT = 5
|
||||||
|
|
||||||
class UnitAutomation{
|
class UnitAutomation{
|
||||||
|
|
||||||
fun automateUnitMoves(unit: MapUnit) {
|
fun automateUnitMoves(unit: MapUnit) {
|
||||||
@ -80,7 +83,7 @@ class UnitAutomation{
|
|||||||
|
|
||||||
if (unit.health < 80 && tryHealUnit(unit, unitDistanceToTiles)) return
|
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 (tryAdvanceTowardsCloseEnemy(unit)) return
|
||||||
|
|
||||||
if (unit.health < 100 && tryHealUnit(unit, unitDistanceToTiles)) return
|
if (unit.health < 100 && tryHealUnit(unit, unitDistanceToTiles)) return
|
||||||
@ -195,9 +198,13 @@ class UnitAutomation{
|
|||||||
|
|
||||||
class AttackableTile(val tileToAttackFrom:TileInfo, val tileToAttack:TileInfo)
|
class AttackableTile(val tileToAttackFrom:TileInfo, val tileToAttack:TileInfo)
|
||||||
|
|
||||||
fun getAttackableEnemies(unit: MapUnit, unitDistanceToTiles: PathsToTilesWithinTurn): ArrayList<AttackableTile> {
|
fun getAttackableEnemies(
|
||||||
val tilesWithEnemies = unit.civInfo.viewableTiles
|
unit: MapUnit,
|
||||||
.filter { containsAttackableEnemy(it, MapUnitCombatant(unit)) }
|
unitDistanceToTiles: PathsToTilesWithinTurn,
|
||||||
|
tilesToCheck: List<TileInfo>? = null
|
||||||
|
): ArrayList<AttackableTile> {
|
||||||
|
val tilesWithEnemies = (tilesToCheck ?: unit.civInfo.viewableTiles)
|
||||||
|
.filter { containsAttackableEnemy(it, MapUnitCombatant(unit)) }
|
||||||
|
|
||||||
val rangeOfAttack = unit.getRange()
|
val rangeOfAttack = unit.getRange()
|
||||||
|
|
||||||
@ -238,17 +245,32 @@ class UnitAutomation{
|
|||||||
.filter { containsAttackableEnemy(it, CityCombatant(city)) }
|
.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 {
|
private fun tryAdvanceTowardsCloseEnemy(unit: MapUnit): Boolean {
|
||||||
// this can be sped up if we check each layer separately
|
// this can be sped up if we check each layer separately
|
||||||
var closeEnemies = unit.getTile().getTilesInDistance(5)
|
val unitDistanceToTiles = unit.movement.getDistanceToTilesWithinTurn(
|
||||||
.filter{ containsAttackableEnemy(it, MapUnitCombatant(unit)) && unit.movement.canReach(it)}
|
unit.getTile().position,
|
||||||
if(unit.type.isRanged())
|
unit.getMaxMovement() * CLOSE_TURNS_AWAY_LIMIT
|
||||||
closeEnemies = closeEnemies.filterNot { it.isCityCenter() && it.getCity()!!.health==1 }
|
)
|
||||||
|
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) {
|
if (closestEnemy != null) {
|
||||||
unit.movement.headTowards(closestEnemy)
|
unit.movement.headTowards(closestEnemy.tileToAttack)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
Reference in New Issue
Block a user