コード例 #1
0
    def connections_from(
            self, node: Node,
            patches: GamePatches) -> Iterator[Tuple[Node, RequirementSet]]:
        """
        Queries all nodes from other areas you can go from a given node. Aka, doors and teleporters
        :param patches:
        :param node:
        :return: Generator of pairs Node + RequirementSet for going to that node
        """
        if isinstance(node, DockNode):
            # TODO: respect is_blast_shield: if already opened once, no requirement needed.
            # Includes opening form behind with different criteria
            try:
                target_node = self.resolve_dock_node(node, patches)
                original_area = self.nodes_to_area(node)
                dock_weakness = patches.dock_weakness.get(
                    (original_area.area_asset_id, node.dock_index),
                    node.default_dock_weakness)

                yield target_node, dock_weakness.requirements
            except IndexError:
                # TODO: fix data to not having docks pointing to nothing
                yield None, RequirementSet.impossible()

        if isinstance(node, TeleporterNode):
            try:
                yield self.resolve_teleporter_node(
                    node, patches), RequirementSet.trivial()
            except IndexError:
                # TODO: fix data to not have teleporters pointing to areas with invalid default_node_index
                print("Teleporter is broken!", node)
                yield None, RequirementSet.impossible()
コード例 #2
0
    def read_area(self, data: Dict) -> Area:
        name = data["name"]
        nodes = read_array(data["nodes"], self.read_node)
        nodes_by_name = {node.name: node for node in nodes}

        connections = {}
        for i, origin_data in enumerate(data["nodes"]):
            origin = nodes[i]
            connections[origin] = {}

            extra_requirement = None
            if is_resource_node(
                    origin) and self.add_self_as_requirement_to_resources:
                extra_requirement = RequirementList.with_single_resource(
                    origin.resource())

            for target_name, target_requirements in origin_data[
                    "connections"].items():
                the_set = read_requirement_set(target_requirements,
                                               self.resource_database)
                if extra_requirement is not None:
                    the_set = the_set.union(RequirementSet([extra_requirement
                                                            ]))

                if the_set != RequirementSet.impossible():
                    connections[origin][nodes_by_name[target_name]] = the_set

        return Area(name, data["asset_id"], data["default_node_index"], nodes,
                    connections)
コード例 #3
0
def log_skip_action_missing_requirement(node: Node, game: GameDescription, requirement_set: RequirementSet):
    if _DEBUG_LEVEL > 1:
        if node in _last_printed_additional and _last_printed_additional[node] == requirement_set:
            print("{}* Skip {}, same additional".format(_indent(), n(node)))
        else:
            print("{}* Skip {}, missing additional:".format(_indent(), n(node)))
            requirement_set.pretty_print(_indent(-1))
            _last_printed_additional[node] = requirement_set
コード例 #4
0
ファイル: node.py プロジェクト: juliabenton/randovania
 def requirements_to_leave(self, patches: GamePatches, current_resources: CurrentResources) -> RequirementSet:
     if current_resources.get("add_self_as_requirement_to_resources") == 1:
         return RequirementSet([
             RequirementList(0, [
                 IndividualRequirement(self.event, 1, False),
             ])
         ])
     else:
         return RequirementSet.trivial()
コード例 #5
0
ファイル: node.py プロジェクト: juliabenton/randovania
 def requirements_to_leave(self, patches: GamePatches, current_resources: CurrentResources) -> RequirementSet:
     # FIXME: using non-resource as key in CurrentResources
     if current_resources.get("add_self_as_requirement_to_resources") == 1:
         return RequirementSet([
             RequirementList(0, [
                 IndividualRequirement(self.pickup_index, 1, False),
             ])
         ])
     else:
         return RequirementSet.trivial()
コード例 #6
0
def read_dock_weakness_database(data: Dict,
                                resource_database: ResourceDatabase,
                                ) -> DockWeaknessDatabase:
    door_types = read_array(data["door"], lambda item: read_dock_weakness(item, resource_database, DockType.DOOR))
    portal_types = read_array(data["portal"], lambda item: read_dock_weakness(item, resource_database, DockType.PORTAL))

    return DockWeaknessDatabase(
        door=door_types,
        morph_ball=[
            DockWeakness(0, "Morph Ball Door", False, RequirementSet.trivial(), DockType.MORPH_BALL_DOOR)
        ],
        other=[
            DockWeakness(0, "Other Door", False, RequirementSet.trivial(), DockType.OTHER)
        ],
        portal=portal_types)
