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:
lyrjie
2019-12-26 12:29:40 +03:00
committed by Yair Morgenstern
parent d823d3d664
commit 935f598282

View File

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