コード例 #1
0
def test_create_permalink_logic(mock_print: MagicMock, ):
    # Setup
    args = MagicMock()
    args.trick_level = LayoutTrickLevel.HARD.value
    args.major_items_mode = False
    args.sky_temple_keys = LayoutSkyTempleKeyMode.ALL_BOSSES.value
    args.skip_item_loss = True
    args.seed = 15000
    args.menu_mod = False
    args.warp_to_start = False

    # Run
    randovania.cli.commands.create_permalink.create_permalink_logic(args)

    # Assert
    permalink = Permalink(
        seed_number=args.seed,
        spoiler=True,
        patcher_configuration=PatcherConfiguration(
            menu_mod=args.menu_mod,
            warp_to_start=args.warp_to_start,
        ),
        layout_configuration=LayoutConfiguration.from_params(
            trick_level_configuration=TrickLevelConfiguration(
                LayoutTrickLevel.HARD),
            sky_temple_keys=LayoutSkyTempleKeyMode.ALL_BOSSES,
            elevators=LayoutElevators.VANILLA,
            starting_location=StartingLocation.default(),
        ),
    )

    # Assert
    mock_print.assert_called_once_with(permalink)
コード例 #2
0
def test_decode(mock_dictionary_byte_hash: MagicMock):
    mock_dictionary_byte_hash.return_value = 120
    # We're mocking the database hash to avoid breaking tests every single time we change the database

    # This test should break whenever we change how permalinks are created
    # When this happens, we must bump the permalink version and change the tests
    encoded = "gAAAfReLCAAC4wAAAOaANg=="

    expected = Permalink(
        seed_number=1000,
        spoiler=True,
        patcher_configuration=PatcherConfiguration(
            menu_mod=True,
            warp_to_start=False,
        ),
        layout_configuration=LayoutConfiguration.from_params(
            trick_level_configuration=TrickLevelConfiguration(
                LayoutTrickLevel.HARD),
            elevators=LayoutElevators.RANDOMIZED,
        ),
    )

    # Uncomment this line to quickly get the new encoded permalink
    # assert expected.as_str == ""
    # print(expected.as_str)

    # Run
    link = Permalink.from_str(encoded)

    # Assert
    assert link == expected
コード例 #3
0
def test_apply_layout(
    mock_ensure_no_menu_mod: MagicMock,
    mock_create_pak_backups: MagicMock,
    mock_add_menu_mod_to_files: MagicMock,
    mock_modern_api: MagicMock,
    mock_create_progress_update_from_successive_messages: MagicMock,
    mock_save_to_file: MagicMock,
    include_menu_mod: bool,
    has_backup_path: bool,
):
    # Setup
    cosmetic_patches = MagicMock()
    description = LayoutDescription(
        version=randovania.VERSION,
        permalink=Permalink(seed_number=1,
                            spoiler=False,
                            patcher_configuration=PatcherConfiguration(
                                menu_mod=include_menu_mod,
                                warp_to_start=MagicMock(),
                            ),
                            layout_configuration=MagicMock()),
        patches=MagicMock(),
        solver_path=(),
    )

    game_root = MagicMock(spec=Path())
    backup_files_path = MagicMock() if has_backup_path else None
    progress_update = MagicMock()
    status_update = mock_create_progress_update_from_successive_messages.return_value

    # Run
    claris_randomizer.apply_layout(description, cosmetic_patches,
                                   backup_files_path, progress_update,
                                   game_root)

    # Assert
    mock_create_progress_update_from_successive_messages.assert_called_once_with(
        progress_update, 400 if include_menu_mod else 100)
    mock_ensure_no_menu_mod.assert_called_once_with(game_root,
                                                    backup_files_path,
                                                    status_update)
    if has_backup_path:
        mock_create_pak_backups.assert_called_once_with(
            game_root, backup_files_path, status_update)
    else:
        mock_create_pak_backups.assert_not_called()
    game_root.joinpath.assert_called_once_with("files", "randovania.json")
    mock_save_to_file.assert_called_once_with(description,
                                              game_root.joinpath.return_value)

    mock_modern_api.assert_called_once_with(game_root, status_update,
                                            description, cosmetic_patches)

    if include_menu_mod:
        mock_add_menu_mod_to_files.assert_called_once_with(
            game_root, status_update)
    else:
        mock_add_menu_mod_to_files.assert_not_called()
コード例 #4
0
def create_permalink_logic(args):
    seed_number = args.seed
    if seed_number is None:
        seed_number = random.randint(0, 2 ** 31)

    permalink = Permalink(
        seed_number=seed_number,
        spoiler=True,
        patcher_configuration=PatcherConfiguration(
            menu_mod=args.menu_mod,
            warp_to_start=args.warp_to_start,
        ),
        layout_configuration=get_layout_configuration_from_args(args),
    )
    _print_permalink(permalink)