コード例 #7
0
def test_set_dangerous_resources():
    # setup
    list_a = MagicMock()
    list_b = MagicMock()
    list_a.dangerous_resources = [1, 2, 3]
    list_b.dangerous_resources = ["a", "b", "c"]

    req_set = RequirementSet([])
    req_set.alternatives = frozenset([list_a, list_b])

    # Run
    result = set(req_set.dangerous_resources)

    # Assert
    assert result == {1, 2, 3, "a", "b", "c"}
コード例 #8
0
def test_simplify_requirement_set_static():
    res_a, id_req_a = make_req_a()
    res_b, id_req_b = make_req_b()

    the_set = RequirementSet([
        RequirementList(0, [id_req_a]),
        RequirementList(0, [id_req_b]),
    ])

    simple_1 = the_set.simplify({res_a: 0, res_b: 0})
    simple_2 = the_set.simplify({res_a: 0, res_b: 1})
    simple_3 = the_set.simplify({res_a: 1, res_b: 1})

    assert simple_1.alternatives == frozenset()
    assert simple_2.alternatives == frozenset([RequirementList(0, [])])
    assert simple_3.alternatives == frozenset([RequirementList(0, [])])
コード例 #9
0
 def build_requirement_set(self) -> Optional[RequirementSet]:
     return RequirementSet([
         RequirementList.without_misc_resources(
             [row.current_individual
              for row in element.rows], self.resource_database)
         for element in self._elements
     ])
コード例 #10
0
    def __init__(self,
                 parent: QWidget,
                 grid_layout: QGridLayout,
                 resource_database: ResourceDatabase,
                 requirement_set: Optional[RequirementSet],
                 edit_mode: bool,
                 num_columns_for_alternatives: int = 2):
        assert requirement_set != RequirementSet.impossible()

        self.parent = parent
        self.resource_database = resource_database
        self.edit_mode = edit_mode
        self.grid_layout = grid_layout
        self._elements = []
        self.num_columns_for_alternatives = num_columns_for_alternatives

        if requirement_set is not None:
            empty = True
            for alternative in requirement_set.alternatives:
                if alternative.items or self.edit_mode:
                    empty = False
                    self._add_box_with_requirements(alternative)

            if empty and not self.edit_mode:
                self._add_box_with_labels(["Trivial."])

        elif not self.edit_mode:
            self._add_box_with_labels(["Impossible to Reach."])
コード例 #11
0
def _modify_resources(game: GameDescription,
                      resource: ResourceInfo,
                      ):
    """
    This change all occurrences of the given resource to have difficulty 4
    :param game:
    :param resource:
    :return:
    """
    new_difficulty = 4
    database = game.resource_database

    def _replace(alternative: RequirementList) -> RequirementList:
        if alternative.get(resource) is not None:
            return RequirementList.without_misc_resources(
                database=database,
                items=[
                    (individual if individual.resource != database.difficulty_resource
                     else IndividualRequirement(database.difficulty_resource, new_difficulty, False))
                    for individual in alternative.values()
                ]
            )
        else:
            return alternative

    for area in game.world_list.all_areas:
        for source, connection in area.connections.items():
            connection.update({
                target: RequirementSet(
                    _replace(alternative)
                    for alternative in requirements.alternatives
                )
                for target, requirements in connection.items()
            })
コード例 #12
0
ファイル: node.py プロジェクト: juliabenton/randovania
 def requirements_to_leave(self, patches: GamePatches, current_resources: CurrentResources) -> RequirementSet:
     return RequirementSet([
         RequirementList(0, [
             IndividualRequirement(patches.translator_gates[self.gate], 1, False),
             IndividualRequirement(self.scan_visor, 1, False),
         ])
     ])
