Взгляд на ботов изнутри или как создать вменяемый ИИ и постараться не сойти с ума

Меня зовут Николай Тупицин и я гейм-дизайнер. А еще и scriptwriter в обоих смыслах этого слова – и сценарист, и скриптовик.

ПЕРВЫЙ БОТ И КОНТРОЛЛЕР ПЕРСОНАЖА

Изначально мы были сосредоточены на ПВП контенте, но потом стало понятно, что бросать неподготовленных людей в мясорубке чересчур жестоко. Недолго думая мы решили добавить простейшую тренировку, в которой должны были быть простейшие боты. С  этого и началась разработка ботов в Warside.

Первого бота звали Mr.Chicken и все что он мог делать – бегать от игрока по прямой, а если в него стреляли – приседать и бояться. Если посмотреть на него изнутри, то весь его интеллект представлялся скриптовой процедурой, вызывающей каждый кадр, и дергающей клавиши управления. Собственно, эта особенность так и осталась – ИИ управляет ботами так же как игрок, нажимая кнопки и целясь мышкой.  Конечно, есть разница, но она небольшая. Именно с этим связано большинство ограничений на количество ботов – ведь ресурсы, расходуемые на бота, будут всегда больше ресурсов, расходуемых на игрока, сколько ни оптимизируй ИИ.

Вообще золотое было время: простые боты практически не доставляли проблем, в их умах не проскальзывала мысль забаговать, начать беспричинно убивать все живое или образовать Скайнет и начать порабощать Землю. Жаль только,  что и  делать они практически ничего не умели. 

Помимо контроллера персонажа, то тут,  то там все еще можно найти некоторые следы этого золотого времени. Например,  на карте «База Элайза-66» внимательные игроки смогут найти странный вырезанный прямоугольник глубоко под землей. Эта «курилка» была предназначена для «хранения» ботов из спавнеров и некоторых комнат. Из-за трудностей повторного спавна ботов там, где необходимо, приходилось спавнить ботов именно в этой курилке, и уже потом телепортировать их куда надо. Однажды, большой паук вывалился из курилки и умер, так и не появившись на арене, где его ждали игроки. Чтобы избежать такой ошибки в дальнейшем, курилку сделали большой, чтобы боты в ней помещались. 

КОНЧЕННЫЕ БОТЫ ИЛИ ЧТО ТАКОЕ FSM

Однако вскоре стало понятно, что примитивных ботов недостаточно. Даже для тренировки требовались болванчики, способные на мало-мальски разумное поведение, к тому же, не покидали настойчивые мысли о создании ПВЕ. Старая добрая процедура трещала по швам и не годилась для эмуляции поведения, ведь линейной программой удобно решать одну конкретную задачу, а не целый класс с разными условиями и зависимостями.  Поэтому я решил, что нужно как можно быстрее озаботиться переводом ботов на конечные автоматы (о которых вы узнаете ниже), сначала в скриптовом формате, а потом, получив и специальную структуру под это дело, от серверных программистов.

Картинка, изображающая пример конечного автомата. Кружки – состояния + действия в них. Стрелочки – переходы с написанными на них условиями.

Конечные автоматы (FSM, Finite State Machine), как подсказывает википедия, это модель дискретного устройства, имеющего один вход, один выход и в каждый момент времени находящегося в одном состоянии из множества возможных. Применительно к ботам это сухое определение можно развернуть так – FSM это алгоритм бота, в котором решение о том, что делать принимается исходя из 2-х вещей – внешнего условия и внутреннего состояния бота.

Картинка, представленная выше, выглядит в коде как то так:

Как видите, подобный подход достаточно удобен, а главное хорошо подходит для описания бота. Ведь практически так задачи по ботам и ставятся – «Ну мы хотим, чтобы он, атакуя (читать в состоянии «атака») всегда держался недалеко от игрока (читать «условие расстояния до игрока»), но если игрок подходит слишком близко – убегал (читать, если выполняется условие «ИГРОК БЛИЗКО» перейти в состоянии «УБЕГАТЬ»)».

Конечные автоматы позволили делать множество разных ботов, у каждого из которых были свои настройки. Для облегчения создания бота были добавлены шаблоны, которые определяли все – от вооружения до тактики. Иногда случались проколы, и появлялись курьезные сочетания. Например, летающему роботу-пчеле был случайно присвоен шаблон милишника, и в итоге нас на карте встречали кровожадные пчелы с тесаками.

 

НУЖНО БОЛЬШЕ БОТОВ

