예제 #1
0
    public List <Piece> GetPiecesOfColour(Piece.PieceColour colour)
    {
        List <Piece> pieces = new List <Piece>();

        foreach (Piece piece in this.pieces)
        {
            if (piece.colour == colour)
            {
                pieces.Add(piece);
            }
        }
        return(pieces);
    }
        public static List <Move> GeneratePseudoLegalMoves(Board board, Piece.PieceColour colour_to_move)
        {
            var moves = new List <Move>();

            for (int start_x = 0; start_x < Board.GridSize; start_x++)
            {
                for (int start_y = 0; start_y < Board.GridSize; start_y++)
                {
                    Piece piece      = board.Cells[start_x, start_y];
                    var   start_cell = new Vector2Int(start_x, start_y);

                    var this_piece_moves = new List <Move>();
                    if (piece.MyPieceColour == colour_to_move)
                    {
                        if (piece.IsSlidingPiece)
                        {
                            this_piece_moves = _GenerateSlidingMoves(start_cell, board.Cells);
                        }
                        else if (piece.MyPieceType == Piece.PieceType.Pawn)
                        {
                            this_piece_moves = _GeneratePawnMoves(start_cell, board.Cells);
                        }
                        else if (piece.MyPieceType == Piece.PieceType.Knight)
                        {
                            this_piece_moves = _GenerateKnightMoves(start_cell, board.Cells);
                        }
                        else if (piece.MyPieceType == Piece.PieceType.King)
                        {
                            this_piece_moves = _GenerateKingMoves(start_cell, board.Cells);
                        }
                    }

                    foreach (Move move in this_piece_moves)
                    {
                        moves.Add(move);
                    }
                }
            }

            return(moves);
        }
        public static List <Move> GenerateMoves(Board board, Piece.PieceColour colour)
        {
            List <Move> moves = GeneratePseudoLegalMoves(board, colour);

            Piece.PieceColour opponent_colour = colour == Piece.PieceColour.White ? Piece.PieceColour.Black : Piece.PieceColour.White;
            List <Move>       pruned_moves    = new();

            #region verify normal moves
            foreach (Move move in moves)
            {
                Board      test_board  = Board.SimulateMove(move, board);
                Vector2Int king_square = default;
                for (var y = 0; y < Board.GridSize; y++)
                {
                    for (var x = 0; x < Board.GridSize; x++)
                    {
                        if (test_board.Cells[x, y].MyPieceType == Piece.PieceType.King && test_board.Cells[x, y].MyPieceColour == board.ColourToMove)
                        {
                            king_square = new Vector2Int(x, y);
                        }
                    }
                }

                //order is important - make move, simulate based on board after that move so pins work
                //we can use pseudolegal moves because even if the piece is pinned, it still counts as being able to capture the king
                List <Move> opponent_responses = GeneratePseudoLegalMoves(test_board, opponent_colour);

                if (opponent_responses.Any(response => response.TargetSquare == king_square))
                {
                    //opponent can capture king - so last move was illegal
                }
                else
                {
                    pruned_moves.Add(move);
                }
            }
            #endregion

            #region castling
            Vector2Int king_start_square = default;
            for (var y = 0; y < Board.GridSize; y++)
            {
                for (var x = 0; x < Board.GridSize; x++)
                {
                    if (board.Cells[x, y].MyPieceType == Piece.PieceType.King && board.Cells[x, y].MyPieceColour == board.ColourToMove)
                    {
                        king_start_square = new Vector2Int(x, y);
                    }
                }
            }

            for (int y = 0; y < Board.GridSize; y++)
            {
                for (int x = 0; x < Board.GridSize; x++)
                {
                    Piece piece = board.Cells[x, y];
                    Piece king  = board.Cells[king_start_square.x, king_start_square.y];

                    List <Move> opponent_moves       = GeneratePseudoLegalMoves(board, opponent_colour);
                    bool        fen_castle_kingside  = board.ColourToMove == Piece.PieceColour.White ? board.fen_white_kingside_castle : board.fen_black_kingside_castle;
                    bool        fen_castle_queenside = board.ColourToMove == Piece.PieceColour.White ? board.fen_white_queenside_castle : board.fen_black_queenside_castle;

                    #region kingside
                    if (piece.MyPieceType == Piece.PieceType.Rook && x > king_start_square.x && piece.MyPieceColour == board.ColourToMove &&
                        king_start_square.y == y && Math.Abs(king_start_square.x - x) == 3 && !piece.HasMovedBefore && !king.HasMovedBefore && fen_castle_kingside)
                    {
                        var  rook_start_square     = new Vector2Int(x, y);
                        bool passing_through_check = false;
                        bool piece_in_way          = false;

                        //check if KING is passing through check or starting in check
                        for (var i = 0; i < 3; i++)
                        {
                            if (opponent_moves.Any(response => response.TargetSquare == new Vector2Int(king_start_square.x + i, king_start_square.y)))
                            {
                                passing_through_check = true;
                            }
                        }

                        //check if there are any pieces in the way
                        for (var i = 1; i < 3; i++)
                        {
                            if (board.Cells[king_start_square.x + i, king_start_square.y].MyPieceType != Piece.PieceType.None)
                            {
                                piece_in_way = true;
                            }
                        }

                        //are we allowed to castle?
                        if (!passing_through_check && !piece_in_way)
                        {
                            var king_target_square = new Vector2Int(king_start_square.x + 2, king_start_square.y);
                            pruned_moves.Add(new Move(king_start_square, king_target_square, true));
                        }
                    }
                    #endregion
                    #region queenside
                    else if (piece.MyPieceType == Piece.PieceType.Rook && x < king_start_square.x && piece.MyPieceColour == board.ColourToMove &&
                             king_start_square.y == y && Math.Abs(king_start_square.x - x) == 4 && !piece.HasMovedBefore && !king.HasMovedBefore && fen_castle_queenside)
                    {
                        var  rook_start_square     = new Vector2Int(x, y);
                        bool passing_through_check = false;
                        bool piece_in_way          = false;

                        for (var i = 0; i > -3; i--)
                        {
                            if (opponent_moves.Any(response => response.TargetSquare == new Vector2Int(king_start_square.x + i, king_start_square.y)))
                            {
                                passing_through_check = true;
                            }
                        }

                        for (var i = 1; i < 4; i++)
                        {
                            if (board.Cells[rook_start_square.x + i, rook_start_square.y].MyPieceType != Piece.PieceType.None)
                            {
                                piece_in_way = true;
                            }
                        }

                        if (!piece.HasMovedBefore && !king.HasMovedBefore && !passing_through_check && !piece_in_way)
                        {
                            var king_target_square = new Vector2Int(king_start_square.x - 2, king_start_square.y);

                            pruned_moves.Add(new Move(king_start_square, king_target_square, true));
                        }
                    }
                    #endregion
                }
            }
            #endregion

            return(pruned_moves);
        }
 public static List <Move> GenerateMoves(Board board)
 {
     Piece.PieceColour colour = board.ColourToMove;
     return(GenerateMoves(board, colour));
 }
