Ejemplo n.º 1
0
def test_create_message_for_hint_relative_area(echoes_game_description,
                                               blank_pickup, players_config,
                                               offset, distance_text):
    hint_name_creator = LocationHintCreator(echoes_game_description.world_list,
                                            None, None)
    world_list = echoes_game_description.world_list
    patches = echoes_game_description.create_game_patches(
    ).assign_pickup_assignment({
        PickupIndex(5): PickupTarget(blank_pickup, 0),
    })

    hint_name_creator = LocationHintCreator(world_list, None, None)
    location_formatters = {
        HintLocationPrecision.RELATIVE_TO_AREA:
        RelativeAreaFormatter(world_list, patches)
    }
    hint = Hint(
        HintType.LOCATION,
        PrecisionPair(HintLocationPrecision.RELATIVE_TO_AREA,
                      HintItemPrecision.DETAILED,
                      include_owner=False,
                      relative=RelativeDataArea(
                          offset, AreaLocation(1039999561, 3822429534),
                          HintRelativeAreaName.NAME)), PickupIndex(5))

    # Run
    result = hint_name_creator.create_message_for_hint(hint, {0: patches},
                                                       players_config,
                                                       location_formatters)

    # Assert
    assert result == (
        f'The &push;&main-color=#FF6705B3;Blank Pickup&pop; can be found '
        f'&push;&main-color=#FF3333;{distance_text} {10 + (offset or 0)} rooms&pop; away from '
        f'Torvus Bog - Great Bridge.')
Ejemplo n.º 2
0
def test_create_hints_item_dark_temple_keys(empty_patches, players_config,
                                            echoes_game_description,
                                            blank_pickup, indices,
                                            expected_message):
    # Setup
    hint_name_creator = LocationHintCreator(echoes_game_description.world_list,
                                            None, None)
    db = echoes_game_description.resource_database
    keys = [
        (PickupIndex(index),
         dataclasses.replace(blank_pickup,
                             progression=((db.get_item(item), 1), )))
        for index, item in zip(indices, echoes_items.DARK_TEMPLE_KEY_ITEMS[1])
    ]

    patches = dataclasses.replace(empty_patches,
                                  pickup_assignment={
                                      pickup_index: PickupTarget(key, 0)
                                      for pickup_index, key in keys
                                  })

    hint = Hint(HintType.RED_TEMPLE_KEY_SET,
                None,
                dark_temple=HintDarkTemple.TORVUS_BOG)

    # Run
    result = hint_name_creator.create_message_for_hint(hint, {0: patches},
                                                       players_config, {})

    # Assert
    assert result == expected_message
Ejemplo n.º 3
0
def create_hints(
    all_patches: Dict[int, GamePatches],
    players_config: PlayersConfiguration,
    world_list: WorldList,
    rng: Random,
) -> list:
    """
    Creates the string patches entries that changes the Lore scans in the game for item pickups
    :param all_patches:
    :param players_config:
    :param world_list:
    :param rng:
    :return:
    """

    hint_name_creator = LocationHintCreator(world_list, rng, _JOKE_HINTS)
    patches = all_patches[players_config.player_index]

    location_formatters: Dict[HintLocationPrecision, LocationFormatter] = {
        HintLocationPrecision.KEYBEARER:
        TemplatedFormatter(
            "The Flying Ing Cache in {node} contains {determiner}{pickup}.",
            hint_name_creator),
        HintLocationPrecision.GUARDIAN:
        GuardianFormatter(),
        HintLocationPrecision.LIGHT_SUIT_LOCATION:
        TemplatedFormatter(
            "U-Mos's reward for returning the Sanctuary energy is {determiner}{pickup}.",
            hint_name_creator),
        HintLocationPrecision.DETAILED:
        TemplatedFormatter(
            "{determiner.title}{pickup} can be found in {node}.",
            hint_name_creator),
        HintLocationPrecision.WORLD_ONLY:
        TemplatedFormatter(
            "{determiner.title}{pickup} can be found in {node}.",
            hint_name_creator),
        HintLocationPrecision.RELATIVE_TO_AREA:
        RelativeAreaFormatter(world_list, patches),
        HintLocationPrecision.RELATIVE_TO_INDEX:
        RelativeItemFormatter(world_list, patches, players_config),
    }

    hints_for_asset: Dict[int, str] = {}
    for asset, hint in patches.hints.items():
        hints_for_asset[
            asset.asset_id] = hint_name_creator.create_message_for_hint(
                hint, all_patches, players_config, location_formatters)

    return [
        create_simple_logbook_hint(
            logbook_node.string_asset_id,
            hints_for_asset.get(logbook_node.string_asset_id,
                                "Someone forgot to leave a message."),
        ) for logbook_node in world_list.all_nodes
        if isinstance(logbook_node, LogbookNode)
    ]
