def _create_elevators_field(patches: GamePatches,
                            game: GameDescription) -> list:
    """
    Creates the elevator entries in the patcher file
    :param patches:
    :param game:
    :return:
    """
    world_list = game.world_list

    elevator_fields = []

    for node, connection in patches.all_elevator_connections():
        elevator_fields.append({
            "instance_id":
            node.extra["teleporter_instance_id"],
            "origin_location":
            _area_identifier_to_json(game.world_list,
                                     node.identifier.area_location),
            "target_location":
            _area_identifier_to_json(game.world_list, connection),
            "room_name":
            _pretty_name_for_elevator(game.game, world_list, node, connection)
        })

    num_teleporter_nodes = sum(
        1 for _ in _get_nodes_by_teleporter_id(world_list))
    if len(elevator_fields) != num_teleporter_nodes:
        raise ValueError("Invalid elevator count. Expected {}, got {}.".format(
            num_teleporter_nodes, len(elevator_fields)))

    return elevator_fields
def serialize_single(player_index: int, num_players: int,
                     patches: GamePatches) -> dict:
    """
    Encodes a given GamePatches into a JSON-serializable dict.
    :param player_index:
    :param num_players:
    :param patches:
    :return:
    """
    game = filtered_database.game_description_for_layout(patches.configuration)
    world_list = game.world_list

    dock_weakness_to_type = {}
    for dock_type, weaknesses in game.dock_weakness_database.weaknesses.items(
    ):
        for weakness in weaknesses.values():
            dock_weakness_to_type[weakness] = dock_type

    result = {
        # This field helps schema migrations, if nothing else
        "game": patches.configuration.game.value,
        "starting_location": patches.starting_location.as_string,
        "starting_items": {
            resource_info.long_name: quantity
            for resource_info, quantity in
            patches.starting_items.as_resource_gain()
        },
        "teleporters": {
            source.identifier.as_string: connection.as_string
            for source, connection in patches.all_elevator_connections()
        },
        "dock_weakness": {
            dock.identifier.as_string: {
                "type": dock_weakness_to_type[weakness].short_name,
                "name": weakness.name,
            }
            for dock, weakness in patches.all_dock_weaknesses()
        },
        "configurable_nodes": {
            identifier.as_string: data_writer.write_requirement(requirement)
            for identifier, requirement in patches.configurable_nodes.items()
        },
        "locations": {
            key: value
            for key, value in _pickup_assignment_to_item_locations(
                world_list, patches.pickup_assignment, num_players).items()
        },
        "hints": {
            identifier.as_string: hint.as_json
            for identifier, hint in patches.hints.items()
        }
    }
    return result