Искусственный интеллект в Heroes of Might and Magic V

См. также: Путь Героев: дизайнерский постмортем >>

Тимур Бухараев
Родился в г. Казани. Закончил факультет Радио-Техники и Кибернетики МФТИ. С 2004 года работает программистом в компании Nival Interactive.

Введение

В этой статье я постараюсь поделиться опытом, полученным при разработке искусственного интеллекта (далее ИИ) в проекте Heroes of Might & Magic V. Однако здесь не будет сказано ни слова об устройстве этого самого интеллекта. Почему же?

Прежде всего - для того, чтобы сконцентрировать внимание на теме организации процесса разработки, отладки и тестирования ИИ. Дело в том, что устройство ИИ в "Героях" достаточно сильно завязано на то, что это именно "Герои", а не какая-то другая игра. И не факт, что знание устройства ИИ в проекте Heroes of Might & Magic V пригодится разработчикам игры о гонках на пепелацах.

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

Историческое отступление

Надо сказать, что бывают ситуации, когда речь идет не о том, как правильно написать ИИ. Иногда речь идет о том, чтобы вообще его написать. Хоть в каком-либо удовлетворительном виде. Так, уже под конец проекта наш издатель, Ubisoft, забил тревогу: в игре отсутствует ИИ! Однако, когда наши менеджеры сообщили мне об этом, я удивился. Ведь он же разрабатывался моим предшественником полтора года, и считался готовым.

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

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

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

Почему же так получилось? Может дело в непрофессионализме моих предшественников? Я так не считаю. Программисты, придумавшие идеологию ИИ и реализовавшие ее - хорошие профессионалы. А самое главное, что все, что они сделали, когда-то работало. Наверное, работало...

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

Так же и с ИИ: это очень хрупкая и тонкая система. А проект мчался вперед. Огромный проект, с большим количеством разработчиков на борту, не все из которых обладали большим опытом. Каждый день в код и данные вносились десятки изменений. Дизайнеры крутили баланс игры. Параметры и способности существ и героев постоянно менялись. Менялись даже базовые правила и формулы игры. Поэтому ничего удивительного, что, вернувшись вдруг проведать, как же поживает наш домик, мы обнаружили лишь кучу карт, хаотично разбросанных по столу. И тогда мы взяли клей и принялись за дело.

Красиво отдаться игроку

Мудрость, которой научились программисты "Нивала" у дизайнеров, звучит следующим образом:

Главная задача ИИ - не выиграть у игрока, а красиво ему отдаться.

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

Надо отметить, что сам принцип хотя и является очень простым и понятным, изначально вызывает у программистов противоречие. Они не хотят делать ИИ, который красиво отдается. Им хочется сделать такой ИИ, который заставит игрока рыдать от собственного бессилия. Но так делать не стоит.

Не пойман - не вор

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

В принципе, ничего плохого в этом нет. Необязательно делать достойного противника. Достаточно создать иллюзию достойного противника. И если вы обманете, но вас не поймают за руку - то вы на коне.

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

Особо любопытные игроки активно ковыряются в ресурсах игры в поисках читов, пытаются отследить их с помощью скриптовых команд. Причем подозрения и обвинения в читерстве идут даже там, где их на самом деле нет. Так, некоторые открытые константы оценочной функции ИИ подозрительные игроки приняли за читы и даже создали свой мод, который их обнуляет. Ломающий оценочную функцию мод был выложен в интернет и торжественно назван античитерским.

Выводы такие: читить можно, но незаметно. Причем лучше сделать много маленьких читов, чем один большой.

Концентрация на задаче

Хотя у нас была мини-команда из программистов с гордым названием AI-Team, самому AI она уделяла не очень-то много времени. Основная работа, которой она выполняла: разработка высокоуровневого кода и данных для игровой механики, расширение набора скриптовых функций, привязка артовых ассетов к игровой логике, создание и поддержка системы автоматических камер в бою.

Когда мне было поручено вернуть AI к жизни, то я, как лидер команды, ухватил эту вкусную и интересную задачу лично. Время рабочего дня, посвященного реанимации AI, распределялось примерно так:

  • 30% - сортировка и распределение приходящих задач и багов
  • 10% - code review чужих изменений
  • 20% - доделка режима ghost mode
  • 10% - походы к дизайнерам полюбоваться на новый "assert"
  • 10% - ответы на вопросы, что и где у нас лежит и как работает
  • 10% - исправление мелких ошибок, которые быстрее поправить, чем перепоручать
  • 5% - выяснение, почему же у художника новая камера в игре - задом наперед
  • 5% - отчаянный скрип извилин при загрузке кода ИИ в мозг

Кстати, мой предшественник писал его примерно в тех же условиях.

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

Вывод из этого такой:

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

Регрессивное тестирование

Что такое хороший ИИ? Чем он вообще должен заниматься? Как формализовать требования? Как проверить, что он готов и работает?

В обсуждениях ИИ, к сожалению, часто не хватает конкретики. А уж какие баги по нему иногда приходят: "AI tupit". Без каких-либо дополнительных объяснений. И что прикажете с этим делать?

