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
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
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
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
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)
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
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
def _material_balance(self): return (chess.pop_count(self.occupied_co[self.turn]) - chess.pop_count(self.occupied_co[not self.turn]))
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)
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