Added new type-based uniqueMap, which will be the base of the "cached uniques revolution", and added a relatively benign use in unit uniques (#5619)

This commit is contained in:
Yair Morgenstern 2021-10-31 21:56:41 +02:00 committed by GitHub
parent 53a0c9b248
commit 52933ca58b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 6 deletions

View File

@ -9,12 +9,14 @@ import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.LocationAction import com.unciv.logic.civilization.LocationAction
import com.unciv.logic.civilization.NotificationIcon import com.unciv.logic.civilization.NotificationIcon
import com.unciv.models.MultiHashMap
import com.unciv.models.UnitActionType import com.unciv.models.UnitActionType
import com.unciv.models.ruleset.Ruleset import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.tile.TerrainType import com.unciv.models.ruleset.tile.TerrainType
import com.unciv.models.ruleset.unique.Unique import com.unciv.models.ruleset.unique.Unique
import com.unciv.models.ruleset.tile.TileImprovement import com.unciv.models.ruleset.tile.TileImprovement
import com.unciv.models.ruleset.unique.StateForConditionals import com.unciv.models.ruleset.unique.StateForConditionals
import com.unciv.models.ruleset.unique.UniqueMapTyped
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.ruleset.unit.BaseUnit import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.ruleset.unit.UnitType import com.unciv.models.ruleset.unit.UnitType
@ -202,6 +204,9 @@ class MapUnit {
@Transient @Transient
private var tempUniques = ArrayList<Unique>() private var tempUniques = ArrayList<Unique>()
@Transient
private var tempUniquesMap = UniqueMapTyped()
fun getUniques(): ArrayList<Unique> = tempUniques fun getUniques(): ArrayList<Unique> = tempUniques
fun getMatchingUniques(placeholderText: String): Sequence<Unique> = fun getMatchingUniques(placeholderText: String): Sequence<Unique> =
@ -212,9 +217,11 @@ class MapUnit {
stateForConditionals: StateForConditionals = StateForConditionals(civInfo, unit=this), stateForConditionals: StateForConditionals = StateForConditionals(civInfo, unit=this),
checkCivInfoUniques:Boolean = false checkCivInfoUniques:Boolean = false
) = sequence { ) = sequence {
yieldAll(tempUniques.asSequence() val tempUniques = tempUniquesMap[uniqueType]
.filter { it.type == uniqueType && it.conditionalsApply(stateForConditionals) } if (tempUniques != null)
) yieldAll(
tempUniques.filter { it.conditionalsApply(stateForConditionals) }
)
if (checkCivInfoUniques) if (checkCivInfoUniques)
yieldAll(civInfo.getMatchingUniques(uniqueType, stateForConditionals)) yieldAll(civInfo.getMatchingUniques(uniqueType, stateForConditionals))
} }
@ -225,7 +232,7 @@ class MapUnit {
fun hasUnique(uniqueType: UniqueType, stateForConditionals: StateForConditionals fun hasUnique(uniqueType: UniqueType, stateForConditionals: StateForConditionals
= StateForConditionals(civInfo, unit=this)): Boolean { = StateForConditionals(civInfo, unit=this)): Boolean {
return tempUniques.any { it.type == uniqueType && it.conditionalsApply(stateForConditionals) } return getMatchingUniques(uniqueType, stateForConditionals).any()
} }
fun updateUniques(ruleset: Ruleset) { fun updateUniques(ruleset: Ruleset) {
@ -239,6 +246,11 @@ class MapUnit {
} }
tempUniques = uniques tempUniques = uniques
val newUniquesMap = UniqueMapTyped()
for (unique in uniques)
if (unique.type != null)
newUniquesMap.addUnique(unique)
tempUniquesMap = newUniquesMap
allTilesCosts1 = hasUnique(UniqueType.AllTilesCost1Move) allTilesCosts1 = hasUnique(UniqueType.AllTilesCost1Move)
canPassThroughImpassableTiles = hasUnique(UniqueType.CanPassImpassable) canPassThroughImpassableTiles = hasUnique(UniqueType.CanPassImpassable)
@ -274,7 +286,7 @@ class MapUnit {
} }
// Init shortcut flags // Init shortcut flags
noTerrainMovementUniques = doubleMovementInTerrain.isEmpty() && noTerrainMovementUniques = doubleMovementInTerrain.isEmpty() &&
!roughTerrainPenalty && !civInfo.nation.ignoreHillMovementCost !roughTerrainPenalty && !civInfo.nation.ignoreHillMovementCost
noBaseTerrainOrHillDoubleMovementUniques = doubleMovementInTerrain noBaseTerrainOrHillDoubleMovementUniques = doubleMovementInTerrain
.none { it.value != DoubleMovementTerrainTarget.Feature } .none { it.value != DoubleMovementTerrainTarget.Feature }
noFilteredDoubleMovementUniques = doubleMovementInTerrain noFilteredDoubleMovementUniques = doubleMovementInTerrain
@ -967,7 +979,7 @@ class MapUnit {
} }
fun interceptDamagePercentBonus(): Int { fun interceptDamagePercentBonus(): Int {
return getUniques().filter { it.placeholderText == "[]% Damage when intercepting"} return getMatchingUniques("[]% Damage when intercepting")
.sumOf { it.params[0].toInt() } .sumOf { it.params[0].toInt() }
} }

View File

@ -1,6 +1,8 @@
package com.unciv.models package com.unciv.models
import java.util.* import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.LinkedHashMap
open class Counter<K> : LinkedHashMap<K, Int>() { open class Counter<K> : LinkedHashMap<K, Int>() {
@ -40,3 +42,13 @@ open class Counter<K> : LinkedHashMap<K, Int>() {
} }
} }
class MultiHashMap<K, V> : LinkedHashMap<K, ArrayList<V>>() {
fun add(key: K, value: V) {
var existingList = get(key)
if (existingList == null) {
existingList = ArrayList()
this[key] = existingList
}
existingList.add(value)
}
}

