Как написать бота для старкрафт 2

Обновлено: 06.07.2024

Шведы написали микро бота, через StarCraft 2 Editor, т.е. никакое левое ПО не задействуется.

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

APM доходит до 15 000.

Что он может (пока):

40 ускоренных бейнлингов vs. 20 маринов (пехота побеждает бейнлингов без потерь)

20 разложенных осадных танков vs. 100 зерглингов (все танки уничтожены, в живых 19 собак)

bwapi-rs

Теперь, когда у нас есть байндинги, мы можем описывать высокоуровневые абстракции. У нас есть 2 типа, с которыми надо работать: чистые значения и непрозрачные указатели.

С чистыми значениями все проще. Возьмем за пример цвета. Нам надо добиться удобного использования из Rust кода, чтобы можно было использовать цвета удобным и естественным образом:

Значит для удобного использования надо будет определить идиоматическое для языка Rust перечисление с константами из C++ и определить методы конвертирования в bwapi_sys::Color с помощью типажа std::convert::From:

Хотя для удобства можно воспользоваться крейтом enum-primitive-derive.

С непрозрачными указателями ничуть не сложнее. Для этого воспользуемся паттерном Newtype:

То есть Player — это некая структура с приватным полем — сырым непрозрачным указателем из C. И вот как можно описать метод Player::color:

Теперь мы можем написать своего первого бота на Rust!

BWAPI

Этой игре уже 20 лет. И она до сих пор популярна, чемпионаты собирают целые залы людей в США даже в 2017 году, где состоялась битва грандмастеров Jaedong vs Bisu. Помимо живых игроков, в битвах участвуют и бездушные машины! И это возможно благодаря BWAPI. Больше полезных ссылок.

Уже более десяти лет вокруг этой игры существует сообщество разработчиков ботов. Энтузиасты пишут ботов и участвуют в различных чемпионатах. Многие из них изучают ИИ и машинное обучение. BWAPI используется университетами для обучения своих студентов. Существует даже твитч канал, который транслирует игры.

Итак, команда фанатов несколько лет назад отреверсила внутреннести Starcraft и написала на C++ API, которое позволяет писать ботов, внедряться в процесс игры и господствовать над жалкими людишками.

Как это часто бывает, прежде чем построить дом, надо добыть руду, выковать инструменты. написать бота, необходимо реализовать API. Что же может предложить со своей стороны Rust?

Взаимодействовать с другими языками из Rust довольно просто. Для этого существует FFI . Позвольте мне предоставить краткую выдержку из документации.

Пусть у нас есть библиотека snappy, у которой есть заголовочный файл snappy-c.h, из которого мы будем копировать объявления функций.

Создадим проект с помощью cargo.

Cargo создал стандартную файловую структуру для проекта.

В Cargo.toml укажем зависимость к libc:

src/main.rs файл будет выглядеть так:

Собираем и запускаем:

Можно вызвать только cargo run , который перед запуском вызывает cargo build . Либо собрать проект и вызвать бинарник напрямую:

Код скомпилируется при условии, что библиотека snappy установлена(для Ubuntu надо поставить пакет libsnappy-dev).

Как можно увидеть, наш бинарник слинкован с разделяемой библиотекой libsnappy. И вызов snappy_max_compressed_length является вызовом функции из этой библиотеки.

bwapi-sys

В экосистеме Раста принято определенным образом называть пакеты, которые линкуются к нативным библиотекам. Любой пакет foo-sys занимается двумя важными функциями:

  • Линкуется к нативной библиотеке libfoo
  • Предоставляет объявления к функциям из библиотеки libfoo. Но только лишь объявления, высокоуровневые абстракции в *-sys крейтах не предоставляются.

Чтобы *-sys пакет умел успешно линковаться, в него встраивают поиск нативной библиотеки и/или сборку библиотеки из исходников.

Чтобы *-sys пакет предоставил объявления, надо или написать их руками, или сгенерировать с помощью bindgen. Снова bindgen. Попытка номер два =)

Генерация байндингов с помощью bwapi-c становится до неприличия простой:

Где BWAPI.h — файл с инклудами всех сишных заголовков из BWAPI-C.

Например, для уже известных функций bindgen сгенерировал такие объявления:

