diff --git a/core/src/com/unciv/logic/automation/Automation.kt b/core/src/com/unciv/logic/automation/Automation.kt index 6c1e31216d..e61163c849 100644 --- a/core/src/com/unciv/logic/automation/Automation.kt +++ b/core/src/com/unciv/logic/automation/Automation.kt @@ -26,8 +26,8 @@ object Automation { return rankStatsForCityWork(stats, city, cityStats) } - fun rankSpecialist(specialist: String, city: City, cityStats: Stats): Float { - val stats = city.cityStats.getStatsOfSpecialist(specialist) + fun rankSpecialist(specialist: String, city: City, cityStats: Stats, localUniqueCache: LocalUniqueCache): Float { + val stats = city.cityStats.getStatsOfSpecialist(specialist, localUniqueCache) var rank = rankStatsForCityWork(stats, city, cityStats, true) // derive GPP score var gpp = 0f @@ -337,10 +337,11 @@ object Automation { /** Support [UniqueType.CreatesOneImprovement] unique - find best tile for placement automation */ fun getTileForConstructionImprovement(city: City, improvement: TileImprovement): Tile? { + val localUniqueCache = LocalUniqueCache() return city.getTiles().filter { it.improvementFunctions.canBuildImprovement(improvement, city.civ) }.maxByOrNull { - rankTileForCityWork(it, city, city.cityStats.currentCityStats) + rankTileForCityWork(it, city, city.cityStats.currentCityStats, localUniqueCache) } } diff --git a/core/src/com/unciv/logic/city/CityStats.kt b/core/src/com/unciv/logic/city/CityStats.kt index 401f401a5d..1ef1b8403a 100644 --- a/core/src/com/unciv/logic/city/CityStats.kt +++ b/core/src/com/unciv/logic/city/CityStats.kt @@ -178,14 +178,14 @@ class CityStats(val city: City) { return !city.containsBuildingUnique(UniqueType.RemoveAnnexUnhappiness) } - fun getStatsOfSpecialist(specialistName: String): Stats { + fun getStatsOfSpecialist(specialistName: String, localUniqueCache: LocalUniqueCache = LocalUniqueCache(false)): Stats { val specialist = city.getRuleset().specialists[specialistName] ?: return Stats() val stats = specialist.cloneStats() - for (unique in city.getMatchingUniques(UniqueType.StatsFromSpecialist)) + for (unique in localUniqueCache.get(UniqueType.StatsFromSpecialist.name, city.getMatchingUniques(UniqueType.StatsFromSpecialist))) if (city.matchesFilter(unique.params[1])) stats.add(unique.stats) - for (unique in city.civ.getMatchingUniques(UniqueType.StatsFromObject)) + for (unique in localUniqueCache.get(UniqueType.StatsFromObject.name, city.civ.getMatchingUniques(UniqueType.StatsFromObject))) if (unique.params[1] == specialistName) stats.add(unique.stats) return stats @@ -193,8 +193,9 @@ class CityStats(val city: City) { private fun getStatsFromSpecialists(specialists: Counter): Stats { val stats = Stats() + val localUniqueCache = LocalUniqueCache() for (entry in specialists.filter { it.value > 0 }) - stats.add(getStatsOfSpecialist(entry.key) * entry.value) + stats.add(getStatsOfSpecialist(entry.key, localUniqueCache) * entry.value) return stats } diff --git a/core/src/com/unciv/logic/city/managers/CityPopulationManager.kt b/core/src/com/unciv/logic/city/managers/CityPopulationManager.kt index 3e83cc4aa6..1573d2578e 100644 --- a/core/src/com/unciv/logic/city/managers/CityPopulationManager.kt +++ b/core/src/com/unciv/logic/city/managers/CityPopulationManager.kt @@ -168,11 +168,11 @@ class CityPopulationManager : IsPartOfGameInfoSerialization { val bestJob: String? = if (city.manualSpecialists) null else getMaxSpecialists() .filter { specialistAllocations[it.key]!! < it.value } .map { it.key } - .maxByOrNull { Automation.rankSpecialist(it, city, cityStats) } + .maxByOrNull { Automation.rankSpecialist(it, city, cityStats, localUniqueCache) } var valueBestSpecialist = 0f if (bestJob != null) { - valueBestSpecialist = Automation.rankSpecialist(bestJob, city, cityStats) + valueBestSpecialist = Automation.rankSpecialist(bestJob, city, cityStats, localUniqueCache) } //assign population @@ -208,7 +208,7 @@ class CityPopulationManager : IsPartOfGameInfoSerialization { if (amount > maxSpecialists[specialistName]!!) specialistAllocations[specialistName] = maxSpecialists[specialistName]!! - + val localUniqueCache = LocalUniqueCache() while (getFreePopulation() < 0) { //evaluate tiles @@ -217,19 +217,19 @@ class CityPopulationManager : IsPartOfGameInfoSerialization { city.workedTiles.asSequence() .map { city.tileMap[it] } .minByOrNull { - Automation.rankTileForCityWork(it, city, city.cityStats.currentCityStats) + Automation.rankTileForCityWork(it, city, city.cityStats.currentCityStats, localUniqueCache) +(if (it.isLocked()) 10 else 0) }!! } val valueWorstTile = if (worstWorkedTile == null) 0f - else Automation.rankTileForCityWork(worstWorkedTile, city, city.cityStats.currentCityStats) + else Automation.rankTileForCityWork(worstWorkedTile, city, city.cityStats.currentCityStats, localUniqueCache) //evaluate specialists val worstAutoJob: String? = if (city.manualSpecialists) null else specialistAllocations.keys - .minByOrNull { Automation.rankSpecialist(it, city, city.cityStats.currentCityStats) } + .minByOrNull { Automation.rankSpecialist(it, city, city.cityStats.currentCityStats, localUniqueCache) } var valueWorstSpecialist = 0f if (worstAutoJob != null) - valueWorstSpecialist = Automation.rankSpecialist(worstAutoJob, city, city.cityStats.currentCityStats) + valueWorstSpecialist = Automation.rankSpecialist(worstAutoJob, city, city.cityStats.currentCityStats, localUniqueCache) // un-assign population @@ -249,7 +249,7 @@ class CityPopulationManager : IsPartOfGameInfoSerialization { // and population goes below the number of specialists, e.g. city is razing. // Let's give a chance to do the work automatically at least. val worstJob = specialistAllocations.keys.minByOrNull { - Automation.rankSpecialist(it, city, city.cityStats.currentCityStats) } + Automation.rankSpecialist(it, city, city.cityStats.currentCityStats, localUniqueCache) } ?: break // sorry, we can do nothing about that specialistAllocations.add(worstJob, -1) }