Skip to content

Commit

Permalink
Implement move undo
Browse files Browse the repository at this point in the history
  • Loading branch information
TollyH committed Mar 2, 2023
1 parent 7b670d1 commit 65aa601
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 6 deletions.
13 changes: 8 additions & 5 deletions ChessGame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public class ChessGame
/// </summary>
public List<(Point, Point)> Moves { get; }
public List<string> MoveText { get; }
public ChessGame? PreviousGameState { get; private set; }
public List<Pieces.Piece> CapturedPieces { get; }

public Point? EnPassantSquare { get; private set; }
Expand Down Expand Up @@ -110,7 +111,7 @@ public ChessGame()
public ChessGame(Pieces.Piece?[,] board, bool currentTurnWhite, bool gameOver, List<(Point, Point)> moves, List<string> moveText,
List<Pieces.Piece> capturedPieces, Point? enPassantSquare, bool whiteMayCastleKingside, bool whiteMayCastleQueenside,
bool blackMayCastleKingside, bool blackMayCastleQueenside, int staleMoveCounter, Dictionary<string, int> boardCounts,
string? initialState)
string? initialState, ChessGame? previousGameState)
{
if (board.GetLength(0) != 8 || board.GetLength(1) != 8)
{
Expand Down Expand Up @@ -148,6 +149,7 @@ public ChessGame(Pieces.Piece?[,] board, bool currentTurnWhite, bool gameOver, L
BoardCounts = boardCounts;

InitialState = initialState ?? ToString();
PreviousGameState = previousGameState;
}

/// <summary>
Expand All @@ -167,7 +169,7 @@ public ChessGame Clone()
return new ChessGame(boardClone, CurrentTurnWhite, GameOver, new(Moves), new(MoveText),
CapturedPieces.Select(c => c.Clone()).ToList(), EnPassantSquare, WhiteMayCastleKingside,
WhiteMayCastleQueenside, BlackMayCastleKingside, BlackMayCastleQueenside, StaleMoveCounter,
new(BoardCounts), InitialState);
new(BoardCounts), InitialState, PreviousGameState?.Clone());
}

/// <summary>
Expand Down Expand Up @@ -245,7 +247,7 @@ public bool IsCastlePossible(bool kingside)
/// If a pawn is promoted, what <see cref="Pieces.Piece"/> should it be promoted to. <see langword="null"/> means the user should be prompted for the type.
/// </param>
/// <param name="updateMoveText">
/// Whether the move should update the game move text. This should usually be <see langword="true"/>,
/// Whether the move should update the game move text and update <see cref="PreviousGameState"/>. This should usually be <see langword="true"/>,
/// but may be set to <see langword="false"/> for performance optimisations in clone games for analysis.
/// </param>
/// <returns><see langword="true"/> if the move was valid and executed, <see langword="false"/> otherwise</returns>
Expand All @@ -267,11 +269,12 @@ public bool MovePiece(Point source, Point destination, bool forceMove = false, T
return false;
}

// Used for generating new move text
// Used for generating new move text and move undoing
ChessGame? oldGame = null;
if (updateMoveText)
{
oldGame = Clone();
PreviousGameState = oldGame;
}

bool pieceMoved;
Expand Down Expand Up @@ -750,7 +753,7 @@ public static ChessGame FromForsythEdwards(string forsythEdwards)
// For the PGN standard, if black moves first then a single move "..." is added to the start of the move text list
return new ChessGame(board, currentTurnWhite, EndingStates.Contains(BoardAnalysis.DetermineGameState(board, currentTurnWhite)),
new(), currentTurnWhite ? new() : new() { "..." }, new(), enPassant, whiteKingside, whiteQueenside, blackKingside, blackQueenside,
staleMoves, new(), null);
staleMoves, new(), null, null);
}
}
}
2 changes: 1 addition & 1 deletion CustomGame.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ private void startButton_Click(object sender, RoutedEventArgs e)
ChessGame.EndingStates.Contains(BoardAnalysis.DetermineGameState(Board, currentTurnWhite)),
new(), currentTurnWhite ? new() : new() { "..." }, new(), EnPassantSquare, castleWhiteKingside.IsChecked ?? false,
castleWhiteQueenside.IsChecked ?? false, castleBlackKingside.IsChecked ?? false,
castleBlackQueenside.IsChecked ?? false, 0, new(), null);
castleBlackQueenside.IsChecked ?? false, 0, new(), null, null);
Close();
}

Expand Down
2 changes: 2 additions & 0 deletions MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
<MenuItem Header="New Game (1 Player - _Black)" Click="NewGameCpuBlack_Click"/>
<MenuItem Header="New Game (0 Player - _Computer Only)" Click="NewGameCpuOnly_Click"/>
<Separator/>
<MenuItem Header="_Undo Move" Click="UndoMove_Click"/>
<Separator/>
<MenuItem Header="Custom _Game..." Click="CustomGame_Click"/>
<Separator/>
<MenuItem Header="Export to _PGN" Click="PGNExport_Click"/>
Expand Down
16 changes: 16 additions & 0 deletions MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,22 @@ private void CustomiseItem_Click(object sender, RoutedEventArgs e)
UpdateGameDisplay();
}

private async void UndoMove_Click(object sender, RoutedEventArgs e)
{
if (game.PreviousGameState is not null
&& ((game.CurrentTurnWhite && !whiteIsComputer) || (!game.CurrentTurnWhite && !blackIsComputer)))
{
game = game.PreviousGameState;
if (whiteIsComputer || blackIsComputer)
{
// Reverse two moves if the opponent is computer controlled
game = game.PreviousGameState!;
}
UpdateGameDisplay();
await CheckComputerMove();
}
}

private void whiteDepthBackingSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (!updateDepthSliders)
Expand Down

0 comments on commit 65aa601

Please sign in to comment.