Files
landingpage/chess/chess_64.py
2026-02-10 16:23:16 +01:00

242 lines
7.0 KiB
Python

# White Constants
W_KIN, W_QUE, W_BIS, W_NHT, W_ROO, W_PAW = range(6)
# Black Constans
B_KIN, B_QUE, B_BIS, B_NHT, B_ROO, B_PAW = range(6,12)
# Turn Constants
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)
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_H = 0x7f7f7f7f7f7f7f7f
NOT_AB = 0xfcfcfcfcfcfcfcfc
NOT_GH = 0x3f3f3f3f3f3f3f3f
FULL_MASK = 0xffffffffffffffff
class Bitboard():
def __init__(self) -> None:
# WHITE 0:King, 1:Queen, 2:Bishop, 3:Knight, 4:Rook, 5:Pawn
# BLACK 6:King, 7:Queen, 8:Bishop, 9:Knight, 10:Rook, 11:Pawn
self.bitboards = [0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0]
self.side_to_move = WHITE
self.bitboards[W_KIN] = 1 << E1
self.bitboards[W_QUE] = 1 << D1
self.bitboards[W_BIS] = (1 << C1) | (1 << F1)
self.bitboards[W_NHT] = (1 << B1) | (1 << G1)
self.bitboards[W_ROO] = (1 << A1) | (1 << H1)
self.bitboards[W_PAW] = 0xFF << 8
self.bitboards[B_KIN] = 1 << E8
self.bitboards[B_QUE] = 1 << D8
self.bitboards[B_BIS] = (1 << C8) | (1 << F8)
self.bitboards[B_NHT] = (1 << B8) | (1 << G8)
self.bitboards[B_ROO] = (1 << A8) | (1 << H8)
self.bitboards[B_PAW] = 0xFF << 48
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
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):
# Setup
# 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
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_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_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
w_attacks = (bit & NOT_A) << 7 | (bit & NOT_H) << 9
PAW_ATTACKS[sq] = w_attacks & FULL_MASK
b_attacks = (bit & NOT_A) >> 9 | (bit & NOT_H) >> 7
PAW_ATTACKS[sq + 64] = b_attacks & FULL_MASK
# --- 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
8 [56] [57] [58] [59] [60] [61] [62] [63]
7 [48] [49] [50] [51] [52] [53] [54] [55]
6 [40] [41] [42] [43] [44] [45] [46] [47]
5 [32] [33] [34] [35] [36] [37] [38] [39]
4 [24] [25] [26] [27] [28] [29] [30] [31]
3 [16] [17] [18] [19] [20] [21] [22] [23]
2 [08] [09] [10] [11] [12] [13] [14] [15]
1 [00] [01] [02] [03] [03] [05] [06] [07]
'''