mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-28 21:35:42 +00:00
Split feast spending quests by scope
This commit is contained in:
@@ -185,6 +185,10 @@ namespace eagle {
|
||||
case SealedValueOneofCase.StartDroughtQuest: return "Start Drought";
|
||||
case SealedValueOneofCase.StartEpidemicQuest: return "Start Epidemic";
|
||||
case SealedValueOneofCase.SpendOnFeastsQuest: return "Host Feasts";
|
||||
case SealedValueOneofCase.SpendOnFeastsInProvinceQuest:
|
||||
return "Host Feasts Locally";
|
||||
case SealedValueOneofCase.SpendOnFeastsAcrossRealmQuest:
|
||||
return "Host Feasts Across Realm";
|
||||
case SealedValueOneofCase.SendSuppliesQuest: return "Send Supplies";
|
||||
case SealedValueOneofCase.RestProvinceQuest: return "Rest Province";
|
||||
case SealedValueOneofCase.ReconProvincesQuest: return "Recon Provinces";
|
||||
@@ -327,4 +331,4 @@ namespace eagle {
|
||||
return template;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-1
@@ -433,6 +433,16 @@ namespace eagle {
|
||||
return $"Host feasts costing {details.TotalGold} gold ({quest.ComponentsFulfilled}/{quest.ComponentCount})";
|
||||
}
|
||||
|
||||
case SealedValueOneofCase.SpendOnFeastsInProvinceQuest: {
|
||||
var details = quest.Details.SpendOnFeastsInProvinceQuest;
|
||||
return $"Host feasts here costing {details.TotalGold} gold ({quest.ComponentsFulfilled}/{quest.ComponentCount})";
|
||||
}
|
||||
|
||||
case SealedValueOneofCase.SpendOnFeastsAcrossRealmQuest: {
|
||||
var details = quest.Details.SpendOnFeastsAcrossRealmQuest;
|
||||
return $"Host feasts across the realm costing {details.TotalGold} gold ({quest.ComponentsFulfilled}/{quest.ComponentCount})";
|
||||
}
|
||||
|
||||
case SealedValueOneofCase.SendSuppliesQuest: {
|
||||
var details = quest.Details.SendSuppliesQuest;
|
||||
var provinceName = model.Provinces[details.TargetProvinceId].Name;
|
||||
@@ -476,4 +486,4 @@ namespace eagle {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,8 @@ message QuestDetails {
|
||||
RepairDevastationQuest repair_devastation_quest = 45;
|
||||
ReconSpecificProvincesQuest recon_specific_provinces_quest = 46;
|
||||
StartDroughtQuest start_drought_quest = 47;
|
||||
SpendOnFeastsInProvinceQuest spend_on_feasts_in_province_quest = 48;
|
||||
SpendOnFeastsAcrossRealmQuest spend_on_feasts_across_realm_quest = 49;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +232,14 @@ message SpendOnFeastsQuest {
|
||||
int32 total_gold = 1;
|
||||
}
|
||||
|
||||
message SpendOnFeastsInProvinceQuest {
|
||||
int32 total_gold = 1;
|
||||
}
|
||||
|
||||
message SpendOnFeastsAcrossRealmQuest {
|
||||
int32 total_gold = 1;
|
||||
}
|
||||
|
||||
message SendSuppliesQuest {
|
||||
int32 target_province_id = 1;
|
||||
int32 total_food = 2;
|
||||
@@ -249,4 +259,4 @@ message RepairDevastationQuest {
|
||||
|
||||
message ReconSpecificProvincesQuest {
|
||||
repeated int32 target_province_ids = 1;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -248,7 +248,7 @@ case class CheckForFulfilledQuestsAction(
|
||||
case _: StartEpidemicQuest =>
|
||||
false // action quest - fulfilled in ControlWeatherCommand
|
||||
// Note: WinBattlesQuest is handled by ComponentQuest case above
|
||||
// Note: SpendOnFeastsQuest, SendSuppliesQuest, RestProvinceQuest,
|
||||
// Note: feast-spending quests, SendSuppliesQuest, RestProvinceQuest,
|
||||
// ReconProvincesQuest, RepairDevastationQuest are ComponentQuests
|
||||
// Note: ReconSpecificProvincesQuest has special handling above
|
||||
case _: ApprehendOutlawQuest =>
|
||||
|
||||
@@ -216,6 +216,7 @@ class CommandFactory extends TCommandFactory {
|
||||
FeastCommand.make(
|
||||
actingFactionId = actingFactionId,
|
||||
province = province,
|
||||
factionProvinces = FactionUtils.provinces(actingFactionId, allProvinces(gameState)),
|
||||
rulingFactionHeroes = province.rulingFactionHeroIds
|
||||
.map(gameState.heroes),
|
||||
factionLeaderIds = faction.leaderIds,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package net.eagle0.eagle.library.actions.impl.command
|
||||
|
||||
import scala.annotation.unused
|
||||
|
||||
import net.eagle0.eagle.{FactionId, HeroId}
|
||||
import net.eagle0.eagle.library.actions.impl.common.ProtolessSimpleAction
|
||||
import net.eagle0.eagle.library.settings.{LoyaltyGainFromFeast, VigorGainFromFeast}
|
||||
@@ -9,14 +11,17 @@ import net.eagle0.eagle.model.action_result.changed_province.concrete.ChangedPro
|
||||
import net.eagle0.eagle.model.action_result.concrete.{ActionResultC, ChangedHeroC, StatDelta, StatNoChange}
|
||||
import net.eagle0.eagle.model.action_result.types.ActionResultType.Feast
|
||||
import net.eagle0.eagle.model.action_result.ActionResultT
|
||||
import net.eagle0.eagle.model.action_result.ActionResultT.ActionResultUpdater
|
||||
import net.eagle0.eagle.model.state.hero.HeroT
|
||||
import net.eagle0.eagle.model.state.province.ProvinceT
|
||||
import net.eagle0.eagle.model.state.quest.SpendOnFeastsQuest
|
||||
import net.eagle0.eagle.model.state.quest.{SpendOnFeastsAcrossRealmQuest, SpendOnFeastsInProvinceQuest}
|
||||
import net.eagle0.eagle.model.state.unaffiliated_hero.UnaffiliatedHeroT
|
||||
|
||||
object FeastCommand {
|
||||
def make(
|
||||
actingFactionId: FactionId,
|
||||
province: ProvinceT,
|
||||
factionProvinces: Vector[ProvinceT],
|
||||
rulingFactionHeroes: Vector[HeroT],
|
||||
factionLeaderIds: Vector[HeroId],
|
||||
goldCost: Int
|
||||
@@ -24,6 +29,7 @@ object FeastCommand {
|
||||
FeastCommand(
|
||||
factionId = actingFactionId,
|
||||
province = province,
|
||||
factionProvinces = factionProvinces,
|
||||
rulingFactionHeroes = rulingFactionHeroes,
|
||||
factionLeaderIds = factionLeaderIds,
|
||||
goldCost = goldCost
|
||||
@@ -32,6 +38,7 @@ object FeastCommand {
|
||||
private case class FeastCommand(
|
||||
factionId: FactionId,
|
||||
province: ProvinceT,
|
||||
factionProvinces: Vector[ProvinceT],
|
||||
rulingFactionHeroes: Vector[HeroT],
|
||||
factionLeaderIds: Vector[HeroId],
|
||||
goldCost: Int
|
||||
@@ -58,16 +65,37 @@ object FeastCommand {
|
||||
)
|
||||
)
|
||||
|
||||
private def feastInThisProvinceQuestCheck(
|
||||
uh: UnaffiliatedHeroT,
|
||||
@unused province: ProvinceT
|
||||
): Boolean =
|
||||
uh.quest.exists {
|
||||
case q: SpendOnFeastsInProvinceQuest => q.componentsFulfilled < q.componentCount
|
||||
case _ => false
|
||||
}
|
||||
|
||||
private def feastAcrossRealmQuestCheck(
|
||||
uh: UnaffiliatedHeroT,
|
||||
@unused province: ProvinceT
|
||||
): Boolean =
|
||||
uh.quest.exists {
|
||||
case q: SpendOnFeastsAcrossRealmQuest => q.componentsFulfilled < q.componentCount
|
||||
case _ => false
|
||||
}
|
||||
|
||||
private def feastAcrossRealmCounterIncrementer: ActionResultUpdater =
|
||||
QuestFulfillmentUtils.withCountersIncremented(
|
||||
provinces = factionProvinces,
|
||||
incrementAmount = goldCost,
|
||||
check = feastAcrossRealmQuestCheck
|
||||
)
|
||||
|
||||
private def changedProvinces: Vector[ChangedProvinceC] = {
|
||||
// Increment SpendOnFeastsQuest progress by goldCost for unaffiliated hero in this province
|
||||
// Increment in-province feast quest progress by goldCost for unaffiliated heroes in this province.
|
||||
val questProgressChange = QuestFulfillmentUtils.counterIncrementedCP(
|
||||
province = province,
|
||||
incrementAmount = goldCost,
|
||||
check = (uh, _) =>
|
||||
uh.quest.exists {
|
||||
case q: SpendOnFeastsQuest => q.componentsFulfilled < q.componentCount
|
||||
case _ => false
|
||||
}
|
||||
check = feastInThisProvinceQuestCheck
|
||||
)
|
||||
|
||||
questProgressChange match {
|
||||
@@ -103,7 +131,7 @@ object FeastCommand {
|
||||
provinceIdActed = Some(province.id),
|
||||
changedHeroes = changedHeroes,
|
||||
changedProvinces = changedProvinces
|
||||
)
|
||||
).update(feastAcrossRealmCounterIncrementer)
|
||||
|
||||
private def optionalVal(value: Double): Option[Double] =
|
||||
if value == 0 then None
|
||||
|
||||
+7
-2
@@ -332,9 +332,14 @@ case class DivineMessagePromptGenerator(
|
||||
s"$divinedHeroName wants to see a magical drought unleashed upon ${targetProvince.name}."
|
||||
)
|
||||
|
||||
case SpendOnFeastsQuest(_, _, totalGold) =>
|
||||
case SpendOnFeastsInProvinceQuest(_, _, totalGold) =>
|
||||
TextGenerationSuccess(
|
||||
s"$divinedHeroName wants $actingHeroName to host lavish feasts spending a total of $totalGold gold."
|
||||
s"$divinedHeroName wants $actingHeroName to host lavish feasts in this province, spending a total of $totalGold gold."
|
||||
)
|
||||
|
||||
case SpendOnFeastsAcrossRealmQuest(_, _, totalGold) =>
|
||||
TextGenerationSuccess(
|
||||
s"$divinedHeroName wants $actingHeroName to host lavish feasts across the realm, spending a total of $totalGold gold."
|
||||
)
|
||||
|
||||
case SendSuppliesQuest(_, _, targetProvinceId, totalFood) =>
|
||||
|
||||
+7
-2
@@ -333,10 +333,15 @@ object QuestEndedGeneratorUtilities {
|
||||
unaffiliatedHeroName <- unaffiliatedHeroNameResult
|
||||
} yield s"$unaffiliatedHeroName wanted to see a magical drought unleashed upon ${targetProvince.name}."
|
||||
|
||||
case SpendOnFeastsQuest(_, _, totalGold) =>
|
||||
case SpendOnFeastsInProvinceQuest(_, _, totalGold) =>
|
||||
for {
|
||||
unaffiliatedHeroName <- unaffiliatedHeroNameResult
|
||||
} yield s"$unaffiliatedHeroName wanted ${faction.name} to host lavish feasts spending a total of $totalGold gold."
|
||||
} yield s"$unaffiliatedHeroName wanted ${faction.name} to host lavish feasts in this province, spending a total of $totalGold gold."
|
||||
|
||||
case SpendOnFeastsAcrossRealmQuest(_, _, totalGold) =>
|
||||
for {
|
||||
unaffiliatedHeroName <- unaffiliatedHeroNameResult
|
||||
} yield s"$unaffiliatedHeroName wanted ${faction.name} to host lavish feasts across the realm, spending a total of $totalGold gold."
|
||||
|
||||
case SendSuppliesQuest(_, _, targetProvinceId, totalFood) =>
|
||||
val targetProvince = gameState.provinces(targetProvinceId)
|
||||
|
||||
+32
-13
@@ -5,7 +5,7 @@ import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.FeastAvailable
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.FeastSelected
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.quest.SpendOnFeastsQuest
|
||||
import net.eagle0.eagle.model.state.quest.{SpendOnFeastsAcrossRealmQuest, SpendOnFeastsInProvinceQuest}
|
||||
import net.eagle0.eagle.FactionId
|
||||
|
||||
object SpendOnFeastsQuestCommandChooser extends DeterministicQuestCommandChooser {
|
||||
@@ -15,20 +15,39 @@ object SpendOnFeastsQuestCommandChooser extends DeterministicQuestCommandChooser
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
uhsWithQuests: Vector[UnaffiliatedHeroWithQuest]
|
||||
): Option[CommandSelection] = {
|
||||
val hasSpendOnFeastsQuest = uhsWithQuests
|
||||
.map(_.quest)
|
||||
.exists(_.isInstanceOf[SpendOnFeastsQuest])
|
||||
val feastCommands = availableCommands.collect { case fa: FeastAvailable => fa }
|
||||
|
||||
if !hasSpendOnFeastsQuest then return None
|
||||
val inProvinceSelection = uhsWithQuests.collect {
|
||||
case UnaffiliatedHeroWithQuest(pid, _, _: SpendOnFeastsInProvinceQuest) => pid
|
||||
}
|
||||
.flatMap(pid => feastCommands.find(_.actingProvinceId == pid))
|
||||
.headOption
|
||||
.map { feastAvailable =>
|
||||
CommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = feastAvailable.actingProvinceId,
|
||||
available = feastAvailable,
|
||||
selected = FeastSelected,
|
||||
reason = "fulfill SpendOnFeastsInProvince quest"
|
||||
)
|
||||
}
|
||||
|
||||
availableCommands.collectFirst { case fa: FeastAvailable => fa }.map { feastAvailable =>
|
||||
CommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = feastAvailable.actingProvinceId,
|
||||
available = feastAvailable,
|
||||
selected = FeastSelected,
|
||||
reason = "fulfill SpendOnFeasts quest"
|
||||
)
|
||||
inProvinceSelection.orElse {
|
||||
val hasAcrossRealmQuest = uhsWithQuests
|
||||
.exists(_.quest.isInstanceOf[SpendOnFeastsAcrossRealmQuest])
|
||||
|
||||
Option
|
||||
.when(hasAcrossRealmQuest)(feastCommands)
|
||||
.flatMap(_.maxByOption(_.goldCost))
|
||||
.map { feastAvailable =>
|
||||
CommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = feastAvailable.actingProvinceId,
|
||||
available = feastAvailable,
|
||||
selected = FeastSelected,
|
||||
reason = "fulfill SpendOnFeastsAcrossRealm quest"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+33
-5
@@ -63,7 +63,8 @@ import net.eagle0.eagle.model.state.quest.{
|
||||
ReturnPrisonerQuest,
|
||||
SendSuppliesQuest,
|
||||
SpecificExpansionQuest,
|
||||
SpendOnFeastsQuest,
|
||||
SpendOnFeastsAcrossRealmQuest,
|
||||
SpendOnFeastsInProvinceQuest,
|
||||
StartBlizzardQuest,
|
||||
StartDroughtQuest,
|
||||
StartEpidemicQuest,
|
||||
@@ -166,7 +167,8 @@ object QuestCreationUtils {
|
||||
restProvinceQuests,
|
||||
reconProvincesQuests(heroes),
|
||||
repairDevastationQuests,
|
||||
spendOnFeastsQuests,
|
||||
spendOnFeastsInProvinceQuests,
|
||||
spendOnFeastsAcrossRealmQuests,
|
||||
reconSpecificProvincesQuests(heroes)
|
||||
)
|
||||
) {
|
||||
@@ -1135,16 +1137,16 @@ object QuestCreationUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private def spendOnFeastsQuests(
|
||||
private def spendOnFeastsInProvinceQuests(
|
||||
@unused province: ProvinceT,
|
||||
@unused allProvinces: Vector[ProvinceT],
|
||||
@unused factions: Vector[FactionT],
|
||||
@unused battalions: Vector[BattalionT],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Vector[Quest]] =
|
||||
functionalRandom.nextIntInclusive(500, 1000).map { totalGold =>
|
||||
functionalRandom.nextIntInclusive(333, 667).map { totalGold =>
|
||||
Vector(
|
||||
SpendOnFeastsQuest(
|
||||
SpendOnFeastsInProvinceQuest(
|
||||
componentCount = totalGold,
|
||||
componentsFulfilled = 0,
|
||||
totalGold = totalGold
|
||||
@@ -1152,6 +1154,32 @@ object QuestCreationUtils {
|
||||
)
|
||||
}
|
||||
|
||||
private def spendOnFeastsAcrossRealmQuests(
|
||||
province: ProvinceT,
|
||||
allProvinces: Vector[ProvinceT],
|
||||
@unused factions: Vector[FactionT],
|
||||
@unused battalions: Vector[BattalionT],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Vector[Quest]] = FactionUtils
|
||||
.provinces(province.getRulingFactionId, allProvinces)
|
||||
.size match {
|
||||
case 0 | 1 => RandomState(Vector(), functionalRandom)
|
||||
case provinceCount =>
|
||||
functionalRandom.nextIntInclusive(750, 1250).map { goldAmountPerProvince =>
|
||||
val totalGold = (Math.pow(
|
||||
provinceCount,
|
||||
GiftProvinceCountExponent.doubleValue
|
||||
) * goldAmountPerProvince).ceil.toInt
|
||||
Vector(
|
||||
SpendOnFeastsAcrossRealmQuest(
|
||||
componentCount = totalGold,
|
||||
componentsFulfilled = 0,
|
||||
totalGold = totalGold
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private def reconSpecificProvincesQuests(heroes: Vector[HeroT]): QuestCreator =
|
||||
(
|
||||
province: ProvinceT,
|
||||
|
||||
@@ -35,6 +35,8 @@ import net.eagle0.eagle.common.unaffiliated_hero_quest.{
|
||||
ReturnPrisonerQuest as ReturnPrisonerQuestProto,
|
||||
SendSuppliesQuest as SendSuppliesQuestProto,
|
||||
SpecificExpansionQuest as SpecificExpansionQuestProto,
|
||||
SpendOnFeastsAcrossRealmQuest as SpendOnFeastsAcrossRealmQuestProto,
|
||||
SpendOnFeastsInProvinceQuest as SpendOnFeastsInProvinceQuestProto,
|
||||
SpendOnFeastsQuest as SpendOnFeastsQuestProto,
|
||||
StartBlizzardQuest as StartBlizzardQuestProto,
|
||||
StartDroughtQuest as StartDroughtQuestProto,
|
||||
@@ -221,9 +223,15 @@ object QuestConverter {
|
||||
QuestProto(details = StartEpidemicQuestProto(q.provinceId))
|
||||
case q: StartDroughtQuest =>
|
||||
QuestProto(details = StartDroughtQuestProto(q.provinceId))
|
||||
case q: SpendOnFeastsQuest =>
|
||||
case q: SpendOnFeastsInProvinceQuest =>
|
||||
QuestProto(
|
||||
details = SpendOnFeastsQuestProto(q.totalGold),
|
||||
details = SpendOnFeastsInProvinceQuestProto(q.totalGold),
|
||||
componentCount = q.componentCount,
|
||||
componentsFulfilled = q.componentsFulfilled
|
||||
)
|
||||
case q: SpendOnFeastsAcrossRealmQuest =>
|
||||
QuestProto(
|
||||
details = SpendOnFeastsAcrossRealmQuestProto(q.totalGold),
|
||||
componentCount = q.componentCount,
|
||||
componentsFulfilled = q.componentsFulfilled
|
||||
)
|
||||
@@ -456,7 +464,25 @@ object QuestConverter {
|
||||
case StartDroughtQuestProto(provinceId, _ /* unknownFieldSet */ ) =>
|
||||
StartDroughtQuest(provinceId)
|
||||
case SpendOnFeastsQuestProto(totalGold, _ /* unknownFieldSet */ ) =>
|
||||
SpendOnFeastsQuest(
|
||||
SpendOnFeastsInProvinceQuest(
|
||||
componentCount = questProto.componentCount,
|
||||
componentsFulfilled = questProto.componentsFulfilled,
|
||||
totalGold = totalGold
|
||||
)
|
||||
case SpendOnFeastsInProvinceQuestProto(
|
||||
totalGold,
|
||||
_ /* unknownFieldSet */
|
||||
) =>
|
||||
SpendOnFeastsInProvinceQuest(
|
||||
componentCount = questProto.componentCount,
|
||||
componentsFulfilled = questProto.componentsFulfilled,
|
||||
totalGold = totalGold
|
||||
)
|
||||
case SpendOnFeastsAcrossRealmQuestProto(
|
||||
totalGold,
|
||||
_ /* unknownFieldSet */
|
||||
) =>
|
||||
SpendOnFeastsAcrossRealmQuest(
|
||||
componentCount = questProto.componentCount,
|
||||
componentsFulfilled = questProto.componentsFulfilled,
|
||||
totalGold = totalGold
|
||||
|
||||
@@ -175,7 +175,16 @@ case class StartEpidemicQuest(provinceId: ProvinceId) extends Quest
|
||||
|
||||
case class StartDroughtQuest(provinceId: ProvinceId) extends Quest
|
||||
|
||||
case class SpendOnFeastsQuest(
|
||||
case class SpendOnFeastsInProvinceQuest(
|
||||
override val componentCount: Int,
|
||||
override val componentsFulfilled: Int,
|
||||
totalGold: Int
|
||||
) extends ComponentQuest {
|
||||
override def withComponentsFulfilled(componentsFulfilled: Int): Quest =
|
||||
this.copy(componentsFulfilled = componentsFulfilled)
|
||||
}
|
||||
|
||||
case class SpendOnFeastsAcrossRealmQuest(
|
||||
override val componentCount: Int,
|
||||
override val componentsFulfilled: Int,
|
||||
totalGold: Int
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ class AvailableFeastCommandFactoryTest extends AnyFlatSpec with Matchers with Be
|
||||
}
|
||||
|
||||
"availableCommand" should "be available even if everybody has maxed loyalty and vigor" in {
|
||||
// Feast is available as long as there's enough gold, so players can complete SpendOnFeastsQuest
|
||||
// Feast is available as long as there's enough gold, so players can complete feast-spending quests.
|
||||
val gameState = GameState(
|
||||
gameId = 0,
|
||||
currentRoundId = 0,
|
||||
|
||||
@@ -279,6 +279,8 @@ scala_test(
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result/types",
|
||||
"//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/unaffiliated_hero/concrete",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -6,6 +6,9 @@ import net.eagle0.eagle.model.action_result.concrete.{ChangedHeroC, StatDelta, S
|
||||
import net.eagle0.eagle.model.action_result.types.ActionResultType.Feast
|
||||
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.{SpendOnFeastsAcrossRealmQuest, SpendOnFeastsInProvinceQuest}
|
||||
import net.eagle0.eagle.model.state.unaffiliated_hero.{RecruitmentInfo, UnaffiliatedHeroType}
|
||||
import net.eagle0.eagle.model.state.unaffiliated_hero.concrete.UnaffiliatedHeroC
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.BeforeAndAfterEach
|
||||
@@ -66,6 +69,7 @@ class FeastCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach
|
||||
.make(
|
||||
actingFactionId = actingFactionId,
|
||||
province = province,
|
||||
factionProvinces = Vector(province),
|
||||
rulingFactionHeroes = Vector(normalHero, fullVigorHero, fullLoyaltyHero),
|
||||
factionLeaderIds = Vector(7),
|
||||
goldCost = 44
|
||||
@@ -83,6 +87,7 @@ class FeastCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach
|
||||
.make(
|
||||
actingFactionId = actingFactionId,
|
||||
province = province,
|
||||
factionProvinces = Vector(province),
|
||||
rulingFactionHeroes = Vector(normalHero, fullVigorHero, fullLoyaltyHero),
|
||||
factionLeaderIds = Vector(7),
|
||||
goldCost = 44
|
||||
@@ -101,6 +106,7 @@ class FeastCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach
|
||||
.make(
|
||||
actingFactionId = actingFactionId,
|
||||
province = province,
|
||||
factionProvinces = Vector(province),
|
||||
rulingFactionHeroes = Vector(normalHero, fullVigorHero, fullLoyaltyHero),
|
||||
factionLeaderIds = Vector(7),
|
||||
goldCost = 100
|
||||
@@ -119,6 +125,7 @@ class FeastCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach
|
||||
.make(
|
||||
actingFactionId = actingFactionId,
|
||||
province = province,
|
||||
factionProvinces = Vector(province),
|
||||
rulingFactionHeroes = Vector(normalHero, fullVigorHero, fullLoyaltyHero),
|
||||
factionLeaderIds = Vector(7),
|
||||
goldCost = 44
|
||||
@@ -140,6 +147,7 @@ class FeastCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach
|
||||
.make(
|
||||
actingFactionId = actingFactionId,
|
||||
province = province,
|
||||
factionProvinces = Vector(province),
|
||||
rulingFactionHeroes = Vector(normalHero, fullVigorHero, fullLoyaltyHero),
|
||||
factionLeaderIds = Vector(7),
|
||||
goldCost = 44
|
||||
@@ -157,6 +165,7 @@ class FeastCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach
|
||||
.make(
|
||||
actingFactionId = actingFactionId,
|
||||
province = province,
|
||||
factionProvinces = Vector(province),
|
||||
rulingFactionHeroes = Vector(normalHero, fullVigorHero, fullLoyaltyHero),
|
||||
factionLeaderIds = Vector(7),
|
||||
goldCost = 44
|
||||
@@ -178,6 +187,7 @@ class FeastCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach
|
||||
.make(
|
||||
actingFactionId = actingFactionId,
|
||||
province = province,
|
||||
factionProvinces = Vector(province),
|
||||
rulingFactionHeroes = Vector(normalHero, fullVigorHero, fullLoyaltyHero),
|
||||
factionLeaderIds = Vector(7),
|
||||
goldCost = 44
|
||||
@@ -195,6 +205,7 @@ class FeastCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach
|
||||
.make(
|
||||
actingFactionId = actingFactionId,
|
||||
province = province,
|
||||
factionProvinces = Vector(province),
|
||||
rulingFactionHeroes = Vector(normalHero, fullVigorHero, fullLoyaltyHero),
|
||||
factionLeaderIds = Vector(7),
|
||||
goldCost = 44
|
||||
@@ -203,4 +214,84 @@ class FeastCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach
|
||||
|
||||
result.changedHeroes.find(_.heroId == allFullHero.id) shouldBe None
|
||||
}
|
||||
|
||||
it should "increment in-province feast quest progress only in the feast province" in {
|
||||
val questHero = UnaffiliatedHeroC(
|
||||
heroId = 90,
|
||||
unaffiliatedHeroType = UnaffiliatedHeroType.Traveler,
|
||||
recruitmentInfo = RecruitmentInfo.HasQuest(
|
||||
SpendOnFeastsInProvinceQuest(
|
||||
componentCount = 400,
|
||||
componentsFulfilled = 120,
|
||||
totalGold = 400
|
||||
)
|
||||
)
|
||||
)
|
||||
val provinceWithQuest = province.copy(unaffiliatedHeroes = Vector(questHero))
|
||||
|
||||
val result = FeastCommand
|
||||
.make(
|
||||
actingFactionId = actingFactionId,
|
||||
province = provinceWithQuest,
|
||||
factionProvinces = Vector(provinceWithQuest),
|
||||
rulingFactionHeroes = Vector(normalHero, fullVigorHero, fullLoyaltyHero),
|
||||
factionLeaderIds = Vector(7),
|
||||
goldCost = 44
|
||||
)
|
||||
.immediateExecute
|
||||
|
||||
result.changedProvinces.collect { case cp: ChangedProvinceC => cp }
|
||||
.flatMap(_.changedUnaffiliatedHeroes)
|
||||
.find(_.heroId == questHero.heroId)
|
||||
.flatMap(_.quest) shouldBe Some(
|
||||
SpendOnFeastsInProvinceQuest(
|
||||
componentCount = 400,
|
||||
componentsFulfilled = 164,
|
||||
totalGold = 400
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
it should "increment across-realm feast quest progress in any faction province" in {
|
||||
val questHero = UnaffiliatedHeroC(
|
||||
heroId = 91,
|
||||
unaffiliatedHeroType = UnaffiliatedHeroType.Traveler,
|
||||
recruitmentInfo = RecruitmentInfo.HasQuest(
|
||||
SpendOnFeastsAcrossRealmQuest(
|
||||
componentCount = 900,
|
||||
componentsFulfilled = 250,
|
||||
totalGold = 900
|
||||
)
|
||||
)
|
||||
)
|
||||
val otherProvince = ProvinceC(
|
||||
id = 13,
|
||||
rulingFactionId = Some(3),
|
||||
rulingHeroId = Some(10),
|
||||
rulingFactionHeroIds = Vector(10),
|
||||
unaffiliatedHeroes = Vector(questHero)
|
||||
)
|
||||
|
||||
val result = FeastCommand
|
||||
.make(
|
||||
actingFactionId = actingFactionId,
|
||||
province = province,
|
||||
factionProvinces = Vector(province, otherProvince),
|
||||
rulingFactionHeroes = Vector(normalHero, fullVigorHero, fullLoyaltyHero),
|
||||
factionLeaderIds = Vector(7),
|
||||
goldCost = 44
|
||||
)
|
||||
.immediateExecute
|
||||
|
||||
result.changedProvinces.collect { case cp: ChangedProvinceC => cp }
|
||||
.flatMap(_.changedUnaffiliatedHeroes)
|
||||
.find(_.heroId == questHero.heroId)
|
||||
.flatMap(_.quest) shouldBe Some(
|
||||
SpendOnFeastsAcrossRealmQuest(
|
||||
componentCount = 900,
|
||||
componentsFulfilled = 294,
|
||||
totalGold = 900
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+78
@@ -47,6 +47,8 @@ import net.eagle0.eagle.model.state.quest.{
|
||||
ReleasePrisonerQuest,
|
||||
ReturnPrisonerQuest,
|
||||
SpecificExpansionQuest,
|
||||
SpendOnFeastsAcrossRealmQuest,
|
||||
SpendOnFeastsInProvinceQuest,
|
||||
TruceCountQuest,
|
||||
TruceWithFactionQuest,
|
||||
UpgradeBattalionQuest,
|
||||
@@ -1138,6 +1140,82 @@ class QuestCreationUtilsTest extends AnyFlatSpec with Matchers with BeforeAndAft
|
||||
}
|
||||
}
|
||||
|
||||
behavior of "spend on feasts in province quests"
|
||||
|
||||
it should "include a spend on feasts in province quest for about two thirds the old cost" in {
|
||||
val quests = QuestCreationUtils
|
||||
.availableQuests(
|
||||
province = province,
|
||||
allProvinces = allProvinces,
|
||||
factions = factions,
|
||||
battalions = Vector(),
|
||||
heroes = Vector(),
|
||||
functionalRandom = new JankyRandom(new Random())
|
||||
)
|
||||
.newValue
|
||||
|
||||
forExactly(1, quests) { quest =>
|
||||
inside(quest) {
|
||||
case SpendOnFeastsInProvinceQuest(count, fulfilled, totalGold) =>
|
||||
count shouldBe totalGold
|
||||
fulfilled shouldBe 0
|
||||
totalGold should be >= 333
|
||||
totalGold should be <= 667
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
behavior of "spend on feasts across realm quests"
|
||||
|
||||
it should "not include a spend on feasts across realm quest if the player has only one province" in {
|
||||
val quests = QuestCreationUtils
|
||||
.availableQuests(
|
||||
province = province,
|
||||
allProvinces = allProvinces,
|
||||
factions = factions,
|
||||
battalions = Vector(),
|
||||
heroes = Vector(),
|
||||
functionalRandom = new JankyRandom(new Random())
|
||||
)
|
||||
.newValue
|
||||
|
||||
forAll(quests) { quest =>
|
||||
quest should not matchPattern {
|
||||
case SpendOnFeastsAcrossRealmQuest(_, _, _) =>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it should "include a more expensive spend on feasts across realm quest if the player has 2 provinces" in {
|
||||
val quests = QuestCreationUtils
|
||||
.availableQuests(
|
||||
province = province,
|
||||
allProvinces = Vector(
|
||||
province,
|
||||
immediate1,
|
||||
immediate2,
|
||||
twoAway.withRulingFactionId(fid),
|
||||
threeAway,
|
||||
fourAway
|
||||
),
|
||||
factions = factions,
|
||||
battalions = Vector(),
|
||||
heroes = Vector(),
|
||||
functionalRandom = new JankyRandom(new Random())
|
||||
)
|
||||
.newValue
|
||||
|
||||
forExactly(1, quests) { quest =>
|
||||
inside(quest) {
|
||||
case SpendOnFeastsAcrossRealmQuest(count, fulfilled, totalGold) =>
|
||||
count shouldBe totalGold
|
||||
fulfilled shouldBe 0
|
||||
totalGold should be >= (750 * Math.pow(2, 0.5)).ceil.toInt
|
||||
totalGold should be <= (1250 * Math.pow(2, 0.5)).ceil.toInt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
behavior of "available manage prisoner quests"
|
||||
|
||||
it should "include execute prisoner quests for any prisoners" in {
|
||||
|
||||
Reference in New Issue
Block a user