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)
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
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)
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
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, {}, {})
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))
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
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)
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)
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)