예제 #1
0
def test_edit_layout_trick_level(option: Options,
                                 initial_layout_configuration_params: dict,
                                 new_trick_level: LayoutTrickLevel):
    # Setup
    option._layout_configuration = LayoutConfiguration.from_params(**initial_layout_configuration_params)
    option._nested_autosave_level = 1

    # Run
    initial_layout_configuration_params["trick_level"] = new_trick_level
    setattr(option, "layout_configuration_trick_level", new_trick_level)

    # Assert
    assert option.layout_configuration == LayoutConfiguration.from_params(**initial_layout_configuration_params)
예제 #2
0
def test_edit_layout_quantity(option: Options,
                              initial_layout_configuration_params: dict):
    # Setup
    option._layout_configuration = LayoutConfiguration.from_params(**initial_layout_configuration_params)
    option._nested_autosave_level = 1
    pickup = next(option._layout_configuration.pickup_quantities.pickups())

    # Run
    initial_layout_configuration_params["pickup_quantities"] = {pickup.name: 12}
    option.set_quantity_for_pickup(pickup, 12)

    # Assert
    assert option.layout_configuration == LayoutConfiguration.from_params(**initial_layout_configuration_params)
def _layout_config_with_data(request):
    trick_config = DummyValue()
    starting_location = DummyValue()
    randomization_mode = DummyValue()
    major_items = DummyValue()
    ammo_config = DummyValue()
    translator_config = DummyValue()
    hints = DummyValue()

    with patch.multiple(TrickLevelConfiguration, bit_pack_unpack=MagicMock(return_value=trick_config)), \
         patch.multiple(StartingLocation, bit_pack_unpack=MagicMock(return_value=starting_location)), \
         patch.multiple(RandomizationMode, bit_pack_unpack=MagicMock(return_value=randomization_mode)), \
         patch.multiple(MajorItemsConfiguration, bit_pack_unpack=MagicMock(return_value=major_items)), \
         patch.multiple(AmmoConfiguration, bit_pack_unpack=MagicMock(return_value=ammo_config)), \
         patch.multiple(TranslatorConfiguration, bit_pack_unpack=MagicMock(return_value=translator_config)), \
         patch.multiple(HintConfiguration, bit_pack_unpack=MagicMock(return_value=hints)):
        yield request.param["encoded"], LayoutConfiguration.from_params(
            trick_level_configuration=trick_config,
            sky_temple_keys=request.param["sky_temple"],
            elevators=request.param["elevators"],
            starting_location=starting_location,
            randomization_mode=randomization_mode,
            major_items_configuration=major_items,
            ammo_configuration=ammo_config,
            translator_configuration=translator_config,
            hints=hints,
        )
예제 #4
0
def test_distribute_command_logic(mock_generate_list: 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.output_file = "asdfasdf/qwerqwerqwer/zxcvzxcv.json"

    # Run
    echoes.distribute_command_logic(args)

    # Assert
    mock_generate_list.assert_called_once_with(permalink=Permalink(
        seed_number=args.seed,
        spoiler=True,
        patcher_configuration=PatcherConfiguration.default(),
        layout_configuration=LayoutConfiguration.from_params(
            trick_level=LayoutTrickLevel.HARD,
            sky_temple_keys=LayoutSkyTempleKeyMode.ALL_BOSSES,
            elevators=LayoutRandomizedFlag.VANILLA,
            pickup_quantities={},
            starting_location=StartingLocation.default(),
            starting_resources=StartingResources.from_non_custom_configuration(
                StartingResourcesConfiguration.VANILLA_ITEM_LOSS_DISABLED),
        ),
    ),
                                               status_update=ANY)

    save_file_mock: MagicMock = mock_generate_list.return_value.save_to_file
    save_file_mock.assert_called_once_with(Path(args.output_file))
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)
예제 #6
0
def test_add_elevator_connections_to_patches_random(echoes_game_data):
    # Setup
    game = data_reader.decode_data(echoes_game_data)
    permalink = dataclasses.replace(Permalink.default(),
                                    layout_configuration=dataclasses.replace(
                                        LayoutConfiguration.default(),
                                        elevators=LayoutElevators.RANDOMIZED))
    expected = dataclasses.replace(GamePatches.with_game(game),
                                   elevator_connection={
                                       589851:
                                       AreaLocation(1039999561, 1868895730),
                                       1572998:
                                       AreaLocation(1039999561, 3479543630),
                                       1966093:
                                       AreaLocation(2252328306, 408633584),
                                       2097251:
                                       AreaLocation(1119434212, 3331021649),
                                       136970379:
                                       AreaLocation(2252328306, 2068511343),
                                       3342446:
                                       AreaLocation(1039999561, 3205424168),
                                       3538975:
                                       AreaLocation(1119434212, 2806956034),
                                       152:
                                       AreaLocation(1006255871, 2889020216),
                                       393260:
                                       AreaLocation(464164546, 3145160350),
                                       524321:
                                       AreaLocation(464164546, 900285955),
                                       589949:
                                       AreaLocation(1006255871, 2278776548),
                                       122:
                                       AreaLocation(464164546, 3528156989),
                                       1245307:
                                       AreaLocation(1006255871, 1345979968),
                                       2949235:
                                       AreaLocation(1006255871, 1287880522),
                                       129:
                                       AreaLocation(1006255871, 2918020398),
                                       2162826:
                                       AreaLocation(1006255871, 1660916974),
                                       4522032:
                                       AreaLocation(1006255871, 3455543403),
                                       38:
                                       AreaLocation(1119434212, 1473133138),
                                       1245332:
                                       AreaLocation(2252328306, 2399252740),
                                       1638535:
                                       AreaLocation(2252328306, 2556480432),
                                   })

    # Run
    result = base_patches_factory.add_elevator_connections_to_patches(
        permalink.layout_configuration,
        Random(permalink.seed_number),
        GamePatches.with_game(game),
    )

    # Assert
    assert result == expected
