import tkinter as tk from tkinter import messagebox from tkinter import Button from functools import partial from PIL import ImageTk, Image class Position: def __init__(self, row, col): self.row = row self.col = col def match(self,list_pos): for pos in list_pos: if pos.row == self.row and pos.col == self.col: return True return False class Piece: def __init__(self, color, board, position=None): self.color = color self.board = board self.has_moved = False self.position = position def __str__(self): pass class King(Piece): def __init__(self,color,board,position=None): super().__init__(color,board,position) self.piece_type = "king" def possible_moves(self): moves = [] offsets = [(1, 0), (0, 1), (-1, 0), (0, -1), (1, 1), (-1, 1), (1, -1), (-1, -1)] for dr, dc in offsets: new_pos = Position(self.position.row + dr, self.position.col + dc) if self.board.is_inside_board(new_pos) and (self.board.is_square_empty(new_pos) or self.board.is_enemy_piece(new_pos, self.color)): moves.append(new_pos) # Castling if not self.board.board[self.position.row][self.position.col].has_moved: print("roozbeh") # Check kingside castling if self.board.board[self.position.row][7] and not self.board.board[self.position.row][7].has_moved: if all(self.board.is_square_empty(Position(self.position.row, c)) for c in range(self.position.col + 1, 7)): print("poo") moves.append(Position(self.position.row, self.position.col + 2)) # Check queenside castling if not self.board.board[self.position.row][0]: print("ali") if self.board.board[self.position.row][0].has_moved: print(self.position.row) print("sook") if self.board.board[self.position.row][0] and not self.board.board[self.position.row][0].has_moved: print("younes") if all(self.board.is_square_empty(Position(self.position.row, c)) for c in range(1, self.position.col)): print("abdolali") moves.append(Position(self.position.row, self.position.col - 2)) return moves def move(self,end_pos): a = self.possible_moves() for pos in a: if pos.row == end_pos.row and pos.col == end_pos.col: return True return False def __str__(self): if self.color == "White": return "K" return "k" class Bishop(Piece): def __init__(self,color,board,position=None): super().__init__(color,board,position) self.piece_type = "bishop" def possible_moves(self): moves = [] directions = [(-1, -1), (-1, 1), (1, 1), (1, -1)] for dr, dc in directions: temp = self.position while True: new_pos = Position(temp.row + dr, temp.col + dc) temp = new_pos if self.board.is_inside_board(new_pos) == False: break if self.board.is_inside_board(new_pos) and (self.board.is_square_empty(new_pos) or self.board.is_enemy_piece(new_pos, self.color)): moves.append(new_pos) if self.board.is_enemy_piece(new_pos, self.color): break if not self.board.is_square_empty(new_pos): break return moves def move(self,end_pos): a = self.possible_moves() for pos in a: if pos.row == end_pos.row and pos.col == end_pos.col: return True return False def __str__(self): if self.color == "White": return "B" return "b" class Pawn(Piece): def __init__(self,color,board,position=None): super().__init__(color,board,position) self.piece_type = "pawn" def possible_moves(self): moves = [] direction = 1 if self.color == "White" else -1 start_row = 1 if self.color == "White" else 6 # Moves for regular pawn advance temp = self.position count = 0 if start_row == temp.row: help = 2 else: help = 1 while count < help: new_pos = Position(temp.row + direction, temp.col) temp = new_pos if self.board.is_inside_board(new_pos) and self.board.is_square_empty(new_pos): moves.append(new_pos) else: break count += 1 # Moves for capturing diagonally temp = self.position new_pos = Position(temp.row + direction, temp.col - 1) if self.board.is_inside_board(new_pos): if self.board.is_enemy_piece(new_pos, self.color): moves.append(new_pos) new_pos = Position(temp.row + direction, temp.col + 1) if self.board.is_inside_board(new_pos): if self.board.is_enemy_piece(new_pos, self.color): moves.append(new_pos) return moves def move(self,end_pos): a = self.possible_moves() for pos in a: if pos.row == end_pos.row and pos.col == end_pos.col: return True return False def __str__(self): if self.color == "White": return "P" return "p" class Rook(Piece): def __init__(self,color,board,positi super().__init__(color,board,position) self.piece_type = "rook" def possible_moves(self): moves = [] directi 0), (-1, 0), (0, 1), (0, -1)] for dr, dc in directions: temp = self.position while True: new_pos = Position(temp.row + dr, temp.col + dc) temp = new_pos if self.board.is_inside_board(new_pos) == False: break if self.board.is_inside_board(new_pos) and (self.board.is_square_empty(new_pos) or self.board.is_enemy_piece(new_pos, self.color)): moves.append(new_pos) if not self.board.is_square_empty(new_pos): break return moves def move(self,end_pos): a = self.possible_moves() for pos in a: if pos.row == end_pos.row and pos.col == end_pos.col: return True return False def __str__(self): if self.color == "White": return "R" return "r" class Knight(Piece): def __init__(self,color,board,positi super().__init__(color,board,position) self.piece_type = "knight" def possible_moves(self): moves = [] ends = [(-2, 1), (-2, -1), (2, -1), (2, 1), (1, 2), (-1, 2), (1, -2), (-1, -2)] temp = self.position for er, ec in ends: new_pos = Position(temp.row + er, temp.col + ec) # print(new_pos.row, new_pos.col) if self.board.is_inside_board(new_pos) and (self.board.is_square_empty(new_pos) or self.board.is_enemy_piece(new_pos, self.color)): moves.append(new_pos) return moves def move(self,end_pos): a = self.possible_moves() for pos in a: if pos.row == end_pos.row and pos.col == end_pos.col: return True return False def __str__(self): if self.color == "White": return "N" return "n" class Queen(Piece): def __init__(self,color,board,positi super().__init__(color,board,position) self.piece_type = "queen" def possible_moves(self): moves = [] directi -1), (-1, 1), (1, 1), (1, -1), (1, 0), (-1, 0), (0, 1), (0, -1)] for dr, dc in directions: temp = self.position while True: new_pos = Position(temp.row + dr, temp.col + dc) temp = new_pos if self.board.is_inside_board(new_pos): if self.board.is_square_empty(new_pos) or self.board.is_enemy_piece(new_pos, self.color): moves.append(new_pos) if not self.board.is_inside_board(new_pos): break if not self.board.is_square_empty(new_pos): break return moves def move(self,end_pos): a = self.possible_moves() for pos in a: if pos.row == end_pos.row and pos.col == end_pos.col: return True return False def __str__(self): if self.color == "White": return "Q" return "q" class Board: def __init__(self): self.board = [[None for _ in range(8)] for _ in range(8)] #initialize the board self.butt for _ in range(8)] for _ in range(8)] self.left_click = [[0 for _ in range(8)] for _ in range(8)] self.right_click = [[0 for _ in range(8)] for _ in range(8)] self.current_player = "White" self.cc = 0 for i in range(8): for j in range(8): bt = Button(master, text = '', height = 5, width = 10, image = ImageTk.PhotoImage(Image.open("/Users/arshiash/Documents/1403-01-06 22.33.08.jpg"))) bt.bind("<Button-1>", self.inner1(i, j)) bt.bind("<Button-2>", self.inner2(i, j)) self.buttons[i][j] = bt bt.grid(row = i, column = j) def inner1(self, i, j): def lft(l): print(type(self)) print("lili") for x in self.board[i][j].possible_moves(): print(x.row, x.col) for ii in range(8): for jj in range(8): self.left_click[ii][jj] = 0 if self.board[i][j]: if self.board[i][j].color == self.current_player: self.left_click[i][j] = 1 return lft def inner2(self, i, j): def rgt(l): flag = False for ii in range(8): for jj in range(8): if self.left_click[ii][jj] == 1: print("salam") flag = True co_ii = ii co_jj = jj if flag == True: for ii in range(8): for jj in range(8): self.right_click[ii][jj] = 0 self.right_click[i][j] = 1 if self.board[co_ii][co_jj].move(Position(i, j)): co_1 = self.board[co_ii][co_jj] co_2 = self.board[i][j] self.move_piece(Position(co_ii, co_jj), Position(i, j)) if (not self.is_check(self.current_player)) and co_1.piece_type == "king" and (co_ii == i) and (abs(co_jj - j) > 1): if co_1.color == "White": if co_ii == 0: if j > co_jj: print("mohammadreza") self.cc = 1 self.move_piece(Position(0, 7), Position(0, 5)) if j < co_jj: self.cc = 1 self.move_piece(Position(0, 0), Position(0, 3)) if co_1.color == "Black": if co_ii == 7: if j > co_jj: self.cc = 1 self.move_piece(Position(7, 7), Position(7, 5)) if j < co_jj: self.cc = 1 self.move_piece(Position(7, 0), Position(7, 3)) temp = False if self.is_check(self.current_player): print("arshia") messagebox.showinfo("NOP", "Your still check") self.remove_piece(self.board[i][j]) self.place_piece(co_1, Position(co_ii, co_jj)) if co_2: print(co_2.piece_type) self.place_piece(co_2, Position(i, j)) temp = True self.current_player = "Black" if self.current_player == "White" else "White" if temp == True: self.current_player = "Black" if self.current_player == "White" else "White" if self.is_checkmate(self.current_player): messagebox.showinfo("The end", f'{self.current_player} lost') master.destroy() return rgt def is_check(self, current_player): #TODO - find current_player's king on the board, check if the king is in check enemy = "Black" if current_player == "White" else "White" for i in range(8): for j in range(8): piece = self.board[i][j] if piece: if piece.color == enemy: if piece.possible_moves(): for pos in piece.possible_moves(): if self.board[pos.row][pos.col]: if self.board[pos.row][pos.col].piece_type == "king": return True return False def is_checkmate(self, current_player): # For simplicity, we consider losing the king as checkmate enemy = "Black" if current_player == "White" else "White" for i in range(8): for j in range(8): if not self.board[i][j]: continue if self.board[i][j].color == enemy: continue co_1 = self.board[i][j] for mv in self.board[i][j].possible_moves(): co_2 = self.board[mv.row][mv.col] if co_1: help1 = self.board[i][j].has_moved if co_2: help2 = self.board[i][j].has_moved self.move_piece(Position(i, j), mv) if not self.is_check(current_player): self.remove_piece(self.board[mv.row][mv.col]) self.place_piece(co_1, Position(i, j)) self.place_piece(co_2, Position(mv.row, mv.col)) if self.board[i][j]: self.board[i][j].has_moved = help1 if self.board[mv.row][mv.col]: self.board[mv.row][mv.col].has_moved = help2 print(i, j, " ", mv.row, mv.col) return False self.remove_piece(self.board[mv.row][mv.col]) self.place_piece(co_1, Position(i, j)) self.place_piece(co_2, Position(mv.row, mv.col)) return True def place_piece(self, piece, position): if piece: self.board[position.row][position.col] = piece if piece: tmp = 'green' if piece.color == "White" else 'black' else: tmp = 'white' if piece: self.buttons[position.row][position.col].config(text = f'{piece.piece_type}', foreground = tmp) piece.positi else: self.buttons[position.row][position.col].config(text = '') def remove_piece(self, piece): self.board[piece.position.row][piece.position.col] = None self.buttons[piece.position.row][piece.position.col].config(text = '') def move_piece(self, start_pos, end_pos): piece = self.board[start_pos.row][start_pos.col] if piece: if piece.move(end_pos) or (piece.piece_type == 'rook' and self.cc == 1): if piece.piece_type == 'rook' and self.cc == 1: self.cc = 0 #TODO (remove piece, place the piece at the end_pos and set has_moved to True) self.remove_piece(piece) self.place_piece(piece, end_pos) piece.has_moved = True piece.positi return True else: print("No piece at the starting position.") return False def is_square_empty(self, position): return self.board[position.row][position.col] is None def is_enemy_piece(self, position, color): if not self.is_square_empty(position): if self.board[position.row][position.col].color == color: return False return True return False def is_inside_board(self, position): if position.row > 7 or position.col > 7 or position.row < 0 or position.col < 0: return False return True class ChessSet: def __init__(self): self.board = Board() self.setup_board() def setup_board(self): # Place white pieces self.board.place_piece(Rook("White",self.board), Position(0, 0)) self.board.place_piece(Knight("White",self.board), Position(0, 1)) self.board.place_piece(Bishop("White",self.board), Position(0, 2)) self.board.place_piece(Queen("White",self.board), Position(0, 3)) self.board.place_piece(King("White",self.board), Position(0, 4)) self.board.place_piece(Bishop("White",self.board), Position(0, 5)) self.board.place_piece(Knight("White",self.board), Position(0, 6)) self.board.place_piece(Rook("White",self.board), Position(0, 7)) for col in range(8): self.board.place_piece(Pawn("White", self.board), Position(1, col)) # Place black pieces self.board.place_piece(Rook("Black",self.board), Position(7, 0)) self.board.place_piece(Knight("Black",self.board), Position(7, 1)) self.board.place_piece(Bishop("Black",self.board), Position(7, 2)) self.board.place_piece(Queen("Black",self.board), Position(7, 3)) self.board.place_piece(King("Black",self.board), Position(7, 4)) self.board.place_piece(Bishop("Black",self.board), Position(7, 5)) self.board.place_piece(Knight("Black",self.board), Position(7, 6)) self.board.place_piece(Rook("Black",self.board), Position(7, 7)) for col in range(8): self.board.place_piece(Pawn("Black", self.board), Position(6, col)) def print_board(self): self.board.print_board() class Chess: def __init__(self): self.chess_set = ChessSet() if __name__ == "__main__": master = tk.Tk() master.geometry("850x680") chess_game = Chess() master.mainloop()