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
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