Beispiel #1
0
def calculate_ranges_for_player_action(
        initial_state: PlayerState,
        player_action: PlayerAction,
        game_board: Board,
        enemy_probability: np.ndarray,
        enemy_min_steps: np.ndarray,
        lookup_round_count: int = -1) \
        -> np.ndarray:

    no_risk_full_range.calculate_ranges_for_player(game_board, initial_state)
    probability_result = np.zeros((game_board.height, game_board.width))

    initial_state = initial_state.copy()
    initial_state.do_action(player_action)
    first_next_state = initial_state.do_move()

    if not first_next_state.verify_move(game_board):
        return probability_result

    first_next_state.success_probability = \
        1 - max([enemy_probability[y, x] for x, y in first_next_state.steps_to_this_point
                 if enemy_min_steps[y, x] <= 1] + [0])

    probability_result[
        first_next_state.position_y,
        first_next_state.position_x] = first_next_state.success_probability

    full_range_result_data = {}
    next_states = [first_next_state]

    current_round = 0
    while len(next_states) > 0 and lookup_round_count != current_round:
        next_states = calculate_next_states(game_board, next_states,
                                            full_range_result_data)

        for state in next_states:
            state_max_risk = max([
                enemy_probability[y, x] for x, y in state.steps_to_this_point
                if enemy_min_steps[y, x] <= current_round + 2
            ] + [0])

            state.success_probability = state.previous[
                -1].success_probability * (1 - state_max_risk)
            probability_result[state.position_y, state.position_x] = \
                max(state.success_probability, probability_result[state.position_y, state.position_x])

        current_round += 1

    return probability_result
class RandomFullRangePlayer(BasePlayer):

    def __init__(self):
        self.roundCounter = 0
        self.board = None
        self.playerState = None
        self.enemies = EnemyCollection()
        self.full_range_result = None
        self.draw_index = 0

    def handle_step(self, step_info, slice_viewer):
        new_occupied_cells = self.enemies.update(step_info)

        self.roundCounter += 1
        own_player = step_info["players"][str(step_info["you"])]

        # init on first step info
        if self.roundCounter == 1:
            self.board = Board(step_info["width"], step_info["height"])
            self.playerState = PlayerState(PlayerDirection[own_player["direction"].upper()],
                                           own_player["speed"],
                                           own_player["x"],
                                           own_player["y"],
                                           self.roundCounter)

        # update cells
        self.board.cells = step_info["cells"]

        if self.full_range_result:
            # recycle the last full_range result
            new_enemies_occupied_cells = [cell for cell in new_occupied_cells
                                          if cell not in self.playerState.steps_to_this_point]
            new_full_range_result = update_full_range_result(self.playerState.game_round,
                                                             self.playerState.get_position_tuple(),
                                                             self.full_range_result,
                                                             new_enemies_occupied_cells)
            new_path_options = [state
                                for directions in new_full_range_result.values()
                                for speeds in directions.values()
                                for state in speeds.values()]

            # add new path options to viewer
            new_path_steps_array = np.zeros((step_info["height"], step_info["width"]))
            for option in new_path_options:
                x = option.position_x
                y = option.position_y
                current_value = new_path_steps_array[y, x]
                new_value = option.game_round - self.roundCounter
                new_path_steps_array[y, x] = new_value if current_value == 0 else min(current_value, new_value)

            slice_viewer.add_data("recycled_full_range_steps", new_path_steps_array)

        # calculate action
        self.full_range_result = no_risk_full_range.calculate_ranges_for_player(self.board, self.playerState, 8)
        path_options = [state
                        for directions in self.full_range_result.values()
                        for speeds in directions.values()
                        for state in speeds.values()]

        if len(path_options) > 0:
            random_player_state_choice = random.choice(path_options)
            player_states = random_player_state_choice.previous + [random_player_state_choice]
            action = player_states[self.roundCounter - 1].action

        # random action if no way to survive
        else:
            action = random.choice(list(PlayerAction))

        # add path options to viewer
        path_steps_array = np.zeros((step_info["height"], step_info["width"]))
        for option in path_options:
            x = option.position_x
            y = option.position_y
            current_value = path_steps_array[y, x]
            new_value = option.game_round - self.roundCounter
            path_steps_array[y, x] = new_value if current_value == 0 else min(current_value, new_value)

        slice_viewer.add_data("full_range_steps", path_steps_array)

        # apply action to local model
        self.playerState.do_action(action)
        self.playerState = self.playerState.do_move()

        return action

    def get_slice_viewer_attributes(self):
        return ["full_range_steps", "recycled_full_range_steps"]
