using System.Collections.Generic; using NUnit.Framework; using BaseGames.Enemies.Abilities; namespace BaseGames.Tests.EditMode.Enemies { public class EnemyAttackSelectorTests { sealed class FakeCandidate : IAttackCandidate { public bool CanUseV = true, InRange = true, ReqLOS = false, ReqGround = false, Executed; public float WeightV = 1f; public int PriorityV = 0; public bool CanUse => CanUseV; public bool RequiresLineOfSight => ReqLOS; public bool RequiresGrounded => ReqGround; public float Weight => WeightV; public int Priority => PriorityV; public bool InAttackRange() => InRange; public bool Execute() { Executed = true; return true; } } static EnemyAttackSelector Sel(params IAttackCandidate[] cs) => new EnemyAttackSelector(new List(cs)); [Test] public void Empty_NoEligible() { var s = Sel(); Assert.IsFalse(s.HasEligible(true, true)); Assert.IsNull(s.Select(true, true, AttackSelectionMode.Priority)); } [Test] public void ExcludesOnCooldown() { var c = new FakeCandidate { CanUseV = false }; Assert.IsFalse(Sel(c).HasEligible(true, true)); } [Test] public void ExcludesOutOfRange() { var c = new FakeCandidate { InRange = false }; Assert.IsFalse(Sel(c).HasEligible(true, true)); } [Test] public void ExcludesWhenNeedsLOS_ButNoLOS() { var c = new FakeCandidate { ReqLOS = true }; Assert.IsFalse(Sel(c).HasEligible(false, true)); Assert.IsTrue (Sel(c).HasEligible(true, true)); } [Test] public void ExcludesWhenNeedsGrounded_ButAirborne() { var c = new FakeCandidate { ReqGround = true }; Assert.IsFalse(Sel(c).HasEligible(true, false)); Assert.IsTrue (Sel(c).HasEligible(true, true)); } [Test] public void Priority_PicksHighest() { var lo = new FakeCandidate { PriorityV = 1 }; var hi = new FakeCandidate { PriorityV = 5 }; var pick = Sel(lo, hi).Select(true, true, AttackSelectionMode.Priority); Assert.AreSame(hi, pick); } [Test] public void Priority_TieTakesFirstInList() { var a = new FakeCandidate { PriorityV = 3 }; var b = new FakeCandidate { PriorityV = 3 }; var pick = Sel(a, b).Select(true, true, AttackSelectionMode.Priority); Assert.AreSame(a, pick); } [Test] public void Priority_SkipsIneligible() { var blocked = new FakeCandidate { PriorityV = 9, InRange = false }; var ok = new FakeCandidate { PriorityV = 1 }; var pick = Sel(blocked, ok).Select(true, true, AttackSelectionMode.Priority); Assert.AreSame(ok, pick); } [Test] public void Weighted_SingleEligible_AlwaysThatOne() { var only = new FakeCandidate { WeightV = 2f }; for (int i = 0; i < 20; i++) Assert.AreSame(only, Sel(only).Select(true, true, AttackSelectionMode.WeightedRandom)); } [Test] public void Weighted_NeverPicksIneligible() { var bad = new FakeCandidate { WeightV = 100f, InRange = false }; var ok = new FakeCandidate { WeightV = 1f }; for (int i = 0; i < 50; i++) Assert.AreSame(ok, Sel(bad, ok).Select(true, true, AttackSelectionMode.WeightedRandom)); } } }