Сетевая игра в main, 0.8.0 и путь от формул обтекания к физике воздуха

Сетевая игра слита в main и выпущена как 0.8.0, залита на itch. Тем же днём разобраны несколько мелких находок (ложное зависание, редкие грозы, боты в воздухе, отказ прототипа паруса), а затем — путь от жалобы «обтекание не физическое» через формулы и уравнение Пуассона к прототипу клеточного автомата на GPU и плану модели воздуха на три масштаба.

Сетевая игра слита в main, выпуск 0.8.0

Ветка feature/multiplayer (координаторы К1 «Сеть», К2 «Игра в сети», К3 «Интерфейс», ~20 исполнителей) слита без конфликтов (08c614f). Версия 0.8.0 (0ac895d, тег v0.8.0), залита на itch через butler. Решение пользователя: сливать сразу, хотя в интернете ещё не проверено — «играют 3 человека, заодно и проверим».

  • Проверка перед слиянием: сетевой тест через Go-сервер в Docker, как через интернет (--net-create, 3a7062e): зона 9312, второй вошёл по коду, термики совпали до номера, Маша видит Колю.

Сетевая игра: чужой пилот рядом

Через Go-сервер в Docker — вижу Колю

Скилл /new-release

(7c1206d): версия → CHANGELOG → releases/X.Y.Z/devlog.txt (простой текст на английском — визуальный редактор itch ломает Markdown) → сборка → тег → butler. Теги v0.5.0…v0.8.0 проставлены задним числом.

Меню больше не грузит мир

(0a3114d). Пользователь заметил, что после запуска игра «тупит»: с первой версии меню грузило полный мир за собой (рельеф, 11 тыс. домов OSM, боты, фоновые поля рельефа 16 с), под картинкой фона его не видно. Решение: грузить по «Лететь» с экраном загрузки. Побочно сломались 9 тестов, ждавших «мир за меню», — починены через Main.load_menu_world() (6b12c1f).

Ложное зависание при выходе

Агент сборки видел 5/10 зависаний собранной игры при выходе, подозревал кеш шейдеров облаков → кеш удалён (b26234d). gdb на зависшем процессе: главный поток ждёт join, рабочие потоки спят. На чистом main — 0/25 (свободная машина, 100 % CPU, вторая копия игры). Вывод: артефакт сборок агента из рабочей копии с незаконченными правками. Урок: проверять на чистом дереве, прежде чем «чинить».

Грозы стали редкими

(105bf45). После детерминизма мира (NET-00) при +26 °C ясно гроза была у старта в 45 из 48 сидов. Пользователь сначала решил «гроза на старте — не баг», но с учётом частоты — «сделать редкими: пилот должен увидеть хоть раз за всё время». Итог: +26 — 0–1 %, +34 — ~50 %.

Половина ботов уже в воздухе

(0e07d62). Пилот-консультант: «первым лететь не весело — улетаешь и никого не видишь». Решение пользователя: floor(N/2), не меньше одного, уже летают; остальные в очереди.

Парус «кожа на скелете» — отказ

Прототип провиса ткани между латами (1,5 %, потом 0,5 %) — пилот-консультант: «натянут как барабан, крыло почти гладкое»; разница с гладким незаметна → прототип удалён (1b9c98b).

Обтекание склона — от формул к физике

Пилот-консультант: «обтекание не физическое». Исследование (docs/research/slope_wind.md): у нас нет разгона ветра на бровке, полоса подъёма фиксированные 250 м, «труба» в седловине наоборот. Ответ пилота-консультанта — числовые ориентиры: разгон до ~2 высот горы от подножия, на 2,5 H ламинарно; круче — сильнее; седловина ×1,5 вдоль оси даже при 15° косого ветра. Путь обсуждения:

  • формулы (вариант A) → поле ветра, согласованное по массе (уравнение Пуассона), на GPU → линейность по ветру (2 базовых поля на уровень устойчивости) → вложенные сетки-клипмапы 50…800 м вокруг пилота (идея пользователя: «глубина дерева по расстоянию») → план docs/archive/plan/wind-field.md (~31 день агентов);
  • CUDA — нет (AMD у пилотов), Rust + rayon — рассмотрен, выбран Vulkan compute;
  • связанная система «нагрев → плавучесть → поток масс» (идея пользователя: клеточный автомат — горячая клетка отдаёт тепло вбок и вверх, подсасывает массу у холодных; затем «переход слой→слой умножением на матрицу коэффициентов переноса», «6 прогонов по осям», «ядро как в обработке изображений»). Физический базис: 5 законов (масса, импульс с Архимедом и нелокальным давлением, энергия, вода, уравнение состояния), по сути — приближение Буссинеска.
  • Прототип на 2D-разрезе хребта (tools/research/heat_ca/, CuPy на RTX 4070 SUPER, 50f1680): над прогретым склоном — подъём до ~1,5 м/с, приток у подножия, растекание на ~1,4 км, опускание вокруг; сходимость по клетке — с 50 м меняется на 5–10 %; явная схема в 3D слишком медленная (50 м — ~17 мин) → эксперименты 1–6 (линейность, Пикар+CG, матрицы переноса, ADI, ядра) у координатора прототипа.

