Пример #1
0
    def is_insufficient_material(self):
        if self.is_variant_loss() or self.is_variant_win():
            return False

        if self.pawns or self.queens:
            return False

        if chess.pop_count(self.KNIGHT | self.BISHOP | self.ROOK) == 1:
            return True

        # Only knights.
        if self.occupied == (self.kings | self.knights):
            return chess.pop_count(self.knights) <= 2

        # Only bishops.
        if self.occupied == (self.kings | self.bishops):
            # All bishops on opposite colors.
            if not self.pieces_mask(chess.BISHOP,
                                    chess.WHITE) & chess.BB_DARK_SQUARES:
                return not self.pieces_mask(
                    chess.BISHOP, chess.BLACK) & chess.BB_LIGHT_SQUARES
            if not self.pieces_mask(chess.BISHOP,
                                    chess.WHITE) & chess.BB_LIGHT_SQUARES:
                return not self.pieces_mask(
                    chess.BISHOP, chess.BLACK) & chess.BB_DARK_SQUARES

        return False
Пример #2
0
    def status(self):
        status = super(CrazyhouseBoard, self).status()

        if chess.pop_count(self.pawns) + self.pockets[chess.WHITE].count(chess.PAWN) + self.pockets[chess.BLACK].count(chess.PAWN) <= 16:
            status &= ~chess.STATUS_TOO_MANY_BLACK_PAWNS
            status &= ~chess.STATUS_TOO_MANY_WHITE_PAWNS

        if chess.pop_count(self.occupied) + len(self.pockets[chess.WHITE]) + len(self.pockets[chess.BLACK]) <= 32:
            status &= ~chess.STATUS_TOO_MANY_BLACK_PIECES
            status &= ~chess.STATUS_TOO_MANY_WHITE_PIECES

        return status
Пример #3
0
    def status(self):
        status = super(CrazyhouseBoard, self).status()

        if chess.pop_count(self.pawns) + self.pockets[chess.WHITE].count(chess.PAWN) + self.pockets[chess.BLACK].count(chess.PAWN) <= 16:
            status &= ~chess.STATUS_TOO_MANY_BLACK_PAWNS
            status &= ~chess.STATUS_TOO_MANY_WHITE_PAWNS

        if chess.pop_count(self.occupied) + len(self.pockets[chess.WHITE]) + len(self.pockets[chess.BLACK]) <= 32:
            status &= ~chess.STATUS_TOO_MANY_BLACK_PIECES
            status &= ~chess.STATUS_TOO_MANY_WHITE_PIECES

        return status
Пример #4
0
    def legal_drop_squares_mask(self):
        king_bb = self.kings & self.occupied_co[self.turn]
        king_square = chess.bit_scan(king_bb)
        if king_square is None or king_square == -1:
            return ~self.occupied

        king_attackers = self.attackers_mask(not self.turn, king_square)
        num_attackers = chess.pop_count(king_attackers)

        if num_attackers == 0:
            return ~self.occupied
        elif num_attackers == 1:
            king_rank_mask = chess.RANK_MASK[king_bb]
            king_file_mask = chess.FILE_MASK[king_bb]
            king_diag_ne = chess.DIAG_MASK_NE[king_bb]
            king_diag_nw = chess.DIAG_MASK_NW[king_bb]

            if king_rank_mask == chess.RANK_MASK[king_attackers]:
                rank_pieces = king_rank_mask & self.occupied
                return chess.RANK_ATTACKS[king_bb][rank_pieces] & ~self.occupied & chess.RANK_ATTACKS[king_attackers][rank_pieces]
            elif king_file_mask == chess.FILE_MASK[king_attackers]:
                file_pieces = king_file_mask & self.occupied
                return chess.FILE_ATTACKS[king_bb][file_pieces] & ~self.occupied & chess.FILE_ATTACKS[king_attackers][file_pieces]
            elif king_diag_ne == chess.DIAG_MASK_NE[king_attackers]:
                ne_pieces = king_diag_ne & self.occupied
                return chess.DIAG_ATTACKS_NE[king_bb][ne_pieces] & ~self.occupied & chess.DIAG_ATTACKS_NE[king_attackers][ne_pieces]
            elif king_diag_nw == chess.DIAG_MASK_NW[king_attackers]:
                nw_pieces = king_diag_nw & self.occupied
                return chess.DIAG_ATTACKS_NW[king_bb][nw_pieces] & ~self.occupied & chess.DIAG_ATTACKS_NW[king_attackers][nw_pieces]

        return chess.BB_VOID
