예제 #1
0
    def is_insufficient_material(self):
        # Enough material.
        if self.knights or self.rooks or self.queens or self.kings:
            return False

        # Must have bishops.
        if not (self.occupied_co[chess.WHITE] & self.bishops and self.occupied_co[chess.BLACK] & self.bishops):
            return False

        # All pawns must be blocked.
        w_pawns = self.pawns & self.occupied_co[chess.WHITE]
        b_pawns = self.pawns & self.occupied_co[chess.BLACK]

        b_blocked_pawns = chess.shift_up(w_pawns) & b_pawns
        w_blocked_pawns = chess.shift_down(b_pawns) & w_pawns

        if (b_blocked_pawns | w_blocked_pawns) != self.pawns:
            return False

        turn = self.turn
        turn = chess.WHITE
        if any(self.generate_pseudo_legal_moves(self.pawns)):
            return False
        turn = chess.BLACK
        if any(self.generate_pseudo_legal_moves(self.pawns)):
            return False
        self.turn = turn

        # Bishop and pawns of each side are on distinct color complexes.
        if self.occupied_co[chess.WHITE] & chess.BB_DARK_SQUARES == 0:
            return self.occupied_co[chess.BLACK] & chess.BB_LIGHT_SQUARES == 0
        elif self.occupied_co[chess.WHITE] & chess.BB_LIGHT_SQUARES == 0:
            return self.occupied_co[chess.BLACK] & chess.BB_DARK_SQUARES == 0
        else:
            return False
예제 #2
0
    def is_insufficient_material(self):
        # Enough material.
        if self.knights or self.rooks or self.queens or self.kings:
            return False

        # Must have bishops.
        if not (self.occupied_co[chess.WHITE] & self.bishops and self.occupied_co[chess.BLACK] & self.bishops):
            return False

        # All pawns must be blocked.
        w_pawns = self.pawns & self.occupied_co[chess.WHITE]
        b_pawns = self.pawns & self.occupied_co[chess.BLACK]

        b_blocked_pawns = chess.shift_up(w_pawns) & b_pawns
        w_blocked_pawns = chess.shift_down(b_pawns) & w_pawns

        if (b_blocked_pawns | w_blocked_pawns) != self.pawns:
            return False

        turn = self.turn
        turn = chess.WHITE
        if any(self.generate_pseudo_legal_moves(self.pawns)):
            return False
        turn = chess.BLACK
        if any(self.generate_pseudo_legal_moves(self.pawns)):
            return False
        self.turn = turn

        # Bishop and pawns of each side are on distinct color complexes.
        if self.occupied_co[chess.WHITE] & chess.BB_DARK_SQUARES == 0:
            return self.occupied_co[chess.BLACK] & chess.BB_LIGHT_SQUARES == 0
        elif self.occupied_co[chess.WHITE] & chess.BB_LIGHT_SQUARES == 0:
            return self.occupied_co[chess.BLACK] & chess.BB_DARK_SQUARES == 0
        else:
            return False
    def get_special_flags(self, board, castling_rights):
        special_flags = 0

        # Hash in the castling flags [768 ... 771].
        if castling_rights[0]:  # white_king
            special_flags ^= POLYGLOT_RANDOM_ARRAY[768]
        if castling_rights[1]:  # white_queen
            special_flags ^= POLYGLOT_RANDOM_ARRAY[769]
        if castling_rights[2]:  # black_king
            special_flags ^= POLYGLOT_RANDOM_ARRAY[770]
        if castling_rights[3]:  # black_queen
            special_flags ^= POLYGLOT_RANDOM_ARRAY[771]

        # Hash in the en passant file [772 ... 779].
        if board.ep_square:
            # But only if there's actually a pawn ready to capture it. Legality
            # of the potential capture is irrelevant.
            if board.turn == chess.WHITE:
                ep_mask = chess.shift_down(chess.BB_SQUARES[board.ep_square])
            else:
                ep_mask = chess.shift_up(chess.BB_SQUARES[board.ep_square])

            ep_mask = chess.shift_left(ep_mask) | chess.shift_right(ep_mask)

            if ep_mask & board.pawns & board.occupied_co[board.turn]:
                rand = POLYGLOT_RANDOM_ARRAY[772 + chess.square_file(board.ep_square)]
                special_flags ^= rand

        # Hash in turn [780]
        if board.turn == chess.WHITE:
            special_flags ^= POLYGLOT_RANDOM_ARRAY[780]

        return special_flags
