155

Подробный разбор нейросети для нашей карточной игры

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


С начало я хотел бы уточнить тот момент, что возможно это не является истинно верной нейросетью, но тем не менее это то, с помощью чего я научил бота играть хорошо. Был вопрос про слои и узлы. Я почитал пару статей дабы освежить в голове такие понятия и на сколько я могу судить, сеть эта однослойная. Я не преследовал цель сделать идеальную сеть, как у всех, чтобы я мог рассказывать месяцами про ее характеристики, да и вообще для меня теория это нечто сложное и мне легче постепенно все это воплотить на практике. Так что развернутого ответа на этот вопрос я, увы, дать не смогу


С чего же я начал, мне было необходимо хранилище этих самих нейронов, я назвал его мозгом, ну и сами нейроны.Класс нейронов состоит из двух параметров - это тег и вес.

Мозг же, это просто List с нейронами, для возможности использовать List и методами, такими как запись нейрона, получение веса и запись в файл.


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

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


Сохранение в файл происходит с помощью библиотеки "System.IO" и "JsonUtility" которая встроена в Unity3d.

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

Теперь сам бот. В комментариях к прошлой статье был вопрос - "как бот взаимодействует с клиентом", по сути у нас есть 3 линии и возможность перетащить карту на одну из линий, чтобы вызвать её туда. Не зависимо от расположения курсора над линией карта становить вперед своих карт, так что по сути просто вызывается метод у линии "Добавить карту". Вот бот и вызывает этот метод, посылая параметром карту, которую хочет поставить.


В начале хода бота, бот ждет, когда ему дадут карту(как и во многих других ККИ у нас в начале твоего хода дают карту), затем начинает смотреть свою руку, а точнее на карты в ней, просто перебирая очередной List с картами. Если стоимость маны у карты выше, чем у бота маны, то он попросту пропускает ее, а вот если маны хватает, то тут уже происходит анализ. (Маленькое отступление) Концепция обучения этого бота такова, что я даю боту информацию, которую считаю необходимой для него, а он на основании нее уже совершает действия. Т.е. я не написал бота, который в начале даже не знал во что играет, а после долгих опытов пришел к выводу, что это похоже на ККИ.(Конец отступления). Для каждой карты бот смотрит все 3 линии, т.е. он каждую карту анализирует по 3 раза. Сначала бот создает новое действие, затем генерирует первый тег, на основании характеристик самой карты, т.е. это выглядит следующим образом "сыграть_id_*стоимость карты*_*сейчас_маны*"(id - Это идентификатор карты), получает из мозга вес этого тега, и записывает тег и вес в это действие. Затем бот смотрит есть ли дружественный сосед и, если есть, из какой он фракции, т.е. добавляет новый тег типа "фракция1_фракция1" или "фракция1_null"(в случае если на линии нет союзников), ну и все добавление тегов сопровождаются получением и записью веса этого тега в действие. Далее, если у карты есть какое-либо действие, которое воспроизведется с ее появлением на столе, то мы боту говорим результат этих действий.


Просмотр результат действий происходит следующим образом, допустим у нас есть механика убить врага напротив, убить выбранного врага, баффнуть своего союзника и достать еще карту из колоды. В начале всего анализа генерируется тег "использовать_*название механики*", далее, если это, к примеру, убить напротив себя, добавляется ID карты с дополнительным весом, равным сумме характеристик врага напротив , т.е. если напротив стоит существо 2/3 с ID = 2, то в тег добавиться запись "_2_5" и этот тег со своим весом записываеться в действие, если у врага есть способности, то мы за каждую способность так же добавим в действие тег с записью "убить_*название способности*".


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


По окончанию анализа каждое действие записывается в лист действий, а так же в самом конце добавляется действие с тегом "nothing_*текущая мана*" и своим весом, что отвечает за пропуск хода. Далее бот пробегается по всему списку и выбирает те действия, которые ему подходят, а точнее самые весомые. НО! У меня, как я уже говорил в прошлом посте, есть коэффициент погрешности, благодаря которому бот может не всегда совершать идеальные, по его мнению, ходы. Т.е перед пробегом по основному листу с действиями, создается дополнительный, изначально пустой лист. Когда мы просматриваем основной лист, мы смотрим его вес, если вес этого действия больше максимального веса в новом списке, то все действия, вес которых ниже чем (макс. вес - погрешность), удаляются, а если у текущего действия сумма (веса + погрешности) >= максимальному весу в новом листе, то просто добавляем его. Далее из полученного списка бот берет случайное действие и совершает его, тратя на это ману, далее он смотрит, может ли он еще что-то сделать, кроме "nothing" и будет ли это хорошим действием. Все разыгранные действия за игру, а именно теги(нейроны) этих действий записываются в отдельный список "задействованных нейронов".


Когда у бота проигрывается действие "nothing", бот передает ход противнику и в этот момент идет просчет урона по себе и по врагу. В зависимости от этого у каждого нейрона в списке "задействованных нейронах" добавляется(в случае нанесения урона) или отнимается(в случае получения урона) вес, где 1 ед. урона = 0.1 ед. веса. Ну и по окончанию игры, если бот выигрывает, мы его хвалим и даем по +10 к каждому сыгранному нейрону, или, в случае проигрыша, отнимает по 10 у каждого нейрона.


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


Если вам интересны такие статьи, то я бы мог попробовать, для примера, написать простенький Tower Defense, в который так же играл бы бот.

Правила сообщества

ОБЩИЕ ПРАВИЛА:

- Уважайте чужой труд и используйте конструктивную критику

- Не занимайтесь саморекламой, пишите качественные и интересные посты

- Никакой политики


СТОИТ ПУБЛИКОВАТЬ:

- Посты о Вашей игре с историей её разработки и описанием полученного опыта

- Обучающие материалы, туториалы

- Интервью с опытными разработчиками

- Анонсы бесплатных мероприятий для разработчиков и истории их посещения;
- Ваши работы, если Вы художник/композитор и хотите поделиться ими на безвозмездной основе

НЕ СТОИТ ПУБЛИКОВАТЬ:

- Посты, содержащие только вопрос или просьбу помочь
- Посты, содержащие только идею игры

- Посты, единственная цель которых - набор команды для разработки игры

- Посты, не относящиеся к тематике сообщества

Подобные посты по решению администрации могут быть перемещены из сообщества в общую ленту.

ЗАПРЕЩЕНО:

- Публиковать бессодержательные посты с рекламой Вашего проекта (см. следующий пункт), а также все прочие посты, содержащие рекламу/рекламные интеграции

- Выдавать чужой труд за свой

Подобные посты будут перемещены из сообщества в общую ленту, а их авторы по решению администрации могут быть внесены в игнор-лист сообщества.


О РАЗМЕЩЕНИИ ССЫЛОК:

Ссылка на сторонний ресурс, связанный с игрой, допускается только при следующих условиях:

- Пост должен быть содержательным и интересным для пользователей, нести пользу для сообщества

- Ссылка должна размещаться непосредственно в начале или конце поста и только один раз

- Cсылка размещается в формате: "Страница игры в Steam: URL"

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества