Как да създадете AI за игри: ръководство за начинаещи

Как да създадете AI за игри: ръководство за начинаещи

Попаднах на интересен материал за изкуствения интелект в игрите. С обяснение на основните неща за AI чрез прости примери, а вътре има много полезни инструменти и методи за удобното му разработване и проектиране. Как, къде и кога да ги използвате също е там.

Повечето от примерите са написани с псевдокод, така че не са необходими напреднали познания по програмиране. Под изрезката има 35 листа текст със снимки и гифчета, така че се пригответе.

UPD. Извинявам се, но вече направих собствен превод на тази статия на Хабре PatientZero. Можете да прочетете неговата версия тук, но по някаква причина статията ме подмина (използвах търсачката, но нещо се обърка). И тъй като пиша в блог, посветен на разработката на игри, реших да оставя моята версия на превода за абонати (някои точки са форматирани по различен начин, някои са умишлено пропуснати по съвет на разработчиците).

Какво е AI?

Игралният AI се фокусира върху това какви действия трябва да извърши даден обект въз основа на условията, в които се намира. Това обикновено се нарича управление на „интелигентен агент“, където агентът е персонаж на играч, превозно средство, бот или понякога нещо по-абстрактно: цяла група от обекти или дори цивилизация. Във всеки случай това е нещо, което трябва да вижда своята среда, да взема решения въз основа на нея и да действа в съответствие с тях. Това се нарича цикъл Sense/Think/Act:

  • Усещане: Агентът намира или получава информация за неща в своята среда, които могат да повлияят на поведението му (заплахи наблизо, предмети за събиране, интересни места за изследване).
  • Помислете: Агентът решава как да реагира (преценява дали е достатъчно безопасно да събира предмети или първо трябва да се бие/скрие).
  • Действайте: агентът извършва действия за изпълнение на предишното решение (започва да се движи към врага или обекта).
  • ... сега ситуацията се е променила поради действията на героите, така че цикълът се повтаря с нови данни.

AI има тенденция да се фокусира върху Sense частта от цикъла. Например, автономните коли правят снимки на пътя, комбинират ги с радарни и лидарни данни и ги интерпретират. Това обикновено се прави чрез машинно обучение, което обработва входящите данни и им придава значение, извличайки семантична информация като „има друга кола на 20 ярда пред вас“. Това са така наречените класификационни проблеми.

Игрите не се нуждаят от сложна система за извличане на информация, тъй като повечето от данните вече са неразделна част от нея. Няма нужда да стартирате алгоритми за разпознаване на изображения, за да определите дали има враг пред вас - играта вече знае и захранва информацията директно в процеса на вземане на решения. Следователно частта на смисъла от цикъла често е много по-проста от частта Мисли и действай.

Ограничения на играта AI

AI има редица ограничения, които трябва да се спазват:

  • AI не е необходимо да се обучава предварително, сякаш е алгоритъм за машинно обучение. Няма смисъл да пишете невронна мрежа по време на разработката, за да наблюдавате десетки хиляди играчи и да научите най-добрия начин да играете срещу тях. Защо? Защото играта не е пусната и няма играчи.
  • Играта трябва да е забавна и предизвикателна, така че агентите не трябва да намират най-добрия подход срещу хората.
  • Агентите трябва да изглеждат реалистични, така че играчите да се чувстват така, сякаш играят срещу истински хора. Програмата AlphaGo превъзхождаше хората, но избраните стъпки бяха много далеч от традиционното разбиране на играта. Ако играта симулира човешки противник, това усещане не трябва да съществува. Алгоритъмът трябва да бъде променен, така че да взема правдоподобни решения, а не идеални.
  • AI трябва да работи в реално време. Това означава, че алгоритъмът не може да монополизира използването на процесора за дълги периоди от време, за да взема решения. Дори 10 милисекунди са твърде дълги, защото повечето игри се нуждаят само от 16 до 33 милисекунди, за да извършат цялата обработка и да преминат към следващия графичен кадър.
  • В идеалния случай поне част от системата трябва да се управлява от данни, така че хората, които не кодират, да могат да правят промени и корекциите да се извършват по-бързо.

Нека да разгледаме подходите на AI, които обхващат целия цикъл Sense/Think/Act.

Вземане на основни решения

Да започнем с най-простата игра - понг. Цел: преместете греблото така, че топката да отскача от него, вместо да лети покрай него. Това е като тенис, където губиш, ако не удариш топката. Тук AI има сравнително лесна задача - да реши в коя посока да премести платформата.

Как да създадете AI за игри: ръководство за начинаещи

Условни твърдения

За AI ​​в Pong най-очевидното решение е винаги да се опитвате да поставите платформата под топката.

Прост алгоритъм за това, написан на псевдокод:

всеки кадър/актуализация, докато играта работи:
ако топката е вляво от греблото:
преместете греблото наляво
иначе, ако топката е вдясно от греблото:
преместете греблото надясно

Ако платформата се движи със скоростта на топката, тогава това е идеалният алгоритъм за AI ​​в Pong. Няма нужда да усложнявате нищо, ако няма толкова много данни и възможни действия за агента.

Този подход е толкова прост, че целият цикъл Sense/Think/Act е едва забележим. Но го има:

  • Частта Sense е в две оператора if. Играта знае къде е топката и къде е платформата, така че AI я търси за тази информация.
  • Частта Think също е включена в двата оператора if. Те въплъщават две решения, които в случая са взаимно изключващи се. В резултат на това се избира едно от трите действия - преместете платформата наляво, преместете я надясно или не правете нищо, ако вече е правилно позиционирана.
  • Частта Act се намира в инструкциите Move Paddle Left и Move Paddle Right. В зависимост от дизайна на играта, те могат да преместят платформата моментално или с определена скорост.

Такива подходи се наричат ​​реактивни - има прост набор от правила (в този случай изявления в кода), които реагират на текущото състояние на света и предприемат действия.

Дърво на решенията

Примерът с Pong всъщност е еквивалентен на формална концепция за ИИ, наречена дърво на решенията. Алгоритъмът минава през него, за да достигне до „лист“ – решение какво действие да предприеме.

Нека направим блокова диаграма на дървото на решенията за алгоритъма на нашата платформа:

Как да създадете AI за игри: ръководство за начинаещи

Всяка част от дървото се нарича възел - AI използва теория на графите, за да опише такива структури. Има два вида възли:

  • Възли за вземане на решения: избор между две алтернативи въз основа на тестване на някакво условие, където всяка алтернатива е представена като отделен възел.
  • Крайни възли: Действието за извършване, което представлява окончателното решение.

Алгоритъмът започва от първия възел („корена“ на дървото). Той или взема решение към кой дъщерен възел да отиде, или изпълнява действието, съхранено във възела, и излиза.