Пример #5
0
    def legal_drop_squares_mask(self):
        king_bb = self.kings & self.occupied_co[self.turn]
        king_square = chess.bit_scan(king_bb)
        if king_square is None or king_square == -1:
            return ~self.occupied

        king_attackers = self.attackers_mask(not self.turn, king_square)
        num_attackers = chess.pop_count(king_attackers)

        if num_attackers == 0:
            return ~self.occupied
        elif num_attackers == 1:
            king_rank_mask = chess.RANK_MASK[king_bb]
            king_file_mask = chess.FILE_MASK[king_bb]
            king_diag_ne = chess.DIAG_MASK_NE[king_bb]
            king_diag_nw = chess.DIAG_MASK_NW[king_bb]

            if king_rank_mask == chess.RANK_MASK[king_attackers]:
                rank_pieces = king_rank_mask & self.occupied
                return chess.RANK_ATTACKS[king_bb][rank_pieces] & ~self.occupied & chess.RANK_ATTACKS[king_attackers][rank_pieces]
            elif king_file_mask == chess.FILE_MASK[king_attackers]:
                file_pieces = king_file_mask & self.occupied
                return chess.FILE_ATTACKS[king_bb][file_pieces] & ~self.occupied & chess.FILE_ATTACKS[king_attackers][file_pieces]
            elif king_diag_ne == chess.DIAG_MASK_NE[king_attackers]:
                ne_pieces = king_diag_ne & self.occupied
                return chess.DIAG_ATTACKS_NE[king_bb][ne_pieces] & ~self.occupied & chess.DIAG_ATTACKS_NE[king_attackers][ne_pieces]
            elif king_diag_nw == chess.DIAG_MASK_NW[king_attackers]:
                nw_pieces = king_diag_nw & self.occupied
                return chess.DIAG_ATTACKS_NW[king_bb][nw_pieces] & ~self.occupied & chess.DIAG_ATTACKS_NW[king_attackers][nw_pieces]

        return chess.BB_VOID
Пример #6
0
 def status(self):
     status = super(RacingKingsBoard, self).status()
     if self.is_check():
         status |= chess.STATUS_RACE_CHECK
     if self.turn == chess.BLACK and all(self.occupied_co[co] & self.kings & chess.BB_RANK_8 for co in chess.COLORS):
         status |= chess.STATUS_RACE_OVER
     if self.pawns:
         status |= chess.STATUS_RACE_MATERIAL
     for color in chess.COLORS:
         if chess.pop_count(self.occupied_co[color] & self.knights) > 2:
             status |= chess.STATUS_RACE_MATERIAL
         if chess.pop_count(self.occupied_co[color] & self.bishops) > 2:
             status |= chess.STATUS_RACE_MATERIAL
         if chess.pop_count(self.occupied_co[color] & self.rooks) > 2:
             status |= chess.STATUS_RACE_MATERIAL
         if chess.pop_count(self.occupied_co[color] & self.queens) > 1:
             status |= chess.STATUS_RACE_MATERIAL
     return status
Пример #7
0
    def test_clear(self):
        board = chess.Bitboard()
        board.clear()

        self.assertEqual(board.turn, chess.WHITE)
        self.assertEqual(board.fullmove_number, 1)
        self.assertEqual(board.halfmove_clock, 0)
        self.assertEqual(board.castling_rights, chess.CASTLING_NONE)
        self.assertFalse(board.ep_square)

        self.assertFalse(board.piece_at(chess.E1))
        self.assertEqual(chess.pop_count(board.occupied), 0)
