Exemple #1
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()
Exemple #2
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)
Exemple #3
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
Exemple #4
0
    def _potential_nodes_from(self, node: Node) -> Iterator[Tuple[Node, RequirementSet, bool]]:
        extra_requirement = _extra_requirement_for_node(self._game, node)
        requirement_to_leave = node.requirements_to_leave(self._state.patches, self._state.resources)

        for target_node, requirements in self._game.world_list.potential_nodes_from(node, self.state.patches):
            if target_node is None:
                continue

            if requirement_to_leave != RequirementSet.trivial():
                requirements = requirements.union(requirement_to_leave)

            if extra_requirement is not None:
                requirements = requirements.union(extra_requirement)

            satisfied = requirements.satisfied(self._state.resources, self._state.energy)
            yield target_node, requirements, satisfied
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}
Exemple #6
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


@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(0, [make_req_a()[1]]),
         RequirementList(0, [make_req_b()[1]])
     ])),
])
def test_expand_alternatives(a: RequirementSet, b: RequirementSet,
                             expected: RequirementSet):
    assert a.expand_alternatives(b) == expected


@pytest.mark.parametrize(["resources", "expected_level"], [
Exemple #7
0
 def get_additional_requirements(self, node: Node) -> RequirementSet:
     return self.additional_requirements.get(node, RequirementSet.trivial())
Exemple #8
0
def test_set_as_str_trivial():
    assert RequirementSet.trivial().as_str == "Trivial"
Exemple #9
0
def test_trivial_requirement_as_set():
    assert Requirement.trivial().as_set(None) == RequirementSet.trivial()
Exemple #10
0
 def requirements_to_leave(self, patches: GamePatches, current_resources: CurrentResources) -> RequirementSet:
     return RequirementSet.trivial()
    def calculate_reach(cls, logic: Logic,
                        initial_state: State) -> "ResolverReach":

        checked_nodes: Dict[Node, int] = {}

        # Keys: nodes to check
        # Value: how much energy was available when visiting that node
        nodes_to_check: Dict[Node, int] = {
            initial_state.node: initial_state.energy
        }

        reach_nodes: Dict[Node, int] = {}
        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 = next(iter(nodes_to_check))
            energy = nodes_to_check.pop(node)

            if node.heal:
                energy = initial_state.maximum_energy

            checked_nodes[node] = energy
            if node != initial_state.node:
                reach_nodes[node] = energy

            requirement_to_leave = node.requirements_to_leave(
                initial_state.patches, initial_state.resources)

            for target_node, requirements in logic.game.world_list.potential_nodes_from(
                    node, initial_state.patches):
                if target_node is None:
                    continue

                if checked_nodes.get(target_node,
                                     math.inf) <= energy or nodes_to_check.get(
                                         target_node, math.inf) <= energy:
                    continue

                if requirement_to_leave != RequirementSet.trivial():
                    requirements = requirements.union(requirement_to_leave)

                # Check if the normal requirements to reach that node is satisfied
                satisfied = requirements.satisfied(initial_state.resources,
                                                   energy)
                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, energy)

                if satisfied:
                    nodes_to_check[
                        target_node] = energy - requirements.minimum_damage(
                            initial_state.resources, energy)
                    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.keys()).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)