def test_database_collectable(preset_manager, game_enum: RandovaniaGame,
                              ignore_events: set[str],
                              ignore_pickups: set[int]):
    game, initial_state, permalink = run_bootstrap(
        preset_manager.default_preset_for_game(game_enum).get_preset())
    all_pickups = set(
        reach_lib.filter_pickup_nodes(game.world_list.iterate_nodes()))
    pool_results = pool_creator.calculate_pool_results(
        permalink.get_preset(0).configuration, game.resource_database)

    initial_state.resources.add_resource_gain(
        pool_results.initial_resources.as_resource_gain())
    for pickup in pool_results.pickups:
        add_pickup_to_state(initial_state, pickup)
    for pickup in pool_results.assignment.values():
        add_pickup_to_state(initial_state, pickup)
    for trick in game.resource_database.trick:
        initial_state.resources.set_resource(
            trick,
            LayoutTrickLevel.maximum().as_number)

    expected_events = sorted([
        event for event in game.resource_database.event
        if event.short_name not in ignore_events
    ],
                             key=lambda it: it.short_name)
    expected_pickups = sorted(it.pickup_index for it in all_pickups
                              if it.pickup_index.index not in ignore_pickups)

    reach = _create_reach_with_unsafe(game, initial_state.heal())
    while list(reach_lib.collectable_resource_nodes(reach.nodes, reach)):
        reach.act_on(
            next(iter(reach_lib.collectable_resource_nodes(reach.nodes,
                                                           reach))))
        reach = advance_reach_with_possible_unsafe_resources(reach)

    # print("\nCurrent reach:")
    # print(game.world_list.node_name(reach.state.node, with_world=True))
    # for world in game.world_list.worlds:
    #     print(f"\n>> {world.name}")
    #     for node in world.all_nodes:
    #         print("[{!s:>5}, {!s:>5}, {!s:>5}] {}".format(
    #             reach.is_reachable_node(node), reach.is_safe_node(node),
    #             reach.state.resources.get(node.resource(), 0) > 0
    #             if isinstance(node, ResourceNode) else "",
    #             game.world_list.node_name(node, with_world=True)))

    collected_indices = set(reach.state.collected_pickup_indices)
    collected_events = {
        resource
        for resource, quantity in reach.state.resources.as_resource_gain()
        if quantity > 0 and resource.resource_type == ResourceType.EVENT
    }
    assert list(reach_lib.collectable_resource_nodes(reach.nodes, reach)) == []
    assert sorted(collected_indices) == expected_pickups
    assert sorted(collected_events,
                  key=lambda it: it.short_name) == expected_events
示例#2
0
    def trick_resources_for_configuration(
        self,
        configuration: TrickLevelConfiguration,
        resource_database: ResourceDatabase,
    ) -> CurrentResources:
        """
        :param configuration:
        :param resource_database:
        :return:
        """

        static_resources = {}

        for trick in resource_database.trick:
            if configuration.minimal_logic:
                level = LayoutTrickLevel.maximum()
            else:
                level = configuration.level_for_trick(trick)
            static_resources[trick] = level.as_number

        return static_resources
def test_reach_size_from_start_echoes(small_echoes_game_description,
                                      default_echoes_configuration, mocker):
    # Setup
    game = derived_nodes.remove_inactive_layers(
        small_echoes_game_description,
        default_echoes_configuration.active_layers()).get_mutable()

    mocker.patch(
        "randovania.game_description.default_database.game_description_for",
        return_value=game)
    generator = game.game.generator

    specific_levels = {
        trick.short_name: LayoutTrickLevel.maximum()
        for trick in game.resource_database.trick
    }

    def item(name: str):
        return find_resource_info_with_long_name(game.resource_database.item,
                                                 name)

    ni = NodeIdentifier.create

    def nodes(*names: str):
        def get_index(n: Node):
            return n.node_index

        result = [
            game.world_list.node_by_identifier(ni(*name.split("/")))
            for name in names
        ]
        result.sort(key=get_index)
        return result

    layout_configuration = dataclasses.replace(
        default_echoes_configuration,
        trick_level=TrickLevelConfiguration(
            minimal_logic=False,
            specific_levels=specific_levels,
            game=default_echoes_configuration.game),
        starting_location=StartingLocationList.with_elements(
            [game.starting_location],
            game=RandovaniaGame.METROID_PRIME_ECHOES,
        ))
    patches = generator.base_patches_factory.create_base_patches(
        layout_configuration, Random(15000), game, False, player_index=0)
    state = generator.bootstrap.calculate_starting_state(
        game, patches, default_echoes_configuration)
    state.resources.add_resource_gain([
        (item("Combat Visor"), 1),
        (item("Amber Translator"), 1),
        (item("Scan Visor"), 1),
        (item("Morph Ball"), 1),
        (item("Power Beam"), 1),
        (item("Charge Beam"), 1),
        (item("Grapple Beam"), 1),
        (item("Dark Beam"), 1),
        (item("Dark Ammo"), 50),
        (item("Missile"), 5),
    ])

    # Run
    reach = OldGeneratorReach.reach_from_state(game, state)
    reach_lib.collect_all_safe_resources_in_reach(reach)

    # Assert

    assert list(reach.nodes) == nodes(
        "Temple Grounds/Path of Eyes/Front of Translator Gate",
        "Temple Grounds/Path of Eyes/Lore Scan",
        "Temple Grounds/Path of Eyes/Translator Gate",
        "Temple Grounds/Path of Eyes/Door to Torvus Transport Access",
        "Temple Grounds/Torvus Transport Access/Door to Path of Eyes",
        "Temple Grounds/Torvus Transport Access/Door to Transport to Torvus Bog",
        "Temple Grounds/Torvus Transport Access/Lock - Door to Transport to Torvus Bog",
        "Temple Grounds/Transport to Torvus Bog/Door to Torvus Transport Access",
        "Temple Grounds/Transport to Torvus Bog/Lock - Door to Torvus Transport Access",
        "Temple Grounds/Transport to Torvus Bog/Elevator to Torvus Bog - Transport to Temple Grounds",
        "Torvus Bog/Transport to Temple Grounds/Elevator to Temple Grounds - Transport to Torvus Bog",
        "Torvus Bog/Transport to Temple Grounds/Door to Temple Transport Access",
        "Torvus Bog/Temple Transport Access/Door to Transport to Temple Grounds",
        "Torvus Bog/Temple Transport Access/Door to Torvus Lagoon",
        "Torvus Bog/Torvus Lagoon/Door to Temple Transport Access",
        "Torvus Bog/Torvus Lagoon/Door to Path of Roots",
        "Torvus Bog/Torvus Lagoon/Keybearer Corpse (S-Dly)",
        "Torvus Bog/Path of Roots/Door to Torvus Lagoon",
        "Torvus Bog/Path of Roots/Door to Great Bridge",
        "Torvus Bog/Path of Roots/Pickup (Missile)",
        "Torvus Bog/Path of Roots/Next to Pickup",
        "Torvus Bog/Path of Roots/Under Lore Scan",
        "Torvus Bog/Path of Roots/Lore Scan",
        "Torvus Bog/Great Bridge/Door to Path of Roots",
    )
    assert len(list(reach.safe_nodes)) == 22