Mini AI Cup #3: Пишем топового бота |
||
МЕНЮ Искусственный интеллект Поиск Регистрация на сайте Помощь проекту ТЕМЫ Новости ИИ Искусственный интеллект Разработка ИИГолосовой помощник Городские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Техническое зрение Чат-боты Авторизация |
2018-11-20 18:31 В начале осени завершился конкурс по написанию ботов Mini AI Cup #3 (aka Mad Cars), в котором участникам необходимо было сражаться на машинках. Участники много спорили о том, что будет работать и что не будет, высказывались и проверялись идеи от простых if’ов до обучения нейросетей, но топовые места заняли ребята с, так называемой, "симуляцией". Давайте попробуем разобраться с тем, что это такое, сравним решения за 1ое, 3е и 4ое места и порассуждаем на тему других возможных решений. Дисклеймер Статья была написана в соавторстве с Алексеем Дичковским (Commandos) и Владимиром Киселевым (Valdemar). Для тех, кому хочется просто почитать про решения победителей, советую сразу начинать с пункта "Симуляция". Постановка задачи В этот раз механика мира сильно походила на мобильную игру Drive Ahead: игрокам давалась машина с расположенной на ней кнопкой; задача — нажать кнопку врага быстрее, чем это сделает он. Если за 600 игровых тиков никто не побеждает, карта начинает погружаться в кучу мусора, которая также может нажать на кнопку. Другими словами, нужно беречь свою кнопку от врагов, окружающего мира и кучи мусора (жизненно, да). Каждому игроку давалось по 5 жизней, игра шла от 5 до 9 раундов, пока у кого-то не заканчивались жизни. Каждый раунд проходил на случайной карте и машинках, одинаковых для обоих участников. Всего было 6 разных карт и 3 вида автомобилей — итого 18 различных комбинаций. Каждый раунд разбит на тики. Тик — это один ход, как в шахматах. Разница только в том, что ходят оба игрока одновременно. Бывают соревнования, где все ходят по очереди, либо можно делать действие только раз в несколько ходов и выделять юнитов рамкой.Каждый тик боту приходит состояние мира и дается возможность совершить 3 действия: Более полные правила можно найти тут. А игры финала посмотреть тут. Общее описание решения Большинство соревнований по написанию ботов очень похожи: есть конечное число тиков (тут для одного раунда примерно 1500 максимум), есть конечное число возможных действий, нужно выбирать такую последовательность действий, чтобы быть лучше, чем твои противники. Чуть позже еще вернемся к тому, что значит "быть лучше", а пока разберемся с тем, как бороться с главной проблемой — огромным количеством вариантов действий: на старте у нас есть одно начальное состояние, затем каждая машинка может двигаться тремя разными способами, что дает нам 9 разных комбинаций для двух машинок, к 1500 ходу это будет уже 9^1500 различных комбинаций… Что чуть больше, чем хотелось бы, если мы планируем успеть перебрать их за время существования Вселенной. Тут мы и подошли к тому, что такое симуляция. Это не какой-то алгоритм, а просто воссоздание правил игры с достаточной или полной точностью, чтобы можно было перебирать решения. Разумеется, мы будем перебирать не все решения, а только часть из них. Для этого будет использоваться алгоритм поиска — в дереве состояний игры мы ищем наилучшее для нас. Алгоритмов достаточно много (от минимакса до MCTS), каждый имеет свои нюансы. Лучше всего ознакомиться с тем, какие решения писали участники прошлых соревнований по ИИ. Это даст базовое понимание, в каких условиях алгоритмы работают, а в каких не очень. Много ссылочек для этого есть в специальном репозитории. При выборе алгоритма следует учитывать:
В данном соревновании на 1 тик давалось около 10-13мс (2 минуты на всю игру). За это время бот должен был считать данные, принять решение и отправить команду для движения. Этого хватало, чтобы просимулировать порядка 500-1000 ходов. Перебирать все состояния не получится. Самый простой алгоритм поиска может выглядеть как сравнение трех вариантов движения: "50 тиков едем влево", "50 тиков едем вправо", "50 тиков жмем стоп". И как бы просто это не звучало, это не сильно далеко от решения победителя. Т.к. мы считаем только на 50 ходов вперед, что в большинстве случаев не досчитывает до конца игры, то нам нужна функция оценки, которая скажет, насколько хорошо и плохо состояние мира для нас. Чаще всего она построена на эвристиках и понимании, что важно для победы. Например, в конкурсе Russian AI Cup 2014 года были гоночки, но победить можно было и приехав последним, если набрать больше бонусных очков. Значит и функция оценки должна стимулировать сбор очков одновременно с быстрым движением по трассе. Оценка может быть посчитана только для последнего состояния симуляции (через 50 тиков) или как сумма оценок промежуточных состояний. Часто оценка "затухает" по времени, чтобы больше влияли состояния, которые произойдут раньше. Т.к. мы не можем наверняка предсказать врага, то и будущие варианты имеют меньшую вероятность случиться, не будем на них сильно полагаться. Также этот прием заставляет бота быстрее выполнять поставленные задачи, а не откладывать все на потом. Но стоит отметить и то, что бот будет меньше рисковать ради последующей выгоды. Раз уж мы собрались предсказывать состояния мира в ответ на наши действия, то нам надо как-то моделировать поведение врагов. Тут нет ничего сложного и существуют пара распространённых вариантов:
Если реализовать все вышеописанные шаги, то, скорее всего, получится весьма неплохой бот, особенно если удастся подобрать хорошую функцию оценки. Но, просматривая свои бои, можно заметить, что в определенных ситуациях он ведет себя странно. Исправить функцию оценки под эти ситуации может быть сложно, либо велик риск сломать другую логику. Тут на помощь приходят костыли и if'ы. Да, последние дни соревнования часто сводятся к написанию костылей и if’ов, чтобы исправить недочеты в каких-то конкретных условиях. Лично я очень не люблю эту часть, но уже не раз замечал, что именно костыли в финале могут влиять на расположение мест в первой десятке, а значит один ненаписанный if может стоить вам призового места (мое сердечко болит, когда я пишу эти слова, я тоже люблю красивые алгоритмы и решения). Q: Можно ли обойтись совсем без симуляции?A: Да, можно использовать решения на эвристиках (деревья принятия решений, куча if'ов и т.п.). Есть хорошая статья с архитектурами ИИ на эвристиках. Q: Насколько использование симуляции лучше подходов на эвристиках?A: Все зависит от задачи. Например, тут некоторые сочетания карт и машин можно было жестко закодировать if'ами и всегда побеждать (или ничья). Однако часто симуляция находит решения, до которых сложно додуматься самому, либо сложно реализовать эвристиками. В данном конкурсе, когда ты переворачиваешь другую машинку, то решения на симуляциях ставили свое колесо на колесо врага, что отключало флаг "в воздухе", а значит враг не мог применять вращение кузова и повернуться обратно на колеса. Но решение не задумывалось о смысле этого, оно просто находило варианты, где враг быстрее упадет на крышу и нажмет свою кнопку. Q: Нейронные сети и RL?A: Как бы это не было популярно, в соревнованиях ботов такие решения редко показывают себя хорошо. Хоть нейросети и не нуждаются в симуляции, т.к. могут просто выдавать действие исходя из входных параметров текущего состояния, им все еще нужно как-то обучаться, а для этого часто приходится писать симулятор, чтобы гонять игры тысячами локально. Лично я верю, что у них есть потенциал. Быть может ими можно решать часть задачи, либо использовать в условиях очень ограниченного времени на ответ. ПримечаниеПо поводу конечного числа возможных действий стоит уточнить, что иногда разрешено "плавно" регулировать какой-то параметр. Например, не просто ехать вперед, а каким-то процентом мощности. В этом случае "конечности" числа выводов легко добиться просто используя несколько значений, например, 0%, 25%, 50%, 75% и 100%. Чаще всего хватает всего двух: "полностью включено" и "полностью выключено". Симуляция В данном соревновании использовали готовый движок chipmunk physics. Ожидания организаторов были в том, что он старый, проверенный временем и имеет много врапперов, чтобы каждый мог включить его в свое решение... В суровой действительности движок выдавал каждый раз разные значения, что делало проблематичным его перезапуск для просчета вариантов ходов. Проблема решалась “в лоб” — писался свой аллокатор памяти на С и целиком копировался кусок памяти с состоянием мира. Такой аллокатор ставил крест на возможности писать решения на языках кроме С++ (на самом деле это было возможно, но очень трудозатратно и аллокатор все равно пришлось бы писать на С). Кроме того, на точность предсказания влиял порядок добавления элементов в игровой мир, что требовало очень точного копирования кода, который использовали организаторы для просчета игр. А вот он уже был на Python. Последним гвоздем в крышку гроба других языков программирования стало то, что движок старый и содержит много оптимизаций, которые невозможно точно воссоздать за время соревнования, чтобы получить свою урезанную версию симуляции физики. В итоге, движок, который должен был дать всем участникам равные условия для симуляции ходов, стал самой сложной преградой для этого. Преодолеть ее смогли человек 10. Первые 7 мест лидерборда заняли исключительно ребята, сделавшие точную симуляцию, что может служить неким доказательством ее важности в таких конкурсах. За исключением пары участников, которые смогли залезть во внутренности chipmunk’а и оптимизировать копирование его состояния, остальные имели примерно равную по производительности симуляцию (что делало соревнование немного более интересным, т.к. ты знаешь, что борьба идет за алгоритм решения, а не "кто больше просчитает ходов"). Алгоритм поиска и предсказание противника С этого пункта начинается раздельное описание решений. Описание алгоритмов будет вестись от лица его автора. Владимир Киселев (Valdemar) 4 место Для поиска по пространству решений был использован случайный поиск (Monte Carlo). Алгоритм выглядит следующим образом:
Мой симулятор выдавал ~100k симуляций мира за 1 секунду, учитывая что на тик есть в среднем ~12мс, получаем 1200 действий на тик. То есть за 1 тик успеваем пройти полный цикл около 20ти раз. Для поиска оптимального решения такого количества итераций явно не хватало. Поэтому была реализована идея с “растягиванием” действий: вместо генома из 60 ходов будем оперировать цепочкой из 12 “растянутых” ходов — считаем, что каждое действие длится 5 тиков подряд. Следует отметить приемы, которые позволили значительно улучшить качество работы алгоритма:
Во время конкурса активно использовал инструменты для локальной разработки, которые позволили быстро находить баги и сосредоточиться сосредоточится на слабых местах стратегии:
mortido:Считать раз в 5 тиков выглядит рискованно, особенно, если противник сильно отходит от предсказанных тобою вариантов. С другой стороны, в данном игровом мире за 5 тиков не так много и происходило. Commandos:Менять по пару действий при таком кол-ве симуляций выглядит не очень осмысленно, ведь за одно действие изменений происходит очень мало. А вот при растягивании одного действия на 5 тиков смысла, кажется, становится больше. Александр Киселев (mortido) 3 место Вооружившись статьями победителей других конкурсов я решил использовать генетический алгоритм. Получилось, правда, что-то похожее на случайный поиск или даже симуляцию отжига, но об этом чуть позже. Закодируем решение массивом из 40 чисел, где -1, 0 и 1 соответствуют движению Вначале каждого раунда я считал сколько времени я уже потратил за всю игру, считал новый лимит времени исходя из того, сколько максимально еще будет раундов, а каждый раунд я полагал длительностью 1200 тиков. Т.о. изначально я старался тратить не больше 11мс на ход, но мог немного "разгуляться" под конец, если предыдущие раунды были быстрее 1200 тиков. Valdemar:Интересно, что у меня эта фишка ухудшила игру. Оказалось, что лучше всегда тратить 20-30мс, чем сначала 11, а под конец 60 Треть этого времени я искал лучший ход противника, остальное уходило на расчет собственного решения. При поиске хода для врага мое поведение моделировалось как лучшее с прошлого хода, сдвинутое на 1 тик. Т.е. как будто я продолжаю действовать согласно плану, составленному в прошлый тик, а он пытается мне противостоять. Сам поиск решения был одинаковый и для себя и для соперника:
В результате нам вернется последовательность действий, которая считается оптимальной. Первый ход в ней и отправляется как действие бота. К сожалению, в моем плане был серьезный недостаток, т.к. количество симуляций, которые можно сделать за тик, было очень небольшое (в т.ч. и из-за долгой оценочной функции), то на сервере соревнования 4 пункт выполнялся всего 1 раз, а для врага и вовсе не выполнялся полностью. Это делало алгоритм больше похожим на случайный поиск или симуляцию отжига (т.к. мы успевали мутировать 1 раз решение с прошлого хода). Менять что-то было уже поздно, да и 3е место удержать удалось. Важным является реализация алгоритмов скрещивания, мутации и генерации начальных случайных решений, т.к. от этого зависит то, какие решения будут проверятся, а полный рандом не так хорош, как может показаться на первый взгляд (он будет работать, но потребуется гораздо больше вариантов перебрать). В итоговой версии генерация случайных решений происходила отрезками, что исключало "дрыгающиеся" на одном месте решения:
По похожей технологии происходила и мутация — случайный отрезок решения заменялся на случайную команду. Скрещивание же происходило выбором точки, до которой бралось решение от 1 родителя, а после от 2-го. Мне понравилось, что мы используем все доступное нам время, для поиска лучшего решения. При этом не страшно, если решение не самое лучшее — мы сможем улучшить его на следующем тике, т.к. оптимизация получается "размазанной" по времени. Также мы всегда пытаемся предугадать, как враг нам испортит жизнь и противостоять этому. Разумеется факт, что часть задумки не работала из-за лимита времени, сильно портит радужную картину. Сейчас я бы не стал реализовывать эту идею в таких условиях, а склонился бы к варианту случайного поиска или симуляции отжига Valdemar: Генетика из 1го поколения больше напоминает случайный поиск, думаю, применение твоих методов рандомизации без скрещивания повысило бы производительность и выдало лучший результат. Commandos: Про ограничение времени — с нашим кол-вом симуляций я про генетику даже не задумывался бы. И мне всё же очень не нравится цикличность — выбрали лучшее для врага, затем выбрали лучшее для себя. Кажется на следующем ходу от врага будут найдены контрмеры, как и контрмеры на контрмеры… Но это актуально только в случае, если у нас много больше времени для рассчётов. Можем случайно получить "дрыгающиеся на одном месте решения”. Хотя в нашем случае хорошо было найти хоть что-то. Алексей Дичковский (Commandos) 1 место Для противника всегда симулировал движение во всех трёх направлениях для каждой своей ветки симуляции. Выбирал худший для себя исход. Для отсечения ненужных веток перебора я использовал скор бейзлайн с прошлого хода — лучший набор действий, который был выбран на предыдущем тике. Имея базовый скор, симулируем всё дерево, которое было выбрано для текущего хода (набор x и y) три раза — учитываем каждый из трёх вариантов поведения соперника. Первый раз симулируется в любом случае полностью — мы не знаем ничего про скор симуляции текущей ветки дерева, пока не просимулировали и не сравнили с хотя бы одним из трёх вариантов поведения соперника. В случае, если после очередной симуляции мы пришли в лист и наш скор оказался хуже, чем бейзлайн, принятый с прошлого хода — оставшиеся симуляции с соперником для этого листа делать бессмысленно (она заведомо хуже бейзлайна). Аналогичная логика переносится на уровень выше — если нет необходимости симулировать ни один из листов поддерева — не симулируем всю ветку целиком. Для ещё большего ускорения после симуляции бейзлайна симулируем наши действия в первую очередь с таким действием противника, которое дало нам наихудший результат. Т.о. на практике выходило, что в большинстве случаев дерево симулируется ровно 1 раз (т.е. против одного действия соперника) Valdemar: Удивлен, что перебор возможных направлений с глубиной 2 дал такой хороший результат. Видимо дьявол в деталях. Идея с лесом деревьев с разными параметрами очень интересная, похожего раньше не встречал. mortido: Здорово! Перебираются разные варианты, выглядит как хорошее распределение времени на вычисления. Выглядит простым в реализации. Не уверен, что глубины 2 хватит в других соревнованиях, где за 40-60 тиков можно выполнить более сложный план действий. Также нравится, что для каждого своего хода проверяется до 3х разных ходов противника.x + y == const ? В итоге да. Когда Функция оценки Владимир Киселев (Valdemar) 4 место Сразу стоит сказать, что в моей оценочной активно использовалась нормализация. Значения, получаемые от симулятора (угол наклона машины, скорость, расстояние и т.д.) переводились в диапазон [0..1]. Итак, в оценочной учитывались:
Угол наклона, близость к кнопке и таран считались 2 раза для меня и противника и давали либо бонус либо штраф, соответственно. Все составляющие умножались на различные коэффициенты в зависимости от типа машины. В случае обычной багги пара карт были учтены вручную:
mortido: Быстрее чем у меня, т.к. я делал много запросов к движку, а они оказались очень медленными. Commandos: В целом суть похожа на мою, разница в деталях и количестве костылей. Возможно местами в чём-то лучше Александр Киселев (mortido) 3 место Большую часть параметров для оценочной функции я брал, используя запросы к физическому движку chipmunk. Эти запросы позволяли находить разные расстояния до ближайших объектов или пересечения объекта и луча. Хотя движок и оптимизировал их, используя свои внутренние структуры и кэши, большое количество обращений к нему, в конечном счете, сильно затормозило симуляцию. Многие компоненты оценочной функции пришлось исключить перед финалом. Изначально я делал одну оценочную функцию и только после написания скрипта для сбора статистики боёв я разделил ее на 3 части и Вот часть компонентов, которые я смог вспомнить на данный момент (не думаю, что точное указание принципиально важно, главное основная идея):
Стоит отметить, что при сложении компонент одни затухали по времени, а другие имели больший коэффициент ближе к концу (например, выгоднее оказаться выше в последний тик и слегка спуститься для разгона сейчас, чем жадно подниматься в текущем) Valdemar: Идея давать больший коэффициент ближе к концу достаточно зыбкая. Можно попасть в ситуацию, когда бот будет думать “сейчас я постою, но через тик начну разгоняться, чтобы получить побольше бонус” и так несколько тиков подряд, пока внезапно не изменится обстановка (противник сделал непредсказуемый ход и т.д.) и ситуация станет сильно хуже. Такое было, он до последнего стоял, чтобы прямо на волоске от смерти начать взлетать. С этим были сложности. Commandos: Не очень понятно, зачем продолжать симуляцию, если враг “умер”… Возможно это костыль для автобусного дедлайна? Идею про повышение бонуса за высоту машинки под конец симуляции можно было бы попробовать, может и “взлетела” бы. Алексей Дичковский (Commandos) 1 место Основная функция оценки делалась под
Пункты 1-5 считались зеркально для меня и соперника, с разным знаком. В пункте 2 для соперника не учитывался “коэффициент набора высоты”. Valdemar: Думаю до этого дошли многие, кто хотя бы пару дней посидел над оценочной. Вся магия в алгоритме поиска и коэффициентах, с которыми суммируются все эти пункты. mortido: Интересная идея с углом к противнику, учитывая его положение через 10 тиков. Костыли и IF'ы Владимир Киселев (Valdemar) 4 место Периодический сбор статистики по матчам показал, что определенные карты на автобусах и багги всегда проигрываются стратегиям на if’ах. Внимание на это я стал обращать примерно за 3 дня до начала финала, к тому моменту идеи для улучшения оценочной уже закончились, а близость призового места не позволяла опустить руки и идти отдыхать. Поэтому, рядом с алгоритмом случайного поиска были добавлены эвристики, которые брали на себя контроль в определенных комбинациях машина-карта. На откуп ифам были отданы:
Во время работы эвристик большую помощь оказал симулятор, который предоставлял дополнительную информацию: скорость движения и угловую скорость. После конкурса выяснилось, что там где я использовал эти данные, участники на if’ах использовали тригонометрию и хитрые вычисления. mortido: Потиковый хардкод меня сильно огорчил, когда я первый раз об этом узнал. Сейчас эта идея не кажется такой уж и плохой в данном соревновании. Commandos: Суровая реальность if’ов. Заткнуть дыры там, где льётся от решения, покрывающего большую часть ситуаций… Я всё же больше старался положить скрипты на оценочную функцию, но это занимало порядком времени, а результат был местами странный. Александр Киселев (mortido) 3 место Это писалось с большой болью в сердце и попытками всячески замаскировать костыли под какую-нибудь логику. Первым делом были разделены 3 оценочные функции. Каждая для своей машинки. Две из них были практически одинаковыми и отличались коэффициентами. Для “Буханки”, которой выгоднее было не сражаться и просто забраться повыше и стоять в оборонительной позе была написана своя функция. Туда шли даже потенциальные поля для пары карт, которые позволяли ей заезжать на высоту, либо запрыгивать на холмик. Я не использовал жесткий хардкод ходов по тикам для карт, где можно было скопировать “лучшее” решение у других. Я лил эту пакость в оценочную функцию. Где в зависимости от карты, машинки и тика могли стоять немного разные задачи, например, минимизировать расстояние переднего колес до какой-то конкретной точки. А дальше генетический алгоритм пытался решить эту задачу. Работало это гораздо хуже хардкода, а настраивать и дебажить было практически невозможно, т.к. рандом вносил много проблем. В спорах после соревнования, где я очень ругал захардкоженные тики, я высказывал, что мог смириться с ними, если бы эти тики были найдены локально тем же алгоритмом поиска, только с огромным запасом времени на вычисление. После я проверил этот вариант… Генетический алгоритм не смог найти даже близко хорошие ходы. В общем если что-то можно сделать просто и это работает — надо делать, принципиальность зачастую только мешает (но я и за здоровую долю любопытства, чтобы проверить и другие варианты). Valdemar: Про потенциальные поля интересно, даже не думал их использовать. Идея добавлять аналог потикового хардкода в поиск видится совсем неправильной. Если мы говорим про принципиальность и эстетическую “красоту” решения, то такой подход еще хуже явных if’ов. А то, что генетический алгоритм не смог найти хорошие ходы совсем неудивительно — на поиск этих ходов участники с эвристиками потратили несколько дней или даже недель. Думаю можно было еще собирать ходы противника из реплеев игр, где ты проиграл и добавлять их + их мутации в качестве стартовой популяции. Правда, звучит как много потраченного времени и кода. Commandos: В данном случае… Если хочешь, чтобы что-то было сделано — сделай это сам, а не проси оценочную сделать так, как ты хочешь. Хотя я тоже много времени убил на то, чтобы сделать желаемое через оценочную, но по итогу она была не очень осмысленной и потиковый хардкод был бы проще и надёжней. Алексей Дичковский (Commandos) 1 место Хардкодить я начал за две недели до конца соревнований. И хардкода набралось огромное количество (больше, чем в любом другом соревновании, что я писал ранее). В основном весь хардкод был в подборе коэффициентов (и добавочных компонентов) для сочетаний карта/машинка. Например на карте pill carcass map для обоих багги сильно возрастал бонус за скорость, если я нахожусь снизу при надвигающемся дедлайне, а также дополнительно начислял очки за нахождение поближе к центру верхней перекладины (как и бонус за сталкивание подальше от центра перекладины соперника). Очень похожий бонус был на island map, где от нас только и требовалось, что перевернуть или столкнуть противника. Также из хорошо отработавших хардкодов была езда на заднем бампере на карте island hole для buggy. Для этого сочетания машинки/карты обычная функция оценки отключалась до момента, пока моя стратегия не решит, что соперник не пошёл в атаку (находится слишком близко). Если же такая ситуация имела место — включалась стандартная функция оценки. Также похожая, и тоже не идеальная имплементация была на той же карте, но уже для автобуса. А для SquaredWheelBuggy на этой карте был предусмотрен штраф за слишком высокую скорость вверх. Иногда физика срабатывала так, что багги просто улетал в космос, функция оценки это находила и считала, что так будет лучше. Скорость большая, мы выше соперника… А вот до момента, когда мы в любом случае умрём, досчитать не хватало дальности симуляции. На одной карте (Pill map, Bus) старт вообще был сделан потиковым хардкодом и не показывался до самого последнего дня соревнования во избежание копирования, которое было нетрудно сделать в этом соревновании (по итогу на таком сочетании карты/машинки имею 100% побед). Также для автобуса была очень удачно заскриптована карта pill hubble map. Скрипт мог отрабатывать как корректно, так и не очень (во всех примерах первый раунд), но мне он очень нравился. Ну и статистика говорит в его пользу. Для тех же автобусов по итогу было две разных оценочных функций на разных картах — было лень тестировать на всех и тестировал только там, где требовались исправления... Описанные моменты не охватывают всю ширину костылизации, но позволяют понять её глубину. Но в основном это всё же замена весов у разных частей оценочной функции и добавления компонентов, зависящих от определённой карты. Благо поддержка таких костылей была заложена в архитектуру изначально (хотя и немного подправлялась по факту). Valdemar: Специфика игры такова, что хардкод действий на некоторых картах позволяет играть идеально — как минимум добиться ничьи при помощи пары условий. Хардкод выглядит ужасно, но при этом невероятно эффективен. mortido: Хорошо залатал дыры в стратегии, пока я пытался написать “идеальную” оценочную функцию. Эмоции Valdemar: Начало контеста было довольно скучным. Создание симулятора требовало много усилий и опытные участники начинали высказывать мнения, что ничего интересного мы не увидим. Затем начались вечера (и даже немного ночи) постоянных доработок и стало гораздо веселее.Я участвую в таких соревнованиях ради эмоций и удовольствия от общения в кругу таких же любителей игрового ИИ. Этакие “фанатики”, которые после рабочего дня за компьютером, приходят домой и дорабатывают бота в ущерб домашним делам и, иногда, сну :)Впечатления великолепные, спасибо mailru за то, что они организуют такие конкурсы. Commandos: Соревнования ботов для меня всегда приносят кучу эмоций: когда ты смотришь как твой бот начинает побеждать всех и ты полночи просто смотришь бои, а потом утром приходят крутые ребята и ломают ему лицо… Очень нравятся моменты, где твоя стратегия начинает находить решения, до которых ты бы не додумался (например как тут с колесом и переворотом). Или когда тебе кидают реплей, где твой бот убил 3 союзников по команде, а ты делаешь вид, что это случайно… хотя это было немного другое соревнование. mortido: Как-то странно я провёл это соревнование, слишком рано начал впиливать костыли. И, пожалуй, немного не так, как стоило. Хотя с другой стороны… Костылями тут очень много погоды и сделалось. Но по итогу это сказалось на оценочной функции — она была не сильно продуманная, за что я чуть не поплатился.Интеграция с чипманком убивала — дотошное копирование движка из питона в С++. На этот раз это была половина успеха. После написания симулятора долго не мог решить, с какой стороны подойти к написанию бота. Потом увидел в топ 1 мортидо Итак Надеемся, статья получилась интересной и нам удалось раскрыть схожесть и разнообразие решений. В ходе описания решений, у авторов произошло много споров и дискуссий на тему оптимальности тех или иных подходов. Часть обсуждений были добавлены в статью, но если у вас остались вопросы, то их можно задать тут или в офф чате соревнования. Отдельное спасибо Дмитрию и Mail.Ru Group за организацию конкурса. Бонус Исходники ValdemarИсходники mortido Пачка гифок, которые остались после соревнования Источник: m.vk.com Комментарии: |
|