Chess-update

This commit is contained in:
VS-Code
2026-02-11 17:22:11 +01:00
parent b5f608ce66
commit b6e36aa2dc

View File

@@ -1,3 +1,5 @@
# region Constants
# White Constants # White Constants
W_KIN, W_QUE, W_BIS, W_NHT, W_ROO, W_PAW = range(6) W_KIN, W_QUE, W_BIS, W_NHT, W_ROO, W_PAW = range(6)
# Black Constans # Black Constans
@@ -8,6 +10,18 @@ WHITE, BLACK = 0, 1
KIN, QUE, BIS, NHT, ROO, PAW = range(6) KIN, QUE, BIS, NHT, ROO, PAW = range(6)
NO_PIECE = 15 NO_PIECE = 15
PIECE_TO_STR = ["wK", "wQ", "wB", "wN", "wR", "wP", "bK", "bQ", "bB", "bN", "bR", "bP"]
# Square Constants
A8, B8, C8, D8, E8, F8, G8, H8 = range(56, 64)
A7, B7, C7, D7, E7, F7, G7, H7 = range(48, 56)
A6, B6, C6, D6, E6, F6, G6, H6 = range(40, 48)
A5, B5, C5, D5, E5, F5, G5, H5 = range(32, 40)
A4, B4, C4, D4, E4, F4, G4, H4 = range(24, 32)
A3, B3, C3, D3, E3, F3, G3, H3 = range(16, 24)
A2, B2, C2, D2, E2, F2, G2, H2 = range(8, 16)
A1, B1, C1, D1, E1, F1, G1, H1 = range(8)
# 0 = Normaler Zug (Quiet Move) # 0 = Normaler Zug (Quiet Move)
QUIET = 0 QUIET = 0
@@ -39,22 +53,29 @@ PROMO_B_CAPTURE = 13
PROMO_R_CAPTURE = 14 PROMO_R_CAPTURE = 14
PROMO_Q_CAPTURE = 15 PROMO_Q_CAPTURE = 15
# Square Constants # Masks
A8, B8, C8, D8, E8, F8, G8, H8 = range(56, 64)
A7, B7, C7, D7, E7, F7, G7, H7 = range(48, 56)
A6, B6, C6, D6, E6, F6, G6, H6 = range(40, 48)
A5, B5, C5, D5, E5, F5, G5, H5 = range(32, 40)
A4, B4, C4, D4, E4, F4, G4, H4 = range(24, 32)
A3, B3, C3, D3, E3, F3, G3, H3 = range(16, 24)
A2, B2, C2, D2, E2, F2, G2, H2 = range(8, 16)
A1, B1, C1, D1, E1, F1, G1, H1 = range(8)
NOT_A = 0xfefefefefefefefe NOT_A = 0xfefefefefefefefe
NOT_H = 0x7f7f7f7f7f7f7f7f NOT_H = 0x7f7f7f7f7f7f7f7f
NOT_AB = 0xfcfcfcfcfcfcfcfc NOT_AB = 0xfcfcfcfcfcfcfcfc
NOT_GH = 0x3f3f3f3f3f3f3f3f NOT_GH = 0x3f3f3f3f3f3f3f3f
FULL_MASK = 0xffffffffffffffff FULL_MASK = 0xffffffffffffffff
# Attacks Movesets & Rays
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
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
# endregion
class Bitboard(): class Bitboard():
def __init__(self) -> None: def __init__(self) -> None:
@@ -79,76 +100,307 @@ class Bitboard():
self.bitboards[B_ROO] = (1 << A8) | (1 << H8) self.bitboards[B_ROO] = (1 << A8) | (1 << H8)
self.bitboards[B_PAW] = 0xFF << 48 self.bitboards[B_PAW] = 0xFF << 48
self.all_pieces = [] self.all_pieces = [0, 0]
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[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.all_pieces[1] = self.bitboards[B_KIN] | self.bitboards[B_QUE] | self.bitboards[B_BIS] | self.bitboards[B_NHT] | self.bitboards[B_ROO] | self.bitboards[B_PAW]
self.move_list = [] self.move_list = []
def get_all_moves(self): def get_all_moves(self):
turn_offset = self.side_to_move * 6 moves = []
opponent_pcs = self.all_pieces[not self.side_to_move] captures = []
friendly_pcs = self.all_pieces[self.side_to_move] turn = self.side_to_move
opp = turn ^ 1
turn_offset = turn * 6
opp_offset = opp *6
# import local Varibles
bbs = self.bitboards
opponent_pcs = self.all_pieces[opp]
friendly_pcs = self.all_pieces[turn]
occupancy = opponent_pcs | friendly_pcs
# region --- King Moves ---
kin_sq = bbs[KIN + turn_offset].bit_length() - 1
kin_attacks = KIN_ATTACKS[kin_sq]
kin_attacks &= ~friendly_pcs
while kin_attacks:
to_sq = (kin_attacks & -kin_attacks).bit_length() - 1
to_mask = 1 << to_sq
kin_attacks &= (kin_attacks - 1)
if to_mask & opponent_pcs:
if to_mask & bbs[PAW + opp_offset]:
capture = PAW + opp_offset
elif to_mask & bbs[NHT + opp_offset]:
capture = NHT + opp_offset
elif to_mask & bbs[BIS + opp_offset]:
capture = BIS + opp_offset
elif to_mask & bbs[ROO + opp_offset]:
capture = ROO + opp_offset
else:
capture = QUE + opp_offset
captures.append(to_sq | (kin_sq << 6) | ((KIN + turn_offset) << 12) | (capture << 16) | CAPTURE << 20)
else:
moves.append(to_sq | (kin_sq << 6) | ((KIN + turn_offset) << 12) | (NO_PIECE << 16) | QUIET << 20)
# endregion
# region --- Knight Moves ---
nht_bb = bbs[NHT + turn_offset]
while nht_bb:
nht_sq = (nht_bb & -nht_bb).bit_length() - 1
nht_bb &= (nht_bb - 1)
nht_attacks = NHT_ATTACKS[nht_sq]
nht_attacks &= ~friendly_pcs
while nht_attacks:
to_sq = (nht_attacks & -nht_attacks).bit_length() - 1
to_mask = 1 << to_sq
nht_attacks &= (nht_attacks - 1)
if to_mask & opponent_pcs:
if to_mask & bbs[PAW + opp_offset]:
capture = PAW + opp_offset
elif to_mask & bbs[NHT + opp_offset]:
capture = NHT + opp_offset
elif to_mask & bbs[BIS + opp_offset]:
capture = BIS + opp_offset
elif to_mask & bbs[ROO + opp_offset]:
capture = ROO + opp_offset
else:
capture = QUE + opp_offset
captures.append(to_sq | (nht_sq << 6) | ((NHT + turn_offset) << 12) | (capture << 16) | CAPTURE << 20)
else:
moves.append(to_sq | (nht_sq << 6) | ((NHT + turn_offset) << 12) | (NO_PIECE << 16) | QUIET << 20)
# endregion
# region --- Pawn Moves ---
paw_bb = bbs[PAW + turn_offset]
while paw_bb:
paw_sq = (paw_bb & -paw_bb).bit_length() - 1
paw_bb &= (paw_bb -1)
paw_attacks = PAW_ATTACKS[paw_sq + turn_offset]
# Irgendwann noch En Passant einfügen
paw_attacks &= opponent_pcs
while paw_attacks:
flag = CAPTURE
to_sq = (paw_attacks & -paw_attacks).bit_length() - 1
to_mask = 1 << to_sq
paw_attacks &= (paw_attacks - 1)
if to_mask & bbs[PAW + opp_offset]:
capture = PAW + opp_offset
elif to_mask & bbs[NHT + opp_offset]:
capture = NHT + opp_offset
elif to_mask & bbs[BIS + opp_offset]:
capture = BIS + opp_offset
elif to_mask & bbs[ROO + opp_offset]:
capture = ROO + opp_offset
else:
capture = QUE + opp_offset
captures.append(to_sq | (paw_sq << 6) | ((PAW + turn_offset) << 12) | (capture << 16) | flag << 20)
if turn == 0:
to_sq = paw_sq + 8
to_mask = 1 << to_sq
if not to_mask & occupancy:
moves.append(to_sq | (paw_sq << 6) | ((PAW + turn_offset) << 12) | (NO_PIECE << 16) | QUIET << 20)
if 8 <= paw_sq <= 15:
to_sq_push = paw_sq + 16
to_mask_push = 1 << to_sq_push
if not to_mask_push & occupancy:
moves.append(to_sq_push | (paw_sq << 6) | ((PAW + turn_offset) << 12) | (NO_PIECE << 16) | DOUBLE_PAWN_PUSH << 20)
else:
to_sq = paw_sq - 8
to_mask = 1 << to_sq
if not to_mask & occupancy:
moves.append(to_sq | (paw_sq << 6) | ((PAW + turn_offset) << 12) | (NO_PIECE << 16) | QUIET << 20)
if 48 <= paw_sq <= 55:
to_sq_push = paw_sq - 16
to_mask_push = 1 << to_sq_push
if not to_mask_push & occupancy:
moves.append(to_sq_push | (paw_sq << 6) | ((PAW + turn_offset) << 12) | (NO_PIECE << 16) | DOUBLE_PAWN_PUSH << 20)
# endregion Pawn Moves
# region --- Bishop Moves ---
bis_bb = bbs[BIS + turn_offset]
while bis_bb:
bis_sq = (bis_bb & -bis_bb).bit_length() - 1
bis_bb &= (bis_bb - 1)
# region North-East
ray = RAYS_NE[bis_sq]
blockers = ray & occupancy
if blockers:
blocker_sq = (blockers & -blockers).bit_length() - 1
ray_to_del = RAYS_NE[blocker_sq]
bis_attacks = (ray ^ ray_to_del) & ~friendly_pcs
else:
bis_attacks = ray
while bis_attacks:
to_sq = (bis_attacks & -bis_attacks).bit_length() - 1
to_mask = 1 << to_sq
bis_attacks &= (bis_attacks - 1)
if to_mask & opponent_pcs:
if to_mask & bbs[PAW + opp_offset]:
capture = PAW + opp_offset
elif to_mask & bbs[NHT + opp_offset]:
capture = NHT + opp_offset
elif to_mask & bbs[BIS + opp_offset]:
capture = BIS + opp_offset
elif to_mask & bbs[ROO + opp_offset]:
capture = ROO + opp_offset
else:
capture = QUE + opp_offset
captures.append(to_sq | (bis_sq << 6) | ((BIS + turn_offset) << 12) | (capture << 16) | CAPTURE << 20)
else:
moves.append(to_sq | (bis_sq << 6) | ((BIS + turn_offset) << 12) | (NO_PIECE << 16) | QUIET << 20)
# endregion
# region North-West
ray = RAYS_NW[bis_sq]
blockers = ray & occupancy
if blockers:
blocker_sq = (blockers & -blockers).bit_length() - 1
ray_to_del = RAYS_NW[blocker_sq]
bis_attacks = (ray ^ ray_to_del) & ~friendly_pcs
else:
bis_attacks = ray
while bis_attacks:
to_sq = (bis_attacks & -bis_attacks).bit_length() - 1
to_mask = 1 << to_sq
bis_attacks &= (bis_attacks - 1)
if to_mask & opponent_pcs:
if to_mask & bbs[PAW + opp_offset]:
capture = PAW + opp_offset
elif to_mask & bbs[NHT + opp_offset]:
capture = NHT + opp_offset
elif to_mask & bbs[BIS + opp_offset]:
capture = BIS + opp_offset
elif to_mask & bbs[ROO + opp_offset]:
capture = ROO + opp_offset
else:
capture = QUE + opp_offset
captures.append(to_sq | (bis_sq << 6) | ((BIS + turn_offset) << 12) | (capture << 16) | CAPTURE << 20)
else:
moves.append(to_sq | (bis_sq << 6) | ((BIS + turn_offset) << 12) | (NO_PIECE << 16) | QUIET << 20)
# endregion
# region South-East
ray = RAYS_SE[bis_sq]
blockers = ray & occupancy
if blockers:
blocker_sq = blockers.bit_length() - 1
ray_to_del = RAYS_SE[blocker_sq]
bis_attacks = (ray ^ ray_to_del) & ~friendly_pcs
else:
bis_attacks = ray
while bis_attacks:
to_sq = (bis_attacks & -bis_attacks).bit_length() - 1
to_mask = 1 << to_sq
bis_attacks &= (bis_attacks - 1)
if to_mask & opponent_pcs:
if to_mask & bbs[PAW + opp_offset]:
capture = PAW + opp_offset
elif to_mask & bbs[NHT + opp_offset]:
capture = NHT + opp_offset
elif to_mask & bbs[BIS + opp_offset]:
capture = BIS + opp_offset
elif to_mask & bbs[ROO + opp_offset]:
capture = ROO + opp_offset
else:
capture = QUE + opp_offset
captures.append(to_sq | (bis_sq << 6) | ((BIS + turn_offset) << 12) | (capture << 16) | CAPTURE << 20)
else:
moves.append(to_sq | (bis_sq << 6) | ((BIS + turn_offset) << 12) | (NO_PIECE << 16) | QUIET << 20)
# endregion
# region South-West
ray = RAYS_SW[bis_sq]
blockers = ray & occupancy
if blockers:
blocker_sq = blockers.bit_length() - 1
ray_to_del = RAYS_SW[blocker_sq]
bis_attacks = (ray ^ ray_to_del) & ~friendly_pcs
else:
bis_attacks = ray
while bis_attacks:
to_sq = (bis_attacks & -bis_attacks).bit_length() - 1
to_mask = 1 << to_sq
bis_attacks &= (bis_attacks - 1)
if to_mask & opponent_pcs:
if to_mask & bbs[PAW + opp_offset]:
capture = PAW + opp_offset
elif to_mask & bbs[NHT + opp_offset]:
capture = NHT + opp_offset
elif to_mask & bbs[BIS + opp_offset]:
capture = BIS + opp_offset
elif to_mask & bbs[ROO + opp_offset]:
capture = ROO + opp_offset
else:
capture = QUE + opp_offset
captures.append(to_sq | (bis_sq << 6) | ((BIS + turn_offset) << 12) | (capture << 16) | CAPTURE << 20)
else:
moves.append(to_sq | (bis_sq << 6) | ((BIS + turn_offset) << 12) | (NO_PIECE << 16) | QUIET << 20)
# endregion
# endregion Bishop Moves
move_list = []
# King Moves
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)
def make_move(self, move): def make_move(self, move):
# Setup # Setup
# Bit 0-5: Target (6 Bit, Index: 0-63) # 6 Bit (0-5): Target (Index: 0-63)
# Bit 6-11: Source (6 Bit, Index: 0-63) # 6 Bit (6-11): Source (Index: 0-63)
# Bit 12-15: Piece moved (4 Bit) 0-11: W_KIN-B_PAW # 4 Bit (12-15): Piece moved (0-11: W_KIN-B_PAW)
# Bit 16-19: Piece Captured (4 Bit) 0-11: W_KIN-B_PAW, 15: Nothing # 4 Bit (16-19): Piece Captured (0-11: W_KIN-B_PAW, 15: Nothing)
#
# Bit 20-23: Flags (4 Bit) # Bit 20-23: Flags (4 Bit)
# 0000: 0 Quiet 0100: 4 Capture 1000: 8 Promo NHT # 0000: 0 Quiet 0100: 4 Capture 1000: 8 Promo NHT
# 0001: 1 Double Pawn Push 0101: 5 En Passant 1001: 9 Promo BIS # 0001: 1 Double Pawn Push 0101: 5 En Passant 1001: 9 Promo BIS
# 0010: 2 King Castle 0110: 1010: 10 Promo ROO # 0010: 2 King Castle 0110: 1010: 10 Promo ROO
# 0011: 3 Queen Castle 0111: 1011: 11 Promo QUE # 0011: 3 Queen Castle 0111: 1011: 11 Promo QUE
pass end = move & 0x3F
start = (move >> 6) & 0x3F
piece = (move >> 12) & 0xF
captured = (move >> 16) & 0xF
flag = (move >> 20) & 0xF
turn = self.side_to_move
self.bitboards[piece] ^= (1 << start) | (1 << end)
self.all_pieces[turn] ^= (1 << start) | (1 << end)
if flag == CAPTURE:
self.bitboards[captured] ^= (1 << end)
self.all_pieces[turn ^ 1] ^= (1 << end)
self.side_to_move ^= 1 # Seite Wechseln
def encode_move(start_sq, end_sq, flag): def print_board(self):
move = 0 board = [" ."] * 64
move |= end_sq for pce in range(12):
move |= start_sq << 6 locations = self.bitboards[pce]
move |= flag << 12 while locations:
return move index = (locations & -locations).bit_length() - 1
board[index] = PIECE_TO_STR[pce]
locations &= (locations - 1)
for c in range(7, -1, -1):
print(f"{c+1} ", end="")
for r in range(8):
print(board[r + (c * 8)], end=" ")
# move_constants.py print("")
print(" A B C D E F G H /n")
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
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(): def initialize():
''' '''
@@ -167,7 +419,7 @@ def initialize():
(bit & NOT_GH) >> 6 | (bit & NOT_H) >> 15 | (bit & NOT_A) >> 17 | (bit & NOT_AB) >> 10 (bit & NOT_GH) >> 6 | (bit & NOT_H) >> 15 | (bit & NOT_A) >> 17 | (bit & NOT_AB) >> 10
NHT_ATTACKS[sq] = nht_attacks & FULL_MASK NHT_ATTACKS[sq] = nht_attacks & FULL_MASK
# Pawns # Pawns Attack
w_attacks = (bit & NOT_A) << 7 | (bit & NOT_H) << 9 w_attacks = (bit & NOT_A) << 7 | (bit & NOT_H) << 9
PAW_ATTACKS[sq] = w_attacks & FULL_MASK PAW_ATTACKS[sq] = w_attacks & FULL_MASK
@@ -225,6 +477,10 @@ def initialize():
RAYS_SW[sq] |= (1 << (i * 8 + j)) RAYS_SW[sq] |= (1 << (i * 8 + j))
i -= 1; j -= 1 i -= 1; j -= 1
initialize()
board = Bitboard()
board.print_board()
''' Board Index: ''' Board Index:
a b c d e f g h a b c d e f g h
8 [56] [57] [58] [59] [60] [61] [62] [63] 8 [56] [57] [58] [59] [60] [61] [62] [63]
@@ -236,6 +492,4 @@ def initialize():
2 [08] [09] [10] [11] [12] [13] [14] [15] 2 [08] [09] [10] [11] [12] [13] [14] [15]
1 [00] [01] [02] [03] [03] [05] [06] [07] 1 [00] [01] [02] [03] [03] [05] [06] [07]
''' '''