Exemple #1
0
def add_artifacts(
    resource_database: ResourceDatabase,
    mode: LayoutArtifactMode,
) -> PoolResults:
    """
    :param resource_database:
    :param mode
    :return:
    """
    item_pool: List[PickupEntry] = []
    initial_resources: CurrentResources = {}

    artifacts_to_place = mode.value

    for i in range(artifacts_to_place):
        item_pool.append(pickup_creator.create_artifact(i, resource_database))

    first_automatic_artifact = artifacts_to_place

    for automatic_artifact in range(first_automatic_artifact, 12):
        resource_info.add_resource_gain_to_current_resources(
            pickup_creator.create_artifact(automatic_artifact,
                                           resource_database).all_resources,
            initial_resources)

    return PoolResults(item_pool, {}, initial_resources)
Exemple #2
0
def calculate_pool_results(layout_configuration: BaseConfiguration,
                           resource_database: ResourceDatabase,
                           base_patches: GamePatches = None,
                           rng: Random = None,
                           rng_required: bool = False
                           ) -> PoolResults:
    """
    Creates a PoolResults with all starting items and pickups in fixed locations, as well as a list of
    pickups we should shuffle.
    :param layout_configuration:
    :param resource_database:
    :return:
    """
    base_results = PoolResults([], {}, {})

    # Adding major items to the pool
    _extend_pool_results(base_results, add_major_items(resource_database,
                                                       layout_configuration.major_items_configuration,
                                                       layout_configuration.ammo_configuration))

    # Adding ammo to the pool
    base_results.pickups.extend(add_ammo(resource_database,
                                         layout_configuration.ammo_configuration))
    try:
        layout_configuration.game.generator.item_pool_creator(
            base_results, layout_configuration, resource_database, base_patches, rng,
        )
    except MissingRng as e:
        if rng_required:
            raise e

    return base_results
Exemple #3
0
def add_artifacts(
    resource_database: ResourceDatabase,
    mode: LayoutArtifactMode,
    artifact_minimum_progression: int,
) -> PoolResults:
    """
    :param resource_database:
    :param mode
    :param artifact_minimum_progression
    :return:
    """
    item_pool: List[PickupEntry] = []
    initial_resources = ResourceCollection.with_database(resource_database)

    artifacts_to_place = mode.value

    for i in range(artifacts_to_place):
        item_pool.append(
            pickup_creator.create_artifact(i, artifact_minimum_progression,
                                           resource_database))

    first_automatic_artifact = artifacts_to_place

    for automatic_artifact in range(first_automatic_artifact, 12):
        initial_resources.add_resource_gain(
            pickup_creator.create_artifact(automatic_artifact,
                                           artifact_minimum_progression,
                                           resource_database).all_resources, )

    return PoolResults(item_pool, {}, initial_resources)
Exemple #4
0
def calculate_pool_results(
    layout_configuration: BaseConfiguration,
    resource_database: ResourceDatabase,
) -> PoolResults:
    """
    Creates a PoolResults with all starting items and pickups in fixed locations, as well as a list of
    pickups we should shuffle.
    :param layout_configuration:
    :param resource_database:
    :return:
    """
    base_results = PoolResults([], {}, {})

    # Adding major items to the pool
    _extend_pool_results(
        base_results,
        add_major_items(resource_database,
                        layout_configuration.major_items_configuration,
                        layout_configuration.ammo_configuration))

    # Adding ammo to the pool
    base_results.pickups.extend(
        add_ammo(
            resource_database, layout_configuration.ammo_configuration,
            layout_configuration.major_items_configuration.
            calculate_provided_ammo()))

    _GAME_SPECIFIC[layout_configuration.game](base_results,
                                              layout_configuration,
                                              resource_database)

    return base_results
Exemple #5
0
def add_artifacts(resource_database: ResourceDatabase,
                     ) -> PoolResults:
    """
    :param resource_database:
    :return:
    """
    item_pool: List[PickupEntry] = []

    for i in range(12):
        item_pool.append(pickup_creator.create_artifact(i, resource_database))

    return PoolResults(item_pool, {}, {})
