def get_heuristic_value(board: Board): """ Given a board, calculates and returns its rating based on heuristics. """ # Get a list of all squares with white pieces and a list of squares with # black pieces. white_squares: List[Square] = board.get_player_squares( PlayerColor.WHITE) black_squares: List[Square] = board.get_player_squares( PlayerColor.BLACK) # If there are any black pieces, calculate the sum of all white pieces' # manhattan displacement to the first black piece in the list. This # piece will remain consistent until it is dead. This fixes the issue of # white pieces, when separated from the black pieces, not being able to # find their way to the black pieces easily. manhattan_dist_sum: int = 0 if (len(black_squares) > 0): black_square: Square = black_squares[0] for white_square in white_squares: displacement: Pos2D = (black_square.pos - white_square.pos) manhattan_dist_sum += abs(displacement.x) + abs(displacement.y) # Calculate the number of white and black pieces. This is a very # important heuristic that will help prioritize preserving white's own # pieces and killing the enemy's black pieces. num_white_pieces: int = len(white_squares) num_black_pieces: int = len(black_squares) # Return the heuristic rating by using the appropriate weights. return round( IDSAgent._WHITE_WEIGHT * num_white_pieces - IDSAgent._BLACK_WEIGHT * num_black_pieces - IDSAgent._DIST_WEIGHT * manhattan_dist_sum, IDSAgent._RATING_NUM_ROUNDING)
def get_heuristic_value(board: Board, player: PlayerColor, parameters: List[float]): """ Given a board, calculates and returns its rating based on heuristics. """ player_squares: List[Square] = board.get_player_squares(player) opponent_squares: List[Square] = board.get_player_squares( player.opposite()) # -- Num pieces -- # Calculate the number of white and black pieces. This is a very # important heuristic that will help prioritize preserving white's own # pieces and killing the enemy's black pieces. num_own_pieces: int = len(player_squares) num_opponent_pieces: int = len(opponent_squares) # -- Mobility -- # Calculate the mobility for both white and black i.e. the number of # possible moves they can make. own_mobility: int = board.get_num_moves(player) opponent_mobility: int = board.get_num_moves(player.opposite()) # -- Cohesiveness -- own_total_distance: int = 0 opponent_total_distance: int = 0 displacement: Pos2D for idx, square in enumerate(player_squares): for square2 in player_squares[idx + 1:]: displacement = square.pos - square2.pos own_total_distance += abs(displacement.x) + abs(displacement.y) for idx, square in enumerate(opponent_squares): for square2 in opponent_squares[idx + 1:]: displacement = square.pos - square2.pos opponent_total_distance += abs(displacement.x) + abs( displacement.y) own_avg_allied_distance: float = own_total_distance / (num_own_pieces + 1) opponent_avg_allied_distance: float = opponent_total_distance / ( num_opponent_pieces + 1) # -- Centrality -- own_total_distance: int = 0 opponent_total_distance: int = 0 x_displacement: float y_displacement: float for square in player_squares: x_displacement = 3.5 - square.pos.x y_displacement = 3.5 - square.pos.y own_total_distance += abs(x_displacement) + abs(y_displacement) for square in opponent_squares: x_displacement = 3.5 - square.pos.x y_displacement = 3.5 - square.pos.y opponent_total_distance += abs(x_displacement) + abs( y_displacement) own_avg_center_distance: float = own_total_distance / (num_own_pieces + 1) opponent_avg_center_distance: float = opponent_total_distance / ( num_opponent_pieces + 1) # Calculate the heuristic score/rating. rounded_heuristic_score: float = round( parameters[0] * num_own_pieces + parameters[1] * num_opponent_pieces + parameters[2] * own_mobility + parameters[3] * opponent_mobility + parameters[4] * own_avg_allied_distance + parameters[5] * opponent_avg_allied_distance + parameters[6] * own_avg_center_distance + parameters[7] * opponent_avg_center_distance, Player._RATING_NUM_ROUNDING) # Return the score as is or negate, depending on the player. # For white, return as is. For black, negate. return rounded_heuristic_score if player == PlayerColor.WHITE \ else -rounded_heuristic_score