Skip to content
Permalink
master
Go to file
 
 
Cannot retrieve contributors at this time
387 lines (297 sloc) 33 KB

Технические правила участия в AiCups 3

Старт соревнования: 30 августа 2018 года.

Соревнование среди создателей искусственного интеллекта. На этот раз предлагаем вам написать своего бота, который сойдется в сложной битве против бота соперника в зубодробительной игре по мотивам Drive Ahead.

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

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

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

Решения можно присылать на любом языке программирования из списка поддерживаемых:

  • Elixir / .zip, .ex
  • Rust / .zip, .rs
  • Scala / .zip, .scala
  • C++11 / .zip, .h, .cpp
  • C++14 / .zip, .h, .hpp, .cpp
  • C++17 / .zip, .h, .hpp, .cpp
  • C# / .zip, .cs
  • Java1.8 / .zip, .java
  • Kotlin / .zip, .kt
  • Haskell / .zip, .hs
  • Go / .zip, .go
  • Python 2.7 / .zip, .py
  • Python 3.6 / .zip, .py
  • PHP7 / .zip, .php
  • Node JS / .zip, .js

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

В этом соревновании используется физический движок Chipmunk. Это популярный кроссплатформенный движок с открытым исходным кодом, написанный на C, он используется во множестве мобильных игрушек, и на нём построены другие движки, такие как Cocos2D, Apportable и Marmalade.

Для удобства участников, а также для снижения пиковых нагрузок на систему запуска, мы подготовили программу для локального запуска и отладки — Local Runner (далее обозначается как LR или ЛР). Она написана на Python 3.4 с использованием визуализатора Pyglet и поставляется в виде исходных кодов. Детальные инструкции по настройке и использованию Вы найдете в разделе 3.

Гайд по быстрому старту находится в файле QUICKSTART.md

С организаторами соревнования можно связаться:

  • в группе Telegram @aicups
  • с помощью формы обратной связи на сайте соревнования  

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

Объявление о конкурсе и политика выдачи призов будет опубликована в понедельник 03 сентября 2018 г. на официальном сайте чемпионата.

Удачи!

1. Описание механики

Игроку предлагается написать стратегию для искусственного интеллекта, который будет управлять автомобилем и пытаться вывести из строя автомобиль соперника нажатием специальной кнопки на его корпусе.  Игры идут до 5 смертей, тот, кто выжил — победитель. Возможны ничьи. При ничейном исходе жизни уменьшаются на единицу у обоих игроков. Кроме этого, было поставлено ограничение сверху на одну игровую сессию. Если в течение 600 тиков (тик — единица времени в игровом мире) победитель так и не будет выявлен, то на карте начнет расти количество мусора. До чьей кнопки мусор доберется первым, тот и проиграет.

Изображение карты с примером координат

На рисунке представлен пример карты. Начало отсчета расположено в левом нижнем углу.

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

Одновременно на одной карте соревнуются два бота, созданные участниками. Каждому боту соответствует один игровой объект типа "Машина". Вся игра продолжается до максимально заданного число игровых тиков. Каждый тик выполняется по алгоритму:

  • игровым ботам передаётся состояние мира и в ответ ожидается команда — "left" (двигаться влево), "right" (двигаться вправо) и "stop" (тормоз);
  • каждая полученная команда в этот же момент будет применена;

После получения всех команд просчитывается новое состояние мира. Нажатие на кнопку противника приносит победу в одном из матчей игровой сессии. Максимально возможное количество матчей в игровой сессии — MATCHES_COUNT = 9).

1.1. Игровые объекты и концепции

1. Машина (Car) — объект, которым управляет решение игрока. Может получать на вход команды "left" (двигаться влево), "right" (двигаться вправо) и "stop" (тормоз). На корпусе машины есть кнопка.

Основные параметры машин задаются переменными:

  • car_body_poly — модель машины (задается списком координат точек)
  • car_body_mass — масса машины
  • button_position — координаты кнопки
  • button_angle — угол поворота кнопки
  • button_hw — размеры кнопки
  • max_speed — максимальная скорость машины

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

Параметры для машины типа Buggy:

car_body_poly = [
    (0, 6),
    (0, 25),
    (33, 42),
    (85, 42),
    (150, 20),
    (150, 0),
    (20, 0)
]

car_body_mass = 200
    
button_position = (40, 42)
    
button_hw = (1, 38)
    
max_speed = 70

Параметры для машины типа SquareWheelsBuggy (наследуется от Buggy):

max_speed = 50
car_body_mass = 230

Параметры для машины типа Bus:

