mirror of
https://github.com/yairm210/Unciv.git
synced 2025-03-16 19:23:28 +07:00
Fix NW placement
This commit is contained in:
parent
64e79ffa0d
commit
a6e61c120b
@ -139,18 +139,22 @@ class MapGenerator(val ruleset: Ruleset) {
|
||||
runAndMeasure("assignRegions") {
|
||||
regions.assignRegions(map, civilizations.filter { ruleset.nations[it.civName]!!.isMajorCiv() }, gameParameters)
|
||||
}
|
||||
// Natural wonders need to go before most resources since there is a minimum distance
|
||||
runAndMeasure("NaturalWonderGenerator") {
|
||||
NaturalWonderGenerator(ruleset, randomness).spawnNaturalWonders(map)
|
||||
}
|
||||
runAndMeasure("placeResourcesAndMinorCivs") {
|
||||
regions.placeResourcesAndMinorCivs(map, civilizations.filter { ruleset.nations[it.civName]!!.isCityState() })
|
||||
}
|
||||
} else {
|
||||
runAndMeasure("NaturalWonderGenerator") {
|
||||
NaturalWonderGenerator(ruleset, randomness).spawnNaturalWonders(map)
|
||||
}
|
||||
// Fallback spread resources function - used when generating maps in map editor
|
||||
runAndMeasure("spreadResources") {
|
||||
spreadResources(map)
|
||||
}
|
||||
}
|
||||
runAndMeasure("NaturalWonderGenerator") {
|
||||
NaturalWonderGenerator(ruleset, randomness).spawnNaturalWonders(map)
|
||||
}
|
||||
runAndMeasure("spreadAncientRuins") {
|
||||
spreadAncientRuins(map)
|
||||
}
|
||||
@ -288,7 +292,9 @@ class MapGenerator(val ruleset: Ruleset) {
|
||||
private fun spreadStrategicResources(tileMap: TileMap, mapRadius: Int) {
|
||||
val strategicResources = ruleset.tileResources.values.filter { it.resourceType == ResourceType.Strategic }
|
||||
// passable land tiles (no mountains, no wonders) without resources yet
|
||||
val candidateTiles = tileMap.values.filter { it.resource == null && !it.isImpassible() }
|
||||
// can't be next to NW
|
||||
val candidateTiles = tileMap.values.filter { it.resource == null && !it.isImpassible()
|
||||
&& it.neighbors.none { neighbor -> neighbor.isNaturalWonder() }}
|
||||
val totalNumberOfResources = candidateTiles.count { it.isLand } * tileMap.mapParameters.resourceRichness
|
||||
val resourcesPerType = (totalNumberOfResources/strategicResources.size).toInt()
|
||||
for (resource in strategicResources) {
|
||||
@ -314,7 +320,8 @@ class MapGenerator(val ruleset: Ruleset) {
|
||||
|
||||
val suitableTiles = tileMap.values
|
||||
.filterNot { it.baseTerrain == Constants.snow && it.isHill() }
|
||||
.filter { it.resource == null && resourcesOfType.any { r -> r.terrainsCanBeFoundOn.contains(it.getLastTerrain().name) } }
|
||||
.filter { it.resource == null && it.neighbors.none { neighbor -> neighbor.isNaturalWonder() }
|
||||
&& resourcesOfType.any { r -> r.terrainsCanBeFoundOn.contains(it.getLastTerrain().name) } }
|
||||
val numberOfResources = tileMap.values.count { it.isLand && !it.isImpassible() } *
|
||||
tileMap.mapParameters.resourceRichness
|
||||
val locations = randomness.chooseSpreadOutLocations(numberOfResources.toInt(), suitableTiles, mapRadius)
|
||||
|
@ -829,12 +829,23 @@ class MapRegions (val ruleset: Ruleset){
|
||||
}
|
||||
|
||||
fun placeResourcesAndMinorCivs(tileMap: TileMap, minorCivs: List<CivilizationInfo>) {
|
||||
placeNaturalWonderImpacts(tileMap)
|
||||
assignLuxuries()
|
||||
placeMinorCivs(tileMap, minorCivs)
|
||||
placeLuxuries(tileMap)
|
||||
placeStrategicAndBonuses(tileMap)
|
||||
}
|
||||
|
||||
/** Places impacts from NWs that have been generated just prior to this step. */
|
||||
private fun placeNaturalWonderImpacts(tileMap: TileMap) {
|
||||
for (tile in tileMap.values.filter { it.isNaturalWonder() }) {
|
||||
placeImpact(ImpactType.Bonus, tile, 1)
|
||||
placeImpact(ImpactType.Strategic, tile, 1)
|
||||
placeImpact(ImpactType.Luxury, tile, 1)
|
||||
placeImpact(ImpactType.MinorCiv, tile, 1)
|
||||
}
|
||||
}
|
||||
|
||||
/** Assigns a luxury to each region. No luxury can be assigned to too many regions.
|
||||
* Some luxuries are earmarked for city states. The rest are randomly distributed or
|
||||
* don't occur att all in the map */
|
||||
|
@ -18,9 +18,14 @@ class NaturalWonderGenerator(val ruleset: Ruleset, val randomness: MapGeneration
|
||||
.filter { it.type == TerrainType.TerrainFeature }
|
||||
.map { it.name }.toSet()
|
||||
|
||||
private val blockedTiles = HashSet<TileInfo>()
|
||||
|
||||
/*
|
||||
https://gaming.stackexchange.com/questions/95095/do-natural-wonders-spawn-more-closely-to-city-states/96479
|
||||
https://www.reddit.com/r/civ/comments/1jae5j/information_on_the_occurrence_of_natural_wonders/
|
||||
Above all, look in assignstartingplots.lua! The wonders are always attempted to be placed in order of
|
||||
which has the least amount of candidate tiles. There is a minimum distance between wonders equal
|
||||
to the map height / 5.
|
||||
*/
|
||||
fun spawnNaturalWonders(tileMap: TileMap) {
|
||||
if (tileMap.mapParameters.noNaturalWonders)
|
||||
@ -31,31 +36,58 @@ class NaturalWonderGenerator(val ruleset: Ruleset, val randomness: MapGeneration
|
||||
mapRadius * naturalWonderCountMultiplier + naturalWonderCountAddedConstant
|
||||
}.roundToInt()
|
||||
|
||||
val spawned = mutableListOf<Terrain>()
|
||||
val chosenWonders = mutableListOf<Terrain>()
|
||||
val wonderCandidateTiles = mutableMapOf<Terrain, Collection<TileInfo>>()
|
||||
val allNaturalWonders = ruleset.terrains.values
|
||||
.filter { it.type == TerrainType.NaturalWonder }.toMutableList()
|
||||
val spawned = mutableListOf<Terrain>()
|
||||
|
||||
while (allNaturalWonders.isNotEmpty() && spawned.size < numberToSpawn) {
|
||||
while (allNaturalWonders.isNotEmpty() && chosenWonders.size < numberToSpawn) {
|
||||
val totalWeight = allNaturalWonders.sumOf { it.weight }.toFloat()
|
||||
val random = randomness.RNG.nextDouble()
|
||||
var sum = 0f
|
||||
for (wonder in allNaturalWonders) {
|
||||
sum += wonder.weight / totalWeight
|
||||
if (random <= sum) {
|
||||
if (spawnSpecificWonder(tileMap, wonder))
|
||||
spawned.add(wonder)
|
||||
chosenWonders.add(wonder)
|
||||
allNaturalWonders.remove(wonder)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// First attempt to spawn the chosen wonders in order of least candidate tiles
|
||||
chosenWonders.forEach {
|
||||
wonderCandidateTiles[it] = getCandidateTilesForWonder(tileMap, it)
|
||||
}
|
||||
chosenWonders.sortBy { wonderCandidateTiles[it]!!.size }
|
||||
for (wonder in chosenWonders) {
|
||||
if (trySpawnOnSuitableLocation(wonderCandidateTiles[wonder]!!.filter { it !in blockedTiles }.toList(), wonder))
|
||||
spawned.add(wonder)
|
||||
}
|
||||
|
||||
// If some wonders were not able to be spawned we will pull a wonder from the fallback list
|
||||
if (spawned.size < numberToSpawn) {
|
||||
// Now we have to do some more calculations. Unfortunately we have to calculate candidate tiles for everyone.
|
||||
allNaturalWonders.forEach {
|
||||
wonderCandidateTiles[it] = getCandidateTilesForWonder(tileMap, it)
|
||||
}
|
||||
allNaturalWonders.sortBy { wonderCandidateTiles[it]!!.size }
|
||||
for (wonder in allNaturalWonders) {
|
||||
if (trySpawnOnSuitableLocation(wonderCandidateTiles[wonder]!!.filter { it !in blockedTiles }
|
||||
.toList(), wonder))
|
||||
spawned.add(wonder)
|
||||
if (spawned.size >= numberToSpawn)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
debug("Natural Wonders for this game: %s", spawned)
|
||||
}
|
||||
|
||||
private fun Unique.getIntParam(index: Int) = params[index].toInt()
|
||||
|
||||
private fun spawnSpecificWonder(tileMap: TileMap, naturalWonder: Terrain): Boolean {
|
||||
private fun getCandidateTilesForWonder(tileMap: TileMap, naturalWonder: Terrain): Collection<TileInfo> {
|
||||
val continentsRelevant = naturalWonder.hasUnique(UniqueType.NaturalWonderLargerLandmass) ||
|
||||
naturalWonder.hasUnique(UniqueType.NaturalWonderSmallerLandmass)
|
||||
val sortedContinents = if (continentsRelevant)
|
||||
@ -98,7 +130,7 @@ class NaturalWonderGenerator(val ruleset: Ruleset, val randomness: MapGeneration
|
||||
}
|
||||
}
|
||||
|
||||
return trySpawnOnSuitableLocation(suitableLocations, naturalWonder)
|
||||
return suitableLocations
|
||||
}
|
||||
|
||||
private fun trySpawnOnSuitableLocation(suitableLocations: List<TileInfo>, wonder: Terrain): Boolean {
|
||||
@ -138,6 +170,8 @@ class NaturalWonderGenerator(val ruleset: Ruleset, val randomness: MapGeneration
|
||||
clearTile(it)
|
||||
it.naturalWonder = wonder.name
|
||||
it.baseTerrain = wonder.turnsInto!!
|
||||
// Add all tiles within a certain distance to a blacklist so NW:s don't cluster
|
||||
blockedTiles.addAll(it.getTilesInDistance(it.tileMap.mapParameters.mapSize.height / 5))
|
||||
}
|
||||
if (convertNeighborsTo != null) {
|
||||
for (tile in location.neighbors) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user