Example #1
0
def test_create_hints_item_joke(empty_patches, players_config):
    # Setup
    asset_id = 1000
    logbook_node, _, world_list = _create_world_list(asset_id, PickupIndex(50))

    patches = dataclasses.replace(
        empty_patches,
        hints={
            world_list.identifier_for_node(logbook_node):
            Hint(HintType.JOKE, None)
        })
    rng = MagicMock()
    namer = EchoesHintNamer({0: patches}, players_config)

    # Run
    result = hints.create_patches_hints({0: patches}, players_config,
                                        world_list, namer, rng)

    # Assert
    joke = "While walking, holding L makes you move faster."
    message = f"&push;&main-color=#45F731;{joke}&pop;"
    assert result[0]['strings'][0] == message
    assert result == [{
        'asset_id': asset_id,
        'strings': [message, '', message]
    }]
Example #2
0
async def test_show_dialog_for_prime3_layout(skip_qtbot, mocker, corruption_game_description, empty_patches):
    mock_execute_dialog = mocker.patch("randovania.gui.lib.async_dialog.execute_dialog", new_callable=AsyncMock)
    mock_clipboard: MagicMock = mocker.patch("randovania.gui.lib.common_qt_lib.set_clipboard")

    options = MagicMock()
    options.options_for_game.return_value.cosmetic_patches = CorruptionCosmeticPatches()
    window = GameDetailsWindow(None, options)
    window.player_index_combo.addItem("Current", 0)
    skip_qtbot.addWidget(window)

    target = MagicMock()
    target.pickup.name = "Boost Ball"

    patches = dataclasses.replace(empty_patches, starting_location=corruption_game_description.starting_location)
    for i in range(100):
        patches.pickup_assignment[PickupIndex(i)] = target

    window.layout_description = MagicMock()
    window.layout_description.all_patches = {0: patches}

    # Run
    await window._show_dialog_for_prime3_layout()

    # Assert
    mock_execute_dialog.assert_awaited_once()
    mock_clipboard.assert_called_once()
Example #3
0
def test_create_hints_nothing(empty_patches, players_config):
    # Setup
    asset_id = 1000
    pickup_index = PickupIndex(0)

    logbook_node, _, world_list = _create_world_list(asset_id, pickup_index)

    patches = dataclasses.replace(empty_patches,
                                  hints={
                                      logbook_node.resource():
                                      Hint(
                                          HintType.LOCATION,
                                          PrecisionPair(
                                              HintLocationPrecision.DETAILED,
                                              HintItemPrecision.DETAILED),
                                          pickup_index)
                                  })
    rng = MagicMock()

    # Run
    result = item_hints.create_hints({0: patches}, players_config, world_list,
                                     rng)

    # Assert
    message = (
        "The &push;&main-color=#FF6705B3;Energy Transfer Module&pop; can be found in "
        "&push;&main-color=#FF3333;World - Area&pop;.")
    assert result == [{
        'asset_id': asset_id,
        'strings': [message, '', message]
    }]
Example #4
0
def test_create_hints_item_location(empty_patches, players_config, pickup,
                                    item, location):
    # Setup
    asset_id = 1000
    pickup_index = PickupIndex(50)
    logbook_node, _, world_list = _create_world_list(asset_id, pickup_index)

    patches = dataclasses.replace(empty_patches,
                                  pickup_assignment={
                                      pickup_index: PickupTarget(pickup, 0),
                                  },
                                  hints={
                                      logbook_node.resource():
                                      Hint(HintType.LOCATION,
                                           PrecisionPair(location[0], item[0]),
                                           pickup_index)
                                  })
    rng = MagicMock()

    # Run
    result = item_hints.create_hints({0: patches}, players_config, world_list,
                                     rng)

    # Assert
    message = "{} can be found in {}.".format(item[1][0].upper() + item[1][1:],
                                              location[1])
    # message = "The Flying Ing Cache in {} contains {}.".format(location[1], item[1])
    assert result == [{
        'asset_id': asset_id,
        'strings': [message, '', message]
    }]
