mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-24 03:53:12 -04:00
Unified 'does resource generate naturally on' checks to include all uniques everywhere
This commit is contained in:
parent
36baea9250
commit
903963787a
@ -23,7 +23,6 @@ import com.unciv.utils.debug
|
|||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.max
|
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
import kotlin.math.sign
|
import kotlin.math.sign
|
||||||
@ -342,8 +341,7 @@ class MapGenerator(val ruleset: Ruleset, private val coroutineScope: CoroutineSc
|
|||||||
// remove the tiles where previous resources have been placed
|
// remove the tiles where previous resources have been placed
|
||||||
val suitableTiles = candidateTiles
|
val suitableTiles = candidateTiles
|
||||||
.filterNot { it.baseTerrain == Constants.snow && it.isHill() }
|
.filterNot { it.baseTerrain == Constants.snow && it.isHill() }
|
||||||
.filter { it.resource == null
|
.filter { it.resource == null && resource.generatesNaturallyOn(it) }
|
||||||
&& resource.terrainsCanBeFoundOn.contains(it.lastTerrain.name) }
|
|
||||||
|
|
||||||
val locations = randomness.chooseSpreadOutLocations(resourcesPerType, suitableTiles, mapRadius)
|
val locations = randomness.chooseSpreadOutLocations(resourcesPerType, suitableTiles, mapRadius)
|
||||||
|
|
||||||
@ -361,8 +359,10 @@ class MapGenerator(val ruleset: Ruleset, private val coroutineScope: CoroutineSc
|
|||||||
|
|
||||||
val suitableTiles = tileMap.values
|
val suitableTiles = tileMap.values
|
||||||
.filterNot { it.baseTerrain == Constants.snow && it.isHill() }
|
.filterNot { it.baseTerrain == Constants.snow && it.isHill() }
|
||||||
.filter { it.resource == null && it.neighbors.none { neighbor -> neighbor.isNaturalWonder() }
|
.filter { it.resource == null
|
||||||
&& resourcesOfType.any { r -> r.terrainsCanBeFoundOn.contains(it.lastTerrain.name) } }
|
&& it.neighbors.none { neighbor -> neighbor.isNaturalWonder() }
|
||||||
|
&& resourcesOfType.any { r -> r.generatesNaturallyOn(it) }
|
||||||
|
}
|
||||||
val numberOfResources = tileMap.values.count { it.isLand && !it.isImpassible() } *
|
val numberOfResources = tileMap.values.count { it.isLand && !it.isImpassible() } *
|
||||||
tileMap.mapParameters.resourceRichness
|
tileMap.mapParameters.resourceRichness
|
||||||
val locations = randomness.chooseSpreadOutLocations(numberOfResources.toInt(), suitableTiles, mapRadius)
|
val locations = randomness.chooseSpreadOutLocations(numberOfResources.toInt(), suitableTiles, mapRadius)
|
||||||
@ -370,8 +370,7 @@ class MapGenerator(val ruleset: Ruleset, private val coroutineScope: CoroutineSc
|
|||||||
val resourceToNumber = Counter<String>()
|
val resourceToNumber = Counter<String>()
|
||||||
|
|
||||||
for (tile in locations) {
|
for (tile in locations) {
|
||||||
val possibleResources = resourcesOfType
|
val possibleResources = resourcesOfType.filter { it.generatesNaturallyOn(tile) }
|
||||||
.filter { it.terrainsCanBeFoundOn.contains(tile.lastTerrain.name) }
|
|
||||||
if (possibleResources.isEmpty()) continue
|
if (possibleResources.isEmpty()) continue
|
||||||
val resourceWithLeastAssignments = possibleResources.minByOrNull { resourceToNumber[it.name] }!!
|
val resourceWithLeastAssignments = possibleResources.minByOrNull { resourceToNumber[it.name] }!!
|
||||||
resourceToNumber.add(resourceWithLeastAssignments.name, 1)
|
resourceToNumber.add(resourceWithLeastAssignments.name, 1)
|
||||||
|
@ -30,14 +30,11 @@ object MapRegionResources {
|
|||||||
ResourceType.Luxury -> MapRegions.ImpactType.Luxury
|
ResourceType.Luxury -> MapRegions.ImpactType.Luxury
|
||||||
}
|
}
|
||||||
val conditionalTerrain = StateForConditionals(attackedTile = tileList.firstOrNull())
|
val conditionalTerrain = StateForConditionals(attackedTile = tileList.firstOrNull())
|
||||||
val weightings = resourceOptions.map {
|
val weightings = resourceOptions.associateWith {
|
||||||
val unique = it.getMatchingUniques(UniqueType.ResourceWeighting, conditionalTerrain).firstOrNull()
|
val unique = it.getMatchingUniques(UniqueType.ResourceWeighting, conditionalTerrain).firstOrNull()
|
||||||
if (unique != null)
|
val weight = if (unique != null) unique.params[0].toFloat() else 1f
|
||||||
unique.params[0].toFloat()
|
weight
|
||||||
else
|
|
||||||
1f
|
|
||||||
}
|
}
|
||||||
val testTerrains = (resourceOptions.size == 1) && !forcePlacement
|
|
||||||
val amountToPlace = (tileList.size / frequency) + 1
|
val amountToPlace = (tileList.size / frequency) + 1
|
||||||
var amountPlaced = 0
|
var amountPlaced = 0
|
||||||
val detailedPlaced = HashMap<TileResource, Int>()
|
val detailedPlaced = HashMap<TileResource, Int>()
|
||||||
@ -45,17 +42,15 @@ object MapRegionResources {
|
|||||||
val fallbackTiles = ArrayList<Tile>()
|
val fallbackTiles = ArrayList<Tile>()
|
||||||
// First pass - avoid impacts entirely
|
// First pass - avoid impacts entirely
|
||||||
for (tile in tileList) {
|
for (tile in tileList) {
|
||||||
if (tile.resource != null ||
|
if (tile.resource != null) continue
|
||||||
(testTerrains &&
|
val possibleResourcesForTile = resourceOptions.filter { it.generatesNaturallyOn(tile) }
|
||||||
(tile.lastTerrain.name !in resourceOptions.first().terrainsCanBeFoundOn ||
|
if (possibleResourcesForTile.isEmpty()) continue
|
||||||
resourceOptions.first().hasUnique(UniqueType.NoNaturalGeneration, conditionalTerrain)) ) ||
|
|
||||||
tile.getBaseTerrain().hasUnique(UniqueType.BlocksResources, conditionalTerrain))
|
|
||||||
continue // Can't place here, can't be a fallback tile
|
|
||||||
if (tileData[tile.position]!!.impacts.containsKey(impactType)) {
|
if (tileData[tile.position]!!.impacts.containsKey(impactType)) {
|
||||||
fallbackTiles.add(tile) // Taken but might be a viable fallback tile
|
fallbackTiles.add(tile) // Taken but might be a viable fallback tile
|
||||||
} else {
|
} else {
|
||||||
// Add a resource to the tile
|
// Add a resource to the tile
|
||||||
val resourceToPlace = resourceOptions.randomWeighted(weightings)
|
val resourceToPlace = possibleResourcesForTile.randomWeighted(possibleResourcesForTile.map { weightings[it] ?: 0f })
|
||||||
tile.setTileResource(resourceToPlace, majorDeposit)
|
tile.setTileResource(resourceToPlace, majorDeposit)
|
||||||
tileData.placeImpact(impactType, tile, baseImpact + Random.nextInt(randomImpact + 1))
|
tileData.placeImpact(impactType, tile, baseImpact + Random.nextInt(randomImpact + 1))
|
||||||
amountPlaced++
|
amountPlaced++
|
||||||
@ -70,7 +65,8 @@ object MapRegionResources {
|
|||||||
// Sorry, we do need to re-sort the list for every pass since new impacts are made with every placement
|
// Sorry, we do need to re-sort the list for every pass since new impacts are made with every placement
|
||||||
val bestTile = fallbackTiles.minByOrNull { tileData[it.position]!!.impacts[impactType]!! }!!
|
val bestTile = fallbackTiles.minByOrNull { tileData[it.position]!!.impacts[impactType]!! }!!
|
||||||
fallbackTiles.remove(bestTile)
|
fallbackTiles.remove(bestTile)
|
||||||
val resourceToPlace = resourceOptions.randomWeighted(weightings)
|
val possibleResourcesForTile = resourceOptions.filter { it.generatesNaturallyOn(bestTile) }
|
||||||
|
val resourceToPlace = possibleResourcesForTile.randomWeighted(possibleResourcesForTile.map { weightings[it] ?: 0f })
|
||||||
bestTile.setTileResource(resourceToPlace, majorDeposit)
|
bestTile.setTileResource(resourceToPlace, majorDeposit)
|
||||||
tileData.placeImpact(impactType, bestTile, baseImpact + Random.nextInt(randomImpact + 1))
|
tileData.placeImpact(impactType, bestTile, baseImpact + Random.nextInt(randomImpact + 1))
|
||||||
amountPlaced++
|
amountPlaced++
|
||||||
@ -95,17 +91,7 @@ object MapRegionResources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (tile in tiles) {
|
for (tile in tiles) {
|
||||||
val conditionalTerrain = StateForConditionals(attackedTile = tile)
|
if (tile.resource == null && resource.generatesNaturallyOn(tile)) {
|
||||||
if (tile.resource == null &&
|
|
||||||
tile.lastTerrain.name in resource.terrainsCanBeFoundOn &&
|
|
||||||
!tile.getBaseTerrain().hasUnique(UniqueType.BlocksResources, conditionalTerrain) &&
|
|
||||||
!resource.hasUnique(UniqueType.NoNaturalGeneration, conditionalTerrain) &&
|
|
||||||
|
|
||||||
resource.getMatchingUniques(UniqueType.TileGenerationConditions).none {
|
|
||||||
tile.temperature!! !in it.params[0].toDouble() .. it.params[1].toDouble()
|
|
||||||
|| tile.humidity!! !in it.params[2].toDouble() .. it.params[3].toDouble()
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
if (ratioProgress >= 1f &&
|
if (ratioProgress >= 1f &&
|
||||||
!(respectImpacts && tileData[tile.position]!!.impacts.containsKey(impactType))) {
|
!(respectImpacts && tileData[tile.position]!!.impacts.containsKey(impactType))) {
|
||||||
tile.setTileResource(resource, majorDeposit)
|
tile.setTileResource(resource, majorDeposit)
|
||||||
|
@ -792,7 +792,7 @@ class MapRegions (val ruleset: Ruleset) {
|
|||||||
continue
|
continue
|
||||||
val weightings = strategicResources.map {
|
val weightings = strategicResources.map {
|
||||||
if (fallbackStrategic) {
|
if (fallbackStrategic) {
|
||||||
if (tile.lastTerrain.name in it.terrainsCanBeFoundOn) 1f else 0f
|
if (it.generatesNaturallyOn(tile)) 1f else 0f
|
||||||
} else {
|
} else {
|
||||||
val uniques = it.getMatchingUniques(UniqueType.MinorDepositWeighting, conditionalTerrain).toList()
|
val uniques = it.getMatchingUniques(UniqueType.MinorDepositWeighting, conditionalTerrain).toList()
|
||||||
uniques.sumOf { unique -> unique.params[0].toInt() }.toFloat()
|
uniques.sumOf { unique -> unique.params[0].toInt() }.toFloat()
|
||||||
@ -822,10 +822,10 @@ class MapRegions (val ruleset: Ruleset) {
|
|||||||
for (resource in strategicResources) {
|
for (resource in strategicResources) {
|
||||||
val extraNeeded = min(2, regions.size - totalPlaced[resource]!!)
|
val extraNeeded = min(2, regions.size - totalPlaced[resource]!!)
|
||||||
if (extraNeeded > 0) {
|
if (extraNeeded > 0) {
|
||||||
if (isWaterOnlyResource(resource, ruleset))
|
val tilesToAddTo = if (!isWaterOnlyResource(resource, ruleset)) landList.asSequence()
|
||||||
MapRegionResources.tryAddingResourceToTiles(tileData, resource, extraNeeded, tileMap.values.asSequence().filter { it.isWater }.shuffled(), respectImpacts = true)
|
else tileMap.values.asSequence().filter { it.isWater }.shuffled()
|
||||||
else
|
|
||||||
MapRegionResources.tryAddingResourceToTiles(tileData, resource, extraNeeded, landList.asSequence(), respectImpacts = true)
|
MapRegionResources.tryAddingResourceToTiles(tileData, resource, extraNeeded, tilesToAddTo, respectImpacts = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,9 +162,7 @@ object StartNormalizer {
|
|||||||
|
|
||||||
if (plot.resource != null) continue
|
if (plot.resource != null) continue
|
||||||
|
|
||||||
val bonusToPlace =
|
val bonusToPlace = productionBonuses.filter { it.generatesNaturallyOn(plot) }.randomOrNull()
|
||||||
productionBonuses.filter { plot.lastTerrain.name in it.terrainsCanBeFoundOn }
|
|
||||||
.randomOrNull()
|
|
||||||
if (bonusToPlace != null) {
|
if (bonusToPlace != null) {
|
||||||
plot.resource = bonusToPlace.name
|
plot.resource = bonusToPlace.name
|
||||||
productionBonusesNeeded--
|
productionBonusesNeeded--
|
||||||
@ -280,7 +278,7 @@ object StartNormalizer {
|
|||||||
val validBonuses = ruleset.tileResources.values.filter {
|
val validBonuses = ruleset.tileResources.values.filter {
|
||||||
it.resourceType == ResourceType.Bonus &&
|
it.resourceType == ResourceType.Bonus &&
|
||||||
it.food >= 1 &&
|
it.food >= 1 &&
|
||||||
plot.lastTerrain.name in it.terrainsCanBeFoundOn
|
it.generatesNaturallyOn(plot)
|
||||||
}
|
}
|
||||||
val goodPlotForOasis =
|
val goodPlotForOasis =
|
||||||
canPlaceOasis && plot.lastTerrain.name in oasisEquivalent!!.occursOn
|
canPlaceOasis && plot.lastTerrain.name in oasisEquivalent!!.occursOn
|
||||||
|
@ -2,6 +2,7 @@ package com.unciv.models.ruleset.tile
|
|||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
|
import com.unciv.logic.map.tile.Tile
|
||||||
import com.unciv.models.ruleset.Belief
|
import com.unciv.models.ruleset.Belief
|
||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
import com.unciv.models.ruleset.RulesetStatsObject
|
import com.unciv.models.ruleset.RulesetStatsObject
|
||||||
@ -143,6 +144,10 @@ class Terrain : RulesetStatsObject() {
|
|||||||
return textList
|
return textList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun canBePlacedOn(tile: Tile){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
fun setTransients() {
|
fun setTransients() {
|
||||||
damagePerTurn = getMatchingUniques(UniqueType.DamagesContainingUnits).sumOf { it.params[0].toInt() }
|
damagePerTurn = getMatchingUniques(UniqueType.DamagesContainingUnits).sumOf { it.params[0].toInt() }
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ class TileImprovement : RulesetStatsObject() {
|
|||||||
val cannotFilters = getMatchingUniques(UniqueType.CannotBuildOnTile).map { it.params[0] }.toSet()
|
val cannotFilters = getMatchingUniques(UniqueType.CannotBuildOnTile).map { it.params[0] }.toSet()
|
||||||
val resourcesImprovedByThis = ruleset.tileResources.values.filter { it.isImprovedBy(name) }
|
val resourcesImprovedByThis = ruleset.tileResources.values.filter { it.isImprovedBy(name) }
|
||||||
|
|
||||||
val expandedCanBeBuiltOn = sequence {
|
val expandedTerrainsCanBeBuiltOn = sequence {
|
||||||
yieldAll(terrainsCanBeBuiltOn)
|
yieldAll(terrainsCanBeBuiltOn)
|
||||||
yieldAll(terrainsCanBeBuiltOn.asSequence().mapNotNull { ruleset.terrains[it] }.flatMap { it.occursOn.asSequence() })
|
yieldAll(terrainsCanBeBuiltOn.asSequence().mapNotNull { ruleset.terrains[it] }.flatMap { it.occursOn.asSequence() })
|
||||||
if (hasUnique(UniqueType.CanOnlyImproveResource))
|
if (hasUnique(UniqueType.CanOnlyImproveResource))
|
||||||
@ -220,21 +220,21 @@ class TileImprovement : RulesetStatsObject() {
|
|||||||
}.filter { it !in cannotFilters }.toMutableSet()
|
}.filter { it !in cannotFilters }.toMutableSet()
|
||||||
|
|
||||||
val terrainsCanBeBuiltOnTypes = sequence {
|
val terrainsCanBeBuiltOnTypes = sequence {
|
||||||
yieldAll(expandedCanBeBuiltOn.asSequence()
|
yieldAll(expandedTerrainsCanBeBuiltOn.asSequence()
|
||||||
.mapNotNull { ruleset.terrains[it]?.type })
|
.mapNotNull { ruleset.terrains[it]?.type })
|
||||||
yieldAll(TerrainType.values().asSequence()
|
yieldAll(TerrainType.values().asSequence()
|
||||||
.filter { it.name in expandedCanBeBuiltOn })
|
.filter { it.name in expandedTerrainsCanBeBuiltOn })
|
||||||
}.filter { it.name !in cannotFilters }.toMutableSet()
|
}.filter { it.name !in cannotFilters }.toMutableSet()
|
||||||
|
|
||||||
if (canOnlyFilters.isNotEmpty() && canOnlyFilters.intersect(expandedCanBeBuiltOn).isEmpty()) {
|
if (canOnlyFilters.isNotEmpty() && canOnlyFilters.intersect(expandedTerrainsCanBeBuiltOn).isEmpty()) {
|
||||||
expandedCanBeBuiltOn.clear()
|
expandedTerrainsCanBeBuiltOn.clear()
|
||||||
if (terrainsCanBeBuiltOnTypes.none { it.name in canOnlyFilters })
|
if (terrainsCanBeBuiltOnTypes.none { it.name in canOnlyFilters })
|
||||||
terrainsCanBeBuiltOnTypes.clear()
|
terrainsCanBeBuiltOnTypes.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun matchesBuildImprovementsFilter(filter: String) =
|
fun matchesBuildImprovementsFilter(filter: String) =
|
||||||
matchesFilter(filter) ||
|
matchesFilter(filter) ||
|
||||||
filter in expandedCanBeBuiltOn ||
|
filter in expandedTerrainsCanBeBuiltOn ||
|
||||||
terrainsCanBeBuiltOnTypes.any { it.name == filter }
|
terrainsCanBeBuiltOnTypes.any { it.name == filter }
|
||||||
|
|
||||||
return ruleset.units.values.asSequence()
|
return ruleset.units.values.asSequence()
|
||||||
|
@ -50,9 +50,8 @@ class TileResource : RulesetStatsObject() {
|
|||||||
if (terrainsCanBeFoundOn.isNotEmpty()) {
|
if (terrainsCanBeFoundOn.isNotEmpty()) {
|
||||||
textList += FormattedLine()
|
textList += FormattedLine()
|
||||||
if (terrainsCanBeFoundOn.size == 1) {
|
if (terrainsCanBeFoundOn.size == 1) {
|
||||||
with (terrainsCanBeFoundOn[0]) {
|
val terrainName = terrainsCanBeFoundOn[0]
|
||||||
textList += FormattedLine("{Can be found on} {$this}", link = "Terrain/$this")
|
textList += FormattedLine("{Can be found on} {$terrainName}", link = "Terrain/$terrainName")
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
textList += FormattedLine("{Can be found on}:")
|
textList += FormattedLine("{Can be found on}:")
|
||||||
terrainsCanBeFoundOn.forEach {
|
terrainsCanBeFoundOn.forEach {
|
||||||
@ -142,6 +141,21 @@ class TileResource : RulesetStatsObject() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun generatesNaturallyOn(tile:Tile): Boolean {
|
||||||
|
if (tile.lastTerrain.name !in terrainsCanBeFoundOn) return false
|
||||||
|
val stateForConditionals = StateForConditionals(tile = tile)
|
||||||
|
if (hasUnique(UniqueType.NoNaturalGeneration, stateForConditionals)) return false
|
||||||
|
if (tile.allTerrains.any { it.hasUnique(UniqueType.BlocksResources, stateForConditionals) }) return false
|
||||||
|
|
||||||
|
if (tile.temperature!=null && tile.humidity!=null) // Only works when in map generation
|
||||||
|
for (unique in getMatchingUniques(UniqueType.TileGenerationConditions, stateForConditionals)){
|
||||||
|
if (tile.temperature!! !in unique.params[0].toDouble() .. unique.params[1].toDouble()) return false
|
||||||
|
if (tile.humidity!! !in unique.params[2].toDouble() .. unique.params[3].toDouble()) return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
fun isStockpiled() = hasUnique(UniqueType.Stockpiled)
|
fun isStockpiled() = hasUnique(UniqueType.Stockpiled)
|
||||||
|
|
||||||
class DepositAmount {
|
class DepositAmount {
|
||||||
@ -149,5 +163,4 @@ class TileResource : RulesetStatsObject() {
|
|||||||
var default: Int = 2
|
var default: Int = 2
|
||||||
var abundant: Int = 3
|
var abundant: Int = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -790,9 +790,6 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
|
|||||||
|
|
||||||
Applicable to: Global, Unit
|
Applicable to: Global, Unit
|
||||||
|
|
||||||
??? example "+30% Strength when fighting City-State units and cities"
|
|
||||||
Applicable to: Global
|
|
||||||
|
|
||||||
??? example "[amount] additional attacks per turn"
|
??? example "[amount] additional attacks per turn"
|
||||||
Example: "[3] additional attacks per turn"
|
Example: "[3] additional attacks per turn"
|
||||||
|
|
||||||
@ -2026,6 +2023,11 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
|
|||||||
|
|
||||||
Applicable to: Conditional
|
Applicable to: Conditional
|
||||||
|
|
||||||
|
??? example "<vs [combatantFilter]>"
|
||||||
|
Example: "<vs [City]>"
|
||||||
|
|
||||||
|
Applicable to: Conditional
|
||||||
|
|
||||||
??? example "<when fighting units from a Civilization with more Cities than you>"
|
??? example "<when fighting units from a Civilization with more Cities than you>"
|
||||||
Applicable to: Conditional
|
Applicable to: Conditional
|
||||||
|
|
||||||
@ -2066,23 +2068,23 @@ Simple unique parameters are explained by mouseover. Complex parameters are expl
|
|||||||
|
|
||||||
Applicable to: Conditional
|
Applicable to: Conditional
|
||||||
|
|
||||||
??? example "<with [amount] to [amount] neighboring [tileFilter] [tileFilter] tiles>"
|
|
||||||
Example: "<with [3] to [3] neighboring [Farm] [Farm] tiles>"
|
|
||||||
|
|
||||||
Applicable to: Conditional
|
|
||||||
|
|
||||||
??? example "<in [tileFilter] tiles>"
|
??? example "<in [tileFilter] tiles>"
|
||||||
Example: "<in [Farm] tiles>"
|
Example: "<in [Farm] tiles>"
|
||||||
|
|
||||||
Applicable to: Conditional
|
Applicable to: Conditional
|
||||||
|
|
||||||
??? example "<in [tileFilter] [tileFilter] tiles>"
|
??? example "<in tiles without [tileFilter]>"
|
||||||
Example: "<in [Farm] [Farm] tiles>"
|
Example: "<in tiles without [Farm]>"
|
||||||
|
|
||||||
Applicable to: Conditional
|
Applicable to: Conditional
|
||||||
|
|
||||||
??? example "<in tiles without [tileFilter]>"
|
??? example "<in tiles adjacent to [tileFilter]>"
|
||||||
Example: "<in tiles without [Farm]>"
|
Example: "<in tiles adjacent to [Farm]>"
|
||||||
|
|
||||||
|
Applicable to: Conditional
|
||||||
|
|
||||||
|
??? example "<in tiles not adjacent to [tileFilter]>"
|
||||||
|
Example: "<in tiles not adjacent to [Farm]>"
|
||||||
|
|
||||||
Applicable to: Conditional
|
Applicable to: Conditional
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user