예제 #7
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
예제 #8
0
def test_run_filler(mock_retcon_playthrough_filler: MagicMock,
                    echoes_game_description,
                    pickup
                    ):
    # Setup
    configuration = LayoutConfiguration.default()
    rng = Random(5000)
    status_update = MagicMock()
    item_pool = [pickup]
    patches = GamePatches.with_game(echoes_game_description)

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

    mock_retcon_playthrough_filler.return_value = patches.assign_hint(
        logbook_nodes[0].resource(), Hint(HintType.LOCATION, None, PickupIndex(0))
    ).assign_pickup_assignment({PickupIndex(1): pickup})

    # Run
    result_patches, remaining_items = runner.run_filler(configuration, echoes_game_description,
                                                        item_pool, patches,
                                                        rng, status_update)

    # Assert
    assert len(result_patches.hints) == len(logbook_nodes)
    assert [hint for hint in patches.hints.values()
            if hint.item_precision is None or hint.location_precision is None] == []
    assert remaining_items == [pickup]
예제 #9
0
def _decode_preset(decoder: BitPackDecoder, manager: PresetManager) -> Preset:
    included_presets = [versioned.get_preset() for versioned in manager.included_presets]

    is_custom_preset = bitpacking.decode_bool(decoder)
    reference_preset = decoder.decode_element(included_presets)
    if is_custom_preset:
        patcher_configuration = PatcherConfiguration.bit_pack_unpack(
            decoder, {"reference": reference_preset.patcher_configuration})
        layout_configuration = LayoutConfiguration.bit_pack_unpack(
            decoder, {"reference": reference_preset.layout_configuration})
        preset = Preset(
            name="{} Custom".format(reference_preset.name),
            description="A customized preset.",
            base_preset_name=reference_preset.name,
            patcher_configuration=patcher_configuration,
            layout_configuration=layout_configuration,
        )

    else:
        preset = reference_preset
    included_data_hash = decoder.decode_single(256)
    expected_data_hash = _dictionary_byte_hash(preset.layout_configuration.game_data)
    if included_data_hash != expected_data_hash:
        raise ValueError("Given permalink is for a Randovania database with hash '{}', "
                         "but current database has hash '{}'.".format(included_data_hash, expected_data_hash))
    return preset
def test_round_trip_generated_patches(echoes_game_data):
    # Setup
    configuration = LayoutConfiguration.from_params(
        trick_level_configuration=TrickLevelConfiguration(
            global_level=LayoutTrickLevel.MINIMAL_RESTRICTIONS,
            specific_levels={},
        ))

    patches = generator._create_randomized_patches(
        permalink=Permalink(
            seed_number=1000,
            spoiler=True,
            patcher_configuration=PatcherConfiguration.default(),
            layout_configuration=configuration,
        ),
        game=data_reader.decode_data(echoes_game_data),
        status_update=lambda x: None,
    )

    # Run
    encoded = game_patches_serializer.serialize(patches, echoes_game_data)
    decoded = game_patches_serializer.decode(encoded, configuration)

    # Assert
    assert patches == decoded
