private List <ChessMove> MakeMove(ChessMove move, bool validateCheck) { var executedMoves = new List <ChessMove>(); var boardChanges = new List <ChessBoardChange>(); var availableMoves = GetAvailableMoves(CurrentPlayer, move.From.HorizontalLocation, move.From.VerticalLocation, validateCheck); ChessMove selectedMove = availableMoves.Where(o => o.CompareTo(move) == 0).FirstOrDefault(); if (selectedMove == null) { throw new ArgumentOutOfRangeException("move", "Invalid move!"); } executedMoves.Add(selectedMove); switch (selectedMove.SpecialMove) { case ChessSpecialMove.EnPassant: var enPassantPiece = _pieces[selectedMove.To.HorizontalLocation, selectedMove.From.VerticalLocation]; executedMoves.Add( new ChessMove( enPassantPiece.Rank, enPassantPiece.Player, selectedMove.To.HorizontalLocation, selectedMove.From.VerticalLocation, ChessBoardLocation.OUTSIDE_BOARD, ChessBoardLocation.OUTSIDE_BOARD, ChessSpecialMove.Capture)); _pieces[selectedMove.To.HorizontalLocation, selectedMove.From.VerticalLocation] = ChessBoardPiece.Empty; // Capture in board change (in en passant case): boardChanges.Add(new ChessBoardChange(selectedMove.To.HorizontalLocation, selectedMove.From.VerticalLocation, PieceSelection.Capture)); break; case ChessSpecialMove.Castling: int rookStartColumn; int rookEndColumn; if (selectedMove.From.HorizontalLocation < selectedMove.To.HorizontalLocation) { // Right hand side castling rookStartColumn = 7; rookEndColumn = selectedMove.To.HorizontalLocation - 1; } else { // Left hand side castling rookStartColumn = 0; rookEndColumn = selectedMove.To.HorizontalLocation + 1; } var rookPiece = _pieces[rookStartColumn, selectedMove.From.VerticalLocation]; executedMoves.Add( new ChessMove( rookPiece.Rank, rookPiece.Player, rookStartColumn, selectedMove.From.VerticalLocation, rookEndColumn, selectedMove.To.VerticalLocation, ChessSpecialMove.Castling)); _pieces[rookStartColumn, selectedMove.From.VerticalLocation] = ChessBoardPiece.Empty; _pieces[rookEndColumn, selectedMove.From.VerticalLocation] = new ChessBoardPiece(rookPiece.Player, rookPiece.Rank); break; case ChessSpecialMove.Promotion: executedMoves.Add( new ChessMove( selectedMove.Rank, selectedMove.Player, selectedMove.From.HorizontalLocation, selectedMove.From.VerticalLocation, ChessBoardLocation.OUTSIDE_BOARD, ChessBoardLocation.OUTSIDE_BOARD, ChessSpecialMove.PromotionOut)); executedMoves.Add( new ChessMove( PieceRank.Queen, selectedMove.Player, ChessBoardLocation.OUTSIDE_BOARD, ChessBoardLocation.OUTSIDE_BOARD, selectedMove.To.HorizontalLocation, selectedMove.To.VerticalLocation, ChessSpecialMove.PromotionIn)); // Use default promotion to queen: ChessBoardPiece piece = _pieces[selectedMove.From.HorizontalLocation, selectedMove.From.VerticalLocation]; piece = new ChessBoardPiece(piece.Player, PieceRank.Queen); _pieces[selectedMove.From.HorizontalLocation, selectedMove.From.VerticalLocation] = piece; break; case ChessSpecialMove.Check: break; case ChessSpecialMove.CheckMate: break; case ChessSpecialMove.None: break; } if (_pieces[selectedMove.To.HorizontalLocation, selectedMove.To.VerticalLocation].Rank != PieceRank.None) { // Capture so let's store it var capturePiece = _pieces[selectedMove.To.HorizontalLocation, selectedMove.To.VerticalLocation]; executedMoves.Add( new ChessMove( capturePiece.Rank, capturePiece.Player, selectedMove.To.HorizontalLocation, selectedMove.To.VerticalLocation, ChessBoardLocation.OUTSIDE_BOARD, ChessBoardLocation.OUTSIDE_BOARD, ChessSpecialMove.Capture)); // Capture in board change: boardChanges.Add(new ChessBoardChange(selectedMove.To.HorizontalLocation, selectedMove.To.VerticalLocation, PieceSelection.Capture)); } else { // Move to as board change: boardChanges.Add(new ChessBoardChange(selectedMove.To.HorizontalLocation, selectedMove.To.VerticalLocation, PieceSelection.PreviousMoveTo)); } _pieces[selectedMove.To.HorizontalLocation, selectedMove.To.VerticalLocation] = _pieces[selectedMove.From.HorizontalLocation, selectedMove.From.VerticalLocation]; _pieces[selectedMove.From.HorizontalLocation, selectedMove.From.VerticalLocation] = ChessBoardPiece.Empty; // Move from as board change: boardChanges.Add(new ChessBoardChange(selectedMove.From.HorizontalLocation, selectedMove.From.VerticalLocation, PieceSelection.PreviousMoveFrom)); _previousMove = selectedMove; CurrentPlayer = CurrentPlayer == PiecePlayer.White ? PiecePlayer.Black : PiecePlayer.White; _moves.Push(executedMoves); _boardChanges.Push(boardChanges); return(executedMoves); }
private void GetKingCastlingMove(PiecePlayer player, List <ChessMove> moves, int column, int row, int rookColumn, bool validateCheck) { var rookPosition = _pieces[rookColumn, row]; if (rookPosition.Player != player || rookPosition.Rank != PieceRank.Rook) { // Not current players rook return; } var rookRow = player == PiecePlayer.White ? 1 : 8; // Rook is at start location. Has it moved earlier? var rooksEarlierMove = _moves.Where( m => m.First().Player == player && m.First().Rank == PieceRank.Rook && m.First().From.VerticalLocation == rookRow && m.First().From.HorizontalLocation == rookColumn).FirstOrDefault(); if (rooksEarlierMove != null) { // Rook has already moved so castling is not anymore available return; } bool ownKingUnderThreat = false; ChessMove[] opponentMoves = new ChessMove[0]; if (validateCheck == true) { opponentMoves = GetBoardThreats( out ownKingUnderThreat, CurrentPlayer == PiecePlayer.White ? PiecePlayer.Black : PiecePlayer.White); } if (ownKingUnderThreat == false) { // Set defaults to left hand side rook castling int delta = -2; int startColumn = 2; int endColumn = column; if (rookColumn > endColumn) { delta = 2; startColumn = column + 1; endColumn = rookColumn; } for (int currentColumn = startColumn; currentColumn < endColumn; currentColumn++) { if (_pieces[currentColumn, row].Player != PiecePlayer.None) { return; } ChessMove opponentMove = opponentMoves.Where( o => o.To.HorizontalLocation == currentColumn && o.To.VerticalLocation == row).FirstOrDefault(); if (opponentMove != null) { return; } } // This castling move is valid moves.Add(new ChessMove(PieceRank.King, player, column, row, column + delta, row, ChessSpecialMove.Castling)); } }
public List <ChessMove> MakeMove(ChessMove move) { return(MakeMove(move, true)); }
private ChessMove[] GetAvailableMoves(PiecePlayer player, int column, int row, bool validateCheck) { List <ChessMove> moves = new List <ChessMove>(); if (player == PiecePlayer.None) { // Game over already return(moves.ToArray()); } if (_pieces[column, row].Player == player) { switch (_pieces[column, row].Rank) { case PieceRank.Pawn: GetPawnMoves(player, moves, column, row); break; case PieceRank.Knight: GetKnightMove(player, moves, column, row); break; case PieceRank.Bishop: GetBishopMove(player, moves, column, row); break; case PieceRank.Rook: GetRookMove(player, moves, column, row); break; case PieceRank.Queen: GetQueenMove(player, moves, column, row); break; case PieceRank.King: GetKingMove(player, moves, column, row, validateCheck); break; default: break; } // Validate all moves for (int i = moves.Count - 1; i >= 0; i--) { bool invalidMove = false; ChessMove move = moves[i]; if (move.To.HorizontalLocation < 0 || move.To.HorizontalLocation > BOARD_SIZE - 1) { // Out of bounds invalidMove = true; } else if (move.To.VerticalLocation < 0 || move.To.VerticalLocation > BOARD_SIZE - 1) { // Out of bounds invalidMove = true; } else if (_pieces[move.To.HorizontalLocation, move.To.VerticalLocation].Player == player) { // Already occupied by team mate invalidMove = true; } if (invalidMove == false && validateCheck == true) { // Let's see if this move would cause check MakeMove(move, false); GetBoardThreats(out var ownKingUnderThreat); if (ownKingUnderThreat == true) { invalidMove = true; } Undo(); } if (invalidMove == true) { moves.RemoveAt(i); } } } return(moves.ToArray()); }