diff --git a/chess/__init__.py b/chess/__init__.py index 35d7db44e..9db05c7b1 100644 --- a/chess/__init__.py +++ b/chess/__init__.py @@ -218,6 +218,7 @@ def scan_reversed(bb, _BB_SQUARES=BB_SQUARES): yield r bb ^= _BB_SQUARES[r] +# TODO: Remove (deprecated) def bit_scan(b, n=0): string = bin(b) l = len(string) @@ -227,15 +228,16 @@ def bit_scan(b, n=0): else: return l - r - 1 - try: - from gmpy2 import popcount as pop_count + from gmpy2 import popcount except ImportError: try: - from gmpy import popcount as pop_count + from gmpy import popcount except ImportError: - def pop_count(b): - return bin(b).count("1") + def popcount(b, _bin=bin): + return _bin(b).count("1") + +pop_count = popcount # TODO: Remove alias def shift_down(b): @@ -1089,15 +1091,15 @@ def chess960_pos(self): if self.promoted: return None - if pop_count(self.bishops) != 4: + if popcount(self.bishops) != 4: return None - if pop_count(self.rooks) != 4: + if popcount(self.rooks) != 4: return None - if pop_count(self.knights) != 4: + if popcount(self.knights) != 4: return None - if pop_count(self.queens) != 2: + if popcount(self.queens) != 2: return None - if pop_count(self.kings) != 2: + if popcount(self.kings) != 2: return None if (BB_RANK_1 & self.knights) << 56 != BB_RANK_8 & self.knights: @@ -1870,7 +1872,7 @@ def is_insufficient_material(self): return False # A single knight or a single bishop. - if pop_count(self.occupied) <= 3: + if popcount(self.occupied) <= 3: return True # More than a single knight. @@ -3049,19 +3051,19 @@ def status(self): errors |= STATUS_NO_WHITE_KING if not self.occupied_co[BLACK] & self.kings: errors |= STATUS_NO_BLACK_KING - if pop_count(self.occupied & self.kings) > 2: + if popcount(self.occupied & self.kings) > 2: errors |= STATUS_TOO_MANY_KINGS # There can not be more than 16 pieces of any color. - if pop_count(self.occupied_co[WHITE]) > 16: + if popcount(self.occupied_co[WHITE]) > 16: errors |= STATUS_TOO_MANY_WHITE_PIECES - if pop_count(self.occupied_co[BLACK]) > 16: + if popcount(self.occupied_co[BLACK]) > 16: errors |= STATUS_TOO_MANY_BLACK_PIECES # There can not be more than eight pawns of any color. - if pop_count(self.occupied_co[WHITE] & self.pawns) > 8: + if popcount(self.occupied_co[WHITE] & self.pawns) > 8: errors |= STATUS_TOO_MANY_WHITE_PAWNS - if pop_count(self.occupied_co[BLACK] & self.pawns) > 8: + if popcount(self.occupied_co[BLACK] & self.pawns) > 8: errors |= STATUS_TOO_MANY_BLACK_PAWNS # Pawns can not be on the backrank. @@ -3179,7 +3181,7 @@ def _slider_blockers(self): for sniper in scan_reversed(snipers & self.occupied_co[not self.turn]): b = BB_BETWEEN[sq][sniper] & self.occupied - if pop_count(b) <= 1: + if popcount(b) <= 1: blockers |= b return blockers @@ -3677,7 +3679,7 @@ def __ne__(self, other): return NotImplemented def __len__(self): - return pop_count(self.mask) + return popcount(self.mask) def __iter__(self): return scan_forward(self.mask) diff --git a/chess/gaviota.py b/chess/gaviota.py index ba4bff92f..e89a32acb 100644 --- a/chess/gaviota.py +++ b/chess/gaviota.py @@ -1788,7 +1788,7 @@ def probe_dtm(self, board): # Only up to 5-men tablebases. if len(white_squares) + len(black_squares) > 5: - raise KeyError("gaviota tables support up to 5 pieces, not {0}: {1}".format(chess.pop_count(board.occupied), board.fen())) + raise KeyError("gaviota tables support up to 5 pieces, not {0}: {1}".format(chess.popcount(board.occupied), board.fen())) # Probe. dtm = self.egtb_get_dtm(req) @@ -2174,8 +2174,8 @@ def _probe_hard(self, board, wdl_only=False): if board.is_insufficient_material(): return 0 - if chess.pop_count(board.occupied) > 5: - raise KeyError("gaviota tables support up to 5 pieces, not {0}: {1}".format(chess.pop_count(board.occupied), board.fen())) + if chess.popcount(board.occupied) > 5: + raise KeyError("gaviota tables support up to 5 pieces, not {0}: {1}".format(chess.popcount(board.occupied), board.fen())) if board.castling_rights: raise KeyError("gaviota tables do not contain positions with castling rights: {0}".format(board.fen())) diff --git a/chess/syzygy.py b/chess/syzygy.py index dd4b0ba7f..96ba87f74 100644 --- a/chess/syzygy.py +++ b/chess/syzygy.py @@ -479,19 +479,19 @@ def calc_key(board, mirror=False): b = board.occupied_co[chess.BLACK ^ mirror] return "".join([ - "K" * chess.pop_count(board.kings & w), - "Q" * chess.pop_count(board.queens & w), - "R" * chess.pop_count(board.rooks & w), - "B" * chess.pop_count(board.bishops & w), - "N" * chess.pop_count(board.knights & w), - "P" * chess.pop_count(board.pawns & w), + "K" * chess.popcount(board.kings & w), + "Q" * chess.popcount(board.queens & w), + "R" * chess.popcount(board.rooks & w), + "B" * chess.popcount(board.bishops & w), + "N" * chess.popcount(board.knights & w), + "P" * chess.popcount(board.pawns & w), "v", - "K" * chess.pop_count(board.kings & b), - "Q" * chess.pop_count(board.queens & b), - "R" * chess.pop_count(board.rooks & b), - "B" * chess.pop_count(board.bishops & b), - "N" * chess.pop_count(board.knights & b), - "P" * chess.pop_count(board.pawns & b), + "K" * chess.popcount(board.kings & b), + "Q" * chess.popcount(board.queens & b), + "R" * chess.popcount(board.rooks & b), + "B" * chess.popcount(board.bishops & b), + "N" * chess.popcount(board.knights & b), + "P" * chess.popcount(board.pawns & b), ]) @@ -1600,7 +1600,7 @@ def probe_ab(self, board, alpha, beta, threats=False): return v, 1 def sprobe_ab(self, board, alpha, beta, threats=False): - if chess.pop_count(board.occupied_co[not board.turn]) > 1: + if chess.popcount(board.occupied_co[not board.turn]) > 1: v, captures_found = self.sprobe_capts(board, alpha, beta) if captures_found: return v, 2 @@ -1610,7 +1610,7 @@ def sprobe_ab(self, board, alpha, beta, threats=False): threats_found = False - if threats or chess.pop_count(board.occupied) >= 6: + if threats or chess.popcount(board.occupied) >= 6: for threat in board.generate_legal_moves(~board.pawns): board.push(threat) try: @@ -1680,8 +1680,8 @@ def probe_wdl(self, board): raise KeyError("syzygy tables do not contain positions with castling rights: {0}".format(board.fen())) # Validate piece count. - if chess.pop_count(board.occupied) > 6: - raise KeyError("syzygy tables support up to 6 pieces, not {0}: {1}".format(chess.pop_count(board.occupied), board.fen())) + if chess.popcount(board.occupied) > 6: + raise KeyError("syzygy tables support up to 6 pieces, not {0}: {1}".format(chess.popcount(board.occupied), board.fen())) # Probe. v, success = self.probe_ab(board, -2, 2) diff --git a/chess/variant.py b/chess/variant.py index 2e6783c51..bf6b01cb0 100644 --- a/chess/variant.py +++ b/chess/variant.py @@ -57,8 +57,8 @@ def was_into_check(self, move): return False def _material_balance(self): - return (chess.pop_count(self.occupied_co[self.turn]) - - chess.pop_count(self.occupied_co[not self.turn])) + return (chess.popcount(self.occupied_co[self.turn]) - + chess.popcount(self.occupied_co[not self.turn])) def is_variant_end(self): return not all(has_pieces for has_pieces in self.occupied_co) @@ -221,12 +221,12 @@ def is_insufficient_material(self): if self.pawns or self.queens: return False - if chess.pop_count(self.KNIGHT | self.BISHOP | self.ROOK) == 1: + if chess.popcount(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 + return chess.popcount(self.knights) <= 2 # Only bishops. if self.occupied == (self.kings | self.bishops): @@ -400,13 +400,13 @@ def status(self): if self.pawns: status |= chess.STATUS_RACE_MATERIAL for color in chess.COLORS: - if chess.pop_count(self.occupied_co[color] & self.knights) > 2: + if chess.popcount(self.occupied_co[color] & self.knights) > 2: status |= chess.STATUS_RACE_MATERIAL - if chess.pop_count(self.occupied_co[color] & self.bishops) > 2: + if chess.popcount(self.occupied_co[color] & self.bishops) > 2: status |= chess.STATUS_RACE_MATERIAL - if chess.pop_count(self.occupied_co[color] & self.rooks) > 2: + if chess.popcount(self.occupied_co[color] & self.rooks) > 2: status |= chess.STATUS_RACE_MATERIAL - if chess.pop_count(self.occupied_co[color] & self.queens) > 1: + if chess.popcount(self.occupied_co[color] & self.queens) > 1: status |= chess.STATUS_RACE_MATERIAL return status @@ -445,7 +445,7 @@ def status(self): status = super(HordeBoard, self).status() status &= ~chess.STATUS_NO_WHITE_KING - if chess.pop_count(self.occupied_co[chess.WHITE]) <= 36: + if chess.popcount(self.occupied_co[chess.WHITE]) <= 36: status &= ~chess.STATUS_TOO_MANY_WHITE_PIECES status &= ~chess.STATUS_TOO_MANY_WHITE_PAWNS @@ -685,11 +685,11 @@ def legal_drop_squares_mask(self): king_square = chess.lsb(king_bb) king_attackers = self.attackers_mask(not self.turn, king_square) - num_attackers = chess.pop_count(king_attackers) + num_attackers = chess.popcount(king_attackers) if not king_attackers: return ~self.occupied - elif chess.pop_count(king_attackers) == 1: + elif chess.popcount(king_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] @@ -809,11 +809,11 @@ def copy(self, stack=True): 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: + if chess.popcount(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: + if chess.popcount(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 diff --git a/test.py b/test.py index 1e8c1e18b..9f8dadd6a 100755 --- a/test.py +++ b/test.py @@ -92,9 +92,9 @@ def test_shifts(self): for shift in shifts: for bb_square in chess.BB_SQUARES: shifted = shift(bb_square) - c = chess.pop_count(shifted) + c = chess.popcount(shifted) self.assertLessEqual(c, 1) - self.assertEqual(c, chess.pop_count(shifted & chess.BB_ALL)) + self.assertEqual(c, chess.popcount(shifted & chess.BB_ALL)) class MoveTestCase(unittest.TestCase): @@ -928,7 +928,7 @@ def test_clear(self): self.assertFalse(board.ep_square) self.assertFalse(board.piece_at(chess.E1)) - self.assertEqual(chess.pop_count(board.occupied), 0) + self.assertEqual(chess.popcount(board.occupied), 0) def test_threefold_repetition(self): board = chess.Board()