using System.Linq; using NUnit.Framework; using UnityEngine; using Vanguard.Board3D; namespace Vanguard.Tests { public sealed class PlaymatLayoutTests { [Test] public void Default_Playmat_Has_Six_Circles_Per_Side() { var config = PlaymatLayoutConfig.CreateDefault(); var layout = new PlaymatLayout(config); for (var seat = 0; seat < 2; seat++) { var positions = Enumerable.Range(-1, PlaymatLayout.RearGuardCount + 1) .Select(slot => layout.CirclePosition(seat, slot)) .ToList(); Assert.AreEqual(6, positions.Count); Assert.AreEqual(6, positions.Select(position => position.ToString()).Distinct().Count()); } } [Test] public void Vanguard_Is_Center_Front_And_Rear_Center_Exists() { var config = PlaymatLayoutConfig.CreateDefault(); var layout = new PlaymatLayout(config); var vanguard = layout.CirclePosition(0, PlaymatLayout.VanguardSlot); var rearCenter = layout.CirclePosition(0, 1); var leftFront = layout.CirclePosition(0, 3); var rightFront = layout.CirclePosition(0, 4); Assert.AreEqual(0f, vanguard.x, 0.0001f); Assert.AreEqual(-config.frontRowZ, vanguard.z, 0.0001f); Assert.AreEqual(0f, rearCenter.x, 0.0001f); Assert.AreEqual(-config.backRowZ, rearCenter.z, 0.0001f); Assert.Less(leftFront.x, 0f); Assert.Greater(rightFront.x, 0f); Assert.AreEqual(vanguard.z, leftFront.z, 0.0001f); Assert.AreEqual(vanguard.z, rightFront.z, 0.0001f); } [Test] public void Opponent_Half_Is_Mirrored() { var config = PlaymatLayoutConfig.CreateDefault(); var layout = new PlaymatLayout(config); for (var slot = PlaymatLayout.VanguardSlot; slot < PlaymatLayout.RearGuardCount; slot++) { var self = layout.CirclePosition(0, slot); var opponent = layout.CirclePosition(1, slot); Assert.AreEqual(-self.x, opponent.x, 0.0001f); Assert.AreEqual(-self.z, opponent.z, 0.0001f); Assert.AreEqual(self.y, opponent.y, 0.0001f); } } [Test] public void Damage_And_Hand_Do_Not_Overlap_Field() { var config = PlaymatLayoutConfig.CreateDefault(); var layout = new PlaymatLayout(config); var damage = Enumerable.Range(0, PlaymatLayout.DamageSlots) .Select(index => layout.DamagePosition(0, index)) .ToList(); Assert.AreEqual(PlaymatLayout.DamageSlots, damage.Select(position => position.ToString()).Distinct().Count()); var hand = Enumerable.Range(0, 5) .Select(index => layout.GetHandPose(index, 5).Position) .ToList(); Assert.AreEqual(5, hand.Select(position => position.ToString()).Distinct().Count()); Assert.IsTrue(hand.All(position => position.z < -4f)); } [Test] public void Deck_Is_Closer_Than_Drop_After_Swap() { var config = PlaymatLayoutConfig.CreateDefault(); var layout = new PlaymatLayout(config); var deck = layout.DeckPosition(0); var drop = layout.DropPosition(0); Assert.Greater(deck.z, drop.z); var opponentDeck = layout.DeckPosition(1); var opponentDrop = layout.DropPosition(1); Assert.Less(opponentDeck.z, opponentDrop.z); } [Test] public void Drop_Target_Finds_Own_And_Opponent_Circles() { var config = PlaymatLayoutConfig.CreateDefault(); var layout = new PlaymatLayout(config); var nearPoint = layout.CirclePosition(0, 3); Assert.IsTrue(layout.TryFindDropTarget(nearPoint, selfPlayer: 1, out var near)); Assert.AreEqual(BoardZone.RearGuard, near.Zone); Assert.AreEqual(3, near.Slot); Assert.AreEqual(1, near.Player); var farPoint = layout.CirclePosition(1, -1); Assert.IsTrue(layout.TryFindDropTarget(farPoint, selfPlayer: 1, out var far)); Assert.AreEqual(BoardZone.Vanguard, far.Zone); Assert.AreEqual(-1, far.Slot); Assert.AreEqual(0, far.Player); } [Test] public void Drop_Target_Recognizes_Shared_Guardian_Zone() { var config = PlaymatLayoutConfig.CreateDefault(); var layout = new PlaymatLayout(config); Assert.IsTrue(layout.TryFindDropTarget( new Vector3(0f, 0f, -0.45f), selfPlayer: 0, out var target)); Assert.AreEqual(BoardZone.Guardian, target.Zone); Assert.AreEqual(0, target.Player); Assert.IsFalse(layout.TryFindDropTarget( new Vector3(0f, 0f, -7f), selfPlayer: 0, out _)); } [Test] public void Move_Is_Limited_To_Own_Column() { Assert.IsTrue(BoardPlacementRules.CanMove(0, 3)); Assert.IsTrue(BoardPlacementRules.CanMove(3, 0)); Assert.IsTrue(BoardPlacementRules.CanMove(2, 4)); Assert.IsTrue(BoardPlacementRules.CanMove(4, 2)); Assert.IsFalse(BoardPlacementRules.CanMove(1, 0)); Assert.IsFalse(BoardPlacementRules.CanMove(0, 1)); Assert.IsFalse(BoardPlacementRules.CanMove(3, 4)); Assert.IsFalse(BoardPlacementRules.CanMove(0, 0)); } [Test] public void Call_Ride_And_Guard_Follow_Classic_Circles() { Assert.IsTrue(BoardPlacementRules.CanCall(0, occupied: false)); Assert.IsTrue(BoardPlacementRules.CanCall(4, occupied: false)); Assert.IsFalse(BoardPlacementRules.CanCall(0, occupied: true)); Assert.IsFalse(BoardPlacementRules.CanCall(5, occupied: false)); Assert.IsTrue(BoardPlacementRules.CanRide(BoardZone.Vanguard, -1)); Assert.IsFalse(BoardPlacementRules.CanRide(BoardZone.RearGuard, 0)); Assert.IsTrue(BoardPlacementRules.CanGuard(BoardZone.Guardian)); Assert.IsFalse(BoardPlacementRules.CanGuard(BoardZone.Damage)); } [Test] public void Call_Ride_Enter_Stand_And_Move_Preserves_State() { Assert.AreEqual( CardState3D.FaceUpStand, BoardPlacementRules.EnterFromHand(CircleAttribute.Vanguard)); Assert.AreEqual( CardState3D.FaceUpStand, BoardPlacementRules.EnterFromHand(CircleAttribute.RearGuard)); var rested = CardState3D.FaceUpRest; Assert.AreEqual(rested, BoardPlacementRules.PreserveOnMove(rested)); Assert.IsTrue(BoardPlacementRules.PreserveOnMove(rested).Rested); Assert.IsTrue(BoardPlacementRules.PreserveOnMove(rested).FaceUp); } } }