Esempio n. 1
0
        public Position PlayMove(Move move)
        {
            // 'My' refers to player to move, 'other' refers to other player
            var my_player = PlayerToMove;
            var other_player = Helper.GetOtherPlayer(my_player);

            var my_pieces = GetPieces(my_player);
            var other_pieces = GetPieces(other_player);

            PlayerPieceSet new_my_pieces = null;
            if (move.IsPromotion)
            {
                Debug.Assert(move.Piece == Exports.Pieces.Pawn);
                var tmp_pieces = PlayerPieceSet.RemovePiece(my_pieces,
                    Exports.Pieces.Pawn, move.FromCell);
                new_my_pieces = PlayerPieceSet.InsertPiece(tmp_pieces,
                    move.PromoteToPiece, move.ToCell);
            }
            else if (move.IsShortCastle || move.IsLongCastle)
            {
                int base_row = my_player == Players.White ?
                    Chessboard.ROW_MIN : Chessboard.ROW_MAX;
                Debug.Assert(move.Piece == Exports.Pieces.King);
                var tmp_pieces = PlayerPieceSet.MovePiece(my_pieces,
                    Exports.Pieces.King, move.FromCell, move.ToCell);

                if (move.IsShortCastle)
                {
                    new_my_pieces = PlayerPieceSet.MovePiece(tmp_pieces,
                        Exports.Pieces.Rook,
                        ChessboardCell.CalculateValue(base_row, Chessboard.COLUMN_H),
                        ChessboardCell.CalculateValue(base_row, Chessboard.COLUMN_F));
                }
                else
                {
                    new_my_pieces = PlayerPieceSet.MovePiece(tmp_pieces,
                        Exports.Pieces.Rook,
                        ChessboardCell.CalculateValue(base_row, Chessboard.COLUMN_A),
                        ChessboardCell.CalculateValue(base_row, Chessboard.COLUMN_D));
                }
            }
            else
            {
                new_my_pieces = PlayerPieceSet.MovePiece(my_pieces,
                    move.Piece, move.FromCell, move.ToCell);
            }

            PlayerPieceSet new_other_pieces = null;
            if (move.IsCapture)
            {
                Exports.Pieces piece_to_remove = Exports.Pieces.NoPiece;
                int remove_piece_at = 0;
                if (move.IsEnPassantCapture)
                {
                    var move_to_cell = new ChessboardCell(move.ToCell);
                    remove_piece_at = ChessboardCell.CalculateValue(
                        move_to_cell.Row + (IsWhiteToMove ? -1 : 1),
                        move_to_cell.Column);
                    // Only pawns can capture en passant
                    piece_to_remove = Exports.Pieces.Pawn;
                }
                else
                {
                    remove_piece_at = move.ToCell;
                    piece_to_remove = other_pieces.GetPieceAtCell(remove_piece_at);
                }
                new_other_pieces = PlayerPieceSet.RemovePiece(other_pieces,
                    piece_to_remove, remove_piece_at);
            }
            else
            {
                // No change to other player's pieces, re-use the object
                new_other_pieces = other_pieces;
            }

            // TODO - consider memory pooling here
            var result = new Position();
            var new_white_pieces =
                IsWhiteToMove ? new_my_pieces : new_other_pieces;
            var new_black_pieces =
                IsWhiteToMove ? new_other_pieces : new_my_pieces;

            int? new_en_passant_capture_column = null;
            if (move.Piece == Exports.Pieces.Pawn)
            {
                var from = new ChessboardCell(move.FromCell);
                var to_row = new ChessboardCell(move.ToCell).Row;
                if (Math.Abs(from.Row - to_row) == 2)
                {
                    new_en_passant_capture_column = from.Column;
                }
            }

            var new_fullmove_number = FullmoveNumber;
            if (other_player == Players.White)
            {
                ++new_fullmove_number;
            }

            var new_halfmove_clock = HalfmoveClock + 1;
            if (move.Piece == Exports.Pieces.Pawn || move.IsCapture)
            {
                new_halfmove_clock = 0;
            }

            var new_white_castling_options = CalcNewCastlingOptions(Players.White,
                new_white_pieces, Chessboard.ROW_MIN);
            var new_black_castling_options = CalcNewCastlingOptions(Players.Black,
                new_black_pieces, Chessboard.ROW_MAX);

            result.Reset(new_white_pieces,
                new_black_pieces,
                other_player,
                new_white_castling_options,
                new_black_castling_options,
                new_en_passant_capture_column,
                new_fullmove_number,
                (ushort)new_halfmove_clock);

            return result;
        }