mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-19 20:28:56 +07:00
Cleaned up UnitAutomation.TryGarrison
Added explainations of various map generation techniques
This commit is contained in:
@ -12,7 +12,6 @@ import com.unciv.logic.civilization.GreatPersonManager
|
|||||||
import com.unciv.logic.map.MapUnit
|
import com.unciv.logic.map.MapUnit
|
||||||
import com.unciv.logic.map.TileInfo
|
import com.unciv.logic.map.TileInfo
|
||||||
import com.unciv.models.gamebasics.GameBasics
|
import com.unciv.models.gamebasics.GameBasics
|
||||||
import com.unciv.models.gamebasics.tile.TerrainType
|
|
||||||
import com.unciv.models.stats.Stats
|
import com.unciv.models.stats.Stats
|
||||||
import com.unciv.ui.utils.getRandom
|
import com.unciv.ui.utils.getRandom
|
||||||
import com.unciv.ui.worldscreen.unit.UnitAction
|
import com.unciv.ui.worldscreen.unit.UnitAction
|
||||||
@ -305,27 +304,25 @@ class UnitAutomation{
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val citiesToTry:Sequence<CityInfo>
|
||||||
|
|
||||||
if (!unit.civInfo.isAtWar()) {
|
if (!unit.civInfo.isAtWar()) {
|
||||||
if (unit.getTile().isCityCenter()) return true // It's always good to have a unit in the city center, so if you haven't found anyone around to attack, forget it.
|
if (unit.getTile().isCityCenter()) return true // It's always good to have a unit in the city center, so if you haven't found anyone around to attack, forget it.
|
||||||
|
citiesToTry = citiesWithoutGarrison.asSequence()
|
||||||
val closestReachableCityWithNoGarrison = citiesWithoutGarrison.asSequence()
|
|
||||||
.sortedBy{ it.getCenterTile().arialDistanceTo(unit.currentTile) }
|
|
||||||
.firstOrNull { unit.movementAlgs().canReach(it.getCenterTile()) }
|
|
||||||
if(closestReachableCityWithNoGarrison==null) return false // no
|
|
||||||
unit.movementAlgs().headTowards(closestReachableCityWithNoGarrison.getCenterTile())
|
|
||||||
return true
|
|
||||||
} else {
|
} else {
|
||||||
if (unit.getTile().isCityCenter() &&
|
if (unit.getTile().isCityCenter() &&
|
||||||
isCityThatNeedsDefendingInWartime(unit.getTile().getCity()!!)) return true
|
isCityThatNeedsDefendingInWartime(unit.getTile().getCity()!!)) return true
|
||||||
|
|
||||||
val closestReachableCityNeedsDefending = citiesWithoutGarrison.asSequence()
|
citiesToTry = citiesWithoutGarrison.asSequence()
|
||||||
.filter { isCityThatNeedsDefendingInWartime(it) }
|
.filter { isCityThatNeedsDefendingInWartime(it) }
|
||||||
.sortedBy{ it.getCenterTile().arialDistanceTo(unit.currentTile) }
|
|
||||||
.firstOrNull { unit.movementAlgs().canReach(it.getCenterTile()) }
|
|
||||||
if(closestReachableCityNeedsDefending==null) return false
|
|
||||||
unit.movementAlgs().headTowards(closestReachableCityNeedsDefending.getCenterTile())
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val closestReachableCityNeedsDefending =citiesToTry
|
||||||
|
.sortedBy{ it.getCenterTile().arialDistanceTo(unit.currentTile) }
|
||||||
|
.firstOrNull { unit.movementAlgs().canReach(it.getCenterTile()) }
|
||||||
|
if(closestReachableCityNeedsDefending==null) return false
|
||||||
|
unit.movementAlgs().headTowards(closestReachableCityNeedsDefending.getCenterTile())
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun tryGoToRuin(unit:MapUnit, unitDistanceToTiles: HashMap<TileInfo, Float>): Boolean {
|
fun tryGoToRuin(unit:MapUnit, unitDistanceToTiles: HashMap<TileInfo, Float>): Boolean {
|
||||||
|
@ -9,9 +9,9 @@ import com.unciv.models.gamebasics.tile.TileResource
|
|||||||
import com.unciv.ui.utils.getRandom
|
import com.unciv.ui.utils.getRandom
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
|
import kotlin.math.abs
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.math.abs
|
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
|
|
||||||
enum class MapType {
|
enum class MapType {
|
||||||
@ -80,7 +80,7 @@ class CelluarAutomataRandomMapGenerator(): SeedRandomMapGenerator() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateInitTerrain(vector: Vector2, distance: Int): TerrainType {
|
private fun generateInitTerrain(vector: Vector2, distance: Int): TerrainType {
|
||||||
var type: TerrainType
|
val type: TerrainType
|
||||||
if (mapType == MapType.Pangaea) {
|
if (mapType == MapType.Pangaea) {
|
||||||
val distanceFactor = (HexMath().getDistance(Vector2.Zero, vector) * 1.8 / distance).toFloat()
|
val distanceFactor = (HexMath().getDistance(Vector2.Zero, vector) * 1.8 / distance).toFloat()
|
||||||
type = if (Random().nextDouble() < landProb.pow(distanceFactor)) TerrainType.Land else TerrainType.Water
|
type = if (Random().nextDouble() < landProb.pow(distanceFactor)) TerrainType.Land else TerrainType.Water
|
||||||
@ -98,37 +98,38 @@ class CelluarAutomataRandomMapGenerator(): SeedRandomMapGenerator() {
|
|||||||
private fun generateTile(vector: Vector2, type: TerrainType): TileInfo {
|
private fun generateTile(vector: Vector2, type: TerrainType): TileInfo {
|
||||||
val tile=TileInfo()
|
val tile=TileInfo()
|
||||||
tile.position=vector
|
tile.position=vector
|
||||||
if (type == TerrainType.Land)
|
if (type == TerrainType.Land) tile.baseTerrain = ""
|
||||||
tile.baseTerrain = ""
|
else tile.baseTerrain = "Ocean"
|
||||||
else
|
|
||||||
tile.baseTerrain = "Ocean"
|
|
||||||
return tile
|
return tile
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setWaterTiles(map: HashMap<String, TileInfo>) {
|
override fun setWaterTiles(map: HashMap<String, TileInfo>) {
|
||||||
//define lakes
|
//define lakes
|
||||||
var waterTiles = map.values.filter { it.isWater() }.map { it.position }
|
var waterTiles = map.values.filter { it.isWater() }.map { it.position }
|
||||||
var tilesInArea = ArrayList<Vector2>()
|
val tilesInArea = ArrayList<Vector2>()
|
||||||
var tilesToCheck = ArrayList<Vector2>()
|
val tilesToCheck = ArrayList<Vector2>()
|
||||||
while (waterTiles.isNotEmpty()) {
|
while (waterTiles.isNotEmpty()) {
|
||||||
val tile = waterTiles.getRandom()
|
val initialWaterTile = waterTiles.getRandom()
|
||||||
tilesInArea.add(tile)
|
tilesInArea += initialWaterTile
|
||||||
tilesToCheck.add(tile)
|
tilesToCheck += initialWaterTile
|
||||||
waterTiles -= tile
|
waterTiles -= initialWaterTile
|
||||||
|
|
||||||
while (tilesToCheck.isNotEmpty()) {
|
while (tilesToCheck.isNotEmpty()) {
|
||||||
val tileChecking = tilesToCheck.getRandom()
|
val tileChecking = tilesToCheck.getRandom()
|
||||||
for (vector in HexMath().getVectorsAtDistance(tileChecking,1).filter { !tilesInArea.contains(it) and waterTiles.contains(it) }) {
|
for (vector in HexMath().getVectorsAtDistance(tileChecking,1)
|
||||||
tilesInArea.add(vector)
|
.filter { !tilesInArea.contains(it) and waterTiles.contains(it) }) {
|
||||||
tilesToCheck.add(vector)
|
tilesInArea += vector
|
||||||
|
tilesToCheck += vector
|
||||||
waterTiles -= vector
|
waterTiles -= vector
|
||||||
}
|
}
|
||||||
tilesToCheck.remove(tileChecking)
|
tilesToCheck -= tileChecking
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tilesInArea.size <= 10) {
|
if (tilesInArea.size <= 10) {
|
||||||
for (vector in tilesInArea) {
|
for (vector in tilesInArea) {
|
||||||
map[vector.toString()]!!.baseTerrain = "Lakes"
|
val tile = map[vector.toString()]!!
|
||||||
|
tile.baseTerrain = "Lakes"
|
||||||
|
tile.setTransients()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tilesInArea.clear()
|
tilesInArea.clear()
|
||||||
@ -174,7 +175,7 @@ class CelluarAutomataRandomMapGenerator(): SeedRandomMapGenerator() {
|
|||||||
else "Ocean"
|
else "Ocean"
|
||||||
val tile = emptyTiles.getRandom()
|
val tile = emptyTiles.getRandom()
|
||||||
|
|
||||||
//change glassland to desert or tundra based on y
|
//change grassland to desert or tundra based on y
|
||||||
if (abs(getLatitude(tile.position)) < maxLatitude * 0.1) {
|
if (abs(getLatitude(tile.position)) < maxLatitude * 0.1) {
|
||||||
if (terrain == "Grassland" || terrain == "Tundra")
|
if (terrain == "Grassland" || terrain == "Tundra")
|
||||||
terrain = "Desert"
|
terrain = "Desert"
|
||||||
@ -183,16 +184,10 @@ class CelluarAutomataRandomMapGenerator(): SeedRandomMapGenerator() {
|
|||||||
terrain = "Tundra"
|
terrain = "Tundra"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (terrain == "Tundra")
|
if (terrain == "Tundra") terrain = "Plains"
|
||||||
terrain = "Plains"
|
else if (terrain == "Desert") terrain = "Grassland"
|
||||||
else if (terrain == "Desert")
|
|
||||||
terrain = "Grassland"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (terrain == "Grassland") {
|
|
||||||
|
|
||||||
}
|
|
||||||
val area = Area(terrain)
|
val area = Area(terrain)
|
||||||
emptyTiles -= tile
|
emptyTiles -= tile
|
||||||
area.addTile(tile)
|
area.addTile(tile)
|
||||||
@ -205,6 +200,13 @@ class CelluarAutomataRandomMapGenerator(): SeedRandomMapGenerator() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This generator simply generates Perlin noise,
|
||||||
|
* "spreads" it out according to the ratio in generateTile,
|
||||||
|
* and assigns it as the height of the various tiles.
|
||||||
|
* Tiles below a certain height threshold (determined in generateTile, currently 50%)
|
||||||
|
* are considered water tiles, the rest are land tiles
|
||||||
|
*/
|
||||||
class PerlinNoiseRandomMapGenerator:SeedRandomMapGenerator(){
|
class PerlinNoiseRandomMapGenerator:SeedRandomMapGenerator(){
|
||||||
override fun generateMap(distance: Int): HashMap<String, TileInfo> {
|
override fun generateMap(distance: Int): HashMap<String, TileInfo> {
|
||||||
val map = HashMap<Vector2, TileInfo>()
|
val map = HashMap<Vector2, TileInfo>()
|
||||||
@ -243,6 +245,10 @@ class PerlinNoiseRandomMapGenerator:SeedRandomMapGenerator(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This generator uses the algorithm from the game "Alexander", outlined here:
|
||||||
|
* http://www.cartania.com/alexander/generation.html
|
||||||
|
*/
|
||||||
class AlexanderRandomMapGenerator:RandomMapGenerator(){
|
class AlexanderRandomMapGenerator:RandomMapGenerator(){
|
||||||
fun generateMap(distance: Int, landExpansionChance:Float): HashMap<String, TileInfo> {
|
fun generateMap(distance: Int, landExpansionChance:Float): HashMap<String, TileInfo> {
|
||||||
val map = HashMap<Vector2, TileInfo?>()
|
val map = HashMap<Vector2, TileInfo?>()
|
||||||
|
Reference in New Issue
Block a user