Существуют 2 стратегии: хранение сгенерированного кода в репозитории и генерация кода на лету при сборке. И тот и другой подход имеет свои преимущества и недостатки.

Приветствуем bwapi-sys, еще одну маленькую ступень к нашей цели.

Помните, я говорил про кроссплатформенность? К проекту присоединился nlinker и реализовал хитрую стратегию. Если целевой таргет — Windows, то скачиваем уже собранную BWAPIC из гитхаба. А для остальных таргетов собираем BWAPI-C из исходников для OpenBW (расскажу чуть позже).

Бот Starcraft 2 на основе перехвата и анализа рендеринга

Matthew Fisher из Стэнфордского Университета написал интересную статью о реализации бота на основе перехвата потока API библиотеки D3D9 (Microsoft Direct 3D, являющуюся частью библиотеки DirectX).



В статье довольно много технических подробностей и выложены исходники кода, которые реализуют бота. Основная задача статьи – показать простую программу, которая работает как перехватчик и интерпретатор команд D3D9. Преимущество такого подхода к реализации бота по сравнению с другими методами (внедрение в адресное пространство, написание бота на скриптовом языке SC2) очевидны – метод универсален и его можно применять к другим программам, создание бота по этому методу должно быть легче и доступнее. Недостатки метода тоже довольно очевидны: на разбор сцены уходит довольно много времени и сил и достичь APM (количество действий в минуту) сравнимых с другими методами скорее всего не получится.

Бот разделен на три компонента:

1. Mirror Driver – хранилище базовых объектов, которые отрисовываются на карте. Объекты представляют собой текстуры, шейдеры, пиксели и другую базовую графическую информацию.
2. Scene Understanding – данные, полученные Mirror Driver поступают на вход этому компоненту, который преобразовывает их в сущности, которые присутствуют в игре. То есть переводит базовую информацию на более высокий уровень, с которой уже можно строить стратегию управления игрой.
3. Decision Making – компонент, отвечающий за принятие решения, или по-простому – мозги бота.

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

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


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

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

По результатам анализа игры SC2 показал, что в “спокойное” время APM бота находится в пределах 500 действий, в режиме битвы от 1000 до 2000. Не все эти действия полезны и микроуправление сложно реализовывать; команды бота могут быть бесполезны или даже вредны, по сравнению с поведением юнита по умолчанию.

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

Пишем бота на Rust

В качестве proof of concept бот будет похож на одну известную страну: весь его функционал будет заключаться в найме рабочих и сборе минералов.

North Korea

South Korea

Начнем с обязательных функций gameInit и newAIModule :

Описание структуры модуля еще проще и красивее, чем в C:

Добавим пару методов для отрисовки статистики и раздачи приказов:

Чтобы тип ExampleAIModule превратился в настоящий модуль, необходимо научить его отзываться на события onXXXX, для чего надо реализовать типаж EventHandler, который является аналогом виртуальной таблицы AIModule_vtable из C:

Сборка и запуск модуля так же просты, как и для C:

OpenBW

