Добрый вечер форумчане!
Недавно вечером я сидел и, как обычно, потихоньку делал свой проект. Проект в моем представлении весьма достойный, но на деле пока практически нулевой. Задача была мной поставлена такая: сделать этакий Hero Defence, проработанный до мелочей, с отличной историей и прочим, и т.д. Не важно. Но вот захотелось мне сделать для волн нападающих достойный ИИ, как собственно и для волн, помогающих защитить что-либо.
До этого я много раз пытался, иногда вполне неплохо, делать такого рода ИИ. Но все, что было раньше - все должно меркнуть, перед новым ИИ. Читал кстати у нас на форума статейки, был даже вполне неплохой вариант (увы не вспомню как называлась карта и кто ее сотворил, было еще явно до 1.24 версии).

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

Цель была понятна, сел изучать литературу. Изучал 2 дня (конечно, мало для такой темы, но начало положено) , сидел, корпел, пил кофе и вставлял спички в глаза. Признаться узнал, что все, что я делал под названием "ИИ" было не больше, чем игрушка ребенка.

Собственно и вопрос таков: есть ли у кого опыт создания хороших ИИ? Что вы для этого использовали? Использовали ли вы только Дерево принятия решений и FMS (конечные автоматы) или же возможно (ну а вдруг) кто-либо интегрировал в кодинг нейронные сети? Конечно, любому картостроителю хотелось бы, чтобы его "ребенок" обучался :) Возможно кто-то пользовался методом "Цепей Маркова"? (вот уж не знал, что их изучение в универе может пригодиться и тут)

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

Если когда-нибудь (уповаю) я доделаю свой проект, всех без исключения добавлю в благодарности
Всем спасибо и хороших выходных господа!

Принятый ответ