コード例 #5
0
ファイル: test_permalink.py プロジェクト: xisi/randovania
def test_decode_v1(mock_dictionary_byte_hash: MagicMock):
    mock_dictionary_byte_hash.return_value = 120
    # We're mocking the database hash to avoid breaking tests every single time we change the database

    # This test should break whenever we change how permalinks are created
    # When this happens, we must bump the permalink version and change the tests
    encoded = "IAAAfReNPArRHMClxLYgIID3"

    expected = Permalink(
        seed_number=1000,
        spoiler=True,
        patcher_configuration=PatcherConfiguration(
            disable_hud_popup=True,
            menu_mod=True,
            speed_up_credits=False,
        ),
        layout_configuration=LayoutConfiguration.from_params(
            trick_level=LayoutTrickLevel.HARD,
            sky_temple_keys=LayoutSkyTempleKeyMode.FULLY_RANDOM,
            elevators=LayoutRandomizedFlag.RANDOMIZED,
            pickup_quantities={
                "Missile Expansion": 10,
                "Light Suit": 9,
            },
            starting_location=StartingLocation.default(),
            starting_resources=StartingResources.default(),
        ),
    )

    # Uncomment this line to quickly get the new encoded permalink
    # assert expected.as_str == ""

    # Run
    link = Permalink.from_str(encoded)

    # Assert
    assert link == expected
コード例 #6
0
    assert encoded == "MAAAfReMYADv"


@pytest.mark.parametrize(
    "invalid",
    ["", "a", "x", "zz", "AAAAfRxALWmCI50gIQD", "AAAAfRxALxmCI50gIQDy"])
def test_decode_invalid(invalid: str):
    with pytest.raises(ValueError):
        Permalink.from_str(invalid)