Ejemplo n.º 4
0
def create_message_for_hint(
    hint: Hint,
    all_patches: Dict[int, GamePatches],
    players_config: PlayersConfiguration,
    hint_name_creator: LocationHintCreator,
    location_formatters: Dict[HintLocationPrecision, LocationFormatter],
    world_list: WorldList,
) -> str:
    if hint.hint_type == HintType.JOKE:
        return color_text(TextColor.JOKE, hint_name_creator.create_joke_hint())

    elif hint.hint_type == HintType.RED_TEMPLE_KEY_SET:
        return create_temple_key_hint(all_patches, players_config.player_index,
                                      hint.dark_temple, world_list)

    else:
        assert hint.hint_type == HintType.LOCATION
        patches = all_patches[players_config.player_index]
        determiner, pickup_name = _calculate_pickup_hint(
            patches.pickup_assignment, world_list, hint.precision.item,
            patches.pickup_assignment.get(hint.target))
        return location_formatters[hint.precision.location].format(
            Determiner(determiner),
            color_text(TextColor.ITEM, pickup_name),
            hint,
        )
Ejemplo n.º 5
0
def create_message_for_hint(
    hint: Hint,
    all_patches: Dict[int, GamePatches],
    players_config: PlayersConfiguration,
    hint_name_creator: LocationHintCreator,
    location_formatters: Dict[HintLocationPrecision, LocationFormatter],
    world_list: WorldList,
) -> str:
    if hint.hint_type == HintType.JOKE:
        return color_text(TextColor.JOKE, hint_name_creator.create_joke_hint())

    elif hint.hint_type == HintType.RED_TEMPLE_KEY_SET:
        return create_temple_key_hint(all_patches, players_config.player_index,
                                      hint.dark_temple, world_list)

    else:
        assert hint.hint_type == HintType.LOCATION
        patches = all_patches[players_config.player_index]
        pickup_target = patches.pickup_assignment.get(hint.target)
        determiner, pickup_name = _calculate_pickup_hint(
            patches.pickup_assignment, world_list, hint.precision.item,
            pickup_target, players_config)

        use_title_formatting = True
        if hint.precision.include_owner and len(
                players_config.player_names) > 1:
            target_player = pickup_target.player if pickup_target is not None else players_config.player_index
            determiner = f"{players_config.player_names[target_player]}'s "
            use_title_formatting = False

        return location_formatters[hint.precision.location].format(
            Determiner(determiner, use_title_formatting),
            color_text(TextColor.ITEM, pickup_name),
            hint,
        )
Ejemplo n.º 6
0
def test_create_message_for_hint_dark_temple_no_keys(empty_patches,
                                                     players_config,
                                                     echoes_game_description):
    # Setup
    hint_name_creator = LocationHintCreator(echoes_game_description.world_list,
                                            None, None)
    hint = Hint(HintType.RED_TEMPLE_KEY_SET,
                None,
                dark_temple=HintDarkTemple.TORVUS_BOG)

    # Run
    result = hint_name_creator.create_message_for_hint(hint,
                                                       {0: empty_patches},
                                                       players_config, {})

    # Assert
    assert result == 'The keys to &push;&main-color=#FF6705B3;Dark Torvus Temple&pop; are nowhere to be found.'
Ejemplo n.º 7
0
def test_create_message_for_hint_relative_item(echoes_game_description,
                                               blank_pickup, players_config,
                                               distance_precise, distance_text,
                                               reference_precision,
                                               reference_name):
    world_list = echoes_game_description.world_list
    patches = echoes_game_description.create_game_patches(
    ).assign_pickup_assignment({
        PickupIndex(5):
        PickupTarget(blank_pickup, 0),
        PickupIndex(15):
        PickupTarget(
            dataclasses.replace(blank_pickup, name="Reference Pickup"), 0),
    })

    hint_name_creator = LocationHintCreator(world_list, None, None)
    location_formatters = {
        HintLocationPrecision.RELATIVE_TO_INDEX:
        RelativeItemFormatter(world_list, patches, players_config),
    }
    hint = Hint(
        HintType.LOCATION,
        PrecisionPair(HintLocationPrecision.RELATIVE_TO_INDEX,
                      HintItemPrecision.DETAILED,
                      include_owner=False,
                      relative=RelativeDataItem(distance_precise,
                                                PickupIndex(15),
                                                reference_precision)),
        PickupIndex(5))

    # Run
    result = hint_name_creator.create_message_for_hint(hint, {0: patches},
                                                       players_config,
                                                       location_formatters)

    # Assert
    assert result == (
        f'The &push;&main-color=#FF6705B3;Blank Pickup&pop; can be found '
        f'&push;&main-color=#FF3333;{distance_text} {7 + (distance_precise or 0)} '
        f'rooms&pop; away from {reference_name}.')