class CombinedFullRangePlayer(BasePlayer):
    def __init__(self):

        self.REACHABLE_POINT_WEIGHT = 1
        self.CUTTING_WEIGHT = 0.2
        self.FILL_WEIGHT = 0.1
        self.SLOW_FORCE_WEIGHT = 0.1

        self.roundCounter = 0
        self.board = None
        self.playerState = None

    def handle_step(self, step_info, slice_viewer):

        self.roundCounter += 1
        own_player = step_info["players"][str(step_info["you"])]

        # init on first step info
        if self.roundCounter == 1:
            self.board = Board(step_info["width"], step_info["height"])
            self.playerState = PlayerState(
                PlayerDirection[own_player["direction"].upper()],
                own_player["speed"], own_player["x"], own_player["y"],
                self.roundCounter)

        # update cells
        self.board.cells = step_info["cells"]

        # build enemy player states
        enemy_player_states = []
        for player_id, player in step_info["players"].items():
            if str(step_info["you"]) != player_id and player["active"]:
                enemy_player_states.append(
                    PlayerState(PlayerDirection[player["direction"].upper()],
                                player["speed"], player["x"], player["y"],
                                self.roundCounter))

        # calculate enemy prediction
        enemy_probabilities, enemy_min_steps = \
            probability_based_prediction.calculate_probabilities_for_players(self.board, enemy_player_states, depth=7)

        # add enemy prediction to viewer
        slice_viewer.add_data("enemy_probability",
                              enemy_probabilities,
                              normalize=False)
        slice_viewer.add_data("enemy_min_steps",
                              enemy_min_steps,
                              normalize=True)

        # add safe_area sizes to viewer
        safe_areas, safe_area_labels = get_risk_evaluated_safe_areas(
            self.board)
        safe_area_sizes = np.zeros(safe_area_labels.shape)
        for area in safe_areas:
            for point in area.points:
                safe_area_sizes[point[1], point[0]] = area.risk

        slice_viewer.add_data("safe_area_sizes",
                              safe_area_sizes,
                              normalize=False)

        # add risk_area to viewer
        slice_viewer.add_data("risk_evaluation",
                              risk_area_calculation.calculate_risk_areas(
                                  self.board),
                              normalize=False)

        # get full range result for each possible action
        player_action_array = [player_action for player_action in PlayerAction]
        input_array = [(self.playerState, player_action, self.board,
                        enemy_probabilities, enemy_min_steps)
                       for player_action in player_action_array]
        pool = mp.Pool(mp.cpu_count())
        path_option_results = pool.starmap(
            enemy_probability_full_range.calculate_ranges_for_player_action,
            input_array)
        pool.close()
        full_range_results = {
            player_action:
            path_option_results[player_action_array.index(player_action)]
            for player_action in PlayerAction
        }

        # calculate reachable points for full range results
        max_reachable_points_value = \
            max(max([np.sum(full_range_result) for full_range_result in full_range_results.values()]), 1)
        reachable_points = {
            player_action:
            np.sum(full_range_result) / max_reachable_points_value
            for player_action, full_range_result in full_range_results.items()
        }

        # calculate action distribution for full range results
        cutting_distribution, fill_distribution = \
            basic_cut_fill_area_detection.determine_cutting_and_fill_values(self.playerState, self.board, 4)

        # build slow down force
        slow_force = {player_action: 0. for player_action in PlayerAction}
        slow_base_state = self.playerState.copy()
        slow_base_state.do_action(PlayerAction.SLOW_DOWN)
        slow_next_state = slow_base_state.do_move()
        if slow_next_state.verify_move(self.board):
            slow_force[PlayerAction.SLOW_DOWN] = 1.

        # calculate weighted evaluation for each possible action
        print(f"\t\t\treachable:\t\t{reachable_points}")
        print(f"\t\t\tcutting:\t\t{cutting_distribution}")
        print(f"\t\t\tfill:\t\t\t{fill_distribution}")
        print(f"\t\t\tslow:\t\t\t{slow_force}")
        weighted_action_evaluation = {
            action: reachable_points[action] * self.REACHABLE_POINT_WEIGHT +
            cutting_distribution[action] * self.CUTTING_WEIGHT +
            fill_distribution[action] * self.FILL_WEIGHT +
            slow_force[action] * self.SLOW_FORCE_WEIGHT
            for action in PlayerAction
        }
        print(f"\t\t\tevaluation:\t\t{weighted_action_evaluation}")

        # chose action based of highest value
        action = max(weighted_action_evaluation,
                     key=weighted_action_evaluation.get)

        # add reachable points to viewer
        selected_reachable_points = full_range_results[action]
        slice_viewer.add_data("full_range_probability",
                              selected_reachable_points,
                              normalize=False)

        # apply action to local model
        self.playerState.do_action(action)
        self.playerState = self.playerState.do_move()

        return action

    def get_slice_viewer_attributes(self):
        return [
            "full_range_probability", "enemy_probability", "enemy_min_steps",
            "safe_area_sizes", "risk_evaluation"
        ]