@pytest.mark.parametrize("spoiler", [False, True])
@pytest.mark.parametrize("patcher", [
    PatcherConfiguration.default(),
    PatcherConfiguration(
        menu_mod=True,
        warp_to_start=False,
    ),
])
@pytest.mark.parametrize("layout", [
    LayoutConfiguration.default(),
    LayoutConfiguration.from_params(
        trick_level=LayoutTrickLevel.HARD,
        sky_temple_keys=LayoutSkyTempleKeyMode.FULLY_RANDOM,
        elevators=LayoutRandomizedFlag.RANDOMIZED,
        pickup_quantities={
            "Missile Expansion": 10,
            "Light Suit": 9,
        },
        starting_location=StartingLocation.default(),
        starting_resources=StartingResources.default(),
    ),
コード例 #7
0
def describe(preset: Preset) -> Iterable[PresetDescription]:
    patcher = preset.patcher_configuration
    configuration = preset.layout_configuration
    major_items = configuration.major_items_configuration

    game_description = data_reader.decode_data(
        preset.layout_configuration.game_data)

    format_params = {}

    def _bool_to_str(b: bool) -> str:
        if b:
            return "Yes"
        else:
            return "No"

    # Item Placement

    random_starting_items = "{} to {}".format(
        major_items.minimum_random_starting_items,
        major_items.maximum_random_starting_items,
    )
    if random_starting_items == "0 to 0":
        random_starting_items = "None"

    format_params[
        "trick_level"] = configuration.trick_level_configuration.pretty_description
    format_params[
        "randomization_mode"] = configuration.randomization_mode.value
    format_params["random_starting_items"] = random_starting_items

    # Items
    format_params["progressive_suit"] = _bool_to_str(
        major_items.progressive_suit)
    format_params["progressive_grapple"] = _bool_to_str(
        major_items.progressive_grapple)
    format_params["split_beam_ammo"] = _bool_to_str(
        configuration.split_beam_ammo)
    format_params["starting_items"] = _calculate_starting_items(
        configuration.major_items_configuration.items_state)
    format_params["item_pool"] = _calculate_item_pool(
        configuration.major_items_configuration)

    # Difficulty
    default_patcher = PatcherConfiguration()

    if patcher.varia_suit_damage == default_patcher.varia_suit_damage and (
            patcher.dark_suit_damage == default_patcher.dark_suit_damage):
        dark_aether_suit_damage = "Normal"
    else:
        dark_aether_suit_damage = "Custom"

    format_params["dark_aether_suit_damage"] = dark_aether_suit_damage
    format_params[
        "dark_aether_damage_strictness"] = configuration.damage_strictness.long_name
    format_params["pickup_model"] = patcher.pickup_model_style.value

    # Gameplay
    translator_gates = "Custom"
    translator_configurations = [
        (configuration.translator_configuration.with_vanilla_actual(),
         "Vanilla (Actual)"),
        (configuration.translator_configuration.with_vanilla_colors(),
         "Vanilla (Colors)"),
        (configuration.translator_configuration.with_full_random(), "Random"),
    ]
    for translator_config, name in translator_configurations:
        if translator_config == configuration.translator_configuration:
            translator_gates = name
            break

    starting_locations = configuration.starting_location.locations

    if len(starting_locations) == 1:
        area = game_description.world_list.area_by_area_location(
            next(iter(starting_locations)))
        format_params[
            "starting_location"] = game_description.world_list.area_name(
                area, distinguish_dark_aether=True)
    else:
        format_params["starting_location"] = "{} locations".format(
            len(starting_locations))

    format_params["translator_gates"] = translator_gates
    format_params["elevators"] = configuration.elevators.value
    format_params["hints"] = "Yes"

    # Game Changes
    missile_launcher_required = True
    main_pb_required = True
    for ammo, state in configuration.ammo_configuration.items_state.items():
        if ammo.name == "Missile Expansion":
            missile_launcher_required = state.requires_major_item
        elif ammo.name == "Power Bomb Expansion":
            main_pb_required = state.requires_major_item

    format_params["missile_launcher_required"] = _bool_to_str(
        missile_launcher_required)
    format_params["main_pb_required"] = _bool_to_str(main_pb_required)
    format_params["warp_to_start"] = _bool_to_str(patcher.warp_to_start)
    format_params["generic_patches"] = "Some"
    format_params["menu_mod"] = _bool_to_str(patcher.menu_mod)
    format_params["include_final_bosses"] = _bool_to_str(
        not configuration.skip_final_bosses)

    # Sky Temple Keys
    if configuration.sky_temple_keys.num_keys == LayoutSkyTempleKeyMode.ALL_BOSSES:
        stk_location = "Bosses"
    elif configuration.sky_temple_keys.num_keys == LayoutSkyTempleKeyMode.ALL_GUARDIANS:
        stk_location = "Guardians"
    else:
        stk_location = "Random"

    format_params["target"] = "{0} of {0}".format(
        configuration.sky_temple_keys.num_keys)
    format_params["location"] = stk_location

    for category, templates in _TEMPLATE_STRINGS.items():
        yield category, [item.format(**format_params) for item in templates]
コード例 #8
0
def test_apply_layout(mock_run_with_args: MagicMock,
                      mock_base_args: MagicMock,
                      mock_ensure_no_menu_mod: MagicMock,
                      mock_create_pak_backups: MagicMock,
                      mock_calculate_indices: MagicMock,
                      mock_add_menu_mod_to_files: MagicMock,
                      mock_create_progress_update_from_successive_messages: MagicMock,
                      mock_save_to_file: MagicMock,
                      seed_number: int,
                      item_loss: bool,
                      elevators: bool,
                      warp_to_start: bool,
                      include_menu_mod: bool,
                      speed_up_credits: bool,
                      ):
    # Setup
    hud_memo_popup_removal: bool = MagicMock()
    cosmetic_patches = CosmeticPatches(disable_hud_popup=hud_memo_popup_removal,
                                       speed_up_credits=speed_up_credits,
                                       )
    description = LayoutDescription(
        version=randovania.VERSION,
        permalink=Permalink(
            seed_number=seed_number,
            spoiler=False,
            patcher_configuration=PatcherConfiguration(
                menu_mod=include_menu_mod,
                warp_to_start=warp_to_start,
            ),
            layout_configuration=LayoutConfiguration.from_params(
                trick_level=MagicMock(),
                sky_temple_keys=MagicMock(),
                elevators=LayoutRandomizedFlag.RANDOMIZED if elevators else LayoutRandomizedFlag.VANILLA,
                pickup_quantities={},
                starting_location=StartingLocation.default(),
                starting_resources=StartingResources.from_item_loss(item_loss),
            )
        ),
        patches=None,
        solver_path=(),
    )

    game_root = MagicMock(spec=Path())
    backup_files_path = MagicMock()
    progress_update = MagicMock()
    status_update = mock_create_progress_update_from_successive_messages.return_value

    mock_calculate_indices.return_value = [10, 25, 1, 2, 5, 1]
    mock_base_args.return_value = []
    expected_args = [
        "-s", str(seed_number),
        "-p", "10,25,1,2,5,1"
    ]
    if not item_loss:
        expected_args.append("-i")
    if elevators:
        expected_args.append("-v")
    if speed_up_credits:
        expected_args.append("-c")
    if warp_to_start:
        expected_args.append("-t")

    # Run
    claris_randomizer.apply_layout(description, cosmetic_patches, backup_files_path, progress_update, game_root)

    # Assert
    mock_base_args.assert_called_once_with(game_root, hud_memo_popup_removal=hud_memo_popup_removal)
    mock_create_progress_update_from_successive_messages.assert_called_once_with(
        progress_update,
        400 if include_menu_mod else 100
    )
    mock_ensure_no_menu_mod.assert_called_once_with(game_root, backup_files_path, status_update)
    mock_create_pak_backups.assert_called_once_with(game_root, backup_files_path, status_update)
    mock_calculate_indices.assert_called_once_with(description)
    game_root.joinpath.assert_called_once_with("files", "randovania.json")
    mock_save_to_file.assert_called_once_with(description, game_root.joinpath.return_value)
    mock_run_with_args.assert_called_once_with(expected_args, "Randomized!", status_update)
    if include_menu_mod:
        mock_add_menu_mod_to_files.assert_called_once_with(game_root, status_update)
    else:
        mock_add_menu_mod_to_files.assert_not_called()
コード例 #9
0
def test_apply_layout(
    mock_ensure_no_menu_mod: MagicMock,
    mock_create_pak_backups: MagicMock,
    mock_add_menu_mod_to_files: MagicMock,
    mock_modern_api: MagicMock,
    mock_apply_patches: MagicMock,
    mock_create_progress_update_from_successive_messages: MagicMock,
    mock_save_to_file: MagicMock,
    include_menu_mod: bool,
    has_backup_path: bool,
):
    # Setup
    cosmetic_patches = MagicMock()
    description = LayoutDescription(
        version=randovania.VERSION,
        permalink=Permalink(
            seed_number=1,
            spoiler=False,
            presets={
                0:
                Preset(name="Name",
                       description="Desc",
                       base_preset_name=None,
                       patcher_configuration=PatcherConfiguration(
                           menu_mod=include_menu_mod,
                           warp_to_start=MagicMock(),
                       ),
                       layout_configuration=MagicMock())
            },
        ),
        all_patches={0: MagicMock()},
        item_order=(),
    )

    game_root = MagicMock(spec=Path())
    backup_files_path = MagicMock() if has_backup_path else None
    progress_update = MagicMock()
    player_config = PlayersConfiguration(0, {0: "you"})
    status_update = mock_create_progress_update_from_successive_messages.return_value

    # Run
    claris_randomizer.apply_layout(description, player_config,
                                   cosmetic_patches, backup_files_path,
                                   progress_update, game_root)

    # Assert
    mock_create_progress_update_from_successive_messages.assert_called_once_with(
        progress_update, 400 if include_menu_mod else 100)
    mock_ensure_no_menu_mod.assert_called_once_with(game_root,
                                                    backup_files_path,
                                                    status_update)
    if has_backup_path:
        mock_create_pak_backups.assert_called_once_with(
            game_root, backup_files_path, status_update)
    else:
        mock_create_pak_backups.assert_not_called()
    game_root.joinpath.assert_called_once_with(
        "files", "randovania.{}".format(LayoutDescription.file_extension()))
    mock_save_to_file.assert_called_once_with(description,
                                              game_root.joinpath.return_value)

    mock_modern_api.assert_called_once_with(game_root, status_update,
                                            description, player_config,
                                            cosmetic_patches)
    mock_apply_patches.assert_called_once_with(game_root,
                                               description.all_patches[0],
                                               cosmetic_patches)

    if include_menu_mod:
        mock_add_menu_mod_to_files.assert_called_once_with(
            game_root, status_update)
    else:
        mock_add_menu_mod_to_files.assert_not_called()
コード例 #10
0
ファイル: test_permalink.py プロジェクト: xisi/randovania
        link.layout_configuration.game_data)
    assert encoded == "IAAAfReOMACm"


@pytest.mark.parametrize(
    "invalid",
    ["", "a", "x", "zz", "AAAAfRxALWmCI50gIQD", "AAAAfRxALxmCI50gIQDy"])
def test_decode_invalid(invalid: str):
    with pytest.raises(ValueError):
        Permalink.from_str(invalid)


@pytest.mark.parametrize("spoiler", [False, True])
@pytest.mark.parametrize("patcher", [
    PatcherConfiguration.default(),
    PatcherConfiguration(
        disable_hud_popup=False, menu_mod=True, speed_up_credits=False),
])
@pytest.mark.parametrize("layout", [
    LayoutConfiguration.default(),
    LayoutConfiguration.from_params(
        trick_level=LayoutTrickLevel.HARD,
        sky_temple_keys=LayoutSkyTempleKeyMode.FULLY_RANDOM,
        elevators=LayoutRandomizedFlag.RANDOMIZED,
        pickup_quantities={
            "Missile Expansion": 10,
            "Light Suit": 9,
        },
        starting_location=StartingLocation.default(),
        starting_resources=StartingResources.default(),
    ),
])