Tuman & Pointer
Pointer Pointer
Ну что, Туман, я тут ковырялся с алгоритмом поиска пути, который минимизирует видимость на сетке с динамическими препятствиями – как бы, стелс-версия алгоритма Дейкстры. Как ты ориентируешься в местах, где тебя практически не видно? Есть какие-нибудь приемы, которые можно было бы превратить в четкую, эффективную процедуру?
Tuman Tuman
Можно считать "видимость" отдельным уровнем затрат. Дай каждому полю базовую стоимость перемещения, а затем добавляй штраф, который растёт в зависимости от того, сколько наблюдателей или источников света могут его видеть. Если препятствия двигаются, используй скользящее окно последних нескольких кадров и перестраивай только те поля, которые изменились. Быстрый трюк – заранее вычислить карту видимости для каждого поля – просто битовая маска, показывающая, какие наблюдатели его видят. Затем, при обновлении, тебе нужно пересчитывать стоимость только для тех полей, маска которых перекрывает движущееся препятствие. При поиске используй A* вместо простого алгоритма Дейкстры: эвристикой может быть расстояние по прямой до цели, но если нужна скрытность, добавь небольшую константу, которая будет подталкивать поиск к маршрутам с меньшим штрафом. Держи очередь приоритетов небольшой, отбрасывая узлы, которые ты уже видел с меньшей стоимостью. Если хочешь более аккуратную функцию, оберни всё это в функцию, которая принимает текущую сетку, список динамических препятствий и целевую точку. Внутри перестрой сетку стоимости, запусти поиск A*, и возвращай путь. Главное – делай сетку стоимости дешевой: используй целочисленные значения, избегай чисел с плавающей точкой, и обновляй только изменённые поля. Это и есть "невидимая" часть – небольшие, локальные обновления, без глобальных пересчетов.
Pointer Pointer
Отличное решение. Приём с битовой маской поддерживает постоянную стоимость обновления на одного наблюдателя, что нам как раз и нужно для работы в реальном времени. Только убедись, что хешируешь маски, чтобы избежать проверки на пересечение O(n). И подумай про ленивую очередь с приоритетами – это позволит поддерживать операции с кучей в O(log n), даже если ты агрессивно обрезаешь данные. Получится чистый и малозадержечный алгоритм.
Tuman Tuman
Звучит надёжно. Хеширование масок ускоряет проверки, а ленивая куча снижает накладные расходы, когда удаляешь узлы. Только следи за просроченными записями в очереди – вычищай их сразу при извлечении, и всё будет работать как часы.
Pointer Pointer
Точно. Держи очередь короткой и отсекай всё лишнее по второстепенным задачам. Если наткнёшься на устаревшие данные, просто выкинь их – остальной путь останется быстрым. Как только это будет готово, можно будет добавлять адаптивные эвристики – может, даже карту штрафов, которая будет обновляться в процессе. Это поднимет скрытность на новый уровень.
Tuman Tuman
Вот и есть план – замкнутый цикл, умная обрезка, а потом пусть обучение подстроит штрафы. Будь лаконичным, и останешься незамеченным, пока карта приспосабливается к каждой новой угрозе.
Pointer Pointer
Отлично, только следи, чтобы обучение не было слишком тяжелым – ну, типа несколько шагов градиента на обновление. Иначе путь потеряет скорость. И не переобучайся, иначе слишком осторожный путь не сдвинется с места, когда угроза спадет.