Beispiel #4
0
class EnemyProbabilityFullRangePlayer(BasePlayer):
    def __init__(self):
        self.roundCounter = 0
        self.board = None
        self.playerState = None

    def handle_step(self, step_info, slice_viewer):

        self.roundCounter += 1
        own_player = step_info["players"][str(step_info["you"])]

        # init on first step info
        if self.roundCounter == 1:
            self.board = Board(step_info["width"], step_info["height"])
            self.playerState = PlayerState(
                PlayerDirection[own_player["direction"].upper()],
                own_player["speed"], own_player["x"], own_player["y"],
                self.roundCounter)

        # update cells
        self.board.cells = step_info["cells"]

        # build enemy player states
        enemy_player_states = []
        for player_id, player in step_info["players"].items():
            if str(step_info["you"]) != player_id and player["active"]:
                enemy_player_states.append(
                    PlayerState(PlayerDirection[player["direction"].upper()],
                                player["speed"], player["x"], player["y"],
                                self.roundCounter))

        # calculate enemy prediction
        enemy_probabilities, enemy_min_steps = \
            probability_based_prediction.calculate_probabilities_for_players(self.board, enemy_player_states, depth=7)

        # add enemy prediction to viewer
        slice_viewer.add_data("enemy_probability",
                              enemy_probabilities,
                              normalize=False)
        slice_viewer.add_data("enemy_min_steps",
                              enemy_min_steps,
                              normalize=True)

        # add safe_area sizes to viewer
        safe_areas, safe_area_labels = get_risk_evaluated_safe_areas(
            self.board)
        safe_area_sizes = np.zeros(safe_area_labels.shape)
        for area in safe_areas:
            for point in area.points:
                safe_area_sizes[point[1], point[0]] = area.risk

        slice_viewer.add_data("safe_area_sizes",
                              safe_area_sizes,
                              normalize=False)

        # add risk_area to viewer
        slice_viewer.add_data("risk_evaluation",
                              risk_area_calculation.calculate_risk_areas(
                                  self.board),
                              normalize=False)

        # apply threshold to probabilities
        enemy_probabilities[enemy_probabilities > 0.19] = 1
        enemy_probabilities[enemy_probabilities != 1] = 0

        # update board with probabilities
        self.board.cells = enemy_probabilities.tolist()

        # calculate action
        full_range_result = no_risk_full_range.calculate_ranges_for_player(
            self.board, self.playerState)
        path_options = [
            state for directions in full_range_result.values()
            for speeds in directions.values() for state in speeds.values()
        ]

        if len(path_options) > 0:

            # determine action with highest amount of reachable points
            action_histogram = {
                player_action: 0
                for player_action in PlayerAction
            }
            for path_option in path_options:
                player_states = path_option.previous + [path_option]
                path_action = player_states[self.roundCounter - 1].action
                action_histogram[path_action] += 1
            action = max(action_histogram, key=action_histogram.get)

        # random action if no way to survive
        else:
            action = random.choice(list(PlayerAction))

        # add path options to viewer
        path_steps_array = np.zeros((step_info["height"], step_info["width"]))
        for option in path_options:
            x = option.position_x
            y = option.position_y
            current_value = path_steps_array[y, x]
            new_value = option.game_round - self.roundCounter
            path_steps_array[y, x] = new_value if current_value == 0 else min(
                current_value, new_value)

        slice_viewer.add_data("full_range_steps", path_steps_array)

        # apply action to local model
        self.playerState.do_action(action)
        self.playerState = self.playerState.do_move()

        return action

    def get_slice_viewer_attributes(self):
        return [
            "full_range_steps", "enemy_probability", "enemy_min_steps",
            "safe_area_sizes", "risk_evaluation"
        ]