Эти ребята пошли еще дальше. Они решили написать open-source версию игры SC:BW! И у них неплохо получается. Одной из их целей была реализация HD картинки, но SC: Remastered их опередили =( На данный момент можно использовать их API для написания ботов (да, тоже на C++). Но самой умопомрачительной фичей является возможность просматривать реплеи прямо в браузере.

Бот для Starcraft на Rust, C и на любом другом языке


StarCraft: Brood War. Как много это значит для меня. И для многих из вас. Настолько много, что я засомневался, давать ли ссылку на вики.

Как-то раз мне в личку постучался Halt и предложил выучить Rust. Как и любые нормальные люди, мы решили начать с hello world написания динамической библиотеки под Windows, которая могла бы загружаться в адресное пространство игры StarCraft и управлять юнитами.

В статье будет описан процесс поиска решений, использования технологий, приемов, которые позволят вам почерпнуть новое в языке Rust и его экосистеме или вдохновиться для реализации бота на своем любимом языке, будь то C, C++, ruby, python, e.t.c.

Эту статью стоит читать непременно под гимн Южной Кореи:

rust-bindgen

Было бы хорошо, если бы мы могли в автоматическом режиме сгенерировать FFI. К счастью, в арсенале растоманов есть такая утилита под названием rust-bindgen. Она умеет генерировать FFI байндинги к C (и некоторым C++) библиотекам.

Как выглядит использование rust-bindgen? Мы берем заголовочные файлы C/C++, натравливаем на них утилиту bindgen, на выходе получаем сгенерированный Rust код с определениями сишных структур и функций. Вот как выглядит генерация FFI для snappy:

Оказалось, что bindgen пасует перед заголовками BWAPI, генерируя тонны неюзабельных простынок кода (из-за виртуальных функций-членов, std::string в публичном API и т.д.). Все дело в том, что BWAPI написан на C++. C++ вообще сложно использовать даже из C++ проектов. Однажды собранную библиотеку лучше влинковывать тем же линковщиком (одинаковых версий), заголовочные файлы лучше парсить тем же компилятором (одинаковых версий). Потому что существует множество факторов, которые могут повлиять на исход. Например, манглинг, который в GNU GCC до сих пор не могут реализовать без ошибок. Эти факторы настолько значимы, что их не смогли побороть даже в gtest , а в документации указали, что лучше бы вам собирать gtest как часть проекта тем же компилятором и тем же линковщиком.

BWAPI-C

C — это лингва франка программирования. Если rust-bindgen хорошо работает для языка C, почему бы не реализовать BWAPI для C, а потом использовать его API? Хорошая идея!

Да, хорошая идея, пока ты не заглянул в кишки BWAPI и не увидел кол-во классов и методов, которые необходимо реализовать =( Особенно все эти расположения структур в памяти, ассемблеры, патчинг памяти и прочие ужасы, на которые у нас нет времени. Надо по максимуму заиспользовать уже существующее решение.

Но надо как-то бороться с манглингом, C++ кодом, наследованиями и виртуальными функциями-членами.

В C++ есть два мощнейших инструмента, которыми мы воспользуемся для решения нашей задачи, это непрозрачные указатели и extern "C" .

extern "C" <> дает возможность C++ коду замаскироваться под C. Это позволяет генерировать чистые имена функций без манглинга.

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

Допустим, у нас есть такой C++ код:

Мы можем превратить в такой C заголовок:

И C++ часть, которая будет связующим звеном между C заголовком и C++ реализацией:

Не все методы классов пришлось обрабатывать таким образом. В BWAPI есть классы, операции над которыми можно реализовать самому, используя значения полей этих структур, например typedef struct Position < int x; int y; >Position; и методы вроде Position::get_distance .

Были и те, над которыми пришлось постараться особенным образом. Например, AIModule должен быть указателем на C++ класс с определенным набором виртуальных функций-членов. Тем не менее, вот заголовок и реализация.

Итак, спустя несколько месяцев кропотливой работы, 554 метода и десяток классов, на свет родилась кроссплатформенная библиотека BWAPI-C, которая позволяет писать ботов на C. Побочным продуктом стала возможность кросскомпиляции и возможность реализовать API на любом другом языке, который поддерживает FFI и соглашение о вызове cdecl.

Если вы пишите библиотеку, пожалуйста, пишите API на C.

Самая главная фишка BWAPI-C — это широчайшая возможность интеграции с другими языками. Python , Ruby , Rust , PHP , Java и многие многие другие умеют работать с C, следовательно на них тоже можно написать бота, если чуть-чуть поработать напильником и реализовать свои обертки.

API для StarCraft II

API для StarCraft II

Blizzard Entertainment и команда StarCraft II рады объявить о выходе API для StarCraft II! Нельзя не отметить старания исследователей, много лет работавших над искусственным интеллектом на основе первой части StarCraft. Теперь же, благодаря API для StarCraft II, исследователи, поклонники сектора Копрулу и энтузиасты смогут превратить StarCraft в платформу для дальнейшего развития ИИ. Сообщество получит «песочницу» для экспериментов, чтобы использовать и самообучающийся, и основанный на алгоритмах искусственный интеллект, а также создавать инструменты, которые будут полезны как любителям StarCraft II, так и исследователям ИИ.

Мы много работали, чтобы дать DeepMind возможность использовать API в своей облачной инфраструктуре, и сегодня результат этой работы увидит свет! Мы подготовили полностью рабочий программный пакет для Linux, созданный для осуществления исследовательской работы в облаке. Это автономный пакет, оптимизированный только для работы с API.

В ходе работы с DeepMind над этим проектом мы узнали много нового, и нам не терпится поскорее предоставить все эти инструменты вам — и увидеть результаты.

Что входит в текущую версию:

  • API для ИИ на основе скриптов;
  • API для ИИ на основе изображений (с поддержкой слоев);
  • документация, образцы кода и ботов;
  • поддержка игры ИИ против ИИ без подключения к сети;
  • набор анонимных записей игрового процесса в режиме 1 на 1*;
  • поддержка Windows и Mac;
  • полноценный программный пакет API для Linux.

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

Хотя мы и включили в комплект образцы кода и примеры ботов, важно подчеркнуть, что этот инструментарий станет основой для будущих исследований ИИ в StarCraft II. В конечном счете именно ваши воображение, изобретательность и усердие определят будущее этого проекта. Нам не терпится увидеть, чего смогут добиться энтузиасты в сфере искусственного интеллекта!

Получить дополнительную информацию о DeepMind и ознакомиться с документами компании можно в ее блоге (на английском языке).

Для начала вы можете принять участие в нашем проекте с открытым исходным кодом на GitHub:

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

Немного о кросскомпиляции

Если кратко, то в Rust она прекрасна! В два клика можно поставить множество тулчейнов для разных платформ. Конкретно тулчейн i686-pc-windows-gnu ставится командой:

Так же можно указать кофиг для cargo в корне проекта .cargo/config :

И это все, что нужно сделать, чтобы скомпилировать проект Rust из Linux под Windows.

Заключение

При реализации осталась нерешенная проблема: мы не контролируем уникальность ссылок, а одновременное существование &mut и & при изменении объекта приведет к неопределенному поведению. Беда. Halt пытался реализовать идиоматичные байндинги, но его запал слегка угас. Также для решения этой задачи придется качественно перелопатить C++ API и правильно проставить const квалификаторы.

Мне очень понравилось работать над этим проектом, я 하루종일 смотрел реплеи и глубоко погрузился в атмосферу. Эта игра оставила 믿어지지 않을 정도인 наследие. Ни одну игру нельзя 비교할 수 없다 по популярности с SC:BW, а ее влияние на 대한민국 정치에게 оказалось немыслимым. Прогеймеры в Корее 아마도 так же популярны, как и 드라마 주연 배우들 корейских дорам, транслирующихся в прайм-тайм. 또한, 한국에서 프로게이머라면 군대의 특별한 육군에 입대할 수 있다.

Пишем бота на C

Эта часть описывает общие принципы устройства модулей Starcraft.

Существуют 2 типа ботов: модуль и клиент. Мы рассмотрим пример написания модуля.

Модуль — это загружаемая библиотека, общий принцип загрузки можно посмотреть здесь. Модуль должен экспортировать 2 функции: newAIModule и gameInit .

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

newAIModule чуть посложнее. Он должен возвращать указатель на C++ класс, у которого существует виртуальная таблица методов с именами onXXXXX, которые вызываются на определенные игровые события. Определим структуру модуля:

Первым полем обязательно должен быть указатель на таблицу методов (магия, все дела). Итак, функция newAIModule :

createAIModuleWrapper — это еще одна магия, которая превращает С указатель в указатель на С++ класс с виртуальными методами функциями-членами.

module_vtable — это статическая переменная на таблицу методов, значения методов заполнены указателями на глобальные функции:

По названию функций и их сигнатур понятно, при каких условиях и с какими аргументами они вызываются. Для примера я все функции сделал пустыми, кроме

Данная функция вызывается при старте игры. В качестве аргумента передается указатель на текущий модуль. BWAPIC_getGame возвращает глобальный указатель на игру, который мы установили с помощью вызова BWAPIC_setGame . Итак, покажем пример кросскомпиляции и работы модуля:

Тыкаем в кнопочки и запускаем игру. Подробнее про запуск можно прочитать на сайте BWAPI и в BWAPI-C.

Результат работы модуля:

image

Чуть более сложный пример модуля, который показывает работу с итераторами, управлением юнитов, поиском минералов, выводом статистики можно найти в bwapi-c/example/Dll.c.

Читайте также: