Slight performance improvements for AI

This commit is contained in:
Yair Morgenstern 2018-08-16 09:13:34 +03:00
parent 1affaa38c2
commit b4fece29e0
15 changed files with 63 additions and 64 deletions

View File

@ -106,7 +106,7 @@ class Automation {
unit.promotions.addPromotion(availablePromotions.getRandom().name) unit.promotions.addPromotion(availablePromotions.getRandom().name)
} }
val unitType = unit.getBaseUnit().unitType val unitType = unit.baseUnit().unitType
if(unitType.isRanged()) rangedUnits.add(unit) if(unitType.isRanged()) rangedUnits.add(unit)
else if(unitType.isMelee()) meleeUnits.add(unit) else if(unitType.isMelee()) meleeUnits.add(unit)
else civilianUnits.add(unit) else civilianUnits.add(unit)
@ -165,7 +165,7 @@ class Automation {
val buildableWonders = getBuildableBuildings().filter { it.isWonder } val buildableWonders = getBuildableBuildings().filter { it.isWonder }
val civUnits = cityInfo.civInfo.getCivUnits() val civUnits = cityInfo.civInfo.getCivUnits()
val militaryUnits = civUnits.filter { it.getBaseUnit().unitType != UnitType.Civilian }.size val militaryUnits = civUnits.filter { it.baseUnit().unitType != UnitType.Civilian }.size
val workers = civUnits.filter { it.name == CityConstructions.Worker }.size val workers = civUnits.filter { it.name == CityConstructions.Worker }.size
val cities = cityInfo.civInfo.cities.size val cities = cityInfo.civInfo.cities.size
@ -204,7 +204,7 @@ class Automation {
fun evaluteCombatStrength(civInfo: CivilizationInfo): Int { fun evaluteCombatStrength(civInfo: CivilizationInfo): Int {
// Since units become exponentially stronger per combat strength increase, we square em all // Since units become exponentially stronger per combat strength increase, we square em all
fun square(x:Int) = x*x fun square(x:Int) = x*x
val unitStrength = civInfo.getCivUnits().map { square(max(it.getBaseUnit().strength, it.getBaseUnit().rangedStrength)) }.sum() val unitStrength = civInfo.getCivUnits().map { square(max(it.baseUnit().strength, it.baseUnit().rangedStrength)) }.sum()
val cityStrength = civInfo.cities.map { square(CityCombatant(it).getCityStrength()) }.sum() val cityStrength = civInfo.cities.map { square(CityCombatant(it).getCityStrength()) }.sum()
return (sqrt(unitStrength.toDouble()) /*+ sqrt(cityStrength.toDouble())*/).toInt() return (sqrt(unitStrength.toDouble()) /*+ sqrt(cityStrength.toDouble())*/).toInt()
} }

View File

@ -36,20 +36,21 @@ class UnitAutomation{
if (tryUpgradeUnit(unit, unitActions)) return if (tryUpgradeUnit(unit, unitActions)) return
// Accompany settlers // Accompany settlers
if (tryAccompanySettler(unit)) return val unitDistanceToTiles = unit.getDistanceToTiles()
if (tryAccompanySettler(unit,unitDistanceToTiles)) return
if (unit.health < 50) { if (unit.health < 50) {
healUnit(unit) healUnit(unit,unitDistanceToTiles)
return return
} // do nothing but heal } // do nothing but heal
// if there is an attackable unit in the vicinity, attack! // if there is an attackable unit in the vicinity, attack!
if (tryAttackNearbyEnemy(unit)) return if (tryAttackNearbyEnemy(unit,unitDistanceToTiles)) return
if (tryGarrisoningUnit(unit)) return if (tryGarrisoningUnit(unit)) return
if (unit.health < 80) { if (unit.health < 80) {
healUnit(unit) healUnit(unit, unitDistanceToTiles)
return return
} // do nothing but heal until 80 health } // do nothing but heal until 80 health
@ -57,7 +58,7 @@ class UnitAutomation{
if (tryAdvanceTowardsCloseEnemy(unit)) return if (tryAdvanceTowardsCloseEnemy(unit)) return
if (unit.health < 100) { if (unit.health < 100) {
healUnit(unit) healUnit(unit, unitDistanceToTiles)
return return
} }
@ -65,7 +66,7 @@ class UnitAutomation{
if (tryHeadTowardsEnemyCity(unit)) return if (tryHeadTowardsEnemyCity(unit)) return
// else, go to a random space // else, go to a random space
randomWalk(unit) randomWalk(unit,unitDistanceToTiles)
// if both failed, then... there aren't any reachable tiles. Which is possible. // if both failed, then... there aren't any reachable tiles. Which is possible.
} }
@ -79,8 +80,8 @@ class UnitAutomation{
} }
} }
fun healUnit(unit:MapUnit) { fun healUnit(unit: MapUnit, unitDistanceToTiles: HashMap<TileInfo, Float>) {
val tilesInDistance = unit.getDistanceToTiles().keys.filter { unit.canMoveTo(it) } val tilesInDistance = unitDistanceToTiles.keys.filter { unit.canMoveTo(it) }
val unitTile = unit.getTile() val unitTile = unit.getTile()
val tilesByHealingRate = tilesInDistance.groupBy { rankTileForHealing(it,unit) } val tilesByHealingRate = tilesInDistance.groupBy { rankTileForHealing(it,unit) }
@ -103,11 +104,10 @@ class UnitAutomation{
class AttackableTile(val tileToAttackFrom:TileInfo, val tileToAttack:TileInfo) class AttackableTile(val tileToAttackFrom:TileInfo, val tileToAttack:TileInfo)
fun getAttackableEnemies(unit: MapUnit): ArrayList<AttackableTile> { fun getAttackableEnemies(unit: MapUnit, unitDistanceToTiles: HashMap<TileInfo, Float>): ArrayList<AttackableTile> {
val tilesWithEnemies = unit.civInfo.getViewableTiles() val tilesWithEnemies = unit.civInfo.getViewableTiles()
.filter { containsAttackableEnemy(it,unit.civInfo) } .filter { containsAttackableEnemy(it,unit.civInfo) }
val distanceToTiles = unit.getDistanceToTiles()
val rangeOfAttack = unit.getRange() val rangeOfAttack = unit.getRange()
val attackableTiles = ArrayList<AttackableTile>() val attackableTiles = ArrayList<AttackableTile>()
@ -116,7 +116,7 @@ class UnitAutomation{
// and then later we round it off to a whole. // and then later we round it off to a whole.
// So the poor unit thought it could attack from the tile, but when it comes to do so it has no movement points! // So the poor unit thought it could attack from the tile, but when it comes to do so it has no movement points!
// Silly floats, basically // Silly floats, basically
val tilesToAttackFrom = distanceToTiles.filter { unit.currentMovement - it.value > 0.1 } val tilesToAttackFrom = unitDistanceToTiles.filter { unit.currentMovement - it.value > 0.1 }
.map { it.key } .map { it.key }
.filter { unit.canMoveTo(it) || it==unit.getTile() } .filter { unit.canMoveTo(it) || it==unit.getTile() }
for(reachableTile in tilesToAttackFrom){ // tiles we'll still have energy after we reach there for(reachableTile in tilesToAttackFrom){ // tiles we'll still have energy after we reach there
@ -131,7 +131,7 @@ class UnitAutomation{
private fun tryAdvanceTowardsCloseEnemy(unit: MapUnit): Boolean { private fun tryAdvanceTowardsCloseEnemy(unit: MapUnit): Boolean {
var closeEnemies = unit.getTile().getTilesInDistance(5) var closeEnemies = unit.getTile().getTilesInDistance(5)
.filter{ containsAttackableEnemy(it, unit.civInfo) && unit.movementAlgs().canReach(it)} .filter{ containsAttackableEnemy(it, unit.civInfo) && unit.movementAlgs().canReach(it)}
if(unit.getBaseUnit().unitType.isRanged()) if(unit.baseUnit().unitType.isRanged())
closeEnemies = closeEnemies.filterNot { it.isCityCenter() && it.getCity()!!.health==1 } closeEnemies = closeEnemies.filterNot { it.isCityCenter() && it.getCity()!!.health==1 }
val closestEnemy = closeEnemies.minBy { it.arialDistanceTo(unit.getTile()) } val closestEnemy = closeEnemies.minBy { it.arialDistanceTo(unit.getTile()) }
@ -143,8 +143,8 @@ class UnitAutomation{
return false return false
} }
private fun tryAccompanySettler(unit: MapUnit): Boolean { private fun tryAccompanySettler(unit: MapUnit, unitDistanceToTiles: HashMap<TileInfo, Float>): Boolean {
val closeTileWithSettler = unit.getDistanceToTiles().keys.firstOrNull { val closeTileWithSettler = unitDistanceToTiles.keys.firstOrNull {
it.civilianUnit != null && it.civilianUnit!!.name == "Settler" it.civilianUnit != null && it.civilianUnit!!.name == "Settler"
} }
if (closeTileWithSettler != null && unit.canMoveTo(closeTileWithSettler)) { if (closeTileWithSettler != null && unit.canMoveTo(closeTileWithSettler)) {
@ -155,10 +155,10 @@ class UnitAutomation{
} }
private fun tryUpgradeUnit(unit: MapUnit, unitActions: List<UnitAction>): Boolean { private fun tryUpgradeUnit(unit: MapUnit, unitActions: List<UnitAction>): Boolean {
if (unit.getBaseUnit().upgradesTo != null) { if (unit.baseUnit().upgradesTo != null) {
val upgradedUnit = GameBasics.Units[unit.getBaseUnit().upgradesTo!!]!! val upgradedUnit = GameBasics.Units[unit.baseUnit().upgradesTo!!]!!
if (upgradedUnit.isBuildable(unit.civInfo)) { if (upgradedUnit.isBuildable(unit.civInfo)) {
val goldCostOfUpgrade = (upgradedUnit.cost - unit.getBaseUnit().cost) * 2 + 10 val goldCostOfUpgrade = (upgradedUnit.cost - unit.baseUnit().cost) * 2 + 10
val upgradeAction = unitActions.firstOrNull { it.name.startsWith("Upgrade to") } val upgradeAction = unitActions.firstOrNull { it.name.startsWith("Upgrade to") }
if (upgradeAction != null && unit.civInfo.gold > goldCostOfUpgrade) { if (upgradeAction != null && unit.civInfo.gold > goldCostOfUpgrade) {
upgradeAction.action() upgradeAction.action()
@ -173,7 +173,7 @@ class UnitAutomation{
if(unit.civInfo.cities.isEmpty()) return false if(unit.civInfo.cities.isEmpty()) return false
var enemyCities = unit.civInfo.exploredTiles.map { unit.civInfo.gameInfo.tileMap[it] } var enemyCities = unit.civInfo.exploredTiles.map { unit.civInfo.gameInfo.tileMap[it] }
.filter { it.isCityCenter() && it.getOwner() != unit.civInfo } .filter { it.isCityCenter() && it.getOwner() != unit.civInfo }
if(unit.getBaseUnit().unitType.isRanged()) if(unit.baseUnit().unitType.isRanged())
enemyCities = enemyCities.filterNot { it.getCity()!!.health==1 } enemyCities = enemyCities.filterNot { it.getCity()!!.health==1 }
val closestReachableEnemyCity = enemyCities val closestReachableEnemyCity = enemyCities
@ -188,8 +188,8 @@ class UnitAutomation{
return false return false
} }
private fun tryAttackNearbyEnemy(unit: MapUnit): Boolean { private fun tryAttackNearbyEnemy(unit: MapUnit, unitDistanceToTiles: HashMap<TileInfo, Float>): Boolean {
val attackableEnemies = getAttackableEnemies(unit) val attackableEnemies = getAttackableEnemies(unit,unitDistanceToTiles)
// Only take enemies we can fight without dying // Only take enemies we can fight without dying
.filter { .filter {
BattleDamage().calculateDamageToAttacker(MapUnitCombatant(unit), BattleDamage().calculateDamageToAttacker(MapUnitCombatant(unit),
@ -204,7 +204,7 @@ class UnitAutomation{
val cityWithHealthLeft = cityTilesToAttack.filter { it.tileToAttack.getCity()!!.health != 1 } // don't want ranged units to attack defeated cities val cityWithHealthLeft = cityTilesToAttack.filter { it.tileToAttack.getCity()!!.health != 1 } // don't want ranged units to attack defeated cities
.minBy { it.tileToAttack.getCity()!!.health } .minBy { it.tileToAttack.getCity()!!.health }
if (unit.getBaseUnit().unitType.isMelee() && capturableCity!=null) if (unit.baseUnit().unitType.isMelee() && capturableCity!=null)
enemyTileToAttack = capturableCity // enter it quickly, top priority! enemyTileToAttack = capturableCity // enter it quickly, top priority!
else if (nonCityTilesToAttack.isNotEmpty()) // second priority, units else if (nonCityTilesToAttack.isNotEmpty()) // second priority, units
@ -225,7 +225,7 @@ class UnitAutomation{
} }
private fun tryGarrisoningUnit(unit: MapUnit): Boolean { private fun tryGarrisoningUnit(unit: MapUnit): Boolean {
if(unit.getBaseUnit().unitType.isMelee()) return false // don't garrison melee units, they're not that good at it if(unit.baseUnit().unitType.isMelee()) return false // don't garrison melee units, they're not that good at it
val reachableCitiesWithoutUnits = unit.civInfo.cities.filter { val reachableCitiesWithoutUnits = unit.civInfo.cities.filter {
val centerTile = it.getCenterTile() val centerTile = it.getCenterTile()
unit.canMoveTo(centerTile) unit.canMoveTo(centerTile)
@ -258,8 +258,8 @@ class UnitAutomation{
return false return false
} }
private fun randomWalk(unit: MapUnit) { private fun randomWalk(unit: MapUnit, unitDistanceToTiles: HashMap<TileInfo, Float>) {
val reachableTiles = unit.getDistanceToTiles() val reachableTiles = unitDistanceToTiles
.filter { unit.canMoveTo(it.key) } .filter { unit.canMoveTo(it.key) }
val reachableTilesMaxWalkingDistance = reachableTiles.filter { it.value == unit.currentMovement } val reachableTilesMaxWalkingDistance = reachableTiles.filter { it.value == unit.currentMovement }
if (reachableTilesMaxWalkingDistance.any()) unit.moveToTile(reachableTilesMaxWalkingDistance.toList().getRandom().first) if (reachableTilesMaxWalkingDistance.any()) unit.moveToTile(reachableTilesMaxWalkingDistance.toList().getRandom().first)
@ -295,7 +295,7 @@ class UnitAutomation{
if(bestCityLocation==null) // We got a badass over here, all tiles within 5 are taken? Screw it, random walk. if(bestCityLocation==null) // We got a badass over here, all tiles within 5 are taken? Screw it, random walk.
{ {
randomWalk(unit) randomWalk(unit, unit.getDistanceToTiles())
return return
} }

View File

@ -43,7 +43,7 @@ class CityCombatant(val city: CityInfo) : ICombatant {
// Garrisoned unit gives up to 20% of strength to city, health-dependant // Garrisoned unit gives up to 20% of strength to city, health-dependant
if(cityTile.militaryUnit!=null) if(cityTile.militaryUnit!=null)
strength += cityTile.militaryUnit!!.getBaseUnit().strength * cityTile.militaryUnit!!.health/100f strength += cityTile.militaryUnit!!.baseUnit().strength * cityTile.militaryUnit!!.health/100f
strength += city.cityConstructions.getBuiltBuildings().sumBy{ it.cityStrength } strength += city.cityConstructions.getBuiltBuildings().sumBy{ it.cityStrength }

View File

@ -18,16 +18,16 @@ class MapUnitCombatant(val unit: MapUnit) : ICombatant {
} }
override fun getAttackingStrength(defender: ICombatant): Int { // todo remove defender override fun getAttackingStrength(defender: ICombatant): Int { // todo remove defender
if (isRanged()) return unit.getBaseUnit().rangedStrength if (isRanged()) return unit.baseUnit().rangedStrength
else return unit.getBaseUnit().strength else return unit.baseUnit().strength
} }
override fun getDefendingStrength(attacker: ICombatant): Int { // todo remove attacker override fun getDefendingStrength(attacker: ICombatant): Int { // todo remove attacker
return unit.getBaseUnit().strength return unit.baseUnit().strength
} }
override fun getUnitType(): UnitType { override fun getUnitType(): UnitType {
return unit.getBaseUnit().unitType return unit.baseUnit().unitType
} }
override fun toString(): String { override fun toString(): String {

View File

@ -199,7 +199,7 @@ class CivilizationInfo {
// disband units until there are none left OR the gold values are normal // disband units until there are none left OR the gold values are normal
if(!isBarbarianCivilization() && gold < -100 && nextTurnStats.gold.toInt() < 0) { if(!isBarbarianCivilization() && gold < -100 && nextTurnStats.gold.toInt() < 0) {
for (i in 1 until (gold / -100)) { for (i in 1 until (gold / -100)) {
var civMilitaryUnits = getCivUnits().filter { it.getBaseUnit().unitType != UnitType.Civilian } var civMilitaryUnits = getCivUnits().filter { it.baseUnit().unitType != UnitType.Civilian }
if (civMilitaryUnits.isNotEmpty()) { if (civMilitaryUnits.isNotEmpty()) {
val unitToDisband = civMilitaryUnits.first() val unitToDisband = civMilitaryUnits.first()
unitToDisband.removeFromTile() unitToDisband.removeFromTile()

View File

@ -21,11 +21,8 @@ class MapUnit {
var attacksThisTurn = 0 var attacksThisTurn = 0
var promotions = UnitPromotions() var promotions = UnitPromotions()
init{ @Transient lateinit var baseUnit: BaseUnit
promotions.unit=this fun baseUnit(): BaseUnit = baseUnit
}
fun getBaseUnit(): BaseUnit = GameBasics.Units[name]!!
fun getMovementString(): String = DecimalFormat("0.#").format(currentMovement.toDouble()) + "/" + maxMovement fun getMovementString(): String = DecimalFormat("0.#").format(currentMovement.toDouble()) + "/" + maxMovement
@Transient @Transient
@ -144,7 +141,7 @@ class MapUnit {
fun getSpecialAbilities(): MutableList<String> { fun getSpecialAbilities(): MutableList<String> {
val abilities = mutableListOf<String>() val abilities = mutableListOf<String>()
val baseUnit = getBaseUnit() val baseUnit = baseUnit()
if(baseUnit.uniques!=null) abilities.addAll(baseUnit.uniques!!) if(baseUnit.uniques!=null) abilities.addAll(baseUnit.uniques!!)
abilities.addAll(promotions.promotions.map { GameBasics.UnitPromotions[it]!!.effect }) abilities.addAll(promotions.promotions.map { GameBasics.UnitPromotions[it]!!.effect })
return abilities return abilities
@ -179,13 +176,13 @@ class MapUnit {
} }
fun removeFromTile(){ fun removeFromTile(){
if (getBaseUnit().unitType== UnitType.Civilian) getTile().civilianUnit=null if (baseUnit().unitType== UnitType.Civilian) getTile().civilianUnit=null
else getTile().militaryUnit=null else getTile().militaryUnit=null
} }
fun putInTile(tile:TileInfo){ fun putInTile(tile:TileInfo){
if(!canMoveTo(tile)) throw Exception("I can't go there!") if(!canMoveTo(tile)) throw Exception("I can't go there!")
if(getBaseUnit().unitType== UnitType.Civilian) if(baseUnit().unitType== UnitType.Civilian)
tile.civilianUnit=this tile.civilianUnit=this
else tile.militaryUnit=this else tile.militaryUnit=this
currentTile = tile currentTile = tile
@ -199,7 +196,7 @@ class MapUnit {
if(tileOwner!=null && tileOwner.civName!=owner if(tileOwner!=null && tileOwner.civName!=owner
&& (tile.isCityCenter() || !civInfo.canEnterTiles(tileOwner))) return false && (tile.isCityCenter() || !civInfo.canEnterTiles(tileOwner))) return false
if (getBaseUnit().unitType== UnitType.Civilian) if (baseUnit().unitType== UnitType.Civilian)
return tile.civilianUnit==null && (tile.militaryUnit==null || tile.militaryUnit!!.owner==owner) return tile.civilianUnit==null && (tile.militaryUnit==null || tile.militaryUnit!!.owner==owner)
else return tile.militaryUnit==null && (tile.civilianUnit==null || tile.civilianUnit!!.owner==owner) else return tile.militaryUnit==null && (tile.civilianUnit==null || tile.civilianUnit!!.owner==owner)
} }
@ -220,11 +217,12 @@ class MapUnit {
fun setTransients(){ fun setTransients(){
promotions.unit=this promotions.unit=this
baseUnit=GameBasics.Units[name]!!
} }
fun getRange(): Int { fun getRange(): Int {
if(getBaseUnit().unitType.isMelee()) return 1 if(baseUnit().unitType.isMelee()) return 1
var range = getBaseUnit().range var range = baseUnit().range
if(hasUnique("+1 Range")) range++ if(hasUnique("+1 Range")) range++
return range return range
} }

View File

@ -20,7 +20,7 @@ class UnitPromotions{
fun getAvailablePromotions(): List<Promotion> { fun getAvailablePromotions(): List<Promotion> {
return GameBasics.UnitPromotions.values return GameBasics.UnitPromotions.values
.filter { unit.getBaseUnit().unitType.toString() in it.unitTypes && it.name !in promotions } .filter { unit.baseUnit().unitType.toString() in it.unitTypes && it.name !in promotions }
.filter { it.prerequisites.isEmpty() || it.prerequisites.any { p->p in promotions } } .filter { it.prerequisites.isEmpty() || it.prerequisites.any { p->p in promotions } }
} }
} }

View File

@ -78,6 +78,7 @@ class BaseUnit : INamed, IConstruction, ICivilopedia {
unit.name = name unit.name = name
unit.maxMovement = movement unit.maxMovement = movement
unit.currentMovement = movement.toFloat() unit.currentMovement = movement.toFloat()
unit.setTransients()
return unit return unit
} }

View File

@ -209,7 +209,7 @@ class EmpireOverviewScreen : CameraStageBaseScreen(){
table.add("Closest city".tr()) table.add("Closest city".tr())
table.row() table.row()
for(unit in civInfo.getCivUnits()){ for(unit in civInfo.getCivUnits()){
val baseUnit = unit.getBaseUnit() val baseUnit = unit.baseUnit()
table.add(unit.name.tr()) table.add(unit.name.tr())
if(baseUnit.strength>0) table.add(baseUnit.strength.toString()) else table.add() if(baseUnit.strength>0) table.add(baseUnit.strength.toString()) else table.add()
if(baseUnit.rangedStrength>0) table.add(baseUnit.rangedStrength.toString()) else table.add() if(baseUnit.rangedStrength>0) table.add(baseUnit.rangedStrength.toString()) else table.add()

View File

@ -26,7 +26,7 @@ class PromotionPickerScreen(mapUnit: MapUnit) : PickerScreen() {
val availablePromotionsGroup = VerticalGroup() val availablePromotionsGroup = VerticalGroup()
availablePromotionsGroup.space(10f) availablePromotionsGroup.space(10f)
val unitType = mapUnit.getBaseUnit().unitType val unitType = mapUnit.baseUnit().unitType
val promotionsForUnitType = GameBasics.UnitPromotions.values.filter { it.unitTypes.contains(unitType.toString()) } val promotionsForUnitType = GameBasics.UnitPromotions.values.filter { it.unitTypes.contains(unitType.toString()) }
val unitAvailablePromotions = mapUnit.promotions.getAvailablePromotions() val unitAvailablePromotions = mapUnit.promotions.getAvailablePromotions()
for (promotion in promotionsForUnitType) { for (promotion in promotionsForUnitType) {

View File

@ -21,7 +21,7 @@ class WorldTileGroup(tileInfo: TileInfo) : TileGroup(tileInfo) {
val whiteHalo = if(unit.isFortified()) ImageGetter.getImage("OtherIcons/Shield.png") val whiteHalo = if(unit.isFortified()) ImageGetter.getImage("OtherIcons/Shield.png")
else ImageGetter.getImage("OtherIcons/Circle.png") else ImageGetter.getImage("OtherIcons/Circle.png")
whiteHalo.setSize(30f,30f) whiteHalo.setSize(30f,30f)
val unitImage = if(unit.getBaseUnit().unitType== UnitType.Civilian) civilianUnitImage!! val unitImage = if(unit.baseUnit().unitType== UnitType.Civilian) civilianUnitImage!!
else militaryUnitImage!! else militaryUnitImage!!
whiteHalo.center(unitImage) whiteHalo.center(unitImage)
unitImage.addActor(whiteHalo) unitImage.addActor(whiteHalo)

View File

@ -106,10 +106,10 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
if(unit.canMoveTo(tile)) if(unit.canMoveTo(tile))
tileGroups[tile]!!.showCircle(colorFromRGB(0, 120, 215)) tileGroups[tile]!!.showCircle(colorFromRGB(0, 120, 215))
val unitType = unit.getBaseUnit().unitType val unitType = unit.baseUnit().unitType
val attackableTiles: List<TileInfo> = when{ val attackableTiles: List<TileInfo> = when{
unitType==UnitType.Civilian -> unit.getDistanceToTiles().keys.toList() unitType==UnitType.Civilian -> unit.getDistanceToTiles().keys.toList()
else -> UnitAutomation().getAttackableEnemies(unit).map { it.tileToAttack } else -> UnitAutomation().getAttackableEnemies(unit, unit.getDistanceToTiles()).map { it.tileToAttack }
} }
@ -117,7 +117,7 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
it.getUnits().isNotEmpty() it.getUnits().isNotEmpty()
&& it.getUnits().first().owner != unit.owner && it.getUnits().first().owner != unit.owner
&& (playerViewableTiles.contains(it) || UnCivGame.Current.viewEntireMapForDebug)}) { && (playerViewableTiles.contains(it) || UnCivGame.Current.viewEntireMapForDebug)}) {
if(unit.getBaseUnit().unitType== UnitType.Civilian) tileGroups[tile]!!.hideCircle() if(unit.baseUnit().unitType== UnitType.Civilian) tileGroups[tile]!!.hideCircle()
else { else {
tileGroups[tile]!!.showCircle(colorFromRGB(237, 41, 57)) tileGroups[tile]!!.showCircle(colorFromRGB(237, 41, 57))
tileGroups[tile]!!.showCrosshair() tileGroups[tile]!!.showCrosshair()

View File

@ -31,7 +31,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
fun update() { fun update() {
val unitTable = worldScreen.bottomBar.unitTable val unitTable = worldScreen.bottomBar.unitTable
if (unitTable.selectedUnit == null if (unitTable.selectedUnit == null
|| unitTable.selectedUnit!!.getBaseUnit().unitType == UnitType.Civilian){ || unitTable.selectedUnit!!.baseUnit().unitType == UnitType.Civilian){
hide() hide()
return return
} // no attacker } // no attacker
@ -121,7 +121,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
attacker.unit.getDistanceToTiles() attacker.unit.getDistanceToTiles()
val attackableEnemy = UnitAutomation().getAttackableEnemies(attacker.unit) val attackableEnemy = UnitAutomation().getAttackableEnemies(attacker.unit, attacker.unit.getDistanceToTiles())
.firstOrNull{ it.tileToAttack == defender.getTile()} .firstOrNull{ it.tileToAttack == defender.getTile()}
if(attackableEnemy==null || !attacker.unit.canAttack()) attackButton.disable() if(attackableEnemy==null || !attacker.unit.canAttack()) attackButton.disable()

View File

@ -47,26 +47,26 @@ class UnitActions {
},true) },true)
} }
if(unit.getBaseUnit().unitType!= UnitType.Civilian if(unit.baseUnit().unitType!= UnitType.Civilian
&& !unit.hasUnique("No defensive terrain bonus") && !unit.isFortified()) { && !unit.hasUnique("No defensive terrain bonus") && !unit.isFortified()) {
actionList += UnitAction("Fortify", { unit.action = "Fortify 0" }, unit.currentMovement != 0f) actionList += UnitAction("Fortify", { unit.action = "Fortify 0" }, unit.currentMovement != 0f)
} }
if(unit.getBaseUnit().unitType!= UnitType.Civilian && unit.promotions.canBePromoted()){ if(unit.baseUnit().unitType!= UnitType.Civilian && unit.promotions.canBePromoted()){
actionList += UnitAction("Promote", actionList += UnitAction("Promote",
{UnCivGame.Current.screen = PromotionPickerScreen(unit)}, {UnCivGame.Current.screen = PromotionPickerScreen(unit)},
unit.currentMovement != 0f) unit.currentMovement != 0f)
} }
if(unit.getBaseUnit().upgradesTo!=null && tile.getOwner()==unit.civInfo) { if(unit.baseUnit().upgradesTo!=null && tile.getOwner()==unit.civInfo) {
var upgradedUnit = unit.getBaseUnit().getUpgradeUnit(unit.civInfo) var upgradedUnit = unit.baseUnit().getUpgradeUnit(unit.civInfo)
// Go up the upgrade tree until you find the first one which isn't obsolete // Go up the upgrade tree until you find the first one which isn't obsolete
while (upgradedUnit.obsoleteTech!=null && unit.civInfo.tech.isResearched(upgradedUnit.obsoleteTech!!)) while (upgradedUnit.obsoleteTech!=null && unit.civInfo.tech.isResearched(upgradedUnit.obsoleteTech!!))
upgradedUnit = upgradedUnit.getUpgradeUnit(unit.civInfo) upgradedUnit = upgradedUnit.getUpgradeUnit(unit.civInfo)
if (upgradedUnit.isBuildable(unit.civInfo)) { if (upgradedUnit.isBuildable(unit.civInfo)) {
val goldCostOfUpgrade = (upgradedUnit.cost - unit.getBaseUnit().cost) * 2 + 10 val goldCostOfUpgrade = (upgradedUnit.cost - unit.baseUnit().cost) * 2 + 10
actionList += UnitAction("Upgrade to [${upgradedUnit.name}] ([$goldCostOfUpgrade] gold)", actionList += UnitAction("Upgrade to [${upgradedUnit.name}] ([$goldCostOfUpgrade] gold)",
{ {
unit.civInfo.gold -= goldCostOfUpgrade unit.civInfo.gold -= goldCostOfUpgrade

View File

@ -62,13 +62,13 @@ class UnitTable(val worldScreen: WorldScreen) : Table(){
unitNameLabel.setText(nameLabelText) unitNameLabel.setText(nameLabelText)
var unitLabelText = "Movement".tr()+": " + unit.getMovementString() var unitLabelText = "Movement".tr()+": " + unit.getMovementString()
if (unit.getBaseUnit().unitType != UnitType.Civilian) if (unit.baseUnit().unitType != UnitType.Civilian)
unitLabelText += "\n"+"Strength".tr()+": " + unit.getBaseUnit().strength unitLabelText += "\n"+"Strength".tr()+": " + unit.baseUnit().strength
if (unit.getBaseUnit().rangedStrength!=0) if (unit.baseUnit().rangedStrength!=0)
unitLabelText += "\n"+"Ranged strength".tr()+": "+unit.getBaseUnit().rangedStrength unitLabelText += "\n"+"Ranged strength".tr()+": "+unit.baseUnit().rangedStrength
if (unit.getBaseUnit().unitType != UnitType.Civilian) if (unit.baseUnit().unitType != UnitType.Civilian)
unitLabelText += "\n"+"XP".tr()+": "+unit.promotions.XP+"/"+unit.promotions.xpForNextPromotion() unitLabelText += "\n"+"XP".tr()+": "+unit.promotions.XP+"/"+unit.promotions.xpForNextPromotion()
if(unit.isFortified() && unit.getFortificationTurns()>0) if(unit.isFortified() && unit.getFortificationTurns()>0)