Сейчас как раз делал ИИ для демки. Циклы для подобного - полная жопа. Пытался детерминировать логику максимально, но всеравно выходили либо зацикливания (один тик я хочу пассать, один тик я бегу от гопников, а потом опять пассать), либо неправильные решения (вокруг куча гопников а я ссу). И тут я пришёл к гениальной мысли: сделать по теме синаптических весов из нейронных сетей. Саму нейросеть не реализовывать, но вот именно эту фишку взять. Т.с. берёшь входы и создаёшь весы выходов, составляя их по формулам из входов. Лучший вес выигрывает, задавая задачу на тик, а чтобы не было зацикливания - переопределение таска идёт лишь при определённых условиях (напр. поведение сильно изменилось, противник умер и т.д.). И дебажить можно легко! Вышло неплохо - всем рекомендую :3
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
1
21
9 лет назад
1
Я в своем проекте делаю подобный ИИ. Научил манипулировать с инвентарем, нападать на слабых, кастовать некоторые скиллы.
1
7
9 лет назад
1
JaBeN_Симфер, Использовал дерево решений через циклы или что-то поинтереснее? Насколько сложен получился алгоритм?
2
29
9 лет назад
Отредактирован 16GB
2
создание ии которое тебе надо упирается, в большое число проверок и всё, ну вот например
который выбирал бы более приоритетные слабозащищенные и уязвимые цели
тут надо будет создать тучу областей и проверять количество юнитов в ней, их урон хп/ману в откате ли спелы если атакуют милишники то лучше идти туда где тоже милишки и т.д
не просто пытался сбивать касты и держать в контроле ДД союзной команды, но и умело передвигаться по полю боя, заходить за спины, уходить от потенциально опасных противников и т.д.
тут тоже если надо чтоб ии уворачивался от спелов, игроков, то придёться во все спелы запихивать вызовы функции ии (например спелл типо волны силы при касте надо давать приказ ии отходить в сторону) и так с каждым спелом, + делать опр. поведение против каждого героя и их связок, например если там маг+ милишник ловач, давать дизебл в мага и убивать милишника первым.
Ну это не особо сложно долго просто, главное будет разграничить действия чтобы они друг другу не мешали,
Собственно и вопрос таков: есть ли у кого опыт создания хороших ИИ? Что вы для этого использовали? Использовали ли вы только Дерево принятия решений и FMS (конечные автоматы) или же возможно (ну а вдруг) кто-либо интегрировал в кодинг нейронные сети? Конечно, любому картостроителю хотелось бы, чтобы его "ребенок" обучался :) Возможно кто-то пользовался методом "Цепей Маркова"? (вот уж не знал, что их изучение в универе может пригодиться и тут)
Жесть какая-то, по сути у тебя будет один главный триггер, переодический, в котором будет всё проверяться и отдаваться приказы нужные, и 2 который будет урон наносимый получаемый отлавливать для проверок первого, ну и про спелы что я писал, что надо будет в них приказы и разграничители запихивать.
А так вообще я считаю что такой ии, не особо нужен, если у врагов будет прикольные триггерные спелы, особенно передвигающие юнитов (их или игроков) и какие-то спелы против которых надо знать как действовать ( ну и это всё в большом разнообразии разумеется), то этого будет достаточно, для годного дефенса
1
7
9 лет назад
Отредактирован Ambruziy
1
16GB, Благодарю за ответ) Хотел бы сказать еще некоторые комментарии.
Что касается кучи проверок - это все верно, но нас приводит опять же к традиционному древу решений, через масс if...them...else. Тут "меня терзают смутные сомненья", что при достаточном кол-ве юнитов (хотя в самом дефенсе планирую совсем немного к слову, не больше 10) эта масса проверок может серьезно загрузить игру. Хотя, это надо смотреть.
Что касается второго замечания: конечно, грамотно продуманная схема приказов даст нам неплохой ии, проблема в том, что чтобы был ИИ отличным, нужно крайне много проверок. Опять же боюсь за производительность :)
Однако если все-же я считаю, что мой комп молодец, встает второй вопрос, который я пока не знаю как решить:
после множества проверок ИИ будет себя вести абсолютно правильно, но именно так, как ты запрограммировал, т.е. ты будешь предвидеть его действия. Задача у меня стоит сложнее: сделать мало мальское обучение ИИ, которое я пока лишь вижу в использовании тех же нейронных сетей (примитивных)
От части конечно можно поступить легче и сделать небольшую выборку действий по вероятностям. Это придаст вполне псевдонепредсказуемый ИИ.
Давайте я представлю как это все вижу без этих сетей, без слишом сложной системы.
Схему пока не рисую, попозже. Методом конечных автоматов.
Есть состояния юнита. Например "Стоит". Проверили, действительно стоит, прикрутили проверки, например: "в поле видимости враг" > проверка на "выгодность" атаки в лоб, если да, то > состояние "Идти в атаку" > цикл на проверу "выгодности" (пусть будет в отдельной ф-ии, где будет учитываться параметры хп, скорости, хп врага и т.д., или сделать струтуры как обект выгодность) > проверка "Враг в области атаки" > цикл выгодность > состояние атаки и т.д. К каждому состоянию прикручены отдельные проверки. Но пока это все опять же все можно предвидеть.
Далее в самих состояниях нужны действия. Например: при создании юнита ему будут даваться способности. Танку: 1 сил на контроль (случ. из 6) 1 скил на соращение дист (1 из 6) и 1 на масс урон вблизи (1 из 6) + пассивки. Каждому типу скила или действия будет приурочен "вес". Исходя из значения "веса" юнит делает действие. Сам вес каждого действия постоянно меняется. Например действие контроля танка имеет изначально малый вес, т.е. противник не делает сразу стан. Однако, когда его цель получила приказ нападать на союзного дд "вес" контроля повышается на % (пусть 200%). В итоге он кастует стан на врага (или не кастует, если есть действие с еще большим приоритетоа, например если очень мало хп приоритет на выживание). Это как будет по идее изначально.
Добавим некую обучаемость, а точнее "опыт". Пусть прошло 5 волн, противни подсчитывает урон, кто больше нанес. Видит, что нанес больше всех маг. Т.е. у того же танка при создании уже будет повышен "вес" на контроль мага. А для дд "вес" на атаку этого мага. Это, собственно то, о чем вы говорили 16GB, но этого мало. Мало потому, что приспосабливаться тут можно к источнику урона, к самому типу урона и т.д. Но всех возможностей факторов не учесть я считаю. Поэтому в идеале нужно обучение получше.
А так вообще я считаю что такой ии, не особо нужен, если у врагов будет прикольные триггерные спелы, особенно передвигающие юнитов (их или игроков) и какие-то спелы против которых надо знать как действовать ( ну и это всё в большом разнообразии разумеется), то этого будет достаточно, для годного дефенса
Тут трудно поспорить :) Само собой спелы должны быть уникальными и разнообразными. И для годного дефенса хватит, но, как любой картограф, я хочу прыгнуть повыше, там, где еще я мало чего знаю. Если кого-то заинтересует, могу кинуть какую-никакую инфу по ии, которую раздобыл
Извиняюсь за возможные опечатки, клавиатура немного раздолбана
0
21
9 лет назад
0
Я делаю по принципу теории игр. Нейронные сети вряд ли пригодятся. Древо пока получается не очень глубокое, больше переборов в циклах.
1
10
9 лет назад
Отредактирован ZLOI_DED
1
Сейчас как раз делал ИИ для демки. Циклы для подобного - полная жопа. Пытался детерминировать логику максимально, но всеравно выходили либо зацикливания (один тик я хочу пассать, один тик я бегу от гопников, а потом опять пассать), либо неправильные решения (вокруг куча гопников а я ссу). И тут я пришёл к гениальной мысли: сделать по теме синаптических весов из нейронных сетей. Саму нейросеть не реализовывать, но вот именно эту фишку взять. Т.с. берёшь входы и создаёшь весы выходов, составляя их по формулам из входов. Лучший вес выигрывает, задавая задачу на тик, а чтобы не было зацикливания - переопределение таска идёт лишь при определённых условиях (напр. поведение сильно изменилось, противник умер и т.д.). И дебажить можно легко! Вышло неплохо - всем рекомендую :3
Принятый ответ
0
7
9 лет назад
0
JaBeN_Симфер, переборы смущают, факторов у меня будет множество, + системка не для ии героя а для ии волн, т.е. юнитов тоже будет не 1-2. Буду начинать как минимум с таких древ )
ZLOI_DED, Спасибо, на счет синаптических весов надо бы мне почитать) Вообще не вижу вариантов создания ИИ без применения тех же самых весов для каждого действия, так что пошел читать))
P.S. ZLOI_DED, если это возможно, сможешь выложить алгоритм действий поподробнее?
1
10
9 лет назад
Отредактирован ZLOI_DED
1
Ambruziy:
P.S. ZLOI_DED, если это возможно, сможешь выложить алгоритм действий поподробнее?
Делаем весы по следующему принципу: профит от выполнения задачи / сложность выполнения.
Т.е. для аттаки можно, к примеру, сделать так: кол-во монет за убийство / расстояние до врага.
enum Task {
Idle, Attack...
}
update()
{
setTask();
executeTask();
}
setTask()
{
float idleWeight = 0f;
float attackWeight = 0f;
if (enemies.size() > 0)
{
Enemy e = getNearestEnemy();
Vector2f diff = new Vector2f(Math.abs(e.getLocation().x-getLocation().x), Math.abs(e.getLocation().y-getLocation().y));
attackWeight = 1f / diff.length();
target = e;
}
float maxWeight = Math.max(idleWeight, attackWeight);
if (currWeight == 0 ||
task == Task.Attack && (target == null || target.isDead() || currWeight-attackWeight>.1f))
if (maxWeight == attackWeight) {
task = Task.Attack;
} else {
task = Task.Idle;
}
}
currWeight = maxWeight;
executeTask()
{
switch (task)
{
case Attack:
if (target != null)
{
followAndAttack(target);
}
break;...
}
}
Базово именно так. Дальше можно всячески усложнить, добавив кучу разных других весов. Единственная сложность - калибровка. Тебе прийдётся запустить её с сотню раз, чтобы откалибровать весы, но это того стоит.
Как калибровать:
  1. Сделай либо сисаут либо вывод прямо на экран весов.
  2. Создавай ситуации и смотри как меняются весы.
  3. Делай выводы и изменяй формулы (напр. эти олухи постоянно обирают монетки, когда должны воевать - увеличить профит от аттаки каким-нибудь модификатором или уменьшить профит от сбора монет. Эти глупцы постоянно деруться, когда должны убегать при лоу хп - увеличить мод побега или уменьшить мод аттаки).
  4. ...
  5. PROFIT!
