diff --git a/core/src/com/unciv/logic/automation/unit/WorkerAutomation.kt b/core/src/com/unciv/logic/automation/unit/WorkerAutomation.kt index 078c0305f0..0d5e085981 100644 --- a/core/src/com/unciv/logic/automation/unit/WorkerAutomation.kt +++ b/core/src/com/unciv/logic/automation/unit/WorkerAutomation.kt @@ -221,13 +221,15 @@ class WorkerAutomation( if (candidateCities.none()) return false // do nothing. val isCandidateTilePredicate: (Tile) -> Boolean = { it.isLand && unit.movement.canPassThrough(it) } + val getTilePriority: (Tile) -> Int = { it.roadStatus.ordinal } val currentTile = unit.getTile() val cityTilesToSeek = ArrayList(tilesOfConnectedCities.sortedBy { it.aerialDistanceTo(currentTile) }) for (toConnectCity in candidateCities) { val toConnectTile = toConnectCity.getCenterTile() + val bfs: BFS = bfsCache[toConnectTile.position] ?: - BFS(toConnectTile, isCandidateTilePredicate).apply { + BFS(toConnectTile, getTilePriority, isCandidateTilePredicate).apply { maxSize = HexMath.getNumberOfTilesInHexagon( WorkerAutomationConst.maxBfsReachPadding + tilesOfConnectedCities.minOf { it.aerialDistanceTo(toConnectTile) } @@ -238,6 +240,7 @@ class WorkerAutomation( while (true) { for (cityTile in cityTilesToSeek.toList()) { // copy since we change while running if (!bfs.hasReachedTile(cityTile)) continue + // we have a winner! val pathToCity = bfs.getPathTo(cityTile) val roadableTiles = pathToCity.filter { it.getUnpillagedRoad() < bestRoadAvailable } diff --git a/core/src/com/unciv/logic/map/BFS.kt b/core/src/com/unciv/logic/map/BFS.kt index debcb63b66..8e7f6c1f41 100644 --- a/core/src/com/unciv/logic/map/BFS.kt +++ b/core/src/com/unciv/logic/map/BFS.kt @@ -1,14 +1,15 @@ package com.unciv.logic.map import com.unciv.logic.map.tile.Tile -import kotlin.collections.ArrayDeque /** * Defines intermediate steps of a breadth-first search, for use in either get shortest path or get connected tiles. */ class BFS( val startingPoint: Tile, - private val predicate : (Tile) -> Boolean + /** The *higher* the number, the *greater* the priority */ + private val priorityFunction: ((Tile) -> Int)? = null, + private val predicate : (Tile) -> Boolean, ) { /** Maximum number of tiles to search */ var maxSize = Int.MAX_VALUE @@ -50,7 +51,11 @@ class BFS( fun nextStep() { if (tilesReached.size >= maxSize) { tilesToCheck.clear(); return } val current = tilesToCheck.removeFirstOrNull() ?: return - for (neighbor in current.neighbors) { + + val sortedNeighbors = if (priorityFunction==null) current.neighbors + else current.neighbors.sortedByDescending(priorityFunction) + + for (neighbor in sortedNeighbors) { if (neighbor !in tilesReached && predicate(neighbor)) { tilesReached[neighbor] = current tilesToCheck.add(neighbor)