Ejemplo n.º 8
0
def create_hints(
    patches: GamePatches,
    world_list: WorldList,
    hide_area: bool,
) -> list:
    """
    Creates the string patches entries that changes the Sky Temple Gateway hint scans with hints for where
    the STK actually are.
    :param patches:
    :param world_list:
    :param hide_area: Should the hint include only the world?
    :return:
    """
    location_hint_creator = LocationHintCreator(world_list)
    sky_temple_key_hints = {}

    for pickup_index, pickup in patches.pickup_assignment.items():
        resources = resource_info.convert_resource_gain_to_current_resources(
            pickup.resource_gain({}))

        for resource, quantity in resources.items():
            if quantity < 1:
                continue

            try:
                key_number = echoes_items.SKY_TEMPLE_KEY_ITEMS.index(
                    resource.index) + 1
            except ValueError:
                continue

            assert resource.index not in sky_temple_key_hints

            sky_temple_key_hints[
                resource.index] = "{} is located in {}.".format(
                    _sky_temple_key_name(key_number),
                    color_text(
                        TextColor.LOCATION,
                        location_hint_creator.index_node_name(
                            pickup_index, hide_area),
                    ),
                )

    for starting_resource, quantity in patches.starting_items.items():
        if quantity < 1:
            continue
        try:
            key_number = echoes_items.SKY_TEMPLE_KEY_ITEMS.index(
                starting_resource.index) + 1
        except ValueError:
            continue

        assert starting_resource.index not in sky_temple_key_hints
        sky_temple_key_hints[
            starting_resource.index] = "{} has no need to be located.".format(
                _sky_temple_key_name(key_number), )

    if len(sky_temple_key_hints) != len(echoes_items.SKY_TEMPLE_KEY_ITEMS):
        raise ValueError(
            "Expected to find {} Sky Temple Keys between pickup placement and starting items, found {}"
            .format(len(echoes_items.SKY_TEMPLE_KEY_ITEMS),
                    len(sky_temple_key_hints)))

    return [
        create_simple_logbook_hint(_SKY_TEMPLE_KEY_SCAN_ASSETS[key_number],
                                   sky_temple_key_hints[key_index]) for
        key_number, key_index in enumerate(echoes_items.SKY_TEMPLE_KEY_ITEMS)
    ]
