Skip to content

Commit d2148d4

Browse files
committed
Mitigate yairm210#10613 - remove a !! by splitting 'getImprovementToImprove' and using it as source of truth for the improvement to start working on, INSTEAD of counting on the fact that chooseImprovement returns that improvement.
Which it looks like it won't, if somehow the improvementInProgress is NOT in the list of potentialTileImprovements. Only case I can think of is: You captured an enemy city with a civ--unique improvement in the middle of construction. So fixed that as well.
1 parent 09dd8c6 commit d2148d4

File tree

1 file changed

+50
-29
lines changed

1 file changed

+50
-29
lines changed

core/src/com/unciv/logic/automation/unit/WorkerAutomation.kt

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class WorkerAutomation(
5050
private val bestRoadAvailable: RoadStatus =
5151
cloningSource?.bestRoadAvailable ?:
5252
//Player can choose not to auto-build roads & railroads.
53-
if (civInfo.isHuman() && (!UncivGame.Current.settings.autoBuildingRoads
53+
if (civInfo.isHuman() && (!UncivGame.Current.settings.autoBuildingRoads
5454
|| UncivGame.Current.settings.autoPlay.isAutoPlayingAndFullAI()))
5555
RoadStatus.None
5656
else civInfo.tech.getBestRoadAvailable()
@@ -163,9 +163,12 @@ class WorkerAutomation(
163163
return
164164
}
165165

166-
if (currentTile.improvementInProgress == null && tileCanBeImproved(unit, currentTile)) {
167-
debug("WorkerAutomation: ${unit.label()} -> start improving $currentTile")
168-
return currentTile.startWorkingOnImprovement(chooseImprovement(unit, currentTile)!!, civInfo, unit)
166+
if (currentTile.improvementInProgress == null) {
167+
val newImprovement = getImprovementToImprove(unit, currentTile)
168+
if (newImprovement != null) {
169+
debug("WorkerAutomation: ${unit.label()} -> start improving $currentTile")
170+
return currentTile.startWorkingOnImprovement(newImprovement, civInfo, unit)
171+
}
169172
}
170173

171174
if (currentTile.improvementInProgress != null) return // we're working!
@@ -180,7 +183,7 @@ class WorkerAutomation(
180183
val citiesToNumberOfUnimprovedTiles = HashMap<String, Int>()
181184
for (city in unit.civ.cities) {
182185
citiesToNumberOfUnimprovedTiles[city.id] = city.getTiles()
183-
.count { it.isLand && it.civilianUnit == null && (tileCanBeImproved(unit, it) || it.isPillaged()) }
186+
.count { it.isLand && it.civilianUnit == null && (it.isPillaged() || tileCanBeImproved(unit, it)) }
184187
}
185188

186189
val mostUndevelopedCity = unit.civ.cities.asSequence()
@@ -302,7 +305,7 @@ class WorkerAutomation(
302305

303306
// These are the expensive calculations (tileCanBeImproved, canReach), so we only apply these filters after everything else it done.
304307
val selectedTile = workableTilesPrioritized
305-
.firstOrNull { unit.movement.canReach(it) && (tileCanBeImproved(unit, it) || it.isPillaged()) }
308+
.firstOrNull { unit.movement.canReach(it) && (it.isPillaged() || tileCanBeImproved(unit, it)) }
306309
?: return currentTile
307310

308311
// Note: workableTiles is a Sequence, and we oiginally used workableTiles.contains for the second
@@ -311,7 +314,7 @@ class WorkerAutomation(
311314
// currentTile is always the very first entry of the _unsorted_ Sequence - if it is still
312315
// contained at all and not dropped by the filters - which is the point here.
313316
return if ( currentTile == selectedTile // No choice
314-
|| (!tileCanBeImproved(unit, currentTile) && !currentTile.isPillaged()) // current tile is unimprovable
317+
|| (!currentTile.isPillaged() && !tileCanBeImproved(unit, currentTile)) // current tile is unimprovable
315318
|| workableTilesCenterFirst.firstOrNull() != currentTile // current tile is unworkable by city
316319
|| getPriority(selectedTile) > getPriority(currentTile)) // current tile is less important
317320
selectedTile
@@ -323,45 +326,62 @@ class WorkerAutomation(
323326
* (but does not check whether the ruleset contains any unit capable of it)
324327
*/
325328
private fun tileCanBeImproved(unit: MapUnit, tile: Tile): Boolean {
329+
return getImprovementToImprove(unit, tile) != null
330+
}
331+
332+
private fun getImprovementToImprove(unit: MapUnit, tile: Tile): TileImprovement? {
326333
//todo This is wrong but works for Alpha Frontier, because the unit has both:
327334
// It should test for the build over time ability, but this tests the create and die ability
328-
if (!tile.isLand && !unit.cache.hasUniqueToCreateWaterImprovements) return false
335+
if (!tile.isLand && !unit.cache.hasUniqueToCreateWaterImprovements) return null
329336
// Allow outlandish mods having non-road improvements on Mountains
330-
if (tile.isImpassible() && !unit.cache.canPassThroughImpassableTiles) return false
331-
if (tile.isCityCenter()) return false
337+
if (tile.isImpassible() && !unit.cache.canPassThroughImpassableTiles) return null
338+
if (tile.isCityCenter()) return null
332339

333340
val city = tile.getCity()
334341
if (city == null || city.civ != civInfo)
335-
return false
342+
return null
336343

337344
if (!city.tilesInRange.contains(tile)
338-
&& !tile.hasViewableResource(civInfo)
339-
&& civInfo.cities.none { it.getCenterTile().aerialDistanceTo(tile) <= 3 })
340-
return false // unworkable tile
345+
&& !tile.hasViewableResource(civInfo)
346+
&& civInfo.cities.none { it.getCenterTile().aerialDistanceTo(tile) <= 3 }
347+
)
348+
return null // unworkable tile
341349

342350
//If the tile is a junk improvement or a fort placed in a bad location.
343351
val junkImprovement = tile.getTileImprovement()?.hasUnique(UniqueType.AutomatedWorkersWillReplace) == true
344-
|| (tile.improvement == Constants.fort && !evaluateFortSuroundings(tile, false)
345-
&& (!civInfo.isHuman() || UncivGame.Current.settings.autoPlay.isAutoPlayingAndFullAI()))
352+
|| (tile.improvement == Constants.fort && !evaluateFortSuroundings(tile, false)
353+
&& (!civInfo.isHuman() || UncivGame.Current.settings.autoPlay.isAutoPlayingAndFullAI()))
346354

347355
if (tile.improvement != null && !junkImprovement
348-
&& !UncivGame.Current.settings.automatedWorkersReplaceImprovements
349-
&& unit.civ.isHuman() && !UncivGame.Current.settings.autoPlay.isAutoPlayingAndFullAI())
350-
return false
356+
&& !UncivGame.Current.settings.automatedWorkersReplaceImprovements
357+
&& unit.civ.isHuman() && !UncivGame.Current.settings.autoPlay.isAutoPlayingAndFullAI()
358+
)
359+
return null
351360

352-
if (tile.improvement == null || junkImprovement) {
353-
if (tile.improvementInProgress != null && unit.canBuildImprovement(tile.getTileImprovementInProgress()!!, tile)) return true
354-
val chosenImprovement = chooseImprovement(unit, tile)
355-
if (chosenImprovement != null && tile.improvementFunctions.canBuildImprovement(chosenImprovement, civInfo) && unit.canBuildImprovement(chosenImprovement, tile)) return true
356-
} else if (!tile.containsGreatImprovement() && tile.hasViewableResource(civInfo)
361+
val anyImprovementIsOk = tile.improvement == null || junkImprovement
362+
363+
if (anyImprovementIsOk
364+
&& tile.improvementInProgress != null
365+
&& unit.canBuildImprovement(tile.getTileImprovementInProgress()!!, tile))
366+
return tile.getTileImprovementInProgress()!!
367+
368+
val isResourceTileWithoutResourceProvider = !tile.containsGreatImprovement()
369+
&& tile.hasViewableResource(civInfo)
357370
&& !tile.tileResource.isImprovedBy(tile.improvement!!)
358-
&& (chooseImprovement(unit, tile) // if the chosen improvement is not null and buildable
359-
.let { it != null && tile.improvementFunctions.canBuildImprovement(it, civInfo) && unit.canBuildImprovement(it, tile)}))
360-
return true
361371

362-
return false // couldn't find anything to construct here
372+
if (anyImprovementIsOk || isResourceTileWithoutResourceProvider) {
373+
val chosenImprovement = chooseImprovement(unit, tile)
374+
if (chosenImprovement != null
375+
&& tile.improvementFunctions.canBuildImprovement(chosenImprovement, civInfo)
376+
&& unit.canBuildImprovement(chosenImprovement, tile)
377+
)
378+
return chosenImprovement
379+
}
380+
381+
return null // couldn't find anything to construct here
363382
}
364383

384+
365385
/**
366386
* Calculate a priority for improving a tile
367387
*/
@@ -384,6 +404,8 @@ class WorkerAutomation(
384404
* Determine the improvement appropriate to a given tile and worker
385405
*/
386406
private fun chooseImprovement(unit: MapUnit, tile: Tile): TileImprovement? {
407+
// You can keep working on half-built improvements, even if they're unique to another civ
408+
if (tile.improvementInProgress != null) return ruleSet.tileImprovements[tile.improvementInProgress!!]
387409

388410
val potentialTileImprovements = ruleSet.tileImprovements.filter {
389411
unit.canBuildImprovement(it.value, tile)
@@ -421,7 +443,6 @@ class WorkerAutomation(
421443

422444
// After gathering all the data, we conduct the hierarchy in one place
423445
val improvementString = when {
424-
tile.improvementInProgress != null -> tile.improvementInProgress!!
425446
improvementStringForResource != null -> if (improvementStringForResource==tile.improvement) null else improvementStringForResource
426447
// if this is a resource that HAS an improvement, but this unit can't build it, don't waste your time
427448
tile.resource != null && tile.tileResource.getImprovements().any() -> return null

0 commit comments

Comments
 (0)