From 1f543843afab3bff6692d0c84b9fcce12b8da6a7 Mon Sep 17 00:00:00 2001 From: Duan Tao Date: Wed, 2 Oct 2019 22:49:07 +0800 Subject: [PATCH] Better worker AI. (#1136) * Better worker AI. * Fix tiles to improve condition. * tilesToImprove changed from member to function. * Minor performance optimization. * Use the same condition for worker AI long term and short term target. --- .../logic/automation/WorkerAutomation.kt | 36 +++++++++++++++---- .../unciv/logic/city/CityExpansionManager.kt | 5 ++- core/src/com/unciv/logic/city/CityInfo.kt | 3 ++ 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/core/src/com/unciv/logic/automation/WorkerAutomation.kt b/core/src/com/unciv/logic/automation/WorkerAutomation.kt index 1085cf28f3..a77f8f1db8 100644 --- a/core/src/com/unciv/logic/automation/WorkerAutomation.kt +++ b/core/src/com/unciv/logic/automation/WorkerAutomation.kt @@ -41,6 +41,23 @@ class WorkerAutomation(val unit: MapUnit) { if(tile.improvementInProgress!=null) return // we're working! if(tryConnectingCities()) return //nothing to do, try again to connect cities + var cityListWithUnImprovedTiles = HashMap() + for (city in unit.civInfo.cities) { + cityListWithUnImprovedTiles[city.name] = + city.getTiles() + .filter { it.isLand && tileNeedToImprove(it, unit.civInfo) } + .size + } + + val mostUndevelopedCity = unit.civInfo.cities.filter{cityListWithUnImprovedTiles[it.name]!! > 0} + .sortedByDescending { cityListWithUnImprovedTiles[it.name] } + .firstOrNull { unit.movement.canReach(it.ccenterTile) } //goto most undevelopped city + if (mostUndevelopedCity != null) { + val reachedTile = unit.movement.headTowards(mostUndevelopedCity.ccenterTile) + if (reachedTile!=tile) unit.doPreTurnAction() + return + } + unit.civInfo.addNotification("[${unit.name}] has no work to do.", unit.currentTile.position, Color.GRAY) } @@ -52,7 +69,7 @@ class WorkerAutomation(val unit: MapUnit) { val targetRoad = unit.civInfo.tech.getBestRoadAvailable() val citiesThatNeedConnecting = unit.civInfo.cities - .filter { it.population.population>3 && !it.isCapital() + .filter { it.population.population>3 && !it.isCapital() && !it.isBeingRazed //City being razed should not be connected. && !it.cityStats.isConnectedToCapital(targetRoad) } if(citiesThatNeedConnecting.isEmpty()) return false // do nothing. @@ -101,12 +118,8 @@ class WorkerAutomation(val unit: MapUnit) { val workableTiles = currentTile.getTilesInDistance(4) .filter { (it.civilianUnit== null || it == currentTile) - && (it.improvement == null || (it.hasViewableResource(unit.civInfo) && !it.containsGreatImprovement() && it.getTileResource().improvement != it.improvement)) - && it.isLand - && !it.getBaseTerrain().impassable - && (it.containsUnfinishedGreatImprovement() || it.canBuildImprovement(chooseImprovement(it, unit.civInfo), unit.civInfo)) - && {val city=it.getCity(); city==null || it.getCity()?.civInfo == unit.civInfo}() // don't work tiles belonging to another civ - }.sortedByDescending { getPriority(it, unit.civInfo) }.toMutableList() + && tileNeedToImprove(it, unit.civInfo) } + .sortedByDescending { getPriority(it, unit.civInfo) }.toMutableList() // the tile needs to be actually reachable - more difficult than it seems, // which is why we DON'T calculate this for every possible tile in the radius, @@ -121,6 +134,15 @@ class WorkerAutomation(val unit: MapUnit) { else return currentTile } + private fun tileNeedToImprove(tile: TileInfo, civInfo: CivilizationInfo): Boolean { + if (!tile.isLand || tile.getBaseTerrain().impassable) + return false + val city=tile.getCity() + if (city == null || city.civInfo != civInfo) + return false + return (tile.improvement == null || (tile.hasViewableResource(civInfo) && !tile.containsGreatImprovement() && tile.getTileResource().improvement != tile.improvement)) + && (tile.containsUnfinishedGreatImprovement() || tile.canBuildImprovement(chooseImprovement(tile, civInfo), civInfo)) + } private fun getPriority(tileInfo: TileInfo, civInfo: CivilizationInfo): Int { var priority = 0 diff --git a/core/src/com/unciv/logic/city/CityExpansionManager.kt b/core/src/com/unciv/logic/city/CityExpansionManager.kt index dcfb8809a2..238de21420 100644 --- a/core/src/com/unciv/logic/city/CityExpansionManager.kt +++ b/core/src/com/unciv/logic/city/CityExpansionManager.kt @@ -11,7 +11,6 @@ class CityExpansionManager { lateinit var cityInfo: CityInfo var cultureStored: Int = 0 - fun clone(): CityExpansionManager { val toReturn = CityExpansionManager() toReturn.cultureStored=cultureStored @@ -118,7 +117,6 @@ class CityExpansionManager { cityInfo.civInfo.updateViewableTiles() } - fun nextTurn(culture: Float) { cultureStored += culture.toInt() if (cultureStored >= getCultureToNextTile()) { @@ -128,7 +126,8 @@ class CityExpansionManager { } fun setTransients(){ - for(tile in cityInfo.tiles.map { cityInfo.tileMap[it] }) + val tiles = cityInfo.getTiles() + for(tile in tiles ) tile.owningCity=cityInfo } //endregion diff --git a/core/src/com/unciv/logic/city/CityInfo.kt b/core/src/com/unciv/logic/city/CityInfo.kt index 568191921d..7628be26f9 100644 --- a/core/src/com/unciv/logic/city/CityInfo.kt +++ b/core/src/com/unciv/logic/city/CityInfo.kt @@ -279,6 +279,7 @@ class CityInfo { } isPuppet=false + cityStats.update() UnCivGame.Current.worldScreen.shouldUpdate=true } @@ -303,6 +304,7 @@ class CityInfo { resistanceCounter = population.population // I checked, and even if you puppet there's resistance for conquering isPuppet = true health = getMaxHealth() / 2 // I think that cities recover to half health when conquered? + cityStats.update() } private fun diplomaticRepercussionsForConqueringCity(oldCiv: CivilizationInfo, conqueringCiv: CivilizationInfo) { @@ -342,6 +344,7 @@ class CityInfo { if(foundingCiv.cities.size == 1) cityConstructions.addBuilding("Palace") // Resurrection! isPuppet = false + cityStats.update() UnCivGame.Current.worldScreen.shouldUpdate=true }