Files
chenmoranzhiandCursor ae13f1d06a 落地无头规则引擎与局内内容,便于命令行复现对战。
规则、卡包与测试放在同一套核心里,避免表现层自行结算。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-09 02:06:23 +08:00

85 lines
2.9 KiB
C#

using CardGame.Core;
using Xunit;
namespace Game.Core.Tests;
public sealed class PhaseBTests
{
private static GameState NewMatch(CardDefinition card, int count = 10) =>
MatchSetup.Create(11, Cards.Repeat(card, count), Cards.Repeat(card, count), Cards.Catalog, shuffle: false);
[Fact]
public void Opening_draw_and_base_supply()
{
var state = NewMatch(Cards.Wisp);
Assert.Equal(4, state.Players[0].Hand.Count);
Assert.Equal(3, state.Players[1].Hand.Count);
Assert.Equal(1, state.Players[0].Energy);
}
[Fact]
public void Play_creature_pays_current_cost()
{
var state = NewMatch(Cards.Wisp);
var wisp = state.Players[0].Hand[0];
state = RulesEngine.Execute(state, new PlayCardAction(0, wisp.Id));
Assert.Equal(0, state.Players[0].Energy);
Assert.Contains(state.Board, e => e.Id == wisp.Id && e.Zone == Zone.Board);
Assert.Equal(0, state.Find(wisp.Id)!.AttacksRemaining);
}
[Fact]
public void Spell_damages_and_goes_to_graveyard()
{
var state = NewMatch(Cards.Spark);
var spark = state.Players[0].Hand[0];
state = RulesEngine.Execute(state, new PlayCardAction(0, spark.Id, new PlayerTarget(1)));
Assert.Equal(19, state.Players[1].Life);
Assert.Contains(state.Players[0].Graveyard, e => e.Id == spark.Id);
}
[Fact]
public void Creature_attacks_after_summoning_sickness()
{
var state = NewMatch(Cards.Wisp, 20);
var wisp = state.Players[0].Hand[0];
state = RulesEngine.Execute(state, new PlayCardAction(0, wisp.Id));
Assert.DoesNotContain(RulesEngine.GetLegalActions(state), a => a is AttackAction);
state = RulesEngine.Execute(state, new EndTurnAction(0));
state = RulesEngine.Execute(state, new EndTurnAction(1));
var attacker = state.Board.Single(e => e.ControllerIndex == 0 && e.Definition.Id == Cards.Wisp.Id);
state = RulesEngine.Execute(state, new AttackAction(0, attacker.Id, new PlayerTarget(1)));
Assert.Equal(19, state.Players[1].Life);
}
[Fact]
public void Shared_board_caps_at_ten()
{
var state = NewMatch(Cards.Wisp, 30);
for (var turn = 0; turn < 8 && !state.IsOver; turn++)
{
while (true)
{
var play = RulesEngine.GetLegalActions(state).OfType<PlayCardAction>().FirstOrDefault();
if (play is null)
{
break;
}
state = RulesEngine.Execute(state, play);
}
if (state.IsOver)
{
break;
}
state = RulesEngine.Execute(state, new EndTurnAction(state.ActivePlayerIndex));
}
Assert.True(state.Board.Count(e => e.Definition.Type != CardType.FieldCard || !e.IsSystem) <= GameState.BoardCapacity);
}
}