def find_moves_to_escape_check(self, king, king_loc, current_player, opposing_player, board): escape_moves = dict() dangerous_moves = list() list_of_escape_moves = list() next_king_moves = self.find_king_escape_moves(king, king_loc, current_player, board) opposing_player_moves = [] for piece_name, location in opposing_player.get_pieces().items(): opposing_player_moves += piece_util.generate_moves_by_piece(piece_name, location, opposing_player, board, True) if piece_name.lower() in ['r', '+r', 'b', '+b'] and len([x for x in next_king_moves if x in opposing_player_moves]) > 0: dangerous_moves += piece_util.generate_attacks_by_piece(piece_name, location, king_loc, current_player, board) if self.debug_mode: print("Moves after generating dangerous moves for " + piece_name + "... " + str(dangerous_moves)) # void all of the opposing player moves where the player already has pieces opposing_player_moves = [x for x in list(set(opposing_player_moves)) if x not in opposing_player.get_pieces().values()] king_escape_moves = [x for x in next_king_moves if x not in opposing_player_moves] escape_moves[king_loc] = king_escape_moves for piece_name, location in current_player.get_pieces().items(): # Avoid changing the king's escape positions if piece_name != king: current_player_moves = piece_util.generate_moves_by_piece(piece_name, location, current_player, board, False) # Find moves that other pieces other than the king can make to move out of check intersecting_moves = [x for x in dangerous_moves if x in current_player_moves] if len(intersecting_moves) > 0: escape_moves[location] = intersecting_moves return escape_moves, dangerous_moves
def update_game_with_action(self, board, action, action_param_1, action_param_2, action_param_3=None): ''' Return type 2D-array of updated game board and boolean indicating whether an action was taken This function handles deciding which action is trying to be taken by the current player and attempts to execute that action. This function lets the functions it calls tell it whether or not the move was successful. ''' if action == 'move': board_origin = action_param_1 board_destination = action_param_2 promotion_move = action_param_3 if self.debug_mode: print(self.current_player.get_name() + " wants to make the following move: " + " ".join([action, action_param_1, action_param_2])) piece_name = piece_util.get_piece_at_location(board, board_origin) if not piece_name: if self.debug_mode: print("There was no piece at board location " + str(board_origin)) return board, False move = [action, action_param_1, action_param_2, action_param_3] board, move_was_made = self.attempt_to_move_piece(board, piece_name, move, board_origin, board_destination) return board, move_was_made elif action == 'drop': piece_name = action_param_1 drop_location = action_param_2 board, drop_was_made = self.attempt_to_drop_piece(piece_name, drop_location, board) return board, drop_was_made
def attempt_to_drop_piece(self, piece_name, drop_location, board): ''' Return type 2D-array of updated game board and boolean indicating whether a drop was made This function explicitly handles the logic for dropping a piece out of captures. It checks all the extensive set of rules regarding whether a drop can be made or not. ''' if piece_util.can_drop_piece(self.game_board, piece_name, self.current_player, drop_location, self.lower_player.captures, self.upper_player.captures): self.game_board = piece_util.drop_piece(board, self.current_player, piece_name, drop_location) if self.current_player is self.upper_player: piece_name = piece_name.upper() self.upper_player.captures.remove(piece_name) self.upper_player.update_pieces(piece_name, drop_location) else: self.lower_player.captures.remove(piece_name) self.lower_player.update_pieces(piece_name, drop_location) else: if self.debug_mode: print(self.current_player.name + " cannot drop " + str(piece_name)) return board, False return board, True
def is_opponent_in_checkmate(self, board, king, current_player, current_player_moves, escape_moves, drop_moves): ''' Return type void This function only gets called when the opposing player is in check. Thus, this function checks whether or not the opposing player is in checkmate based on the moves to escape check generated in the is_opponent_in_check function. If the opposing player is in checkmate, then the in_checkmate attribute of the opposing player is set to True, If the opposing player is not in checkmate, the escape_moves attribute is set to the escape moves generated. ''' num_pieces_in_checkmate = 0 for move_from, end_locs in escape_moves.items(): for move_to in end_locs: temp_board = deepcopy(board) temp_pieces = copy(current_player.get_pieces()) temp_moves = current_player_moves col, row = piece_util.convert_board_pos_to_index(move_to[1]), piece_util.convert_board_pos_to_index(game_board.map_char_to_num[move_to[0]]) if temp_board[row][col] != '': piece_to_remove = temp_board[row][col] temp_pieces.pop(piece_to_remove, None) piece_name = piece_util.get_piece_at_location(temp_board, move_from) temp_board = piece_util.make_move(temp_board, piece_name, move_from, move_to) for temp_piece_name, temp_loc in temp_pieces.items(): temp_moves += piece_util.generate_moves_by_piece(temp_piece_name, temp_loc, current_player, temp_board, False) if move_to in temp_moves: num_pieces_in_checkmate += 1 opposing_player = self.get_opposing_player() king_loc = opposing_player.get_piece_location(king) # void any drop locations that the current player already has pieces at drop_moves = [x for x in drop_moves if x not in current_player.get_pieces().values()] for piece in opposing_player.captures: for drop in drop_moves: temp_board = deepcopy(board) temp_captures = copy(opposing_player.captures) temp_moves = list() temp_board = piece_util.drop_piece(temp_board, current_player, piece, drop) for temp_piece_name, temp_loc in current_player.get_pieces().items(): temp = piece_util.generate_moves_by_piece(temp_piece_name, temp_loc, current_player, temp_board, False) temp_moves += temp temp_moves = [x for x in list(set(temp_moves)) if x not in current_player.get_pieces().values()] if king_loc in temp_moves: drop_moves.remove(drop) # if number of pieces in checkmates are equal to the number of moves to escape, # then there is no place to go and game is over if num_pieces_in_checkmate == (len(escape_moves.values()) + len(drop_moves)): opposing_player.in_checkmate = True else: opposing_player.escape_moves = { 'drop_moves': drop_moves, 'escape_moves': escape_moves }
def initialize_board(self, defaultConfiguation, listOfPiecesAndLocations): lower_pieces = dict() upper_pieces = dict() board = [['' for i in range(NUM_COLS)] for j in range(NUM_ROWS)] if not defaultConfiguation and listOfPiecesAndLocations: for initial_pieces in listOfPiecesAndLocations: piece_name = initial_pieces['piece'] loc = initial_pieces['position'] col = piece_utils.convert_board_pos_to_index(loc[1]) row = piece_utils.convert_board_pos_to_index( map_char_to_num[loc[0]]) if (col >= 0 and col < NUM_COLS and row >= 0 and row < NUM_ROWS): piece_name_value = ord(piece_name) if len( piece_name) == 1 else ord(piece_name[1:]) if piece_name_value > 64 and piece_name_value < 91: upper_pieces[piece_name] = loc elif piece_name_value > 96 and piece_name_value < 123: lower_pieces[piece_name] = loc board[row][col] = piece_name else: print("Piece " + str(piece_name) + " not inserted because of invalid " " board location: (" + str(col) + ", " + str(row) + ")") else: if not defaultConfiguation and not listOfPiecesAndLocations: print( "Invalid board configuation... initializing game with default board configuation." ) board[0][0] = 'k' board[1][0] = 'g' board[2][0] = 's' board[3][0] = 'b' board[4][0] = 'r' board[0][1] = 'p' board[0][4] = 'K' board[1][4] = 'G' board[2][4] = 'S' board[3][4] = 'B' board[4][4] = 'R' board[4][3] = 'P' upper_pieces = { 'K': 'a5', 'G': 'b5', 'S': 'c5', 'B': 'd5', 'R': 'e5', 'P': 'e4' } lower_pieces = { 'k': 'a1', 'g': 'b1', 's': 'c1', 'b': 'd1', 'r': 'e1', 'p': 'a2' } self.set_lower_pieces(lower_pieces) self.set_upper_pieces(upper_pieces) return board
def get_possible_piece_moves(self, current_player, board): moves = [] for piece_name, location in current_player.get_pieces().items(): moves += piece_util.generate_moves_by_piece(piece_name, location, current_player, board, False) return moves
def find_king_escape_moves(self, king, king_loc, current_player, board): next_king_moves = piece_util.generate_moves_by_piece(king, king_loc, current_player, board, False) next_king_moves = [x for x in next_king_moves if x not in current_player.get_pieces().values()] return next_king_moves
def attempt_to_move_piece(self, board, piece_name, move, board_origin, board_destination): ''' Return type 2D-array of updated game board and boolean indicating whether an move was made This function explicitly handles the logic for making a move. It checks all the extensive set of rules regarding whether a move can be made or not. ''' move = move[:-1] if move[3] is None else move if piece_util.can_make_move(board, self.current_player, piece_name, board_origin, board_destination): potential_moves = piece_util.generate_moves_by_piece(piece_name, board_origin, self.current_player, board, False) if self.debug_mode: print("Player " + self.current_player.get_name() + " has piece " + str(piece_name) + ", and potential moves: " + str(potential_moves)) opposing_player_moves = [] if piece_name.lower() == 'k': opposing_player = self.get_opposing_player() opposing_player_moves = self.get_possible_piece_moves(opposing_player, board) if board_destination in opposing_player_moves: if self.debug_mode: print("Player " + self.current_player.get_name() + " was going to make a move to put them in check.") return board, False else: if board_destination in potential_moves: if len(move) > 3 or piece_util.should_pawn_be_promoted(piece_name, self.current_player, board_destination): if piece_util.can_be_promoted(piece_name, board_origin, board_destination): temp_piece_name = piece_name piece_name = piece_util.promote_piece(piece_name) self.update_player_piece(self.current_player, temp_piece_name, board_destination) else: if self.debug_mode: print(self.current_player.name + " tried to illegally promote " + str(piece_name) + ".") return board, False else: if self.debug_mode: print("Promotion of " + str(piece_name) + " invalid...") destination_piece = piece_util.get_piece_at_location(board, board_destination) if destination_piece is not None: if not piece_util.piece_owned_by_player(self.current_player, destination_piece): # "unpromotes" a promoted piece upon capturing captured_piece = destination_piece if len(destination_piece) == 1 else destination_piece[1:] if captured_piece is not '': self.update_player_captures(self.current_player, captured_piece, destination_piece) else: if self.debug_mode: print("Move (" + str(move) + ") attempted by " + self.current_player.name + ", but they already own " + str(destination_piece)) return board, False opposing_player = self.get_opposing_player() board = piece_util.make_move(board, piece_name, board_origin, board_destination) self.update_player_piece(self.current_player, piece_name, board_destination) else: if self.debug_mode: print("Destination (" + str(board_destination) + ") not in potential moves: " + str(potential_moves)) return board, False else: if self.debug_mode: print(self.current_player.name + " cannot move " + str(piece_name)) return board, False return board, True