python-chess icon indicating copy to clipboard operation
python-chess copied to clipboard

Baseboard/Board: add method to count total number of pieces

Open kraktus opened this issue 10 months ago • 2 comments

Unless I've missed it, not possible to and useful when working with tbs for example. My goto implementation for now is

len(chess.SquareSet(board.occupied))

not sure about the name, baseboard.nb_pieces, baseboard.total_nb_pieces, baseboard.pieces_count (but could be thought as the count of pieces per type).

kraktus avatar Feb 21 '25 08:02 kraktus

I also think that a function for this could be useful, because not every user comes up with the best implementation for this.

This seems to be the best method, python-chess also uses it internally:

chess.popcount(board.occupied)

In my test, it is almost 5 times faster than your method:

import time
import chess

board = chess.Board()

t = time.perf_counter()
[len(chess.SquareSet(board.occupied)) for _ in range(10_000_000)]
total = time.perf_counter() - t
print('Test1:', total)

t = time.perf_counter()
[chess.popcount(board.occupied) for _ in range(10_000_000)]
total = time.perf_counter() - t
print('Test2:', total)
Test1: 3.1755944349997662
Test2: 0.6580440879997695

Torom avatar Mar 26 '25 19:03 Torom

I also found myself wanting a pieces_count member that I could get at while using your api. I ended up going with a solution that uses int.bitcount: https://github.com/Phillyclause89/ChessMoveHeatmap/blob/e482a42978f824ab477e4c0e2ee2467e004e5b71/chmengine/utils/init.py#L12

# Python 3.8+ has bit_count(); otherwise count the '1's in the binary repr
try:
    _bit_count: Callable[[int], int] = int.bit_count
except AttributeError:
    def _bit_count(occ: int) -> int:
        return bin(occ).count('1')

def pieces_count_from_board(board: Board) -> int:
    """Return the number of pieces on the board

    This uses the internal bitboard to count occupied squares in O(1) time.
    On Python ≥ 3.8 it calls `int.bit_count()`. On Python 3.7 it falls back
    to `bin(...).count('1')` for compatibility.

    Parameters
    ----------
    board : chess.Board
        A board object to count pieces from

    Returns
    -------
    int
        Number of pieces on the board.

    Examples
    --------
    >>> from chess import Board
    >>> mate_board = Board('8/2p2p2/4p3/2k5/8/6q1/2K5/1r1q4 w - - 2 59')
    >>> pieces_count_from_board(mate_board)
    8
    >>> pieces_count_from_board(Board())
    32
    """
    return _bit_count(board.occupied)

Phillyclause89 avatar Apr 25 '25 18:04 Phillyclause89