コード例 #13
0
    def calculate_reach(cls, logic: Logic,
                        initial_state: State) -> "ResolverReach":

        checked_nodes = set()
        nodes_to_check: List[Node] = [initial_state.node]

        reach_nodes: List[Node] = []
        requirements_by_node: Dict[Node,
                                   Set[RequirementList]] = defaultdict(set)

        path_to_node: Dict[Node, Tuple[Node, ...]] = {}
        path_to_node[initial_state.node] = tuple()

        while nodes_to_check:
            node = nodes_to_check.pop()
            checked_nodes.add(node)

            if node != initial_state.node:
                reach_nodes.append(node)

            for target_node, requirements in logic.game.world_list.potential_nodes_from(
                    node, initial_state.patches):
                if target_node in checked_nodes or target_node in nodes_to_check:
                    continue

                # Check if the normal requirements to reach that node is satisfied
                satisfied = requirements.satisfied(
                    initial_state.resources, initial_state.resource_database)
                if satisfied:
                    # If it is, check if we additional requirements figured out by backtracking is satisfied
                    satisfied = logic.get_additional_requirements(
                        node).satisfied(initial_state.resources,
                                        initial_state.resource_database)

                if satisfied:
                    nodes_to_check.append(target_node)
                    path_to_node[target_node] = path_to_node[node] + (node, )

                elif target_node:
                    # If we can't go to this node, store the reason in order to build the satisfiable requirements.
                    # Note we ignore the 'additional requirements' here because it'll be added on the end.
                    requirements_by_node[target_node].update(
                        requirements.alternatives)

        # Discard satisfiable requirements of nodes reachable by other means
        for node in set(reach_nodes).intersection(requirements_by_node.keys()):
            requirements_by_node.pop(node)

        if requirements_by_node:
            satisfiable_requirements = frozenset.union(*[
                RequirementSet(requirements).union(
                    logic.get_additional_requirements(node)).alternatives
                for node, requirements in requirements_by_node.items()
            ])
        else:
            satisfiable_requirements = frozenset()

        return ResolverReach(reach_nodes, path_to_node,
                             satisfiable_requirements, logic)
コード例 #14
0
def test_requirement_as_set_3():
    req = RequirementOr([
        Requirement.impossible(),
        _req("A"),
    ])
    assert req.as_set(None) == RequirementSet([
        RequirementList([_req("A")]),
    ])
コード例 #15
0
def test_requirement_as_set_2():
    req = RequirementAnd([
        Requirement.trivial(),
        _req("A"),
    ])
    assert req.as_set(None) == RequirementSet([
        RequirementList([_req("A")]),
    ])
コード例 #16
0
    def reach_from_state(cls,
                         game: GameDescription,
                         initial_state: State,
                         ) -> "GeneratorReach":

        reach = cls(game, initial_state, networkx.DiGraph())
        reach._expand_graph([GraphPath(None, initial_state.node, RequirementSet.trivial())])
        return reach
コード例 #17
0
 def requirements_to_leave(
         self, patches: GamePatches,
         current_resources: CurrentResources) -> RequirementSet:
     return RequirementSet([
         RequirementList(0, [
             IndividualRequirement(self.pickup_node.pickup_index, 1, False),
         ])
     ])
コード例 #18
0
def read_requirement_set(
        data: List[List[Dict]],
        resource_database: ResourceDatabase) -> RequirementSet:
    alternatives = read_array(
        data, lambda x: read_requirement_list(
            x, resource_database=resource_database))
    return RequirementSet(alternative for alternative in alternatives
                          if alternative is not None)
コード例 #19
0
ファイル: node.py プロジェクト: ursineasylum/randovania
    def requirements_to_leave(
            self, patches: GamePatches,
            current_resources: CurrentResources) -> RequirementSet:
        items = [IndividualRequirement(self.scan_visor, 1, False)]
        if self.required_translator is not None:
            items.append(
                IndividualRequirement(self.required_translator, 1, False))

        return RequirementSet([RequirementList(0, items)])
コード例 #20
0
def test_requirement_as_set_4():
    req = RequirementOr([
        Requirement.impossible(),
        _req("A"),
        Requirement.trivial(),
    ])
    assert req.as_set == RequirementSet([
        RequirementList([]),
    ])
コード例 #21
0
def test_replace_missing(replacement):
    trivial = RequirementSet.trivial()

    req_a = SimpleResourceInfo(0, "A", "A", "")
    id_req_a = IndividualRequirement(req_a, 1, False)

    result = trivial.replace(id_req_a, replacement)

    assert result == trivial