예제 #11
0
 def default(cls) -> "Permalink":
     return Permalink(
         seed_number=0,
         spoiler=True,
         patcher_configuration=PatcherConfiguration.default(),
         layout_configuration=LayoutConfiguration.default(),
     )
예제 #12
0
def test_edit_layout_trick_level(option: Options,
                                 initial_layout_configuration_params: dict,
                                 new_trick_level: LayoutTrickLevel):
    # Setup
    option._layout_configuration = LayoutConfiguration.from_params(
        **initial_layout_configuration_params)
    option._nested_autosave_level = 1

    # Run
    initial_layout_configuration_params[
        "trick_level_configuration"] = TrickLevelConfiguration(new_trick_level)
    option.set_layout_configuration_field(
        "trick_level_configuration", TrickLevelConfiguration(new_trick_level))

    # Assert
    assert option.layout_configuration == LayoutConfiguration.from_params(
        **initial_layout_configuration_params)
def test_decode(patches_with_data):
    encoded, expected = patches_with_data

    # Run
    decoded = game_patches_serializer.decode(encoded,
                                             LayoutConfiguration.default())

    # Assert
    assert decoded == expected
예제 #14
0
 def from_json_dict(cls, param: dict) -> "Permalink":
     return Permalink(
         seed_number=param["seed"],
         spoiler=param["spoiler"],
         patcher_configuration=PatcherConfiguration.from_json_dict(
             param["patcher_configuration"]),
         layout_configuration=LayoutConfiguration.from_json_dict(
             param["layout_configuration"]),
     )
예제 #15
0
파일: echoes.py 프로젝트: xisi/randovania
def get_layout_configuration_from_args(args) -> LayoutConfiguration:
    return LayoutConfiguration.from_params(
        trick_level=LayoutTrickLevel(args.trick_level),
        sky_temple_keys=LayoutSkyTempleKeyMode(args.sky_temple_keys),
        elevators=LayoutRandomizedFlag.VANILLA,
        pickup_quantities={},
        starting_location=StartingLocation.default(),
        starting_resources=StartingResources.from_item_loss(
            not args.skip_item_loss),
    )
예제 #16
0
def test_decode(layout_config_with_data):
    # Setup
    data, expected = layout_config_with_data

    # Run
    decoder = BitPackDecoder(data)
    result = LayoutConfiguration.bit_pack_unpack(decoder, {})

    # Assert
    assert result == expected
예제 #17
0
 def from_json_dict(cls, value) -> "Preset":
     return Preset(
         name=value["name"],
         description=value["description"],
         base_preset_name=value["base_preset_name"],
         patcher_configuration=PatcherConfiguration.from_json_dict(
             value["patcher_configuration"]),
         layout_configuration=LayoutConfiguration.from_json_dict(
             value["layout_configuration"]),
     )
예제 #18
0
def test_create_patches(
    mock_random: MagicMock,
    mock_calculate_item_pool: MagicMock,
    mock_create_base_patches: MagicMock,
    mock_retcon_playthrough_filler: MagicMock,
    mock_indices_for_unassigned_pickups: MagicMock,
):
    # Setup
    seed_number: int = 91319
    game = default_prime2_game_description()
    status_update: Union[MagicMock, Callable[[str], None]] = MagicMock()
    configuration = LayoutConfiguration.from_params(
        trick_level=LayoutTrickLevel.NO_TRICKS,
        sky_temple_keys=LayoutSkyTempleKeyMode.FULLY_RANDOM,
        elevators=LayoutRandomizedFlag.VANILLA,
        pickup_quantities={},
        starting_location=StartingLocation.default(),
        starting_resources=StartingResources.from_item_loss(False),
    )
    permalink = Permalink(
        seed_number=seed_number,
        spoiler=True,
        patcher_configuration=PatcherConfiguration.default(),
        layout_configuration=configuration,
    )
    mock_calculate_item_pool.return_value = list(
        sorted(game.pickup_database.original_pickup_mapping.values()))
    mock_create_base_patches.return_value.starting_location = game.starting_location
    mock_create_base_patches.return_value.custom_initial_items = None

    filler_patches = mock_retcon_playthrough_filler.return_value

    # Run
    result = generator._create_patches(permalink, game, status_update)

    # Assert
    mock_random.assert_called_once_with(permalink.as_str)
    mock_calculate_item_pool.assert_called_once_with(permalink, game)

    mock_create_base_patches.assert_called_once_with(mock_random.return_value,
                                                     game, permalink, ANY)

    mock_retcon_playthrough_filler.assert_called_once_with(
        ANY, ANY, ANY, mock_random.return_value, status_update)

    mock_indices_for_unassigned_pickups.assert_called_once_with(
        mock_random.return_value, game, filler_patches.pickup_assignment, ANY)
    filler_patches.assign_new_pickups.assert_called_once_with(
        mock_indices_for_unassigned_pickups.return_value)

    assert result == filler_patches.assign_new_pickups.return_value