class CorridorCombinedBidirectionalPathPlayer(BasePlayer):

    def __init__(self):

        self.REACHABLE_POINT_WEIGHT = 1
        self.FILL_WEIGHT = 0.2
        self.SLOW_FORCE_WEIGHT = 0.1

        self.roundCounter = 0
        self.board = None
        self.playerState = None
        self.pathFinder = None

    def handle_step(self, step_info, slice_viewer):

        self.roundCounter += 1
        own_player = step_info["players"][str(step_info["you"])]

        # init on first step info
        if self.roundCounter == 1:
            self.board = Board(step_info["width"], step_info["height"])
            self.playerState = PlayerState(PlayerDirection[own_player["direction"].upper()],
                                           own_player["speed"],
                                           own_player["x"],
                                           own_player["y"],
                                           self.roundCounter)
            self.pathFinder = BidirectionalPathFinder(self.board, 5, 2)

        # update cells
        self.board.cells = step_info["cells"]

        # build enemy player states
        enemy_player_states = []
        for player_id, player in step_info["players"].items():
            if str(step_info["you"]) != player_id and player["active"]:
                enemy_player_states.append(
                    PlayerState(
                        PlayerDirection[player["direction"].upper()],
                        player["speed"],
                        player["x"],
                        player["y"],
                        self.roundCounter))

        # calculate enemy prediction
        enemy_probabilities, enemy_min_steps = \
            probability_based_prediction.calculate_probabilities_for_players(self.board, enemy_player_states, depth=7)

        # add enemy prediction to viewer
        slice_viewer.add_data("enemy_probability", enemy_probabilities, normalize=False)
        slice_viewer.add_data("enemy_min_steps", enemy_min_steps, normalize=True)

        # get path finder results for each possible action
        self.pathFinder.update(self.board, self.playerState, enemy_probabilities, enemy_min_steps)
        path_finder_rating_result_map = self.pathFinder.get_result_rating_map()
        path_finder_steps_result_map = self.pathFinder.get_result_steps_map()

        # calculate reachable points for full range results
        max_reachable_points_value = \
            max(max([np.sum(result) for result in path_finder_rating_result_map.values()]), 1)
        reachable_points = {player_action: np.sum(result) / max_reachable_points_value
                            for player_action, result in path_finder_rating_result_map.items()}

        # calculate action distribution for full range results
        fill_distribution = corridor_fill_detection.determine_fill_values(self.playerState, self.board)

        # build slow down force
        slow_force = {player_action: 0. for player_action in PlayerAction}
        slow_base_state = self.playerState.copy()
        slow_base_state.do_action(PlayerAction.SLOW_DOWN)
        slow_next_state = slow_base_state.do_move()
        if slow_next_state.verify_move(self.board):
            slow_force[PlayerAction.SLOW_DOWN] = 1.

        # calculate weighted evaluation for each possible action
        print(f"\t\t\treachable:\t\t{reachable_points}")
        print(f"\t\t\tfill:\t\t\t{fill_distribution}")
        print(f"\t\t\tslow:\t\t\t{slow_force}")
        weighted_action_evaluation = {action:
                                      reachable_points[action] * self.REACHABLE_POINT_WEIGHT +
                                      fill_distribution[action] * self.FILL_WEIGHT +
                                      slow_force[action] * self.SLOW_FORCE_WEIGHT
                                      for action in PlayerAction}
        print(f"\t\t\tevaluation:\t\t{weighted_action_evaluation}")

        # chose action based of highest value
        action = max(weighted_action_evaluation, key=weighted_action_evaluation.get)

        # add reachable points to viewer
        slice_viewer.add_data("reachable_points_rating", path_finder_rating_result_map[action], normalize=False)
        slice_viewer.add_data("reachable_points_steps", path_finder_steps_result_map[action], normalize=True)

        # apply action to local model
        self.playerState.do_action(action)
        self.playerState = self.playerState.do_move()

        return action

    def get_slice_viewer_attributes(self):
        return ["reachable_points_rating", "reachable_points_steps", "enemy_probability", "enemy_min_steps"]
