/// <summary> /// Redoes the last undone action. /// </summary> public void Redo() { lock (_syncLock) { if (CanRedo) { Memento = _breadCrumbs.Pop(); } else { throw new ArgumentException("Nothing to redo"); } } }
/// <summary> /// Undoes the last action taken. The action can be retaken /// using <see cref="Redo"/>, if there were no /// <see cref="Update"/> calls in between. /// </summary> public void Undo() { lock (_syncLock) { if (CanUndo) { _breadCrumbs.Push(Memento); Memento = Memento.Parent; } else { throw new ArgumentException("Nothing to undo"); } } }
/// <summary> /// Updates the state of the game with the current action. /// </summary> /// <param name="action">The action to be played by the current player</param> /// <exception cref="ArgumentException"> /// If the move is invalid. The action's validity should be verified upstream. /// </exception> public void Update(IUpdateAction action) { lock (_syncLock) { if (action.IsValidOn(State)) { Memento = Memento.Update(action); _breadCrumbs.Clear(); } else { throw new ArgumentException("Invalid move: " + action); } } }
// Only when loading an existing memento private Game(GameMemento memento) { Memento = memento; }
// Only to initialise the game private Game(int size, FullPlayerSpecPair specs, bool isFirstPlayerPlaying) { Memento = new RootMemento(specs, size, isFirstPlayerPlaying); }
/// <summary> /// Returns a new game corresponding to the given memento. /// </summary> /// <param name="memento"></param> /// <returns></returns> public static Game FromMemento(GameMemento memento) { return(new Game(memento)); }
protected GameMemento(GameMemento parent) { Parent = parent; }
public MementoNode(GameMemento previous, IUpdateAction action) : base(previous) { Action = action; }
protected bool Equals(GameMemento other) { return(Equals(Parent, other.Parent)); }