def possible_moves(self): x, y = self.square # typical one hop moves moves = list( map( lambda square: Move.typical( self.board, piece=self, new_square=square), filter( # Either no piece or enemy piece to capture lambda square: square and (not self.board[ square] or self.board[square].player != self.player), (Square(x + 1, y), Square(x, y + 1), Square(x + 1, y + 1), Square(x - 1, y + 1), Square(x - 1, y), Square(x, y - 1), Square(x + 1, y - 1), Square(x - 1, y - 1))))) # castling moves king_side_castle = self.king_side_castle() if king_side_castle: moves.append(king_side_castle) queen_side_castle = self.queen_side_castle() if queen_side_castle: moves.append(queen_side_castle) return moves
def attack_squares(self): x, y = self.square right_square = Square(x + 1, y - 1) if self.player == Player.WHITE else Square( x + 1, y + 1) left_square = Square(x - 1, y - 1) if self.player == Player.WHITE else Square( x - 1, y + 1) return list( filter( # Either no piece or enemy piece to capture lambda square: square and (not self.board[ square] or self.board[square].player != self.player), [left_square, right_square]))
def develop(self, min_percent: Optional[float] = None, max_percent: Optional[float] = None) -> None: starting_square = Square(self.starting_point.x, self.starting_point.y, self.current_generation) self.squares[starting_square.x][starting_square.y] = starting_square self.__not_reproduced_squares.append([starting_square]) minp_exists = min_percent is not None maxp_exists = max_percent is not None pass_once = True while minp_exists or maxp_exists or pass_once: while self.__not_reproduced_squares != deque( [[]]) and self.count <= self.max_count: self.__develop_one_generation() if maxp_exists: if self.count / self.max_count >= max_percent: break pass_once = False print() if maxp_exists: if self.count / self.max_count >= max_percent: break else: self.__destroy() if minp_exists: if self.count / self.max_count >= min_percent: break else: self.__destroy()
def handle_click(self, pos): if self._promotion_move: # Handle promotion piece_cls = get_promotion_selection(pos) if piece_cls: self._promotion_move.new_piece = piece_cls( self._promotion_move.player, self._board) self.make_move(self._promotion_move) self._promotion_move = None self._selected_piece = None return pos = pos[0] - BOARD_LEFT, pos[1] - BOARD_TOP if 0 <= pos[0] < BOARD_WIDTH and 0 <= pos[1] < BOARD_HEIGHT: clicked_square = Square(pos[0] // SQUARE, pos[1] // SQUARE) if self._selected_piece: # if piece already selected if self._board[clicked_square] and self._board[ clicked_square].player == self._turn: self._selected_piece = self._board[ clicked_square] # if player's on own piece, change selection else: move = self.get_move(self._selected_piece, clicked_square) if move: if move.pawn_promoted: # Wait for user to make a choice self._promotion_move = move else: # Make a move if not for promotion self.make_move(move) self._selected_piece = None else: # if no piece was selected, select the piece on the square (if any) if belongs to (turn's) player if self._board[clicked_square] and self._board[ clicked_square].player == self._turn: self._selected_piece = self._board[clicked_square]
def attack_squares(self): x, y = self.square squares = [] for direction in [ [Square(x - i, y - i) for i in range(1, min(x + 1, y + 1))], [Square(x + i, y + i) for i in range(1, min(8 - x, 8 - y))], [Square(x + i, y - i) for i in range(1, min(8 - x, y + 1))], [Square(x - i, y + i) for i in range(1, min(x + 1, 8 - y))], ]: for square in direction: if not self.board[square]: # if nothing in pathway squares.append(square) continue if self.board[square].player != self.player: # if enemy in pathway squares.append(square) break return squares
def attack_squares(self): x, y = self.square squares = [] for direction in [ [Square(i, y) for i in reversed(range(0, x))], [Square(i, y) for i in range(x + 1, 8)], [Square(x, j) for j in reversed(range(0, y))], [Square(x, j) for j in range(y + 1, 8)], ]: for square in direction: if not self.board[square]: # if nothing in pathway squares.append(square) continue if self.board[ square].player != self.player: # if enemy in pathway squares.append(square) break return squares
def attack_squares(self): x, y = self.square # typical one hop moves return list( filter( # Either no piece or enemy piece to capture lambda square: square and (not self.board[ square] or self.board[square].player != self.player), (Square(x + 1, y), Square(x, y + 1), Square(x + 1, y + 1), Square(x - 1, y + 1), Square(x - 1, y), Square( x, y - 1), Square(x + 1, y - 1), Square(x - 1, y - 1))))
def __destroy(self) -> None: self.squares = [[None for y in range(self.size.y + 1)] for x in range(self.size.x + 1)] self.count = 1 self.current_generation = 1 self.__not_reproduced_squares = deque() starting_square = Square(self.starting_point.x, self.starting_point.y, self.current_generation) self.squares[starting_square.x][starting_square.y] = starting_square self.__not_reproduced_squares.append([starting_square])
def test_move_equal_operator(move): assert move == Move(Square(1, 1), value=1) assert not move == Move(Square(1, 1), value=0) assert not move == Move(Square(1, 1), value=2) assert not move == Move(Square(0, 1), value=1) assert not move == Move(Square(0, 0), value=1) assert not move == Move(Square(0, 0), value=0)
def _get_square() -> Square: """Ask human player for square coordinates.""" while True: try: pos = input(" Give disk position (x,y): ") coordinates = [ int(x.strip()) for x in pos.split(",") if x.strip() ] if len(coordinates) != 2: raise ValueError return Square(coordinates[0], coordinates[1]) except ValueError: print_error("give coordinates in the form 'x,y'!", indent=2)
def attack_squares(self): x, y = self.square return list( filter( lambda square: square and (not self.board[ square] or self.board[square].player != self.player), [ Square(x - 1, y - 2), Square(x + 1, y - 2), Square(x - 2, y - 1), Square(x + 2, y - 1), Square(x - 1, y + 2), Square(x + 1, y + 2), Square(x - 2, y + 1), Square(x + 2, y + 1) ]))
def en_passant(self): x, y = self.square if self.board.last_move: last_move = self.board.last_move enemy_piece, from_square, to_square = last_move.piece, last_move.old_square, last_move.new_square if isinstance(enemy_piece, Pawn) and \ ((enemy_piece.player == Player.WHITE and from_square.y == 6 and to_square.y == 4) or (enemy_piece.player == Player.BLACK and from_square.y == 1 and to_square.y == 3)) \ and y == to_square.y and abs(to_square.x - x) == 1: # checking the condition for en-passant en_passant_square = Square( to_square.x, y - 1 if self.player == Player.WHITE else y + 1) return Move.en_passant(self.board, self, en_passant_square, enemy_piece)
def __init__(self, size=8): self._size = size # init game board with empty disks self._board = [[Disk.EMPTY for _ in range(self._size)] for _ in range(self._size)] # set starting positions row = (self._size - 1) // 2 if self._size % 2 == 0 else (self._size - 1) // 2 - 1 col = self._size // 2 self._board[row][row] = Disk.BLACK self._board[row][col] = Disk.WHITE self._board[col][row] = Disk.WHITE self._board[col][col] = Disk.BLACK # keep track of empty squares on board to avoid checking already filled positions self._empty_squares = set( Square(x, y) for x in range(self._size) for y in range(self._size) if self._board[y][x] == Disk.EMPTY )
def queen_side_castle(self): x, y = self.square if not self.moved: # King must not have moved if not self.board[Square(3, y)] and not self.board[Square(2, y)] and not self.board[Square(1, y)] and \ self.board[Square(0, y)]: # no pieces between rook and king and rook must not have moved piece: Piece = self.board[Square(0, y)] if piece.player == self.player and isinstance( piece, Rook) and not piece.moved: if not self.under_check(): # NOTE: No castling under check return Move.castle(self.board, king=self, new_king_square=Square(2, y), rook=piece, new_rook_square=Square(3, y))
def attack_squares(self): x, y = self.square squares = [] for direction in [ # Bishop moves [Square(x - i, y - i) for i in range(1, min(x + 1, y + 1))], [Square(x + i, y + i) for i in range(1, min(8 - x, 8 - y))], [Square(x + i, y - i) for i in range(1, min(8 - x, y + 1))], [Square(x - i, y + i) for i in range(1, min(x + 1, 8 - y))], # Rook moves [Square(i, y) for i in reversed(range(0, x))], [Square(i, y) for i in range(x + 1, 8)], [Square(x, j) for j in reversed(range(0, y))], [Square(x, j) for j in range(y + 1, 8)], ]: for square in direction: if not self.board[square]: # if nothing in pathway squares.append(square) continue if self.board[ square].player != self.player: # if enemy in pathway squares.append(square) break return squares
def __square_reproduce(self, square: Square, generation: int) -> list: self.count += 1 x = square.x y = square.y neighboring_coordinates = None right = Vector(x + 1, y) up = Vector(x, y + 1) left = Vector(x - 1, y) bottom = Vector(x, y - 1) if self.quadratic: right_up = Vector(x + 1, y + 1) right_down = Vector(x + 1, y - 1) left_up = Vector(x - 1, y + 1) left_down = Vector(x - 1, y - 1) neighboring_coordinates = [ right, up, left, bottom, right_up, right_down, left_up, left_down ] else: neighboring_coordinates = [right, up, left, bottom] neighboring_squares = [] # 'nc' stands for 'neighboring coordinate' for nc in neighboring_coordinates: if (nc.x <= self.size.x and nc.x >= 0 and nc.y <= self.size.y and nc.y >= 0 and self.__able_to_reproduce()): if self.squares[nc.x][nc.y] is None: self.squares[nc.x][nc.y] = Square(nc.x, nc.y, generation) neighboring_squares.append(self.squares[nc.x][nc.y]) return neighboring_squares
def square(): return Square(1, 1)
def possible_moves(self): x, y = self.square forward_square = Square( x, y - 1) if self.player == Player.WHITE else Square(x, y + 1) forward_two_square = Square( x, y - 2) if self.player == Player.WHITE else Square(x, y + 2) right_square = Square(x + 1, y - 1) if self.player == Player.WHITE else Square( x + 1, y + 1) left_square = Square(x - 1, y - 1) if self.player == Player.WHITE else Square( x - 1, y + 1) moves = [] if not self.moved: # if not yet moved if not self.board[forward_square] and not self.board[ forward_two_square]: # if nothing in first two squares, can move two squares moves.append( Move.typical(self.board, piece=self, new_square=forward_two_square)) # promotion occurs if pawn reaches last rank promotion = (y - 1) == 0 if self.player == Player.WHITE else (y + 1) == 7 if promotion: # note: promoted piece is determined by the player. if forward_square and not self.board[ forward_square]: # if nothing forward, can move one square forward moves.append( Move.pawn_promotion(self.board, self, forward_square, new_piece=None)) if right_square and self.board[right_square] and self.board[ right_square].player != self.player: moves.append( Move.pawn_promotion(self.board, self, right_square, new_piece=None)) if left_square and self.board[left_square] and self.board[ left_square].player != self.player: moves.append( Move.pawn_promotion(self.board, self, left_square, new_piece=None)) else: # if no promotion possible (typical) if forward_square and not self.board[ forward_square]: # if nothing forward, can move one square forward moves.append(Move.typical(self.board, self, forward_square)) if right_square and self.board[right_square] and self.board[ right_square].player != self.player: moves.append(Move.typical(self.board, self, right_square)) if left_square and self.board[left_square] and self.board[ left_square].player != self.player: moves.append(Move.typical(self.board, self, left_square)) en_passant = self.en_passant() if en_passant: moves.append(en_passant) return moves
from __future__ import annotations from board import Board from chess import Chess from pieces import King, Queen, Rook, Bishop, Knight, Pawn from utils import Player, Square, History WHITE, BLACK = Player.WHITE, Player.BLACK INITIAL_POSITIONS = [ # White pieces (Pawn, Player.WHITE, Square(0, 6)), (Pawn, Player.WHITE, Square(1, 6)), (Pawn, Player.WHITE, Square(2, 6)), (Pawn, Player.WHITE, Square(3, 6)), (Pawn, Player.WHITE, Square(4, 6)), (Pawn, Player.WHITE, Square(5, 6)), (Pawn, Player.WHITE, Square(6, 6)), (Pawn, Player.WHITE, Square(7, 6)), (Rook, Player.WHITE, Square(0, 7)), (Knight, Player.WHITE, Square(1, 7)), (Bishop, Player.WHITE, Square(2, 7)), (Queen, Player.WHITE, Square(3, 7)), (King, Player.WHITE, Square(4, 7)), (Bishop, Player.WHITE, Square(5, 7)), (Knight, Player.WHITE, Square(6, 7)), (Rook, Player.WHITE, Square(7, 7)), # Black pieces (Pawn, Player.BLACK, Square(0, 1)), (Pawn, Player.BLACK, Square(1, 1)), (Pawn, Player.BLACK, Square(2, 1)),
def test_square_not_equal_operator(square): assert square != Square(0, 0) assert square != Square(0, 1) assert square != Square(1, 0) assert not square != Square(1, 1)
def move(): return Move(Square(1, 1), disk=Disk.WHITE, value=1)