Каква е ползата от това дървото на решенията да върши същата работа като операторите if в предишния раздел? Тук има обща система, при която всяко решение има само едно условие и два възможни резултата. Това позволява на разработчика да създава AI от данни, представящи решения в дърво, без да се налага да го кодира твърдо. Нека го представим под формата на таблица:

Как да създадете AI за игри: ръководство за начинаещи

От страна на кода ще получите система за четене на низове. Създайте възел за всеки от тях, свържете логиката за вземане на решения на базата на втората колона и дъщерните възли на базата на третата и четвъртата колона. Все още трябва да програмирате условията и действията, но сега структурата на играта ще бъде по-сложна. Тук добавяте допълнителни решения и действия и след това персонализирате целия AI, като просто редактирате текстовия файл с дефиниция на дърво. След това прехвърляте файла на дизайнера на играта, който може да промени поведението, без да прекомпилира играта или да променя кода.

Дърветата на решенията са много полезни, когато се изграждат автоматично от голям набор от примери (например с помощта на алгоритъма ID3). Това ги прави ефективен и високоефективен инструмент за класифициране на ситуации въз основа на получените данни. Ние обаче надхвърляме простата система за агенти за избор на действия.

сценарии

Ние анализирахме система от дърво на решенията, която използва предварително създадени условия и действия. Човекът, който проектира AI, може да организира дървото както иска, но все пак трябва да разчита на кодера, който го е програмирал всичко. Какво ще стане, ако можем да дадем на дизайнера инструментите за създаване на свои собствени условия или действия?

За да не се налага програмистът да пише код за условията Is Ball Left Of Paddle и Is Ball Right Of Paddle, той може да създаде система, в която дизайнерът ще напише условия за проверка на тези стойности. Тогава данните в дървото на решенията ще изглеждат така:

Как да създадете AI за игри: ръководство за начинаещи

По същество това е същото като в първата таблица, но решенията вътре в себе си имат собствен код, малко като условната част на оператор if. От страна на кода, това ще се прочете във втората колона за възлите на решението, но вместо да търси конкретно условие за изпълнение (Is Ball Left Of Paddle), то оценява условния израз и съответно връща true или false. Това се прави с помощта на скриптовия език Lua или Angelscript. Използвайки ги, разработчикът може да вземе обекти в своята игра (топка и гребло) и да създаде променливи, които ще бъдат налични в скрипта (ball.position). Освен това скриптовият език е по-прост от C++. Не изисква пълен етап на компилация, така че е идеален за бързо регулиране на логиката на играта и позволява на „некодерите“ сами да създават необходимите функции.

В примера по-горе скриптовият език се използва само за оценка на условния израз, но може да се използва и за действия. Например данните Move Paddle Right могат да станат израз на скрипт (ball.position.x += 10). Така че действието също е дефинирано в скрипта, без да е необходимо да програмирате Move Paddle Right.

Можете да отидете дори по-далеч и да напишете цялото дърво на решенията на скриптов език. Това ще бъде код под формата на твърдо кодирани условни изрази, но те ще бъдат разположени във външни скриптови файлове, тоест ще могат да бъдат променяни без повторно компилиране на цялата програма. Често можете да редактирате файла със скрипта по време на игра, за да тествате бързо различни отговори на AI.

Отговор на събитието

Примерите по-горе са идеални за Pong. Те непрекъснато изпълняват цикъла Разум/Мисли/Действай и действат въз основа на последното състояние на света. Но в по-сложните игри трябва да реагирате на отделни събития, а не да оценявате всичко наведнъж. Понгът в случая вече е лош пример. Да изберем друг.

Представете си стрелец, в който враговете са неподвижни, докато не открият играча, след което действат в зависимост от своята „специализация“: някой ще тича да „бърза“, някой ще атакува отдалеч. Това все още е основна реактивна система - "ако играч бъде забелязан, направете нещо" - но тя може логически да бъде разделена на събитие Player Seen и реакция (изберете отговор и го изпълнете).

Това ни връща към цикъла Разум/Мислене/Действие. Можем да кодираме Sense част, която ще проверява всеки кадър дали AI вижда играча. Ако не, нищо не се случва, но ако види, тогава се създава събитието Player Seen. Кодът ще има отделен раздел, който казва „когато се случи събитието Player Seen, направете“, където е отговорът, от който се нуждаете, за да адресирате частите „Мисли и действай“. Така ще настроите реакции към събитието Player Seen: за „бързащия“ герой - ChargeAndAttack и за снайпериста - HideAndSnipe. Тези връзки могат да бъдат създадени във файла с данни за бързо редактиране, без да се налага повторно компилиране. Тук също може да се използва скриптов език.

Вземане на трудни решения

Въпреки че простите системи за реакция са много мощни, има много ситуации, в които те не са достатъчни. Понякога трябва да вземете различни решения въз основа на това, което агентът прави в момента, но е трудно да си представим това като условие. Понякога има твърде много условия, за да бъдат ефективно представени в дърво на решения или скрипт. Понякога трябва да прецените предварително как ще се промени ситуацията, преди да вземете решение за следващата стъпка. Необходими са по-сложни подходи за решаване на тези проблеми.

Машина с крайно състояние

Краен автомат или FSM (finite state machine) е начин да кажем, че нашият агент в момента е в едно от няколко възможни състояния и че може да преминава от едно състояние в друго. Има определен брой такива състояния - оттук и името. Най-добрият пример от живота е светофар. Има различни последователности от светлини на различни места, но принципът е един и същ - всяко състояние представлява нещо (спиране, ходене и т.н.). Светофарът е само в едно състояние във всеки даден момент и се премества от едно в друго въз основа на прости правила.

Подобна е историята с NPC в игрите. Например, нека вземем страж със следните състояния:

  • Патрулиране.
  • Атакуващ.
  • бягане.

И тези условия за промяна на състоянието му:

  • Ако стражът види врага, той атакува.
  • Ако стражът атакува, но вече не вижда врага, той се връща да патрулира.
  • Ако пазач атакува, но е тежко ранен, той бяга.

Можете също така да напишете оператори if с променлива за състояние на пазител и различни проверки: има ли враг наблизо, какво е нивото на здраве на NPC и т.н. Нека добавим още няколко състояния:

  • Безделие – между патрулки.
  • Търсене - когато забелязаният враг е изчезнал.
  • Намиране на помощ - когато врагът е забелязан, но е твърде силен, за да се бие сам.

Изборът за всеки от тях е ограничен - например, пазачът няма да отиде да търси скрит враг, ако има ниско здраве.

