Source code for draughts.boards.american

from __future__ import annotations

from typing import Generator

import numpy as np

from draughts.boards.base import BaseBoard
from draughts.models import Color, Figure
from draughts.move import Move

# fmt: off
SQUARES = [B8, D8, F8, H8,
        A7, C7, E7, G7,
        B6, D6, F6, H6,
        A5, C5, E5, G5,
        B4, D4, F4, H4,
        A3, C3, E3, G3,
        B2, D2, F2, H2,
        A1, C1, E1, G1] = range(32)
# fmt: on


[docs] class Board(BaseBoard): """ **Board for American checkers.** Game rules: - Board size: 8x8 - Short moves only - Only the king can capture backwards - Capture - choose any """ GAME_TYPE = 23 STARTING_COLOR = Color.WHITE STARTING_POSITION = np.array([1] * 12 + [0] * 8 + [-1] * 12, dtype=np.int8) VARIANT_NAME = "American checkers" ROW_IDX = {val: val // 4 for val in range(len(STARTING_POSITION))} COL_IDX = {val: val % 8 for val in range(len(STARTING_POSITION))} size = int(np.sqrt(len(STARTING_POSITION) * 2)) # def __init__( # self, starting_position=STARTING_POSITION, turn=STARTING_COLOR, *args, **kwargs # ) -> None: # super().__init__(starting_position, turn, *args, **kwargs) @property def is_draw(self) -> bool: return self.is_threefold_repetition @property def legal_moves(self) -> Generator[Move, None, None]: if self.turn == Color.BLACK: squares_list = np.transpose(np.nonzero(self._pos > 0)) else: squares_list = np.transpose(np.nonzero(self._pos < 0)) for square in squares_list.flatten(): moves = self._legal_moves_from(square) for move in moves: yield move def _legal_moves_from( self, square: int, is_after_capture=False ) -> Generator[Move, None, None]: row = self.ROW_IDX[square] moves = [] odd = bool(row % 2 != 0 and self.turn == Color.BLACK) or ( row % 2 == 0 and self.turn == Color.WHITE ) is_king = bool(self[square] == self.turn.value * Figure.KING) # is_king = False # DEBUG for mv_offset, cap_offset, dir in [ (4 - odd, 7, self.turn.value), (5 - odd, 9, self.turn.value), ] + is_king * [ (4 - (not odd), 7, -self.turn.value), (5 - (not odd), 9, -self.turn.value), ]: move_sq = square + mv_offset * (dir) capture_sq = square + cap_offset * (dir) if ( 0 <= move_sq < len(self._pos) and row + 1 * (dir) == self.ROW_IDX[move_sq] and self[move_sq] == 0 and not is_after_capture ): moves.append(Move([square, move_sq])) elif ( 0 <= capture_sq < len(self._pos) and row + 2 * (dir) == self.ROW_IDX[capture_sq] and self[capture_sq] == 0 and self[move_sq] * self.turn.value < 0 ): move = Move( [square, capture_sq], captured_list=[move_sq], captured_entities=[self[move_sq]], ) moves.append(move) self.push(move, False) moves += [move + m for m in self._legal_moves_from(capture_sq, True)] self.pop(False) return moves
if __name__ == "__main__": board = Board() for i in range(10): # random move move = np.random.choice(list(board.legal_moves)) board.push(move) print(board.pdn)