コード例 #1
0
    def fill_unassigned_hints(self, patches: GamePatches,
                              world_list: WorldList,
                              rng: Random,
                              scan_asset_initial_pickups: dict[NodeIdentifier, frozenset[PickupIndex]],
                              ) -> GamePatches:
        new_hints = copy.copy(patches.hints)

        # Get all LogbookAssets from the WorldList
        potential_hint_locations: set[NodeIdentifier] = {
            world_list.identifier_for_node(node)
            for node in world_list.iterate_nodes()
            if isinstance(node, LogbookNode)
        }
        for logbook in potential_hint_locations:
            if logbook not in scan_asset_initial_pickups:
                scan_asset_initial_pickups[logbook] = frozenset()

        # But remove these that already have hints
        potential_hint_locations -= patches.hints.keys()

        # We try our best to not hint the same thing twice
        hinted_indices: set[PickupIndex] = {hint.target for hint in patches.hints.values() if hint.target is not None}

        # Get interesting items to place hints for
        possible_indices: set[PickupIndex] = {
            index
            for index, target in patches.pickup_assignment.items()
            if self.interesting_pickup_to_hint(target.pickup)
        }
        possible_indices -= hinted_indices

        debug.debug_print("fill_unassigned_hints had {} decent indices for {} hint locations".format(
            len(possible_indices), len(potential_hint_locations)))

        if debug.debug_level() > 1:
            print(f"> Num pickups per asset:")
            for asset, pickups in scan_asset_initial_pickups.items():
                print(f"* {asset}: {len(pickups)} pickups")
            print("> Done.")

        all_pickup_indices = [
            node.pickup_index
            for node in world_list.iterate_nodes()
            if isinstance(node, PickupNode)
        ]
        rng.shuffle(all_pickup_indices)

        # If there isn't enough indices, use unhinted non-majors placed by generator
        if (num_indices_needed := len(potential_hint_locations) - len(possible_indices)) > 0:
            potential_indices = [
                index for index in all_pickup_indices
                if index not in possible_indices and index not in hinted_indices
            ]
            debug.debug_print(
                f"Had only {len(possible_indices)} hintable indices, but needed {len(potential_hint_locations)}."
                f" Found {len(potential_indices)} less desirable locations.")
            possible_indices |= set(potential_indices[:num_indices_needed])
コード例 #2
0
def _assign_remaining_items(
    rng: Random,
    world_list: WorldList,
    pickup_assignment: PickupAssignment,
    remaining_items: List[PickupEntry],
    randomization_mode: RandomizationMode,
) -> PickupAssignment:
    """

    :param rng:
    :param world_list:
    :param pickup_assignment:
    :param remaining_items:
    :return:
    """

    unassigned_pickup_nodes = list(
        filter_unassigned_pickup_nodes(world_list.iterate_nodes(),
                                       pickup_assignment))

    num_etm = len(unassigned_pickup_nodes) - len(remaining_items)
    if num_etm < 0:
        raise InvalidConfiguration(
            "Received {} remaining items, but there's only {} unassigned pickups"
            .format(len(remaining_items), len(unassigned_pickup_nodes)))

    # Shuffle the items to add and the spots to choose from
    rng.shuffle(remaining_items)
    rng.shuffle(unassigned_pickup_nodes)

    assignment = {}

    if randomization_mode is RandomizationMode.MAJOR_MINOR_SPLIT:
        remaining_majors = [
            item for item in remaining_items if not item.is_expansion
        ] + ([None] * num_etm)
        unassigned_major_locations = [
            pickup_node for pickup_node in unassigned_pickup_nodes
            if pickup_node.major_location
        ]

        for pickup_node, item in zip(unassigned_major_locations,
                                     remaining_majors):
            if item is not None:
                assignment[pickup_node.pickup_index] = item
                remaining_items.remove(item)
            unassigned_pickup_nodes.remove(pickup_node)

    assignment.update({
        pickup_node.pickup_index: item
        for pickup_node, item in zip(unassigned_pickup_nodes, remaining_items)
    })
    return assignment
コード例 #3
0
ファイル: hints.py プロジェクト: randovania/randovania
def hide_patches_hints(world_list: WorldList) -> list:
    """
    Creates the string patches entries that changes the Lore scans in the game
    completely useless text.
    :return:
    """

    return [
        create_simple_logbook_hint(logbook_node.string_asset_id,
                                   "Some item was placed somewhere.")
        for logbook_node in world_list.iterate_nodes()
        if isinstance(logbook_node, LogbookNode)
    ]
コード例 #4
0
def export_all_indices(
    patches: GamePatches,
    useless_target: PickupTarget,
    world_list: WorldList,
    rng: Random,
    model_style: PickupModelStyle,
    data_source: PickupModelDataSource,
    exporter: PickupExporter,
    visual_etm: PickupEntry,
) -> List[ExportedPickupDetails]:
    """
    Creates the patcher data for all pickups in the game
    :param patches:
    :param useless_target:
    :param world_list:
    :param rng:
    :param model_style:
    :param data_source:
    :param exporter:
    :param visual_etm:
    :return:
    """
    pickup_assignment = patches.pickup_assignment

    pickup_list = list(pickup_assignment.values())
    rng.shuffle(pickup_list)

    indices = sorted(node.pickup_index for node in world_list.iterate_nodes()
                     if isinstance(node, PickupNode))

    pickups = [
        exporter.export(
            index,
            pickup_assignment.get(index, useless_target),
            _get_visual_model(i, pickup_list, data_source, visual_etm),
            model_style,
        ) for i, index in enumerate(indices)
    ]

    return pickups
コード例 #5
0
ファイル: hints.py プロジェクト: randovania/randovania
def create_patches_hints(
    all_patches: Dict[int, GamePatches],
    players_config: PlayersConfiguration,
    world_list: WorldList,
    namer: HintNamer,
    rng: Random,
) -> list:
    exporter = HintExporter(namer, rng, JOKE_HINTS)

    hints_for_asset: dict[NodeIdentifier, str] = {}
    for identifier, hint in all_patches[
            players_config.player_index].hints.items():
        hints_for_asset[identifier] = exporter.create_message_for_hint(
            hint, all_patches, players_config, True)

    return [
        create_simple_logbook_hint(
            logbook_node.string_asset_id,
            hints_for_asset.get(world_list.identifier_for_node(logbook_node),
                                "Someone forgot to leave a message."),
        ) for logbook_node in world_list.iterate_nodes()
        if isinstance(logbook_node, LogbookNode)
    ]
コード例 #6
0
def pickup_index_to_node(world_list: WorldList, index: PickupIndex) -> PickupNode:
    for node in world_list.iterate_nodes():
        if isinstance(node, PickupNode) and node.pickup_index == index:
            return node
    raise ValueError(f"PickupNode with {index} not found.")
コード例 #7
0
def _get_nodes_by_teleporter_id(
        world_list: WorldList) -> Iterator[TeleporterNode]:
    for node in world_list.iterate_nodes():
        if isinstance(node, TeleporterNode) and node.editable:
            yield node