В крайна сметка има огромен списък с „ако“ , Че " може да стане твърде тромаво, така че трябва да формализираме метод, който ни позволява да имаме предвид състоянията и преходите между състоянията. За да направим това, вземаме предвид всички състояния и под всяко състояние записваме в списък всички преходи към други състояния, заедно с условията, необходими за тях.

Как да създадете AI за игри: ръководство за начинаещи

Това е таблица за преход на състояния - изчерпателен начин за представяне на FSM. Нека начертаем диаграма и да получим пълен преглед на това как се променя поведението на NPC.

Как да създадете AI за игри: ръководство за начинаещи

Диаграмата отразява същността на вземането на решения за този агент въз основа на текущата ситуация. Освен това всяка стрелка показва преход между състояния, ако условието до нея е вярно.

При всяка актуализация проверяваме текущото състояние на агента, разглеждаме списъка с преходи и ако условията за прехода са изпълнени, той приема новото състояние. Например, всеки кадър проверява дали 10-секундният таймер е изтекъл и ако е така, тогава охраната преминава от състояние на празен ход в състояние на патрулиране. По същия начин състоянието Attacking проверява здравето на агента - ако е ниско, тогава преминава в състояние Fleeing.

Това е обработка на преходи между състояния, но какво да кажем за поведението, свързано със самите състояния? От гледна точка на прилагане на действителното поведение за конкретно състояние, обикновено има два типа "кука", където присвояваме действия на FSM:

  • Действия, които извършваме периодично за текущото състояние.
  • Действията, които предприемаме, когато преминаваме от едно състояние в друго.

Примери за първия тип. Състоянието на патрулиране ще премества агента по маршрута на патрулиране всеки кадър. Състоянието Attacking ще се опитва да инициира атака всеки кадър или преход към състояние, където това е възможно.

За втория тип помислете за прехода „ако врагът е видим и врагът е твърде силен, тогава отидете в състояние „Намиране на помощ“. Агентът трябва да избере къде да отиде за помощ и да съхранява тази информация, така че състоянието Намиране на помощ да знае къде да отиде. След като бъде намерена помощ, агентът се връща в състояние на атака. В този момент той ще иска да каже на съюзника за заплахата, така че може да се случи действието NotifyFriendOfThreat.

Още веднъж можем да погледнем на тази система през призмата на цикъла Разум/Мисли/Действай. Смисълът е въплътен в данните, използвани от логиката на прехода. Помислете - налични са преходи във всяко състояние. И действието се извършва чрез действия, извършвани периодично в рамките на дадена държава или при преходи между държави.

Понякога преходните условия на непрекъснато проучване могат да бъдат скъпи. Например, ако всеки агент извършва сложни изчисления на всеки кадър, за да определи дали може да вижда врагове и дали може да премине от състояние на патрулиране към състояние на атака, това ще отнеме много време на процесора.

Важните промени в състоянието на света могат да се разглеждат като събития, които ще бъдат обработени, когато настъпят. Вместо FSM да проверява условието за преход „може ли моят агент да вижда играча?“ всеки кадър, отделна система може да бъде конфигурирана да проверява по-рядко (напр. 5 пъти в секунда). И резултатът е да издадете Player Seen, когато проверката премине.

Това се предава на FSM, който сега трябва да премине към условието за получено събитие Player Seen и да отговори съответно. Полученото поведение е същото, с изключение на почти незабележимо забавяне преди отговор. Но производителността се подобри в резултат на отделянето на частта Sense в отделна част от програмата.

Йерархичен краен автомат

Работата с големи FSM обаче не винаги е удобна. Ако искаме да разширим състоянието на атака, за да разделим MeleeAttacking и RangedAttacking, ще трябва да променим преходите от всички други състояния, които водят до състоянието Attacking (настоящо и бъдещо).

Вероятно сте забелязали, че в нашия пример има много дублиращи се преходи. Повечето преходи в състояние на празен ход са идентични с преходите в състояние на патрулиране. Би било хубаво да не се повтаряме, особено ако добавим още подобни състояния. Има смисъл да се групират празен ход и патрулиране под общия етикет „небойни“, където има само един общ набор от преходи към бойни състояния. Ако мислим за този етикет като състояние, тогава празен ход и патрулиране стават подсъстояния. Пример за използване на отделна таблица за преход за ново небойно подсъстояние:

Основни състояния:
Как да създадете AI за игри: ръководство за начинаещи

Извън бойно състояние:
Как да създадете AI за игри: ръководство за начинаещи

И под формата на диаграма:

Как да създадете AI за игри: ръководство за начинаещи

Това е същата система, но с ново небойно състояние, което включва празен ход и патрулиране. С всяко състояние, съдържащо FSM с подсъстояния (и тези подсъстояния, от своя страна, съдържащи свои собствени FSM - и така нататък толкова дълго, колкото ви е необходимо), получаваме Йерархична крайна машина или HFSM (йерархична крайна машина). Чрез групиране на небойното състояние, ние изрязваме куп излишни преходи. Можем да направим същото за всички нови състояния с общи преходи. Например, ако в бъдеще разширим състоянието Attacking до състоянията MeleeAttacking и MissileAttacking, те ще бъдат подсъстояния, които преминават едно към друго въз основа на разстоянието до врага и наличността на амуниции. В резултат на това сложните поведения и подповедения могат да бъдат представени с минимум дублирани преходи.

Дърво на поведението

С HFSM се създават сложни комбинации от поведение по прост начин. Съществува обаче малка трудност, че вземането на решения под формата на правила за преход е тясно свързано с текущото състояние. И в много игри това е точно това, което е необходимо. И внимателното използване на йерархията на състоянието може да намали броя на повторенията на прехода. Но понякога се нуждаете от правила, които работят независимо в какъв щат се намирате или които се прилагат в почти всеки щат. Например, ако здравето на агент спадне до 25%, вие ще искате той да избяга, независимо дали е бил в битка, неактивен или е говорил - ще трябва да добавите това условие към всяко състояние. И ако вашият дизайнер по-късно иска да промени ниския праг на здраве от 25% на 10%, тогава това ще трябва да се направи отново.

В идеалния случай тази ситуация изисква система, в която решенията за това „в какво състояние да бъдем“ са извън самите състояния, за да се правят промени само на едно място и да не се засягат условията на прехода. Тук се появяват дървета на поведението.

Има няколко начина за прилагането им, но същността е приблизително една и съща за всички и е подобна на дърво на решенията: алгоритъмът започва с „коренен“ възел и дървото съдържа възли, които представляват решения или действия. Все пак има няколко ключови разлики:

  • Възлите вече връщат една от трите стойности: успешно (ако заданието е завършено), неуспешно (ако не може да бъде стартирано) или изпълняващо се (ако все още работи и няма краен резултат).
  • Няма повече възли за вземане на решения за избор между две алтернативи. Вместо това те са възли Decorator, които имат един дъщерен възел. Ако успеят, те изпълняват своя единствен дъщерен възел.
  • Възлите, които извършват действия, връщат Running стойност, за да представят извършваните действия.