コード例 #22
0
def test_requirement_as_set_5():
    req = RequirementAnd([
        _req("A"),
        _req("B"),
        _req("C"),
    ])
    assert req.as_set(None) == RequirementSet([
        RequirementList([_req("A"), _req("B"), _req("C")]),
    ])
コード例 #23
0
ファイル: generator_reach.py プロジェクト: xisi/randovania
    def reach_from_state(
        cls,
        logic: Logic,
        initial_state: State,
    ) -> "GeneratorReach":

        reach = cls(logic, initial_state, networkx.DiGraph())
        reach._expand_graph(
            [GraphPath(None, initial_state.node, RequirementSet.trivial())])
        return reach
コード例 #24
0
ファイル: resolver.py プロジェクト: xisi/randovania
def _simplify_requirement_set_for_additional_requirements(
        requirements: RequirementSet, state: State) -> RequirementSet:
    new_alternatives = [
        _simplify_requirement_list(alternative, state)
        for alternative in requirements.alternatives
    ]
    return RequirementSet(alternative for alternative in new_alternatives

                          # RequirementList.simplify may return None
                          if alternative is not None)
コード例 #25
0
def test_prevent_redundant():
    res_a, id_req_a = make_req_a()
    res_b, id_req_b = make_req_b()

    the_set = RequirementSet([
        RequirementList(0, [id_req_a]),
        RequirementList(0, [id_req_a, id_req_b]),
    ])

    assert the_set.alternatives == frozenset([RequirementList(0, [id_req_a])])
コード例 #26
0
    def reach_from_state(
        cls,
        game: GameDescription,
        initial_state: State,
    ) -> "GeneratorReach":

        reach = cls(game, initial_state, graph_module.RandovaniaGraph.new())
        game.world_list.ensure_has_node_cache()
        reach._expand_graph(
            [GraphPath(None, initial_state.node, RequirementSet.trivial())])
        return reach
コード例 #27
0
ファイル: generator_reach.py プロジェクト: xisi/randovania
def _extra_requirement_for_node(game: GameDescription,
                                node: Node) -> Optional[RequirementSet]:
    extra_requirement = None

    if is_resource_node(node):
        node_resource = node.resource()
        if node_resource in game.dangerous_resources:
            extra_requirement = RequirementSet(
                [RequirementList.with_single_resource(node_resource)])

    return extra_requirement
コード例 #28
0
def test_requirement_as_set_1():
    req = RequirementAnd([
        _req("A"),
        RequirementOr([_req("B"), _req("C")]),
        RequirementOr([_req("D"), _req("E")]),
    ])
    assert req.as_set == RequirementSet([
        RequirementList([_req("A"), _req("B"), _req("D")]),
        RequirementList([_req("A"), _req("B"), _req("E")]),
        RequirementList([_req("A"), _req("C"), _req("D")]),
        RequirementList([_req("A"), _req("C"), _req("E")]),
    ])
コード例 #29
0
def _simplify_additional_requirement_set(
    requirements: RequirementSet,
    state: State,
    dangerous_resources: FrozenSet[ResourceInfo],
) -> RequirementSet:
    new_alternatives = [
        _simplify_requirement_list(alternative, state, dangerous_resources)
        for alternative in requirements.alternatives
    ]
    return RequirementSet(alternative for alternative in new_alternatives

                          # RequirementList.simplify may return None
                          if alternative is not None)
コード例 #30
0
def test_apply_edit_connections_change(
    echoes_game_data,
    qtbot,
):
    # Setup
    window = DataEditorWindow(echoes_game_data, True)
    qtbot.addWidget(window)
    game = window.game_description

    landing_site = game.world_list.area_by_asset_id(1655756413)
    source = landing_site.node_with_name("Save Station")
    target = landing_site.node_with_name("Door to Service Access")

    # Run
    window.world_selector_box.setCurrentIndex(
        window.world_selector_box.findText("Temple Grounds"))
    window.area_selector_box.setCurrentIndex(
        window.area_selector_box.findText(landing_site.name))
    window._apply_edit_connections(source, target, RequirementSet.trivial())

    # Assert
    assert landing_site.connections[source][target] == RequirementSet.trivial()