Add AI quest handlers for blizzard, drought, and epidemic filtering (#6649)

* Add AI quest handlers for blizzard, drought, and epidemic own-province filtering

Create ControlWeatherQuestCommandChooser to handle StartBlizzardQuest and
StartDroughtQuest via the ControlWeather command. Update StartEpidemicQuest
CommandChooser to skip quests targeting the acting faction's own provinces.
Both handlers verify the appropriate command is available before selecting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Address review: use inside() pattern and extract questTargets method

- Replace asInstanceOf with inside() pattern in ControlWeather and
  StartEpidemic test assertions
- Extract questTargets into a private method in
  ControlWeatherQuestCommandChooser and match directly on its result

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-15 07:35:23 -07:00
committed by GitHub
co-authored by Claude Opus 4.6
parent 334a431f14
commit 7bdbd7ec8f
9 changed files with 523 additions and 8 deletions
+11 -5
View File
@@ -55,12 +55,19 @@ The AI processes quest handlers in priority order. The first handler that produc
| `DevelopProvincesQuest` | `DevelopProvincesQuestCommandChooser` | Switches provinces to Develop order. Prefers provinces without hostile neighbors. |
| `MobilizeProvincesQuest` | `MobilizeProvincesQuestCommandChooser` | Switches provinces to Mobilize order. Prefers provinces with hostile neighbors. Skipped if a DevelopProvincesQuest also exists (conflict avoidance). |
### Weather/Epidemic Quests
| Quest | Handler | Notes |
|-------|---------|-------|
| `StartEpidemicQuest` | `StartEpidemicQuestCommandChooser` | Start an epidemic in a province. Skipped if the target province belongs to the acting faction. |
| `StartBlizzardQuest` | `ControlWeatherQuestCommandChooser` | Start a blizzard via ControlWeather command. Skipped if the target province belongs to the acting faction. |
| `StartDroughtQuest` | `ControlWeatherQuestCommandChooser` | Start a drought via ControlWeather command. Skipped if the target province belongs to the acting faction. |
### Other Quests
| Quest | Handler | Conditions |
|-------|---------|------------|
| `RestProvinceQuest` | `RestProvinceQuestCommandChooser` | Use the Rest command in a specific province |
| `StartEpidemicQuest` | `StartEpidemicQuestCommandChooser` | Start an epidemic in a province |
| `SwearBrotherhoodWithHeroQuest` | `SwearBrotherhoodQuestCommandChooser` | Swear brotherhood with a specific hero |
| `DismissSpecificVassalQuest` | `DismissSpecificVassalCommandChooser` | Only if province has more than 2 heroes AND the unaffiliated hero's power >= target hero's power * `RequiredPowerMultiplierForDismiss` |
@@ -92,8 +99,6 @@ The following quests have no handler in `FulfillQuestsCommandSelector` and must
### Special Event Quests
- `SuppressRiotByForceQuest` - Suppress a riot by force
- `FightBeastsAloneQuest` - Fight beasts alone
- `StartBlizzardQuest` - Start a blizzard in a province
- `StartDroughtQuest` - Start a drought in a province
- `ApprehendOutlawQuest` - Apprehend an outlaw hero
### Miscellaneous
@@ -131,5 +136,6 @@ The AI prioritizes quests in the order they appear in `FulfillQuestsCommandSelec
18. MobilizeProvinces
19. SendSupplies
20. StartEpidemic
21. SwearBrotherhood
22. Alliance
21. ControlWeather (StartBlizzard/StartDrought)
22. SwearBrotherhood
23. Alliance
@@ -318,6 +318,7 @@ scala_library(
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers/quest_command_selectors:alliance_quest_command_chooser",
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers/quest_command_selectors:alms_across_realm_quest_command_chooser",
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers/quest_command_selectors:alms_to_province_quest_command_chooser",
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers/quest_command_selectors:control_weather_quest_command_chooser",
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers/quest_command_selectors:develop_provinces_quest_command_chooser",
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers/quest_command_selectors:dismiss_specific_vassal_command_chooser",
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers/quest_command_selectors:execute_prisoner_quest_command_chooser",
@@ -5,6 +5,7 @@ import net.eagle0.eagle.library.util.command_choice_helpers.quest_command_select
AllianceQuestCommandChooser,
AlmsAcrossRealmQuestCommandChooser,
AlmsToProvinceQuestCommandChooser,
ControlWeatherQuestCommandChooser,
DevelopProvincesQuestCommandChooser,
DismissSpecificVassalCommandChooser,
ExecutePrisonerQuestCommandChooser,
@@ -55,6 +56,7 @@ object FulfillQuestsCommandSelector {
MobilizeProvincesQuestCommandChooser,
SendSuppliesQuestCommandChooser,
StartEpidemicQuestCommandChooser,
ControlWeatherQuestCommandChooser,
SwearBrotherhoodQuestCommandChooser,
AllianceQuestCommandChooser
)
@@ -73,6 +73,29 @@ scala_library(
],
)
scala_library(
name = "control_weather_quest_command_chooser",
srcs = ["ControlWeatherQuestCommandChooser.scala"],
visibility = [
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers:__subpackages__",
"//src/test/scala/net/eagle0/eagle/library/util/command_choice_helpers/quest_command_selectors:__pkg__",
],
exports = [
":quest_command_chooser",
],
deps = [
":quest_command_chooser",
":unaffiliated_hero_with_quest",
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
"//src/main/scala/net/eagle0/eagle/library/util:command_selection",
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
"//src/main/scala/net/eagle0/eagle/model/state/command/common",
"//src/main/scala/net/eagle0/eagle/model/state/command/selected",
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
"//src/main/scala/net/eagle0/eagle/model/state/quest",
],
)
scala_library(
name = "develop_provinces_quest_command_chooser",
srcs = ["DevelopProvincesQuestCommandChooser.scala"],
@@ -0,0 +1,57 @@
package net.eagle0.eagle.library.util.command_choice_helpers.quest_command_selectors
import net.eagle0.eagle.{FactionId, ProvinceId}
import net.eagle0.eagle.library.util.CommandSelection
import net.eagle0.eagle.model.state.command.available.AvailableCommand
import net.eagle0.eagle.model.state.command.available.AvailableCommand.ControlWeatherAvailable
import net.eagle0.eagle.model.state.command.common.ControlWeatherType
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.ControlWeatherSelected
import net.eagle0.eagle.model.state.game_state.GameState
import net.eagle0.eagle.model.state.quest.{StartBlizzardQuest, StartDroughtQuest}
object ControlWeatherQuestCommandChooser extends DeterministicQuestCommandChooser {
private def questTargets(
actingFactionId: FactionId,
gameState: GameState,
uhsWithQuests: Vector[UnaffiliatedHeroWithQuest]
): Vector[(ProvinceId, ControlWeatherType)] =
uhsWithQuests
.map(_.quest)
.collect {
case q: StartBlizzardQuest => (q.provinceId, ControlWeatherType.StartBlizzard)
case q: StartDroughtQuest => (q.provinceId, ControlWeatherType.StartDrought)
}
.filterNot {
case (pid, _) =>
gameState.provinces.get(pid).exists(_.rulingFactionId.contains(actingFactionId))
}
override def chosenDeterministicCommand(
actingFactionId: FactionId,
gameState: GameState,
availableCommands: Vector[AvailableCommand],
uhsWithQuests: Vector[UnaffiliatedHeroWithQuest]
): Option[CommandSelection] =
questTargets(actingFactionId, gameState, uhsWithQuests) match {
case Vector() => None
case targets =>
availableCommands.collectFirst { case cwa: ControlWeatherAvailable => cwa }.flatMap { controlWeather =>
targets.collectFirst {
case (provinceId, weatherType)
if controlWeather.options
.exists(opt => opt.provinceId == provinceId && opt.controlWeatherTypes.contains(weatherType)) =>
CommandSelection(
actingFactionId = actingFactionId,
actingProvinceId = controlWeather.actingProvinceId,
available = controlWeather,
selected = ControlWeatherSelected(
selectedType = weatherType,
selectedProvinceId = provinceId,
actingHeroId = controlWeather.availableHeroIds.head
),
reason = s"fulfill $weatherType quest"
)
}
}
}
}
@@ -18,12 +18,10 @@ object StartEpidemicQuestCommandChooser extends DeterministicQuestCommandChooser
val targetProvinceIds = uhsWithQuests
.map(_.quest)
.collect { case q: StartEpidemicQuest => q.provinceId }
.filterNot(pid => gameState.provinces.get(pid).exists(_.rulingFactionId.contains(actingFactionId)))
.toSet
if targetProvinceIds.isEmpty then return None
availableCommands.collect { case sea: StartEpidemicAvailable => sea }.flatMap { startEpidemicAvailable =>
// Find a target province that matches a quest and is in available options
startEpidemicAvailable.options
.find(opt => targetProvinceIds.contains(opt.targetProvinceId))
.map { matchingOption =>
@@ -69,6 +69,28 @@ scala_test(
],
)
scala_test(
name = "control_weather_quest_command_chooser_test",
srcs = ["ControlWeatherQuestCommandChooserTest.scala"],
deps = [
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
"//src/main/scala/net/eagle0/eagle/library/util:command_selection",
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers/quest_command_selectors:control_weather_quest_command_chooser",
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers/quest_command_selectors:unaffiliated_hero_with_quest",
"//src/main/scala/net/eagle0/eagle/model/state:round_phase",
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
"//src/main/scala/net/eagle0/eagle/model/state/command/common",
"//src/main/scala/net/eagle0/eagle/model/state/command/selected",
"//src/main/scala/net/eagle0/eagle/model/state/date",
"//src/main/scala/net/eagle0/eagle/model/state/faction/concrete",
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
"//src/main/scala/net/eagle0/eagle/model/state/hero/concrete",
"//src/main/scala/net/eagle0/eagle/model/state/province/concrete",
"//src/main/scala/net/eagle0/eagle/model/state/quest",
"//src/main/scala/net/eagle0/eagle/model/state/run_status",
],
)
scala_test(
name = "develop_provinces_quest_command_chooser_test",
srcs = ["DevelopProvincesQuestCommandChooserTest.scala"],
@@ -177,3 +199,24 @@ scala_test(
"//src/main/scala/net/eagle0/eagle/model/state/run_status",
],
)
scala_test(
name = "start_epidemic_quest_command_chooser_test",
srcs = ["StartEpidemicQuestCommandChooserTest.scala"],
deps = [
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
"//src/main/scala/net/eagle0/eagle/library/util:command_selection",
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers/quest_command_selectors:start_epidemic_quest_command_chooser",
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers/quest_command_selectors:unaffiliated_hero_with_quest",
"//src/main/scala/net/eagle0/eagle/model/state:round_phase",
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
"//src/main/scala/net/eagle0/eagle/model/state/command/selected",
"//src/main/scala/net/eagle0/eagle/model/state/date",
"//src/main/scala/net/eagle0/eagle/model/state/faction/concrete",
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
"//src/main/scala/net/eagle0/eagle/model/state/hero/concrete",
"//src/main/scala/net/eagle0/eagle/model/state/province/concrete",
"//src/main/scala/net/eagle0/eagle/model/state/quest",
"//src/main/scala/net/eagle0/eagle/model/state/run_status",
],
)
@@ -0,0 +1,219 @@
package net.eagle0.eagle.library.util.command_choice_helpers.quest_command_selectors
import net.eagle0.eagle.{FactionId, HeroId, ProvinceId}
import net.eagle0.eagle.model.state.{GameType, RoundPhase}
import net.eagle0.eagle.model.state.command.available.AvailableCommand.{ControlWeatherAvailable, TargetProvinceOptions}
import net.eagle0.eagle.model.state.command.common.ControlWeatherType
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.ControlWeatherSelected
import net.eagle0.eagle.model.state.date.Date
import net.eagle0.eagle.model.state.date.Date.Month.June
import net.eagle0.eagle.model.state.faction.concrete.FactionC
import net.eagle0.eagle.model.state.game_state.GameState
import net.eagle0.eagle.model.state.hero.concrete.HeroC
import net.eagle0.eagle.model.state.province.concrete.ProvinceC
import net.eagle0.eagle.model.state.quest.{ImproveAgricultureQuest, StartBlizzardQuest, StartDroughtQuest}
import net.eagle0.eagle.model.state.run_status.RunStatus
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import org.scalatest.Inside.inside
class ControlWeatherQuestCommandChooserTest extends AnyFlatSpec with Matchers {
private val actingFactionId: FactionId = 1
private val enemyFactionId: FactionId = 2
private val factionLeaderId: HeroId = 10
private val heroId: HeroId = 20
private val ownProvinceId: ProvinceId = 100
private val enemyProvinceId: ProvinceId = 200
private val gameState: GameState = {
val factionLeader = HeroC(id = factionLeaderId, factionId = Some(actingFactionId))
val hero = HeroC(id = heroId, factionId = None)
val ownProvince = ProvinceC(
id = ownProvinceId,
rulingFactionId = Some(actingFactionId),
rulingFactionHeroIds = Vector(factionLeaderId)
)
val enemyProvince = ProvinceC(
id = enemyProvinceId,
rulingFactionId = Some(enemyFactionId)
)
val faction = FactionC(
id = actingFactionId,
factionHeadId = factionLeaderId,
name = "Test Faction",
leaderIds = Vector(factionLeaderId)
)
val enemyFaction = FactionC(
id = enemyFactionId,
factionHeadId = 99,
name = "Enemy Faction",
leaderIds = Vector(99)
)
GameState(
gameId = 1,
currentRoundId = 1,
currentPhase = RoundPhase.PlayerCommands,
currentDate = Some(Date(year = 1501, month = June)),
actionResultCount = 0,
provinces = Map(
ownProvinceId -> ownProvince,
enemyProvinceId -> enemyProvince
),
heroes = Map(factionLeaderId -> factionLeader, heroId -> hero),
battalions = Map.empty,
destroyedBattalions = Map.empty,
factions = Map(actingFactionId -> faction, enemyFactionId -> enemyFaction),
factionCommandCounts = Map.empty,
killedHeroes = Map.empty,
destroyedFactions = Map.empty,
outstandingBattles = Vector.empty,
battleCounter = 0,
deferredNotifications = Vector.empty,
runStatus = RunStatus.Running,
victor = None,
battalionTypes = Vector.empty,
randomSeed = 1L,
chronicleEntries = Vector.empty,
gameType = GameType.Normal
)
}
private val controlWeatherAvailable = ControlWeatherAvailable(
options = Vector(
TargetProvinceOptions(
provinceId = enemyProvinceId,
controlWeatherTypes = Vector(ControlWeatherType.StartBlizzard, ControlWeatherType.StartDrought)
),
TargetProvinceOptions(
provinceId = ownProvinceId,
controlWeatherTypes = Vector(ControlWeatherType.StartBlizzard)
)
),
actingProvinceId = ownProvinceId,
availableHeroIds = Vector(factionLeaderId)
)
"ControlWeatherQuestCommandChooser" should "return a command for StartBlizzard quest on enemy province" in {
val result = ControlWeatherQuestCommandChooser.chosenDeterministicCommand(
actingFactionId = actingFactionId,
gameState = gameState,
availableCommands = Vector(controlWeatherAvailable),
uhsWithQuests = Vector(
UnaffiliatedHeroWithQuest(
pid = ownProvinceId,
heroId = heroId,
quest = StartBlizzardQuest(provinceId = enemyProvinceId)
)
)
)
result shouldBe defined
inside(result.get.selected) {
case selected: ControlWeatherSelected =>
selected.selectedType shouldBe ControlWeatherType.StartBlizzard
selected.selectedProvinceId shouldBe enemyProvinceId
}
}
it should "return a command for StartDrought quest on enemy province" in {
val result = ControlWeatherQuestCommandChooser.chosenDeterministicCommand(
actingFactionId = actingFactionId,
gameState = gameState,
availableCommands = Vector(controlWeatherAvailable),
uhsWithQuests = Vector(
UnaffiliatedHeroWithQuest(
pid = ownProvinceId,
heroId = heroId,
quest = StartDroughtQuest(provinceId = enemyProvinceId)
)
)
)
result shouldBe defined
inside(result.get.selected) {
case selected: ControlWeatherSelected =>
selected.selectedType shouldBe ControlWeatherType.StartDrought
selected.selectedProvinceId shouldBe enemyProvinceId
}
}
it should "return None when quest targets own province" in {
val result = ControlWeatherQuestCommandChooser.chosenDeterministicCommand(
actingFactionId = actingFactionId,
gameState = gameState,
availableCommands = Vector(controlWeatherAvailable),
uhsWithQuests = Vector(
UnaffiliatedHeroWithQuest(
pid = ownProvinceId,
heroId = heroId,
quest = StartBlizzardQuest(provinceId = ownProvinceId)
)
)
)
result shouldBe None
}
it should "return None when no weather quests exist" in {
val result = ControlWeatherQuestCommandChooser.chosenDeterministicCommand(
actingFactionId = actingFactionId,
gameState = gameState,
availableCommands = Vector(controlWeatherAvailable),
uhsWithQuests = Vector(
UnaffiliatedHeroWithQuest(
pid = ownProvinceId,
heroId = heroId,
quest = ImproveAgricultureQuest(provinceId = ownProvinceId, desiredValue = 50)
)
)
)
result shouldBe None
}
it should "return None when ControlWeatherAvailable is not in available commands" in {
val result = ControlWeatherQuestCommandChooser.chosenDeterministicCommand(
actingFactionId = actingFactionId,
gameState = gameState,
availableCommands = Vector.empty,
uhsWithQuests = Vector(
UnaffiliatedHeroWithQuest(
pid = ownProvinceId,
heroId = heroId,
quest = StartBlizzardQuest(provinceId = enemyProvinceId)
)
)
)
result shouldBe None
}
it should "return None when weather type is not available for the target province" in {
val limitedOptions = ControlWeatherAvailable(
options = Vector(
TargetProvinceOptions(
provinceId = enemyProvinceId,
controlWeatherTypes = Vector(ControlWeatherType.EndBlizzard) // only EndBlizzard, not StartBlizzard
)
),
actingProvinceId = ownProvinceId,
availableHeroIds = Vector(factionLeaderId)
)
val result = ControlWeatherQuestCommandChooser.chosenDeterministicCommand(
actingFactionId = actingFactionId,
gameState = gameState,
availableCommands = Vector(limitedOptions),
uhsWithQuests = Vector(
UnaffiliatedHeroWithQuest(
pid = ownProvinceId,
heroId = heroId,
quest = StartBlizzardQuest(provinceId = enemyProvinceId)
)
)
)
result shouldBe None
}
}
@@ -0,0 +1,166 @@
package net.eagle0.eagle.library.util.command_choice_helpers.quest_command_selectors
import net.eagle0.eagle.{FactionId, HeroId, ProvinceId}
import net.eagle0.eagle.model.state.{GameType, RoundPhase}
import net.eagle0.eagle.model.state.command.available.AvailableCommand.{StartEpidemicAvailable, StartEpidemicOptions}
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.StartEpidemicSelected
import net.eagle0.eagle.model.state.date.Date
import net.eagle0.eagle.model.state.date.Date.Month.June
import net.eagle0.eagle.model.state.faction.concrete.FactionC
import net.eagle0.eagle.model.state.game_state.GameState
import net.eagle0.eagle.model.state.hero.concrete.HeroC
import net.eagle0.eagle.model.state.province.concrete.ProvinceC
import net.eagle0.eagle.model.state.quest.{ImproveAgricultureQuest, StartEpidemicQuest}
import net.eagle0.eagle.model.state.run_status.RunStatus
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import org.scalatest.Inside.inside
class StartEpidemicQuestCommandChooserTest extends AnyFlatSpec with Matchers {
private val actingFactionId: FactionId = 1
private val enemyFactionId: FactionId = 2
private val factionLeaderId: HeroId = 10
private val heroId: HeroId = 20
private val ownProvinceId: ProvinceId = 100
private val enemyProvinceId: ProvinceId = 200
private val neutralProvinceId: ProvinceId = 300
private val gameState: GameState = {
val factionLeader = HeroC(id = factionLeaderId, factionId = Some(actingFactionId))
val hero = HeroC(id = heroId, factionId = None)
val ownProvince = ProvinceC(
id = ownProvinceId,
rulingFactionId = Some(actingFactionId),
rulingFactionHeroIds = Vector(factionLeaderId)
)
val enemyProvince = ProvinceC(
id = enemyProvinceId,
rulingFactionId = Some(enemyFactionId)
)
val neutralProvince = ProvinceC(
id = neutralProvinceId
)
val faction = FactionC(
id = actingFactionId,
factionHeadId = factionLeaderId,
name = "Test Faction",
leaderIds = Vector(factionLeaderId)
)
val enemyFaction = FactionC(
id = enemyFactionId,
factionHeadId = 99,
name = "Enemy Faction",
leaderIds = Vector(99)
)
GameState(
gameId = 1,
currentRoundId = 1,
currentPhase = RoundPhase.PlayerCommands,
currentDate = Some(Date(year = 1501, month = June)),
actionResultCount = 0,
provinces = Map(
ownProvinceId -> ownProvince,
enemyProvinceId -> enemyProvince,
neutralProvinceId -> neutralProvince
),
heroes = Map(factionLeaderId -> factionLeader, heroId -> hero),
battalions = Map.empty,
destroyedBattalions = Map.empty,
factions = Map(actingFactionId -> faction, enemyFactionId -> enemyFaction),
factionCommandCounts = Map.empty,
killedHeroes = Map.empty,
destroyedFactions = Map.empty,
outstandingBattles = Vector.empty,
battleCounter = 0,
deferredNotifications = Vector.empty,
runStatus = RunStatus.Running,
victor = None,
battalionTypes = Vector.empty,
randomSeed = 1L,
chronicleEntries = Vector.empty,
gameType = GameType.Normal
)
}
private val startEpidemicAvailable = StartEpidemicAvailable(
options = Vector(
StartEpidemicOptions(targetProvinceId = enemyProvinceId),
StartEpidemicOptions(targetProvinceId = ownProvinceId)
),
actingProvinceId = ownProvinceId,
availableHeroIds = Vector(factionLeaderId)
)
"StartEpidemicQuestCommandChooser" should "return a command when quest targets an enemy province" in {
val result = StartEpidemicQuestCommandChooser.chosenDeterministicCommand(
actingFactionId = actingFactionId,
gameState = gameState,
availableCommands = Vector(startEpidemicAvailable),
uhsWithQuests = Vector(
UnaffiliatedHeroWithQuest(
pid = ownProvinceId,
heroId = heroId,
quest = StartEpidemicQuest(provinceId = enemyProvinceId)
)
)
)
result shouldBe defined
inside(result.get.selected) {
case selected: StartEpidemicSelected =>
selected.selectedProvinceId shouldBe enemyProvinceId
}
}
it should "return None when quest targets own province" in {
val result = StartEpidemicQuestCommandChooser.chosenDeterministicCommand(
actingFactionId = actingFactionId,
gameState = gameState,
availableCommands = Vector(startEpidemicAvailable),
uhsWithQuests = Vector(
UnaffiliatedHeroWithQuest(
pid = ownProvinceId,
heroId = heroId,
quest = StartEpidemicQuest(provinceId = ownProvinceId)
)
)
)
result shouldBe None
}
it should "return None when no StartEpidemicQuest exists" in {
val result = StartEpidemicQuestCommandChooser.chosenDeterministicCommand(
actingFactionId = actingFactionId,
gameState = gameState,
availableCommands = Vector(startEpidemicAvailable),
uhsWithQuests = Vector(
UnaffiliatedHeroWithQuest(
pid = ownProvinceId,
heroId = heroId,
quest = ImproveAgricultureQuest(provinceId = ownProvinceId, desiredValue = 50)
)
)
)
result shouldBe None
}
it should "return None when StartEpidemicAvailable is not in available commands" in {
val result = StartEpidemicQuestCommandChooser.chosenDeterministicCommand(
actingFactionId = actingFactionId,
gameState = gameState,
availableCommands = Vector.empty,
uhsWithQuests = Vector(
UnaffiliatedHeroWithQuest(
pid = ownProvinceId,
heroId = heroId,
quest = StartEpidemicQuest(provinceId = enemyProvinceId)
)
)
)
result shouldBe None
}
}