Поле обтекания, сценарий «солнце на один склон»

Принцип: физическая корректность в пределах модели

Пользователь: «Нравится пилоту-консультанту — ориентир, а не требование… любая симуляция — модель, любая модель имеет границы»; «под „нравится“ можно бесконечно крутить коэффициенты — бесперспективно». Отсюда — задача WF-16: калибровка по схеме Professor (HEP): прогоны → полиномы → χ² против числовых ориентиров с погрешностями. Запущен поиск табличных данных (литература 70–90-х и измерения).

Прочее

Своя иконка и заставка, папка профиля Deltaplan с переносом старого, Shader Baker, дебандинг; лог-файлы у игрока оставлены (нужны для разбора вылетов у пилота на Windows на спортивном крыле); постоянно падающие тесты удалены; замер тестов: последовательно ~22 мин, в 8 процессов ~3 мин.

Дневник разработки — этот Hugo-блог в site/content/diary/ и скилл /diary: все данные исследований сохраняем, возможно, потом будет статья на Хабр. Для калибровки скачаны измерения холма Askervein (Zenodo 4095052, CC BY 4.0, b4429b0) — разгон ветра по мачтам на вершине.

Итоги опытов прототипа

(54753a2, 960ebec, 457928d, 75f5698, итог — 60d11fd, tools/research/heat_ca/out/summary.md, раздел «Слои как матрицы»). Критерий — сначала физика, потом точность, потом цена на GPU:

  • 1, 3 — суперпозиция и линейные ядра: линейно только при подъёме в сантиметры в секунду; при 250 Вт/м² ошибка суперпозиции 69 %, термик из суммы ядер втрое слабее. Пользователь: «не впечатляют».
  • 6 — «ядро струи» (цепочка формул: размытие нагрева, тёплый бассейн, плавучая струя, Прандтль, волна, проекция): 1–2 мс, место/сила/потолок термика ±5–30 %, поле грубое. Годится как мгновенная оценка.
  • 4 — матрицы перехода слой→слой (идея пользователя: гармоники по x, блочная прогонка 4×4 вверх/вниз, повторы с Андерсоном): та же неподвижная точка, 1–2 %, 56–66 повторов почти не зависят от клетки (200…12,5 м), 0,33 с против 24,6 с шагами на 12,5 м.
  • 5 — ADI-прогонки: та же точка, 100–190 раундов, но итерация пока дорогая.
  • 2 — Пикар (импульс Озеена + проекция одним V-циклом + тепло): ≤ 0,5 % по ветру, ~1 % по θ′, ×5…×36 быстрее шагов; оценка 3D по области 200 м — 2–5 с. Выбран для игры.
  • Находка: эталоны базы недосчитаны (абсолютный критерий установления) — на 3–8 % по ветру и 10–23 % по θ′ от точной неподвижной точки; её нашли все исполнители независимо.
  • Сходимость по клетке: 200 м — склонового ветра нет, 100 м — самая грубая с правильной картиной, 50 м — подъём с ошибкой ~15 %, мельче 25 м смысла нет.

Три масштаба модели воздуха

Пользователь: ощущение полёта — это «общая правдивость (над полем термик)» и «локальные возмущения (крыло шатает, как в реальности)». Отсюда: (1) среднее поле — Пикар на GPU, 200 м по области и 100/50 м окнами вокруг пилота, раз в игровой час; (2) термики — нынешние пузыри, но место, сила (w* Дирдорфа), потолок и снос — из поля; (3) болтанка и рывки — нынешняя форма, сила из сдвига и нагрева поля. Масштабы 2 и 3 не имеют своих ручек «где и насколько». Главный вопрос стыка — двойной счёт тепла: конвективная вертикаль поля идёт пилоту только через пузыри с тем же потоком массы. Термики в сети — список источников от ведущего (или квантование). План docs/plan/air_model.md (0f07933, ~31 день, шлюз после 3D-эталона на CuPy) заменил план поля ветра по массе: у того не было ни тепла, ни инерции.