예제 #5
0
    private bool isSquareAttackedByOtherSide(Vector2 pos, Piece.PieceColour colour)
    {
        if (colour == Piece.PieceColour.Black)
        {
            colour = Piece.PieceColour.White;
        }
        else
        {
            colour = Piece.PieceColour.Black;
        }

        List <Vector2> attacks = new List <Vector2>();

        foreach (Piece piece in board.GetPiecesOfColour(colour))
        {
            switch (piece.type)
            {
            case Piece.PieceType.Pawn:
                if (piece.colour == Piece.PieceColour.White)
                {
                    attacks.Add(new Vector2(piece.BoardPosition.x + 1, piece.BoardPosition.y + 1));
                    attacks.Add(new Vector2(piece.BoardPosition.x - 1, piece.BoardPosition.y + 1));
                }
                if (piece.colour == Piece.PieceColour.Black)
                {
                    attacks.Add(new Vector2(piece.BoardPosition.x + 1, piece.BoardPosition.y - 1));
                    attacks.Add(new Vector2(piece.BoardPosition.x - 1, piece.BoardPosition.y - 1));
                }
                break;

            case Piece.PieceType.Knight:
                for (int i = -1; i < 2; i += 2)
                {
                    for (int j = -1; j < 2; j += 2)
                    {
                        Vector2 checkpos = new Vector2(piece.BoardPosition.x + 2 * i, piece.BoardPosition.y + 1 * j);
                        attacks.Add(checkpos);
                    }
                }
                for (int i = -1; i < 2; i += 2)
                {
                    for (int j = -1; j < 2; j += 2)
                    {
                        Vector2 checkpos = new Vector2(piece.BoardPosition.x + 1 * i, piece.BoardPosition.y + 2 * j);
                        if (!board.isSquareOccupied(checkpos))
                        {
                            attacks.Add(checkpos);
                        }
                        else
                        {
                            if (board.GetPieceOnSquare(checkpos).colour != piece.colour)
                            {
                                attacks.Add(checkpos);
                            }
                        }
                    }
                }
                break;

            case Piece.PieceType.Bishop:
                for (int i = -1; i < 2; i += 2)
                {
                    for (int j = -1; j < 2; j += 2)
                    {
                        bool    inbounds   = true;
                        bool    foundPiece = false;
                        Vector2 checkpos   = new Vector2(piece.BoardPosition.x + i, piece.BoardPosition.y + j);
                        inbounds = isPosInBounds(checkpos);
                        while (inbounds && !foundPiece)
                        {
                            if (board.isSquareOccupied(checkpos))
                            {
                                foundPiece = true;
                            }
                            attacks.Add(checkpos);

                            checkpos = new Vector2(checkpos.x + i, checkpos.y + j);
                            inbounds = isPosInBounds(checkpos);
                        }
                    }
                }
                break;

            case Piece.PieceType.Rook:
                for (int i = -1; i < 2; i += 2)
                {
                    Vector2 checkpos   = new Vector2(piece.BoardPosition.x + i, piece.BoardPosition.y);
                    bool    inbounds   = true;
                    bool    foundPiece = false;
                    inbounds = isPosInBounds(checkpos);
                    while (inbounds && !foundPiece)
                    {
                        if (board.isSquareOccupied(checkpos))
                        {
                            foundPiece = true;
                        }
                        attacks.Add(checkpos);

                        checkpos = new Vector2(checkpos.x + i, checkpos.y);
                        inbounds = isPosInBounds(checkpos);
                    }
                }
                for (int i = -1; i < 2; i += 2)
                {
                    Vector2 checkpos   = new Vector2(piece.BoardPosition.x, piece.BoardPosition.y + i);
                    bool    inbounds   = true;
                    bool    foundPiece = false;
                    inbounds = isPosInBounds(checkpos);
                    while (inbounds && !foundPiece)
                    {
                        if (board.isSquareOccupied(checkpos))
                        {
                            foundPiece = true;
                        }
                        attacks.Add(checkpos);

                        checkpos = new Vector2(checkpos.x, checkpos.y + i);
                        inbounds = isPosInBounds(checkpos);
                    }
                }
                break;

            case Piece.PieceType.Queen:
                for (int i = -1; i < 2; i += 2)
                {
                    for (int j = -1; j < 2; j += 2)
                    {
                        bool    inbounds   = true;
                        bool    foundPiece = false;
                        Vector2 checkpos   = new Vector2(piece.BoardPosition.x + i, piece.BoardPosition.y + j);
                        inbounds = isPosInBounds(checkpos);
                        while (inbounds && !foundPiece)
                        {
                            if (board.isSquareOccupied(checkpos))
                            {
                                foundPiece = true;
                            }
                            attacks.Add(checkpos);

                            checkpos = new Vector2(checkpos.x + i, checkpos.y + j);
                            inbounds = isPosInBounds(checkpos);
                        }
                    }
                }
                for (int i = -1; i < 2; i += 2)
                {
                    Vector2 checkpos   = new Vector2(piece.BoardPosition.x + i, piece.BoardPosition.y);
                    bool    inbounds   = true;
                    bool    foundPiece = false;
                    inbounds = isPosInBounds(checkpos);
                    while (inbounds && !foundPiece)
                    {
                        if (board.isSquareOccupied(checkpos))
                        {
                            foundPiece = true;
                        }
                        attacks.Add(checkpos);

                        checkpos = new Vector2(checkpos.x + i, checkpos.y);
                        inbounds = isPosInBounds(checkpos);
                    }
                }
                for (int i = -1; i < 2; i += 2)
                {
                    Vector2 checkpos   = new Vector2(piece.BoardPosition.x, piece.BoardPosition.y + i);
                    bool    inbounds   = true;
                    bool    foundPiece = false;
                    inbounds = isPosInBounds(checkpos);
                    while (inbounds && !foundPiece)
                    {
                        if (board.isSquareOccupied(checkpos))
                        {
                            foundPiece = true;
                        }
                        attacks.Add(checkpos);

                        checkpos = new Vector2(checkpos.x, checkpos.y + i);
                        inbounds = isPosInBounds(checkpos);
                    }
                }
                break;

            case Piece.PieceType.King:
                for (int i = -1; i < 2; i += 2)
                {
                    for (int j = -1; j < 2; j += 2)
                    {
                        bool    inbounds = true;
                        Vector2 checkpos = new Vector2(piece.BoardPosition.x + i, piece.BoardPosition.y + j);
                        inbounds = isPosInBounds(checkpos);
                        if (inbounds)
                        {
                            attacks.Add(checkpos);
                        }
                    }
                }
                for (int i = -1; i < 2; i += 2)
                {
                    Vector2 checkpos = new Vector2(piece.BoardPosition.x + i, piece.BoardPosition.y);
                    bool    inbounds = true;
                    inbounds = isPosInBounds(checkpos);
                    if (inbounds)
                    {
                        attacks.Add(checkpos);
                    }
                }
                for (int i = -1; i < 2; i += 2)
                {
                    Vector2 checkpos = new Vector2(piece.BoardPosition.x, piece.BoardPosition.y + i);
                    bool    inbounds = true;
                    inbounds = isPosInBounds(checkpos);
                    if (inbounds)
                    {
                        attacks.Add(checkpos);
                    }
                }
                break;
            }
        }

        return(attacks.Contains(pos));
    }