oecs-sharp/Game.CardWars.Tests/CardEffectTests.cs

139 lines
4.7 KiB
C#
Raw Permalink Normal View History

using FluentAssertions;
using Game.CardWars;
using OECS;
using Xunit;
namespace Game.CardWars.Tests;
public class CardEffectTests
{
private static (World World, SystemGroup Group) Setup()
{
CardEffectRegistry.ClearForTests();
return GameFactory.Create(playerCount: 2, seed: 42);
}
[Fact]
public void WarriorEffect_AddsHornWhenAnotherWarriorExists()
{
var (world, group) = Setup();
var state = world.ReadSingleton<GameState>();
var player = PlayCardCommand.FindPlayerByIndex(world, state.CurrentPlayerIndex);
// Play two warriors.
var hand = GameUtil.GetHandCards(world, player);
var warrior1 = FindCardWithEffect(world, hand, CardEffect.Warrior);
var warrior2 = FindSecondCardWithEffect(world, hand, CardEffect.Warrior);
if (warrior1 == Entity.Null || warrior2 == Entity.Null) return; // Not enough warriors in deck.
var def = world.ReadComponent<CardDef>(warrior1);
world.Commands.Enqueue(new PlayCardCommand
{
CardEntity = warrior1,
Rank = def.Ranks[0],
FaceDown = false,
TargetPlayer = null
});
group.RunLogical();
// First warrior: no other warrior, no horn.
GameUtil.GetFieldCards(world, player).Should().Contain(warrior1);
world.HasComponent<Horn>(warrior1).Should().BeFalse(because: "no other warrior on field");
// Play second warrior.
var def2 = world.ReadComponent<CardDef>(warrior2);
world.Commands.Enqueue(new PlayCardCommand
{
CardEntity = warrior2,
Rank = def2.Ranks[0],
FaceDown = false,
TargetPlayer = null
});
group.RunLogical();
// Second warrior has another warrior, should get horn.
// But Wait — the effect checks "other" warriors on field. The first warrior
// is on field, so the second warrior should get a horn.
world.HasComponent<Horn>(warrior2).Should().BeTrue(because: "another warrior exists on field");
}
[Fact]
public void MercenaryEffect_SetsPendingChoice()
{
var (world, group) = Setup();
var state = world.ReadSingleton<GameState>();
var player = PlayCardCommand.FindPlayerByIndex(world, state.CurrentPlayerIndex);
// Play first mercenary (no effect).
var hand = GameUtil.GetHandCards(world, player);
var merc = FindCardWithEffect(world, hand, CardEffect.Mercenary);
if (merc == Entity.Null) return;
var def = world.ReadComponent<CardDef>(merc);
world.Commands.Enqueue(new PlayCardCommand
{
CardEntity = merc,
Rank = def.Ranks[0],
FaceDown = false,
TargetPlayer = null
});
group.RunLogical();
// Play second mercenary. We need another one from a drawn card.
var publicDeck = GameUtil.FindEntity<PublicDeck>(world);
GameUtil.DrawCard(world, publicDeck, player);
var newHand = GameUtil.GetHandCards(world, player);
var merc2 = FindCardWithEffect(world, newHand, CardEffect.Mercenary);
if (merc2 == Entity.Null) return;
var def2 = world.ReadComponent<CardDef>(merc2);
world.Commands.Enqueue(new PlayCardCommand
{
CardEntity = merc2,
Rank = def2.Ranks[0],
FaceDown = false,
TargetPlayer = null
});
group.RunLogical();
// Should have a pending Mercenary choice.
world.HasSingleton<PendingMercenary>().Should().BeTrue();
var pending = world.ReadSingleton<PendingMercenary>();
pending.CardEntity.Should().Be(merc2);
// Resolve the choice (pick a target).
world.Commands.Enqueue(new ResolveChoiceCommand { Target = merc });
group.RunLogical();
// The pending should be cleared.
world.HasSingleton<PendingMercenary>().Should().BeFalse();
}
private static Entity FindCardWithEffect(World world, List<Entity> cards, CardEffect effect)
{
foreach (var c in cards)
{
if (world.HasComponent<CardDef>(c) && world.ReadComponent<CardDef>(c).Effect == effect)
return c;
}
return Entity.Null;
}
private static Entity FindSecondCardWithEffect(World world, List<Entity> cards, CardEffect effect)
{
Entity first = Entity.Null;
foreach (var c in cards)
{
if (world.HasComponent<CardDef>(c) && world.ReadComponent<CardDef>(c).Effect == effect)
{
if (first == Entity.Null) first = c;
else return c;
}
}
return Entity.Null;
}
}