using Theriapolis.Core.Rules.Stats; using Xunit; namespace Theriapolis.Tests.Rules; public sealed class AbilityScoreTests { [Theory] [InlineData(1, -5)] [InlineData(8, -1)] [InlineData(9, -1)] [InlineData(10, 0)] [InlineData(11, 0)] [InlineData(12, 1)] [InlineData(15, 2)] [InlineData(18, 4)] [InlineData(20, 5)] [InlineData(30, 10)] public void Mod_MatchesD20Table(int score, int expected) { Assert.Equal(expected, AbilityScores.Mod(score)); } [Fact] public void Mod_FloorsTowardNegativeInfinity() { // Score 9 → -1, score 7 → -2 (per d20 floor convention; not C# truncate) Assert.Equal(-1, AbilityScores.Mod(9)); Assert.Equal(-2, AbilityScores.Mod(7)); Assert.Equal(-3, AbilityScores.Mod(5)); } [Fact] public void Constructor_ClampsToValidRange() { var a = new AbilityScores(0, 31, 50, -10, 100, 18); Assert.Equal(1, a.STR); // 0 clamped up to 1 Assert.Equal(30, a.DEX); // 31 clamped down to 30 Assert.Equal(30, a.CON); Assert.Equal(1, a.INT); // -10 clamped up to 1 Assert.Equal(30, a.WIS); Assert.Equal(18, a.CHA); } [Fact] public void StandardArray_IsCanonical() { Assert.Equal(new[] { 15, 14, 13, 12, 10, 8 }, AbilityScores.StandardArray); } [Fact] public void Get_ReturnsValueByAbilityId() { var a = new AbilityScores(11, 13, 15, 10, 12, 14); Assert.Equal(11, a.Get(AbilityId.STR)); Assert.Equal(13, a.Get(AbilityId.DEX)); Assert.Equal(15, a.Get(AbilityId.CON)); Assert.Equal(10, a.Get(AbilityId.INT)); Assert.Equal(12, a.Get(AbilityId.WIS)); Assert.Equal(14, a.Get(AbilityId.CHA)); } [Fact] public void With_ReturnsNewBlock_LeavesOriginalUnchanged() { var a = new AbilityScores(10, 10, 10, 10, 10, 10); var b = a.With(AbilityId.STR, 18); Assert.Equal(10, a.STR); // unchanged Assert.Equal(18, b.STR); Assert.Equal(10, b.DEX); // others copied } [Fact] public void Plus_AppliesAllMods() { var a = new AbilityScores(10, 10, 10, 10, 10, 10); var mods = new Dictionary { { AbilityId.STR, 1 }, { AbilityId.WIS, 2 } }; var b = a.Plus(mods); Assert.Equal(11, b.STR); Assert.Equal(12, b.WIS); Assert.Equal(10, b.DEX); } [Fact] public void ModFor_UsesStandardFormula() { var a = new AbilityScores(15, 14, 13, 12, 10, 8); Assert.Equal( 2, a.ModFor(AbilityId.STR)); // (15-10)/2 = 2 Assert.Equal( 2, a.ModFor(AbilityId.DEX)); // (14-10)/2 = 2 Assert.Equal( 1, a.ModFor(AbilityId.CON)); // (13-10)/2 = 1 Assert.Equal( 1, a.ModFor(AbilityId.INT)); Assert.Equal( 0, a.ModFor(AbilityId.WIS)); Assert.Equal(-1, a.ModFor(AbilityId.CHA)); } }