Привеет! Слушайте, добавить в генератор карт: «import random

def generate_voxel_layer(width, height, filled=True):
    layer = {}
    for y in range(height):
        if filled:
            row = '1' * width
        else:
            row = '0' * width
        layer[f"Y{y}"] = f"f{row}"
    return layer

def generate_voxels(width, height, depth):
    voxels = {'Solid': {}, 'Portal0': {}, 'Portal1': {}, 'Portal2': {}}
    for voxel_type in voxels:
        voxels[voxel_type] = {}
        for z in range(depth + 1):
            voxels[voxel_type][f"Z{z}"] = {}
            if z == 0 or z == depth:
                voxels[voxel_type][f"Z{z}"] = generate_voxel_layer(width, height, filled=True)
            else:
                layer = {}
                for y in range(height):
                    row = ''
                    for x in range(width):
                        if x == 0 or x == width - 1 or y == 0 or y == height - 1:
                            row += '1'  # Стены
                        else:
                            row += '0'  # Пустое пространство
                    layer[f"Y{y}"] = f"f{row}"
                voxels[voxel_type][f"Z{z}"] = layer
    return voxels

def generate_items(width, height, depth):
    items = []
    current_index = 0
    occupied_positions = set()  # Множество для хранения занятых позиций

    # Позиции дверей (на уровне z = 1)
    # Выбираем случайную стену для каждой двери
    walls = ['left', 'right', 'top', 'bottom']
    entry_wall = random.choice(walls)
    exit_wall = random.choice([w for w in walls if w != entry_wall])

    # Функция для получения позиции и углов двери в зависимости от стены
    def get_door_position(wall):
        if wall == 'left':
            x = 1
            y = random.randint(1, height - 2)
            angles = "-90 180 0"
        elif wall == 'right':
            x = width - 2
            y = random.randint(1, height - 2)
            angles = "-90 0 0"
        elif wall == 'top':
            x = random.randint(1, width - 2)
            y = height - 2
            angles = "-90 90 0"
        elif wall == 'bottom':
            x = random.randint(1, width - 2)
            y = 1
            angles = "-90 -90 0"
        return x, y, angles

    # Получаем позиции и углы дверей с проверкой на минимальное расстояние
    max_attempts = 10
    for _ in range(max_attempts):
        entry_x, entry_y, entry_angles = get_door_position(entry_wall)
        exit_x, exit_y, exit_angles = get_door_position(exit_wall)
        # Проверяем минимальное расстояние между дверями
        if abs(entry_x - exit_x) + abs(entry_y - exit_y) >= min(width, height) // 2:
            break
    else:
        pass

    entry_z = exit_z = 1  # Уровень пола

    # Добавляем позиции дверей в занятые позиции
    occupied_positions.update({(entry_x, entry_y, entry_z), (exit_x, exit_y, exit_z)})

    # Входная дверь
    entry_door = {
        "Index": str(current_index),
        "Type": "ITEM_ENTRY_DOOR",
        "Deletable": "0",
        "VoxelPos": f"{entry_x} {entry_y} {entry_z}",
        "LocalPos": "0 0 0",
        "Angles": entry_angles,
        "ITEM_PROPERTY_DOOR_IS_COOP": "0",
        "Facing": "0 0 0",
        "ConnectionVisiblity": "0",
        "DoorInstanceID": "6.000000",
        "Enabled": "1"
    }
    items.append(entry_door)
    entry_door_index = current_index
    current_index += 1

    # Кооперативная входная дверь
    coop_entry_door = {
        "Index": str(current_index),
        "Type": "ITEM_COOP_ENTRY_DOOR",
        "Deletable": "0",
        "VoxelPos": f"{entry_x} {entry_y} {entry_z}",
        "LocalPos": "0 0 0",
        "Angles": entry_angles,
        "ITEM_PROPERTY_DOOR_IS_COOP": "0",
        "Facing": "0 0 0",
        "ConnectionVisiblity": "0",
        "DoorInstanceID": "0.000000",
        "Enabled": "0"
    }
    items.append(coop_entry_door)
    coop_entry_door_index = current_index
    current_index += 1

    # Выходная дверь
    exit_door = {
        "Index": str(current_index),
        "Type": "ITEM_EXIT_DOOR",
        "Deletable": "0",
        "VoxelPos": f"{exit_x} {exit_y} {exit_z}",
        "LocalPos": "0 0 0",
        "Angles": exit_angles,
        "ITEM_PROPERTY_CONNECTION_COUNT": "1",
        "ITEM_PROPERTY_START_OPEN": "0",
        "ITEM_PROPERTY_DOOR_IS_COOP": "0",
        "Facing": "0 0 0",
        "ConnectionVisiblity": "0",
        "DoorInstanceID": "1.000000",
        "Enabled": "1"
    }
    items.append(exit_door)
    exit_door_index = current_index
    current_index += 1

    # Кооперативная выходная дверь
    coop_exit_door = {
        "Index": str(current_index),
        "Type": "ITEM_COOP_EXIT_DOOR",
        "Deletable": "0",
        "VoxelPos": f"{exit_x} {exit_y} {exit_z}",
        "LocalPos": "0 0 0",
        "Angles": exit_angles,
        "ITEM_PROPERTY_CONNECTION_COUNT": "0",
        "ITEM_PROPERTY_DOOR_IS_COOP": "0",
        "ITEM_PROPERTY_COOP_EXIT_STARTS_LOCKED": "1",
        "Facing": "0 0 0",
        "ConnectionVisiblity": "0",
        "DoorInstanceID": "3.000000",
        "Enabled": "0"
    }
    items.append(coop_exit_door)
    coop_exit_door_index = current_index
    current_index += 1

    # Кнопка (на случайной позиции в комнате)
    while True:
        button_x = random.randint(2, width - 3)
        button_y = random.randint(2, height - 3)
        button_z = 1
        if (button_x, button_y, button_z) not in occupied_positions:
            break
    occupied_positions.add((button_x, button_y, button_z))
    button_item = {
        "Index": str(current_index),
        "Type": "ITEM_BUTTON_FLOOR",
        "Deletable": "1",
        "VoxelPos": f"{button_x} {button_y} {button_z}",
        "LocalPos": "0 0 0",
        "Angles": "0 0 0",
        "ITEM_PROPERTY_BUTTON_TYPE": "0",
        "Facing": "0 0 0",
        "ConnectionVisiblity": "0"
    }
    items.append(button_item)
    button_index = current_index
    current_index += 1

    # Куб (рядом с кнопкой)
    cube_x = button_x
    cube_y_options = [button_y - 1, button_y + 1]
    random.shuffle(cube_y_options)
    for cube_y_candidate in cube_y_options:
        if 1 <= cube_y_candidate < height - 1:
            cube_y = cube_y_candidate
            if (cube_x, cube_y, 1) not in occupied_positions:
                break
    else:
        # Если все позиции заняты, выберем случайную
        while True:
            cube_x = random.randint(2, width - 3)
            cube_y = random.randint(2, height - 3)
            if (cube_x, cube_y, 1) not in occupied_positions:
                break
    cube_z = 1
    occupied_positions.add((cube_x, cube_y, cube_z))
    cube_item = {
        "Index": str(current_index),
        "Type": "ITEM_CUBE",
        "Deletable": "1",
        "VoxelPos": f"{cube_x} {cube_y} {cube_z}",
        "LocalPos": "0 0 0",
        "Angles": "0 0 0",
        "ITEM_PROPERTY_CUBE_TYPE": "0",
        "ITEM_PROPERTY_DROPPER_ENABLED": "1",
        "ITEM_PROPERTY_AUTO_DROP_CUBE": "1",
        "ITEM_PROPERTY_AUTO_RESPAWN_CUBE": "1",
        "Facing": "0 0 0",
        "ConnectionVisiblity": "0"
    }
    items.append(cube_item)
    cube_index = current_index
    current_index += 1

    # Дроппер (на потолке над кубом)
    dropper_z = depth - 1  # Под потолком
    occupied_positions.add((cube_x, cube_y, dropper_z))
    dropper_item = {
        "Index": str(current_index),
        "Type": "ITEM_DROPPER_CUBE",
        "Deletable": "1",
        "VoxelPos": f"{cube_x} {cube_y} {dropper_z}",
        "LocalPos": "0 0 0",
        "Angles": "0 0 180",  # Ориентация вниз
        "ITEM_PROPERTY_CONNECTION_COUNT": "0",
        "ITEM_PROPERTY_CUBE_TYPE": "0",
        "ITEM_PROPERTY_DROPPER_ENABLED": "1",
        "ITEM_PROPERTY_AUTO_DROP_CUBE": "1",
        "ITEM_PROPERTY_AUTO_RESPAWN_CUBE": "1",
        "Facing": "0 0 0",
        "ConnectionVisiblity": "0"
    }
    items.append(dropper_item)
    dropper_index = current_index
    current_index += 1

    # Добавляем позиции дроппера в занятые позиции
    occupied_positions.add((cube_x, cube_y, dropper_z))

    # Рандомное количество турелей
    num_turrets = random.randint(0, 3)
    for _ in range(num_turrets):
        attempts = 0
        while attempts < 10:
            turret_x = random.randint(2, width - 3)
            turret_y = random.randint(2, height - 3)
            turret_z = 1
            if (turret_x, turret_y, turret_z) not in occupied_positions:
                break
            attempts += 1
        else:
            continue  # Если не нашли свободное место, пропускаем турель
        occupied_positions.add((turret_x, turret_y, turret_z))
        turret_item = {
            "Index": str(current_index),
            "Type": "ITEM_TURRET",
            "Deletable": "1",
            "VoxelPos": f"{turret_x} {turret_y} {turret_z}",
            "LocalPos": "0 0 0",
            "Angles": "0 0 0",
            "Facing": f"0 {random.choice([0, 90, 180, 270])} 0",
            "ConnectionVisiblity": "0"
        }
        items.append(turret_item)
        current_index += 1

    return items, entry_door_index, coop_entry_door_index, exit_door_index, coop_exit_door_index, button_index, cube_index, dropper_index

