def run_filler( configuration: LayoutConfiguration, game: GameDescription, item_pool: List[PickupEntry], patches: GamePatches, rng: Random, status_update: Callable[[str], None], ) -> Tuple[GamePatches, List[PickupEntry]]: """ Runs the filler logic for the given configuration and item pool. Returns a GamePatches with progression items and hints assigned, along with all items in the pool that weren't assigned. :param configuration: :param game: :param item_pool: :param patches: :param rng: :param status_update: :return: """ major_items, expansions = _split_expansions(item_pool) rng.shuffle(major_items) rng.shuffle(expansions) major_configuration = configuration.major_items_configuration new_game, state = bootstrap.logic_bootstrap(configuration, game, patches) new_game.patch_requirements(state.resources, configuration.damage_strictness.value) filler_patches = retcon_playthrough_filler( new_game, state, major_items, rng, configuration=FillerConfiguration( randomization_mode=configuration.available_locations. randomization_mode, minimum_random_starting_items=major_configuration. minimum_random_starting_items, maximum_random_starting_items=major_configuration. maximum_random_starting_items, indices_to_exclude=configuration.available_locations. excluded_indices, ), status_update=status_update) # Since we haven't added expansions yet, these hints will always be for items added by the filler. full_hints_patches = fill_unassigned_hints(filler_patches, game.world_list, rng) if configuration.hints.item_hints: result = add_hints_precision(full_hints_patches, rng) else: result = replace_hints_without_precision_with_jokes(full_hints_patches) return result, major_items + expansions
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 new_game, state = logic_bootstrap(layout_configuration, game, patches) new_game.simplify_connections(state.resources) filler_patches = retcon.retcon_playthrough_filler(new_game, state, tuple(available_pickups), rng, 0, 0, status_update) assert filler_patches == patches
def test_retcon_filler_integration(default_layout_configuration): layout_configuration = default_layout_configuration rng = Random("fixed-seed!") status_update = MagicMock() game = default_database.game_description_for(layout_configuration.game) patches = game.create_game_patches() available_pickups = game.pickup_database.all_useful_pickups new_game, state = logic_bootstrap(layout_configuration, game, patches) new_game.patch_requirements(state.resources, layout_configuration.damage_strictness.value) filler_patches = retcon.retcon_playthrough_filler( new_game, state, tuple(available_pickups), rng, FillerConfiguration( randomization_mode=RandomizationMode.FULL, minimum_random_starting_items=0, maximum_random_starting_items=0, indices_to_exclude=frozenset(), ), status_update) assert filler_patches == patches
def run_filler(rng: Random, player_pools: Dict[int, PlayerPool], status_update: Callable[[str], None], ) -> FillerResults: """ Runs the filler logic for the given configuration and item pool. Returns a GamePatches with progression items and hints assigned, along with all items in the pool that weren't assigned. :param player_pools: :param rng: :param status_update: :return: """ player_states = [] player_expansions: Dict[int, List[PickupEntry]] = {} for index, pool in player_pools.items(): status_update(f"Creating state for player {index + 1}") major_items, player_expansions[index] = _split_expansions(pool.pickups) rng.shuffle(major_items) rng.shuffle(player_expansions[index]) new_game, state = bootstrap.logic_bootstrap(pool.configuration, pool.game, pool.patches) new_game.patch_requirements(state.resources, pool.configuration.damage_strictness.value) major_configuration = pool.configuration.major_items_configuration player_states.append(PlayerState( index=index, game=new_game, initial_state=state, pickups_left=major_items, configuration=FillerConfiguration( randomization_mode=pool.configuration.available_locations.randomization_mode, minimum_random_starting_items=major_configuration.minimum_random_starting_items, maximum_random_starting_items=major_configuration.maximum_random_starting_items, indices_to_exclude=pool.configuration.available_locations.excluded_indices, ), )) try: filler_result, actions_log = retcon_playthrough_filler(rng, player_states, status_update=status_update) except UnableToGenerate as e: message = "{}\n\n{}".format( str(e), "\n\n".join( "#### Player {}\n{}".format(player.index + 1, player.current_state_report()) for player in player_states ), ) debug.debug_print(message) raise UnableToGenerate(message) from e results = {} for player_state, patches in filler_result.items(): game = player_state.game if game.game == RandovaniaGame.PRIME2: # Since we haven't added expansions yet, these hints will always be for items added by the filler. full_hints_patches = fill_unassigned_hints(patches, game.world_list, rng, player_state.scan_asset_initial_pickups) if player_pools[player_state.index].configuration.hints.item_hints: result = add_hints_precision(player_state, full_hints_patches, rng) else: result = replace_hints_without_precision_with_jokes(full_hints_patches) else: result = patches results[player_state.index] = FillerPlayerResult( game=game, patches=result, unassigned_pickups=player_state.pickups_left + player_expansions[player_state.index], ) return FillerResults(results, actions_log)
async def run_filler( rng: Random, player_pools: list[PlayerPool], status_update: Callable[[str], None], ) -> FillerResults: """ Runs the filler logic for the given configuration and item pool. Returns a GamePatches with progression items and hints assigned, along with all items in the pool that weren't assigned. :param player_pools: :param rng: :param status_update: :return: """ player_states = [] player_expansions: dict[int, list[PickupEntry]] = {} for index, pool in enumerate(player_pools): config = pool.configuration status_update(f"Creating state for player {index + 1}") if config.multi_pickup_placement: major_items, player_expansions[index] = list(pool.pickups), [] else: major_items, player_expansions[index] = _split_expansions( pool.pickups) rng.shuffle(major_items) rng.shuffle(player_expansions[index]) new_game, state = pool.game_generator.bootstrap.logic_bootstrap( config, pool.game, pool.patches) major_configuration = config.major_items_configuration player_states.append( PlayerState( index=index, game=new_game, initial_state=state, pickups_left=major_items, configuration=FillerConfiguration( randomization_mode=config.available_locations. randomization_mode, minimum_random_starting_items=major_configuration. minimum_random_starting_items, maximum_random_starting_items=major_configuration. maximum_random_starting_items, indices_to_exclude=config.available_locations. excluded_indices, multi_pickup_placement=config.multi_pickup_placement, multi_pickup_new_weighting=config. multi_pickup_new_weighting, logical_resource_action=config.logical_resource_action, first_progression_must_be_local=config. first_progression_must_be_local, minimum_available_locations_for_hint_placement=config. minimum_available_locations_for_hint_placement, minimum_location_weight_for_hint_placement=config. minimum_location_weight_for_hint_placement, ), )) try: filler_result, actions_log = retcon_playthrough_filler( rng, player_states, status_update=status_update) except UnableToGenerate as e: message = "{}\n\n{}".format( str(e), "\n\n".join( "#### Player {}\n{}".format(player.index + 1, player.current_state_report()) for player in player_states), ) debug.debug_print(message) raise UnableToGenerate(message) from e results = {} for player_state, patches in filler_result.items(): player_pool = player_pools[player_state.index] hint_distributor = player_pool.game_generator.hint_distributor results[player_state.index] = FillerPlayerResult( game=player_state.game, patches=await hint_distributor.assign_post_filler_hints(patches, rng, player_pool, player_state), unassigned_pickups=player_state.pickups_left + player_expansions[player_state.index], ) return FillerResults(results, actions_log)
def run_filler( rng: Random, player_pools: Dict[int, PlayerPool], status_update: Callable[[str], None], ) -> FillerResults: """ Runs the filler logic for the given configuration and item pool. Returns a GamePatches with progression items and hints assigned, along with all items in the pool that weren't assigned. :param player_pools: :param rng: :param status_update: :return: """ player_states = {} player_expansions = {} for index, pool in player_pools.items(): major_items, player_expansions[index] = _split_expansions(pool.pickups) rng.shuffle(major_items) rng.shuffle(player_expansions[index]) new_game, state = bootstrap.logic_bootstrap(pool.configuration, pool.game, pool.patches) new_game.patch_requirements(state.resources, pool.configuration.damage_strictness.value) major_configuration = pool.configuration.major_items_configuration player_states[index] = PlayerState( game=new_game, initial_state=state, pickups_left=major_items, configuration=FillerConfiguration( randomization_mode=pool.configuration.available_locations. randomization_mode, minimum_random_starting_items=major_configuration. minimum_random_starting_items, maximum_random_starting_items=major_configuration. maximum_random_starting_items, indices_to_exclude=pool.configuration.available_locations. excluded_indices, ), ) filler_result, actions_log = retcon_playthrough_filler( rng, player_states, status_update=status_update) results = {} for index, patches in filler_result.items(): game = player_pools[index].game # Since we haven't added expansions yet, these hints will always be for items added by the filler. full_hints_patches = fill_unassigned_hints(patches, game.world_list, rng) if player_pools[index].configuration.hints.item_hints: result = add_hints_precision(full_hints_patches, rng) else: result = replace_hints_without_precision_with_jokes( full_hints_patches) results[index] = FillerPlayerResult( game=game, patches=result, unassigned_pickups=player_states[index].pickups_left + player_expansions[index], ) return FillerResults(results, actions_log)