Example #1
0
def _inner_advance_depth(
    state: State,
    logic: Logic,
    status_update: Callable[[str], None],
) -> Tuple[Optional[State], bool]:

    if logic.game.victory_condition.satisfied(state.resources,
                                              state.resource_database):
        return state, True

    reach = ResolverReach.calculate_reach(logic, state)
    debug.log_new_advance(state, reach)
    status_update("Resolving... {} total resources".format(len(
        state.resources)))

    has_action = False
    for action in reach.satisfiable_actions(state):
        new_result = _inner_advance_depth(state=state.act_on_node(
            action, path=reach.path_to_node[action]),
                                          logic=logic,
                                          status_update=status_update)

        # We got a positive result. Send it back up
        if new_result[0] is not None:
            return new_result
        else:
            has_action = True

    debug.log_rollback(state, has_action)
    if not has_action:
        logic.additional_requirements[
            state.
            node] = _simplify_requirement_set_for_additional_requirements(
                reach.satisfiable_as_requirement_set, state)

    return None, has_action
Example #2
0
async def _inner_advance_depth(
    state: State,
    logic: Logic,
    status_update: Callable[[str], None],
    *,
    reach: Optional[ResolverReach] = None,
) -> Tuple[Optional[State], bool]:
    """

    :param state:
    :param logic:
    :param status_update:
    :param reach: A precalculated reach for the given state
    :return:
    """

    if logic.game.victory_condition.satisfied(state.resources, state.energy):
        return state, True

    # Yield back to the asyncio runner, so cancel can do something
    await asyncio.sleep(0)

    if reach is None:
        reach = ResolverReach.calculate_reach(logic, state)

    debug.log_new_advance(state, reach)
    status_update("Resolving... {} total resources".format(len(
        state.resources)))

    for action, energy in reach.possible_actions(state):
        if _should_check_if_action_is_safe(state, action,
                                           logic.game.dangerous_resources,
                                           logic.game.world_list.all_nodes):

            potential_state = state.act_on_node(
                action, path=reach.path_to_node[action], new_energy=energy)
            potential_reach = ResolverReach.calculate_reach(
                logic, potential_state)

            # If we can go back to where we were, it's a simple safe node
            if state.node in potential_reach.nodes:
                new_result = await _inner_advance_depth(
                    state=potential_state,
                    logic=logic,
                    status_update=status_update,
                    reach=potential_reach,
                )

                if not new_result[1]:
                    debug.log_rollback(state, True, True)

                # If a safe node was a dead end, we're certainly a dead end as well
                return new_result

    debug.log_checking_satisfiable_actions()
    has_action = False
    for action, energy in reach.satisfiable_actions(
            state, logic.game.victory_condition):
        new_result = await _inner_advance_depth(
            state=state.act_on_node(action,
                                    path=reach.path_to_node[action],
                                    new_energy=energy),
            logic=logic,
            status_update=status_update,
        )

        # We got a positive result. Send it back up
        if new_result[0] is not None:
            return new_result
        else:
            has_action = True

    debug.log_rollback(state, has_action, False)
    additional_requirements = reach.satisfiable_as_requirement_set

    if has_action:
        additional = set()
        for resource_node in reach.collectable_resource_nodes(state):
            additional |= logic.get_additional_requirements(
                resource_node).alternatives

        additional_requirements = additional_requirements.union(
            RequirementSet(additional))

    logic.additional_requirements[
        state.node] = _simplify_additional_requirement_set(
            additional_requirements, state, logic.game.dangerous_resources)
    return None, has_action