gooo
This commit is contained in:
6
chess/bishop.py
Normal file
6
chess/bishop.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from chess_piece import ChessPiece
|
||||
from player import Player
|
||||
|
||||
class Bishop(ChessPiece):
|
||||
def __init__(self, piece_color: Player):
|
||||
super().__init__(piece_color)
|
||||
@@ -28,8 +28,25 @@ class MoveValidity(Enum):
|
||||
|
||||
|
||||
# TODO: create UndoException
|
||||
class UndoException(Exception):
|
||||
pass
|
||||
|
||||
# create default board setup (y, x) not (x, y)
|
||||
# blank spaces are set to none, as seen in the chess_gui_small_view
|
||||
DEFAULT_BOARD = [
|
||||
[Rook(Player.BLACK), Knight(Player.BLACK), Bishop(Player.BLACK), Queen(Player.BLACK), King(Player.BLACK), Bishop(Player.BLACK), Knight(Player.BLACK), Rook(Player.BLACK)],
|
||||
[Pawn(Player.BLACK), Pawn(Player.BLACK), Pawn(Player.BLACK), Pawn(Player.BLACK), Pawn(Player.BLACK), Pawn(Player.BLACK), Pawn(Player.BLACK), Pawn(Player.BLACK)],
|
||||
[None, None, None, None, None, None, None, None],
|
||||
[None, None, None, None, None, None, None, None],
|
||||
[None, None, None, None, None, None, None, None],
|
||||
[None, None, None, None, None, None, None, None],
|
||||
[Pawn(Player.WHITE), Pawn(Player.WHITE), Pawn(Player.WHITE), Pawn(Player.WHITE), Pawn(Player.WHITE), Pawn(Player.WHITE), Pawn(Player.WHITE), Pawn(Player.WHITE)],
|
||||
[Rook(Player.WHITE), Knight(Player.WHITE), Bishop(Player.WHITE), Queen(Player.WHITE), King(Player.WHITE), Bishop(Player.WHITE), Knight(Player.WHITE), Rook(Player.WHITE)]
|
||||
]
|
||||
|
||||
|
||||
class ChessModel:
|
||||
# TODO: fill in this class
|
||||
pass
|
||||
def __init__(self):
|
||||
self.__board = DEFAULT_BOARD
|
||||
|
||||
# i wanna do easy checking for whether a piece can skip over another piece
|
||||
@@ -5,11 +5,7 @@ from abc import ABC, abstractmethod
|
||||
|
||||
ChessPieceT = TypeVar('ChessPieceT')
|
||||
|
||||
# my list of custom exceptions
|
||||
class PieceOutOfBoundsError(Exception): pass
|
||||
class StartEndPositionMismatch(Exception): pass
|
||||
|
||||
class ChessPiece:
|
||||
class ChessPiece(ABC):
|
||||
def __init__(self, piece_color: Player):
|
||||
self.player = piece_color
|
||||
|
||||
@@ -36,17 +32,36 @@ class ChessPiece:
|
||||
raise TypeError(f'each element in the board list bust be another list')
|
||||
|
||||
for v in arr:
|
||||
if not isinstance(v, ChessPiece):
|
||||
raise TypeError(f'each element in each row of the board must be of type ChessPiece')
|
||||
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 = board[move.to_row][move.to_col]
|
||||
board_dest: ChessPiece = board[move.from_row][move.from_col]
|
||||
within_bounds = board_dim <= move.to_col <= board_dim and board_dim <= move.to_row <= board_dim
|
||||
different_position = move.from_col != move.to_col and move.from_row != move.to_row
|
||||
at_position = board_orig == self
|
||||
is_piece_class = isinstance(board_dest, ChessPiece)
|
||||
taking_friendly_piece = board_dest.player != self.player
|
||||
board_orig: ChessPiece | None = board[move.from_col][move.from_row]
|
||||
board_dest: ChessPiece = board[move.to_col][move.to_row]
|
||||
|
||||
print(f'within_bounds={within_bounds}, different_position={different_position}, at_position={at_position}, is_piece_class={is_piece_class}, taking_friendly_piece={taking_friendly_piece}')
|
||||
return within_bounds and different_position and at_position and is_piece_class and taking_friendly_piece
|
||||
# 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
|
||||
6
chess/king.py
Normal file
6
chess/king.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from chess_piece import ChessPiece
|
||||
from player import Player
|
||||
|
||||
class King(ChessPiece):
|
||||
def __init__(self, piece_color: Player):
|
||||
super().__init__(piece_color)
|
||||
6
chess/knight.py
Normal file
6
chess/knight.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from chess_piece import ChessPiece
|
||||
from player import Player
|
||||
|
||||
class Knight(ChessPiece):
|
||||
def __init__(self, piece_color: Player):
|
||||
super().__init__(piece_color)
|
||||
@@ -68,14 +68,38 @@ def valid_range(max: int) -> list[int]:
|
||||
# class for static move sets
|
||||
class StaticMoveSet(MoveSets):
|
||||
def is_valid_move(self, move: Move) -> bool:
|
||||
# get the difference between the to and from row / column
|
||||
from_to_row_diff = move.to_row - move.from_row
|
||||
from_to_col_diff = move.to_col - move.from_col
|
||||
|
||||
# iterate over each move set, checking if it follows any of the move sets passed to the method
|
||||
for ms in self.move_sets:
|
||||
if from_to_row_diff == ms[0] and from_to_col_diff == ms[1]:
|
||||
# checks if the difference in y and x is equal to any available options
|
||||
if from_to_col_diff == ms[0] and from_to_row_diff == ms[1]:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
# in these lists, the move sets are static, so the y and x are a set of combo's of ways to move
|
||||
|
||||
"""
|
||||
pawn move sets are mostly static, but there will be an override for the is_valid_move method,
|
||||
checking to see if the pawn can move 1 up 1 left / right to take another enemy piece
|
||||
these values simulate these move sets, with x being the pawn, m being a possible static move,
|
||||
and p being possible moves (such as the case i explained)
|
||||
##########
|
||||
# x #
|
||||
# pmp #
|
||||
# m #
|
||||
# #
|
||||
# #
|
||||
# m #
|
||||
# pmp #
|
||||
# x #
|
||||
##########
|
||||
"""
|
||||
pawn_valid_move_sets = [(1, 0), (2, 0)]
|
||||
|
||||
# in these lists, the move sets are dynamic, so the y and x are a range of times they can move on the x and y
|
||||
rook_valid_move_sets = [(0, 8), (8, 0), (0, -8), (-8, 0)]
|
||||
|
||||
@@ -116,6 +140,6 @@ class DynamicMoveSet(MoveSets):
|
||||
# create move sets
|
||||
|
||||
# static move sets
|
||||
pawn_move_sets = StaticMoveSet((0, 1), (0, 2))
|
||||
pawn_move_sets = StaticMoveSet(*pawn_valid_move_sets)
|
||||
|
||||
# dynamic move sets
|
||||
@@ -1,12 +1,17 @@
|
||||
from chess_piece import ChessPiece
|
||||
from move import Move
|
||||
from move import Move, pawn_move_sets
|
||||
from player import Player
|
||||
from move_sets import pawn_valid_move_sets
|
||||
|
||||
class Pawn(ChessPiece):
|
||||
def __init__(self, piece_color: Player):
|
||||
super().__init__(piece_color)
|
||||
|
||||
def is_valid_move(self, move: Move, board: list[list[ChessPiece]]) -> bool:
|
||||
# run original check and other piece specific checks
|
||||
orig_is_valid = super().is_valid_move(move, board)
|
||||
# run original check and move set checks
|
||||
orig_valid = super().is_valid_move(move, board)
|
||||
pawn_move_set_valid = pawn_move_sets.is_valid_move(move)
|
||||
|
||||
# run piece specific check about diagonal taking
|
||||
|
||||
print(f'orig_valid={orig_valid}, pawn_move_set_valid={pawn_move_set_valid}')
|
||||
return orig_valid and pawn_move_set_valid
|
||||
6
chess/queen.py
Normal file
6
chess/queen.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from chess_piece import ChessPiece
|
||||
from player import Player
|
||||
|
||||
class Queen(ChessPiece):
|
||||
def __init__(self, piece_color: Player):
|
||||
super().__init__(piece_color)
|
||||
6
chess/rook.py
Normal file
6
chess/rook.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from chess_piece import ChessPiece
|
||||
from player import Player
|
||||
|
||||
class Rook(ChessPiece):
|
||||
def __init__(self, piece_color: Player):
|
||||
super().__init__(piece_color)
|
||||
@@ -1,11 +1,16 @@
|
||||
from chess_piece import ChessPiece
|
||||
from pytest import fixture, mark
|
||||
from pytest import fixture
|
||||
from player import Player
|
||||
from move import StaticMoveSet, Move, DynamicMoveSet, valid_range
|
||||
from move import StaticMoveSet, Move, DynamicMoveSet, valid_range, pawn_valid_move_sets
|
||||
from random import randint, choice
|
||||
from pawn import Pawn
|
||||
from chess_model import DEFAULT_BOARD
|
||||
|
||||
|
||||
# chess piece tests
|
||||
|
||||
# general piece
|
||||
|
||||
@fixture
|
||||
def valid_piece():
|
||||
return ChessPiece(Player.WHITE)
|
||||
@@ -19,11 +24,29 @@ def test_update_player(valid_piece: ChessPiece):
|
||||
|
||||
def test_repr_str(valid_piece: ChessPiece):
|
||||
rep = str(valid_piece)
|
||||
assert 'player='
|
||||
assert 'player=' in rep
|
||||
|
||||
# pawn piece
|
||||
|
||||
_INIT_PAWN_ORIGINAL_VAL = (4, 1)
|
||||
|
||||
@fixture
|
||||
def valid_board():
|
||||
# ask how to define the board
|
||||
pass
|
||||
|
||||
@fixture
|
||||
def valid_black_pawn():
|
||||
return Pawn(Player.BLACK)
|
||||
|
||||
def test_valid_move_black_pawn_1(valid_black_pawn: Pawn):
|
||||
# try all valid pawn moves
|
||||
for ms in pawn_valid_move_sets:
|
||||
assert valid_black_pawn.is_valid_move(Move(_INIT_PAWN_ORIGINAL_VAL[0], _INIT_PAWN_ORIGINAL_VAL[1], _INIT_PAWN_ORIGINAL_VAL[0]+ms[1], _INIT_PAWN_ORIGINAL_VAL[1]+ms[0]), DEFAULT_BOARD)
|
||||
|
||||
# move set testing (kinda separate from main project)
|
||||
|
||||
_init_val = 4
|
||||
_INIT_MOVE_ORIGIN_VAL = 4
|
||||
|
||||
# static move sets
|
||||
|
||||
@@ -37,13 +60,14 @@ def valid_static_move_set():
|
||||
|
||||
def test_valid_static_moves(valid_static_move_set: StaticMoveSet):
|
||||
for ms in _static_move_sets:
|
||||
assert valid_static_move_set.is_valid_move(Move(_init_val, _init_val, _init_val+ms[0], _init_val+ms[1]))
|
||||
print(ms)
|
||||
assert valid_static_move_set.is_valid_move(Move(_INIT_MOVE_ORIGIN_VAL, _INIT_MOVE_ORIGIN_VAL, _INIT_MOVE_ORIGIN_VAL+ms[0], _INIT_MOVE_ORIGIN_VAL+ms[1]))
|
||||
|
||||
# test invalid
|
||||
|
||||
def test_invalid_static_moves(valid_static_move_set: StaticMoveSet):
|
||||
for ms in _static_move_sets:
|
||||
assert not valid_static_move_set.is_valid_move(Move(_init_val, _init_val, _init_val+ms[0]+(-1 if ms[0] < 0 else 1), _init_val+ms[1]+(-1 if ms[1] < 0 else 1)))
|
||||
assert not valid_static_move_set.is_valid_move(Move(_INIT_MOVE_ORIGIN_VAL, _INIT_MOVE_ORIGIN_VAL, _INIT_MOVE_ORIGIN_VAL+ms[0]+(-1 if ms[0] < 0 else 1), _INIT_MOVE_ORIGIN_VAL+ms[1]+(-1 if ms[1] < 0 else 1)))
|
||||
|
||||
# dynamic move sets
|
||||
|
||||
@@ -75,7 +99,7 @@ def test_valid_dynamic_moves(valid_dynamic_move_set: DynamicMoveSet):
|
||||
rnd_col = choice(valid_range_col)
|
||||
|
||||
# test dat thing
|
||||
assert valid_dynamic_move_set.is_valid_move(Move(_init_val, _init_val, _init_val+rnd_row, _init_val+rnd_col))
|
||||
assert valid_dynamic_move_set.is_valid_move(Move(_INIT_MOVE_ORIGIN_VAL, _INIT_MOVE_ORIGIN_VAL, _INIT_MOVE_ORIGIN_VAL+rnd_row, _INIT_MOVE_ORIGIN_VAL+rnd_col))
|
||||
|
||||
_RND_MIN = 10
|
||||
_RND_MAX = 20
|
||||
@@ -101,4 +125,4 @@ def test_invalid_dynamic_moves(valid_dynamic_move_set: DynamicMoveSet):
|
||||
col_rnd_add = col + (rnd if col > 0 else -rnd)
|
||||
|
||||
#print(f'{ms}, ({_init_val}+{row_rnd_add}, {_init_val}+{col_rnd_add}) = ({_init_val+row_rnd_add}, {_init_val+col_rnd_add})')
|
||||
assert not valid_dynamic_move_set.is_valid_move(Move(_init_val, _init_val, _init_val+row_rnd_add, _init_val+col_rnd_add))
|
||||
assert not valid_dynamic_move_set.is_valid_move(Move(_INIT_MOVE_ORIGIN_VAL, _INIT_MOVE_ORIGIN_VAL, _INIT_MOVE_ORIGIN_VAL+row_rnd_add, _INIT_MOVE_ORIGIN_VAL+col_rnd_add))
|
||||
Reference in New Issue
Block a user