diff --git a/core/src/com/unciv/GameStarter.kt b/core/src/com/unciv/GameStarter.kt index 61cc984913..7a5e97f410 100644 --- a/core/src/com/unciv/GameStarter.kt +++ b/core/src/com/unciv/GameStarter.kt @@ -3,10 +3,12 @@ package com.unciv import com.badlogic.gdx.math.Vector2 import com.unciv.logic.GameInfo import com.unciv.logic.civilization.CivilizationInfo +import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileMap import com.unciv.models.gamebasics.GameBasics import com.unciv.ui.NewGameScreen import com.unciv.ui.utils.getRandom +import java.util.* class GameStarter(){ fun startNewGame(newGameParameters: NewGameScreen.NewGameParameters): GameInfo { @@ -14,26 +16,13 @@ class GameStarter(){ gameInfo.tileMap = TileMap(newGameParameters.mapRadius, newGameParameters.mapType) gameInfo.tileMap.gameInfo = gameInfo // need to set this transient before placing units in the map + val startingLocations = getStartingLocations(newGameParameters.numberOfEnemies+1,gameInfo.tileMap) - fun vectorIsWithinNTilesOfEdge(vector: Vector2,n:Int): Boolean { - return vector.x < newGameParameters.mapRadius-n - && vector.x > n-newGameParameters.mapRadius - && vector.y < newGameParameters.mapRadius-n - && vector.y > n-newGameParameters.mapRadius - } - - val distanceAroundStartingPointNoOneElseWillStartIn = 5 - val freeTiles = gameInfo.tileMap.values - .filter { it.isLand() && vectorIsWithinNTilesOfEdge(it.position,3)} - .toMutableList() - val playerPosition = freeTiles.getRandom().position val playerCiv = CivilizationInfo(newGameParameters.nation) playerCiv.difficulty=newGameParameters.difficulty gameInfo.civilizations.add(playerCiv) // first one is player civ - freeTiles.removeAll(gameInfo.tileMap.getTilesInDistance(playerPosition, distanceAroundStartingPointNoOneElseWillStartIn )) - val barbarianCivilization = CivilizationInfo() gameInfo.civilizations.add(barbarianCivilization)// second is barbarian civ @@ -51,20 +40,46 @@ class GameStarter(){ // and only now do we add units for everyone, because otherwise both the gameInfo.setTransients() and the placeUnit will both add the unit to the civ's unit list! - for (civ in gameInfo.civilizations.toList().filter { !it.isBarbarianCivilization() }) { - if(freeTiles.isEmpty()){ - gameInfo.civilizations.remove(civ) - continue - } // we can't add any more civs. - val startingLocation = freeTiles.toList().getRandom().position + for (civ in gameInfo.civilizations.filter { !it.isBarbarianCivilization() }) { + val startingLocation = startingLocations.pop()!! - civ.placeUnitNearTile(startingLocation, "Settler") - civ.placeUnitNearTile(startingLocation, "Warrior") - civ.placeUnitNearTile(startingLocation, "Scout") - - freeTiles.removeAll(gameInfo.tileMap.getTilesInDistance(startingLocation, distanceAroundStartingPointNoOneElseWillStartIn )) + civ.placeUnitNearTile(startingLocation.position, "Settler") + civ.placeUnitNearTile(startingLocation.position, "Warrior") + civ.placeUnitNearTile(startingLocation.position, "Scout") } return gameInfo } + + fun getStartingLocations(numberOfPlayers:Int,tileMap: TileMap): Stack { + for(minimumDistanceBetweenStartingLocations in 7 downTo 1){ + val freeTiles = tileMap.values + .filter { it.isLand() && vectorIsWithinNTilesOfEdge(it.position,3,tileMap)} + .toMutableList() + + val startingLocations = ArrayList() + for(player in 0..numberOfPlayers){ + if(freeTiles.isEmpty()) break // we failed to get all the starting locations with this minimum distance + val randomLocation = freeTiles.getRandom() + startingLocations.add(randomLocation) + freeTiles.removeAll(tileMap.getTilesInDistance(randomLocation.position,minimumDistanceBetweenStartingLocations)) + } + if(startingLocations.size < numberOfPlayers) continue // let's try again with less minimum distance! + val stack = Stack() + stack.addAll(startingLocations) + return stack + } + throw Exception("Didn't manage to get starting locations even with distance of 1?") + } + + fun vectorIsWithinNTilesOfEdge(vector: Vector2,n:Int, tileMap: TileMap): Boolean { + val arrayXIndex = vector.x.toInt()-tileMap.leftX + val arrayYIndex = vector.y.toInt()-tileMap.bottomY + + return arrayXIndex < tileMap.tileMatrix.size-n + && arrayXIndex > n + && arrayYIndex < tileMap.tileMatrix[arrayXIndex].size-n + && arrayYIndex > n + } + } \ No newline at end of file diff --git a/core/src/com/unciv/ui/NewGameScreen.kt b/core/src/com/unciv/ui/NewGameScreen.kt index b47e150d58..d636fe4bbd 100644 --- a/core/src/com/unciv/ui/NewGameScreen.kt +++ b/core/src/com/unciv/ui/NewGameScreen.kt @@ -115,6 +115,7 @@ class NewGameScreen: PickerScreen(){ worldSizeToRadius["Small"] = 10 worldSizeToRadius["Medium"] = 20 worldSizeToRadius["Large"] = 30 + worldSizeToRadius["Huge"] = 40 val worldSizeSelectBox = TranslatedSelectBox(worldSizeToRadius.keys, "Medium", skin) worldSizeSelectBox.addListener(object : ChangeListener() { @@ -128,7 +129,7 @@ class NewGameScreen: PickerScreen(){ newGameOptionsTable.add("{Number of enemies}:".tr()) val enemiesSelectBox = SelectBox(skin) val enemiesArray = Array() - (1..5).forEach { enemiesArray.add(it) } + (1..GameBasics.Nations.size-1).forEach { enemiesArray.add(it) } enemiesSelectBox.items = enemiesArray enemiesSelectBox.selected = newGameParameters.numberOfEnemies