Този малък набор от възли може да се комбинира, за да създаде голям брой сложни поведения. Нека си представим охраната на HFSM от предишния пример като дърво на поведението:

Как да създадете AI за игри: ръководство за начинаещи

С тази структура не трябва да има очевиден преход от състояния на празен ход/патрулиране към състояния на атака или други. Ако врагът е видим и здравето на героя е ниско, изпълнението ще спре на възела Бягащ, независимо кой възел е изпълнявал преди това - Патрулиращ, Бездействащ, Атакуващ или който и да е друг.

Как да създадете AI за игри: ръководство за начинаещи

Дърветата на поведението са сложни – има много начини да ги съставите и намирането на правилната комбинация от декоратори и съставни възли може да бъде предизвикателство. Има и въпроси относно това колко често да проверяваме дървото - искаме ли да преминем през всяка част от него или само когато едно от условията се е променило? Как да съхраняваме състоянието, отнасящо се до възлите - как да разберем кога сме били на празен ход за 10 секунди или как да разберем кои възли са се изпълнявали последния път, за да можем да обработим последователността правилно?

Ето защо има много реализации. Например, някои системи са заменили декораторските възли с вградени декоратори. Те преоценяват дървото, когато условията на декоратора се променят, помагат за свързване на възли и предоставят периодични актуализации.

Система, базирана на помощни програми

Някои игри имат много различни механики. Желателно е те да получат всички предимства на простите и общи правила за преход, но не непременно под формата на пълно дърво на поведение. Вместо да имате ясен набор от възможности за избор или дърво с възможни действия, по-лесно е да разгледате всички действия и да изберете най-подходящото в момента.

Системата, базирана на помощни програми, ще помогне точно с това. Това е система, при която агентът има различни действия и избира кои от тях да извърши въз основа на относителната полезност на всяко от тях. Където полезността е произволна мярка за това колко важно или желателно е за агента да извърши това действие.

Изчислената полезност на действие въз основа на текущото състояние и среда, агентът може да провери и избере най-подходящото друго състояние по всяко време. Това е подобно на FSM, с изключение на случаите, когато преходите се определят от оценка за всяко потенциално състояние, включително текущото. Моля, имайте предвид, че ние избираме най-полезното действие, за да продължим (или да останем, ако вече сме го завършили). За по-голямо разнообразие това може да бъде балансирана, но произволна селекция от малък списък.

Системата присвоява произволен диапазон от стойности на полезност - например от 0 (напълно нежелателно) до 100 (напълно желателно). Всяко действие има редица параметри, които влияят върху изчисляването на тази стойност. Връщайки се към нашия пример с пазител:

Как да създадете AI за игри: ръководство за начинаещи

Преходите между действията са двусмислени - всяко състояние може да последва всяко друго. Приоритетите на действие се намират в върнатите полезни стойности. Ако врагът е видим и този враг е силен, а здравето на героя е ниско, тогава и Fleeing, и FindingHelp ще върнат високи ненулеви стойности. В този случай FindingHelp винаги ще бъде по-висок. По същия начин небойните дейности никога не връщат повече от 50, така че те винаги ще бъдат по-ниски от бойните. Трябва да вземете това предвид, когато създавате действия и изчислявате тяхната полезност.

В нашия пример действията връщат или фиксирана постоянна стойност, или една от двете фиксирани стойности. Една по-реалистична система би върнала оценка от непрекъснат диапазон от стойности. Например, действието Бягство връща по-високи стойности на полезност, ако здравето на агента е ниско, а действието Атака връща по-ниски стойности на полезност, ако врагът е твърде силен. Поради това действието Бягство има предимство пред Атаката във всяка ситуация, в която агентът смята, че няма достатъчно здраве, за да победи врага. Това позволява действията да бъдат приоритизирани въз основа на произволен брой критерии, което прави този подход по-гъвкав и променлив от дървото на поведението или FSM.

Всяко действие има много условия за изчисляване на програмата. Те могат да бъдат написани на скриптов език или като поредица от математически формули. Sims, който симулира ежедневието на героя, добавя допълнителен слой на изчисление - агентът получава поредица от "мотивации", които влияят на оценките за полезност. Ако герой е гладен, той ще стане още по-гладен с течение на времето и стойността на полезността на действието EatFood ще нараства, докато персонажът не го изпълни, намалявайки нивото на глада и връщайки стойността EatFood на нула.

Идеята за избор на действия въз основа на рейтингова система е доста проста, така че системата, базирана на помощни програми, може да се използва като част от процесите на вземане на решения с изкуствен интелект, а не като пълна замяна на тях. Дървото на решенията може да поиска оценка на полезността на два дъщерни възела и да избере по-високия. По подобен начин дървото на поведението може да има съставен помощен възел за оценка на полезността на действията, за да се реши кое дете да се изпълни.

Движение и навигация

В предишните примери имахме платформа, която местехме наляво или надясно, и пазач, който патрулира или атакува. Но как точно да се справим с движението на агенти за определен период от време? Как да зададем скорост, как да избягваме препятствията и как да планираме маршрут, когато достигането до дестинация е по-трудно от простото движение по права линия? Нека да разгледаме това.

Управление

В началния етап ще приемем, че всеки агент има стойност на скоростта, която включва колко бързо се движи и в каква посока. Може да се измерва в метри в секунда, километри в час, пиксели в секунда и т.н. Като си припомним цикъла Sense/Think/Act, можем да си представим, че частта Think избира скорост, а частта Act прилага тази скорост към агента. Обикновено игрите имат система за физика, която изпълнява тази задача вместо вас, като научава стойността на скоростта на всеки обект и я коригира. Следователно можете да оставите AI с една задача - да реши каква скорост трябва да има агентът. Ако знаете къде трябва да бъде агентът, тогава трябва да го преместите в правилната посока с определена скорост. Много тривиално уравнение:

желано_пътуване = позиция_дестинация – позиция_агент

Представете си 2D свят. Агентът е в точка (-2,-2), дестинацията е някъде на североизток в точка (30, 20), а необходимият път за агента да стигне до там е (32, 22). Да кажем, че тези позиции се измерват в метри - ако приемем скоростта на агента за 5 метра в секунда, тогава ще мащабираме нашия вектор на изместване и ще получим скорост от приблизително (4.12, 2.83). С тези параметри агентът ще пристигне на местоназначението си за почти 8 секунди.