Ручная калибровка медленнее чем то что с нейронными сетями, но быстрее в том плане, что ты видишь лучше что поменять надо.
0
7
9 лет назад
0
ZLOI_DED, отлично! Спасибо за инфу, буду пробовать :)
0
10
9 лет назад
0
Ambruziy:
ZLOI_DED, отлично! Спасибо за инфу, буду пробовать :)
Дописал setTask();
0
29
9 лет назад
0
Что касается кучи проверок - это все верно, но нас приводит опять же к традиционному древу решений, через масс if...them...else. Тут "меня терзают смутные сомненья", что при достаточном кол-ве юнитов (хотя в самом дефенсе планирую совсем немного к слову, не больше 10) эта масса проверок может серьезно загрузить игру. Хотя, это надо смотреть.
У меня в карте используеться система урона с тучей if в ней 4к строк вида
if IsUnitType(t,UNIT_TYPE_HERO) and Dm > 0. and GetUnitAbilityLevel(t,'A085') > 0 then
call SaveReal(udg_AssassinHash,GetHandleId(t),StringHash("LSDC"),Dm+LoadReal(udg_AssassinHash,GetHandleId(t),StringHash("LSDC")))
endif

if IsUnitType(t,UNIT_TYPE_HERO) and Dm > 0. and GetUnitAbilityLevel(t,'A045') > 0 then
call SaveReal(udg_AssassinHash,GetHandleId(t),StringHash("MADC"),Dm+LoadReal(udg_AssassinHash,GetHandleId(t),StringHash("MADC")))
endif

