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 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 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 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 ); } }