Esempio n. 1
0
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
Esempio n. 4
0
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)
Esempio n. 5
0
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)
Esempio n. 6
0
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)