Reinitialize repository and add working move generation for all pieces

This commit is contained in:
Moritz Eigenauer 2025-11-12 17:01:12 +01:00
commit 951a8bbec6
28 changed files with 3373 additions and 0 deletions

View file

@ -0,0 +1,197 @@
import tkinter as tk
class ChessBitboardApp:
def __init__(self, root):
self.root = root
self.root.title("Chess Bitboard Generator")
# The bitboard, stored as a 64-bit integer
self.bitboard = 0
# A dictionary to keep track of squares and their marked state
# Key: (row, col), Value: {
# 'widget': tk.Frame, 'label_alg': tk.Label, 'label_idx': tk.Label,
# 'marked': bool, 'original_color': str
# }
self.squares = {}
# --- Create the GUI ---
# Frame for the chessboard
board_frame = tk.Frame(root)
board_frame.pack()
# Create the 8x8 grid of squares
# We loop from row 7 (rank 8) down to 0 (rank 1) for visual layout
for r in range(7, -1, -1): # 7, 6, 5, ... 0
for c in range(8): # 0, 1, 2, ... 7
# Determine the square's original color
is_light_square = (r + c) % 2 == 1
original_color = "#F0D9B5" if is_light_square else "#B58863"
# Create the square as a Frame
square = tk.Frame(
board_frame,
width=50,
height=50,
bg=original_color,
relief="sunken",
borderwidth=1
)
# Make frame *not* resize to labels
square.pack_propagate(False) # Use pack_propagate since we use place/pack inside
square.grid(row=7 - r, column=c)
# --- Add labels to the square (Feature 2) ---
algebraic_not = f"{'abcdefgh'[c]}{r + 1}"
bit_index = r * 8 + c
label_alg = tk.Label(square, text=algebraic_not, bg=original_color, font=("Arial", 8, "bold"))
label_alg.place(x=2, y=1) # Use place to position label
label_idx = tk.Label(square, text=f"{bit_index}", bg=original_color, font=("Arial", 8))
label_idx.place(relx=1.0, rely=1.0, anchor='se', x=-2, y=-1) # Use place for bottom-right
# Bind the click event to all parts of the square
click_lambda = lambda event, row=r, col=c: self.on_square_click(event, row, col)
square.bind("<Button-1>", click_lambda)
label_alg.bind("<Button-1>", click_lambda)
label_idx.bind("<Button-1>", click_lambda)
# Store the square's info
self.squares[(r, c)] = {
'widget': square,
'label_alg': label_alg,
'label_idx': label_idx,
'marked': False,
'original_color': original_color
}
# Frame for the bitboard display
info_frame = tk.Frame(root, pady=10)
info_frame.pack()
# --- Make display labels copyable (Feature 1) ---
self.binary_var = tk.StringVar()
self.int_var = tk.StringVar()
tk.Label(info_frame, text="Binary:").pack()
self.binary_label = tk.Entry(
info_frame,
textvariable=self.binary_var,
state="readonly",
font=("Courier", 10),
width=77 # 64 chars + 15 underscores + 'b'
)
self.binary_label.pack()
tk.Label(info_frame, text="Integer:").pack()
self.int_label = tk.Entry(
info_frame,
textvariable=self.int_var,
state="readonly",
font=("Courier", 12, "bold"),
width=22
)
self.int_label.pack()
# --- Add Entry for pasting bitboard (Feature 3) ---
input_frame = tk.Frame(root, pady=5)
input_frame.pack()
tk.Label(input_frame, text="Paste Bitboard (int) and Press Enter:").pack(side=tk.LEFT)
self.paste_entry = tk.Entry(input_frame, font=("Courier", 12), width=22)
self.paste_entry.pack(side=tk.LEFT, padx=5)
self.paste_entry.bind("<Return>", self.on_paste_bitboard)
# Initialize display
self.update_display()
def on_square_click(self, event, row, col):
"""Handles the click event for a square."""
square_info = self.squares[(row, col)]
# Toggle the marked state
square_info['marked'] = not square_info['marked']
self.update_square_visuals(row, col)
# Recalculate the bitboard and update the display
self.recalculate_bitboard()
self.update_display()
def update_square_visuals(self, row, col):
"""Updates a single square's color based on its 'marked' state."""
square_info = self.squares[(row, col)]
is_marked = square_info['marked']
new_color = "#50C878" if is_marked else square_info['original_color']
label_fg_color = "white" if is_marked else "black" # Make text white on green
square_info['widget'].config(bg=new_color)
square_info['label_alg'].config(bg=new_color, fg=label_fg_color)
square_info['label_idx'].config(bg=new_color, fg=label_fg_color)
def recalculate_bitboard(self):
"""Recalculates the 64-bit integer from the marked squares."""
self.bitboard = 0
for r in range(8):
for c in range(8):
if self.squares[(r, c)]['marked']:
bit_index = r * 8 + c
self.bitboard |= (1 << bit_index)
def update_display(self):
"""Updates the binary and integer labels."""
# Update the integer label
self.int_var.set(f"{self.bitboard}")
# Update the binary label
binary_string = f"{self.bitboard:064b}"
formatted_binary = "b" + "_".join(binary_string[i:i+8] for i in range(0, 64, 4))
self.binary_var.set(f"{formatted_binary}")
def on_paste_bitboard(self, event):
"""Handles the 'Enter' key press in the paste entry box."""
try:
# Get text from entry and convert to integer
new_bitboard = int(self.paste_entry.get())
if 0 <= new_bitboard <= (1 << 64) - 1:
self.bitboard = new_bitboard
# Update the board visuals from the new bitboard
self.update_board_from_bitboard()
# Update the display labels
self.update_display()
else:
# Handle out-of-range numbers
self.paste_entry.delete(0, tk.END)
self.paste_entry.insert(0, "Out of 64-bit range")
except ValueError:
# Handle non-integer input
self.paste_entry.delete(0, tk.END)
self.paste_entry.insert(0, "Invalid Integer")
def update_board_from_bitboard(self):
"""Updates the visual state of all squares based on self.bitboard."""
for r in range(8):
for c in range(8):
bit_index = r * 8 + c
square_info = self.squares[(r, c)]
# Check if the bit at bit_index is set
if (self.bitboard >> bit_index) & 1:
square_info['marked'] = True
else:
square_info['marked'] = False
# Update the square's color
self.update_square_visuals(r, c)
if __name__ == "__main__":
root = tk.Tk()
app = ChessBitboardApp(root)
root.mainloop()