internal ChessMove[] GetBoardThreats(out bool ownKingUnderThreat, PiecePlayer playerToEvaluate)
        {
            ChessBoardLocation kingLocation  = new ChessBoardLocation(-1, -1);
            List <ChessMove>   opponentMoves = new List <ChessMove>();
            var player = playerToEvaluate == PiecePlayer.White ? PiecePlayer.Black : PiecePlayer.White;

            for (int i = 0; i < BOARD_SIZE; i++)
            {
                for (int j = 0; j < BOARD_SIZE; j++)
                {
                    if (_pieces[i, j].Player == playerToEvaluate)
                    {
                        var moves = GetAvailableMoves(playerToEvaluate, i, j, false);
                        opponentMoves.AddRange(moves);
                    }
                    else if (_pieces[i, j].Player == player && _pieces[i, j].Rank == PieceRank.King)
                    {
                        kingLocation = new ChessBoardLocation(i, j);
                    }
                }
            }

            ownKingUnderThreat = opponentMoves.Where(o =>
                                                     o.To.HorizontalLocation == kingLocation.HorizontalLocation &&
                                                     o.To.VerticalLocation == kingLocation.VerticalLocation).Any();

            if (ownKingUnderThreat == true)
            {
                // Currently board has been verified as "check".
                // Now let's verify that is it also "checkmate".
            }

            return(opponentMoves.ToArray());
        }
 public ChessMove(PieceRank rank, PiecePlayer player, int horizontalLocationFrom, int verticalLocationFrom, int horizontalLocationTo, int verticalLocationTo, ChessSpecialMove specialMove)
 {
     Rank        = rank;
     Player      = player;
     From        = new ChessBoardLocation(horizontalLocationFrom, verticalLocationFrom);
     To          = new ChessBoardLocation(horizontalLocationTo, verticalLocationTo);
     SpecialMove = specialMove;
 }
        private bool IsOccupiedByOpponent(PiecePlayer player, int column, int row)
        {
            if (column < 0 || column > BOARD_SIZE - 1 || row < 0 || row > BOARD_SIZE - 1)
            {
                // Out of bounds
                return(false);
            }

            return(_pieces[column, row].Player != player && _pieces[column, row].Player != PiecePlayer.None);
        }
