namespace Chessistics.Engine.Model; public class BoardSnapshot { public int Width { get; } public int Height { get; } public CellType[,] Grid { get; } public IReadOnlyList Productions { get; } public IReadOnlyList Demands { get; } public IReadOnlyList Pieces { get; } public IReadOnlyList Transformers { get; } public SimPhase Phase { get; } public int TurnNumber { get; } public IReadOnlyDictionary RemainingStock { get; } // Campaign info (null in legacy level mode) public CampaignSnapshot? Campaign { get; } public BoardSnapshot(BoardState state) { Width = state.Width; Height = state.Height; Phase = state.Phase; TurnNumber = state.TurnNumber; // Deep copy grid Grid = new CellType[Width, Height]; Array.Copy(state.Grid, Grid, state.Grid.Length); Productions = state.Productions.Values .Select(p => new ProductionSnapshot(p.Position, p.Name, p.Cargo, p.Amount, state.ProductionBuffers[p.Position])) .ToList(); Demands = state.Demands.Values .Select(d => new DemandSnapshot(d.Position, d.Name, d.Cargo, d.Required, d.Deadline, d.ReceivedCount, d.IsSatisfied, d.MissionIndex, d.Definition.ConsumptionPerTurn, d.Definition.SustainTurns, d.Buffer, d.SustainedTurns, d.InShortage)) .ToList(); Pieces = state.Pieces .Select(p => new PieceSnapshot(p.Id, p.Kind, p.Level, p.StartCell, p.EndCell, p.CurrentCell, p.Cargo, p.CargoFilter, p.SocialStatus)) .ToList(); Transformers = state.Transformers.Values .Select(t => new TransformerSnapshot(t.Position, t.Name, t.InputCargo, t.InputRequired, t.OutputCargo, t.OutputAmount, state.TransformerInputBuffers[t.Position], state.TransformerOutputBuffers[t.Position])) .ToList(); RemainingStock = new Dictionary(state.RemainingStock); if (state.Campaign != null) { Campaign = new CampaignSnapshot( state.Campaign.CampaignDef.Name, state.Campaign.CurrentMissionIndex, state.Campaign.CompletedMissions.ToList(), state.Campaign.AvailablePieceKinds.ToHashSet(), state.Campaign.AvailableLevels.ToHashSet() ); } } } public record ProductionSnapshot(Coords Position, string Name, CargoType Cargo, int Amount, int BufferCount); public record DemandSnapshot( Coords Position, string Name, CargoType Cargo, int Required, int Deadline, int ReceivedCount, bool IsSatisfied, int MissionIndex = 0, int ConsumptionPerTurn = 0, int SustainTurns = 0, int Buffer = 0, int SustainedTurns = 0, bool InShortage = false); public record PieceSnapshot(int Id, PieceKind Kind, int Level, Coords StartCell, Coords EndCell, Coords CurrentCell, CargoType? Cargo, CargoType? CargoFilter, int SocialStatus); public record TransformerSnapshot(Coords Position, string Name, CargoType InputCargo, int InputRequired, CargoType OutputCargo, int OutputAmount, int InputBufferCount, int OutputBufferCount); public record CampaignSnapshot(string Name, int CurrentMissionIndex, IReadOnlyList CompletedMissions, IReadOnlySet AvailablePieceKinds, IReadOnlySet AvailableLevels);