mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-28 20:55:44 +00:00
Add Warden prisoner interrogation
This commit is contained in:
+31
-2
@@ -22,6 +22,8 @@ namespace eagle {
|
||||
public Toggle ReturnToggle;
|
||||
public ToggleGroup decisionToggleGroup;
|
||||
|
||||
private Toggle _interrogateToggle;
|
||||
|
||||
public TMP_Dropdown moveToDropdown;
|
||||
|
||||
public HeroDetailsController heroDetails;
|
||||
@@ -67,12 +69,29 @@ namespace eagle {
|
||||
_availableCommand.ManagePrisonerCommand;
|
||||
private ProvinceId ActingProvinceId => ManagePrisonersCommand.ActingProvinceId;
|
||||
|
||||
private Toggle InterrogateToggle {
|
||||
get {
|
||||
if (_interrogateToggle != null) return _interrogateToggle;
|
||||
|
||||
_interrogateToggle = Instantiate(ExecuteToggle, ExecuteToggle.transform.parent);
|
||||
_interrogateToggle.name = "Interrogate Toggle";
|
||||
_interrogateToggle.onValueChanged.RemoveAllListeners();
|
||||
_interrogateToggle.group = decisionToggleGroup;
|
||||
|
||||
var label = _interrogateToggle.GetComponentInChildren<TMP_Text>();
|
||||
label.text = "Interrogate";
|
||||
|
||||
return _interrogateToggle;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureTouchTargets() {
|
||||
TouchTargetUtils.EnsureMinimumTouchTargets(
|
||||
ReleaseToggle,
|
||||
MoveToggle,
|
||||
ExileToggle,
|
||||
ExecuteToggle,
|
||||
InterrogateToggle,
|
||||
ReturnToggle,
|
||||
NextHeroButton);
|
||||
TouchTargetUtils.EnsureMinimumTouchHeight(moveToDropdown);
|
||||
@@ -128,6 +147,10 @@ namespace eagle {
|
||||
return SelectedPrisonerToManage.AvailableOptions.First(
|
||||
opt => opt.SealedValueCase ==
|
||||
PrisonerManagementOption.SealedValueOneofCase.Exile);
|
||||
else if (InterrogateToggle.isOn)
|
||||
return SelectedPrisonerToManage.AvailableOptions.First(
|
||||
opt => opt.SealedValueCase ==
|
||||
PrisonerManagementOption.SealedValueOneofCase.Interrogate);
|
||||
else if (ReturnToggle.isOn)
|
||||
return SelectedPrisonerToManage.AvailableOptions.First(
|
||||
opt => opt.SealedValueCase ==
|
||||
@@ -194,6 +217,9 @@ namespace eagle {
|
||||
bool hasExecute = options.Any(
|
||||
opt => opt.SealedValueCase ==
|
||||
PrisonerManagementOption.SealedValueOneofCase.Execute);
|
||||
bool hasInterrogate = options.Any(
|
||||
opt => opt.SealedValueCase ==
|
||||
PrisonerManagementOption.SealedValueOneofCase.Interrogate);
|
||||
bool hasReturn = options.Any(
|
||||
opt => opt.SealedValueCase ==
|
||||
PrisonerManagementOption.SealedValueOneofCase.Return);
|
||||
@@ -202,11 +228,14 @@ namespace eagle {
|
||||
ConfigureToggle(MoveToggle, hasMove);
|
||||
ConfigureToggle(ExileToggle, hasExile);
|
||||
ConfigureToggle(ExecuteToggle, hasExecute);
|
||||
ConfigureToggle(InterrogateToggle, hasInterrogate);
|
||||
ConfigureToggle(ReturnToggle, hasReturn);
|
||||
|
||||
// Select first available option (priority order: Release > Move > Exile > Execute >
|
||||
// Return)
|
||||
// Select first available option (priority order: Release > Interrogate > Move >
|
||||
// Exile > Execute > Return)
|
||||
if (hasRelease) ReleaseToggle.isOn = true;
|
||||
else if (hasInterrogate)
|
||||
InterrogateToggle.isOn = true;
|
||||
else if (hasMove)
|
||||
MoveToggle.isOn = true;
|
||||
else if (hasExile)
|
||||
|
||||
@@ -88,6 +88,8 @@ namespace eagle {
|
||||
case PrisonerManagementOption.SealedValueOneofCase.Exile: return "Exile";
|
||||
case PrisonerManagementOption.SealedValueOneofCase.Release: return "Release";
|
||||
case PrisonerManagementOption.SealedValueOneofCase.Return: return "Return";
|
||||
case PrisonerManagementOption.SealedValueOneofCase.Interrogate:
|
||||
return "Interrogate";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ message PrisonerManagementOption {
|
||||
PrisonerManagementOptionExile exile = 3;
|
||||
PrisonerManagementOptionReturn return = 4;
|
||||
PrisonerManagementOptionMove move = 5;
|
||||
PrisonerManagementOptionInterrogate interrogate = 6;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,3 +42,6 @@ message PrisonerManagementOptionMove {
|
||||
int32 to_province_id = 1;
|
||||
}
|
||||
|
||||
message PrisonerManagementOptionInterrogate {
|
||||
|
||||
}
|
||||
|
||||
+18
-2
@@ -10,6 +10,7 @@ import net.eagle0.eagle.model.state.command.available.AvailableCommand.{
|
||||
}
|
||||
import net.eagle0.eagle.model.state.command.common.PrisonerManagementOption
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.hero.Profession
|
||||
import net.eagle0.eagle.model.state.unaffiliated_hero.{UnaffiliatedHeroT, UnaffiliatedHeroType}
|
||||
|
||||
object AvailableManagePrisonersCommandFactory extends ScalaAvailableCommandsFactory {
|
||||
@@ -29,16 +30,26 @@ object AvailableManagePrisonersCommandFactory extends ScalaAvailableCommandsFact
|
||||
private def optionsForPrisoner(
|
||||
prisoner: UnaffiliatedHeroT,
|
||||
moveToPids: Vector[ProvinceId],
|
||||
hasWarden: Boolean,
|
||||
gameState: GameState
|
||||
): Vector[PrisonerManagementOption] = {
|
||||
val factionWithThisPrisonerAsLeader = gameState.factions.values
|
||||
.find(_.leaderIds.contains(prisoner.heroId))
|
||||
|
||||
val interrogateOptions = Option
|
||||
.when(
|
||||
hasWarden && factionWithThisPrisonerAsLeader
|
||||
.map(_.id)
|
||||
.orElse(prisoner.lastFactionId)
|
||||
.exists(fid => gameState.provinces.values.exists(_.rulingFactionId.contains(fid)))
|
||||
)(PrisonerManagementOption.Interrogate)
|
||||
.toVector
|
||||
|
||||
factionWithThisPrisonerAsLeader match {
|
||||
case Some(faction) =>
|
||||
Vector(
|
||||
PrisonerManagementOption.Execute
|
||||
) ++ moveToPids
|
||||
) ++ interrogateOptions ++ moveToPids
|
||||
.map(pid => PrisonerManagementOption.Move(toProvinceId = pid))
|
||||
.toVector ++ Option
|
||||
.when(
|
||||
@@ -54,7 +65,7 @@ object AvailableManagePrisonersCommandFactory extends ScalaAvailableCommandsFact
|
||||
PrisonerManagementOption.Execute,
|
||||
PrisonerManagementOption.Exile,
|
||||
PrisonerManagementOption.Release
|
||||
) ++ moveToPids
|
||||
) ++ interrogateOptions ++ moveToPids
|
||||
.map(pid => PrisonerManagementOption.Move(toProvinceId = pid))
|
||||
.toVector
|
||||
}
|
||||
@@ -72,6 +83,10 @@ object AvailableManagePrisonersCommandFactory extends ScalaAvailableCommandsFact
|
||||
.provinces(provinceId)
|
||||
.unaffiliatedHeroes
|
||||
.filter(_.unaffiliatedHeroType == UnaffiliatedHeroType.Prisoner)
|
||||
val hasWarden = gameState
|
||||
.provinces(provinceId)
|
||||
.rulingFactionHeroIds
|
||||
.exists(heroId => gameState.heroes(heroId).profession == Profession.Warden)
|
||||
|
||||
Option.when(prisoners.nonEmpty) {
|
||||
ManagePrisonersAvailable(
|
||||
@@ -90,6 +105,7 @@ object AvailableManagePrisonersCommandFactory extends ScalaAvailableCommandsFact
|
||||
provinceId,
|
||||
gameState
|
||||
),
|
||||
hasWarden = hasWarden,
|
||||
gameState
|
||||
)
|
||||
)
|
||||
|
||||
@@ -463,6 +463,7 @@ scala_library(
|
||||
"//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/game_state",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero:profession",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/unaffiliated_hero",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -87,6 +87,7 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/settings:truce_gold_cost",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/faction_utils",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/quest_fulfillment:quest_fulfillment_utils",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/view_filters:province_view_filter",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result:action_result_trait",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result:notification_trait",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result/concrete:action_result_concrete",
|
||||
@@ -750,6 +751,7 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:eagle_require",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/quest_fulfillment:quest_fulfillment_utils",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/quest_fulfillment/prisoner_management:prisoner_management_quest_matchers",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/view_filters:province_view_filter",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result:action_result_trait",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result:changed_battalion_trait",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result:changed_hero_trait",
|
||||
@@ -758,14 +760,18 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result/changed_province/concrete",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result/concrete:action_result_concrete",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result/concrete:changed_battalion_concrete",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result/concrete:changed_faction_concrete",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result/concrete:changed_hero_concrete",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result/concrete:notification_concrete",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result/generated_text_request",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result/types",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/faction",
|
||||
"//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/province:deferred_change_trait",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/quest",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/unaffiliated_hero",
|
||||
"//src/main/scala/net/eagle0/eagle/model/view/province:province_view",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import net.eagle0.eagle.library.actions.impl.common.{
|
||||
import net.eagle0.eagle.library.settings.{AllianceGoldCost, BreakAllianceGoldCost, InviteGoldCost, TruceGoldCost}
|
||||
import net.eagle0.eagle.library.util.faction_utils.FactionUtils
|
||||
import net.eagle0.eagle.library.util.quest_fulfillment.QuestFulfillmentChecker
|
||||
import net.eagle0.eagle.library.util.view_filters.ProvinceViewFilter
|
||||
import net.eagle0.eagle.library.EagleCommandException
|
||||
import net.eagle0.eagle.library.EagleInternalException
|
||||
import net.eagle0.eagle.model.state.{BattalionTypeId, CombatUnit as ModelCombatUnit, TributeAmount}
|
||||
@@ -347,6 +348,8 @@ class CommandFactory extends TCommandFactory {
|
||||
.getOrElse(throw new IllegalArgumentException(s"No prisoner found for hero ${sc.prisonerHeroId}")),
|
||||
chosenOption = prisonerManagementOptionMap(sc.chosenOption),
|
||||
allProvinces = allProvinces(gameState),
|
||||
allFactions = allFactions(gameState),
|
||||
provinceViewForInterrogation = province => ProvinceViewFilter.filteredProvinceView(province, gameState),
|
||||
questFulfillmentChecker = questFulfillmentChecker(gameState),
|
||||
gameId = gameState.gameId,
|
||||
currentRoundId = gameState.currentRoundId
|
||||
@@ -796,6 +799,7 @@ class CommandFactory extends TCommandFactory {
|
||||
case PrisonerManagementOption.Release => CommandPrisonerManagementOption.Release
|
||||
case PrisonerManagementOption.Execute => CommandPrisonerManagementOption.Execute
|
||||
case PrisonerManagementOption.Exile => CommandPrisonerManagementOption.Exile
|
||||
case PrisonerManagementOption.Interrogate => CommandPrisonerManagementOption.Interrogate
|
||||
case PrisonerManagementOption.Move(toProvinceId) => CommandPrisonerManagementOption.Move(toProvinceId)
|
||||
case PrisonerManagementOption.Return(toFactionId) => CommandPrisonerManagementOption.Return(toFactionId)
|
||||
}
|
||||
|
||||
+75
-2
@@ -1,9 +1,12 @@
|
||||
package net.eagle0.eagle.library.actions.impl.command
|
||||
|
||||
import scala.annotation.unused
|
||||
|
||||
import net.eagle0.eagle.{FactionId, GameId, HeroId, ProvinceId, RoundId}
|
||||
import net.eagle0.eagle.library.actions.impl.command.ManagePrisonersCommand.PrisonerManagementOption.{
|
||||
Execute,
|
||||
Exile,
|
||||
Interrogate,
|
||||
Move,
|
||||
Release,
|
||||
Return
|
||||
@@ -11,10 +14,11 @@ import net.eagle0.eagle.library.actions.impl.command.ManagePrisonersCommand.Pris
|
||||
import net.eagle0.eagle.library.actions.impl.common.ProtolessSequentialResultsAction
|
||||
import net.eagle0.eagle.library.util.quest_fulfillment.prisoner_management.PrisonerManagementQuestMatchers
|
||||
import net.eagle0.eagle.library.util.quest_fulfillment.QuestFulfillmentChecker
|
||||
import net.eagle0.eagle.library.util.quest_fulfillment.QuestFulfillmentUtils
|
||||
import net.eagle0.eagle.library.util.EagleRequire.commandRequire
|
||||
import net.eagle0.eagle.model.action_result.{ActionResultT, NotificationDetails, NotificationT}
|
||||
import net.eagle0.eagle.model.action_result.changed_province.concrete.ChangedProvinceC
|
||||
import net.eagle0.eagle.model.action_result.concrete.{ActionResultC, NotificationC}
|
||||
import net.eagle0.eagle.model.action_result.concrete.{ActionResultC, ChangedFactionC, NotificationC}
|
||||
import net.eagle0.eagle.model.action_result.generated_text_request.LlmRequestT.{
|
||||
PrisonerExecutedMessage,
|
||||
PrisonerExiledMessage,
|
||||
@@ -22,9 +26,16 @@ import net.eagle0.eagle.model.action_result.generated_text_request.LlmRequestT.{
|
||||
PrisonerReturnedMessage
|
||||
}
|
||||
import net.eagle0.eagle.model.action_result.types.ActionResultType
|
||||
import net.eagle0.eagle.model.action_result.types.ActionResultType.{PrisonerExecuted, PrisonerExiled, PrisonerReleased}
|
||||
import net.eagle0.eagle.model.action_result.types.ActionResultType.{
|
||||
PrisonerExecuted,
|
||||
PrisonerExiled,
|
||||
PrisonerReleased,
|
||||
ReconSucceeded
|
||||
}
|
||||
import net.eagle0.eagle.model.state.faction.FactionT
|
||||
import net.eagle0.eagle.model.state.province.DeferredChange.{PrisonerMoved, PrisonerReturned}
|
||||
import net.eagle0.eagle.model.state.province.ProvinceT
|
||||
import net.eagle0.eagle.model.state.quest.ReconProvincesQuest
|
||||
import net.eagle0.eagle.model.state.unaffiliated_hero.{RecruitmentInfo, UnaffiliatedHeroT}
|
||||
import net.eagle0.eagle.model.state.unaffiliated_hero.UnaffiliatedHeroType.{
|
||||
MovingPrisoner,
|
||||
@@ -32,6 +43,7 @@ import net.eagle0.eagle.model.state.unaffiliated_hero.UnaffiliatedHeroType.{
|
||||
ReturningPrisoner,
|
||||
Traveler
|
||||
}
|
||||
import net.eagle0.eagle.model.view.province.ProvinceView
|
||||
|
||||
object ManagePrisonersCommand {
|
||||
sealed trait PrisonerManagementOption
|
||||
@@ -45,6 +57,8 @@ object ManagePrisonersCommand {
|
||||
case class Move(toProvinceId: ProvinceId) extends PrisonerManagementOption
|
||||
|
||||
case object Execute extends PrisonerManagementOption
|
||||
|
||||
case object Interrogate extends PrisonerManagementOption
|
||||
}
|
||||
|
||||
case class PrisonerToManage(
|
||||
@@ -58,6 +72,8 @@ object ManagePrisonersCommand {
|
||||
prisonerUnaffiliatedHero: UnaffiliatedHeroT,
|
||||
selectedOption: PrisonerManagementOption,
|
||||
allProvinces: Vector[ProvinceT],
|
||||
allFactions: Vector[FactionT],
|
||||
provinceViewForInterrogation: ProvinceT => ProvinceView,
|
||||
questFulfillmentChecker: QuestFulfillmentChecker,
|
||||
gameId: GameId,
|
||||
currentRoundId: RoundId
|
||||
@@ -278,6 +294,33 @@ object ManagePrisonersCommand {
|
||||
isFailed = (quest, _ /*questHolderProvince*/ ) => releaseAllPrisonersQuestMatch(quest)
|
||||
)
|
||||
}
|
||||
case Interrogate =>
|
||||
val interrogatedFactionId = prisonerUnaffiliatedHero.lastFactionId
|
||||
.orElse(allFactions.find(_.leaderIds.contains(prisonerUnaffiliatedHero.heroId)).map(_.id))
|
||||
.getOrElse(
|
||||
throw new IllegalArgumentException(
|
||||
s"No faction found to interrogate prisoner ${prisonerUnaffiliatedHero.heroId} about"
|
||||
)
|
||||
)
|
||||
val targetProvince = allProvinces
|
||||
.find(_.rulingFactionId.contains(interrogatedFactionId))
|
||||
.getOrElse(
|
||||
throw new IllegalArgumentException(s"No province found for faction $interrogatedFactionId")
|
||||
)
|
||||
val factionProvinces = allProvinces.filter(_.rulingFactionId.contains(actingFactionId))
|
||||
val baseResult = ActionResultC(
|
||||
actionResultType = ReconSucceeded,
|
||||
actingFactionId = Some(actingFactionId),
|
||||
provinceId = Some(provinceId),
|
||||
changedFactions = Vector(
|
||||
ChangedFactionC(
|
||||
factionId = actingFactionId,
|
||||
updatedReconnedProvinces = Vector(provinceViewForInterrogation(targetProvince))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
Vector(reconProvincesQuestIncrementer(factionProvinces)(baseResult))
|
||||
case Execute =>
|
||||
val llmRequestId =
|
||||
s"prisoner_executed $currentRoundId ${prisonerUnaffiliatedHero.heroId}"
|
||||
@@ -341,6 +384,16 @@ object ManagePrisonersCommand {
|
||||
prisonerUnaffiliatedHero: UnaffiliatedHeroT,
|
||||
chosenOption: PrisonerManagementOption,
|
||||
allProvinces: Vector[ProvinceT],
|
||||
allFactions: Vector[FactionT] = Vector.empty,
|
||||
provinceViewForInterrogation: ProvinceT => ProvinceView = province =>
|
||||
ProvinceView(
|
||||
id = province.id,
|
||||
name = province.name,
|
||||
rulingFactionId = province.rulingFactionId,
|
||||
fullInfo = None,
|
||||
knownEvents = Vector.empty,
|
||||
asOf = None
|
||||
),
|
||||
questFulfillmentChecker: QuestFulfillmentChecker,
|
||||
gameId: GameId,
|
||||
currentRoundId: RoundId
|
||||
@@ -373,9 +426,29 @@ object ManagePrisonersCommand {
|
||||
prisonerUnaffiliatedHero = prisonerUnaffiliatedHero,
|
||||
selectedOption = chosenOption,
|
||||
allProvinces = allProvinces,
|
||||
allFactions = allFactions,
|
||||
provinceViewForInterrogation = provinceViewForInterrogation,
|
||||
questFulfillmentChecker = questFulfillmentChecker,
|
||||
gameId = gameId,
|
||||
currentRoundId = currentRoundId
|
||||
)
|
||||
}
|
||||
|
||||
private def reconProvincesQuestCheck(
|
||||
uh: UnaffiliatedHeroT,
|
||||
@unused province: ProvinceT
|
||||
): Boolean =
|
||||
uh.quest.exists {
|
||||
case q: ReconProvincesQuest => q.componentsFulfilled < q.componentCount
|
||||
case _ => false
|
||||
}
|
||||
|
||||
private def reconProvincesQuestIncrementer(
|
||||
factionProvinces: Vector[ProvinceT]
|
||||
): ActionResultT => ActionResultT =
|
||||
QuestFulfillmentUtils.withCountersIncremented(
|
||||
provinces = factionProvinces,
|
||||
incrementAmount = 1,
|
||||
check = reconProvincesQuestCheck
|
||||
)
|
||||
}
|
||||
|
||||
+2
@@ -25,6 +25,7 @@ import net.eagle0.eagle.api.command.util.prisoner_management_type.{
|
||||
PrisonerManagementOption as PrisonerManagementOptionProto,
|
||||
PrisonerManagementOptionExecute,
|
||||
PrisonerManagementOptionExile,
|
||||
PrisonerManagementOptionInterrogate,
|
||||
PrisonerManagementOptionMove,
|
||||
PrisonerManagementOptionRelease,
|
||||
PrisonerManagementOptionReturn
|
||||
@@ -881,6 +882,7 @@ object AvailableCommandConverter {
|
||||
case PrisonerManagementOption.Release => PrisonerManagementOptionRelease()
|
||||
case PrisonerManagementOption.Execute => PrisonerManagementOptionExecute()
|
||||
case PrisonerManagementOption.Exile => PrisonerManagementOptionExile()
|
||||
case PrisonerManagementOption.Interrogate => PrisonerManagementOptionInterrogate()
|
||||
case PrisonerManagementOption.Move(toProvinceId) => PrisonerManagementOptionMove(toProvinceId = toProvinceId)
|
||||
case PrisonerManagementOption.Return(toFactionId) => PrisonerManagementOptionReturn(toFactionId = toFactionId)
|
||||
}
|
||||
|
||||
+8
-6
@@ -21,6 +21,7 @@ import net.eagle0.eagle.api.command.util.prisoner_management_type.{
|
||||
PrisonerManagementOption as PrisonerManagementOptionProto,
|
||||
PrisonerManagementOptionExecute,
|
||||
PrisonerManagementOptionExile,
|
||||
PrisonerManagementOptionInterrogate,
|
||||
PrisonerManagementOptionMove,
|
||||
PrisonerManagementOptionRelease,
|
||||
PrisonerManagementOptionReturn
|
||||
@@ -432,12 +433,13 @@ object SelectedCommandConverter {
|
||||
|
||||
private def prisonerManagementOptionFromProto(opt: PrisonerManagementOptionProto): PrisonerManagementOption =
|
||||
opt match {
|
||||
case _: PrisonerManagementOptionRelease => PrisonerManagementOption.Release
|
||||
case _: PrisonerManagementOptionExecute => PrisonerManagementOption.Execute
|
||||
case _: PrisonerManagementOptionExile => PrisonerManagementOption.Exile
|
||||
case move: PrisonerManagementOptionMove => PrisonerManagementOption.Move(toProvinceId = move.toProvinceId)
|
||||
case ret: PrisonerManagementOptionReturn => PrisonerManagementOption.Return(toFactionId = ret.toFactionId)
|
||||
case PrisonerManagementOptionProto.Empty =>
|
||||
case _: PrisonerManagementOptionRelease => PrisonerManagementOption.Release
|
||||
case _: PrisonerManagementOptionExecute => PrisonerManagementOption.Execute
|
||||
case _: PrisonerManagementOptionExile => PrisonerManagementOption.Exile
|
||||
case _: PrisonerManagementOptionInterrogate => PrisonerManagementOption.Interrogate
|
||||
case move: PrisonerManagementOptionMove => PrisonerManagementOption.Move(toProvinceId = move.toProvinceId)
|
||||
case ret: PrisonerManagementOptionReturn => PrisonerManagementOption.Return(toFactionId = ret.toFactionId)
|
||||
case PrisonerManagementOptionProto.Empty =>
|
||||
throw new ProtoConversionException("PrisonerManagementOption has no value set")
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ enum PrisonerManagementOption:
|
||||
case Release
|
||||
case Execute
|
||||
case Exile
|
||||
case Interrogate
|
||||
case Move(toProvinceId: ProvinceId)
|
||||
case Return(toFactionId: FactionId)
|
||||
|
||||
|
||||
+59
@@ -8,6 +8,7 @@ import net.eagle0.eagle.model.state.command.common.PrisonerManagementOption
|
||||
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.hero.Profession
|
||||
import net.eagle0.eagle.model.state.province.concrete.ProvinceC
|
||||
import net.eagle0.eagle.model.state.province.Neighbor
|
||||
import net.eagle0.eagle.model.state.run_status.RunStatus
|
||||
@@ -28,6 +29,7 @@ class AvailableManagePrisonerCommandsFactoryTest extends AnyFlatSpec with Before
|
||||
private val actingProvinceId: ProvinceId = 5
|
||||
|
||||
private val enemyFactionLeaderHid: HeroId = 19
|
||||
private val wardenHeroId: HeroId = 23
|
||||
|
||||
private val neighbor1ProvinceId: ProvinceId = 21
|
||||
private val neighbor2ProvinceId: ProvinceId = 31
|
||||
@@ -45,6 +47,7 @@ class AvailableManagePrisonerCommandsFactoryTest extends AnyFlatSpec with Before
|
||||
heroes = Map(
|
||||
17 -> HeroC(id = 17),
|
||||
18 -> HeroC(id = 18),
|
||||
wardenHeroId -> HeroC(id = wardenHeroId, profession = Profession.Warden),
|
||||
enemyFactionLeaderHid -> HeroC(id = enemyFactionLeaderHid)
|
||||
),
|
||||
provinces = Map(
|
||||
@@ -196,6 +199,62 @@ class AvailableManagePrisonerCommandsFactoryTest extends AnyFlatSpec with Before
|
||||
}
|
||||
}
|
||||
|
||||
it should "not include an Interrogate option without a Warden in the province" in {
|
||||
val ac = getManagePrisonersCommand(baseGameState)
|
||||
|
||||
inside(ac.prisoners.find(_.prisoner.heroId == enemyFactionLeaderHid)) {
|
||||
case Some(prisoner) =>
|
||||
prisoner.availableOptions should not contain PrisonerManagementOption.Interrogate
|
||||
}
|
||||
}
|
||||
|
||||
it should "include an Interrogate option for a faction leader when a Warden is in the province" in {
|
||||
val actingProvince = inside(baseGameState.provinces(actingProvinceId)) {
|
||||
case province: ProvinceC => province
|
||||
}
|
||||
val gs = baseGameState.copy(
|
||||
provinces = baseGameState.provinces.updated(
|
||||
actingProvinceId,
|
||||
actingProvince.copy(rulingFactionHeroIds = Vector(wardenHeroId))
|
||||
)
|
||||
)
|
||||
|
||||
val ac = getManagePrisonersCommand(gs)
|
||||
|
||||
inside(ac.prisoners.find(_.prisoner.heroId == enemyFactionLeaderHid)) {
|
||||
case Some(prisoner) =>
|
||||
prisoner.availableOptions should contain(PrisonerManagementOption.Interrogate)
|
||||
}
|
||||
}
|
||||
|
||||
it should "include an Interrogate option for a prisoner with a last faction when a Warden is in the province" in {
|
||||
val actingProvince = inside(baseGameState.provinces(actingProvinceId)) {
|
||||
case province: ProvinceC => province
|
||||
}
|
||||
val prisoner = inside(actingProvince.unaffiliatedHeroes.find(_.heroId == 17)) {
|
||||
case Some(uh: UnaffiliatedHeroC) => uh
|
||||
}
|
||||
val gs = baseGameState.copy(
|
||||
provinces = baseGameState.provinces.updated(
|
||||
actingProvinceId,
|
||||
actingProvince.copy(
|
||||
rulingFactionHeroIds = Vector(wardenHeroId),
|
||||
unaffiliatedHeroes = actingProvince.unaffiliatedHeroes.map {
|
||||
case uh if uh.heroId == 17 => prisoner.copy(lastFactionId = Some(enemyFactionId))
|
||||
case uh => uh
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val ac = getManagePrisonersCommand(gs)
|
||||
|
||||
inside(ac.prisoners.find(_.prisoner.heroId == 17)) {
|
||||
case Some(prisoner) =>
|
||||
prisoner.availableOptions should contain(PrisonerManagementOption.Interrogate)
|
||||
}
|
||||
}
|
||||
|
||||
it should "return a Move option if there is an owned adjacent province" in {
|
||||
val neighborProvince = inside(baseGameState.provinces(neighbor1ProvinceId)) {
|
||||
case province: ProvinceC =>
|
||||
|
||||
@@ -526,14 +526,17 @@ scala_test(
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result:changed_hero_trait",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result:notification_trait",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result/changed_province/concrete",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result/concrete:changed_faction_concrete",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result/concrete:notification_concrete",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result/generated_text_request",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result/types",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/faction/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/quest",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/unaffiliated_hero",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/unaffiliated_hero/concrete",
|
||||
"//src/main/scala/net/eagle0/eagle/model/view/province:province_view",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
+50
-3
@@ -6,7 +6,7 @@ import net.eagle0.eagle.library.settings.{QuestFailedRecruitmentPenalty, QuestRe
|
||||
import net.eagle0.eagle.library.util.quest_fulfillment.QuestFulfillmentChecker
|
||||
import net.eagle0.eagle.library.EagleCommandException
|
||||
import net.eagle0.eagle.model.action_result.changed_province.concrete.ChangedProvinceC
|
||||
import net.eagle0.eagle.model.action_result.concrete.NotificationC
|
||||
import net.eagle0.eagle.model.action_result.concrete.{ChangedFactionC, NotificationC}
|
||||
import net.eagle0.eagle.model.action_result.generated_text_request.LlmRequestT.PrisonerExecutedMessage
|
||||
import net.eagle0.eagle.model.action_result.types.ActionResultType
|
||||
import net.eagle0.eagle.model.action_result.types.ActionResultType.{
|
||||
@@ -14,11 +14,13 @@ import net.eagle0.eagle.model.action_result.types.ActionResultType.{
|
||||
PrisonerExiled,
|
||||
PrisonerReleased,
|
||||
QuestFailed,
|
||||
QuestFulfilled
|
||||
QuestFulfilled,
|
||||
ReconSucceeded
|
||||
}
|
||||
import net.eagle0.eagle.model.action_result.NotificationDetails
|
||||
import net.eagle0.eagle.model.action_result.NotificationT
|
||||
import net.eagle0.eagle.model.state.date.Date
|
||||
import net.eagle0.eagle.model.state.faction.concrete.FactionC
|
||||
import net.eagle0.eagle.model.state.province.concrete.ProvinceC
|
||||
import net.eagle0.eagle.model.state.province.DeferredChange.{PrisonerMoved, PrisonerReturned}
|
||||
import net.eagle0.eagle.model.state.province.Neighbor
|
||||
@@ -38,6 +40,7 @@ import net.eagle0.eagle.model.state.unaffiliated_hero.UnaffiliatedHeroType.{
|
||||
ReturningPrisoner,
|
||||
Traveler
|
||||
}
|
||||
import net.eagle0.eagle.model.view.province.ProvinceView
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.BeforeAndAfterEach
|
||||
@@ -101,6 +104,21 @@ class ManagePrisonersCommandTest extends AnyFlatSpec with Matchers with BeforeAn
|
||||
)
|
||||
)
|
||||
|
||||
private val allFactions = Vector(
|
||||
FactionC(id = actingFactionId, factionHeadId = 1, name = "Acting Faction", leaderIds = Vector(1)),
|
||||
FactionC(id = enemyFactionId, factionHeadId = 97, name = "Enemy Faction", leaderIds = Vector(97))
|
||||
)
|
||||
|
||||
private def provinceViewForInterrogation(province: net.eagle0.eagle.model.state.province.ProvinceT): ProvinceView =
|
||||
ProvinceView(
|
||||
id = province.id,
|
||||
name = province.name,
|
||||
rulingFactionId = province.rulingFactionId,
|
||||
fullInfo = None,
|
||||
knownEvents = Vector.empty,
|
||||
asOf = None
|
||||
)
|
||||
|
||||
private val heroIdDesiringExecute = 983
|
||||
private val heroIdDesiringRelease = 984
|
||||
private val heroIdDesiringExile = 985
|
||||
@@ -169,6 +187,7 @@ class ManagePrisonersCommandTest extends AnyFlatSpec with Matchers with BeforeAn
|
||||
heroId = 97,
|
||||
availableOptions = Vector(
|
||||
PrisonerManagementOption.Execute,
|
||||
PrisonerManagementOption.Interrogate,
|
||||
PrisonerManagementOption.Return(enemyFactionId),
|
||||
PrisonerManagementOption.Move(toProvinceId = neighboringProvinceId)
|
||||
)
|
||||
@@ -228,7 +247,35 @@ class ManagePrisonersCommandTest extends AnyFlatSpec with Matchers with BeforeAn
|
||||
currentRoundId = 17
|
||||
)
|
||||
|
||||
ex.getMessage shouldBe "requirement failed: Selected management type Release was not among available options Vector(Execute, Return(98), Move(17))"
|
||||
ex.getMessage shouldBe "requirement failed: Selected management type Release was not among available options Vector(Execute, Interrogate, Return(98), Move(17))"
|
||||
}
|
||||
|
||||
"interrogate" should "reveal a province occupied by the prisoner's faction" in {
|
||||
val ar = ManagePrisonersCommand
|
||||
.make(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = actingProvinceId,
|
||||
availablePrisoners = availablePrisoners,
|
||||
prisonerUnaffiliatedHero = firstUH97,
|
||||
chosenOption = PrisonerManagementOption.Interrogate,
|
||||
allProvinces = allProvinces,
|
||||
allFactions = allFactions,
|
||||
provinceViewForInterrogation = provinceViewForInterrogation,
|
||||
questFulfillmentChecker = questFulfillmentChecker,
|
||||
gameId = 0xcafeface,
|
||||
currentRoundId = 17
|
||||
)
|
||||
.results
|
||||
.loneElement
|
||||
|
||||
ar.actionResultType shouldBe ReconSucceeded
|
||||
ar.actingFactionId shouldBe Some(actingFactionId)
|
||||
ar.provinceId shouldBe Some(actingProvinceId)
|
||||
inside(ar.changedFactions.loneElement) {
|
||||
case changedFaction: ChangedFactionC =>
|
||||
changedFaction.factionId shouldBe actingFactionId
|
||||
changedFaction.updatedReconnedProvinces.map(_.id) shouldBe Vector(enemyProvinceId)
|
||||
}
|
||||
}
|
||||
|
||||
"execute" should "set the basics" in {
|
||||
|
||||
+2
@@ -21,6 +21,7 @@ import net.eagle0.eagle.api.command.util.prisoner_management_type.{
|
||||
PrisonerManagementOption as PrisonerManagementOptionProto,
|
||||
PrisonerManagementOptionExecute,
|
||||
PrisonerManagementOptionExile,
|
||||
PrisonerManagementOptionInterrogate,
|
||||
PrisonerManagementOptionMove,
|
||||
PrisonerManagementOptionRelease,
|
||||
PrisonerManagementOptionReturn
|
||||
@@ -525,6 +526,7 @@ class SelectedCommandConverterTest extends AnyFlatSpec with Matchers {
|
||||
convert(PrisonerManagementOptionRelease()) shouldBe PrisonerManagementOption.Release
|
||||
convert(PrisonerManagementOptionExecute()) shouldBe PrisonerManagementOption.Execute
|
||||
convert(PrisonerManagementOptionExile()) shouldBe PrisonerManagementOption.Exile
|
||||
convert(PrisonerManagementOptionInterrogate()) shouldBe PrisonerManagementOption.Interrogate
|
||||
convert(PrisonerManagementOptionMove(toProvinceId = 42)) shouldBe PrisonerManagementOption.Move(toProvinceId = 42)
|
||||
convert(PrisonerManagementOptionReturn(toFactionId = 7)) shouldBe PrisonerManagementOption.Return(toFactionId = 7)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user