Можете да преизчислите стойностите по всяко време. Ако агентът е на половината път до целта, движението ще бъде половината от дължината, но тъй като максималната скорост на агента е 5 m/s (решихме това по-горе), скоростта ще бъде същата. Това работи и за движещи се цели, позволявайки на агента да прави малки промени, докато се движат.

Но ние искаме повече вариации - например бавно увеличаване на скоростта, за да симулираме герой, който се движи от изправен в тичащ. Същото може да се направи и накрая преди спиране. Тези характеристики са известни като поведение на управление, всяко от които има специфични имена: Търсене, Бягство, Пристигане и т.н. Идеята е, че силите на ускорение могат да бъдат приложени към скоростта на агента въз основа на сравняване на позицията и текущата скорост на агента с дестинацията в за да използвате различни методи за придвижване до целта.

Всяко поведение има малко по-различна цел. Търсене и пристигане са начини за придвижване на агент до дестинация. Избягването на препятствията и разделянето коригират движението на агента, за да избегнат препятствията по пътя към целта. Подравняването и кохезията поддържат агентите да се движат заедно. Могат да се сумират произволен брой различни поведения на кормилното управление, за да се получи един вектор на пътя, като се вземат предвид всички фактори. Агент, който използва поведението на пристигане, разделяне и избягване на препятствия, за да стои далеч от стени и други агенти. Този подход работи добре на открити места без ненужни подробности.

При по-трудни условия добавянето на различни поведения работи по-зле - например агент може да се заклещи в стена поради конфликт между Пристигане и Избягване на препятствие. Следователно трябва да обмислите опции, които са по-сложни от простото добавяне на всички стойности. Начинът е следният: вместо да сумирате резултатите от всяко поведение, можете да обмислите движението в различни посоки и да изберете най-добрия вариант.

Въпреки това, в сложна среда със задънени улици и избори кой път да поемем, ще имаме нужда от нещо още по-напреднало.

Намиране на начин

Поведението на кормилното управление е чудесно за просто движение в открита зона (футболно игрище или арена), където придвижването от А до Б е права пътека само с незначителни заобиколки около препятствия. За сложни маршрути се нуждаем от намиране на пътя, което е начин за изследване на света и вземане на решение за маршрут през него.

Най-простият е да приложите решетка към всяко квадратче до агента и да прецените кой от тях има право да се движи. Ако една от тях е дестинация, следвайте маршрута от всеки квадрат до предишния, докато стигнете до началото. Това е маршрутът. В противен случай повторете процеса с близките други квадрати, докато намерите дестинацията си или свършите квадратите (което означава, че няма възможен маршрут). Това е това, което е официално известно като Търсене в ширина или BFS (алгоритъм за търсене в ширина). На всяка крачка той гледа във всички посоки (оттук широчина, "широчина"). Пространството за търсене е като фронт на вълна, който се движи, докато достигне желаното място - пространството за търсене се разширява на всяка стъпка, докато се включи крайната точка, след което може да бъде проследено обратно до началото.

Как да създадете AI за игри: ръководство за начинаещи

В резултат на това ще получите списък с квадрати, по които е съставен желаният маршрут. Това е пътят (следователно намиране на пътя) - списък с места, които агентът ще посети, докато следва дестинацията.

Като се има предвид, че знаем позицията на всеки квадрат в света, можем да използваме поведението на управление, за да се движим по пътя - от възел 1 до възел 2, след това от възел 2 до възел 3 и т.н. Най-лесният вариант е да се насочите към центъра на следващия квадрат, но още по-добър вариант е да спрете в средата на ръба между текущия квадрат и следващия. Поради това агентът ще може да изрязва ъглите при остри завои.

Алгоритъмът BFS също има недостатъци - той изследва толкова много квадрати в "грешната" посока, колкото и в "правилната" посока. Тук влиза в действие по-сложен алгоритъм, наречен A* (A star). Работи по същия начин, но вместо сляпо да изследва съседни квадрати (след това съседи на съседи, след това съседи на съседи на съседи и т.н.), той събира възлите в списък и ги сортира, така че следващият изследван възел винаги да е който води до най-краткия път. Възлите се сортират въз основа на евристика, която отчита две неща – „цената“ на хипотетичен маршрут до желания квадрат (включително всякакви пътни разходи) и оценка на това колко далеч е този квадрат от дестинацията (предубедено търсенето в правилна посока).

Как да създадете AI за игри: ръководство за начинаещи

Този пример показва, че агентът изследва един квадрат наведнъж, като всеки път избира съседния, който е най-обещаващ. Полученият път е същият като BFS, но по-малко квадрати са взети предвид в процеса - което има голямо влияние върху производителността на играта.

Движение без решетка

Но повечето игри не са подредени в мрежа и често е невъзможно да се направи това, без да се жертва реализма. Необходими са компромиси. Какъв размер трябва да бъдат квадратите? Твърде големи и няма да могат правилно да представят малки коридори или завои, твърде малки и ще има твърде много квадратчета за търсене, което в крайна сметка ще отнеме много време.

Първото нещо, което трябва да разберем е, че мрежата ни дава графика на свързани възли. Алгоритмите A* и BFS всъщност работят върху графики и изобщо не се интересуват от нашата мрежа. Можем да поставим възли навсякъде в света на играта: докато има връзка между всеки два свързани възела, както и между началната и крайната точка и поне един от възлите, алгоритъмът ще работи също толкова добре, колкото преди. Това често се нарича система от точки, тъй като всеки възел представлява значима позиция в света, която може да бъде част от произволен брой хипотетични пътеки.

Как да създадете AI за игри: ръководство за начинаещи
Пример 1: възел във всеки квадрат. Търсенето започва от възела, където се намира агентът, и завършва на възела на желания квадрат.

Как да създадете AI за игри: ръководство за начинаещи
Пример 2: По-малък набор от възли (пътни точки). Търсенето започва от квадрата на агента, преминава през необходимия брой възли и след това продължава до дестинацията.

Това е напълно гъвкава и мощна система. Но е необходимо известно внимание при решаването къде и как да поставите точка, в противен случай агентите може просто да не видят най-близката точка и няма да могат да започнат пътя. Би било по-лесно, ако можехме автоматично да поставяме пътни точки въз основа на геометрията на света.

Това е мястото, където се появява навигационната мрежа или navmesh (навигационна мрежа). Това обикновено е 2D мрежа от триъгълници, която се наслагва върху геометрията на света - навсякъде, където агентът има право да ходи. Всеки от триъгълниците в мрежата става възел в графиката и има до три съседни триъгълника, които стават съседни възли в графиката.

Тази снимка е пример от двигателя на Unity - той анализира геометрията в света и създаде навигационна мрежа (на екранната снимка в светло синьо). Всеки полигон в навигационна мрежа е зона, където агент може да стои или да се мести от един полигон в друг полигон. В този пример полигоните са по-малки от етажите, на които са разположени - това се прави, за да се вземе предвид размерът на агента, който ще се простира отвъд номиналната си позиция.