class MostReachablePointsWeightedPlayer(BasePlayer):

    def __init__(self):
        self.roundCounter = 0
        self.board = None
        self.playerState = None

    def handle_step(self, step_info, slice_viewer):
        self.roundCounter += 1
        own_player = step_info["players"][str(step_info["you"])]

        # init on first step info
        if self.roundCounter == 1:
            self.board = Board(step_info["width"], step_info["height"])
            self.playerState = PlayerState(PlayerDirection[own_player["direction"].upper()],
                                           own_player["speed"],
                                           own_player["x"],
                                           own_player["y"],
                                           self.roundCounter)

        # update cells
        self.board.cells = step_info["cells"]

        # build enemy player states
        enemy_player_states = []
        for player_id, player in step_info["players"].items():
            if str(step_info["you"]) != player_id and player["active"]:
                enemy_player_states.append(
                    PlayerState(
                        PlayerDirection[player["direction"].upper()],
                        player["speed"],
                        player["x"],
                        player["y"],
                        self.roundCounter))

        # calculate enemy prediction
        enemy_probabilities, enemy_min_steps = \
            probability_based_prediction.calculate_probabilities_for_players(self.board, enemy_player_states,
                                                                             depth=15, probability_cutoff=0.001)

        # add enemy prediction to viewer
        slice_viewer.add_data("enemy_probability", enemy_probabilities, normalize=False)
        slice_viewer.add_data("enemy_min_steps", enemy_min_steps, normalize=True)

        # add safe_area sizes to viewer
        safe_areas, safe_area_labels = get_risk_evaluated_safe_areas(self.board)
        safe_area_sizes = np.zeros(safe_area_labels.shape)
        for area in safe_areas:
            for point in area.points:
                safe_area_sizes[point[1], point[0]] = area.risk

        slice_viewer.add_data("safe_area_sizes", safe_area_sizes, normalize=False)

        start_time = time.time()
        # add risk_area to viewer
        slice_viewer.add_data("risk_evaluation", risk_area_calculation.calculate_risk_areas(self.board), normalize=False)

        # determine amount of reachable points for each action
        pool_input_array = [(player_action, enemy_probabilities, enemy_min_steps) for player_action in PlayerAction]
        pool = mp.Pool(mp.cpu_count())
        weighted_points_results = pool.starmap(self.get_weighted_points_for_action, pool_input_array)
        pool.close()
        action_rating = {}
        action_weight_mapping = {}
        for idx, weighted_points_result in enumerate(weighted_points_results):
            action_weight_mapping[pool_input_array[idx][0]] = weighted_points_result
            action_rating[pool_input_array[idx][0]] = np.sum(weighted_points_result)

        # chose action based of highest value
        action = max(action_rating, key=action_rating.get)

        # add weighted points to viewer
        slice_viewer.add_data("weighted_points", action_weight_mapping[action], normalize=True)

        # apply action to local model
        self.playerState.do_action(action)
        self.playerState = self.playerState.do_move()

        return action

    def get_slice_viewer_attributes(self):
        return ["weighted_points", "enemy_probability", "enemy_min_steps", "safe_area_sizes", "risk_evaluation"]

    def get_weighted_points_for_action(self,
                                       player_action: PlayerAction,
                                       probabilities: np.ndarray,
                                       min_steps: np.ndarray):
        player_state = self.playerState.copy()
        player_state.do_action(player_action)
        player_state = player_state.do_move()
        full_range_result = \
            reachable_points.calculate_reachable_points_weighted(player_state, 1, self.board, probabilities, min_steps, 50000)
        return full_range_result
