diff --git a/android/assets/jsons/translations/template.properties b/android/assets/jsons/translations/template.properties index 7d211e40cd..9ab59d8103 100644 --- a/android/assets/jsons/translations/template.properties +++ b/android/assets/jsons/translations/template.properties @@ -357,6 +357,7 @@ Inner Sea = Number of City-States = One City Challenge = No Barbarians = +Disable starting bias = Raging Barbarians = No Ancient Ruins = No Natural Wonders = diff --git a/core/src/com/unciv/logic/GameStarter.kt b/core/src/com/unciv/logic/GameStarter.kt index 6c7a441797..cae285aba0 100644 --- a/core/src/com/unciv/logic/GameStarter.kt +++ b/core/src/com/unciv/logic/GameStarter.kt @@ -22,8 +22,10 @@ import kotlin.collections.HashSet object GameStarter { // temporary instrumentation while tuning/debugging private const val consoleTimings = false + private lateinit var gameSetupInfo: GameSetupInfo fun startNewGame(gameSetupInfo: GameSetupInfo): GameInfo { + this.gameSetupInfo = gameSetupInfo if (consoleTimings) debug("\nGameStarter run with parameters %s, map %s", gameSetupInfo.gameParameters, gameSetupInfo.mapParameters) @@ -57,7 +59,7 @@ object GameStarter { } else runAndMeasure("generateMap") { // The mapgen needs to know what civs are in the game to generate regions, starts and resources addCivilizations(gameSetupInfo.gameParameters, gameInfo, ruleset, existingMap = false) - tileMap = mapGen.generateMap(gameSetupInfo.mapParameters, gameInfo.civilizations) + tileMap = mapGen.generateMap(gameSetupInfo.mapParameters, gameSetupInfo.gameParameters, gameInfo.civilizations) tileMap.mapParameters = gameSetupInfo.mapParameters // Now forget them for a moment! MapGen can silently fail to place some city states, so then we'll use the old fallback method to place those. gameInfo.civilizations.clear() @@ -415,9 +417,9 @@ object GameStarter { .sortedBy { civ -> when { civ.civName in tileMap.startingLocationsByNation -> 1 // harshest requirements - civ.nation.startBias.any { it in tileMap.naturalWonders } -> 2 - civ.nation.startBias.contains(Constants.tundra) -> 3 // Tundra starts are hard to find, so let's do them first - civ.nation.startBias.isNotEmpty() -> 4 // less harsh + civ.nation.startBias.any { it in tileMap.naturalWonders } && !gameSetupInfo.gameParameters.noStartBias -> 2 + civ.nation.startBias.contains(Constants.tundra) && !gameSetupInfo.gameParameters.noStartBias -> 3 // Tundra starts are hard to find, so let's do them first + civ.nation.startBias.isNotEmpty() && !gameSetupInfo.gameParameters.noStartBias -> 4 // less harsh else -> 5 // no requirements } } @@ -457,6 +459,9 @@ object GameStarter { freeTiles: MutableList, startScores: HashMap ): TileInfo { + if (gameSetupInfo.gameParameters.noStartBias) { + return freeTiles.random() + } if (civ.nation.startBias.any { it in tileMap.naturalWonders }) { // startPref wants Natural wonder neighbor: Rare and very likely to be outside getDistanceFromEdge val wonderNeighbor = tileMap.values.asSequence() @@ -485,6 +490,6 @@ object GameStarter { } } } - return preferredTiles.lastOrNull() ?: freeTiles.last() + return preferredTiles.randomOrNull() ?: freeTiles.random() } } diff --git a/core/src/com/unciv/logic/map/mapgenerator/MapGenerator.kt b/core/src/com/unciv/logic/map/mapgenerator/MapGenerator.kt index 721f82df23..64a8757c86 100644 --- a/core/src/com/unciv/logic/map/mapgenerator/MapGenerator.kt +++ b/core/src/com/unciv/logic/map/mapgenerator/MapGenerator.kt @@ -11,6 +11,8 @@ import com.unciv.logic.map.Perlin import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileMap import com.unciv.models.Counter +import com.unciv.models.metadata.GameParameters +import com.unciv.models.metadata.GameSetupInfo import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.tile.ResourceType import com.unciv.models.ruleset.tile.Terrain @@ -71,7 +73,7 @@ class MapGenerator(val ruleset: Ruleset) { getMatchingUniques(UniqueType.TileGenerationConditions) .map { unique -> TerrainOccursRange(this, unique) } - fun generateMap(mapParameters: MapParameters, civilizations: List = emptyList()): TileMap { + fun generateMap(mapParameters: MapParameters, gameParameters: GameParameters = GameParameters(), civilizations: List = emptyList()): TileMap { val mapSize = mapParameters.mapSize val mapType = mapParameters.type @@ -134,7 +136,7 @@ class MapGenerator(val ruleset: Ruleset) { regions.generateRegions(map, civilizations.count { ruleset.nations[it.civName]!!.isMajorCiv() }) } runAndMeasure("assignRegions") { - regions.assignRegions(map, civilizations.filter { ruleset.nations[it.civName]!!.isMajorCiv() }) + regions.assignRegions(map, civilizations.filter { ruleset.nations[it.civName]!!.isMajorCiv() }, gameParameters) } runAndMeasure("placeResourcesAndMinorCivs") { regions.placeResourcesAndMinorCivs(map, civilizations.filter { ruleset.nations[it.civName]!!.isCityState() }) diff --git a/core/src/com/unciv/logic/map/mapgenerator/MapRegions.kt b/core/src/com/unciv/logic/map/mapgenerator/MapRegions.kt index 61a63c7f22..7b0c853356 100644 --- a/core/src/com/unciv/logic/map/mapgenerator/MapRegions.kt +++ b/core/src/com/unciv/logic/map/mapgenerator/MapRegions.kt @@ -9,6 +9,7 @@ import com.unciv.logic.map.MapResources import com.unciv.logic.map.MapShape import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileMap +import com.unciv.models.metadata.GameParameters import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.tile.ResourceType import com.unciv.models.ruleset.tile.Terrain @@ -211,7 +212,7 @@ class MapRegions (val ruleset: Ruleset){ return Pair(splitOffRegion, regionToSplit) } - fun assignRegions(tileMap: TileMap, civilizations: List) { + fun assignRegions(tileMap: TileMap, civilizations: List, gameParameters: GameParameters) { if (civilizations.isEmpty()) return // first assign region types @@ -269,6 +270,12 @@ class MapRegions (val ruleset: Ruleset){ // First assign coast bias civs for (civ in coastBiasCivs) { + // If noStartBias is enabled consider these to be randomCivs + if (gameParameters.noStartBias) { + randomCivs.addAll(coastBiasCivs) + break + } + // Try to find a coastal start, preferably a really coastal one var startRegion = unpickedRegions.filter { tileMap[it.startPosition!!].isCoastalTile() } .maxByOrNull { it.terrainCounts["Coastal"] ?: 0 } @@ -307,6 +314,12 @@ class MapRegions (val ruleset: Ruleset){ // Next do positive bias civs for (civ in positiveBiasCivs) { + // If noStartBias is enabled consider these to be randomCivs + if (gameParameters.noStartBias) { + randomCivs.addAll(positiveBiasCivs) + break + } + // Try to find a start that matches any of the desired regions, ideally with lots of desired terrain val preferred = ruleset.nations[civ.civName]!!.startBias val startRegion = unpickedRegions.filter { it.type in preferred } @@ -331,6 +344,12 @@ class MapRegions (val ruleset: Ruleset){ // Next do negative bias ones (ie "Avoid []") for (civ in negativeBiasCivs) { + // If noStartBias is enabled consider these to be randomCivs + if (gameParameters.noStartBias) { + randomCivs.addAll(negativeBiasCivs) + break + } + val avoided = ruleset.nations[civ.civName]!!.startBias.map { it.getPlaceholderParameters()[0] } // Try to find a region not of the avoided types, secondary sort by least number of undesired terrains val startRegion = unpickedRegions.filterNot { it.type in avoided } diff --git a/core/src/com/unciv/models/metadata/GameParameters.kt b/core/src/com/unciv/models/metadata/GameParameters.kt index 54f2847803..dba752331a 100644 --- a/core/src/com/unciv/models/metadata/GameParameters.kt +++ b/core/src/com/unciv/models/metadata/GameParameters.kt @@ -26,6 +26,7 @@ class GameParameters { // Default values are the default new game var godMode = false var nuclearWeaponsEnabled = true var religionEnabled = false + var noStartBias = false var victoryTypes: ArrayList = arrayListOf() var startingEra = "Ancient era" diff --git a/core/src/com/unciv/ui/newgamescreen/GameOptionsTable.kt b/core/src/com/unciv/ui/newgamescreen/GameOptionsTable.kt index fdfefe01a4..b770644853 100644 --- a/core/src/com/unciv/ui/newgamescreen/GameOptionsTable.kt +++ b/core/src/com/unciv/ui/newgamescreen/GameOptionsTable.kt @@ -72,6 +72,7 @@ class GameOptionsTable( checkboxTable.addNuclearWeaponsCheckbox() checkboxTable.addIsOnlineMultiplayerCheckbox() checkboxTable.addReligionCheckbox(cityStateSlider) + checkboxTable.addNoStartBiasCheckbox() add(checkboxTable).center().row() if (!isPortrait) @@ -124,6 +125,10 @@ class GameOptionsTable( cityStateSlider?.run { setRange(0f, numberOfCityStates().toFloat()) } } + private fun Table.addNoStartBiasCheckbox() = + addCheckbox("Disable starting bias", gameParameters.noStartBias) + { gameParameters.noStartBias = it } + private fun Table.addCityStatesSlider(): UncivSlider? { val maxCityStates = numberOfCityStates() if (maxCityStates == 0) return null