Chessistics/chessistics-tests/Simulation/PhaseTests.cs

248 lines
8.9 KiB
C#
Raw Normal View History

using Chessistics.Engine.Commands;
using Chessistics.Engine.Events;
using Chessistics.Engine.Model;
using Chessistics.Tests.Helpers;
using Xunit;
namespace Chessistics.Tests.Simulation;
/// <summary>
/// Regression tests for SimPhase transitions.
/// Bug: StepSimulationCommand always set phase to Paused, even during auto-play (Running).
/// </summary>
public class PhaseTests
{
private static SimHelper CreateSimpleRunnable()
{
var campaign = new CampaignDef
{
Name = "Phase Test", InitialWidth = 4, InitialHeight = 1,
Missions =
[
new MissionDef
{
Id = 1, Name = "M1",
TerrainPatch = new TerrainPatch
{
NewWidth = 4, NewHeight = 1,
Cells =
[
new PatchCell { Col = 0, Row = 0, Type = CellType.Production,
Production = new ProductionDef(new Coords(0, 0), "P", CargoType.Wood, 4) },
new PatchCell { Col = 3, Row = 0, Type = CellType.Demand,
Demand = new DemandDef(new Coords(3, 0), "D", CargoType.Wood, 99) }
]
},
UnlockedPieces = [PieceKind.Rook],
UnlockedLevels = [new PieceUpgrade(PieceKind.Rook, 1)],
Stock = [new PieceStock(PieceKind.Rook, 2)]
}
]
};
var sim = SimHelper.FromCampaign(campaign);
sim.Sim.ProcessCommand(new LoadCampaignCommand());
sim.Place(PieceKind.Rook, (1, 0), (2, 0));
return sim;
}
[Fact]
public void ManualStep_FromPaused_RemainsInPaused()
{
var sim = CreateSimpleRunnable();
Assert.Equal(SimPhase.Paused, sim.Snapshot.Phase);
sim.Step();
Assert.Equal(SimPhase.Paused, sim.Snapshot.Phase);
}
[Fact]
public void AutoPlayStep_FromRunning_StaysRunning()
{
var sim = CreateSimpleRunnable();
// Resume → Running, then step (simulates auto-play timer)
sim.Resume();
Assert.Equal(SimPhase.Running, sim.Snapshot.Phase);
sim.Step();
// Phase should stay Running — this was the bug (used to revert to Paused)
Assert.Equal(SimPhase.Running, sim.Snapshot.Phase);
}
[Fact]
public void AutoPlayStep_MultipleSteps_StaysRunning()
{
var sim = CreateSimpleRunnable();
sim.Resume();
// Multiple consecutive steps from Running should all stay Running
for (int i = 0; i < 5; i++)
{
sim.Step();
Assert.Equal(SimPhase.Running, sim.Snapshot.Phase);
}
}
[Fact]
public void AutoPlayStep_CollisionCausesPause()
{
var campaign = new CampaignDef
{
Name = "Collision Phase Test", InitialWidth = 4, InitialHeight = 2,
Missions =
[
new MissionDef
{
Id = 1, Name = "M1",
TerrainPatch = new TerrainPatch
{
NewWidth = 4, NewHeight = 2,
Cells =
[
new PatchCell { Col = 0, Row = 0, Type = CellType.Production,
Production = new ProductionDef(new Coords(0, 0), "P", CargoType.Wood, 4) },
new PatchCell { Col = 3, Row = 0, Type = CellType.Demand,
Demand = new DemandDef(new Coords(3, 0), "D", CargoType.Wood, 99) }
]
},
UnlockedPieces = [PieceKind.Rook],
UnlockedLevels = [new PieceUpgrade(PieceKind.Rook, 1)],
Stock = [new PieceStock(PieceKind.Rook, 3)]
}
]
};
var sim = SimHelper.FromCampaign(campaign);
sim.Sim.ProcessCommand(new LoadCampaignCommand());
// Two rooks with same end cell → collision on first step
sim.Place(PieceKind.Rook, (0, 1), (1, 1));
sim.Place(PieceKind.Rook, (2, 1), (1, 1));
sim.Resume();
Assert.Equal(SimPhase.Running, sim.Snapshot.Phase);
var events = sim.Step();
// Collision should auto-pause even from Running
Assert.Contains(events, e => e is PieceReturnedToStockEvent);
Assert.Equal(SimPhase.Paused, sim.Snapshot.Phase);
}
[Fact]
public void AutoPlayStep_LastMissionComplete_SetsMissionComplete()
{
var campaign = new CampaignDef
{
Name = "Last Mission Phase Test", InitialWidth = 3, InitialHeight = 1,
Missions =
[
new MissionDef
{
Id = 1, Name = "M1",
TerrainPatch = new TerrainPatch
{
NewWidth = 3, NewHeight = 1,
Cells =
[
new PatchCell { Col = 0, Row = 0, Type = CellType.Production,
Production = new ProductionDef(new Coords(0, 0), "P", CargoType.Wood, 4) },
new PatchCell { Col = 2, Row = 0, Type = CellType.Demand,
Demand = new DemandDef(new Coords(2, 0), "D", CargoType.Wood, 1) }
]
},
UnlockedPieces = [PieceKind.Rook],
UnlockedLevels = [new PieceUpgrade(PieceKind.Rook, 1)],
Stock = [new PieceStock(PieceKind.Rook, 1)]
}
]
};
var sim = SimHelper.FromCampaign(campaign);
sim.Sim.ProcessCommand(new LoadCampaignCommand());
sim.Place(PieceKind.Rook, (1, 0), (2, 0));
// Running auto-play → last mission completes → MissionComplete phase
sim.Resume();
Assert.Equal(SimPhase.Running, sim.Snapshot.Phase);
// Step until mission complete
for (int i = 0; i < 20; i++)
{
sim.Step();
if (sim.Snapshot.Phase == SimPhase.MissionComplete)
break;
}
Assert.Equal(SimPhase.MissionComplete, sim.Snapshot.Phase);
}
[Fact]
public void AutoPlayStep_NonLastMissionComplete_AutoAdvances_StaysRunning()
{
var campaign = new CampaignDef
{
Name = "Auto-Advance Phase Test", InitialWidth = 3, InitialHeight = 1,
Missions =
[
new MissionDef
{
Id = 1, Name = "M1",
TerrainPatch = new TerrainPatch
{
NewWidth = 3, NewHeight = 1,
Cells =
[
new PatchCell { Col = 0, Row = 0, Type = CellType.Production,
Production = new ProductionDef(new Coords(0, 0), "P", CargoType.Wood, 4) },
new PatchCell { Col = 2, Row = 0, Type = CellType.Demand,
Demand = new DemandDef(new Coords(2, 0), "D", CargoType.Wood, 1) }
]
},
UnlockedPieces = [PieceKind.Rook],
UnlockedLevels = [new PieceUpgrade(PieceKind.Rook, 1)],
Stock = [new PieceStock(PieceKind.Rook, 2)]
},
new MissionDef
{
Id = 2, Name = "M2",
TerrainPatch = new TerrainPatch
{
NewWidth = 5, NewHeight = 1,
Cells =
[
new PatchCell { Col = 4, Row = 0, Type = CellType.Demand,
Demand = new DemandDef(new Coords(4, 0), "D2", CargoType.Wood, 99) }
]
},
UnlockedPieces = [],
UnlockedLevels = [],
Stock = [new PieceStock(PieceKind.Rook, 1)]
}
]
};
var sim = SimHelper.FromCampaign(campaign);
sim.Sim.ProcessCommand(new LoadCampaignCommand());
sim.Place(PieceKind.Rook, (1, 0), (2, 0));
sim.Resume();
// Step until mission 1 completes and auto-advances
bool advanced = false;
for (int i = 0; i < 20; i++)
{
var events = sim.Step();
if (events.Any(e => e is MissionStartedEvent ms && ms.MissionIndex == 1))
{
advanced = true;
// Phase should still be Running after auto-advance
Assert.Equal(SimPhase.Running, sim.Snapshot.Phase);
break;
}
}
Assert.True(advanced, "Mission 1 should have auto-advanced to Mission 2");
Assert.Equal(1, sim.Snapshot.Campaign!.CurrentMissionIndex);
}
}