Files
TheriapolisV3/Theriapolis.Tests/Combat/InitiativeTests.cs
T

84 lines
3.2 KiB
C#
Raw Normal View History

using Theriapolis.Core.Data;
using Theriapolis.Core.Rules.Combat;
using Theriapolis.Core.Rules.Stats;
using Theriapolis.Core.Util;
using Xunit;
namespace Theriapolis.Tests.Combat;
public sealed class InitiativeTests
{
private readonly ContentResolver _content = new(new ContentLoader(TestHelpers.DataDirectory));
[Fact]
public void NewEncounter_AppendsInitiativeLogEntry()
{
var combatants = MakeThree();
var enc = new Encounter(0xCAFEUL, 1, combatants);
Assert.Contains(enc.Log, l => l.Type == CombatLogEntry.Kind.Initiative);
}
[Fact]
public void InitiativeOrder_ContainsEveryCombatantExactlyOnce()
{
var combatants = MakeThree();
var enc = new Encounter(0xCAFEUL, 1, combatants);
Assert.Equal(combatants.Count, enc.InitiativeOrder.Count);
Assert.Equal(combatants.Count, enc.InitiativeOrder.Distinct().Count());
foreach (int idx in enc.InitiativeOrder)
Assert.InRange(idx, 0, combatants.Count - 1);
}
[Fact]
public void EndTurn_AdvancesToNextLivingCombatant()
{
var combatants = MakeThree();
var enc = new Encounter(0xCAFEUL, 1, combatants);
var first = enc.CurrentActor;
enc.EndTurn();
Assert.NotEqual(first.Id, enc.CurrentActor.Id);
}
[Fact]
public void EndTurn_WrappingIncrementsRoundCounter()
{
var combatants = MakeThree();
var enc = new Encounter(0xCAFEUL, 1, combatants);
Assert.Equal(1, enc.RoundNumber);
// Advance N turns to wrap once.
for (int i = 0; i < combatants.Count; i++) enc.EndTurn();
Assert.Equal(2, enc.RoundNumber);
}
[Fact]
public void CheckForVictory_EndsWhenOnlyOneSideRemains()
{
var brigand = _content.Npcs.Templates.First(t => t.Id == "brigand_footpad");
var wolf = _content.Npcs.Templates.First(t => t.Id == "wolf");
var hero = Combatant.FromNpcTemplate(brigand, id: 1, new Vec2(0, 0));
var foe = Combatant.FromNpcTemplate(wolf, id: 2, new Vec2(1, 0));
// Force opposite allegiances. Brigand defaults Hostile; rebuild "hero" as Player-side.
hero = Combatant.FromNpcTemplate(brigand with { DefaultAllegiance = "player" }, id: 1, new Vec2(0, 0));
var enc = new Encounter(1UL, 1, new[] { hero, foe });
// Knock out the foe.
Resolver.ApplyDamage(foe, foe.MaxHp);
Assert.True(enc.CheckForVictory());
Assert.True(enc.IsOver);
Assert.Contains(enc.Log, l => l.Type == CombatLogEntry.Kind.EncounterEnd);
}
private List<Combatant> MakeThree()
{
var brigand = _content.Npcs.Templates.First(t => t.Id == "brigand_footpad");
var wolf = _content.Npcs.Templates.First(t => t.Id == "wolf");
var captain = _content.Npcs.Templates.First(t => t.Id == "brigand_captain");
// Mix allegiances so CheckForVictory doesn't end the encounter immediately.
return new List<Combatant>
{
Combatant.FromNpcTemplate(brigand with { DefaultAllegiance = "player" }, id: 1, new Vec2(0, 0)),
Combatant.FromNpcTemplate(wolf, id: 2, new Vec2(2, 0)),
Combatant.FromNpcTemplate(captain, id: 3, new Vec2(4, 0)),
};
}
}