Как да създадете AI за игри: ръководство за начинаещи

Можем да търсим маршрут през тази мрежа, отново използвайки алгоритъма A*. Това ще ни даде почти идеален маршрут в света, който взема предвид цялата геометрия и не изисква ненужни възли и създаване на точки.

Pathfinding е твърде обширна тема, за която един раздел от статия не е достатъчен. Ако искате да го проучите по-подробно, тогава това ще ви помогне Уебсайт на Амит Пател.

планиране

Научихме с намирането на път, че понякога не е достатъчно просто да изберем посока и да се движим – трябва да изберем маршрут и да направим няколко завоя, за да стигнем до желаната дестинация. Можем да обобщим тази идея: постигането на цел не е просто следващата стъпка, а цяла последователност, в която понякога трябва да погледнете няколко стъпки напред, за да разберете коя трябва да бъде първата. Това се нарича планиране. Pathfinding може да се разглежда като едно от няколкото разширения на планирането. По отношение на нашия цикъл Разум/Мисли/Действай, това е мястото, където частта Мисли планира множество части Действие за бъдещето.

Нека да разгледаме примера на настолната игра Magic: The Gathering. Тръгваме първи със следния комплект карти в ръцете си:

  • Блато - Дава 1 черна мана (карта земя).
  • Гора - дава 1 зелена мана (земя карта).
  • Магьосник беглец - Изисква 1 синя мана за призоваване.
  • Elvish Mystic - Изисква 1 зелена мана за призоваване.

Игнорираме останалите три карти, за да улесним. Според правилата на играча е позволено да играе 1 земна карта на ход, той може да „докосне“ тази карта, за да извлече мана от нея, и след това да хвърли магии (включително призоваване на същество) според количеството мана. В тази ситуация човешкият играч знае да играе Forest, да докосне 1 зелена мана и след това да призове Elvish Mystic. Но как AI на играта може да разбере това?

Лесно планиране

Тривиалният подход е да опитвате всяко действие последователно, докато не останат подходящи. Като гледа картите, AI вижда какво може да играе Swamp. И той го играе. Остават ли други действия този ход? Не може да призове нито Elvish Mystic, нито Fugitive Wizard, тъй като те изискват съответно зелена и синя мана, за да ги призове, докато Swamp осигурява само черна мана. И вече няма да може да играе Forest, защото вече е играл Swamp. По този начин изкуственият интелект на играта следваше правилата, но го правеше зле. Може да се подобри.

Планирането може да намери списък с действия, които довеждат играта до желаното състояние. Точно както всеки квадрат на пътека имаше съседи (при намиране на път), всяко действие в план също има съседи или наследници. Можем да търсим тези действия и последващи действия, докато достигнем желаното състояние.

В нашия пример желаният резултат е „призоваване на същество, ако е възможно“. В началото на хода виждаме само две възможни действия, разрешени от правилата на играта:

1. Играйте Swamp (резултат: Swamp в играта)
2. Играйте Forest (резултат: Forest в играта)

Всяко предприето действие може да доведе до следващи действия и да затвори други, отново в зависимост от правилата на играта. Представете си, че играем Swamp - това ще премахне Swamp като следваща стъпка (вече сме го изиграли) и това също ще премахне Forest (защото според правилата можете да играете една карта земя на ход). След това AI ​​добавя получаване на 1 черна мана като следваща стъпка, защото няма други опции. Ако продължи напред и избере Tap the Swamp, той ще получи 1 единица черна мана и няма да може да направи нищо с нея.

1. Играйте Swamp (резултат: Swamp в играта)
1.1 „Tap“ Swamp (резултат: Swamp „tapped“, +1 единица черна мана)
Няма налични действия - КРАЙ
2. Играйте Forest (резултат: Forest в играта)

Списъкът с действия беше кратък, стигнахме до задънена улица. Повтаряме процеса за следващата стъпка. Играем Forest, отворете действието „вземете 1 зелена мана“, което от своя страна ще отвори третото действие - призовете Elvish Mystic.

1. Играйте Swamp (резултат: Swamp в играта)
1.1 „Tap“ Swamp (резултат: Swamp „tapped“, +1 единица черна мана)
Няма налични действия - КРАЙ
2. Играйте Forest (резултат: Forest в играта)
2.1 „Докоснете“ гора (резултат: Гората е „докосната“, +1 единица зелена мана)
2.1.1 Призоваване на Elvish Mystic (резултат: Elvish Mystic в игра, -1 зелена мана)
Няма налични действия - КРАЙ

Накрая проучихме всички възможни действия и намерихме план, който призовава създание.

Това е много опростен пример. Препоръчително е да изберете най-добрия възможен план, а не всеки план, който отговаря на определени критерии. По принцип е възможно да се оценят потенциални планове въз основа на резултата или общата полза от тяхното изпълнение. Можете да си спечелите 1 точка за игра на земна карта и 3 точки за призоваване на същество. Играта на Swamp би била план с 1 точка. И играейки Forest → Tap the Forest → summon Elvish Mystic веднага ще даде 4 точки.

Ето как работи планирането в Magic: The Gathering, но същата логика важи и в други ситуации. Например, преместване на пешка, за да се направи място за движение на епископа в шах. Или се покрийте зад стена, за да стреляте безопасно в XCOM по този начин. В общи линии схванахте идеята.

Подобрено планиране

Понякога има твърде много потенциални действия, за да се обмисли всяка възможна опция. Връщайки се към примера с Magic: The Gathering: да кажем, че в играта и в ръката ви има няколко карти земя и същества - броят на възможните комбинации от ходове може да бъде десетки. Има няколко решения на проблема.

Първият метод е обратно верижно свързване. Вместо да опитвате всички комбинации, по-добре е да започнете с крайния резултат и да се опитате да намерите директен път. Вместо да вървим от корена на дървото към конкретно листо, ние се движим в обратната посока – от листа към корена. Този метод е по-лесен и бърз.

Ако врагът има 1 здраве, можете да намерите плана „нанасяне на 1 или повече щети“. За да се постигне това, трябва да бъдат изпълнени редица условия:

1. Щетите могат да бъдат причинени от заклинание - трябва да е в ръка.
2. За да направите магия, имате нужда от мана.
3. За да получите мана, трябва да изиграете карта земя.
4. За да играете земна карта, трябва да я имате в ръката си.

Друг начин е най-доброто първо търсене. Вместо да изпробваме всички пътища, ние избираме най-подходящия. Най-често този метод дава оптималния план без излишни разходи за търсене. A* е форма на най-добро първо търсене - като изследва най-обещаващите маршрути от самото начало, той вече може да намери най-добрия път, без да се налага да проверява други опции.