def add_dark_temple_keys(resource_database: ResourceDatabase, ) -> PoolResults:
    """
    :param resource_database:
    :return:
    """
    item_pool: List[PickupEntry] = []

    for temple_index in range(3):
        for i in range(3):
            item_pool.append(
                create_dark_temple_key(i, temple_index, resource_database))

    return PoolResults(item_pool, {}, {})
Exemple #7
0
def add_energy_cells(resource_database: ResourceDatabase, ) -> PoolResults:
    """
    :param resource_database:
    :return:
    """
    item_pool: List[PickupEntry] = []

    for i in range(9):
        item_pool.append(
            pickup_creator.create_energy_cell(i, resource_database))

    return PoolResults(item_pool, {},
                       ResourceCollection.with_database(resource_database))
Exemple #8
0
def calculate_pool_results(
    layout_configuration: EchoesConfiguration,
    resource_database: ResourceDatabase,
) -> PoolResults:
    """
    Creates a PoolResults with all starting items and pickups in fixed locations, as well as a list of
    pickups we should shuffle.
    :param layout_configuration:
    :param resource_database:
    :return:
    """
    base_results = PoolResults([], {}, {})

    # Adding major items to the pool
    _extend_pool_results(
        base_results,
        add_major_items(resource_database,
                        layout_configuration.major_items_configuration,
                        layout_configuration.ammo_configuration))

    # Adding ammo to the pool
    base_results.pickups.extend(
        add_ammo(
            resource_database, layout_configuration.ammo_configuration,
            layout_configuration.major_items_configuration.
            calculate_provided_ammo()))

    if layout_configuration.game == RandovaniaGame.PRIME2:
        # Adding Dark Temple Keys to pool
        _extend_pool_results(base_results,
                             add_dark_temple_keys(resource_database))

        # Adding Sky Temple Keys to pool
        _extend_pool_results(
            base_results,
            add_sky_temple_key_distribution_logic(
                resource_database, layout_configuration.sky_temple_keys))

    elif layout_configuration.game == RandovaniaGame.PRIME3:
        # Adding Energy Cells to pool
        _extend_pool_results(base_results, add_energy_cells(resource_database))

    elif layout_configuration.game == RandovaniaGame.PRIME1:
        _extend_pool_results(base_results, add_artifacts(resource_database))

    return base_results
Exemple #9
0
def add_major_items(
    resource_database: ResourceDatabase,
    major_items_configuration: MajorItemsConfiguration,
    ammo_configuration: AmmoConfiguration,
) -> PoolResults:
    """

    :param resource_database:
    :param major_items_configuration:
    :param ammo_configuration:
    :return:
    """

    item_pool: List[PickupEntry] = []
    new_assignment: Dict[PickupIndex, PickupEntry] = {}
    initial_resources: CurrentResources = {}

    for item, state in major_items_configuration.items_state.items():
        if len(item.ammo_index) != len(state.included_ammo):
            raise InvalidConfiguration(
                "Item {0.name} uses {0.ammo_index} as ammo, but there's only {1} values in included_ammo"
                .format(item, len(state.included_ammo)))

        ammo, locked_ammo = _find_ammo_for(item.ammo_index, ammo_configuration)

        if state.include_copy_in_original_location:
            if item.original_index is None:
                raise InvalidConfiguration(
                    "Item {0.name} does not exist in the original game, cannot use state {1}"
                    .format(item, state), )
            new_assignment[item.original_index] = create_major_item(
                item, state, True, resource_database, ammo, locked_ammo)

        for _ in range(state.num_shuffled_pickups):
            item_pool.append(
                create_major_item(item, state, True, resource_database, ammo,
                                  locked_ammo))

        for _ in range(state.num_included_in_starting_items):
            add_resource_gain_to_current_resources(
                create_major_item(item, state, False, resource_database, ammo,
                                  locked_ammo).all_resources,
                initial_resources)

    return PoolResults(item_pool, new_assignment, initial_resources)