示例#4
0
        internal void SetBoard(string board)
        {
            CleanUp();

            string[] rows = board.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < rows.Length; i++)
            {
                for (int j = 0; j < rows[i].Length; j++)
                {
                    char        piece      = rows[i][j];
                    PiecePlayer pieceColor = char.ToLower(piece) == piece ? PiecePlayer.Black : PiecePlayer.White;
                    PieceRank   pieceRank;

                    switch (char.ToLower(piece))
                    {
                    case '-':
                        pieceColor = PiecePlayer.None;
                        pieceRank  = PieceRank.None;
                        break;

                    case 'k':
                        pieceRank = PieceRank.King;
                        break;

                    case 'q':
                        pieceRank = PieceRank.Queen;
                        break;

                    case 'b':
                        pieceRank = PieceRank.Bishop;
                        break;

                    case 'r':
                        pieceRank = PieceRank.Rook;
                        break;

                    case 'p':
                        pieceRank = PieceRank.Pawn;
                        break;

                    case 'n':
                        pieceRank = PieceRank.Knight;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("board");
                    }

                    _pieces[j, i] = new ChessBoardPiece(pieceColor, pieceRank);
                }
            }
        }
        private void GetKnightMove(PiecePlayer player, List <ChessMove> moves, int column, int row)
        {
            moves.Add(new ChessMove(PieceRank.Knight, player, column, row, column - 1, row + 2));
            moves.Add(new ChessMove(PieceRank.Knight, player, column, row, column - 1, row - 2));

            moves.Add(new ChessMove(PieceRank.Knight, player, column, row, column + 1, row + 2));
            moves.Add(new ChessMove(PieceRank.Knight, player, column, row, column + 1, row - 2));

            moves.Add(new ChessMove(PieceRank.Knight, player, column, row, column - 2, row + 1));
            moves.Add(new ChessMove(PieceRank.Knight, player, column, row, column - 2, row - 1));

            moves.Add(new ChessMove(PieceRank.Knight, player, column, row, column + 2, row + 1));
            moves.Add(new ChessMove(PieceRank.Knight, player, column, row, column + 2, row - 1));
        }
 private void GetPawnMovesEnPassant(PiecePlayer player, List <ChessMove> moves, int column, int row, int columnDelta, int rowDelta)
 {
     // En passant move:
     if (_previousMove != null && IsOccupiedByOpponent(player, column + columnDelta, row) == true)
     {
         ChessBoardPiece piece = GetPiece(column + columnDelta, row);
         if (piece.Rank == PieceRank.Pawn && piece.Player != player)
         {
             if (_previousMove.To.HorizontalLocation == column + columnDelta && _previousMove.To.VerticalLocation == row && Math.Abs(_previousMove.To.VerticalLocation - _previousMove.From.VerticalLocation) == 2)
             {
                 moves.Add(new ChessMove(PieceRank.Pawn, player, column, row, column + columnDelta, row + rowDelta, ChessSpecialMove.EnPassant));
             }
         }
     }
 }
        private void GetKingMove(PiecePlayer player, List <ChessMove> moves, int column, int row, bool validateCheck)
        {
            moves.Add(new ChessMove(PieceRank.King, player, column, row, column - 1, row - 1));
            moves.Add(new ChessMove(PieceRank.King, player, column, row, column, row - 1));
            moves.Add(new ChessMove(PieceRank.King, player, column, row, column - 1, row));

            moves.Add(new ChessMove(PieceRank.King, player, column, row, column + 1, row + 1));
            moves.Add(new ChessMove(PieceRank.King, player, column, row, column, row + 1));
            moves.Add(new ChessMove(PieceRank.King, player, column, row, column + 1, row));

            moves.Add(new ChessMove(PieceRank.King, player, column, row, column + 1, row - 1));
            moves.Add(new ChessMove(PieceRank.King, player, column, row, column - 1, row + 1));

            // Check castling moves (rules from Wikipedia: http://en.wikipedia.org/wiki/Chess)
            // - Neither of the pieces involved in castling may have been previously
            //   moved during the game.
            // - There must be no pieces between the king and the rook.
            // - The king may not be in check, nor may the king pass through squares
            //   that are under attack by enemy pieces, nor move to a square where it is in check.
            int kingStartColumn = 4;
            int kingStartRow    = player == PiecePlayer.White ? 7 : 0;

            if (column == kingStartColumn && row == kingStartRow)
            {
                // King is at start location. Has it moved earlier?
                var kingsEarlierMove = _moves.Where(
                    m => m.First().Player == player && m.First().Rank == PieceRank.King).FirstOrDefault();
                if (kingsEarlierMove != null)
                {
                    // King has already moved so castling is not anymore available
                    return;
                }

                // Left hand side rook
                GetKingCastlingMove(player, moves, column, row, 0, validateCheck);

                // Right hand side rook
                GetKingCastlingMove(player, moves, column, row, 7, validateCheck);
            }
        }
        private void GetHorizontalAndVerticalMoves(PieceRank rank, PiecePlayer player, List <ChessMove> moves, int column, int row)
        {
            // To left
            for (int i = column - 1; i >= 0; i--)
            {
                if (IsOccupiedByOpponent(player, i, row) == true)
                {
                    moves.Add(new ChessMove(rank, player, column, row, i, row));
                }
                else if (IsEmpty(i, row) == true)
                {
                    moves.Add(new ChessMove(rank, player, column, row, i, row));
                    continue;
                }

                break;
            }

            // To right
            for (int i = column + 1; i < BOARD_SIZE; i++)
            {
                if (IsOccupiedByOpponent(player, i, row) == true)
                {
                    moves.Add(new ChessMove(rank, player, column, row, i, row));
                }
                else if (IsEmpty(i, row) == true)
                {
                    moves.Add(new ChessMove(rank, player, column, row, i, row));
                    continue;
                }

                break;
            }

            // To up
            for (int i = row - 1; i >= 0; i--)
            {
                if (IsOccupiedByOpponent(player, column, i) == true)
                {
                    moves.Add(new ChessMove(rank, player, column, row, column, i));
                }
                else if (IsEmpty(column, i) == true)
                {
                    moves.Add(new ChessMove(rank, player, column, row, column, i));
                    continue;
                }

                break;
            }

            // To down
            for (int i = row + 1; i < BOARD_SIZE; i++)
            {
                if (IsOccupiedByOpponent(player, column, i) == true)
                {
                    moves.Add(new ChessMove(rank, player, column, row, column, i));
                }
                else if (IsEmpty(column, i) == true)
                {
                    moves.Add(new ChessMove(rank, player, column, row, column, i));
                    continue;
                }

                break;
            }
        }
        private void GetDiagonalMoves(PieceRank rank, PiecePlayer player, List <ChessMove> moves, int column, int row)
        {
            // To north-east
            for (int i = 1; i <= BOARD_SIZE; i++)
            {
                if (IsOccupiedByOpponent(player, column + i, row - i) == true)
                {
                    moves.Add(new ChessMove(rank, player, column, row, column + i, row - i));
                }
                else if (IsEmpty(column + i, row - i) == true)
                {
                    moves.Add(new ChessMove(rank, player, column, row, column + i, row - i));
                    continue;
                }

                break;
            }

            // To south-east
            for (int i = 1; i <= BOARD_SIZE; i++)
            {
                if (IsOccupiedByOpponent(player, column + i, row + i) == true)
                {
                    moves.Add(new ChessMove(rank, player, column, row, column + i, row + i));
                }
                else if (IsEmpty(column + i, row + i) == true)
                {
                    moves.Add(new ChessMove(rank, player, column, row, column + i, row + i));
                    continue;
                }

                break;
            }

            // To north-west
            for (int i = 1; i <= BOARD_SIZE; i++)
            {
                if (IsOccupiedByOpponent(player, column - i, row - i) == true)
                {
                    moves.Add(new ChessMove(rank, player, column, row, column - i, row - i));
                }
                else if (IsEmpty(column - i, row - i) == true)
                {
                    moves.Add(new ChessMove(rank, player, column, row, column - i, row - i));
                    continue;
                }

                break;
            }

            // To south-west
            for (int i = 1; i <= BOARD_SIZE; i++)
            {
                if (IsOccupiedByOpponent(player, column - i, row + i) == true)
                {
                    moves.Add(new ChessMove(rank, player, column, row, column - i, row + i));
                }
                else if (IsEmpty(column - i, row + i) == true)
                {
                    moves.Add(new ChessMove(rank, player, column, row, column - i, row + i));
                    continue;
                }

                break;
            }
        }
 private void GetQueenMove(PiecePlayer player, List <ChessMove> moves, int column, int row)
 {
     GetHorizontalAndVerticalMoves(PieceRank.Queen, player, moves, column, row);
     GetDiagonalMoves(PieceRank.Queen, player, moves, column, row);
 }
 private void GetBishopMove(PiecePlayer player, List <ChessMove> moves, int column, int row)
 {
     GetDiagonalMoves(PieceRank.Bishop, player, moves, column, row);
 }
 private void GetRookMove(PiecePlayer player, List <ChessMove> moves, int column, int row)
 {
     GetHorizontalAndVerticalMoves(PieceRank.Rook, player, moves, column, row);
 }
        private void GetPawnMoves(PiecePlayer player, List <ChessMove> moves, int column, int row)
        {
            ChessSpecialMove specialMove = ChessSpecialMove.None;

            if (player == PiecePlayer.White)
            {
                if (row == 1)
                {
                    specialMove = ChessSpecialMove.Promotion;
                }

                if (IsOccupiedByOpponent(player, column, row - 1) == false)
                {
                    moves.Add(new ChessMove(PieceRank.Pawn, player, column, row, column, row - 1, specialMove));
                }

                if (row == 6 && IsEmpty(column, row - 1) == true && IsEmpty(column, row - 2) == true)
                {
                    moves.Add(new ChessMove(PieceRank.Pawn, player, column, row, column, row - 2));
                }

                // Move only available for pawn if there is opponent piece:
                if (IsOccupiedByOpponent(player, column + 1, row - 1) == true)
                {
                    moves.Add(new ChessMove(PieceRank.Pawn, player, column, row, column + 1, row - 1, specialMove));
                }

                if (IsOccupiedByOpponent(player, column - 1, row - 1) == true)
                {
                    moves.Add(new ChessMove(PieceRank.Pawn, player, column, row, column - 1, row - 1, specialMove));
                }

                GetPawnMovesEnPassant(player, moves, column, row, -1, -1);
                GetPawnMovesEnPassant(player, moves, column, row, 1, -1);
            }
            else
            {
                if (row == 6)
                {
                    specialMove = ChessSpecialMove.Promotion;
                }

                if (IsOccupiedByOpponent(player, column, row + 1) == false)
                {
                    moves.Add(new ChessMove(PieceRank.Pawn, player, column, row, column, row + 1, specialMove));
                }

                if (row == 1 && IsEmpty(column, row + 1) == true && IsEmpty(column, row + 2) == true)
                {
                    moves.Add(new ChessMove(PieceRank.Pawn, player, column, row, column, row + 2));
                }

                // Move only available for pawn if there is opponent piece:
                if (IsOccupiedByOpponent(player, column + 1, row + 1) == true)
                {
                    moves.Add(new ChessMove(PieceRank.Pawn, player, column, row, column + 1, row + 1, specialMove));
                }

                if (IsOccupiedByOpponent(player, column - 1, row + 1) == true)
                {
                    moves.Add(new ChessMove(PieceRank.Pawn, player, column, row, column - 1, row + 1, specialMove));
                }

                GetPawnMovesEnPassant(player, moves, column, row, -1, 1);
                GetPawnMovesEnPassant(player, moves, column, row, 1, 1);
            }
        }
        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));
            }
        }
        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());
        }
示例#16
0
 public ChessBoardPiece(PiecePlayer player, PieceRank rank)
 {
     Player = player;
     Rank   = rank;
 }