Интересна и все по-популярна опция за най-добро първо търсене е Търсене на дърво в Монте Карло. Вместо да гадае кои планове са по-добри от другите, когато избира всяко следващо действие, алгоритъмът избира произволни наследници на всяка стъпка, докато стигне до края (когато планът е довел до победа или поражение). След това крайният резултат се използва за увеличаване или намаляване на теглото на предишни опции. Повтаряйки този процес няколко пъти подред, алгоритъмът дава добра оценка за това кой е най-добрият следващ ход, дори ако ситуацията се промени (ако врагът предприеме действие, за да пречи на играча).

Нито една история за планирането в игрите не би била пълна без планиране на целево ориентирано действие или GOAP (планиране на целево ориентирано действие). Това е широко използван и обсъждан метод, но с изключение на няколко отличителни детайла, това е по същество методът на обратно верижно свързване, за който говорихме по-рано. Ако целта е била да „унищожи играча“ и играчът е зад прикритие, планът може да бъде: унищожи с граната → вземи я → хвърли я.

Обикновено има няколко цели, всяка със свой приоритет. Ако целта с най-висок приоритет не може да бъде изпълнена (никаква комбинация от действия не създава план за „убий играча“, защото играчът не се вижда), AI ще се върне към целите с по-нисък приоритет.

Обучение и адаптация

Вече казахме, че изкуственият интелект на игрите обикновено не използва машинно обучение, защото не е подходящ за управление на агенти в реално време. Но това не означава, че не можете да заимствате нещо от тази област. Искаме противник в шутър, от който можем да научим нещо. Например, разберете за най-добрите позиции на картата. Или противник в бойна игра, който би блокирал често използваните комбо движения на играча, мотивирайки го да използва други. Така че машинното обучение може да бъде доста полезно в такива ситуации.

Статистика и вероятности

Преди да навлезем в сложни примери, нека видим докъде можем да стигнем, като направим няколко прости измервания и ги използваме за вземане на решения. Например стратегия в реално време - как да определим дали даден играч може да започне атака в първите няколко минути на играта и каква защита да подготвим срещу това? Можем да проучим миналия опит на играча, за да разберем какви могат да бъдат бъдещите реакции. Да започнем с това, че нямаме такива необработени данни, но можем да ги съберем - всеки път, когато AI играе срещу човек, той може да запише времето на първата атака. След няколко сесии ще получим средна стойност за времето, което ще отнеме на играча да атакува в бъдеще.

Има и проблем със средните стойности: ако играчът се втурна 20 пъти и играе бавно 20 пъти, тогава необходимите стойности ще бъдат някъде по средата и това няма да ни даде нищо полезно. Едно от решенията е да се ограничат входните данни - могат да се вземат предвид последните 20 броя.

Подобен подход се използва, когато се оценява вероятността от определени действия, като се допуска, че миналите предпочитания на играча ще бъдат същите в бъдеще. Ако играч ни атакува пет пъти с огнена топка, два пъти със светкавица и веднъж с меле, очевидно е, че той предпочита огнена топка. Нека екстраполираме и видим вероятността за използване на различни оръжия: огнена топка=62,5%, светкавица=25% и меле=12,5%. Нашата игра AI трябва да се подготви да се защити от пожар.

Друг интересен метод е използването на Naive Bayes Classifier за изучаване на големи количества входни данни и класифициране на ситуацията, така че AI да реагира по желания начин. Байесовите класификатори са най-известни с използването си във филтри за спам по имейл. Там те преглеждат думите, сравняват ги с мястото, където тези думи са се появявали преди (в спам или не) и правят заключения относно входящите имейли. Можем да направим същото дори с по-малко входове. Въз основа на цялата полезна информация, която AI вижда (като какви вражески единици са създадени, или какви магии използват, или какви технологии са изследвали), и крайния резултат (война или мир, бързане или защита и т.н.) - ще изберем желаното поведение на AI.

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

Адаптация, базирана на стойността

Като се има предвид съдържанието на нашия свят на играта и правилата, можем да променим набора от стойности, които влияят върху вземането на решения, вместо просто да използваме входните данни. Ние правим това:

  • Оставете AI да събира данни за състоянието на света и ключови събития по време на играта (както по-горе).
  • Нека променим няколко важни стойности въз основа на тези данни.
  • Ние изпълняваме нашите решения въз основа на обработка или оценка на тези стойности.

Например, агент има няколко стаи, от които да избира на карта на шутър от първо лице. Всяка стая има своя собствена стойност, която определя колко е желана да бъде посетена. AI произволно избира в коя стая да отиде въз основа на стойността. След това агентът си спомня в коя стая е бил убит и намалява нейната стойност (вероятността той да се върне там). По същия начин за обратната ситуация - ако агентът унищожи много опоненти, тогава стойността на стаята се увеличава.

Марков модел

Ами ако използвахме събраните данни, за да правим прогнози? Ако помним всяка стая, в която виждаме играч за определен период от време, ще предвидим в коя стая може да отиде играчът. Чрез проследяване и записване на движенията на играча в стаите (стойности), можем да ги предвидим.

Да вземем три стаи: червена, зелена и синя. А също и наблюденията, които записахме, докато гледахме игровата сесия:

Как да създадете AI за игри: ръководство за начинаещи

Броят на наблюденията във всяка стая е почти равен - все още не знаем къде да направим добро място за засада. Събирането на статистика също се усложнява от прераждането на играчи, които се появяват равномерно по цялата карта. Но данните за следващата стая, в която влизат, след като се появят на картата, вече са полезни.

Вижда се, че зелената стая подхожда на играчите - повечето хора се преместват от червената стая в нея, 50% от които остават там. Синята стая, напротив, не е популярна, почти никой не ходи в нея, а ако го правят, не остава дълго.

Но данните ни казват нещо по-важно - когато играч е в синя стая, следващата стая, в която го виждаме, ще бъде червена, а не зелена. Въпреки че зелената стая е по-популярна от червената стая, ситуацията се променя, ако играчът е в синята стая. Следващото състояние (т.е. стаята, в която играчът ще отиде) зависи от предишното състояние (т.е. стаята, в която играчът се намира в момента). Тъй като изследваме зависимостите, ще направим по-точни прогнози, отколкото ако просто преброим наблюденията независимо.

Прогнозирането на бъдещо състояние въз основа на данни от минало състояние се нарича модел на Марков, а такива примери (със стаи) се наричат ​​вериги на Марков. Тъй като моделите представляват вероятността от промени между последователни състояния, те се показват визуално като FSM с вероятност около всеки преход. По-рано използвахме FSM, за да представим поведенческото състояние, в което е бил агент, но тази концепция се разпростира до всяко състояние, независимо дали е свързано с агента или не. В този случай състоянията представляват стаята, която агентът заема:

