diff --git a/core/src/com/unciv/logic/automation/ConstructionAutomation.kt b/core/src/com/unciv/logic/automation/ConstructionAutomation.kt index d668e555ab..a33a7cf175 100644 --- a/core/src/com/unciv/logic/automation/ConstructionAutomation.kt +++ b/core/src/com/unciv/logic/automation/ConstructionAutomation.kt @@ -7,6 +7,7 @@ import com.unciv.logic.city.CityConstructions import com.unciv.logic.city.PerpetualConstruction import com.unciv.logic.civilization.CityAction import com.unciv.logic.civilization.PlayerType +import com.unciv.logic.map.BFS import com.unciv.models.ruleset.Building import com.unciv.models.ruleset.VictoryType import com.unciv.models.stats.Stat @@ -29,13 +30,6 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ val cities = civInfo.cities.size val allTechsAreResearched = civInfo.tech.getNumberOfTechsResearched() >= civInfo.gameInfo.ruleSet.technologies.size - val buildableWorkboatUnits = cityInfo.cityConstructions.getConstructableUnits() - .filter { it.uniques.contains("May create improvements on water resources") } - val canBuildWorkboat = buildableWorkboatUnits.any() - && !cityInfo.getTiles().any { it.civilianUnit?.hasUnique("May create improvements on water resources")==true } - val needWorkboat = canBuildWorkboat - && cityInfo.getTiles().any { it.isWater && it.hasViewableResource(civInfo) && it.improvement == null } - val isAtWar = civInfo.isAtWar() val preferredVictoryType = civInfo.victoryType() @@ -119,9 +113,25 @@ class ConstructionAutomation(val cityConstructions: CityConstructions){ } private fun addWorkBoatChoice() { - if (needWorkboat) { - addChoice(relativeCostEffectiveness, buildableWorkboatUnits.minBy { it.cost }!!.name, 0.6f) + val buildableWorkboatUnits = cityInfo.cityConstructions.getConstructableUnits() + .filter { it.uniques.contains("May create improvements on water resources") } + val canBuildWorkboat = buildableWorkboatUnits.any() + && !cityInfo.getTiles().any { it.civilianUnit?.hasUnique("May create improvements on water resources") == true } + if (!canBuildWorkboat) return + val tilesThatNeedWorkboat = cityInfo.getTiles() + .filter { it.isWater && it.hasViewableResource(civInfo) && it.improvement == null }.toList() + if (tilesThatNeedWorkboat.isEmpty()) return + + // If we can't reach the tile we need to improve within 10 turns, it's probably unreachable. + val bfs = BFS(cityInfo.getCenterTile()) { (it.isWater || it.isCityCenter()) && it.isFriendlyTerritory(civInfo) } + for (i in 1..10) { + bfs.nextStep() + if (tilesThatNeedWorkboat.any { bfs.hasReachedTile(it) }) + break } + if (tilesThatNeedWorkboat.none { bfs.hasReachedTile(it) }) return + + addChoice(relativeCostEffectiveness, buildableWorkboatUnits.minBy { it.cost }!!.name, 0.6f) } private fun addWorkerChoice() { diff --git a/core/src/com/unciv/logic/map/BFS.kt b/core/src/com/unciv/logic/map/BFS.kt index 39b8328087..e7f0132811 100644 --- a/core/src/com/unciv/logic/map/BFS.kt +++ b/core/src/com/unciv/logic/map/BFS.kt @@ -6,31 +6,33 @@ import java.util.ArrayDeque /** * Defines intermediate steps of a breadth-first search, for use in either get shortest path or get onnected tiles. */ -class BFS(val startingPoint: TileInfo, val predicate : (TileInfo) -> Boolean){ +class BFS(val startingPoint: TileInfo, val predicate : (TileInfo) -> Boolean) { var tilesToCheck = ArrayDeque() + /** each tile reached points to its parent tile, where we got to it from */ val tilesReached = HashMap() - init{ + init { tilesToCheck.add(startingPoint) tilesReached[startingPoint] = startingPoint } - fun stepToEnd(){ - while(tilesToCheck.isNotEmpty()) + fun stepToEnd() { + while (tilesToCheck.isNotEmpty()) nextStep() } + fun stepUntilDestination(destination: TileInfo): BFS { - while(!tilesReached.containsKey(destination) && tilesToCheck.isNotEmpty()) + while (!tilesReached.containsKey(destination) && tilesToCheck.isNotEmpty()) nextStep() return this } - fun nextStep(){ + fun nextStep() { val current = tilesToCheck.remove() - for(neighbor in current.neighbors){ - if(predicate(neighbor) && !tilesReached.containsKey(neighbor)){ + for (neighbor in current.neighbors) { + if (predicate(neighbor) && !tilesReached.containsKey(neighbor)) { tilesReached[neighbor] = current tilesToCheck.add(neighbor) } @@ -41,7 +43,7 @@ class BFS(val startingPoint: TileInfo, val predicate : (TileInfo) -> Boolean){ val path = ArrayList() path.add(destination) var currentNode = destination - while(currentNode != startingPoint) { + while (currentNode != startingPoint) { val parent = tilesReached[currentNode] if (parent == null) return ArrayList()// destination is not in our path currentNode = parent