248 lines
8.9 KiB
C#
248 lines
8.9 KiB
C#
|
|
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);
|
||
|
|
}
|
||
|
|
}
|