예제 #4
0
    def hash_ep_square(self, board: chess.Board) -> int:
        # Hash in the en passant file.
        if board.ep_square:
            # But only if there's actually a pawn ready to capture it. Legality
            # of the potential capture is irrelevant.
            if board.turn == chess.WHITE:
                ep_mask = chess.shift_down(chess.BB_SQUARES[board.ep_square])
            else:
                ep_mask = chess.shift_up(chess.BB_SQUARES[board.ep_square])
            ep_mask = chess.shift_left(ep_mask) | chess.shift_right(ep_mask)

            if ep_mask & board.pawns & board.occupied_co[board.turn]:
                return self.array[772 + chess.square_file(board.ep_square)]
        return 0
예제 #5
0
def zobrist_hash(board):
    """
    Calculates the Polyglot Zobrist hash of the position.

    A zobrist hash is an exclusive or of pseudo random values picked from
    an array. Which values are picked is decided by features of the
    position, such as piece positions, castling rights and en passant
    squares. For this implementation an array of 781 values is required.
    """
    # Hash in the board setup.
    zobrist_hash = board_zobrist_hash(board)

    # Hash in the castling flags.
    if board.has_kingside_castling_rights(chess.WHITE):
        zobrist_hash ^= POLYGLOT_RANDOM_ARRAY[768]
    if board.has_queenside_castling_rights(chess.WHITE):
        zobrist_hash ^= POLYGLOT_RANDOM_ARRAY[768 + 1]
    if board.has_kingside_castling_rights(chess.BLACK):
        zobrist_hash ^= POLYGLOT_RANDOM_ARRAY[768 + 2]
    if board.has_queenside_castling_rights(chess.BLACK):
        zobrist_hash ^= POLYGLOT_RANDOM_ARRAY[768 + 3]

    # Hash in the en passant file.
    if board.ep_square:
        # But only if theres actually a pawn ready to capture it. Legality
        # of the potential capture is irrelevant.
        if board.turn == chess.WHITE:
            ep_mask = chess.shift_down(chess.BB_SQUARES[board.ep_square])
        else:
            ep_mask = chess.shift_up(chess.BB_SQUARES[board.ep_square])
        ep_mask = chess.shift_left(ep_mask) | chess.shift_right(ep_mask)

        if ep_mask & board.pawns & board.occupied_co[board.turn]:
            zobrist_hash ^= POLYGLOT_RANDOM_ARRAY[772 + chess.square_file(board.ep_square)]

    # Hash in the turn.
    if board.turn == chess.WHITE:
        zobrist_hash ^= POLYGLOT_RANDOM_ARRAY[780]

    return zobrist_hash
