Piece
File containing implementation for each figure in the game. Code structure allows to easily add new Figures for more game variants.
1"""File containing implementation for each figure in the game. Code structure allows to easily add new Figures for more game variants. 2""" 3 4import customtkinter as ctk 5from typing import Callable, Any 6from PIL import Image 7import platform 8import os 9if platform.system() == 'Windows': 10 import pywinstyles 11 12from tools import resource_path, get_from_config, update_error_log 13from properties import COLOR 14 15class Piece: 16 """Parent class for every figure. Has general implementation of functions that can be reused. 17 Abstract method which raises NotImplementedError if check_possible_moves() is not implemented to prevent adding figure that could cause errors when used. 18 """ 19 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 20 """Constructor: 21 - loading assets 22 - virtual function for checking possible moves 23 - checking turns 24 - updating assets 25 - representation of the class for easier debugging 26 27 Args: 28 color (str): Color of the figure. 29 board : Board object on which figures will be placed. 30 position (tuple[int, int]): Position on the board. 31 """ 32 self.color: str = color 33 self.board = board 34 self.position: tuple[int, int] = position 35 self.first_move: bool = False 36 self.image: ctk.CTkImage | None = None 37 38 def check_possible_moves(self, color: str, checking: bool=False): 39 """Virtual function. 40 41 Args: 42 color (str): Color of the figure to move. 43 checking (bool, optional): Flag indicating search. Defaults to False. 44 45 Raises: 46 NotImplementedError: All Figures have to have this function implemented. 47 """ 48 raise NotImplementedError 49 50 def check_turn(self, current_color: str) -> bool: 51 """Checks which player has its right to move. 52 53 Args: 54 current_color (str): Color of the clicked figure. 55 56 Returns: 57 bool: True if its given color turn, False otherwise. 58 """ 59 return False if current_color == self.color else True 60 61 def load_image(self, piece: str | None=None) -> None | ctk.CTkImage: 62 """Loads asset for the piece. 63 64 Args: 65 piece (str | None, optional): Piece string representation. Defaults to None. 66 67 Returns: 68 None | ctk.CTkImage: If piece representation passed function will try to load asset. None otherwise. 69 70 Raises: 71 FileExistsError: If file doesn't exist game will crash and give feedback in the console. 72 FileNotFoundError: If file couldn't be found game will crash and give feedback in the console. 73 """ 74 if not piece: 75 piece_name = (self.__class__.__name__).lower() 76 else: 77 piece_name = piece 78 path: str = resource_path(os.path.join('assets', f'{get_from_config('theme')}', f'{piece_name}_{self.color}.png')) 79 try: 80 loaded_image = Image.open(path).convert('RGBA') 81 size = int(get_from_config('size')) - 10 82 if piece: 83 return ctk.CTkImage( 84 light_image=loaded_image, 85 dark_image=loaded_image, 86 size=(size, size)) 87 self.image = ctk.CTkImage( 88 light_image=loaded_image, 89 dark_image=loaded_image, 90 size=(size, size)) 91 except (FileExistsError, FileNotFoundError) as e: 92 update_error_log(e) 93 return None 94 95 def update_image(self) -> None: 96 """Function updating cell asset. 97 """ 98 self.load_image() 99 self.board.board[self.position[0]][self.position[1]].configure(image=self.image) 100 101 def __str__(self) -> str: 102 """Overriding string representation of the class used in print() for example. 103 104 Returns: 105 str: Representation of the class Piece: {piece name} Color:{piece color} 106 """ 107 return f'Piece: {self.__class__.__name__} | Color: {'white' if self.color == 'w' else 'black'} | Position {self.position}' 108 109class Pawn(Piece): 110 """Implementation of the pawn. Supports en passant, promotions, moving and capturing. 111 112 Args: 113 Piece (Piece): Inheritance from the master class Piece to access general functions of the figures. 114 """ 115 def __init__(self, color: str, board, position: tuple[int, int], notation_func: Callable) -> None: 116 """Constructor: 117 basic setup of master class Piece 118 loads additional flags necessary for correct pawn implementation 119 120 Args: 121 color (str): Color of the pawn. 122 board : Board object on which the pawn will be placed. 123 position (tuple[int, int]): Position of the pawn on the board. 124 notation_func (Callable): Callable function from notation module used to note the move. 125 """ 126 super().__init__(color, board, position) 127 self.color: str = color # b | w 128 self.position: tuple[int, int] = position 129 self.board = board # Board object (import loop occurs if imported for type annotation) 130 self.load_image() 131 self.first_move: bool = True 132 self.moved_by_two: bool = False 133 self.can_en_passant: bool = False 134 self.move: int = 1 if self.color == 'b' else -1 135 self.notation_func: Callable = notation_func 136 137 def check_possible_moves(self, color: str, checking: bool=False) -> list[tuple[int, int]]: 138 """Function checking all possible moves for the Pawn. 139 140 Args: 141 color (str): Color of the pawn. 142 checking (bool, optional): Flag to know when player makes move and when algorithm checks possible moves. Defaults to False. 143 144 Returns: 145 list[tuple[int, int]]: Returns list of all legal positions to which pawn can move. 146 """ 147 possible_moves: list[tuple[int, int]] = [] 148 if self.check_turn(color): 149 return possible_moves 150 move = self.move 151 x: int = self.position[0] 152 y: int = self.position[1] 153 forward_one = (x + move, y) 154 forward_two = (x + move + move, y) 155 if not self.board.board[forward_one[0]][forward_one[1]].figure: 156 possible_moves.append(forward_one) 157 if self.first_move and not self.board.board[forward_two[0]][forward_two[1]].figure: 158 possible_moves.append(forward_two) 159 for offset in [-1, 1]: 160 if 0 <= y + offset < 8: 161 capture_position = (x + move, y + offset) 162 target_square = self.board.board[capture_position[0]][capture_position[1]] 163 if target_square.figure and target_square.figure.color != self.color: 164 possible_moves.append(capture_position) 165 adjacent_pawn = self.board.board[x][y + offset].figure 166 if isinstance(adjacent_pawn, Pawn) and adjacent_pawn.color != self.color and adjacent_pawn.moved_by_two: 167 possible_moves.append((x + move, y + offset)) 168 self.can_en_passant = True 169 return possible_moves 170 171 def choose_figure(self, event: Any, figure, choose_piece_menu: ctk.CTkLabel, choose_piece_menu_1: ctk.CTkFrame) -> None: 172 """Function responsible of promoting the pawn to other figure. 173 174 Args: 175 event (Any): Event type. Doesn't matter but is required parameter by customtkinter. 176 figure : Figure chosen by the player. 177 choose_piece_menu (ctk.CTkLabel): Label widget. 178 choose_piece_menu_1 (ctk.CTkFrame): Frame widget. 179 """ 180 x, y = self.position[0], self.position[1] 181 self.board.board[x][y].figure = figure(self.color, self.board, self.position) 182 self.board.board[x][y].update() 183 self.notation_func(self.board.board[x][y].figure.__class__.__name__) 184 choose_piece_menu.destroy() 185 choose_piece_menu_1.destroy() 186 187 def create_button(self, choose_piece_menu: ctk.CTkLabel, figure, choose_piece_menu_1: ctk.CTkFrame) -> None: 188 """Function creating the button for one of the figure possible to choose from the menu. 189 190 Args: 191 choose_piece_menu (ctk.CTkLabel): Label in which button will be created. 192 figure : Figure that will be possible to choose by clicking the button. 193 choose_piece_menu_1 (ctk.CTkFrame): Frame widget. 194 """ 195 piece_image: ctk.CTkImage | None = self.load_image(str(figure.__name__)) 196 button_figure: ctk.CTkLabel = ctk.CTkLabel( 197 master = choose_piece_menu, 198 text = '', 199 image = piece_image, 200 corner_radius = 0 201 ) 202 button_figure.pack(side=ctk.LEFT, padx=10, pady=10) 203 button_figure.bind('<Button-1>', lambda e: self.choose_figure(e, figure, choose_piece_menu, choose_piece_menu_1)) 204 205 def promote(self) -> bool: 206 """Function checking if pawn is ont the end of the board. If so it force the player to choose the figure they want to promote to. 207 208 Returns: 209 bool: True if pawn was promoted. False otherwise. 210 """ 211 if self.position[0] in {0, 7}: 212 choose_piece_menu_1: ctk.CTkFrame = ctk.CTkFrame( 213 master = self.board, corner_radius=0, 214 fg_color = COLOR.BACKGROUND 215 ) 216 choose_piece_menu_1.place(relx=0, rely=0, relwidth=1, relheight=1) 217 if platform.system() == 'Windows': 218 pywinstyles.set_opacity(choose_piece_menu_1, value=0.01, color="#000001") 219 choose_piece_menu: ctk.CTkFrame = ctk.CTkFrame( 220 master = self.board, 221 fg_color = COLOR.BACKGROUND, 222 corner_radius = 0, 223 border_color = COLOR.DARK_TEXT, 224 border_width = 4 225 ) 226 choose_piece_menu.place(relx=0.5, rely=0.5, anchor=ctk.CENTER) 227 possible_figures = [Knight, Bishop, Rook, Queen] 228 for figure in possible_figures: 229 self.create_button(choose_piece_menu, figure, choose_piece_menu_1) 230 return True 231 return False 232 233 def notate(self, figure_name: Piece, moves_record, capture: bool, check: bool, checkmate: bool) -> None: 234 """Helper function to note the move of the pawn. 235 236 Args: 237 figure_name (Piece): Name of the figure. 238 moves_record : Object of MovesRecord. Cannot specify type due to circular imports. 239 capture (bool): Flag to check if capture occurred. 240 check (bool): Flag to check if after pawn move check occurred. 241 checkmate (bool): Flag to check if after pawn move checkmate occurred. 242 """ 243 moves_record.record_move(figure_name, 244 capture=capture, castle=None, check=check, checkmate=checkmate, 245 promotion=f'{self.board.board[self.position[0]][self.position[1]].figure.__class__.__name__[0]}' 246 ) 247 248class Knight(Piece): 249 """Implementation of the Knight. 250 251 Args: 252 Piece : Inheritance from the master class Piece to access general functions of the figures. 253 """ 254 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 255 """Constructor is really basic. Setups master class and setups board, color and loads asset. 256 257 Args: 258 color (str): Color of the Knight. 259 board : Board object on which figures will be placed. 260 position (tuple[int, int]): Position on the board. 261 """ 262 super().__init__(color, board, position) 263 self.color: str = color 264 self.board = board 265 self.load_image() 266 self.moves: list[tuple[int, int]] = [ 267 (-2,-1), (-2, 1), 268 (-1,-2), (-1, 2), 269 ( 1,-2), ( 1, 2), 270 ( 2,-1), ( 2, 1) 271 ] 272 self.special_cases: dict[tuple[int, int], list[int]] = { 273 (1, 1): [0, 1, 2, 4], 274 (1, 6): [0, 1, 3, 5], 275 (6, 6): [3, 5, 6, 7], 276 (6, 1): [2, 4, 3, 5], 277 (0, 0): [0, 1, 2, 3, 4, 6], 278 (0, 1): [0, 1, 2, 3, 4], 279 (1, 0): [0, 1, 2, 4, 7] 280 } 281 282 def check_moves(self, exceptions: list[int]) -> list[tuple[int, int]]: 283 """Function checking possible moves for the Knight. 284 285 Args: 286 exceptions (list[int]): List of position that are not legal. 287 288 Returns: 289 list[tuple[int, int]]: List of all legal moves. 290 """ 291 possible_moves: list[tuple[int, int]] = [] 292 for i, move in enumerate(self.moves): 293 if i in exceptions: 294 continue 295 new_position = (self.position[0] + move[0], self.position[1] + move[1]) 296 if 0 <= new_position[0] <= 7 and 0 <= new_position[1] <= 7: 297 target_square = self.board.board[new_position[0]][new_position[1]] 298 if not target_square.figure or target_square.figure.color != self.color: 299 possible_moves.append(new_position) 300 return possible_moves 301 302 def check_possible_moves(self, color: str, checking: bool = False) -> list[tuple[int, int]]: 303 """Function checking all possible moves for the Knight. 304 305 Args: 306 color (str): Color of the Knight. 307 checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False. 308 309 Returns: 310 list[tuple[int, int]]: List of all legal position to which Knight can move. 311 """ 312 if self.check_turn(color) and not checking: 313 return [] 314 if 2 <= self.position[0] <= 5 and self.position[1] in {1, 6} and self.position not in self.special_cases: 315 if self.position[1] == 1: 316 return self.check_moves([2, 4]) 317 if self.position[1] == 6: 318 return self.check_moves([3, 5]) 319 if 2 <= self.position[1] <= 5 and self.position[0] in {1, 6} and self.position not in self.special_cases: 320 if self.position[0] == 1: 321 return self.check_moves([0, 1]) 322 if self.position[0] == 6: 323 return self.check_moves([6, 7]) 324 if self.position in self.special_cases: 325 return self.check_moves(self.special_cases[self.position]) 326 return self.check_moves([]) 327 328class Bishop(Piece): 329 """Implementation of the Bishop. 330 331 Args: 332 Piece : Inheritance from the master class Piece to access general functions of the figures. 333 """ 334 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 335 """Constructor is really basic. Setups master class and setups board, color and loads asset. 336 337 Args: 338 color (str): Color of the Bishop. 339 board : Board object on which figures will be placed. 340 position (tuple[int, int]): Position on the board. 341 """ 342 super().__init__(color, board, position) 343 self.color: str = color 344 self.board = board 345 self.load_image() 346 self.moves_vec = [ 347 (-1, -1), (-1, 1), 348 ( 1, -1), (1, 1) 349 ] 350 351 def check_possible_moves(self, color: str, checking: bool = False) -> list[tuple[int, int]]: 352 """Function checking all possible moves of the Bishop. 353 354 Args: 355 color (str): Color of the Bishop. 356 checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False. 357 358 Returns: 359 list[tuple[int, int]]: List of all legal position to which Bishop can move. 360 """ 361 possible_moves: list[tuple[int, int]] = [] 362 if self.check_turn(color) and not checking: 363 return possible_moves 364 for move in self.moves_vec: 365 for i in range(1, 8): 366 multiplied_vec = tuple(x * i for x in move) 367 x = self.position[0] + multiplied_vec[0] 368 y = self.position[1] + multiplied_vec[1] 369 if 0 <= x <= 7 and 0 <= y <= 7: 370 if not self.board.board[x][y].figure: 371 possible_moves.append((x, y)) 372 elif self.board.board[x][y].figure.color != self.color: 373 possible_moves.append((x, y)) 374 break 375 else: 376 break 377 else: 378 break 379 return possible_moves 380 381class Rook(Piece): 382 """Implementation of the Rook. 383 384 Args: 385 Piece : Inheritance from the master class Piece to access general functions of the figures. 386 """ 387 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 388 """Constructor is really basic. Setups master class and setups board, color and loads asset. 389 390 Args: 391 color (str): Color of the Rook. 392 board : Board object on which figures will be placed. 393 position (tuple[int, int]): Position on the board. 394 """ 395 super().__init__(color, board, position) 396 self.color: str = color 397 self.board = board 398 self.load_image() 399 self.first_move: bool = True 400 self.moves_vec = [ 401 (-1, 0), (0,-1), 402 ( 1, 0), (0, 1) 403 ] 404 405 def check_possible_moves(self, color: str, checking: bool = False) -> list[tuple[int, int]]: 406 """Function checking all possible moves of the Rook. 407 408 Args: 409 color (str): Color of the Rook. 410 checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False. 411 412 Returns: 413 list[tuple[int, int]]: List of all legal position to which Rook can move. 414 """ 415 possible_moves: list[tuple[int, int]] = [] 416 if self.check_turn(color) and not checking: 417 return possible_moves 418 for move in self.moves_vec: 419 for i in range(1, 8): 420 multiplied_vec = tuple(x * i for x in move) 421 x = self.position[0] + multiplied_vec[0] 422 y = self.position[1] + multiplied_vec[1] 423 if 0 <= x <= 7 and 0 <= y <= 7: 424 if not self.board.board[x][y].figure: 425 possible_moves.append((x, y)) 426 elif self.board.board[x][y].figure.color != self.color: 427 possible_moves.append((x, y)) 428 break 429 else: 430 break 431 else: 432 break 433 return possible_moves 434 435class Queen(Piece): 436 """Implementation of the Queen. 437 438 Args: 439 Piece : Inheritance from the master class Piece to access general functions of the figures. 440 """ 441 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 442 """Constructor is really basic. Setups master class and setups board, color and loads asset. 443 444 Args: 445 color (str): Color of the Queen. 446 board : Board object on which figures will be placed. 447 position (tuple[int, int]): Position on the board. 448 """ 449 super().__init__(color, board, position) 450 self.color: str = color 451 self.board = board 452 self.load_image() 453 self.moves_vec = [ 454 (-1, 0), (0,-1), 455 ( 1, 0), (0, 1), 456 (-1, -1), (-1, 1), 457 ( 1, -1), (1, 1) 458 ] 459 460 def check_possible_moves(self, color: str, checking: bool = False) -> list[tuple[int, int]]: 461 """Function checking all possible moves of the Queen. 462 463 Args: 464 color (str): Color of the Queen. 465 checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False. 466 467 Returns: 468 list[tuple[int, int]]: List of all legal position to which Queen can move. 469 """ 470 possible_moves: list[tuple[int, int]] = [] 471 if self.check_turn(color) and not checking: 472 return possible_moves 473 for move in self.moves_vec: 474 for i in range(1, 8): 475 multiplied_vec = tuple(x * i for x in move) 476 x = self.position[0] + multiplied_vec[0] 477 y = self.position[1] + multiplied_vec[1] 478 if 0 <= x <= 7 and 0 <= y <= 7: 479 if not self.board.board[x][y].figure: 480 possible_moves.append((x, y)) 481 elif self.board.board[x][y].figure.color != self.color: 482 possible_moves.append((x, y)) 483 break 484 else: 485 break 486 else: 487 break 488 return possible_moves 489 490class King(Piece): 491 """Implementation of the King. 492 493 Args: 494 Piece : Inheritance from the master class Piece to access general functions of the figures. 495 """ 496 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 497 """Constructor is really basic. Setups master class and setups board, color and loads asset. 498 499 Args: 500 color (str): Color of the King. 501 board : Board object on which figures will be placed. 502 position (tuple[int, int]): Position on the board. 503 """ 504 super().__init__(color, board, position) 505 self.color: str = color 506 self.board = board 507 self.load_image() 508 self.first_move: bool = True 509 self.can_castle: bool = False 510 511 def check_possible_moves(self, color: str, checking: bool = False) -> list[tuple[int, int]]: 512 """Function checking all possible moves of the King. 513 514 Args: 515 color (str): Color of the King. 516 checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False. 517 518 Returns: 519 list[tuple[int, int]]: List of all legal position to which King can move. 520 """ 521 possible_moves: list[tuple[int, int]] = [] 522 if self.check_turn(color) and not checking: 523 return possible_moves 524 for i in range(max(0, self.position[0] - 1), min(8, self.position[0] + 2)): 525 for j in range(max(0, self.position[1] - 1), min(8, self.position[1] + 2)): 526 if not self.board.board[i][j].figure: 527 possible_moves.append((i, j)) 528 if self.board.board[i][j].figure and self.board.board[i][j].figure.color != self.color: 529 possible_moves.append((i, j)) 530 if self.first_move and not checking: 531 possible_moves.extend(self.get_castling_moves()) 532 return possible_moves 533 534 def get_castling_moves(self) -> list[tuple[int, int]]: 535 """Function checking moves for castle. 536 537 Returns: 538 list[tuple[int, int]]: List of legal positions. 539 """ 540 castling_moves = [] 541 row = self.position[0] 542 if self.can_castle_kingside(): 543 castling_moves.append((row, 6)) 544 if self.can_castle_queenside(): 545 castling_moves.append((row, 2)) 546 return castling_moves 547 548 def can_castle_kingside(self) -> bool: 549 """Function checking if King can perform castle from King side. 550 551 Returns: 552 bool: True if King can castle. False otherwise. 553 """ 554 row, col = self.position 555 if self.first_move and isinstance(self.board.board[row][7].figure, Rook) and self.board.board[row][7].figure.first_move: 556 for i in range(col + 1, 7): 557 if self.board.board[row][i].figure or self.board.is_under_attack((row, i), self.color): 558 return False 559 if self.board.is_under_attack((row, 6), self.color) or self.board.is_under_attack((row, col), self.color): 560 return False 561 return True 562 return False 563 564 def can_castle_queenside(self) -> bool: 565 """Function checking if King can perform castle from Queen side. 566 567 Returns: 568 bool: True if King can castle. False otherwise. 569 """ 570 row, col = self.position 571 if self.first_move and isinstance(self.board.board[row][0].figure, Rook) and self.board.board[row][0].figure.first_move: 572 for i in range(col - 1, 0, -1): 573 if self.board.board[row][i].figure or self.board.is_under_attack((row, i), self.color): 574 return False 575 if self.board.is_under_attack((row, 2), self.color) or self.board.is_under_attack((row, col), self.color): 576 return False 577 return True 578 return False
16class Piece: 17 """Parent class for every figure. Has general implementation of functions that can be reused. 18 Abstract method which raises NotImplementedError if check_possible_moves() is not implemented to prevent adding figure that could cause errors when used. 19 """ 20 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 21 """Constructor: 22 - loading assets 23 - virtual function for checking possible moves 24 - checking turns 25 - updating assets 26 - representation of the class for easier debugging 27 28 Args: 29 color (str): Color of the figure. 30 board : Board object on which figures will be placed. 31 position (tuple[int, int]): Position on the board. 32 """ 33 self.color: str = color 34 self.board = board 35 self.position: tuple[int, int] = position 36 self.first_move: bool = False 37 self.image: ctk.CTkImage | None = None 38 39 def check_possible_moves(self, color: str, checking: bool=False): 40 """Virtual function. 41 42 Args: 43 color (str): Color of the figure to move. 44 checking (bool, optional): Flag indicating search. Defaults to False. 45 46 Raises: 47 NotImplementedError: All Figures have to have this function implemented. 48 """ 49 raise NotImplementedError 50 51 def check_turn(self, current_color: str) -> bool: 52 """Checks which player has its right to move. 53 54 Args: 55 current_color (str): Color of the clicked figure. 56 57 Returns: 58 bool: True if its given color turn, False otherwise. 59 """ 60 return False if current_color == self.color else True 61 62 def load_image(self, piece: str | None=None) -> None | ctk.CTkImage: 63 """Loads asset for the piece. 64 65 Args: 66 piece (str | None, optional): Piece string representation. Defaults to None. 67 68 Returns: 69 None | ctk.CTkImage: If piece representation passed function will try to load asset. None otherwise. 70 71 Raises: 72 FileExistsError: If file doesn't exist game will crash and give feedback in the console. 73 FileNotFoundError: If file couldn't be found game will crash and give feedback in the console. 74 """ 75 if not piece: 76 piece_name = (self.__class__.__name__).lower() 77 else: 78 piece_name = piece 79 path: str = resource_path(os.path.join('assets', f'{get_from_config('theme')}', f'{piece_name}_{self.color}.png')) 80 try: 81 loaded_image = Image.open(path).convert('RGBA') 82 size = int(get_from_config('size')) - 10 83 if piece: 84 return ctk.CTkImage( 85 light_image=loaded_image, 86 dark_image=loaded_image, 87 size=(size, size)) 88 self.image = ctk.CTkImage( 89 light_image=loaded_image, 90 dark_image=loaded_image, 91 size=(size, size)) 92 except (FileExistsError, FileNotFoundError) as e: 93 update_error_log(e) 94 return None 95 96 def update_image(self) -> None: 97 """Function updating cell asset. 98 """ 99 self.load_image() 100 self.board.board[self.position[0]][self.position[1]].configure(image=self.image) 101 102 def __str__(self) -> str: 103 """Overriding string representation of the class used in print() for example. 104 105 Returns: 106 str: Representation of the class Piece: {piece name} Color:{piece color} 107 """ 108 return f'Piece: {self.__class__.__name__} | Color: {'white' if self.color == 'w' else 'black'} | Position {self.position}'
Parent class for every figure. Has general implementation of functions that can be reused. Abstract method which raises NotImplementedError if check_possible_moves() is not implemented to prevent adding figure that could cause errors when used.
20 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 21 """Constructor: 22 - loading assets 23 - virtual function for checking possible moves 24 - checking turns 25 - updating assets 26 - representation of the class for easier debugging 27 28 Args: 29 color (str): Color of the figure. 30 board : Board object on which figures will be placed. 31 position (tuple[int, int]): Position on the board. 32 """ 33 self.color: str = color 34 self.board = board 35 self.position: tuple[int, int] = position 36 self.first_move: bool = False 37 self.image: ctk.CTkImage | None = None
Constructor:
- loading assets
- virtual function for checking possible moves
- checking turns
- updating assets
- representation of the class for easier debugging
Arguments:
- color (str): Color of the figure.
- board : Board object on which figures will be placed.
- position (tuple[int, int]): Position on the board.
39 def check_possible_moves(self, color: str, checking: bool=False): 40 """Virtual function. 41 42 Args: 43 color (str): Color of the figure to move. 44 checking (bool, optional): Flag indicating search. Defaults to False. 45 46 Raises: 47 NotImplementedError: All Figures have to have this function implemented. 48 """ 49 raise NotImplementedError
Virtual function.
Arguments:
- color (str): Color of the figure to move.
- checking (bool, optional): Flag indicating search. Defaults to False.
Raises:
- NotImplementedError: All Figures have to have this function implemented.
51 def check_turn(self, current_color: str) -> bool: 52 """Checks which player has its right to move. 53 54 Args: 55 current_color (str): Color of the clicked figure. 56 57 Returns: 58 bool: True if its given color turn, False otherwise. 59 """ 60 return False if current_color == self.color else True
Checks which player has its right to move.
Arguments:
- current_color (str): Color of the clicked figure.
Returns:
bool: True if its given color turn, False otherwise.
62 def load_image(self, piece: str | None=None) -> None | ctk.CTkImage: 63 """Loads asset for the piece. 64 65 Args: 66 piece (str | None, optional): Piece string representation. Defaults to None. 67 68 Returns: 69 None | ctk.CTkImage: If piece representation passed function will try to load asset. None otherwise. 70 71 Raises: 72 FileExistsError: If file doesn't exist game will crash and give feedback in the console. 73 FileNotFoundError: If file couldn't be found game will crash and give feedback in the console. 74 """ 75 if not piece: 76 piece_name = (self.__class__.__name__).lower() 77 else: 78 piece_name = piece 79 path: str = resource_path(os.path.join('assets', f'{get_from_config('theme')}', f'{piece_name}_{self.color}.png')) 80 try: 81 loaded_image = Image.open(path).convert('RGBA') 82 size = int(get_from_config('size')) - 10 83 if piece: 84 return ctk.CTkImage( 85 light_image=loaded_image, 86 dark_image=loaded_image, 87 size=(size, size)) 88 self.image = ctk.CTkImage( 89 light_image=loaded_image, 90 dark_image=loaded_image, 91 size=(size, size)) 92 except (FileExistsError, FileNotFoundError) as e: 93 update_error_log(e) 94 return None
Loads asset for the piece.
Arguments:
- piece (str | None, optional): Piece string representation. Defaults to None.
Returns:
None | ctk.CTkImage: If piece representation passed function will try to load asset. None otherwise.
Raises:
- FileExistsError: If file doesn't exist game will crash and give feedback in the console.
- FileNotFoundError: If file couldn't be found game will crash and give feedback in the console.
110class Pawn(Piece): 111 """Implementation of the pawn. Supports en passant, promotions, moving and capturing. 112 113 Args: 114 Piece (Piece): Inheritance from the master class Piece to access general functions of the figures. 115 """ 116 def __init__(self, color: str, board, position: tuple[int, int], notation_func: Callable) -> None: 117 """Constructor: 118 basic setup of master class Piece 119 loads additional flags necessary for correct pawn implementation 120 121 Args: 122 color (str): Color of the pawn. 123 board : Board object on which the pawn will be placed. 124 position (tuple[int, int]): Position of the pawn on the board. 125 notation_func (Callable): Callable function from notation module used to note the move. 126 """ 127 super().__init__(color, board, position) 128 self.color: str = color # b | w 129 self.position: tuple[int, int] = position 130 self.board = board # Board object (import loop occurs if imported for type annotation) 131 self.load_image() 132 self.first_move: bool = True 133 self.moved_by_two: bool = False 134 self.can_en_passant: bool = False 135 self.move: int = 1 if self.color == 'b' else -1 136 self.notation_func: Callable = notation_func 137 138 def check_possible_moves(self, color: str, checking: bool=False) -> list[tuple[int, int]]: 139 """Function checking all possible moves for the Pawn. 140 141 Args: 142 color (str): Color of the pawn. 143 checking (bool, optional): Flag to know when player makes move and when algorithm checks possible moves. Defaults to False. 144 145 Returns: 146 list[tuple[int, int]]: Returns list of all legal positions to which pawn can move. 147 """ 148 possible_moves: list[tuple[int, int]] = [] 149 if self.check_turn(color): 150 return possible_moves 151 move = self.move 152 x: int = self.position[0] 153 y: int = self.position[1] 154 forward_one = (x + move, y) 155 forward_two = (x + move + move, y) 156 if not self.board.board[forward_one[0]][forward_one[1]].figure: 157 possible_moves.append(forward_one) 158 if self.first_move and not self.board.board[forward_two[0]][forward_two[1]].figure: 159 possible_moves.append(forward_two) 160 for offset in [-1, 1]: 161 if 0 <= y + offset < 8: 162 capture_position = (x + move, y + offset) 163 target_square = self.board.board[capture_position[0]][capture_position[1]] 164 if target_square.figure and target_square.figure.color != self.color: 165 possible_moves.append(capture_position) 166 adjacent_pawn = self.board.board[x][y + offset].figure 167 if isinstance(adjacent_pawn, Pawn) and adjacent_pawn.color != self.color and adjacent_pawn.moved_by_two: 168 possible_moves.append((x + move, y + offset)) 169 self.can_en_passant = True 170 return possible_moves 171 172 def choose_figure(self, event: Any, figure, choose_piece_menu: ctk.CTkLabel, choose_piece_menu_1: ctk.CTkFrame) -> None: 173 """Function responsible of promoting the pawn to other figure. 174 175 Args: 176 event (Any): Event type. Doesn't matter but is required parameter by customtkinter. 177 figure : Figure chosen by the player. 178 choose_piece_menu (ctk.CTkLabel): Label widget. 179 choose_piece_menu_1 (ctk.CTkFrame): Frame widget. 180 """ 181 x, y = self.position[0], self.position[1] 182 self.board.board[x][y].figure = figure(self.color, self.board, self.position) 183 self.board.board[x][y].update() 184 self.notation_func(self.board.board[x][y].figure.__class__.__name__) 185 choose_piece_menu.destroy() 186 choose_piece_menu_1.destroy() 187 188 def create_button(self, choose_piece_menu: ctk.CTkLabel, figure, choose_piece_menu_1: ctk.CTkFrame) -> None: 189 """Function creating the button for one of the figure possible to choose from the menu. 190 191 Args: 192 choose_piece_menu (ctk.CTkLabel): Label in which button will be created. 193 figure : Figure that will be possible to choose by clicking the button. 194 choose_piece_menu_1 (ctk.CTkFrame): Frame widget. 195 """ 196 piece_image: ctk.CTkImage | None = self.load_image(str(figure.__name__)) 197 button_figure: ctk.CTkLabel = ctk.CTkLabel( 198 master = choose_piece_menu, 199 text = '', 200 image = piece_image, 201 corner_radius = 0 202 ) 203 button_figure.pack(side=ctk.LEFT, padx=10, pady=10) 204 button_figure.bind('<Button-1>', lambda e: self.choose_figure(e, figure, choose_piece_menu, choose_piece_menu_1)) 205 206 def promote(self) -> bool: 207 """Function checking if pawn is ont the end of the board. If so it force the player to choose the figure they want to promote to. 208 209 Returns: 210 bool: True if pawn was promoted. False otherwise. 211 """ 212 if self.position[0] in {0, 7}: 213 choose_piece_menu_1: ctk.CTkFrame = ctk.CTkFrame( 214 master = self.board, corner_radius=0, 215 fg_color = COLOR.BACKGROUND 216 ) 217 choose_piece_menu_1.place(relx=0, rely=0, relwidth=1, relheight=1) 218 if platform.system() == 'Windows': 219 pywinstyles.set_opacity(choose_piece_menu_1, value=0.01, color="#000001") 220 choose_piece_menu: ctk.CTkFrame = ctk.CTkFrame( 221 master = self.board, 222 fg_color = COLOR.BACKGROUND, 223 corner_radius = 0, 224 border_color = COLOR.DARK_TEXT, 225 border_width = 4 226 ) 227 choose_piece_menu.place(relx=0.5, rely=0.5, anchor=ctk.CENTER) 228 possible_figures = [Knight, Bishop, Rook, Queen] 229 for figure in possible_figures: 230 self.create_button(choose_piece_menu, figure, choose_piece_menu_1) 231 return True 232 return False 233 234 def notate(self, figure_name: Piece, moves_record, capture: bool, check: bool, checkmate: bool) -> None: 235 """Helper function to note the move of the pawn. 236 237 Args: 238 figure_name (Piece): Name of the figure. 239 moves_record : Object of MovesRecord. Cannot specify type due to circular imports. 240 capture (bool): Flag to check if capture occurred. 241 check (bool): Flag to check if after pawn move check occurred. 242 checkmate (bool): Flag to check if after pawn move checkmate occurred. 243 """ 244 moves_record.record_move(figure_name, 245 capture=capture, castle=None, check=check, checkmate=checkmate, 246 promotion=f'{self.board.board[self.position[0]][self.position[1]].figure.__class__.__name__[0]}' 247 )
Implementation of the pawn. Supports en passant, promotions, moving and capturing.
Arguments:
- Piece (Piece): Inheritance from the master class Piece to access general functions of the figures.
116 def __init__(self, color: str, board, position: tuple[int, int], notation_func: Callable) -> None: 117 """Constructor: 118 basic setup of master class Piece 119 loads additional flags necessary for correct pawn implementation 120 121 Args: 122 color (str): Color of the pawn. 123 board : Board object on which the pawn will be placed. 124 position (tuple[int, int]): Position of the pawn on the board. 125 notation_func (Callable): Callable function from notation module used to note the move. 126 """ 127 super().__init__(color, board, position) 128 self.color: str = color # b | w 129 self.position: tuple[int, int] = position 130 self.board = board # Board object (import loop occurs if imported for type annotation) 131 self.load_image() 132 self.first_move: bool = True 133 self.moved_by_two: bool = False 134 self.can_en_passant: bool = False 135 self.move: int = 1 if self.color == 'b' else -1 136 self.notation_func: Callable = notation_func
Constructor:
basic setup of master class Piece loads additional flags necessary for correct pawn implementation
Arguments:
- color (str): Color of the pawn.
- board : Board object on which the pawn will be placed.
- position (tuple[int, int]): Position of the pawn on the board.
- notation_func (Callable): Callable function from notation module used to note the move.
138 def check_possible_moves(self, color: str, checking: bool=False) -> list[tuple[int, int]]: 139 """Function checking all possible moves for the Pawn. 140 141 Args: 142 color (str): Color of the pawn. 143 checking (bool, optional): Flag to know when player makes move and when algorithm checks possible moves. Defaults to False. 144 145 Returns: 146 list[tuple[int, int]]: Returns list of all legal positions to which pawn can move. 147 """ 148 possible_moves: list[tuple[int, int]] = [] 149 if self.check_turn(color): 150 return possible_moves 151 move = self.move 152 x: int = self.position[0] 153 y: int = self.position[1] 154 forward_one = (x + move, y) 155 forward_two = (x + move + move, y) 156 if not self.board.board[forward_one[0]][forward_one[1]].figure: 157 possible_moves.append(forward_one) 158 if self.first_move and not self.board.board[forward_two[0]][forward_two[1]].figure: 159 possible_moves.append(forward_two) 160 for offset in [-1, 1]: 161 if 0 <= y + offset < 8: 162 capture_position = (x + move, y + offset) 163 target_square = self.board.board[capture_position[0]][capture_position[1]] 164 if target_square.figure and target_square.figure.color != self.color: 165 possible_moves.append(capture_position) 166 adjacent_pawn = self.board.board[x][y + offset].figure 167 if isinstance(adjacent_pawn, Pawn) and adjacent_pawn.color != self.color and adjacent_pawn.moved_by_two: 168 possible_moves.append((x + move, y + offset)) 169 self.can_en_passant = True 170 return possible_moves
Function checking all possible moves for the Pawn.
Arguments:
- color (str): Color of the pawn.
- checking (bool, optional): Flag to know when player makes move and when algorithm checks possible moves. Defaults to False.
Returns:
list[tuple[int, int]]: Returns list of all legal positions to which pawn can move.
172 def choose_figure(self, event: Any, figure, choose_piece_menu: ctk.CTkLabel, choose_piece_menu_1: ctk.CTkFrame) -> None: 173 """Function responsible of promoting the pawn to other figure. 174 175 Args: 176 event (Any): Event type. Doesn't matter but is required parameter by customtkinter. 177 figure : Figure chosen by the player. 178 choose_piece_menu (ctk.CTkLabel): Label widget. 179 choose_piece_menu_1 (ctk.CTkFrame): Frame widget. 180 """ 181 x, y = self.position[0], self.position[1] 182 self.board.board[x][y].figure = figure(self.color, self.board, self.position) 183 self.board.board[x][y].update() 184 self.notation_func(self.board.board[x][y].figure.__class__.__name__) 185 choose_piece_menu.destroy() 186 choose_piece_menu_1.destroy()
Function responsible of promoting the pawn to other figure.
Arguments:
- event (Any): Event type. Doesn't matter but is required parameter by customtkinter.
- figure : Figure chosen by the player.
- choose_piece_menu (ctk.CTkLabel): Label widget.
- choose_piece_menu_1 (ctk.CTkFrame): Frame widget.
206 def promote(self) -> bool: 207 """Function checking if pawn is ont the end of the board. If so it force the player to choose the figure they want to promote to. 208 209 Returns: 210 bool: True if pawn was promoted. False otherwise. 211 """ 212 if self.position[0] in {0, 7}: 213 choose_piece_menu_1: ctk.CTkFrame = ctk.CTkFrame( 214 master = self.board, corner_radius=0, 215 fg_color = COLOR.BACKGROUND 216 ) 217 choose_piece_menu_1.place(relx=0, rely=0, relwidth=1, relheight=1) 218 if platform.system() == 'Windows': 219 pywinstyles.set_opacity(choose_piece_menu_1, value=0.01, color="#000001") 220 choose_piece_menu: ctk.CTkFrame = ctk.CTkFrame( 221 master = self.board, 222 fg_color = COLOR.BACKGROUND, 223 corner_radius = 0, 224 border_color = COLOR.DARK_TEXT, 225 border_width = 4 226 ) 227 choose_piece_menu.place(relx=0.5, rely=0.5, anchor=ctk.CENTER) 228 possible_figures = [Knight, Bishop, Rook, Queen] 229 for figure in possible_figures: 230 self.create_button(choose_piece_menu, figure, choose_piece_menu_1) 231 return True 232 return False
Function checking if pawn is ont the end of the board. If so it force the player to choose the figure they want to promote to.
Returns:
bool: True if pawn was promoted. False otherwise.
234 def notate(self, figure_name: Piece, moves_record, capture: bool, check: bool, checkmate: bool) -> None: 235 """Helper function to note the move of the pawn. 236 237 Args: 238 figure_name (Piece): Name of the figure. 239 moves_record : Object of MovesRecord. Cannot specify type due to circular imports. 240 capture (bool): Flag to check if capture occurred. 241 check (bool): Flag to check if after pawn move check occurred. 242 checkmate (bool): Flag to check if after pawn move checkmate occurred. 243 """ 244 moves_record.record_move(figure_name, 245 capture=capture, castle=None, check=check, checkmate=checkmate, 246 promotion=f'{self.board.board[self.position[0]][self.position[1]].figure.__class__.__name__[0]}' 247 )
Helper function to note the move of the pawn.
Arguments:
- figure_name (Piece): Name of the figure.
- moves_record : Object of MovesRecord. Cannot specify type due to circular imports.
- capture (bool): Flag to check if capture occurred.
- check (bool): Flag to check if after pawn move check occurred.
- checkmate (bool): Flag to check if after pawn move checkmate occurred.
Inherited Members
249class Knight(Piece): 250 """Implementation of the Knight. 251 252 Args: 253 Piece : Inheritance from the master class Piece to access general functions of the figures. 254 """ 255 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 256 """Constructor is really basic. Setups master class and setups board, color and loads asset. 257 258 Args: 259 color (str): Color of the Knight. 260 board : Board object on which figures will be placed. 261 position (tuple[int, int]): Position on the board. 262 """ 263 super().__init__(color, board, position) 264 self.color: str = color 265 self.board = board 266 self.load_image() 267 self.moves: list[tuple[int, int]] = [ 268 (-2,-1), (-2, 1), 269 (-1,-2), (-1, 2), 270 ( 1,-2), ( 1, 2), 271 ( 2,-1), ( 2, 1) 272 ] 273 self.special_cases: dict[tuple[int, int], list[int]] = { 274 (1, 1): [0, 1, 2, 4], 275 (1, 6): [0, 1, 3, 5], 276 (6, 6): [3, 5, 6, 7], 277 (6, 1): [2, 4, 3, 5], 278 (0, 0): [0, 1, 2, 3, 4, 6], 279 (0, 1): [0, 1, 2, 3, 4], 280 (1, 0): [0, 1, 2, 4, 7] 281 } 282 283 def check_moves(self, exceptions: list[int]) -> list[tuple[int, int]]: 284 """Function checking possible moves for the Knight. 285 286 Args: 287 exceptions (list[int]): List of position that are not legal. 288 289 Returns: 290 list[tuple[int, int]]: List of all legal moves. 291 """ 292 possible_moves: list[tuple[int, int]] = [] 293 for i, move in enumerate(self.moves): 294 if i in exceptions: 295 continue 296 new_position = (self.position[0] + move[0], self.position[1] + move[1]) 297 if 0 <= new_position[0] <= 7 and 0 <= new_position[1] <= 7: 298 target_square = self.board.board[new_position[0]][new_position[1]] 299 if not target_square.figure or target_square.figure.color != self.color: 300 possible_moves.append(new_position) 301 return possible_moves 302 303 def check_possible_moves(self, color: str, checking: bool = False) -> list[tuple[int, int]]: 304 """Function checking all possible moves for the Knight. 305 306 Args: 307 color (str): Color of the Knight. 308 checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False. 309 310 Returns: 311 list[tuple[int, int]]: List of all legal position to which Knight can move. 312 """ 313 if self.check_turn(color) and not checking: 314 return [] 315 if 2 <= self.position[0] <= 5 and self.position[1] in {1, 6} and self.position not in self.special_cases: 316 if self.position[1] == 1: 317 return self.check_moves([2, 4]) 318 if self.position[1] == 6: 319 return self.check_moves([3, 5]) 320 if 2 <= self.position[1] <= 5 and self.position[0] in {1, 6} and self.position not in self.special_cases: 321 if self.position[0] == 1: 322 return self.check_moves([0, 1]) 323 if self.position[0] == 6: 324 return self.check_moves([6, 7]) 325 if self.position in self.special_cases: 326 return self.check_moves(self.special_cases[self.position]) 327 return self.check_moves([])
Implementation of the Knight.
Arguments:
- Piece : Inheritance from the master class Piece to access general functions of the figures.
255 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 256 """Constructor is really basic. Setups master class and setups board, color and loads asset. 257 258 Args: 259 color (str): Color of the Knight. 260 board : Board object on which figures will be placed. 261 position (tuple[int, int]): Position on the board. 262 """ 263 super().__init__(color, board, position) 264 self.color: str = color 265 self.board = board 266 self.load_image() 267 self.moves: list[tuple[int, int]] = [ 268 (-2,-1), (-2, 1), 269 (-1,-2), (-1, 2), 270 ( 1,-2), ( 1, 2), 271 ( 2,-1), ( 2, 1) 272 ] 273 self.special_cases: dict[tuple[int, int], list[int]] = { 274 (1, 1): [0, 1, 2, 4], 275 (1, 6): [0, 1, 3, 5], 276 (6, 6): [3, 5, 6, 7], 277 (6, 1): [2, 4, 3, 5], 278 (0, 0): [0, 1, 2, 3, 4, 6], 279 (0, 1): [0, 1, 2, 3, 4], 280 (1, 0): [0, 1, 2, 4, 7] 281 }
Constructor is really basic. Setups master class and setups board, color and loads asset.
Arguments:
- color (str): Color of the Knight.
- board : Board object on which figures will be placed.
- position (tuple[int, int]): Position on the board.
283 def check_moves(self, exceptions: list[int]) -> list[tuple[int, int]]: 284 """Function checking possible moves for the Knight. 285 286 Args: 287 exceptions (list[int]): List of position that are not legal. 288 289 Returns: 290 list[tuple[int, int]]: List of all legal moves. 291 """ 292 possible_moves: list[tuple[int, int]] = [] 293 for i, move in enumerate(self.moves): 294 if i in exceptions: 295 continue 296 new_position = (self.position[0] + move[0], self.position[1] + move[1]) 297 if 0 <= new_position[0] <= 7 and 0 <= new_position[1] <= 7: 298 target_square = self.board.board[new_position[0]][new_position[1]] 299 if not target_square.figure or target_square.figure.color != self.color: 300 possible_moves.append(new_position) 301 return possible_moves
Function checking possible moves for the Knight.
Arguments:
- exceptions (list[int]): List of position that are not legal.
Returns:
list[tuple[int, int]]: List of all legal moves.
303 def check_possible_moves(self, color: str, checking: bool = False) -> list[tuple[int, int]]: 304 """Function checking all possible moves for the Knight. 305 306 Args: 307 color (str): Color of the Knight. 308 checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False. 309 310 Returns: 311 list[tuple[int, int]]: List of all legal position to which Knight can move. 312 """ 313 if self.check_turn(color) and not checking: 314 return [] 315 if 2 <= self.position[0] <= 5 and self.position[1] in {1, 6} and self.position not in self.special_cases: 316 if self.position[1] == 1: 317 return self.check_moves([2, 4]) 318 if self.position[1] == 6: 319 return self.check_moves([3, 5]) 320 if 2 <= self.position[1] <= 5 and self.position[0] in {1, 6} and self.position not in self.special_cases: 321 if self.position[0] == 1: 322 return self.check_moves([0, 1]) 323 if self.position[0] == 6: 324 return self.check_moves([6, 7]) 325 if self.position in self.special_cases: 326 return self.check_moves(self.special_cases[self.position]) 327 return self.check_moves([])
Function checking all possible moves for the Knight.
Arguments:
- color (str): Color of the Knight.
- checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False.
Returns:
list[tuple[int, int]]: List of all legal position to which Knight can move.
Inherited Members
329class Bishop(Piece): 330 """Implementation of the Bishop. 331 332 Args: 333 Piece : Inheritance from the master class Piece to access general functions of the figures. 334 """ 335 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 336 """Constructor is really basic. Setups master class and setups board, color and loads asset. 337 338 Args: 339 color (str): Color of the Bishop. 340 board : Board object on which figures will be placed. 341 position (tuple[int, int]): Position on the board. 342 """ 343 super().__init__(color, board, position) 344 self.color: str = color 345 self.board = board 346 self.load_image() 347 self.moves_vec = [ 348 (-1, -1), (-1, 1), 349 ( 1, -1), (1, 1) 350 ] 351 352 def check_possible_moves(self, color: str, checking: bool = False) -> list[tuple[int, int]]: 353 """Function checking all possible moves of the Bishop. 354 355 Args: 356 color (str): Color of the Bishop. 357 checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False. 358 359 Returns: 360 list[tuple[int, int]]: List of all legal position to which Bishop can move. 361 """ 362 possible_moves: list[tuple[int, int]] = [] 363 if self.check_turn(color) and not checking: 364 return possible_moves 365 for move in self.moves_vec: 366 for i in range(1, 8): 367 multiplied_vec = tuple(x * i for x in move) 368 x = self.position[0] + multiplied_vec[0] 369 y = self.position[1] + multiplied_vec[1] 370 if 0 <= x <= 7 and 0 <= y <= 7: 371 if not self.board.board[x][y].figure: 372 possible_moves.append((x, y)) 373 elif self.board.board[x][y].figure.color != self.color: 374 possible_moves.append((x, y)) 375 break 376 else: 377 break 378 else: 379 break 380 return possible_moves
Implementation of the Bishop.
Arguments:
- Piece : Inheritance from the master class Piece to access general functions of the figures.
335 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 336 """Constructor is really basic. Setups master class and setups board, color and loads asset. 337 338 Args: 339 color (str): Color of the Bishop. 340 board : Board object on which figures will be placed. 341 position (tuple[int, int]): Position on the board. 342 """ 343 super().__init__(color, board, position) 344 self.color: str = color 345 self.board = board 346 self.load_image() 347 self.moves_vec = [ 348 (-1, -1), (-1, 1), 349 ( 1, -1), (1, 1) 350 ]
Constructor is really basic. Setups master class and setups board, color and loads asset.
Arguments:
- color (str): Color of the Bishop.
- board : Board object on which figures will be placed.
- position (tuple[int, int]): Position on the board.
352 def check_possible_moves(self, color: str, checking: bool = False) -> list[tuple[int, int]]: 353 """Function checking all possible moves of the Bishop. 354 355 Args: 356 color (str): Color of the Bishop. 357 checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False. 358 359 Returns: 360 list[tuple[int, int]]: List of all legal position to which Bishop can move. 361 """ 362 possible_moves: list[tuple[int, int]] = [] 363 if self.check_turn(color) and not checking: 364 return possible_moves 365 for move in self.moves_vec: 366 for i in range(1, 8): 367 multiplied_vec = tuple(x * i for x in move) 368 x = self.position[0] + multiplied_vec[0] 369 y = self.position[1] + multiplied_vec[1] 370 if 0 <= x <= 7 and 0 <= y <= 7: 371 if not self.board.board[x][y].figure: 372 possible_moves.append((x, y)) 373 elif self.board.board[x][y].figure.color != self.color: 374 possible_moves.append((x, y)) 375 break 376 else: 377 break 378 else: 379 break 380 return possible_moves
Function checking all possible moves of the Bishop.
Arguments:
- color (str): Color of the Bishop.
- checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False.
Returns:
list[tuple[int, int]]: List of all legal position to which Bishop can move.
Inherited Members
382class Rook(Piece): 383 """Implementation of the Rook. 384 385 Args: 386 Piece : Inheritance from the master class Piece to access general functions of the figures. 387 """ 388 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 389 """Constructor is really basic. Setups master class and setups board, color and loads asset. 390 391 Args: 392 color (str): Color of the Rook. 393 board : Board object on which figures will be placed. 394 position (tuple[int, int]): Position on the board. 395 """ 396 super().__init__(color, board, position) 397 self.color: str = color 398 self.board = board 399 self.load_image() 400 self.first_move: bool = True 401 self.moves_vec = [ 402 (-1, 0), (0,-1), 403 ( 1, 0), (0, 1) 404 ] 405 406 def check_possible_moves(self, color: str, checking: bool = False) -> list[tuple[int, int]]: 407 """Function checking all possible moves of the Rook. 408 409 Args: 410 color (str): Color of the Rook. 411 checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False. 412 413 Returns: 414 list[tuple[int, int]]: List of all legal position to which Rook can move. 415 """ 416 possible_moves: list[tuple[int, int]] = [] 417 if self.check_turn(color) and not checking: 418 return possible_moves 419 for move in self.moves_vec: 420 for i in range(1, 8): 421 multiplied_vec = tuple(x * i for x in move) 422 x = self.position[0] + multiplied_vec[0] 423 y = self.position[1] + multiplied_vec[1] 424 if 0 <= x <= 7 and 0 <= y <= 7: 425 if not self.board.board[x][y].figure: 426 possible_moves.append((x, y)) 427 elif self.board.board[x][y].figure.color != self.color: 428 possible_moves.append((x, y)) 429 break 430 else: 431 break 432 else: 433 break 434 return possible_moves
Implementation of the Rook.
Arguments:
- Piece : Inheritance from the master class Piece to access general functions of the figures.
388 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 389 """Constructor is really basic. Setups master class and setups board, color and loads asset. 390 391 Args: 392 color (str): Color of the Rook. 393 board : Board object on which figures will be placed. 394 position (tuple[int, int]): Position on the board. 395 """ 396 super().__init__(color, board, position) 397 self.color: str = color 398 self.board = board 399 self.load_image() 400 self.first_move: bool = True 401 self.moves_vec = [ 402 (-1, 0), (0,-1), 403 ( 1, 0), (0, 1) 404 ]
Constructor is really basic. Setups master class and setups board, color and loads asset.
Arguments:
- color (str): Color of the Rook.
- board : Board object on which figures will be placed.
- position (tuple[int, int]): Position on the board.
406 def check_possible_moves(self, color: str, checking: bool = False) -> list[tuple[int, int]]: 407 """Function checking all possible moves of the Rook. 408 409 Args: 410 color (str): Color of the Rook. 411 checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False. 412 413 Returns: 414 list[tuple[int, int]]: List of all legal position to which Rook can move. 415 """ 416 possible_moves: list[tuple[int, int]] = [] 417 if self.check_turn(color) and not checking: 418 return possible_moves 419 for move in self.moves_vec: 420 for i in range(1, 8): 421 multiplied_vec = tuple(x * i for x in move) 422 x = self.position[0] + multiplied_vec[0] 423 y = self.position[1] + multiplied_vec[1] 424 if 0 <= x <= 7 and 0 <= y <= 7: 425 if not self.board.board[x][y].figure: 426 possible_moves.append((x, y)) 427 elif self.board.board[x][y].figure.color != self.color: 428 possible_moves.append((x, y)) 429 break 430 else: 431 break 432 else: 433 break 434 return possible_moves
Function checking all possible moves of the Rook.
Arguments:
- color (str): Color of the Rook.
- checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False.
Returns:
list[tuple[int, int]]: List of all legal position to which Rook can move.
Inherited Members
436class Queen(Piece): 437 """Implementation of the Queen. 438 439 Args: 440 Piece : Inheritance from the master class Piece to access general functions of the figures. 441 """ 442 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 443 """Constructor is really basic. Setups master class and setups board, color and loads asset. 444 445 Args: 446 color (str): Color of the Queen. 447 board : Board object on which figures will be placed. 448 position (tuple[int, int]): Position on the board. 449 """ 450 super().__init__(color, board, position) 451 self.color: str = color 452 self.board = board 453 self.load_image() 454 self.moves_vec = [ 455 (-1, 0), (0,-1), 456 ( 1, 0), (0, 1), 457 (-1, -1), (-1, 1), 458 ( 1, -1), (1, 1) 459 ] 460 461 def check_possible_moves(self, color: str, checking: bool = False) -> list[tuple[int, int]]: 462 """Function checking all possible moves of the Queen. 463 464 Args: 465 color (str): Color of the Queen. 466 checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False. 467 468 Returns: 469 list[tuple[int, int]]: List of all legal position to which Queen can move. 470 """ 471 possible_moves: list[tuple[int, int]] = [] 472 if self.check_turn(color) and not checking: 473 return possible_moves 474 for move in self.moves_vec: 475 for i in range(1, 8): 476 multiplied_vec = tuple(x * i for x in move) 477 x = self.position[0] + multiplied_vec[0] 478 y = self.position[1] + multiplied_vec[1] 479 if 0 <= x <= 7 and 0 <= y <= 7: 480 if not self.board.board[x][y].figure: 481 possible_moves.append((x, y)) 482 elif self.board.board[x][y].figure.color != self.color: 483 possible_moves.append((x, y)) 484 break 485 else: 486 break 487 else: 488 break 489 return possible_moves
Implementation of the Queen.
Arguments:
- Piece : Inheritance from the master class Piece to access general functions of the figures.
442 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 443 """Constructor is really basic. Setups master class and setups board, color and loads asset. 444 445 Args: 446 color (str): Color of the Queen. 447 board : Board object on which figures will be placed. 448 position (tuple[int, int]): Position on the board. 449 """ 450 super().__init__(color, board, position) 451 self.color: str = color 452 self.board = board 453 self.load_image() 454 self.moves_vec = [ 455 (-1, 0), (0,-1), 456 ( 1, 0), (0, 1), 457 (-1, -1), (-1, 1), 458 ( 1, -1), (1, 1) 459 ]
Constructor is really basic. Setups master class and setups board, color and loads asset.
Arguments:
- color (str): Color of the Queen.
- board : Board object on which figures will be placed.
- position (tuple[int, int]): Position on the board.
461 def check_possible_moves(self, color: str, checking: bool = False) -> list[tuple[int, int]]: 462 """Function checking all possible moves of the Queen. 463 464 Args: 465 color (str): Color of the Queen. 466 checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False. 467 468 Returns: 469 list[tuple[int, int]]: List of all legal position to which Queen can move. 470 """ 471 possible_moves: list[tuple[int, int]] = [] 472 if self.check_turn(color) and not checking: 473 return possible_moves 474 for move in self.moves_vec: 475 for i in range(1, 8): 476 multiplied_vec = tuple(x * i for x in move) 477 x = self.position[0] + multiplied_vec[0] 478 y = self.position[1] + multiplied_vec[1] 479 if 0 <= x <= 7 and 0 <= y <= 7: 480 if not self.board.board[x][y].figure: 481 possible_moves.append((x, y)) 482 elif self.board.board[x][y].figure.color != self.color: 483 possible_moves.append((x, y)) 484 break 485 else: 486 break 487 else: 488 break 489 return possible_moves
Function checking all possible moves of the Queen.
Arguments:
- color (str): Color of the Queen.
- checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False.
Returns:
list[tuple[int, int]]: List of all legal position to which Queen can move.
Inherited Members
491class King(Piece): 492 """Implementation of the King. 493 494 Args: 495 Piece : Inheritance from the master class Piece to access general functions of the figures. 496 """ 497 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 498 """Constructor is really basic. Setups master class and setups board, color and loads asset. 499 500 Args: 501 color (str): Color of the King. 502 board : Board object on which figures will be placed. 503 position (tuple[int, int]): Position on the board. 504 """ 505 super().__init__(color, board, position) 506 self.color: str = color 507 self.board = board 508 self.load_image() 509 self.first_move: bool = True 510 self.can_castle: bool = False 511 512 def check_possible_moves(self, color: str, checking: bool = False) -> list[tuple[int, int]]: 513 """Function checking all possible moves of the King. 514 515 Args: 516 color (str): Color of the King. 517 checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False. 518 519 Returns: 520 list[tuple[int, int]]: List of all legal position to which King can move. 521 """ 522 possible_moves: list[tuple[int, int]] = [] 523 if self.check_turn(color) and not checking: 524 return possible_moves 525 for i in range(max(0, self.position[0] - 1), min(8, self.position[0] + 2)): 526 for j in range(max(0, self.position[1] - 1), min(8, self.position[1] + 2)): 527 if not self.board.board[i][j].figure: 528 possible_moves.append((i, j)) 529 if self.board.board[i][j].figure and self.board.board[i][j].figure.color != self.color: 530 possible_moves.append((i, j)) 531 if self.first_move and not checking: 532 possible_moves.extend(self.get_castling_moves()) 533 return possible_moves 534 535 def get_castling_moves(self) -> list[tuple[int, int]]: 536 """Function checking moves for castle. 537 538 Returns: 539 list[tuple[int, int]]: List of legal positions. 540 """ 541 castling_moves = [] 542 row = self.position[0] 543 if self.can_castle_kingside(): 544 castling_moves.append((row, 6)) 545 if self.can_castle_queenside(): 546 castling_moves.append((row, 2)) 547 return castling_moves 548 549 def can_castle_kingside(self) -> bool: 550 """Function checking if King can perform castle from King side. 551 552 Returns: 553 bool: True if King can castle. False otherwise. 554 """ 555 row, col = self.position 556 if self.first_move and isinstance(self.board.board[row][7].figure, Rook) and self.board.board[row][7].figure.first_move: 557 for i in range(col + 1, 7): 558 if self.board.board[row][i].figure or self.board.is_under_attack((row, i), self.color): 559 return False 560 if self.board.is_under_attack((row, 6), self.color) or self.board.is_under_attack((row, col), self.color): 561 return False 562 return True 563 return False 564 565 def can_castle_queenside(self) -> bool: 566 """Function checking if King can perform castle from Queen side. 567 568 Returns: 569 bool: True if King can castle. False otherwise. 570 """ 571 row, col = self.position 572 if self.first_move and isinstance(self.board.board[row][0].figure, Rook) and self.board.board[row][0].figure.first_move: 573 for i in range(col - 1, 0, -1): 574 if self.board.board[row][i].figure or self.board.is_under_attack((row, i), self.color): 575 return False 576 if self.board.is_under_attack((row, 2), self.color) or self.board.is_under_attack((row, col), self.color): 577 return False 578 return True 579 return False
Implementation of the King.
Arguments:
- Piece : Inheritance from the master class Piece to access general functions of the figures.
497 def __init__(self, color: str, board, position: tuple[int, int]) -> None: 498 """Constructor is really basic. Setups master class and setups board, color and loads asset. 499 500 Args: 501 color (str): Color of the King. 502 board : Board object on which figures will be placed. 503 position (tuple[int, int]): Position on the board. 504 """ 505 super().__init__(color, board, position) 506 self.color: str = color 507 self.board = board 508 self.load_image() 509 self.first_move: bool = True 510 self.can_castle: bool = False
Constructor is really basic. Setups master class and setups board, color and loads asset.
Arguments:
- color (str): Color of the King.
- board : Board object on which figures will be placed.
- position (tuple[int, int]): Position on the board.
512 def check_possible_moves(self, color: str, checking: bool = False) -> list[tuple[int, int]]: 513 """Function checking all possible moves of the King. 514 515 Args: 516 color (str): Color of the King. 517 checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False. 518 519 Returns: 520 list[tuple[int, int]]: List of all legal position to which King can move. 521 """ 522 possible_moves: list[tuple[int, int]] = [] 523 if self.check_turn(color) and not checking: 524 return possible_moves 525 for i in range(max(0, self.position[0] - 1), min(8, self.position[0] + 2)): 526 for j in range(max(0, self.position[1] - 1), min(8, self.position[1] + 2)): 527 if not self.board.board[i][j].figure: 528 possible_moves.append((i, j)) 529 if self.board.board[i][j].figure and self.board.board[i][j].figure.color != self.color: 530 possible_moves.append((i, j)) 531 if self.first_move and not checking: 532 possible_moves.extend(self.get_castling_moves()) 533 return possible_moves
Function checking all possible moves of the King.
Arguments:
- color (str): Color of the King.
- checking (bool, optional): Flag to recognize between human making a move and algorithm checking if after move check doesn't occurs. Defaults to False.
Returns:
list[tuple[int, int]]: List of all legal position to which King can move.
535 def get_castling_moves(self) -> list[tuple[int, int]]: 536 """Function checking moves for castle. 537 538 Returns: 539 list[tuple[int, int]]: List of legal positions. 540 """ 541 castling_moves = [] 542 row = self.position[0] 543 if self.can_castle_kingside(): 544 castling_moves.append((row, 6)) 545 if self.can_castle_queenside(): 546 castling_moves.append((row, 2)) 547 return castling_moves
Function checking moves for castle.
Returns:
list[tuple[int, int]]: List of legal positions.
549 def can_castle_kingside(self) -> bool: 550 """Function checking if King can perform castle from King side. 551 552 Returns: 553 bool: True if King can castle. False otherwise. 554 """ 555 row, col = self.position 556 if self.first_move and isinstance(self.board.board[row][7].figure, Rook) and self.board.board[row][7].figure.first_move: 557 for i in range(col + 1, 7): 558 if self.board.board[row][i].figure or self.board.is_under_attack((row, i), self.color): 559 return False 560 if self.board.is_under_attack((row, 6), self.color) or self.board.is_under_attack((row, col), self.color): 561 return False 562 return True 563 return False
Function checking if King can perform castle from King side.
Returns:
bool: True if King can castle. False otherwise.
565 def can_castle_queenside(self) -> bool: 566 """Function checking if King can perform castle from Queen side. 567 568 Returns: 569 bool: True if King can castle. False otherwise. 570 """ 571 row, col = self.position 572 if self.first_move and isinstance(self.board.board[row][0].figure, Rook) and self.board.board[row][0].figure.first_move: 573 for i in range(col - 1, 0, -1): 574 if self.board.board[row][i].figure or self.board.is_under_attack((row, i), self.color): 575 return False 576 if self.board.is_under_attack((row, 2), self.color) or self.board.is_under_attack((row, col), self.color): 577 return False 578 return True 579 return False
Function checking if King can perform castle from Queen side.
Returns:
bool: True if King can castle. False otherwise.