car_body_poly = [
    (0, 6),
    (8, 62),
    (136, 62),
    (153, 32),
    (153, 5),
    (110, 0),
    (23, 0)
]
car_body_mass = 700
    
button_position = (137, 59)
button_angle = -math.atan(3/1.7)
button_hw = (1, 28)
    
max_speed = 45

Для колес каждой машины также задаются масса, позиция и радиус. Полную информацию об этом можно найти в папке mechanic/game_objects в файлах base_car.py и cars.py, а также формат данных в разделе разделе 2.1.

2. Игровой матч (Match) — игровая сессия проводится в несколько матчей. Для каждого матча случайным образом выбираются карта и модель машины. Каждый раз, когда была нажата кнопка одного из игроков, начинается новый раунд с новыми параметрами. Максимальное количество раундов задается константой MATCHES_COUNT = 9. Максимальное отведенное на все матчи вместе количество тиков задается константой MAX_TICK_COUNT = 20000, максимальное время — MAX_EXECUTION_TIME = 120 секунд.

3. Мусор (Deadline) — когда количество тиков в игре достигает числа, установленного в TICKS_TO_DEADLINE = 600, снизу карты начинает подниматься мусор. Когда линия мусора касается кнопки одного из игроков, он проигрывает.

4. Карта (Map) — каждый игровой матч, из которых состоит сессия, проводится на одной из доступных карт:

  • PillMap
  • PillHubbleMap (наследуется от PillMap)
  • PillHillMap (наследуется от PillMap)
  • PillCarcassMap (наследуется от PillMap)
  • IslandMap
  • IslandHoleMap

Основные параметры, описывающие игровую карту:

  • base_arcs — базовые сегменты арок границ карты (задаются через точку, радиус, стартовый угол, конечный угол, количество сегментов)
  • base_segments — базовые сегменты границ карты
  • additional_arcs — дополнительные сегменты арок (задаются аналогично базовым)
  • additional_segments — дополнительные сегменты границ
  • segment_friction — коэффициент трения о поверхность
  • segment_height — толщина границы карты, по-умолачнию 10
  • cars_start_position — стартовые позиции машин

Максимальные размеры карты задаются в классе Map переменными max_width и max_height и равны соответственно 1200 и 800.

Параметры для карты PillMap:

base_arcs = [
    ((300, 400), 300, math.pi/2, math.pi * 3/2, 30),
    ((900, 400), 300, math.pi/2, -math.pi / 2,  30),
]
    
base_segments = [
    ((300, 100), (900, 100)),
    ((300, 700), (900, 700))
]

Параметры для карты PillHubbleMap (наследуется от PillMap):

additional_arcs = [
    ((600, -150), 300, math.pi/3.2, math.pi/1.45, 30)
]

Параметры для карты PillHillMap (наследуется от PillMap):

additional_arcs = [
    ((300, 300), 200, -math.pi / 2, -math.pi / 6, 30),
    ((900, 300), 200, math.pi * 3 / 2, math.pi * 7 / 6, 30),
]
additional_segments = [
    ((465, 195), (735, 195))
]

Параметры для карты PillCarcassMap (наследуется от PillMap):

additional_segments = [
    ((300, 400), (900, 400))
]

Параметры для карты IslandMap:

base_segments = [
    ((100, 100), (1100, 100)),
]

Параметры для карты IslandHoleMap:

base_segments = [
    ((10, 400), (50, 200)),
    ((50, 200), (300, 200)),
    ((380, 150), (820, 150)),
    ((900, 200), (1150, 200)),
    ((1150, 200), (1190, 400))
]
base_arcs = [
    ((300, 100), 100, math.pi / 6, math.pi / 2, 30),
    ((900, 100), 100, math.pi / 2, math.pi * 5 / 6, 30),
]

Полная информация о картах может быть найдена в файле mechanic/game_objects/maps.py.

1.2. Игровые взаимодействия

Все игровые взаимодействия обсчитываются физическим движком Chipmunk, включая коллизии. Подробнее на официальном сайте

1.3. Условия победы

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

  • игровой объект перевернулся и нажал на свою кнопку самостоятельно;
  • игровой объект покинул пределы карты;
  • уровень мусора достиг кнопки игрового объекта.

Игра длится фиксированное число тиков, однако, она завершится раньше, если на карте остался всего один бот с количеством очков > 0.

Максимальное количество очков в игре = 5.

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

2. Создание решения

Решение пользователя - это программа-бот, которая взаимодействует с сервером через потоки стандратного ввода-вывода. Она может быть написана на любом языке из списка поддерживаемых. Для некоторых языков будут доступны стандартная библиотека, библиотека для разбора JSON, и дополнения, предложенные участниками. Приветствуются pull-request'ы в репозиторий соревнования.

