Source code for chipiron.environments.chess_env.board.iboard

import typing
from dataclasses import asdict
from typing import Any, Iterator, Protocol, Self

import chess
import shakmaty_python_binding
import yaml

from chipiron.environments.chess_env.board.board_modification import BoardModificationP
from chipiron.environments.chess_env.move import moveUci
from chipiron.environments.chess_env.move.imove import moveKey

from .utils import FenPlusHistory, FenPlusMoveHistory, fen

# identifier that should be unique to any position
boardKey = tuple[
    int, int, int, int, int, int, bool, int, int | None, int, int, int, int, int
]

# identifier that removes the info (such as rounds) to count easily repeating position at difference round of the game
boardKeyWithoutCounters = tuple[
    int, int, int, int, int, int, bool, int, int | None, int, int, int
]


[docs]class LegalMoveKeyGeneratorP(Protocol): generated_moves: ( dict[moveKey, chess.Move] | list[shakmaty_python_binding.MyMove] | None ) all_generated_keys: list[moveKey] | None # whether to sort the legal_moves by their respective uci for easy comparison of various implementations sort_legal_moves: bool = False def __iter__(self) -> Iterator[moveKey]: ... def __next__(self) -> moveKey: ...
[docs] def more_than_one_move(self) -> bool: ...
[docs] def get_all(self) -> list[moveKey]: ...
@property def fen(self) -> fen: ...
[docs]def compute_key( pawns: int, knights: int, bishops: int, rooks: int, queens: int, kings: int, turn: bool, castling_rights: int, ep_square: int | None, white: int, black: int, promoted: int, fullmove_number: int, halfmove_clock: int, ) -> boardKey: """ Computes and returns a unique key representing the current state of the chess board. The key is computed by concatenating various attributes of the board, including the positions of pawns, knights, bishops, rooks, queens, and kings, as well as the current turn, castling rights, en passant square, halfmove clock, occupied squares for each color, promoted pieces, and the fullmove number. It is faster than calling the fen. Returns: str: A unique key representing the current state of the chess board. """ string: boardKey = ( pawns, knights, bishops, rooks, queens, kings, turn, castling_rights, ep_square, white, black, promoted, fullmove_number, halfmove_clock, ) return string
# Note that we do not use Dict[Square, Piece] because of the rust version that would need to transform # tuple[chess.PieceType, chess.Color] into Piece and would lose time PieceMap = typing.Annotated[ dict[chess.Square, tuple[chess.PieceType, chess.Color]], "a dictionary that list the pieces on the board", ]
[docs]class IBoard(Protocol): fast_representation_: boardKey legal_moves_: LegalMoveKeyGeneratorP
[docs] def get_uci_from_move_key(self, move_key: moveKey) -> moveUci: assert self.legal_moves_.generated_moves is not None return self.legal_moves_.generated_moves[move_key].uci()
[docs] def get_move_key_from_uci(self, move_uci: moveUci) -> moveKey: number_moves: int = len(self.legal_moves_.get_all()) i: int assert self.legal_moves_.generated_moves is not None for i in range(number_moves): if self.legal_moves_.generated_moves[i].uci() == move_uci: return i raise Exception( "the code should not have reached this point: problem with" " legal moves / uci relation in boards object it seems" )
[docs] def play_move_key(self, move: moveKey) -> BoardModificationP | None: ...
[docs] def play_move_uci(self, move_uci: moveUci) -> BoardModificationP | None: ...
@property def fen(self) -> fen: ... @property def move_history_stack( self, ) -> list[moveUci]: ...
[docs] def ply(self) -> int: """ Returns the number of half-moves (plies) that have been played on the board. :return: The number of half-moves played on the board. :rtype: int """ ...
@property def turn(self) -> chess.Color: """ Get the current turn color. Returns: chess.Color: The color of the current turn. """ ...
[docs] def copy(self, stack: bool, deep_copy_legal_moves: bool = True) -> Self: """ Create a copy of the current board. Args: stack (bool): Whether to copy the move stack as well. Returns: BoardChi: A new instance of the BoardChi class with the copied board. """ ...
[docs] def is_game_over(self) -> bool: """ Check if the game is over. Returns: bool: True if the game is over, False otherwise. """ ...
@property def pawns(self) -> chess.Bitboard: ... @property def knights(self) -> chess.Bitboard: ... @property def bishops(self) -> chess.Bitboard: ... @property def rooks(self) -> chess.Bitboard: ... @property def queens(self) -> chess.Bitboard: ... @property def kings(self) -> chess.Bitboard: ... @property def white(self) -> chess.Bitboard: ... @property def black(self) -> chess.Bitboard: ... @property def halfmove_clock(self) -> int: ... @property def promoted(self) -> chess.Bitboard: ... @property def fullmove_number(self) -> int: ... @property def castling_rights(self) -> chess.Bitboard: ... @property def occupied(self) -> chess.Bitboard: ...
[docs] def occupied_color(self, color: chess.Color) -> chess.Bitboard: ...
[docs] def result(self, claim_draw: bool = False) -> str: ...
[docs] def termination(self) -> chess.Termination | None: ...
[docs] def dump(self, file: Any) -> None: # create minimal info for reconstruction that is the class FenPlusMoveHistory current_fen: fen = self.fen fen_plus_moves: FenPlusMoveHistory = FenPlusMoveHistory( current_fen=current_fen, historical_moves=self.move_history_stack ) yaml.dump(asdict(fen_plus_moves), file, default_flow_style=False)
@property def ep_square(self) -> int | None: ... @property def fast_representation(self) -> boardKey: """ Returns a fast representation of the board. This method computes and returns a string representation of the board that can be quickly generated and used for various purposes. :return: A string representation of the board. :rtype: str """ return self.fast_representation_ @property def fast_representation_without_counters(self) -> boardKeyWithoutCounters: """ Returns a fast representation of the board. This method computes and returns a string representation of the board that can be quickly generated and used for various purposes. :return: A string representation of the board. :rtype: str """ assert self.fast_representation_ is not None return self.fast_representation_[:-2]
[docs] def is_zeroing(self, move: moveKey) -> bool: ...
[docs] def is_attacked(self, a_color: chess.Color) -> bool: ...
@property def legal_moves(self) -> LegalMoveKeyGeneratorP: ...
[docs] def number_of_pieces_on_the_board(self) -> int: ...
[docs] def piece_map(self) -> dict[chess.Square, tuple[chess.PieceType, chess.Color]]: ...
[docs] def has_kingside_castling_rights(self, color: chess.Color) -> bool: ...
[docs] def has_queenside_castling_rights(self, color: chess.Color) -> bool: ...
[docs] def print_chess_board(self) -> str: ...
[docs] def tell_result(self) -> None: ...
[docs] def into_fen_plus_history(self) -> FenPlusHistory: ...