Beispiel #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()
Beispiel #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)
    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."])
def test_basic_search_with_translator_gate(has_translator: bool,
                                           echoes_resource_database):
    # Setup
    scan_visor = echoes_resource_database.get_by_type_and_index(
        ResourceType.ITEM, 10)

    node_a = GenericNode("Node A", True, 0)
    node_b = GenericNode("Node B", True, 1)
    node_c = GenericNode("Node C", True, 2)
    translator_node = TranslatorGateNode("Translator Gate", True, 3,
                                         TranslatorGate(1), scan_visor)

    world_list = WorldList([
        World("Test World", 1, [
            Area(
                "Test Area A", False, 10, 0,
                [node_a, node_b, node_c, translator_node], {
                    node_a: {
                        node_b: RequirementSet.trivial(),
                        translator_node: RequirementSet.trivial(),
                    },
                    node_b: {
                        node_a: RequirementSet.trivial(),
                    },
                    node_c: {
                        translator_node: RequirementSet.trivial(),
                    },
                    translator_node: {
                        node_a: RequirementSet.trivial(),
                        node_c: RequirementSet.trivial(),
                    },
                })
        ])
    ])
    game = GameDescription(0, "",
                           DockWeaknessDatabase([], [], [],
                                                []), echoes_resource_database,
                           RequirementSet.impossible(), None, {}, world_list)

    patches = GamePatches.with_game(game)
    patches = patches.assign_gate_assignment({TranslatorGate(1): scan_visor})
    initial_state = State({scan_visor: 1 if has_translator else 0}, (), 99,
                          node_a, patches, None, echoes_resource_database)

    # Run
    reach = reach_with_all_safe_resources(game, initial_state)

    # Assert
    if has_translator:
        assert set(
            reach.safe_nodes) == {node_a, node_b, translator_node, node_c}
    else:
        assert set(reach.safe_nodes) == {node_a, node_b}
Beispiel #5
0
def test_trivial_merge():
    trivial = RequirementSet.trivial()
    impossible = RequirementSet.impossible()
    res_a, id_req_a = make_req_a()

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

    assert trivial.union(trivial) == trivial
    assert trivial.union(the_set) == the_set
    assert the_set.union(trivial) == the_set
    assert trivial.union(impossible) == impossible
    assert impossible.union(the_set) == impossible
    assert the_set.union(impossible) == impossible
    assert the_set.union(the_set) == the_set
Beispiel #6
0
    def read_area(self, data: Dict) -> Area:
        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] = {}

            for target_name, target_requirements in origin_data["connections"].items():
                the_set = read_requirement_set(target_requirements, self.resource_database)

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

        return Area(data["name"], data["in_dark_aether"], data["asset_id"], data["default_node_index"],
                    nodes, connections)
Beispiel #7
0
    the_set = RequirementSet([
        RequirementList(0, [id_req_a]),
    ])

    assert trivial.union(trivial) == trivial
    assert trivial.union(the_set) == the_set
    assert the_set.union(trivial) == the_set
    assert trivial.union(impossible) == impossible
    assert impossible.union(the_set) == impossible
    assert the_set.union(impossible) == impossible
    assert the_set.union(the_set) == the_set


@pytest.mark.parametrize("replacement", [
    RequirementSet.impossible(),
    make_single_set(make_req_a()),
    RequirementSet([RequirementList(
        0, [make_req_a()[1], make_req_b()[1]])]),
])
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

Beispiel #8
0
def test_set_as_str_impossible():
    assert RequirementSet.impossible().as_str == "Impossible"
Beispiel #9
0
def test_impossible_requirement_as_set():
    assert Requirement.impossible().as_set(None) == RequirementSet.impossible()
Beispiel #10
0
    the_set = RequirementSet([
        RequirementList([id_req_a]),
    ])

    assert trivial.union(trivial) == trivial
    assert trivial.union(the_set) == the_set
    assert the_set.union(trivial) == the_set
    assert trivial.union(impossible) == impossible
    assert impossible.union(the_set) == impossible
    assert the_set.union(impossible) == impossible
    assert the_set.union(the_set) == the_set


@pytest.mark.parametrize(["a", "b", "expected"], [
    (RequirementSet.impossible(), make_single_set(make_req_a()), make_single_set(make_req_a())),
    (RequirementSet.impossible(), RequirementSet.trivial(), RequirementSet.trivial()),
    (RequirementSet.trivial(), make_single_set(make_req_a()), RequirementSet.trivial()),
    (make_single_set(make_req_a()), make_single_set(make_req_b()),
     RequirementSet([RequirementList([make_req_a()[1]]), RequirementList([make_req_b()[1]])])),
])
def test_expand_alternatives(a: RequirementSet, b: RequirementSet, expected: RequirementSet):
    assert a.expand_alternatives(b) == expected


@pytest.mark.parametrize(["input_data", "output_data"], [
    ([], []),
    ([(0, False)], []),
    ([(0, True)], [0]),
    ([(0, True), (0, False)], [0]),
    ([(0, True), (1, False)], [0]),
Beispiel #11
0
 def final_requirement_set(self) -> Optional[RequirementSet]:
     result = self._connections_visualizer.build_requirement_set()
     if result == RequirementSet.impossible():
         return None
     return result