using Chessistics.Engine.Commands; using Chessistics.Engine.Events; using Chessistics.Engine.Model; using Chessistics.Tests.Helpers; using Xunit; namespace Chessistics.Tests.Simulation; public class GameSimTests { private SimHelper CreateLevel1Sim() { var level = new BoardBuilder(4, 4) .WithProduction(0, 0, "Scierie", CargoType.Wood) .WithDemand(3, 0, "Depot Royal", CargoType.Wood, 3, 30) .WithStock(PieceKind.Rook, 3) .Build(); return SimHelper.FromLevel(level); } [Fact] public void PlacePiece_Succeeds() { var sim = CreateLevel1Sim(); var events = sim.Place(PieceKind.Rook, (0, 0), (1, 0)); Assert.Single(events); Assert.IsType(events[0]); var placed = (PiecePlacedEvent)events[0]; Assert.Equal(PieceKind.Rook, placed.Kind); } [Fact] public void PlacePiece_StockExhausted_Rejected() { var sim = CreateLevel1Sim(); sim.Place(PieceKind.Rook, (0, 0), (1, 0)); sim.Place(PieceKind.Rook, (0, 1), (1, 1)); sim.Place(PieceKind.Rook, (0, 2), (1, 2)); // 4th rook — only 3 in stock var events = sim.Place(PieceKind.Rook, (0, 3), (1, 3)); Assert.IsType(events[0]); } [Fact] public void PlaceDuringRunning_Succeeds() { // In the new system, placement works in any phase var sim = CreateLevel1Sim(); sim.Place(PieceKind.Rook, (0, 0), (1, 0)); sim.Resume(); // Paused → Running var events = sim.Place(PieceKind.Rook, (0, 1), (1, 1)); Assert.IsType(events[0]); } [Fact] public void RemoveDuringRunning_Succeeds() { // In the new system, removal works in any phase var sim = CreateLevel1Sim(); sim.Place(PieceKind.Rook, (0, 0), (1, 0)); sim.Resume(); // Paused → Running var events = sim.Remove(1); Assert.IsType(events[0]); } [Fact] public void SinglePiece_Oscillates() { var sim = CreateLevel1Sim(); sim.Place(PieceKind.Rook, (0, 0), (2, 0)); // Step 1: piece moves from (0,0) to (2,0) var events1 = sim.Step(); Assert.Contains(events1, e => e is PieceMovedEvent m && m.From == new Coords(0, 0) && m.To == new Coords(2, 0)); // Step 2: piece moves back from (2,0) to (0,0) var events2 = sim.Step(); Assert.Contains(events2, e => e is PieceMovedEvent m && m.From == new Coords(2, 0) && m.To == new Coords(0, 0)); // Step 3: piece moves forward again var events3 = sim.Step(); Assert.Contains(events3, e => e is PieceMovedEvent m && m.From == new Coords(0, 0) && m.To == new Coords(2, 0)); } [Fact] public void ChainedPieces_TransferCargo() { var sim = CreateLevel1Sim(); sim.Place(PieceKind.Rook, (0, 0), (1, 0)); sim.Place(PieceKind.Rook, (2, 0), (3, 0)); var allEvents = sim.StepN(20); Assert.Contains(allEvents, e => e is CargoProducedEvent); Assert.Contains(allEvents, e => e is CargoTransferredEvent); } [Fact] public void Production_GeneratesEveryTurn() { var sim = CreateLevel1Sim(); sim.Place(PieceKind.Rook, (0, 0), (1, 0)); var allEvents = sim.StepN(6); var prodEvents = allEvents.OfType().ToList(); Assert.Equal(6, prodEvents.Count); } [Fact] public void MissionComplete_WhenAllDemandsMet() { var level = new BoardBuilder(3, 1) .WithProduction(0, 0, "P", CargoType.Wood) .WithDemand(2, 0, "D", CargoType.Wood, 1, 30) .WithStock(PieceKind.Rook, 2) .Build(); var sim = SimHelper.FromLevel(level); sim.Place(PieceKind.Rook, (1, 0), (2, 0)); var allEvents = sim.StepN(10); Assert.Contains(allEvents, e => e is MissionCompleteEvent); } [Fact] public void InitialPhase_IsPaused() { var sim = CreateLevel1Sim(); var snap = sim.Snapshot; Assert.Equal(SimPhase.Paused, snap.Phase); } [Fact] public void StepFromPaused_Works() { var sim = CreateLevel1Sim(); sim.Place(PieceKind.Rook, (1, 0), (2, 0)); // Step directly from Paused var events = sim.Step(); Assert.Contains(events, e => e is TurnStartedEvent); } }