def generate_connections(entry_door_index, coop_entry_door_index, exit_door_index, coop_exit_door_index, button_index, cube_index, dropper_index):
    connections = []

    # Соединяем входные двери
    connections.append({
        "Sender": str(entry_door_index),
        "Receiver": str(coop_entry_door_index),
        "Type": "CONNECTION_BARRIER_ANCHOR_TO_EXTENT"
    })

    # Соединяем выходные двери
    connections.append({
        "Sender": str(exit_door_index),
        "Receiver": str(coop_exit_door_index),
        "Type": "CONNECTION_BARRIER_ANCHOR_TO_EXTENT"
    })

    # Соединяем кнопку с выходной дверью
    connections.append({
        "Sender": str(button_index),
        "Receiver": str(exit_door_index),
        "Type": "CONNECTION_STANDARD"
    })

    # Соединяем куб с дроппером
    connections.append({
        "Sender": str(cube_index),
        "Receiver": str(dropper_index),
        "Type": "CONNECTION_BOX_DROPPER"
    })

    return connections

def generate_map():
    # Случайные размеры комнаты в диапазоне от 6 до 10
    width = random.randint(6, 10)
    height = random.randint(6, 10)
    depth = random.randint(3, 6)

    voxels = generate_voxels(width, height, depth)
    items_info = generate_items(width, height, depth)
    items = items_info[0]
    connections = generate_connections(*items_info[1:])

    map_data = {
        "AppID": "644",
        "Version": "14",
        "FileID": "0x0000000000000000",
        "Timestamp_Created": "0x0000000066A51551",
        "Timestamp_Modified": "0x0000000066A51551",
        "CompileTime": "15.000000",
        "Coop": "0",
        "Title": "Random Simple Map",
        "Description": "This is a randomly generated simple map.",
        "PreviewDirty": "1",
        "ChamberSize": f"{width} {height} {depth}",
        "Voxels": voxels,
        "Items": {
            "Item": items
        },
        "Connections": {
            "Connection": connections
        }
    }
    return map_data

