В статьях и интервью, посвященных созданию игр, довольно часто упоминается термин «искусственный интеллект» или ИИ. Как правило, подобные описания ограничиваются фразами вроде «реалистичный ИИ» или «продвинутый ИИ». Однако для симулятора, а именно об авиасимуляторе пойдет речь ниже, ИИ играет роль не меньшую, чем физическая модель самолета.
Для начала немного истории и общих понятий. Следует отметить, что принципиальные различия в устройстве ИИ разных авиасимуляторов найти достаточно сложно, так как оптимальные методы решения подобных задач известны давно и используются повсеместно. ИИ летчика, а также любой другой ИИ «водителя технического средства» — это так называемая «машина состояний». Весь объем решаемых ИИ задач разделяется на такое количество основных режимов (состояний), при котором поведение ИИ в каждом из режимов может быть описано своим достаточно простым алгоритмом с минимальным количеством условностей. Для летчика времен Второй мировой это порядка 20-30 «состояний» таких, как «руление по аэродрому», «взлет», «полет на точку», «полет за ведущим», «поиск, выбор и распределение воздушных целей», «заход на атаку воздушной цели», «атака воздушной цели» и так далее.
Каждое «состояние» имеет также набор условий — когда происходит вход и набор параметров для выхода.
Внутри каждого «состояния» есть алгоритм управления самолетом, его системами и вооружением. Он зависит от ряда внешних условий. Например, в состоянии «захода на атаку наземной цели» есть пять основных уровней принятия решений:
ИИ строит траекторию полета и график изменения скорости вдоль нее в зависимости от своего положения, а также положения наземной цели.
ИИ управляет ручкой управления, педалями и ручкой газа в зависимости от отклонения от построенной траектории и заданной скорости, с учетом текущей скорости и высоты, а также особенностей самолета.
ИИ продолжает оценивать обстановку вокруг себя и, в случае появлении угрозы или преждевременного пропадания цели, а также появления более приоритетных целей – выходит из «состояния захода» и переходит в то состояние, которое будет наилучшим образом соответствовать сложившейся обстановке.
ИИ продолжает следить за поступающими из системы скрипта миссии командами, и в случае поступления новой команды прекратит выполнять атаку, перейдет в состояние соответствующее выполнению вновь поступившей команды.
ИИ следит за состоянием самолета. Например, если остаток топлива или оружия не будет позволять ему продолжать атаку, то он выйдет из этого состояния и перейдет в «состояние возврата на базу».
Как уже было отмечено выше, такой подход в той или иной мере применяется фактически во всех авиасимах. В этой связи возникает вопрос – если сравнивать разные проекты, почему тогда так заметна разница в общей логике того, что делает ИИ в игре? Как водится, «дьявол кроется в деталях». Общий подход к архитектуре ИИ «устаканился» в индустрии уже много лет назад и мало чем отличается в разных проектах. Однако внутренние алгоритмы принятия решений внутри этих «состояний», а также условия переключения между состояниями в каждом проекте сделаны по-своему, и именно этот уровень реализации ИИ определяет различия между поведением ИИ самолетов в разных проектах.
ИИ самолетов в Rise of Flight (RoF).
ИИ для проекта RoF, в основном, был сделан по образу и подобию предшественников. Однако нам необходимо было привнести какую-то изюминку, которая отличала бы наш ИИ от других в лучшую сторону.
ИИ в RoF управляет таким же самолетом, каким управляет игрок, без упрощений физической модели. Это приятно для пользователя тем, что самолеты ИИ, так же, как и самолет игрока, движутся «как живые», также правдоподобно себя ведут при взлете/посадке, маневрировании и при получении повреждений. Игрок не чувствует, что «ИИ меня перекручивает, потому что летает по рельсам», и наоборот, не чувствует что «слишком просто перекрутить ИИ потому, что тот летает, используя упрощенную физическую модель». Все по-честному, и игроки это почувствовали.
Особенный упор был сделан на комплексном подходе к логике «состояния поиска, выбора и распределения воздушных целей». Алгоритм выбора был сделан весьма разветвленным, со множеством дополнительных условий. Они направлены на усиление влияния воздушной обстановки вокруг ИИ-самолета, на принятие им решений по выбору целей и распределения их между ведомыми.
Хотелось бы более подробно остановиться именно на второй особенности нашего ИИ. На алгоритме выбора воздушных целей. Во-первых, мы начали с составления экспертной оценки того, как цели отбирались в жизни. Причем как для опытного летчика, так и для новичка. Для этого мы пригласили пару заслуженных игроков в «Ил-2: Штурмовик» и исторического консультанта. В течение нескольких часов допрашивали их с пристрастием о том, какие факторы воздушной боевой обстановки влияют на выбор цели и как они это делают. Понятное дело, что основная проблема в этом случае — это выбор «точки отсчета», некоего мерила, с которым можно было бы сравнивать все остальные факторы боевой обстановки. При помощи такого сравнения уже можно было бы сопоставить их между собой.
В качестве такого критерия оценки было выбрано время сближения. Дальше следовал ряд вопросов, например: «Представь, эксперт, вот перед тобой две цели. До перехвата одной надо лететь минуту, а до второй — две минуты (на минуту больше), но вторая быстрее (то есть опаснее). Насколько она должна быть быстрее, чтобы, несмотря на то, что она дальше, ты (или реальный летчик) все же атаковал бы более отдаленную, но более быструю цель». На что эксперт отвечал «ну… я полетел бы атаковать более скоростную цель, которая на минуту дальше, чем менее скоростная, только если бы разница в скоростях целей была бы более 100 км/ч». Таким образом, мы получили сравнение важности разницы по скоростям целей и разницы по времени перехвата. Далее таким же образом составлялись сравнения приоритетов относительно времени перехвата для всех остальных параметров, среди которых:
— Разница максимальных скоростей целей на их текущих высотах.
— Разница максимальных скороподъемностей целей на их текущих высотах.
— Разница высот целей.
— Разница в количестве других вражеских самолетов в районе целей.
— Разница в классе целей (истребитель, разведчик, бомбардировщик).
Обработав стандартным способом экспертные оценки нескольких человек, откорректировав эти оценки для разных уровней сложности ИИ, мы получили стандартный метод сортировки целей по их приоритетности. Если взять, что разница по времени перехвата в 60 секунд дает +1 в копилку «приоритетности цели», то разница в 120 секунд даст +2. Экспертное сравнение говорит о том, что если 60 секунд — это +1, то разница в максимальных скоростях в 100км/ч — это тоже +1, а разница в 50 км/ч — это +0.5. И так далее по всем параметрам.
Далее происходит выбор цели из списка всех видимых ИИ-летчиком целей: сначала исключаются те, которые подпадают под условия фильтрации:
— Цели, перехват которых займет слишком много времени (по причине большой дальности, или по причине их большой высоты, или же по причине того, что они очень скоростные)
— Цели, вокруг которых настолько больше истребителей противников, чем истребителей союзников вокруг самолета игрока. Таким образом, бой с ними самоубийствен (это условие, в основном, влияет на ИИ-асов).
— Цели выше, чем максимальная высота полета самолета ИИ-летчика.
— Цели, значительно выше самолета ИИ-летчика, у которых при этом значительно выше скороподъемность.
После фильтрации «бесперспективных» целей, происходит их сортировка по приоритетности. Для этого берется каждая прошедшая фильтр цель и сравнивается со всеми остальными целями по всем вышеперечисленным экспертным параметрам. Сумма параметров является сравнением приоритетности между парой целей. Потом для каждой цели суммируются все парные оценки для тех пар, в которых она участвует. Далее цели сортируются по финальным суммам, от большей к меньшей.
Таким образом у нас появляется список целей, отсортированный по их приоритетности. Далее необходимо назначить цели ведомым. Эта логика зависит от уровня ИИ и от количества целей. ИИ-лидер высокого уровня при превосходстве в числе и в высоте, отправит в бой только часть ведомых, а сам с оставшимися будет прикрывать их на большой высоте, на случай появления дополнительных противников. ИИ-лидер низкого уровня отправит просто по одному самолету своей группы на каждую цель, начиная с приоритетных. ИИ-лидер высокого уровня будет отправлять минимум по два самолета на цель. Ну и так далее.
ИИ-ведомые также следят за обстановкой. Даже при выполнении атаки цели, назначенной лидером, в случае появления другого противника, который представляет серьезную угрозу самому ведомому, они переключатся на новую цель. Ведомые также следят за обстановкой вокруг лидера — если ему будет угрожать опасность от противников, не назначенных на атаку, они переключаться на атаку этих врагов, чтобы прикрыть лидера. Ведомые прекращают атаку назначенной цели, если они в процессе атаки слишком далеко удалились от лидера, и возвращаются к нему.
В результате RoF получил логику выбора целей ИИ-лидером звена наиболее приближенную к реальной практике воздушного боя среди всех представленных на тот момент аналогов. Причем логика эта получилась прозрачной и легко корректируемой, просто изменением значений указанных выше «парных параметров». Кроме того, в RoF реализовано множество интересных особенностей поведения ИИ: противозенитные маневры, система учета видимости цели, учитывающая освещенность, закрытие облаками, подсвет прожекторами. При этом на освещенность цели влияют также и источники света на самой цели такие, как аэронавигационные огни, вспышки выстрелов пулеметов, пожары.
Надо заметить, что некоторые пользователи восприняли часть этих «фич» за баги. Например, когда ИИ-лидер звена игрока не хотел атаковать значительно превосходящие силы противника. В этом случае ИИ-лидер просто не хотел ввязываться в бой, в котором вряд ли выживет он, а также его звено. Возьмем другую ситуацию, когда ИИ-лидер не хотел атаковать разведчика, идущего прямо над головой звена игрока, на большой высоте. На самом деле, ИИ-лидер просто прикинул, что время набора высоты до этого разведчика настолько велико, что к тому моменту, как это свершиться, он, скорее всего, улетит на свою территорию. В этих случаях нам приходилось объяснять, что «это как раз приближенная к реальности модель поведения, ИИ-летчики высокого уровня отнюдь не глупы и в авантюры стараются не ввязываться». Хотя, конечно же, при столь высоком уровне сложности ИИ, как в RoF, проблем было не избежать. Мы их планомерно вычленяли и исправляли. Отдельное спасибо хочется сказать Александру Петряеву, программисту ИИ, который создавал программную архитектуру и код, что уже 4 с половиной года служат в проекте RoF, который также еще много лет будут служить основой для ИИ-летчиков в новом проекте серии «Ил-2: Штурмовик».
ИИ самолетов в «Битве за Сталинград» (БзС).
Хочется отметить, что ИИ летчика в RoF изначально разрабатывался с дальним прицелом на самолеты Второй Мировой войны. С минимальными изменениями ИИ RoF мог быть использован и в «Ил-2: БзС». Однако мы решили, что очередной шаг вперед в этой области необходим и выбрали точку, где подобные изменения, на наш взгляд, будут наиболее востребованы. В RoF при проектировании и разработке ИИ мы сделали фокус на логике поиска и выбора целей, а в БзС мы решили сосредоточиться на боевом маневрировании при ведении ближнего воздушного боя. В RoF в «состоянии атаки воздушной цели» ИИ-истребители фактически выполняют всегда один универсальный маневр – поворачивают на цель по кратчайшей 3-х мерной дуге, где бы враг ни находился (сзади, справа, сверху, снизу). Для Первой Мировой войны такой подход был оправдан по той причине, что воздушный бой на самолетах того периода очень компактный, скоротечный. Время разворота очень маленькое, маневрирование происходит на скоростях порой меньше 100 км/ч и разложить его на «маневры» очень сложно.
Однако во время Второй Мировой войны картина воздушного противостояния радикально отличается: бой стал более масштабным, расстояния между самолетами при маневрировании намного больше, намного выше скорости, намного больше время разворота. В этой ситуации структурирование маневренного боя становится более очевидным, появляется возможность это структурирование формализовать. Этой задачей занялся наш новый программист ИИ, Илья aka «naryv» Стешов. Надо сказать, что, в первую очередь, он занялся доводкой и отладкой ИИ в проекте RoF. Все изменения, которые произошли в ИИ весной этого года – его заслуга и результат его деятельности. Кроме того, для составления технического задания снова были привлечены эксперты, которые давали консультации по вопросам боевого маневрирования – какие маневры применялись, в каких случаях они применялись, как влиял уровень летчика на применение тех или иных маневров, каковы были условия начала и прекращения маневров. Получив экспертную оценку, мы выбрали следующий путь решения задачи: «состояние атаки воздушной цели» стало «макроуровнем», раскрывающимся внутри себя в «машину состояний» нижнего уровня. Каждый маневр ближнего воздушного боя проектировался как отдельное «состояние» этой новой низкоуровневой машины. При этом логика «макросостояния атаки воздушной цели» продолжала функционировать со всеми условиями входа и выхода, что позволило сделать это нововведение в рамках архитектуры ИИ RoF без серьезных трудозатрат на архитектурные изменения в верхнем уровне «машины состояний», а также всей остальной логики ИИ. Какие маневры и когда применяет ИИ-истребитель в ближнем бою в БзС:
— «Доворот и стрельба». Это основной режим, в целом аналогичный алгоритму наведения, использовавшемуся в RoF. Применяется, когда цель близко к линии прицеливания и надо довернуть на нее и стрелять.
— «Свеча». Самолет резко уходит вверх на максимальном режиме работы двигателя. Применяется для сохранения энергии при большом превышении по скорости при «проскакивании» противника. Переводит скорость самолета в высоту.
— «Полупетля». Самолет выполняет половину «Петли Нестерова». Цель применения та же, что и у «Свечи».
— «Горка». Самолет набирает высоту по прямой, довольно крутой траектории (но не вертикальной). Применяется тогда, когда происходит «проскакивание» цели при умеренном превышении по скорости. В случае, когда атака была произведена сбоку или «в лоб». Цель применения снова та же – сохранение энергии путем перевода скорости в высоту.
— «Боевой разворот». Самолет набирает высоту по крутой спирали с потерей скорости. Цель применения та же, что и у «Горки», но также может применяться после атаки на цель сзади.
— «Восходящая спираль». Самолет выполняет разворот на максимальном газу в сторону цели, на постоянной скорости и с набором высоты. Применяется в тех случаях, когда в процессе атаки цель оказывается выше более чем на 100-200 метров и сбоку от нас (не по курсу).
— «Нисходящая спираль». Самолет выполняет разворот на максимальном газу в сторону цели со снижением и набором скорости. Применяется тогда, когда цель ниже более чем на 100-200 метров и сбоку от нас (не по курсу). Также может быть применена для попытки сбросить противника с хвоста при достаточном запасе высоты, т.к. в нисходящих спиралях развиваются очень высокие и продолжительные перегрузки.
— «Форсированный разворот». Самолет выполняет разворот в горизонтальной плоскости на максимальном газу и перегрузке. Применяется, когда цель на приблизительно той же высоте, что и наш самолет, сбоку от нас, но в передней полусфере.
— «Вираж». Самолет выполняет разворот в горизонтальной плоскости на максимальном газу, перегрузкой поддерживая постоянную оптимальную скорость выполнения виража. Применяется во всех остальных случаях.
— «High Yo-Yo». Самолет при выполнении «виража» немного уменьшает крен на непродолжительное время, слегка набирая высоту за счет некоторой потери скорости. Это подрежим маневра «вираж». Применяется, когда в начале выполнения виража скорость оказалась значительно выше оптимальной, и, чтобы не тратить энергию зря, эта скорость переводится в преимущество по высоте.
— «Low Yo-Yo». Самолет при выполнении «виража» слегка увеличивает крен на непродолжительное время, немного набирая скорость за счет потери высоты. Это, в свою очередь, позволяет кратковременно ускорить разворот на цель за счет увеличения перегрузки. Этот подрежим маневра «вираж» применяется, когда угол на цель не меняется продолжительное время (когда самолеты не могут обойти друг друга в вираже).
— «Переворот». Самолет «переворачивается на спину» и выполняет вторую половину «Петли Нестерова» с максимальной перегрузкой на максимальном газу. Применяется в случае, когда надо сбросить противника с хвоста и есть достаточный запас высоты.
— «Скольжение». Самолет отклоняет руль направления, продолжая полет по прямой. Применяется, чтобы создать ложное впечатление о направлении полета для противника, выполняющего прицеливание и стрельбу с большого расстояния.
— «Ножницы». Самолет сбрасывает скорость и выполняет последовательные отвороты вправо и влево. Применяется, чтобы сбросить противника с хвоста, когда запас высоты недостаточен и когда самолет ИИ-летчика более устойчив на малых скоростях, чем самолет противника.
— «Штопорная бочка». ИИ-летчик «подрывает» самолет вверх и одновременно закручивает его по крену. Также применяется для сбрасывания противника с хвоста. Маневр очень сложный и доступен только ИИ-асам.
— «Оборонительный доворот». ИИ-летчик удерживает противника на перпендикулярном курсе, постоянно набирая высоту и снижаясь. Применяется в случаях, когда противник выполняет атаку с большого расстояния с целью затруднить ему прицеливание.
Кроме создания новой разветвленной системы выбора дальнейшего маневра при ведении ближнего воздушного боя, зависящей от уровня ИИ, мы провели ряд работ, направленных на повышение реалистичности поведения ИИ-истребителя в воздушном бою:
— Была введена система ограничения видимости целей для ИИ конструкцией кабины. Она настраивается уникально для каждого самолета и учитывает не только возможные повороты головы летчика в кабине, но и возможные перемещения (привставания, приседания, заглядывания).
— В режиме ведения воздушного боя был введен подрежим поиска цели, которая была потеряна по какой-либо причине: ИИ-летчик ставит самолет в вираж и пытается снова увидеть цель; если сразу не получилось, то он перекладывает вираж в другую сторону. Так до тех пор, пока он не решит, что он окончательно потерял цель.
— Также в режиме ведения воздушного боя, когда цель оказалась слишком высоко, был добавлен режим набора высоты по оптимальной траектории, чтобы ИИ-летчик пытался догнать цель по высоте самым оптимальным способом.
— При уклонении от истребителей противника штурмовики и бомбардировщики теперь выполняют не только «змейку», но и пикирование, когда это позволяет высота и расстояние до противника.
— Так же мы создали функционал передового авианаводчика, который может оценивать обстановку на вверенном ему участке поля боя и наводить истребители и штурмовики на цели, используя радиообмен. В то же время, сами ИИ-самолеты имеют все навыки для взаимодействия и радиообмена с наводчиком.
— В дополнение к существующей логике атаки наземных целей ИИ-самолеты будут обучены применять неуправляемые ракеты с пикирования, а Ju-87 и Пе-2 выполнять бомбометание с отвесного пикирования.
— Ввиду возросших скоростей и разнообразия стрелкового вооружения была улучшена система подсчета и выдерживания упреждения при стрельбе по воздушным целям. ИИ-летчики теперь учитывают не только параметры движения цели, но и отличия в баллистике различного пушечного и пулеметного вооружения.
Нам также удалось добиться следующего:
— ИИ-летчики были обучены вести радиообмен с аэродромом и со своими ведомыми/ведущими.
— ИИ-самолеты также были научены выполнять руление со стоянки на взлетную полосу для взлета и с полосы на стоянку после посадки.
— ИИ-самолеты теперь знают и умеют пользоваться системами самолета, которые отсутствовали во время Первой мировой, но появились во Вторую мировую: убираемые шасси, закрылки и посадочные щитки, блокировка хвостового колеса, аэронавигационный огни, посадочные фары, освещение кабины, открываемый фонарь кабины, возможность покидания самолета с парашютом, воздушные тормоза, колесные тормоза, управляемый нагнетатель и регулятор оборотов.
Важно отметить, что почти весь новый функционал уже готов. Вы лично можете проверить это, приняв участие в начавшемся недавно раннем доступе. Система ИИ уже в RoF была достаточно продвинутой. В БзС же она стала еще сложнее, что неминуемо приведет к некоторым багам, но времени для отладки достаточно. К релизу мы рассчитываем довести показатели ИИ-летчиков до очень высокого уровня качества.
Кто-то может спросить: «Зачем вам все это надо»? Ответ на этот вопрос довольно прост – мы стремимся сделать картину воздушного боя максимально правдоподобной не только за счет детальной и реалистичной модели полета, но и за счет разветвленной, комплексной и реалистичной логики поведения ИИ-союзников и ИИ-противников. При создании ИИ в авиасимуляторе крайне важно постараться найти хрупкий баланс между излишней «роботизацией» и чрезмерным «оболваниваем» ИИ-противника. Навряд ли найдется много желающих посостязаться с идеальной «машиной для убийств», не делающей ошибок, равно как и отстреливать тупоголовых болванчиков, которые сами лезут под пули. Задача, стоящая перед нами, сложна и крайне интересна – сделать максимально «очеловеченного» и приближенного к реальности ИИ-летчика.
Оглядываясь назад, можно без ложной скромности утверждать, что кое-что нам уже удалось. И удалось неплохо. Однако мы не стоим на месте – постоянно развиваемся, ставим новые задачи и находим пути их решения. Мы ищем единомышленников и соратников. Присоединяйтесь!
Даниил «Han» Тусеев, руководитель проекта «Ил-2 Штурмовик: Битва за Сталинград».
Автор: AnatolySubbotin