Greatly improved performance of worker's automated city connecting

This commit is contained in:
Yair Morgenstern 2020-07-24 00:08:05 +03:00
parent bcfcadf5bc
commit 2e024c67e0

View File

@ -67,40 +67,42 @@ class WorkerAutomation(val unit: MapUnit) {
val targetRoad = unit.civInfo.tech.getBestRoadAvailable() val targetRoad = unit.civInfo.tech.getBestRoadAvailable()
val citiesThatNeedConnecting = unit.civInfo.cities val citiesThatNeedConnecting = unit.civInfo.cities.asSequence()
.filter { it.population.population>3 && !it.isCapital() && !it.isBeingRazed //City being razed should not be connected. .filter { it.population.population>3 && !it.isCapital() && !it.isBeingRazed //City being razed should not be connected.
&& !it.cityStats.isConnectedToCapital(targetRoad) } && !it.cityStats.isConnectedToCapital(targetRoad)
if(citiesThatNeedConnecting.isEmpty()) return false // do nothing. // Cities that are too far away make the caReach() calculations devastatingly long
&& it.getCenterTile().aerialDistanceTo(unit.getTile()) < 20 }
if(citiesThatNeedConnecting.none()) return false // do nothing.
val citiesThatNeedConnectingBfs = citiesThatNeedConnecting val citiesThatNeedConnectingBfs = citiesThatNeedConnecting
.sortedBy { it.getCenterTile().aerialDistanceTo(unit.getTile()) }
.map { city -> BFS(city.getCenterTile()){it.isLand && unit.movement.canPassThrough(it)} } .map { city -> BFS(city.getCenterTile()){it.isLand && unit.movement.canPassThrough(it)} }
.toMutableList()
val connectedCities = unit.civInfo.cities.filter { it.isCapital() || it.cityStats.isConnectedToCapital(targetRoad) } val connectedCities = unit.civInfo.cities.filter { it.isCapital() || it.cityStats.isConnectedToCapital(targetRoad) }
.map { it.getCenterTile() } .map { it.getCenterTile() }
while(citiesThatNeedConnectingBfs.any()){ // Since further away cities take longer to get to and - most importantly - the canReach() to them is very long,
for(bfs in citiesThatNeedConnectingBfs.toList()){ // we order cities by their closeness to the worker first, and then check for each one whether there's a viable path
// it can take to an existing connected city.
for(bfs in citiesThatNeedConnectingBfs) {
while (bfs.tilesToCheck.isNotEmpty()) {
bfs.nextStep() bfs.nextStep()
if(bfs.tilesToCheck.isEmpty()){ // can't get to any connected city from here for (city in connectedCities)
citiesThatNeedConnectingBfs.remove(bfs) if (bfs.tilesToCheck.contains(city)) { // we have a winner!
continue val pathToCity = bfs.getPathTo(city).asSequence()
}
for(city in connectedCities)
if(bfs.tilesToCheck.contains(city)) { // we have a winner!
val pathToCity = bfs.getPathTo(city)
val roadableTiles = pathToCity.filter { it.roadStatus < targetRoad } val roadableTiles = pathToCity.filter { it.roadStatus < targetRoad }
val tileToConstructRoadOn :TileInfo val tileToConstructRoadOn: TileInfo
if(unit.currentTile in roadableTiles) tileToConstructRoadOn = unit.currentTile if (unit.currentTile in roadableTiles) tileToConstructRoadOn = unit.currentTile
else{ else {
val reachableTiles = roadableTiles val reachableTile = roadableTiles
.filter { unit.movement.canMoveTo(it)&& unit.movement.canReach(it)} .sortedBy { it.aerialDistanceTo(unit.getTile()) }
if(reachableTiles.isEmpty()) continue .firstOrNull { unit.movement.canMoveTo(it) && unit.movement.canReach(it) }
tileToConstructRoadOn = reachableTiles.minBy { unit.movement.getShortestPath(it).size }!! if (reachableTile == null) continue
tileToConstructRoadOn = reachableTile
unit.movement.headTowards(tileToConstructRoadOn) unit.movement.headTowards(tileToConstructRoadOn)
} }
if(unit.currentMovement>0 && unit.currentTile==tileToConstructRoadOn if (unit.currentMovement > 0 && unit.currentTile == tileToConstructRoadOn
&& unit.currentTile.improvementInProgress!=targetRoad.name) { && unit.currentTile.improvementInProgress != targetRoad.name) {
val improvement = targetRoad.improvement(unit.civInfo.gameInfo.ruleSet)!! val improvement = targetRoad.improvement(unit.civInfo.gameInfo.ruleSet)!!
tileToConstructRoadOn.startWorkingOnImprovement(improvement, unit.civInfo) tileToConstructRoadOn.startWorkingOnImprovement(improvement, unit.civInfo)
} }
@ -108,6 +110,7 @@ class WorkerAutomation(val unit: MapUnit) {
} }
} }
} }
return false return false
} }