Exemplo n.º 1
0
def test_add_resources_into_another(blank_resource_db, a, b, result):
    a = wrap(blank_resource_db, a)
    b = wrap(blank_resource_db, b)
    result = wrap(blank_resource_db, result)

    ac = ResourceCollection.from_dict(blank_resource_db, a)
    bc = ResourceCollection.from_dict(blank_resource_db, b)

    ac.add_resource_gain(bc.as_resource_gain())

    assert dict(ac.as_resource_gain()) == result
Exemplo n.º 2
0
def test_assign_extra_initial_items_merge(empty_patches, initial, new_items, expected):
    db = empty_patches.game.resource_database
    initial = wrap(db, initial)
    new_items = wrap(db, new_items)
    expected = wrap(db, expected)

    # Setup
    initial_patches = dataclasses.replace(empty_patches, starting_items=ResourceCollection.from_dict(db, initial))

    # Run
    new_patches = initial_patches.assign_extra_initial_items(
        ResourceCollection.from_dict(db, new_items).as_resource_gain(),
    )

    # Assert
    assert new_patches.starting_items == ResourceCollection.from_dict(db, expected)
Exemplo n.º 3
0
def test_add_pickup_to_state(state_game_data, empty_patches,
                             generic_item_category):
    # Starting State
    db = state_game_data.resource_database
    starting_node = state_game_data.world_list.resolve_teleporter_connection(
        empty_patches.game.starting_location)
    s = state.State(ResourceCollection(), (), 99, starting_node, empty_patches,
                    None, state_game_data)

    resource_a = db.item[0]
    resource_b = db.item[1]
    p = PickupEntry("B",
                    2,
                    generic_item_category,
                    generic_item_category,
                    progression=(
                        (resource_a, 1),
                        (resource_b, 1),
                    ))

    # Run
    state.add_pickup_to_state(s, p)
    state.add_pickup_to_state(s, p)

    # Assert
    assert s.resources == ResourceCollection.from_dict(db, {
        resource_a: 1,
        resource_b: 1,
    })
Exemplo n.º 4
0
def test_collected_pickup_indices(state_game_data, empty_patches):
    # Setup
    db = state_game_data.resource_database
    starting = state_game_data.world_list.resolve_teleporter_connection(
        empty_patches.game.starting_location)
    pickup_nodes = [
        node for node in empty_patches.game.world_list.all_nodes
        if isinstance(node, PickupNode)
    ]

    context = NodeContext(
        empty_patches,
        ResourceCollection(),
        empty_patches.game.resource_database,
        empty_patches.game.world_list,
    )
    resources = ResourceCollection.from_dict(
        db, {
            db.item[0]: 5,
            pickup_nodes[0].resource(context): 1,
            pickup_nodes[1].resource(context): 1
        })
    s = state.State(resources, (), 99, starting, empty_patches, None,
                    state_game_data)

    # Run
    indices = list(s.collected_pickup_indices)

    # Assert
    assert indices == [
        pickup_nodes[0].pickup_index, pickup_nodes[1].pickup_index
    ]
Exemplo n.º 5
0
def test_remove_resource_missing(echoes_resource_database):
    m = echoes_resource_database.get_item("Missile")
    beam = echoes_resource_database.get_item("Light")
    col = ResourceCollection.from_dict(echoes_resource_database, {
        beam: 1,
    })
    col.remove_resource(m)

    assert dict(col.as_resource_gain()) == {beam: 1}
Exemplo n.º 6
0
def test_requirement_damage(damage, items, requirement,
                            echoes_resource_database):
    req = data_reader.read_requirement(requirement, echoes_resource_database)

    collection = ResourceCollection.from_dict(
        echoes_resource_database,
        {echoes_resource_database.get_item(item): 1
         for item in items})

    assert req.damage(collection, echoes_resource_database) == damage
Exemplo n.º 7
0
def test_sky_temple_key_distribution_logic_all_bosses_valid(
        echoes_resource_database):
    # Run
    results = sky_temple_keys.add_sky_temple_key_distribution_logic(
        echoes_resource_database, LayoutSkyTempleKeyMode.ALL_BOSSES)

    # Assert
    assert results.pickups == []
    assert results.initial_resources == ResourceCollection.from_dict(
        echoes_resource_database, {})
    assert list(
        results.assignment.keys()
    ) == sky_temple_keys._GUARDIAN_INDICES + sky_temple_keys._SUB_GUARDIAN_INDICES
Exemplo n.º 8
0
def test_sky_temple_key_distribution_logic_all_guardians_valid(
        echoes_resource_database):
    # Run
    results = sky_temple_keys.add_sky_temple_key_distribution_logic(
        echoes_resource_database, LayoutSkyTempleKeyMode.ALL_GUARDIANS)

    # Assert
    assert results.pickups == []
    assert results.initial_resources == ResourceCollection.from_dict(
        echoes_resource_database, {
            echoes_resource_database.get_item(f'TempleKey{i}'): 1
            for i in range(4, 10)
        })
    assert list(results.assignment.keys()) == sky_temple_keys._GUARDIAN_INDICES
