mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-29 05:15:44 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4960987147 | ||
|
|
5d9a267b4b |
@@ -70,14 +70,16 @@ scala_library(
|
||||
],
|
||||
deps = [
|
||||
":resolve_diplomacy_command_selector",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/library/settings:invite_gold_cost",
|
||||
"//src/main/scala/net/eagle0/eagle/library/settings:min_chance_for_a_i_invite",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:command_selection",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers:available_command_selector",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers:province_gold_surplus_calculator",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers:trust_for_diplomacy",
|
||||
"//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",
|
||||
],
|
||||
)
|
||||
@@ -93,7 +95,6 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers",
|
||||
@@ -134,13 +135,13 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//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:available_command_selector",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/faction_utils",
|
||||
"//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/game_state",
|
||||
],
|
||||
)
|
||||
@@ -153,14 +154,14 @@ scala_library(
|
||||
],
|
||||
deps = [
|
||||
":ai_client_utils",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:battalion_utils",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:command_selection",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:eagle_require",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:province_distances",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers:province_gold_surplus_calculator",
|
||||
"//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/game_state",
|
||||
],
|
||||
)
|
||||
@@ -173,7 +174,6 @@ scala_library(
|
||||
"//src/test/scala/net/eagle0/eagle/ai:__pkg__",
|
||||
],
|
||||
exports = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:command_selection",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
],
|
||||
@@ -184,9 +184,6 @@ scala_library(
|
||||
":march_toward_province_command_chooser",
|
||||
":move_leader_to_better_province_command_chooser",
|
||||
":seek_more_leaders_command_chooser",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//src/main/scala/net/eagle0/common:more_option",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
@@ -210,6 +207,9 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/food_consumption",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero:hero_utils",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/province",
|
||||
"//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",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
@@ -232,10 +232,10 @@ scala_library(
|
||||
deps = [
|
||||
":faction_leader_province_ranker",
|
||||
":march_toward_province_command_chooser",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//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:province_distances",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/faction",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
],
|
||||
@@ -251,8 +251,6 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/library:eagle_internal_exception",
|
||||
@@ -263,8 +261,10 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:eagle_require",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers:available_command_selector",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers:command_chooser",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers:ransom_offer_helpers",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/faction_utils",
|
||||
"//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/diplomacy_offer/status",
|
||||
"//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/province",
|
||||
@@ -279,8 +279,6 @@ scala_library(
|
||||
"//src/test/scala/net/eagle0/eagle/ai:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:more_option",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/library/settings:loyalty_gain_from_feast",
|
||||
@@ -293,6 +291,8 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers:sworn_brother_chooser",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/faction_utils",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero:hero_utils",
|
||||
"//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/game_state",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/province",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.eagle0.eagle.ai
|
||||
|
||||
import net.eagle0.common.{FunctionalRandom, RandomState}
|
||||
import net.eagle0.eagle.api.available_command.AvailableCommand
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.CommandChoiceHelpers.{
|
||||
chosenCommandWhileTraveling,
|
||||
chosenDevelopCommand,
|
||||
@@ -10,7 +9,8 @@ import net.eagle0.eagle.library.util.command_choice_helpers.CommandChoiceHelpers
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.CommandChooser
|
||||
import net.eagle0.eagle.library.util.faction_utils.FactionUtils
|
||||
import net.eagle0.eagle.library.util.province.ProvinceUtils
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.FactionId
|
||||
|
||||
@@ -25,7 +25,7 @@ object EarlyGameAIClient {
|
||||
gs: GameState,
|
||||
acs: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[CommandSelection] =
|
||||
): RandomState[ScalaCommandSelection] =
|
||||
CommandChooser
|
||||
.choose(
|
||||
actingFactionId = actingFactionId,
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package net.eagle0.eagle.ai
|
||||
|
||||
import net.eagle0.common.{FunctionalRandom, RandomState}
|
||||
import net.eagle0.eagle.api.available_command.{AvailableCommand, MarchAvailableCommand}
|
||||
import net.eagle0.eagle.api.selected_command.MarchSelectedCommand
|
||||
import net.eagle0.eagle.common.combat_unit.CombatUnit
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.AvailableCommandSelector.randomSelectionForType
|
||||
import net.eagle0.eagle.library.util.faction_utils.FactionUtils
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.MarchAvailable
|
||||
import net.eagle0.eagle.model.state.command.selected.CombatUnit
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.MarchSelected
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.FactionId
|
||||
|
||||
@@ -16,10 +17,10 @@ object FixLeaderAloneCommandSelector {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] = {
|
||||
): RandomState[Option[ScalaCommandSelection]] = {
|
||||
val factions = gameState.factions.values.toVector
|
||||
val provinces = gameState.provinces
|
||||
randomSelectionForType[MarchAvailableCommand](
|
||||
randomSelectionForType[MarchAvailable](
|
||||
availableCommands,
|
||||
functionalRandom
|
||||
) {
|
||||
@@ -40,15 +41,15 @@ object FixLeaderAloneCommandSelector {
|
||||
.map { destination =>
|
||||
fr.nextRandomElement(opmc.availableHeroIds)
|
||||
.map { hid =>
|
||||
CombatUnit(factionId = actingFactionId, heroId = hid)
|
||||
CombatUnit(heroId = hid, battalionId = None)
|
||||
}
|
||||
.map { combatUnit =>
|
||||
Some(
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = ac.actingProvinceId,
|
||||
available = ac,
|
||||
selected = MarchSelectedCommand(
|
||||
selected = MarchSelected(
|
||||
gold = 0,
|
||||
food = 0,
|
||||
originProvince = opmc.originProvinceId,
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
package net.eagle0.eagle.ai
|
||||
|
||||
import net.eagle0.eagle.api.available_command.{AvailableCommand, DiplomacyAvailableCommand}
|
||||
import net.eagle0.eagle.api.command.util.diplomacy_option.InvitationOption
|
||||
import net.eagle0.eagle.api.selected_command.DiplomacySelectedCommand
|
||||
import net.eagle0.eagle.library.settings.MinChanceForAIInvite
|
||||
import net.eagle0.eagle.library.settings.{InviteGoldCost, MinChanceForAIInvite}
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.{ProvinceGoldSurplusCalculator, TrustForDiplomacy}
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.AvailableCommandSelector.flatSelectionForType
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.{DiplomacyAvailable, DiplomacyOption}
|
||||
import net.eagle0.eagle.model.state.command.common.DiplomacyOptionType
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.DiplomacySelected
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.FactionId
|
||||
|
||||
object InvitationCommandSelector {
|
||||
private case class InvitationOptionWithChance(
|
||||
invitationOption: InvitationOption,
|
||||
targetFactionId: FactionId,
|
||||
acceptanceChance: Int
|
||||
)
|
||||
|
||||
@@ -20,39 +21,45 @@ object InvitationCommandSelector {
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] =
|
||||
flatSelectionForType[DiplomacyAvailableCommand](acs = availableCommands) { diplomacyAvailableCommand =>
|
||||
diplomacyAvailableCommand.options.collect { case io: InvitationOption => io }.filter { invitationOption =>
|
||||
TrustForDiplomacy.meetsConditionsForInvitation(
|
||||
actingFactionId = actingFactionId,
|
||||
targetFactionId = invitationOption.targetFactionId,
|
||||
gameState = gameState
|
||||
)
|
||||
}.filter { invitationOption =>
|
||||
ProvinceGoldSurplusCalculator.provinceGoldSurplus(
|
||||
gameState.provinces(diplomacyAvailableCommand.actingProvinceId)
|
||||
) >= invitationOption.goldCost
|
||||
}.map { invitationOption =>
|
||||
InvitationOptionWithChance(
|
||||
invitationOption = invitationOption,
|
||||
acceptanceChance = ResolveDiplomacyCommandSelector.invitationAcceptanceChance(
|
||||
actingFactionId,
|
||||
invitationOption.targetFactionId,
|
||||
gameState.factions.values.toVector,
|
||||
gameState.provinces.values.toVector
|
||||
): Option[ScalaCommandSelection] =
|
||||
flatSelectionForType[DiplomacyAvailable](acs = availableCommands) { diplomacyAvailable =>
|
||||
// Find options that have Invitation as an option type
|
||||
diplomacyAvailable.options
|
||||
.filter(opt => opt.optionTypes.contains(DiplomacyOptionType.Invitation))
|
||||
.filter { diplomacyOption =>
|
||||
TrustForDiplomacy.meetsConditionsForInvitation(
|
||||
actingFactionId = actingFactionId,
|
||||
targetFactionId = diplomacyOption.targetFactionId,
|
||||
gameState = gameState
|
||||
)
|
||||
)
|
||||
}.maxByOption(_.acceptanceChance)
|
||||
}
|
||||
.filter { _ =>
|
||||
ProvinceGoldSurplusCalculator.provinceGoldSurplus(
|
||||
gameState.provinces(diplomacyAvailable.actingProvinceId)
|
||||
) >= InviteGoldCost.intValue
|
||||
}
|
||||
.map { diplomacyOption =>
|
||||
InvitationOptionWithChance(
|
||||
targetFactionId = diplomacyOption.targetFactionId,
|
||||
acceptanceChance = ResolveDiplomacyCommandSelector.invitationAcceptanceChance(
|
||||
actingFactionId,
|
||||
diplomacyOption.targetFactionId,
|
||||
gameState.factions.values.toVector,
|
||||
gameState.provinces.values.toVector
|
||||
)
|
||||
)
|
||||
}
|
||||
.maxByOption(_.acceptanceChance)
|
||||
.filter(_.acceptanceChance >= MinChanceForAIInvite.intValue)
|
||||
.map { iowc =>
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = diplomacyAvailableCommand.actingProvinceId,
|
||||
available = diplomacyAvailableCommand,
|
||||
selected = DiplomacySelectedCommand(
|
||||
selectedOption = iowc.invitationOption,
|
||||
targetFactionId = iowc.invitationOption.targetFactionId,
|
||||
sentHeroId = diplomacyAvailableCommand.recommendedHeroId
|
||||
actingProvinceId = diplomacyAvailable.actingProvinceId,
|
||||
available = diplomacyAvailable,
|
||||
selected = DiplomacySelected(
|
||||
selectedOption = DiplomacyOptionType.Invitation,
|
||||
targetFactionId = iowc.targetFactionId,
|
||||
sentHeroId = diplomacyAvailable.recommendedHeroId
|
||||
),
|
||||
reason = "maybeInviteOtherFaction"
|
||||
)
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
package net.eagle0.eagle.ai
|
||||
|
||||
import net.eagle0.eagle.{FactionId, ProvinceId}
|
||||
import net.eagle0.eagle.api.available_command.{MarchAvailableCommand, MarchCommandFromOneProvince}
|
||||
import net.eagle0.eagle.api.selected_command.MarchSelectedCommand
|
||||
import net.eagle0.eagle.common.combat_unit.CombatUnit
|
||||
import net.eagle0.eagle.library.util.{BattalionUtils, CommandSelection, ProvinceDistances}
|
||||
import net.eagle0.eagle.library.util.{BattalionUtils, ProvinceDistances, ScalaCommandSelection}
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.ProvinceGoldSurplusCalculator.provinceGoldSurplus
|
||||
import net.eagle0.eagle.library.util.EagleRequire.internalRequire
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.{MarchAvailable, MarchCommandFromOneProvince}
|
||||
import net.eagle0.eagle.model.state.command.selected.CombatUnit
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.MarchSelected
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
|
||||
object MarchTowardProvinceCommandChooser {
|
||||
def marchTowardProvinceCommand(
|
||||
ac: MarchAvailableCommand,
|
||||
ac: MarchAvailable,
|
||||
fid: FactionId,
|
||||
opmc: MarchCommandFromOneProvince,
|
||||
destinationProvinceId: ProvinceId,
|
||||
gs: GameState,
|
||||
favorLeaders: Boolean
|
||||
): Option[CommandSelection] = {
|
||||
): Option[ScalaCommandSelection] = {
|
||||
val bestCommand =
|
||||
opmc.availableDestinationProvinces
|
||||
.map(dest => (opmc, gs.provinces(dest.provinceId)))
|
||||
@@ -49,7 +49,7 @@ object MarchTowardProvinceCommandChooser {
|
||||
AIClientUtils.takenHeroIdsForMarchTowardFocus(
|
||||
originProvince = originProvince,
|
||||
destinationProvince = dest,
|
||||
availableHeroIds = opmc.availableHeroIds.toVector,
|
||||
availableHeroIds = opmc.availableHeroIds,
|
||||
favorLeaders = favorLeaders,
|
||||
factions = gs.factions.values.toVector,
|
||||
heroes = gs.heroes
|
||||
@@ -72,7 +72,7 @@ object MarchTowardProvinceCommandChooser {
|
||||
)
|
||||
.map {
|
||||
case (hid, bid) =>
|
||||
CombatUnit(factionId = fid, heroId = hid, battalionId = bid)
|
||||
CombatUnit(heroId = hid, battalionId = bid)
|
||||
}
|
||||
|
||||
val foodToTake = 2 * BattalionUtils.monthlyConsumedFood(
|
||||
@@ -80,11 +80,11 @@ object MarchTowardProvinceCommandChooser {
|
||||
gs.battalionTypes
|
||||
)
|
||||
val goldToTake = provinceGoldSurplus(originProvince)
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = fid,
|
||||
actingProvinceId = actingProvinceId,
|
||||
available = ac,
|
||||
selected = MarchSelectedCommand(
|
||||
selected = MarchSelected(
|
||||
marchingUnits = takenUnits, // Check the food cost here?
|
||||
destinationProvinceId = dest.id,
|
||||
originProvince = opmc.originProvinceId,
|
||||
|
||||
@@ -3,11 +3,6 @@ package net.eagle0.eagle.ai
|
||||
import net.eagle0.common.{FunctionalRandom, MoreOption, RandomState}
|
||||
import net.eagle0.eagle.{FactionId, ProvinceId}
|
||||
import net.eagle0.eagle.ai.AIClientUtils
|
||||
import net.eagle0.eagle.api.available_command.*
|
||||
import net.eagle0.eagle.api.command.OneProvinceAvailableCommands
|
||||
import net.eagle0.eagle.api.selected_command.{MarchSelectedCommand, ReconSelectedCommand}
|
||||
import net.eagle0.eagle.common.combat_unit.CombatUnit
|
||||
import net.eagle0.eagle.common.improvement_type.ImprovementType
|
||||
import net.eagle0.eagle.library.settings.{MinSupportForTaxes, MonthsReconConsideredRecent}
|
||||
import net.eagle0.eagle.library.util.*
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.{
|
||||
@@ -30,6 +25,12 @@ import net.eagle0.eagle.library.util.hero.HeroUtils
|
||||
import net.eagle0.eagle.library.util.province.ProvinceUtils
|
||||
import net.eagle0.eagle.library.util.EagleRequire.internalRequire
|
||||
import net.eagle0.eagle.library.util.ProvinceDistances
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.*
|
||||
import net.eagle0.eagle.model.state.command.available.OneProvinceAvailableCommands
|
||||
import net.eagle0.eagle.model.state.command.common.ImprovementType
|
||||
import net.eagle0.eagle.model.state.command.selected.CombatUnit
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.{MarchSelected, ReconSelected}
|
||||
import net.eagle0.eagle.model.state.date.Date.given
|
||||
import net.eagle0.eagle.model.state.faction.FactionRelationship as FactionRelationshipC
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
@@ -60,13 +61,13 @@ object MidGameAIClient {
|
||||
gs: GameState,
|
||||
opac: OneProvinceAvailableCommands,
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[CommandSelection] = {
|
||||
): RandomState[ScalaCommandSelection] = {
|
||||
validateNoFactionLeaderAlone(gs, factionId)
|
||||
|
||||
CommandChooser.choose(
|
||||
actingFactionId = factionId,
|
||||
gameState = gs,
|
||||
availableCommands = opac.commands.toVector,
|
||||
availableCommands = opac.commands,
|
||||
rankedChoosers = Vector[CommandChooser](
|
||||
(fid: FactionId, gs: GameState, acs: Vector[AvailableCommand], fr: FunctionalRandom) =>
|
||||
chosenUniversalCommand(fid, gs, acs, fr),
|
||||
@@ -128,15 +129,14 @@ object MidGameAIClient {
|
||||
factionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] =
|
||||
flatSelectionForType[SendSuppliesAvailableCommand](availableCommands) {
|
||||
case available @ SendSuppliesAvailableCommand(
|
||||
): Option[ScalaCommandSelection] =
|
||||
flatSelectionForType[SendSuppliesAvailable](availableCommands) {
|
||||
case available @ SendSuppliesAvailable(
|
||||
goldAvailable,
|
||||
foodAvailable,
|
||||
availableDestinationProvinceIds,
|
||||
actingProvinceId,
|
||||
_ /* availableHeroIds */,
|
||||
_ /* unknownFieldSet */
|
||||
_ /* availableHeroIds */
|
||||
) =>
|
||||
val actingProvince = gameState.provinces(actingProvinceId)
|
||||
val foodMonthsToHoldBack =
|
||||
@@ -216,7 +216,7 @@ object MidGameAIClient {
|
||||
chooser: CommandChooser,
|
||||
functionalRandom: FunctionalRandom,
|
||||
reason: String
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
chooser(actingFactionId, gs, acs, functionalRandom).map(
|
||||
_.map(_.withReason(reason))
|
||||
)
|
||||
@@ -227,7 +227,7 @@ object MidGameAIClient {
|
||||
acs: Vector[AvailableCommand],
|
||||
choosersAndReasons: Vector[(CommandChooser, String)],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] = choosersAndReasons match {
|
||||
): RandomState[Option[ScalaCommandSelection]] = choosersAndReasons match {
|
||||
case cr +: tail =>
|
||||
chosenGenericCommand(
|
||||
actingFactionId = actingFactionId,
|
||||
@@ -256,7 +256,7 @@ object MidGameAIClient {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
chosenGenericCommandFromRankedOptions(
|
||||
actingFactionId = actingFactionId,
|
||||
gs = gameState,
|
||||
@@ -327,7 +327,7 @@ object MidGameAIClient {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
provincesWithFactionLeader(actingFactionId, gameState).map { province =>
|
||||
MoreOption
|
||||
.flatWhen(province.rulingFactionHeroIds.size < 4)(
|
||||
@@ -400,7 +400,7 @@ object MidGameAIClient {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
provincesWithFactionLeader(actingFactionId, gameState).map { province =>
|
||||
MoreOption
|
||||
.flatWhen(province.rulingFactionHeroIds.size < 4)(
|
||||
@@ -486,7 +486,7 @@ object MidGameAIClient {
|
||||
actingFactionId: FactionId,
|
||||
gs: GameState,
|
||||
acs: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] = {
|
||||
): Option[ScalaCommandSelection] = {
|
||||
def reconnedFullInfoFor(provinceId: ProvinceId): Option[FullProvinceInfoC] =
|
||||
gs.factions(actingFactionId)
|
||||
.reconnedProvinces
|
||||
@@ -515,7 +515,7 @@ object MidGameAIClient {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
provinceId: ProvinceId
|
||||
): Option[CommandSelection] =
|
||||
): Option[ScalaCommandSelection] =
|
||||
MoreOption
|
||||
.flatWhen(
|
||||
gameState.provinces(provinceId).support < MinSupportForTaxes.doubleValue
|
||||
@@ -541,12 +541,12 @@ object MidGameAIClient {
|
||||
gameState: GameState,
|
||||
opac: OneProvinceAvailableCommands,
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[CommandSelection] =
|
||||
): RandomState[ScalaCommandSelection] =
|
||||
CommandChooser
|
||||
.choose(
|
||||
actingFactionId = actingFactionId,
|
||||
gameState = gameState,
|
||||
availableCommands = opac.commands.toVector,
|
||||
availableCommands = opac.commands,
|
||||
rankedChoosers = Vector[CommandChooser](
|
||||
(actingFactionId, gameState, availableCommands, functionalRandom) =>
|
||||
RandomState(
|
||||
@@ -682,8 +682,8 @@ object MidGameAIClient {
|
||||
gs: GameState,
|
||||
acs: Vector[AvailableCommand],
|
||||
factionId: FactionId
|
||||
): Option[CommandSelection] =
|
||||
flatSelectionForType[ImproveAvailableCommand](acs) { availableCommand =>
|
||||
): Option[ScalaCommandSelection] =
|
||||
flatSelectionForType[ImproveAvailable](acs) { availableCommand =>
|
||||
val province = gs.provinces(availableCommand.actingProvinceId)
|
||||
val existingBattalions = province.battalionIds
|
||||
.map(gs.battalions)
|
||||
@@ -706,7 +706,7 @@ object MidGameAIClient {
|
||||
actingFactionId = factionId,
|
||||
actingProvinceId = province.id,
|
||||
availableCommands = acs,
|
||||
improvementType = ImprovementType.DEVASTATION
|
||||
improvementType = ImprovementType.Devastation
|
||||
)
|
||||
.orElse {
|
||||
val neededAgriculture = notAvailable
|
||||
@@ -729,7 +729,7 @@ object MidGameAIClient {
|
||||
actingFactionId = factionId,
|
||||
actingProvinceId = province.id,
|
||||
availableCommands = acs,
|
||||
improvementType = ImprovementType.AGRICULTURE
|
||||
improvementType = ImprovementType.Agriculture
|
||||
)
|
||||
else
|
||||
ImproveCommandSelector
|
||||
@@ -737,7 +737,7 @@ object MidGameAIClient {
|
||||
actingFactionId = factionId,
|
||||
actingProvinceId = province.id,
|
||||
availableCommands = acs,
|
||||
improvementType = ImprovementType.ECONOMY
|
||||
improvementType = ImprovementType.Economy
|
||||
)
|
||||
end if
|
||||
}
|
||||
@@ -749,10 +749,10 @@ object MidGameAIClient {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] = {
|
||||
): RandomState[Option[ScalaCommandSelection]] = {
|
||||
def go(
|
||||
provincesRS: RandomState[Vector[ProvinceT]]
|
||||
): RandomState[Option[CommandSelection]] = provincesRS.continue {
|
||||
): RandomState[Option[ScalaCommandSelection]] = provincesRS.continue {
|
||||
case (province +: tail, fr) =>
|
||||
MoreOption
|
||||
.flatWhen(province.rulingFactionHeroIds.size < 6)(
|
||||
@@ -850,13 +850,13 @@ object MidGameAIClient {
|
||||
actingFactionId: FactionId,
|
||||
gs: GameState,
|
||||
acs: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] = {
|
||||
): Option[ScalaCommandSelection] = {
|
||||
val factionLeaderProvincesNeedingHeroes =
|
||||
provincesWithFactionLeader(actingFactionId, gs)
|
||||
.filter(p => p.rulingFactionHeroIds.size < p.heroCap)
|
||||
val cs = for {
|
||||
(marchCommand, _) <- acs.zipWithIndex.collectFirst {
|
||||
case (ac: MarchAvailableCommand, idx) => (ac, idx)
|
||||
case (ac: MarchAvailable, idx) => (ac, idx)
|
||||
}
|
||||
} yield {
|
||||
// Find the march command origin provinces that contain extra heroes
|
||||
@@ -924,14 +924,14 @@ object MidGameAIClient {
|
||||
private def selectedReconCommand(
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
ac: ReconAvailableCommand,
|
||||
ac: ReconAvailable,
|
||||
targetProvinceId: ProvinceId
|
||||
): CommandSelection =
|
||||
CommandSelection(
|
||||
): ScalaCommandSelection =
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = ac.actingProvinceId,
|
||||
available = ac,
|
||||
selected = ReconSelectedCommand(
|
||||
selected = ReconSelected(
|
||||
actingHeroId = ac.availableHeroIds.maxBy(hid => gameState.heroes(hid).vigor),
|
||||
targetProvinceId = targetProvinceId
|
||||
),
|
||||
@@ -942,8 +942,8 @@ object MidGameAIClient {
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
acs: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] =
|
||||
flatSelectionForType[ReconAvailableCommand](acs) { ac =>
|
||||
): Option[ScalaCommandSelection] =
|
||||
flatSelectionForType[ReconAvailable](acs) { ac =>
|
||||
val targetProvincesNeighboringMe = ac.availableTargetProvinces
|
||||
.map(gameState.provinces)
|
||||
.filter(_.rulingFactionId.exists(_ != actingFactionId))
|
||||
@@ -1010,11 +1010,11 @@ object MidGameAIClient {
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
acs: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] = {
|
||||
): Option[ScalaCommandSelection] = {
|
||||
val faction = gameState.factions(actingFactionId)
|
||||
val factionLeaders = faction.leaderIds
|
||||
flatSelectionForType[MarchAvailableCommand](acs) { marchAvailableCommand =>
|
||||
marchAvailableCommand.oneProvinceCommands.flatMap { opmc =>
|
||||
flatSelectionForType[MarchAvailable](acs) { marchAvailable =>
|
||||
marchAvailable.oneProvinceCommands.flatMap { opmc =>
|
||||
val originProvince = gameState.provinces(opmc.originProvinceId)
|
||||
val leadersInOriginProvince =
|
||||
originProvince.rulingFactionHeroIds.intersect(factionLeaders)
|
||||
@@ -1040,18 +1040,17 @@ object MidGameAIClient {
|
||||
) // don't send a leader into a province under attack
|
||||
|
||||
validDestinations.minByOption(_.rulingFactionHeroIds.size).map { destinationProvince =>
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = marchAvailableCommand.actingProvinceId,
|
||||
available = marchAvailableCommand,
|
||||
selected = MarchSelectedCommand(
|
||||
actingProvinceId = marchAvailable.actingProvinceId,
|
||||
available = marchAvailable,
|
||||
selected = MarchSelected(
|
||||
gold = 0,
|
||||
food = 0,
|
||||
originProvince = originProvince.id,
|
||||
destinationProvinceId = destinationProvince.id,
|
||||
marchingUnits = Vector(
|
||||
CombatUnit(
|
||||
factionId = actingFactionId,
|
||||
heroId = leaderIdToMove,
|
||||
battalionId = None
|
||||
)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package net.eagle0.eagle.ai
|
||||
|
||||
import net.eagle0.eagle.{FactionId, ProvinceId}
|
||||
import net.eagle0.eagle.api.available_command.{AvailableCommand, MarchAvailableCommand, MarchCommandFromOneProvince}
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ProvinceDistances
|
||||
import net.eagle0.eagle.library.util.ProvinceDistances.ProvinceAndDistance
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.{MarchAvailable, MarchCommandFromOneProvince}
|
||||
import net.eagle0.eagle.model.state.faction.FactionT
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
|
||||
@@ -21,7 +22,7 @@ object MoveLeaderToBetterProvinceCommandChooser {
|
||||
actingFactionId: FactionId,
|
||||
gs: GameState,
|
||||
acs: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] =
|
||||
): Option[ScalaCommandSelection] =
|
||||
maybeMoveLeaderToBetterProvinceCommandWithChooser(
|
||||
actingFactionId = actingFactionId,
|
||||
gs = gs,
|
||||
@@ -31,11 +32,11 @@ object MoveLeaderToBetterProvinceCommandChooser {
|
||||
)
|
||||
|
||||
private def candidatesForMarchCommand(
|
||||
marchCommand: MarchAvailableCommand,
|
||||
marchCommand: MarchAvailable,
|
||||
gs: GameState,
|
||||
faction: FactionT
|
||||
): Vector[MarchCommandFromOneProvince] =
|
||||
marchCommand.oneProvinceCommands.toVector.filter { opmc =>
|
||||
marchCommand.oneProvinceCommands.filter { opmc =>
|
||||
val originProvince = gs.provinces(opmc.originProvinceId)
|
||||
if opmc.availableHeroIds.intersect(faction.leaderIds).isEmpty then false
|
||||
else if originProvince.rulingFactionHeroIds.length < 2 then false
|
||||
@@ -57,7 +58,7 @@ object MoveLeaderToBetterProvinceCommandChooser {
|
||||
ProvinceDistances
|
||||
.closestProvinceThroughFriendliesOption(
|
||||
desiredPid,
|
||||
mcfop.availableDestinationProvinces.map(_.provinceId).toVector,
|
||||
mcfop.availableDestinationProvinces.map(_.provinceId),
|
||||
actingFactionId,
|
||||
gs.provinces
|
||||
)
|
||||
@@ -75,10 +76,10 @@ object MoveLeaderToBetterProvinceCommandChooser {
|
||||
gs: GameState,
|
||||
acs: Vector[AvailableCommand],
|
||||
betterDestinationChooser: DestinationChooser
|
||||
): Option[CommandSelection] = {
|
||||
): Option[ScalaCommandSelection] = {
|
||||
val cs = for {
|
||||
faction <- gs.factions.get(actingFactionId)
|
||||
marchCommand <- acs.collectFirst { case ac: MarchAvailableCommand => ac }
|
||||
marchCommand <- acs.collectFirst { case ac: MarchAvailable => ac }
|
||||
} yield {
|
||||
// Find the march command origin provinces that contain a faction leader
|
||||
val candidatesWithDistances = candidateCommandsWithDistances(
|
||||
|
||||
@@ -1,42 +1,25 @@
|
||||
package net.eagle0.eagle.ai
|
||||
|
||||
import net.eagle0.common.{FunctionalRandom, RandomState}
|
||||
import net.eagle0.eagle.api.available_command.{
|
||||
AvailableCommand,
|
||||
ResolveAllianceOfferAvailableCommand,
|
||||
ResolveBreakAllianceAvailableCommand,
|
||||
ResolveInvitationAvailableCommand,
|
||||
ResolveRansomOfferAvailableCommand,
|
||||
ResolveTruceOfferAvailableCommand
|
||||
}
|
||||
import net.eagle0.eagle.api.selected_command.{
|
||||
ResolveAllianceOfferSelectedCommand,
|
||||
ResolveBreakAllianceSelectedCommand,
|
||||
ResolveInvitationSelectedCommand,
|
||||
ResolveRansomOfferSelectedCommand,
|
||||
ResolveTruceOfferSelectedCommand,
|
||||
SelectedCommand
|
||||
}
|
||||
import net.eagle0.eagle.common.diplomacy_offer.RansomOfferDetails
|
||||
import net.eagle0.eagle.common.diplomacy_offer_status.DiplomacyOfferStatus.{
|
||||
DIPLOMACY_OFFER_STATUS_ACCEPTED,
|
||||
DIPLOMACY_OFFER_STATUS_IMPRISONED,
|
||||
DIPLOMACY_OFFER_STATUS_REJECTED
|
||||
}
|
||||
import net.eagle0.eagle.library.settings.{
|
||||
AiAllianceAcceptanceBaseChance,
|
||||
AiTruceAcceptanceBaseChance,
|
||||
MinimumPrestigeDifferenceToInvite
|
||||
}
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.{CommandChooser, RansomOfferHelpers}
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.AvailableCommandSelector.{
|
||||
randomSelectionForType,
|
||||
selectionForType
|
||||
}
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.CommandChooser
|
||||
import net.eagle0.eagle.library.util.faction_utils.FactionUtils
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.EagleRequire.internalRequire
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.library.EagleInternalException
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.*
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.*
|
||||
import net.eagle0.eagle.model.state.diplomacy_offer.status.{Accepted, Imprisoned, Rejected, Status}
|
||||
import net.eagle0.eagle.model.state.faction.FactionT
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.province.ProvinceT
|
||||
@@ -50,7 +33,7 @@ object ResolveDiplomacyCommandSelector {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
CommandChooser.choose(
|
||||
actingFactionId = actingFactionId,
|
||||
gameState = gameState,
|
||||
@@ -70,8 +53,8 @@ object ResolveDiplomacyCommandSelector {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
randomSelectionForType[ResolveInvitationAvailableCommand](
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
randomSelectionForType[ResolveInvitationAvailable](
|
||||
availableCommands,
|
||||
functionalRandom
|
||||
) {
|
||||
@@ -83,7 +66,7 @@ object ResolveDiplomacyCommandSelector {
|
||||
functionalRandom = fr
|
||||
).map { resolveInviteSelection =>
|
||||
Some(
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = 0,
|
||||
available = resolveInvitationAc,
|
||||
@@ -96,7 +79,7 @@ object ResolveDiplomacyCommandSelector {
|
||||
|
||||
private def selectionForResolveInvitationCommand(
|
||||
actingFactionId: FactionId,
|
||||
ac: ResolveInvitationAvailableCommand,
|
||||
ac: ResolveInvitationAvailable,
|
||||
gs: GameState,
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[SelectedCommand] = functionalRandom.nextDouble.map { roll =>
|
||||
@@ -104,20 +87,20 @@ object ResolveDiplomacyCommandSelector {
|
||||
val factions = gs.factions.values.toVector
|
||||
val provinces = gs.provinces.values.toVector
|
||||
val bestInvitation = ac.invitations
|
||||
.maxBy(inv => invitationAcceptanceChance(inv.originatingFactionId, invitedFid, factions, provinces))
|
||||
.maxBy(inv => invitationAcceptanceChance(inv.offeringFactionId, invitedFid, factions, provinces))
|
||||
|
||||
internalRequire(
|
||||
bestInvitation.eligibleStatuses.contains(DIPLOMACY_OFFER_STATUS_ACCEPTED),
|
||||
bestInvitation.eligibleStatuses.contains(Accepted),
|
||||
"Cannot handle invitation without ACCEPTED option"
|
||||
)
|
||||
internalRequire(
|
||||
bestInvitation.eligibleStatuses.contains(DIPLOMACY_OFFER_STATUS_REJECTED),
|
||||
bestInvitation.eligibleStatuses.contains(Rejected),
|
||||
"Cannot handle invitation without REJECTED option"
|
||||
)
|
||||
|
||||
val bestOriginatingFid = bestInvitation.originatingFactionId
|
||||
val bestOriginatingFid = bestInvitation.offeringFactionId
|
||||
|
||||
ResolveInvitationSelectedCommand(
|
||||
ResolveInvitationSelected(
|
||||
originatingFactionId = bestOriginatingFid,
|
||||
resolution =
|
||||
if 100.0 * roll < invitationAcceptanceChance(
|
||||
@@ -126,8 +109,8 @@ object ResolveDiplomacyCommandSelector {
|
||||
factions,
|
||||
provinces
|
||||
)
|
||||
then DIPLOMACY_OFFER_STATUS_ACCEPTED
|
||||
else DIPLOMACY_OFFER_STATUS_REJECTED
|
||||
then Accepted
|
||||
else Rejected
|
||||
)
|
||||
}
|
||||
|
||||
@@ -149,8 +132,8 @@ object ResolveDiplomacyCommandSelector {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
randomSelectionForType[ResolveTruceOfferAvailableCommand](
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
randomSelectionForType[ResolveTruceOfferAvailable](
|
||||
availableCommands,
|
||||
functionalRandom
|
||||
) {
|
||||
@@ -162,7 +145,7 @@ object ResolveDiplomacyCommandSelector {
|
||||
functionalRandom = fr
|
||||
).map { resolveTruceOfferSelection =>
|
||||
Some(
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = 0,
|
||||
available = resolveTruceAc,
|
||||
@@ -175,7 +158,7 @@ object ResolveDiplomacyCommandSelector {
|
||||
|
||||
private def selectionForResolveTruceOfferSelectedCommand(
|
||||
actingFactionId: FactionId,
|
||||
ac: ResolveTruceOfferAvailableCommand,
|
||||
ac: ResolveTruceOfferAvailable,
|
||||
gs: GameState,
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[SelectedCommand] = functionalRandom.nextDouble.map { roll =>
|
||||
@@ -183,20 +166,20 @@ object ResolveDiplomacyCommandSelector {
|
||||
val factions = gs.factions.values.toVector
|
||||
val provinces = gs.provinces.values.toVector
|
||||
val bestOffer = ac.offers
|
||||
.maxBy(inv => truceOfferAcceptanceChance(inv.originatingFactionId, actingFid, factions, provinces))
|
||||
.maxBy(inv => truceOfferAcceptanceChance(inv.offeringFactionId, actingFid, factions, provinces))
|
||||
|
||||
internalRequire(
|
||||
bestOffer.eligibleStatuses.contains(DIPLOMACY_OFFER_STATUS_ACCEPTED),
|
||||
bestOffer.eligibleStatuses.contains(Accepted),
|
||||
"Cannot handle truce offer without ACCEPTED option"
|
||||
)
|
||||
internalRequire(
|
||||
bestOffer.eligibleStatuses.contains(DIPLOMACY_OFFER_STATUS_REJECTED),
|
||||
bestOffer.eligibleStatuses.contains(Rejected),
|
||||
"Cannot handle truce offer without REJECTED option"
|
||||
)
|
||||
|
||||
val bestOriginatingFid = bestOffer.originatingFactionId
|
||||
val bestOriginatingFid = bestOffer.offeringFactionId
|
||||
|
||||
ResolveTruceOfferSelectedCommand(
|
||||
ResolveTruceOfferSelected(
|
||||
originatingFactionId = bestOriginatingFid,
|
||||
resolution =
|
||||
if 100.0 * roll < truceOfferAcceptanceChance(
|
||||
@@ -205,8 +188,8 @@ object ResolveDiplomacyCommandSelector {
|
||||
factions = factions,
|
||||
provinces = provinces
|
||||
)
|
||||
then DIPLOMACY_OFFER_STATUS_ACCEPTED
|
||||
else DIPLOMACY_OFFER_STATUS_REJECTED
|
||||
then Accepted
|
||||
else Rejected
|
||||
)
|
||||
}
|
||||
|
||||
@@ -270,9 +253,9 @@ object ResolveDiplomacyCommandSelector {
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] =
|
||||
selectionForType[ResolveRansomOfferAvailableCommand](availableCommands) { resolveRansomAc =>
|
||||
CommandSelection(
|
||||
): Option[ScalaCommandSelection] =
|
||||
selectionForType[ResolveRansomOfferAvailable](availableCommands) { resolveRansomAc =>
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = 0,
|
||||
available = resolveRansomAc,
|
||||
@@ -284,25 +267,26 @@ object ResolveDiplomacyCommandSelector {
|
||||
}
|
||||
|
||||
private def selectionForResolveRansomOfferSelectedCommand(
|
||||
ac: ResolveRansomOfferAvailableCommand
|
||||
): SelectedCommand =
|
||||
ac.offers.head.offerDetails match {
|
||||
case rod: RansomOfferDetails =>
|
||||
ResolveRansomOfferSelectedCommand(
|
||||
offeringFactionId = ac.offers.head.originatingFactionId,
|
||||
ransomOffer = Some(ac.offers.head),
|
||||
resolution = RansomOfferHelpers.chosenResolution(rod)
|
||||
)
|
||||
case _ => throw new EagleInternalException("Not a ransom offer")
|
||||
}
|
||||
ac: ResolveRansomOfferAvailable
|
||||
): SelectedCommand = {
|
||||
val offer = ac.offers.head
|
||||
// TODO: Proper scoring requires ransom details not currently in DiplomacyOfferInfo
|
||||
// For now, accept all ransom offers
|
||||
val resolution = if offer.eligibleStatuses.contains(Accepted) then Accepted else Rejected
|
||||
ResolveRansomOfferSelected(
|
||||
offeringFactionId = offer.offeringFactionId,
|
||||
prisonerHeroId = offer.heroId.get,
|
||||
resolution = resolution
|
||||
)
|
||||
}
|
||||
|
||||
private def resolveAllianceOfferSelectedCommand(
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
randomSelectionForType[ResolveAllianceOfferAvailableCommand](
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
randomSelectionForType[ResolveAllianceOfferAvailable](
|
||||
availableCommands,
|
||||
functionalRandom
|
||||
) {
|
||||
@@ -314,7 +298,7 @@ object ResolveDiplomacyCommandSelector {
|
||||
functionalRandom = fr
|
||||
).map { resolveAllianceOfferSelection =>
|
||||
Some(
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = 0,
|
||||
available = resolveAllianceAc,
|
||||
@@ -330,8 +314,8 @@ object ResolveDiplomacyCommandSelector {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
randomSelectionForType[ResolveBreakAllianceAvailableCommand](
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
randomSelectionForType[ResolveBreakAllianceAvailable](
|
||||
availableCommands,
|
||||
functionalRandom
|
||||
) {
|
||||
@@ -341,7 +325,7 @@ object ResolveDiplomacyCommandSelector {
|
||||
functionalRandom = fr
|
||||
).map { resolveBreakAllianceSelection =>
|
||||
Some(
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = 0,
|
||||
available = resolveBreakAllianceAc,
|
||||
@@ -354,7 +338,7 @@ object ResolveDiplomacyCommandSelector {
|
||||
|
||||
private def selectionForResolveAllianceOfferSelectedCommand(
|
||||
actingFactionId: FactionId,
|
||||
ac: ResolveAllianceOfferAvailableCommand,
|
||||
ac: ResolveAllianceOfferAvailable,
|
||||
gs: GameState,
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[SelectedCommand] = functionalRandom.nextDouble.map { roll =>
|
||||
@@ -362,20 +346,20 @@ object ResolveDiplomacyCommandSelector {
|
||||
val factions = gs.factions.values.toVector
|
||||
val provinces = gs.provinces.values.toVector
|
||||
val bestOffer = ac.offers
|
||||
.maxBy(inv => allianceOfferAcceptanceChance(inv.originatingFactionId, actingFid, factions, provinces))
|
||||
.maxBy(inv => allianceOfferAcceptanceChance(inv.offeringFactionId, actingFid, factions, provinces))
|
||||
|
||||
internalRequire(
|
||||
bestOffer.eligibleStatuses.contains(DIPLOMACY_OFFER_STATUS_ACCEPTED),
|
||||
bestOffer.eligibleStatuses.contains(Accepted),
|
||||
"Cannot handle alliance offer without ACCEPTED option"
|
||||
)
|
||||
internalRequire(
|
||||
bestOffer.eligibleStatuses.contains(DIPLOMACY_OFFER_STATUS_REJECTED),
|
||||
bestOffer.eligibleStatuses.contains(Rejected),
|
||||
"Cannot handle alliance offer without REJECTED option"
|
||||
)
|
||||
|
||||
val bestOriginatingFid = bestOffer.originatingFactionId
|
||||
val bestOriginatingFid = bestOffer.offeringFactionId
|
||||
|
||||
ResolveAllianceOfferSelectedCommand(
|
||||
ResolveAllianceOfferSelected(
|
||||
originatingFactionId = bestOriginatingFid,
|
||||
resolution =
|
||||
if 100.0 * roll < allianceOfferAcceptanceChance(
|
||||
@@ -384,26 +368,26 @@ object ResolveDiplomacyCommandSelector {
|
||||
factions = factions,
|
||||
provinces = provinces
|
||||
)
|
||||
then DIPLOMACY_OFFER_STATUS_ACCEPTED
|
||||
else DIPLOMACY_OFFER_STATUS_REJECTED
|
||||
then Accepted
|
||||
else Rejected
|
||||
)
|
||||
}
|
||||
|
||||
// FIXME: always imprison ambassadors for now
|
||||
// Note: doesn't use gameState or functionalRandom roll
|
||||
private def selectionForResolveBreakAllianceSelectedCommand(
|
||||
ac: ResolveBreakAllianceAvailableCommand,
|
||||
ac: ResolveBreakAllianceAvailable,
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[SelectedCommand] = functionalRandom.nextDouble.map { _ =>
|
||||
val offer = ac.offers.head
|
||||
|
||||
ResolveBreakAllianceSelectedCommand(
|
||||
originatingFactionId = ac.offers.head.originatingFactionId,
|
||||
ResolveBreakAllianceSelected(
|
||||
originatingFactionId = offer.offeringFactionId,
|
||||
resolution =
|
||||
if offer.eligibleStatuses.contains(DIPLOMACY_OFFER_STATUS_IMPRISONED)
|
||||
then DIPLOMACY_OFFER_STATUS_IMPRISONED
|
||||
else if offer.eligibleStatuses.contains(DIPLOMACY_OFFER_STATUS_ACCEPTED)
|
||||
then DIPLOMACY_OFFER_STATUS_ACCEPTED
|
||||
if offer.eligibleStatuses.contains(Imprisoned)
|
||||
then Imprisoned
|
||||
else if offer.eligibleStatuses.contains(Accepted)
|
||||
then Accepted
|
||||
else
|
||||
throw new EagleInternalException(
|
||||
"Unable to handle a break alliance command without IMPRISONED or ACCEPTED options"
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package net.eagle0.eagle.ai
|
||||
|
||||
import net.eagle0.common.MoreOption
|
||||
import net.eagle0.eagle.api.available_command.{AvailableCommand, MarchAvailableCommand}
|
||||
import net.eagle0.eagle.api.selected_command.MarchSelectedCommand
|
||||
import net.eagle0.eagle.common.combat_unit.CombatUnit
|
||||
import net.eagle0.eagle.library.settings.{LoyaltyGainFromFeast, MinimumLoyaltyForSwearBrotherhood}
|
||||
import net.eagle0.eagle.library.util.{CommandSelection, ProvinceDistances}
|
||||
import net.eagle0.eagle.library.util.{ProvinceDistances, ScalaCommandSelection}
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.{
|
||||
CommandChoiceHelpers,
|
||||
HeroGiftCommandSelector,
|
||||
@@ -14,6 +11,10 @@ import net.eagle0.eagle.library.util.command_choice_helpers.{
|
||||
}
|
||||
import net.eagle0.eagle.library.util.faction_utils.FactionUtils
|
||||
import net.eagle0.eagle.library.util.hero.HeroUtils
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.MarchAvailable
|
||||
import net.eagle0.eagle.model.state.command.selected.CombatUnit
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.MarchSelected
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.hero.HeroT
|
||||
import net.eagle0.eagle.model.state.province.ProvinceT
|
||||
@@ -32,12 +33,12 @@ object SeekMoreLeadersCommandChooser {
|
||||
|
||||
case class Candidate(hero: HeroT, province: ProvinceT)
|
||||
private def maybeMoveTowardDestination(
|
||||
command: MarchAvailableCommand,
|
||||
command: MarchAvailable,
|
||||
hero: HeroT,
|
||||
startingProvince: ProvinceT,
|
||||
factionHeadProvince: ProvinceT,
|
||||
gameState: GameState
|
||||
): Option[CommandSelection] = {
|
||||
): Option[ScalaCommandSelection] = {
|
||||
val opmc = command.oneProvinceCommands
|
||||
.find(_.originProvinceId == startingProvince.id)
|
||||
.get
|
||||
@@ -58,14 +59,13 @@ object SeekMoreLeadersCommandChooser {
|
||||
.minByOption(_._3)
|
||||
|
||||
bestDestination.map { destPid =>
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = factionHeadProvince.rulingFactionId.get,
|
||||
actingProvinceId = command.actingProvinceId,
|
||||
available = command,
|
||||
selected = MarchSelectedCommand(
|
||||
selected = MarchSelected(
|
||||
marchingUnits = Vector(
|
||||
CombatUnit(
|
||||
factionId = factionHeadProvince.rulingFactionId.get,
|
||||
heroId = hero.id,
|
||||
battalionId = None
|
||||
)
|
||||
@@ -84,7 +84,7 @@ object SeekMoreLeadersCommandChooser {
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
acs: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] = {
|
||||
): Option[ScalaCommandSelection] = {
|
||||
val provincesVector = gameState.provinces.values.toVector
|
||||
FactionUtils
|
||||
.provinces(actingFactionId, provincesVector)
|
||||
@@ -106,7 +106,7 @@ object SeekMoreLeadersCommandChooser {
|
||||
.map(hero => Candidate(hero, province))
|
||||
}
|
||||
|
||||
val marchACs = acs.collect { case ac: MarchAvailableCommand => ac }
|
||||
val marchACs = acs.collect { case ac: MarchAvailable => ac }
|
||||
|
||||
val marchableCandidates = candidates.flatMap { c =>
|
||||
marchACs.find { mac =>
|
||||
@@ -137,7 +137,7 @@ object SeekMoreLeadersCommandChooser {
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
acs: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] = {
|
||||
): Option[ScalaCommandSelection] = {
|
||||
val faction = gameState.factions(actingFactionId)
|
||||
gameState.provinces.values
|
||||
.find(_.rulingFactionHeroIds.contains(faction.factionHeadId))
|
||||
|
||||
@@ -460,7 +460,6 @@ 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/types",
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters/command/available:available_command_converter",
|
||||
"//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/game_state",
|
||||
@@ -1304,7 +1303,6 @@ scala_library(
|
||||
],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/common:province_order_type_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//src/main/scala/net/eagle0/common:more_option",
|
||||
@@ -1319,7 +1317,6 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers:command_chooser",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/province",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result:action_result_trait",
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters/command/available:available_command_converter",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/province",
|
||||
@@ -1342,7 +1339,6 @@ scala_library(
|
||||
],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/library/actions/applier:action_result_applier",
|
||||
@@ -1354,7 +1350,6 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/province",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result:action_result_trait",
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters/command/available:available_command_converter",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/province",
|
||||
|
||||
+3
-8
@@ -11,7 +11,6 @@ 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.ActionResultType.EndHandleRiotsPhase
|
||||
import net.eagle0.eagle.model.action_result.ActionResultT
|
||||
import net.eagle0.eagle.model.proto_converters.command.available.AvailableCommandConverter
|
||||
import net.eagle0.eagle.model.state.command.available.OneProvinceAvailableCommands
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.province.ProvinceT
|
||||
@@ -39,19 +38,15 @@ case class EndHandleRiotsPhaseAction(
|
||||
commandsForProvince(province.id).map { opac =>
|
||||
seq.withRandomActionResults { (gs, fr) =>
|
||||
val actingFactionId = province.rulingFactionId.get
|
||||
val protoCommands = opac.commands.map { cmd =>
|
||||
AvailableCommandConverter.toProto(cmd, gs, actingFactionId)
|
||||
}
|
||||
CommandChoiceHelpers
|
||||
.handleRiotSelectedCommand(
|
||||
actingFactionId = actingFactionId,
|
||||
gameState = gs,
|
||||
availableCommands = protoCommands,
|
||||
availableCommands = opac.commands,
|
||||
functionalRandom = fr
|
||||
)
|
||||
.continue {
|
||||
case (Some(cs), nextFr) =>
|
||||
val scs = cs.toScala(opac.commands)
|
||||
case (Some(scs), nextFr) =>
|
||||
val cmd = commandFactory.makeTCommand(
|
||||
actingFactionId = province.rulingFactionId.get,
|
||||
gameState = gs,
|
||||
@@ -66,7 +61,7 @@ case class EndHandleRiotsPhaseAction(
|
||||
case TCommand.Sequential(action) =>
|
||||
RandomState(action.results, nextFr)
|
||||
}
|
||||
case (None, nextFr) =>
|
||||
case (None, nextFr) =>
|
||||
RandomState(Vector.empty[ActionResultT], nextFr)
|
||||
}
|
||||
}
|
||||
|
||||
+48
-53
@@ -2,17 +2,16 @@ package net.eagle0.eagle.library.actions.impl.action
|
||||
|
||||
import net.eagle0.common.{FunctionalRandom, MoreOption, RandomState}
|
||||
import net.eagle0.eagle.{FactionId, ProvinceId}
|
||||
import net.eagle0.eagle.api.available_command.{AvailableCommand as ProtoAvailableCommand, RestAvailableCommand}
|
||||
import net.eagle0.eagle.library.actions.applier.ActionResultApplier
|
||||
import net.eagle0.eagle.library.actions.impl.command.TCommandFactory
|
||||
import net.eagle0.eagle.library.actions.impl.common.{ProtolessRandomSequentialResultsAction, TCommand}
|
||||
import net.eagle0.eagle.library.actions.random_state_sequencer.RandomStateSequencer
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.CommandChooser
|
||||
import net.eagle0.eagle.library.util.province.ProvinceUtils
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.action_result.ActionResultT
|
||||
import net.eagle0.eagle.model.proto_converters.command.available.AvailableCommandConverter
|
||||
import net.eagle0.eagle.model.state.command.available.OneProvinceAvailableCommands
|
||||
import net.eagle0.eagle.model.state.command.available.{AvailableCommand, OneProvinceAvailableCommands}
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.RestAvailable
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.province.ProvinceOrderType.*
|
||||
import net.eagle0.eagle.model.state.province.ProvinceT
|
||||
@@ -47,11 +46,10 @@ case class PerformVassalCommandsPhaseAction(
|
||||
case (sequencer, province) =>
|
||||
commandsForProvince(province.id).map { opac =>
|
||||
sequencer.withRandomActionResults { (gs, fr) =>
|
||||
chooseCommand(gs, province.id, fr).continue {
|
||||
case (Some(cs), nextFr) =>
|
||||
val scs = cs.toScala(opac.commands)
|
||||
chooseCommand(gs, province.id, opac.commands, fr).continue {
|
||||
case (Some(scs), nextFr) =>
|
||||
val cmd = commandFactory.makeTCommand(
|
||||
actingFactionId = cs.actingFactionId,
|
||||
actingFactionId = scs.actingFactionId,
|
||||
gameState = gs,
|
||||
availableCommand = scs.available,
|
||||
selectedCommand = scs.selected
|
||||
@@ -64,7 +62,7 @@ case class PerformVassalCommandsPhaseAction(
|
||||
case TCommand.Sequential(action) =>
|
||||
RandomState(action.results, nextFr)
|
||||
}
|
||||
case (None, nextFr) =>
|
||||
case (None, nextFr) =>
|
||||
RandomState(Vector.empty[ActionResultT], nextFr)
|
||||
}
|
||||
}
|
||||
@@ -76,15 +74,15 @@ case class PerformVassalCommandsPhaseAction(
|
||||
private def maybeRestCommand(
|
||||
actingFactionId: FactionId,
|
||||
gs: GameState,
|
||||
commandOptions: Vector[ProtoAvailableCommand],
|
||||
commandOptions: Vector[AvailableCommand],
|
||||
provinceId: ProvinceId,
|
||||
reason: String
|
||||
): Option[CommandSelection] = {
|
||||
): Option[ScalaCommandSelection] = {
|
||||
val heroes =
|
||||
gs.provinces(provinceId).rulingFactionHeroIds.map(gs.heroes)
|
||||
MoreOption.flatWhen(
|
||||
commandOptions.collectFirst {
|
||||
case ac: RestAvailableCommand =>
|
||||
case ac: RestAvailable =>
|
||||
ac
|
||||
}.isDefined && shouldRest(heroes)
|
||||
) {
|
||||
@@ -95,10 +93,10 @@ case class PerformVassalCommandsPhaseAction(
|
||||
private def selectedCommandFromOrders(
|
||||
actingFactionId: FactionId,
|
||||
gs: GameState,
|
||||
commandOptions: Vector[ProtoAvailableCommand],
|
||||
commandOptions: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom,
|
||||
provinceId: ProvinceId
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
gs.provinces(provinceId).provinceOrders match {
|
||||
case Entrust =>
|
||||
chosenEntrustCommand(
|
||||
@@ -145,45 +143,42 @@ case class PerformVassalCommandsPhaseAction(
|
||||
def chooseCommand(
|
||||
gs: GameState,
|
||||
provinceId: ProvinceId,
|
||||
commands: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
commandsForProvince(provinceId).map { oneProvinceAvailableCommands =>
|
||||
val actingFactionId = gs.provinces(provinceId).rulingFactionId.get
|
||||
val protoCommands = oneProvinceAvailableCommands.commands.map { cmd =>
|
||||
AvailableCommandConverter.toProto(cmd, gs, actingFactionId)
|
||||
}
|
||||
CommandChooser.choose(
|
||||
actingFactionId,
|
||||
gs,
|
||||
protoCommands,
|
||||
Vector[CommandChooser](
|
||||
resolveTributeSelectedCommand,
|
||||
defendSelectedCommand,
|
||||
handleRiotSelectedCommand,
|
||||
(
|
||||
fid: FactionId,
|
||||
gsC: GameState,
|
||||
acs: Vector[ProtoAvailableCommand],
|
||||
fr: FunctionalRandom
|
||||
) =>
|
||||
RandomState(
|
||||
maybeRestCommand(
|
||||
fid,
|
||||
gsC,
|
||||
acs,
|
||||
provinceId,
|
||||
"chosen vassal command: rest"
|
||||
),
|
||||
fr
|
||||
): RandomState[Option[ScalaCommandSelection]] = {
|
||||
val actingFactionId = gs.provinces(provinceId).rulingFactionId.get
|
||||
CommandChooser.choose(
|
||||
actingFactionId,
|
||||
gs,
|
||||
commands,
|
||||
Vector[CommandChooser](
|
||||
resolveTributeSelectedCommand,
|
||||
defendSelectedCommand,
|
||||
handleRiotSelectedCommand,
|
||||
(
|
||||
fid: FactionId,
|
||||
gsC: GameState,
|
||||
acs: Vector[AvailableCommand],
|
||||
fr: FunctionalRandom
|
||||
) =>
|
||||
RandomState(
|
||||
maybeRestCommand(
|
||||
fid,
|
||||
gsC,
|
||||
acs,
|
||||
provinceId,
|
||||
"chosen vassal command: rest"
|
||||
),
|
||||
(
|
||||
fid: FactionId,
|
||||
gsC: GameState,
|
||||
acs: Vector[ProtoAvailableCommand],
|
||||
fr: FunctionalRandom
|
||||
) => selectedCommandFromOrders(fid, gsC, acs, fr, provinceId)
|
||||
),
|
||||
functionalRandom
|
||||
)
|
||||
}.get
|
||||
fr
|
||||
),
|
||||
(
|
||||
fid: FactionId,
|
||||
gsC: GameState,
|
||||
acs: Vector[AvailableCommand],
|
||||
fr: FunctionalRandom
|
||||
) => selectedCommandFromOrders(fid, gsC, acs, fr, provinceId)
|
||||
),
|
||||
functionalRandom
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+8
-15
@@ -1,17 +1,15 @@
|
||||
package net.eagle0.eagle.library.actions.impl.action
|
||||
|
||||
import net.eagle0.common.{FunctionalRandom, RandomState}
|
||||
import net.eagle0.eagle.api.available_command.AvailableCommand as ProtoAvailableCommand
|
||||
import net.eagle0.eagle.library.actions.applier.ActionResultApplier
|
||||
import net.eagle0.eagle.library.actions.impl.command.TCommandFactory
|
||||
import net.eagle0.eagle.library.actions.impl.common.{ProtolessRandomSequentialResultsAction, TCommand}
|
||||
import net.eagle0.eagle.library.actions.random_state_sequencer.RandomStateSequencer
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.CommandChoiceHelpers
|
||||
import net.eagle0.eagle.library.util.province.ProvinceUtils
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.action_result.ActionResultT
|
||||
import net.eagle0.eagle.model.proto_converters.command.available.AvailableCommandConverter
|
||||
import net.eagle0.eagle.model.state.command.available.OneProvinceAvailableCommands
|
||||
import net.eagle0.eagle.model.state.command.available.{AvailableCommand, OneProvinceAvailableCommands}
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.province.ProvinceT
|
||||
import net.eagle0.eagle.ProvinceId
|
||||
@@ -43,15 +41,10 @@ case class PerformVassalDefenseDecisionsAction(
|
||||
case (sequencer, province) =>
|
||||
commandsForProvince(province.id).map { opac =>
|
||||
sequencer.withRandomActionResults { (gs, fr) =>
|
||||
val actingFactionId = province.rulingFactionId.get
|
||||
val protoCommands = opac.commands.map { cmd =>
|
||||
AvailableCommandConverter.toProto(cmd, gs, actingFactionId)
|
||||
}
|
||||
chooseCommand(gs, province.id, protoCommands, fr).continue {
|
||||
case (Some(cs), nextFr) =>
|
||||
val scs = cs.toScala(opac.commands)
|
||||
chooseCommand(gs, province.id, opac.commands, fr).continue {
|
||||
case (Some(scs), nextFr) =>
|
||||
val cmd = commandFactory.makeTCommand(
|
||||
actingFactionId = cs.actingFactionId,
|
||||
actingFactionId = scs.actingFactionId,
|
||||
gameState = gs,
|
||||
availableCommand = scs.available,
|
||||
selectedCommand = scs.selected
|
||||
@@ -64,7 +57,7 @@ case class PerformVassalDefenseDecisionsAction(
|
||||
case TCommand.Sequential(action) =>
|
||||
RandomState(action.results, nextFr)
|
||||
}
|
||||
case (None, nextFr) =>
|
||||
case (None, nextFr) =>
|
||||
RandomState(Vector.empty[ActionResultT], nextFr)
|
||||
}
|
||||
}
|
||||
@@ -76,9 +69,9 @@ case class PerformVassalDefenseDecisionsAction(
|
||||
private def chooseCommand(
|
||||
gs: GameState,
|
||||
provinceId: ProvinceId,
|
||||
commandOptions: Vector[ProtoAvailableCommand],
|
||||
commandOptions: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
CommandChoiceHelpers.resolveTributeSelectedCommand(
|
||||
actingFactionId = gs.provinces(provinceId).rulingFactionId.get,
|
||||
gameState = gs,
|
||||
|
||||
+18
-25
@@ -1,12 +1,13 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers
|
||||
|
||||
import net.eagle0.eagle.{FactionId, HeroId}
|
||||
import net.eagle0.eagle.api.available_command.{AvailableCommand, DiplomacyAvailableCommand}
|
||||
import net.eagle0.eagle.api.command.util.diplomacy_option.{AllianceOption, DiplomacyOption}
|
||||
import net.eagle0.eagle.api.selected_command.DiplomacySelectedCommand
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.AvailableCommandSelector.ofType
|
||||
import net.eagle0.eagle.library.util.faction_utils.FactionUtils
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.{DiplomacyAvailable, DiplomacyOption}
|
||||
import net.eagle0.eagle.model.state.command.common.DiplomacyOptionType
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.DiplomacySelected
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
|
||||
object AllianceOfferCommandSelector {
|
||||
@@ -16,13 +17,13 @@ object AllianceOfferCommandSelector {
|
||||
): Vector[HeroId] =
|
||||
hids.filterNot(FactionUtils.isFactionLeader(_, gameState.factions.values.toVector))
|
||||
|
||||
private def allianceOptionWithTarget(
|
||||
private def hasAllianceOptionWithTarget(
|
||||
options: Vector[DiplomacyOption],
|
||||
targetFactionId: FactionId
|
||||
): Option[AllianceOption] =
|
||||
options.collectFirst {
|
||||
case x @ AllianceOption(tfid, _, _ /* unknownFieldSet */ ) if tfid == targetFactionId =>
|
||||
x
|
||||
): Boolean =
|
||||
options.exists { opt =>
|
||||
opt.targetFactionId == targetFactionId &&
|
||||
opt.optionTypes.contains(DiplomacyOptionType.Alliance)
|
||||
}
|
||||
|
||||
def chosenAllianceWithFactionCommand(
|
||||
@@ -30,27 +31,19 @@ object AllianceOfferCommandSelector {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
targetFactionId: FactionId
|
||||
): Option[CommandSelection] =
|
||||
ofType[DiplomacyAvailableCommand](availableCommands).find { ac =>
|
||||
allianceOptionWithTarget(
|
||||
ac.options.toVector,
|
||||
targetFactionId
|
||||
).isDefined && usableHeroIds(
|
||||
ac.availableHeroIds.toVector,
|
||||
gameState
|
||||
).nonEmpty
|
||||
): Option[ScalaCommandSelection] =
|
||||
ofType[DiplomacyAvailable](availableCommands).find { ac =>
|
||||
hasAllianceOptionWithTarget(ac.options, targetFactionId) &&
|
||||
usableHeroIds(ac.availableHeroIds, gameState).nonEmpty
|
||||
}.map { ac =>
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = ac.actingProvinceId,
|
||||
available = ac,
|
||||
selected = DiplomacySelectedCommand(
|
||||
selectedOption = allianceOptionWithTarget(
|
||||
ac.options.toVector,
|
||||
targetFactionId
|
||||
).get,
|
||||
selected = DiplomacySelected(
|
||||
selectedOption = DiplomacyOptionType.Alliance,
|
||||
targetFactionId = targetFactionId,
|
||||
sentHeroId = usableHeroIds(ac.availableHeroIds.toVector, gameState).maxBy { hid =>
|
||||
sentHeroId = usableHeroIds(ac.availableHeroIds, gameState).maxBy { hid =>
|
||||
gameState.heroes(hid).vigor
|
||||
}
|
||||
),
|
||||
|
||||
+13
-12
@@ -1,15 +1,16 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers
|
||||
|
||||
import net.eagle0.eagle.{FactionId, ProvinceId}
|
||||
import net.eagle0.eagle.api.available_command.{AlmsAvailableCommand, AvailableCommand}
|
||||
import net.eagle0.eagle.api.selected_command.AlmsSelectedCommand
|
||||
import net.eagle0.eagle.library.actions.impl.command.AlmsCommand
|
||||
import net.eagle0.eagle.library.settings.MinSupportForTaxes
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.AvailableCommandSelector.flatSelectionForType
|
||||
import net.eagle0.eagle.library.util.food_consumption.FoodConsumptionUtils.foodConsumptionMonthsToHold
|
||||
import net.eagle0.eagle.library.util.hero.HeroUtils
|
||||
import net.eagle0.eagle.library.util.province.ProvinceUtils
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.AlmsAvailable
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.AlmsSelected
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.hero.HeroT
|
||||
import net.eagle0.eagle.model.state.province.ProvinceT
|
||||
@@ -43,7 +44,7 @@ object AlmsCommandSelector {
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] = chosenAlmsForSupportWithMinimumCommand(
|
||||
): Option[ScalaCommandSelection] = chosenAlmsForSupportWithMinimumCommand(
|
||||
actingFactionId = actingFactionId,
|
||||
gameState = gameState,
|
||||
availableCommands = availableCommands,
|
||||
@@ -56,8 +57,8 @@ object AlmsCommandSelector {
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
minimumFood: Int,
|
||||
provinceId: ProvinceId
|
||||
): Option[CommandSelection] =
|
||||
flatSelectionForType[AlmsAvailableCommand](availableCommands) { availableCommand =>
|
||||
): Option[ScalaCommandSelection] =
|
||||
flatSelectionForType[AlmsAvailable](availableCommands) { availableCommand =>
|
||||
val province = gameState
|
||||
.provinces(availableCommand.actingProvinceId)
|
||||
|
||||
@@ -77,8 +78,8 @@ object AlmsCommandSelector {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
minimumFood: Int
|
||||
): Option[CommandSelection] =
|
||||
flatSelectionForType[AlmsAvailableCommand](availableCommands) { availableCommand =>
|
||||
): Option[ScalaCommandSelection] =
|
||||
flatSelectionForType[AlmsAvailable](availableCommands) { availableCommand =>
|
||||
val province = gameState
|
||||
.provinces(availableCommand.actingProvinceId)
|
||||
|
||||
@@ -94,10 +95,10 @@ object AlmsCommandSelector {
|
||||
private def maybeAlmsCommandForProvince(
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommand: AlmsAvailableCommand,
|
||||
availableCommand: AlmsAvailable,
|
||||
minimumFood: Int,
|
||||
province: ProvinceT
|
||||
): Option[CommandSelection] = {
|
||||
): Option[ScalaCommandSelection] = {
|
||||
val foodAfterFeedingTroops = surplusFood(province, gameState)
|
||||
val effectiveMinimumFood = minimumFood.min(foodAfterFeedingTroops)
|
||||
|
||||
@@ -139,11 +140,11 @@ object AlmsCommandSelector {
|
||||
.min(desiredFood, availableCommand.foodAvailable)
|
||||
.ceil
|
||||
.toInt
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = availableCommand.actingProvinceId,
|
||||
available = availableCommand,
|
||||
selected = AlmsSelectedCommand(
|
||||
selected = AlmsSelected(
|
||||
amount = foodToUse,
|
||||
actingHeroId = bestHero.id
|
||||
),
|
||||
|
||||
+15
-14
@@ -1,16 +1,17 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers
|
||||
|
||||
import net.eagle0.eagle.{FactionId, ProvinceId}
|
||||
import net.eagle0.eagle.api.available_command.*
|
||||
import net.eagle0.eagle.api.selected_command.*
|
||||
import net.eagle0.eagle.common.combat_unit.CombatUnit
|
||||
import net.eagle0.eagle.library.settings.{
|
||||
MinVigorForMarch,
|
||||
RequiredRatioToAttack,
|
||||
RequiredRatioToAttackWithoutTakingCastles
|
||||
}
|
||||
import net.eagle0.eagle.library.util.{BattalionPower, CommandSelection, ShardokMapInfo}
|
||||
import net.eagle0.eagle.library.util.{BattalionPower, ScalaCommandSelection, ShardokMapInfo}
|
||||
import net.eagle0.eagle.library.util.faction_utils.FactionUtils
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.MarchAvailable
|
||||
import net.eagle0.eagle.model.state.command.selected.{CombatUnit, SelectedCommand}
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.MarchSelected
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.hero.HeroT
|
||||
import net.eagle0.eagle.model.state.hero.Profession.{Engineer, Mage}
|
||||
@@ -53,14 +54,14 @@ object AttackCommandChooser {
|
||||
// this might be a supporting attack
|
||||
private def chosenAttackOnProvinceCommand(
|
||||
actingFactionId: FactionId,
|
||||
ac: MarchAvailableCommand,
|
||||
ac: MarchAvailable,
|
||||
selectedUnits: Vector[CombatUnit],
|
||||
goldAvailable: Int,
|
||||
foodAvailable: Int,
|
||||
originProvinceId: ProvinceId,
|
||||
destinationProvince: ProvinceT,
|
||||
gameState: GameState
|
||||
): MarchSelectedCommand = MarchSelectedCommand(
|
||||
): MarchSelected = MarchSelected(
|
||||
marchingUnits = selectedUnits,
|
||||
originProvince = originProvinceId,
|
||||
destinationProvinceId = destinationProvince.id,
|
||||
@@ -73,7 +74,7 @@ object AttackCommandChooser {
|
||||
)
|
||||
|
||||
case class CommandInfo(
|
||||
sc: MarchSelectedCommand,
|
||||
sc: MarchSelected,
|
||||
requiresRiverCrossing: Boolean,
|
||||
totalBattalionPower: Double
|
||||
)
|
||||
@@ -91,7 +92,7 @@ object AttackCommandChooser {
|
||||
def possibleAttackCommands(
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
ac: MarchAvailableCommand
|
||||
ac: MarchAvailable
|
||||
): Vector[PossibleAttackCommandInfo] =
|
||||
(for {
|
||||
opmc <- ac.oneProvinceCommands
|
||||
@@ -152,9 +153,9 @@ object AttackCommandChooser {
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
acs: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] =
|
||||
): Option[ScalaCommandSelection] =
|
||||
// find march commands to an enemy-occupied territory
|
||||
flatSelectionForType[MarchAvailableCommand](acs) { ac =>
|
||||
flatSelectionForType[MarchAvailable](acs) { ac =>
|
||||
possibleAttackCommands(
|
||||
actingFactionId,
|
||||
gameState,
|
||||
@@ -196,7 +197,7 @@ object AttackCommandChooser {
|
||||
.sum
|
||||
)
|
||||
.map { sc =>
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = ac.actingProvinceId,
|
||||
available = ac,
|
||||
@@ -212,9 +213,9 @@ object AttackCommandChooser {
|
||||
acs: Vector[AvailableCommand],
|
||||
knownEnemyHeroCount: ProvinceId => Int,
|
||||
knownEnemyBattalions: ProvinceId => Vector[BattalionViewC]
|
||||
): Option[CommandSelection] =
|
||||
): Option[ScalaCommandSelection] =
|
||||
// find march commands to an enemy-occupied territory
|
||||
flatSelectionForType[MarchAvailableCommand](acs) { ac =>
|
||||
flatSelectionForType[MarchAvailable](acs) { ac =>
|
||||
val attackCommands =
|
||||
possibleAttackCommands(
|
||||
actingFactionId = actingFactionId,
|
||||
@@ -309,7 +310,7 @@ object AttackCommandChooser {
|
||||
}.flatMap { commandInfos =>
|
||||
commandInfos.maxByOption(_.totalBattalionPower)
|
||||
}.map { commandInfo =>
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = ac.actingProvinceId,
|
||||
available = ac,
|
||||
|
||||
+57
-61
@@ -2,19 +2,15 @@ package net.eagle0.eagle.library.util.command_choice_helpers
|
||||
|
||||
import net.eagle0.common.{FunctionalRandom, RandomState}
|
||||
import net.eagle0.common.hostility.Hostility
|
||||
import net.eagle0.eagle.api.available_command.{AttackDecisionAvailableCommand, AvailableCommand}
|
||||
import net.eagle0.eagle.api.command.util.attack_decision_type.{
|
||||
AdvanceDecision,
|
||||
DemandTributeDecision,
|
||||
SafePassageDecision,
|
||||
WithdrawDecision
|
||||
}
|
||||
import net.eagle0.eagle.api.selected_command.AttackDecisionSelectedCommand
|
||||
import net.eagle0.eagle.common.tribute_amount.TributeAmount
|
||||
import net.eagle0.eagle.library.settings.MinimumPercentageOfEnemyToAttack
|
||||
import net.eagle0.eagle.library.util.{BattalionPower, CommandSelection, IncomingArmyUtils}
|
||||
import net.eagle0.eagle.library.util.{BattalionPower, IncomingArmyUtils, ScalaCommandSelection}
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.AvailableCommandSelector.flatSelectionForType
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.CommandChooserImplicits.*
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.AttackDecisionAvailable
|
||||
import net.eagle0.eagle.model.state.command.common.AttackDecisionType
|
||||
import net.eagle0.eagle.model.state.command.common.AttackDecisionType.{Advance, DemandTribute, SafePassage, Withdraw}
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.AttackDecisionSelected
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.FactionId
|
||||
|
||||
@@ -24,7 +20,7 @@ object AttackDecisionCommandChooser {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
CommandChooser.choose(
|
||||
actingFactionId = actingFactionId,
|
||||
gameState = gameState,
|
||||
@@ -74,22 +70,22 @@ object AttackDecisionCommandChooser {
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] =
|
||||
flatSelectionForType[AttackDecisionAvailableCommand](availableCommands) { withdrawAc =>
|
||||
): Option[ScalaCommandSelection] =
|
||||
flatSelectionForType[AttackDecisionAvailable](availableCommands) { withdrawAc =>
|
||||
Option.when(
|
||||
withdrawAc.availableDecisions
|
||||
.contains(WithdrawDecision()) &&
|
||||
.contains(Withdraw) &&
|
||||
(!okToAttack(
|
||||
withdrawAc,
|
||||
gameState
|
||||
) || withdrawAc.availableDecisions.size == 1)
|
||||
)(
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = withdrawAc.actingProvinceId,
|
||||
available = withdrawAc,
|
||||
selected = AttackDecisionSelectedCommand(
|
||||
decision = WithdrawDecision()
|
||||
selected = AttackDecisionSelected(
|
||||
decision = Withdraw
|
||||
),
|
||||
reason = "withdrawArmySelectedCommand"
|
||||
)
|
||||
@@ -100,35 +96,38 @@ object AttackDecisionCommandChooser {
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] =
|
||||
flatSelectionForType[AttackDecisionAvailableCommand](availableCommands) { availableCommand =>
|
||||
): Option[ScalaCommandSelection] =
|
||||
flatSelectionForType[AttackDecisionAvailable](availableCommands) { availableCommand =>
|
||||
availableCommand.availableDecisions.collectFirst {
|
||||
case DemandTributeDecision(maxTribute, _ /* unknownFieldSet */ ) =>
|
||||
tributeToDemand(maxTribute.get).flatMap { tribute =>
|
||||
Option.when(
|
||||
(okToAttack(
|
||||
availableCommand,
|
||||
gameState
|
||||
) || availableCommand.availableDecisions.size == 1) &&
|
||||
availableCommand.availableDecisions
|
||||
.contains(DemandTributeDecision())
|
||||
)(
|
||||
CommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = availableCommand.actingProvinceId,
|
||||
available = availableCommand,
|
||||
selected = AttackDecisionSelectedCommand(
|
||||
decision = DemandTributeDecision(Some(tribute))
|
||||
),
|
||||
reason = "demandTributeSelectedCommand"
|
||||
case dt @ DemandTribute(maxGold, maxFood) =>
|
||||
tributeToDemand(maxGold, maxFood).flatMap {
|
||||
case (demandedGold, demandedFood) =>
|
||||
val hasDemandTributeOption = availableCommand.availableDecisions.exists {
|
||||
case DemandTribute(_, _) => true
|
||||
case _ => false
|
||||
}
|
||||
Option.when(
|
||||
(okToAttack(
|
||||
availableCommand,
|
||||
gameState
|
||||
) || availableCommand.availableDecisions.size == 1) && hasDemandTributeOption
|
||||
)(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = availableCommand.actingProvinceId,
|
||||
available = availableCommand,
|
||||
selected = AttackDecisionSelected(
|
||||
decision = DemandTribute(demandedGold, demandedFood)
|
||||
),
|
||||
reason = "demandTributeSelectedCommand"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}.flatten
|
||||
}
|
||||
|
||||
private def okToAttack(
|
||||
availableCommand: AttackDecisionAvailableCommand,
|
||||
availableCommand: AttackDecisionAvailable,
|
||||
gameState: GameState
|
||||
): Boolean = {
|
||||
val armies = availableCommand.armies
|
||||
@@ -158,29 +157,26 @@ object AttackDecisionCommandChooser {
|
||||
}
|
||||
|
||||
private def tributeToDemand(
|
||||
maxTribute: TributeAmount
|
||||
): Option[TributeAmount] =
|
||||
Option.when(2 * maxTribute.gold + maxTribute.food > 4000) {
|
||||
val goldDemanded = 0.max(maxTribute.gold - 200)
|
||||
val foodDemanded = 0.max(maxTribute.food - 400)
|
||||
maxGold: Int,
|
||||
maxFood: Int
|
||||
): Option[(Int, Int)] =
|
||||
Option.when(2 * maxGold + maxFood > 4000) {
|
||||
val goldDemanded = 0.max(maxGold - 200)
|
||||
val foodDemanded = 0.max(maxFood - 400)
|
||||
|
||||
if goldDemanded == 0 && foodDemanded == 0 then tributeToDemand(maxTribute).get
|
||||
else
|
||||
TributeAmount(
|
||||
gold = goldDemanded,
|
||||
food = foodDemanded
|
||||
)
|
||||
if goldDemanded == 0 && foodDemanded == 0 then tributeToDemand(maxGold, maxFood).get
|
||||
else (goldDemanded, foodDemanded)
|
||||
}
|
||||
|
||||
private def advanceArmySelectedCommand(
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] =
|
||||
flatSelectionForType[AttackDecisionAvailableCommand](availableCommands) { availableCommand =>
|
||||
): Option[ScalaCommandSelection] =
|
||||
flatSelectionForType[AttackDecisionAvailable](availableCommands) { availableCommand =>
|
||||
Option.when(
|
||||
availableCommand.availableDecisions
|
||||
.contains(AdvanceDecision()) && (
|
||||
.contains(Advance) && (
|
||||
availableCommand.availableDecisions.size == 1 ||
|
||||
okToAttack(
|
||||
availableCommand,
|
||||
@@ -188,12 +184,12 @@ object AttackDecisionCommandChooser {
|
||||
)
|
||||
)
|
||||
) {
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
available = availableCommand,
|
||||
actingProvinceId = availableCommand.actingProvinceId,
|
||||
selected = AttackDecisionSelectedCommand(
|
||||
decision = AdvanceDecision()
|
||||
selected = AttackDecisionSelected(
|
||||
decision = Advance
|
||||
),
|
||||
reason = "advanceArmySelectedCommand"
|
||||
)
|
||||
@@ -204,15 +200,15 @@ object AttackDecisionCommandChooser {
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] =
|
||||
flatSelectionForType[AttackDecisionAvailableCommand](availableCommands) { availableCommand =>
|
||||
): Option[ScalaCommandSelection] =
|
||||
flatSelectionForType[AttackDecisionAvailable](availableCommands) { availableCommand =>
|
||||
availableCommand.availableDecisions.collectFirst {
|
||||
case spd: SafePassageDecision =>
|
||||
CommandSelection(
|
||||
case spd @ SafePassage(_) =>
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
available = availableCommand,
|
||||
actingProvinceId = availableCommand.actingProvinceId,
|
||||
selected = AttackDecisionSelectedCommand(
|
||||
selected = AttackDecisionSelected(
|
||||
decision = spd
|
||||
),
|
||||
reason = "safePassageSelectedCommand"
|
||||
|
||||
+6
-6
@@ -3,8 +3,8 @@ package net.eagle0.eagle.library.util.command_choice_helpers
|
||||
import scala.reflect.ClassTag
|
||||
|
||||
import net.eagle0.common.{FunctionalRandom, RandomState}
|
||||
import net.eagle0.eagle.api.available_command.AvailableCommand
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
|
||||
object AvailableCommandSelector {
|
||||
def ofType[T <: AvailableCommand: ClassTag](
|
||||
@@ -17,20 +17,20 @@ object AvailableCommandSelector {
|
||||
|
||||
def selectionForType[T <: AvailableCommand: ClassTag](
|
||||
acs: Vector[AvailableCommand]
|
||||
)(f: T => CommandSelection): Option[CommandSelection] =
|
||||
)(f: T => ScalaCommandSelection): Option[ScalaCommandSelection] =
|
||||
acs.collectFirst { case ac: T => f(ac) }
|
||||
|
||||
def flatSelectionForType[T <: AvailableCommand: ClassTag](
|
||||
acs: Vector[AvailableCommand]
|
||||
)(f: T => Option[CommandSelection]): Option[CommandSelection] =
|
||||
)(f: T => Option[ScalaCommandSelection]): Option[ScalaCommandSelection] =
|
||||
ofType(acs).flatMap(f).headOption
|
||||
|
||||
def randomSelectionForType[T <: AvailableCommand: ClassTag](
|
||||
acs: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
)(
|
||||
f: (T, FunctionalRandom) => RandomState[Option[CommandSelection]]
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
f: (T, FunctionalRandom) => RandomState[Option[ScalaCommandSelection]]
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
functionalRandom.nextFlatCollectFirst(acs) {
|
||||
case ac: T =>
|
||||
fr => f(ac, fr)
|
||||
|
||||
@@ -9,11 +9,12 @@ scala_library(
|
||||
],
|
||||
deps = [
|
||||
":available_command_selector",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//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/faction_utils",
|
||||
"//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",
|
||||
],
|
||||
)
|
||||
@@ -32,8 +33,6 @@ scala_library(
|
||||
],
|
||||
deps = [
|
||||
":available_command_selector",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/library/actions/impl/command:alms_command",
|
||||
"//src/main/scala/net/eagle0/eagle/library/settings:min_support_for_taxes",
|
||||
@@ -41,6 +40,8 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/food_consumption",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero:hero_utils",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/province",
|
||||
"//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/game_state",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/province",
|
||||
@@ -61,8 +62,6 @@ scala_library(
|
||||
":available_command_selector",
|
||||
":combat_unit_selector",
|
||||
":march_supplies_helpers",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/library/settings:min_vigor_for_march",
|
||||
"//src/main/scala/net/eagle0/eagle/library/settings:required_ratio_to_attack",
|
||||
@@ -71,6 +70,8 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:command_selection",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:shardok_map_info",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/faction_utils",
|
||||
"//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/game_state",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/province",
|
||||
@@ -91,14 +92,15 @@ scala_library(
|
||||
deps = [
|
||||
":available_command_selector",
|
||||
":command_chooser",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/library/settings:minimum_percentage_of_enemy_to_attack",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:battalion_power",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:command_selection",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:incoming_army_utils",
|
||||
"//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",
|
||||
],
|
||||
)
|
||||
@@ -111,9 +113,9 @@ scala_library(
|
||||
"//src/test/scala/net/eagle0/eagle/library/util/command_choice_helpers:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:command_selection",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -125,14 +127,17 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/util:__pkg__",
|
||||
"//src/test/scala/net/eagle0/eagle/library/util/command_choice_helpers:__pkg__",
|
||||
],
|
||||
exports = [
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/command/selected",
|
||||
],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/common:combat_unit_scala_proto",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:battalion_power",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:eagle_require",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/battalion_suitability",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero:hero_utils",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state:battalion_type",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/battalion",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/command/selected",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero:gender",
|
||||
],
|
||||
@@ -150,10 +155,10 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//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/game_state",
|
||||
],
|
||||
)
|
||||
@@ -168,9 +173,10 @@ scala_library(
|
||||
"//src/test/scala/net/eagle0/eagle:__subpackages__",
|
||||
],
|
||||
exports = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/common:combat_unit_scala_proto",
|
||||
"//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/selected",
|
||||
],
|
||||
deps = [
|
||||
":alms_command_selector",
|
||||
@@ -186,11 +192,6 @@ scala_library(
|
||||
":organize_command_selector",
|
||||
":province_gold_surplus_calculator",
|
||||
":ransom_offer_helpers",
|
||||
"//src/main/protobuf/net/eagle0/common:hostility_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api/command/util:armed_battalion_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api/command/util:battalion_with_food_cost_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//src/main/scala/net/eagle0/common:more_option",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
@@ -219,6 +220,9 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/model/state:battalion_type_id",
|
||||
"//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/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",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
@@ -238,10 +242,10 @@ scala_library(
|
||||
],
|
||||
deps = [
|
||||
":available_command_selector",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//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/selected",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -259,8 +263,6 @@ scala_library(
|
||||
deps = [
|
||||
":available_command_selector",
|
||||
":province_gold_surplus_calculator",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/library/settings:max_combat_unit_count_per_side",
|
||||
@@ -270,6 +272,8 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/faction_utils",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/food_consumption",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/province",
|
||||
"//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/game_state",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/province",
|
||||
],
|
||||
@@ -288,7 +292,6 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:command_selection",
|
||||
@@ -304,6 +307,7 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers/quest_command_selectors:truce_with_faction_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/library/util/province",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/unaffiliated_hero",
|
||||
],
|
||||
@@ -319,10 +323,10 @@ scala_library(
|
||||
],
|
||||
deps = [
|
||||
":available_command_selector",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//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/selected",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
],
|
||||
)
|
||||
@@ -354,11 +358,12 @@ scala_library(
|
||||
deps = [
|
||||
":available_command_selector",
|
||||
":hero_selector",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//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/hero:hero_utils",
|
||||
"//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/province",
|
||||
],
|
||||
@@ -392,14 +397,13 @@ scala_library(
|
||||
deps = [
|
||||
":available_command_selector",
|
||||
":province_gold_surplus_calculator",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/common:battalion_type_scala_proto",
|
||||
"//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/battalion_type_finder",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/province",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/battalion",
|
||||
"//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/game_state",
|
||||
],
|
||||
)
|
||||
@@ -451,11 +455,11 @@ scala_library(
|
||||
"//src/test/scala/net/eagle0/eagle/library/util/command_choice_helpers:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//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:available_command_selector",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/command/selected",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -484,11 +488,12 @@ scala_library(
|
||||
],
|
||||
deps = [
|
||||
":available_command_selector",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//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/faction_utils",
|
||||
"//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",
|
||||
],
|
||||
)
|
||||
|
||||
+3
-5
@@ -2,12 +2,12 @@ package net.eagle0.eagle.library.util.command_choice_helpers
|
||||
|
||||
import scala.annotation.tailrec
|
||||
|
||||
import net.eagle0.eagle.common.combat_unit.CombatUnit
|
||||
import net.eagle0.eagle.library.util.battalion_suitability.{BattalionSuitability, SuitabilityLevel}
|
||||
import net.eagle0.eagle.library.util.hero.HeroUtils
|
||||
import net.eagle0.eagle.library.util.BattalionPower
|
||||
import net.eagle0.eagle.library.util.EagleRequire.internalRequire
|
||||
import net.eagle0.eagle.model.state.battalion.BattalionT
|
||||
import net.eagle0.eagle.model.state.command.selected.CombatUnit
|
||||
import net.eagle0.eagle.model.state.hero.HeroT
|
||||
import net.eagle0.eagle.model.state.BattalionType
|
||||
|
||||
@@ -39,15 +39,13 @@ object CombatUnitSelector {
|
||||
val bestHero = hs.minBy(h => (suitability(h, bestBattalion).ordinal, -HeroUtils.power(h)))
|
||||
CombatUnit(
|
||||
heroId = bestHero.id,
|
||||
battalionId = Some(bestBattalion.id),
|
||||
factionId = bestHero.factionId.get
|
||||
battalionId = Some(bestBattalion.id)
|
||||
)
|
||||
}
|
||||
.getOrElse(
|
||||
CombatUnit(
|
||||
heroId = hs.maxBy(HeroUtils.power).id,
|
||||
battalionId = bs.maxByOption(BattalionPower.power).map(_.id),
|
||||
factionId = hs.head.factionId.get
|
||||
battalionId = bs.maxByOption(BattalionPower.power).map(_.id)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
+267
-267
File diff suppressed because it is too large
Load Diff
+8
-8
@@ -3,8 +3,8 @@ package net.eagle0.eagle.library.util.command_choice_helpers
|
||||
import scala.annotation.tailrec
|
||||
|
||||
import net.eagle0.common.{FunctionalRandom, RandomState}
|
||||
import net.eagle0.eagle.api.available_command.AvailableCommand
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.FactionId
|
||||
|
||||
@@ -15,7 +15,7 @@ trait CommandChooser {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]]
|
||||
): RandomState[Option[ScalaCommandSelection]]
|
||||
}
|
||||
|
||||
object CommandChooser {
|
||||
@@ -26,7 +26,7 @@ object CommandChooser {
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
rankedChoosers: Vector[CommandChooser],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] = rankedChoosers match {
|
||||
): RandomState[Option[ScalaCommandSelection]] = rankedChoosers match {
|
||||
case h +: t =>
|
||||
h(actingFactionId, gameState, availableCommands, functionalRandom) match {
|
||||
case rss @ RandomState(Some(_), _) => rss
|
||||
@@ -43,14 +43,14 @@ object CommandChooserImplicits {
|
||||
FactionId,
|
||||
GameState,
|
||||
Vector[AvailableCommand]
|
||||
) => Option[CommandSelection]
|
||||
) => Option[ScalaCommandSelection]
|
||||
) extends CommandChooser {
|
||||
override def apply(
|
||||
factionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
RandomState(
|
||||
deterministicChooser(factionId, gameState, availableCommands),
|
||||
functionalRandom
|
||||
@@ -63,14 +63,14 @@ object CommandChooserImplicits {
|
||||
GameState,
|
||||
Vector[AvailableCommand],
|
||||
FunctionalRandom
|
||||
) => RandomState[Option[CommandSelection]]
|
||||
) => RandomState[Option[ScalaCommandSelection]]
|
||||
) extends CommandChooser {
|
||||
override def apply(
|
||||
factionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
randomChooser(factionId, gameState, availableCommands, functionalRandom)
|
||||
}
|
||||
}
|
||||
|
||||
+13
-12
@@ -1,10 +1,11 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers
|
||||
|
||||
import net.eagle0.eagle.{FactionId, HeroId, ProvinceId}
|
||||
import net.eagle0.eagle.api.available_command.{AvailableCommand, ExileVassalAvailableCommand}
|
||||
import net.eagle0.eagle.api.selected_command.ExileVassalSelectedCommand
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.AvailableCommandSelector.ofType
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.ExileVassalAvailable
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.ExileVassalSelected
|
||||
|
||||
object ExileVassalCommandSelector {
|
||||
def chosenSpecificDismissVassalCommandForProvince(
|
||||
@@ -13,20 +14,20 @@ object ExileVassalCommandSelector {
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
dismissedHeroId: HeroId,
|
||||
reason: String
|
||||
): Option[CommandSelection] =
|
||||
ofType[ExileVassalAvailableCommand](availableCommands)
|
||||
.find(exileVassalCommand =>
|
||||
exileVassalCommand.exilableHeroIds
|
||||
): Option[ScalaCommandSelection] =
|
||||
ofType[ExileVassalAvailable](availableCommands)
|
||||
.find(exileVassalAvailable =>
|
||||
exileVassalAvailable.exilableHeroIds
|
||||
.contains(
|
||||
dismissedHeroId
|
||||
) && exileVassalCommand.actingProvinceId == actingProvinceId
|
||||
) && exileVassalAvailable.actingProvinceId == actingProvinceId
|
||||
)
|
||||
.map { exileVassalCommand =>
|
||||
CommandSelection(
|
||||
.map { exileVassalAvailable =>
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = actingProvinceId,
|
||||
available = exileVassalCommand,
|
||||
selected = ExileVassalSelectedCommand(exiledHeroId = dismissedHeroId),
|
||||
available = exileVassalAvailable,
|
||||
selected = ExileVassalSelected(exiledHeroId = dismissedHeroId),
|
||||
reason = reason
|
||||
)
|
||||
}
|
||||
|
||||
+21
-24
@@ -4,16 +4,17 @@ import scala.annotation.tailrec
|
||||
|
||||
import net.eagle0.common.{FunctionalRandom, RandomState}
|
||||
import net.eagle0.eagle.{FactionId, HeroId, ProvinceId}
|
||||
import net.eagle0.eagle.api.available_command.{AvailableCommand, MarchAvailableCommand, MarchCommandFromOneProvince}
|
||||
import net.eagle0.eagle.api.selected_command.MarchSelectedCommand
|
||||
import net.eagle0.eagle.common.combat_unit.CombatUnit
|
||||
import net.eagle0.eagle.library.settings.MaxCombatUnitCountPerSide
|
||||
import net.eagle0.eagle.library.util.{BattalionUtils, CommandSelection}
|
||||
import net.eagle0.eagle.library.util.{BattalionUtils, ScalaCommandSelection}
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.AvailableCommandSelector.randomSelectionForType
|
||||
import net.eagle0.eagle.library.util.faction_utils.FactionUtils
|
||||
import net.eagle0.eagle.library.util.food_consumption.FoodConsumptionUtils.foodConsumptionMonthsToHold
|
||||
import net.eagle0.eagle.library.util.province.ProvinceUtils
|
||||
import net.eagle0.eagle.library.util.EagleRequire.internalRequire
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.{MarchAvailable, MarchCommandFromOneProvince}
|
||||
import net.eagle0.eagle.model.state.command.selected.{CombatUnit, SelectedCommand}
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.MarchSelected
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.province.ProvinceT
|
||||
|
||||
@@ -25,8 +26,8 @@ object ExpandCommandSelector {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
randomSelectionForType[MarchAvailableCommand](
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
randomSelectionForType[MarchAvailable](
|
||||
availableCommands,
|
||||
functionalRandom
|
||||
) {
|
||||
@@ -107,11 +108,11 @@ object ExpandCommandSelector {
|
||||
private def safeExpansionSelectedCommand(
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommand: MarchAvailableCommand,
|
||||
availableCommand: MarchAvailable,
|
||||
oneProvinceCommand: MarchCommandFromOneProvince,
|
||||
safeExpansionCandidateProvinces: Vector[ProvinceT],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] = {
|
||||
): RandomState[Option[ScalaCommandSelection]] = {
|
||||
val province = gameState.provinces(availableCommand.actingProvinceId)
|
||||
val rulingFactionHeroIds = province.rulingFactionHeroIds
|
||||
|
||||
@@ -151,11 +152,11 @@ object ExpandCommandSelector {
|
||||
private def expansionAdjacentToEnemySelectedCommand(
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommand: MarchAvailableCommand,
|
||||
availableCommand: MarchAvailable,
|
||||
oneProvinceCommand: MarchCommandFromOneProvince,
|
||||
adjacentEnemyCandidateProvinces: Vector[ProvinceT],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] = {
|
||||
): RandomState[Option[ScalaCommandSelection]] = {
|
||||
val province = gameState.provinces(availableCommand.actingProvinceId)
|
||||
val rulingFactionHeroIds = province.rulingFactionHeroIds
|
||||
|
||||
@@ -201,7 +202,6 @@ object ExpandCommandSelector {
|
||||
opmc: MarchCommandFromOneProvince,
|
||||
heroCount: Int,
|
||||
battalionCount: Int,
|
||||
fid: FactionId,
|
||||
factionLeaders: Vector[HeroId],
|
||||
otherCountLeftBehind: Int,
|
||||
functionalRandom: FunctionalRandom
|
||||
@@ -223,7 +223,7 @@ object ExpandCommandSelector {
|
||||
.map(_.take(battalionCount))
|
||||
.map { battalionIdsWithFoodCosts =>
|
||||
val food =
|
||||
battalionIdsWithFoodCosts.map(_.monthlyFood).sum.ceil.toInt * 2
|
||||
battalionIdsWithFoodCosts.map(_.foodCost).sum * 2
|
||||
|
||||
val battalionIds =
|
||||
battalionIdsWithFoodCosts.map(_.battalionId).sorted.map(Option(_))
|
||||
@@ -233,8 +233,7 @@ object ExpandCommandSelector {
|
||||
.map { pair =>
|
||||
CombatUnit(
|
||||
heroId = pair._1,
|
||||
battalionId = pair._2,
|
||||
factionId = fid
|
||||
battalionId = pair._2
|
||||
)
|
||||
}
|
||||
|
||||
@@ -250,10 +249,10 @@ object ExpandCommandSelector {
|
||||
originatingProvince: ProvinceT,
|
||||
candidateDestinationProvinces: Vector[ProvinceT],
|
||||
oneProvinceCommand: MarchCommandFromOneProvince,
|
||||
availableCommand: MarchAvailableCommand,
|
||||
availableCommand: MarchAvailable,
|
||||
gameState: GameState,
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] = {
|
||||
): RandomState[Option[ScalaCommandSelection]] = {
|
||||
val rulingFactionHeroIds = originatingProvince.rulingFactionHeroIds
|
||||
val randomNone = RandomState(None, functionalRandom)
|
||||
|
||||
@@ -290,7 +289,6 @@ object ExpandCommandSelector {
|
||||
opmc = oneProvinceCommand,
|
||||
heroCount = heroCountToSend,
|
||||
battalionCount = battalionCountToSend.min(heroCountToSend),
|
||||
fid = actingFactionId,
|
||||
factionLeaders = gameState
|
||||
.factions(actingFactionId)
|
||||
.leaderIds
|
||||
@@ -353,11 +351,11 @@ object ExpandCommandSelector {
|
||||
)
|
||||
|
||||
Option.when(minFoodToSend <= foodAvailableToSend) {
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = availableCommand.actingProvinceId,
|
||||
available = availableCommand,
|
||||
selected = MarchSelectedCommand(
|
||||
selected = MarchSelected(
|
||||
marchingUnits = marchingUnitsWithFood.units,
|
||||
destinationProvinceId = chosenCandidateProvince.id,
|
||||
originProvince = oneProvinceCommand.originProvinceId,
|
||||
@@ -376,9 +374,9 @@ object ExpandCommandSelector {
|
||||
private def spreadHeroesCommand(
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommand: MarchAvailableCommand,
|
||||
availableCommand: MarchAvailable,
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
availableCommand.oneProvinceCommands.flatMap { opmc =>
|
||||
spreadHeroesMarchCandidates(
|
||||
gameState,
|
||||
@@ -415,17 +413,16 @@ object ExpandCommandSelector {
|
||||
opmc = opmc,
|
||||
heroCount = heroCountToSend,
|
||||
battalionCount = battalionCountToSend,
|
||||
fid = actingFactionId,
|
||||
factionLeaders = gameState.factions(actingFactionId).leaderIds,
|
||||
otherCountLeftBehind = originProvince.rulingFactionHeroIds.length - opmc.availableHeroIds.length,
|
||||
functionalRandom = functionalRandom
|
||||
).map { marchingUnitsWithFood =>
|
||||
Some(
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = availableCommand.actingProvinceId,
|
||||
available = availableCommand,
|
||||
selected = MarchSelectedCommand(
|
||||
selected = MarchSelected(
|
||||
marchingUnits = marchingUnitsWithFood.units,
|
||||
destinationProvinceId = destinationProvince.id,
|
||||
originProvince = opmc.originProvinceId,
|
||||
|
||||
+5
-5
@@ -1,7 +1,6 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers
|
||||
|
||||
import net.eagle0.common.{FunctionalRandom, RandomState}
|
||||
import net.eagle0.eagle.api.available_command.AvailableCommand
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.quest_command_selectors.{
|
||||
AllianceQuestCommandChooser,
|
||||
AlmsAcrossRealmQuestCommandChooser,
|
||||
@@ -16,7 +15,8 @@ import net.eagle0.eagle.library.util.command_choice_helpers.quest_command_select
|
||||
UnaffiliatedHeroWithQuest
|
||||
}
|
||||
import net.eagle0.eagle.library.util.province.ProvinceUtils
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.FactionId
|
||||
|
||||
@@ -40,7 +40,7 @@ object FulfillQuestsCommandSelector {
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
uhsWithQuests: Vector[UnaffiliatedHeroWithQuest],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
functionalRandom.nextFlatCollectFirst(choosers) {
|
||||
case chooser =>
|
||||
fr =>
|
||||
@@ -60,7 +60,7 @@ object FulfillQuestsCommandSelector {
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
uhsWithQuests: Vector[UnaffiliatedHeroWithQuest],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
choiceFrom(
|
||||
choosers = choosers,
|
||||
actingFactionId = actingFactionId,
|
||||
@@ -76,7 +76,7 @@ object FulfillQuestsCommandSelector {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] = {
|
||||
): RandomState[Option[ScalaCommandSelection]] = {
|
||||
val myProvinces = gameState.provinces.values
|
||||
.filter(_.rulingFactionId.contains(actingFactionId))
|
||||
.filter(province => ProvinceUtils.ruledByFactionLeader(province, gameState.factions.values.toVector))
|
||||
|
||||
+12
-11
@@ -1,10 +1,11 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers
|
||||
|
||||
import net.eagle0.eagle.{FactionId, HeroId, ProvinceId}
|
||||
import net.eagle0.eagle.api.available_command.{AvailableCommand, HeroGiftAvailableCommand}
|
||||
import net.eagle0.eagle.api.selected_command.HeroGiftSelectedCommand
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.AvailableCommandSelector.flatSelectionForType
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.HeroGiftAvailable
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.HeroGiftSelected
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
|
||||
object HeroGiftCommandSelector {
|
||||
@@ -14,17 +15,17 @@ object HeroGiftCommandSelector {
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
provinceId: ProvinceId,
|
||||
maxAmount: Int
|
||||
): Option[CommandSelection] =
|
||||
flatSelectionForType[HeroGiftAvailableCommand](availableCommands) { heroGiftAvailableCommand =>
|
||||
): Option[ScalaCommandSelection] =
|
||||
flatSelectionForType[HeroGiftAvailable](availableCommands) { heroGiftAvailableCommand =>
|
||||
heroGiftAvailableCommand.eligibleGifts
|
||||
.filter(_.recipientProvinceId == provinceId)
|
||||
.minByOption(eligibleGift => gameState.heroes(eligibleGift.recipientHeroId).loyalty)
|
||||
.map { eligibleGift =>
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
available = heroGiftAvailableCommand,
|
||||
actingProvinceId = heroGiftAvailableCommand.actingProvinceId,
|
||||
selected = HeroGiftSelectedCommand(
|
||||
selected = HeroGiftSelected(
|
||||
recipientHeroId = eligibleGift.recipientHeroId,
|
||||
amount = eligibleGift.goldAvailable.min(maxAmount)
|
||||
),
|
||||
@@ -38,16 +39,16 @@ object HeroGiftCommandSelector {
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
heroId: HeroId,
|
||||
reason: String
|
||||
): Option[CommandSelection] =
|
||||
flatSelectionForType[HeroGiftAvailableCommand](availableCommands) { heroGiftAvailableCommand =>
|
||||
): Option[ScalaCommandSelection] =
|
||||
flatSelectionForType[HeroGiftAvailable](availableCommands) { heroGiftAvailableCommand =>
|
||||
heroGiftAvailableCommand.eligibleGifts
|
||||
.find(_.recipientHeroId == heroId)
|
||||
.map { eligibleGift =>
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
available = heroGiftAvailableCommand,
|
||||
actingProvinceId = heroGiftAvailableCommand.actingProvinceId,
|
||||
selected = HeroGiftSelectedCommand(
|
||||
selected = HeroGiftSelected(
|
||||
recipientHeroId = heroId,
|
||||
amount = eligibleGift.goldAvailable
|
||||
),
|
||||
|
||||
+31
-28
@@ -1,16 +1,17 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers
|
||||
|
||||
import net.eagle0.eagle.{FactionId, ProvinceId}
|
||||
import net.eagle0.eagle.api.available_command.{AvailableCommand, ImproveAvailableCommand}
|
||||
import net.eagle0.eagle.api.selected_command.ImproveSelectedCommand
|
||||
import net.eagle0.eagle.common.improvement_type.ImprovementType
|
||||
import net.eagle0.eagle.common.improvement_type.ImprovementType.DEVASTATION
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.AvailableCommandSelector.{
|
||||
flatSelectionForType,
|
||||
selectionForType
|
||||
}
|
||||
import net.eagle0.eagle.library.util.hero.HeroUtils
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.ImproveAvailable
|
||||
import net.eagle0.eagle.model.state.command.common.ImprovementType
|
||||
import net.eagle0.eagle.model.state.command.common.ImprovementType.Devastation
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.ImproveSelected
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.province.ProvinceT
|
||||
|
||||
@@ -21,19 +22,18 @@ object ImproveCommandSelector {
|
||||
improvementType: ImprovementType,
|
||||
province: ProvinceT
|
||||
): Double = improvementType match {
|
||||
case ImprovementType.ECONOMY => province.economy
|
||||
case ImprovementType.AGRICULTURE => province.agriculture
|
||||
case ImprovementType.INFRASTRUCTURE => province.infrastructure
|
||||
case ImprovementType.DEVASTATION =>
|
||||
case ImprovementType.Economy => province.economy
|
||||
case ImprovementType.Agriculture => province.agriculture
|
||||
case ImprovementType.Infrastructure => province.infrastructure
|
||||
case ImprovementType.Devastation =>
|
||||
province.economyDevastation + province.agricultureDevastation + province.infrastructureDevastation
|
||||
case _ => throw new IllegalArgumentException("Illegal improvement type")
|
||||
}
|
||||
|
||||
private def chosenType(
|
||||
availableTypes: Vector[ImprovementType],
|
||||
province: ProvinceT
|
||||
): ImprovementType =
|
||||
if availableTypes.contains(DEVASTATION) then DEVASTATION
|
||||
if availableTypes.contains(Devastation) then Devastation
|
||||
else availableTypes.minBy(provinceValueForType(_, province))
|
||||
|
||||
def chosenSpecificImprovementCommandForProvince(
|
||||
@@ -41,20 +41,21 @@ object ImproveCommandSelector {
|
||||
actingProvinceId: ProvinceId,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
improvementType: ImprovementType
|
||||
): Option[CommandSelection] =
|
||||
flatSelectionForType[ImproveAvailableCommand](availableCommands) { improveCommand =>
|
||||
): Option[ScalaCommandSelection] =
|
||||
flatSelectionForType[ImproveAvailable](availableCommands) { improveCommand =>
|
||||
val actingPid = improveCommand.actingProvinceId
|
||||
Option.when(
|
||||
actingPid == actingProvinceId && improveCommand.availableTypes
|
||||
.contains(improvementType)
|
||||
) {
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = actingPid,
|
||||
available = improveCommand,
|
||||
selected = ImproveSelectedCommand(
|
||||
selected = ImproveSelected(
|
||||
improvementType = improvementType,
|
||||
actingHeroId = improveCommand.recommendedHeroId
|
||||
actingHeroId = improveCommand.recommendedHeroId,
|
||||
lockType = false
|
||||
),
|
||||
reason = "chosenSpecificImprovementCommandForProvince"
|
||||
)
|
||||
@@ -66,21 +67,22 @@ object ImproveCommandSelector {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
improvementType: ImprovementType
|
||||
): Option[CommandSelection] =
|
||||
flatSelectionForType[ImproveAvailableCommand](availableCommands) { improveCommand =>
|
||||
): Option[ScalaCommandSelection] =
|
||||
flatSelectionForType[ImproveAvailable](availableCommands) { improveCommand =>
|
||||
val actingPid = improveCommand.actingProvinceId
|
||||
Option.when(improveCommand.availableTypes.contains(improvementType)) {
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = actingPid,
|
||||
available = improveCommand,
|
||||
selected = ImproveSelectedCommand(
|
||||
selected = ImproveSelected(
|
||||
improvementType = improvementType,
|
||||
actingHeroId = minimallyFatiguedHeroes(
|
||||
improveCommand.availableHeroIds.toVector.map(
|
||||
gameState.heroes(_)
|
||||
)
|
||||
).maxBy(HeroUtils.power(_)).id
|
||||
).maxBy(HeroUtils.power(_)).id,
|
||||
lockType = false
|
||||
),
|
||||
reason = "chosenSpecificImprovementCommand"
|
||||
)
|
||||
@@ -90,13 +92,13 @@ object ImproveCommandSelector {
|
||||
def commandSelection(
|
||||
gameState: GameState,
|
||||
actingFactionId: FactionId,
|
||||
improveAvailableCommand: ImproveAvailableCommand
|
||||
): CommandSelection =
|
||||
CommandSelection(
|
||||
improveAvailableCommand: ImproveAvailable
|
||||
): ScalaCommandSelection =
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = improveAvailableCommand.actingProvinceId,
|
||||
available = improveAvailableCommand,
|
||||
selected = ImproveSelectedCommand(
|
||||
selected = ImproveSelected(
|
||||
improvementType = chosenType(
|
||||
improveAvailableCommand.availableTypes.toVector,
|
||||
gameState.provinces(improveAvailableCommand.actingProvinceId)
|
||||
@@ -105,7 +107,8 @@ object ImproveCommandSelector {
|
||||
improveAvailableCommand.availableHeroIds.toVector.map(
|
||||
gameState.heroes(_)
|
||||
)
|
||||
).maxBy(HeroUtils.power(_)).id
|
||||
).maxBy(HeroUtils.power(_)).id,
|
||||
lockType = false
|
||||
),
|
||||
reason = "ImproveCommandSelector.commandSelection"
|
||||
)
|
||||
@@ -114,8 +117,8 @@ object ImproveCommandSelector {
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] =
|
||||
selectionForType[ImproveAvailableCommand](availableCommands) { improveCommand =>
|
||||
): Option[ScalaCommandSelection] =
|
||||
selectionForType[ImproveAvailable](availableCommands) { improveCommand =>
|
||||
commandSelection(gameState, actingFactionId, improveCommand)
|
||||
}
|
||||
}
|
||||
|
||||
+23
-20
@@ -2,25 +2,22 @@ package net.eagle0.eagle.library.util.command_choice_helpers
|
||||
|
||||
import scala.annotation.tailrec
|
||||
|
||||
import net.eagle0.eagle.api.available_command.{AvailableCommand, OrganizeTroopsAvailableCommand}
|
||||
import net.eagle0.eagle.api.selected_command.OrganizeTroopsSelectedCommand
|
||||
import net.eagle0.eagle.api.selected_command.OrganizeTroopsSelectedCommand.{ChangedBattalion, NewBattalion}
|
||||
import net.eagle0.eagle.common.battalion_type.BattalionTypeId as ProtoBattalionTypeId
|
||||
import net.eagle0.eagle.library.util.battalion_type_finder.BattalionTypeFinder
|
||||
import net.eagle0.eagle.library.util.battalion_type_finder.BattalionTypeFinder.battalionType
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.AvailableCommandSelector.flatSelectionForType
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.ProvinceGoldSurplusCalculator
|
||||
import net.eagle0.eagle.library.util.province.ProvinceUtils
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.{BattalionType, BattalionTypeId}
|
||||
import net.eagle0.eagle.model.state.battalion.BattalionT
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.OrganizeTroopsAvailable
|
||||
import net.eagle0.eagle.model.state.command.selected.{ChangedBattalion, NewBattalion}
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.OrganizeTroopsSelected
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.FactionId
|
||||
|
||||
object OrganizeCommandSelector {
|
||||
// Helper to convert Scala BattalionTypeId to proto BattalionTypeId
|
||||
private def toProtoBattalionTypeId(typeId: BattalionTypeId): ProtoBattalionTypeId =
|
||||
ProtoBattalionTypeId.fromValue(typeId.value)
|
||||
|
||||
case class ChangedBattalionsResult(
|
||||
changedBattalions: Vector[ChangedBattalion],
|
||||
@@ -62,7 +59,12 @@ object OrganizeCommandSelector {
|
||||
gold - goldCost,
|
||||
foodSurplus - foodCost,
|
||||
bs,
|
||||
ChangedBattalion(id = b.id, newTroops = missing) +: acc
|
||||
ChangedBattalion(
|
||||
id = b.id,
|
||||
troopsFromOtherBattalion = Vector(),
|
||||
newTroops = missing,
|
||||
dismissedTroops = 0
|
||||
) +: acc
|
||||
)
|
||||
else
|
||||
ChangedBattalionsResult(
|
||||
@@ -70,6 +72,7 @@ object OrganizeCommandSelector {
|
||||
remainingGold = gold,
|
||||
remainingFoodSurplus = foodSurplus
|
||||
)
|
||||
end if
|
||||
|
||||
case _ =>
|
||||
ChangedBattalionsResult(
|
||||
@@ -148,7 +151,8 @@ object OrganizeCommandSelector {
|
||||
.headOption match {
|
||||
case Some(x) =>
|
||||
val newBattalion = NewBattalion(
|
||||
`type` = toProtoBattalionTypeId(x.battalionTypeId),
|
||||
typeId = x.battalionTypeId.value,
|
||||
troopsFromOtherBattalion = Vector(),
|
||||
newTroops = battalionType(x.battalionTypeId, allBattalionTypes).capacity
|
||||
)
|
||||
go(
|
||||
@@ -178,25 +182,24 @@ object OrganizeCommandSelector {
|
||||
|
||||
def selectedOrganizeCommand(
|
||||
actingFactionId: FactionId,
|
||||
availableCommand: OrganizeTroopsAvailableCommand,
|
||||
availableCommand: OrganizeTroopsAvailable,
|
||||
gameState: GameState,
|
||||
extraFoodSurplus: Int,
|
||||
reason: String
|
||||
): Option[CommandSelection] = {
|
||||
): Option[ScalaCommandSelection] = {
|
||||
val province = gameState.provinces(availableCommand.actingProvinceId)
|
||||
val foodSurplus =
|
||||
ProvinceUtils.monthlyFoodSurplus(province, gameState) + extraFoodSurplus
|
||||
val goldSurplus = ProvinceGoldSurplusCalculator.provinceGoldSurplus(province)
|
||||
if foodSurplus <= 0 || goldSurplus <= 0 then None
|
||||
else {
|
||||
// Convert proto BattalionTypeId to Scala BattalionTypeId
|
||||
val costs = availableCommand.troopCosts
|
||||
.map(tc => BattalionTypeId.fromInt(tc.`type`.value) -> tc.costPerTroop)
|
||||
.map(tc => BattalionTypeId.fromInt(tc.battalionTypeId) -> tc.costPerTroop)
|
||||
.toMap
|
||||
val eligibleTypeIds = availableCommand.availableBattalionTypes
|
||||
.filter(_.meetsRequirements)
|
||||
.toVector
|
||||
.map(abt => BattalionTypeId.fromInt(abt.typeId.value))
|
||||
.map(abt => BattalionTypeId.fromInt(abt.typeId))
|
||||
|
||||
val toppedBattalionResults = changedBattalions(
|
||||
gold = goldSurplus,
|
||||
@@ -222,11 +225,11 @@ object OrganizeCommandSelector {
|
||||
Option.when(
|
||||
toppedBattalionResults.changedBattalions.nonEmpty || newBattalionResults.newBattalions.nonEmpty
|
||||
) {
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = availableCommand.actingProvinceId,
|
||||
available = availableCommand,
|
||||
selected = OrganizeTroopsSelectedCommand(
|
||||
selected = OrganizeTroopsSelected(
|
||||
changedBattalions = toppedBattalionResults.changedBattalions,
|
||||
newBattalions = newBattalionResults.newBattalions
|
||||
),
|
||||
@@ -243,8 +246,8 @@ object OrganizeCommandSelector {
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
extraFoodSurplus: Int,
|
||||
reason: String
|
||||
): Option[CommandSelection] =
|
||||
flatSelectionForType[OrganizeTroopsAvailableCommand](availableCommands) { availableCommand =>
|
||||
): Option[ScalaCommandSelection] =
|
||||
flatSelectionForType[OrganizeTroopsAvailable](availableCommands) { availableCommand =>
|
||||
selectedOrganizeCommand(
|
||||
actingFactionId = actingFactionId,
|
||||
availableCommand = availableCommand,
|
||||
@@ -259,7 +262,7 @@ object OrganizeCommandSelector {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
reason: String
|
||||
): Option[CommandSelection] = chosenOrganizeCommandWithFoodSurplus(
|
||||
): Option[ScalaCommandSelection] = chosenOrganizeCommandWithFoodSurplus(
|
||||
actingFactionId = actingFactionId,
|
||||
gameState = gameState,
|
||||
availableCommands = availableCommands,
|
||||
|
||||
+11
-10
@@ -1,28 +1,29 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers
|
||||
|
||||
import net.eagle0.eagle.{FactionId, HeroId}
|
||||
import net.eagle0.eagle.api.available_command.{AvailableCommand, SwearBrotherhoodAvailableCommand}
|
||||
import net.eagle0.eagle.api.selected_command.SwearBrotherhoodSelectedCommand
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.AvailableCommandSelector.flatSelectionForType
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.SwearBrotherhoodAvailable
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.SwearBrotherhoodSelected
|
||||
|
||||
object SwearBrotherhoodCommandSelector {
|
||||
def chosenCommandForSpecificHero(
|
||||
actingFactionId: FactionId,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
desiredHeroId: HeroId
|
||||
): Option[CommandSelection] =
|
||||
flatSelectionForType[SwearBrotherhoodAvailableCommand](availableCommands) { swearBrotherhoodAvailableCommand =>
|
||||
): Option[ScalaCommandSelection] =
|
||||
flatSelectionForType[SwearBrotherhoodAvailable](availableCommands) { swearBrotherhoodAvailable =>
|
||||
Option.when(
|
||||
swearBrotherhoodAvailableCommand.availableHeroes
|
||||
swearBrotherhoodAvailable.availableHeroes
|
||||
.map(_.heroId)
|
||||
.contains(desiredHeroId)
|
||||
) {
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = swearBrotherhoodAvailableCommand.actingProvinceId,
|
||||
available = swearBrotherhoodAvailableCommand,
|
||||
selected = SwearBrotherhoodSelectedCommand(newBrotherHeroId = desiredHeroId),
|
||||
actingProvinceId = swearBrotherhoodAvailable.actingProvinceId,
|
||||
available = swearBrotherhoodAvailable,
|
||||
selected = SwearBrotherhoodSelected(newBrotherHeroId = desiredHeroId),
|
||||
reason = "chose swear brotherhood"
|
||||
)
|
||||
}
|
||||
|
||||
+18
-22
@@ -1,12 +1,13 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers
|
||||
|
||||
import net.eagle0.eagle.{FactionId, HeroId}
|
||||
import net.eagle0.eagle.api.available_command.{AvailableCommand, DiplomacyAvailableCommand}
|
||||
import net.eagle0.eagle.api.command.util.diplomacy_option.{DiplomacyOption, TruceOption}
|
||||
import net.eagle0.eagle.api.selected_command.DiplomacySelectedCommand
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.AvailableCommandSelector.ofType
|
||||
import net.eagle0.eagle.library.util.faction_utils.FactionUtils
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.{DiplomacyAvailable, DiplomacyOption}
|
||||
import net.eagle0.eagle.model.state.command.common.DiplomacyOptionType
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.DiplomacySelected
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
|
||||
object TruceOfferCommandSelector {
|
||||
@@ -16,13 +17,13 @@ object TruceOfferCommandSelector {
|
||||
): Vector[HeroId] =
|
||||
hids.filterNot(FactionUtils.isFactionLeader(_, gameState.factions.values.toVector))
|
||||
|
||||
private def truceOptionWithTarget(
|
||||
private def hasTruceOptionWithTarget(
|
||||
options: Vector[DiplomacyOption],
|
||||
targetFactionId: FactionId
|
||||
): Option[TruceOption] =
|
||||
options.collectFirst {
|
||||
case x @ TruceOption(tfid, _, _ /* unknownFieldSet */ ) if tfid == targetFactionId =>
|
||||
x
|
||||
): Boolean =
|
||||
options.exists { opt =>
|
||||
opt.targetFactionId == targetFactionId &&
|
||||
opt.optionTypes.contains(DiplomacyOptionType.Truce)
|
||||
}
|
||||
|
||||
def chosenTruceWithFactionCommand(
|
||||
@@ -30,24 +31,19 @@ object TruceOfferCommandSelector {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
targetFactionId: FactionId
|
||||
): Option[CommandSelection] =
|
||||
ofType[DiplomacyAvailableCommand](availableCommands).find { ac =>
|
||||
truceOptionWithTarget(
|
||||
ac.options.toVector,
|
||||
targetFactionId
|
||||
).isDefined && usableHeroIds(
|
||||
ac.availableHeroIds.toVector,
|
||||
gameState
|
||||
).nonEmpty
|
||||
): Option[ScalaCommandSelection] =
|
||||
ofType[DiplomacyAvailable](availableCommands).find { ac =>
|
||||
hasTruceOptionWithTarget(ac.options, targetFactionId) &&
|
||||
usableHeroIds(ac.availableHeroIds, gameState).nonEmpty
|
||||
}.map { ac =>
|
||||
CommandSelection(
|
||||
ScalaCommandSelection(
|
||||
actingFactionId = actingFactionId,
|
||||
actingProvinceId = ac.actingProvinceId,
|
||||
available = ac,
|
||||
selected = DiplomacySelectedCommand(
|
||||
selectedOption = truceOptionWithTarget(ac.options.toVector, targetFactionId).get,
|
||||
selected = DiplomacySelected(
|
||||
selectedOption = DiplomacyOptionType.Truce,
|
||||
targetFactionId = targetFactionId,
|
||||
sentHeroId = usableHeroIds(ac.availableHeroIds.toVector, gameState).maxBy { hid =>
|
||||
sentHeroId = usableHeroIds(ac.availableHeroIds, gameState).maxBy { hid =>
|
||||
gameState.heroes(hid).vigor
|
||||
}
|
||||
),
|
||||
|
||||
+9
-9
@@ -1,10 +1,11 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers.quest_command_selectors
|
||||
|
||||
import net.eagle0.common.{FunctionalRandom, RandomState}
|
||||
import net.eagle0.eagle.api.available_command.{AvailableCommand, DiplomacyAvailableCommand}
|
||||
import net.eagle0.eagle.api.command.util.diplomacy_option.AllianceOption
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.{AllianceOfferCommandSelector, TrustForDiplomacy}
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.DiplomacyAvailable
|
||||
import net.eagle0.eagle.model.state.command.common.DiplomacyOptionType
|
||||
import net.eagle0.eagle.model.state.faction.FactionRelationship.RelationshipLevel.Ally
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.quest.concrete.AllianceQuest
|
||||
@@ -17,13 +18,12 @@ object AllianceQuestCommandChooser extends QuestCommandChooser {
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
uhsWithQuests: Vector[UnaffiliatedHeroWithQuest],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] = {
|
||||
): RandomState[Option[ScalaCommandSelection]] = {
|
||||
val allianceTargets: Vector[FactionId] = availableCommands.collect {
|
||||
case cmd: DiplomacyAvailableCommand =>
|
||||
cmd.options.collect {
|
||||
case alliance: AllianceOption =>
|
||||
alliance.targetFactionId
|
||||
}
|
||||
case cmd: DiplomacyAvailable =>
|
||||
cmd.options.filter { opt =>
|
||||
opt.optionTypes.contains(DiplomacyOptionType.Alliance)
|
||||
}.map(_.targetFactionId)
|
||||
}.flatten
|
||||
|
||||
functionalRandom
|
||||
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers.quest_command_selectors
|
||||
import net.eagle0.eagle.api.available_command.AvailableCommand
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.AlmsCommandSelector
|
||||
import net.eagle0.eagle.library.util.faction_utils.FactionUtils
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.quest.concrete.AlmsAcrossRealmQuest
|
||||
import net.eagle0.eagle.FactionId
|
||||
@@ -23,7 +23,7 @@ object AlmsAcrossRealmQuestCommandChooser extends DeterministicQuestCommandChoos
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] =
|
||||
): Option[ScalaCommandSelection] =
|
||||
FactionUtils
|
||||
.provinces(actingFactionId, gameState.provinces.values.toVector)
|
||||
.flatMap { p =>
|
||||
@@ -49,7 +49,7 @@ object AlmsAcrossRealmQuestCommandChooser extends DeterministicQuestCommandChoos
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
uhsWithQuests: Vector[UnaffiliatedHeroWithQuest]
|
||||
): Option[CommandSelection] =
|
||||
): Option[ScalaCommandSelection] =
|
||||
maxRequestedAmount(uhsWithQuests).flatMap { amount =>
|
||||
bestCommand(
|
||||
desiredAmount = amount,
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers.quest_command_selectors
|
||||
import net.eagle0.eagle.{FactionId, ProvinceId}
|
||||
import net.eagle0.eagle.api.available_command.AvailableCommand
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.AlmsCommandSelector
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.quest.concrete.AlmsToProvinceQuest
|
||||
|
||||
@@ -12,7 +12,7 @@ object AlmsToProvinceQuestCommandChooser extends DeterministicQuestCommandChoose
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
uhsWithQuests: Vector[UnaffiliatedHeroWithQuest]
|
||||
): Option[CommandSelection] =
|
||||
): Option[ScalaCommandSelection] =
|
||||
uhsWithQuests
|
||||
.map(uhwq => (uhwq.pid, uhwq.quest))
|
||||
.collect {
|
||||
|
||||
+12
-11
@@ -13,12 +13,13 @@ scala_library(
|
||||
deps = [
|
||||
":quest_command_chooser",
|
||||
":unaffiliated_hero_with_quest",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//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:alliance_offer_command_selector",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers:trust_for_diplomacy",
|
||||
"//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/faction",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/quest/concrete",
|
||||
@@ -39,11 +40,11 @@ scala_library(
|
||||
deps = [
|
||||
":quest_command_chooser",
|
||||
":unaffiliated_hero_with_quest",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//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:alms_command_selector",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/faction_utils",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/quest/concrete",
|
||||
],
|
||||
@@ -63,10 +64,10 @@ scala_library(
|
||||
deps = [
|
||||
":quest_command_chooser",
|
||||
":unaffiliated_hero_with_quest",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//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:alms_command_selector",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/quest/concrete",
|
||||
],
|
||||
@@ -86,7 +87,6 @@ scala_library(
|
||||
deps = [
|
||||
":quest_command_chooser",
|
||||
":unaffiliated_hero_with_quest",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:more_option",
|
||||
"//src/main/scala/net/eagle0/common:more_seq",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
@@ -94,6 +94,7 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:command_selection",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers:exile_vassal_command_selector",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero:hero_utils",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/quest/concrete",
|
||||
],
|
||||
@@ -113,11 +114,11 @@ scala_library(
|
||||
deps = [
|
||||
":quest_command_chooser",
|
||||
":unaffiliated_hero_with_quest",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//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:hero_gift_command_selector",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/faction_utils",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/quest/concrete",
|
||||
],
|
||||
@@ -137,10 +138,10 @@ scala_library(
|
||||
deps = [
|
||||
":quest_command_chooser",
|
||||
":unaffiliated_hero_with_quest",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//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:hero_gift_command_selector",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/quest/concrete",
|
||||
],
|
||||
@@ -159,11 +160,11 @@ scala_library(
|
||||
deps = [
|
||||
":quest_command_chooser",
|
||||
":unaffiliated_hero_with_quest",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/common:improvement_type_scala_proto",
|
||||
"//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:improve_command_selector",
|
||||
"//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/quest/concrete",
|
||||
],
|
||||
@@ -182,10 +183,10 @@ scala_library(
|
||||
],
|
||||
deps = [
|
||||
":unaffiliated_hero_with_quest",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//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/game_state",
|
||||
],
|
||||
)
|
||||
@@ -203,13 +204,13 @@ scala_library(
|
||||
deps = [
|
||||
":quest_command_chooser",
|
||||
":unaffiliated_hero_with_quest",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//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:truce_offer_command_selector",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers:trust_for_diplomacy",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/faction_utils",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/quest/concrete",
|
||||
],
|
||||
@@ -228,11 +229,11 @@ scala_library(
|
||||
deps = [
|
||||
":quest_command_chooser",
|
||||
":unaffiliated_hero_with_quest",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//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:truce_offer_command_selector",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers:trust_for_diplomacy",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/quest/concrete",
|
||||
],
|
||||
|
||||
+3
-3
@@ -2,11 +2,11 @@ package net.eagle0.eagle.library.util.command_choice_helpers.quest_command_selec
|
||||
|
||||
import net.eagle0.common.MoreOption
|
||||
import net.eagle0.common.MoreSeq.flatCollectFirst
|
||||
import net.eagle0.eagle.api.available_command.AvailableCommand
|
||||
import net.eagle0.eagle.library.settings.RequiredPowerMultiplierForDismiss
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.ExileVassalCommandSelector
|
||||
import net.eagle0.eagle.library.util.hero.HeroUtils
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.quest.concrete.DismissSpecificVassalQuest
|
||||
import net.eagle0.eagle.FactionId
|
||||
@@ -18,7 +18,7 @@ object DismissSpecificVassalCommandChooser extends DeterministicQuestCommandChoo
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
uhsWithQuests: Vector[UnaffiliatedHeroWithQuest]
|
||||
): Option[CommandSelection] =
|
||||
): Option[ScalaCommandSelection] =
|
||||
uhsWithQuests.flatCollectFirst {
|
||||
case UnaffiliatedHeroWithQuest(
|
||||
pid,
|
||||
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers.quest_command_selectors
|
||||
import net.eagle0.eagle.api.available_command.AvailableCommand
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.HeroGiftCommandSelector
|
||||
import net.eagle0.eagle.library.util.faction_utils.FactionUtils
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.quest.concrete.GiveToHeroesAcrossRealmQuest
|
||||
import net.eagle0.eagle.FactionId
|
||||
@@ -23,7 +23,7 @@ object GiveToHeroesAcrossRealmQuestCommandChooser extends DeterministicQuestComm
|
||||
actingFactionId: FactionId,
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand]
|
||||
): Option[CommandSelection] =
|
||||
): Option[ScalaCommandSelection] =
|
||||
FactionUtils
|
||||
.provinces(actingFactionId, gameState.provinces.values.toVector)
|
||||
.flatMap { p =>
|
||||
@@ -45,7 +45,7 @@ object GiveToHeroesAcrossRealmQuestCommandChooser extends DeterministicQuestComm
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
uhsWithQuests: Vector[UnaffiliatedHeroWithQuest]
|
||||
): Option[CommandSelection] =
|
||||
): Option[ScalaCommandSelection] =
|
||||
maxRequestedAmount(uhsWithQuests).flatMap { amount =>
|
||||
bestCommand(
|
||||
desiredAmount = amount,
|
||||
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers.quest_command_selectors
|
||||
|
||||
import net.eagle0.eagle.{FactionId, ProvinceId}
|
||||
import net.eagle0.eagle.api.available_command.AvailableCommand
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.HeroGiftCommandSelector
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.quest.concrete.GiveToHeroesInProvinceQuest
|
||||
|
||||
@@ -13,7 +13,7 @@ object GiveToHeroesInProvinceQuestCommandChooser extends DeterministicQuestComma
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
uhsWithQuests: Vector[UnaffiliatedHeroWithQuest]
|
||||
): Option[CommandSelection] =
|
||||
): Option[ScalaCommandSelection] =
|
||||
uhsWithQuests
|
||||
.map(uhwq => (uhwq.pid, uhwq.quest))
|
||||
.collect {
|
||||
|
||||
+7
-7
@@ -1,9 +1,9 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers.quest_command_selectors
|
||||
|
||||
import net.eagle0.eagle.api.available_command.AvailableCommand
|
||||
import net.eagle0.eagle.common.improvement_type.ImprovementType.{AGRICULTURE, ECONOMY, INFRASTRUCTURE}
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.ImproveCommandSelector
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.common.ImprovementType.{Agriculture, Economy, Infrastructure}
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.quest.concrete.{
|
||||
ImproveAgricultureQuest,
|
||||
@@ -18,13 +18,13 @@ object ImproveQuestCommandChooser extends DeterministicQuestCommandChooser {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
uhsWithQuests: Vector[UnaffiliatedHeroWithQuest]
|
||||
): Option[CommandSelection] =
|
||||
): Option[ScalaCommandSelection] =
|
||||
uhsWithQuests
|
||||
.map(uhwq => (uhwq.pid, uhwq.quest))
|
||||
.collect {
|
||||
case (pid, _: ImproveEconomyQuest) => (pid, ECONOMY)
|
||||
case (pid, _: ImproveAgricultureQuest) => (pid, AGRICULTURE)
|
||||
case (pid, _: ImproveInfrastructureQuest) => (pid, INFRASTRUCTURE)
|
||||
case (pid, _: ImproveEconomyQuest) => (pid, Economy)
|
||||
case (pid, _: ImproveAgricultureQuest) => (pid, Agriculture)
|
||||
case (pid, _: ImproveInfrastructureQuest) => (pid, Infrastructure)
|
||||
}
|
||||
.flatMap {
|
||||
case (pid, it) =>
|
||||
|
||||
+5
-5
@@ -1,8 +1,8 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers.quest_command_selectors
|
||||
|
||||
import net.eagle0.common.{FunctionalRandom, RandomState}
|
||||
import net.eagle0.eagle.api.available_command.AvailableCommand
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.FactionId
|
||||
|
||||
@@ -13,7 +13,7 @@ trait QuestCommandChooser {
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
uhsWithQuests: Vector[UnaffiliatedHeroWithQuest],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]]
|
||||
): RandomState[Option[ScalaCommandSelection]]
|
||||
}
|
||||
|
||||
abstract class DeterministicQuestCommandChooser extends QuestCommandChooser {
|
||||
@@ -23,7 +23,7 @@ abstract class DeterministicQuestCommandChooser extends QuestCommandChooser {
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
uhsWithQuests: Vector[UnaffiliatedHeroWithQuest],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] = RandomState(
|
||||
): RandomState[Option[ScalaCommandSelection]] = RandomState(
|
||||
chosenDeterministicCommand(
|
||||
actingFactionId,
|
||||
gameState,
|
||||
@@ -38,5 +38,5 @@ abstract class DeterministicQuestCommandChooser extends QuestCommandChooser {
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
uhsWithQuests: Vector[UnaffiliatedHeroWithQuest]
|
||||
): Option[CommandSelection]
|
||||
): Option[ScalaCommandSelection]
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers.quest_command_selectors
|
||||
|
||||
import net.eagle0.common.{FunctionalRandom, RandomState}
|
||||
import net.eagle0.eagle.api.available_command.AvailableCommand
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.{TruceOfferCommandSelector, TrustForDiplomacy}
|
||||
import net.eagle0.eagle.library.util.faction_utils.FactionUtils
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.quest.concrete.TruceCountQuest
|
||||
import net.eagle0.eagle.FactionId
|
||||
@@ -16,7 +16,7 @@ object TruceCountQuestCommandChooser extends QuestCommandChooser {
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
uhsWithQuests: Vector[UnaffiliatedHeroWithQuest],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Option[CommandSelection]] =
|
||||
): RandomState[Option[ScalaCommandSelection]] =
|
||||
functionalRandom
|
||||
.nextFlatCollectFirst(uhsWithQuests.map(_.quest)) {
|
||||
case _: TruceCountQuest =>
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
package net.eagle0.eagle.library.util.command_choice_helpers.quest_command_selectors
|
||||
|
||||
import net.eagle0.eagle.api.available_command.AvailableCommand
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.{TruceOfferCommandSelector, TrustForDiplomacy}
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.game_state.GameState
|
||||
import net.eagle0.eagle.model.state.quest.concrete.TruceWithFactionQuest
|
||||
import net.eagle0.eagle.FactionId
|
||||
@@ -13,7 +13,7 @@ object TruceWithFactionQuestCommandChooser extends DeterministicQuestCommandChoo
|
||||
gameState: GameState,
|
||||
availableCommands: Vector[AvailableCommand],
|
||||
uhsWithQuests: Vector[UnaffiliatedHeroWithQuest]
|
||||
): Option[CommandSelection] =
|
||||
): Option[ScalaCommandSelection] =
|
||||
uhsWithQuests
|
||||
.map(_.quest)
|
||||
.collect { case twfq: TruceWithFactionQuest => twfq }
|
||||
|
||||
@@ -4,7 +4,7 @@ scala_library(
|
||||
name = "common",
|
||||
srcs = ["CommandTypes.scala"],
|
||||
visibility = [
|
||||
"//src/main/scala/net/eagle0/eagle/library/actions:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/library:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters/command:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/command:__subpackages__",
|
||||
"//src/test/scala/net/eagle0/eagle:__subpackages__",
|
||||
|
||||
@@ -30,20 +30,18 @@ scala_test(
|
||||
name = "fix_leader_alone_command_selector_test",
|
||||
srcs = ["FixLeaderAloneCommandSelectorTest.scala"],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/ai:fix_leader_alone_command_selector",
|
||||
"//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/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/province",
|
||||
"//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/util/command_choice_helpers:available_command_matcher",
|
||||
"//src/test/scala/net/eagle0/eagle/library/util/command_choice_helpers:selected_command_matcher",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -51,8 +49,6 @@ scala_test(
|
||||
name = "invitation_command_selector_test",
|
||||
srcs = ["InvitationCommandSelectorTest.scala"],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/ai:invitation_command_selector",
|
||||
"//src/main/scala/net/eagle0/eagle/library/settings:gold_per_hero_held_back",
|
||||
@@ -64,6 +60,9 @@ scala_test(
|
||||
"//src/main/scala/net/eagle0/eagle/library/settings:prestige_per_supported_province",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:command_selection",
|
||||
"//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/faction",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/faction/concrete",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
@@ -77,9 +76,6 @@ scala_test(
|
||||
name = "mid_game_ai_client_test",
|
||||
srcs = ["MidGameAIClientTest.scala"],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/common:battalion_type_scala_proto",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/ai:mid_game_ai_client",
|
||||
"//src/main/scala/net/eagle0/eagle/library/settings:gold_per_hero_held_back",
|
||||
@@ -90,6 +86,9 @@ scala_test(
|
||||
"//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/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",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/faction/concrete",
|
||||
@@ -107,13 +106,13 @@ scala_test(
|
||||
name = "move_leader_to_better_province_command_chooser_test",
|
||||
srcs = ["MoveLeaderToBetterProvinceCommandChooserTest.scala"],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/ai:move_leader_to_better_province_command_chooser",
|
||||
"//src/main/scala/net/eagle0/eagle/library/settings:gold_per_hero_held_back",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:command_selection",
|
||||
"//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/faction",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/faction/concrete",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
@@ -146,8 +145,6 @@ scala_test(
|
||||
name = "seek_more_leaders_command_chooser_test",
|
||||
srcs = ["SeekMoreLeadersCommandChooserTest.scala"],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/ai:seek_more_leaders_command_chooser",
|
||||
"//src/main/scala/net/eagle0/eagle/library/settings:ai_minimum_charisma_for_sworn_brother",
|
||||
@@ -156,6 +153,9 @@ scala_test(
|
||||
"//src/main/scala/net/eagle0/eagle/library/settings:minimum_loyalty_for_swear_brotherhood",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:command_selection",
|
||||
"//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/faction",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/faction/concrete",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
|
||||
|
||||
@@ -4,15 +4,14 @@ import scala.util.Random
|
||||
|
||||
import net.eagle0.common.SeededRandom
|
||||
import net.eagle0.eagle.{FactionId, HeroId, ProvinceId}
|
||||
import net.eagle0.eagle.api.available_command.{
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.{
|
||||
AvailableDestinationProvince,
|
||||
MarchAvailableCommand,
|
||||
MarchAvailable,
|
||||
MarchCommandFromOneProvince
|
||||
}
|
||||
import net.eagle0.eagle.api.selected_command.MarchSelectedCommand
|
||||
import net.eagle0.eagle.common.combat_unit.CombatUnit
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.AvailableCommandMatcher.equalAvailableCommand
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.SelectedCommandMatcher.equalSelectedCommand
|
||||
import net.eagle0.eagle.model.state.command.selected.CombatUnit
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.MarchSelected
|
||||
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
|
||||
@@ -23,6 +22,7 @@ import net.eagle0.eagle.model.state.RoundPhase
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.BeforeAndAfterEach
|
||||
import org.scalatest.Inside.inside
|
||||
|
||||
class FixLeaderAloneCommandSelectorTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach {
|
||||
|
||||
@@ -81,6 +81,35 @@ class FixLeaderAloneCommandSelectorTest extends AnyFlatSpec with Matchers with B
|
||||
chronicleEntries = Vector.empty
|
||||
)
|
||||
|
||||
private def makeMarchAvailable(
|
||||
actingProvinceId: ProvinceId,
|
||||
oneProvinceCommands: Vector[MarchCommandFromOneProvince]
|
||||
): MarchAvailable =
|
||||
MarchAvailable(
|
||||
oneProvinceCommands = oneProvinceCommands,
|
||||
actingProvinceId = actingProvinceId,
|
||||
availableTypes = Vector.empty
|
||||
)
|
||||
|
||||
private def makeMarchCommand(
|
||||
originProvinceId: ProvinceId,
|
||||
availableDestinationProvinces: Vector[AvailableDestinationProvince],
|
||||
availableHeroIds: Vector[HeroId],
|
||||
goldAvailable: Int = 0,
|
||||
foodAvailable: Int = 0
|
||||
): MarchCommandFromOneProvince =
|
||||
MarchCommandFromOneProvince(
|
||||
suitableBattalionsForHeroes = Map.empty,
|
||||
originProvinceId = originProvinceId,
|
||||
goldCost = 0,
|
||||
goldAvailable = goldAvailable,
|
||||
foodAvailable = foodAvailable,
|
||||
availableDestinationProvinces = availableDestinationProvinces,
|
||||
availableHeroIds = availableHeroIds,
|
||||
availableBattalions = Vector.empty,
|
||||
recommendedBattleConfig = None
|
||||
)
|
||||
|
||||
private val province14: ProvinceC = ProvinceC(
|
||||
id = 14,
|
||||
rulingFactionId = Some(factionId),
|
||||
@@ -117,11 +146,11 @@ class FixLeaderAloneCommandSelectorTest extends AnyFlatSpec with Matchers with B
|
||||
provinces = mapifyProvinces(province14, province15, province16, province17)
|
||||
)
|
||||
|
||||
private val availableCommands = Vector(
|
||||
MarchAvailableCommand(
|
||||
private val availableCommands: Vector[AvailableCommand] = Vector(
|
||||
makeMarchAvailable(
|
||||
actingProvinceId = factionLeaderProvinceId,
|
||||
oneProvinceCommands = Vector(
|
||||
MarchCommandFromOneProvince(
|
||||
makeMarchCommand(
|
||||
originProvinceId = 15,
|
||||
availableHeroIds = Vector(151),
|
||||
availableDestinationProvinces = Vector(14, 16).map(pid =>
|
||||
@@ -133,10 +162,10 @@ class FixLeaderAloneCommandSelectorTest extends AnyFlatSpec with Matchers with B
|
||||
)
|
||||
)
|
||||
),
|
||||
MarchAvailableCommand(
|
||||
makeMarchAvailable(
|
||||
actingProvinceId = factionLeaderProvinceId,
|
||||
oneProvinceCommands = Vector(
|
||||
MarchCommandFromOneProvince(
|
||||
makeMarchCommand(
|
||||
originProvinceId = 16,
|
||||
availableHeroIds = Vector(161),
|
||||
availableDestinationProvinces = Vector(15, 17).map(pid =>
|
||||
@@ -178,34 +207,21 @@ class FixLeaderAloneCommandSelectorTest extends AnyFlatSpec with Matchers with B
|
||||
.newValue
|
||||
.get
|
||||
|
||||
selection.available should equalAvailableCommand(
|
||||
MarchAvailableCommand(
|
||||
actingProvinceId = factionLeaderProvinceId,
|
||||
oneProvinceCommands = Vector(
|
||||
MarchCommandFromOneProvince(
|
||||
originProvinceId = 16,
|
||||
availableHeroIds = Vector(161),
|
||||
availableDestinationProvinces = Vector(15, 17).map(pid =>
|
||||
AvailableDestinationProvince(
|
||||
provinceId = pid,
|
||||
requiresRiverCrossing = false
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
selection.actingProvinceId shouldBe factionLeaderProvinceId
|
||||
|
||||
selection.selected should equalSelectedCommand(
|
||||
MarchSelectedCommand(
|
||||
gold = 0,
|
||||
food = 0,
|
||||
originProvince = 16,
|
||||
destinationProvinceId = 17,
|
||||
marchingUnits = Vector(
|
||||
CombatUnit(factionId = factionId, heroId = 161, battalionId = None)
|
||||
)
|
||||
)
|
||||
)
|
||||
inside(selection.available) {
|
||||
case marchAvailable: MarchAvailable =>
|
||||
marchAvailable.actingProvinceId shouldBe factionLeaderProvinceId
|
||||
marchAvailable.oneProvinceCommands should have length 1
|
||||
marchAvailable.oneProvinceCommands.head.originProvinceId shouldBe 16
|
||||
}
|
||||
|
||||
inside(selection.selected) {
|
||||
case marchSelected: MarchSelected =>
|
||||
marchSelected.originProvince shouldBe 16
|
||||
marchSelected.destinationProvinceId shouldBe 17
|
||||
marchSelected.marchingUnits should have length 1
|
||||
marchSelected.marchingUnits.head.heroId shouldBe 161
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package net.eagle0.eagle.ai
|
||||
|
||||
import net.eagle0.eagle.{FactionId, HeroId, ProvinceId}
|
||||
import net.eagle0.eagle.api.available_command.{AvailableCommand, DiplomacyAvailableCommand}
|
||||
import net.eagle0.eagle.api.command.util.diplomacy_option.{InvitationOption, TruceOption}
|
||||
import net.eagle0.eagle.api.selected_command.DiplomacySelectedCommand
|
||||
import net.eagle0.eagle.library.settings.{
|
||||
GoldPerHeroHeldBack,
|
||||
MinChanceForAIInvite,
|
||||
@@ -13,6 +10,10 @@ import net.eagle0.eagle.library.settings.{
|
||||
MinimumTrustToInvite,
|
||||
PrestigePerSupportedProvince
|
||||
}
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.{DiplomacyAvailable, DiplomacyOption}
|
||||
import net.eagle0.eagle.model.state.command.common.DiplomacyOptionType
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.DiplomacySelected
|
||||
import net.eagle0.eagle.model.state.faction.{FactionRelationship, FactionT}
|
||||
import net.eagle0.eagle.model.state.faction.concrete.FactionC
|
||||
import net.eagle0.eagle.model.state.faction.FactionRelationship.RelationshipLevel.Hostile
|
||||
@@ -116,13 +117,18 @@ class InvitationCommandSelectorTest extends AnyFlatSpec with Matchers with Befor
|
||||
provinces = mapifyProvinces(actingProvince, province90, province91, province99)
|
||||
)
|
||||
|
||||
private val invitationOption =
|
||||
InvitationOption(targetFactionId = targetFactionId, goldCost = 1000)
|
||||
private val diplomacyAvailableCommand = DiplomacyAvailableCommand(
|
||||
options = Vector(
|
||||
TruceOption(targetFactionId = targetFactionId),
|
||||
invitationOption
|
||||
),
|
||||
private val invitationOption: DiplomacyOption =
|
||||
DiplomacyOption(
|
||||
targetFactionId = targetFactionId,
|
||||
optionTypes = Vector(DiplomacyOptionType.Invitation)
|
||||
)
|
||||
private val truceOption: DiplomacyOption =
|
||||
DiplomacyOption(
|
||||
targetFactionId = targetFactionId,
|
||||
optionTypes = Vector(DiplomacyOptionType.Truce)
|
||||
)
|
||||
private val diplomacyAvailableCommand: DiplomacyAvailable = DiplomacyAvailable(
|
||||
options = Vector(truceOption, invitationOption),
|
||||
availableHeroIds = Vector(15, 25, 35),
|
||||
actingProvinceId = actingProvinceId,
|
||||
recommendedHeroId = 25
|
||||
@@ -157,26 +163,26 @@ class InvitationCommandSelectorTest extends AnyFlatSpec with Matchers with Befor
|
||||
|
||||
chosenCommand.available shouldBe diplomacyAvailableCommand
|
||||
inside(chosenCommand.selected) {
|
||||
case DiplomacySelectedCommand(
|
||||
selectedOption,
|
||||
targetFactionId,
|
||||
sentHeroId,
|
||||
_ /* unknownFieldSet */
|
||||
) =>
|
||||
selectedOption shouldBe invitationOption
|
||||
targetFactionId shouldBe targetFactionId
|
||||
case DiplomacySelected(selectedOption, selectedTargetFid, sentHeroId) =>
|
||||
selectedOption shouldBe DiplomacyOptionType.Invitation
|
||||
selectedTargetFid shouldBe targetFactionId
|
||||
sentHeroId shouldBe 25
|
||||
}
|
||||
}
|
||||
|
||||
it should "return nothing if there is no invitation option" in {
|
||||
val onlyTruceOption = DiplomacyOption(
|
||||
targetFactionId = targetFactionId,
|
||||
optionTypes = Vector(DiplomacyOptionType.Truce)
|
||||
)
|
||||
|
||||
InvitationCommandSelector
|
||||
.maybeInviteOtherFaction(
|
||||
actingFactionId = actingFactionId,
|
||||
gameState = gameState,
|
||||
availableCommands = Vector(
|
||||
diplomacyAvailableCommand.withOptions(
|
||||
Vector(TruceOption(targetFactionId = targetFactionId))
|
||||
diplomacyAvailableCommand.copy(
|
||||
options = Vector(onlyTruceOption)
|
||||
)
|
||||
)
|
||||
) shouldBe empty
|
||||
|
||||
@@ -1,24 +1,20 @@
|
||||
package net.eagle0.eagle.ai
|
||||
|
||||
import net.eagle0.eagle.{BattalionId, FactionId, HeroId, ProvinceId}
|
||||
import net.eagle0.eagle.api.available_command.{
|
||||
AvailableCommand,
|
||||
AvailableDestinationProvince,
|
||||
ImproveAvailableCommand,
|
||||
MarchAvailableCommand,
|
||||
MarchCommandFromOneProvince,
|
||||
ReconAvailableCommand
|
||||
}
|
||||
import net.eagle0.eagle.api.selected_command.{ImproveSelectedCommand, MarchSelectedCommand, ReconSelectedCommand}
|
||||
import net.eagle0.eagle.common.battalion_type.{
|
||||
BattalionType as ProtoBattalionType,
|
||||
BattalionTypeId as ProtoBattalionTypeId
|
||||
}
|
||||
import net.eagle0.eagle.common.improvement_type.ImprovementType
|
||||
import net.eagle0.eagle.library.settings.{GoldPerHeroHeldBack, MonthsReconConsideredRecent}
|
||||
import net.eagle0.eagle.model.state.{Army, BattalionType, MovingArmy, Supplies}
|
||||
import net.eagle0.eagle.model.state.battalion.concrete.BattalionC
|
||||
import net.eagle0.eagle.model.state.battalion.BattalionT
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.{
|
||||
AvailableDestinationProvince,
|
||||
ImproveAvailable,
|
||||
MarchAvailable,
|
||||
MarchCommandFromOneProvince,
|
||||
ReconAvailable
|
||||
}
|
||||
import net.eagle0.eagle.model.state.command.common.ImprovementType
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.{ImproveSelected, MarchSelected, ReconSelected}
|
||||
import net.eagle0.eagle.model.state.date.Date
|
||||
import net.eagle0.eagle.model.state.faction.{FactionRelationship, FactionT}
|
||||
import net.eagle0.eagle.model.state.faction.concrete.FactionC
|
||||
@@ -114,6 +110,35 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
private def neighbor(provinceId: ProvinceId): Neighbor =
|
||||
Neighbor(provinceId = provinceId, startingPositionIndex = 0)
|
||||
|
||||
private def makeMarchAvailable(
|
||||
actingProvinceId: ProvinceId,
|
||||
oneProvinceCommands: Vector[MarchCommandFromOneProvince]
|
||||
): MarchAvailable =
|
||||
MarchAvailable(
|
||||
oneProvinceCommands = oneProvinceCommands,
|
||||
actingProvinceId = actingProvinceId,
|
||||
availableTypes = Vector.empty
|
||||
)
|
||||
|
||||
private def makeMarchCommand(
|
||||
originProvinceId: ProvinceId,
|
||||
availableDestinationProvinces: Vector[AvailableDestinationProvince],
|
||||
availableHeroIds: Vector[HeroId],
|
||||
goldAvailable: Int = 0,
|
||||
foodAvailable: Int = 0
|
||||
): MarchCommandFromOneProvince =
|
||||
MarchCommandFromOneProvince(
|
||||
suitableBattalionsForHeroes = Map.empty,
|
||||
originProvinceId = originProvinceId,
|
||||
goldCost = 0,
|
||||
goldAvailable = goldAvailable,
|
||||
foodAvailable = foodAvailable,
|
||||
availableDestinationProvinces = availableDestinationProvinces,
|
||||
availableHeroIds = availableHeroIds,
|
||||
availableBattalions = Vector.empty,
|
||||
recommendedBattleConfig = None
|
||||
)
|
||||
|
||||
private def date(year: Int, month: Int): Date =
|
||||
Date(year = year, month = Date.Month.fromInt(month))
|
||||
|
||||
@@ -203,10 +228,10 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
)
|
||||
|
||||
val acs = Vector(
|
||||
MarchAvailableCommand(
|
||||
makeMarchAvailable(
|
||||
actingProvinceId = 1,
|
||||
oneProvinceCommands = Vector(
|
||||
MarchCommandFromOneProvince(
|
||||
makeMarchCommand(
|
||||
originProvinceId = 2,
|
||||
availableDestinationProvinces = Vector(1, 3, 4).map(pid =>
|
||||
AvailableDestinationProvince(
|
||||
@@ -216,7 +241,7 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
),
|
||||
availableHeroIds = Vector(87)
|
||||
),
|
||||
MarchCommandFromOneProvince(
|
||||
makeMarchCommand(
|
||||
originProvinceId = 3,
|
||||
availableDestinationProvinces = Vector(1, 2).map(pid =>
|
||||
AvailableDestinationProvince(
|
||||
@@ -242,13 +267,12 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
.get
|
||||
commandSelection.actingProvinceId shouldBe 1
|
||||
inside(commandSelection.selected) {
|
||||
case MarchSelectedCommand(
|
||||
case MarchSelected(
|
||||
_, /* gold */
|
||||
_, /* food */
|
||||
originProvince,
|
||||
destinationProvinceId,
|
||||
marchingUnits,
|
||||
_ /* uknownFieldSet */
|
||||
marchingUnits
|
||||
) =>
|
||||
destinationProvinceId shouldBe 1
|
||||
originProvince shouldBe 3
|
||||
@@ -278,10 +302,10 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
)
|
||||
|
||||
val acs = Vector(
|
||||
MarchAvailableCommand(
|
||||
makeMarchAvailable(
|
||||
actingProvinceId = 1,
|
||||
oneProvinceCommands = Vector(
|
||||
MarchCommandFromOneProvince(
|
||||
makeMarchCommand(
|
||||
originProvinceId = 2,
|
||||
availableDestinationProvinces = Vector(1, 3, 4).map(pid =>
|
||||
AvailableDestinationProvince(
|
||||
@@ -291,7 +315,7 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
),
|
||||
availableHeroIds = Vector(87)
|
||||
),
|
||||
MarchCommandFromOneProvince(
|
||||
makeMarchCommand(
|
||||
originProvinceId = 3,
|
||||
availableDestinationProvinces = Vector(1, 2).map(pid =>
|
||||
AvailableDestinationProvince(
|
||||
@@ -337,10 +361,10 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
)
|
||||
|
||||
val acs = Vector(
|
||||
MarchAvailableCommand(
|
||||
makeMarchAvailable(
|
||||
actingProvinceId = 1,
|
||||
oneProvinceCommands = Vector(
|
||||
MarchCommandFromOneProvince(
|
||||
makeMarchCommand(
|
||||
originProvinceId = 1,
|
||||
availableDestinationProvinces = Vector(2, 3, 4).map(pid =>
|
||||
AvailableDestinationProvince(
|
||||
@@ -350,7 +374,7 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
),
|
||||
availableHeroIds = Vector(123, 124, 125, 126, 127, 128)
|
||||
),
|
||||
MarchCommandFromOneProvince(
|
||||
makeMarchCommand(
|
||||
originProvinceId = 2,
|
||||
availableDestinationProvinces = Vector(1, 3, 4).map(pid =>
|
||||
AvailableDestinationProvince(
|
||||
@@ -360,7 +384,7 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
),
|
||||
availableHeroIds = Vector(87)
|
||||
),
|
||||
MarchCommandFromOneProvince(
|
||||
makeMarchCommand(
|
||||
originProvinceId = 3,
|
||||
availableDestinationProvinces = Vector(1, 2).map(pid =>
|
||||
AvailableDestinationProvince(
|
||||
@@ -406,7 +430,7 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
)
|
||||
|
||||
val acs = Vector(
|
||||
ReconAvailableCommand(
|
||||
ReconAvailable(
|
||||
availableTargetProvinces = Vector(23),
|
||||
actingProvinceId = 19,
|
||||
availableHeroIds = Vector(9)
|
||||
@@ -447,7 +471,7 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
)
|
||||
|
||||
val acs = Vector(
|
||||
ReconAvailableCommand(
|
||||
ReconAvailable(
|
||||
availableTargetProvinces = Vector(23),
|
||||
actingProvinceId = 19,
|
||||
availableHeroIds = Vector(9)
|
||||
@@ -493,7 +517,7 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
)
|
||||
|
||||
val acs = Vector(
|
||||
ReconAvailableCommand(
|
||||
ReconAvailable(
|
||||
availableTargetProvinces = Vector(7, 23),
|
||||
actingProvinceId = 19,
|
||||
availableHeroIds = Vector(9)
|
||||
@@ -510,11 +534,7 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
.selected
|
||||
|
||||
inside(selected) {
|
||||
case ReconSelectedCommand(
|
||||
actingHeroId,
|
||||
targetProvinceId,
|
||||
_ /* uknownFieldSet */
|
||||
) =>
|
||||
case ReconSelected(actingHeroId, targetProvinceId) =>
|
||||
actingHeroId shouldBe 9
|
||||
targetProvinceId shouldBe 23
|
||||
}
|
||||
@@ -553,7 +573,7 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
)
|
||||
|
||||
val acs = Vector(
|
||||
ReconAvailableCommand(
|
||||
ReconAvailable(
|
||||
availableTargetProvinces = Vector(7, 23),
|
||||
actingProvinceId = 19,
|
||||
availableHeroIds = Vector(9)
|
||||
@@ -570,11 +590,7 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
.selected
|
||||
|
||||
inside(selected) {
|
||||
case ReconSelectedCommand(
|
||||
actingHeroId,
|
||||
targetProvinceId,
|
||||
_ /* uknownFieldSet */
|
||||
) =>
|
||||
case ReconSelected(actingHeroId, targetProvinceId) =>
|
||||
actingHeroId shouldBe 9
|
||||
targetProvinceId shouldBe 23
|
||||
}
|
||||
@@ -613,7 +629,7 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
)
|
||||
|
||||
val acs = Vector(
|
||||
ReconAvailableCommand(
|
||||
ReconAvailable(
|
||||
availableTargetProvinces = Vector(7, 23),
|
||||
actingProvinceId = 19,
|
||||
availableHeroIds = Vector(9)
|
||||
@@ -676,7 +692,7 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
)
|
||||
|
||||
val acs = Vector(
|
||||
ReconAvailableCommand(
|
||||
ReconAvailable(
|
||||
availableTargetProvinces = Vector(7, 23),
|
||||
actingProvinceId = 19,
|
||||
availableHeroIds = Vector(9)
|
||||
@@ -693,11 +709,7 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
.selected
|
||||
|
||||
inside(selected) {
|
||||
case ReconSelectedCommand(
|
||||
actingHeroId,
|
||||
targetProvinceId,
|
||||
_ /* uknownFieldSet */
|
||||
) =>
|
||||
case ReconSelected(actingHeroId, targetProvinceId) =>
|
||||
actingHeroId shouldBe 9
|
||||
targetProvinceId shouldBe 7
|
||||
}
|
||||
@@ -731,15 +743,6 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
makeBattalionType(ScalaBattalionTypeId.Longbowmen)
|
||||
)
|
||||
|
||||
// Proto battalion types for use in proto MarchAvailableCommand
|
||||
private val protoBattalionTypes: Vector[ProtoBattalionType] = Vector(
|
||||
ProtoBattalionType(typeId = ProtoBattalionTypeId.LIGHT_INFANTRY),
|
||||
ProtoBattalionType(typeId = ProtoBattalionTypeId.HEAVY_INFANTRY, minimumEconomy = 60),
|
||||
ProtoBattalionType(typeId = ProtoBattalionTypeId.LIGHT_CAVALRY, minimumAgriculture = 60),
|
||||
ProtoBattalionType(typeId = ProtoBattalionTypeId.HEAVY_CAVALRY, minimumEconomy = 60, minimumAgriculture = 60),
|
||||
ProtoBattalionType(typeId = ProtoBattalionTypeId.LONGBOWMEN)
|
||||
)
|
||||
|
||||
private val improveForTroopsProvince: ProvinceC = ProvinceC(
|
||||
id = 17,
|
||||
rulingFactionId = Some(factionId),
|
||||
@@ -749,17 +752,18 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
battalionIds = Vector(3)
|
||||
)
|
||||
|
||||
private val improveForTroopsAC: ImproveAvailableCommand =
|
||||
ImproveAvailableCommand(
|
||||
private val improveForTroopsAC: ImproveAvailable =
|
||||
ImproveAvailable(
|
||||
availableTypes = Vector(
|
||||
ImprovementType.ECONOMY,
|
||||
ImprovementType.AGRICULTURE,
|
||||
ImprovementType.INFRASTRUCTURE,
|
||||
ImprovementType.DEVASTATION
|
||||
ImprovementType.Economy,
|
||||
ImprovementType.Agriculture,
|
||||
ImprovementType.Infrastructure,
|
||||
ImprovementType.Devastation
|
||||
),
|
||||
availableHeroIds = Vector(6, 7, 8),
|
||||
recommendedHeroId = 6,
|
||||
actingProvinceId = 17
|
||||
actingProvinceId = 17,
|
||||
lockedType = None
|
||||
)
|
||||
|
||||
private val improveForTroopsACs: Vector[AvailableCommand] = Vector(
|
||||
@@ -846,7 +850,7 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
|
||||
command.actingProvinceId shouldBe 17
|
||||
command.actingFactionId shouldBe factionId
|
||||
command.selected shouldBe a[ImproveSelectedCommand]
|
||||
command.selected shouldBe a[ImproveSelected]
|
||||
}
|
||||
|
||||
it should "improve devastation if available" in {
|
||||
@@ -871,7 +875,7 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
|
||||
command.actingProvinceId shouldBe 17
|
||||
command.actingFactionId shouldBe factionId
|
||||
command.selected shouldBe a[ImproveSelectedCommand]
|
||||
command.selected shouldBe a[ImproveSelected]
|
||||
}
|
||||
|
||||
it should "improve economy if we're closer to that requirement" in {
|
||||
@@ -886,12 +890,12 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
)
|
||||
)
|
||||
|
||||
val acsWithoutDevastation = Vector(
|
||||
improveForTroopsAC.update(
|
||||
_.availableTypes := Vector(
|
||||
ImprovementType.ECONOMY,
|
||||
ImprovementType.AGRICULTURE,
|
||||
ImprovementType.INFRASTRUCTURE
|
||||
val acsWithoutDevastation: Vector[AvailableCommand] = Vector(
|
||||
improveForTroopsAC.copy(
|
||||
availableTypes = Vector(
|
||||
ImprovementType.Economy,
|
||||
ImprovementType.Agriculture,
|
||||
ImprovementType.Infrastructure
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -905,13 +909,8 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
.get
|
||||
|
||||
inside(command.selected) {
|
||||
case ImproveSelectedCommand(
|
||||
improvementType,
|
||||
_,
|
||||
_,
|
||||
_ /* uknownFieldSet */
|
||||
) =>
|
||||
improvementType shouldBe ImprovementType.ECONOMY
|
||||
case ImproveSelected(improvementType, _, _) =>
|
||||
improvementType shouldBe ImprovementType.Economy
|
||||
}
|
||||
}
|
||||
|
||||
@@ -927,12 +926,12 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
)
|
||||
)
|
||||
|
||||
val acsWithoutDevastation = Vector(
|
||||
improveForTroopsAC.update(
|
||||
_.availableTypes := Vector(
|
||||
ImprovementType.ECONOMY,
|
||||
ImprovementType.AGRICULTURE,
|
||||
ImprovementType.INFRASTRUCTURE
|
||||
val acsWithoutDevastation: Vector[AvailableCommand] = Vector(
|
||||
improveForTroopsAC.copy(
|
||||
availableTypes = Vector(
|
||||
ImprovementType.Economy,
|
||||
ImprovementType.Agriculture,
|
||||
ImprovementType.Infrastructure
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -946,13 +945,8 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
.get
|
||||
|
||||
inside(command.selected) {
|
||||
case ImproveSelectedCommand(
|
||||
improvementType,
|
||||
_,
|
||||
_,
|
||||
_ /* uknownFieldSet */
|
||||
) =>
|
||||
improvementType shouldBe ImprovementType.AGRICULTURE
|
||||
case ImproveSelected(improvementType, _, _) =>
|
||||
improvementType shouldBe ImprovementType.Agriculture
|
||||
}
|
||||
}
|
||||
|
||||
@@ -977,9 +971,10 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
)
|
||||
)
|
||||
|
||||
private val spreadLeadersAC: MarchAvailableCommand = MarchAvailableCommand(
|
||||
oneProvinceCommands = Vector[MarchCommandFromOneProvince](
|
||||
MarchCommandFromOneProvince(
|
||||
private val spreadLeadersAC: MarchAvailable = makeMarchAvailable(
|
||||
actingProvinceId = 7,
|
||||
oneProvinceCommands = Vector(
|
||||
makeMarchCommand(
|
||||
originProvinceId = 7,
|
||||
availableDestinationProvinces = Vector(12, 15).map(pid =>
|
||||
AvailableDestinationProvince(
|
||||
@@ -989,9 +984,7 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
),
|
||||
availableHeroIds = Vector(10, 20, 30, 40, 50)
|
||||
)
|
||||
),
|
||||
actingProvinceId = 7,
|
||||
availableTypes = protoBattalionTypes
|
||||
)
|
||||
)
|
||||
|
||||
"maybeSpreadLeadersCommand" should "move a leader to a province without leaders" in {
|
||||
@@ -1005,13 +998,12 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
|
||||
.selected
|
||||
|
||||
inside(selection) {
|
||||
case MarchSelectedCommand(
|
||||
case MarchSelected(
|
||||
gold,
|
||||
food,
|
||||
originProvince,
|
||||
destinationProvinceId,
|
||||
marchingUnits,
|
||||
_ /* uknownFieldSet */
|
||||
marchingUnits
|
||||
) =>
|
||||
originProvince shouldBe 7
|
||||
destinationProvinceId shouldBe 15
|
||||
|
||||
+51
-23
@@ -1,13 +1,14 @@
|
||||
package net.eagle0.eagle.ai
|
||||
|
||||
import net.eagle0.eagle.{FactionId, HeroId, ProvinceId}
|
||||
import net.eagle0.eagle.api.available_command.{
|
||||
import net.eagle0.eagle.library.settings.GoldPerHeroHeldBack
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.{
|
||||
AvailableDestinationProvince,
|
||||
MarchAvailableCommand,
|
||||
MarchAvailable,
|
||||
MarchCommandFromOneProvince
|
||||
}
|
||||
import net.eagle0.eagle.api.selected_command.MarchSelectedCommand
|
||||
import net.eagle0.eagle.library.settings.GoldPerHeroHeldBack
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.MarchSelected
|
||||
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
|
||||
@@ -40,6 +41,35 @@ class MoveLeaderToBetterProvinceCommandChooserTest extends AnyFlatSpec with Matc
|
||||
private def neighbor(provinceId: ProvinceId): Neighbor =
|
||||
Neighbor(provinceId = provinceId, startingPositionIndex = 0)
|
||||
|
||||
private def makeMarchAvailable(
|
||||
actingProvinceId: ProvinceId,
|
||||
oneProvinceCommands: Vector[MarchCommandFromOneProvince]
|
||||
): MarchAvailable =
|
||||
MarchAvailable(
|
||||
oneProvinceCommands = oneProvinceCommands,
|
||||
actingProvinceId = actingProvinceId,
|
||||
availableTypes = Vector.empty
|
||||
)
|
||||
|
||||
private def makeMarchCommand(
|
||||
originProvinceId: ProvinceId,
|
||||
availableDestinationProvinces: Vector[AvailableDestinationProvince],
|
||||
availableHeroIds: Vector[HeroId],
|
||||
goldAvailable: Int = 0,
|
||||
foodAvailable: Int = 0
|
||||
): MarchCommandFromOneProvince =
|
||||
MarchCommandFromOneProvince(
|
||||
suitableBattalionsForHeroes = Map.empty,
|
||||
originProvinceId = originProvinceId,
|
||||
goldCost = 0,
|
||||
goldAvailable = goldAvailable,
|
||||
foodAvailable = foodAvailable,
|
||||
availableDestinationProvinces = availableDestinationProvinces,
|
||||
availableHeroIds = availableHeroIds,
|
||||
availableBattalions = Vector.empty,
|
||||
recommendedBattleConfig = None
|
||||
)
|
||||
|
||||
private def makeFaction(
|
||||
id: FactionId,
|
||||
factionHeadId: HeroId = 0,
|
||||
@@ -139,10 +169,10 @@ class MoveLeaderToBetterProvinceCommandChooserTest extends AnyFlatSpec with Matc
|
||||
)
|
||||
|
||||
val acs = Vector(
|
||||
MarchAvailableCommand(
|
||||
makeMarchAvailable(
|
||||
actingProvinceId = 1,
|
||||
oneProvinceCommands = Vector(
|
||||
MarchCommandFromOneProvince(
|
||||
makeMarchCommand(
|
||||
originProvinceId = 2,
|
||||
availableDestinationProvinces = Vector(1, 3, 4).map(pid =>
|
||||
AvailableDestinationProvince(
|
||||
@@ -152,7 +182,7 @@ class MoveLeaderToBetterProvinceCommandChooserTest extends AnyFlatSpec with Matc
|
||||
),
|
||||
availableHeroIds = Vector(87)
|
||||
),
|
||||
MarchCommandFromOneProvince(
|
||||
makeMarchCommand(
|
||||
originProvinceId = 1,
|
||||
availableDestinationProvinces = Vector(2, 3).map(pid =>
|
||||
AvailableDestinationProvince(
|
||||
@@ -182,13 +212,12 @@ class MoveLeaderToBetterProvinceCommandChooserTest extends AnyFlatSpec with Matc
|
||||
.get
|
||||
commandSelection.actingProvinceId shouldBe 1
|
||||
inside(commandSelection.selected) {
|
||||
case MarchSelectedCommand(
|
||||
_, /* gold */
|
||||
_, /* food */
|
||||
case MarchSelected(
|
||||
gold,
|
||||
food,
|
||||
originProvince,
|
||||
destinationProvinceId,
|
||||
marchingUnits,
|
||||
_ /* uknownFieldSet */
|
||||
marchingUnits
|
||||
) =>
|
||||
destinationProvinceId shouldBe 2
|
||||
originProvince shouldBe 1
|
||||
@@ -211,10 +240,10 @@ class MoveLeaderToBetterProvinceCommandChooserTest extends AnyFlatSpec with Matc
|
||||
)
|
||||
|
||||
val acs = Vector(
|
||||
MarchAvailableCommand(
|
||||
makeMarchAvailable(
|
||||
actingProvinceId = 1,
|
||||
oneProvinceCommands = Vector(
|
||||
MarchCommandFromOneProvince(
|
||||
makeMarchCommand(
|
||||
originProvinceId = 1,
|
||||
availableDestinationProvinces = Vector(2, 3).map(pid =>
|
||||
AvailableDestinationProvince(
|
||||
@@ -226,7 +255,7 @@ class MoveLeaderToBetterProvinceCommandChooserTest extends AnyFlatSpec with Matc
|
||||
goldAvailable = 6000,
|
||||
foodAvailable = 7000
|
||||
),
|
||||
MarchCommandFromOneProvince(
|
||||
makeMarchCommand(
|
||||
originProvinceId = 2,
|
||||
availableDestinationProvinces = Vector(1, 3, 4).map(pid =>
|
||||
AvailableDestinationProvince(
|
||||
@@ -256,13 +285,12 @@ class MoveLeaderToBetterProvinceCommandChooserTest extends AnyFlatSpec with Matc
|
||||
.get
|
||||
commandSelection.actingProvinceId shouldBe 1
|
||||
inside(commandSelection.selected) {
|
||||
case MarchSelectedCommand(
|
||||
_, /* gold */
|
||||
_, /* food */
|
||||
case MarchSelected(
|
||||
gold,
|
||||
food,
|
||||
originProvince,
|
||||
destinationProvinceId,
|
||||
marchingUnits,
|
||||
_ /* uknownFieldSet */
|
||||
marchingUnits
|
||||
) =>
|
||||
destinationProvinceId shouldBe 4
|
||||
originProvince shouldBe 2
|
||||
@@ -283,10 +311,10 @@ class MoveLeaderToBetterProvinceCommandChooserTest extends AnyFlatSpec with Matc
|
||||
)
|
||||
|
||||
val acs = Vector(
|
||||
MarchAvailableCommand(
|
||||
makeMarchAvailable(
|
||||
actingProvinceId = 1,
|
||||
oneProvinceCommands = Vector(
|
||||
MarchCommandFromOneProvince(
|
||||
makeMarchCommand(
|
||||
originProvinceId = 2,
|
||||
availableDestinationProvinces = Vector(1, 3, 4).map(pid =>
|
||||
AvailableDestinationProvince(
|
||||
@@ -296,7 +324,7 @@ class MoveLeaderToBetterProvinceCommandChooserTest extends AnyFlatSpec with Matc
|
||||
),
|
||||
availableHeroIds = Vector(87)
|
||||
),
|
||||
MarchCommandFromOneProvince(
|
||||
makeMarchCommand(
|
||||
originProvinceId = 1,
|
||||
availableDestinationProvinces = Vector(2, 3).map(pid =>
|
||||
AvailableDestinationProvince(
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
package net.eagle0.eagle.ai
|
||||
|
||||
import net.eagle0.eagle.{FactionId, HeroId, ProvinceId}
|
||||
import net.eagle0.eagle.api.available_command.{
|
||||
AvailableCommand,
|
||||
AvailableDestinationProvince,
|
||||
EligibleGift,
|
||||
FeastAvailableCommand,
|
||||
HeroGiftAvailableCommand,
|
||||
ImproveAvailableCommand,
|
||||
MarchAvailableCommand,
|
||||
MarchCommandFromOneProvince,
|
||||
SwearBrotherhoodAvailableCommand
|
||||
}
|
||||
import net.eagle0.eagle.api.available_command.SwearBrotherhoodAvailableCommand.HeroAndBackstory
|
||||
import net.eagle0.eagle.api.selected_command.{
|
||||
FeastSelectedCommand,
|
||||
HeroGiftSelectedCommand,
|
||||
MarchSelectedCommand,
|
||||
SwearBrotherhoodSelectedCommand
|
||||
}
|
||||
import net.eagle0.eagle.common.combat_unit.CombatUnit
|
||||
import net.eagle0.eagle.common.improvement_type.ImprovementType
|
||||
import net.eagle0.eagle.library.settings.{
|
||||
AiMinimumCharismaForSwornBrother,
|
||||
AiMinimumConstitutionForSwornBrother,
|
||||
LoyaltyGainFromFeast,
|
||||
MinimumLoyaltyForSwearBrotherhood
|
||||
}
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.library.util.ScalaCommandSelection
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.{
|
||||
AvailableDestinationProvince,
|
||||
EligibleGift,
|
||||
FeastAvailable,
|
||||
HeroAndBackstory,
|
||||
HeroGiftAvailable,
|
||||
ImproveAvailable,
|
||||
MarchAvailable,
|
||||
MarchCommandFromOneProvince,
|
||||
SwearBrotherhoodAvailable
|
||||
}
|
||||
import net.eagle0.eagle.model.state.command.common.ImprovementType
|
||||
import net.eagle0.eagle.model.state.command.selected.CombatUnit
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.{
|
||||
FeastSelected,
|
||||
HeroGiftSelected,
|
||||
MarchSelected,
|
||||
SwearBrotherhoodSelected
|
||||
}
|
||||
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
|
||||
@@ -50,12 +50,12 @@ class SeekMoreLeadersCommandChooserTest extends AnyFlatSpec with Matchers with B
|
||||
private def mapifyHeroes(hs: HeroT*): Map[HeroId, HeroT] = hs.map(h => h.id -> h).toMap
|
||||
private def mapifyFactions(fs: FactionT*): Map[FactionId, FactionT] = fs.map(f => f.id -> f).toMap
|
||||
|
||||
private val swearBrotherhoodAC = SwearBrotherhoodAvailableCommand(
|
||||
private val swearBrotherhoodAC: SwearBrotherhoodAvailable = SwearBrotherhoodAvailable(
|
||||
actingProvinceId = 17,
|
||||
availableHeroes = Vector(9, 12, 13).map(hid => HeroAndBackstory(heroId = hid))
|
||||
availableHeroes = Vector(9, 12, 13).map(hid => HeroAndBackstory(heroId = hid, backstoryTextId = ""))
|
||||
)
|
||||
|
||||
private val heroGiftAC = HeroGiftAvailableCommand(
|
||||
private val heroGiftAC: HeroGiftAvailable = HeroGiftAvailable(
|
||||
eligibleGifts = Vector(9, 12, 13).map { hid =>
|
||||
EligibleGift(
|
||||
recipientHeroId = hid,
|
||||
@@ -66,8 +66,8 @@ class SeekMoreLeadersCommandChooserTest extends AnyFlatSpec with Matchers with B
|
||||
actingProvinceId = 17
|
||||
)
|
||||
|
||||
private val feastAC =
|
||||
FeastAvailableCommand(goldCost = 120, actingProvinceId = 17)
|
||||
private val feastAC: FeastAvailable =
|
||||
FeastAvailable(goldCost = 120, actingProvinceId = 17)
|
||||
|
||||
private val tryToSwearBrotherhoodACs: Vector[AvailableCommand] =
|
||||
Vector(heroGiftAC, feastAC, swearBrotherhoodAC)
|
||||
@@ -149,6 +149,35 @@ class SeekMoreLeadersCommandChooserTest extends AnyFlatSpec with Matchers with B
|
||||
chronicleEntries = Vector.empty
|
||||
)
|
||||
|
||||
private def makeMarchAvailable(
|
||||
actingProvinceId: ProvinceId,
|
||||
oneProvinceCommands: Vector[MarchCommandFromOneProvince]
|
||||
): MarchAvailable =
|
||||
MarchAvailable(
|
||||
oneProvinceCommands = oneProvinceCommands,
|
||||
actingProvinceId = actingProvinceId,
|
||||
availableTypes = Vector.empty
|
||||
)
|
||||
|
||||
private def makeMarchCommand(
|
||||
originProvinceId: ProvinceId,
|
||||
availableDestinationProvinces: Vector[AvailableDestinationProvince],
|
||||
availableHeroIds: Vector[HeroId],
|
||||
goldAvailable: Int = 0,
|
||||
foodAvailable: Int = 0
|
||||
): MarchCommandFromOneProvince =
|
||||
MarchCommandFromOneProvince(
|
||||
suitableBattalionsForHeroes = Map.empty,
|
||||
originProvinceId = originProvinceId,
|
||||
goldCost = 0,
|
||||
goldAvailable = goldAvailable,
|
||||
foodAvailable = foodAvailable,
|
||||
availableDestinationProvinces = availableDestinationProvinces,
|
||||
availableHeroIds = availableHeroIds,
|
||||
availableBattalions = Vector.empty,
|
||||
recommendedBattleConfig = None
|
||||
)
|
||||
|
||||
private val swearBrotherhoodGameState: GameState = makeGameState(
|
||||
makeProvince(
|
||||
id = 17,
|
||||
@@ -172,17 +201,18 @@ class SeekMoreLeadersCommandChooserTest extends AnyFlatSpec with Matchers with B
|
||||
makeFaction(id = 4, factionHeadId = 1, leaderIds = Vector(1))
|
||||
)
|
||||
|
||||
private val improveForTroopsAC: ImproveAvailableCommand =
|
||||
ImproveAvailableCommand(
|
||||
private val improveForTroopsAC: ImproveAvailable =
|
||||
ImproveAvailable(
|
||||
availableTypes = Vector(
|
||||
ImprovementType.ECONOMY,
|
||||
ImprovementType.AGRICULTURE,
|
||||
ImprovementType.INFRASTRUCTURE,
|
||||
ImprovementType.DEVASTATION
|
||||
ImprovementType.Economy,
|
||||
ImprovementType.Agriculture,
|
||||
ImprovementType.Infrastructure,
|
||||
ImprovementType.Devastation
|
||||
),
|
||||
availableHeroIds = Vector(6, 7, 8),
|
||||
recommendedHeroId = 6,
|
||||
actingProvinceId = 17
|
||||
actingProvinceId = 17,
|
||||
lockedType = None
|
||||
)
|
||||
|
||||
private val improveForTroopsACs: Vector[AvailableCommand] = Vector(
|
||||
@@ -207,10 +237,7 @@ class SeekMoreLeadersCommandChooserTest extends AnyFlatSpec with Matchers with B
|
||||
|
||||
selection.available shouldBe swearBrotherhoodAC
|
||||
inside(selection.selected) {
|
||||
case SwearBrotherhoodSelectedCommand(
|
||||
newBrotherHeroId,
|
||||
_ /* unknownFieldSet */
|
||||
) =>
|
||||
case SwearBrotherhoodSelected(newBrotherHeroId) =>
|
||||
newBrotherHeroId shouldBe 12
|
||||
}
|
||||
}
|
||||
@@ -219,8 +246,9 @@ class SeekMoreLeadersCommandChooserTest extends AnyFlatSpec with Matchers with B
|
||||
val noOptionForMyChoice = Vector[AvailableCommand](
|
||||
feastAC,
|
||||
heroGiftAC,
|
||||
swearBrotherhoodAC.withAvailableHeroes(
|
||||
Vector(9, 13).map(hid => HeroAndBackstory(heroId = hid))
|
||||
SwearBrotherhoodAvailable(
|
||||
actingProvinceId = 17,
|
||||
availableHeroes = Vector(9, 13).map(hid => HeroAndBackstory(heroId = hid, backstoryTextId = ""))
|
||||
)
|
||||
)
|
||||
|
||||
@@ -233,17 +261,16 @@ class SeekMoreLeadersCommandChooserTest extends AnyFlatSpec with Matchers with B
|
||||
.get
|
||||
|
||||
selection.available should not be swearBrotherhoodAC
|
||||
selection.selected should not matchPattern {
|
||||
case SwearBrotherhoodSelectedCommand(_, _ /* unknownFieldSet */ ) =>
|
||||
}
|
||||
selection.selected should not matchPattern { case SwearBrotherhoodSelected(_) => }
|
||||
}
|
||||
|
||||
it should "feast if the best hero is >=85 loyalty" in {
|
||||
val noOptionForMyChoice = Vector[AvailableCommand](
|
||||
feastAC,
|
||||
heroGiftAC,
|
||||
swearBrotherhoodAC.withAvailableHeroes(
|
||||
Vector(9, 13).map(hid => HeroAndBackstory(heroId = hid))
|
||||
SwearBrotherhoodAvailable(
|
||||
actingProvinceId = 17,
|
||||
availableHeroes = Vector(9, 13).map(hid => HeroAndBackstory(heroId = hid, backstoryTextId = ""))
|
||||
)
|
||||
)
|
||||
|
||||
@@ -263,17 +290,16 @@ class SeekMoreLeadersCommandChooserTest extends AnyFlatSpec with Matchers with B
|
||||
.get
|
||||
|
||||
selection.available shouldBe feastAC
|
||||
selection.selected should matchPattern {
|
||||
case FeastSelectedCommand(_ /* unknownFieldSet */ ) =>
|
||||
}
|
||||
selection.selected should matchPattern { case FeastSelected => }
|
||||
}
|
||||
|
||||
it should "give if the best hero is <85 loyalty" in {
|
||||
val noOptionForMyChoice = Vector[AvailableCommand](
|
||||
feastAC,
|
||||
heroGiftAC,
|
||||
swearBrotherhoodAC.withAvailableHeroes(
|
||||
Vector(9, 13).map(hid => HeroAndBackstory(heroId = hid))
|
||||
SwearBrotherhoodAvailable(
|
||||
actingProvinceId = 17,
|
||||
availableHeroes = Vector(9, 13).map(hid => HeroAndBackstory(heroId = hid, backstoryTextId = ""))
|
||||
)
|
||||
)
|
||||
|
||||
@@ -294,11 +320,7 @@ class SeekMoreLeadersCommandChooserTest extends AnyFlatSpec with Matchers with B
|
||||
|
||||
selection.available shouldBe heroGiftAC
|
||||
inside(selection.selected) {
|
||||
case HeroGiftSelectedCommand(
|
||||
recipientHeroId,
|
||||
amount,
|
||||
_ /* unknownFieldSet */
|
||||
) =>
|
||||
case HeroGiftSelected(recipientHeroId, amount) =>
|
||||
recipientHeroId shouldBe 12
|
||||
amount shouldBe 100
|
||||
}
|
||||
@@ -377,9 +399,10 @@ class SeekMoreLeadersCommandChooserTest extends AnyFlatSpec with Matchers with B
|
||||
makeFaction(id = 4, factionHeadId = 1, leaderIds = Vector(1))
|
||||
)
|
||||
|
||||
val marchAC = MarchAvailableCommand(
|
||||
val marchAC = makeMarchAvailable(
|
||||
actingProvinceId = 17,
|
||||
oneProvinceCommands = Vector(
|
||||
MarchCommandFromOneProvince(
|
||||
makeMarchCommand(
|
||||
originProvinceId = 20,
|
||||
availableDestinationProvinces = Vector(17, 909).map(pid =>
|
||||
AvailableDestinationProvince(
|
||||
@@ -389,9 +412,7 @@ class SeekMoreLeadersCommandChooserTest extends AnyFlatSpec with Matchers with B
|
||||
),
|
||||
availableHeroIds = Vector(12, 15, 16)
|
||||
)
|
||||
),
|
||||
actingProvinceId = 17,
|
||||
availableTypes = Vector()
|
||||
)
|
||||
)
|
||||
|
||||
val moveHeroACs: Vector[AvailableCommand] =
|
||||
@@ -409,18 +430,14 @@ class SeekMoreLeadersCommandChooserTest extends AnyFlatSpec with Matchers with B
|
||||
)
|
||||
.get
|
||||
|
||||
selectionWithReason shouldBe CommandSelection(
|
||||
actingFactionId = 4,
|
||||
actingProvinceId = 17,
|
||||
available = marchAC,
|
||||
selected = MarchSelectedCommand(
|
||||
gold = 0,
|
||||
food = 0,
|
||||
originProvince = 20,
|
||||
destinationProvinceId = 17,
|
||||
marchingUnits = Vector(CombatUnit(factionId = 4, heroId = 12, battalionId = None))
|
||||
),
|
||||
reason = "Moving a good hero toward the faction leader"
|
||||
)
|
||||
selectionWithReason.actingProvinceId shouldBe 17
|
||||
selectionWithReason.available shouldBe marchAC
|
||||
inside(selectionWithReason.selected) {
|
||||
case MarchSelected(_, _, originProvince, destinationProvinceId, marchingUnits) =>
|
||||
originProvince shouldBe 20
|
||||
destinationProvinceId shouldBe 17
|
||||
marchingUnits.map(_.heroId) should contain(12)
|
||||
}
|
||||
selectionWithReason.reason shouldBe "Moving a good hero toward the faction leader"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -699,7 +699,6 @@ scala_test(
|
||||
srcs = ["PerformVassalCommandsPhaseActionTest.scala"],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:available_command_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/api:selected_command_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//src/main/scala/net/eagle0/eagle/library/actions/applier:action_result_applier",
|
||||
"//src/main/scala/net/eagle0/eagle/library/actions/impl/action:perform_vassal_commands_phase_action",
|
||||
@@ -725,7 +724,6 @@ scala_test(
|
||||
"//src/main/scala/net/eagle0/eagle/library/settings:vassal_minimum_gold_to_send_supplies",
|
||||
"//src/main/scala/net/eagle0/eagle/library/settings:vigor_gain_from_feast",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/command_choice_helpers",
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters/command/available:available_command_converter",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state:army",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state:battalion_type",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state:battalion_type_id",
|
||||
|
||||
+107
-100
@@ -3,13 +3,6 @@ package net.eagle0.eagle.library.actions.impl.action
|
||||
import scala.util.Random
|
||||
|
||||
import net.eagle0.common.SeededRandom
|
||||
import net.eagle0.eagle.api.available_command.{
|
||||
FeastAvailableCommand as ProtoFeastAvailableCommand,
|
||||
HeroGiftAvailableCommand as ProtoHeroGiftAvailableCommand,
|
||||
MarchAvailableCommand as ProtoMarchAvailableCommand,
|
||||
SendSuppliesAvailableCommand as ProtoSendSuppliesAvailableCommand
|
||||
}
|
||||
import net.eagle0.eagle.api.selected_command.{HeroGiftSelectedCommand, RestSelectedCommand, SendSuppliesSelectedCommand}
|
||||
import net.eagle0.eagle.library.actions.applier.ActionResultApplier
|
||||
import net.eagle0.eagle.library.actions.impl.command.TCommandFactory
|
||||
import net.eagle0.eagle.library.settings.{
|
||||
@@ -35,21 +28,23 @@ import net.eagle0.eagle.library.settings.{
|
||||
VigorGainFromFeast
|
||||
}
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.CommandChoiceHelpers
|
||||
import net.eagle0.eagle.library.util.command_choice_helpers.SelectedCommandMatcher.*
|
||||
import net.eagle0.eagle.library.util.CommandSelection
|
||||
import net.eagle0.eagle.model.proto_converters.command.available.AvailableCommandConverter
|
||||
import net.eagle0.eagle.model.state.{Army, BattalionType, BattalionTypeId, MovingArmy, RoundPhase, Supplies}
|
||||
import net.eagle0.eagle.model.state.{Army, BattalionType, MovingArmy, RoundPhase, Supplies}
|
||||
import net.eagle0.eagle.model.state.battalion.concrete.BattalionC
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand
|
||||
import net.eagle0.eagle.model.state.command.available.AvailableCommand.*
|
||||
import net.eagle0.eagle.model.state.command.available.OneProvinceAvailableCommands
|
||||
import net.eagle0.eagle.model.state.command.common.*
|
||||
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.{
|
||||
HeroGiftSelected,
|
||||
RestSelected,
|
||||
SendSuppliesSelected
|
||||
}
|
||||
import net.eagle0.eagle.model.state.date.Date
|
||||
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.{Neighbor, ProvinceOrderType}
|
||||
import net.eagle0.eagle.model.state.province.concrete.ProvinceC
|
||||
import net.eagle0.eagle.model.state.province.Neighbor
|
||||
import net.eagle0.eagle.model.state.province.ProvinceOrderType.{Develop, Expand}
|
||||
import net.eagle0.eagle.model.state.run_status.RunStatus
|
||||
import net.eagle0.eagle.model.state.BattalionTypeId.{HeavyCavalry, HeavyInfantry, LightInfantry}
|
||||
@@ -61,8 +56,6 @@ import org.scalatest.Inside.inside
|
||||
|
||||
class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach with MockFactory {
|
||||
|
||||
import net.eagle0.common.ProtoMatchers.*
|
||||
|
||||
private val functionalRandom = SeededRandom(new Random().nextLong())
|
||||
|
||||
private val commandFactory: TCommandFactory = mock[TCommandFactory]
|
||||
@@ -382,13 +375,6 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
|
||||
private val foodPerProvinceHeldBack: Int = 300
|
||||
|
||||
/** Helper to convert Scala commands to proto for CommandChoiceHelpers tests */
|
||||
private def toProtoCommands(
|
||||
commands: Vector[AvailableCommand],
|
||||
gs: GameState
|
||||
): Vector[net.eagle0.eagle.api.available_command.AvailableCommand] =
|
||||
commands.map(cmd => AvailableCommandConverter.toProto(cmd, gs, actingFactionId))
|
||||
|
||||
override def beforeEach(): Unit = {
|
||||
MinSupportForTaxes.setDoubleValue(45.0)
|
||||
FoodIncreasePerAgriculture.setDoubleValue(50.0)
|
||||
@@ -439,28 +425,30 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
val developingGS =
|
||||
gameState.copy(provinces = gameState.provinces.updated(developingProvince.id, developingProvince))
|
||||
|
||||
val commands = Vector(
|
||||
feastCommand,
|
||||
giftCommand,
|
||||
restCommand,
|
||||
improveCommand,
|
||||
marchCommand
|
||||
)
|
||||
|
||||
val selection = PerformVassalCommandsPhaseAction(
|
||||
gameState = developingGS,
|
||||
commandsForProvince = Map(
|
||||
developingProvince.id -> Some(
|
||||
OneProvinceAvailableCommands(
|
||||
provinceId = developingProvince.id,
|
||||
commands = Vector(
|
||||
feastCommand,
|
||||
giftCommand,
|
||||
restCommand,
|
||||
improveCommand,
|
||||
marchCommand
|
||||
)
|
||||
commands = commands
|
||||
)
|
||||
)
|
||||
),
|
||||
commandFactory = commandFactory,
|
||||
actionResultApplier = actionResultApplier
|
||||
).chooseCommand(developingGS, developingProvince.id, functionalRandom).newValue.get
|
||||
).chooseCommand(developingGS, developingProvince.id, commands, functionalRandom).newValue.get
|
||||
|
||||
inside(selection.available) {
|
||||
case fac: ProtoFeastAvailableCommand =>
|
||||
case fac: FeastAvailable =>
|
||||
fac.actingProvinceId shouldBe developingProvince.id
|
||||
}
|
||||
}
|
||||
@@ -478,32 +466,34 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
.updated(5, veryTiredHero2.copy(loyalty = 70))
|
||||
)
|
||||
|
||||
val commands = Vector(
|
||||
feastCommand,
|
||||
giftCommand,
|
||||
restCommand,
|
||||
improveCommand,
|
||||
marchCommand
|
||||
)
|
||||
|
||||
val selection = PerformVassalCommandsPhaseAction(
|
||||
gameState = developingGS,
|
||||
commandsForProvince = Map(
|
||||
developingProvince.id -> Some(
|
||||
OneProvinceAvailableCommands(
|
||||
provinceId = developingProvince.id,
|
||||
commands = Vector(
|
||||
feastCommand,
|
||||
giftCommand,
|
||||
restCommand,
|
||||
improveCommand,
|
||||
marchCommand
|
||||
)
|
||||
commands = commands
|
||||
)
|
||||
)
|
||||
),
|
||||
commandFactory = commandFactory,
|
||||
actionResultApplier = actionResultApplier
|
||||
).chooseCommand(developingGS, developingProvince.id, functionalRandom).newValue.get
|
||||
).chooseCommand(developingGS, developingProvince.id, commands, functionalRandom).newValue.get
|
||||
|
||||
inside(selection.available) {
|
||||
case hgac: ProtoHeroGiftAvailableCommand =>
|
||||
case hgac: HeroGiftAvailable =>
|
||||
hgac.actingProvinceId shouldBe developingProvince.id
|
||||
}
|
||||
inside(selection.selected) {
|
||||
case HeroGiftSelectedCommand(recipientHeroId, _, _) =>
|
||||
case HeroGiftSelected(recipientHeroId, _) =>
|
||||
recipientHeroId shouldBe 2
|
||||
}
|
||||
}
|
||||
@@ -521,25 +511,27 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
.updated(5, veryTiredHero2.copy(loyalty = 70))
|
||||
)
|
||||
|
||||
val commands = Vector(
|
||||
feastCommand,
|
||||
giftCommand,
|
||||
restCommand,
|
||||
improveCommand,
|
||||
marchCommand
|
||||
)
|
||||
|
||||
val selection = PerformVassalCommandsPhaseAction(
|
||||
gameState = developingGS,
|
||||
commandsForProvince = Map(
|
||||
developingProvince.id -> Some(
|
||||
OneProvinceAvailableCommands(
|
||||
provinceId = developingProvince.id,
|
||||
commands = Vector(
|
||||
feastCommand,
|
||||
giftCommand,
|
||||
restCommand,
|
||||
improveCommand,
|
||||
marchCommand
|
||||
)
|
||||
commands = commands
|
||||
)
|
||||
)
|
||||
),
|
||||
commandFactory = commandFactory,
|
||||
actionResultApplier = actionResultApplier
|
||||
).chooseCommand(developingGS, developingProvince.id, functionalRandom).newValue.get
|
||||
).chooseCommand(developingGS, developingProvince.id, commands, functionalRandom).newValue.get
|
||||
|
||||
selection.available should not matchPattern {
|
||||
case _: HeroGiftAvailable =>
|
||||
@@ -548,25 +540,28 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
}
|
||||
|
||||
"chosen rest command" should "return the rest command" in {
|
||||
val protoCommands = toProtoCommands(Vector(restCommand, improveCommand), gameState)
|
||||
val selection = CommandChoiceHelpers
|
||||
val commands = Vector(restCommand, improveCommand)
|
||||
val selection = CommandChoiceHelpers
|
||||
.chosenRestCommand(
|
||||
actingFactionId = actingFactionId,
|
||||
gameState = gameState,
|
||||
availableCommands = protoCommands,
|
||||
availableCommands = commands,
|
||||
reason = "dummy reason"
|
||||
)
|
||||
.get
|
||||
|
||||
selection.available shouldBe protoCommands.head
|
||||
selection.selected should equalSelectedCommand(RestSelectedCommand())
|
||||
selection.available shouldBe restCommand
|
||||
inside(selection.selected) {
|
||||
case RestSelected =>
|
||||
succeed
|
||||
}
|
||||
}
|
||||
|
||||
"chooseRestCommand" should "return nothing if there is no rest command" in {
|
||||
CommandChoiceHelpers.chosenRestCommand(
|
||||
actingFactionId = actingFactionId,
|
||||
gameState = gameState,
|
||||
availableCommands = toProtoCommands(Vector(improveCommand), gameState),
|
||||
availableCommands = Vector(improveCommand),
|
||||
reason = "dummy reason"
|
||||
) shouldBe empty
|
||||
}
|
||||
@@ -576,21 +571,23 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
val developingGS =
|
||||
gameState.copy(provinces = gameState.provinces.updated(developingProvince.id, developingProvince))
|
||||
|
||||
val commands = Vector(restCommand, improveCommand, marchCommand)
|
||||
|
||||
val selection = PerformVassalCommandsPhaseAction(
|
||||
gameState = developingGS,
|
||||
commandsForProvince = Map(
|
||||
developingProvince.id -> Some(
|
||||
OneProvinceAvailableCommands(
|
||||
provinceId = developingProvince.id,
|
||||
commands = Vector(restCommand, improveCommand, marchCommand)
|
||||
commands = commands
|
||||
)
|
||||
)
|
||||
),
|
||||
commandFactory = commandFactory,
|
||||
actionResultApplier = actionResultApplier
|
||||
).chooseCommand(developingGS, developingProvince.id, functionalRandom).newValue.get
|
||||
).chooseCommand(developingGS, developingProvince.id, commands, functionalRandom).newValue.get
|
||||
|
||||
selection.available shouldBe toProtoCommands(Vector(improveCommand), developingGS).head
|
||||
selection.available shouldBe improveCommand
|
||||
}
|
||||
|
||||
"choose on a Developing province with no improvement available" should "return an successful Rest" in {
|
||||
@@ -598,21 +595,23 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
val developingGS =
|
||||
gameState.copy(provinces = gameState.provinces.updated(developingProvince.id, developingProvince))
|
||||
|
||||
val commands = Vector(restCommand, marchCommand)
|
||||
|
||||
val selection = PerformVassalCommandsPhaseAction(
|
||||
gameState = developingGS,
|
||||
commandsForProvince = Map(
|
||||
developingProvince.id -> Some(
|
||||
OneProvinceAvailableCommands(
|
||||
provinceId = developingProvince.id,
|
||||
commands = Vector(restCommand, marchCommand)
|
||||
commands = commands
|
||||
)
|
||||
)
|
||||
),
|
||||
commandFactory = commandFactory,
|
||||
actionResultApplier = actionResultApplier
|
||||
).chooseCommand(developingGS, developingProvince.id, functionalRandom).newValue.get
|
||||
).chooseCommand(developingGS, developingProvince.id, commands, functionalRandom).newValue.get
|
||||
|
||||
selection.available shouldBe toProtoCommands(Vector(restCommand), developingGS).head
|
||||
selection.available shouldBe restCommand
|
||||
}
|
||||
|
||||
"choose on an Expanding province" should "return a successful March" in {
|
||||
@@ -621,15 +620,17 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
provinces = marchGameState.provinces.updated(marchingProvince.id, marchingProvince)
|
||||
)
|
||||
|
||||
val commands = Vector(
|
||||
restCommand,
|
||||
improveCommand,
|
||||
marchCommand
|
||||
)
|
||||
|
||||
val commandsMap = Map(
|
||||
marchingProvince.id -> Some(
|
||||
OneProvinceAvailableCommands(
|
||||
provinceId = marchingProvince.id,
|
||||
commands = Vector(
|
||||
restCommand,
|
||||
improveCommand,
|
||||
marchCommand
|
||||
)
|
||||
commands = commands
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -639,12 +640,12 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
commandsForProvince = commandsMap,
|
||||
commandFactory = commandFactory,
|
||||
actionResultApplier = actionResultApplier
|
||||
).chooseCommand(marchingGS, actingProvince.id, functionalRandom).newValue.get
|
||||
).chooseCommand(marchingGS, actingProvince.id, commands, functionalRandom).newValue.get
|
||||
|
||||
// Verify the selected command is a march command matching our expected march
|
||||
inside(selection.available) {
|
||||
case _: ProtoMarchAvailableCommand =>
|
||||
selection.available shouldBe toProtoCommands(Vector(marchCommand), marchingGS).head
|
||||
case mac: MarchAvailable =>
|
||||
mac shouldBe marchCommand
|
||||
}
|
||||
}
|
||||
|
||||
@@ -654,11 +655,13 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
provinces = marchGameState.provinces.updated(marchingProvince.id, marchingProvince)
|
||||
)
|
||||
|
||||
val commands = Vector(restCommand, improveCommand)
|
||||
|
||||
val commandsMap = Map(
|
||||
marchingProvince.id -> Some(
|
||||
OneProvinceAvailableCommands(
|
||||
provinceId = marchingProvince.id,
|
||||
commands = Vector(restCommand, improveCommand)
|
||||
commands = commands
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -668,9 +671,9 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
commandsForProvince = commandsMap,
|
||||
commandFactory = commandFactory,
|
||||
actionResultApplier = actionResultApplier
|
||||
).chooseCommand(marchingGS, actingProvince.id, functionalRandom).newValue.get
|
||||
).chooseCommand(marchingGS, actingProvince.id, commands, functionalRandom).newValue.get
|
||||
|
||||
selection.available shouldBe toProtoCommands(Vector(improveCommand), marchingGS).head
|
||||
selection.available shouldBe improveCommand
|
||||
}
|
||||
|
||||
"suppliesToSend" should "return all available gold even if there is no food" in {
|
||||
@@ -761,8 +764,8 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
heroes = marchGameState.heroes.updated(leader.id, leader)
|
||||
)
|
||||
|
||||
private val availableSendSuppliesCommand: ProtoSendSuppliesAvailableCommand =
|
||||
ProtoSendSuppliesAvailableCommand(
|
||||
private val availableSendSuppliesCommand: SendSuppliesAvailable =
|
||||
SendSuppliesAvailable(
|
||||
actingProvinceId = actingProvince.id,
|
||||
availableHeroIds = actingProvince.rulingFactionHeroIds,
|
||||
goldAvailable = 2500,
|
||||
@@ -798,8 +801,9 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
.updated(actingProvinceWithIntermediateNeighbor.id, actingProvinceWithIntermediateNeighbor)
|
||||
.updated(leaderProvinceWithIntermediateNeighbor.id, leaderProvinceWithIntermediateNeighbor)
|
||||
)
|
||||
val ac = availableSendSuppliesCommand.update(
|
||||
_.availableDestinationProvinceIds :+= intermediateProvince.id
|
||||
val ac = availableSendSuppliesCommand.copy(
|
||||
availableDestinationProvinceIds =
|
||||
availableSendSuppliesCommand.availableDestinationProvinceIds :+ intermediateProvince.id
|
||||
)
|
||||
|
||||
CommandChoiceHelpers.preferredSuppliesDestination(
|
||||
@@ -837,9 +841,9 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
.updated(actingProvinceWithIntermediateNeighbor.id, actingProvinceWithIntermediateNeighbor)
|
||||
.updated(leaderProvinceWithIntermediateNeighbor.id, leaderProvinceWithIntermediateNeighbor)
|
||||
)
|
||||
val ac = availableSendSuppliesCommand.update(
|
||||
_.availableDestinationProvinceIds :+= intermediateProvince.id,
|
||||
_.availableDestinationProvinceIds :+= leaderProvince.id
|
||||
val ac = availableSendSuppliesCommand.copy(
|
||||
availableDestinationProvinceIds =
|
||||
availableSendSuppliesCommand.availableDestinationProvinceIds :+ intermediateProvince.id :+ leaderProvince.id
|
||||
)
|
||||
|
||||
CommandChoiceHelpers.preferredSuppliesDestination(
|
||||
@@ -894,9 +898,9 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
).map(p => p.id -> p).toMap,
|
||||
factions = Map(factionWithBrother.id -> factionWithBrother)
|
||||
)
|
||||
val ac = availableSendSuppliesCommand.update(
|
||||
_.actingProvinceId := 15,
|
||||
_.availableDestinationProvinceIds := Vector(16, 17)
|
||||
val ac = availableSendSuppliesCommand.copy(
|
||||
actingProvinceId = 15,
|
||||
availableDestinationProvinceIds = Vector(16, 17)
|
||||
)
|
||||
|
||||
CommandChoiceHelpers.preferredSuppliesDestination(
|
||||
@@ -951,9 +955,9 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
).map(p => p.id -> p).toMap,
|
||||
factions = Map(factionWithBrother.id -> factionWithBrother)
|
||||
)
|
||||
val ac = availableSendSuppliesCommand.update(
|
||||
_.actingProvinceId := 15,
|
||||
_.availableDestinationProvinceIds := Vector(16, 17)
|
||||
val ac = availableSendSuppliesCommand.copy(
|
||||
actingProvinceId = 15,
|
||||
availableDestinationProvinceIds = Vector(16, 17)
|
||||
)
|
||||
|
||||
CommandChoiceHelpers.preferredSuppliesDestination(
|
||||
@@ -987,8 +991,9 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
.updated(actingProvinceWithIntermediateNeighbor.id, actingProvinceWithIntermediateNeighbor)
|
||||
.updated(leaderProvinceWithIntermediateNeighbor.id, leaderProvinceWithIntermediateNeighbor)
|
||||
)
|
||||
val ac = availableSendSuppliesCommand.update(
|
||||
_.availableDestinationProvinceIds :+= intermediateProvince.id
|
||||
val ac = availableSendSuppliesCommand.copy(
|
||||
availableDestinationProvinceIds =
|
||||
availableSendSuppliesCommand.availableDestinationProvinceIds :+ intermediateProvince.id
|
||||
)
|
||||
|
||||
CommandChoiceHelpers.preferredSuppliesDestination(
|
||||
@@ -1023,8 +1028,9 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
.updated(actingProvinceWithIntermediateNeighbor.id, actingProvinceWithIntermediateNeighbor)
|
||||
.updated(leaderProvinceWithIntermediateNeighbor.id, leaderProvinceWithIntermediateNeighbor)
|
||||
)
|
||||
val ac = availableSendSuppliesCommand.update(
|
||||
_.availableDestinationProvinceIds :+= intermediateProvince.id
|
||||
val ac = availableSendSuppliesCommand.copy(
|
||||
availableDestinationProvinceIds =
|
||||
availableSendSuppliesCommand.availableDestinationProvinceIds :+ intermediateProvince.id
|
||||
)
|
||||
|
||||
val selection = CommandChoiceHelpers
|
||||
@@ -1032,14 +1038,13 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
.get
|
||||
|
||||
selection.available shouldBe ac
|
||||
selection.selected should equalSelectedCommand(
|
||||
SendSuppliesSelectedCommand(
|
||||
gold = 1900,
|
||||
food = 3200,
|
||||
actingHeroId = fullyRestedHero1.id,
|
||||
destinationProvinceId = intermediateProvince.id
|
||||
)
|
||||
)
|
||||
inside(selection.selected) {
|
||||
case SendSuppliesSelected(gold, food, actingHeroId, destinationProvinceId) =>
|
||||
gold shouldBe 1900
|
||||
food shouldBe 3200
|
||||
actingHeroId shouldBe fullyRestedHero1.id
|
||||
destinationProvinceId shouldBe intermediateProvince.id
|
||||
}
|
||||
}
|
||||
|
||||
it should "return nothing if the supplies are empty" in {
|
||||
@@ -1067,8 +1072,9 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
.updated(actingProvinceWithIntermediateNeighbor.id, actingProvinceWithIntermediateNeighbor)
|
||||
.updated(leaderProvinceWithIntermediateNeighbor.id, leaderProvinceWithIntermediateNeighbor)
|
||||
)
|
||||
val ac = availableSendSuppliesCommand.update(
|
||||
_.availableDestinationProvinceIds :+= intermediateProvince.id
|
||||
val ac = availableSendSuppliesCommand.copy(
|
||||
availableDestinationProvinceIds =
|
||||
availableSendSuppliesCommand.availableDestinationProvinceIds :+ intermediateProvince.id
|
||||
)
|
||||
|
||||
CommandChoiceHelpers.maybeChosenSendSuppliesCommand(
|
||||
@@ -1100,8 +1106,9 @@ class PerformVassalCommandsPhaseActionTest extends AnyFlatSpec with Matchers wit
|
||||
.updated(actingProvinceWithIntermediateNeighbor.id, actingProvinceWithIntermediateNeighbor)
|
||||
.updated(leaderProvinceWithIntermediateNeighbor.id, leaderProvinceWithIntermediateNeighbor)
|
||||
)
|
||||
val ac = availableSendSuppliesCommand.update(
|
||||
_.availableDestinationProvinceIds :+= intermediateProvince.id
|
||||
val ac = availableSendSuppliesCommand.copy(
|
||||
availableDestinationProvinceIds =
|
||||
availableSendSuppliesCommand.availableDestinationProvinceIds :+ intermediateProvince.id
|
||||
)
|
||||
CommandChoiceHelpers.maybeChosenSendSuppliesCommand(
|
||||
actingFactionId,
|
||||
|
||||
Reference in New Issue
Block a user