using CardGame.Core; using Xunit; namespace Game.Core.Tests; public sealed class AiSearchTests { [Fact] public void Prefers_face_damage_when_lethal_or_high_value() { var state = new GameState(9) { Catalog = Cards.Catalog }; MatchSetup.PlaceSystemField(state, 0, Cards.BaseField); MatchSetup.PlaceSystemField(state, 1, Cards.BaseField); state.Players[1].Life = 1; var attacker = state.NewEntity(Cards.Wisp, 0, Zone.Board, Factions.Guard); attacker.EnteredOnTurn = 0; attacker.AttacksRemaining = 1; state.Board.Add(attacker); state.ActivePlayerIndex = 0; state.TurnNumber = 2; var legal = RulesEngine.GetLegalActions(state); var (action, top) = TurnBeamSearch.ChooseWithTrace(state, legal); Assert.IsType(action); Assert.Contains(top, t => t.Chosen && t.Label.Contains("敌方主战者", StringComparison.Ordinal)); } [Fact] public void PlayUntil_returns_step_trace() { var state = MatchSetup.CreateStartingBattle(11, Cards.Catalog, shuffle: false); state = RulesEngine.Execute(state, new EndTurnAction(0)); var (_, trace) = TurnBeamSearch.PlayUntil(state, untilPlayerIndex: 0); Assert.NotEmpty(trace.Steps); Assert.All(trace.Steps, s => Assert.NotEmpty(s.TopCandidates)); } [Fact] public void ChooseWithTrace_works_when_all_scores_are_negative() { var state = MatchSetup.CreateStartingBattle(13, Cards.Catalog, shuffle: false); state.Players[0].Life = 1; state.Players[1].Life = 20; var legal = RulesEngine.GetLegalActions(state); var (action, top) = TurnBeamSearch.ChooseWithTrace(state, legal); Assert.NotNull(action); Assert.Contains(top, t => t.Chosen); } }