mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-23 03:23:17 -04:00
chore(purity): CityStateFunctions
This commit is contained in:
parent
ca44be05d5
commit
885e62e501
@ -209,7 +209,7 @@ class City : IsPartOfGameInfoSerialization, INamed {
|
||||
|
||||
@Readonly fun getRuleset() = civ.gameInfo.ruleset
|
||||
|
||||
fun getResourcesGeneratedByCity(civResourceModifiers: Map<String, Float>) = CityResources.getResourcesGeneratedByCity(this, civResourceModifiers)
|
||||
@Readonly fun getResourcesGeneratedByCity(civResourceModifiers: Map<String, Float>) = CityResources.getResourcesGeneratedByCity(this, civResourceModifiers)
|
||||
@Readonly fun getAvailableResourceAmount(resourceName: String) = CityResources.getAvailableResourceAmount(this, resourceName)
|
||||
|
||||
@Readonly fun isGrowing() = foodForNextTurn() > 0
|
||||
|
@ -11,9 +11,10 @@ import yairm210.purity.annotations.Readonly
|
||||
object CityResources {
|
||||
|
||||
/** Returns ALL resources, city-wide and civ-wide */
|
||||
@Readonly
|
||||
fun getResourcesGeneratedByCity(city: City, resourceModifiers: Map<String, Float>): ResourceSupplyList {
|
||||
val cityResources = getResourcesGeneratedByCityNotIncludingBuildings(city, resourceModifiers)
|
||||
addCityResourcesGeneratedFromUniqueBuildings(city, cityResources, resourceModifiers)
|
||||
@LocalState val cityResources = getResourcesGeneratedByCityNotIncludingBuildings(city, resourceModifiers)
|
||||
cityResources += getCityResourcesGeneratedFromUniqueBuildings(city, resourceModifiers)
|
||||
return cityResources
|
||||
}
|
||||
|
||||
@ -55,15 +56,18 @@ object CityResources {
|
||||
return cityResources
|
||||
}
|
||||
|
||||
private fun addCityResourcesGeneratedFromUniqueBuildings(city: City, cityResources: ResourceSupplyList, resourceModifer: Map<String, Float>) {
|
||||
@Readonly
|
||||
private fun getCityResourcesGeneratedFromUniqueBuildings(city: City, resourceModifer: Map<String, Float>): ResourceSupplyList {
|
||||
val buildingResources = ResourceSupplyList()
|
||||
for (unique in city.getMatchingUniques(UniqueType.ProvidesResources, city.state, false)) { // E.G "Provides [1] [Iron]"
|
||||
val resource = city.getRuleset().tileResources[unique.params[1]]
|
||||
?: continue
|
||||
cityResources.add(
|
||||
buildingResources.add(
|
||||
resource, unique.getSourceNameForUser(),
|
||||
(unique.params[0].toFloat() * resourceModifer[resource.name]!!).toInt()
|
||||
)
|
||||
}
|
||||
return buildingResources
|
||||
}
|
||||
|
||||
/** Gets the number of resources available to this city
|
||||
|
@ -119,6 +119,7 @@ class CityStateFunctions(val civInfo: Civilization) {
|
||||
}
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun turnsForGreatPersonFromCityState(): Int = ((37 + Random.Default.nextInt(7)) * civInfo.gameInfo.speed.modifier).toInt()
|
||||
|
||||
/** Gain a random great person from the city state */
|
||||
@ -143,6 +144,7 @@ class CityStateFunctions(val civInfo: Civilization) {
|
||||
|
||||
val city = cities.city1
|
||||
|
||||
@Readonly
|
||||
fun giftableUniqueUnit(): BaseUnit? {
|
||||
val uniqueUnit = civInfo.gameInfo.ruleset.units[civInfo.cityStateUniqueUnit]
|
||||
?: return null
|
||||
@ -152,6 +154,7 @@ class CityStateFunctions(val civInfo: Civilization) {
|
||||
return null
|
||||
return uniqueUnit
|
||||
}
|
||||
@Readonly
|
||||
fun randomGiftableUnit() =
|
||||
city.cityConstructions.getConstructableUnits()
|
||||
.filter { !it.isCivilian() && it.isLandUnit && it.uniqueTo == null }
|
||||
@ -160,6 +163,7 @@ class CityStateFunctions(val civInfo: Civilization) {
|
||||
it.value > 0 && receivingCiv.getResourceAmount(it.key) < it.value
|
||||
} }
|
||||
.toList().randomOrNull()
|
||||
|
||||
val militaryUnit = giftableUniqueUnit() // If the receiving civ has discovered the required tech and not the obsolete tech for our unique, always give them the unique
|
||||
?: randomGiftableUnit() // Otherwise pick at random
|
||||
?: return // That filter _can_ result in no candidates, if so, quit silently
|
||||
@ -242,6 +246,7 @@ class CityStateFunctions(val civInfo: Civilization) {
|
||||
diplomacy.addInfluence(-20f)
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun otherCivCanPledgeProtection(otherCiv: Civilization): Boolean {
|
||||
// Must be a known city state
|
||||
if(!civInfo.isCityState || !otherCiv.isMajorCiv() || otherCiv.isDefeated() || !civInfo.knows(otherCiv))
|
||||
@ -262,6 +267,7 @@ class CityStateFunctions(val civInfo: Civilization) {
|
||||
return true
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun otherCivCanWithdrawProtection(otherCiv: Civilization): Boolean {
|
||||
// Must be a known city state
|
||||
if(!civInfo.isCityState || !otherCiv.isMajorCiv() || otherCiv.isDefeated() || !civInfo.knows(otherCiv))
|
||||
@ -334,6 +340,7 @@ class CityStateFunctions(val civInfo: Civilization) {
|
||||
}
|
||||
|
||||
/** @return a Sequence of NotificationActions for use in addNotification, showing Capital on map if any, then opening diplomacy */
|
||||
@Readonly
|
||||
fun getNotificationActions() = sequence {
|
||||
// Notification click will first point to CS location, if any, then open diplomacy.
|
||||
// That's fine for the influence notifications and for afraid too.
|
||||
@ -348,6 +355,7 @@ class CityStateFunctions(val civInfo: Civilization) {
|
||||
yield(DiplomacyAction(civInfo.civName))
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun getDiplomaticMarriageCost(): Int {
|
||||
// https://github.com/Gedemon/Civ5-DLL/blob/master/CvGameCoreDLL_Expansion1/CvMinorCivAI.cpp, line 7812
|
||||
var cost = (500 * civInfo.gameInfo.speed.goldCostModifier).toInt()
|
||||
@ -362,6 +370,7 @@ class CityStateFunctions(val civInfo: Civilization) {
|
||||
return cost
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun canBeMarriedBy(otherCiv: Civilization): Boolean {
|
||||
return (!civInfo.isDefeated()
|
||||
&& civInfo.isCityState
|
||||
@ -488,6 +497,7 @@ class CityStateFunctions(val civInfo: Civilization) {
|
||||
return modifiers
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun goldGainedByTribute(): Int {
|
||||
// These values are close enough, linear increase throughout the game
|
||||
var gold = (10 * civInfo.gameInfo.speed.goldGiftModifier).toInt() * 5 // rounding down to nearest 5
|
||||
@ -565,6 +575,7 @@ class CityStateFunctions(val civInfo: Civilization) {
|
||||
return
|
||||
}
|
||||
|
||||
@Readonly
|
||||
fun getNumThreateningBarbarians(): Int {
|
||||
if (civInfo.gameInfo.gameParameters.noBarbarians) return 0
|
||||
val barbarianCiv = civInfo.gameInfo.civilizations.firstOrNull { it.isBarbarian }
|
||||
@ -785,13 +796,16 @@ class CityStateFunctions(val civInfo: Civilization) {
|
||||
}
|
||||
}
|
||||
|
||||
fun getCityStateResourcesForAlly() = ResourceSupplyList().apply {
|
||||
@Readonly
|
||||
fun getCityStateResourcesForAlly(): ResourceSupplyList {
|
||||
val resourceSupplyList = ResourceSupplyList()
|
||||
// TODO: City-states don't give allies resources from civ-wide uniques!
|
||||
val civResourceModifiers = civInfo.getResourceModifiers()
|
||||
for (city in civInfo.cities) {
|
||||
// IGNORE the fact that they consume their own resources - #4769
|
||||
addPositiveByResource(city.getResourcesGeneratedByCity(civResourceModifiers), Constants.cityStates)
|
||||
resourceSupplyList.addPositiveByResource(city.getResourcesGeneratedByCity(civResourceModifiers), Constants.cityStates)
|
||||
}
|
||||
return resourceSupplyList
|
||||
}
|
||||
|
||||
// TODO: Optimize, update whenever status changes, otherwise retain the same list
|
||||
|
@ -33,6 +33,7 @@ import com.unciv.models.translations.getPlaceholderParameters
|
||||
import com.unciv.models.translations.tr
|
||||
import com.unciv.ui.components.extensions.toPercent
|
||||
import com.unciv.utils.randomWeighted
|
||||
import yairm210.purity.annotations.Pure
|
||||
import yairm210.purity.annotations.Readonly
|
||||
import kotlin.random.Random
|
||||
|
||||
@ -197,7 +198,7 @@ class QuestManager : IsPartOfGameInfoSerialization {
|
||||
}
|
||||
|
||||
// Readability helper - No asSequence(): call frequency * data size is small
|
||||
private fun getQuests(predicate: (Quest) -> Boolean) = ruleset.quests.values.filter(predicate)
|
||||
@Readonly private fun getQuests(predicate: (Quest) -> Boolean) = ruleset.quests.values.filter(predicate)
|
||||
|
||||
private fun tryStartNewGlobalQuest() {
|
||||
if (globalQuestCountdown != 0)
|
||||
@ -206,7 +207,7 @@ class QuestManager : IsPartOfGameInfoSerialization {
|
||||
return
|
||||
|
||||
val majorCivs = civ.getKnownCivs().filter { it.isMajorCiv() && !it.isAtWarWith(civ) } // A Sequence - fine because the count below can be different for each Quest
|
||||
fun Quest.isAssignable() = majorCivs.count { civ -> isQuestValid(this, civ) } >= minimumCivs
|
||||
@Readonly fun Quest.isAssignable() = majorCivs.count { civ -> isQuestValid(this, civ) } >= minimumCivs
|
||||
val assignableQuests = getQuests {
|
||||
it.isGlobal() && it.isAssignable()
|
||||
}
|
||||
@ -574,7 +575,7 @@ class QuestManager : IsPartOfGameInfoSerialization {
|
||||
return ""
|
||||
|
||||
val listOfLeadersAsTranslatedString = evaluation.winners.joinToString(separator = ", ") { it.assignee.tr() }
|
||||
fun getScoreString(name: String, score: Int) = "[$name] with [$score] [$scoreDescriptor]".tr()
|
||||
@Pure fun getScoreString(name: String, score: Int) = "[$name] with [$score] [$scoreDescriptor]".tr()
|
||||
val leadersString = getScoreString(listOfLeadersAsTranslatedString, evaluation.maxScore)
|
||||
|
||||
if (inquiringAssignedQuest in evaluation.winners)
|
||||
|
@ -194,7 +194,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
|
||||
|
||||
override fun getStatBuyCost(city: City, stat: Stat): Int? = costFunctions.getStatBuyCost(city, stat)
|
||||
|
||||
fun getDisbandGold(civInfo: Civilization) = getBaseGoldCost(civInfo, null).toInt() / 20
|
||||
@Readonly fun getDisbandGold(civInfo: Civilization) = getBaseGoldCost(civInfo, null).toInt() / 20
|
||||
|
||||
override fun shouldBeDisplayed(cityConstructions: CityConstructions): Boolean {
|
||||
val rejectionReasons = getRejectionReasons(cityConstructions)
|
||||
|
Loading…
x
Reference in New Issue
Block a user