Пример #8
0
    def is_insufficient_material(self):
        if self.is_variant_loss() or self.is_variant_win():
            return False

        if self.pawns or self.queens:
            return False

        if chess.pop_count(self.KNIGHT | self.BISHOP | self.ROOK) == 1:
            return True

        # Only knights.
        if self.occupied == (self.kings | self.knights):
            return chess.pop_count(self.knights) <= 2

        # Only bishops.
        if self.occupied == (self.kings | self.bishops):
            # All bishops on opposite colors.
            if not self.pieces_mask(chess.BISHOP, chess.WHITE) & chess.BB_DARK_SQUARES:
                return not self.pieces_mask(chess.BISHOP, chess.BLACK) & chess.BB_LIGHT_SQUARES
            if not self.pieces_mask(chess.BISHOP, chess.WHITE) & chess.BB_LIGHT_SQUARES:
                return not self.pieces_mask(chess.BISHOP, chess.BLACK) & chess.BB_DARK_SQUARES

        return False
Пример #9
0
    def status(self):
        status = super(HordeBoard, self).status()
        status &= ~chess.STATUS_NO_WHITE_KING

        if chess.pop_count(self.occupied_co[chess.WHITE]) <= 36:
            status &= ~chess.STATUS_TOO_MANY_WHITE_PIECES
            status &= ~chess.STATUS_TOO_MANY_WHITE_PAWNS

        if not self.pawns & chess.BB_RANK_8 and not self.occupied_co[chess.BLACK] & chess.BB_RANK_1:
            status &= ~chess.STATUS_PAWNS_ON_BACKRANK

        if self.occupied_co[chess.WHITE] & self.kings:
            status |= chess.STATUS_TOO_MANY_KINGS

        return status
Пример #10
0
    def status(self):
        status = super(HordeBoard, self).status()
        status &= ~chess.STATUS_NO_WHITE_KING

        if chess.pop_count(self.occupied_co[chess.WHITE]) <= 36:
            status &= ~chess.STATUS_TOO_MANY_WHITE_PIECES
            status &= ~chess.STATUS_TOO_MANY_WHITE_PAWNS

        if not self.pawns & chess.BB_RANK_8 and not self.occupied_co[chess.BLACK] & chess.BB_RANK_1:
            status &= ~chess.STATUS_PAWNS_ON_BACKRANK

        if self.occupied_co[chess.WHITE] & self.kings:
            status |= chess.STATUS_TOO_MANY_KINGS

        return status
Пример #11
0
 def _material_balance(self):
     return (chess.pop_count(self.occupied_co[self.turn]) -
             chess.pop_count(self.occupied_co[not self.turn]))
Пример #12
0
def material(board):
    name = ""
    name += "K" * chess.pop_count(board.kings & board.occupied_co[chess.WHITE])
    name += "Q" * chess.pop_count(board.queens & board.occupied_co[chess.WHITE])
    name += "R" * chess.pop_count(board.rooks & board.occupied_co[chess.WHITE])
    name += "B" * chess.pop_count(board.bishops & board.occupied_co[chess.WHITE])
    name += "N" * chess.pop_count(board.knights & board.occupied_co[chess.WHITE])
    name += "P" * chess.pop_count(board.pawns & board.occupied_co[chess.WHITE])
    name += "v"
    name += "K" * chess.pop_count(board.kings & board.occupied_co[chess.BLACK])
    name += "Q" * chess.pop_count(board.queens & board.occupied_co[chess.BLACK])
    name += "R" * chess.pop_count(board.rooks & board.occupied_co[chess.BLACK])
    name += "B" * chess.pop_count(board.bishops & board.occupied_co[chess.BLACK])
    name += "N" * chess.pop_count(board.knights & board.occupied_co[chess.BLACK])
    name += "P" * chess.pop_count(board.pawns & board.occupied_co[chess.BLACK])
    return name
 def material_count(self):
     return chess.pop_count(self.position.occupied)
