Compare commits

...
Author SHA1 Message Date
adminandClaude Opus 4.5 3c92ef3ac0 Convert battle request and conquest actions to use Scala types
Convert three RoundPhaseAdvancer actions to accept Scala GameState instead of
individual proto-converted fields:
- PerformUncontestedConquestAction
- EndAttackDecisionPhaseAction
- RequestBattlesAction

Each action now extracts the fields it needs internally, simplifying the call
sites in RoundPhaseAdvancer.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 07:53:05 -08:00
9 changed files with 217 additions and 201 deletions
@@ -225,25 +225,7 @@ object RoundPhaseAdvancer {
actionResultProtoApplier.applyActionResults(
currentState,
PerformUncontestedConquestAction(
gameId = currentState.gameId,
currentRoundId = currentState.currentRoundId,
currentDate = DateConverter.fromProto(currentState.currentDate),
provinces = currentState.provinces.values
.map(ProvinceConverter.fromProto)
.map(p => p.id -> p)
.toMap,
factions = currentState.factions.values
.map(FactionConverter.fromProto)
.map(f => f.id -> f)
.toMap,
heroes = currentState.heroes.values
.map(HeroConverter.fromProto)
.map(h => h.id -> h)
.toMap,
battalions = currentState.battalions.values
.map(BattalionConverter.fromProto)
.map(b => (b.id, b))
.toMap
GameStateConverter.fromProto(currentState)
).results
.map(ActionResultProtoConverter.toProto)
)
@@ -258,12 +240,7 @@ object RoundPhaseAdvancer {
actionResultProtoApplier.applyActionResults(
currentState,
EndAttackDecisionPhaseAction(
gameId = currentState.gameId,
currentRoundId = currentState.currentRoundId,
currentDate = DateConverter.fromProto(currentState.currentDate),
provinces = currentState.provinces.values
.map(ProvinceConverter.fromProto)
.toVector
GameStateConverter.fromProto(currentState)
).results.map(ActionResultProtoConverter.toProto)
)
}
@@ -299,24 +276,7 @@ object RoundPhaseAdvancer {
case BATTLE_REQUEST =>
val requestBattlesAction = RequestBattlesAction(
gameId = currentState.gameId,
currentRoundId = currentState.currentRoundId,
currentDate = DateConverter.fromProto(currentState.currentDate),
battleCounter = currentState.battleCounter,
heroes = currentState.heroes.view.mapValues(HeroConverter.fromProto).toMap,
battalions = currentState.battalions.view
.mapValues(BattalionConverter.fromProto)
.toMap,
provinces = currentState.provinces.view
.mapValues(ProvinceConverter.fromProto)
.toMap,
factions = currentState.factions.view
.mapValues(FactionConverter.fromProto)
.toMap,
battalionTypes = currentState.battalionTypes.map { bt =>
val converted = BattalionTypeConverter.fromProto(bt)
converted.typeId -> converted
}.toMap
GameStateConverter.fromProto(currentState)
)
val requestResults = actionResultProtoApplier.applyActionResults(
currentState,
@@ -265,6 +265,7 @@ scala_library(
"//src/main/scala/net/eagle0/eagle/model/action_result/types:end_attack_decision_phase_result_type",
"//src/main/scala/net/eagle0/eagle/model/state:round_phase",
"//src/main/scala/net/eagle0/eagle/model/state/date",
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
"//src/main/scala/net/eagle0/eagle/model/state/hero:gender",
"//src/main/scala/net/eagle0/eagle/model/state/province",
"//src/main/scala/net/eagle0/eagle/model/state/quest",
@@ -1162,9 +1163,9 @@ scala_library(
"//src/main/scala/net/eagle0/eagle/model/state:army",
"//src/main/scala/net/eagle0/eagle/model/state:round_phase",
"//src/main/scala/net/eagle0/eagle/model/state/battalion",
"//src/main/scala/net/eagle0/eagle/model/state/battalion/concrete",
"//src/main/scala/net/eagle0/eagle/model/state/date",
"//src/main/scala/net/eagle0/eagle/model/state/faction",
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
"//src/main/scala/net/eagle0/eagle/model/state/hero",
"//src/main/scala/net/eagle0/eagle/model/state/hero:gender",
"//src/main/scala/net/eagle0/eagle/model/state/hero/concrete",
@@ -1697,6 +1698,7 @@ scala_library(
"//src/main/scala/net/eagle0/eagle/model/state/battalion",
"//src/main/scala/net/eagle0/eagle/model/state/date",
"//src/main/scala/net/eagle0/eagle/model/state/faction",
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
"//src/main/scala/net/eagle0/eagle/model/state/hero",
"//src/main/scala/net/eagle0/eagle/model/state/hero:gender",
"//src/main/scala/net/eagle0/eagle/model/state/province",
@@ -1,23 +1,23 @@
package net.eagle0.eagle.library.actions.impl.action
import net.eagle0.eagle.{GameId, RoundId}
import net.eagle0.eagle.library.actions.impl.common.ProtolessSequentialResultsAction
import net.eagle0.eagle.library.util.quest_fulfillment.QuestFulfillmentUtils
import net.eagle0.eagle.model.action_result.concrete.ActionResultC
import net.eagle0.eagle.model.action_result.types.EndAttackDecisionPhaseResultType
import net.eagle0.eagle.model.action_result.ActionResultT
import net.eagle0.eagle.model.state.date.Date
import net.eagle0.eagle.model.state.game_state.GameState
import net.eagle0.eagle.model.state.province.ProvinceT
import net.eagle0.eagle.model.state.quest.concrete.TruceWithFactionQuest
import net.eagle0.eagle.model.state.quest.QuestT
import net.eagle0.eagle.model.state.RoundPhase
case class EndAttackDecisionPhaseAction(
gameId: GameId,
currentRoundId: RoundId,
currentDate: Date,
provinces: Vector[ProvinceT]
gameState: GameState
) extends ProtolessSequentialResultsAction {
private val gameId = gameState.gameId
private val currentRoundId = gameState.currentRoundId
private val currentDate = gameState.currentDate.get
private val provinces = gameState.provinces.values.toVector
override def results: Vector[ActionResultT] =
WithdrawnArmiesReturnHomeAction(
@@ -1,6 +1,6 @@
package net.eagle0.eagle.library.actions.impl.action
import net.eagle0.eagle.{BattalionId, FactionId, GameId, HeroId, ProvinceId, RoundId}
import net.eagle0.eagle.{FactionId, ProvinceId}
import net.eagle0.eagle.library.actions.impl.common.ProtolessSequentialResultsAction
import net.eagle0.eagle.library.util.faction_utils.FactionUtils
import net.eagle0.eagle.library.util.EagleRequire.internalRequire
@@ -13,21 +13,19 @@ import net.eagle0.eagle.model.action_result.types.{
}
import net.eagle0.eagle.model.action_result.ActionResultT
import net.eagle0.eagle.model.state.{HostileArmyGroup, RoundPhase}
import net.eagle0.eagle.model.state.battalion.BattalionT
import net.eagle0.eagle.model.state.date.Date as DateT
import net.eagle0.eagle.model.state.faction.FactionT
import net.eagle0.eagle.model.state.hero.HeroT
import net.eagle0.eagle.model.state.game_state.GameState
import net.eagle0.eagle.model.state.province.ProvinceT
case class PerformUncontestedConquestAction(
gameId: GameId,
currentRoundId: RoundId,
currentDate: DateT,
provinces: Map[ProvinceId, ProvinceT],
factions: Map[FactionId, FactionT],
heroes: Map[HeroId, HeroT],
battalions: Map[BattalionId, BattalionT]
gameState: GameState
) extends ProtolessSequentialResultsAction {
private val gameId = gameState.gameId
private val currentRoundId = gameState.currentRoundId
private val currentDate = gameState.currentDate.get
private val provinces = gameState.provinces
private val factions = gameState.factions
private val heroes = gameState.heroes
private val battalions = gameState.battalions
private val endPhaseAction: ActionResultT = ActionResultC(
actionResultType = EndUncontestedConquestPhaseResultType,
@@ -2,7 +2,7 @@ package net.eagle0.eagle.library.actions.impl.action
import scala.util.hashing.MurmurHash3
import net.eagle0.eagle.{BattalionId, FactionId, GameId, HeroId, ProvinceId, RoundId}
import net.eagle0.eagle.{FactionId, GameId, ProvinceId, RoundId}
import net.eagle0.eagle.library.actions.impl.common.ProtolessSequentialResultsAction
import net.eagle0.eagle.library.util.BattalionUtils
import net.eagle0.eagle.library.util.EagleRequire.internalRequire
@@ -10,10 +10,8 @@ import net.eagle0.eagle.model.action_result.changed_province.concrete.ChangedPro
import net.eagle0.eagle.model.action_result.concrete.ActionResultC
import net.eagle0.eagle.model.action_result.types.{SentSuppliesResultType, StartBattleResultType}
import net.eagle0.eagle.model.action_result.ActionResultT
import net.eagle0.eagle.model.state.{Army, BattalionType, BattalionTypeId, HostileArmyGroup, MovingArmy, Supplies}
import net.eagle0.eagle.model.state.battalion.BattalionT
import net.eagle0.eagle.model.state.faction.FactionT
import net.eagle0.eagle.model.state.hero.HeroT
import net.eagle0.eagle.model.state.{Army, BattalionType, HostileArmyGroup, MovingArmy, Supplies}
import net.eagle0.eagle.model.state.game_state.GameState
import net.eagle0.eagle.model.state.province.ProvinceT
import net.eagle0.eagle.model.state.shardok_battle.{BattleType, ShardokBattle, ShardokPlayer, VictoryCondition}
import net.eagle0.eagle.model.state.unit_status.UnitStatus
@@ -21,16 +19,17 @@ import net.eagle0.eagle.model.state.HostileArmyGroupStatus.Attacking
import net.eagle0.eagle.shardok_interface.ResolvedEagleUnit
case class RequestBattlesAction(
gameId: GameId,
currentRoundId: RoundId,
currentDate: net.eagle0.eagle.model.state.date.Date,
battleCounter: Int,
heroes: Map[HeroId, HeroT],
battalions: Map[BattalionId, BattalionT],
provinces: Map[ProvinceId, ProvinceT],
factions: Map[FactionId, FactionT],
battalionTypes: Map[BattalionTypeId, BattalionType]
gameState: GameState
) extends ProtolessSequentialResultsAction {
private val gameId = gameState.gameId
private val currentRoundId = gameState.currentRoundId
private val currentDate = gameState.currentDate.get
private val battleCounter = gameState.battleCounter
private val heroes = gameState.heroes
private val battalions = gameState.battalions
private val provinces = gameState.provinces
private val factions = gameState.factions
private val battalionTypes = gameState.battalionTypes.map(bt => bt.typeId -> bt).toMap
override def results: Vector[ActionResultT] =
provincesWithAttackingArmies.zipWithIndex.flatMap { case (pwaas, idx) => handleOneProvince(pwaas, idx) }
@@ -93,8 +93,10 @@ scala_test(
"//src/main/scala/net/eagle0/eagle/model/state:army",
"//src/main/scala/net/eagle0/eagle/model/state:round_phase",
"//src/main/scala/net/eagle0/eagle/model/state/date",
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
"//src/main/scala/net/eagle0/eagle/model/state/province/concrete",
"//src/main/scala/net/eagle0/eagle/model/state/quest/concrete",
"//src/main/scala/net/eagle0/eagle/model/state/run_status",
"//src/main/scala/net/eagle0/eagle/model/state/unaffiliated_hero",
"//src/main/scala/net/eagle0/eagle/model/state/unaffiliated_hero/concrete",
"//src/test/scala/net/eagle0/eagle/library/actions/impl:action_impl_pkg",
@@ -709,15 +711,20 @@ scala_test(
"//src/main/scala/net/eagle0/eagle/model/state:army",
"//src/main/scala/net/eagle0/eagle/model/state:battalion_type_id",
"//src/main/scala/net/eagle0/eagle/model/state:combat_unit",
"//src/main/scala/net/eagle0/eagle/model/state:round_phase",
"//src/main/scala/net/eagle0/eagle/model/state:supplies",
"//src/main/scala/net/eagle0/eagle/model/state/battalion",
"//src/main/scala/net/eagle0/eagle/model/state/battalion/concrete",
"//src/main/scala/net/eagle0/eagle/model/state/date",
"//src/main/scala/net/eagle0/eagle/model/state/faction",
"//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",
"//src/main/scala/net/eagle0/eagle/model/state/hero/concrete",
"//src/main/scala/net/eagle0/eagle/model/state/province",
"//src/main/scala/net/eagle0/eagle/model/state/province:orders",
"//src/main/scala/net/eagle0/eagle/model/state/province/concrete",
"//src/main/scala/net/eagle0/eagle/model/state/run_status",
"//src/test/scala/net/eagle0/eagle/library/actions/impl:action_impl_pkg",
],
)
@@ -921,11 +928,18 @@ scala_test(
"//src/main/scala/net/eagle0/eagle/model/action_result/generated_text_request",
"//src/main/scala/net/eagle0/eagle/model/action_result/types/base:action_result_type",
"//src/main/scala/net/eagle0/eagle/model/state:battalion_type",
"//src/main/scala/net/eagle0/eagle/model/state:round_phase",
"//src/main/scala/net/eagle0/eagle/model/state/battalion",
"//src/main/scala/net/eagle0/eagle/model/state/battalion/concrete",
"//src/main/scala/net/eagle0/eagle/model/state/date",
"//src/main/scala/net/eagle0/eagle/model/state/faction",
"//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",
"//src/main/scala/net/eagle0/eagle/model/state/hero/concrete",
"//src/main/scala/net/eagle0/eagle/model/state/province",
"//src/main/scala/net/eagle0/eagle/model/state/province/concrete",
"//src/main/scala/net/eagle0/eagle/model/state/run_status",
"//src/main/scala/net/eagle0/eagle/model/state/shardok_battle",
],
)
@@ -20,9 +20,11 @@ import net.eagle0.eagle.model.state.{
Supplies
}
import net.eagle0.eagle.model.state.date.Date
import net.eagle0.eagle.model.state.game_state.GameState
import net.eagle0.eagle.model.state.province.concrete.ProvinceC
import net.eagle0.eagle.model.state.province.ProvinceT
import net.eagle0.eagle.model.state.quest.concrete.TruceWithFactionQuest
import net.eagle0.eagle.model.state.run_status.RunStatus
import net.eagle0.eagle.model.state.unaffiliated_hero.{RecruitmentInfo, UnaffiliatedHeroT}
import net.eagle0.eagle.model.state.unaffiliated_hero.concrete.UnaffiliatedHeroC
import net.eagle0.eagle.model.state.unaffiliated_hero.UnaffiliatedHeroType.{Outlaw, Resident, Traveler}
@@ -38,6 +40,30 @@ class EndAttackDecisionPhaseActionTest extends AnyFlatSpec with Matchers {
private val currentRoundId: RoundId = 921
private val currentDate = Date(year = 221, month = Date.Month.April)
private def makeGameState(provinces: Vector[ProvinceT]): GameState = GameState(
gameId = gameId,
currentRoundId = currentRoundId,
currentPhase = RoundPhase.AttackDecision,
currentDate = Some(currentDate),
actionResultCount = 0,
provinces = provinces.map(p => p.id -> p).toMap,
heroes = Map.empty,
battalions = Map.empty,
destroyedBattalions = Map.empty,
factions = Map.empty,
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 = 12345L,
chronicleEntries = Vector.empty
)
private val provincesWithWithdrawingArmy: Vector[ProvinceT] = Vector(
ProvinceC(
id = 4,
@@ -121,10 +147,7 @@ class EndAttackDecisionPhaseActionTest extends AnyFlatSpec with Matchers {
"execute" should "set the basics" in {
val results =
EndAttackDecisionPhaseAction(
gameId = gameId,
currentRoundId = currentRoundId,
currentDate = currentDate,
provinces = Vector.empty
makeGameState(Vector.empty)
).results
results.head.actionResultType shouldBe EndAttackDecisionPhaseResultType
@@ -149,10 +172,7 @@ class EndAttackDecisionPhaseActionTest extends AnyFlatSpec with Matchers {
val results =
EndAttackDecisionPhaseAction(
gameId = gameId,
currentRoundId = currentRoundId,
currentDate = currentDate,
provinces = provincesWithTruceQuest
makeGameState(provincesWithTruceQuest)
).results
forExactly(1, results) { result =>
@@ -175,10 +195,7 @@ class EndAttackDecisionPhaseActionTest extends AnyFlatSpec with Matchers {
"incoming armies still present for this round" should "set the basics" in {
val results =
EndAttackDecisionPhaseAction(
gameId = gameId,
currentRoundId = currentRoundId,
currentDate = currentDate,
provinces = provincesWithWithdrawingArmy
makeGameState(provincesWithWithdrawingArmy)
).results
results should have size 3
@@ -190,10 +207,7 @@ class EndAttackDecisionPhaseActionTest extends AnyFlatSpec with Matchers {
it should "generate outlaws" in {
val result =
EndAttackDecisionPhaseAction(
gameId = gameId,
currentRoundId = currentRoundId,
currentDate = currentDate,
provinces = provincesWithWithdrawingArmy
makeGameState(provincesWithWithdrawingArmy)
)
.results(1)
@@ -222,10 +236,7 @@ class EndAttackDecisionPhaseActionTest extends AnyFlatSpec with Matchers {
it should "remove the relevant hostile army" in {
val result =
EndAttackDecisionPhaseAction(
gameId = gameId,
currentRoundId = currentRoundId,
currentDate = currentDate,
provinces = provincesWithWithdrawingArmy
makeGameState(provincesWithWithdrawingArmy)
).results.head
inside(result.changedProvinces.loneElement) {
@@ -237,10 +248,7 @@ class EndAttackDecisionPhaseActionTest extends AnyFlatSpec with Matchers {
it should "destroy the battalions" in {
val result =
EndAttackDecisionPhaseAction(
gameId = gameId,
currentRoundId = currentRoundId,
currentDate = currentDate,
provinces = provincesWithWithdrawingArmy
makeGameState(provincesWithWithdrawingArmy)
)
.results(1)
@@ -250,10 +258,7 @@ class EndAttackDecisionPhaseActionTest extends AnyFlatSpec with Matchers {
it should "generate a notification" in {
val result =
EndAttackDecisionPhaseAction(
gameId = gameId,
currentRoundId = currentRoundId,
currentDate = currentDate,
provinces = provincesWithWithdrawingArmy
makeGameState(provincesWithWithdrawingArmy)
)
.results(1)
@@ -18,15 +18,22 @@ import net.eagle0.eagle.model.state.{
Supplies
}
import net.eagle0.eagle.model.state.battalion.concrete.BattalionC
import net.eagle0.eagle.model.state.battalion.BattalionT
import net.eagle0.eagle.model.state.date.Date
import net.eagle0.eagle.model.state.faction.concrete.FactionC
import net.eagle0.eagle.model.state.faction.FactionRelationship
import net.eagle0.eagle.model.state.faction.FactionRelationship.RelationshipLevel
import net.eagle0.eagle.model.state.faction.FactionT
import net.eagle0.eagle.model.state.game_state.GameState
import net.eagle0.eagle.model.state.hero.{Gender, Profession}
import net.eagle0.eagle.model.state.hero.concrete.HeroC
import net.eagle0.eagle.model.state.hero.HeroT
import net.eagle0.eagle.model.state.province.concrete.ProvinceC
import net.eagle0.eagle.model.state.province.ProvinceOrderType
import net.eagle0.eagle.model.state.province.ProvinceOrderType.Entrust
import net.eagle0.eagle.model.state.province.ProvinceT
import net.eagle0.eagle.model.state.run_status.RunStatus
import net.eagle0.eagle.model.state.RoundPhase
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import org.scalatest.Inside.inside
@@ -34,7 +41,39 @@ import org.scalatest.Inspectors.forExactly
import org.scalatest.LoneElement.convertToCollectionLoneElementWrapper
class PerformUncontestedConquestActionTest extends AnyFlatSpec with Matchers {
private val attackerId = 1
private val attackerId = 1
private val gameId = 12345L
private val currentRoundId = 9
private val currentDate = Date(year = 1, month = Date.Month.January)
private def makeGameState(
provinces: Map[Int, ProvinceT],
factions: Map[Int, FactionT],
heroes: Map[Int, HeroT] = this.heroes,
battalions: Map[Int, BattalionT] = this.battalions
): GameState = GameState(
gameId = gameId,
currentRoundId = currentRoundId,
currentPhase = RoundPhase.UncontestedConquest,
currentDate = Some(currentDate),
actionResultCount = 0,
provinces = provinces,
heroes = heroes,
battalions = battalions,
destroyedBattalions = Map.empty,
factions = factions,
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 = 12345L,
chronicleEntries = Vector.empty
)
private val heroes: Map[Int, HeroC] = Map(
92 -> HeroC(
@@ -117,13 +156,7 @@ class PerformUncontestedConquestActionTest extends AnyFlatSpec with Matchers {
)
val results = PerformUncontestedConquestAction(
gameId = 12345L,
currentRoundId = 9,
currentDate = Date(year = 1, month = Date.Month.January),
provinces = provinces,
factions = factions,
heroes = heroes,
battalions = battalions
makeGameState(provinces, factions)
).results
results.loneElement.actionResultType.shouldBe(
@@ -176,13 +209,7 @@ class PerformUncontestedConquestActionTest extends AnyFlatSpec with Matchers {
)
val results = PerformUncontestedConquestAction(
gameId = 12345L,
currentRoundId = 9,
currentDate = Date(year = 1, month = Date.Month.January),
provinces = provinces,
factions = factions,
heroes = heroes,
battalions = battalions
makeGameState(provinces, factions)
).results
results.size.shouldBe(3)
@@ -240,13 +267,7 @@ class PerformUncontestedConquestActionTest extends AnyFlatSpec with Matchers {
)
val results = PerformUncontestedConquestAction(
gameId = 12345L,
currentRoundId = 9,
currentDate = Date(year = 1, month = Date.Month.January),
provinces = provinces,
factions = factions,
heroes = heroes,
battalions = battalions
makeGameState(provinces, factions)
).results
inside(results.head.changedProvinces.head) {
@@ -312,13 +333,7 @@ class PerformUncontestedConquestActionTest extends AnyFlatSpec with Matchers {
)
val results = PerformUncontestedConquestAction(
gameId = 12345L,
currentRoundId = 9,
currentDate = Date(year = 1, month = Date.Month.January),
provinces = provinces,
factions = factions,
heroes = heroes,
battalions = battalions
makeGameState(provinces, factions)
).results
results.size.shouldBe(3)
@@ -414,13 +429,7 @@ class PerformUncontestedConquestActionTest extends AnyFlatSpec with Matchers {
val ex = the[EagleInternalException] thrownBy
PerformUncontestedConquestAction(
gameId = 12345L,
currentRoundId = 9,
currentDate = Date(year = 1, month = Date.Month.January),
provinces = provinces,
factions = factions,
heroes = heroes,
battalions = battalions
makeGameState(provinces, factions)
).results
ex.getMessage.shouldBe(
@@ -511,13 +520,7 @@ class PerformUncontestedConquestActionTest extends AnyFlatSpec with Matchers {
)
val result = PerformUncontestedConquestAction(
gameId = 12345L,
currentRoundId = 9,
currentDate = Date(year = 1, month = Date.Month.January),
provinces = provinces,
factions = factions,
heroes = heroes,
battalions = battalions
makeGameState(provinces, factions)
).results.head
result.actionResultType.shouldBe(WithdrawalForTruceResultType)
@@ -5,15 +5,22 @@ import net.eagle0.eagle.library.EagleInternalException
import net.eagle0.eagle.model.action_result.changed_province.concrete.ChangedProvinceC
import net.eagle0.eagle.model.state.*
import net.eagle0.eagle.model.state.battalion.concrete.BattalionC
import net.eagle0.eagle.model.state.battalion.BattalionT
import net.eagle0.eagle.model.state.date.Date
import net.eagle0.eagle.model.state.faction.concrete.FactionC
import net.eagle0.eagle.model.state.faction.FactionT
import net.eagle0.eagle.model.state.game_state.GameState
import net.eagle0.eagle.model.state.hero.concrete.HeroC
import net.eagle0.eagle.model.state.hero.Gender.{Female, Male}
import net.eagle0.eagle.model.state.hero.HeroT
import net.eagle0.eagle.model.state.hero.Profession.NoProfession
import net.eagle0.eagle.model.state.province.{Neighbor, ProvinceOrderType}
import net.eagle0.eagle.model.state.province.concrete.ProvinceC
import net.eagle0.eagle.model.state.province.ProvinceT
import net.eagle0.eagle.model.state.run_status.RunStatus
import net.eagle0.eagle.model.state.shardok_battle.{BattleType, VictoryCondition}
import net.eagle0.eagle.model.state.HostileArmyGroupStatus.{Attacking, AwaitingDecision}
import net.eagle0.eagle.model.state.RoundPhase
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import org.scalatest.Inside.inside
@@ -23,6 +30,40 @@ class RequestBattlesActionTest extends AnyFlatSpec with Matchers {
private val attackerId = 1
private val defenderId = 2
private def makeGameState(
gameId: GameId,
currentRoundId: RoundId,
currentDate: Date,
battleCounter: Int,
provinces: Map[ProvinceId, ProvinceT],
factions: Map[FactionId, FactionT],
heroes: Map[HeroId, HeroT] = this.heroes,
battalions: Map[BattalionId, BattalionT] = this.battalions,
battalionTypes: Map[BattalionTypeId, BattalionType] = this.battalionTypes
): GameState = GameState(
gameId = gameId,
currentRoundId = currentRoundId,
currentPhase = RoundPhase.BattleRequest,
currentDate = Some(currentDate),
actionResultCount = 0,
provinces = provinces,
heroes = heroes,
battalions = battalions,
destroyedBattalions = Map.empty,
factions = factions,
factionCommandCounts = Map.empty,
killedHeroes = Map.empty,
destroyedFactions = Map.empty,
outstandingBattles = Vector.empty,
battleCounter = battleCounter,
deferredNotifications = Vector.empty,
runStatus = RunStatus.Running,
victor = None,
battalionTypes = battalionTypes.values.toVector,
randomSeed = 12345L,
chronicleEntries = Vector.empty
)
private val heroes = Map[HeroId, HeroC](
92 -> HeroC(
id = 92,
@@ -137,15 +178,14 @@ class RequestBattlesActionTest extends AnyFlatSpec with Matchers {
)
val action = RequestBattlesAction(
gameId = 0xcafe,
currentRoundId = 9,
currentDate = Date(year = 1501, month = Date.Month.June),
battleCounter = 0x17,
heroes = heroes,
battalions = battalions,
provinces = provinces,
factions = factions,
battalionTypes = battalionTypes
makeGameState(
gameId = 0xcafe,
currentRoundId = 9,
currentDate = Date(year = 1501, month = Date.Month.June),
battleCounter = 0x17,
provinces = provinces,
factions = factions
)
)
val results = action.results
@@ -226,15 +266,14 @@ class RequestBattlesActionTest extends AnyFlatSpec with Matchers {
)
val results = RequestBattlesAction(
gameId = 0x123,
currentRoundId = 9,
currentDate = Date(year = 1501, month = Date.Month.June),
battleCounter = 0,
heroes = heroes,
battalions = battalions,
provinces = provinces,
factions = factions,
battalionTypes = battalionTypes
makeGameState(
gameId = 0x123,
currentRoundId = 9,
currentDate = Date(year = 1501, month = Date.Month.June),
battleCounter = 0,
provinces = provinces,
factions = factions
)
).results
results.size shouldBe 2
@@ -283,15 +322,14 @@ class RequestBattlesActionTest extends AnyFlatSpec with Matchers {
val ex = the[EagleInternalException] thrownBy
RequestBattlesAction(
gameId = 0x123,
currentRoundId = 9,
currentDate = Date(year = 1501, month = Date.Month.June),
battleCounter = 0,
heroes = heroes,
battalions = battalions,
provinces = provinces,
factions = factions,
battalionTypes = battalionTypes
makeGameState(
gameId = 0x123,
currentRoundId = 9,
currentDate = Date(year = 1501, month = Date.Month.June),
battleCounter = 0,
provinces = provinces,
factions = factions
)
).results
ex.getMessage shouldBe "requirement failed: all armies must be attacking in the battle request phase"
@@ -330,15 +368,14 @@ class RequestBattlesActionTest extends AnyFlatSpec with Matchers {
)
val results = RequestBattlesAction(
gameId = 0x123,
currentRoundId = 9,
currentDate = Date(year = 1501, month = Date.Month.June),
battleCounter = 0,
heroes = heroes,
battalions = battalions,
provinces = provinces,
factions = factions,
battalionTypes = battalionTypes
makeGameState(
gameId = 0x123,
currentRoundId = 9,
currentDate = Date(year = 1501, month = Date.Month.June),
battleCounter = 0,
provinces = provinces,
factions = factions
)
).results
inside(results.head.changedProvinces.head) {
@@ -402,15 +439,14 @@ class RequestBattlesActionTest extends AnyFlatSpec with Matchers {
)
val results = RequestBattlesAction(
gameId = 0xabc123,
currentRoundId = 9,
currentDate = Date(year = 1501, month = Date.Month.June),
battleCounter = 0xa5,
heroes = heroes,
battalions = battalions,
provinces = provinces,
factions = factions,
battalionTypes = battalionTypes
makeGameState(
gameId = 0xabc123,
currentRoundId = 9,
currentDate = Date(year = 1501, month = Date.Month.June),
battleCounter = 0xa5,
provinces = provinces,
factions = factions
)
).results
results should have size 1
@@ -473,15 +509,14 @@ class RequestBattlesActionTest extends AnyFlatSpec with Matchers {
)
val action = RequestBattlesAction(
gameId = 0x123,
currentRoundId = 9,
currentDate = Date(year = 1501, month = Date.Month.June),
battleCounter = 0,
heroes = heroes,
battalions = battalions,
provinces = provinces,
factions = factions,
battalionTypes = battalionTypes
makeGameState(
gameId = 0x123,
currentRoundId = 9,
currentDate = Date(year = 1501, month = Date.Month.June),
battleCounter = 0,
provinces = provinces,
factions = factions
)
)
val results = action.results