예제 #19
0
def get_layout_configuration_from_args(args) -> LayoutConfiguration:
    try:
        sky_temple_keys = int(args.sky_temple_keys)
    except ValueError:
        sky_temple_keys = args.sky_temple_keys

    # TODO: support for item loss
    return LayoutConfiguration.from_params(
        trick_level_configuration=TrickLevelConfiguration(
            LayoutTrickLevel(args.trick_level)),
        sky_temple_keys=LayoutSkyTempleKeyMode(sky_temple_keys),
        elevators=LayoutElevators.VANILLA,
        starting_location=StartingLocation.default(),
    )
예제 #20
0
def test_create_pickup_all_from_pool(echoes_resource_database,
                                     disable_hud_popup: bool
                                     ):
    layout_configuration = LayoutConfiguration.from_params()
    item_pool = pool_creator.calculate_pool_results(layout_configuration, echoes_resource_database)[0]
    index = PickupIndex(0)
    if disable_hud_popup:
        memo_data = None
    else:
        memo_data = default_prime2_memo_data()

    for item in item_pool:
        try:
            patcher_file._create_pickup(index, item, item, PickupModelStyle.ALL_VISIBLE, memo_data)
        except Exception as e:
            assert str(e) == item.name
예제 #21
0
def test_encode(mock_dictionary_byte_hash: MagicMock):
    # Setup
    mock_dictionary_byte_hash.return_value = 120
    link = Permalink(
        seed_number=1000,
        spoiler=True,
        patcher_configuration=PatcherConfiguration.default(),
        layout_configuration=LayoutConfiguration.default(),
    )

    # Run
    encoded = link.as_str

    # Assert
    mock_dictionary_byte_hash.assert_called_once_with(
        link.layout_configuration.game_data)
    assert encoded == "MAAAfReMYADv"
def _test_data():
    data = default_data.decode_default_prime2()
    game = data_reader.decode_data(data)
    configuration = LayoutConfiguration.from_params()
    permalink = Permalink(
        seed_number=15000,
        spoiler=True,
        patcher_configuration=PatcherConfiguration.default(),
        layout_configuration=configuration,
    )
    patches = GamePatches.with_game(game)
    patches = patches.assign_gate_assignment(
        base_patches_factory.gate_assignment_for_configuration(
            configuration, game.resource_database, Random(15000)))
    game, state = logic_bootstrap(configuration, game, patches)

    return game, state, permalink
예제 #23
0
def test_retcon_filler_integration():
    layout_configuration = LayoutConfiguration.default()

    rng = Random("fixed-seed!")
    status_update = MagicMock()

    game = data_reader.decode_data(layout_configuration.game_data)
    patches = GamePatches.with_game(game)
    available_pickups = game.pickup_database.all_useful_pickups

    logic, state = logic_bootstrap(layout_configuration, game, patches)
    logic.game.simplify_connections(state.resources)

    filler_patches = retcon.retcon_playthrough_filler(logic, state,
                                                      tuple(available_pickups),
                                                      rng, status_update)
    assert filler_patches == patches
예제 #24
0
파일: echoes.py 프로젝트: xisi/randovania
def validate_command_logic(args):
    debug._DEBUG_LEVEL = args.debug
    data = prime_database.decode_data_file(args)
    game = data_reader.decode_data(data)

    if args.layout_file is not None:
        description = LayoutDescription.from_file(Path(args.layout_file))
        configuration = description.permalink.layout_configuration
        patches = description.patches
    else:
        configuration = LayoutConfiguration.default()
        patches = GamePatches.with_game(game).assign_pickup_assignment(
            game.pickup_database.original_pickup_mapping)

    final_state_by_resolve = resolver.resolve(configuration=configuration,
                                              game=game,
                                              patches=patches)
    print(final_state_by_resolve)
예제 #25
0
def test_output_name_for(mock_shareable_hash: PropertyMock, empty_patches):
    # Setup
    permalink_mock = MagicMock(spec=Permalink(
        seed_number=15000,
        spoiler=True,
        patcher_configuration=PatcherConfiguration.default(),
        layout_configuration=LayoutConfiguration.default(),
    ))
    layout = LayoutDescription(version="0.15.0",
                               permalink=permalink_mock,
                               patches=empty_patches,
                               solver_path=())
    mock_shareable_hash.return_value = "PermalinkStr"

    # Run
    result = simplified_patcher._output_name_for(layout)

    # Assert
    assert result == "Echoes Randomizer - PermalinkStr"
