{"id":52118,"date":"2019-11-01T00:00:00","date_gmt":"2019-10-31T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih"},"modified":"2020-02-18T13:59:47","modified_gmt":"2020-02-18T10:59:47","slug":"kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih","status":"publish","type":"post","link":"https:\/\/prohoster.info\/ro\/blog\/news\/kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih","title":{"rendered":"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/9e57175b233a104e0df98383b374eded.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAm dat peste un material interesant despre inteligen\u021ba artificial\u0103 \u00een jocuri. Acesta explic\u0103 conceptele de baz\u0103 despre AI prin exemple simple, iar \u00een interior sunt multe instrumente \u0219i metode utile pentru dezvoltarea \u0219i proiectarea sa convenabil\u0103. Cum, unde \u0219i c\u00e2nd s\u0103 le folose\u0219ti - sunt de asemenea incluse.<\/p>\n<p>Majoritatea exemplelor sunt scrise \u00een pseudocod, a\u0219a c\u0103 nu sunt necesare cuno\u0219tin\u021be profunde de programare. Sub articol sunt 35 de pagini de text cu imagini \u0219i GIF-uri, a\u0219a c\u0103 preg\u0103te\u0219te-te.<\/p>\n<p>UPD. \u00cemi pare r\u0103u, dar am mai realizat un traducere a acestui articol pe Habr. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/users\/PatientZero\/\">PatientZero<\/a><\/noindex>. Po\u021bi citi varianta lui <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/post\/420219\/\">aici<\/a><\/noindex>, dar dintr-un anumit motiv articolul mi-a sc\u0103pat (am folosit c\u0103utarea, dar ceva nu a mers bine). A\u0219a c\u0103, deoarece scriu pe un blog dedicat dezvolt\u0103rii jocurilor, am decis s\u0103 las varianta mea de traducere pentru abona\u021bi (unele puncte sunt formulate diferit, iar altele sunt inten\u021bionat omise la sfatul dezvoltatorilor).<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Ce este AI?<\/h2>\n<p>\nAI-ul de jocuri se concentreaz\u0103 pe ac\u021biunile pe care un obiect trebuie s\u0103 le execute, \u00een func\u021bie de condi\u021biile \u00een care se afl\u0103. De obicei, acest lucru este numit gestionarea \u201eagen\u021bilor inteligen\u021bi\u201d, unde agentul este un personaj din joc, un vehicul, un bot \u0219i, uneori, chiar ceva mai abstract: un grup \u00eentreg de entit\u0103\u021bi sau chiar o civiliza\u021bie. \u00cen fiecare caz, acesta este un lucru care trebuie s\u0103 observe mediul s\u0103u, s\u0103 ia decizii bazate pe acesta \u0219i s\u0103 ac\u021bioneze \u00een consecin\u021b\u0103. Acest lucru se nume\u0219te ciclul Sense\/Think\/Act (Simte\/Strategizeaz\u0103\/Ac\u021bioneaz\u0103):<\/p>\n<ul>\n<li>Sense: agentul g\u0103se\u0219te sau prime\u0219te informa\u021bii despre lucruri din mediul s\u0103u, care pot influen\u021ba comportamentul s\u0103u (amenin\u021b\u0103ri apropiate, obiecte de colectat, locuri interesante de explorat).<\/li>\n<li>Think: agentul decide cum s\u0103 reac\u021bioneze (evalueaz\u0103 dac\u0103 este suficient de sigur s\u0103 colecteze obiecte sau dac\u0103 mai \u00eent\u00e2i trebuie s\u0103 se lupte\/ascund\u0103).<\/li>\n<li>Act: agentul \u00eendepline\u0219te ac\u021biuni pentru punerea \u00een aplicare a deciziei anterioare (\u00eencepe s\u0103 se \u00eendrepte spre inamic sau obiect).<\/li>\n<li>\u2026acum situa\u021bia s-a schimbat din cauza ac\u021biunilor personajelor, astfel c\u0103 ciclul se repet\u0103 cu date noi.<\/li>\n<\/ul>\n<p>\n\u00cen general, IA se concentreaz\u0103 pe partea de Sense a ciclului. De exemplu, automobilele autonome fac fotografii ale drumului, le combin\u0103 cu datele de radar \u0219i lidar, \u0219i le interpreteaz\u0103. De obicei, acest lucru este realizat de \u00eenv\u0103\u021barea automat\u0103, care proceseaz\u0103 datele de intrare \u0219i le d\u0103 sens, extr\u0103g\u00e2nd informa\u021bii semantice precum \u201eexist\u0103 o alt\u0103 ma\u0219in\u0103 la 20 de metri \u00een fa\u021ba ta\u201d. Acestea sunt a\u0219a-numitele probleme de clasificare.<\/p>\n<p>Jocurile nu necesit\u0103 un sistem complicat pentru extragerea informa\u021biilor, deoarece cea mai mare parte a datelor este deja o parte integrant\u0103 a acestora. Nu este nevoie s\u0103 rulezi algoritmi de recunoa\u0219tere a imaginilor pentru a determina dac\u0103 exist\u0103 un inamic \u00een fa\u021b\u0103 \u2014 jocul \u0219tie deja \u0219i transmite informa\u021biile \u00een procesul de luare a deciziilor. Prin urmare, partea de Sense a ciclului este adeseori mult mai simpl\u0103 dec\u00e2t Think \u0219i Act.<\/p>\n<h2>Limit\u0103rile IA-ului din jocuri<\/h2>\n<p>\nIA are o serie de limit\u0103ri care trebuie respectate:<\/p>\n<ul>\n<li>IA nu trebuie antrenat\u0103 \u00een avans, ca un algoritm de \u00eenv\u0103\u021bare automat\u0103. Este inutil s\u0103 scrii o re\u021bea neural\u0103 \u00een timpul dezvolt\u0103rii, pentru a observa zeci de mii de juc\u0103tori \u0219i a \u00eenv\u0103\u021ba cea mai bun\u0103 modalitate de a juca \u00eempotriva lor. De ce? Pentru c\u0103 jocul nu a fost lansat \u00eenc\u0103, iar juc\u0103torii nu exist\u0103.<\/li>\n<li>Jocul trebuie s\u0103 fie distractiv \u0219i provocator, astfel c\u0103 agen\u021bii nu ar trebui s\u0103 g\u0103seasc\u0103 cea mai bun\u0103 abordare \u00eempotriva oamenilor.<\/li>\n<li>Agen\u021bii trebuie s\u0103 par\u0103 reali\u0219ti, astfel \u00eenc\u00e2t juc\u0103torii s\u0103 simt\u0103 c\u0103 joac\u0103 \u00eempotriva unor oameni adev\u0103ra\u021bi. Programul AlphaGo a dep\u0103\u0219it oamenii, dar pa\u0219ii ale\u0219i au fost foarte diferi\u021bi de \u00een\u021belegerea tradi\u021bional\u0103 a jocului. Dac\u0103 jocul imit\u0103 un adversar uman, acest sentiment nu ar trebui s\u0103 existe. Algoritmul trebuie modificat pentru a lua decizii plauzibile, nu perfecte.<\/li>\n<li>IA trebuie s\u0103 func\u021bioneze \u00een timp real. Asta \u00eenseamn\u0103 c\u0103 algoritmul nu poate monopoliza utilizarea procesorului pentru o perioad\u0103 lung\u0103 de timp pentru a lua decizii. Chiar \u0219i 10 milisecunde pentru asta \u2014 este prea mult, deoarece majoritatea jocurilor necesit\u0103 \u00eentre 16 \u0219i 33 milisecunde pentru a efectua toat\u0103 procesarea \u0219i a trece la urm\u0103torul cadru grafic.<\/li>\n<li>Ideal ar fi ca m\u0103car o parte din sistem s\u0103 fie gestionat\u0103 de date, astfel \u00eenc\u00e2t \u201eneprogramatorii\u201d s\u0103 poat\u0103 face modific\u0103ri \u0219i s\u0103 corect\u0103rile s\u0103 aib\u0103 loc mai repede.<\/li>\n<\/ul>\n<p>\nS\u0103 lu\u0103m \u00een considerare abord\u0103rile IA care acoper\u0103 \u00eentregul ciclu Sense\/Think\/Act.<\/p>\n<h3>Luarea deciziilor de baz\u0103<\/h3>\n<p>\nS\u0103 \u00eencepem cu cel mai simplu joc - Pong. Scopul: muta\u021bi platforma (paddle) astfel \u00eenc\u00e2t mingea s\u0103 rico\u0219eze de pe ea, nu s\u0103 treac\u0103 pe l\u00e2ng\u0103. Este ca tenisul, \u00een care pierde\u021bi dac\u0103 nu love\u0219ti mingea. Aici, AI-ul are o sarcin\u0103 relativ u\u0219oar\u0103 - s\u0103 decid\u0103 \u00een ce direc\u021bie s\u0103 mi\u0219te platforma.<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/e1935d657b9f090bf60c365c21e8f92b.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3>Operatori condi\u021bionali<\/h3>\n<p>\nPentru AI \u00een Pong, exist\u0103 o solu\u021bie evident\u0103 - s\u0103 \u00eencerce \u00eentotdeauna s\u0103 pozi\u021bioneze platforma sub minge.<\/p>\n<p>Un algoritm simplu pentru aceasta, scris \u00een pseudocod:<\/p>\n<p><i>\u00een fiecare cadru\/update at\u00e2ta timp c\u00e2t jocul este \u00een desf\u0103\u0219urare:<br \/>\ndac\u0103 mingea este la st\u00e2nga platformei:<br \/>\n mi\u0219c\u0103 platforma la st\u00e2nga<br \/>\nalt dac\u0103 mingea este la dreapta platformei:<br \/>\n mi\u0219c\u0103 platforma la dreapta<\/i><\/p>\n<p>Dac\u0103 platforma se mi\u0219c\u0103 cu viteza mingii, atunci acesta este algoritmul ideal pentru AI \u00een Pong. Nu este necesar s\u0103 complic\u0103m lucrurile, dac\u0103 datele \u0219i posibilele ac\u021biuni pentru agent nu sunt at\u00e2t de multe.<\/p>\n<p>Aceast\u0103 abordare este at\u00e2t de simpl\u0103, \u00eenc\u00e2t \u00eentregul ciclu Sense\/Think\/Act este barely noticeable. Dar exist\u0103:<\/p>\n<ul>\n<li>Partea Sense se afl\u0103 \u00een cele dou\u0103 operatori if. Jocul \u0219tie unde este mingea \u0219i unde este platforma, deci AI-ul \u00eei cere aceste informa\u021bii. <\/li>\n<li>Partea Think se \u00eencadreaz\u0103, de asemenea, \u00een cele dou\u0103 operatori if. Ele \u00eentruchipeaz\u0103 cele dou\u0103 solu\u021bii, care \u00een acest caz sunt exclusiv active. Ca rezultat, se alege una dintre cele trei ac\u021biuni - muta\u021bi platforma la st\u00e2nga, muta\u021bi la dreapta sau nu face\u021bi nimic dac\u0103 aceasta este deja pozi\u021bionat\u0103 corect.<\/li>\n<li>Partea Act se afl\u0103 \u00een operatorii Move Paddle Left \u0219i Move Paddle Right. \u00cen func\u021bie de designul jocului, acestea pot mi\u0219ca platforma instantaneu sau cu o anumit\u0103 vitez\u0103. <\/li>\n<\/ul>\n<p>\nAstfel de abord\u0103ri sunt denumite reactive - exist\u0103 un set simplu de reguli (\u00een acest caz, operatorii if \u00een cod), care reac\u021bioneaz\u0103 la starea curent\u0103 a lumii \u0219i ac\u021bioneaz\u0103.<\/p>\n<h3>Arbore decizional<\/h3>\n<p>\nExemplul cu jocul Pong este, de fapt, echivalent cu conceptul formal de AI, numit arbore decizional. Algoritmul \u00eel parcurge pentru a ajunge la \u201efrunza\u201d - decizia cu privire la ce ac\u021biune s\u0103 \u00eentreprind\u0103.<\/p>\n<p>S\u0103 facem un diagram\u0103 a arborelui decizional pentru algoritmul platformei noastre:<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/d3b7290ba93144967cd849416cd5eef3.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nFiecare parte a arborelui se nume\u0219te node (nod) - AI-ul folose\u0219te teoria grafurilor pentru a descrie structuri similare. Exist\u0103 dou\u0103 tipuri de noduri:<\/p>\n<ul>\n<li>Noduri de decizie: alegerea \u00eentre dou\u0103 alternative pe baza verific\u0103rii unei anumite condi\u021bii, unde fiecare alternativ\u0103 este reprezentat\u0103 sub form\u0103 de nod separat.<\/li>\n<li>Noduri terminale: ac\u021biunea de realizat, care reprezint\u0103 decizia final\u0103.<\/li>\n<\/ul>\n<p>\nAlgoritmul \u00eencepe cu primul nod (\u201er\u0103d\u0103cina\u201d arborelui). Acesta decide fie la ce nod copil s\u0103 treac\u0103, fie execut\u0103 o ac\u021biune stocat\u0103 \u00een nod \u0219i se finalizeaz\u0103.<\/p>\n<p>Care este avantajul, dac\u0103 arborele decizional realizeaz\u0103 aceea\u0219i munc\u0103 ca operatorii if din sec\u021biunea anterioar\u0103? Exist\u0103 un sistem comun, \u00een care fiecare decizie are o singur\u0103 condi\u021bie \u0219i dou\u0103 rezultate posibile. Acest lucru permite dezvoltatorului s\u0103 construiasc\u0103 AI din date care reprezint\u0103 decizii \u00een arbore, evit\u00e2nd hardcodarea acestora. S\u0103 ne imagin\u0103m sub form\u0103 de tabel:<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/6875293a60ff9d0efa26fb5e1aa4b21c.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPe partea de cod, ve\u021bi ob\u021bine un sistem pentru citirea liniilor. Crea\u021bi un nod pentru fiecare dintre ele, conecta\u021bi logica de luare a deciziilor pe baza celei de-a doua coloane \u0219i nodurile copil pe baza celor de-a treia \u0219i a patra coloane. Trebuie s\u0103 programa\u021bi \u00eenc\u0103 condi\u021biile \u0219i ac\u021biunile, dar acum structura jocului va fi mai complex\u0103. Aici ad\u0103uga\u021bi decizii \u0219i ac\u021biuni suplimentare \u0219i, apoi, ajusta\u021bi \u00eentregul AI, modific\u00e2nd pur \u0219i simplu un fi\u0219ier text cu defini\u021bia arborelui. Apoi, transfera\u021bi fi\u0219ierul designerului de jocuri, care poate schimba comportamentul f\u0103r\u0103 a recompila jocul \u0219i a modifica codul.<\/p>\n<p>Arborii decizionali sunt foarte utili atunci c\u00e2nd sunt construi\u021bi automat pe baza unui set mare de exemple (de exemplu, folosind algoritmul ID3). Acest lucru le face un instrument eficient \u0219i performant pentru clasificarea situa\u021biilor pe baza datelor ob\u021binute. Cu toate acestea, dep\u0103\u0219im o simpl\u0103 sistem pentru selectarea ac\u021biunilor de c\u0103tre agen\u021bi.<\/p>\n<h3>Scenarii<\/h3>\n<p>\nAm analizat sistemul arborelui decizional care utiliza condi\u021bii \u0219i ac\u021biuni create anterior. Persoana care proiecteaz\u0103 AI-ul poate organiza arborele a\u0219a cum dore\u0219te, dar \u00eenc\u0103 trebuie s\u0103 se bazeze pe programatorul care a scris tot codul. Ce ar fi dac\u0103 am putea oferi designerului instrumente pentru a crea propriile condi\u021bii sau ac\u021biuni?<\/p>\n<p>Pentru a evita ca programatorul s\u0103 scrie cod pentru condi\u021biile Is Ball Left Of Paddle \u0219i Is Ball Right Of Paddle, el poate construi un sistem \u00een care designerul s\u0103 \u00eenregistreze condi\u021biile pentru a verifica aceste valori. Atunci datele arborelui decizional vor ar\u0103ta astfel:<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/8e77f7c3410d097e8b7d8e1209355cc6.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n\u00cen esen\u021b\u0103, aceasta este la fel ca \u00een prima tabel\u0103, \u00eens\u0103 solu\u021biile au propriul cod, ceva asem\u0103n\u0103tor cu partea condi\u021bional\u0103 a operatorului if. Din punct de vedere al codului, acest lucru ar fi citit \u00een a doua coloan\u0103 pentru nodurile de decizie, dar \u00een loc s\u0103 caute o condi\u021bie specific\u0103 de executat (Este mingea la st\u00e2nga paletei), evalueaz\u0103 expresia condi\u021bional\u0103 \u0219i returneaz\u0103 true sau false \u00een consecin\u021b\u0103. Aceasta se face cu ajutorul limbajului de scripting Lua sau Angelscript. Prin acestea, dezvoltatorul poate manipula obiectele din jocul s\u0103u (mingea \u0219i paleta) \u0219i poate crea variabile utilizabile \u00een scenariul (ball.position). \u00cen plus, limbajul de scripting este mai simplu dec\u00e2t C++. Nu necesit\u0103 o etap\u0103 complet\u0103 de compilare, fiind astfel ideal pentru ajustarea rapid\u0103 a logicii de joc \u0219i permi\u021b\u00e2nd \u201enon-programatorilor\u201d s\u0103 creeze ei \u00een\u0219i\u0219i func\u021biile dorite.<\/p>\n<p>\u00cen exemplul oferit, limbajul de scripting este folosit doar pentru a evalua expresia condi\u021bional\u0103, \u00eens\u0103 poate fi utilizat \u0219i pentru ac\u021biuni. De exemplu, datele Move Paddle Right pot deveni un operator de scripting (ball.position.x += 10). Astfel, ac\u021biunea este definit\u0103 \u0219i \u00een script, f\u0103r\u0103 a necesita programarea Move Paddle Right.<\/p>\n<p>Se poate merge \u0219i mai departe \u0219i se poate scrie complet un arbore de decizie \u00een limbajul de scripting. Acesta va fi cod sub form\u0103 de operatori condi\u021bionali hardcoded, dar vor fi \u00een fi\u0219iere externe de script, ceea ce \u00eenseamn\u0103 c\u0103 pot fi modificate f\u0103r\u0103 a re-compila \u00eentreaga program\u0103. Adesea, fi\u0219ierul scriptului poate fi modificat chiar \u00een timpul jocului, pentru a testa rapid diferite reac\u021bii ale AI-ului.<\/p>\n<h3>Reac\u021bionarea la evenimente<\/h3>\n<p>\nExemplele de mai sus se aplic\u0103 perfect \u00een Pong. Acestea ruleaz\u0103 continuu un ciclu Sens\/Reflectare\/Ac\u021biune \u0219i ac\u021bioneaz\u0103 pe baza ultimei st\u0103ri a lumii. \u00cens\u0103 \u00een jocuri mai complexe, este necesar s\u0103 se reac\u021bioneze la evenimente individuale, nu s\u0103 se evalueze totul deodat\u0103. \u00cen acest caz, Pong nu mai este un exemplu adecvat. S\u0103 alegem altceva. <\/p>\n<p>Imagina\u021bi-v\u0103 un shooter, unde inamicii sunt nemi\u0219ca\u021bi p\u00e2n\u0103 c\u00e2nd descoper\u0103 juc\u0103torul, dup\u0103 care ac\u021bioneaz\u0103 \u00een func\u021bie de \u201especializarea\u201d lor: unii vor alerga \u201erush\u201d, al\u021bii vor ataca de la distan\u021b\u0103. Aceasta este \u00een continuare o sistem de reac\u021bie de baz\u0103 \u2013 \u201edac\u0103 juc\u0103torul este v\u0103zut, atunci f\u0103 ceva\u201d \u2013 dar poate fi logic \u00eemp\u0103r\u021bit \u00een evenimentul Juc\u0103tor V\u0103zut (player seen) \u0219i reac\u021bia (alege un r\u0103spuns \u0219i execut\u0103-l).<\/p>\n<p>Aceasta ne \u00eentoarce la ciclul Sense\/Think\/Act. Putem programa partea de Sense care va verifica \u00een fiecare cadru dac\u0103 AI-ul vede juc\u0103torul. Dac\u0103 nu, nu se \u00eent\u00e2mpl\u0103 nimic, dar dac\u0103 vede, se creeaz\u0103 un eveniment Player Seen. Codul va avea o sec\u021biune separat\u0103 care spune: \u201ec\u00e2nd are loc evenimentul Player Seen, f\u0103 \u201d, unde  reprezint\u0103 r\u0103spunsul de care ai nevoie pentru a te referi la p\u0103r\u021bile Think \u0219i Act. Astfel, vei configura reac\u021biile la evenimentul Player Seen: pentru personajul \u201eg\u0103l\u0103gios\u201d \u2013 ChargeAndAttack, iar pentru lunetist \u2013 HideAndSnipe. Aceste leg\u0103turi pot fi create \u00een fi\u0219ierul de date pentru a fi editate rapid f\u0103r\u0103 a fi nevoie s\u0103 recompili toate. \u0218i aici se poate folosi un limbaj de script.<\/p>\n<h2>Acceptarea deciziilor complexe<\/h2>\n<p>\nDe\u0219i sistemele simple de reac\u021bie sunt foarte eficiente, exist\u0103 multe situa\u021bii \u00een care acestea sunt insuficiente. Uneori, este necesar s\u0103 ia decizii diferite, bazate pe ceea ce agentul face \u00een acel moment, dar a prezenta acest lucru ca o condi\u021bie este dificil. Uneori exist\u0103 prea multe condi\u021bii pentru a le reprezenta eficient \u00eentr-un arbore de decizie sau script. Uneori, este necesar s\u0103 evalu\u0103m din timp cum se va schimba situa\u021bia \u00eenainte de a lua o decizie cu privire la urm\u0103torul pas. Pentru a rezolva aceste probleme, sunt necesare abord\u0103ri mai complexe.<\/p>\n<h3>Ma\u0219ina de stare finit\u0103<\/h3>\n<p>\nMa\u0219ina de stare finit\u0103 sau FSM (finite state machine) este un mod de a spune c\u0103 agentul nostru se afl\u0103 \u00een prezent \u00eentr-o stare din mai multe posibile, \u0219i c\u0103 poate trece dintr-o stare \u00een alta. Exist\u0103 un num\u0103r prestabilit de astfel de st\u0103ri \u2013 de aici \u0219i numele. Cel mai bun exemplu din via\u021b\u0103 este semaforul. \u00cen diferite locuri sunt diferite secven\u021be de lumini, dar principiul este acela\u0219i \u2013 fiecare stare reprezint\u0103 ceva (stai, mergi etc.). Semaforul se afl\u0103 \u00eentr-o singur\u0103 stare \u00een orice moment dat, \u0219i trece de la una la alta pe baza unor reguli simple.<\/p>\n<p>Cu NPC-urile din jocuri, povestea este similar\u0103. Ca exemplu, s\u0103 lu\u0103m un gardian cu urm\u0103toarele st\u0103ri:<\/p>\n<ul>\n<li>Patrul\u00e2nd (Patrolling).<\/li>\n<li>Atac\u00e2nd (Attacking).<\/li>\n<li>Fugind (Fleeing).<\/li>\n<\/ul>\n<p>\nIar condi\u021biile pentru schimbarea st\u0103rii sale sunt:<\/p>\n<ul>\n<li>Dac\u0103 gardianul vede un inamic, atac\u0103.<\/li>\n<li>Dac\u0103 gardianul atac\u0103, dar nu mai vede inamicul, se \u00eentoarce la patrulare.<\/li>\n<li>Dac\u0103 gardianul atac\u0103, dar este r\u0103nit grav, fuge.<\/li>\n<\/ul>\n<p>\nDe asemenea, putem scrie if-operatori cu variabila de stare a gardianului \u0219i diverse verific\u0103ri: exist\u0103 un du\u0219man \u00een apropiere, care este nivelul de s\u0103n\u0103tate al NPC-ului etc. S\u0103 ad\u0103ug\u0103m c\u00e2teva st\u0103ri suplimentare:<\/p>\n<ul>\n<li>Inactivitate (Idling) \u2014 \u00eentre patrul\u0103ri.<\/li>\n<li>C\u0103utare (Searching) \u2014 c\u00e2nd du\u0219manul observat s-a ascuns.<\/li>\n<li>A cere ajutor (Finding Help) \u2014 c\u00e2nd un du\u0219man este observat, dar este prea puternic pentru a lupta cu el singur.<\/li>\n<\/ul>\n<p>\nAlegerile fiec\u0103ruia sunt limitate \u2014 de exemplu, gardianul nu va merge s\u0103 caute du\u0219manul ascuns dac\u0103 are s\u0103n\u0103tate sc\u0103zut\u0103.<\/p>\n<p>&Icirc;n cele din urm\u0103, o list\u0103 uria\u0219\u0103 de &laquo;dac\u0103 &lt;x \u0438 y, \u043d\u043e \u043d\u0435 z&gt;, atunci &lt;p&gt;&raquo;, poate deveni prea voluminoas\u0103, a\u0219a c\u0103 ar trebui s\u0103 formaliz\u0103m o metod\u0103 care s\u0103 ne permit\u0103 s\u0103 re\u021binem st\u0103rile \u0219i tranzi\u021biile &icirc;ntre st\u0103ri. Pentru a face acest lucru, vom lua &icirc;n considerare toate st\u0103rile \u0219i, sub fiecare stare, vom nota o list\u0103 cu toate tranzi\u021biile c\u0103tre alte st\u0103ri, &icirc;mpreun\u0103 cu condi\u021biile necesare pentru acestea.<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/ba4c401aa20de3d22d2478cba5a4b1ec.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAceasta este o tabel\u0103 a tranzi\u021biilor de stare \u2014 o modalitate complex\u0103 de a reprezenta FSM. S\u0103 desen\u0103m o diagram\u0103 \u0219i s\u0103 ob\u021binem o imagine de ansamblu complet\u0103 a modului \u00een care se schimb\u0103 comportamentul NPC-ului.<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/b4182359983cf573872dacc575af13dc.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDiagrama reflect\u0103 esen\u021ba lu\u0103rii deciziilor pentru acest agent pe baza situa\u021biei curente. Fiecare s\u0103geat\u0103 arat\u0103 o tranzi\u021bie \u00eentre st\u0103ri, dac\u0103 condi\u021bia al\u0103turat\u0103 este adev\u0103rat\u0103.<\/p>\n<p>La fiecare actualizare, verific\u0103m starea curent\u0103 a agentului, examin\u0103m lista de tranzi\u021bii \u0219i, dac\u0103 condi\u021biile pentru tranzi\u021bie sunt \u00eendeplinite, acesta \u00ee\u0219i schimb\u0103 starea. De exemplu, la fiecare cadru, se verific\u0103 dac\u0103 timerul de 10 secunde a expirat, iar dac\u0103 da, atunci din starea Idling, gardianul trece \u00een Patrolling. \u00cen acela\u0219i mod, starea Attacking verific\u0103 s\u0103n\u0103tatea agentului \u2014 dac\u0103 este sc\u0103zut\u0103, trece \u00een starea Fleeing.<\/p>\n<p>Aceasta este procesarea tranzi\u021biilor \u00eentre st\u0103ri, dar ce zici de comportamentul legat de st\u0103rile \u00een sine? \u00cen ceea ce prive\u0219te implementarea comportamentului efectiv pentru o stare specific\u0103, de obicei exist\u0103 dou\u0103 tipuri de \u201ehook-uri\u201d, unde atribuim ac\u021biuni la FSM:<\/p>\n<ul>\n<li>Ac\u021biuni pe care le execut\u0103m periodic pentru starea curent\u0103.<\/li>\n<li>Ac\u021biuni pe care le \u00eentreprindem c\u00e2nd trecem dintr-o stare \u00een alta.<\/li>\n<\/ul>\n<p>\nExemple pentru primul tip. Starea Patrolling va muta agentul pe traseul de patrulare la fiecare cadru. Starea Attacking va \u00eencerca, la fiecare cadru, s\u0103 \u00eenceap\u0103 un atac sau s\u0103 treac\u0103 \u00eentr-o stare c\u00e2nd acest lucru este posibil.<\/p>\n<p>Pentru al doilea tip, s\u0103 examin\u0103m tranzi\u021bia \u201edac\u0103 inamicul este vizibil \u0219i inamicul este prea puternic, atunci trece\u021bi \u00eentr-o stare de G\u0103sire Ajutor. Agentul trebuie s\u0103 aleag\u0103 unde s\u0103 mearg\u0103 pentru ajutor \u0219i s\u0103 p\u0103streze aceast\u0103 informa\u021bie, astfel \u00eenc\u00e2t starea G\u0103sire Ajutor s\u0103 \u0219tie c\u0103tre cine s\u0103 se adreseze. Odat\u0103 ce ajutorul este g\u0103sit, agentul revine la starea Atacare. \u00cen acel moment, el va dori s\u0103 informeze un aliat despre amenin\u021bare, motiv pentru care poate ap\u0103rea ac\u021biunea NotificarePrietenDespreAmenin\u021bare.<\/p>\n<p>\u0218i din nou, putem privi acest sistem prin prisma ciclului Simte\/G\u00e2nde\u0219te\/Ac\u021bioneaz\u0103. Simte se \u00eentruchipeaz\u0103 \u00een datele utilizate \u00een logica tranzi\u021biei. G\u00e2nde\u0219te \u2014 \u00een tranzi\u021biile disponibile \u00een fiecare stare. Iar Ac\u021bioneaz\u0103 se realizeaz\u0103 prin ac\u021biunile desf\u0103\u0219urate periodic \u00een cadrul st\u0103rii sau la tranzi\u021biile dintre st\u0103ri.<\/p>\n<p>Uneori, sondajul continuu al condi\u021biilor de tranzi\u021bie poate fi costisitor. De exemplu, dac\u0103 fiecare agent ar efectua calcule complexe \u00een fiecare cadru pentru a determina dac\u0103 vede inamicii \u0219i pentru a \u00een\u021belege dac\u0103 poate trece de la starea Patrulare la Atacare \u2014 acest lucru va consuma mult timp de procesor. <\/p>\n<p>Schimb\u0103rile importante \u00een starea lumii pot fi considerate evenimente care vor fi procesate pe m\u0103sur\u0103 ce apar. \u00cen loc ca FSM s\u0103 verifice \u00een fiecare cadru condi\u021bia de tranzi\u021bie \u201epoate agentul meu s\u0103-l vad\u0103 pe juc\u0103tor?\u201d, se poate configura un sistem separat pentru a efectua verific\u0103rile mai rar (de exemplu, de 5 ori pe secund\u0103). Iar rezultatul va fi emiterea Player Seen, atunci c\u00e2nd verificarea trece. <\/p>\n<p>Aceasta se transmite \u00een FSM, care acum trebuie s\u0103 treac\u0103 la condi\u021bia 'Eveniment Player Seen primit' \u0219i s\u0103 reac\u021bioneze corespunz\u0103tor. Comportamentul final este acela\u0219i, cu excep\u021bia unei \u00eent\u00e2rzieri aproape imperceptibile \u00eenainte de r\u0103spuns. Dar performan\u021ba a \u00eembun\u0103t\u0103\u021bit \u00een urma separ\u0103rii p\u0103r\u021bii Sense \u00eentr-o parte separat\u0103 a programului.<\/p>\n<h3>Ma\u0219in\u0103 de st\u0103ri finite ierarhic\u0103<\/h3>\n<p>\nCu toate acestea, lucrul cu FSM mari nu este \u00eentotdeauna convenabil. Dac\u0103 dorim s\u0103 extindem starea de atac, \u00eenlocuind-o cu atacuri M\u00e2ini (MeleeAttacking) \u0219i atacuri la distan\u021b\u0103 (RangedAttacking), va trebui s\u0103 modific\u0103m tranzi\u021biile din toate celelalte st\u0103ri care duc la starea Atacare (cele actuale \u0219i viitoare).<\/p>\n<p>Cu siguran\u021b\u0103 a\u021bi observat c\u0103 \u00een exemplul nostru exist\u0103 multe tranzi\u021bii duplicate. Cele mai multe tranzi\u021bii \u00een starea Idling sunt identice cu cele din starea Patrolling. Ar fi bine s\u0103 evit\u0103m redundan\u021ba, mai ales dac\u0103 ad\u0103ug\u0103m mai multe st\u0103ri asem\u0103n\u0103toare. Are sens s\u0103 grup\u0103m Idling \u0219i Patrolling sub o etichet\u0103 comun\u0103 \u201enon-combate\u201d, unde exist\u0103 un singur set comun de tranzi\u021bii c\u0103tre st\u0103rile de lupt\u0103. Dac\u0103 ne imagin\u0103m aceast\u0103 etichet\u0103 ca o stare, Idling \u0219i Patrolling devin sub-st\u0103ri. Exemplu de utilizare a unei tabele separate de tranzi\u021bii pentru noua sub-stare non-combat:<\/p>\n<p><i>St\u0103rile principale:<\/i><br \/>\n<img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/d86dd918acbe81b9bf22c2fb34aecee3.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\n<i>Starea \u00een afara luptei:<\/i><br \/>\n<img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/9d5bc2053010a32c5f68d7f0192c04ed.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n\u0218i sub form\u0103 de diagram\u0103:<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/0ccf95ecafa9ce2a6ea5b5b9833ddc4f.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAceasta este aceea\u0219i sistem\u0103, dar cu o nou\u0103 stare non-combat, care include Idling \u0219i Patrolling. Fiecare stare con\u021bine un FSM cu sub-st\u0103ri (iar aceste sub-st\u0103ri, la r\u00e2ndul lor, con\u021bin propriile FSM \u2013 \u0219i a\u0219a mai departe c\u00e2t de mult este necesar), ob\u021binem a\u0219a-numitul Hierarchical Finite State Machine sau HFSM (ma\u0219in\u0103 de st\u0103ri finite ierarhic\u0103). Grup\u00e2nd starea non-combat, am eliminat multe tranzi\u021bii redundante. Acela\u0219i lucru \u00eel putem face pentru orice noi st\u0103ri cu tranzi\u021bii comune. De exemplu, dac\u0103 \u00een viitor extindem starea Attacking la st\u0103rile MeleeAttacking \u0219i MissileAttacking, acestea vor fi sub-st\u0103ri care se vor tranzita \u00eentre ele pe baza distan\u021bei fa\u021b\u0103 de inamic \u0219i a disponibilit\u0103\u021bii muni\u021biilor. \u00cen final, modele complexe de comportament \u0219i submodele de comportament pot fi reprezentate cu un minim de tranzi\u021bii duplicate.<\/p>\n<h3>Arborele comportamentelor<\/h3>\n<p>\nCu HFSM se creeaz\u0103 combina\u021bii complexe de comportamente \u00eentr-un mod simplu. Cu toate acestea, exist\u0103 o mic\u0103 dificultate, deoarece luarea deciziilor sub form\u0103 de reguli de tranzi\u021bie este str\u00e2ns legat\u0103 de starea curent\u0103. \u0218i \u00een multe jocuri, acest lucru este exact ceea ce este necesar. O utilizare atent\u0103 a ierarhiei de st\u0103ri poate reduce num\u0103rul de redundan\u021be \u00een tranzi\u021bii. Dar uneori sunt necesare reguli care s\u0103 func\u021bioneze indiferent de starea \u00een care v\u0103 afla\u021bi sau care se aplic\u0103 aproape \u00een orice st\u0103ri. De exemplu, dac\u0103 s\u0103n\u0103tatea agentului scade sub 25%, v-ar pl\u0103cea s\u0103 fug\u0103 indiferent dac\u0103 se afl\u0103 \u00een lupt\u0103, se afl\u0103 \u00een repaus sau discut\u0103 \u2013 va trebui s\u0103 ad\u0103uga\u021bi aceast\u0103 condi\u021bie \u00een fiecare stare. \u0218i dac\u0103 designerul dumneavoastr\u0103 va dori mai t\u00e2rziu s\u0103 schimbe pragul de s\u0103n\u0103tate sc\u0103zut de la 25% la 10%, va trebui s\u0103 se ocupe din nou de acest lucru.<\/p>\n<p>Ideal pentru aceast\u0103 situa\u021bie este un sistem \u00een care deciziile \u201e\u00een ce stare s\u0103 ne afl\u0103m\u201d se afl\u0103 \u00een afara st\u0103rilor \u00een sine, astfel \u00eenc\u00e2t modific\u0103rile s\u0103 fie realizate \u00eentr-un singur loc, f\u0103r\u0103 a afecta condi\u021biile de tranzi\u021bie. Aici apar arborii comportamentali.<\/p>\n<p>Exist\u0103 mai multe modalit\u0103\u021bi de a le implementa, dar esen\u021ba pentru toate este aproximativ aceea\u0219i \u0219i seam\u0103n\u0103 cu un arbore de decizie: algoritmul \u00eencepe cu un nod \u201er\u0103d\u0103cin\u0103\u201d, iar \u00een arbore se afl\u0103 noduri care reprezint\u0103 fie decizii, fie ac\u021biuni. Totu\u0219i, exist\u0103 c\u00e2teva diferen\u021be cheie:<\/p>\n<ul>\n<li>Acum nodurile returneaz\u0103 unul dintre cele trei valori: Succeeded (dac\u0103 opera\u021biunea a fost finalizat\u0103), Failed (dac\u0103 nu se poate porni) sau Running (dac\u0103 este \u00eenc\u0103 \u00een desf\u0103\u0219urare \u0219i nu exist\u0103 un rezultat final).<\/li>\n<li>Nu mai exist\u0103 noduri de decizie pentru a alege \u00eentre dou\u0103 alternative. \u00cen locul lor exist\u0103 noduri Decorator, care au un singur nod copil. Dac\u0103 acestea reu\u0219esc, atunci execut\u0103 nodul lor unic copil.<\/li>\n<li>Nodurile care efectueaz\u0103 ac\u021biuni returneaz\u0103 valoarea Running pentru a reprezenta ac\u021biunile \u00een desf\u0103\u0219urare.<\/li>\n<\/ul>\n<p>\nAceast\u0103 mic\u0103 serie de noduri poate fi combinat\u0103 pentru a crea un num\u0103r mare de modele complexe de comportament. S\u0103 ne imagin\u0103m HFSM-ul unui garda din exemplul anterior sub forma unui arbore comportamental:<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/5eaa5c725e4ada8285f16f95bb206d53.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCu aceast\u0103 structur\u0103, nu ar trebui s\u0103 existe o tranzi\u021bie explicit\u0103 de la st\u0103rile Idling\/Patrolling la starea Attacking sau la alte st\u0103ri. Dac\u0103 inamicul este vizibil \u0219i s\u0103n\u0103tatea personajului este sc\u0103zut\u0103, execu\u021bia se va opri la nodul Fleeing, indiferent de nodul pe care l-a executat anterior \u2014 Patrolling, Idling, Attacking sau oricare altul.<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/e1c1dcc2055174aa7cfa846364b1709a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nArborii comportamentali sunt complec\u0219i \u2014 exist\u0103 multe modalit\u0103\u021bi de a-i construi, iar g\u0103sirea combina\u021biei corecte de decoratori \u0219i noduri compuse poate fi problematic\u0103. Exist\u0103, de asemenea, \u00eentreb\u0103ri despre c\u00e2t de des s\u0103 verific\u0103m arborele \u2014 vrem s\u0103 trecem prin fiecare parte a acestuia sau doar atunci c\u00e2nd una dintre condi\u021bii s-a schimbat? Cum s\u0103 p\u0103str\u0103m starea asociat\u0103 nodurilor \u2014 cum s\u0103 \u0219tim c\u00e2nd am fost \u00een starea Idling timp de 10 secunde sau cum s\u0103 \u0219tim ce noduri au fost executate ultima dat\u0103, pentru a gestiona corect secven\u021ba?<\/p>\n<p>Exact din acest motiv exist\u0103 numeroase implement\u0103ri. De exemplu, \u00een unele sisteme, nodurile decorator au fost \u00eenlocuite cu decoratori \u00eencorpora\u021bi. Ace\u0219tia reevalueaz\u0103 arborele atunci c\u00e2nd condi\u021biile decoratorului se schimb\u0103, ajut\u0103 la conectarea nodurilor \u0219i ofer\u0103 actualiz\u0103ri periodice.<\/p>\n<h3>Sistem bazat pe utilitate<\/h3>\n<p>\nUnele jocuri au multe mecanici diferite. Este de dorit ca acestea s\u0103 beneficieze de toate avantajele regulilor simple \u0219i generale de tranzi\u021bie, dar nu este obligatoriu s\u0103 fie sub forma unui arbore comportamental complet. \u00cen loc s\u0103 existe un set clar de alegeri sau un arbore de ac\u021biuni posibile, este mai simplu s\u0103 studiem toate ac\u021biunile \u0219i s\u0103 alegem pe cea mai potrivit\u0103 \u00een acel moment.<\/p>\n<p>Un sistem bazat pe utilitate va ajuta exact \u00een acest sens. Este un sistem \u00een care agentul are o multitudine de ac\u021biuni \u0219i alege singur pe care s\u0103 o execute, baz\u00e2ndu-se pe utilitatea relativ\u0103 a fiec\u0103rei ac\u021biuni. Aici, utilitatea este o m\u0103sur\u0103 arbitrar\u0103 a c\u00e2t de important\u0103 sau dorit\u0103 este executarea acestei ac\u021biuni pentru agent. <\/p>\n<p>Calcul\u00e2nd utilitatea ac\u021biunii pe baza st\u0103rii curente \u0219i a mediuului, agentul poate verifica \u0219i alege cel mai potrivit alt stat \u00een orice moment. Acest lucru este similar cu un FSM, cu excep\u021bia faptului c\u0103 tranzi\u021biile sunt determinate de evaluarea pentru fiecare stare poten\u021bial\u0103, inclusiv starea curent\u0103. Re\u021bine\u021bi c\u0103 alegem cea mai util\u0103 ac\u021biune pentru tranzi\u021bie (sau r\u0103m\u00e2nem, dac\u0103 deja am realizat-o). Pentru o diversitate mai mare, aceasta poate fi o alegere ponderat\u0103, dar aleatorie, dintr-o mic\u0103 list\u0103.<\/p>\n<p>Sistemul atribuie un interval aleator de valori de utilitate \u2014 de exemplu, de la 0 (complet nedorit) la 100 (complet dorit). Fiecare ac\u021biune are o serie de parametri care influen\u021beaz\u0103 calcularea acestei valori. Revenind la exemplul nostru cu gardianul:<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/085fb2c197bde93d78455d18e63c9c25.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nTranzi\u021biile \u00eentre ac\u021biuni sunt ambigue \u2014 orice stare poate urma dup\u0103 oricare alta. Priorit\u0103\u021bile ac\u021biunilor sunt \u00een valorile de utilitate returnate. Dac\u0103 inamicul este vizibil, iar acest inamic este puternic, iar s\u0103n\u0103tatea personajului este sc\u0103zut\u0103, atunci at\u00e2t Fleeing, c\u00e2t \u0219i FindingHelp vor returna valori mari, nenule. \u00cen acest caz, FindingHelp va fi \u00eentotdeauna mai mare. \u00cen mod similar, ac\u021biunile non-combat nu returneaz\u0103 niciodat\u0103 mai mult de 50, a\u0219a c\u0103 vor fi \u00eentotdeauna sub cele de combate. Acest lucru trebuie luat \u00een considerare atunci c\u00e2nd se creeaz\u0103 ac\u021biuni \u0219i se calculeaz\u0103 utilitatea lor.<\/p>\n<p>\u00cen exemplul nostru, ac\u021biunile returneaz\u0103 fie o valoare constant\u0103 fix\u0103, fie una din dou\u0103 valori fixe. O sistem mai realist presupune returnarea unei evalu\u0103ri dintr-un interval continuu de valori. De exemplu, ac\u021biunea Fug\u0103 returneaz\u0103 valori de utilitate mai mari dac\u0103 s\u0103n\u0103tatea agentului este sc\u0103zut\u0103, iar ac\u021biunea Atac returneaz\u0103 valori mai mici dac\u0103 inamicul este prea puternic. Din aceast\u0103 cauz\u0103, ac\u021biunea Fug\u0103 are prioritate fa\u021b\u0103 de Atac \u00een orice situa\u021bie \u00een care agentul simte c\u0103 nu are destul\u0103 s\u0103n\u0103tate pentru a \u00eenvinge adversarul. Aceasta permite modificarea priorit\u0103\u021bilor ac\u021biunilor pe baza unui num\u0103r variat de criterii, f\u0103c\u00e2nd astfel abordarea mai flexibil\u0103 \u0219i variabil\u0103 dec\u00e2t un arbore de comportament sau un FSM.<\/p>\n<p>Fiecare ac\u021biune are multe condi\u021bii pentru calcularea programului. Acestea pot fi scrise \u00eentr-un limbaj de scriptare sau sub forma unei serii de formule matematice. \u00cen The Sims, care simuleaz\u0103 rutina zilnic\u0103 a unui personaj, se adaug\u0103 un nivel suplimentar de calcule \u2014 agentul prime\u0219te o serie de \u201emotiva\u021bii\u201d care influen\u021beaz\u0103 evalu\u0103rile de utilitate. Dac\u0103 personajul \u00eei este foame, atunci \u00een timp el va deveni \u0219i mai \u00eenfometat, iar rezultatul de utilitate al ac\u021biunii M\u00e2ncare va cre\u0219te p\u00e2n\u0103 c\u00e2nd personajul o va efectua, sc\u0103z\u00e2nd astfel nivelul foamei \u0219i restabilind valoarea M\u00e2nc\u0103 la zero. <\/p>\n<p>Ideea de a alege ac\u021biuni pe baza unui sistem de evalu\u0103ri este destul de simpl\u0103, prin urmare sistemul bazat pe utilitate poate fi utilizat ca parte a proceselor de luare a deciziilor AI, nu ca o \u00eenlocuire complet\u0103 a acestora. Un arbore de decizii poate solicita o evaluare de utilitate a dou\u0103 noduri fiu \u0219i poate alege pe cel cu o valoare mai mare. \u00cen mod similar, un arbore de comportament poate avea un nod compus de Utilitate pentru a evalua utilitatea ac\u021biunilor, pentru a decide care element fiu s\u0103 fie executat.<\/p>\n<h2>Mi\u0219care \u0219i navigare<\/h2>\n<p>\n\u00cen exemplele anterioare, am avut o platform\u0103 pe care o mutam la st\u00e2nga sau la dreapta \u0219i un gardian care patrula sau ataca. Dar cum anume proces\u0103m mi\u0219carea agentului pe o anumit\u0103 perioad\u0103 de timp? Cum stabilim viteza, cum evit\u0103m obstacolele \u0219i cum planific\u0103m ruta dac\u0103 a ajunge la destina\u021bie este mai complicat dec\u00e2t a merge \u00een linie dreapt\u0103? S\u0103 examin\u0103m acest aspect.<\/p>\n<h3>Gestionare<\/h3>\n<p>\n\u00cen stadiul ini\u021bial, s\u0103 presupunem c\u0103 fiecare agent are o valoare a vitezei, care include c\u00e2t de repede se mi\u0219c\u0103 \u0219i \u00een ce direc\u021bie. Aceasta poate fi m\u0103surat\u0103 \u00een metri pe secund\u0103, kilometri pe or\u0103, pixeli pe secund\u0103 etc. Amintindu-ne de ciclul Sense\/Think\/Act, ne putem imagina c\u0103 partea de Think selecteaz\u0103 viteza, iar partea de Act aplic\u0103 aceast\u0103 vitez\u0103 agentului. De obicei, \u00een jocuri exist\u0103 un sistem fizic care \u00eendepline\u0219te aceast\u0103 sarcin\u0103 pentru tine, evalu\u00e2nd valoarea vitezei fiec\u0103rui obiect \u0219i ajust\u00e2nd-o. Prin urmare, putem l\u0103sa AI-ul cu o singur\u0103 sarcin\u0103 - s\u0103 decid\u0103 ce vitez\u0103 ar trebui s\u0103 aib\u0103 agentul. Dac\u0103 se \u0219tie unde ar trebui s\u0103 fie agentul, atunci trebuie s\u0103-l deplas\u0103m \u00een direc\u021bia corect\u0103 cu viteza stabilit\u0103. O ecua\u021bie foarte simpl\u0103:<\/p>\n<p><i>desired_travel = destination_position \u2013 agent_position<\/i><\/p>\n<p>Imagineaz\u0103-\u021bi o lume 2D. Agentul este \u00een punctul (-2,-2), destina\u021bia undeva \u00een nord-est \u00een punctul (30, 20), iar calea necesar\u0103 pentru agent pentru a ajunge acolo este (32, 22). S\u0103 presupunem c\u0103 aceste pozi\u021bii sunt m\u0103surate \u00een metri - dac\u0103 lu\u0103m viteza agentului ca fiind de 5 metri pe secund\u0103, atunci vom scala vectorul nostru de deplasare \u0219i vom ob\u021bine o vitez\u0103 de aproximativ (4.12, 2.83). Cu aceste parametrii, agentul ar ajunge la destina\u021bie aproape dup\u0103 8 secunde.<\/p>\n<p>Valorile pot fi recalibrate \u00een orice moment. Dac\u0103 agentul a fost la jum\u0103tatea drumului spre obiectiv, deplasarea ar fi fost jum\u0103tate din lungime, dar deoarece viteza maxim\u0103 a agentului este de 5 m\/s (am decis asta mai sus), viteza va fi aceea\u0219i. Acest lucru func\u021bioneaz\u0103 de asemenea pentru \u021binte \u00een mi\u0219care, permi\u021b\u00e2nd agentului s\u0103 efectueze mici ajust\u0103ri pe m\u0103sur\u0103 ce acestea se deplaseaz\u0103.<\/p>\n<p>Dar ne dorim mai mult\u0103 variabilitate - de exemplu, s\u0103 cre\u0219tem \u00eencet viteza pentru a simula un personaj care se mi\u0219c\u0103 dintr-o stare de repaus c\u0103tre alergare. La fel se poate face \u0219i la final \u00eenainte de a se opri. Aceste caracteristici sunt cunoscute sub numele de comportamente de direc\u021bionare, fiecare av\u00e2nd nume specifice: Seek (c\u0103utare), Flee (fug\u0103), Arrival (sosire) etc. Ideea este c\u0103 for\u021bele de accelera\u021bie pot fi aplicate vitezei agentului, pe baza compara\u021biei \u00eentre pozi\u021bia agentului \u0219i viteza curent\u0103 cu punctul de destina\u021bie, pentru a utiliza diferite modalit\u0103\u021bi de a se deplasa c\u0103tre obiectiv.<\/p>\n<p>Fiecare comportament are un scop u\u0219or diferit. Seek \u0219i Arrival sunt modalit\u0103\u021bi de a muta agentul c\u0103tre destina\u021bie. Obstacle Avoidance (evitarea obstacolelor) \u0219i Separation (separarea) corecteaz\u0103 mi\u0219carea agentului pentru a ocoli obstacolele \u00eent\u00e2lnite pe calea c\u0103tre \u021bint\u0103. Alignment (alinirea) \u0219i Cohesion (coeziunea) men\u021bin agen\u021bii \u00eempreun\u0103 \u00een timpul deplas\u0103rii. Orice num\u0103r de comportamente de steering diferite poate fi sumat pentru a ob\u021bine un singur vector de direc\u021bie av\u00e2nd \u00een vedere to\u021bi factorii. Un agent folose\u0219te comportamentele Arrival, Separation \u0219i Obstacle Avoidance pentru a se men\u021bine departe de pere\u021bi \u0219i al\u021bi agen\u021bi. Aceast\u0103 abordare func\u021bioneaz\u0103 bine \u00een loca\u021bii deschise f\u0103r\u0103 detalii suplimentare. <\/p>\n<p>\u00cen condi\u021bii mai dificile, combinarea diferitelor comportamente func\u021bioneaz\u0103 mai prost \u2014 de exemplu, agentul poate r\u0103m\u00e2ne blocat \u00een perete din cauza conflictului dintre Arrival \u0219i Obstacle Avoidance. De aceea, trebuie s\u0103 lu\u0103m \u00een considerare op\u021biuni care sunt mai complexe dec\u00e2t simpla adunare a tuturor valorilor. O astfel de metod\u0103 este: \u00een loc s\u0103 ad\u0103ug\u0103m rezultatele fiec\u0103rui comportament, putem analiza mi\u0219carea \u00een diferite direc\u021bii \u0219i alege cea mai bun\u0103 op\u021biune. <\/p>\n<p>Cu toate acestea, \u00een medii complexe cu impasuri \u0219i alegeri de direc\u021bie, avem nevoie de ceva \u0219i mai avansat.<\/p>\n<h3>G\u0103sirea c\u0103ii<\/h3>\n<p>\nComportamentele de steering sunt excelente pentru mi\u0219carea simpl\u0103 pe teren deschis (teren de fotbal sau aren\u0103), unde a ajunge de la A la B este un drum direct cu mici abateri \u00een jurul obstacolelor. Pentru rute complexe, avem nevoie de pathfinding (g\u0103sirea c\u0103ii), care este o modalitate de a explora lumea \u0219i de a lua decizii cu privire la traseul prin ea.<\/p>\n<p>Cea mai simpl\u0103 metod\u0103 este s\u0103 suprapui o gril\u0103 pe fiecare p\u0103trat adiacent agentului \u0219i s\u0103 evaluezi \u00een care dintre ele este permis\u0103 mi\u0219carea. Dac\u0103 unul dintre ele este destina\u021bia, atunci urmeaz\u0103 din acel p\u0103trat pe traseul de la fiecare p\u0103trat la cel anterior, p\u00e2n\u0103 ajungi la \u00eenceput. Acesta este traseul. \u00cen caz contrar, repet\u0103 procesul cu cele mai apropiate p\u0103trate, p\u00e2n\u0103 c\u00e2nd g\u0103se\u0219ti destina\u021bia sau se termin\u0103 p\u0103tratul (ceea ce \u00eenseamn\u0103 c\u0103 nu exist\u0103 niciun traseu posibil). Acesta este ceea ce se cunoa\u0219te formal ca Search in Wider Area (Breadth-First Search sau BFS). La fiecare pas, acesta se uit\u0103 \u00een toate direc\u021biile (de aceea se nume\u0219te \u201elarg\u201d). Spa\u021biul de c\u0103utare seam\u0103n\u0103 cu un front de und\u0103 care se deplaseaz\u0103, p\u00e2n\u0103 c\u00e2nd ajunge la locul dorit - zona de c\u0103utare se extinde la fiecare pas p\u00e2n\u0103 c\u00e2nd ajunge la punctul final, dup\u0103 care se poate urm\u0103ri traseul \u00eenapoi la \u00eenceput.<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/d367e62bc53033b05388538649853a41.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCa rezultat, vei ob\u021bine o list\u0103 de p\u0103trate, care formeaz\u0103 traseul dorit. Acesta este drumul (de aici, pathfinding) - o list\u0103 de locuri pe care agentul le va vizita, urm\u00e2nd c\u0103tre destina\u021bie.<\/p>\n<p>Av\u00e2nd \u00een vedere c\u0103 \u0219tim pozi\u021bia fiec\u0103rui p\u0103trat din lume, putem folosi comportamentele de direc\u021bionare pentru a ne deplasa pe traseu - de la nodul 1 la nodul 2, apoi de la nodul 2 la nodul 3 \u0219i a\u0219a mai departe. Cea mai simpl\u0103 variant\u0103 este s\u0103 te \u00eendrep\u021bi c\u0103tre centrul p\u0103tratului urm\u0103tor, dar \u0219i mai bine este s\u0103 te opre\u0219ti la mijlocul marginii \u00eentre p\u0103tratul curent \u0219i urm\u0103torul. Astfel, agentul va putea s\u0103 taie col\u021burile la viraje abrupte.<\/p>\n<p>Algoritmul BFS are \u0219i dezavantaje - acesta exploreaz\u0103 la fel de multe p\u0103trate \u00een direc\u021bia \u201egre\u0219it\u0103\u201d ca \u0219i \u00een direc\u021bia \u201ecorect\u0103\u201d. Aici intervine un algoritm mai complex numit A* (A star). Acesta func\u021bioneaz\u0103 similar, dar \u00een loc s\u0103 exploreze f\u0103r\u0103 direc\u021bie p\u0103tratele vecine (apoi vecinii vecinilor, apoi vecinii vecinilor vecinilor \u0219i a\u0219a mai departe), acesta colecteaz\u0103 nodurile \u00eentr-o list\u0103 \u0219i le sorteaz\u0103 astfel \u00eenc\u00e2t urm\u0103torul nod explorat s\u0103 fie \u00eentotdeauna cel care va conduce la cel mai scurt traseu. Nodurile sunt sortate pe baza unei heuristicii care ia \u00een considerare dou\u0103 aspecte - \u201ecostul\u201d traseului ipotetic c\u0103tre p\u0103tratul dorit (inclusiv orice costuri de deplasare) \u0219i o estimare a c\u00e2t de departe este acest p\u0103trat de destina\u021bie (\u00eendrept\u00e2nd c\u0103utarea \u00een direc\u021bia corect\u0103).<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/1cab4f53fa5af6b31d352c7bcf453d7e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAcest exemplu arat\u0103 c\u0103 agentul exploreaz\u0103 c\u00e2te un p\u0103trat pe r\u00e2nd, aleg\u00e2nd de fiecare dat\u0103 vecinul cel mai promi\u021b\u0103tor. Calea ob\u021binut\u0103 este aceea\u0219i ca \u00een cazul BFS, dar \u00een proces au fost examinati mai pu\u021bini p\u0103tra\u021bi \u2014 ceea ce conteaz\u0103 foarte mult pentru performan\u021ba jocului.<\/p>\n<h3>Mi\u0219care f\u0103r\u0103 plas\u0103<\/h3>\n<p>\nDar majoritatea jocurilor nu sunt structurate pe o plas\u0103 \u0219i, adesea, nu este posibil s\u0103 o realiz\u0103m f\u0103r\u0103 a afecta realismul. Sunt necesare compromisuri. Ce dimensiuni ar trebui s\u0103 aib\u0103 p\u0103tratele? Prea mari \u2014 \u0219i nu vor putea reda corect coridoarele sau virajele mici, prea mici \u2014 vor fi prea multe p\u0103trate de c\u0103utat, ceea ce va dura o ve\u0219nicie.<\/p>\n<p>Primul lucru de \u00een\u021beles este c\u0103 plas\u0103 ne ofer\u0103 un graf de noduri interconectate. Algoritmii A* \u0219i BFS func\u021bioneaz\u0103 de fapt pe grafuri \u0219i nu le pas\u0103 deloc de plasa noastr\u0103. Am putea plasa nodurile \u00een orice loc din lumea jocului: at\u00e2ta timp c\u00e2t exist\u0103 o leg\u0103tur\u0103 \u00eentre orice dou\u0103 noduri conectate, precum \u0219i \u00eentre punctul de start \u0219i cel de sosire \u0219i cel pu\u021bin unul dintre noduri \u2014 algoritmul va func\u021biona la fel de bine ca \u00eenainte. Adesea, acest lucru este numit sistem de puncte de navigare (waypoint), deoarece fiecare nod reprezint\u0103 o pozi\u021bie semnificativ\u0103 \u00een lume, care poate face parte din orice num\u0103r de trasee ipotetice.<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/d87e9d4bb2a2fc713d32abc158506eaa.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Exemplul 1: un nod \u00een fiecare p\u0103trat. C\u0103utarea \u00eencepe din nodul \u00een care se afl\u0103 agentul \u0219i se termin\u0103 \u00een nodul p\u0103tratului dorit.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/b535a5db805efdc427d7c5724b866982.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Exemplul 2: un set mai mic de noduri (puncte de navigare). C\u0103utarea \u00eencepe \u00een p\u0103tratul cu agentul, trece printr-un num\u0103r necesar de noduri \u0219i apoi continu\u0103 p\u00e2n\u0103 la destina\u021bie.<\/i><\/p>\n<p>Aceasta este o sistem\u0103 destul de flexibil\u0103 \u0219i puternic\u0103. Dar este necesar\u0103 o oarecare pruden\u021b\u0103 \u00een deciziile privind unde \u0219i cum s\u0103 plas\u0103m waypoint-urile, altfel agen\u021bii s-ar putea s\u0103 nu vad\u0103 pur \u0219i simplu cea mai apropiat\u0103 punct \u0219i s\u0103 nu poat\u0103 \u00eencepe drumul. Ar fi mai u\u0219or dac\u0103 am putea plasa automat punctele de navigare pe baza geometriei lumii.<\/p>\n<p>Aici apare mesh-ul de navigare sau navmesh (plasa de navigare). Aceasta este, de obicei, o plas\u0103 2D de triunghiuri, care se suprapune peste geometria lumii \u2014 peste tot unde agentului \u00eei este permis s\u0103 se mi\u0219te. Fiecare dintre triunghiurile din plas\u0103 devine un nod \u00een graf \u0219i are p\u00e2n\u0103 la trei triunghiuri adiacente, care devin noduri vecine \u00een graf. <\/p>\n<p>Aceast\u0103 imagine este un exemplu din motorul Unity \u2014 acesta a analizat geometria din lume \u0219i a creat navmesh (\u00een captura de ecran, de culoare albastru deschis). Fiecare poligon din navmesh reprezint\u0103 o zon\u0103 pe care agentul poate sta sau se poate muta de la un poligon la altul. \u00cen acest exemplu, poligoanele sunt mai mici dec\u00e2t etajele pe care sunt situate \u2014 acest lucru este realizat pentru a \u021bine cont de dimensiunile agentului, care vor dep\u0103\u0219i pozi\u021bia sa nominal\u0103.<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/845705ba7b9a9d469203aedf7942da41.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPutem c\u0103uta un traseu prin aceast\u0103 re\u021bea, utiliz\u00e2nd din nou algoritmul A*. Acesta ne va oferi o rut\u0103 aproape perfect\u0103 \u00een lume, care ia \u00een considerare toat\u0103 geometria \u0219i \u00een acela\u0219i timp nu necesit\u0103 noduri suplimentare \u0219i crearea punctelor de referin\u021b\u0103.<\/p>\n<p>Pathfinding-ul este o tem\u0103 prea vast\u0103, despre care nu poate fi acoperit\u0103 \u00eentr-o singur\u0103 sec\u021biune a articolului. Dac\u0103 dori\u021bi s\u0103 o explora\u021bi mai detaliat, acest lucru v\u0103 va ajuta <noindex><a rel=\"nofollow\" href=\"https:\/\/www.redblobgames.com\/pathfinding\/a-star\/introduction.html\">site-ul lui Amit Patel<\/a><\/noindex>.<\/p>\n<h2>Planificare<\/h2>\n<p>\nNe-am dat seama cu pathfinding c\u0103 uneori nu este suficient s\u0103 alegem o direc\u021bie \u0219i s\u0103 mergem \u2014 trebuie s\u0103 alegem o rut\u0103 \u0219i s\u0103 facem c\u00e2teva \u00eentors\u0103turi pentru a ajunge la destina\u021bia dorit\u0103. Putem generaliza aceast\u0103 idee: atingerea unui obiectiv nu este doar o simpl\u0103 pas, ci este un \u00eentreg \u0219ir, unde uneori este necesar s\u0103 privim \u00eenainte c\u00e2\u021biva pa\u0219i pentru a \u0219ti cum ar trebui s\u0103 fie primul. Aceasta se nume\u0219te planificare. Pathfinding poate fi considerat ca una dintre numeroasele complet\u0103ri ale planific\u0103rii. Din perspectiva ciclului nostru Sense\/Think\/Act, aceasta este partea unde Thinking-ul planific\u0103 mai multe aspecte ale Act-ului pentru viitor.<\/p>\n<p>S\u0103 lu\u0103m ca exemplu jocul de mas\u0103 Magic: The Gathering. Noi juc\u0103m primii cu urm\u0103torul set de c\u0103r\u021bi \u00een m\u00e2n\u0103:<\/p>\n<ul>\n<li>Swamp \u2014 ofer\u0103 1 man\u0103 neagr\u0103 (carte de p\u0103m\u00e2nt).<\/li>\n<li>Forest \u2014 ofer\u0103 1 man\u0103 verde (carte de p\u0103m\u00e2nt).<\/li>\n<li>Fugitive Wizard \u2014 necesit\u0103 1 man\u0103 albastr\u0103 pentru a fi invocat.<\/li>\n<li>Elvish Mystic \u2014 necesit\u0103 1 man\u0103 verde pentru a fi invocat.<\/li>\n<\/ul>\n<p>\nIgnor\u0103m celelalte trei c\u0103r\u021bi pentru a simplifica. Conform regulilor, unui juc\u0103tor \u00eei este permis s\u0103 joace 1 carte de p\u0103m\u00e2nt pe tur\u0103, el poate \u201etap\u201d aceast\u0103 carte pentru a extrage din ea man\u0103, \u0219i apoi s\u0103 foloseasc\u0103 vr\u0103ji (inclusiv invocarea unei creaturi) \u00een func\u021bie de cantitatea de man\u0103. \u00cen aceast\u0103 situa\u021bie, juc\u0103torul uman \u0219tie c\u0103 trebuie s\u0103 joace Forest, s\u0103 \u201etapeze\u201d 1 man\u0103 verde \u0219i apoi s\u0103 invoce Elvish Mystic. Dar cum poate ghici acest lucru inteligen\u021ba artificial\u0103 de joc?<\/p>\n<h3>Planificare simpl\u0103<\/h3>\n<p>\nAbordarea trivial\u0103 este de a \u00eencerca fiecare ac\u021biune pe r\u00e2nd, p\u00e2n\u0103 c\u00e2nd nu mai r\u0103m\u00e2n op\u021biuni potrivite. Privind c\u0103r\u021bile, IA vede c\u0103 poate juca Swamp. \u0218i \u00eel joac\u0103. Mai sunt alte ac\u021biuni posibil de efectuat \u00een aceast\u0103 rund\u0103? Nu poate chema nici Elvish Mystic, nici Fugitive Wizard, deoarece invocarea lor necesit\u0103, respectiv, man\u0103 verde \u0219i albastr\u0103, iar Swamp ofer\u0103 doar man\u0103 neagr\u0103. \u0218i nu va mai putea juca Forest, deoarece a jucat deja Swamp. Astfel, IA a ac\u021bionat conform regulilor, dar a f\u0103cut-o prost. Exist\u0103 loc de \u00eembun\u0103t\u0103\u021bire.<\/p>\n<p>Planificarea poate g\u0103si o list\u0103 de ac\u021biuni care duc jocul \u00een starea dorit\u0103. La fel cum fiecare p\u0103tr\u0103\u021bel de pe calea de c\u0103utare are vecini, fiecare ac\u021biune din plan are \u0219i ea vecini sau succesorii. Putem c\u0103uta aceste ac\u021biuni \u0219i ac\u021biunile ulterioare, p\u00e2n\u0103 ajungem \u00een starea dorit\u0103.<\/p>\n<p>\u00cen exemplul nostru, rezultatul dorit este \u201ea chema o fiin\u021b\u0103, dac\u0103 este posibil\u201d. La \u00eenceputul rundei, vedem doar dou\u0103 ac\u021biuni posibile, permise de regulile jocului:<\/p>\n<p><i>1. A juca Swamp (rezultatul: Swamp \u00een joc)<br \/>\n2. A juca Forest (rezultatul: Forest \u00een joc)<\/i><\/p>\n<p>Fiecare ac\u021biune acceptat\u0103 poate duce la ac\u021biuni suplimentare \u0219i poate \u00eenchide altele, din nou \u00een func\u021bie de regulile jocului. Imagina\u021bi-v\u0103 c\u0103 am jucat Swamp \u2014 acest lucru va elimina Swamp ca urm\u0103tor pas (l-am jucat deja), de asemenea va elimina \u0219i Forest (deoarece conform regulilor, putem juca o singur\u0103 carte de teren pe tur). Dup\u0103 aceasta, IA adaug\u0103 ca urm\u0103tor pas \u2014 ob\u021binerea a 1 man\u0103 neagr\u0103, pentru c\u0103 nu exist\u0103 alte op\u021biuni. Dac\u0103 merge mai departe \u0219i alege s\u0103 \u201etapeze\u201d Swamp, va ob\u021bine 1 unitate de man\u0103 neagr\u0103 \u0219i nu va putea face nimic cu aceasta.<\/p>\n<p><i>1. A juca Swamp (rezultatul: Swamp \u00een joc)<br \/>\n 1.1 \u201eTapare\u201d Swamp (rezultatul: Swamp \u201etapat\u0103\u201d, +1 unitate de man\u0103 neagr\u0103)<br \/>\n Nu exist\u0103 ac\u021biuni disponibile \u2013 SF\u00c2R\u0218IT<br \/>\n2. A juca Forest (rezultatul: Forest \u00een joc)<\/i><\/p>\n<p>Lista ac\u021biunilor s-a scurtat, am ajuns \u00eentr-un impas. Repet\u0103m procesul pentru urm\u0103toarea ac\u021biune. Juc\u0103m Forest, deschidem ac\u021biunea \u201ea ob\u021bine 1 man\u0103 verde\u201d, care la r\u00e2ndul ei va deschide a treia ac\u021biune \u2014 invocarea Elvish Mystic.<\/p>\n<p><i>1. A juca Swamp (rezultatul: Swamp \u00een joc)<br \/>\n 1.1 \u201eTapare\u201d Swamp (rezultatul: Swamp \u201etapat\u0103\u201d, +1 unitate de man\u0103 neagr\u0103)<br \/>\n Nu exist\u0103 ac\u021biuni disponibile \u2013 SF\u00c2R\u0218IT<br \/>\n2. A juca Forest (rezultatul: Forest \u00een joc)<br \/>\n 2.1 \u201eTapare\u201d Forest (rezultatul: Forest \u201etapat\u0103\u201d, +1 unitate de man\u0103 verde)<br \/>\n 2.1.1 Invocare Elvish Mystic (rezultatul: Elvish Mystic \u00een joc, -1 unitate de man\u0103 verde)<br \/>\n Nu exist\u0103 ac\u021biuni disponibile \u2013 SF\u00c2R\u0218IT<\/i><\/p>\n<p>\u00cen cele din urm\u0103, am studiat toate ac\u021biunile posibile \u0219i am g\u0103sit un plan pentru a invoca o fiin\u021b\u0103.<\/p>\n<p>Acesta este un exemplu foarte simplificat. Este recomandat s\u0103 alege\u021bi cel mai bun plan posibil, nu oricare care se \u00eencadreaz\u0103 \u00een anumite criterii. De obicei, planurile pot fi evaluate pe baza rezultatului final sau a beneficiului total ob\u021binut din implementarea lor. Pute\u021bi ob\u021bine 1 punct pentru a juca o carte de teren \u0219i 3 puncte pentru a chema o creatur\u0103. A juca Swamp ar fi un plan care ofer\u0103 1 punct. Iar a juca Forest \u2192 Tap the Forest \u2192 cheama Elvish Mystic \u2014 ar aduce imediat 4 puncte. <\/p>\n<p>A\u0219a func\u021bioneaz\u0103 planificarea \u00een Magic: The Gathering, dar aceea\u0219i logic\u0103 se aplic\u0103 \u0219i \u00een alte situa\u021bii. De exemplu, mut\u00e2nd un pion pentru a face loc pentru o mi\u0219care a unui nebun \u00een \u0219ah. Sau ascunz\u00e2ndu-te \u00een spatele unui zid pentru a trage \u00een siguran\u021b\u0103 \u00een XCOM. \u00cen general, a\u021bi \u00een\u021beles ideea.<\/p>\n<h3>Planificare \u00eembun\u0103t\u0103\u021bit\u0103<\/h3>\n<p>\nUneori exist\u0103 prea multe ac\u021biuni poten\u021biale pentru a lua \u00een considerare fiecare variant\u0103 posibil\u0103. Revenind la exemplul din Magic: The Gathering: s\u0103 presupunem c\u0103 \u00een joc ave\u021bi mai multe c\u0103r\u021bi de teren \u0219i creaturi \u00een m\u00e2n\u0103 \u2014 num\u0103rul combina\u021biilor posibile de mut\u0103ri poate ajunge la zeci. Exist\u0103 mai multe solu\u021bii pentru aceast\u0103 problem\u0103.<\/p>\n<p>Primul mod este chaining invers (backwards chaining). \u00cen loc s\u0103 verific\u0103m toate combina\u021biile, este mai bine s\u0103 \u00eencepem de la rezultatul final \u0219i s\u0103 \u00eencerc\u0103m s\u0103 g\u0103sim un drum direct. \u00cen loc de a merge de la r\u0103d\u0103cina copacului la o frunz\u0103 specific\u0103, ne \u00eendrept\u0103m \u00een direc\u021bia opus\u0103 \u2014 de la frunz\u0103 la r\u0103d\u0103cin\u0103. Aceast\u0103 metod\u0103 este mai simpl\u0103 \u0219i mai rapid\u0103.<\/p>\n<p>Dac\u0103 adversarul are 1 punct de s\u0103n\u0103tate, pute\u021bi g\u0103si un plan \u201ea provoca 1 sau mai mult\u0103 daune\u201d. Pentru a realiza acest lucru, trebuie s\u0103 \u00eendeplini\u021bi o serie de condi\u021bii: <\/p>\n<p>1. Daunele pot fi provocate de un vr\u0103jitor \u2014 acesta trebuie s\u0103 fie \u00een m\u00e2n\u0103.<br \/>\n2. Pentru a juca vr\u0103jitoria \u2014 este nevoie de man\u0103.<br \/>\n3. Pentru a ob\u021bine man\u0103 \u2014 trebuie s\u0103 juca\u021bi o carte de teren.<br \/>\n4. Pentru a juca o carte de teren \u2014 trebuie s\u0103 o ave\u021bi \u00een m\u00e2n\u0103.<\/p>\n<p>O alt\u0103 metod\u0103 este best-first search (c\u0103utarea celui mai bun \u00eent\u00e2i). \u00cen loc s\u0103 verific\u0103m toate c\u0103ile, alegem cea mai potrivit\u0103. De cele mai multe ori, aceast\u0103 metod\u0103 ofer\u0103 un plan optim f\u0103r\u0103 costuri inutile de c\u0103utare. A* este o form\u0103 de c\u0103utare a celui mai bun \u00eent\u00e2i \u2014 explor\u00e2nd cele mai promi\u021b\u0103toare rute \u00eenc\u0103 de la \u00eenceput, poate g\u0103si deja cel mai bun drum f\u0103r\u0103 a verifica celelalte variante.<\/p>\n<p>O variant interesant \u0219i din ce \u00een ce mai popular al c\u0103ut\u0103rii de tip best-first este Monte Carlo Tree Search. \u00cen loc s\u0103 ghiceasc\u0103 care planuri sunt cele mai bune la alegerea fiec\u0103rei ac\u021biuni ulterioare, algoritmul alege succesorii aleatorii la fiecare pas, p\u00e2n\u0103 ajunge la final (c\u00e2nd planul conduce la victorie sau \u00eenfr\u00e2ngere). Rezultatul final este apoi folosit pentru a cre\u0219te sau a sc\u0103dea evaluarea \u201egreut\u0103\u021bii\u201d op\u021biunilor anterioare. Repet\u00e2nd acest proces de mai multe ori, algoritmul ofer\u0103 o bun\u0103 evaluare a urm\u0103torului pas, chiar dac\u0103 situa\u021bia se schimb\u0103 (dac\u0103 adversarul ia m\u0103suri pentru a \u00eempiedica juc\u0103torul). <\/p>\n<p>\u00cen povestea despre planificarea \u00een jocuri nu poate lipsi Goal-Oriented Action Planning sau GOAP (planificarea ac\u021biunilor orientat\u0103 spre obiective). Acesta este un metod\u0103 folosit\u0103 \u0219i discutat\u0103 pe larg, dar, \u00een afar\u0103 de c\u00e2teva detalii distinctive, este, \u00een esen\u021b\u0103, o metod\u0103 de backwards chaining, despre care am vorbit anterior. Dac\u0103 sarcina este \u201ea distruge juc\u0103torul\u201d, iar juc\u0103torul se afl\u0103 \u00een spatele unei acoperiri, planul ar putea fi: distruge cu o grenad\u0103 \u2192 ia-o \u2192 arunc-o.<\/p>\n<p>De obicei, exist\u0103 mai multe obiective, fiecare cu prioritatea sa. Dac\u0103 obiectivul cu cea mai mare prioritate nu poate fi \u00eendeplinit (nici o combina\u021bie de ac\u021biuni nu creeaz\u0103 planul \u201ea distruge juc\u0103torul\u201d, deoarece juc\u0103torul nu este vizibil), AI-ul se va \u00eentoarce la obiectivele cu o prioritate mai mic\u0103.<\/p>\n<h2>\u00cenv\u0103\u021bare \u0219i adaptare<\/h2>\n<p>\nAm mai spus c\u0103 AI-ul din jocuri nu folose\u0219te de obicei \u00eenv\u0103\u021barea automat\u0103, deoarece nu se potrive\u0219te pentru controlul agen\u021bilor \u00een timp real. Dar aceasta nu \u00eenseamn\u0103 c\u0103 nu se poate lua ceva din acest domeniu. Vrem un adversar \u00een shooter care poate \u00eenv\u0103\u021ba ceva. De exemplu, s\u0103 \u00eenve\u021be cele mai bune pozi\u021bii de pe hart\u0103. Sau un adversar \u00een fighting care ar bloca combo-urile frecvent utilizate de juc\u0103tor, motiv\u00e2ndu-l s\u0103 utilizeze altele. Astfel, \u00eenv\u0103\u021barea automat\u0103 \u00een aceste situa\u021bii poate fi foarte util\u0103.<\/p>\n<h3>Statistici \u0219i probabilit\u0103\u021bi<\/h3>\n<p>\n\u00cenainte de a trece la exemple mai complexe, s\u0103 ne d\u0103m seama c\u00e2t de departe putem ajunge, lu\u00e2nd c\u00e2teva m\u0103sur\u0103tori simple \u0219i folosindu-le pentru a lua decizii. De exemplu, strategia \u00een timp real \u2013 cum putem determina dac\u0103 un juc\u0103tor poate \u00eencepe un atac \u00een primele minute ale jocului \u0219i ce ap\u0103rare s\u0103 preg\u0103tim \u00eempotriva acestuia? Putem analiza experien\u021ba anterioar\u0103 a juc\u0103torului pentru a \u00een\u021belege care ar putea fi reac\u021bia sa viitoare. \u00cencepem cu faptul c\u0103 nu avem astfel de date ini\u021biale, dar le putem aduna \u2014 de fiecare dat\u0103 c\u00e2nd AI joac\u0103 \u00eempotriva unei persoane, poate \u00eenregistra timpul primului atac. Dup\u0103 c\u00e2teva sesiuni, vom ob\u021bine o medie a timpului \u00een care juc\u0103torul va ataca \u00een viitor.<\/p>\n<p>Exist\u0103 o problem\u0103 cu valorile medii: dac\u0103 juc\u0103torul a \u201eatacat\u201d de 20 de ori \u0219i a jucat \u00eencet de 20 de ori, valorile de care avem nevoie vor fi undeva la mijloc \u0219i nu ne vor oferi nimic util. O solu\u021bie ar fi s\u0103 limit\u0103m datele de intrare \u2013 putem lua \u00een considerare ultimele 20 de puncte.<\/p>\n<p>O abordare similar\u0103 este folosit\u0103 pentru a evalua probabilitatea unor ac\u021biuni specifice, presupun\u00e2nd c\u0103 preferin\u021bele anterioare ale juc\u0103torului vor fi acelea\u0219i \u00een viitor. Dac\u0103 juc\u0103torul ne atac\u0103 de cinci ori cu foc, de dou\u0103 ori cu fulgerul \u0219i o dat\u0103 corp cu corp, este evident c\u0103 prefer\u0103 atacurile cu foc. Extrapol\u0103m \u0219i vedem probabilitatea utiliz\u0103rii diferitelor tipuri de arme: foc=62,5%, fulger=25% \u0219i corp cu corp=12,5%. AI-ul nostru de joc trebuie s\u0103 se preg\u0103teasc\u0103 pentru ap\u0103rarea \u00eempotriva focului.<\/p>\n<p>O alt\u0103 metod\u0103 interesant\u0103 este utilizarea Naive Bayes Classifier (clasificator bayesian naiv) pentru a analiza cantit\u0103\u021bi mari de date de intrare \u0219i a clasifica situa\u021bia, astfel \u00eenc\u00e2t AI-ul s\u0103 reac\u021bioneze corespunz\u0103tor. Clasificatoarele bayesiene sunt celebre pentru utilizarea lor \u00een filtrele de spam pentru e-mail. Acolo analizeaz\u0103 cuvintele, le compar\u0103 cu locurile unde aceste cuvinte au ap\u0103rut anterior (\u00een spam sau nu) \u0219i trag concluzii despre mesajele primite. Putem face acela\u0219i lucru chiar \u0219i cu mai pu\u021bine date de intrare. Pe baza tuturor informa\u021biilor utile pe care le vede AI-ul (de exemplu, ce unit\u0103\u021bi inamice au fost create, sau ce vr\u0103ji folosesc, sau ce tehnologii au cercetat) \u0219i a rezultatului final (r\u0103zboi sau pace, \u201eatac\u201d sau ap\u0103rare etc.) \u2014 vom alege comportamentul potrivit pentru AI.<\/p>\n<p>Toate aceste metode de \u00eenv\u0103\u021bare sunt suficiente, dar ideal ar fi s\u0103 le utiliz\u0103m pe baza datelor din testare. Iar IA va \u00eenv\u0103\u021ba s\u0103 se adapteze la diferitele strategii folosite de testerii dvs. IA care se adapteaz\u0103 la juc\u0103tor dup\u0103 lansare poate deveni prea previzibil sau, dimpotriv\u0103, prea greu de \u00eenvins.<\/p>\n<h3>Adaptarea pe baza valorilor<\/h3>\n<p>\nAv\u00e2nd \u00een vedere con\u021binutul lumii noastre de joc \u0219i regulile, putem schimba setul de valori care influen\u021beaz\u0103 luarea deciziilor, \u0219i nu doar s\u0103 folosim datele de intrare. Proced\u0103m astfel:<\/p>\n<ul>\n<li>S\u0103 l\u0103s\u0103m IA s\u0103 adune date despre starea lumii \u0219i evenimentele cheie din timpul jocului (a\u0219a cum s-a men\u021bionat mai sus).<\/li>\n<li>Vom schimba c\u00e2teva valori importante (value) pe baza acestor date.<\/li>\n<li>Vom implementa deciziile noastre bazate pe procesarea sau evaluarea acestor valori.<\/li>\n<\/ul>\n<p>\nDe exemplu, agentul are mai multe camere de ales pe harta unui shooter din perspectiva \u00eent\u00e2i. Fiecare camer\u0103 are valoarea sa, care determin\u0103 c\u00e2t de dorit\u0103 este pentru a fi vizitat\u0103. IA alege aleatoriu \u00een ce camer\u0103 s\u0103 mearg\u0103, baz\u00e2ndu-se pe valoarea respectiv\u0103. Apoi, agentul \u00ee\u0219i aminte\u0219te \u00een ce camer\u0103 a fost ucis \u0219i scade valoarea acesteia (probabilitatea c\u0103 se va \u00eentoarce acolo). Similar \u00een situa\u021bia invers\u0103 \u2014 dac\u0103 agentul distruge mul\u021bi inamici, atunci valoarea camerei cre\u0219te.<\/p>\n<h3>Modelul Markov<\/h3>\n<p>\nCe s-ar \u00eent\u00e2mpla dac\u0103 am folosi datele adunate pentru prognoz\u0103? Dac\u0103 ne amintim fiecare camer\u0103 \u00een care vedem juc\u0103torul pe o perioad\u0103 determinat\u0103, vom putea prezice \u00een ce camer\u0103 ar putea merge juc\u0103torul. Urm\u0103rind \u0219i \u00eenregistr\u00e2nd mi\u0219c\u0103rile juc\u0103torului prin camere (values), putem face prognoze.<\/p>\n<p>S\u0103 lu\u0103m trei camere: ro\u0219ie, verde \u0219i albastr\u0103. \u015ei de asemenea observa\u021biile pe care le-am \u00eenregistrat \u00een timpul vizion\u0103rii unei sesiuni de joc:<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/6e90a365b72a176c36c9a14213baaafc.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nNum\u0103rul observa\u021biilor pentru fiecare camer\u0103 este aproape egal \u2014 unde s\u0103 facem un loc bun pentru o ambuscad\u0103 nu \u0219tim \u00eenc\u0103. Colectarea statisticilor este, de asemenea, complicat\u0103 de respawnul juc\u0103torilor, care apar uniform pe \u00eentreaga hart\u0103. Dar datele despre urm\u0103toarea camer\u0103 \u00een care intr\u0103 dup\u0103 apari\u021bia pe hart\u0103 sunt deja utile.<\/p>\n<p>Este clar c\u0103 camera verde \u00eei satisface pe juc\u0103tori \u2014 majoritatea oamenilor din camera ro\u0219ie trec \u00een ea, dintre care 50% r\u0103m\u00e2n acolo \u00een continuare. Camera albastr\u0103, dimpotriv\u0103, nu este popular\u0103, \u00een ea aproape c\u0103 nu se intr\u0103, iar dac\u0103 se intr\u0103, nu se r\u0103m\u00e2ne mult timp. <\/p>\n<p>Dar datele ne spun ceva mai important \u2014 atunci c\u00e2nd juc\u0103torul se afl\u0103 \u00een camera albastr\u0103, urm\u0103toarea camer\u0103 \u00een care \u00eel vom vedea cel mai probabil va fi camera ro\u0219ie, \u0219i nu cea verde. De\u0219i camera verde este mai popular\u0103 dec\u00e2t cea ro\u0219ie, situa\u021bia se schimb\u0103 atunci c\u00e2nd juc\u0103torul se afl\u0103 \u00een camera albastr\u0103. Starea urm\u0103toare (adic\u0103 camera \u00een care juc\u0103torul va trece) depinde de starea anterioar\u0103 (adic\u0103 camera \u00een care se afl\u0103 juc\u0103torul \u00een prezent). Datorit\u0103 cercet\u0103rii dependen\u021belor, vom face prognoze mai precise dec\u00e2t dac\u0103 am num\u0103ra pur \u0219i simplu observa\u021biile independent unele de altele.<\/p>\n<p>Previzionarea st\u0103rii viitoare pe baza datelor din starea anterioar\u0103 se nume\u0219te model Markov (Markov model), iar exemplele de acest tip (cu camere) se numesc lan\u021buri Markov. Deoarece modelele reprezint\u0103 probabilitatea schimb\u0103rilor \u00eentre st\u0103rile consecutive, ele sunt reprezentate vizual sub forma unui FSM cu probabilit\u0103\u021bi \u00een jurul fiec\u0103rui tranzi\u021bie. Anterior, am folosit FSM pentru a reprezenta starea comportamental\u0103 \u00een care se afla agentul, dar aceast\u0103 conceptie se extinde la orice stare, indiferent dac\u0103 este sau nu legat\u0103 de agent. \u00cen acest caz, st\u0103rile reprezint\u0103 camera ocupat\u0103 de agent:<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/edb32dff7a3298b19c3fa4d66f48e9f4.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAceasta este o variant\u0103 simpl\u0103 de reprezentare a probabilit\u0103\u021bii relative a schimb\u0103rilor de st\u0103ri, oferind inteligen\u021bei artificiale o anumit\u0103 capacitate de a prezice urm\u0103toarea stare. Se pot anticipa mai multe pa\u0219i \u00eenainte.<\/p>\n<p>Dac\u0103 juc\u0103torul se afl\u0103 \u00een camera verde, exist\u0103 o \u0219ans\u0103 de 50% c\u0103 va r\u0103m\u00e2ne acolo la urm\u0103toarea observa\u021bie. Dar care este probabilitatea ca el s\u0103 fie \u00eenc\u0103 acolo \u0219i dup\u0103 aceea? Exist\u0103 nu doar \u0219ansa ca juc\u0103torul s\u0103 fi r\u0103mas \u00een camera verde dup\u0103 dou\u0103 observa\u021bii, ci \u0219i \u0219ansa c\u0103 a plecat \u0219i s-a \u00eentors. Iat\u0103 un nou tabel care ia \u00een considerare noile date:<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/f87afff68b066a879661e37f68654ae2.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nDin el reiese c\u0103 \u0219ansa de a-l vedea pe juc\u0103tor \u00een camera verde dup\u0103 dou\u0103 observa\u021bii va fi de 51% \u2014 21%, c\u0103 va veni din camera ro\u0219ie, 5% dintre ace\u0219tia, c\u0103 juc\u0103torul va vizita camera albastr\u0103 \u00eentre ele, \u0219i 25%, c\u0103 juc\u0103torul nu va pleca deloc din camera verde.<\/p>\n<p>Tabelul este doar un instrument vizual \u2014 procedura necesit\u0103 doar multiplicarea probabilit\u0103\u021bilor la fiecare pas. Aceasta \u00eenseamn\u0103 c\u0103 po\u021bi privi departe \u00een viitor cu o singur\u0103 ajustare: presupunem c\u0103 \u0219ansa de a intra \u00eentr-o camer\u0103 depinde \u00een totalitate de camera curent\u0103. Acest lucru se nume\u0219te proprietatea Markov (Markov Property) \u2014 starea viitoare depinde doar de prezent. Dar nu este 100% exact. Juc\u0103torii pot schimba deciziile \u00een func\u021bie de al\u021bi factori: nivelul de s\u0103n\u0103tate sau num\u0103rul de muni\u021bie. Deoarece nu \u00eenregistr\u0103m aceste valori, prognozele noastre vor fi mai pu\u021bin precise.<\/p>\n<h3>N-Grams<\/h3>\n<p>\nDar ce zici de exemplul cu lupta \u0219i prezicerea combina\u021biilor de mi\u0219c\u0103ri ale juc\u0103torului? La fel! Dar \u00een loc de o singur\u0103 stare sau eveniment, vom explora \u00eentregi secven\u021be din care const\u0103 un combo.<\/p>\n<p>Una dintre modalit\u0103\u021bile de a face acest lucru este de a p\u0103stra fiecare intrare (de exemplu, Kick, Punch sau Block) \u00eentr-un buffer \u0219i de a \u00eenregistra \u00eentregul buffer ca un eveniment. A\u0219adar, juc\u0103torul apas\u0103 repetat Kick, Kick, Punch pentru a folosi atacul SuperDeathFist, sistemul AI stocheaz\u0103 toate intr\u0103rile \u00een buffer \u0219i re\u021bine ultimele trei utilizate la fiecare pas.<\/p>\n<p><img decoding=\"async\" alt=\"Cum s\u0103 creezi un AI de jocuri: ghid pentru \u00eencep\u0103tori\" src=\"\/wp-content\/uploads\/2019\/11\/9a95226ae155dca5e45a66d4440f3cd4.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n(Textul cu litere \u00eengro\u0219ate arat\u0103 momentele c\u00e2nd juc\u0103torul lanseaz\u0103 atacul SuperDeathFist.)<\/p>\n<p>AI-ul va vedea toate op\u021biunile c\u00e2nd juc\u0103torul a ales Kick, urmat de alt Kick, \u0219i apoi va observa c\u0103 urm\u0103toarea intrare este \u00eentotdeauna Punch. Acest lucru va permite agentului s\u0103 prevad\u0103 combo-ul SuperDeathFist \u0219i s\u0103-l blocheze, dac\u0103 este posibil.<\/p>\n<p>Aceste secven\u021be de evenimente se numesc N-gram-uri (N-grams), unde N este num\u0103rul de elemente stocate. \u00cen exemplul anterior, a fost un 3-gram (trigram), ceea ce \u00eenseamn\u0103: primele dou\u0103 \u00eenregistr\u0103ri sunt utilizate pentru a prezice a treia. Prin urmare, \u00eentr-un 5-gram, primele patru \u00eenregistr\u0103ri prezic a cincea \u0219i a\u0219a mai departe.<\/p>\n<p>Dezvoltatorul trebuie s\u0103 aleag\u0103 cu aten\u021bie dimensiunea N-gram-urilor. Un num\u0103r mai mic de N necesit\u0103 mai pu\u021bin\u0103 memorie, dar stocheaz\u0103 \u0219i o istorie mai mic\u0103. De exemplu, un 2-gram (bigram) va \u00eenregistra Kick, Kick sau Kick, Punch, dar nu va putea stoca Kick, Kick, Punch, a\u0219a c\u0103 AI-ul nu va reac\u021biona la combo-ul SuperDeathFist.<\/p>\n<p>Pe de alt\u0103 parte, numerele mari necesit\u0103 mai mult\u0103 memorie \u0219i AI-ul va avea mai multe dificult\u0103\u021bi \u00een a \u00eenv\u0103\u021ba, deoarece vor ap\u0103rea mult mai multe op\u021biuni posibile. Dac\u0103 ai avut trei intr\u0103ri posibile Kick, Punch sau Block, iar noi am folosit un 10-gram, atunci ar ie\u0219i aproximativ 60 de mii de variante diferite.<\/p>\n<p>Modelul bigramului este un lan\u021b Markov simplu \u2014 fiecare pereche \u201estare anterioar\u0103\/stare curent\u0103\u201d este un bigram, iar tu po\u021bi prezice a doua stare pe baza primei. Trigramul \u0219i n-gramurile mai mari pot fi, de asemenea, considerate lan\u021buri Markov, unde toate elementele (cu excep\u021bia ultimului din n-gram) formeaz\u0103 \u00eempreun\u0103 prima stare, iar ultimul element \u2014 a doua. Un exemplu din lupta arat\u0103 \u0219ansa de tranzi\u021bie de la starea Kick \u0219i Kick la starea Kick \u0219i Punch. Consider\u00e2nd mai multe \u00eenregistr\u0103ri ale istoricului de intrare ca o unitate, practic transform\u0103m secven\u021ba de intrare \u00eentr-o parte a unei st\u0103ri \u00eentregi. Aceasta ne ofer\u0103 proprietatea Markov, permi\u021b\u00e2nd utilizarea lan\u021burilor Markov pentru a prezice urm\u0103toarea intrare \u0219i a ghici ce mi\u0219care de combina\u021bie va fi urm\u0103toarea.<\/p>\n<h2>Concluzie<\/h2>\n<p>\nAm discutat despre cele mai comune instrumente \u0219i abord\u0103ri \u00een dezvoltarea inteligen\u021bei artificiale. De asemenea, am analizat situa\u021biile \u00een care acestea trebuie aplicate \u0219i unde sunt deosebit de utile. <\/p>\n<p>Asta ar trebui s\u0103 fie suficient pentru a \u00een\u021belege lucrurile de baz\u0103 \u00een IA de joc. Dar, desigur, aceasta nu sunt toate metodele. Printre cele mai pu\u021bin populare, dar la fel de eficiente se num\u0103r\u0103:<\/p>\n<ul>\n<li>algoritmi de optimizare, inclusiv urcarea pe dealuri, cobor\u00e2rea prin gradient \u0219i algoritmi genetici<\/li>\n<li>algoritmi competi\u021bionali de c\u0103utare\/planificare (minimax \u0219i t\u0103ierea alpha-beta)<\/li>\n<li>metode de clasificare (perceptroni, re\u021bele neuronale \u0219i ma\u0219ini cu vectori de suport)<\/li>\n<li>sisteme pentru procesarea percep\u021biei \u0219i memoriei agen\u021bilor<\/li>\n<li>abord\u0103ri arhitecturale pentru IA (sisteme hibride, submul\u021bimi de arhitecturi \u0219i alte metode de suprapunere a sistemelor IA)<\/li>\n<li>instrumente de anima\u021bie (planificarea \u0219i coordonarea mi\u0219c\u0103rilor)<\/li>\n<li>factori de performan\u021b\u0103 (nivelul de detaliu, algoritmii anytime \u0219i timeslicing)<\/li>\n<\/ul>\n<p>\nResursele online despre acest subiect:<\/p>\n<p>1. Pe GameDev.net exist\u0103 <noindex><a rel=\"nofollow\" href=\"https:\/\/www.gamedev.net\/articles\/programming\/artificial-intelligence\/\">o sec\u021biune cu articole \u0219i tutoriale despre IA<\/a><\/noindex>, dar \u0219i pentru <noindex><a rel=\"nofollow\" href=\"https:\/\/www.gamedev.net\/forums\/forum\/6-artificial-intelligence\/\">forum<\/a><\/noindex>.<br \/>\n2. <noindex><a rel=\"nofollow\" href=\"http:\/\/aigamedev.com\/\">AiGameDev.com<\/a><\/noindex> con\u021bine numeroase prezent\u0103ri \u0219i articole pe o gam\u0103 larg\u0103 de subiecte legate de dezvoltarea IA \u00een jocuri.<br \/>\n3. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.gdcvault.com\/\">The GDC Vault<\/a><\/noindex> include topicuri de la summitul GDC AI, multe dintre acestea fiind disponibile gratuit.<br \/>\n4. Materiale utile pot fi g\u0103site de asemenea pe site-ul <noindex><a rel=\"nofollow\" href=\"http:\/\/gameai.com\/\">AI Game Programmers Guild<\/a><\/noindex>.<br \/>\n5. Tommy Thompson, cercet\u0103tor \u00een IA \u0219i dezvoltator de jocuri, face videoclipuri pe canalul s\u0103u de YouTube <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/user\/tthompso\">AI and Games<\/a><\/noindex> cu explica\u021bii \u0219i studii despre IA \u00een jocuri comerciale.<\/p>\n<p>C\u0103r\u021bi despre acest subiect:<\/p>\n<p>1. Seria de c\u0103r\u021bi Game AI Pro este o colec\u021bie de articole scurte care explic\u0103 cum s\u0103 implementa\u021bi func\u021bii specifice sau cum s\u0103 rezolva\u021bi probleme concrete.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"http:\/\/go.gamedev.net\/?id=13722X707581&amp;xs=1&amp;isjs=1&amp;url=https%3A%2F%2Famzn.to%2F2KGoB8n&amp;xguid=f8ad586e5984991508efff4754027dbd&amp;xuuid=305451ecead59d76ca830fded0aab276&amp;xsessid=6ccb8b9fa3f10b478b65f7ed703a447b&amp;xcreo=0&amp;xed=0&amp;sref=https%3A%2F%2Fwww.gamedev.net%2Farticles%2Fprogramming%2Fartificial-intelligence%2Fthe-total-beginners-guide-to-game-ai-r4942%2F%3Fdo%3Dedit%26d%3D1%26id%3D4942%26csrfKey%3D7015c6d2c5c643e87baa74f8e5d2c094&amp;pref=https%3A%2F%2Fwww.gamedev.net%2Farticles%2Fprogramming%2Fartificial-intelligence%2Fthe-total-beginners-guide-to-game-ai-r4942%2F&amp;xtz=420&amp;jv=13.7.1&amp;bv=2.5.1\">Game AI Pro: Inteligen\u021ba Colectat\u0103 a Profesioni\u0219tilor \u00een AI pentru Jocuri<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"http:\/\/go.gamedev.net\/?id=13722X707581&amp;xs=1&amp;isjs=1&amp;url=https%3A%2F%2Famzn.to%2F2KFKyoe&amp;xguid=f8ad586e5984991508efff4754027dbd&amp;xuuid=305451ecead59d76ca830fded0aab276&amp;xsessid=6ccb8b9fa3f10b478b65f7ed703a447b&amp;xcreo=0&amp;xed=0&amp;sref=https%3A%2F%2Fwww.gamedev.net%2Farticles%2Fprogramming%2Fartificial-intelligence%2Fthe-total-beginners-guide-to-game-ai-r4942%2F%3Fdo%3Dedit%26d%3D1%26id%3D4942%26csrfKey%3D7015c6d2c5c643e87baa74f8e5d2c094&amp;pref=https%3A%2F%2Fwww.gamedev.net%2Farticles%2Fprogramming%2Fartificial-intelligence%2Fthe-total-beginners-guide-to-game-ai-r4942%2F&amp;xtz=420&amp;jv=13.7.1&amp;bv=2.5.1\">Game AI Pro 2: Inteligen\u021ba Colectat\u0103 a Profesioni\u0219tilor \u00een AI pentru Jocuri<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/amzn.to\/2KF4irS\">Game AI Pro 3: Inteligen\u021ba Colectat\u0103 a Profesioni\u0219tilor \u00een AI pentru Jocuri<\/a><\/noindex><\/p>\n<p>2. Seria AI Game Programming Wisdom este predecesoarea seriei Game AI Pro. Aceasta con\u021bine metode mai vechi, dar aproape toate sunt relevante \u0219i ast\u0103zi.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/amzn.to\/2ARFhKx\">AI Game Programming Wisdom 1<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/amzn.to\/2Mkv4eh\">AI Game Programming Wisdom 2<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/amzn.to\/2nnuYEh\">AI Game Programming Wisdom 3<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/amzn.to\/2ARFEEV\">AI Game Programming Wisdom 4<\/a><\/noindex><\/p>\n<p>3. <noindex><a rel=\"nofollow\" href=\"https:\/\/amzn.to\/2AWKuRh\">Inteligen\u021ba Artificial\u0103: O Abordare Modern\u0103<\/a><\/noindex> \u2014 este unul dintre textele de baz\u0103 pentru to\u021bi cei care doresc s\u0103 \u00een\u021beleag\u0103 domeniul general al inteligen\u021bei artificiale. Aceasta nu este o carte despre dezvoltarea de jocuri \u2014 ci \u00eenva\u021b\u0103 conceptele de baz\u0103 ale IA.<br \/>\n<br \/>Sursa: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/pixonic\/blog\/428892\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041d\u0430\u0442\u043a\u043d\u0443\u043b\u0441\u044f \u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u043e\u0431 \u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442\u0435 \u0432 \u0438\u0433\u0440\u0430\u0445. \u0421 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435\u043c \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u0432\u0435\u0449\u0435\u0439 \u043f\u0440\u043e \u0418\u0418 \u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445, \u0430 \u0435\u0449\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u043c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043b\u044f \u0435\u0433\u043e \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041a\u0430\u043a, \u0433\u0434\u0435 \u0438 \u043a\u043e\u0433\u0434\u0430 \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u2014 \u0442\u043e\u0436\u0435 \u0435\u0441\u0442\u044c. \u0411\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u0432 \u043f\u0441\u0435\u0432\u0434\u043e\u043a\u043e\u0434\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0433\u043b\u0443\u0431\u043e\u043a\u0438\u0435 \u0437\u043d\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f. \u041f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c 35 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[702],"tags":[],"class_list":["post-52118","post","type-post","status-publish","format-standard","hentry","category-news"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041d\u0430\u0442\u043a\u043d\u0443\u043b\u0441\u044f \u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u043e\u0431.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/ro\/blog\/news\/kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"ro_RO\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0418\u0418: \u0433\u0430\u0439\u0434 \u0434\u043b\u044f \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0445 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041d\u0430\u0442\u043a\u043d\u0443\u043b\u0441\u044f \u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u043e\u0431.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/ro\/blog\/news\/kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T10:59:47+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Cum s\u0103 creezi un AI pentru jocuri: ghid pentru \u00eencep\u0103tori | ProHoster","description":"Am dat peste un material interesant despre.","canonical_url":"https:\/\/prohoster.info\/ro\/blog\/news\/kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"ro_RO","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0418\u0418: \u0433\u0430\u0439\u0434 \u0434\u043b\u044f \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0445 | ProHoster","og:description":"\u041d\u0430\u0442\u043a\u043d\u0443\u043b\u0441\u044f \u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u043e\u0431.","og:url":"https:\/\/prohoster.info\/ro\/blog\/news\/kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T21:00:00+00:00","article:modified_time":"2020-02-18T10:59:47+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"52118","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-24 02:32:21","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 20:49:49","updated":"2026-01-24 02:32:21","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/52118","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/comments?post=52118"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/52118\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media?parent=52118"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/categories?post=52118"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/tags?post=52118"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}