def format_map_data(map_data):
    def format_item(item):
        return "\n".join([f'\t\t\t"{k}"\t\t"{v}"' for k, v in item.items()])

    def format_connection(connection):
        return "\n".join([f'\t\t\t"{k}"\t\t"{v}"' for k, v in connection.items()])

    formatted_map = ['"portal2_puzzle"', '{']
    for key, value in map_data.items():
        if key == "Voxels":
            formatted_map.append(f'\t"{key}"')
            formatted_map.append('\t{')
            for voxel_type, voxel_data in value.items():
                formatted_map.append(f'\t\t"{voxel_type}"')
                formatted_map.append('\t\t{')
                for z, z_data in voxel_data.items():
                    formatted_map.append(f'\t\t\t"{z}"')
                    formatted_map.append('\t\t\t{')
                    for y, y_data in z_data.items():
                        formatted_map.append(f'\t\t\t\t"{y}"\t\t"{y_data}"')
                    formatted_map.append('\t\t\t}')
                formatted_map.append('\t\t}')
            formatted_map.append('\t}')
        elif key == "Items":
            formatted_map.append(f'\t"{key}"')
            formatted_map.append('\t{')
            for item in value["Item"]:
                formatted_map.append('\t\t"Item"')
                formatted_map.append('\t\t{')
                formatted_map.append(format_item(item))
                formatted_map.append('\t\t}')
            formatted_map.append('\t}')
        elif key == "Connections":
            formatted_map.append(f'\t"{key}"')
            formatted_map.append('\t{')
            for connection in value["Connection"]:
                formatted_map.append('\t\t"Connection"')
                formatted_map.append('\t\t{')
                formatted_map.append(format_connection(connection))
                formatted_map.append('\t\t}')
            formatted_map.append('\t}')
        else:
            formatted_map.append(f'\t"{key}"\t\t"{value}"')
    formatted_map.append('}')
    return "\n".join(formatted_map)

if __name__ == "__main__":
    map_data = generate_map()
    formatted_map = format_map_data(map_data)
    print(formatted_map)», чуть больше хаотичности для объектов. Кстати, ещё, добавьте освещение для карты, например: «"Item"
		{
			"Index"		"4"
			"Type"		"ITEM_OBSERVATION_ROOM"
			"Deletable"		"0"
			"VoxelPos"		"7 2 1"
			"LocalPos"		"0 0 0"
			"Angles"		"-90 0 0"
			"Facing"		"0 0 0"
			"ConnectionVisiblity"		"0"
		}», я надеюсь, вы понимаете, что это практически тоже самое, что и дверь (почти): смотрит ОТ стены, НО всегда, слушайте, занимает 2 клетки по x, и одну по y И никогда не может смотреть вверх или вниз.