67 lines
3.3 KiB
Python
67 lines
3.3 KiB
Python
from player import Player
|
|
from move import Move
|
|
from typing import TypeVar
|
|
from abc import ABC, abstractmethod
|
|
|
|
ChessPieceT = TypeVar('ChessPieceT')
|
|
|
|
class ChessPiece(ABC):
|
|
def __init__(self, piece_color: Player):
|
|
self.player = piece_color
|
|
|
|
@property
|
|
def player(self):
|
|
return self.__player
|
|
|
|
@player.setter
|
|
def player(self, new_val):
|
|
if not isinstance(new_val, Player):
|
|
raise TypeError(f'new value for player is not of type Player')
|
|
self.__player = new_val
|
|
|
|
def __str__(self):
|
|
# im not making this abstract, attributes amongst each piece are the same, str repr is also dynamic for the class name
|
|
return f'[{self.__class__.__name__} player={self.player}]'
|
|
|
|
def is_valid_move(self, move: Move, board: list[list[ChessPieceT]]) -> bool:
|
|
if not isinstance(board, list):
|
|
raise TypeError(f'board must be a list')
|
|
|
|
for arr in board:
|
|
if not isinstance(arr, list):
|
|
raise TypeError(f'each element in the board list bust be another list')
|
|
|
|
for v in arr:
|
|
if not isinstance(v, ChessPiece) and v != None:
|
|
raise TypeError(f'each element in each row of the board must be of type ChessPiece or must be None')
|
|
|
|
# create variables for the board dimensions, original spot and destination spot
|
|
board_dim = len(board)
|
|
board_orig: ChessPiece | None = board[move.from_col][move.from_row]
|
|
board_dest: ChessPiece = board[move.to_col][move.to_row]
|
|
|
|
# check if move is within bounds by checking if y and x are within the board dimensions
|
|
move_col_valid = 0 <= move.to_col <= board_dim
|
|
move_row_valid = 0 <= move.to_row <= board_dim
|
|
within_bounds = move_col_valid and move_row_valid
|
|
|
|
# check if player is still at the original position they started at
|
|
different_position = move.from_col != move.to_col or move.from_row != move.to_row
|
|
|
|
# check if the current piece trying to be moved is in the same spot on the board
|
|
#print(f'{board_orig} => {self}')
|
|
#is_current_piece = board_orig is self
|
|
is_current_piece = True
|
|
|
|
# check if the destination is not empty, if so, do destination specific checks
|
|
is_piece_class = isinstance(board_dest, ChessPiece)
|
|
|
|
# setting all these values being checked within the conditional to true, cuz if they don't have to be ran, they should still be true to return the true result of all the booleans combined
|
|
not_taking_friendly_piece = True
|
|
if is_piece_class:
|
|
# determines whether an enemy piece is being taken
|
|
not_taking_friendly_piece = board_dest.player != self.player
|
|
|
|
print(f'within_bounds={within_bounds}, different_position={different_position}, is_current_piece={is_current_piece}, not_taking_friendly_piece={not_taking_friendly_piece}, ({within_bounds and different_position and is_current_piece and not_taking_friendly_piece})')
|
|
print(f'(other) is_piece_class={is_piece_class}, board_dim={board_dim}, move_col_valid={move_col_valid} ({move.from_col} -> {move.to_col}), move_row_valid={move_row_valid} ({move.from_row} -> {move.to_row})')
|
|
return within_bounds and different_position and is_current_piece and not_taking_friendly_piece |