{"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\/it\/blog\/news\/kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih","title":{"rendered":"Come creare un'IA di gioco: guida per principianti","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/9e57175b233a104e0df98383b374eded.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nHo trovato un materiale interessante sull'intelligenza artificiale nei giochi. Con una spiegazione delle nozioni di base sull'IA tramite esempi semplici, e contiene anche molti strumenti e metodi utili per lo sviluppo e la progettazione comoda. Come, dove e quando usarli \u2014 ci sono anche queste informazioni.<\/p>\n<p>La maggior parte degli esempi \u00e8 scritta in pseudocodice, quindi non sono richieste conoscenze approfondite di programmazione. Di seguito ci sono 35 pagine di testo con immagini e GIF, quindi preparatevi.<\/p>\n<p>UPD. Mi scuso, ma ho gi\u00e0 fatto una traduzione di questo articolo su Habr. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/users\/PatientZero\/\">PatientZero<\/a><\/noindex>. Puoi leggere la sua versione <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/post\/420219\/\">qui<\/a><\/noindex>, ma per qualche motivo l'articolo mi era sfuggito (ho usato la ricerca, ma qualcosa \u00e8 andato storto). E poich\u00e9 scrivo in un blog dedicato allo sviluppo di giochi, ho deciso di lasciare la mia traduzione per gli iscritti (alcuni aspetti li ho presentati in modo diverso, altri \u2014 intenzionalmente omessi su consiglio degli sviluppatori).<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Cos'\u00e8 l'IA?<\/h2>\n<p>\nL'IA nei giochi si concentra su quali azioni un oggetto deve eseguire in base alle condizioni in cui si trova. Questo viene solitamente definito gestione di \"agenti intelligenti\", dove l'agente \u00e8 un personaggio di gioco, un veicolo, un bot, e talvolta \u00e8 qualcosa di pi\u00f9 astratto: un intero gruppo di entit\u00e0 o persino una civilt\u00e0. In ogni caso, \u00e8 un'entit\u00e0 che deve percepire il suo ambiente, prendere decisioni sulla base di esso e agire di conseguenza. Questo si chiama ciclo Sense\/Think\/Act (Percepire\/Pensare\/Agire):<\/p>\n<ul>\n<li>Percepire: l'agente trova o riceve informazioni su cose nel suo ambiente che possono influenzare il suo comportamento (minacce vicine, oggetti da raccogliere, luoghi interessanti da esplorare).<\/li>\n<li>Pensare: l'agente decide come reagire (considera se \u00e8 abbastanza sicuro raccogliere oggetti o se prima deve combattere\/nascondersi).<\/li>\n<li>Agire: l'agente compie azioni per attuare la decisione precedente (inizia a muoversi verso il nemico o l'oggetto).<\/li>\n<li>\u2026ora la situazione \u00e8 cambiata a causa delle azioni dei personaggi, quindi il ciclo si ripete con nuovi dati.<\/li>\n<\/ul>\n<p>\nL'IA, di solito, si concentra sulla parte Sense del ciclo. Ad esempio, le auto a guida autonoma scattano foto della strada, le uniscono ai dati del radar e del lidar, e le interpretano. Solitamente, questo viene fatto dall'apprendimento automatico, che elabora i dati in ingresso e d\u00e0 loro significato, estraendo informazioni semantiche come \"c'\u00e8 un'altra auto a 20 yards davanti a te\". Questi sono i cosiddetti problemi di classificazione.<\/p>\n<p>I giochi non hanno bisogno di un sistema complesso per estrarre informazioni, poich\u00e9 gran parte dei dati \u00e8 gi\u00e0 parte integrante di essi. Non \u00e8 necessario eseguire algoritmi di riconoscimento delle immagini per determinare se c'\u00e8 un nemico davanti \u2014 il gioco gi\u00e0 lo sa e comunica queste informazioni direttamente nel processo decisionale. Pertanto, la parte del ciclo Sense \u00e8 spesso molto pi\u00f9 semplice rispetto a Think e Act.<\/p>\n<h2>Limitazioni dell'IA nei giochi<\/h2>\n<p>\nL'IA ha una serie di limitazioni da rispettare:<\/p>\n<ul>\n<li>L'IA non deve essere addestrata in anticipo, come se fosse un algoritmo di apprendimento automatico. \u00c8 inutile scrivere una rete neurale durante lo sviluppo, per osservare decine di migliaia di giocatori e studiare il miglior modo di giocare contro di loro. Perch\u00e9? Perch\u00e9 il gioco non \u00e8 stato rilasciato e non ci sono giocatori.<\/li>\n<li>Il gioco deve intrattenere e mettere alla prova, quindi gli agenti non devono trovare il miglior approccio contro le persone.<\/li>\n<li>Gli agenti devono apparire realistici, affinch\u00e9 i giocatori si sentano come se stessero giocando contro persone reali. Il programma AlphaGo ha superato l'uomo, ma le mosse scelte erano molto lontane dalla comprensione tradizionale del gioco. Se il gioco imita un avversario umano, non deve esserci tale sensazione. L'algoritmo deve essere modificato affinch\u00e9 prenda decisioni plausibili e non perfette.<\/li>\n<li>L'IA deve funzionare in tempo reale. Questo significa che l'algoritmo non pu\u00f2 monopolizzare l'uso della CPU per un lungo periodo per prendere decisioni. Anche 10 millisecondi per questo sono troppo lunghi, poich\u00e9 la maggior parte dei giochi richiede da 16 a 33 millisecondi per completare l'elaborazione e passare al fotogramma successivo.<\/li>\n<li>\u00c8 ideale se almeno una parte del sistema \u00e8 gestita dai dati, affinch\u00e9 i \"non programmatori\" possano apportare modifiche e per rendere le correzioni pi\u00f9 rapide.<\/li>\n<\/ul>\n<p>\nEsaminiamo gli approcci dell'IA che coprono l'intero ciclo Sense\/Think\/Act.<\/p>\n<h3>Presi di decisioni di base<\/h3>\n<p>\nIniziamo con il gioco pi\u00f9 semplice: Pong. Obiettivo: spostare la piattaforma (paddle) in modo che la palla rimbalzi su di essa e non la superi. \u00c8 come il tennis, dove perdi se non colpisci la palla. Qui l'IA ha un compito relativamente semplice: decidere in quale direzione muovere la piattaforma.<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/e1935d657b9f090bf60c365c21e8f92b.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3>Operatori condizionali<\/h3>\n<p>\nPer l'IA in Pong c'\u00e8 una soluzione ovvia: cercare sempre di posizionare la piattaforma sotto la palla.<\/p>\n<p>Un semplice algoritmo per questo, scritto in pseudocodice:<\/p>\n<p><i>ogni frame\/aggiornamento mentre il gioco \u00e8 in esecuzione:<br \/>\nse la palla \u00e8 a sinistra della piattaforma:<br \/>\n muovi la piattaforma a sinistra<br \/>\naltrimenti se la palla \u00e8 a destra della piattaforma:<br \/>\n muovi la piattaforma a destra<\/i><\/p>\n<p>Se la piattaforma si muove alla velocit\u00e0 della palla, allora questo \u00e8 l'algoritmo ideale per l'IA in Pong. Non c'\u00e8 bisogno di complicare le cose se i dati e le possibili azioni per l'agente non sono cos\u00ec tanti.<\/p>\n<p>Questo approccio \u00e8 cos\u00ec semplice che l'intero ciclo Sense\/Think\/Act \u00e8 appena percepibile. Ma c'\u00e8:<\/p>\n<ul>\n<li>La parte Sense si trova nei due operatori if. Il gioco sa dove si trova la palla e dove \u00e8 la piattaforma, quindi l'IA si riferisce ad essa per avere queste informazioni. <\/li>\n<li>La parte Think \u00e8 anch'essa composta da due operatori if. Rappresentano due decisioni, che in questo caso sono mutuamente esclusive. Di conseguenza, viene scelta una delle tre azioni: spostare la piattaforma a sinistra, spostarla a destra o non fare nulla se \u00e8 gi\u00e0 posizionata correttamente.<\/li>\n<li>La parte Act si trova negli operatori Muovi la piattaforma a sinistra e Muovi la piattaforma a destra. A seconda del design del gioco, possono spostare la piattaforma istantaneamente o con una certa velocit\u00e0. <\/li>\n<\/ul>\n<p>\nTali approcci vengono chiamati reattivi: ci sono un insieme semplice di regole (in questo caso operatori if nel codice) che rispondono allo stato attuale del mondo e agiscono.<\/p>\n<h3>Albero delle decisioni<\/h3>\n<p>\nL'esempio del gioco Pong \u00e8 infatti equivalente al concetto formale di IA chiamato albero delle decisioni. L'algoritmo lo attraversa per raggiungere una 'foglia' \u2014 la decisione su quale azione intraprendere.<\/p>\n<p>Creiamo un diagramma di flusso dell'albero delle decisioni per l'algoritmo della nostra piattaforma:<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/d3b7290ba93144967cd849416cd5eef3.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nOgni parte dell'albero si chiama nodo (node) \u2014 l'IA utilizza la teoria dei grafi per descrivere strutture simili. Ci sono due tipi di nodi:<\/p>\n<ul>\n<li>Nodi decisionali: scelta tra due alternative basata sul controllo di una condizione, dove ogni alternativa \u00e8 rappresentata come un nodo separato.<\/li>\n<li>Nodi finali: azione da eseguire, rappresentante la decisione finale.<\/li>\n<\/ul>\n<p>\nL'algoritmo inizia dal primo nodo (\u00abradice\u00bb dell'albero). Esso pu\u00f2 prendere una decisione su quale nodo figlio passare, oppure eseguire un'azione memorizzata nel nodo e concludersi.<\/p>\n<p>Qual \u00e8 dunque il vantaggio, se l'albero delle decisioni svolge lo stesso compito degli operatori if della sezione precedente? Qui c'\u00e8 un sistema generale, dove ogni decisione ha solo una condizione e due possibili risultati. Questo consente allo sviluppatore di creare un'IA dai dati che rappresentano decisioni nell'albero, evitando di hardcodificarle. Immaginiamo in forma di tabella:<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/6875293a60ff9d0efa26fb5e1aa4b21c.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDal lato del codice avrete un sistema per leggere le righe. Create un nodo per ciascuna di esse, collegate la logica decisionale basata sulla seconda colonna e i nodi figli in base alla terza e quarta colonna. Dovrete ancora programmare le condizioni e le azioni, ma ora la struttura del gioco sar\u00e0 pi\u00f9 complessa. In essa aggiungete decisioni e azioni supplementari, e poi configurate tutta l'IA semplicemente modificando un file di testo con la definizione dell'albero. Successivamente, passate il file al game designer, che potr\u00e0 cambiare il comportamento senza ricompilare il gioco e senza modificare il codice.<\/p>\n<p>Gli alberi decisionali sono molto utili quando vengono costruiti automaticamente sulla base di un ampio insieme di esempi (ad esempio, utilizzando l'algoritmo ID3). Questo li rende uno strumento efficace e ad alte prestazioni per la classificazione delle situazioni in base ai dati acquisiti. Tuttavia, superiamo la semplice struttura per la scelta delle azioni degli agenti.<\/p>\n<h3>Scenari<\/h3>\n<p>\nAbbiamo analizzato un sistema di alberi decisionali che utilizzava condizioni e azioni predefinite. La persona che progetta l'IA pu\u00f2 organizzare l'albero come desidera, ma deve comunque fare affidamento su un programmatore che l'ha tutto programmato. E se potessimo dare al designer gli strumenti per creare le proprie condizioni o azioni?<\/p>\n<p>Per evitare che il programmatore debba scrivere codice per le condizioni Is Ball Left Of Paddle e Is Ball Right Of Paddle, pu\u00f2 creare un sistema in cui il designer registrer\u00e0 le condizioni per controllare questi valori. Allora i dati dell'albero delle decisioni appariranno cos\u00ec:<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/8e77f7c3410d097e8b7d8e1209355cc6.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn sostanza, \u00e8 la stessa cosa che nella prima tabella, ma le soluzioni al loro interno hanno un proprio codice, un po' simile alla parte condizionale dell'operatore if. Dalla parte del codice, questo verrebbe letto nella seconda colonna per i nodi decisionali, ma invece di cercare una condizione specifica da eseguire (Is Ball Left Of Paddle), valuta l'espressione condizionale e restituisce true o false di conseguenza. Questo viene fatto attraverso il linguaggio di scripting Lua o Angelscript. Con questi, lo sviluppatore pu\u00f2 prendere oggetti nel proprio gioco (ball e paddle) e creare variabili che saranno accessibili nello script (ball.position). Inoltre, il linguaggio di scripting \u00e8 pi\u00f9 semplice del C++. Non richiede una fase di compilazione completa, quindi \u00e8 perfetto per rapidi aggiustamenti della logica di gioco e consente ai \"non programmatori\" di creare le funzioni necessarie.<\/p>\n<p>Nell'esempio fornito, il linguaggio di scripting viene utilizzato solo per valutare un'espressione condizionale, ma pu\u00f2 essere utilizzato anche per azioni. Ad esempio, Move Paddle Right pu\u00f2 diventare un'operazione di scripting (ball.position.x += 10). In questo modo, l'azione viene anche definita nello script, senza la necessit\u00e0 di programmare Move Paddle Right.<\/p>\n<p>Si pu\u00f2 andare ancora oltre e scrivere completamente un albero decisionale in linguaggio di scripting. Questo sar\u00e0 codice sotto forma di operatori condizionali hardcoded, ma saranno situati in file di script esterni, ovvero possono essere modificati senza ricompilare l'intero programma. Spesso \u00e8 possibile modificare il file di script direttamente durante il gioco, per testare rapidamente diverse reazioni dell'IA.<\/p>\n<h3>Reazione agli eventi<\/h3>\n<p>\nGli esempi sopra si adattano perfettamente a Pong. Attivano continuamente il ciclo Sense\/Think\/Act e agiscono in base all'ultimo stato del mondo. Ma nei giochi pi\u00f9 complessi \u00e8 necessario reagire a singoli eventi, e non valutare tutto e subito. In tal caso, Pong non \u00e8 pi\u00f9 un buon esempio. Scegliamo un altro. <\/p>\n<p>Immagina uno shooter in cui i nemici sono immobili finch\u00e9 non rilevano il giocatore, dopodich\u00e9 agiscono in base alla loro \"specializzazione\": qualcuno correr\u00e0 per attaccare, qualcuno attaccher\u00e0 da lontano. Questa \u00e8 ancora una base reattiva \u2014 \"se il giocatore \u00e8 visto, allora fai qualcosa\" \u2014 ma pu\u00f2 essere logicamente separata in evento Player Seen (giocatore visto) e reazione (scegli la risposta e attuala).<\/p>\n<p>Questo ci riporta al ciclo Sense\/Think\/Act. Possiamo codificare la parte Sense, che controlla ad ogni frame se l'IA vede il giocatore. Se non lo vede, non succede nulla, ma se lo vede, si genera un evento Player Seen. Il codice avr\u00e0 una sezione separata che dice: \u00abquando si verifica l'evento Player Seen, fai \u00bb, dove  \u00e8 la risposta necessaria per accedere alle parti Think e Act. In questo modo, imposterai le reazioni all'evento Player Seen: per il personaggio che 'corre' \u2014 ChargeAndAttack, e per il cecchino \u2014 HideAndSnipe. Questi collegamenti possono essere creati in un file dati per una modifica rapida senza la necessit\u00e0 di ricompilare da zero. Qui si pu\u00f2 utilizzare anche il linguaggio di scripting.<\/p>\n<h2>Prendere decisioni complesse<\/h2>\n<p>\nSebbene i sistemi di reazione semplici siano molto efficaci, ci sono molte situazioni in cui non sono sufficienti. A volte \u00e8 necessario prendere diverse decisioni, basate su ci\u00f2 che l'agente sta facendo in quel momento, ma rappresentare questo come una condizione \u00e8 difficile. A volte ci sono troppe condizioni per rappresentarle efficacemente in un albero delle decisioni o in uno script. A volte \u00e8 necessario valutare in anticipo come cambier\u00e0 la situazione, prima di prendere una decisione sul passo successivo. Per affrontare questi problemi sono necessari approcci pi\u00f9 complessi.<\/p>\n<h3>Macchina a stati finiti<\/h3>\n<p>\nLa macchina a stati finiti o FSM (Finite State Machine) \u00e8 un modo per dire che il nostro agente \u00e8 attualmente in uno di diversi stati possibili, e che pu\u00f2 passare da uno stato all'altro. Gli stati sono definiti in numero finito \u2014 da qui il nome. Il miglior esempio della vita quotidiana \u00e8 un semaforo. In diversi luoghi ci sono diverse sequenze di luci, ma il principio \u00e8 lo stesso: ogni stato rappresenta qualcosa (ferma, vai, ecc.). Il semaforo si trova sempre in uno stato in un dato momento, e passa da uno all'altro sulla base di semplici regole.<\/p>\n<p>Con gli NPC nei giochi, la storia \u00e8 simile. Prendiamo come esempio un guardiano con i seguenti stati:<\/p>\n<ul>\n<li>In pattuglia (Patrolling).<\/li>\n<li>In attacco (Attacking).<\/li>\n<li>In fuga (Fleeing).<\/li>\n<\/ul>\n<p>\nE con queste condizioni per cambiare il suo stato:<\/p>\n<ul>\n<li>Se il guardiano vede un avversario, attacca.<\/li>\n<li>Se il guardiano attacca, ma non vede pi\u00f9 l'avversario, torna in pattuglia.<\/li>\n<li>Se il guardiano attacca, ma \u00e8 gravemente ferito, fugge.<\/li>\n<\/ul>\n<p>\n\u00c8 possibile anche scrivere operatori if con variabili di stato del guardiano e varie verifiche: se c'\u00e8 un nemico nelle vicinanze, quale \u00e8 il livello di salute dell'NPN e cos\u00ec via. Aggiungiamo ancora alcuni stati:<\/p>\n<ul>\n<li>Inattivit\u00e0 (Idling) \u2014 tra i pattugliamenti.<\/li>\n<li>Ricerca (Searching) \u2014 quando un nemico avvistato \u00e8 scomparso.<\/li>\n<li>Chiedere aiuto (Finding Help) \u2014 quando un nemico \u00e8 avvistato, ma \u00e8 troppo forte per combatterlo da solo.<\/li>\n<\/ul>\n<p>\nLa scelta per ognuno di essi \u00e8 limitata: ad esempio, il guardiano non andr\u00e0 a cercare il nemico scomparso se ha poca salute.<\/p>\n<p>Alla fine, un&#039;enorme lista &quot;se&quot; pu&ograve; diventare troppo ingombrante, quindi &egrave; necessario formalizzare un metodo che ci permetta di tenere a mente gli stati e le transizioni tra gli stati. Per fare ci&ograve;, prenderemo in considerazione tutti gli stati e, sotto ogni stato, scriveremo in un elenco tutte le transizioni verso altri stati, insieme alle condizioni necessarie per esse. &lt;x \u0438 y, \u043d\u043e \u043d\u0435 z&gt;, allora &lt;p&gt;&raquo;, potrebbe diventare troppo ingombrante, quindi &egrave; necessario formalizzare un metodo che ci consenta di tenere a mente gli stati e le transizioni tra gli stati. Per fare ci&ograve;, considereremo tutti gli stati e, per ciascuno di essi, scriveremo in un elenco tutte le transizioni verso altri stati, insieme alle condizioni necessarie per esse.<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/ba4c401aa20de3d22d2478cba5a4b1ec.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nQuesta \u00e8 una tabella di transizione di stati \u2014 un modo complesso di rappresentare una FSM. Disegniamo un diagramma e otteniamo una panoramica completa di come cambia il comportamento dell'NPC.<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/b4182359983cf573872dacc575af13dc.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIl diagramma riflette l'essenza della presa di decisioni per questo agente in base alla situazione attuale. Ogni freccia mostra la transizione tra stati, se la condizione a essa associata \u00e8 vera.<\/p>\n<p>Ad ogni aggiornamento controlliamo lo stato attuale dell'agente, esaminiamo l'elenco delle transizioni e se le condizioni per la transizione sono soddisfatte, egli accetta un nuovo stato. Ad esempio, ad ogni frame viene controllato se il timer di 10 secondi \u00e8 scaduto e, se s\u00ec, dallo stato di Idling, il guardiano passa a Patrolling. In modo simile, lo stato di Attacking controlla la salute dell'agente: se \u00e8 bassa, passa allo stato di Fleeing.<\/p>\n<p>Questa \u00e8 la gestione delle transizioni tra stati, ma che dire del comportamento legato agli stati stessi? Per quanto riguarda l'implementazione del comportamento effettivo per uno stato specifico, di solito ci sono due tipi di \"ganci\", dove assegnamo azioni alla FSM:<\/p>\n<ul>\n<li>Azioni che eseguiamo periodicamente per lo stato attuale.<\/li>\n<li>Azioni che intraprendiamo quando passiamo da uno stato a un altro.<\/li>\n<\/ul>\n<p>\nEsempi per il primo tipo. Lo stato di Patrolling muover\u00e0 l'agente lungo il percorso di pattugliamento ad ogni frame. Lo stato di Attacking tenter\u00e0 di avviare un attacco o passare a uno stato quando possibile ad ogni frame.<\/p>\n<p>Per il secondo tipo, consideriamo il passaggio \"se il nemico \u00e8 visibile e il nemico \u00e8 troppo forte, allora passare allo stato Finding Help. L'agente deve scegliere dove andare per ricevere aiuto e conservare queste informazioni affinch\u00e9 lo stato Finding Help sappia dove rivolgersi. Una volta trovato aiuto, l'agente torna allo stato Attacking. A questo punto vorr\u00e0 segnalare al compagno la minaccia, quindi potrebbe verificarsi l'azione NotifyFriendOfThreat.<\/p>\n<p>Ancora una volta, possiamo esaminare questo sistema attraverso il ciclo Sense\/Think\/Act. Sense si realizza nei dati utilizzati dalla logica di transizione. Think \u2013 nelle transizioni disponibili in ogni stato. E Act si concretizza nelle azioni eseguite periodicamente all'interno dello stato o nelle transizioni tra stati.<\/p>\n<p>A volte, il sondaggio continuo delle condizioni di transizione pu\u00f2 essere dispendioso. Ad esempio, se ogni agente deve eseguire calcoli complessi ogni fotogramma per determinare se vede i nemici e comprendere se pu\u00f2 passare dallo stato Patrolling a Attacking \u2013 questo richieder\u00e0 molto tempo di elaborazione. <\/p>\n<p>Le importanti modifiche nello stato del mondo possono essere considerate eventi che verranno elaborati man mano che si verificano. Invece di controllare ogni fotogramma se l'agente pu\u00f2 vedere il giocatore, \u00e8 possibile impostare un sistema separato per eseguire controlli meno frequentemente (ad esempio, 5 volte al secondo). E il risultato sar\u00e0 Player Seen, una volta che il controllo \u00e8 superato. <\/p>\n<p>Questo viene passato al FSM, il quale ora deve passare alla condizione Player Seen event received e rispondere di conseguenza. Il comportamento finale rimane lo stesso, eccetto per un ritardo quasi impercettibile prima della risposta. Tuttavia, le prestazioni sono migliorate grazie alla separazione di parte del Sense in una parte separata del programma.<\/p>\n<h3>Macchina a stati finiti gerarchica<\/h3>\n<p>\nTuttavia, lavorare con grandi FSM non \u00e8 sempre comodo. Se desideriamo ampliare lo stato di attacco, sostituendolo con attacchi a distanza MeleeAttacking (corpo a corpo) e RangedAttacking (da distanza), dovremo modificare le transizioni di tutti gli altri stati che portano allo stato Attacking (quelli correnti e futuri).<\/p>\n<p>Sicuramente avrete notato che nel nostro esempio ci sono molte transizioni duplicate. La maggior parte delle transizioni nello stato di Idling sono identiche a quelle nello stato di Patrolling. Sarebbe opportuno non ripetersi, soprattutto se aggiungeremo altri stati simili. Ha senso raggruppare Idling e Patrolling sotto un'etichetta comune 'non bellica', dove c'\u00e8 un unico insieme comune di transizioni verso stati di combattimento. Se consideriamo questa etichetta come uno stato, allora Idling e Patrolling diventeranno sottostati. Ecco un esempio di utilizzo di una tabella delle transizioni separata per un nuovo sottostato non bellico:<\/p>\n<p><i>Stati principali:<\/i><br \/>\n<img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/d86dd918acbe81b9bf22c2fb34aecee3.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\n<i>Stato fuori combattimento:<\/i><br \/>\n<img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/9d5bc2053010a32c5f68d7f0192c04ed.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nE in forma di diagramma:<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/0ccf95ecafa9ce2a6ea5b5b9833ddc4f.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nQuesta \u00e8 la stessa identica sistema, ma con un nuovo stato non bellico che comprende Idling e Patrolling. Con ogni stato contenente un FSM con sottostati (e questi sottostati, a loro volta, contengono i propri FSM \u2014 e cos\u00ec via quante volte \u00e8 necessario), otteniamo una Gerarchia di Macchine a Stati Finiti o HFSM. Raggruppando lo stato non bellico, abbiamo eliminato un sacco di transizioni ridondanti. Lo stesso possiamo fare per qualsiasi nuovo stato con transizioni comuni. Ad esempio, se in futuro espandiamo lo stato Attacking in stati MeleeAttacking e MissileAttacking, questi saranno sottostati, che si scambiano transizioni tra di loro in base alla distanza dal nemico e alla disponibilit\u00e0 di munizioni. Alla fine, modelli di comportamento complessi e sottomodelli di comportamento possono essere rappresentati con un minimo di transizioni duplicate.<\/p>\n<h3>Albero dei comportamenti<\/h3>\n<p>\nCon HFSM si creano combinazioni complesse di comportamenti in modo semplice. Tuttavia, c'\u00e8 una piccola difficolt\u00e0, poich\u00e9 la presa di decisione sotto forma di regole di transizione \u00e8 strettamente legata allo stato attuale. E in molti giochi \u00e8 proprio ci\u00f2 che serve. Un'attenta utilizzo della gerarchia degli stati pu\u00f2 ridurre il numero di ripetizioni nelle transizioni. Ma a volte servono regole che funzionano indipendentemente dallo stato in cui ti trovi o che si applicano quasi in qualsiasi stato. Ad esempio, se la salute dell'agente scende al 25%, vorresti che fuggisse indipendentemente dal fatto che fosse in combattimento, inattivo o che stesse parlando \u2014 dovresti aggiungere questa condizione in ogni stato. E se in seguito il tuo designer decidesse di modificare la soglia di bassa salute dal 25% al 10%, dovresti occuparmene di nuovo.<\/p>\n<p>In ideale per questa situazione serve un sistema in cui le decisioni \"in quale stato trovarsi\" siano al di fuori degli stati stessi, in modo da apportare modifiche in un solo posto e non modificare le condizioni di transizione. Qui entrano in gioco gli alberi dei comportamenti.<\/p>\n<p>Esistono diversi modi per implementarli, ma l'essenza \u00e8 pi\u00f9 o meno la stessa e assomiglia a un albero delle decisioni: l'algoritmo inizia da un nodo \"radice\", e nell'albero ci sono nodi che rappresentano o decisioni o azioni. Ci sono per\u00f2 alcune differenze chiave:<\/p>\n<ul>\n<li>Ora i nodi restituiscono uno dei tre valori: Succeeded (se il lavoro \u00e8 stato completato), Failed (se non \u00e8 possibile avviarlo) o Running (se \u00e8 ancora in esecuzione e non c'\u00e8 un risultato finale).<\/li>\n<li>Non ci sono pi\u00f9 nodi decisionali per scegliere tra due alternative. Invece, ci sono nodi Decorator, che hanno un solo nodo figlio. Se ottengono Succeed, eseguono il loro unico nodo figlio.<\/li>\n<li>I nodi che eseguono azioni restituiscono il valore Running per rappresentare le azioni in corso.<\/li>\n<\/ul>\n<p>\nQuesto piccolo insieme di nodi pu\u00f2 essere combinato per creare un gran numero di modelli complessi di comportamento. Immaginiamo l'HFSM di una sentinella dall'esempio precedente rappresentata come un albero del comportamento:<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/5eaa5c725e4ada8285f16f95bb206d53.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCon questa struttura non dovrebbe esserci un passaggio esplicito dagli stati Idling\/Patrolling allo stato Attacking o a qualsiasi altro. Se il nemico \u00e8 visibile e la salute del personaggio \u00e8 bassa, l'esecuzione si fermer\u00e0 sul nodo Fleeing, indipendentemente dal nodo che \u00e8 stato precedentemente eseguito \u2014 Patrolling, Idling, Attacking o qualsiasi altro.<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/e1c1dcc2055174aa7cfa846364b1709a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nGli alberi dei comportamenti sono complessi: ci sono molti modi per comporli, e trovare la giusta combinazione di decoratori e nodi composti pu\u00f2 essere problematico. Ci sono anche domande su quanto spesso controllare l'albero: vogliamo attraversarlo su ogni parte o solo quando una delle condizioni \u00e8 cambiata? Come mantenere lo stato relativo ai nodi: come sapere quando siamo stati nello stato di Idling per 10 secondi o come sapere quali nodi sono stati eseguiti l'ultima volta per gestire correttamente la sequenza?<\/p>\n<p>\u00c8 per questo che esistono molte implementazioni. Ad esempio, in alcuni sistemi i nodi decoratore sono stati sostituiti con decoratori incorporati. Questi rivalutano l'albero al cambiamento delle condizioni del decoratore, aiutano a collegare i nodi e forniscono aggiornamenti periodici.<\/p>\n<h3>Sistema basato su utilit\u00e0<\/h3>\n<p>\nAlcuni giochi hanno molte meccaniche diverse. \u00c8 auspicabile che tutte possano trarre vantaggio da regole semplici e comuni per le transizioni, ma non necessariamente in forma di un albero comportamentale completo. Invece di avere un insieme chiaro di scelte o un albero di possibili azioni, \u00e8 pi\u00f9 semplice esplorare tutte le azioni e scegliere quella pi\u00f9 appropriata al momento.<\/p>\n<p>Il sistema basato su utilit\u00e0 (utility-based system) \u00e8 proprio ci\u00f2 di cui abbiamo bisogno. Si tratta di un sistema in cui l\u2019agente ha molte azioni a disposizione e sceglie autonomamente quale eseguire, basandosi sull\u2019utilit\u00e0 relativa di ciascuna. Dove l'utilit\u00e0 \u00e8 una misura arbitraria dell'importanza o della desiderabilit\u00e0 dell'esecuzione di quell'azione per l'agente. <\/p>\n<p>L'utilit\u00e0 calcolata dell'azione, basata sullo stato attuale e sull'ambiente, pu\u00f2 essere verificata dall'agente per scegliere un altro stato potenzialmente pi\u00f9 adatto in qualsiasi momento. Questo \u00e8 simile a un FSM, ad eccezione del fatto che le transizioni sono definite dalla valutazione di ciascuno stato potenziale, incluso quello attuale. Si noti che scegliamo l'azione pi\u00f9 utile per la transizione (o rimaniamo fermi se l'abbiamo gi\u00e0 eseguita). Per una maggiore variet\u00e0, potrebbe essere una scelta ponderata, ma casuale, da una piccola lista.<\/p>\n<p>Il sistema assegna un intervallo arbitrario di valori di utilit\u00e0 - ad esempio, da 0 (completamente indesiderabile) a 100 (completamente desiderabile). Ogni azione ha una serie di parametri che influenzano il calcolo di questo valore. Ritornando al nostro esempio con il guardiano:<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/085fb2c197bde93d78455d18e63c9c25.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nLe transizioni tra le azioni non sono univoche: qualsiasi stato pu\u00f2 seguire qualsiasi altro. Le priorit\u00e0 delle azioni sono stabilite dai valori di utilit\u00e0 restituiti. Se il nemico \u00e8 visibile e questo nemico \u00e8 forte, e la salute del personaggio \u00e8 bassa, allora sia Fleeing che FindingHelp restituiranno valori alti e diversi da zero. In questo caso, FindingHelp sar\u00e0 sempre superiore. Analogamente, le azioni non di combattimento non restituiscono mai pi\u00f9 di 50, quindi saranno sempre inferiori a quelle di combattimento. Questo deve essere considerato quando si creano azioni e si calcola la loro utilit\u00e0.<\/p>\n<p>Nel nostro esempio, le azioni restituiscono un valore costante fisso o uno dei due valori fissi. Un sistema pi\u00f9 realistico prevede il ritorno di una valutazione da un intervallo continuo di valori. Ad esempio, l'azione Fleeing restituisce valori di utilit\u00e0 pi\u00f9 elevati se la salute dell'agente \u00e8 bassa, mentre l'azione Attacking restituisce valori pi\u00f9 bassi se il nemico \u00e8 troppo forte. Per questo motivo, l'azione Fleeing ha la priorit\u00e0 su Attacking in qualsiasi situazione in cui l'agente sente di avere una salute insufficiente per vincere contro l'avversario. Ci\u00f2 consente di modificare le priorit\u00e0 delle azioni sulla base di un numero qualsiasi di criteri, rendendo questo approccio pi\u00f9 flessibile e variabile rispetto a un albero comportamentale o FSM.<\/p>\n<p>Ogni azione ha molte condizioni per calcolare il programma. Possono essere scritte in un linguaggio di scripting o come una serie di formule matematiche. In The Sims, che modella la giornata della persona, viene aggiunto un ulteriore livello di calcolo: l'agente riceve una serie di \"motivazioni\" che influenzano le valutazioni di utilit\u00e0. Se il personaggio ha fame, nel tempo diventer\u00e0 ancora pi\u00f9 affamato, e il risultato dell'azione EatFood aumenter\u00e0 finch\u00e9 il personaggio non la eseguir\u00e0, riducendo il livello di fame e riportando il valore di EatFood a zero. <\/p>\n<p>L'idea di scegliere le azioni basandosi su un sistema di valutazione \u00e8 piuttosto semplice, quindi il sistema basato sull'utilit\u00e0 pu\u00f2 essere utilizzato come parte dei processi decisionali dell'IA, e non come loro completa sostituzione. Un albero decisionale pu\u00f2 richiedere una valutazione di utilit\u00e0 di due nodi figli e scegliere il pi\u00f9 alto. Allo stesso modo, un albero comportamentale pu\u00f2 avere un nodo composito Utility per valutare l'utilit\u00e0 delle azioni, per decidere quale elemento figlio eseguire.<\/p>\n<h2>Movimento e navigazione<\/h2>\n<p>\nNegli esempi precedenti avevamo una piattaforma che spostavamo a sinistra o a destra e una guardia che pattugliava o attaccava. Ma come gestiamo esattamente il movimento dell'agente per un certo periodo di tempo? Come impostiamo la velocit\u00e0, come evitiamo gli ostacoli e come pianifichiamo un percorso se raggiungere la destinazione \u00e8 pi\u00f9 complesso che muoversi in linea retta? Vediamo di approfondire.<\/p>\n<h3>Gestione<\/h3>\n<p>\nNella fase iniziale, consideriamo che ogni agente ha un valore di velocit\u00e0 che include quanto rapidamente si muove e in quale direzione. Questa pu\u00f2 essere misurata in metri al secondo, chilometri all'ora, pixel al secondo, ecc. Ricordando il ciclo Sense\/TThink\/Act, possiamo immaginare che la parte Think scelga la velocit\u00e0, mentre la parte Act applichi questa velocit\u00e0 all'agente. Di solito nei giochi esiste un sistema fisico che svolge questo compito per te, valutando il valore di velocit\u00e0 di ciascun oggetto e regolando di conseguenza. Pertanto, possiamo lasciare all'IA un'unica missione: decidere quale velocit\u00e0 debba avere l'agente. Se sappiamo dove deve trovarsi l'agente, dobbiamo muoverlo nella giusta direzione con la velocit\u00e0 stabilita. Un'equazione molto semplice:<\/p>\n<p><i>desired_travel = destination_position \u2013 agent_position<\/i><\/p>\n<p>Immagina un mondo 2D. L'agente si trova al punto (-2,-2), la destinazione \u00e8 da qualche parte a nord-est al punto (30, 20), e il percorso necessario per l'agente per arrivarci \u00e8 (32, 22). Supponiamo che queste posizioni siano misurate in metri: se prendiamo la velocit\u00e0 dell'agente come 5 metri al secondo, scaleremo il nostro vettore di movimento e otterremo una velocit\u00e0 di circa (4.12, 2.83). Con questi parametri, l'agente arriverebbe a destinazione in quasi 8 secondi.<\/p>\n<p>I valori possono essere ricalcolati in qualsiasi momento. Se l'agente si trovava a met\u00e0 strada verso la meta, il movimento sarebbe stato la met\u00e0 della lunghezza, ma poich\u00e9 la velocit\u00e0 massima dell'agente \u00e8 di 5 m\/s (abbiamo stabilito questo in precedenza), la velocit\u00e0 rimarr\u00e0 la stessa. Questo funziona anche per gli obiettivi in movimento, permettendo all'agente di apportare piccole modifiche man mano che si spostano.<\/p>\n<p>Ma vogliamo maggiore variabilit\u00e0: ad esempio, aumentare lentamente la velocit\u00e0 per simulare un personaggio che passa da uno stato stazionario a una corsa. Lo stesso pu\u00f2 avvenire alla fine prima di fermarsi. Queste funzionalit\u00e0 sono note come behaviour di steering, ognuna delle quali ha nomi specifici: Seek (ricerca), Flee (fuga), Arrival (arrivo) e cos\u00ec via. L'idea \u00e8 che forze di accelerazione possano essere applicate alla velocit\u00e0 dell'agente, basandosi sul confronto tra la posizione dell'agente e la velocit\u00e0 attuale con il punto di destinazione, per utilizzare vari metodi di movimento verso l'obiettivo.<\/p>\n<p>Ogni comportamento ha un obiettivo leggermente diverso. Seek e Arrival sono modi per muovere l'agente verso una destinazione. L'Obstacle Avoidance (evitare ostacoli) e la Separation (separazione) correggono il movimento dell'agente per aggirare gli ostacoli lungo il percorso verso l'obiettivo. L'Alignment (allineamento) e la Cohesion (coesione) mantengono gli agenti in movimento insieme. Un numero qualsiasi di comportamenti di steering diversi pu\u00f2 essere sommato per ottenere un unico vettore di percorso tenendo conto di tutti i fattori. Un agente utilizza i comportamenti di Arrival, Separation e Obstacle Avoidance per stare lontano da muri e altri agenti. Questo approccio funziona bene in luoghi aperti senza troppi dettagli. <\/p>\n<p>In condizioni pi\u00f9 difficili, la somma di comportamenti diversi funziona peggio: ad esempio, un agente potrebbe bloccarsi contro un muro a causa di un conflitto tra Arrival e Obstacle Avoidance. Pertanto, \u00e8 necessario considerare opzioni pi\u00f9 complesse rispetto alla semplice somma di tutti i valori. Un modo \u00e8: invece di sommare i risultati di ogni comportamento, possiamo considerare il movimento in diverse direzioni e scegliere l'opzione migliore. <\/p>\n<p>Tuttavia, in un ambiente complesso con vicoli ciechi e scelta della direzione in cui andare, avremo bisogno di qualcosa di ancora pi\u00f9 avanzato.<\/p>\n<h3>Ricerca del percorso<\/h3>\n<p>\nI comportamenti di steering sono eccellenti per il semplice movimento in spazi aperti (un campo da calcio o un'arena), dove arrivare da A a B \u00e8 una linea retta con poche deviazioni da ostacoli. Per percorsi complessi abbiamo bisogno di pathfinding, che \u00e8 un modo per esplorare il mondo e decidere un percorso attraverso di esso.<\/p>\n<p>Il metodo pi\u00f9 semplice consiste nell'applicare una griglia a ogni quadrato adiacente all'agente e valutare in quali di essi \u00e8 consentito muoversi. Se uno di questi quadrati \u00e8 il punto di arrivo, segui il percorso da quel quadrato fino al precedente, continuando fino a raggiungere l'inizio. Questo rappresenta il percorso. Altrimenti, ripeti il processo con i quadrati vicini, finch\u00e9 non trovi il punto di arrivo o non ci sono pi\u00f9 quadrati disponibili (il che significa che non esiste un percorso possibile). Questo \u00e8 formalmente noto come Breadth-First Search o BFS (algoritmo di ricerca in ampiezza). A ogni passo, analizza in tutte le direzioni (da qui il termine<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/d367e62bc53033b05388538649853a41.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDi conseguenza, otterrai un elenco di quadrati che compongono il percorso necessario. Questo \u00e8 il cammino (da cui pathfinding) \u2014 l'elenco dei luoghi che l'agente visiter\u00e0 seguendo verso il punto di arrivo.<\/p>\n<p>Considerando che conosciamo la posizione di ogni quadrato nel mondo, possiamo utilizzare i comportamenti di guida per muoverci lungo il percorso \u2014 da nodo 1 a nodo 2, poi da nodo 2 a nodo 3 e cos\u00ec via. La soluzione pi\u00f9 semplice \u00e8 dirigersi verso il centro del quadrato successivo, ma \u00e8 ancora meglio fermarsi a met\u00e0 del bordo tra il quadrato corrente e quello successivo. In questo modo, l'agente pu\u00f2 tagliare gli angoli nelle curve pi\u00f9 strette.<\/p>\n<p>L'algoritmo BFS ha anche dei lati negativi: esplora tanti quadrati nella \u201cdirezione sbagliata\u201d quanto in quella \u201cgiusta\u201d. Qui entra in gioco un algoritmo pi\u00f9 complesso chiamato A* (A star). Funziona in modo simile, ma invece di esplorare ciecamente i quadrati vicini (poi i vicini dei vicini, e cos\u00ec via), raccoglie i nodi in un elenco e li ordina in modo che il prossimo nodo esplorato sia sempre quello che porter\u00e0 al percorso pi\u00f9 breve. I nodi sono ordinati in base a un'euristica che considera due fattori: il \u201ccosto\u201d del percorso ipotetico verso il quadrato desiderato (inclusi eventuali costi di movimento) e una stima della distanza di quel quadrato dal punto di arrivo (orientando cos\u00ec la ricerca nella direzione corretta).<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/1cab4f53fa5af6b31d352c7bcf453d7e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn questo esempio si mostra che l'agente esplora un quadrato alla volta, scegliendo di volta in volta il pi\u00f9 promettente tra i vicini. Il percorso risultante \u00e8 lo stesso di quello di BFS, ma sono stati considerati meno quadrati durante il processo, il che \u00e8 fondamentale per le prestazioni del gioco.<\/p>\n<h3>Movimento senza griglia<\/h3>\n<p>\nMa la maggior parte dei giochi non \u00e8 costruita su una griglia, e spesso non \u00e8 possibile farlo senza compromettere la realt\u00e0. Sono necessari compromessi. Quali dovrebbero essere le dimensioni dei quadrati? Se sono troppo grandi, non riusciranno a rappresentare adeguatamente corridoi stretti o curve; se troppo piccoli, ci saranno troppi quadrati da cercare, il che richieder\u00e0 molto tempo.<\/p>\n<p>La prima cosa da capire \u00e8 che la griglia ci fornisce un grafo di nodi collegati. Gli algoritmi A* e BFS funzionano effettivamente su grafi e non si interessano affatto della nostra griglia. Potremmo posizionare i nodi in qualsiasi luogo del mondo di gioco: con una connessione tra qualsiasi due nodi connessi, nonch\u00e9 tra il punto di partenza e quello di arrivo e almeno uno dei nodi, l'algoritmo funzioner\u00e0 altrettanto bene come prima. Questo \u00e8 frequentemente chiamato sistema di waypoint, poich\u00e9 ogni nodo rappresenta una posizione significativa nel mondo, che pu\u00f2 far parte di qualsiasi quantit\u00e0 di percorsi ipotetici.<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/d87e9d4bb2a2fc713d32abc158506eaa.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Esempio 1: un nodo in ogni quadrato. La ricerca inizia dal nodo in cui si trova l'agente e termina nel nodo del quadrato desiderato.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/b535a5db805efdc427d7c5724b866982.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Esempio 2: un set pi\u00f9 piccolo di nodi (waypoint). La ricerca inizia nel quadrato con l'agente, attraversa il numero necessario di nodi e poi prosegue verso la destinazione.<\/i><\/p>\n<p>Questo \u00e8 un sistema piuttosto flessibile e potente. Ma \u00e8 necessaria un po' di cautela nelle decisioni su dove e come posizionare i waypoint, altrimenti gli agenti potrebbero semplicemente non vedere il punto pi\u00f9 vicino e non riuscire ad avviare il percorso. Sarebbe pi\u00f9 semplice se potessimo posizionare automaticamente i waypoint in base alla geometria del mondo.<\/p>\n<p>Qui entra in gioco la navigation mesh o navmesh (griglia di navigazione). Di solito \u00e8 una griglia 2D di triangoli sovrapposta alla geometria del mondo, ovunque sia consentito all'agente muoversi. Ogni triangolo nella griglia diventa un nodo nel grafo e pu\u00f2 avere fino a tre triangoli adiacenti, che diventano nodi vicini nel grafo. <\/p>\n<p>Questa immagine \u00e8 un esempio del motore Unity: ha analizzato la geometria nel mondo e ha creato un navmesh (nella schermata di colore azzurro chiaro). Ogni poligono nel navmesh \u00e8 un\u2019area su cui un agente pu\u00f2 stare o muoversi da un poligono a un altro. In questo esempio, i poligoni sono pi\u00f9 piccoli dei piani su cui sono situati, per tenere conto delle dimensioni dell\u2019agente, che uscir\u00e0 al di fuori della sua posizione nominale.<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/845705ba7b9a9d469203aedf7942da41.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPossiamo cercare un percorso attraverso questa rete, riutilizzando l\u2019algoritmo A*. Questo ci dar\u00e0 un percorso praticamente ideale nel mondo, che tiene conto di tutta la geometria e non richiede nodi aggiuntivi e creazione di waypoint.<\/p>\n<p>Il pathfinding \u00e8 un argomento troppo vasto, che non pu\u00f2 essere trattato in un solo capitolo di un articolo. Se desideri esplorarlo pi\u00f9 a fondo, questo pu\u00f2 essere utile <noindex><a rel=\"nofollow\" href=\"https:\/\/www.redblobgames.com\/pathfinding\/a-star\/introduction.html\">sito di Amit Patel<\/a><\/noindex>.<\/p>\n<h2>Pianificazione<\/h2>\n<p>\nAbbiamo appurato con il pathfinding che a volte non basta semplicemente scegliere una direzione e muoversi: dobbiamo selezionare un percorso e fare diverse inversioni per arrivare alla meta desiderata. Possiamo generalizzare questa idea: raggiungere un obiettivo non \u00e8 solo il passo successivo, ma un'intera sequenza, dove a volte \u00e8 necessario guardare avanti di alcuni passi per capire quale dovrebbe essere il primo. Questo si chiama pianificazione. Il pathfinding pu\u00f2 essere considerato come uno dei tanti complementi alla pianificazione. Dal punto di vista del nostro ciclo Sense \/ Think \/ Act, \u00e8 qui che parte del Think pianifica alcune parti dell'Act per il futuro.<\/p>\n<p>Prendiamo come esempio il gioco di carte Magic: The Gathering. Siamo i primi a giocare con questa mano di carte:<\/p>\n<ul>\n<li>Palude \u2014 fornisce 1 mana nero (carta terreno).<\/li>\n<li>Foresta \u2014 fornisce 1 mana verde (carta terreno).<\/li>\n<li>Mago Fuggitivo \u2014 richiede 1 mana blu per essere evocato.<\/li>\n<li>Mistico Elfico \u2014 richiede 1 mana verde per essere evocato.<\/li>\n<\/ul>\n<p>\nIgnoriamo le restanti tre carte per semplificare. Secondo le regole, al giocatore \u00e8 consentito giocare 1 carta terreno a turno; pu\u00f2 \"tapparla\" per ottenere mana da essa e poi utilizzare incantesimi (incluso evocare creature) in base al mana disponibile. In questa situazione, il giocatore umano sa che deve giocare Foresta, \"tappare\" 1 mana verde e poi evocare il Mistico Elfico. Ma come pu\u00f2 scoprirlo l'IA di gioco?<\/p>\n<h3>Pianificazione semplice<\/h3>\n<p>\nUn approccio banale consiste nel provare ogni azione a turno, fino a quando non rimangono opzioni valide. Guardando le carte, l'IA vede che pu\u00f2 giocare Swamp. E lo gioca. Ci sono altre azioni rimaste in questo turno? Non pu\u00f2 evocare n\u00e9 Elvish Mystic n\u00e9 Fugitive Wizard, poich\u00e9 per evocare questi ultimi sono richieste rispettivamente mana verde e blu, mentre Swamp fornisce solo mana nera. E non potr\u00e0 giocare Forest, perch\u00e9 ha gi\u00e0 giocato Swamp. Pertanto, l'IA del gioco ha rispettato le regole, ma lo ha fatto male. Si pu\u00f2 migliorare.<\/p>\n<p>La pianificazione pu\u00f2 trovare un elenco di azioni che portano il gioco nello stato desiderato. Proprio come ogni quadrato del percorso aveva vicini (nella ricerca del percorso), ogni azione nel piano ha anche vicini o successori. Possiamo cercare queste azioni e le azioni successive, fino a quando non raggiungiamo lo stato desiderato.<\/p>\n<p>Nel nostro esempio, il risultato desiderato \u00e8 \u00abevocare una creatura, se possibile\u00bb. All'inizio del turno vediamo solo due possibili azioni consentite dalle regole del gioco:<\/p>\n<p><i>1. Giocare Swamp (risultato: Swamp in gioco)<br \/>\n2. Giocare Forest (risultato: Forest in gioco)<\/i><\/p>\n<p>Ogni azione presa pu\u00f2 portare a ulteriori azioni e chiudere altre, ancora una volta a seconda delle regole del gioco. Immagina di aver giocato Swamp \u2014 questo rimuover\u00e0 Swamp come passo successivo (l'abbiamo gi\u00e0 giocato), cos\u00ec come rimuover\u00e0 Forest (perch\u00e9 secondo le regole si pu\u00f2 giocare una sola carta terra per turno). Dopo di ci\u00f2, l'IA aggiunge come passo successivo - ottenere 1 mana nera, perch\u00e9 non ci sono altre opzioni. Se va avanti e sceglie di Tap the Swamp, ricever\u00e0 1 unit\u00e0 di mana nera e non potr\u00e0 fare nulla con essa.<\/p>\n<p><i>1. Giocare Swamp (risultato: Swamp in gioco)<br \/>\n 1.1 \u00abTappare\u00bb Swamp (risultato: Swamp \u00abtappata\u00bb, +1 unit\u00e0 di mana nera)<br \/>\n Nessuna azione disponibile - FINE<br \/>\n2. Giocare Forest (risultato: Forest in gioco)<\/i><\/p>\n<p>L'elenco delle azioni \u00e8 risultato breve, siamo giunti a un vicolo cieco. Ripetiamo il processo per l'azione successiva. Giocando Forest, sblocchiamo l'azione \u00abottenere 1 mana verde\u00bb, che a sua volta sbloccher\u00e0 la terza azione - evocare Elvish Mystic.<\/p>\n<p><i>1. Giocare Swamp (risultato: Swamp in gioco)<br \/>\n 1.1 \u00abTappare\u00bb Swamp (risultato: Swamp \u00abtappata\u00bb, +1 unit\u00e0 di mana nera)<br \/>\n Nessuna azione disponibile - FINE<br \/>\n2. Giocare Forest (risultato: Forest in gioco)<br \/>\n 2.1 \u00abTappare\u00bb Forest (risultato: Forest \u00abtappata\u00bb, +1 unit\u00e0 di mana verde)<br \/>\n 2.1.1 Evocare Elvish Mystic (risultato: Elvish Mystic in gioco, -1 unit\u00e0 di mana verde)<br \/>\n Nessuna azione disponibile - FINE<\/i><\/p>\n<p>Infine, abbiamo esaminato tutte le azioni possibili e trovato un piano per evocare una creatura.<\/p>\n<p>Questo \u00e8 un esempio molto semplificato. \u00c8 preferibile scegliere il miglior piano possibile, piuttosto che qualsiasi piano che soddisfi alcuni criteri. Di norma, si possono valutare i potenziali piani in base al risultato finale o al guadagno complessivo derivante dalla loro esecuzione. Puoi guadagnare 1 punto per la giocata di una terra e 3 punti per il richiamo di una creatura. Giocare una Swamp sarebbe un piano che fornisce 1 punto. Giocare una Forest \u2192 Tap the Forest \u2192 evocare un Elvish Mystic dar\u00e0 subito 4 punti. <\/p>\n<p>Ecco come funziona la pianificazione in Magic: The Gathering, ma la stessa logica si applica anche in altre situazioni. Per esempio, muovere un pedone per liberare spazio per il movimento di un alfiere negli scacchi. Oppure nascondersi dietro un muro per sparare in sicurezza in XCOM. In generale, hai capito il concetto.<\/p>\n<h3>Pianificazione avanzata<\/h3>\n<p>\nA volte ci sono troppe azioni potenziali per considerare ogni possibile opzione. Ritornando all'esempio di Magic: The Gathering: supponiamo che in gioco tu abbia diverse carte terra e creature in mano; il numero di possibili combinazioni di mosse pu\u00f2 contarsi a decine. Ci sono diverse soluzioni a questo problema.<\/p>\n<p>Il primo metodo \u00e8 il backwards chaining (catena di retrocessione). Invece di esaminare tutte le combinazioni, \u00e8 meglio partire dal risultato finale e cercare di trovare un percorso diretto. Invece di muoversi dalla radice dell'albero a una foglia specifica, ci spostiamo in direzione opposta: dalla foglia alla radice. Questo metodo \u00e8 pi\u00f9 semplice e veloce.<\/p>\n<p>Se l'avversario ha 1 punto vita, puoi trovare un piano \"infliggere 1 o pi\u00f9 danni\". Per ottenere ci\u00f2, \u00e8 necessario soddisfare una serie di condizioni: <\/p>\n<p>1. Il danno pu\u00f2 essere inflitto da un incantesimo \u2014 deve essere in mano.<br \/>\n2. Per lanciare l'incantesimo serve mana.<br \/>\n3. Per ottenere mana \u2014 bisogna giocare una carta terra.<br \/>\n4. Per giocare una carta terra \u2014 bisogna averla in mano.<\/p>\n<p>Un altro metodo \u00e8 il best-first search (cerca il migliore per primo). Invece di esaminare tutte le strade, scegliamo quella pi\u00f9 appropriata. Questo metodo fornisce spesso un piano ottimale senza costi aggiuntivi per la ricerca. L'A* \u00e8 una forma di ricerca del migliore per primo \u2014 esplorando i percorsi pi\u00f9 promettenti fin dall'inizio, pu\u00f2 gi\u00e0 trovare il percorso migliore senza la necessit\u00e0 di esaminare le altre opzioni.<\/p>\n<p>Un'opzione interessante e sempre pi\u00f9 popolare della best-first search \u00e8 la Monte Carlo Tree Search. Invece di indovinare quali piani siano migliori rispetto agli altri nella scelta di ogni successivo passo, l'algoritmo seleziona successori casuali a ogni passo, fino a raggiungere la fine (quando il piano porta a una vittoria o a una sconfitta). Il risultato finale viene utilizzato per aumentare o diminuire la valutazione del 'peso' delle opzioni precedenti. Ripetendo questo processo pi\u00f9 volte, l'algoritmo fornisce una buona valutazione di quale sia il passo successivo migliore, anche se la situazione cambia (se l'avversario prende misure per ostacolare il giocatore). <\/p>\n<p>Nella narrazione sulla pianificazione nei giochi non pu\u00f2 mancare il Goal-Oriented Action Planning o GOAP (pianificazione delle azioni orientate agli obiettivi). Questo \u00e8 un metodo ampiamente utilizzato e discusso, ma a parte alcuni dettagli distintivi, \u00e8 sostanzialmente un metodo di backwards chaining, di cui abbiamo parlato in precedenza. Se l'obiettivo era 'eliminare il giocatore', e il giocatore si trova dietro un riparo, il piano potrebbe essere: lancia una granata \u2192 avvicinati \u2192 lanciala.<\/p>\n<p>Di solito ci sono diversi obiettivi, ognuno con la propria priorit\u00e0. Se l'obiettivo con la priorit\u00e0 pi\u00f9 alta non pu\u00f2 essere raggiunto (nessuna combinazione di azioni crea un piano per 'eliminare il giocatore', perch\u00e9 il giocatore non \u00e8 visibile), l'IA torner\u00e0 agli obiettivi con priorit\u00e0 pi\u00f9 bassa.<\/p>\n<h2>Apprendimento e adattamento<\/h2>\n<p>\nAbbiamo gi\u00e0 detto che l'IA nei giochi di solito non utilizza l'apprendimento automatico, perch\u00e9 non \u00e8 adatta alla gestione degli agenti in tempo reale. Ma ci\u00f2 non significa che non si possano prendere in prestito elementi da questo ambito. Vogliamo un avversario in uno sparatutto dal quale poter imparare qualcosa. Ad esempio, conoscere le migliori posizioni sulla mappa. O un avversario in un picchiaduro che bloccasse le combo frequentemente utilizzate dal giocatore, spingendo a usare altre mosse. Quindi, l'apprendimento automatico in tali situazioni pu\u00f2 essere molto utile.<\/p>\n<h3>Statistiche e probabilit\u00e0<\/h3>\n<p>\nPrima di passare a esempi complessi, vediamo fino a che punto possiamo spingerci, prendendo alcune semplici misurazioni e utilizzandole per prendere decisioni. Ad esempio, la strategia in tempo reale: come possiamo determinare se un giocatore pu\u00f2 iniziare un attacco nei primi minuti del gioco e quale difesa preparare contro questo? Possiamo studiare l'esperienza passata del giocatore per capire quale potrebbe essere la futura reazione. Cominciamo col dire che non abbiamo tali dati di partenza, ma possiamo raccolgiere \u2014 ogni volta che l'IA gioca contro un umano, pu\u00f2 registrare il tempo del primo attacco. Dopo alcune sessioni otterremo un valore medio del tempo in cui il giocatore attaccher\u00e0 in futuro.<\/p>\n<p>Esiste anche un problema con le medie: se un giocatore ha \"rushato\" 20 volte e ha giocato lentamente 20 volte, i valori necessari saranno da qualche parte nel mezzo, e questo non ci dar\u00e0 nulla di utile. Una delle soluzioni \u00e8 limitare i dati in ingresso: possiamo considerare le ultime 20 istanze.<\/p>\n<p>Un approccio simile viene utilizzato nella valutazione della probabilit\u00e0 di determinate azioni, assumendo che le preferenze passate del giocatore siano le stesse nel futuro. Se un giocatore ci attacca cinque volte con una palla di fuoco, due volte con una saetta e una volta in corpo a corpo, \u00e8 evidente che preferisce la palla di fuoco. Estendiamo e vediamo la probabilit\u00e0 di utilizzo di diverse armi: palla di fuoco = 62,5%, saetta = 25% e corpo a corpo = 12,5%. La nostra IA di gioco deve prepararsi a difendersi dal fuoco.<\/p>\n<p>Un altro metodo interessante \u00e8 l'uso del Naive Bayes Classifier (classificatore bayesiano naive) per analizzare grandi volumi di dati in ingresso e classificare la situazione, affinch\u00e9 l'IA reagisca nel modo corretto. I classificatori bayesiani sono noti principalmente per il loro uso nei filtri antispam delle email. Qui esaminano le parole, le confrontano con quelle che sono apparse in precedenza (nello spam o meno) e traggono conclusioni sui messaggi in arrivo. Possiamo fare lo stesso anche con un minor numero di dati in ingresso. Sulla base di tutte le informazioni utili che l'IA osserva (ad esempio, quali unit\u00e0 nemiche sono state create, o quali incantesimi stanno usando, o quali tecnologie hanno ricercato), e il risultato finale (guerra o pace, \"rushare\" o difendersi, ecc.) \u2014 sceglieremo il comportamento appropriato dell'IA.<\/p>\n<p>Tutti questi metodi di apprendimento sono sufficienti, ma \u00e8 preferibile utilizzarli sulla base dei dati ottenuti dai test. L'IA imparer\u00e0 ad adattarsi a diverse strategie utilizzate dai vostri playtester. Un'IA che si adatta al giocatore dopo il rilascio pu\u00f2 diventare troppo prevedibile o, al contrario, troppo difficile da battere.<\/p>\n<h3>Adattamento basato sui valori<\/h3>\n<p>\nConsiderando il contenuto del nostro mondo di gioco e delle regole, possiamo modificare l'insieme di valori che influenzano le decisioni, anzich\u00e9 utilizzare semplicemente i dati in ingresso. Procediamo cos\u00ec:<\/p>\n<ul>\n<li>Lasciamo che l'IA raccolga dati sulla situazione del mondo e sugli eventi chiave durante il gioco (come indicato sopra).<\/li>\n<li>Modificheremo alcuni valori importanti sulla base di questi dati.<\/li>\n<li>Implementiamo le nostre decisioni basate sull'elaborazione o sulla valutazione di questi valori.<\/li>\n<\/ul>\n<p>\nAd esempio, un agente ha diverse stanze tra cui scegliere in una mappa di uno sparatutto in prima persona. Ogni stanza ha un proprio valore che determina quanto sia desiderabile visitarla. L'IA sceglie casualmente quale stanza esplorare, basandosi sul valore. Poi l'agente ricorda in quale stanza \u00e8 stato ucciso e riduce il valore di quella stanza (la probabilit\u00e0 che vi ritorni). Analogamente, se l'agente distrugge molti nemici, il valore della stanza aumenta.<\/p>\n<h3>Modello di Markov<\/h3>\n<p>\nE se utilizzassimo i dati raccolti per fare previsioni? Se memorizziamo ogni stanza in cui vediamo il giocatore per un certo periodo di tempo, potremmo anticipare in quale stanza potrebbe spostarsi. Monitorando e registrando i movimenti del giocatore tra le stanze (valori), possiamo prevederli.<\/p>\n<p>Consideriamo tre stanze: rossa, verde e blu. E anche le osservazioni che abbiamo registrato durante la visione della sessione di gioco:<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/6e90a365b72a176c36c9a14213baaafc.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nIl numero di osservazioni in ogni stanza \u00e8 quasi uguale \u2014 dobbiamo ancora determinare dove creare un buon punto di imboscata. La raccolta delle statistiche \u00e8 ulteriormente complicata dal respawn dei giocatori, che si presenta uniformemente su tutta la mappa. Ma i dati sulla stanza successiva in cui entrano dopo il respawn sulla mappa sono gi\u00e0 utili.<\/p>\n<p>\u00c8 evidente che la stanza verde soddisfa i giocatori: la maggior parte delle persone dalla stanza rossa si trasferisce l\u00ec, il 50% delle quali rimane poi l\u00ec. Al contrario, la stanza blu non gode di popolarit\u00e0, quasi nessuno ci entra, e se lo fa, non si ferma. <\/p>\n<p>Ma i dati ci dicono qualcosa di pi\u00f9 importante: quando un giocatore si trova nella stanza blu, la stanza successiva in cui probabilmente lo vedremo sar\u00e0 rossa, e non verde. Nonostante la stanza verde sia pi\u00f9 popolare di quella rossa, la situazione cambia se il giocatore si trova nella blu. Il prossimo stato (cio\u00e8 la stanza in cui il giocatore si trasferir\u00e0) dipende dallo stato precedente (cio\u00e8 dalla stanza in cui si trova attualmente il giocatore). A causa dello studio delle dipendenze, faremo previsioni pi\u00f9 accurate rispetto a se semplicemente conteggiassimo le osservazioni in modo indipendente l'una dall'altra.<\/p>\n<p>Prevedere il futuro stato basandosi sui dati dello stato passato \u00e8 chiamato modello di Markov (Markov model), e tali esempi (con le stanze) vengono chiamati catene di Markov. Poich\u00e9 i modelli rappresentano la probabilit\u00e0 di cambiamenti tra stati successivi, vengono visualizzati come un FSM con la probabilit\u00e0 associata a ciascun passaggio. In precedenza, abbiamo usato FSM per rappresentare lo stato comportamentale in cui si trovava l'agente, ma questo concetto si estende a qualsiasi stato, indipendentemente dal fatto che sia collegato all'agente o meno. In questo caso, gli stati rappresentano la stanza occupata dall'agente:<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/edb32dff7a3298b19c3fa4d66f48e9f4.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nQuesto \u00e8 un semplice modo per rappresentare la probabilit\u00e0 relativa dei cambiamenti di stato, offrendo all'IA una certa possibilit\u00e0 di prevedere il prossimo stato. \u00c8 possibile prevedere diversi passi in avanti.<\/p>\n<p>Se il giocatore \u00e8 nella stanza verde, c'\u00e8 il 50% di probabilit\u00e0 che rimanga l\u00ec al prossimo rilevamento. Ma qual \u00e8 la probabilit\u00e0 che lui sia ancora l\u00ec anche dopo? Non c'\u00e8 solo la possibilit\u00e0 che il giocatore sia rimasto nella stanza verde dopo due rilevamenti, ma anche che sia andato via e poi tornato. Ecco una nuova tabella che tiene conto dei nuovi dati:<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/f87afff68b066a879661e37f68654ae2.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nDa essa si evince che la probabilit\u00e0 di vedere il giocatore nella stanza verde dopo due osservazioni sar\u00e0 del 51%: il 21% che provenga dalla stanza rossa, il 5% che il giocatore visiti la stanza blu nel mezzo, e il 25% che il giocatore non si sposti affatto dalla stanza verde.<\/p>\n<p>La tabella \u00e8 semplicemente uno strumento visivo; la procedura richiede solo la moltiplicazione delle probabilit\u00e0 in ogni passaggio. Questo significa che puoi guardare lontano nel futuro con una sola precisazione: presumiamo che la possibilit\u00e0 di entrare in una stanza dipenda interamente dalla stanza attuale. Questo \u00e8 noto come propriet\u00e0 di Markov (Markov Property): lo stato futuro dipende solo dal presente. Ma non \u00e8 garantito al 100%. I giocatori possono cambiare decisioni a seconda di altri fattori: livello di salute o numero di munizioni. Poich\u00e9 non fissiamo questi valori, le nostre previsioni saranno meno accurate.<\/p>\n<h3>N-Grams<\/h3>\n<p>\nE per quanto riguarda l'esempio del fighting e della previsione delle combo del giocatore? \u00c8 lo stesso! Ma invece di uno stato o di un evento singolo, esploreremo intere sequenze che compongono il colpo combo.<\/p>\n<p>Uno dei modi per farlo \u00e8 mantenere ogni input (ad esempio, Calcio, Pugno o Blocco) in un buffer e registrare l'intero buffer come un evento. Quindi, se il giocatore preme ripetutamente Calcio, Calcio, Pugno per utilizzare l'attacco SuperDeathFist, il sistema IA memorizza tutti gli input nel buffer e ricorda gli ultimi tre usati in ogni passaggio.<\/p>\n<p><img decoding=\"async\" alt=\"Come creare un&#039;IA di gioco: guida per principianti\" src=\"\/wp-content\/uploads\/2019\/11\/9a95226ae155dca5e45a66d4440f3cd4.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n(In grassetto sono evidenziate le righe quando il giocatore lancia l'attacco SuperDeathFist.)<\/p>\n<p>L'IA vedr\u00e0 tutte le possibilit\u00e0 quando il giocatore sceglie Calcio, seguito da un altro Calcio, per poi notare che il prossimo input \u00e8 sempre Pugno. Questo consentir\u00e0 all'agente di prevedere la combo SuperDeathFist e bloccarla se possibile.<\/p>\n<p>Queste sequenze di eventi sono chiamate N-grammi (N-grams), dove N \u00e8 il numero di elementi memorizzati. Nell'esempio precedente era un trigramma (3-gram), il che significa: i primi due registrazioni sono utilizzate per prevedere la terza. Di conseguenza, in un 5-grammo, le prime quattro registrazioni prevedono la quinta, e cos\u00ec via.<\/p>\n<p>Lo sviluppatore deve scegliere con attenzione la dimensione degli N-grammi. Un numero minore di N richiede meno memoria, ma conserva anche una storia minore. Ad esempio, un bigramma (2-gram) registrerebbe Calcio, Calcio o Calcio, Pugno, ma non potrebbe memorizzare Calcio, Calcio, Pugno, quindi l'IA non reagirebbe alla combo SuperDeathFist.<\/p>\n<p>D'altra parte, numeri maggiori richiedono pi\u00f9 memoria e sar\u00e0 pi\u00f9 difficile per l'IA apprendere, poich\u00e9 ci saranno molte pi\u00f9 possibilit\u00e0. Se hai tre possibili input: Calcio, Pugno o Blocco, e utilizziamo un 10-grammo, avremo circa 60.000 varianti diverse.<\/p>\n<p>Il modello di bigramma \u00e8 una semplice catena di Markov: ogni coppia \"stato passato\/stato attuale\" \u00e8 un bigramma e puoi prevedere il secondo stato sulla base del primo. Le 3-grammi e le N-grammi pi\u00f9 grandi possono anche essere considerate catene di Markov, dove tutti gli elementi (tranne l'ultimo nella N-gramma) insieme formano il primo stato, e l'ultimo elemento \u00e8 il secondo. Un esempio con il combattimento mostra la probabilit\u00e0 di transizione dallo stato Calcio e Calcio allo stato Calcio e Pugno. Considerando pi\u00f9 registrazioni della storia di ingresso come un'unica unit\u00e0, in sostanza, trasformiamo la sequenza di ingresso in parte di uno stato intero. Questo ci fornisce la propriet\u00e0 markoviana, permettendo di utilizzare catene di Markov per prevedere il prossimo input e indovinare quale mossa combinata sar\u00e0 la prossima.<\/p>\n<h2>Conclusione<\/h2>\n<p>\nAbbiamo discusso degli strumenti e degli approcci pi\u00f9 diffusi nello sviluppo dell'intelligenza artificiale. Inoltre, abbiamo analizzato le situazioni in cui \u00e8 necessario applicarli e dove sono particolarmente utili. <\/p>\n<p>Questo dovrebbe essere sufficiente per comprendere le basi dell'IA nei giochi. Ma, naturalmente, non esaurisce tutti i metodi. Tra quelli meno popolari, ma comunque efficaci, ci sono:<\/p>\n<ul>\n<li>algoritmi di ottimizzazione, tra cui l'ascensione collinare, il gradiente discendente e gli algoritmi genetici<\/li>\n<li>algoritmi competitivi di ricerca\/pianificazione (minimax e potatura alpha-beta)<\/li>\n<li>metodi di classificazione (percettroni, reti neurali e macchine a vettori di supporto)<\/li>\n<li>sistemi per l'elaborazione della percezione e della memoria degli agenti<\/li>\n<li>approcci architettonici all'IA (sistemi ibridi, sottoinsieme di architetture e altri modi di sovrapporre i sistemi di IA)<\/li>\n<li>strumenti di animazione (pianificazione e coordinamento del movimento)<\/li>\n<li>fattori di prestazione (livello di dettaglio, algoritmi anytime e timeslicing)<\/li>\n<\/ul>\n<p>\nRisorse online sull'argomento:<\/p>\n<p>1. Su GameDev.net c'\u00e8 <noindex><a rel=\"nofollow\" href=\"https:\/\/www.gamedev.net\/articles\/programming\/artificial-intelligence\/\">una sezione con articoli e tutorial sull'IA<\/a><\/noindex>, e inoltre <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> contiene numerose presentazioni e articoli su un'ampia gamma di argomenti legati allo sviluppo dell'IA nei giochi.<br \/>\n3. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.gdcvault.com\/\">Il GDC Vault<\/a><\/noindex> include argomenti dal summit GDC AI, molti dei quali sono disponibili gratuitamente.<br \/>\n4. Materiali utili possono anche essere trovati sul sito <noindex><a rel=\"nofollow\" href=\"http:\/\/gameai.com\/\">AI Game Programmers Guild<\/a><\/noindex>.<br \/>\n5. Tommy Thompson, ricercatore di IA e sviluppatore di giochi, realizza video sul canale YouTube <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/user\/tthompso\">AI and Games<\/a><\/noindex> con spiegazioni e approfondimenti sull'IA nei giochi commerciali.<\/p>\n<p>Libri sull'argomento:<\/p>\n<p>1. La serie di libri Game AI Pro \u00e8 una raccolta di articoli brevi che spiegano come implementare funzionalit\u00e0 specifiche o come risolvere problemi particolari.<\/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: Saggezza Raccolta dai Professionisti dell'AI nei Giochi<\/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: Saggezza Raccolta dai Professionisti dell'AI nei Giochi<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/amzn.to\/2KF4irS\">Game AI Pro 3: Saggezza Raccolta dai Professionisti dell'AI nei Giochi<\/a><\/noindex><\/p>\n<p>2. La serie AI Game Programming Wisdom \u00e8 il predecessore della serie Game AI Pro. Contiene metodi pi\u00f9 datati, ma quasi tutti sono ancora rilevanti oggi.<\/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\">Intelligenza Artificiale: Un Approccio Moderno<\/a><\/noindex> \u2014 \u00e8 uno dei testi fondamentali per chiunque voglia capire il campo dell'intelligenza artificiale. Non \u00e8 un libro sulla sviluppo di giochi \u2014 insegna le basi dell'IA.<br \/>\n<br \/>Fonte: <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.1.1 - 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\/it\/blog\/news\/kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\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\/it\/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\udd47Come creare un'IA di gioco: guida per principianti | ProHoster","description":"Ho trovato un materiale interessante su.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/news\/kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","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\/it\/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\/it\/wp-json\/wp\/v2\/posts\/52118","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=52118"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/52118\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=52118"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=52118"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=52118"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}