```python
import argparse
import math
import random
from dataclasses import dataclass
from typing import List, Tuple

import matplotlib.pyplot as plt
import matplotlib.patches as patches
import networkx as nx


@dataclass
class Config:
    num_rooms: int = 20
    map_width: int = 200
    map_height: int = 200
    room_min_size: int = 5
    room_max_size: int = 20
    passageway_width: int = 3
    extra_connections_factor: float = 0.4
    max_attempts_multiplier: int = 10
    random_seed: int = None  # Установите целое число для воспроизводимых результатов


@dataclass
class Room:
    x: int
    y: int
    width: int
    height: int

    def center(self) -> Tuple[float, float]:
        """Вычислить координаты центра комнаты."""
        center_x = self.x + self.width / 2
        center_y = self.y + self.height / 2
        return center_x, center_y

    def intersects(self, other: 'Room') -> bool:
        """Проверить, пересекается ли эта комната с другой."""
        return (
            self.x < other.x + other.width and
            self.x + self.width > other.x and
            self.y < other.y + other.height and
            self.y + self.height > other.y
        )


class MapGenerator:
    def __init__(self, config: Config):
        self.config = config
        if config.random_seed is not None:
            random.seed(config.random_seed)

    def generate_rooms(self) -> List[Room]:
        """Генерировать неперекрывающиеся комнаты внутри границ карты."""
        rooms = []
        max_attempts = self.config.num_rooms * self.config.max_attempts_multiplier
        attempts = 0

        while len(rooms) < self.config.num_rooms and attempts < max_attempts:
            width = random.randint(
                self.config.room_min_size, self.config.room_max_size)
            height = random.randint(
                self.config.room_min_size, self.config.room_max_size)
            x = random.randint(0, self.config.map_width - width)
            y = random.randint(0, self.config.map_height - height)
            new_room = Room(x, y, width, height)

            if not any(new_room.intersects(other) for other in rooms):
                rooms.append(new_room)
            attempts += 1

        if len(rooms) < self.config.num_rooms:
            print(
                f"Warning: Only {len(rooms)} out of {self.config.num_rooms} rooms were placed "
                f"after {attempts} attempts."
            )
        return rooms

    def connect_rooms(self, rooms: List[Room]) -> nx.Graph:
        """Соединить комнаты с использованием MST и добавить дополнительные соединения на основе конфигурации."""
        G = nx.Graph()

        # Добавить узлы с позициями
        for idx, room in enumerate(rooms):
            G.add_node(idx, pos=room.center())

        # Добавить все возможные рёбра с евклидовым расстоянием как весом
        for i in range(len(rooms)):
            for j in range(i + 1, len(rooms)):
                pos_i = rooms[i].center()
                pos_j = rooms[j].center()
                distance = math.hypot(pos_i[0] - pos_j[0], pos_i[1] - pos_j[1])
                G.add_edge(i, j, weight=distance)

        # Вычислить Минимальное Остовное Дерево (MST)
        mst = nx.minimum_spanning_tree(G)

        # Определить количество дополнительных соединений
        extra_connections = int(
            self.config.extra_connections_factor * len(rooms))
        potential_extra = set(G.edges()) - set(mst.edges())

        if potential_extra:
            sorted_extra = sorted(
                potential_extra,
                key=lambda edge: G.edges[edge]['weight']
            )
            num_extra = min(extra_connections, len(sorted_extra))
            extra_edges = sorted_extra[:num_extra]
            mst.add_edges_from(extra_edges)

        return mst


class MapVisualizer:
    def __init__(self, config: Config):
        self.config = config

    def draw_map_2d(self, rooms: List[Room], connections: nx.Graph) -> None:
        """Отрисовать карту в 2D с использованием matplotlib."""
        fig, ax = plt.subplots(figsize=(15, 15))

        # Отрисовка комнат
        for idx, room in enumerate(rooms):
            rect = patches.Rectangle(
                (room.x, room.y),
                room.width,
                room.height,
                linewidth=1,
                edgecolor='black',
                facecolor='cyan',
                alpha=0.8
            )
            ax.add_patch(rect)

            cx, cy = room.center()
            ax.plot(cx, cy, 'ro')  # Красная точка в центре
            ax.text(
                cx, cy, str(idx + 1),
                color='white', ha='center', va='center',
                fontsize=8, fontweight='bold'
            )

        # Отрисовка коридоров как ортогональных коридоров
        for edge in connections.edges():
            self._draw_corridor_2d(ax, rooms[edge[0]], rooms[edge[1]])

        # Настройка графика
        ax.set_xlim(0, self.config.map_width)
        ax.set_ylim(0, self.config.map_height)
        ax.set_aspect('equal')
        ax.set_title(
            'Случайно сгенерированные комнаты с ортогональными коридорами (2D)', fontsize=16
        )
        ax.set_xlabel('X', fontsize=12)
        ax.set_ylabel('Y', fontsize=12)
        ax.grid(True, which='both', linestyle='--', linewidth=0.5, alpha=0.7)
        plt.show()

    def _draw_corridor_2d(self, ax, room_a: Room, room_b: Room) -> None:
        """Отрисовать ортогональный коридор между двумя комнатами в 2D."""
        ax_center = room_a.center()
        bx_center = room_b.center()

        horizontal_first = random.choice([True, False])

        if horizontal_first:
            intermediate_point = (bx_center[0], ax_center[1])
            self._draw_rectangle_corridor(
                ax,
                start=(ax_center[0], ax_center[1]),
                end=intermediate_point,
                orientation='horizontal'
            )
            self._draw_rectangle_corridor(
                ax,
                start=intermediate_point,
                end=bx_center,
                orientation='vertical'
            )
        else:
            intermediate_point = (ax_center[0], bx_center[1])
            self._draw_rectangle_corridor(
                ax,
                start=(ax_center[0], ax_center[1]),
                end=intermediate_point,
                orientation='vertical'
            )
            self._draw_rectangle_corridor(
                ax,
                start=intermediate_point,
                end=bx_center,
                orientation='horizontal'
            )

    def _draw_rectangle_corridor(self, ax, start: Tuple[float, float], end: Tuple[float, float], orientation: str) -> None:
        """Вспомогательный метод для отрисовки прямоугольного коридора."""
        if orientation == 'horizontal':
            corridor_length = abs(end[0] - start[0])
            corridor_x = min(start[0], end[0])
            corridor_y = start[1] - self.config.passageway_width / 2
            rect = patches.Rectangle(
                (corridor_x, corridor_y),
                corridor_length,
                self.config.passageway_width,
                linewidth=0,
                edgecolor=None,
                facecolor='blue',
                alpha=0.6
            )
        else:
            corridor_length = abs(end[1] - start[1])
            corridor_x = start[0] - self.config.passageway_width / 2
            corridor_y = min(start[1], end[1])
            rect = patches.Rectangle(
                (corridor_x, corridor_y),
                self.config.passageway_width,
                corridor_length,
                linewidth=0,
                edgecolor=None,
                facecolor='blue',
                alpha=0.6
            )
        ax.add_patch(rect)


def parse_arguments() -> argparse.Namespace:
    """Анализировать аргументы командной строки."""
    parser = argparse.ArgumentParser(
        description="Генерация и визуализация карт с комнатами и коридорами."
    )
    parser.add_argument(
        '--view', type=str, default='2d',
        choices=['2d'],
        help="Тип визуализации: '2d'. По умолчанию: '2d'."
    )
    parser.add_argument(
        '--seed', type=int, default=None,
        help="Случайное семя для воспроизводимости."
    )
    # Место для будущей поддержки файла конфигурации
    parser.add_argument(
        '--config', type=str, default=None,
        help="Путь к файлу конфигурации (опционально)."
    )
    return parser.parse_args()


def main():
    args = parse_arguments()

    # Инициализация конфигурации
    config = Config(
        num_rooms=20,
        map_width=200,
        map_height=200,
        room_min_size=5,
        room_max_size=20,
        passageway_width=3,
        extra_connections_factor=0.4,
        max_attempts_multiplier=10,
        random_seed=args.seed
    )

    # Генерация карты
    generator = MapGenerator(config)
    rooms = generator.generate_rooms()
    connections = generator.connect_rooms(rooms)

    # Визуализация карты
    visualizer = MapVisualizer(config)
    if args.view in ['2d']:
        visualizer.draw_map_2d(rooms, connections)


if __name__ == "__main__":
    main()
```
Сделай чтобы показывало как генерируется карта.
Тип как появляется первая комната, как соединяется все.