Barbarians only heal by pillaging, simplified barbarian automation

This commit is contained in:
Yair Morgenstern
2021-03-19 10:39:55 +02:00
parent a08a5a7435
commit ba51222841
4 changed files with 16 additions and 85 deletions

View File

@ -1050,6 +1050,8 @@
"name": "Barbarians", "name": "Barbarians",
"outerColor": [0,0,0], "outerColor": [0,0,0],
"innerColor": [182,0,0] "innerColor": [182,0,0]
"uniques": ["Can only heal by pillaging"],
} }
] ]

View File

@ -1,15 +1,8 @@
package com.unciv.logic.automation package com.unciv.logic.automation
import com.unciv.Constants import com.unciv.Constants
import com.unciv.logic.battle.Battle
import com.unciv.logic.battle.BattleDamage
import com.unciv.logic.battle.MapUnitCombatant
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.MapUnit import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.PathsToTilesWithinTurn
import com.unciv.logic.map.TileInfo
import com.unciv.models.AttackableTile
import com.unciv.models.ruleset.unit.UnitType
class BarbarianAutomation(val civInfo: CivilizationInfo) { class BarbarianAutomation(val civInfo: CivilizationInfo) {
@ -21,14 +14,11 @@ class BarbarianAutomation(val civInfo: CivilizationInfo) {
} }
private fun automateUnit(unit: MapUnit) { private fun automateUnit(unit: MapUnit) {
when { if (unit.currentTile.improvement == Constants.barbarianEncampment) automateUnitOnEncampment(unit)
unit.currentTile.improvement == Constants.barbarianEncampment -> automateEncampment(unit) else automateCombatUnit(unit)
unit.type == UnitType.Scout -> automateScout(unit)
else -> automateCombatUnit(unit)
}
} }
private fun automateEncampment(unit: MapUnit) { private fun automateUnitOnEncampment(unit: MapUnit) {
// 1 - trying to upgrade // 1 - trying to upgrade
if (UnitAutomation.tryUpgradeUnit(unit)) return if (UnitAutomation.tryUpgradeUnit(unit)) return
@ -40,25 +30,8 @@ class BarbarianAutomation(val civInfo: CivilizationInfo) {
} }
private fun automateCombatUnit(unit: MapUnit) { private fun automateCombatUnit(unit: MapUnit) {
val unitDistanceToTiles = unit.movement.getDistanceToTiles() // 1 - Try pillaging to restore health (barbs don't auto-heal)
val nearEnemyTiles = BattleHelper.getAttackableEnemies(unit, unitDistanceToTiles) if (unit.health < 50 && UnitAutomation.tryPillageImprovement(unit)) return
// 1 - heal or fortifying if death is near
if (unit.health < 50) {
val possibleDamage = nearEnemyTiles
.map {
BattleDamage.calculateDamageToAttacker(MapUnitCombatant(unit),
it.tileToAttackFrom,
Battle.getMapCombatantOfTile(it.tileToAttack)!!)
}
.sum()
val possibleHeal = unit.rankTileForHealing(unit.currentTile)
if (possibleDamage > possibleHeal) {
UnitAutomation.runAway(unit)
}
unit.fortifyIfCan()
return
}
// 2 - trying to upgrade // 2 - trying to upgrade
if (UnitAutomation.tryUpgradeUnit(unit)) return if (UnitAutomation.tryUpgradeUnit(unit)) return
@ -71,55 +44,8 @@ class BarbarianAutomation(val civInfo: CivilizationInfo) {
// 4 - trying to pillage tile or route // 4 - trying to pillage tile or route
if (UnitAutomation.tryPillageImprovement(unit)) return if (UnitAutomation.tryPillageImprovement(unit)) return
// 5 - heal the unit if needed
if (unit.health < 100 && UnitAutomation.tryHealUnit(unit)) return
// 6 - wander // 6 - wander
UnitAutomation.wander(unit) UnitAutomation.wander(unit)
} }
private fun automateScout(unit: MapUnit) {
val unitDistanceToTiles = unit.movement.getDistanceToTiles()
val nearEnemyTiles = BattleHelper.getAttackableEnemies(unit, unitDistanceToTiles)
// 1 - heal or run if death is near
if (unit.health < 50) {
if (nearEnemyTiles.isNotEmpty()) UnitAutomation.runAway(unit)
unit.fortifyIfCan()
return
}
// 2 - trying to capture someone
// TODO
// 3 - trying to pillage tile or trade route
if (UnitAutomation.tryPillageImprovement(unit)) return
// 4 - heal the unit if needed
if (unit.health < 100 && UnitAutomation.tryHealUnit(unit)) return
// 5 - wander
UnitAutomation.wander(unit)
}
private fun findFurthestTileCanMoveTo(
unit: MapUnit,
unitDistanceToTiles: PathsToTilesWithinTurn,
nearEnemyTiles: List<AttackableTile>
): TileInfo? {
val possibleTiles = unitDistanceToTiles.keys.filter { unit.movement.canMoveTo(it) }
if(possibleTiles.isEmpty()) return null
val enemies = nearEnemyTiles.mapNotNull { it.tileToAttack.militaryUnit }
var furthestTile: Pair<TileInfo, Float> = possibleTiles.random() to 0f
for (enemy in enemies) {
for (tile in possibleTiles) {
val distance = enemy.movement.getMovementCostBetweenAdjacentTiles(enemy.currentTile, tile, enemy.civInfo)
if (distance > furthestTile.second) {
furthestTile = tile to distance
}
}
}
return furthestTile.first
}
} }

View File

@ -441,6 +441,8 @@ class MapUnit {
private fun heal() { private fun heal() {
if (isEmbarked()) return // embarked units can't heal if (isEmbarked()) return // embarked units can't heal
if (civInfo.hasUnique("Can only heal by pillaging")) return
var amountToHealBy = rankTileForHealing(getTile()) var amountToHealBy = rankTileForHealing(getTile())
if (amountToHealBy == 0) return if (amountToHealBy == 0) return

View File

@ -227,10 +227,10 @@ open class TileInfo {
val tileType = unique.params[1] val tileType = unique.params[1]
if (tileType == improvement) continue // This is added to the calculation in getImprovementStats. we don't want to add it twice if (tileType == improvement) continue // This is added to the calculation in getImprovementStats. we don't want to add it twice
if (matchesUniqueFilter(tileType, observingCiv) if (matchesUniqueFilter(tileType, observingCiv)
|| (tileType == "Strategic resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Strategic) || tileType == "Strategic resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Strategic
|| (tileType == "Luxury resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Luxury) || tileType == "Luxury resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Luxury
|| (tileType == "Bonus resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Bonus) || tileType == "Bonus resource" && hasViewableResource(observingCiv) && getTileResource().resourceType == ResourceType.Bonus
|| (tileType == "Water resource" && isWater && hasViewableResource(observingCiv)) || tileType == "Water resource" && isWater && hasViewableResource(observingCiv)
) stats.add(unique.stats) ) stats.add(unique.stats)
} }
} }
@ -606,11 +606,12 @@ open class TileInfo {
} }
for (terrainFeature in terrainFeatures.toList()) { for (terrainFeature in terrainFeatures.toList()) {
if (!ruleset.terrains.containsKey(terrainFeature)) { val terrainFeatureObject = ruleset.terrains[terrainFeature]
if (terrainFeatureObject == null) {
terrainFeatures.remove(terrainFeature) terrainFeatures.remove(terrainFeature)
continue continue
} }
val terrainFeatureObject = ruleset.terrains[terrainFeature]!!
if (terrainFeatureObject.occursOn.isNotEmpty() && !terrainFeatureObject.occursOn.contains(baseTerrain)) if (terrainFeatureObject.occursOn.isNotEmpty() && !terrainFeatureObject.occursOn.contains(baseTerrain))
terrainFeatures.remove(terrainFeature) terrainFeatures.remove(terrainFeature)
} }