BoardState.CaptureSave/RestoreFromSave deep-copy every mutable field (grid, pieces, demands, transformers, buffers, stock, campaign progress) into a WorldSave slot. GameSim.QuickSave/QuickLoad expose slotted saves and emit StateSavedEvent / StateRestoredEvent — the latter carries a fresh BoardSnapshot so the presentation can rebuild board, pieces, trajectories, objectives, stock, camera, and control bar in one pass. F5/F9 trigger it in Main; harness gains quick_save/quick_load commands so UI tests can checkpoint a scenario and resume without replaying from scratch. Seven xUnit tests cover the roundtrip (including independence from post-save mutations, campaign state, and multi-slot isolation).
64 lines
1.9 KiB
C#
64 lines
1.9 KiB
C#
using Chessistics.Engine.Commands;
|
|
using Chessistics.Engine.Events;
|
|
using Chessistics.Engine.Model;
|
|
|
|
namespace Chessistics.Engine.Simulation;
|
|
|
|
public class GameSim
|
|
{
|
|
private readonly BoardState _state;
|
|
private readonly Dictionary<int, WorldSave> _saveSlots = new();
|
|
private const int DefaultSlot = 0;
|
|
|
|
public GameSim(LevelDef level)
|
|
{
|
|
_state = BoardState.FromLevel(level);
|
|
}
|
|
|
|
public GameSim(CampaignDef campaign)
|
|
{
|
|
_state = BoardState.FromCampaign(campaign);
|
|
}
|
|
|
|
public IReadOnlyList<IWorldEvent> ProcessCommand(IWorldCommand command)
|
|
{
|
|
var changeList = new List<IWorldEvent>();
|
|
try
|
|
{
|
|
command.Apply(_state, changeList);
|
|
}
|
|
catch (CommandRejectedException ex)
|
|
{
|
|
return [ex.RejectionEvent];
|
|
}
|
|
return changeList;
|
|
}
|
|
|
|
public BoardSnapshot GetSnapshot() => new(_state);
|
|
|
|
/// <summary>
|
|
/// Capture a full deep-copy of the world into an in-memory slot.
|
|
/// Returns a single StateSavedEvent — no state mutation.
|
|
/// </summary>
|
|
public IReadOnlyList<IWorldEvent> QuickSave(int slot = DefaultSlot)
|
|
{
|
|
_saveSlots[slot] = _state.CaptureSave();
|
|
return [new StateSavedEvent(_state.TurnNumber, slot)];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restore the world from a saved slot. Emits StateRestoredEvent with a
|
|
/// fresh snapshot — the presentation layer must rebuild all visuals.
|
|
/// Returns an empty list (no event) if the slot is empty.
|
|
/// </summary>
|
|
public IReadOnlyList<IWorldEvent> QuickLoad(int slot = DefaultSlot)
|
|
{
|
|
if (!_saveSlots.TryGetValue(slot, out var save))
|
|
return [];
|
|
|
|
_state.RestoreFromSave(save);
|
|
return [new StateRestoredEvent(new BoardSnapshot(_state), slot)];
|
|
}
|
|
|
|
public bool HasSave(int slot = DefaultSlot) => _saveSlots.ContainsKey(slot);
|
|
}
|