Bundles in-flight work on the campaign/missions system (CampaignDef, MissionDef, TerrainPatch, TransformerDef, MissionChecker, CampaignLoader, FlavorBanner, transformer rules), plan files, and matching tests. Baseline commit so the upcoming automation testing harness lands on a clean tree.
219 lines
8.5 KiB
C#
219 lines
8.5 KiB
C#
using Chessistics.Engine.Commands;
|
|
using Chessistics.Engine.Events;
|
|
using Chessistics.Engine.Model;
|
|
using Chessistics.Tests.Helpers;
|
|
using Xunit;
|
|
|
|
namespace Chessistics.Tests.Simulation;
|
|
|
|
public class TransformerTests
|
|
{
|
|
/// <summary>
|
|
/// Build a campaign with a production, a transformer, and a demand:
|
|
/// Production(Wood) → [Transformer: Wood→Tools] → Demand(Tools)
|
|
/// Layout (5x1):
|
|
/// (0,0) Production(Wood,4)
|
|
/// (2,0) Transformer(Wood→Tools, input=2, output=1)
|
|
/// (4,0) Demand(Tools, 2)
|
|
/// </summary>
|
|
private static CampaignDef CreateTransformerCampaign()
|
|
{
|
|
return new CampaignDef
|
|
{
|
|
Name = "Transformer Test",
|
|
InitialWidth = 5,
|
|
InitialHeight = 1,
|
|
Missions =
|
|
[
|
|
new MissionDef
|
|
{
|
|
Id = 1,
|
|
Name = "Forge",
|
|
TerrainPatch = new TerrainPatch
|
|
{
|
|
NewWidth = 5,
|
|
NewHeight = 1,
|
|
Cells =
|
|
[
|
|
new PatchCell { Col = 0, Row = 0, Type = CellType.Production,
|
|
Production = new ProductionDef(new Coords(0, 0), "Scierie", CargoType.Wood, 4) },
|
|
new PatchCell { Col = 2, Row = 0, Type = CellType.Transformer,
|
|
Transformer = new TransformerDef(new Coords(2, 0), "Forge", CargoType.Wood, 2, CargoType.Tools, 1) },
|
|
new PatchCell { Col = 4, Row = 0, Type = CellType.Demand,
|
|
Demand = new DemandDef(new Coords(4, 0), "Armurerie", CargoType.Tools, 2) }
|
|
]
|
|
},
|
|
UnlockedPieces = [PieceKind.Rook],
|
|
UnlockedLevels = [new PieceUpgrade(PieceKind.Rook, 1)],
|
|
Stock = [new PieceStock(PieceKind.Rook, 3)]
|
|
}
|
|
]
|
|
};
|
|
}
|
|
|
|
[Fact]
|
|
public void Transformer_ReceivesInputCargo()
|
|
{
|
|
var campaign = CreateTransformerCampaign();
|
|
var sim = SimHelper.FromCampaign(campaign);
|
|
sim.Sim.ProcessCommand(new LoadCampaignCommand());
|
|
|
|
// Place rook between production and transformer: (1,0)↔(2,0)
|
|
// Rook oscillates between (1,0) and (2,0), picking up wood and delivering to transformer
|
|
sim.Place(PieceKind.Rook, (0, 0), (1, 0));
|
|
|
|
var events = sim.StepN(5);
|
|
|
|
// Should see cargo transferred to the transformer position
|
|
Assert.Contains(events, e => e is CargoTransferredEvent ct
|
|
&& ct.To == new Coords(2, 0) && ct.Type == CargoType.Wood);
|
|
}
|
|
|
|
[Fact]
|
|
public void Transformer_ConvertsAfterInputThreshold()
|
|
{
|
|
var campaign = CreateTransformerCampaign();
|
|
var sim = SimHelper.FromCampaign(campaign);
|
|
sim.Sim.ProcessCommand(new LoadCampaignCommand());
|
|
|
|
// Rook delivers wood to transformer
|
|
sim.Place(PieceKind.Rook, (0, 0), (1, 0));
|
|
|
|
var events = sim.StepN(10);
|
|
|
|
// After enough deliveries, transformation should occur
|
|
Assert.Contains(events, e => e is CargoConvertedEvent cc
|
|
&& cc.TransformerCell == new Coords(2, 0)
|
|
&& cc.InputCargo == CargoType.Wood
|
|
&& cc.OutputCargo == CargoType.Tools);
|
|
}
|
|
|
|
[Fact]
|
|
public void Transformer_OutputPickedUpByPiece()
|
|
{
|
|
var campaign = CreateTransformerCampaign();
|
|
var sim = SimHelper.FromCampaign(campaign);
|
|
sim.Sim.ProcessCommand(new LoadCampaignCommand());
|
|
|
|
// Rook 1: delivers wood to transformer
|
|
sim.Place(PieceKind.Rook, (0, 0), (1, 0));
|
|
// Rook 2: picks up tools from transformer and delivers to demand
|
|
sim.Place(PieceKind.Rook, (3, 0), (4, 0));
|
|
|
|
var events = sim.StepN(20);
|
|
|
|
// Should see tools being transferred from transformer to rook 2
|
|
Assert.Contains(events, e => e is CargoTransferredEvent ct
|
|
&& ct.From == new Coords(2, 0) && ct.Type == CargoType.Tools);
|
|
}
|
|
|
|
[Fact]
|
|
public void Transformer_FullChain_CompleteMission()
|
|
{
|
|
var campaign = CreateTransformerCampaign();
|
|
var sim = SimHelper.FromCampaign(campaign);
|
|
sim.Sim.ProcessCommand(new LoadCampaignCommand());
|
|
|
|
// Full chain: Production → Rook1 → Transformer → Rook2 → Demand
|
|
sim.Place(PieceKind.Rook, (0, 0), (1, 0)); // delivers wood to transformer
|
|
sim.Place(PieceKind.Rook, (3, 0), (4, 0)); // picks up tools, delivers to demand
|
|
|
|
var events = sim.StepN(50);
|
|
|
|
// Mission should complete (2 tools delivered)
|
|
Assert.Contains(events, e => e is MissionCompleteEvent);
|
|
}
|
|
|
|
[Fact]
|
|
public void Transformer_DoesNotConvertWrongCargo()
|
|
{
|
|
// Transformer expects Wood but receives Stone — should not convert
|
|
var campaign = new CampaignDef
|
|
{
|
|
Name = "Wrong Cargo",
|
|
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), "Carriere", CargoType.Stone, 4) },
|
|
new PatchCell { Col = 2, Row = 0, Type = CellType.Transformer,
|
|
Transformer = new TransformerDef(new Coords(2, 0), "Forge", CargoType.Wood, 1, CargoType.Tools, 1) },
|
|
new PatchCell { Col = 3, Row = 0, Type = CellType.Demand,
|
|
Demand = new DemandDef(new Coords(3, 0), "D", CargoType.Tools, 1) }
|
|
]
|
|
},
|
|
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, (0, 0), (1, 0));
|
|
|
|
var events = sim.StepN(10);
|
|
|
|
// No conversion should happen (stone != wood)
|
|
Assert.DoesNotContain(events, e => e is CargoConvertedEvent);
|
|
}
|
|
|
|
[Fact]
|
|
public void Transformer_AccumulatesInput()
|
|
{
|
|
// Transformer with inputRequired=3 should accumulate over multiple deliveries
|
|
var campaign = new CampaignDef
|
|
{
|
|
Name = "Accumulate",
|
|
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), "Scierie", CargoType.Wood, 4) },
|
|
new PatchCell { Col = 2, Row = 0, Type = CellType.Transformer,
|
|
Transformer = new TransformerDef(new Coords(2, 0), "Forge", CargoType.Wood, 3, CargoType.Tools, 2) },
|
|
new PatchCell { Col = 3, Row = 0, Type = CellType.Demand,
|
|
Demand = new DemandDef(new Coords(3, 0), "D", CargoType.Tools, 2) }
|
|
]
|
|
},
|
|
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, (0, 0), (1, 0));
|
|
sim.Place(PieceKind.Rook, (2, 0), (3, 0));
|
|
|
|
var events = sim.StepN(30);
|
|
|
|
// After 3 wood deliveries, conversion should produce 2 tools
|
|
var conversions = events.Where(e => e is CargoConvertedEvent cc && cc.OutputAmount == 2).ToList();
|
|
Assert.NotEmpty(conversions);
|
|
|
|
// Mission should complete (2 tools delivered)
|
|
Assert.Contains(events, e => e is MissionCompleteEvent);
|
|
}
|
|
}
|