if GetUnitAbilityLevel(t,'B03V') > 0 and Dm > 4. and t != s then
set r1 = Dm*.3
set udg_DBR[w] = Dm
call UnitDamageTarget(udg_NDCD[q+1],t,r1,true,false,ATTACK_TYPE_HERO,DAMAGE_TYPE_UNKNOWN,WEAPON_TYPE_WHOKNOWS)
set Dm = Dm+r1
endif

if LoadBoolean(udg_AssassinHash,GetHandleId(t),StringHash("MoDB")) and Dm > 5. and t != s then
set udg_D = LoadUnitHandle(udg_AssassinHash,GetHandleId(t),StringHash("MoDC"))
set r1 = Dm*(.10+.10*GetUnitAbilityLevel(udg_D,'A0GU'))
set udg_DBR[w] = Dm
call UnitDamageTarget(udg_NDCD[GetPlayerId(GetOwningPlayer(udg_D))+1],t,r1,true,false,ATTACK_TYPE_HERO,DAMAGE_TYPE_UNKNOWN,WEAPON_TYPE_WHOKNOWS)
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\Possession\\PossessionMissile.mdl",t,"chest"))
set Dm = Dm+r1
endif


if Dm > 5. and GetUnitAbilityLevel(dc,'A0F6') > 0 and t != s then
set r1 = Dm*(.1+.05*GetUnitAbilityLevel(dc,'A0F6'))
set udg_DBR[w] = Dm
call UnitDamageTarget(udg_NDCD[q+1],t,r1,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_MAGIC,null)
if r1 > 65. then
call JT(t,0,12,0.8,0.7,"|cffFF6600"+I2S(R2I(r1))+"!",dc)
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl",t,"origin"))
endif
set Dm = Dm+r1
endif
И это вызывается при каждом получении урона. Ничего не лагает. В твоём случае это будет в периодическом триггере вызываться. Если период будет где-то .05, то всё нормально будет.
Что касается второго замечания: конечно, грамотно продуманная схема приказов даст нам неплохой ии, проблема в том, что чтобы был ИИ отличным, нужно крайне много проверок. Опять же боюсь за производительность :)
Даже если будет, всегда потом можно оптимизировать код.
Однако если все-же я считаю, что мой комп молодец, встает второй вопрос, который я пока не знаю как решить:
после множества проверок ИИ будет себя вести абсолютно правильно, но именно так, как ты запрограммировал, т.е. ты будешь предвидеть его действия.
Ну в свою карту, где ты играешь не против игроков, а против крипов в любом случае не особо интересно играть, поэтому я так и не сделал не одной крупной пве карты.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.