Exemple #10
0
def add_sky_temple_key_distribution_logic(
    resource_database: ResourceDatabase,
    mode: LayoutSkyTempleKeyMode,
) -> PoolResults:
    """
    Adds the given Sky Temple Keys to the item pool
    :param resource_database:
    :param mode:
    :return:
    """

    item_pool: List[PickupEntry] = []
    new_assignment: Dict[PickupIndex, PickupEntry] = {}
    initial_resources: CurrentResources = {}

    if mode == LayoutSkyTempleKeyMode.ALL_BOSSES or mode == LayoutSkyTempleKeyMode.ALL_GUARDIANS:
        locations_to_place = _GUARDIAN_INDICES[:]
        if mode == LayoutSkyTempleKeyMode.ALL_BOSSES:
            locations_to_place += _SUB_GUARDIAN_INDICES

        for key_number, location in enumerate(locations_to_place):
            new_assignment[location] = create_sky_temple_key(
                key_number, resource_database)
        first_automatic_key = len(locations_to_place)

    else:
        keys_to_place = mode.value
        if not isinstance(keys_to_place, int):
            raise InvalidConfiguration(
                "Unknown Sky Temple Key mode: {}".format(mode))

        for key_number in range(keys_to_place):
            item_pool.append(
                create_sky_temple_key(key_number, resource_database))
        first_automatic_key = keys_to_place

    for automatic_key_number in range(first_automatic_key, 9):
        add_resource_gain_to_current_resources(
            create_sky_temple_key(automatic_key_number,
                                  resource_database).all_resources,
            initial_resources)

    return PoolResults(item_pool, new_assignment, initial_resources)
Exemple #11
0
def pool_creator(results: PoolResults, configuration: BaseConfiguration,
                 db: ResourceDatabase, base_patches: GamePatches,
                 rng: Random) -> None:
    assert isinstance(configuration, CSConfiguration)
    if rng is None:
        raise MissingRng("Pool Creator")
    if base_patches is None:
        return

    def get_valid_indices(indices):
        return [p for p in indices if p not in results.assignment.keys()]

    def get_valid_pickups(pickups):
        pickup_iter = lambda w: (p for p in results.pickups if p.name == w)
        return [
            next(pickup_iter(w)) for w in pickups
            if next(pickup_iter(w), None) is not None
        ]

    # puppies
    if not configuration.puppies_anywhere:
        puppy_indices = get_valid_indices(PUPPY_INDICES)
        rng.shuffle(puppy_indices)
        puppies: list[PickupEntry] = list(
            filter(lambda p: p.item_category.name == "puppies",
                   results.pickups))
        for p in puppies:
            results.pickups.remove(p)
            results.assignment[puppy_indices.pop()] = p

    # weapon to break blocks in first cave (do it this way to ensure a particular distribution chance)
    if base_patches.starting_location.area_name in {
            "Start Point", "First Cave", "Hermit Gunsmith"
    }:
        sn_weapons = list(SN_WEAPONS)

        bubble_sn = db.get_by_type_and_index(ResourceType.TRICK, "SNBubbler")
        missile_sn = db.get_by_type_and_index(ResourceType.TRICK, "SNMissiles")

        if configuration.trick_level.level_for_trick(bubble_sn).is_enabled:
            sn_weapons.append("Bubbler")
        if configuration.trick_level.level_for_trick(missile_sn).is_enabled:
            sn_weapons.extend({
                "Missile Launcher", "Super Missile Launcher",
                "Progressive Missile Launcher"
            })

        sn_weapons = get_valid_pickups(sn_weapons)

        first_cave_indices = get_valid_indices(FIRST_CAVE_INDICES)
        if first_cave_indices and sn_weapons:
            index = rng.choice(first_cave_indices)
            weapon = rng.choice(sn_weapons)

            results.pickups.remove(weapon)
            results.assignment[index] = weapon

    # strong weapon and life capsule in camp
    if base_patches.starting_location.area_name == "Camp":
        strong_weapons = get_valid_pickups(STRONG_WEAPONS)
        life_capsules = get_valid_pickups(["5HP Life Capsule"])
        camp_indices = get_valid_indices(CAMP_INDICES)

        rng.shuffle(camp_indices)

        if camp_indices and strong_weapons:
            results.assignment[camp_indices.pop()] = rng.choice(strong_weapons)
        if camp_indices and life_capsules:
            results.assignment[camp_indices.pop()] = rng.choice(life_capsules)