mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-27 22:06:05 -04:00
chore: More luxury assignment into the new object
This commit is contained in:
parent
2582d913d3
commit
3eff497bd8
@ -1,5 +1,8 @@
|
|||||||
package com.unciv.logic.map.mapgenerator.mapregions
|
package com.unciv.logic.map.mapgenerator.mapregions
|
||||||
|
|
||||||
|
import com.unciv.logic.map.MapResources
|
||||||
|
import com.unciv.logic.map.TileMap
|
||||||
|
import com.unciv.logic.map.tile.Tile
|
||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
import com.unciv.models.ruleset.tile.ResourceType
|
import com.unciv.models.ruleset.tile.ResourceType
|
||||||
import com.unciv.models.ruleset.tile.TerrainType
|
import com.unciv.models.ruleset.tile.TerrainType
|
||||||
@ -7,8 +10,11 @@ import com.unciv.models.ruleset.tile.TileResource
|
|||||||
import com.unciv.models.ruleset.unique.StateForConditionals
|
import com.unciv.models.ruleset.unique.StateForConditionals
|
||||||
import com.unciv.models.ruleset.unique.UniqueType
|
import com.unciv.models.ruleset.unique.UniqueType
|
||||||
import com.unciv.ui.components.extensions.randomWeighted
|
import com.unciv.ui.components.extensions.randomWeighted
|
||||||
|
import kotlin.math.abs
|
||||||
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
object LuxuryResourcePlacementLogic {
|
object LuxuryResourcePlacementLogic {
|
||||||
|
|
||||||
@ -88,8 +94,7 @@ object LuxuryResourcePlacementLogic {
|
|||||||
100 - min(tileData.size.toFloat().pow(0.2f) * 16, 100f).toInt() // Approximately
|
100 - min(tileData.size.toFloat().pow(0.2f) * 16, 100f).toInt() // Approximately
|
||||||
val targetDisabledLuxuries = (ruleset.tileResources.values
|
val targetDisabledLuxuries = (ruleset.tileResources.values
|
||||||
.count { it.resourceType == ResourceType.Luxury } * disabledPercent) / 100
|
.count { it.resourceType == ResourceType.Luxury } * disabledPercent) / 100
|
||||||
val randomLuxuries = remainingLuxuries.drop(targetDisabledLuxuries)
|
return remainingLuxuries.drop(targetDisabledLuxuries)
|
||||||
return randomLuxuries
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCandidateLuxuries(
|
private fun getCandidateLuxuries(
|
||||||
@ -160,4 +165,260 @@ object LuxuryResourcePlacementLogic {
|
|||||||
}
|
}
|
||||||
return cityStateLuxuries
|
return cityStateLuxuries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Places all Luxuries onto [tileMap]. Assumes that assignLuxuries and placeMinorCivs have been called. */
|
||||||
|
fun placeLuxuries(
|
||||||
|
regions: ArrayList<Region>,
|
||||||
|
tileMap: TileMap,
|
||||||
|
tileData: TileDataMap,
|
||||||
|
ruleset: Ruleset,
|
||||||
|
cityStateLuxuries: List<String>,
|
||||||
|
randomLuxuries: List<String>
|
||||||
|
) {
|
||||||
|
|
||||||
|
placeLuxuriesAtMajorCivStartLocations(regions, tileMap, ruleset, tileData, randomLuxuries)
|
||||||
|
placeLuxuriesAtMinorCivStartLocations(tileMap, ruleset, regions, randomLuxuries, cityStateLuxuries, tileData)
|
||||||
|
addRegionalLuxuries(tileData, regions, tileMap, ruleset)
|
||||||
|
addRandomLuxuries(randomLuxuries, tileData, tileMap, regions, ruleset)
|
||||||
|
|
||||||
|
|
||||||
|
val specialLuxuries = ruleset.tileResources.values.filter {
|
||||||
|
it.resourceType == ResourceType.Luxury &&
|
||||||
|
it.hasUnique(UniqueType.LuxurySpecialPlacement)
|
||||||
|
}
|
||||||
|
val placedSpecials = HashMap<String, Int>()
|
||||||
|
specialLuxuries.forEach { placedSpecials[it.name] = 0 } // init map
|
||||||
|
|
||||||
|
addExtraLuxuryToStarts(
|
||||||
|
tileMap,
|
||||||
|
regions,
|
||||||
|
randomLuxuries,
|
||||||
|
specialLuxuries,
|
||||||
|
cityStateLuxuries,
|
||||||
|
tileData,
|
||||||
|
ruleset,
|
||||||
|
placedSpecials
|
||||||
|
)
|
||||||
|
|
||||||
|
fillSpecialLuxuries(specialLuxuries, tileMap, regions, placedSpecials, tileData)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** top up marble-type specials if needed */
|
||||||
|
private fun fillSpecialLuxuries(
|
||||||
|
specialLuxuries: List<TileResource>,
|
||||||
|
tileMap: TileMap,
|
||||||
|
regions: ArrayList<Region>,
|
||||||
|
placedSpecials: HashMap<String, Int>,
|
||||||
|
tileData: TileDataMap
|
||||||
|
) {
|
||||||
|
for (special in specialLuxuries) {
|
||||||
|
val targetNumber = when (tileMap.mapParameters.mapResources) {
|
||||||
|
MapResources.sparse -> (regions.size * 0.5f).toInt()
|
||||||
|
MapResources.abundant -> (regions.size * 0.9f).toInt()
|
||||||
|
else -> (regions.size * 0.75f).toInt()
|
||||||
|
}
|
||||||
|
val numberToPlace = max(2, targetNumber - placedSpecials[special.name]!!)
|
||||||
|
MapRegionResources.tryAddingResourceToTiles(
|
||||||
|
tileData, special, numberToPlace, tileMap.values.asSequence().shuffled(), 1f,
|
||||||
|
true, 6, 0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addExtraLuxuryToStarts(
|
||||||
|
tileMap: TileMap,
|
||||||
|
regions: ArrayList<Region>,
|
||||||
|
randomLuxuries: List<String>,
|
||||||
|
specialLuxuries: List<TileResource>,
|
||||||
|
cityStateLuxuries: List<String>,
|
||||||
|
tileData: TileDataMap,
|
||||||
|
ruleset: Ruleset,
|
||||||
|
placedSpecials: HashMap<String, Int>
|
||||||
|
) {
|
||||||
|
if (tileMap.mapParameters.mapResources == MapResources.sparse) return
|
||||||
|
for (region in regions) {
|
||||||
|
val tilesToCheck = tileMap[region.startPosition!!].getTilesInDistanceRange(1..2)
|
||||||
|
val candidateLuxuries = randomLuxuries.shuffled().toMutableList()
|
||||||
|
if (tileMap.mapParameters.mapResources != MapResources.strategicBalance)
|
||||||
|
candidateLuxuries += specialLuxuries.shuffled()
|
||||||
|
.map { it.name } // Include marble!
|
||||||
|
candidateLuxuries += cityStateLuxuries.shuffled()
|
||||||
|
candidateLuxuries += regions.mapNotNull { it.luxury }.shuffled()
|
||||||
|
for (luxury in candidateLuxuries) {
|
||||||
|
if (MapRegionResources.tryAddingResourceToTiles(
|
||||||
|
tileData,
|
||||||
|
ruleset.tileResources[luxury]!!,
|
||||||
|
1,
|
||||||
|
tilesToCheck
|
||||||
|
) > 0
|
||||||
|
) {
|
||||||
|
if (placedSpecials.containsKey(luxury)) // Keep track of marble-type specials as they may be placed now.
|
||||||
|
placedSpecials[luxury] = placedSpecials[luxury]!! + 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addRandomLuxuries(
|
||||||
|
randomLuxuries: List<String>,
|
||||||
|
tileData: TileDataMap,
|
||||||
|
tileMap: TileMap,
|
||||||
|
regions: ArrayList<Region>,
|
||||||
|
ruleset: Ruleset
|
||||||
|
) {
|
||||||
|
if (randomLuxuries.isEmpty()) return
|
||||||
|
var targetRandomLuxuries = tileData.size.toFloat().pow(0.45f).toInt() // Approximately
|
||||||
|
targetRandomLuxuries *= when (tileMap.mapParameters.mapResources) {
|
||||||
|
MapResources.sparse -> 80
|
||||||
|
MapResources.abundant -> 133
|
||||||
|
else -> 100
|
||||||
|
}
|
||||||
|
targetRandomLuxuries /= 100
|
||||||
|
targetRandomLuxuries += Random.nextInt(regions.size) // Add random number based on number of civs
|
||||||
|
val minimumRandomLuxuries = tileData.size.toFloat().pow(0.2f).toInt() // Approximately
|
||||||
|
val worldTiles = tileMap.values.asSequence().shuffled()
|
||||||
|
for ((index, luxury) in randomLuxuries.shuffled().withIndex()) {
|
||||||
|
val targetForThisLuxury = if (randomLuxuries.size > 8) targetRandomLuxuries / 10
|
||||||
|
else {
|
||||||
|
val minimum = max(3, minimumRandomLuxuries - index)
|
||||||
|
max(
|
||||||
|
minimum,
|
||||||
|
(targetRandomLuxuries * MapRegions.randomLuxuryRatios[randomLuxuries.size]!![index] + 0.5f).toInt()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
MapRegionResources.tryAddingResourceToTiles(
|
||||||
|
tileData,
|
||||||
|
ruleset.tileResources[luxury]!!,
|
||||||
|
targetForThisLuxury,
|
||||||
|
worldTiles,
|
||||||
|
0.25f,
|
||||||
|
true,
|
||||||
|
4,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addRegionalLuxuries(
|
||||||
|
tileData: TileDataMap,
|
||||||
|
regions: ArrayList<Region>,
|
||||||
|
tileMap: TileMap,
|
||||||
|
ruleset: Ruleset
|
||||||
|
) {
|
||||||
|
val idealCivsForMapSize = max(2, tileData.size / 500)
|
||||||
|
var regionTargetNumber =
|
||||||
|
(tileData.size / 600) - (0.3f * abs(regions.size - idealCivsForMapSize)).toInt()
|
||||||
|
regionTargetNumber += when (tileMap.mapParameters.mapResources) {
|
||||||
|
MapResources.abundant -> 1
|
||||||
|
MapResources.sparse -> -1
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
regionTargetNumber = max(1, regionTargetNumber)
|
||||||
|
for (region in regions) {
|
||||||
|
val resource = ruleset.tileResources[region.luxury] ?: continue
|
||||||
|
fun Tile.isShoreOfContinent(continent: Int) =
|
||||||
|
isWater && neighbors.any { it.getContinent() == continent }
|
||||||
|
|
||||||
|
val candidates = if (isWaterOnlyResource(resource, ruleset))
|
||||||
|
tileMap.getTilesInRectangle(region.rect)
|
||||||
|
.filter { it.isShoreOfContinent(region.continentID) }
|
||||||
|
else region.tiles.asSequence()
|
||||||
|
MapRegionResources.tryAddingResourceToTiles(
|
||||||
|
tileData,
|
||||||
|
resource,
|
||||||
|
regionTargetNumber,
|
||||||
|
candidates.shuffled(),
|
||||||
|
0.4f,
|
||||||
|
true,
|
||||||
|
4,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun placeLuxuriesAtMinorCivStartLocations(
|
||||||
|
tileMap: TileMap,
|
||||||
|
ruleset: Ruleset,
|
||||||
|
regions: ArrayList<Region>,
|
||||||
|
randomLuxuries: List<String>,
|
||||||
|
cityStateLuxuries: List<String>,
|
||||||
|
tileData: TileDataMap
|
||||||
|
) {
|
||||||
|
for (startLocation in tileMap.startingLocationsByNation
|
||||||
|
.filterKeys { ruleset.nations[it]!!.isCityState }.map { it.value.first() }) {
|
||||||
|
val region = regions.firstOrNull { startLocation in it.tiles }
|
||||||
|
val tilesToCheck = startLocation.getTilesInDistanceRange(1..2)
|
||||||
|
// 75% probability that we first attempt to place a "city state" luxury, then a random or regional one
|
||||||
|
// 25% probability of going the other way around
|
||||||
|
val globalLuxuries =
|
||||||
|
if (region?.luxury != null) randomLuxuries + listOf(region.luxury) else randomLuxuries
|
||||||
|
val candidateLuxuries = if (Random.nextInt(100) >= 25)
|
||||||
|
cityStateLuxuries.shuffled() + globalLuxuries.shuffled()
|
||||||
|
else
|
||||||
|
globalLuxuries.shuffled() + cityStateLuxuries.shuffled()
|
||||||
|
// Now try adding one until we are successful
|
||||||
|
for (luxury in candidateLuxuries) {
|
||||||
|
if (MapRegionResources.tryAddingResourceToTiles(
|
||||||
|
tileData,
|
||||||
|
ruleset.tileResources[luxury]!!,
|
||||||
|
1,
|
||||||
|
tilesToCheck
|
||||||
|
) > 0
|
||||||
|
) break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun placeLuxuriesAtMajorCivStartLocations(
|
||||||
|
regions: ArrayList<Region>,
|
||||||
|
tileMap: TileMap,
|
||||||
|
ruleset: Ruleset,
|
||||||
|
tileData: TileDataMap,
|
||||||
|
randomLuxuries: List<String>
|
||||||
|
) {
|
||||||
|
val averageFertilityDensity =
|
||||||
|
regions.sumOf { it.totalFertility } / regions.sumOf { it.tiles.size }.toFloat()
|
||||||
|
for (region in regions) {
|
||||||
|
var targetLuxuries = 1
|
||||||
|
if (tileMap.mapParameters.mapResources == MapResources.legendaryStart)
|
||||||
|
targetLuxuries++
|
||||||
|
if (region.totalFertility / region.tiles.size.toFloat() < averageFertilityDensity) {
|
||||||
|
targetLuxuries++
|
||||||
|
}
|
||||||
|
|
||||||
|
val luxuryToPlace = ruleset.tileResources[region.luxury] ?: continue
|
||||||
|
// First check 2 inner rings
|
||||||
|
val firstPass = tileMap[region.startPosition!!].getTilesInDistanceRange(1..2)
|
||||||
|
.shuffled().sortedBy { it.getTileFertility(false) } // Check bad tiles first
|
||||||
|
targetLuxuries -= MapRegionResources.tryAddingResourceToTiles(
|
||||||
|
tileData,
|
||||||
|
luxuryToPlace,
|
||||||
|
targetLuxuries,
|
||||||
|
firstPass,
|
||||||
|
0.5f
|
||||||
|
) // Skip every 2nd tile on first pass
|
||||||
|
|
||||||
|
if (targetLuxuries > 0) {
|
||||||
|
val secondPass = firstPass + tileMap[region.startPosition!!].getTilesAtDistance(3)
|
||||||
|
.shuffled().sortedBy { it.getTileFertility(false) } // Check bad tiles first
|
||||||
|
targetLuxuries -= MapRegionResources.tryAddingResourceToTiles(
|
||||||
|
tileData,
|
||||||
|
luxuryToPlace,
|
||||||
|
targetLuxuries,
|
||||||
|
secondPass
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (targetLuxuries > 0) {
|
||||||
|
// Try adding in 1 luxury from the random rotation as compensation
|
||||||
|
for (luxury in randomLuxuries) {
|
||||||
|
if (MapRegionResources.tryAddingResourceToTiles(
|
||||||
|
tileData, ruleset.tileResources[luxury]!!, 1, firstPass) > 0
|
||||||
|
) break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,6 @@ import com.unciv.utils.Tag
|
|||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.math.pow
|
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@ -660,7 +659,7 @@ class MapRegions (val ruleset: Ruleset){
|
|||||||
|
|
||||||
val (cityStateLuxuries, randomLuxuries) = LuxuryResourcePlacementLogic.assignLuxuries(regions, tileData, ruleset)
|
val (cityStateLuxuries, randomLuxuries) = LuxuryResourcePlacementLogic.assignLuxuries(regions, tileData, ruleset)
|
||||||
MinorCivPlacer.placeMinorCivs(regions, tileMap, minorCivs, usingArchipelagoRegions, tileData, ruleset)
|
MinorCivPlacer.placeMinorCivs(regions, tileMap, minorCivs, usingArchipelagoRegions, tileData, ruleset)
|
||||||
placeLuxuries(tileMap, cityStateLuxuries, randomLuxuries)
|
LuxuryResourcePlacementLogic.placeLuxuries(regions, tileMap, tileData, ruleset, cityStateLuxuries, randomLuxuries)
|
||||||
placeStrategicAndBonuses(tileMap)
|
placeStrategicAndBonuses(tileMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,137 +674,6 @@ class MapRegions (val ruleset: Ruleset){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Places all Luxuries onto [tileMap]. Assumes that assignLuxuries and placeMinorCivs have been called. */
|
|
||||||
private fun placeLuxuries(
|
|
||||||
tileMap: TileMap,
|
|
||||||
cityStateLuxuries: List<String>,
|
|
||||||
randomLuxuries: List<String>
|
|
||||||
) {
|
|
||||||
|
|
||||||
// First place luxuries at major civ start locations
|
|
||||||
val averageFertilityDensity = regions.sumOf { it.totalFertility } / regions.sumOf { it.tiles.size }.toFloat()
|
|
||||||
for (region in regions) {
|
|
||||||
var targetLuxuries = 1
|
|
||||||
if (tileMap.mapParameters.mapResources == MapResources.legendaryStart)
|
|
||||||
targetLuxuries++
|
|
||||||
if (region.totalFertility / region.tiles.size.toFloat() < averageFertilityDensity) {
|
|
||||||
targetLuxuries++
|
|
||||||
}
|
|
||||||
|
|
||||||
val luxuryToPlace = ruleset.tileResources[region.luxury] ?: continue
|
|
||||||
// First check 2 inner rings
|
|
||||||
val firstPass = tileMap[region.startPosition!!].getTilesInDistanceRange(1..2)
|
|
||||||
.shuffled().sortedBy { it.getTileFertility(false) } // Check bad tiles first
|
|
||||||
targetLuxuries -= MapRegionResources.tryAddingResourceToTiles(tileData, luxuryToPlace, targetLuxuries, firstPass, 0.5f) // Skip every 2nd tile on first pass
|
|
||||||
|
|
||||||
if (targetLuxuries > 0) {
|
|
||||||
val secondPass = firstPass + tileMap[region.startPosition!!].getTilesAtDistance(3)
|
|
||||||
.shuffled().sortedBy { it.getTileFertility(false) } // Check bad tiles first
|
|
||||||
targetLuxuries -= MapRegionResources.tryAddingResourceToTiles(tileData, luxuryToPlace, targetLuxuries, secondPass)
|
|
||||||
}
|
|
||||||
if (targetLuxuries > 0) {
|
|
||||||
// Try adding in 1 luxury from the random rotation as compensation
|
|
||||||
for (luxury in randomLuxuries) {
|
|
||||||
if (MapRegionResources.tryAddingResourceToTiles(tileData, ruleset.tileResources[luxury]!!, 1, firstPass) > 0) break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Second place one (1) luxury at minor civ start locations
|
|
||||||
// Check only ones that got a start location
|
|
||||||
for (startLocation in tileMap.startingLocationsByNation
|
|
||||||
.filterKeys { ruleset.nations[it]!!.isCityState }.map { it.value.first() }) {
|
|
||||||
val region = regions.firstOrNull { startLocation in it.tiles }
|
|
||||||
val tilesToCheck = startLocation.getTilesInDistanceRange(1..2)
|
|
||||||
// 75% probability that we first attempt to place a "city state" luxury, then a random or regional one
|
|
||||||
// 25% probability of going the other way around
|
|
||||||
val globalLuxuries = if (region?.luxury != null) randomLuxuries + listOf(region.luxury) else randomLuxuries
|
|
||||||
val candidateLuxuries = if (Random.nextInt(100) >= 25)
|
|
||||||
cityStateLuxuries.shuffled() + globalLuxuries.shuffled()
|
|
||||||
else
|
|
||||||
globalLuxuries.shuffled() + cityStateLuxuries.shuffled()
|
|
||||||
// Now try adding one until we are successful
|
|
||||||
for (luxury in candidateLuxuries) {
|
|
||||||
if (MapRegionResources.tryAddingResourceToTiles(tileData, ruleset.tileResources[luxury]!!, 1, tilesToCheck) > 0) break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Third add regional luxuries
|
|
||||||
// The target number depends on map size and how close we are to an "ideal number" of civs for the map
|
|
||||||
val idealCivs = max(2, tileData.size / 500)
|
|
||||||
var regionTargetNumber = (tileData.size / 600) - (0.3f * abs(regions.size - idealCivs)).toInt()
|
|
||||||
regionTargetNumber += when (tileMap.mapParameters.mapResources) {
|
|
||||||
MapResources.abundant -> 1
|
|
||||||
MapResources.sparse -> -1
|
|
||||||
else -> 0
|
|
||||||
}
|
|
||||||
regionTargetNumber = max(1, regionTargetNumber)
|
|
||||||
for (region in regions) {
|
|
||||||
val resource = ruleset.tileResources[region.luxury] ?: continue
|
|
||||||
fun Tile.isShoreOfContinent(continent: Int) = isWater && neighbors.any { it.getContinent() == continent }
|
|
||||||
val candidates = if (isWaterOnlyResource(resource, ruleset))
|
|
||||||
tileMap.getTilesInRectangle(region.rect).filter { it.isShoreOfContinent(region.continentID) }
|
|
||||||
else region.tiles.asSequence()
|
|
||||||
MapRegionResources.tryAddingResourceToTiles(tileData, resource, regionTargetNumber, candidates.shuffled(), 0.4f, true, 4, 2)
|
|
||||||
}
|
|
||||||
// Fourth add random luxuries
|
|
||||||
if (randomLuxuries.isNotEmpty()) {
|
|
||||||
var targetRandomLuxuries = tileData.size.toFloat().pow(0.45f).toInt() // Approximately
|
|
||||||
targetRandomLuxuries *= when (tileMap.mapParameters.mapResources) {
|
|
||||||
MapResources.sparse -> 80
|
|
||||||
MapResources.abundant -> 133
|
|
||||||
else -> 100
|
|
||||||
}
|
|
||||||
targetRandomLuxuries /= 100
|
|
||||||
targetRandomLuxuries += Random.nextInt(regions.size) // Add random number based on number of civs
|
|
||||||
val minimumRandomLuxuries = tileData.size.toFloat().pow(0.2f).toInt() // Approximately
|
|
||||||
val worldTiles = tileMap.values.asSequence().shuffled()
|
|
||||||
for ((index, luxury) in randomLuxuries.shuffled().withIndex()) {
|
|
||||||
val targetForThisLuxury = if (randomLuxuries.size > 8) targetRandomLuxuries / 10
|
|
||||||
else {
|
|
||||||
val minimum = max(3, minimumRandomLuxuries - index)
|
|
||||||
max(minimum, (targetRandomLuxuries * randomLuxuryRatios[randomLuxuries.size]!![index] + 0.5f).toInt())
|
|
||||||
}
|
|
||||||
MapRegionResources.tryAddingResourceToTiles(tileData, ruleset.tileResources[luxury]!!, targetForThisLuxury, worldTiles, 0.25f,
|
|
||||||
true, 4, 2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val specialLuxuries = ruleset.tileResources.values.filter {
|
|
||||||
it.resourceType == ResourceType.Luxury &&
|
|
||||||
it.hasUnique(UniqueType.LuxurySpecialPlacement)
|
|
||||||
}
|
|
||||||
val placedSpecials = HashMap<String, Int>()
|
|
||||||
specialLuxuries.forEach { placedSpecials[it.name] = 0 } // init map
|
|
||||||
|
|
||||||
// Fifth, on resource settings other than sparse, add an extra luxury to starts
|
|
||||||
if (tileMap.mapParameters.mapResources != MapResources.sparse) {
|
|
||||||
for (region in regions) {
|
|
||||||
val tilesToCheck = tileMap[region.startPosition!!].getTilesInDistanceRange(1..2)
|
|
||||||
val candidateLuxuries = randomLuxuries.shuffled().toMutableList()
|
|
||||||
if (tileMap.mapParameters.mapResources != MapResources.strategicBalance)
|
|
||||||
candidateLuxuries += specialLuxuries.shuffled().map { it.name } // Include marble!
|
|
||||||
candidateLuxuries += cityStateLuxuries.shuffled()
|
|
||||||
candidateLuxuries += regions.mapNotNull { it.luxury }.shuffled()
|
|
||||||
for (luxury in candidateLuxuries) {
|
|
||||||
if (MapRegionResources.tryAddingResourceToTiles(tileData, ruleset.tileResources[luxury]!!, 1, tilesToCheck) > 0) {
|
|
||||||
if (placedSpecials.containsKey(luxury)) // Keep track of marble-type specials as they may be placed now.
|
|
||||||
placedSpecials[luxury] = placedSpecials[luxury]!! + 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Sixth, top up marble-type specials if needed
|
|
||||||
for (special in specialLuxuries) {
|
|
||||||
val targetNumber = when (tileMap.mapParameters.mapResources) {
|
|
||||||
MapResources.sparse -> (regions.size * 0.5f).toInt()
|
|
||||||
MapResources.abundant -> (regions.size * 0.9f).toInt()
|
|
||||||
else -> (regions.size * 0.75f).toInt()
|
|
||||||
}
|
|
||||||
val numberToPlace = max(2, targetNumber - placedSpecials[special.name]!!)
|
|
||||||
MapRegionResources.tryAddingResourceToTiles(tileData, special, numberToPlace, tileMap.values.asSequence().shuffled(), 1f,
|
|
||||||
true, 6, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun placeStrategicAndBonuses(tileMap: TileMap) {
|
private fun placeStrategicAndBonuses(tileMap: TileMap) {
|
||||||
val strategicResources = ruleset.tileResources.values.filter { it.resourceType == ResourceType.Strategic }
|
val strategicResources = ruleset.tileResources.values.filter { it.resourceType == ResourceType.Strategic }
|
||||||
// As usual, if there are any relevant json definitions, assume they are complete
|
// As usual, if there are any relevant json definitions, assume they are complete
|
||||||
|
Loading…
x
Reference in New Issue
Block a user