Added spy steal tech timer (#11657)

This commit is contained in:
Oskar Niesen
2024-05-29 15:58:50 -05:00
committed by GitHub
parent d82669d26c
commit 498a64fa16
2 changed files with 49 additions and 30 deletions

View File

@ -13,23 +13,24 @@ import com.unciv.logic.civilization.managers.EspionageManager
import com.unciv.models.ruleset.unique.StateForConditionals import com.unciv.models.ruleset.unique.StateForConditionals
import com.unciv.models.ruleset.unique.Unique import com.unciv.models.ruleset.unique.Unique
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
import kotlin.math.ceil
import kotlin.random.Random import kotlin.random.Random
enum class SpyAction(val displayString: String, val hasTurns: Boolean, internal val isSetUp: Boolean, private val isDoingWork: Boolean = false) { enum class SpyAction(val displayString: String, val hasCountdownTurns: Boolean, val showTurns: Boolean, internal val isSetUp: Boolean, private val isDoingWork: Boolean = false) {
None("None", false, false), None("None", false, false, false),
Moving("Moving", true, false, true), Moving("Moving", true, true, false, true),
EstablishNetwork("Establishing Network", true, false, true), EstablishNetwork("Establishing Network", true, true, false, true),
Surveillance("Observing City", false, true), Surveillance("Observing City", false, false, true),
StealingTech("Stealing Tech", false, true, true), StealingTech("Stealing Tech", false, true, true, true),
RiggingElections("Rigging Elections", false, true) { RiggingElections("Rigging Elections", false, true, true) {
override fun isDoingWork(spy: Spy) = !spy.civInfo.isAtWarWith(spy.getCity().civ) override fun isDoingWork(spy: Spy) = !spy.civInfo.isAtWarWith(spy.getCity().civ)
}, },
Coup("Coup", true, true, true), Coup("Coup", false, false, true, true),
CounterIntelligence("Counter-intelligence", false, true) { CounterIntelligence("Counter-intelligence", false, false, true) {
override fun isDoingWork(spy: Spy) = spy.turnsRemainingForAction > 0 override fun isDoingWork(spy: Spy) = spy.turnsRemainingForAction > 0
}, },
Dead("Dead", true, false), Dead("Dead", true, true, false),
; ;
internal open fun isDoingWork(spy: Spy) = isDoingWork internal open fun isDoingWork(spy: Spy) = isDoingWork
} }
@ -81,13 +82,13 @@ class Spy private constructor() : IsPartOfGameInfoSerialization {
} }
fun setAction(newAction: SpyAction, turns: Int = 0) { fun setAction(newAction: SpyAction, turns: Int = 0) {
assert(!newAction.hasTurns || turns > 0) // hasTurns==false but turns > 0 is allowed (CounterIntelligence), hasTurns==true and turns==0 is not. assert(!newAction.hasCountdownTurns || turns > 0) // hasTurns==false but turns > 0 is allowed (CounterIntelligence), hasTurns==true and turns==0 is not.
action = newAction action = newAction
turnsRemainingForAction = turns turnsRemainingForAction = turns
} }
fun endTurn() { fun endTurn() {
if (action.hasTurns && --turnsRemainingForAction > 0) return if (action.hasCountdownTurns && --turnsRemainingForAction > 0) return
when (action) { when (action) {
SpyAction.None -> return SpyAction.None -> return
SpyAction.Moving -> { SpyAction.Moving -> {
@ -115,19 +116,12 @@ class Spy private constructor() : IsPartOfGameInfoSerialization {
setAction(SpyAction.StealingTech) // There are new techs to steal! setAction(SpyAction.StealingTech) // There are new techs to steal!
} }
SpyAction.StealingTech -> { SpyAction.StealingTech -> {
val stealableTechs = espionageManager.getTechsToSteal(getCity().civ) turnsRemainingForAction = getTurnsRemainingToStealTech()
if (stealableTechs.isEmpty()) {
if (turnsRemainingForAction == -1) {
setAction(SpyAction.Surveillance) setAction(SpyAction.Surveillance)
addNotification("Your spy [$name] cannot steal any more techs from [${getCity().civ}] as we've already researched all the technology they know!") addNotification("Your spy [$name] cannot steal any more techs from [${getCity().civ}] as we've already researched all the technology they know!")
return } else if (turnsRemainingForAction == 0) {
}
val techStealCost = stealableTechs.maxOfOrNull { civInfo.gameInfo.ruleset.technologies[it]!!.cost }!!
var progressThisTurn = getCity().cityStats.currentCityStats.science
// 33% spy bonus for each level
progressThisTurn *= (rank + 2f) / 3f
progressThisTurn *= getEfficiencyModifier().toFloat()
progressTowardsStealingTech += progressThisTurn.toInt()
if (progressTowardsStealingTech > techStealCost) {
stealTech() stealTech()
} }
} }
@ -159,6 +153,30 @@ class Spy private constructor() : IsPartOfGameInfoSerialization {
private fun startStealingTech() { private fun startStealingTech() {
setAction(SpyAction.StealingTech) setAction(SpyAction.StealingTech)
progressTowardsStealingTech = 0 progressTowardsStealingTech = 0
turnsRemainingForAction = getTurnsRemainingToStealTech()
}
/**
* @return The number of turns left to steal the technology, note that this is a guess and may change.
* A 0 means that we are ready to steal the technology.
* A -1 means we have no techonologies to steal.
*/
private fun getTurnsRemainingToStealTech(): Int {
val stealableTechs = espionageManager.getTechsToSteal(getCity().civ)
if (stealableTechs.isEmpty()) return -1
val techStealCost = stealableTechs.maxOfOrNull { civInfo.gameInfo.ruleset.technologies[it]!!.cost }!!
var progressThisTurn = getCity().cityStats.currentCityStats.science
// 33% spy bonus for each level
progressThisTurn *= (rank + 2f) / 3f
progressThisTurn *= getEfficiencyModifier().toFloat()
progressTowardsStealingTech += progressThisTurn.toInt()
if (progressTowardsStealingTech >= techStealCost) {
return 0
} else {
return ceil((techStealCost - progressTowardsStealingTech) / progressThisTurn).toInt()
}
} }
private fun stealTech() { private fun stealTech() {

View File

@ -85,7 +85,8 @@ class EspionageOverviewScreen(val civInfo: Civilization, val worldScreen: WorldS
spySelectionTable.add(spy.name.toLabel()) spySelectionTable.add(spy.name.toLabel())
spySelectionTable.add(spy.rank.toLabel()) spySelectionTable.add(spy.rank.toLabel())
spySelectionTable.add(spy.getLocationName().toLabel()) spySelectionTable.add(spy.getLocationName().toLabel())
val actionString = if (spy.action.hasTurns) "[${spy.action.displayString}] ${spy.turnsRemainingForAction}${Fonts.turn}" val actionString = if (spy.action.showTurns && spy.turnsRemainingForAction != -1)
"[${spy.action.displayString}] ${spy.turnsRemainingForAction}${Fonts.turn}"
else spy.action.displayString else spy.action.displayString
spySelectionTable.add(actionString.toLabel()) spySelectionTable.add(actionString.toLabel())