예제 #6
0
파일: hash.py 프로젝트: rzhadev/Dio
def apply_hash(key, board, move: chess.Move):
    pivot = 1 if board.piece_at(move.from_square).color else 0

    from_square = move.from_square
    from_piece_type = board.piece_type_at(move.from_square)
    fpiece_index = (typing.cast(chess.PieceType, from_piece_type) -
                    1) * 2 + pivot
    to_square = move.to_square

    # move the piece at the source square
    key ^= Z_ARR[64 * fpiece_index + from_square]
    key ^= Z_ARR[64 * fpiece_index + to_square]

    # update castling rights
    if (from_piece_type == chess.KING):
        # castling move
        if (chess.square_distance(from_square, to_square) > 1):
            rook_index = (typing.cast(chess.PieceType, chess.ROOK) -
                          1) * 2 + pivot

            # queenside
            if (to_square == chess.C1 or to_square == chess.C8):
                if (board.turn):
                    key ^= Z_ARR[64 * rook_index + chess.A1]
                    key ^= Z_ARR[64 * rook_index + chess.D1]
                    key ^= Z_ARR[769]
                else:
                    key ^= Z_ARR[64 * rook_index + chess.A8]
                    key ^= Z_ARR[64 * rook_index + chess.D8]
                    key ^= Z_ARR[771]

            # kingside
            elif (to_square == chess.G1 or to_square == chess.G8):
                if (board.turn):
                    key ^= Z_ARR[64 * rook_index + chess.H1]
                    key ^= Z_ARR[64 * rook_index + chess.F1]
                    key ^= Z_ARR[768]
                else:
                    key ^= Z_ARR[64 * rook_index + chess.H8]
                    key ^= Z_ARR[64 * rook_index + chess.F8]
                    key ^= Z_ARR[770]
        # non castling move with king moving
        else:
            if board.has_castling_rights(board.turn):
                if board.turn:
                    key ^= Z_ARR[768]
                    key ^= Z_ARR[769]
                else:
                    key ^= Z_ARR[770]
                    key ^= Z_ARR[771]

    elif from_piece_type == chess.ROOK:
        if (board.has_queenside_castling_rights(board.turn)
                and from_square == chess.A1 or from_square == chess.A8):
            if board.turn:
                key ^= Z_ARR[769]
            else:
                key ^= Z_ARR[771]
        if (board.has_kingside_castling_rights(board.turn)
                and (from_square == chess.H1 or from_square == chess.H8)):
            if board.turn:
                key ^= Z_ARR[768]
            else:
                key ^= Z_ARR[770]

    # capture moves
    if board.is_capture(move) and not board.is_en_passant(move):
        # remove the piece at the moving to square
        to_piece_type = board.piece_type_at(to_square)
        tpiece_index = (typing.cast(chess.PieceType, to_piece_type) - 1) * \
            2 + (1 if board.piece_at(move.to_square).color else 0)
        key ^= Z_ARR[64 * tpiece_index + to_square]

    # promotion
    if (from_piece_type == chess.PAWN
            and (chess.square_rank(to_square) == 0
                 or chess.square_rank(to_square) == 7)):
        if move.promotion:
            new_p_index = (typing.cast(chess.PieceType, move.promotion) -
                           1) * 2 + pivot
            # replace current piece type with new piece type
            key ^= Z_ARR[64 * fpiece_index + to_square]
            key ^= Z_ARR[64 * new_p_index + to_square]

    # update ep rights (chess.polyglot)
    if board.ep_square:
        if board.turn == chess.WHITE:
            ep_mask = chess.shift_down(chess.BB_SQUARES[board.ep_square])
        else:
            ep_mask = chess.shift_up(chess.BB_SQUARES[board.ep_square])
        ep_mask = chess.shift_left(ep_mask) | chess.shift_right(ep_mask)

        if ep_mask & board.pawns & board.occupied_co[board.turn]:
            key ^= Z_ARR[772 + chess.square_file(board.ep_square)]

    if (board.is_en_passant(move)):
        to_square_file = chess.square_file(to_square)
        if board.turn:
            capture_rank = chess.square_rank(to_square) - 1
            cap_square = chess.square(to_square_file, capture_rank)
            tpiece_index = (typing.cast(chess.PieceType, chess.PAWN) - 1) * 2
            key ^= Z_ARR[64 * tpiece_index + cap_square]
        else:
            capture_rank = chess.square_rank(to_square) + 1
            cap_square = chess.square(to_square_file, capture_rank)
            tpiece_index = (typing.cast(chess.PieceType, chess.PAWN) -
                            1) * 2 + 1
            key ^= Z_ARR[64 * tpiece_index + cap_square]

    return key