2026-04-10 14:58:03 +02:00
|
|
|
using Chessistics.Engine.Events;
|
|
|
|
|
using Chessistics.Engine.Model;
|
|
|
|
|
using Chessistics.Tests.Helpers;
|
|
|
|
|
using Xunit;
|
|
|
|
|
|
|
|
|
|
namespace Chessistics.Tests.Simulation;
|
|
|
|
|
|
|
|
|
|
public class FullLevelTests
|
|
|
|
|
{
|
|
|
|
|
[Fact]
|
2026-04-10 15:25:25 +02:00
|
|
|
public void Level1_PremierConvoi_Victory()
|
2026-04-10 14:58:03 +02:00
|
|
|
{
|
2026-04-10 15:25:25 +02:00
|
|
|
// GDD Level 1: 4x4, Scierie(0,0) → Depot(3,0), 3 Rooks
|
|
|
|
|
// Solution: single rook relay at (1,0)↔(2,0)
|
2026-04-10 14:58:03 +02:00
|
|
|
var level = new BoardBuilder(4, 4)
|
2026-04-10 21:44:12 +02:00
|
|
|
.WithProduction(0, 0, "Scierie", CargoType.Wood)
|
2026-04-10 14:58:03 +02:00
|
|
|
.WithDemand(3, 0, "Depot Royal", CargoType.Wood, 3, 30)
|
|
|
|
|
.WithStock(PieceKind.Rook, 3)
|
|
|
|
|
.Build();
|
|
|
|
|
var sim = SimHelper.FromLevel(level);
|
|
|
|
|
|
|
|
|
|
sim.Place(PieceKind.Rook, (1, 0), (2, 0));
|
|
|
|
|
sim.Start();
|
|
|
|
|
|
|
|
|
|
var allEvents = sim.StepN(30);
|
|
|
|
|
Assert.Contains(allEvents, e => e is VictoryEvent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
2026-04-10 15:25:25 +02:00
|
|
|
public void Level2_DeuxClients_Victory()
|
2026-04-10 14:58:03 +02:00
|
|
|
{
|
2026-04-10 15:25:25 +02:00
|
|
|
// GDD Level 2: 6x6, Scierie(0,0), Depot Royal(5,0), Caserne(5,4)
|
|
|
|
|
// Stock: 6 Rooks + 1 Bishop (fixed from GDD's 4R+1B — insufficient)
|
|
|
|
|
//
|
|
|
|
|
// Solution requires two routes from single source:
|
|
|
|
|
// Route 1 → (5,0): A(1,0↔2,0), B(2,0↔4,0)
|
|
|
|
|
// Route 2 → (5,4): C(0,1↔0,2), D(0,2↔2,2), E(2,2↔3,2),
|
|
|
|
|
// Bishop(3,2↔4,3), G(4,3↔5,3)
|
|
|
|
|
// Total needed: 6 Rooks + 1 Bishop
|
2026-04-10 14:58:03 +02:00
|
|
|
var level = new BoardBuilder(6, 6)
|
2026-04-10 21:44:12 +02:00
|
|
|
.WithProduction(0, 0, "Scierie", CargoType.Wood)
|
2026-04-10 15:25:25 +02:00
|
|
|
.WithDemand(5, 0, "Depot Royal", CargoType.Wood, 2, 50)
|
|
|
|
|
.WithDemand(5, 4, "Caserne", CargoType.Wood, 2, 50)
|
|
|
|
|
.WithStock(PieceKind.Rook, 6)
|
2026-04-10 14:58:03 +02:00
|
|
|
.WithStock(PieceKind.Bishop, 1)
|
|
|
|
|
.Build();
|
|
|
|
|
var sim = SimHelper.FromLevel(level);
|
|
|
|
|
|
2026-04-10 15:25:25 +02:00
|
|
|
// Route 1: bottom row → demand (5,0)
|
|
|
|
|
sim.Place(PieceKind.Rook, (1, 0), (2, 0));
|
|
|
|
|
sim.Place(PieceKind.Rook, (2, 0), (4, 0));
|
|
|
|
|
|
|
|
|
|
// Route 2: up then right → demand (5,4)
|
2026-04-10 14:58:03 +02:00
|
|
|
sim.Place(PieceKind.Rook, (0, 1), (0, 2));
|
2026-04-10 15:25:25 +02:00
|
|
|
sim.Place(PieceKind.Rook, (0, 2), (2, 2));
|
|
|
|
|
// 5th rook — stock exhausted at 4!
|
|
|
|
|
var events5 = sim.Place(PieceKind.Rook, (2, 2), (3, 2));
|
|
|
|
|
Assert.DoesNotContain(events5, e => e is PlacementRejectedEvent);
|
2026-04-10 14:58:03 +02:00
|
|
|
|
2026-04-10 15:25:25 +02:00
|
|
|
sim.Place(PieceKind.Bishop, (3, 2), (4, 3));
|
|
|
|
|
|
|
|
|
|
// 6th rook needed but only 4 in stock
|
|
|
|
|
var events6 = sim.Place(PieceKind.Rook, (4, 3), (5, 3));
|
|
|
|
|
Assert.DoesNotContain(events6, e => e is PlacementRejectedEvent);
|
2026-04-10 14:58:03 +02:00
|
|
|
|
2026-04-10 15:25:25 +02:00
|
|
|
sim.Start();
|
|
|
|
|
var allEvents = sim.StepN(60);
|
|
|
|
|
Assert.Contains(allEvents, e => e is VictoryEvent);
|
2026-04-10 14:58:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
2026-04-10 15:25:25 +02:00
|
|
|
public void Level3_LeCol_Victory()
|
2026-04-10 14:58:03 +02:00
|
|
|
{
|
2026-04-10 15:35:37 +02:00
|
|
|
// GDD Level 3: 6x6, L-shaped wall, 2 cargo types, knights jump obstacle
|
|
|
|
|
// Stock: 8 Rooks + 2 Knights (fixed from GDD's 4R+1B+2K)
|
2026-04-10 15:25:25 +02:00
|
|
|
//
|
2026-04-10 15:35:37 +02:00
|
|
|
// CargoFilter (Phase 2) prevents cross-route contamination:
|
|
|
|
|
// pieces auto-inherit their production's cargo type via relay chain.
|
2026-04-10 15:25:25 +02:00
|
|
|
//
|
2026-04-10 15:35:37 +02:00
|
|
|
// Route Wood (0,0→5,5): R1(0,1↔1,1), K1(1,1↔3,2),
|
|
|
|
|
// R2(3,2↔4,2), R3(4,2↔5,2), R4(5,2↔5,3), R5(5,3↔5,4)
|
|
|
|
|
// Route Stone (5,0→0,5): S1(4,0↔3,0), S2(3,0↔2,0),
|
|
|
|
|
// K2(2,0↔1,2), S3(1,2↔1,3), S4(1,3↔1,4), S5(1,4↔0,4)
|
|
|
|
|
// Total: 10 Rooks + 2 Knights
|
2026-04-10 14:58:03 +02:00
|
|
|
var level = new BoardBuilder(6, 6)
|
2026-04-10 21:44:12 +02:00
|
|
|
.WithProduction(0, 0, "Scierie", CargoType.Wood)
|
|
|
|
|
.WithProduction(5, 0, "Carriere", CargoType.Stone)
|
2026-04-10 15:35:37 +02:00
|
|
|
.WithDemand(5, 5, "Depot Royal", CargoType.Wood, 2, 60)
|
|
|
|
|
.WithDemand(0, 5, "Forge", CargoType.Stone, 2, 60)
|
2026-04-10 14:58:03 +02:00
|
|
|
.WithWall(2, 2).WithWall(2, 3).WithWall(2, 4).WithWall(3, 4).WithWall(4, 4)
|
2026-04-10 15:35:37 +02:00
|
|
|
.WithStock(PieceKind.Rook, 10)
|
|
|
|
|
.WithStock(PieceKind.Knight, 2)
|
2026-04-10 14:58:03 +02:00
|
|
|
.Build();
|
|
|
|
|
var sim = SimHelper.FromLevel(level);
|
|
|
|
|
|
2026-04-10 15:35:37 +02:00
|
|
|
// Route Wood: prod(0,0) → demand(5,5)
|
2026-04-10 15:25:25 +02:00
|
|
|
sim.Place(PieceKind.Rook, (0, 1), (1, 1));
|
|
|
|
|
sim.Place(PieceKind.Knight, (1, 1), (3, 2));
|
|
|
|
|
sim.Place(PieceKind.Rook, (3, 2), (4, 2));
|
|
|
|
|
sim.Place(PieceKind.Rook, (4, 2), (5, 2));
|
|
|
|
|
sim.Place(PieceKind.Rook, (5, 2), (5, 3));
|
|
|
|
|
sim.Place(PieceKind.Rook, (5, 3), (5, 4));
|
2026-04-10 14:58:03 +02:00
|
|
|
|
2026-04-10 15:35:37 +02:00
|
|
|
// Route Stone: prod(5,0) → demand(0,5)
|
|
|
|
|
sim.Place(PieceKind.Rook, (4, 0), (3, 0));
|
|
|
|
|
sim.Place(PieceKind.Rook, (3, 0), (2, 0));
|
|
|
|
|
sim.Place(PieceKind.Knight, (2, 0), (1, 2));
|
|
|
|
|
sim.Place(PieceKind.Rook, (1, 2), (1, 3));
|
|
|
|
|
sim.Place(PieceKind.Rook, (1, 3), (1, 4));
|
|
|
|
|
sim.Place(PieceKind.Rook, (1, 4), (0, 4));
|
|
|
|
|
|
2026-04-10 14:58:03 +02:00
|
|
|
sim.Start();
|
2026-04-10 15:35:37 +02:00
|
|
|
var allEvents = sim.StepN(80);
|
2026-04-10 15:25:25 +02:00
|
|
|
Assert.Contains(allEvents, e => e is VictoryEvent);
|
2026-04-10 14:58:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Level1_InsufficientPieces_NoVictory()
|
|
|
|
|
{
|
|
|
|
|
var level = new BoardBuilder(4, 4)
|
2026-04-10 21:44:12 +02:00
|
|
|
.WithProduction(0, 0, "Scierie", CargoType.Wood)
|
2026-04-10 15:25:25 +02:00
|
|
|
.WithDemand(3, 3, "Depot Royal", CargoType.Wood, 3, 5)
|
|
|
|
|
.WithStock(PieceKind.Rook, 1)
|
2026-04-10 14:58:03 +02:00
|
|
|
.Build();
|
|
|
|
|
var sim = SimHelper.FromLevel(level);
|
|
|
|
|
|
|
|
|
|
sim.Place(PieceKind.Rook, (1, 1), (2, 1));
|
|
|
|
|
sim.Start();
|
|
|
|
|
|
|
|
|
|
var allEvents = sim.StepN(8);
|
|
|
|
|
|
|
|
|
|
Assert.DoesNotContain(allEvents, e => e is VictoryEvent);
|
|
|
|
|
Assert.Contains(allEvents, e => e is DeadlineExpiredEvent);
|
|
|
|
|
}
|
|
|
|
|
}
|