예제 #26
0
def _load_previous_state(persistence_path: Path,
                         layout_configuration: LayoutConfiguration,
                         ) -> Optional[dict]:
    previous_layout_path = persistence_path.joinpath("layout_configuration.json")
    try:
        with previous_layout_path.open() as previous_layout_file:
            previous_layout = LayoutConfiguration.from_json_dict(json.load(previous_layout_file))
    except (FileNotFoundError, TypeError, KeyError, json.JSONDecodeError):
        return None

    if previous_layout != layout_configuration:
        return None

    previous_state_path = persistence_path.joinpath("state.json")
    try:
        with previous_state_path.open() as previous_state_file:
            return json.load(previous_state_file)
    except (FileNotFoundError, json.JSONDecodeError):
        return None
def test_calculate_reach_with_all_pickups(test_data):
    game, state, _ = test_data

    item_pool = calculate_item_pool(LayoutConfiguration.from_params(),
                                    game.resource_database, state.patches)
    add_resources_into_another(state.resources, item_pool[0].starting_items)
    for pickup in item_pool[1]:
        add_pickup_to_state(state, pickup)

    first_reach, second_reach = _create_reaches_and_compare(game, state)
    first_actions, second_actions = _compare_actions(first_reach, second_reach)

    found_pickups = set(
        filter_pickup_nodes(filter_reachable(second_reach.nodes, first_reach)))
    all_pickups = set(filter_pickup_nodes(game.world_list.all_nodes))

    # assert (len(list(first_reach.nodes)), len(first_actions)) == (898, 9)
    # assert (len(list(second_reach.nodes)), len(second_actions)) == (898, 9)
    pprint.pprint(first_actions)
    assert all_pickups == found_pickups
def test_reach_size_from_start(echoes_game_description):
    # Setup
    configuration = LayoutConfiguration.from_params(
        trick_level_configuration=TrickLevelConfiguration(
            LayoutTrickLevel.HYPERMODE), )
    patches = GamePatches.with_game(echoes_game_description)
    patches = patches.assign_gate_assignment(
        base_patches_factory.gate_assignment_for_configuration(
            configuration, echoes_game_description.resource_database,
            Random(15000)))

    game, state = logic_bootstrap(configuration, echoes_game_description,
                                  patches)

    # Run
    reach = GeneratorReach.reach_from_state(game, state)

    # Assert
    assert len(list(reach.nodes)) == 26
    assert len(list(reach.safe_nodes)) == 4
예제 #29
0
    def bit_pack_unpack(cls, decoder: BitPackDecoder) -> "Permalink":
        version, seed, spoiler = decoder.decode(_PERMALINK_MAX_VERSION,
                                                _PERMALINK_MAX_SEED, 2)
        cls._raise_if_different_version(version)

        included_data_hash = decoder.decode(256)[0]

        patcher_configuration = PatcherConfiguration.bit_pack_unpack(decoder)
        layout_configuration = LayoutConfiguration.bit_pack_unpack(decoder)

        expected_data_hash = _dictionary_byte_hash(
            layout_configuration.game_data)
        if included_data_hash != expected_data_hash:
            raise ValueError(
                "Given permalink is for a Randovania database with hash '{}', "
                "but current database has hash '{}'.".format(
                    included_data_hash, expected_data_hash))

        return Permalink(seed, bool(spoiler), patcher_configuration,
                         layout_configuration)
예제 #30
0
def _test_data():
    data = default_data.decode_default_prime2()
    game = data_reader.decode_data(data, False)
    configuration = LayoutConfiguration.from_params(
        trick_level=LayoutTrickLevel.NO_TRICKS,
        sky_temple_keys=LayoutSkyTempleKeyMode.FULLY_RANDOM,
        elevators=LayoutRandomizedFlag.VANILLA,
        pickup_quantities={},
        starting_location=StartingLocation.default(),
        starting_resources=StartingResources.default(),
    )
    permalink = Permalink(
        seed_number=15000,
        spoiler=True,
        patcher_configuration=PatcherConfiguration.default(),
        layout_configuration=configuration,
    )
    logic, state = logic_bootstrap(configuration, game,
                                   GamePatches.with_game(game))

    return logic, state, permalink