From b5f608ce66b00aa36868b0e5418e315952c454cf Mon Sep 17 00:00:00 2001 From: VS-Code <-> Date: Tue, 10 Feb 2026 16:23:16 +0100 Subject: [PATCH] Update-Chess --- chess/chess_64.py | 196 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 144 insertions(+), 52 deletions(-) diff --git a/chess/chess_64.py b/chess/chess_64.py index 55f7ad6..db6c3f1 100644 --- a/chess/chess_64.py +++ b/chess/chess_64.py @@ -6,6 +6,39 @@ B_KIN, B_QUE, B_BIS, B_NHT, B_ROO, B_PAW = range(6,12) WHITE, BLACK = 0, 1 # Piece Constants KIN, QUE, BIS, NHT, ROO, PAW = range(6) +NO_PIECE = 15 + +# 0 = Normaler Zug (Quiet Move) +QUIET = 0 + +# 1 = Doppelschritt Bauer (wichtig für En Passant im nächsten Zug) +DOUBLE_PAWN_PUSH = 1 + +# 2 & 3 = Rochaden +KING_CASTLE = 2 +QUEEN_CASTLE = 3 + +# 4 = Normaler Schlagzug (Capture) +# Manche Engines codieren Captures extra, manche schauen einfach aufs Brett. +# Für den Anfang reicht es, Captures einfach als Flag 4 zu markieren. +CAPTURE = 4 + +# 5 = En Passant Schlag +EP_CAPTURE = 5 + +# 8-15 = Umwandlungen (Promotion) +# Struktur: 8 + Figur (Springer=0, Läufer=1, Turm=2, Dame=3) +PROMO_KNIGHT = 8 +PROMO_BISHOP = 9 +PROMO_ROOK = 10 +PROMO_QUEEN = 11 + +# Umwandlung mit Schlagen (optional, spart Zeit beim Checken) +PROMO_N_CAPTURE = 12 +PROMO_B_CAPTURE = 13 +PROMO_R_CAPTURE = 14 +PROMO_Q_CAPTURE = 15 + # Square Constants A8, B8, C8, D8, E8, F8, G8, H8 = range(56, 64) A7, B7, C7, D7, E7, F7, G7, H7 = range(48, 56) @@ -22,17 +55,6 @@ NOT_AB = 0xfcfcfcfcfcfcfcfc NOT_GH = 0x3f3f3f3f3f3f3f3f FULL_MASK = 0xffffffffffffffff -INDEX_TO_FIELD = [ - "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1", - "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2", - "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3", - "a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4", - "a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5", - "a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6", - "a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7", - "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8", -] - class Bitboard(): def __init__(self) -> None: @@ -56,83 +78,152 @@ class Bitboard(): self.bitboards[B_NHT] = (1 << B8) | (1 << G8) self.bitboards[B_ROO] = (1 << A8) | (1 << H8) self.bitboards[B_PAW] = 0xFF << 48 - - self.all_white = self.bitboards[W_KIN] | self.bitboards[W_QUE] | self.bitboards[W_BIS] | self.bitboards[W_NHT] | self.bitboards[W_ROO] | self.bitboards[W_PAW] - self.all_black = self.bitboards[W_KIN] | self.bitboards[W_QUE] | self.bitboards[W_BIS] | self.bitboards[W_NHT] | self.bitboards[W_ROO] | self.bitboards[W_PAW] - self.all_piece = self.all_white | self.all_black + + self.all_pieces = [] + self.all_pieces[0] = self.bitboards[W_KIN] | self.bitboards[W_QUE] | self.bitboards[W_BIS] | self.bitboards[W_NHT] | self.bitboards[W_ROO] | self.bitboards[W_PAW] + self.all_pieces[1] = self.bitboards[W_KIN] | self.bitboards[W_QUE] | self.bitboards[W_BIS] | self.bitboards[W_NHT] | self.bitboards[W_ROO] | self.bitboards[W_PAW] self.move_list = [] def get_all_moves(self): turn_offset = self.side_to_move * 6 - + opponent_pcs = self.all_pieces[not self.side_to_move] + friendly_pcs = self.all_pieces[self.side_to_move] + + move_list = [] # King Moves - king = self.bitboards[KIN] - king_moves = 0 - king_moves = (king & NOT_A) >> 1 | (king & NOT_A) << 7 | king << 8 | (king & NOT_H) << 9 | (king & NOT_H) << 1 | (king & NOT_H) >> 7 | king >> 8 | (king & NOT_A) >> 9 - king_moves &= FULL_MASK + kin_sq = self.bitboards[KIN + turn_offset].bit_length() - 1 + kin_moves = KIN_ATTACKS[kin_sq] + kin_moves &= ~friendly_pcs + + while kin_moves: + flag = 0 + to_sq = (kin_moves & -kin_moves).bit_length() - 1 + move_list.append(to_sq | (kin_sq << 6) | flag << 12) + + - pass - - - - def make_move(self, move): # Setup - # Bit 0-5: Target (6 Bit, Index: 0-63) - # Bit 6-11: Source (6 Bit, Index: 0-63) - # Bit 12-15: Flags (4 Bit) - # 0000: 0 Quiet 0100: 4 Capture 1000: 8 Promo NHT - # 0001: 1 Double Pawn Push 0101: 5 En Passant 1001: 9 Promo BIS - # 0010: 2 King Castle 0110: 1010: 10 Promo ROO - # 0011: 3 Queen Castle 0111: 1011: 11 Promo QUE + # Bit 0-5: Target (6 Bit, Index: 0-63) + # Bit 6-11: Source (6 Bit, Index: 0-63) + # Bit 12-15: Piece moved (4 Bit) 0-11: W_KIN-B_PAW + # Bit 16-19: Piece Captured (4 Bit) 0-11: W_KIN-B_PAW, 15: Nothing + # + # Bit 20-23: Flags (4 Bit) + # 0000: 0 Quiet 0100: 4 Capture 1000: 8 Promo NHT + # 0001: 1 Double Pawn Push 0101: 5 En Passant 1001: 9 Promo BIS + # 0010: 2 King Castle 0110: 1010: 10 Promo ROO + # 0011: 3 Queen Castle 0111: 1011: 11 Promo QUE pass +def encode_move(start_sq, end_sq, flag): + move = 0 + move |= end_sq + move |= start_sq << 6 + move |= flag << 12 + return move + + + +# move_constants.py + KIN_ATTACKS = [0] * 64 NHT_ATTACKS = [0] * 64 PAW_ATTACKS = [0] * 128 # 0-63 für Weiße Bauern, 64-127 für Schwarze Bauern -RAY_N = [0] * 64 -RAY_NE = [0] * 64 -RAY_E = [0] * 64 -RAY_SE = [0] * 64 -RAY_S = [0] * 64 -RAY_SW = [0] * 64 -RAY_W = [0] * 64 -RAY_NW = [0] * 64 + + +RAYS_N = [0] * 64 +RAYS_NE = [0] * 64 +RAYS_E = [0] * 64 +RAYS_SE = [0] * 64 +RAYS_S = [0] * 64 +RAYS_SW = [0] * 64 +RAYS_W = [0] * 64 +RAYS_NW = [0] * 64 def initialize(): + ''' + Calculate all Attack patterns and Rays + ''' for sq in range(64): + bit = 1 << sq + # --- Pieces --- # King - kin = 1 << sq - kin_attacks = (kin & NOT_A) << 7 | kin << 8 | (kin & NOT_H) << 9 | (kin & NOT_H) << 1 | \ - (kin & NOT_H) >> 7 | kin >> 8 | (kin & NOT_A) >> 9 | (kin & NOT_A) >> 1 + kin_attacks = (bit & NOT_A) << 7 | bit << 8 | (bit & NOT_H) << 9 | (bit & NOT_H) << 1 | \ + (bit & NOT_H) >> 7 | bit >> 8 | (bit & NOT_A) >> 9 | (bit & NOT_A) >> 1 KIN_ATTACKS[sq] = kin_attacks & FULL_MASK # Knight - nht = 1 << sq - nht_attacks = (nht & NOT_AB) << 6 | (nht & NOT_A) << 15 | (nht & NOT_H) << 17 | (nht & NOT_GH) << 10 | \ - (nht & NOT_GH) >> 6 | (nht & NOT_H) >> 15 | (nht & NOT_A) >> 17 | (nht & NOT_AB) >> 10 + nht_attacks = (bit & NOT_AB) << 6 | (bit & NOT_A) << 15 | (bit & NOT_H) << 17 | (bit & NOT_GH) << 10 | \ + (bit & NOT_GH) >> 6 | (bit & NOT_H) >> 15 | (bit & NOT_A) >> 17 | (bit & NOT_AB) >> 10 NHT_ATTACKS[sq] = nht_attacks & FULL_MASK # Pawns - paw = 1 << sq - - w_attacks = (paw & NOT_A) << 7 | (paw & NOT_H) << 9 + w_attacks = (bit & NOT_A) << 7 | (bit & NOT_H) << 9 PAW_ATTACKS[sq] = w_attacks & FULL_MASK - b_attacks = (paw & NOT_A) >> 9 | (paw & NOT_H) >> 7 + b_attacks = (bit & NOT_A) >> 9 | (bit & NOT_H) >> 7 PAW_ATTACKS[sq + 64] = b_attacks & FULL_MASK - # Rays - # North + # --- Rays --- + r, f = sq // 8, sq % 8 + + # North (r+) + RAYS_N[sq] = 0 + for i in range(r + 1, 8): + RAYS_N[sq] |= (1 << (i * 8 + f)) + + # South (r-) + RAYS_S[sq] = 0 + for i in range(r - 1, -1, -1): + RAYS_S[sq] |= (1 << (i * 8 + f)) + + # East (f+) + RAYS_E[sq] = 0 + for i in range(f + 1, 8): + RAYS_E[sq] |= (1 << (r * 8 + i)) + + # West (f-) + RAYS_W[sq] = 0 + for i in range(f - 1, -1, -1): + RAYS_W[sq] |= (1 << (r * 8 + i)) + + # North-East (r+, f+) + RAYS_NE[sq] = 0 + i, j = r + 1, f + 1 + while i < 8 and j < 8: + RAYS_NE[sq] |= (1 << (i * 8 + j)) + i += 1; j += 1 + + # North-West (r+, f-) + RAYS_NW[sq] = 0 + i, j = r + 1, f - 1 + while i < 8 and j >= 0: + RAYS_NW[sq] |= (1 << (i * 8 + j)) + i += 1; j -= 1 + + # South-East (r-, f+) + RAYS_SE[sq] = 0 + i, j = r - 1, f + 1 + while i >= 0 and j < 8: + RAYS_SE[sq] |= (1 << (i * 8 + j)) + i -= 1; j += 1 + + # South-West (r-, f-) + RAYS_SW[sq] = 0 + i, j = r - 1, f - 1 + while i >= 0 and j >= 0: + RAYS_SW[sq] |= (1 << (i * 8 + j)) + i -= 1; j -= 1 ''' Board Index: a b c d e f g h @@ -147,3 +238,4 @@ def initialize(): ''' +