Beispiel #7
0
class MostReachablePointsFullRangePlayer(BasePlayer):

    def __init__(self):
        self.roundCounter = 0
        self.board = None
        self.playerState = None

    def handle_step(self, step_info, slice_viewer):

        self.roundCounter += 1
        own_player = step_info["players"][str(step_info["you"])]

        # init on first step info
        if self.roundCounter == 1:
            self.board = Board(step_info["width"], step_info["height"])
            self.playerState = PlayerState(PlayerDirection[own_player["direction"].upper()],
                                           own_player["speed"],
                                           own_player["x"],
                                           own_player["y"],
                                           self.roundCounter)

        # update cells
        self.board.cells = step_info["cells"]

        # build enemy player states
        enemy_player_states = []
        for player_id, player in step_info["players"].items():
            if str(step_info["you"]) != player_id and player["active"]:
                enemy_player_states.append(
                    PlayerState(
                        PlayerDirection[player["direction"].upper()],
                        player["speed"],
                        player["x"],
                        player["y"],
                        self.roundCounter))

        # calculate enemy prediction
        enemy_probabilities, enemy_min_steps = \
            probability_based_prediction.calculate_probabilities_for_players(self.board, enemy_player_states, depth=7)

        # add enemy prediction to viewer
        slice_viewer.add_data("enemy_probability", enemy_probabilities, normalize=False)
        slice_viewer.add_data("enemy_min_steps", enemy_min_steps, normalize=True)

        # add safe_area sizes to viewer
        safe_areas, safe_area_labels = get_risk_evaluated_safe_areas(self.board)
        safe_area_sizes = np.zeros(safe_area_labels.shape)
        for area in safe_areas:
            for point in area.points:
                safe_area_sizes[point[1], point[0]] = area.risk

        slice_viewer.add_data("safe_area_sizes", safe_area_sizes, normalize=False)

        # add risk_area to viewer
        slice_viewer.add_data("risk_evaluation", risk_area_calculation.calculate_risk_areas(self.board), normalize=False)

        # apply threshold to probabilities
        enemy_probabilities[enemy_probabilities > 0.19] = 1
        enemy_probabilities[enemy_probabilities != 1] = 0

        # update board with probabilities
        self.board.cells = enemy_probabilities.tolist()

        # determine amount of reachable points for each action
        player_action_array = [player_action for player_action in PlayerAction]
        pool = mp.Pool(mp.cpu_count())
        path_option_results = pool.map(
            self.get_full_range_path_options_for_action, player_action_array)
        pool.close()
        action_histogram = {player_action: len(path_option_results[player_action_array.index(player_action)])
                            for player_action in PlayerAction}
        # apply inverse weight based on probability of next possible enemy step
        probabilities_in_next_step = np.copy(enemy_probabilities)
        probabilities_in_next_step[enemy_min_steps != 1] = 0
        for action, possible_points_count in action_histogram.items():
            if possible_points_count > 0:
                current_player_state = self.playerState.copy()
                current_player_state.do_action(action)
                possible_next_player_state = current_player_state.do_move()
                max_probability_of_steps = 0
                for x, y in possible_next_player_state.steps_to_this_point:
                    max_probability_of_steps = max(probabilities_in_next_step[y, x], max_probability_of_steps)
                action_histogram[action] = (1 - max_probability_of_steps) * possible_points_count

        # chose action based of highest value
        action = max(action_histogram, key=action_histogram.get)

        # add path options to viewer
        path_steps_array = np.zeros((step_info["height"], step_info["width"]))
        path_options = path_option_results[player_action_array.index(action)]
        for option in path_options:
            x = option.position_x
            y = option.position_y
            current_value = path_steps_array[y, x]
            new_value = option.game_round - self.roundCounter
            path_steps_array[y, x] = new_value if current_value == 0 else min(current_value, new_value)

        slice_viewer.add_data("full_range_steps", path_steps_array)

        # apply action to local model
        self.playerState.do_action(action)
        self.playerState = self.playerState.do_move()

        return action

    def get_slice_viewer_attributes(self):
        return ["full_range_steps", "enemy_probability", "enemy_min_steps", "safe_area_sizes", "risk_evaluation"]

    def get_full_range_path_options_for_action(self, player_action: PlayerAction):
        player_state = self.playerState.copy()
        player_state.do_action(player_action)
        player_state = player_state.do_move()
        if not player_state.verify_move(self.board):
            return []
        full_range_result = no_risk_full_range.calculate_ranges_for_player(self.board, player_state)
        path_options = [state
                        for directions in full_range_result.values()
                        for speeds in directions.values()
                        for state in speeds.values()]
        return path_options