AI no longer tries to construct work boats that can't reach their intended destination

This commit is contained in:
Yair Morgenstern 2020-11-05 20:02:02 +02:00
parent d0dce25590
commit 4e0c88cc20
2 changed files with 30 additions and 18 deletions

View File

@ -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() {

View File

@ -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<TileInfo>()
/** each tile reached points to its parent tile, where we got to it from */
val tilesReached = HashMap<TileInfo, TileInfo>()
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<TileInfo>()
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