using System.Collections.Generic; using NUnit.Framework; using NightclubArcadia.Skills; using UnityEngine; namespace NightclubArcadia.Skills.Tests { public class SkillCheckSystemTests { sealed class FixedRollSource : IRollSource { readonly int _value; public FixedRollSource(int value) => _value = value; public int Roll(int sides) => _value; } static SkillBibleEntry Entry(string id, string display, int rank) { return new SkillBibleEntry { id = id, displayName = display, axis = "Social", domain = string.Empty, notes = string.Empty, targetFiringsPerHour = 5f, opposedTo = string.Empty, alliedWith = System.Array.Empty(), primaryChannel = "Testimonial", secondaryChannel = "None", clueYield = "Low", startingRank = rank, accentColor = Color.white, }; } SkillDatabase CreateDatabase(params (string id, string display, int rank)[] skills) { var db = ScriptableObject.CreateInstance(); var list = new List(); foreach (var (id, display, rank) in skills) { var def = ScriptableObject.CreateInstance(); def.EditorSet(Entry(id, display, rank)); list.Add(def); } db.EditorSetSkills(list); return db; } [Test] public void Resolve_SumsModifiers_AndSucceedsWhenTotalMeetsDc() { var db = CreateDatabase(("placement", "PLACEMENT", 2)); var skills = new PlayerSkills(db); var state = new SkillStateModifiers(); var system = new SkillCheckSystem(db, skills, state, new FixedRollSource(10)); var result = system.Resolve("placement", 12, 1); Assert.AreEqual(13, result.Total); Assert.IsTrue(result.Success); Assert.AreEqual(SkillCheckDegree.Success, result.Degree); Assert.AreEqual(2, result.RankMod); Assert.AreEqual(1, result.SituationalMod); Assert.AreEqual(0, result.StateMod); } [Test] public void Resolve_NaturalOne_IsCriticalFailureEvenIfModifiersWouldPass() { var db = CreateDatabase(("placement", "PLACEMENT", 10)); var skills = new PlayerSkills(db); var state = new SkillStateModifiers(); var system = new SkillCheckSystem(db, skills, state, new FixedRollSource(1)); var result = system.Resolve("placement", 5, 5); Assert.IsFalse(result.Success); Assert.AreEqual(SkillCheckDegree.CriticalFailure, result.Degree); } [Test] public void Resolve_NaturalTwenty_IsCriticalSuccessEvenIfBelowDc() { var db = CreateDatabase(("placement", "PLACEMENT", 0)); var skills = new PlayerSkills(db); var state = new SkillStateModifiers(); var system = new SkillCheckSystem(db, skills, state, new FixedRollSource(20)); var result = system.Resolve("placement", 25, 0); Assert.IsTrue(result.Success); Assert.AreEqual(SkillCheckDegree.CriticalSuccess, result.Degree); } [Test] public void Resolve_ExactDc_IsSuccess() { var db = CreateDatabase(("placement", "PLACEMENT", 1)); var skills = new PlayerSkills(db); var state = new SkillStateModifiers(); var system = new SkillCheckSystem(db, skills, state, new FixedRollSource(10)); var result = system.Resolve("placement", 11, 0); Assert.AreEqual(11, result.Total); Assert.IsTrue(result.Success); } [Test] public void Resolve_AppliesNegativeAndWildcardStateModifiers() { var db = CreateDatabase(("long_shift", "THE LONG SHIFT", 1)); var skills = new PlayerSkills(db); var state = new SkillStateModifiers(); state.Set("drunk", "long_shift", -2); state.Set("crowd", "*", -1); var system = new SkillCheckSystem(db, skills, state, new FixedRollSource(10)); var result = system.Resolve("long_shift", 5, 0); Assert.AreEqual(-3, result.StateMod); Assert.AreEqual(8, result.Total); } [Test] public void Resolve_UnknownSkill_DoesNotThrow_AndUsesZeroRank() { var db = CreateDatabase(("placement", "PLACEMENT", 3)); var skills = new PlayerSkills(db); var state = new SkillStateModifiers(); var system = new SkillCheckSystem(db, skills, state, new FixedRollSource(10)); SkillCheckResult result = default; Assert.DoesNotThrow(() => result = system.Resolve("nosuchskill", 10, 0)); Assert.AreEqual(0, result.RankMod); Assert.AreEqual("NOSUCHSKILL", result.SkillDisplayName); } [Test] public void Resolve_DoesNotMutatePlayerSkills() { var db = CreateDatabase(("placement", "PLACEMENT", 2)); var skills = new PlayerSkills(db); var before = skills.GetRank("placement"); var state = new SkillStateModifiers(); var system = new SkillCheckSystem(db, skills, state, new FixedRollSource(10)); system.Resolve("placement", 10, 0); Assert.AreEqual(before, skills.GetRank("placement")); Assert.AreEqual(1, skills.AllRanks.Count); } } }