Exemplo n.º 9
0
def test_assign_pickup_to_starting_items(empty_patches, state_game_data,
                                         generic_item_category):
    # Setup
    db = state_game_data.resource_database
    starting_node = state_game_data.world_list.resolve_teleporter_connection(
        empty_patches.game.starting_location)
    starting = state.State(ResourceCollection(), (), 99, starting_node,
                           empty_patches, None, state_game_data)

    resource_a = db.get_item("Ammo")
    resource_b = db.item[0]
    p = PickupEntry(
        "A",
        2,
        generic_item_category,
        generic_item_category,
        progression=((resource_a, 5), ),
        extra_resources=(),
        unlocks_resource=True,
        resource_lock=ResourceLock(resource_a, resource_a, resource_b),
    )

    # Run
    final = starting.assign_pickup_to_starting_items(p)

    # Assert
    assert final.patches.starting_items == ResourceCollection.from_dict(
        db, {
            resource_a: 5,
            resource_b: 0
        })
    assert final.resources == ResourceCollection.from_dict(
        db, {
            resource_a: 5,
            resource_b: 0
        })
Exemplo n.º 10
0
def test_sky_temple_key_distribution_logic_with_quantity(
        echoes_resource_database, quantity: int):
    # Run
    results = sky_temple_keys.add_sky_temple_key_distribution_logic(
        echoes_resource_database, LayoutSkyTempleKeyMode(quantity))

    # ItemResourceInfo(f'Sky Temple Key {i}', , 1, frozendict({"item_id": item_ids[i - 1]})): 1
    # Assert
    assert results.pickups == [
        pickup_creator.create_sky_temple_key(i, echoes_resource_database)
        for i in range(quantity)
    ]
    assert results.assignment == {}
    assert results.initial_resources == ResourceCollection.from_dict(
        echoes_resource_database, {
            echoes_resource_database.get_item(f'TempleKey{i}'): 1
            for i in range(quantity + 1, 10)
        })
def test_create_starting_popup_items(default_echoes_configuration,
                                     echoes_resource_database):
    starting_items = ResourceCollection.from_dict(
        echoes_resource_database, {
            echoes_resource_database.get_item_by_name("Missile"): 15,
            echoes_resource_database.energy_tank: 3,
            echoes_resource_database.get_item_by_name("Dark Beam"): 1,
            echoes_resource_database.get_item_by_name("Screw Attack"): 1,
        })

    # Run
    result = patch_data_factory._create_starting_popup(
        default_echoes_configuration, echoes_resource_database, starting_items)

    # Assert
    assert result == [
        'Extra starting items:',
        'Dark Beam, 3 Energy Tank, 15 Missiles, Screw Attack'
    ]
Exemplo n.º 12
0
def test_state_with_pickup(state_game_data, empty_patches,
                           generic_item_category):
    # Setup
    db = state_game_data.resource_database
    starting = state.State(ResourceCollection(), (), 99, None, empty_patches,
                           None, state_game_data)

    resource_a = db.item[0]
    p = PickupEntry("A",
                    2,
                    generic_item_category,
                    generic_item_category,
                    progression=((resource_a, 1), ))

    # Run
    final = state.state_with_pickup(starting, p)

    # Assert
    assert final.previous_state is starting
    assert final.resources == ResourceCollection.from_dict(db, {resource_a: 1})
Exemplo n.º 13
0
 def ctx(*args: ResourceInfo):
     resources = ResourceCollection.from_dict(db, {r: 1 for r in args})
     return NodeContext(empty_patches, resources, db, node_provider)
Exemplo n.º 14
0
def _col_for(db: ResourceDatabase, *args: ResourceInfo):
    return ResourceCollection.from_dict(db, {resource: 1 for resource in args})
Exemplo n.º 15
0
def test_basic_search_with_translator_gate(has_translator: bool,
                                           echoes_resource_database,
                                           echoes_game_patches):
    # Setup
    scan_visor = echoes_resource_database.get_item("DarkVisor")
    nc = functools.partial(NodeIdentifier.create, "Test World", "Test Area A")

    node_a = GenericNode(nc("Node A"), 0, True, None, "", ("default", ), {})
    node_b = GenericNode(nc("Node B"), 1, True, None, "", ("default", ), {})
    node_c = GenericNode(nc("Node C"), 2, True, None, "", ("default", ), {})
    translator_node = ConfigurableNode(
        translator_identif := nc("Translator Gate"), 3, True, None, "",
        ("default", ), {})

    world_list = WorldList([
        World("Test World", [
            Area(
                "Test Area A", None, True,
                [node_a, node_b, node_c, translator_node], {
                    node_a: {
                        node_b: Requirement.trivial(),
                        translator_node: Requirement.trivial(),
                    },
                    node_b: {
                        node_a: Requirement.trivial(),
                    },
                    node_c: {
                        translator_node: Requirement.trivial(),
                    },
                    translator_node: {
                        node_a: Requirement.trivial(),
                        node_c: Requirement.trivial(),
                    },
                }, {})
        ], {})
    ])
    game = GameDescription(RandovaniaGame.METROID_PRIME_ECHOES,
                           DockWeaknessDatabase([], {}, {}, (None, None)),
                           echoes_resource_database, ("default", ),
                           Requirement.impossible(), None, {}, None,
                           world_list)

    patches = echoes_game_patches.assign_node_configuration([
        (translator_identif, ResourceRequirement.simple(scan_visor)),
    ])
    initial_state = State(
        ResourceCollection.from_dict(echoes_resource_database,
                                     {scan_visor: 1 if has_translator else 0}),
        (),
        99,
        node_a,
        patches,
        None,
        StateGameData(echoes_resource_database, game.world_list, 100, 99),
    )

    # Run
    reach = reach_lib.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}
