From ec652680997ddc69a12ed3d013d90e4dc727d784 Mon Sep 17 00:00:00 2001 From: Yair Morgenstern Date: Sat, 1 Dec 2018 22:16:26 +0200 Subject: [PATCH] AI now uses Great People properly Fixed bug where loading a game with a free policy would freeze everything --- android/assets/jsons/Translations.json | 3 +- android/assets/jsons/Units.json | 2 +- core/src/com/unciv/UnCivGame.kt | 3 +- .../unciv/logic/automation/UnitAutomation.kt | 126 ++++++++----- core/src/com/unciv/logic/city/CityStats.kt | 33 ++-- core/src/com/unciv/logic/map/MapUnit.kt | 17 +- core/src/com/unciv/ui/utils/ImageGetter.kt | 1 + .../unciv/ui/worldscreen/unit/UnitActions.kt | 172 +++++++++--------- 8 files changed, 198 insertions(+), 159 deletions(-) diff --git a/android/assets/jsons/Translations.json b/android/assets/jsons/Translations.json index bda50181e1..425b09c837 100644 --- a/android/assets/jsons/Translations.json +++ b/android/assets/jsons/Translations.json @@ -2899,10 +2899,11 @@ Romanian:"Accepta" Spanish:"Aceptar" } + "There's nothing on the table":{ Italian:"Non c'è niente da trattare" Russian:"Вы ничего не предложили" //Don't know how to properly translate this one, but i think this will do okay - French:"Rien n'est en jeu //Don't know how to properly translate this one, I went with the figurative sens e.g. nothing is in danger of being lost + French:"Rien n'est en jeu" //Don't know how to properly translate this one, I went with the figurative sens e.g. nothing is in danger of being lost Spanish:"No hay nada sobre la mesa" } diff --git a/android/assets/jsons/Units.json b/android/assets/jsons/Units.json index bbaf45f5fd..3261721245 100644 --- a/android/assets/jsons/Units.json +++ b/android/assets/jsons/Units.json @@ -394,7 +394,7 @@ name:"Great Merchant", unbuildable:true, unitType:"Civilian", - uniques:["Can undertake a trade mission, giving a large sum of gold","Can build improvement: Customs House"] + uniques:["Can undertake a trade mission, giving a large sum of gold","Can build improvement: Customs house"] movement:2 }, { diff --git a/core/src/com/unciv/UnCivGame.kt b/core/src/com/unciv/UnCivGame.kt index 23dff849f8..3b353427ab 100644 --- a/core/src/com/unciv/UnCivGame.kt +++ b/core/src/com/unciv/UnCivGame.kt @@ -55,13 +55,12 @@ class UnCivGame : Game() { worldScreen = WorldScreen() setWorldScreen() - } fun setWorldScreen() { setScreen(worldScreen) - worldScreen.update() Gdx.input.inputProcessor = worldScreen.stage + worldScreen.update() // This can set the screen to the policy picker or tech picker screen, so the input processor must come before } override fun resume() { diff --git a/core/src/com/unciv/logic/automation/UnitAutomation.kt b/core/src/com/unciv/logic/automation/UnitAutomation.kt index a11937d6aa..a841e8b815 100644 --- a/core/src/com/unciv/logic/automation/UnitAutomation.kt +++ b/core/src/com/unciv/logic/automation/UnitAutomation.kt @@ -8,10 +8,12 @@ import com.unciv.logic.battle.MapUnitCombatant import com.unciv.logic.city.CityInfo import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.DiplomaticStatus +import com.unciv.logic.civilization.GreatPersonManager import com.unciv.logic.map.MapUnit import com.unciv.logic.map.TileInfo import com.unciv.models.gamebasics.GameBasics import com.unciv.models.gamebasics.tile.TerrainType +import com.unciv.models.stats.Stats import com.unciv.ui.utils.getRandom import com.unciv.ui.worldscreen.unit.UnitAction import com.unciv.ui.worldscreen.unit.UnitActions @@ -21,21 +23,20 @@ class UnitAutomation{ fun automateUnitMoves(unit: MapUnit) { if (unit.name == "Settler") { - automateSettlerActions(unit) - return + return SpecificUnitAutomation().automateSettlerActions(unit) } if (unit.name == "Worker") { - WorkerAutomation(unit).automateWorkerAction() - return + return WorkerAutomation(unit).automateWorkerAction() } if(unit.name=="Work Boats"){ - automateWorkBoats(unit) - return + return SpecificUnitAutomation().automateWorkBoats(unit) } - if(unit.name.startsWith("Great")) return // I don't know what to do with you yet. + if(unit.name.startsWith("Great")){ + return SpecificUnitAutomation().automateGreatPerson(unit)// I don't know what to do with you yet. + } val unitActions = UnitActions().getUnitActions(unit,UnCivGame.Current.worldScreen) var unitDistanceToTiles = unit.getDistanceToTiles() @@ -81,30 +82,6 @@ class UnitAutomation{ // if both failed, then... there aren't any reachable tiles. Which is possible. } - private fun hasWorkableSeaResource(tileInfo: TileInfo, civInfo: CivilizationInfo): Boolean { - return tileInfo.hasViewableResource(civInfo) && tileInfo.isWater() && tileInfo.improvement==null - } - - private fun automateWorkBoats(unit: MapUnit) { - val seaResourcesInCities = unit.civInfo.cities.flatMap { it.getTilesInRange() }.asSequence() - .filter { hasWorkableSeaResource(it, unit.civInfo) && (unit.canMoveTo(it) || unit.currentTile == it) } - val closestReachableResource = seaResourcesInCities.sortedBy { it.arialDistanceTo(unit.currentTile) } - .firstOrNull { unit.movementAlgs().canReach(it) } - - if (closestReachableResource != null) { - unit.movementAlgs().headTowards(closestReachableResource) - if (unit.currentMovement > 0 && unit.currentTile == closestReachableResource) { - val createImprovementAction = UnitActions().getUnitActions(unit, UnCivGame.Current.worldScreen) - .firstOrNull { it.name.startsWith("Create") } // could be either fishing boats or oil well - if (createImprovementAction != null) { - createImprovementAction.action() - return // unit is already gone, can't "explore" - } - } - } - else explore(unit, unit.getDistanceToTiles()) - } - fun rankTileForHealing(tileInfo: TileInfo, unit: MapUnit): Int { val tileOwner = tileInfo.getOwner() when{ @@ -322,7 +299,7 @@ class UnitAutomation{ return true } - private fun explore(unit: MapUnit, unitDistanceToTiles: HashMap) { + internal fun explore(unit: MapUnit, unitDistanceToTiles: HashMap) { val distanceToTiles:HashMap if(tryGoToRuin(unit,unitDistanceToTiles)) { @@ -347,6 +324,49 @@ class UnitAutomation{ else if (reachableTiles.any()) unit.moveToTile(reachableTiles.toList().getRandom().first) } + fun automatedExplore(unit:MapUnit){ + if(tryGoToRuin(unit,unit.getDistanceToTiles()) && unit.currentMovement==0f) return + + for(i in 1..10){ + val unexploredTilesAtDistance = unit.getTile().getTilesAtDistance(i) + .filter { unit.canMoveTo(it) && it.position !in unit.civInfo.exploredTiles + && unit.movementAlgs().canReach(it) } + if(unexploredTilesAtDistance.isNotEmpty()){ + unit.movementAlgs().headTowards(unexploredTilesAtDistance.getRandom()) + return + } + } + } + +} + +class SpecificUnitAutomation{ + + private fun hasWorkableSeaResource(tileInfo: TileInfo, civInfo: CivilizationInfo): Boolean { + return tileInfo.hasViewableResource(civInfo) && tileInfo.isWater() && tileInfo.improvement==null + } + + fun automateWorkBoats(unit: MapUnit) { + val seaResourcesInCities = unit.civInfo.cities.flatMap { it.getTilesInRange() }.asSequence() + .filter { hasWorkableSeaResource(it, unit.civInfo) && (unit.canMoveTo(it) || unit.currentTile == it) } + val closestReachableResource = seaResourcesInCities.sortedBy { it.arialDistanceTo(unit.currentTile) } + .firstOrNull { unit.movementAlgs().canReach(it) } + + if (closestReachableResource != null) { + unit.movementAlgs().headTowards(closestReachableResource) + if (unit.currentMovement > 0 && unit.currentTile == closestReachableResource) { + val createImprovementAction = UnitActions().getUnitActions(unit, UnCivGame.Current.worldScreen) + .firstOrNull { it.name.startsWith("Create") } // could be either fishing boats or oil well + if (createImprovementAction != null) { + createImprovementAction.action() + return // unit is already gone, can't "explore" + } + } + } + else UnitAutomation().explore(unit, unit.getDistanceToTiles()) + } + + fun rankTileAsCityCenter(tileInfo: TileInfo, nearbyTileRankings: Map): Float { val bestTilesFromOuterLayer = tileInfo.getTilesAtDistance(2) .asSequence() @@ -362,7 +382,8 @@ class UnitAutomation{ return rank } - private fun automateSettlerActions(unit: MapUnit) { + + fun automateSettlerActions(unit: MapUnit) { if(unit.getTile().militaryUnit==null) return // Don't move until you're accompanied by a military unit val tilesNearCities = unit.civInfo.gameInfo.civilizations.flatMap { it.cities } @@ -382,7 +403,7 @@ class UnitAutomation{ if(bestCityLocation==null) // We got a badass over here, all tiles within 5 are taken? Screw it, random walk. { - explore(unit, unit.getDistanceToTiles()) + UnitAutomation().explore(unit, unit.getDistanceToTiles()) return } @@ -398,18 +419,39 @@ class UnitAutomation{ } } - fun automatedExplore(unit:MapUnit){ - if(tryGoToRuin(unit,unit.getDistanceToTiles()) && unit.currentMovement==0f) return + fun automateGreatPerson(unit: MapUnit) { + val relatedStat = GreatPersonManager().statToGreatPersonMapping.entries.first { it.value==unit.name }.key - for(i in 1..10){ - val unexploredTilesAtDistance = unit.getTile().getTilesAtDistance(i) - .filter { unit.canMoveTo(it) && it.position !in unit.civInfo.exploredTiles - && unit.movementAlgs().canReach(it) } - if(unexploredTilesAtDistance.isNotEmpty()){ - unit.movementAlgs().headTowards(unexploredTilesAtDistance.getRandom()) + val citiesByStatBoost = unit.civInfo.cities.sortedByDescending{ + val stats = Stats() + for (bonus in it.cityStats.statPercentBonusList.values) stats.add(bonus) + stats.toHashMap()[relatedStat]!! + } + for(city in citiesByStatBoost){ + val pathToCity =unit.movementAlgs().getShortestPath(city.getCenterTile()) + if(pathToCity.isEmpty()) continue + if(pathToCity.size>2) { + unit.movementAlgs().headTowards(city.getCenterTile()) return } + + // if we got here, we're pretty close, start looking! + val tiles = city.getTiles().asSequence() + .filter { (unit.canMoveTo(it) || unit.currentTile==it) + && it.isLand() + && !it.isCityCenter() + && it.resource==null } + .sortedByDescending { Automation().rankTile(it,unit.civInfo) }.toList() + val chosenTile = tiles.firstOrNull { unit.movementAlgs().canReach(it) } + if(chosenTile==null) continue // to another city + + unit.movementAlgs().headTowards(chosenTile) + if(unit.currentTile==chosenTile && unit.currentMovement>0) + UnitActions().getUnitActions(unit,UnCivGame.Current.worldScreen) + .first { it.name.startsWith("Construct") }.action() + return } + } } \ No newline at end of file diff --git a/core/src/com/unciv/logic/city/CityStats.kt b/core/src/com/unciv/logic/city/CityStats.kt index f5cddc1f01..cfab399baf 100644 --- a/core/src/com/unciv/logic/city/CityStats.kt +++ b/core/src/com/unciv/logic/city/CityStats.kt @@ -11,14 +11,11 @@ import com.unciv.models.stats.Stats class CityStats { - @Transient - var baseStatList = LinkedHashMap() - @Transient - var happinessList = LinkedHashMap() - @Transient - var currentCityStats: Stats = Stats() // This is so we won't have to calculate this multiple times - takes a lot of time, especially on phones - @Transient - lateinit var cityInfo: CityInfo + @Transient var baseStatList = LinkedHashMap() + @Transient var statPercentBonusList = LinkedHashMap() + @Transient var happinessList = LinkedHashMap() + @Transient var currentCityStats: Stats = Stats() // This is so we won't have to calculate this multiple times - takes a lot of time, especially on phones + @Transient lateinit var cityInfo: CityInfo //region pure fuctions private fun getStatsFromTiles(): Stats { @@ -28,7 +25,7 @@ class CityStats { return stats } - fun getStatsFromTradeRoute(): Stats { + private fun getStatsFromTradeRoute(): Stats { val stats = Stats() if (!cityInfo.isCapital() && isConnectedToCapital(RoadStatus.Road)) { val civInfo = cityInfo.civInfo @@ -252,15 +249,19 @@ class CityStats { newBaseStatList["Buildings"] = cityInfo.cityConstructions.getStats() newBaseStatList["Policies"] = getStatsFromPolicies(civInfo.policies.adoptedPolicies) - val statPercentBonuses = cityInfo.cityConstructions.getStatPercentBonuses() - statPercentBonuses.add(getStatPercentBonusesFromGoldenAge(cityInfo.civInfo.goldenAges.isGoldenAge())) - statPercentBonuses.add(getStatPercentBonusesFromPolicies(civInfo.policies.adoptedPolicies, cityInfo.cityConstructions)) + val newStatPercentBonusList = LinkedHashMap() + newStatPercentBonusList["Buildings"] = cityInfo.cityConstructions.getStatPercentBonuses() + newStatPercentBonusList["Golden Age"]=getStatPercentBonusesFromGoldenAge(cityInfo.civInfo.goldenAges.isGoldenAge()) + newStatPercentBonusList["Policies"]=getStatPercentBonusesFromPolicies(civInfo.policies.adoptedPolicies, cityInfo.cityConstructions) // from wonders - Culture in all cities increased by 25% - statPercentBonuses.add(getStatPercentBonusesFromWonders()) - statPercentBonuses.add(getStatPercentBonusesFromRailroad()) - statPercentBonuses.add(getStatPercentBonusesFromMarble()) - statPercentBonuses.add(getStatPercentBonusesFromComputers()) + newStatPercentBonusList["Wonders"]=getStatPercentBonusesFromWonders() + newStatPercentBonusList["Railroad"]=getStatPercentBonusesFromRailroad() + newStatPercentBonusList["Marble"]=getStatPercentBonusesFromMarble() + newStatPercentBonusList["Computers"]=getStatPercentBonusesFromComputers() + statPercentBonusList=newStatPercentBonusList + val statPercentBonuses = Stats() + for(bonus in statPercentBonusList.values) statPercentBonuses.add(bonus) //val stats = Stats() for (stat in newBaseStatList.values) stat.production *= 1 + statPercentBonuses.production / 100 diff --git a/core/src/com/unciv/logic/map/MapUnit.kt b/core/src/com/unciv/logic/map/MapUnit.kt index dc4a2f51d7..7023319629 100644 --- a/core/src/com/unciv/logic/map/MapUnit.kt +++ b/core/src/com/unciv/logic/map/MapUnit.kt @@ -6,6 +6,7 @@ import com.unciv.logic.automation.UnitAutomation import com.unciv.logic.automation.WorkerAutomation import com.unciv.logic.civilization.CivilizationInfo import com.unciv.models.gamebasics.GameBasics +import com.unciv.models.gamebasics.tech.TechEra import com.unciv.models.gamebasics.unit.BaseUnit import com.unciv.models.gamebasics.unit.UnitType import com.unciv.ui.utils.getRandom @@ -327,34 +328,38 @@ class MapUnit { val city = civInfo.cities.getRandom() city.population.population++ city.population.autoAssignPopulation() - civInfo.addNotification("We have found survivors the ruins - population added to ["+city.name+"]",city.location, Color.GREEN) + civInfo.addNotification("We have found survivors the ruins - population added to ["+city.name+"]",currentTile.position, Color.GREEN) } val researchableAncientEraTechs = GameBasics.Technologies.values - .filter { !civInfo.tech.isResearched(it.name) && civInfo.tech.canBeResearched(it.name)} + .filter { + !civInfo.tech.isResearched(it.name) + && civInfo.tech.canBeResearched(it.name) + && it.era() == TechEra.Ancient + } if(researchableAncientEraTechs.isNotEmpty()) actions.add { val tech = researchableAncientEraTechs.getRandom().name civInfo.tech.techsResearched.add(tech) if(civInfo.tech.techsToResearch.contains(tech)) civInfo.tech.techsToResearch.remove(tech) - civInfo.addNotification("We have discovered the lost technology of [$tech] in the ruins!",null, Color.BLUE) + civInfo.addNotification("We have discovered the lost technology of [$tech] in the ruins!",currentTile.position, Color.BLUE) } actions.add { val chosenUnit = listOf("Settler","Worker","Warrior").getRandom() civInfo.placeUnitNearTile(currentTile.position,chosenUnit) - civInfo.addNotification("A [$chosenUnit] has joined us!",null, Color.BLUE) + civInfo.addNotification("A [$chosenUnit] has joined us!",currentTile.position, Color.BROWN) } if(!type.isCivilian()) actions.add { promotions.XP+=10 - civInfo.addNotification("An ancient tribe trains our [$name] in their ways of combat!",null, Color.RED) + civInfo.addNotification("An ancient tribe trains our [$name] in their ways of combat!",currentTile.position, Color.RED) } actions.add { val amount = listOf(25,60,100).getRandom() civInfo.gold+=amount - civInfo.addNotification("We have found a stash of [$amount] gold in the ruins!!",null, Color.RED) + civInfo.addNotification("We have found a stash of [$amount] gold in the ruins!!",currentTile.position, Color.GOLD) } (actions.getRandom())() diff --git a/core/src/com/unciv/ui/utils/ImageGetter.kt b/core/src/com/unciv/ui/utils/ImageGetter.kt index c4c3d86106..cab7e12f40 100644 --- a/core/src/com/unciv/ui/utils/ImageGetter.kt +++ b/core/src/com/unciv/ui/utils/ImageGetter.kt @@ -76,6 +76,7 @@ object ImageGetter { fun getImprovementIcon(improvementName:String, size:Float=20f):Actor{ val iconGroup = getImage("ImprovementIcons/$improvementName").surroundWithCircle(size) + val improvement = GameBasics.TileImprovements[improvementName]!! when { improvement.food>0 -> iconGroup.circle.color= foodCircleColor diff --git a/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt b/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt index a3d06864e2..a96da9256f 100644 --- a/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt +++ b/core/src/com/unciv/ui/worldscreen/unit/UnitActions.kt @@ -16,7 +16,7 @@ import com.unciv.ui.worldscreen.optionstable.YesNoPopupTable import java.util.* import kotlin.math.max -class UnitAction(var name: String, var action:()->Unit, var canAct:Boolean) +class UnitAction(var name: String, var canAct:Boolean, var action:()->Unit) class UnitActions { @@ -33,35 +33,34 @@ class UnitActions { val unitTable = worldScreen.bottomBar.unitTable val actionList = ArrayList() - if(unit.action!=null && unit.action!!.startsWith("moveTo")){ + if(unit.action!=null && unit.action!!.startsWith("moveTo")) { actionList += - UnitAction("Stop movement", { - unitTable.currentlyExecutingAction = null - unit.action=null - },true) + UnitAction("Stop movement", true) { + unitTable.currentlyExecutingAction = null + unit.action = null + } } if(!unit.type.isCivilian() && !unit.isEmbarked() && !unit.type.isWaterUnit() && !unit.hasUnique("No defensive terrain bonus") && !unit.isFortified()) { - actionList += UnitAction("Fortify", { unit.action = "Fortify 0" }, unit.currentMovement != 0f) + actionList += UnitAction("Fortify", unit.currentMovement != 0f) { unit.action = "Fortify 0" } } if(!unit.isFortified() && actionList.none{it.name=="Fortify"} && unit.action!="Sleep") { - actionList += UnitAction("Sleep", { unit.action = "Sleep" }, unit.currentMovement != 0f) + actionList += UnitAction("Sleep",unit.currentMovement != 0f) { unit.action = "Sleep" } } if(unit.type == UnitType.Scout){ if(unit.action != "explore") - actionList += UnitAction("Explore", { UnitAutomation().automatedExplore(unit); unit.action = "explore" }, - unit.currentMovement != 0f) + actionList += UnitAction("Explore",unit.currentMovement != 0f) + { UnitAutomation().automatedExplore(unit); unit.action = "explore" } else - actionList += UnitAction("Stop exploration", { unit.action = null }, true) + actionList += UnitAction("Stop exploration", true) { unit.action = null } } - if(!unit.type.isCivilian() && unit.promotions.canBePromoted()){ - actionList += UnitAction("Promote", - {UnCivGame.Current.screen = PromotionPickerScreen(unit)}, - unit.currentMovement != 0f) + if(!unit.type.isCivilian() && unit.promotions.canBePromoted()) { + actionList += UnitAction("Promote", unit.currentMovement != 0f) + { UnCivGame.Current.screen = PromotionPickerScreen(unit) } } if(unit.baseUnit().upgradesTo!=null && tile.getOwner()==unit.civInfo) { @@ -73,60 +72,57 @@ class UnitActions { if (upgradedUnit.isBuildable(unit.civInfo)) { var goldCostOfUpgrade = (upgradedUnit.cost - unit.baseUnit().cost) * 2 + 10 - if(unit.civInfo.policies.isAdopted("Professional Army")) goldCostOfUpgrade = (goldCostOfUpgrade* 0.66f).toInt() + if (unit.civInfo.policies.isAdopted("Professional Army")) goldCostOfUpgrade = (goldCostOfUpgrade * 0.66f).toInt() actionList += UnitAction("Upgrade to [${upgradedUnit.name}] ([$goldCostOfUpgrade] gold)", - { - unit.civInfo.gold -= goldCostOfUpgrade - val unitTile = unit.getTile() - unit.destroy() - val newunit = unit.civInfo.placeUnitNearTile(unitTile.position, upgradedUnit.name) - newunit.health = unit.health - newunit.promotions = unit.promotions - newunit.currentMovement=0f - }, unit.civInfo.gold >= goldCostOfUpgrade && !unit.isEmbarked() - && unit.currentMovement == unit.getMaxMovement().toFloat() ) + && unit.currentMovement == unit.getMaxMovement().toFloat() + ) { + unit.civInfo.gold -= goldCostOfUpgrade + val unitTile = unit.getTile() + unit.destroy() + val newunit = unit.civInfo.placeUnitNearTile(unitTile.position, upgradedUnit.name) + newunit.health = unit.health + newunit.promotions = unit.promotions + newunit.currentMovement = 0f + } } } if(unit.hasUnique("Must set up to ranged attack") && unit.action != "Set Up" && !unit.isEmbarked()) - actionList+=UnitAction("Set up", - {unit.action="Set Up"; unit.currentMovement = max(0f, unit.currentMovement-1)}, - unit.currentMovement != 0f) + actionList+=UnitAction("Set up",unit.currentMovement != 0f) + {unit.action="Set Up"; unit.currentMovement = max(0f, unit.currentMovement-1)} if (unit.hasUnique("Founds a new city") && !unit.isEmbarked()) { actionList += UnitAction("Found city", - { - worldScreen.displayTutorials("CityFounded") - - unit.civInfo.addCity(tile.position) - tile.improvement=null - unitTable.currentlyExecutingAction = null // In case the settler was in the middle of doing something and we then founded a city with it - unit.destroy() - }, unit.currentMovement != 0f && !tile.getTilesInDistance(3).any { it.isCityCenter() }) + { + worldScreen.displayTutorials("CityFounded") + + unit.civInfo.addCity(tile.position) + tile.improvement = null + unitTable.currentlyExecutingAction = null // In case the settler was in the middle of doing something and we then founded a city with it + unit.destroy() + } } if (unit.hasUnique("Can build improvements on tiles") && !unit.isEmbarked()) { actionList += UnitAction("Construct improvement", - { worldScreen.game.screen = ImprovementPickerScreen(tile) }, unit.currentMovement != 0f && !tile.isCityCenter() - && GameBasics.TileImprovements.values.any { tile.canBuildImprovement(it, unit.civInfo) }) + && GameBasics.TileImprovements.values.any { tile.canBuildImprovement(it, unit.civInfo) } + ) { worldScreen.game.screen = ImprovementPickerScreen(tile) } if("automation" == unit.action){ - actionList += UnitAction("Stop automation", - {unit.action = null},true) + actionList += UnitAction("Stop automation",true) {unit.action = null} } else { - actionList += UnitAction("Automate", - { - unit.action = "automation" - WorkerAutomation(unit).automateWorkerAction() - },unit.currentMovement != 0f - ) + actionList += UnitAction("Automate", unit.currentMovement != 0f) + { + unit.action = "automation" + WorkerAutomation(unit).automateWorkerAction() + } } } @@ -135,68 +131,62 @@ class UnitActions { && tile.getTileResource().improvement == improvement && unit.civInfo.tech.isResearched(GameBasics.TileImprovements[improvement]!!.techRequired!!) ) - actionList += UnitAction("Create $improvement", { + actionList += UnitAction("Create $improvement", unit.currentMovement != 0f) { tile.improvement = improvement unit.destroy() - }, unit.currentMovement != 0f) + } } + for(unique in unit.getUniques().filter { it.startsWith("Can build improvement: ") }){ + val improvementName = unique.replace("Can build improvement: ","") + actionList += UnitAction("Construct $improvementName", + unit.currentMovement != 0f && !tile.isCityCenter(), + constructImprovementAndDestroyUnit(unit, improvementName)) + } + + if (unit.name == "Great Scientist" && !unit.isEmbarked()) { - actionList += UnitAction( "Discover Technology", - { - unit.civInfo.tech.freeTechs += 1 - unit.destroy() - worldScreen.game.screen = TechPickerScreen(true, unit.civInfo) - },unit.currentMovement != 0f) - actionList += UnitAction("Construct Academy", - constructImprovementAndDestroyUnit(unit, "Academy"), - unit.currentMovement != 0f && !tile.isCityCenter()) + actionList += UnitAction( "Discover Technology",unit.currentMovement != 0f + ) { + unit.civInfo.tech.freeTechs += 1 + unit.destroy() + worldScreen.game.screen = TechPickerScreen(true, unit.civInfo) + } } if (unit.name == "Great Artist" && !unit.isEmbarked()) { - actionList += UnitAction( "Start Golden Age", - { - unit.civInfo.goldenAges.enterGoldenAge() - unit.destroy() - },unit.currentMovement != 0f - ) - actionList += UnitAction("Construct Landmark", - constructImprovementAndDestroyUnit(unit, "Landmark"), - unit.currentMovement != 0f && !tile.isCityCenter()) + actionList += UnitAction( "Start Golden Age",unit.currentMovement != 0f + ) { + unit.civInfo.goldenAges.enterGoldenAge() + unit.destroy() + } } if (unit.name == "Great Engineer" && !unit.isEmbarked()) { actionList += UnitAction( "Hurry Wonder", - { - tile.getCity()!!.cityConstructions.addProduction(300 + 30 * tile.getCity()!!.population.population) //http://civilization.wikia.com/wiki/Great_engineer_(Civ5) - unit.destroy() - }, unit.currentMovement != 0f && - tile.isCityCenter() && - tile.getCity()!!.cityConstructions.getCurrentConstruction() is Building && - (tile.getCity()!!.cityConstructions.getCurrentConstruction() as Building).isWonder) - - actionList += UnitAction("Construct Manufactory", - constructImprovementAndDestroyUnit(unit, "Manufactory"), - unit.currentMovement != 0f && !tile.isCityCenter()) + tile.isCityCenter() && + tile.getCity()!!.cityConstructions.getCurrentConstruction() is Building && + (tile.getCity()!!.cityConstructions.getCurrentConstruction() as Building).isWonder + ) { + tile.getCity()!!.cityConstructions.addProduction(300 + 30 * tile.getCity()!!.population.population) //http://civilization.wikia.com/wiki/Great_engineer_(Civ5) + unit.destroy() + } } if (unit.name == "Great Merchant" && !unit.isEmbarked()) { - actionList += UnitAction("Conduct Trade Mission", - { - unit.civInfo.gold += 350 // + 50 * era_number - todo! - unit.destroy() - },unit.currentMovement != 0f) - actionList += UnitAction( "Construct Customs House", - constructImprovementAndDestroyUnit(unit, "Customs house"), - unit.currentMovement != 0f && !tile.isCityCenter()) + actionList += UnitAction("Conduct Trade Mission", unit.currentMovement != 0f + ) { + unit.civInfo.gold += 350 // + 50 * era_number - todo! + unit.destroy() + } } - actionList += UnitAction("Disband unit", - { - YesNoPopupTable("Do you really want to disband this unit?".tr(), - {unit.destroy(); worldScreen.update()} ) - },unit.currentMovement != 0f) + actionList += UnitAction("Disband unit",unit.currentMovement != 0f + ) { + YesNoPopupTable("Do you really want to disband this unit?".tr(), + {unit.destroy(); worldScreen.update()} ) + } return actionList }