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

В этом туториале вы создадите базового бота зергов, который сможет производить зерглингов и отправлять их по карте для атаки врага. Я предполагал, что у вас есть базовые знания программирования на Python и вы смогли установить PySC2 2.0.

Давайте начнем.

1. Создание базового агента.

Во-первых, давайте импортируем основные модули:

Теперь мы можем создать нашего агента:

step Метод - это основная часть нашего агента, именно здесь мы принимаем все решения. В конце каждого шага вы должны вернуть действие, в этом случае действие - ничего не делать. Скоро мы добавим еще несколько действий.

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

Я считаю, что новый формат намного проще, и ему легче следовать, Тимо здесь отлично поработал.

Полный код этого шага находится здесь.

2. Добавьте код запуска.

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

Я решил использовать здесь карту Abyssal Reef, она немного интереснее, чем карта Simple 64 из моих предыдущих руководств.

Здесь мы указываем, что первый игрок - наш агент, а раса агента - зерги. Вы можете выбрать другую расу, просто используя sc2_env.Race.protoss, sc2_env.Race.terran или даже sc2_env.Race.random, если вы смелы.

Затем мы указываем, что второй игрок является ботом, что означает, что он использует внутренний ИИ игры, раса бота случайна, а уровень сложности очень прост. Возможные уровни сложности: very_easy, easy, medium, medium_hard, hard, harder, very_hard, cheat_vision, cheat_money и cheat_insane. Обратите внимание, что medium_hard на самом деле «сложно» в игре, hard - «сложнее», harder - «очень сложно», а very_hard - «элитный».

В этом поле вы также можете указать другого агента, позволяя двум агентам играть друг против друга!

Здесь мы указываем разрешение экрана и миникарты, это значения по умолчанию, как и в PySC2 1.x. Эти разрешения по существу определяют, сколько «пикселей» данных находится в каждом векторном слое, эти слои включают такие вещи, как высота местности, видимость и владение единицей. Ваш бот может использовать эти функции для принятия решений.

Одной из новых функций PySC2 2.0 является добавление слоя RGB, по сути, визуализированной игры, которую увидит человек, и если вы хотите использовать этот слой, вам нужно будет указать здесь размеры как rgb_dimensions, однако мы не будем расскажите об этом в этом уроке.

Этот параметр определяет, сколько «игровых шагов» пройдет, прежде чем ваш бот выберет действие. По умолчанию это значение равно 8, что составляет примерно 300 APM при «нормальной» скорости игры, мы установим его на 160, чтобы уменьшить APM до 150. Дополнительный APM на данном этапе не требуется, и игра завершится быстрее. если вы предпримете меньше действий.

Здесь мы устанавливаем фиксированную продолжительность каждой игры, значение по умолчанию в PySC2 1.x составляло около 30 минут при нормальной скорости. В PySC2 2.0 вы можете установить это значение в 0, чтобы игра продолжалась столько, сколько необходимо.

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

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

Теперь вы можете запустить свой агент:

python zerg_agent.py

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

Полный код этого шага находится здесь.

3. Выберите дрон.

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

Одна из замечательных новых функций PySC2 2.0 - это добавление функциональных модулей. Я знаю, что это крутая функция, потому что я ее создал. Это позволяет вам получать информацию о единицах измерения на экране, которые вы не можете наблюдать или которые могут быть более сложными с помощью векторного слоя экрана. Мы будем использовать функциональные единицы для выбора дрона.

Еще одна интересная новая функция - добавление списка отрядов, который позволяет вам извлекать типы отрядов по их имени. Раньше мы кодировали наши собственные типы единиц с помощью чего-то вроде _TERRAN_SCV = 45, но теперь мы можем использовать что-то вроде units.Terran.SCV. Я тоже эту фичу сделал :)

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

Также нам понадобится модуль random для нескольких вещей.

Далее нам нужно включить функциональные блоки:

Теперь внутри метода step() давайте воспользуемся функцией функциональных единиц, чтобы получить список всех дронов на экране:

Это круто, правда ?! Благодаря новой точечной нотации все выглядит намного чище, спасибо, Тимо! Раньше вы могли сделать что-то вроде:

Теперь давайте выберем дрон:

Параметр select_all_type здесь действует как CTRL + щелчок, поэтому все дроны на экране будут выбраны. Как видите, координаты x и y дрона доступны как свойства. Есть еще много других свойств, к которым вы можете получить доступ, например health, shields, energy, build_progress и, что важно, ideal_harvesters и assigned_harvesters для баз и веспен.

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

Полный код этого шага находится здесь.

4. Постройте нерестилище.

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

Этот код проверяет как одиночный, так и множественный выбор, чтобы убедиться, что первый выбранный блок является правильным типом. В верхней части step() мы можем использовать этот метод с:

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

Затем мы можем выбрать случайную точку на экране, надеюсь, на некоторой ползучести:

В конце мы вводим в действие случайные координаты.

Дайте ему пробежку и посмотрите, как оно пойдет. Если повезет, у вас будет множество нерестилищ. Как сделать так, чтобы все наши дроны не превратились в нерестилища?

Давайте добавим еще один служебный метод для выбора единиц с заданным типом единиц:

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

Затем мы можем использовать этот метод для получения нерестилищ:

Так лучше, теперь мы будем строить нерестовый бассейн, только если у нас его еще нет.

Полный код этого шага находится здесь.

5. Стройте зерглингов.

Почти готово! Теперь у нас есть нерестилище, и мы можем наконец построить несколько зерглингов. Начнем с выделения всех личинок на экране:

Затем мы можем создать зерглингов. Поместите этот код чуть выше предыдущего блока:

Пройдите тест, у вас должна получиться пара Зерглингов.

Это здорово, но мы не можем построить достаточно зерглингов, чтобы быть эффективными, наш запас ограничен. Нам нужны Повелители.

Полный код этого шага находится здесь.

6. Создайте больше повелителей

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

И последнее, что мне не нравится, давайте добавим еще один метод:

Теперь мы можем заменить проверки действий:

а также:

а также:

Если вы сейчас протестируете своего бота, то обнаружите, что он производит много зерглингов, пора атаковать!

Полный код этого шага находится здесь.

7. Атака

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

Давайте создадим __init__() метод для инициализации переменной:

Это в начале метода step() добавьте следующее:

Код obs.first() проверяет, является ли это первым шагом игры. Затем мы получаем центральные координаты x и y наших юнитов на миникарте. Для этого есть векторный слой, который показывает все юниты на миникарте в зависимости от того, кому они принадлежат. Я объясню это более подробно в будущих уроках.

Теперь у нас есть место для атаки, давайте приступим. Сначала выбираем нашу армию:

Теперь перед этим мы можем атаковать:

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

Да, это больше похоже на то!

Полный код этого шага находится здесь.

Если вам нравится этот урок, поддержите меня на Patreon. Также присоединяйтесь ко мне в Discord или подписывайтесь на меня в Twitch, Medium, GitHub, Twitter и YouTube.