def decode_single(player_index: int, all_pools: dict[int, PoolResults],
                  game: GameDescription, game_modifications: dict,
                  configuration: BaseConfiguration) -> GamePatches:
    """
    Decodes a dict created by `serialize` back into a GamePatches.
    :param player_index:
    :param all_pools:
    :param game:
    :param game_modifications:
    :param configuration:
    :return:
    """
    world_list = game.world_list
    weakness_db = game.dock_weakness_database

    if game_modifications["game"] != game.game.value:
        raise ValueError(
            f"Expected '{game.game.value}', got '{game_modifications['game']}'"
        )

    initial_pickup_assignment = all_pools[player_index].assignment

    # Starting Location
    starting_location = AreaIdentifier.from_string(
        game_modifications["starting_location"])

    # Initial items
    starting_items = ResourceCollection.from_dict(
        game.resource_database, {
            find_resource_info_with_long_name(game.resource_database.item,
                                              resource_name): quantity
            for resource_name, quantity in
            game_modifications["starting_items"].items()
        })

    # Elevators
    elevator_connection = [(world_list.get_teleporter_node(
        NodeIdentifier.from_string(source_name)),
                            AreaIdentifier.from_string(target_name))
                           for source_name, target_name in
                           game_modifications["teleporters"].items()]

    # Dock Weakness
    def get_dock(ni: NodeIdentifier):
        result = game.world_list.node_by_identifier(ni)
        assert isinstance(result, DockNode)
        return result

    dock_weakness = [(get_dock(NodeIdentifier.from_string(source_name)),
                      weakness_db.get_by_weakness(
                          weakness_data["type"],
                          weakness_data["name"],
                      )) for source_name, weakness_data in
                     game_modifications["dock_weakness"].items()]

    # Configurable Nodes
    configurable_nodes = {
        NodeIdentifier.from_string(identifier):
        data_reader.read_requirement(requirement, game.resource_database)
        for identifier, requirement in
        game_modifications["configurable_nodes"].items()
    }

    # Pickups
    target_name_re = re.compile(r"(.*) for Player (\d+)")

    pickup_assignment: PickupAssignment = {}
    for world_name, world_data in game_modifications["locations"].items():
        for area_node_name, target_name in typing.cast(dict[str, str],
                                                       world_data).items():
            if target_name == _ETM_NAME:
                continue

            pickup_name_match = target_name_re.match(target_name)
            if pickup_name_match is not None:
                pickup_name = pickup_name_match.group(1)
                target_player = int(pickup_name_match.group(2)) - 1
            else:
                pickup_name = target_name
                target_player = 0

            node_identifier = NodeIdentifier.create(
                world_name, *area_node_name.split("/", 1))
            node = world_list.node_by_identifier(node_identifier)
            assert isinstance(node, PickupNode)
            if node.pickup_index in initial_pickup_assignment:
                pickup = initial_pickup_assignment[node.pickup_index]
                if (pickup_name, target_player) != (pickup.name, player_index):
                    raise ValueError(
                        f"{area_node_name} should be vanilla based on configuration"
                    )

            elif pickup_name != _ETM_NAME:
                configuration_item_pool = all_pools[target_player].pickups
                pickup = _find_pickup_with_name(configuration_item_pool,
                                                pickup_name)
                configuration_item_pool.remove(pickup)
            else:
                pickup = None

            if pickup is not None:
                pickup_assignment[node.pickup_index] = PickupTarget(
                    pickup, target_player)

    # Hints
    hints = {}
    for identifier_str, hint in game_modifications["hints"].items():
        hints[NodeIdentifier.from_string(identifier_str)] = Hint.from_json(
            hint)

    patches = GamePatches.create_from_game(game, player_index, configuration)
    patches = patches.assign_dock_weakness(dock_weakness)
    patches = patches.assign_elevators(elevator_connection)
    return dataclasses.replace(
        patches,
        pickup_assignment=pickup_assignment,  # PickupAssignment
        configurable_nodes=configurable_nodes,
        starting_items=starting_items,  # ResourceGainTuple
        starting_location=starting_location,  # AreaIdentifier
        hints=hints,
    )