Поэтому как при сборе требований, так и при тестировании необходимо собирать use cases. Это некие игровые ситуации, в которых поведение ИИ однозначно определяется с помощью здравого смысла. И, следовательно, отклонение реального поведения от заданного однозначно указывает на ошибку.

В "Героях" мы такие тестовые ситуации оформили в виде набора карт. Требования к тестам такие:

  • Ожидаемое поведение
  • Однозначный ответ "да" или "нет" на вопрос, соответствует ли наблюдаемое поведение ожидаемому
  • Быстрое воспроизведение поведения для анализа
  • Небольшой размер

Для иллюстрации приведу пример одной такой карты:

 

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

Если же выбор происходит неправильно, то тест провален. Это означает, что система оценки ресурсов ИИ сломана.

Проверки тестов следует автоматизировать с помощь скриптов и регулярно их запускать. Надо отметить, что некоторые тестовые карты при изменениях кода ломались многократно. К сожалению, тестовые карты мы начали делать только в декабре 2005, то есть уже под конец проекта, а автоматизация запуска и проверок была реализована и вовсе после выхода игры в тираж.

Итак, регрессивные тесты являются важнейшим средством сохранения работоспособности такой сложной системы, как искусственный интеллект.

Специальный режим для отладки ИИ

Вот, скажем, требуется выяснить, как ИИ раскачал своего героя или отстроил свой замок. А как? Лазить в отладчик? Создавать для этого скриптовые команды и писать их в консоли? Можно, но долго и неудобно. Поэтому одна из первых работ по реанимации ИИ была посвящена созданию специального режима игры, в котором можно было бы наблюдать за ИИ от первого лица и устраивать игры ИИ друг с другом без участия человека.

Отныне большинство наблюдений за поведением ИИ можно было проводить через обычный пользовательский интерфейс игры, что гораздо комфортней, чем ставить breakpoint в игре и смотреть значения переменных.

Кроме того, я поставил рядом с собой второй компьютер и устраивал на нем регулярные схватки ИИ друг с другом. Наблюдая за этим процессом периферическим зрением, иногда удавалось отлавливать ошибки (кстати, не только связанные с ИИ) и исправлять их по горячим следам.

Так что не ленитесь обеспечивать себя удобным инструментарием для разработки ИИ.

Визуализация ИИ

Но и через стандартный интерфейс можно узнать не все. Очень важный вопрос, на который должен уметь ответить разработчик, глядя на поведение ИИ: почему он поступил так, а не иначе? Почему вместо того, чтобы напасть на моего слабого героя, этот дурак поскакал мимо за очередным сундучком? На этот вопрос, несомненно, можно ответить, запустив игру под отладчиком. Но это долго, не оперативно и невероятно утомительно.

А вот наглядное визуальное представление процессов, происходящих в ИИ, значительно облегчит процесс получения ответа на вопрос "почему" и последующее исправление ошибки.

Приведу несколько примеров такого представления:


Содержимое объекта, отвечающего за поиск путей


Оценки объектов на карте. Маленькие зеленые столбики ИИ хочет захватить меньше, а большие и красные - больше


Зона угроз. Красными точками помечена зона вокруг страшного вражеского героя, в которую не следует ходить. На этом же скриншоте видно, что для отладки ИИ можно также использовать тултипы

Вывод: визуализация сокращает время отладки и исправления ошибок ИИ в разы!

Протоколирование

Еще одним очень полезным методом отладки и тестирования ИИ является создание логов, то есть текстовых файлов, в котором ИИ пишет рапорт о проделанной работе. Его можно запустить на ночь, а утром прочитать, что же было сделано.

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

Вот пример такого лога:

При исправлении ошибки, связанной с неправильным строительством города, из всего лога реально интересны только три строчки:

Игра с ИИ

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

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

Поэтому, нужно обязательно находить время играть с ИИ лично.

Вывод

На этом, пожалуй, все. Если у кого-то будет желание узнать, как же устроен ИИ в пятых "Героях", то лучше рассказать об этом как-нибудь отдельно. А здесь остается лишь подвести итоги в виде краткого списка рецептов по приготовлению ИИ в компьютерных играх. Надеюсь, кто-то сумеет воспользоваться ими себе во благо:

  1. Главная задача ИИ - не выиграть у игрока, а красиво ему отдаться.
  2. Читить можно, но незаметно. Лучше сделать много маленьких читов, чем один большой.
  3. Главным необходимым условием для создания ИИ является концентрация усилий на задаче и отстранение от всех остальных проблем.
  4. Регрессивные тесты являются важнейшим средством сохранения работоспособности ИИ.
  5. Не ленитесь обеспечивать себя удобным инструментарием для разработки ИИ.
  6. Визуализация сокращает время отладки и исправления ошибок ИИ в разы.
  7. Нужно обязательно играть с ИИ лично.

Статья написана на основе доклада на КРИ-2006.

[29.09.2006]

Copyright © 2016 ООО "ДТФ.РУ". Все права защищены.

Воспроизведение материалов или их частей в любом виде и форме без письменного согласия запрещено.

Замечания и предложения отправляйте через форму обратной связи.

Пользовательское соглашение