Example #5
0
def test_create_hints_light_suit_location(empty_patches, players_config,
                                          pickup, item):
    # Setup
    asset_id = 1000
    pickup_index = PickupIndex(50)

    logbook_node, _, world_list = _create_world_list(asset_id, pickup_index)

    patches = dataclasses.replace(
        empty_patches,
        pickup_assignment={
            pickup_index: PickupTarget(pickup, 0),
        },
        hints={
            logbook_node.resource():
            Hint(
                HintType.LOCATION,
                PrecisionPair(HintLocationPrecision.LIGHT_SUIT_LOCATION,
                              item[0]), pickup_index)
        })
    rng = MagicMock()

    # Run
    result = item_hints.create_hints({0: patches}, players_config, world_list,
                                     rng)

    # Assert
    message = f"U-Mos's reward for returning the Sanctuary energy is {item[1]}."
    assert result == [{
        'asset_id': asset_id,
        'strings': [message, '', message]
    }]
 def g(index, loc):
     return (
         PickupIndex(index),
         PrecisionPair(loc,
                       HintItemPrecision.DETAILED,
                       include_owner=False),
     )
Example #7
0
def test_create_hints_item_dark_temple_keys(empty_patches, players_config,
                                            echoes_game_description, pickup,
                                            indices, expected_message):
    # Setup
    db = echoes_game_description.resource_database
    keys = [
        (PickupIndex(index),
         dataclasses.replace(pickup,
                             resources=(ConditionalResources(
                                 None, None, ((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 = item_hints.create_message_for_hint(
        hint, {0: patches}, players_config, None, {},
        echoes_game_description.world_list)

    # Assert
    assert result == expected_message
Example #8
0
    async def known_collected_locations(
        self,
        executor: MemoryOperationExecutor,
    ) -> Tuple[Set[PickupIndex], List[DolRemotePatch]]:
        """Fetches pickup indices that have been collected.
        The list may return less than all collected locations, depending on implementation details.
        This function also returns a list of remote patches that must be performed via `execute_remote_patches`.
        """
        multiworld_magic_item = self.game.resource_database.multiworld_magic_item
        if multiworld_magic_item is None:
            return set(), []

        memory_ops = await self._memory_op_for_items(executor,
                                                     [multiworld_magic_item])
        op_result = await executor.perform_single_memory_operation(*memory_ops)

        magic_inv = InventoryItem(*struct.unpack(">II", op_result))
        if magic_inv.amount > 0:
            self.logger.info(
                f"magic item was at {magic_inv.amount}/{magic_inv.capacity}")
            locations = {PickupIndex(magic_inv.amount - 1)}
            patches = [
                DolRemotePatch([],
                               all_prime_dol_patches.
                               adjust_item_amount_and_capacity_patch(
                                   self.version.powerup_functions,
                                   self.game.game,
                                   multiworld_magic_item.extra["item_id"],
                                   -magic_inv.amount,
                               ))
            ]
            return locations, patches
        else:
            return set(), []
Example #9
0
def test_run_validated_hud_text():
    # Setup
    rng = MagicMock()
    rng.randint.return_value = 0
    details = pickup_exporter.ExportedPickupDetails(
        index=PickupIndex(0),
        scan_text="scan",
        hud_text=["Energy Transfer Module acquired!"],
        conditional_resources=[
            ConditionalResources(None, None, ()),
        ],
        conversion=[],
        model=PickupModel(
            game=RandovaniaGame.METROID_PRIME_ECHOES,
            name="EnergyTransferModule",
        ),
        other_player=False,
        original_pickup=None,
    )

    # Run
    data = patch_data_factory.echoes_pickup_details_to_patcher(details, rng)

    # Assert
    assert data['hud_text'] == ['Run validated!']
async def test_show_dialog_for_prime3_layout(skip_qtbot, mocker,
                                             corruption_game_description):
    mock_execute_dialog = mocker.patch(
        "randovania.gui.lib.async_dialog.execute_dialog",
        new_callable=AsyncMock)
    mock_clipboard: MagicMock = mocker.patch(
        "PySide2.QtWidgets.QApplication.clipboard")

    window = SeedDetailsWindow(None, MagicMock())
    window.player_index_combo.addItem("Current", 0)
    skip_qtbot.addWidget(window)

    collections.namedtuple("MockPickup", ["name"])
    target = MagicMock()
    target.pickup.name = "Boost Ball"

    patches = corruption_game_description.create_game_patches()
    for i in range(100):
        patches.pickup_assignment[PickupIndex(i)] = target

    window.layout_description = MagicMock()
    window.layout_description.all_patches = {0: patches}

    # Run
    await window._show_dialog_for_prime3_layout()

    # Assert
    mock_execute_dialog.assert_awaited_once()
    mock_clipboard.return_value.setText.assert_called_once()
Example #11
0
def test_pickup_data_for_pb_expansion_unlocked(echoes_item_database, echoes_resource_database):
    # Setup
    pickup = pickup_creator.create_ammo_expansion(
        echoes_item_database.ammo["Power Bomb Expansion"],
        [2],
        False,
        echoes_resource_database,
    )
    creator = pickup_exporter.PickupExporterSolo(patch_data_factory._simplified_memo_data())

    # Run
    details = creator.export(PickupIndex(0), PickupTarget(pickup, 0), pickup, PickupModelStyle.ALL_VISIBLE)
    result = patch_data_factory.echoes_pickup_details_to_patcher(details, MagicMock())

    # Assert
    assert result == {
        "pickup_index": 0,
        "scan": "Power Bomb Expansion. Provides 2 Power Bombs and 1 Item Percentage",
        "model": {"game": "prime2", "name": "PowerBombExpansion"},
        "hud_text": ["Power Bomb Expansion acquired!"],
        'resources': [{'amount': 2, 'index': 43},
                      {'amount': 1, 'index': 47}],
        "conditional_resources": [],
        "convert": [],
    }
Example #12
0
 def from_json(cls, value: dict,
               game: RandovaniaGame) -> "AvailableLocationsConfiguration":
     return cls(
         randomization_mode=RandomizationMode(value["randomization_mode"]),
         excluded_indices=frozenset(
             PickupIndex(item) for item in value["excluded_indices"]),
         game=game,
     )
Example #13
0
 def from_json(cls, data) -> "GameSessionAction":
     return GameSessionAction(
         provider=data["provider"],
         provider_row=data["provider_row"],
         receiver=data["receiver"],
         pickup=data["pickup"],
         location=PickupIndex(data["location"]),
         time=datetime.datetime.fromisoformat(data["time"]),
     )
Example #14
0
 def from_json(cls, value) -> "Hint":
     return Hint(
         hint_type=HintType(value["hint_type"]),
         precision=PrecisionPair(
             location=HintLocationPrecision(value["location_precision"]),
             item=HintItemPrecision(value["item_precision"]),
         ),
         target=PickupIndex(value["target"]),
     )
Example #15
0
def test_add_relative_hint(echoes_game_description, empty_patches,
                           location_precision):
    # Setup
    rng = Random(5000)
    target_precision = MagicMock()
    precise_distance = MagicMock()
    precision = MagicMock()
    patches = empty_patches.assign_pickup_assignment({
        PickupIndex(8):
        PickupTarget(_make_pickup(ItemCategory.MOVEMENT), 0),
    })

    if location_precision == HintLocationPrecision.RELATIVE_TO_AREA:
        max_distance = 8
        data = RelativeDataArea(
            precise_distance,
            AreaLocation(0x3BFA3EFF, 0x62AC8AC4),
            precision,
        )
    else:
        max_distance = 20
        data = RelativeDataItem(
            precise_distance,
            PickupIndex(8),
            precision,
        )

    # Run
    result = runner.add_relative_hint(echoes_game_description.world_list,
                                      patches,
                                      rng,
                                      PickupIndex(1),
                                      target_precision,
                                      location_precision,
                                      precise_distance,
                                      precision,
                                      max_distance=max_distance)

    # Assert
    pair = PrecisionPair(location_precision,
                         target_precision,
                         include_owner=False,
                         relative=data)
    assert result == Hint(HintType.LOCATION, pair, PickupIndex(1))
    async def _show_dialog_for_prime3_layout(self):
        from randovania.games.prime3.patcher import gollop_corruption_patcher
        from randovania.games.prime3.layout.corruption_cosmetic_patches import CorruptionCosmeticPatches
        from randovania.games.prime3.layout.corruption_configuration import CorruptionConfiguration
        from randovania.game_description import default_database

        cosmetic = typing.cast(
            CorruptionCosmeticPatches,
            self._options.options_for_game(RandovaniaGame.METROID_PRIME_CORRUPTION).cosmetic_patches,
        )
        configuration = typing.cast(
            CorruptionConfiguration,
            self.layout_description.get_preset(self.current_player_index).configuration,
        )
        patches = self.layout_description.all_patches[self.current_player_index]
        game = default_database.game_description_for(RandovaniaGame.METROID_PRIME_CORRUPTION)

        pickup_names = []
        for index in range(game.world_list.num_pickup_nodes):
            p_index = PickupIndex(index)
            if p_index in patches.pickup_assignment:
                name = patches.pickup_assignment[p_index].pickup.name
            else:
                name = "Missile Expansion"
            pickup_names.append(name)

        layout_string = gollop_corruption_patcher.layout_string_for_items(pickup_names)
        starting_location = patches.starting_location

        starting_items = patches.starting_items.duplicate()
        starting_items.add_resource_gain([
            (game.resource_database.get_item_by_name("Suit Type"), cosmetic.player_suit.value),
        ])
        if configuration.start_with_corrupted_hypermode:
            hypermode_original = 0
        else:
            hypermode_original = 1

        commands = "\n".join([
            f'set seed="{layout_string}"',
            f'set "starting_items={gollop_corruption_patcher.starting_items_for(starting_items, hypermode_original)}"',
            f'set "starting_location={gollop_corruption_patcher.starting_location_for(game, starting_location)}"',
            f'set "random_door_colors={str(cosmetic.random_door_colors).lower()}"',
            f'set "random_welding_colors={str(cosmetic.random_welding_colors).lower()}"',
        ])
        dialog_text = (
            "There is no integrated patcher for Metroid Prime 3: Corruption games.\n"
            "Download the randomizer for it from #corruption-general in the Metroid Prime Randomizer Discord, "
            "and use the following commands as a seed.\n\n"
            "\n{}").format(commands)

        message_box = ScrollLabelDialog(dialog_text, "Commands for patcher", self)
        message_box.resize(750, 200)
        message_box.label.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)
        common_qt_lib.set_clipboard(commands)
        await async_dialog.execute_dialog(message_box)
Example #17
0
def test_filter_usable_locations(state_for_blank, must_be_local,
                                 num_assigned_pickups):
    state_for_blank.configuration = dataclasses.replace(
        state_for_blank.configuration,
        first_progression_must_be_local=must_be_local)
    state_for_blank.num_assigned_pickups = num_assigned_pickups

    locations_weighted = {
        (state_for_blank, PickupIndex(0)): 1,
        (MagicMock(), PickupIndex(0)): 1,
    }

    # Run
    filtered = state_for_blank.filter_usable_locations(locations_weighted)

    # Assert
    if must_be_local and num_assigned_pickups == 0:
        assert filtered == {(state_for_blank, PickupIndex(0)): 1}
    else:
        assert filtered == locations_weighted
Example #18
0
async def test_run_filler(
    echoes_game_description,
    default_layout_configuration,
    mocker,
):
    # Setup
    rng = Random(5000)
    status_update = MagicMock()

    logbook_nodes = [
        node for node in echoes_game_description.world_list.all_nodes
        if isinstance(node, LogbookNode)
    ]

    player_pools = {
        0: create_player_pool(rng, default_layout_configuration, 0, 1),
    }
    initial_pickup_count = len(player_pools[0].pickups)

    patches = echoes_game_description.create_game_patches()
    patches = patches.assign_hint(
        logbook_nodes[0].resource(),
        Hint(HintType.LOCATION, None, PickupIndex(0)))
    action_log = (MagicMock(), MagicMock())
    player_state = MagicMock()
    player_state.index = 0
    player_state.game = player_pools[0].game
    player_state.pickups_left = runner._split_expansions(
        player_pools[0].pickups)[0]
    player_state.scan_asset_initial_pickups = {}

    mocker.patch(
        "randovania.generator.filler.runner.retcon_playthrough_filler",
        autospec=True,
        return_value=({
            player_state: patches
        }, action_log))

    # Run
    filler_result = await runner.run_filler(rng, player_pools, status_update)

    assert filler_result.action_log == action_log
    assert len(filler_result.player_results) == 1
    result_patches = filler_result.player_results[0].patches
    remaining_items = filler_result.player_results[0].unassigned_pickups

    # Assert
    assert len(result_patches.hints) == len(logbook_nodes)
    assert [
        hint for hint in result_patches.hints.values()
        if hint.precision is None
    ] == []
    assert initial_pickup_count == len(remaining_items) + len(
        result_patches.pickup_assignment.values())
Example #19
0
def _pickup_node():
    return PickupNode(
        pickup_index=PickupIndex(1),
        major_location=True,
        identifier=NodeIdentifier.create("W", "A", "Pickup (Ultra Beam)"),
        heal=False,
        location=None,
        layers=("default", ),
        description="",
        extra={},
    )
def test_create_message_for_hint_relative_item(echoes_game_description, 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(pickup, 0),
        PickupIndex(15):
        PickupTarget(dataclasses.replace(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 = item_hints.create_message_for_hint(hint, {0: patches},
                                                players_config,
                                                hint_name_creator,
                                                location_formatters,
                                                world_list)

    # Assert
    assert result == (
        f'The &push;&main-color=#FF6705B3;Pickup&pop; can be found '
        f'&push;&main-color=#FF3333;{distance_text} {7 + distance_precise} rooms&pop; away from {reference_name}.'
    )
Example #21
0
    def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata) -> "BitPackPickupEntryList":
        result = []
        index_mapping = metadata["index_mapping"]
        num_players = metadata["num_players"]

        for _ in range(len(index_mapping)):
            index = PickupIndex(decoder.decode_single(255))
            target_player = bitpacking.decode_int_with_limits(decoder, (num_players,))
            pickup = BitPackPickupEntry.bit_pack_unpack(decoder, index_mapping[index], metadata["database"])
            result.append((index, PickupTarget(pickup, target_player)))

        return BitPackPickupEntryList(result, num_players, metadata["database"])
Example #22
0
    def bit_pack_unpack(cls, decoder: BitPackDecoder,
                        metadata) -> "BitPackPickupEntryList":
        result = []
        index_mapping = metadata["index_mapping"]

        for _ in range(len(index_mapping)):
            index = PickupIndex(decoder.decode_single(255))
            pickup = BitPackPickupEntry.bit_pack_unpack(
                decoder, index_mapping[index], metadata["database"])
            result.append((index, pickup))

        return BitPackPickupEntryList(result, metadata["database"])
Example #23
0
    def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata):
        randomization_mode = RandomizationMode.bit_pack_unpack(decoder, metadata)

        if bitpacking.decode_bool(decoder):
            indices = bitpacking.decode_sorted_array_elements(decoder, _ALL_INDICES)
        else:
            indices = []

        return AvailableLocationsConfiguration(
            randomization_mode=randomization_mode,
            excluded_indices=frozenset(PickupIndex(item) for item in indices),
        )
Example #24
0
 def from_json(cls, name: str, value: dict) -> "MajorItem":
     return cls(
         name=name,
         item_category=ItemCategory(value["item_category"]),
         model_index=value["model_index"],
         progression=tuple(value["progression"]),
         ammo_index=tuple(value.get("ammo", [])),
         converts_indices=tuple(value.get("converts_indices", [])),
         required=value.get("required", False),
         original_index=PickupIndex(value["original_index"])
         if "original_index" in value else None,
         probability_offset=value["probability_offset"],
     )
Example #25
0
def test_create_hints_item_location(echoes_game_patches, blank_pickup, item,
                                    location, owner, is_multiworld,
                                    echoes_game_description, monkeypatch):
    # Setup
    asset_id = 1000
    pickup_index = PickupIndex(50)
    logbook_node, _, world_list = _create_world_list(asset_id, pickup_index)
    monkeypatch.setattr(echoes_game_description, "world_list", world_list)

    players_config = PlayersConfiguration(
        player_index=0,
        player_names={
            i: f"Player {i + 1}"
            for i in range(int(is_multiworld) + 1)
        },
    )
    location_precision, determiner, item_name = item
    if owner and is_multiworld:
        determiner = "&push;&main-color=#d4cc33;Player 1&pop;'s"

    patches = dataclasses.replace(
        echoes_game_patches,
        pickup_assignment={
            pickup_index: PickupTarget(blank_pickup, 0),
        },
        hints={
            world_list.identifier_for_node(logbook_node):
            Hint(
                HintType.LOCATION,
                PrecisionPair(location[0],
                              location_precision,
                              include_owner=owner),
                pickup_index,
            )
        })
    rng = MagicMock()
    namer = EchoesHintNamer({0: patches}, players_config)

    # Run
    result = hints.create_patches_hints({0: patches}, players_config,
                                        world_list, namer, rng)

    # Assert
    message = "{} {} can be found in {}.".format(determiner, item_name,
                                                 location[1])
    # message = "The Flying Ing Cache in {} contains {}.".format(location[1], item[1])
    assert result[0]['strings'][0] == message
    assert result == [{
        'asset_id': asset_id,
        'strings': [message, '', message]
    }]
Example #26
0
def test_prime1_pickup_details_to_patcher_shiny_missile(
        prime1_resource_database, other_player: bool):
    # Setup
    rng = MagicMock()
    rng.randint.return_value = 0
    detail = pickup_exporter.ExportedPickupDetails(
        index=PickupIndex(15),
        scan_text="Your Missile Expansion. Provides 5 Missiles",
        hud_text=["Missile Expansion acquired!"],
        conditional_resources=[
            ConditionalResources(
                None,
                None,
                ((prime1_resource_database.get_item_by_name("Missile"), 6), ),
            )
        ],
        conversion=[],
        model=PickupModel(RandovaniaGame.METROID_PRIME, "Missile"),
        other_player=other_player,
        original_pickup=None,
    )
    if other_player:
        shiny_stuff = {
            'model': {
                'game': 'prime1',
                'name': 'Missile'
            },
            'scanText': 'Your Missile Expansion. Provides 5 Missiles',
            'hudmemoText': 'Missile Expansion acquired!',
        }
    else:
        shiny_stuff = {
            'model': {
                'game': 'prime1',
                'name': 'Shiny Missile'
            },
            'scanText': 'Your Shiny Missile Expansion. Provides 5 Missiles',
            'hudmemoText': 'Shiny Missile Expansion acquired!',
        }

    # Run
    result = prime1_pickup_details_to_patcher(detail, False, rng)

    # Assert
    assert result == {
        'type': 'Missile',
        'currIncrease': 6,
        'maxIncrease': 6,
        'respawn': False,
        **shiny_stuff,
    }
Example #27
0
def test_create_message_for_hint_relative_area(echoes_game_description, pickup,
                                               players_config,
                                               distance_precise,
                                               distance_text):
    world_list = echoes_game_description.world_list
    patches = echoes_game_description.create_game_patches(
    ).assign_pickup_assignment({
        PickupIndex(5): PickupTarget(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(distance_precise,
                                      AreaLocation(1039999561, 3822429534),
                                      HintRelativeAreaName.NAME)),
        PickupIndex(5))

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

    # Assert
    assert result == (
        f'The &push;&main-color=#FF6705B3;Pickup&pop; can be found '
        f'&push;&main-color=#FF3333;{distance_text} 10 rooms&pop; away from Torvus Bog - Great Bridge.'
    )
Example #28
0
        def _describe_action(action: GameSessionTeamAction) -> dict:
            provider: int = action.provider_row
            receiver: int = action.receiver_row
            time = datetime.datetime.fromisoformat(action.time)
            target = description.all_patches[provider].pickup_assignment[
                PickupIndex(action.provider_location_index)]

            message = (
                f"{location_to_name[provider]} found {target.pickup.name} "
                f"for {location_to_name[receiver]}.")
            return {
                "message": message,
                "time": time.astimezone(datetime.timezone.utc).isoformat(),
            }
Example #29
0
def test_add_hints_precision(empty_patches):
    failed_relative_provider = MagicMock(return_value=None)
    relative_hint_provider = MagicMock()
    player_state = MagicMock()
    rng = MagicMock()
    hints = [
        Hint(
            HintType.LOCATION,
            PrecisionPair(HintLocationPrecision.DETAILED,
                          HintItemPrecision.DETAILED,
                          include_owner=False), PickupIndex(1)),
        Hint(HintType.LOCATION, None, PickupIndex(2)),
        Hint(HintType.LOCATION, None, PickupIndex(3)),
    ]
    nc = NodeIdentifier.create

    initial_patches = empty_patches
    for i, hint in enumerate(hints):
        initial_patches = initial_patches.assign_hint(nc("w", "a", f"{i}"),
                                                      hint)

    hint_distributor = EchoesHintDistributor()
    hint_distributor._get_relative_hint_providers = MagicMock(
        return_value=[failed_relative_provider, relative_hint_provider])

    # Run
    result = hint_distributor.add_hints_precision(player_state,
                                                  initial_patches, rng)

    # Assert
    failed_relative_provider.assert_called_once_with(player_state,
                                                     initial_patches, rng,
                                                     PickupIndex(2))
    relative_hint_provider.assert_called_once_with(player_state,
                                                   initial_patches, rng,
                                                   PickupIndex(3))
    assert result.hints == {
        nc("w", "a", "0"):
        Hint(
            HintType.LOCATION,
            PrecisionPair(HintLocationPrecision.DETAILED,
                          HintItemPrecision.DETAILED,
                          include_owner=False), PickupIndex(1)),
        nc("w", "a", "1"):
        Hint(
            HintType.LOCATION,
            PrecisionPair(HintLocationPrecision.WORLD_ONLY,
                          HintItemPrecision.PRECISE_CATEGORY,
                          include_owner=True), PickupIndex(2)),
        nc("w", "a", "2"):
        relative_hint_provider.return_value,
    }
Example #30
0
def export_all_indices(
    patches: GamePatches,
    useless_target: PickupTarget,
    pickup_count: int,
    rng: Random,
    model_style: PickupModelStyle,
    data_source: PickupModelDataSource,
    exporter: PickupExporter,
    visual_etm: PickupEntry,
) -> List[ExportedPickupDetails]:
    """
    Creates the patcher data for all pickups in the game
    :param patches:
    :param useless_target:
    :param pickup_count:
    :param rng:
    :param model_style:
    :param data_source:
    :param exporter:
    :param visual_etm:
    :return:
    """
    pickup_assignment = patches.pickup_assignment

    pickup_list = list(pickup_assignment.values())
    rng.shuffle(pickup_list)

    pickups = [
        exporter.export(
            PickupIndex(i),
            pickup_assignment.get(PickupIndex(i), useless_target),
            _get_visual_model(i, pickup_list, data_source, visual_etm),
            model_style,
        ) for i in range(pickup_count)
    ]

    return pickups