Ejemplo n.º 9
0
def create_hints(patches: GamePatches,
                 world_list: WorldList,
                 rng: Random,
                 ) -> list:
    """
    Creates the string patches entries that changes the Lore scans in the game for item pickups
    :param patches:
    :param world_list:
    :param rng:
    :return:
    """

    hint_name_creator = LocationHintCreator(world_list)
    joke_items = sorted(set(_PRIME_1_ITEMS) | set(_PRIME_3_ITEMS))
    joke_locations = sorted(set(_PRIME_1_LOCATIONS) | set(_PRIME_3_LOCATIONS))
    joke_hints = sorted(_JOKE_HINTS)

    rng.shuffle(joke_items)
    rng.shuffle(joke_locations)
    rng.shuffle(joke_hints)

    hints_for_asset: Dict[int, str] = {}

    for asset, hint in patches.hints.items():
        if hint.precision.is_joke:
            if not joke_hints:
                joke_hints = sorted(_JOKE_HINTS)
                rng.shuffle(joke_hints)
            message = color_text(TextColor.JOKE, joke_hints.pop())

        else:
            target = patches.pickup_assignment.get(hint.target)

            # Determine location name
            if hint.hint_type is HintType.GUARDIAN:
                node_name = color_text(TextColor.GUARDIAN, _GUARDIAN_NAMES[hint.target])
            elif hint.location_precision == HintLocationPrecision.WRONG_GAME:
                node_name = color_text(TextColor.JOKE, "{} (?)".format(joke_locations.pop())
                                       if joke_locations else "an unknown location")
            else:
                node_name = color_text(TextColor.LOCATION, hint_name_creator.index_node_name(
                    hint.target,
                    hint.location_precision != HintLocationPrecision.DETAILED
                ))

            # Determine pickup name
            if target is not None:
                is_joke, determiner, pickup_name = _calculate_pickup_hint(
                    hint.item_precision,
                    _calculate_determiner(patches.pickup_assignment, target.pickup),
                    target.pickup,
                    joke_items,
                )
            else:
                is_joke = False
                determiner = "the " if len(patches.pickup_assignment) == 118 else "an "
                pickup_name = "Energy Transfer Module"

            if hint.hint_type is HintType.LOCATION:
                determiner = determiner.title()

            pickup_name = color_text(TextColor.JOKE if is_joke else TextColor.ITEM, pickup_name)
            message = _HINT_MESSAGE_TEMPLATES[hint.hint_type].format(determiner=determiner,
                                                                     pickup=pickup_name,
                                                                     node=node_name)
        hints_for_asset[asset.asset_id] = message

    return [
        create_simple_logbook_hint(
            logbook_node.string_asset_id,
            hints_for_asset.get(logbook_node.string_asset_id, "Someone forgot to leave a message."),
        )
        for logbook_node in world_list.all_nodes
        if isinstance(logbook_node, LogbookNode)
    ]
Ejemplo n.º 10
0
def test_create_hints_all_placed(hide_area: bool, multiworld: bool,
                                 empty_patches, echoes_game_description):
    # Setup
    hint_creator = LocationHintCreator(echoes_game_description.world_list,
                                       None, None)
    players_config = PlayersConfiguration(0, {
        0: "you",
        1: "them"
    } if multiworld else {0: "you"})
    patches = empty_patches.assign_new_pickups([
        (PickupIndex(17 + key),
         PickupTarget(
             pickup_creator.create_sky_temple_key(
                 key, echoes_game_description.resource_database), 0))
        for key in range(5 if multiworld else 9)
    ])
    other_patches = empty_patches.assign_new_pickups([
        (PickupIndex(17 + key),
         PickupTarget(
             pickup_creator.create_sky_temple_key(
                 key, echoes_game_description.resource_database), 0))
        for key in range(5, 9)
    ])
    expected = [
        {
            "asset_id":
            0xD97685FE,
            "strings":
            _create_hint_text(hide_area, multiworld, 1,
                              "Sky Temple Grounds - Profane Path")
        },
        {
            "asset_id":
            0x32413EFD,
            "strings":
            _create_hint_text(hide_area, multiworld, 2,
                              "Sky Temple Grounds - Phazon Grounds")
        },
        {
            "asset_id":
            0xDD8355C3,
            "strings":
            _create_hint_text(hide_area, multiworld, 3,
                              "Sky Temple Grounds - Ing Reliquary")
        },
        {
            "asset_id":
            0x3F5F4EBA,
            "strings":
            _create_hint_text(hide_area, multiworld, 4,
                              "Great Temple - Transport A Access")
        },
        {
            "asset_id":
            0xD09D2584,
            "strings":
            _create_hint_text(hide_area, multiworld, 5,
                              "Great Temple - Temple Sanctuary")
        },
        {
            "asset_id":
            0x3BAA9E87,
            "strings":
            _create_hint_text(hide_area, multiworld, 6,
                              "Great Temple - Transport B Access")
        },
        {
            "asset_id":
            0xD468F5B9,
            "strings":
            _create_hint_text(hide_area, multiworld, 7,
                              "Great Temple - Main Energy Controller")
        },
        {
            "asset_id":
            0x2563AE34,
            "strings":
            _create_hint_text(hide_area, multiworld, 8,
                              "Great Temple - Main Energy Controller")
        },
        {
            "asset_id":
            0xCAA1C50A,
            "strings":
            _create_hint_text(hide_area, multiworld, 9,
                              "Agon Wastes - Mining Plaza")
        },
    ]

    # Run
    result = sky_temple_key_hint.create_hints(
        {
            0: patches,
            1: other_patches
        } if multiworld else {0: patches}, players_config,
        echoes_game_description.resource_database, {
            0: hint_creator,
            1: hint_creator
        } if multiworld else {0: hint_creator}, hide_area)

    # Assert
    assert result == expected