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