Trade routes now travel between harbors over water, and are calculated once per civilization instead of per city

This commit is contained in:
Yair Morgenstern
2018-11-01 19:27:57 +02:00
parent 60b86decfb
commit 5a6e5043b3
9 changed files with 79 additions and 26 deletions

View File

@ -280,7 +280,8 @@
name:"Harbor",
maintenance:2,
hurryCostModifier:25,
uniques:["+1 production from all sea resources worked by the city","Connects trade routes over water"] // todo - trade routes over water!
uniques:["+1 production from all sea resources worked by the city",
"Connects trade routes over water","Can only be built in coastal cities"]
requiredTech:"Compass"
},
{

View File

@ -299,7 +299,7 @@
]
]
Worker:[
WorkerTrained:[
[
"You have trained a worker!",
"Workers are vital to your cities' growth, since only they can onstruct improvements on tiles",

View File

@ -21,8 +21,8 @@ android {
applicationId "com.unciv.game"
minSdkVersion 14
targetSdkVersion 26
versionCode 152
versionName "2.9.6"
versionCode 153
versionName "2.9.7"
}
buildTypes {
release {

View File

@ -17,7 +17,7 @@ class UnCivGame : Game() {
* This exists so that when debugging we can see the entire map.
* Remember to turn this to false before commit and upload!
*/
val viewEntireMapForDebug = true
val viewEntireMapForDebug = false
lateinit var worldScreen: WorldScreen

View File

@ -15,6 +15,7 @@ import kotlin.math.min
class CityInfo {
@Transient lateinit var civInfo: CivilizationInfo
@Transient var isConnectedToCapital = false
var location: Vector2 = Vector2.Zero
var name: String = ""
var health = 200
@ -78,6 +79,7 @@ class CityInfo {
toReturn.tiles.addAll(tiles)
toReturn.workedTiles.addAll(workedTiles)
toReturn.isBeingRazed=isBeingRazed
toReturn.isConnectedToCapital = isConnectedToCapital
return toReturn
}

View File

@ -224,32 +224,14 @@ class CityStats {
fun isConnectedToCapital(roadType: RoadStatus): Boolean {
if (cityInfo.civInfo.cities.count() < 2) return false// first city!
if(roadType==RoadStatus.Road) return cityInfo.isConnectedToCapital // this transient is not applicable to connection via railroad.
val capitalTile = cityInfo.civInfo.getCapital().getCenterTile()
val BFS =
if(roadType==RoadStatus.Road) BFS(capitalTile){it.roadStatus!=RoadStatus.None}
else BFS(capitalTile){it.roadStatus == roadType}
val BFS = BFS(capitalTile){it.roadStatus == roadType}
val cityTile = cityInfo.getCenterTile()
BFS.stepUntilDestination(cityTile)
return BFS.tilesReached.containsKey(cityTile)
// val tilesReached = HashSet<TileInfo>()
// var tilesToCheck: List<TileInfo> = listOf(cityInfo.getCenterTile())
// while (tilesToCheck.isNotEmpty()) {
// val newTiles = tilesToCheck
// .flatMap { it.neighbors }.distinct()
// .filter {
// !tilesReached.contains(it)
// && !tilesToCheck.contains(it)
// && (roadType !== RoadStatus.Road || it.roadStatus !== RoadStatus.None)
// && (roadType !== RoadStatus.Railroad || it.roadStatus === roadType)
// }
//
// if (newTiles.contains(capitalTile)) return true
// tilesReached.addAll(tilesToCheck)
// tilesToCheck = newTiles
// }
// return false
}
//endregion

View File

@ -4,6 +4,7 @@ import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.math.Vector2
import com.unciv.logic.GameInfo
import com.unciv.logic.city.CityInfo
import com.unciv.logic.map.BFS
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.RoadStatus
import com.unciv.logic.map.TileInfo
@ -15,6 +16,8 @@ import com.unciv.models.gamebasics.tile.TileResource
import com.unciv.models.stats.Stats
import com.unciv.ui.utils.getRandom
import com.unciv.ui.utils.tr
import java.util.*
import kotlin.collections.HashMap
import kotlin.math.max
import kotlin.math.pow
import kotlin.math.roundToInt
@ -255,6 +258,7 @@ class CivilizationInfo {
cityInfo.civInfo = this // must be before the city's setTransients because it depends on the tilemap, that comes from the civInfo
cityInfo.setTransients()
}
setCitiesConnectedToCapitalTransients()
}
fun endTurn() {
@ -296,6 +300,7 @@ class CivilizationInfo {
fun startTurn(){
getViewableTiles() // adds explored tiles so that the units will be able to perform automated actions better
setCitiesConnectedToCapitalTransients()
for (city in cities)
city.cityStats.update()
happiness = getHappinessForNextTurn().values.sum().roundToInt()
@ -328,5 +333,62 @@ class CivilizationInfo {
newCity.cityConstructions.chooseNextConstruction()
}
fun setCitiesConnectedToCapitalTransients(){
if(cities.isEmpty()) return // eg barbarians
// We map which cities we've reached, to the mediums they've been reached by -
// this is so we know that if we've seen which cities can be connected by port A, and one
// of those is city B, then we don't need to check the cities that B can connect to by port,
// since we'll get the same cities we got from A, since they're connected to the same sea.
val citiesReachedToMediums = HashMap<CityInfo,ArrayList<String>>()
var citiesToCheck = mutableListOf(getCapital())
citiesReachedToMediums[getCapital()] = arrayListOf("Start")
while(citiesToCheck.isNotEmpty() && citiesReachedToMediums.size<cities.size){
val newCitiesToCheck = mutableListOf<CityInfo>()
for(cityToConnectFrom in citiesToCheck){
val reachedMediums = citiesReachedToMediums[cityToConnectFrom]!!
// This is copypasta and can be cleaned up
if(!reachedMediums.contains("Road")){
val roadBfs = BFS(cityToConnectFrom.getCenterTile()){it.roadStatus!=RoadStatus.None}
roadBfs.stepToEnd()
val reachedCities = cities.filter { roadBfs.tilesReached.containsKey(it.getCenterTile())}
for(reachedCity in reachedCities){
if(!citiesReachedToMediums.containsKey(reachedCity)){
newCitiesToCheck.add(reachedCity)
citiesReachedToMediums[reachedCity] = arrayListOf()
}
val cityReachedByMediums = citiesReachedToMediums[reachedCity]!!
if(!cityReachedByMediums.contains("Road"))
cityReachedByMediums.add("Road")
}
citiesReachedToMediums[cityToConnectFrom]!!.add("Road")
}
if(!reachedMediums.contains("Harbor")
&& cityToConnectFrom.cityConstructions.containsBuildingOrEquivalent("Harbor")){
val seaBfs = BFS(cityToConnectFrom.getCenterTile()){it.isWater() || it.isCityCenter()}
seaBfs.stepToEnd()
val reachedCities = cities.filter { seaBfs.tilesReached.containsKey(it.getCenterTile())}
for(reachedCity in reachedCities){
if(!citiesReachedToMediums.containsKey(reachedCity)){
newCitiesToCheck.add(reachedCity)
citiesReachedToMediums[reachedCity] = arrayListOf()
}
val cityReachedByMediums = citiesReachedToMediums[reachedCity]!!
if(!cityReachedByMediums.contains("Harbor"))
cityReachedByMediums.add("Harbor")
}
citiesReachedToMediums[cityToConnectFrom]!!.add("Harbor")
}
}
citiesToCheck = newCitiesToCheck
}
for(city in cities){
city.isConnectedToCapital = citiesReachedToMediums.containsKey(city)
}
}
//endregion
}

View File

@ -12,6 +12,11 @@ class BFS(val startingPoint: TileInfo, val predicate : (TileInfo) -> Boolean){
tilesReached.put(startingPoint,startingPoint)
}
fun stepToEnd(){
while(tilesToCheck.isNotEmpty())
nextStep()
}
fun stepUntilDestination(destination: TileInfo){
while(!tilesReached.containsKey(destination) && tilesToCheck.isNotEmpty())
nextStep()

View File

@ -94,6 +94,7 @@ class WorldScreen : CameraStageBaseScreen() {
val cloneCivilization = gameClone.getPlayerCivilization()
kotlin.concurrent.thread {
civInfo.happiness = gameClone.getPlayerCivilization().getHappinessForNextTurn().values.sum().toInt()
gameInfo.civilizations.forEach { it.setCitiesConnectedToCapitalTransients() }
}
if(bottomBar.unitTable.selectedUnit!=null){