Files
chess/backups/main.py.bak
2024-09-29 01:38:31 -04:00

250 lines
12 KiB
Python

import curses
import chess
import chess.engine
import os
import random
# Initialize Stockfish engine
stockfish_path = "/usr/games/stockfish"
engine = chess.engine.SimpleEngine.popen_uci(stockfish_path)
# Define ASCII/Nerd Font pieces
PIECE_SYMBOLS = {
'P': '', 'N': '', 'B': '', 'R': '', 'Q': '', 'K': '',
'p': '', 'n': '', 'b': '', 'r': '', 'q': '', 'k': ''
}
def draw_board(stdscr, board, cell_width, cell_height, start_y, start_x, selected_square=None, move_history=[], legal_moves=[], player_color=None):
stdscr.clear()
max_y, max_x = stdscr.getmaxyx()
# Draw the move history
move_history_y = 2
stdscr.addstr(0, 0, "Move History:")
for index, move in enumerate(move_history[-(max_y // 2 - 2):]): # Display limited history
stdscr.addstr(move_history_y + index, 0, move)
# Draw the chessboard oriented towards the player
for board_y in range(8):
actual_row = board_y if player_color == chess.BLACK else 7 - board_y # Orient the row correctly based on player color
for board_x in range(8):
actual_col = board_x if player_color == chess.WHITE else 7 - board_x # Orient the column correctly
piece = board.piece_at(chess.square(actual_col, actual_row))
display_piece = PIECE_SYMBOLS[piece.symbol()] if piece else ' '
# Determine square color
square_color = curses.color_pair(1) if (actual_row + actual_col) % 2 == 0 else curses.color_pair(2)
is_selected = (selected_square == chess.square(actual_col, actual_row))
is_legal_move = chess.square(actual_col, actual_row) in legal_moves
if is_selected:
square_color = curses.color_pair(3) # Highlight selected square
elif is_legal_move:
square_color = curses.color_pair(4) # Highlight legal move square
stdscr.attron(square_color)
# Ensure that the piece is drawn centered in the cell
for line in range(cell_height):
if line == cell_height // 2: # Only draw the piece on the middle line
cell_content = display_piece.center(cell_width)
else:
cell_content = ' ' * cell_width # Clear remaining lines in the cell
try:
stdscr.addstr(start_y + board_y * cell_height + line, start_x + board_x * cell_width, cell_content)
except curses.error:
pass
stdscr.attroff(square_color)
stdscr.refresh()
def get_square_from_position(mouse_x, mouse_y, cell_width, cell_height, start_x, start_y, player_color):
row = (mouse_y - start_y) // cell_height
col = (mouse_x - start_x) // cell_width
if player_color == chess.BLACK:
col = 7 - col # Reverse column for black orientation
if player_color == chess.WHITE:
row = 7 - row # Reverse row for white orientation
if 0 <= row < 8 and 0 <= col < 8:
return chess.square(col, row)
return None
def main(stdscr):
curses.curs_set(0)
stdscr.clear()
curses.mousemask(curses.ALL_MOUSE_EVENTS | curses.REPORT_MOUSE_POSITION)
curses.start_color()
curses.init_pair(1, curses.COLOR_WHITE, 94) # Light brown background
curses.init_pair(2, curses.COLOR_BLACK, 58) # Dark brown background
curses.init_pair(3, curses.COLOR_BLACK, curses.COLOR_WHITE) # Highlight selected square in grey
curses.init_pair(4, curses.COLOR_GREEN, curses.COLOR_WHITE) # Highlight legal move square
# Get difficulty input
stdscr.addstr(0, 0, "Enter difficulty level (1-20): ")
stdscr.refresh()
while True:
try:
difficulty_input = stdscr.getstr().decode().strip()
difficulty = int(difficulty_input)
if 1 <= difficulty <= 20:
break
else:
stdscr.addstr(1, 0, "Invalid input. Please enter a number between 1 and 20.")
except ValueError:
stdscr.addstr(1, 0, "Invalid input. Please enter a valid integer.")
stdscr.refresh()
stdscr.getch()
stdscr.clear()
stdscr.addstr(0, 0, "Enter difficulty level (1-20): ")
# Randomly assign player color
player_color = chess.WHITE if random.choice([True, False]) else chess.BLACK
player_side = "White" if player_color == chess.WHITE else "Black"
stdscr.clear()
stdscr.addstr(0, 0, f"You are playing as: {player_side}")
stdscr.refresh()
stdscr.getch()
board = chess.Board()
move_history = []
undo_stack = []
redo_stack = []
cell_width = 5 # Adjusted size for larger icons
cell_height = 3
selected_square = None
piece_selected = False
moving_mode = False
legal_moves = []
original_square = None
while True:
rows, cols = stdscr.getmaxyx()
cell_width = max(5, min(6, (cols - 20) // 16)) # Ensure room for the move history
cell_height = 3
start_y = (rows - cell_height * 8) // 2
start_x = 20 # Start drawing the board from column 20 to make space for move history
draw_board(stdscr, board, cell_width, cell_height, start_y, start_x, selected_square, move_history, legal_moves, player_color)
if board.is_game_over():
stdscr.addstr(rows - 1, 0, "Game Over! Press any key to exit.")
stdscr.getch()
break
player_turn = board.turn == player_color
while player_turn:
try:
key = stdscr.getch()
if key == ord('q'):
engine.quit()
return
if key == ord('u'): # Undo both your move and the computer's move
if len(board.move_stack) > 1:
move1 = board.pop()
move2 = board.pop()
undo_stack.append((move1, move2))
redo_stack.clear() # Clear redo stack as we made a new undo
move_history.pop()
move_history.pop()
draw_board(stdscr, board, cell_width, cell_height, start_y, start_x, selected_square, move_history, legal_moves, player_color)
break
if key == ord('r'): # Redo both your move and the computer's move
if len(undo_stack) > 0:
move1, move2 = undo_stack.pop()
board.push(move2) # Push computer's move first
board.push(move1) # Push your move
redo_stack.append((move1, move2))
move_history.append(f"{'White' if player_color == chess.WHITE else 'Black'}: {move1}")
move_history.append(f"{'Black' if player_color == chess.WHITE else 'White'}: {move2}")
draw_board(stdscr, board, cell_width, cell_height, start_y, start_x, selected_square, move_history, legal_moves, player_color)
break
if key == curses.KEY_MOUSE:
_, mouse_x, mouse_y, _, button_state = curses.getmouse()
if button_state & curses.BUTTON1_CLICKED:
square = get_square_from_position(mouse_x, mouse_y, cell_width, cell_height, start_x, start_y, player_color)
if square is not None:
if not piece_selected and board.piece_at(square) and board.piece_at(square).color == player_color:
selected_square = square
original_square = selected_square
piece_selected = True
moving_mode = False
legal_moves = [move.to_square for move in board.legal_moves if move.from_square == selected_square]
draw_board(stdscr, board, cell_width, cell_height, start_y, start_x, selected_square, move_history, legal_moves, player_color)
elif piece_selected and selected_square != square:
move = chess.Move(selected_square, square)
if move in board.legal_moves:
board.push(move)
move_history.append(f"{player_side}: {move}")
selected_square = None
piece_selected = False
redo_stack.clear() # Clear redo stack when a new move is made
player_turn = False
break
selected_square = None
piece_selected = False
elif piece_selected:
if key in [curses.KEY_UP, curses.KEY_DOWN, curses.KEY_LEFT, curses.KEY_RIGHT]:
rank = chess.square_rank(selected_square)
file = chess.square_file(selected_square)
if key == curses.KEY_UP:
rank += 1 if player_color == chess.WHITE else -1
elif key == curses.KEY_DOWN:
rank -= 1 if player_color == chess.WHITE else 1
elif key == curses.KEY_LEFT:
file -= 1 if player_color == chess.WHITE else -1
elif key == curses.KEY_RIGHT:
file += 1 if player_color == chess.WHITE else -1
if 0 <= rank < 8 and 0 <= file < 8:
selected_square = chess.square(file, rank)
draw_board(stdscr, board, cell_width, cell_height, start_y, start_x, selected_square, move_history, legal_moves, player_color)
elif key == ord('\n'):
if not moving_mode:
moving_mode = True
legal_moves = [move.to_square for move in board.legal_moves if move.from_square == selected_square]
original_square = selected_square
draw_board(stdscr, board, cell_width, cell_height, start_y, start_x, selected_square, move_history, legal_moves, player_color)
else:
if selected_square != original_square:
move = chess.Move(original_square, selected_square)
if move in board.legal_moves:
board.push(move)
move_history.append(f"{player_side}: {move}")
selected_square = None
piece_selected = False
moving_mode = False
redo_stack.clear() # Clear the redo stack when a new move is made
player_turn = False
break
selected_square = original_square
moving_mode = False
except curses.error:
pass
if not player_turn:
result = engine.play(board, chess.engine.Limit(time=1.0 + (difficulty - 1) * 0.1))
board.push(result.move)
move_history.append(f"{'White' if not player_color else 'Black'}: {result.move}")
undo_stack.clear() # Clear undo stack after computer move
engine.quit()
if __name__ == "__main__":
curses.wrapper(main)