Как да създадете AI за игри: ръководство за начинаещи

Това е прост начин за представяне на относителната вероятност от промени в състоянието, давайки на AI известна способност да предвиди следващото състояние. Можете да предвидите няколко стъпки напред.

Ако играч е в зелената стая, има 50% шанс той да остане там следващия път, когато бъде наблюдаван. Но какви са шансовете той да остане там дори след това? Не само има шанс играчът да е останал в зелената стая след две наблюдения, но също така има шанс да е напуснал и да се е върнал. Ето новата таблица, която взема предвид новите данни:

Как да създадете AI за игри: ръководство за начинаещи

То показва, че шансът да видите играча в зелената стая след две наблюдения ще бъде равен на 51% - 21%, че той ще бъде от червената стая, 5% от тях, че играчът ще посети синята стая между тях и 25%, че играчът няма да напусне зелената стая.

Таблицата е просто визуален инструмент - процедурата изисква само умножаване на вероятностите на всяка стъпка. Това означава, че можете да погледнете далеч в бъдещето с едно предупреждение: предполагаме, че шансът за влизане в стая зависи изцяло от текущата стая. Това се нарича Markov Property - бъдещото състояние зависи само от настоящето. Но това не е сто процента точно. Играчите могат да променят решенията си в зависимост от други фактори: ниво на здраве или количество боеприпаси. Тъй като не записваме тези стойности, нашите прогнози ще бъдат по-малко точни.

N-грамове

Какво ще кажете за примера на бойна игра и предвиждане на комбо ходовете на играча? Същото! Но вместо едно състояние или събитие, ние ще разгледаме целите последователности, които съставляват комбо удар.

Един от начините да направите това е да съхраните всеки вход (като Kick, Punch или Block) в буфер и да запишете целия буфер като събитие. Така че играчът многократно натиска Kick, Kick, Punch, за да използва атаката SuperDeathFist, AI системата съхранява всички входове в буфер и запомня последните три, използвани във всяка стъпка.

Как да създадете AI за игри: ръководство за начинаещи
(Редовете с удебелен шрифт са, когато играчът стартира атаката SuperDeathFist.)

AI ще види всички опции, когато играчът избере Kick, последван от друг Kick, и след това ще забележи, че следващият вход винаги е Punch. Това ще позволи на агента да предвиди комбинирания ход на SuperDeathFist и да го блокира, ако е възможно.

Тези поредици от събития се наричат ​​N-грами, където N е броят на съхранените елементи. В предишния пример беше 3-грам (триграма), което означава: първите два записа се използват за предсказване на третия. Съответно, в 5-грам, първите четири записа предсказват петия и така нататък.

Дизайнерът трябва внимателно да избере размера на N-грамите. По-малко N изисква по-малко памет, но също така съхранява по-малко история. Например, 2-грам (биграма) ще запише Kick, Kick или Kick, Punch, но няма да може да съхрани Kick, Kick, Punch, така че AI няма да отговори на комбинацията SuperDeathFist.

От друга страна, по-големите числа изискват повече памет и AI ще бъде по-труден за обучение, тъй като ще има много повече възможни опции. Ако имате три възможни входа на Kick, Punch или Block и ние използваме 10 грама, това ще бъде около 60 хиляди различни опции.

Моделът на биграма е проста верига на Марков - всяка двойка минало състояние/текущо състояние е биграма и можете да предвидите второто състояние въз основа на първото. 3-грамовите и по-големите N-грами също могат да се разглеждат като вериги на Марков, където всички елементи (с изключение на последния в N-грамата) заедно образуват първото състояние, а последният елемент - второто. Примерът за бойна игра показва шанса за преминаване от състояние Kick and Kick към състояние Kick and Punch. Като третираме множество записи в хронологията на въвеждане като едно цяло, ние по същество трансформираме входната последователност в част от цялото състояние. Това ни дава свойството на Марков, което ни позволява да използваме вериги на Марков, за да предвидим следващия вход и да познаем какъв комбо ход ще бъде следващият.

Заключение

Говорихме за най-разпространените инструменти и подходи в развитието на изкуствения интелект. Разгледахме и ситуациите, в които трябва да се използват и къде са особено полезни.

Това трябва да е достатъчно, за да разберете основите на ИИ на играта. Но, разбира се, това не са всички методи. По-малко популярни, но не по-малко ефективни включват:

  • оптимизационни алгоритми, включително изкачване по хълм, градиентно спускане и генетични алгоритми
  • състезателно търсене/алгоритми за планиране (minimax и алфа-бета подрязване)
  • методи за класификация (перцептрони, невронни мрежи и опорни векторни машини)
  • системи за обработка на възприятието и паметта на агентите
  • архитектурни подходи към AI (хибридни системи, подмножества архитектури и други начини за наслагване на AI системи)
  • инструменти за анимация (планиране и координация на движението)
  • фактори на ефективността (ниво на детайлност, по всяко време и алгоритми за разделяне на времето)

Онлайн ресурси по темата:

1. GameDev.net има раздел със статии и уроци за AIИ форума.
2. AiGameDev.com съдържа много презентации и статии по широк спектър от теми, свързани с разработването на AI игри.
3. Трезорът на GDC включва теми от GDC AI Summit, много от които са достъпни безплатно.
4. На сайта могат да бъдат намерени и полезни материали Гилдията на програмистите на AI игри.
5. Томи Томпсън, изследовател на AI и разработчик на игри, прави видеоклипове в YouTube AI и игри с обяснение и изучаване на AI в комерсиалните игри.

Книги по темата:

1. Поредицата от книги Game AI Pro е колекция от кратки статии, които обясняват как да внедрите специфични функции или как да решите конкретни проблеми.

Game AI Pro: Събрана мъдрост на професионалистите в играта AI
Game AI Pro 2: Събрана мъдрост на професионалистите в играта AI
Game AI Pro 3: Събрана мъдрост на професионалистите в играта AI

2. AI Game Programming Wisdom series е предшественик на Game AI Pro серията. Той съдържа по-стари методи, но почти всички са актуални дори днес.

Мъдрост за програмиране на AI игри 1
Мъдрост за програмиране на AI игри 2
Мъдрост за програмиране на AI игри 3
Мъдрост за програмиране на AI игри 4

3. Изкуствен интелект: Модерен подход е един от основните текстове за всеки, който иска да разбере общата област на изкуствения интелект. Това не е книга за разработването на игри - тя учи основите на AI.

Източник: www.habr.com

Добавяне на нов коментар