2026-04-10 14:58:03 +02:00
|
|
|
using Chessistics.Engine.Events;
|
|
|
|
|
using Chessistics.Engine.Model;
|
|
|
|
|
using Chessistics.Engine.Rules;
|
|
|
|
|
using Chessistics.Tests.Helpers;
|
|
|
|
|
using Xunit;
|
|
|
|
|
|
|
|
|
|
namespace Chessistics.Tests.Rules;
|
|
|
|
|
|
|
|
|
|
public class TransferResolverTests
|
|
|
|
|
{
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Production_GivesToAdjacentEmptyPiece()
|
|
|
|
|
{
|
|
|
|
|
var board = new BoardBuilder(4, 4)
|
2026-04-10 21:44:12 +02:00
|
|
|
.WithProduction(0, 0, "P", CargoType.Wood)
|
2026-04-10 14:58:03 +02:00
|
|
|
.WithDemand(3, 0, "D", CargoType.Wood, 1, 99)
|
|
|
|
|
.WithStock(PieceKind.Rook, 3)
|
|
|
|
|
.BuildState();
|
|
|
|
|
|
|
|
|
|
// Place a piece at (1,0) — adjacent to production at (0,0)
|
|
|
|
|
var piece = new PieceState(1, PieceKind.Rook, new Coords(1, 0), new Coords(2, 0), 0);
|
|
|
|
|
piece.CurrentCell = new Coords(1, 0);
|
|
|
|
|
board.Pieces.Add(piece);
|
|
|
|
|
|
|
|
|
|
// Fill production buffer
|
2026-04-10 21:44:12 +02:00
|
|
|
board.ProductionBuffers[new Coords(0, 0)] = 1;
|
2026-04-10 14:58:03 +02:00
|
|
|
|
|
|
|
|
var events = TransferResolver.ResolveTransfers(board);
|
|
|
|
|
|
|
|
|
|
Assert.Contains(events, e => e is CargoTransferredEvent ct
|
|
|
|
|
&& ct.From == new Coords(0, 0)
|
|
|
|
|
&& ct.To == new Coords(1, 0)
|
|
|
|
|
&& ct.Type == CargoType.Wood);
|
|
|
|
|
|
|
|
|
|
Assert.Equal(CargoType.Wood, piece.Cargo);
|
2026-04-10 21:44:12 +02:00
|
|
|
Assert.Equal(0, board.ProductionBuffers[new Coords(0, 0)]);
|
2026-04-10 14:58:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Production_DoesNotGiveToPieceWithCargo()
|
|
|
|
|
{
|
|
|
|
|
var board = new BoardBuilder(4, 4)
|
2026-04-10 21:44:12 +02:00
|
|
|
.WithProduction(0, 0, "P", CargoType.Wood)
|
2026-04-10 14:58:03 +02:00
|
|
|
.WithDemand(3, 0, "D", CargoType.Wood, 1, 99)
|
|
|
|
|
.WithStock(PieceKind.Rook, 3)
|
|
|
|
|
.BuildState();
|
|
|
|
|
|
|
|
|
|
var piece = new PieceState(1, PieceKind.Rook, new Coords(1, 0), new Coords(2, 0), 0);
|
|
|
|
|
piece.CurrentCell = new Coords(1, 0);
|
|
|
|
|
piece.Cargo = CargoType.Wood; // already carrying
|
|
|
|
|
board.Pieces.Add(piece);
|
2026-04-10 21:44:12 +02:00
|
|
|
board.ProductionBuffers[new Coords(0, 0)] = 1;
|
2026-04-10 14:58:03 +02:00
|
|
|
|
|
|
|
|
var events = TransferResolver.ResolveTransfers(board);
|
|
|
|
|
|
|
|
|
|
// No transfer from production — piece already has cargo
|
|
|
|
|
Assert.DoesNotContain(events, e => e is CargoTransferredEvent ct && ct.From == new Coords(0, 0));
|
2026-04-10 21:44:12 +02:00
|
|
|
Assert.Equal(1, board.ProductionBuffers[new Coords(0, 0)]);
|
2026-04-10 14:58:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Piece_TransfersToAdjacentEmptyPiece()
|
|
|
|
|
{
|
|
|
|
|
var board = new BoardBuilder(4, 4)
|
2026-04-10 21:44:12 +02:00
|
|
|
.WithProduction(0, 0, "P", CargoType.Wood)
|
2026-04-10 14:58:03 +02:00
|
|
|
.WithDemand(3, 0, "D", CargoType.Wood, 1, 99)
|
|
|
|
|
.WithStock(PieceKind.Rook, 3)
|
|
|
|
|
.BuildState();
|
|
|
|
|
|
|
|
|
|
var giver = new PieceState(1, PieceKind.Rook, new Coords(1, 0), new Coords(2, 0), 0);
|
|
|
|
|
giver.CurrentCell = new Coords(1, 0);
|
|
|
|
|
giver.Cargo = CargoType.Wood;
|
|
|
|
|
|
|
|
|
|
var receiver = new PieceState(2, PieceKind.Rook, new Coords(2, 0), new Coords(3, 0), 1);
|
|
|
|
|
receiver.CurrentCell = new Coords(2, 0);
|
|
|
|
|
|
|
|
|
|
board.Pieces.AddRange([giver, receiver]);
|
|
|
|
|
|
|
|
|
|
var events = TransferResolver.ResolveTransfers(board);
|
|
|
|
|
|
|
|
|
|
Assert.Contains(events, e => e is CargoTransferredEvent ct
|
|
|
|
|
&& ct.GivingPieceId == 1 && ct.ReceivingPieceId == 2);
|
|
|
|
|
Assert.Null(giver.Cargo);
|
|
|
|
|
Assert.Equal(CargoType.Wood, receiver.Cargo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Piece_DeliversToDemand()
|
|
|
|
|
{
|
|
|
|
|
var board = new BoardBuilder(4, 4)
|
2026-04-10 21:44:12 +02:00
|
|
|
.WithProduction(0, 0, "P", CargoType.Wood)
|
2026-04-10 14:58:03 +02:00
|
|
|
.WithDemand(3, 0, "D", CargoType.Wood, 3, 99)
|
|
|
|
|
.WithStock(PieceKind.Rook, 3)
|
|
|
|
|
.BuildState();
|
|
|
|
|
|
|
|
|
|
var piece = new PieceState(1, PieceKind.Rook, new Coords(2, 0), new Coords(3, 0), 0);
|
|
|
|
|
piece.CurrentCell = new Coords(2, 0); // adjacent to demand at (3,0)
|
|
|
|
|
piece.Cargo = CargoType.Wood;
|
|
|
|
|
board.Pieces.Add(piece);
|
|
|
|
|
|
|
|
|
|
var events = TransferResolver.ResolveTransfers(board);
|
|
|
|
|
|
|
|
|
|
Assert.Contains(events, e => e is CargoTransferredEvent ct
|
|
|
|
|
&& ct.To == new Coords(3, 0) && ct.GivingPieceId == 1);
|
|
|
|
|
Assert.Contains(events, e => e is DemandProgressEvent dp
|
|
|
|
|
&& dp.Current == 1 && dp.Required == 3);
|
|
|
|
|
Assert.Null(piece.Cargo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Piece_DoesNotDeliverWrongType()
|
|
|
|
|
{
|
|
|
|
|
var board = new BoardBuilder(4, 4)
|
2026-04-10 21:44:12 +02:00
|
|
|
.WithProduction(0, 0, "P", CargoType.Wood)
|
2026-04-10 14:58:03 +02:00
|
|
|
.WithDemand(3, 0, "D", CargoType.Wood, 3, 99) // wants Wood
|
|
|
|
|
.WithStock(PieceKind.Rook, 3)
|
|
|
|
|
.BuildState();
|
|
|
|
|
|
|
|
|
|
var piece = new PieceState(1, PieceKind.Rook, new Coords(2, 0), new Coords(3, 0), 0);
|
|
|
|
|
piece.CurrentCell = new Coords(2, 0);
|
|
|
|
|
piece.Cargo = CargoType.Stone; // carrying Stone, demand wants Wood
|
|
|
|
|
board.Pieces.Add(piece);
|
|
|
|
|
|
|
|
|
|
var events = TransferResolver.ResolveTransfers(board);
|
|
|
|
|
|
|
|
|
|
Assert.DoesNotContain(events, e => e is CargoTransferredEvent ct && ct.To == new Coords(3, 0));
|
|
|
|
|
Assert.Equal(CargoType.Stone, piece.Cargo); // still holding
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void HigherStatus_ReceivesFirst()
|
|
|
|
|
{
|
|
|
|
|
var board = new BoardBuilder(4, 4)
|
2026-04-10 21:44:12 +02:00
|
|
|
.WithProduction(0, 0, "P", CargoType.Wood)
|
2026-04-10 14:58:03 +02:00
|
|
|
.WithDemand(3, 0, "D", CargoType.Wood, 1, 99)
|
|
|
|
|
.WithStock(PieceKind.Rook, 3)
|
|
|
|
|
.WithStock(PieceKind.Knight, 3)
|
|
|
|
|
.BuildState();
|
|
|
|
|
|
|
|
|
|
// Giver piece at (1,0) with cargo
|
|
|
|
|
var giver = new PieceState(1, PieceKind.Rook, new Coords(1, 0), new Coords(2, 0), 0);
|
|
|
|
|
giver.CurrentCell = new Coords(1, 0);
|
|
|
|
|
giver.Cargo = CargoType.Wood;
|
|
|
|
|
|
|
|
|
|
// Two receivers: Rook (status 5) and Knight (status 3) both adjacent
|
|
|
|
|
var rookReceiver = new PieceState(2, PieceKind.Rook, new Coords(1, 1), new Coords(2, 1), 1);
|
|
|
|
|
rookReceiver.CurrentCell = new Coords(1, 1); // adjacent to (1,0)
|
|
|
|
|
|
|
|
|
|
var knightReceiver = new PieceState(3, PieceKind.Knight, new Coords(2, 0), new Coords(0, 1), 2);
|
|
|
|
|
knightReceiver.CurrentCell = new Coords(2, 0); // adjacent to (1,0)
|
|
|
|
|
|
|
|
|
|
board.Pieces.AddRange([giver, rookReceiver, knightReceiver]);
|
|
|
|
|
|
|
|
|
|
var events = TransferResolver.ResolveTransfers(board);
|
|
|
|
|
|
|
|
|
|
// Rook (status 5) should receive before Knight (status 3)
|
|
|
|
|
var transfer = events.OfType<CargoTransferredEvent>().First(e => e.GivingPieceId == 1);
|
|
|
|
|
Assert.Equal(2, transfer.ReceivingPieceId); // rook receives
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void HigherStatus_GivesFirst()
|
|
|
|
|
{
|
|
|
|
|
var board = new BoardBuilder(4, 4)
|
2026-04-10 21:44:12 +02:00
|
|
|
.WithProduction(0, 0, "P", CargoType.Wood)
|
2026-04-10 14:58:03 +02:00
|
|
|
.WithDemand(3, 0, "D", CargoType.Wood, 1, 99)
|
|
|
|
|
.WithStock(PieceKind.Rook, 3)
|
|
|
|
|
.WithStock(PieceKind.Knight, 3)
|
|
|
|
|
.BuildState();
|
|
|
|
|
|
|
|
|
|
// Two givers: Rook (5) at (1,0) and Knight (3) at (1,1), both with cargo
|
|
|
|
|
var rook = new PieceState(1, PieceKind.Rook, new Coords(1, 0), new Coords(2, 0), 0);
|
|
|
|
|
rook.CurrentCell = new Coords(1, 0);
|
|
|
|
|
rook.Cargo = CargoType.Wood;
|
|
|
|
|
|
|
|
|
|
var knight = new PieceState(2, PieceKind.Knight, new Coords(1, 1), new Coords(3, 2), 1);
|
|
|
|
|
knight.CurrentCell = new Coords(1, 1);
|
|
|
|
|
knight.Cargo = CargoType.Wood;
|
|
|
|
|
|
|
|
|
|
// One receiver adjacent to both: at (2,0) — adjacent to rook at (1,0) but not to knight at (1,1)
|
|
|
|
|
// Let's make receiver at (1,2) — adjacent to knight (1,1) only
|
|
|
|
|
// Actually: receiver at (2,1) — adjacent to nothing. Let me think...
|
|
|
|
|
// Receiver needs to be adjacent to both. (1,0) and (1,1) share neighbor (2,0)? No, (2,0) is adjacent to (1,0) only.
|
|
|
|
|
// Shared neighbor: none directly... Let's change: both givers adjacent to same receiver
|
|
|
|
|
// Put receiver at (0, 0) — but that's production. Put receiver at (0, 1):
|
|
|
|
|
// (0,1) is adjacent to (1,1) [knight] and (0,0) [production], not to (1,0) [rook]
|
|
|
|
|
// Let's use a simpler setup:
|
|
|
|
|
|
|
|
|
|
// Rook with cargo at (2,0), Knight with cargo at (2,2), receiver at (2,1) — adjacent to both
|
|
|
|
|
rook.CurrentCell = new Coords(2, 0);
|
|
|
|
|
knight.CurrentCell = new Coords(2, 2);
|
|
|
|
|
|
|
|
|
|
var receiver = new PieceState(3, PieceKind.Rook, new Coords(2, 1), new Coords(3, 1), 2);
|
|
|
|
|
receiver.CurrentCell = new Coords(2, 1);
|
|
|
|
|
|
|
|
|
|
board.Pieces.AddRange([rook, knight, receiver]);
|
|
|
|
|
|
|
|
|
|
var events = TransferResolver.ResolveTransfers(board);
|
|
|
|
|
|
|
|
|
|
// Rook (status 5) should give first to the receiver
|
|
|
|
|
var transfer = events.OfType<CargoTransferredEvent>().First();
|
|
|
|
|
Assert.Equal(1, transfer.GivingPieceId); // rook gives first
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
2026-04-10 21:44:12 +02:00
|
|
|
public void TieBreaker_ClockwiseDirection_EvenTurn()
|
2026-04-10 14:58:03 +02:00
|
|
|
{
|
|
|
|
|
var board = new BoardBuilder(4, 4)
|
2026-04-10 21:44:12 +02:00
|
|
|
.WithProduction(0, 0, "P", CargoType.Wood)
|
2026-04-10 14:58:03 +02:00
|
|
|
.WithDemand(3, 0, "D", CargoType.Wood, 1, 99)
|
|
|
|
|
.WithStock(PieceKind.Knight, 5)
|
|
|
|
|
.BuildState();
|
|
|
|
|
|
2026-04-10 21:44:12 +02:00
|
|
|
// Giver at (1,1) with cargo, two receivers: right(2,1) and up(1,2)
|
|
|
|
|
// On even turn (TurnNumber=0), clockwise from right: right=0 < up=1
|
|
|
|
|
var giver = new PieceState(1, PieceKind.Rook, new Coords(1, 1), new Coords(2, 1), 0);
|
|
|
|
|
giver.CurrentCell = new Coords(1, 1);
|
|
|
|
|
giver.Cargo = CargoType.Wood;
|
|
|
|
|
|
|
|
|
|
var receiverRight = new PieceState(2, PieceKind.Rook, new Coords(2, 1), new Coords(3, 1), 1);
|
|
|
|
|
receiverRight.CurrentCell = new Coords(2, 1); // right of giver
|
|
|
|
|
|
|
|
|
|
var receiverUp = new PieceState(3, PieceKind.Rook, new Coords(1, 2), new Coords(1, 3), 2);
|
|
|
|
|
receiverUp.CurrentCell = new Coords(1, 2); // up of giver
|
|
|
|
|
|
|
|
|
|
board.Pieces.AddRange([giver, receiverRight, receiverUp]);
|
|
|
|
|
board.TurnNumber = 2; // even turn
|
|
|
|
|
|
|
|
|
|
var events = TransferResolver.ResolveTransfers(board);
|
|
|
|
|
var transfer = events.OfType<CargoTransferredEvent>().First();
|
|
|
|
|
|
|
|
|
|
// On even turn, right(0) has priority over up(1)
|
|
|
|
|
Assert.Equal(2, transfer.ReceivingPieceId); // receiverRight
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void TieBreaker_ClockwiseDirection_OddTurn()
|
|
|
|
|
{
|
|
|
|
|
var board = new BoardBuilder(4, 4)
|
|
|
|
|
.WithProduction(0, 0, "P", CargoType.Wood)
|
|
|
|
|
.WithDemand(3, 0, "D", CargoType.Wood, 1, 99)
|
|
|
|
|
.WithStock(PieceKind.Knight, 5)
|
|
|
|
|
.BuildState();
|
|
|
|
|
|
|
|
|
|
// Same setup but on odd turn: left=0 < down=1 < right=2 < up=3
|
|
|
|
|
var giver = new PieceState(1, PieceKind.Rook, new Coords(1, 1), new Coords(2, 1), 0);
|
|
|
|
|
giver.CurrentCell = new Coords(1, 1);
|
|
|
|
|
giver.Cargo = CargoType.Wood;
|
2026-04-10 14:58:03 +02:00
|
|
|
|
2026-04-10 21:44:12 +02:00
|
|
|
var receiverRight = new PieceState(2, PieceKind.Rook, new Coords(2, 1), new Coords(3, 1), 1);
|
|
|
|
|
receiverRight.CurrentCell = new Coords(2, 1); // right of giver
|
2026-04-10 14:58:03 +02:00
|
|
|
|
2026-04-10 21:44:12 +02:00
|
|
|
var receiverLeft = new PieceState(3, PieceKind.Rook, new Coords(0, 1), new Coords(0, 2), 2);
|
|
|
|
|
receiverLeft.CurrentCell = new Coords(0, 1); // left of giver
|
2026-04-10 14:58:03 +02:00
|
|
|
|
2026-04-10 21:44:12 +02:00
|
|
|
board.Pieces.AddRange([giver, receiverRight, receiverLeft]);
|
|
|
|
|
board.TurnNumber = 1; // odd turn
|
2026-04-10 14:58:03 +02:00
|
|
|
|
|
|
|
|
var events = TransferResolver.ResolveTransfers(board);
|
|
|
|
|
var transfer = events.OfType<CargoTransferredEvent>().First();
|
|
|
|
|
|
2026-04-10 21:44:12 +02:00
|
|
|
// On odd turn, left(0) has priority over right(2)
|
|
|
|
|
Assert.Equal(3, transfer.ReceivingPieceId); // receiverLeft
|
2026-04-10 14:58:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Cargo_MovesOneHopPerTurn()
|
|
|
|
|
{
|
|
|
|
|
var board = new BoardBuilder(5, 4)
|
2026-04-10 21:44:12 +02:00
|
|
|
.WithProduction(0, 0, "P", CargoType.Wood)
|
2026-04-10 14:58:03 +02:00
|
|
|
.WithDemand(4, 0, "D", CargoType.Wood, 1, 99)
|
|
|
|
|
.WithStock(PieceKind.Rook, 5)
|
|
|
|
|
.BuildState();
|
|
|
|
|
|
|
|
|
|
// Chain of 3 pieces: A(0,0→1,0), B(1,0→2,0), C(2,0→3,0)
|
|
|
|
|
// All currently at their start cells with A having cargo
|
|
|
|
|
var a = new PieceState(1, PieceKind.Rook, new Coords(0, 0), new Coords(1, 0), 0);
|
|
|
|
|
a.CurrentCell = new Coords(1, 0); // at end cell, adjacent to B
|
|
|
|
|
a.Cargo = CargoType.Wood;
|
|
|
|
|
|
|
|
|
|
var b = new PieceState(2, PieceKind.Rook, new Coords(1, 0), new Coords(2, 0), 1);
|
|
|
|
|
b.CurrentCell = new Coords(2, 0); // at end cell, adjacent to C
|
|
|
|
|
|
|
|
|
|
var c = new PieceState(3, PieceKind.Rook, new Coords(2, 0), new Coords(3, 0), 2);
|
|
|
|
|
c.CurrentCell = new Coords(3, 0); // at end cell
|
|
|
|
|
|
|
|
|
|
board.Pieces.AddRange([a, b, c]);
|
|
|
|
|
|
|
|
|
|
var events = TransferResolver.ResolveTransfers(board);
|
|
|
|
|
|
|
|
|
|
// A gives to B (adjacent: (1,0)→(2,0))
|
|
|
|
|
Assert.Contains(events, e => e is CargoTransferredEvent ct && ct.GivingPieceId == 1 && ct.ReceivingPieceId == 2);
|
|
|
|
|
|
|
|
|
|
// B should NOT give to C in the same turn (B just received, participated)
|
|
|
|
|
Assert.DoesNotContain(events, e => e is CargoTransferredEvent ct && ct.GivingPieceId == 2 && ct.ReceivingPieceId == 3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void NoCrossTransfer_NonAdjacent()
|
|
|
|
|
{
|
|
|
|
|
var board = new BoardBuilder(5, 4)
|
2026-04-10 21:44:12 +02:00
|
|
|
.WithProduction(0, 0, "P", CargoType.Wood)
|
2026-04-10 14:58:03 +02:00
|
|
|
.WithDemand(4, 0, "D", CargoType.Wood, 1, 99)
|
|
|
|
|
.WithStock(PieceKind.Rook, 5)
|
|
|
|
|
.BuildState();
|
|
|
|
|
|
|
|
|
|
var giver = new PieceState(1, PieceKind.Rook, new Coords(0, 0), new Coords(1, 0), 0);
|
|
|
|
|
giver.CurrentCell = new Coords(0, 0);
|
|
|
|
|
giver.Cargo = CargoType.Wood;
|
|
|
|
|
|
|
|
|
|
var farPiece = new PieceState(2, PieceKind.Rook, new Coords(2, 0), new Coords(3, 0), 1);
|
|
|
|
|
farPiece.CurrentCell = new Coords(2, 0); // 2 cells away, not adjacent
|
|
|
|
|
|
|
|
|
|
board.Pieces.AddRange([giver, farPiece]);
|
|
|
|
|
|
|
|
|
|
var events = TransferResolver.ResolveTransfers(board);
|
|
|
|
|
|
|
|
|
|
// No piece-to-piece transfer — they're not adjacent
|
|
|
|
|
Assert.DoesNotContain(events, e => e is CargoTransferredEvent ct && ct.GivingPieceId == 1 && ct.ReceivingPieceId == 2);
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-16 21:22:49 +02:00
|
|
|
[Fact]
|
|
|
|
|
public void Production_Amount3_FeedsMultiplePieces()
|
|
|
|
|
{
|
|
|
|
|
var board = new BoardBuilder(4, 4)
|
|
|
|
|
.WithProduction(0, 0, "P", CargoType.Wood, amount: 3)
|
|
|
|
|
.WithDemand(3, 0, "D", CargoType.Wood, 10, 99)
|
|
|
|
|
.WithStock(PieceKind.Rook, 5)
|
|
|
|
|
.BuildState();
|
|
|
|
|
|
|
|
|
|
// Three pieces adjacent to production at (0,0): (1,0), (0,1)
|
|
|
|
|
var p1 = new PieceState(1, PieceKind.Rook, new Coords(1, 0), new Coords(2, 0), 0);
|
|
|
|
|
p1.CurrentCell = new Coords(1, 0);
|
|
|
|
|
var p2 = new PieceState(2, PieceKind.Rook, new Coords(0, 1), new Coords(0, 2), 1);
|
|
|
|
|
p2.CurrentCell = new Coords(0, 1);
|
|
|
|
|
|
|
|
|
|
board.Pieces.AddRange([p1, p2]);
|
|
|
|
|
board.ProductionBuffers[new Coords(0, 0)] = 3; // amount=3
|
|
|
|
|
|
|
|
|
|
var events = TransferResolver.ResolveTransfers(board);
|
|
|
|
|
|
|
|
|
|
// Both pieces should receive cargo (buffer had 3, 2 pieces adjacent)
|
|
|
|
|
Assert.Equal(CargoType.Wood, p1.Cargo);
|
|
|
|
|
Assert.Equal(CargoType.Wood, p2.Cargo);
|
|
|
|
|
Assert.Equal(1, board.ProductionBuffers[new Coords(0, 0)]); // 3 - 2 = 1 remaining
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-10 14:58:03 +02:00
|
|
|
[Fact]
|
|
|
|
|
public void DemandPriority_OverPieceReceiver()
|
|
|
|
|
{
|
|
|
|
|
var board = new BoardBuilder(4, 4)
|
2026-04-10 21:44:12 +02:00
|
|
|
.WithProduction(0, 0, "P", CargoType.Wood)
|
2026-04-10 14:58:03 +02:00
|
|
|
.WithDemand(2, 0, "D", CargoType.Wood, 3, 99)
|
|
|
|
|
.WithStock(PieceKind.Rook, 5)
|
|
|
|
|
.BuildState();
|
|
|
|
|
|
|
|
|
|
// Piece with cargo at (1,0) adjacent to both demand at (2,0) and empty piece at (1,1)
|
|
|
|
|
var giver = new PieceState(1, PieceKind.Rook, new Coords(1, 0), new Coords(2, 0), 0);
|
|
|
|
|
giver.CurrentCell = new Coords(1, 0);
|
|
|
|
|
giver.Cargo = CargoType.Wood;
|
|
|
|
|
|
|
|
|
|
var receiver = new PieceState(2, PieceKind.Rook, new Coords(1, 1), new Coords(2, 1), 1);
|
|
|
|
|
receiver.CurrentCell = new Coords(1, 1); // adjacent to giver
|
|
|
|
|
|
|
|
|
|
board.Pieces.AddRange([giver, receiver]);
|
|
|
|
|
|
|
|
|
|
var events = TransferResolver.ResolveTransfers(board);
|
|
|
|
|
|
|
|
|
|
// Should deliver to demand, not to piece
|
|
|
|
|
Assert.Contains(events, e => e is CargoTransferredEvent ct && ct.To == new Coords(2, 0));
|
|
|
|
|
Assert.DoesNotContain(events, e => e is CargoTransferredEvent ct && ct.ReceivingPieceId == 2);
|
|
|
|
|
}
|
|
|
|
|
}
|