def material_count(board):
    return chess.pop_count(board.occupied)
Пример #15
0
 def _material_balance(self):
     return (chess.pop_count(self.occupied_co[self.turn]) -
             chess.pop_count(self.occupied_co[not self.turn]))
 def material_count(self):
     return chess.pop_count(self.position.occupied)
Пример #17
0
def material(board):
    name = ""
    name += "K" * chess.pop_count(board.kings & board.occupied_co[chess.WHITE])
    name += "Q" * chess.pop_count(board.queens
                                  & board.occupied_co[chess.WHITE])
    name += "R" * chess.pop_count(board.rooks & board.occupied_co[chess.WHITE])
    name += "B" * chess.pop_count(board.bishops
                                  & board.occupied_co[chess.WHITE])
    name += "N" * chess.pop_count(board.knights
                                  & board.occupied_co[chess.WHITE])
    name += "P" * chess.pop_count(board.pawns & board.occupied_co[chess.WHITE])
    name += "v"
    name += "K" * chess.pop_count(board.kings & board.occupied_co[chess.BLACK])
    name += "Q" * chess.pop_count(board.queens
                                  & board.occupied_co[chess.BLACK])
    name += "R" * chess.pop_count(board.rooks & board.occupied_co[chess.BLACK])
    name += "B" * chess.pop_count(board.bishops
                                  & board.occupied_co[chess.BLACK])
    name += "N" * chess.pop_count(board.knights
                                  & board.occupied_co[chess.BLACK])
    name += "P" * chess.pop_count(board.pawns & board.occupied_co[chess.BLACK])
    return name
Пример #18
0
    def _probe_hard(self, board, wdl_only=False):
        if chess.pop_count(board.occupied_co[chess.WHITE]) > 16:
            return None
        if chess.pop_count(board.occupied_co[chess.BLACK]) > 16:
            return None

        if board.is_insufficient_material():
            return 0

        if board.castling_rights:
            return None

        stm = ctypes.c_uint(0 if board.turn == chess.WHITE else 1)
        ep_square = ctypes.c_uint(board.ep_square if board.ep_square else 64)
        castling = ctypes.c_uint(0)

        c_ws = (ctypes.c_uint * 17)()
        c_wp = (ctypes.c_ubyte * 17)()

        i = -1
        for i, square in enumerate(chess.SquareSet(board.occupied_co[chess.WHITE])):
            c_ws[i] = square
            c_wp[i] = board.piece_type_at(square)

        c_ws[i + 1] = 64
        c_wp[i + 1] = 0

        c_bs = (ctypes.c_uint * 17)()
        c_bp = (ctypes.c_ubyte * 17)()

        i = -1
        for i, square in enumerate(chess.SquareSet(board.occupied_co[chess.BLACK])):
            c_bs[i] = square
            c_bp[i] = board.piece_type_at(square)

        c_bs[i + 1] = 64
        c_bp[i + 1] = 0

        # Do a hard probe.
        info = ctypes.c_uint()
        pliestomate = ctypes.c_uint()
        if not wdl_only:
            ret = self.libgtb.tb_probe_hard(stm, ep_square, castling, c_ws, c_bs, c_wp, c_bp, ctypes.byref(info), ctypes.byref(pliestomate))
            dtm = int(pliestomate.value)
        else:
            ret = self.libgtb.tb_probe_WDL_hard(stm, ep_square, castling, c_ws, c_bs, c_wp, c_bp, ctypes.byref(info))
            dtm = 1

        # Probe forbidden.
        if info.value == 3:
            logging.warning("Tablebase for %s marked as forbidden", board.fen())
            return None

        # Probe failed or unknown.
        if not ret or info.value == 7:
            return None

        # Draw.
        if info.value == 0:
            return 0

        # White mates.
        if info.value == 1:
            return dtm if board.turn == chess.WHITE else -dtm

        # Black mates.
        if info.value == 2:
            return dtm if board.turn == chess.BLACK else -dtm
def material_count(board):
    return chess.pop_count(board.occupied)