using Theriapolis.Core; using Theriapolis.Core.Data; using Theriapolis.Core.Loot; using Theriapolis.Core.Util; using Xunit; namespace Theriapolis.Tests.Loot; public sealed class LootRollerTests { private readonly ContentResolver _content = new(new ContentLoader(TestHelpers.DataDirectory)); [Fact] public void LootTables_LoadCleanly() { Assert.True(_content.LootTables.Count >= 9, $"expected ≥9 loot tables, got {_content.LootTables.Count}"); Assert.Contains("loot_brigand_low", _content.LootTables.Keys); Assert.Contains("loot_brigand_high", _content.LootTables.Keys); Assert.Contains("loot_wild_low", _content.LootTables.Keys); } [Fact] public void Roll_UnknownTable_ReturnsEmpty() { var rng = new SeededRng(0xCAFEUL); var drops = LootRoller.Roll("not_a_table", _content.LootTables, _content.Items, rng); Assert.Empty(drops); } [Fact] public void Roll_EmptyTableId_ReturnsEmpty() { var rng = new SeededRng(0xCAFEUL); var drops = LootRoller.Roll("", _content.LootTables, _content.Items, rng); Assert.Empty(drops); } [Fact] public void Roll_SameSeed_ProducesSameDrops() { var a = LootRoller.Roll("loot_brigand_high", _content.LootTables, _content.Items, new SeededRng(42UL)); var b = LootRoller.Roll("loot_brigand_high", _content.LootTables, _content.Items, new SeededRng(42UL)); Assert.Equal(a.Count, b.Count); for (int i = 0; i < a.Count; i++) { Assert.Equal(a[i].Def.Id, b[i].Def.Id); Assert.Equal(a[i].Qty, b[i].Qty); } } [Fact] public void Roll_QtyAlwaysWithinBounds() { // Roll many times; verify no result has qty outside the table-defined range. var table = _content.LootTables["loot_brigand_high"]; var bounds = table.Drops.ToDictionary(d => d.ItemId, d => (d.QtyMin, d.QtyMax)); for (int seed = 0; seed < 50; seed++) { var drops = LootRoller.Roll("loot_brigand_high", _content.LootTables, _content.Items, new SeededRng((ulong)seed)); foreach (var drop in drops) { var (mn, mx) = bounds[drop.Def.Id]; Assert.InRange(drop.Qty, mn, mx); } } } [Fact] public void Roll_OneHundredSamples_AverageDropCountIsReasonable() { // The "high" brigand table has 5 drops with cumulative chance summing // around 1.95. Across 100 samples expect ≥50 total drops. int totalDrops = 0; for (int seed = 0; seed < 100; seed++) { var drops = LootRoller.Roll("loot_brigand_high", _content.LootTables, _content.Items, new SeededRng((ulong)seed)); totalDrops += drops.Count; } Assert.True(totalDrops >= 50, $"expected ≥50 drops in 100 samples, got {totalDrops}"); } }