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: MOVEMENT ExecuteMovement(state, changeList); // Sub-phase 2: COLLISION DETECTION var collisions = CollisionDetector.DetectCollisions(state.Pieces); if (collisions.Count > 0) { foreach (var (idA, idB, cell) in collisions) changeList.Add(new CollisionDetectedEvent(idA, idB, cell)); state.Phase = SimPhase.Collision; changeList.Add(new TurnEndedEvent(state.TurnNumber)); return; } // Sub-phase 3: TRANSFERS var transferEvents = TransferResolver.ResolveTransfers(state); changeList.AddRange(transferEvents); // Sub-phase 4: PRODUCTION ExecuteProduction(state, changeList); // Check victory / defeat if (VictoryChecker.AllDemandsMet(state)) { state.Phase = SimPhase.Victory; changeList.Add(new VictoryEvent(ComputeMetrics(state))); } else if (VictoryChecker.AnyDeadlineExpired(state)) { state.Phase = SimPhase.Defeat; foreach (var demand in VictoryChecker.GetExpiredDemands(state)) changeList.Add(new DeadlineExpiredEvent(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(piece.Id, from, to)); } } private static void ExecuteProduction(BoardState state, List changeList) { foreach (var (pos, prod) in state.Productions) { if (state.ProductionBuffers[pos] != null) continue; // buffer already full if (state.TurnNumber % prod.Interval == 0) { state.ProductionBuffers[pos] = prod.Cargo; changeList.Add(new CargoProducedEvent(pos, prod.Cargo)); } } } private static Metrics ComputeMetrics(BoardState state) { return new Metrics( PiecesUsed: state.Pieces.Count, TurnsTaken: state.TurnNumber, CellsOccupied: state.OccupiedCells.Count ); } }