Chessistics/chessistics-engine/Simulation/TurnExecutor.cs

86 lines
2.9 KiB
C#
Raw Normal View History

using Chessistics.Engine.Events;
using Chessistics.Engine.Model;
using Chessistics.Engine.Rules;
namespace Chessistics.Engine.Simulation;
public static class TurnExecutor
{
public static void ExecuteTurn(BoardState state, List<IWorldEvent> changeList)
{
state.TurnNumber++;
changeList.Add(new TurnStartedEvent(state.TurnNumber));
// Sub-phase 1: PRODUCTION
ExecuteProduction(state, changeList);
// Sub-phase 2: TRANSFERS
var transferEvents = TransferResolver.ResolveTransfers(state);
changeList.AddRange(transferEvents);
// Sub-phase 3: MOVEMENT
ExecuteMovement(state, changeList);
// Sub-phase 4: COLLISION RESOLUTION
var collisions = CollisionResolver.ResolveCollisions(state.Pieces);
foreach (var (survivor, destroyed, cell) in collisions)
{
foreach (var victim in destroyed)
{
state.Pieces.Remove(victim);
state.DestroyedPieces.Add(victim);
victim.Cargo = null;
changeList.Add(new PieceDestroyedEvent(
state.TurnNumber, victim.Id, survivor?.Id, cell));
}
}
// Check victory / defeat
if (VictoryChecker.AllDemandsMet(state))
{
state.Phase = SimPhase.Victory;
changeList.Add(new VictoryEvent(state.TurnNumber, ComputeMetrics(state)));
}
else if (VictoryChecker.AnyDeadlineExpired(state))
{
state.Phase = SimPhase.Defeat;
foreach (var demand in VictoryChecker.GetExpiredDemands(state))
changeList.Add(new DeadlineExpiredEvent(state.TurnNumber, demand.Position, demand.Name));
}
changeList.Add(new TurnEndedEvent(state.TurnNumber));
}
private static void ExecuteMovement(BoardState state, List<IWorldEvent> changeList)
{
// Compute all targets first (simultaneous movement)
var moves = state.Pieces.Select(p => (piece: p, from: p.CurrentCell, to: p.TargetCell)).ToList();
// Apply all moves
foreach (var (piece, from, to) in moves)
{
piece.CurrentCell = to;
state.OccupiedCells.Add(to);
changeList.Add(new PieceMovedEvent(state.TurnNumber, piece.Id, from, to));
}
}
private static void ExecuteProduction(BoardState state, List<IWorldEvent> changeList)
{
foreach (var (pos, prod) in state.Productions)
{
state.ProductionBuffers[pos] = prod.Amount;
changeList.Add(new CargoProducedEvent(state.TurnNumber, pos, prod.Cargo));
}
}
private static Metrics ComputeMetrics(BoardState state)
{
return new Metrics(
PiecesUsed: state.Pieces.Count + state.DestroyedPieces.Count,
TurnsTaken: state.TurnNumber,
CellsOccupied: state.OccupiedCells.Count
);
}
}