Размах ПВЕ составляющей постоянно увеличивался, заменив простых болванчиков с тренировки. На носу был режим выживание, в котором боты спавнились кучами, но ресурсы сервера не были бесконечными. Ботам достался один жуткий минус от процедуры – решение о том, что делать принималось каждый кадрКаждую толику времени все боты (включая мертвых или еще не отспавненных) на карте скрипели мозгами над принятием тривиального решения «Продолжать ли делать то, что делал, если ничего не изменилось». При малом количестве ботов, на это не обращаешь внимания, но стоит использовать реально большое количество – и боевой сервер ПВЕ неимоверно раздувается, захватывая все ресурсы. О том, что происходило, если запустить сразу несколько ПВЕ миссий, думаю, можно догадаться.

Спасение пришло от серверных программистов, которые добавили механизмсобытий, заодно расширив с помощью них функционал конечных автоматов. По сути, теперь боты думали, что делать не каждый кадр, а только тогда, когда происходило что-нибудь значимое. Данное нововведение позволило существенно разгрузить сервер, и создавать действительно большие группы ботов.

Поскольку систему вводили в короткие сроки, посыпалось много забавных курьезов. Например, из-за небольшого недосмотра, боты продолжали работать после смерти и реагировали на приближение врага к их трупу, даже пытались его атаковать. Получилось, по-моему, только у паука-суицидника, который после смерти начинал работать как натуральная мина. Другой курьез был в том, что от ботов можно было прятаться прямо перед их носом. Достаточно было подкрасться к боту, отвлеченному другим игроком, и ничего не делать – новых событий не происходило, и бот просто не знал о вашем существовании.

НУЖНО ЕЩЕ БОЛЬШЕ БОТОВ

Несмотря на (или благодаря?) механизм событий, мы поняли, что нам нужно больше ботов, причем разнообразных в собственном поведении. Это требование упиралось в большую внутреннюю связность автоматов. Большая связность означает, что, если я хочу изменить в готовом автомате одно состояние, мне придется переписывать чуть ли не весь автомат (точнее все состояния, что связаны с изменяемым куском). А подобное переписывание крайне отрицательно сказывается на скорости создания ботов.

Сначала я пытался разделять автоматы на маленькие куски, которые повторялись из автомата в автомат (например, состояние «Покой»), но из этого не вышло ничего путного – для некоторых ботов приходилось переписывать даже состояние «Покой», пусть даже все переписывание и заключалось в добавлении одного условия и соответствующего действия.

Просмотрев некоторое количество материалов по этой проблеме, я наткнулся на достаточно элегантное решение. Автор предлагал использовать вместо одного конечного автомата, описывающего полное поведение бота, несколько таких и переключать их специальной процедурой. То есть мы делили автомат на несколько «поведений» – например, поведение в покое, поведение в атаке на врага или поведение на выполнении миссий, которые уже выбираются исходя из каких-либо условий. Это позволяет переписывать не всего бота, а только поведение, которым он отличается, а значит, скорость работы по созданию новых ботов растет.

После введения такой процедуры решений писать стало действительно легче, а ошибки даже забавнее. Одна такая чуть не разрослась в детективную историю. В режиме выживание боты вели себя вполне естественно, но ботов с дробовиком всегда что-то убивало около объекта который они должны были разрушить. При этом судя по взрыву стреляли из ракетницы. Я долго искал таинственного убийцу, пока наконец не увидел, что их поведение «уничтожить объект», повторяло поведение пауков суицидников. И они действительно подбегали к объекту и взрывались, хотя во всех остальных случаях вели себя естественно.

 

Идеальная синхронизация, или что происходит когда противники равны и управляются одним и тем же интеллектом. (Слева направо: Бот корпорат, Я, Бот коммунар).

 

В БЕСКОНЕЧНОСТЬ И ДАЛЬШЕ

Улучшать ботов можно и дальше. Помимо усовершенствования структуры непосредственно «Мозга» ботов, так же происходят и изменения вспомогательных процедур. Агросписок оформился из скриптовой составляющей, Pathfinding (система поиска пути) также пришел на замену скриптовым процедурам перемещения, даже некоторые типы атаки были заменены низкоуровневыми эквивалентами. Текущая структура ИИ позволяет проводить подобные замены быстро и безболезненно, и я считаю, что её нам хватит надолго. Впрочем, если у кого-то есть конкретные предложения (с четким обоснованием) буду рад услышать.

 

И помните, у ботов тоже есть душа!