Решение предоставляется участником на сайте соревнования как ZIP-архив, внутри которого обязательно есть файл с названием main, корректный для выбранного участником языка программирования. Последнее включает в себя:

  • корректное расширение (.py для Python, .cpp для С++ и т. д.)
  • корректный синтаксис (к примеру, внутри С++ должна быть функция main()),
  • корректные подключения других модулей/пакетов выбранного языка  

После загрузки решение будет сначала скомпилировано (для компилируемых языков: C++, Go, Java, C#), а затем запущено в специальном docker-контейнере. Взаимодействие решения с внешним миром происходит происходит через потоки ввода/вывода.

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

2.1. Архитектура решения

Самое простое решение на языке программирования Python 3 будет состоять из одного файла main.py. Клиент инициирует сессию и запускает этот скрипт в начале работы. Клиент скрывает внутри себя работу с сетью и обработку ошибок, и является посредником между игровой механикой и решением участника. Он передает JSON от мира в стандартный поток ввода (stdin) и забирает ответ из стандартного потока вывода (stdout) (для Python это sys.stdin и sys.stdout). Напомним, что для корректной работы решение должно запускаться с параметрами для ввода/вывода без буфера (для Python это флаг -u при запуске интерпретатора).

Максимальный размер файла стратегии — 20 Мб.

Решение стартует один раз и далее работает в бесконечном цикле. Обрабатывать остановку не обязательно, в конце игры dockerd завершит работу всех контейнеров. Внутри цикла заключается обработка ввода/вывода, происходит обработка JSON и вызов главного обработчика (пример простой стратегии на Python):

import json
import random
    
while True:    
    z = input()  # получение ответа от сервера
    commands = ['left', 'right', 'stop']  # доступные команды
    cmd = random.choice(commands)  # случайный выбор действия
    print(json.dumps({"command": cmd, 'debug': cmd})  # отправка результата

После старта игры, сервер-механика рассылает всем подключившимся решениям конфигурацию первого матча. В неё входят следующие параметры:

  • typenew_match
  • params — параметры игрового мира
    • my_lives - число жизней стратегии

    • enemy_lives — число жизней противника

    • proto_map — описывает свойства карты

      • external_id — внешний id карты
      • segments — сегменты карты
    • proto_car

      • external_id - внешний id машины

      • button_poly - полигон кнопки

      • car_body_poly - полигон машины

      • car_body_mass- масса машины

      • car_body_friction - трение кузова машины

      • car_body_elasticity - эластичность кузова машины

      • max_speed - максимальная угловая скорость колес

      • max_angular_speed - максимальная угловая скорость в воздухе (данный параметр больше не используется и скоро будет удален)

      • torque - крутящий момент кузова машины в воздухе

      • drive - привод машины (передний, задний, полный)

      • rear_wheel_radius - радиус заднего колеса

      • rear_wheel_mass - масса заднего колеса

      • rear_wheel_position - положение заднего колеса в координатах относительно кузова машины

      • rear_wheel_friction - трение заднего колеса

      • rear_wheel_elasticity - эластичность заднего колеса

      • rear_wheel_groove_offset - смещение крепления заднего колеса относительно кузова

      • rear_wheel_damp_position - положение пружины заднего колеса

      • rear_wheel_damp_length - длина пружины заднего колеса

      • rear_wheel_damp_stiffness - жесткость пружины заднего колеса

      • rear_wheel_damp_damping - затухание пружины заднего колеса

      • front_wheel_radius - радиус переднего колеса

      • front_wheel_mass - масса переднего колеса

      • front_wheel_position - положение переднего колеса в координатах относительно кузова машины

      • front_wheel_friction - трение переднего колеса

      • front_wheel_elasticity - эластичность переднего колеса

      • front_wheel_groove_offset - смещение крепления переднего колеса относительно кузова

      • front_wheel_damp_position - положение пружины переднего колеса

      • front_wheel_damp_length - длина пружины переднего колеса

      • front_wheel_damp_stiffness - жесткость пружины переднего колеса

      • front_wheel_damp_damping - затухание пружины переднего колеса

      Для машины с квадратными колесами еще приходит

      • squared_wheels - признак квадратных колес

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

Формат тика:

  • typetick
  • params — параметры игрового мира
    • my_car [ (x_нижнего_левого_угла_машины, y_нижнего_левого_угла_машины), угол машины, 1 | -1 (слева или справа находится машина), (x_заднего_колеса_машины, y_заднего_колеса_машины, угол_заднего_колеса_машины), (x_переднего_колеса_машины, y_переднего_колеса_машины, угол_переднего_колеса_машины) ]
    • enemy_car [ (x_нижнего_левого_угла_машины, y_нижнего_левого_угла_машины), угол машины, 1 | -1 (слева или справа находится машина), (x_заднего_колеса_машины, y_заднего_колеса_машины, угол_заднего_колеса_машины), (x_переднего_колеса_машины, y_переднего_колеса_машины, угол_переднего_колеса_машины) ]
    • deadline_position — положение линии смерти

Пример конфигурации мира можно найти в файле match_params_example.json

Ответ на один тик не должен превышать REQUEST_MAX_TIME = 5 секунд. Суммарное время ответов на всю игру не должно превышать MAX_EXECUTION_TIME = 120 секунд для MAX_TICK_COUNT = 20000 тиков.

3. Особенности запуска Local Runner

В этот раз Local Runner написано на языке программирования Python версии 3.4. Для запуска потребуется интерпретатор Python версии 3.4 или новее. Local Runner нужен для демонстрации и тестирования механики игры, при помощи него игроки могут пробовать свои решения на собственном компьютере. Аналогичный код работает у нас на серверах для запуска игровых сессий.

Интерфейс программы можно увидеть на рисунке ниже:

Local Runner

Белое поле со схематично изображенными игровыми объектами. Машинки игроков отображаются без спрайтов, разными цветами выделены корпус автомобиля, колеса, кнопка. При запуске без явного указания команды для старта стратегии, в Local Runner можно управлять машинкой с клавиатуры, используя стрелочки (влево, вправо, вниз для тормоза). В таком режиме удобно попробовать управление машинкой и найти пищу для размышлений.

В папке examples можно найти примеры простых стратегий на различных языках программирования. Его поведение определяется случайным выбором одной из доступных команд. Запустить Local Runner можно командой python localrunner.py при условии, что установлены все зависимости из requirements.txt.

Аргументы, которые можно передать в Local Runner:

  • -h или --help — показать справку
  • -f или --fpкоманда для запуска исполняемого файла стратегии первого игрока
  • --fpl — путь к логам первого игрока
  • -s или --spкоманда для запуска исполняемого файла стратегии второго игрока
  • --spl — путь к логам второго игрока
  • -m или --matches — список пар (карта, машина) для игровых матчей (-m PillHillMap,Bus PillHillMap,Buggy PillHubbleMap,Buggy)

Таким образом, примеры запуска при установленном python3 и зависимостями:

  • $ python3 localrunner.py — запуск с управлением с клавиатуры
  • $ python3 localrunner.py -f "python strategy.py" — запуск с явным указанием первого решения на python, лежащего в той же папке
  • $ python3 localrunner.py -f "java -jar /maic3/strategy.jar" — запуск решения на Java, лежащего по абсолютному пути в условной папке /maic3/
  • $ python3 localrunner.py -f "java -jar ../strategy_1/solution.jar" -s "../strategy_2/solution.exe" — запуск двух стратегий по относительному пути в папке на один уровень вверх.

Внимание! Под командой запуска подразумевается полная команда, используемая для исполнения решения-стратегии. Частой ошибкой участников является попытка использовать, например, main.py вместо python main.py или main.cs вместо пути к скомпилированному бинарному файлу.

Важно! Не стоит забывать про буферизацию ввода/вывода в используемом инструментарии (например, интерпретатору python нужно передать флаг -u или выставить соответствующую переменную окружения). Без этого корректная работа не гарантирована.

Local Runner поддерживает переопределение параметров мира с помощью переменных окружения. В папке mechanic содержатся файлы:

  • constants.py
    • TICKS_TO_DEADLINE = 600 — количество тиков до начала движения мусора
    • MATCHES — список матчей в формате "{карта},{машина}"
    • MAX_EXECUTION_TIME = 120 секунд — всё доступное стратегии время
    • REQUEST_MAX_TIME = 5 миллисекунд — максимальное время, отведенное на один тик
    • MAX_TICK_COUNT = 20000 — максимальное количество тиков на игру
    • SEED — зерно мира, влияет на генерацию матчей
    • MATCHES_COUNT = 9 — максимальное количество матчей
  • game.py
  • match.py
  • player.py
  • strategy.py Классы, описанные в последних четырех файлах отвечают за создание игровых матчей, хранение информации об игроках и игровых стратегиях.

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

4. Отладочный просмотр на сайте

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

Спасибо, что участвуете в наших чемпионатах!

You can’t perform that action at this time.