Download rules.py from end000/Checkers-WSPForge-Russian-v2: direct link, hf CLI and curl.
- Browser
- Download file 4.17 kB
-
https://huggingface.co/end000/Checkers-WSPForge-Russian-v2/resolve/main/rules.py
- Command line
-
hf download hf://end000/Checkers-WSPForge-Russian-v2/rules.py
-
curl -L -o rules.py https://huggingface.co/end000/Checkers-WSPForge-Russian-v2/resolve/main/rules.py
4.17 kB
| from collections import Counter | |
| import numpy as np | |
| from draughts import RussianBoard | |
| from draughts.models import Color | |
| from loguru import logger | |
| logger.remove() | |
| NAMES = RussianBoard.SQUARE_NAMES | |
| def encode(board, perspective): | |
| masks = (board.white_men, board.white_kings, board.black_men, board.black_kings) | |
| if perspective == Color.BLACK: | |
| masks = masks[2:] + masks[:2] | |
| x = np.zeros(128, np.float32) | |
| for p, mask in enumerate(masks): | |
| while mask: | |
| bit = mask & -mask | |
| s = bit.bit_length() - 1 | |
| x[p * 32 + (s if perspective == Color.WHITE else 31 - s)] = 1 | |
| mask ^= bit | |
| return x | |
| def key(board): | |
| return (board.white_men, board.white_kings, board.black_men, board.black_kings, board.turn.value) | |
| def algebraic_fen(board): | |
| sides = [] | |
| for label, man, king in (("W", board.white_men, board.white_kings), ("B", board.black_men, board.black_kings)): | |
| fields = [("K" if king & (1 << s) else "") + NAMES[s] for s in range(32) if (man | king) & (1 << s)] | |
| sides.append(label + ",".join(fields)) | |
| return ("W" if board.turn == Color.WHITE else "B") + ":" + ":".join(sides) | |
| def move_text(move): | |
| return (":" if move.captured_list else "-").join(NAMES[s] for s in move.square_list) | |
| class Adjudicator: | |
| def __init__(self, board, max_plies=300): | |
| self.max_plies = max_plies | |
| self.plies = 0 | |
| self.seen = Counter({key(board): 1}) | |
| self.quiet_kings = 0 | |
| self.material_stable = 0 | |
| self.regulation_key = None | |
| self.regulation_moves = [0, 0] | |
| self._regulation(board) | |
| def _regulation(self, b): | |
| counts = (b.white_men.bit_count(), b.white_kings.bit_count(), b.black_men.bit_count(), b.black_kings.bit_count()) | |
| wm, wk, bm, bk = counts | |
| lone_side = 0 if wm == 0 and wk == 1 else 1 if bm == 0 and bk == 1 else None | |
| if lone_side is None: | |
| new = None | |
| else: | |
| other_m, other_k = (bm, bk) if lone_side == 0 else (wm, wk) | |
| lone_mask = b.white_kings if lone_side == 0 else b.black_kings | |
| diagonal = any((lone_mask >> s) & 1 for s in range(32) if NAMES[s][0] == str("abcdefgh"[int(NAMES[s][1]) - 1])) | |
| if other_k >= 1 and other_m + other_k <= 2: | |
| limit = 5 | |
| elif other_k >= 1 and other_m + other_k == 3 and diagonal: | |
| limit = 5 | |
| elif other_m == 0 and other_k >= 3: | |
| limit = 15 | |
| else: | |
| limit = None | |
| new = (lone_side, other_m, other_k, limit) if limit is not None else None | |
| if new != self.regulation_key: | |
| self.regulation_key = new | |
| self.regulation_moves = [0, 0] | |
| def update(self, board, move, moving_piece, mover): | |
| self.plies += 1 | |
| self.seen[key(board)] += 1 | |
| self.quiet_kings = self.quiet_kings + 1 if abs(moving_piece) == 2 and not move.captured_list else 0 | |
| self.material_stable = 0 if move.captured_list or move.is_promotion else self.material_stable + 1 | |
| old = self.regulation_key | |
| self._regulation(board) | |
| if old is not None and old == self.regulation_key: | |
| self.regulation_moves[0 if mover == Color.WHITE else 1] += 1 | |
| def outcome(self, board, legal): | |
| if not legal: | |
| return -board.turn.value, "no_legal_moves" | |
| if self.seen[key(board)] >= 3: | |
| return 0, "threefold" | |
| if self.quiet_kings >= 30: | |
| return 0, "15_king_moves" | |
| if self.regulation_key is not None: | |
| lone, _, _, limit = self.regulation_key | |
| if self.regulation_moves[1 - lone] >= limit: | |
| return 0, f"regulation_{limit}" | |
| count = (board.white_men | board.white_kings | board.black_men | board.black_kings).bit_count() | |
| both_kings = bool(board.white_kings and board.black_kings) | |
| if both_kings and ((count <= 5 and self.material_stable >= 60) or (count <= 7 and self.material_stable >= 120)): | |
| return 0, "stable_endgame" | |
| if self.plies >= self.max_plies: | |
| return 0, "experimental_ply_cap" | |
| return None | |