Only warn when lone leader fix fails (#8692)

This commit is contained in:
2026-07-17 19:55:28 -07:00
committed by GitHub
parent 1bea610232
commit 89d1d15979
2 changed files with 114 additions and 5 deletions
@@ -68,14 +68,28 @@ object MidGameAIClient {
)
}
private[ai] def maybeFixLeaderAlone(
actingFactionId: FactionId,
gameState: GameState,
availableCommands: Vector[AvailableCommand],
functionalRandom: FunctionalRandom
): RandomState[Option[CommandSelection]] = {
val selection = FixLeaderAloneCommandSelector.maybeFixLeaderAlone(
actingFactionId,
gameState,
availableCommands,
functionalRandom
)
if selection.newValue.isEmpty then validateNoFactionLeaderAlone(gameState, actingFactionId)
selection
}
def chosenMidGameCommand(
factionId: FactionId,
gs: GameState,
opac: OneProvinceAvailableCommands,
functionalRandom: FunctionalRandom
): RandomState[CommandSelection] = {
validateNoFactionLeaderAlone(gs, factionId)
): RandomState[CommandSelection] =
CommandChooser.choose(
actingFactionId = factionId,
gameState = gs,
@@ -93,7 +107,7 @@ object MidGameAIClient {
),
functionalRandom
),
FixLeaderAloneCommandSelector.maybeFixLeaderAlone,
maybeFixLeaderAlone,
(actingFactionId, gameState, availableCommands, functionalRandom) =>
RandomState(
maybeChosenRelaySuppliesCommand(
@@ -135,7 +149,6 @@ object MidGameAIClient {
functionalRandom = fr
)
}
}
// Send supplies to a neighbor that's running low
private def maybeChosenRelaySuppliesCommand(
@@ -1,5 +1,7 @@
package net.eagle0.eagle.ai
import java.io.{ByteArrayOutputStream, PrintStream}
import net.eagle0.common.SeededRandom
import net.eagle0.eagle.{BattalionId, FactionId, HeroId, ProvinceId}
import net.eagle0.eagle.library.settings.{
@@ -230,6 +232,12 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
name = ""
)
private def capturedOutput[A](action: => A): String = {
val bytes = new ByteArrayOutputStream()
val _ = Console.withOut(new PrintStream(bytes, true, "UTF-8"))(action)
bytes.toString("UTF-8")
}
private val faction = makeFaction(
id = factionId,
factionHeadId = leaderId,
@@ -276,6 +284,94 @@ class MidGameAIClientTest extends AnyFlatSpec with Matchers with BeforeAndAfterE
heroCap = 20
)
"maybeFixLeaderAlone" should "warn when a lone leader cannot be fixed" in {
val gs = makeGameState(
factions = Map(factionId -> faction),
provinces = mapifyProvinces(
provinceA.copy(
name = "Wichel",
rulingFactionHeroIds = Vector(leaderId)
)
),
heroes = Map.empty
)
val output = capturedOutput {
MidGameAIClient
.maybeFixLeaderAlone(
actingFactionId = factionId,
gameState = gs,
availableCommands = Vector.empty,
functionalRandom = SeededRandom(1234)
)
.newValue shouldBe empty
}
output should include("We have a faction leader by themselves in Wichel")
}
it should "not warn when it selects a fix for the lone leader" in {
val donor = provinceC.copy(rulingFactionHeroIds = Vector(11, 12, 13))
val destination = provinceD.copy(
name = "Wichel",
rulingFactionHeroIds = Vector(leaderId)
)
val gs = makeGameState(
factions = Map(factionId -> faction),
provinces = mapifyProvinces(donor, destination),
heroes = Map.empty
)
val marchAvailable = makeMarchAvailable(
actingProvinceId = destination.id,
oneProvinceCommands = Vector(
makeMarchCommand(
originProvinceId = donor.id,
availableDestinationProvinces = Vector(
AvailableDestinationProvince(
provinceId = destination.id,
requiresRiverCrossing = false
)
),
availableHeroIds = donor.rulingFactionHeroIds
)
)
)
val output = capturedOutput {
MidGameAIClient
.maybeFixLeaderAlone(
actingFactionId = factionId,
gameState = gs,
availableCommands = Vector(marchAvailable),
functionalRandom = SeededRandom(1234)
)
.newValue should not be empty
}
output should not include "We have a faction leader by themselves"
}
it should "not warn when there is no lone leader" in {
val gs = makeGameState(
factions = Map(factionId -> faction),
provinces = mapifyProvinces(provinceA.copy(rulingFactionHeroIds = Vector.empty)),
heroes = Map.empty
)
val output = capturedOutput {
MidGameAIClient
.maybeFixLeaderAlone(
actingFactionId = factionId,
gameState = gs,
availableCommands = Vector.empty,
functionalRandom = SeededRandom(1234)
)
.newValue shouldBe empty
}
output shouldBe empty
}
it should "maybeMoveHeroesToFocusCommand" in {}
"maybeMoveHeroesToHubProvince" should "move heroes if extras are available" in {