Code of War, David Mouton

На семинаре, который провел Давид Мутон, можно было написать своего бота для игры Code of War, и испытать его против ботов других участников.

Видеоверсия семинара доступна на сайте Haxe.

В принципе, если вам интересно самим попробовать игру, то все, что нужно иметь на машине, это git-клиент, nodejs и npm.

Код игры можно склонировать командой:

git clone https://gitlab.com/damoebius/codeofwar.git

Также нужно будет установить зависимости командой:

cd codeofwar & npm i

(плюс, конечно же, лучше ознакомиться и с readme проекта - https://gitlab.com/damoebius/codeofwar/blob/master/README.md)

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

В игре участвует два игрока (два бота).

Каждый ход на планетах “рождаются” новые поселенцы.

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

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

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

Размер планет выбирается случайно, от него зависит максимальная численность населения. Каждый ход на планете происходит прирост населения - 5 поселенцев (эту и другие константы всегда можно подправить в классе с константами - Game.hx).

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

Каждый ход игра осуществляет следующие действия:

  • посылает игрокам полную информацию о состоянии игры (количество поселенцев на планета, информация о всех кораблях, об их экипажах, пунктах отправления и назначения, о времени отправления и т.д.);
  • получает от каждого игрока список “приказов”. В игре есть только один вид приказов - отправить корабль с планеты на планету (на любую планету).
  • обновляет на основании действующих приказов текущее состояние игры;
  • проверяет не достигнуто ли условие окончания партии.

Во время обновления состояния игры происходят расчеты:

  • отправления кораблей, которые сокращают численность населения планеты, с которой отправлен корабль;
  • движение кораблей (корабли движутся с постоянной скоростью к точке назначения);
  • обработка прибытия корабля к точке назначения. Если планета уже принадлежит игроку, то численность ее населения возрастает на численность экипажа корабля. В противном случае сравнивается численность экипажа корабля и населения планеты, и если на корабле окажется больше людей, чем на планете, то планета захватывается игроком, при этом, если, например на планете было 50 вражеских поселенцев, а на корабле - 60, то после захвата планеты на ней останется 10 ваших поселенцев.

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

Также игрок может быть дисквалифицирован по следующим причинам:

  • попытка отдать приказ, который не может быть выполнен;
  • “бездействие” бота в течение 1000 мс;
  • вызов исключения (throw exception) во время работы бота.

Более подробно с правилами игры, а также с основными игровыми сущностями, можно ознакомиться в readme проекта.

Логика бота игрока должна быть описана в классе MyIA.hx в методе getOrders(), который на входе получает игровой контекст - информацию о состоянии игры, а на выходе должен возвращать список приказов.

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

Протестировать своего бота можно на локальном сервере, для этого нужно:

1. собрать проект:

npm run build

2. запустить сервер:

npm start

3. собрать бота:

npm run build:ai

4. перейти на страницу сервера - http://localhost:8092/play.html

(полный список npm-команд можно посмотреть в файле package.json)

На локальном сервере против игрока выступает простенький Basic bot.

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

npm run login BotName BotPassword

а затем выполнить команду:

npm run publish

После этого ваш бот появится в списке доступных ботов.

Далее Давид показал и пояснил код пары ботов.

В качестве самого примитивного бота Давид написал бот Sacrificer, который каждый ход отправляет корабль с одним поселенцем к родной планете противника. Естественно, что такой бот проиграет, ведь такая стратегия лишена смысла.

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

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

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

Третьего бота написал Роберт Конрад, который назвал его Robbot. Логика этого бота оказалась очень проста и уместилась по словам Роберта в 15 строк кода - каждый ход бот посылает корабль с 20 поселенцами на самую слабую планету противника.

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

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

Надеюсь, что приз все-таки Роберт получил.

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

В качестве возможного улучшения удобства для игроков-программистов я бы предложил добавить на сайт онлайн редактор кода для ботов. При этом код ботов можно либо интерпретировать с помощью hscript, либо компилировать их на сервере, как это сделано на try.haxe.org или kodegarden.org.