- 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()