View File

@ -5,6 +5,9 @@ import com.unciv.logic.city.CityInfo
import com.unciv.models.stats.Stats import com.unciv.models.stats.Stats
import com.unciv.models.translations.* import com.unciv.models.translations.*
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val sourceObjectName: String? = null) { class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val sourceObjectName: String? = null) {
@ -107,6 +110,8 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
class UniqueMap: HashMap<String, ArrayList<Unique>>() { class UniqueMap: HashMap<String, ArrayList<Unique>>() {
//todo Once all untyped Uniques are converted, this should be HashMap<UniqueType, *> //todo Once all untyped Uniques are converted, this should be HashMap<UniqueType, *>
// For now, we can have both map types "side by side" each serving their own purpose,
// and gradually this one will be deprecated in favor of the other
fun addUnique(unique: Unique) { fun addUnique(unique: Unique) {
if (!containsKey(unique.placeholderText)) this[unique.placeholderText] = ArrayList() if (!containsKey(unique.placeholderText)) this[unique.placeholderText] = ArrayList()
this[unique.placeholderText]!!.add(unique) this[unique.placeholderText]!!.add(unique)
@ -121,3 +126,12 @@ class UniqueMap: HashMap<String, ArrayList<Unique>>() {
fun getAllUniques() = this.asSequence().flatMap { it.value.asSequence() } fun getAllUniques() = this.asSequence().flatMap { it.value.asSequence() }
} }
class UniqueMapTyped: EnumMap<UniqueType, ArrayList<Unique>>(UniqueType::class.java) {
fun addUnique(unique: Unique) {
if (!containsKey(unique.type)) this[unique.type] = ArrayList()
this[unique.type]!!.add(unique)
}
fun getUniques(uniqueType: UniqueType): Sequence<Unique> =
this[uniqueType]?.asSequence() ?: sequenceOf()
}