{"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\/fr\/blog\/news\/kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih","title":{"rendered":"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/9e57175b233a104e0df98383b374eded.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nJe suis tomb\u00e9 sur un article int\u00e9ressant sur l'intelligence artificielle dans les jeux. Il explique les concepts de base sur l'IA \u00e0 travers des exemples simples, et contient \u00e9galement de nombreux outils et m\u00e9thodes utiles pour son d\u00e9veloppement et sa conception. Il y a des conseils sur comment, o\u00f9 et quand les utiliser.<\/p>\n<p>La plupart des exemples sont \u00e9crits en pseudocode, donc des connaissances approfondies en programmation ne seront pas n\u00e9cessaires. Il y a 35 pages de texte avec des images et des GIF, alors pr\u00e9parez-vous.<\/p>\n<p>UPD. Je m'excuse, mais j'ai d\u00e9j\u00e0 fait ma propre traduction de cet article sur Habr. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/users\/PatientZero\/\">PatientZero<\/a><\/noindex>. Vous pouvez lire ma version <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/post\/420219\/\">ici<\/a><\/noindex>, mais il semble que cet article m'ait \u00e9chapp\u00e9 (j'ai utilis\u00e9 la recherche, mais quelque chose a mal tourn\u00e9). Comme j'\u00e9cris dans un blog d\u00e9di\u00e9 au d\u00e9veloppement de jeux, j'ai d\u00e9cid\u00e9 de laisser ma version de la traduction pour mes abonn\u00e9s (certains points sont pr\u00e9sent\u00e9s diff\u00e9remment, d'autres sont intentionnellement omis sur les conseils des d\u00e9veloppeurs).<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Qu'est-ce que l'IA ?<\/h2>\n<p>\nL'IA de jeu se concentre sur les actions qu'un objet doit effectuer en fonction des conditions dans lesquelles il se trouve. Cela s'appelle g\u00e9n\u00e9ralement la gestion des \u00ab agents intelligents \u00bb, o\u00f9 l'agent peut \u00eatre un personnage de jeu, un v\u00e9hicule, un bot, et parfois quelque chose de plus abstrait : un groupe entier d'entit\u00e9s ou m\u00eame une civilisation. Dans chaque cas, c'est un \u00e9l\u00e9ment qui doit percevoir son environnement, prendre des d\u00e9cisions bas\u00e9es sur cela et agir en cons\u00e9quence. Cela s'appelle le cycle Sense\/Think\/Act (Percevoir\/Penser\/Agir) :<\/p>\n<ul>\n<li>Sense : l'agent trouve ou re\u00e7oit des informations sur des \u00e9l\u00e9ments dans son environnement qui peuvent influencer son comportement (menaces \u00e0 proximit\u00e9, objets \u00e0 collecter, lieux int\u00e9ressants \u00e0 explorer).<\/li>\n<li>Think : l'agent d\u00e9cide comment r\u00e9agir (il \u00e9value s'il est suffisamment en s\u00e9curit\u00e9 pour collecter des objets ou s'il doit d'abord se battre\/se cacher).<\/li>\n<li>Act : l'agent effectue des actions pour mettre en \u0153uvre la d\u00e9cision pr\u00e9c\u00e9dente (il commence \u00e0 se d\u00e9placer vers l'ennemi ou l'objet).<\/li>\n<li>\u2026la situation a maintenant chang\u00e9 en raison des actions des personnages, donc le cycle se r\u00e9p\u00e8te avec de nouvelles donn\u00e9es.<\/li>\n<\/ul>\n<p>\nL'IA se concentre g\u00e9n\u00e9ralement sur la partie Sense du cycle. Par exemple, les voitures autonomes prennent des images de la route, les combinent avec des donn\u00e9es radar et lidar, et les interpr\u00e8tent. Cela est g\u00e9n\u00e9ralement fait par l'apprentissage automatique, qui traite les donn\u00e9es entrantes et leur donne un sens, en extrayant des informations s\u00e9mantiques comme \u00ab il y a une autre voiture \u00e0 20 m\u00e8tres devant vous \u00bb. Ce sont ce qu'on appelle des probl\u00e8mes de classification.<\/p>\n<p>Les jeux n'ont pas besoin d'un syst\u00e8me complexe pour extraire des informations, car la plupart des donn\u00e9es en font d\u00e9j\u00e0 partie int\u00e9grante. Il n'est pas n\u00e9cessaire d'ex\u00e9cuter des algorithmes de reconnaissance d'image pour d\u00e9terminer s'il y a un ennemi devant \u2014 le jeu le sait d\u00e9j\u00e0 et transmet les informations directement pendant le processus de prise de d\u00e9cision. Par cons\u00e9quent, la partie Sense du cycle est souvent beaucoup plus simple que Think et Act.<\/p>\n<h2>Les limitations de l'IA dans les jeux vid\u00e9o<\/h2>\n<p>\nL'IA doit respecter un certain nombre de limitations :<\/p>\n<ul>\n<li>L'IA n'a pas besoin d'\u00eatre pr\u00e9alablement entra\u00een\u00e9e, comme un algorithme d'apprentissage automatique. Il est inutile d'\u00e9crire un r\u00e9seau neuronal pendant le d\u00e9veloppement pour observer des dizaines de milliers de joueurs et apprendre la meilleure fa\u00e7on de jouer contre eux. Pourquoi ? Parce que le jeu n'est pas encore sorti et qu'il n'y a pas de joueurs.<\/li>\n<li>Le jeu doit divertir et repr\u00e9senter un d\u00e9fi, donc les agents ne doivent pas trouver la meilleure approche contre les humains.<\/li>\n<li>Les agents doivent avoir l'air r\u00e9alistes pour que les joueurs aient l'impression de jouer contre de vraies personnes. Le programme AlphaGo a d\u00e9pass\u00e9 l'humain, mais les mouvements choisis \u00e9taient tr\u00e8s \u00e9loign\u00e9s de la compr\u00e9hension traditionnelle du jeu. Si le jeu imite un adversaire humain, cette impression ne doit pas exister. L'algorithme doit \u00eatre modifi\u00e9 pour qu'il prenne des d\u00e9cisions plausibles, et non parfaites.<\/li>\n<li>L'IA doit fonctionner en temps r\u00e9el. Cela signifie que l'algorithme ne peut pas monopoliser l'utilisation du processeur pendant trop longtemps pour prendre des d\u00e9cisions. M\u00eame 10 millisecondes pour cela \u2014 c'est trop long, car la plupart des jeux se contentent de 16 \u00e0 33 millisecondes pour effectuer tout le traitement et passer au cadre graphique suivant.<\/li>\n<li>Id\u00e9alement, au moins une partie du syst\u00e8me doit \u00eatre g\u00e9r\u00e9e par des donn\u00e9es, afin que les \u00ab non-codeurs \u00bb puissent apporter des modifications et que les ajustements se fassent plus rapidement.<\/li>\n<\/ul>\n<p>\nExaminons les approches de l'IA qui couvrent l'ensemble du cycle Sense\/Think\/Act.<\/p>\n<h3>Prise de d\u00e9cisions de base<\/h3>\n<p>\nCommen\u00e7ons par le jeu le plus simple \u2014 Pong. Objectif : d\u00e9placer la plateforme (paddle) pour que la balle rebondisse dessus, au lieu de passer \u00e0 c\u00f4t\u00e9. C'est comme le tennis, o\u00f9 vous perdez si vous ne renvoyez pas la balle. Ici, l'IA a une t\u00e2che relativement facile \u2014 d\u00e9cider dans quelle direction d\u00e9placer la plateforme.<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/e1935d657b9f090bf60c365c21e8f92b.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3>Op\u00e9rateurs conditionnels<\/h3>\n<p>\nPour l'IA dans Pong, la solution la plus \u00e9vidente est de toujours tenter de positionner la plateforme sous la balle.<\/p>\n<p>Voici un algorithme simple pour cela, \u00e9crit en pseudo-code :<\/p>\n<p><i>chaque trame\/mise \u00e0 jour pendant que le jeu est en cours :<br \/>\nsi la balle est \u00e0 gauche de la plateforme :<br \/>\n d\u00e9placer la plateforme \u00e0 gauche<br \/>\nsinon si la balle est \u00e0 droite de la plateforme :<br \/>\n d\u00e9placer la plateforme \u00e0 droite<\/i><\/p>\n<p>Si la plateforme se d\u00e9place \u00e0 la vitesse de la balle, c'est l'algorithme id\u00e9al pour l'IA dans Pong. Il n'est pas n\u00e9cessaire de compliquer les choses si les donn\u00e9es et les actions possibles pour l'agent ne sont pas si nombreuses.<\/p>\n<p>Cette approche est si simple que tout le cycle Sense\/Think\/Act est \u00e0 peine perceptible. Mais il est pr\u00e9sent :<\/p>\n<ul>\n<li>La partie Sense se trouve dans les deux op\u00e9rateurs if. Le jeu sait o\u00f9 est la balle et o\u00f9 est la plateforme, donc l'IA s'y r\u00e9f\u00e8re pour obtenir ces informations. <\/li>\n<li>La partie Think entre \u00e9galement dans les deux op\u00e9rateurs if. Ils incarnent deux solutions qui, dans ce cas, sont mutuellement exclusives. En cons\u00e9quence, une des trois actions est choisie \u2014 d\u00e9placer la plateforme \u00e0 gauche, d\u00e9placer \u00e0 droite, ou ne rien faire si elle est d\u00e9j\u00e0 positionn\u00e9e correctement.<\/li>\n<li>La partie Act se trouve dans les op\u00e9rateurs Move Paddle Left et Move Paddle Right. En fonction du design du jeu, ils peuvent d\u00e9placer la plateforme instantan\u00e9ment ou \u00e0 une certaine vitesse. <\/li>\n<\/ul>\n<p>\nCes approches sont appel\u00e9es r\u00e9actives \u2014 il y a un ensemble simple de r\u00e8gles (dans ce cas, des op\u00e9rateurs if dans le code) qui r\u00e9agissent \u00e0 l'\u00e9tat actuel du monde et agissent.<\/p>\n<h3>Arbre de d\u00e9cision<\/h3>\n<p>\nL'exemple du jeu Pong \u00e9quivaut en fait \u00e0 une conception formelle de l'IA, qui est appel\u00e9e arbre de d\u00e9cision. L'algorithme le parcourt pour atteindre une \u00ab feuille \u00bb \u2014 une d\u00e9cision sur quelle action entreprendre.<\/p>\n<p>Cr\u00e9ons un diagramme de l'arbre de d\u00e9cision pour l'algorithme de notre plateforme :<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/d3b7290ba93144967cd849416cd5eef3.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nChaque partie de l'arbre s'appelle un node (n\u0153ud) \u2014 l'IA utilise la th\u00e9orie des graphes pour d\u00e9crire de telles structures. Il existe deux types de n\u0153uds :<\/p>\n<ul>\n<li>N\u0153uds de d\u00e9cision : choix entre deux alternatives bas\u00e9 sur la v\u00e9rification d'une certaine condition, o\u00f9 chaque alternative est repr\u00e9sent\u00e9e sous forme de n\u0153ud distinct.<\/li>\n<li>N\u0153uds finaux : action \u00e0 ex\u00e9cuter, repr\u00e9sentant la d\u00e9cision finale.<\/li>\n<\/ul>\n<p>\nL'algorithme commence par le premier n\u0153ud (\u00ab racine \u00bb de l'arbre). Il prend soit la d\u00e9cision de passer \u00e0 un n\u0153ud enfant, soit ex\u00e9cute une action stock\u00e9e dans le n\u0153ud et se termine.<\/p>\n<p>Quel est l'avantage, si les arbres de d\u00e9cision font le m\u00eame travail que les op\u00e9rateurs if dans la section pr\u00e9c\u00e9dente ? Il existe ici un syst\u00e8me g\u00e9n\u00e9ral o\u00f9 chaque d\u00e9cision a une seule condition et deux r\u00e9sultats possibles. Cela permet au d\u00e9veloppeur de cr\u00e9er une IA \u00e0 partir de donn\u00e9es repr\u00e9sentant des d\u00e9cisions dans l'arbre, \u00e9vitant ainsi son hardcoding. Repr\u00e9sentons cela sous forme de tableau :<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/6875293a60ff9d0efa26fb5e1aa4b21c.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDu c\u00f4t\u00e9 du code, vous obtiendrez un syst\u00e8me pour lire des lignes. Cr\u00e9ez un n\u0153ud pour chacune d'elles, connectez la logique de prise de d\u00e9cision bas\u00e9e sur la deuxi\u00e8me colonne et des n\u0153uds enfants bas\u00e9s sur les troisi\u00e8me et quatri\u00e8me colonnes. Vous devez encore programmer les conditions et les actions, mais maintenant la structure du jeu sera plus complexe. Vous ajouterez des d\u00e9cisions et des actions suppl\u00e9mentaires, puis configurerez toute l'IA simplement en modifiant un fichier texte d\u00e9finissant l'arbre. Vous transmettrez ensuite le fichier au concepteur de jeux, qui pourra modifier le comportement sans recompilation du jeu ni modification du code.<\/p>\n<p>Les arbres de d\u00e9cision sont tr\u00e8s utiles lorsqu'ils sont construits automatiquement sur la base d'un grand ensemble d'exemples (par exemple, en utilisant l'algorithme ID3). Cela en fait un outil efficace et performant pour classifier des situations sur la base des donn\u00e9es obtenues. Cependant, nous d\u00e9passons le simple syst\u00e8me de choix d'actions par les agents.<\/p>\n<h3>Sc\u00e9narios<\/h3>\n<p>\nNous avons examin\u00e9 le syst\u00e8me d'arbre de d\u00e9cision qui utilisait des conditions et des actions pr\u00e9d\u00e9finies. La personne qui con\u00e7oit l'IA peut organiser l'arbre comme elle le souhaite, mais elle doit encore compter sur le codeur qui l\u2019a programm\u00e9e. Que se passerait-il si nous pouvions donner au designer des outils pour cr\u00e9er ses propres conditions ou actions ?<\/p>\n<p>Pour qu'un programmeur n'ait pas \u00e0 \u00e9crire de code pour les conditions Is Ball Left Of Paddle et Is Ball Right Of Paddle, il peut cr\u00e9er un syst\u00e8me dans lequel le designer enregistrera les conditions pour v\u00e9rifier ces valeurs. Les donn\u00e9es de l'arbre de d\u00e9cision ressembleront alors \u00e0 ceci :<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/8e77f7c3410d097e8b7d8e1209355cc6.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEn r\u00e9alit\u00e9, c'est la m\u00eame chose que dans le premier tableau, mais les solutions elles-m\u00eames ont leur propre code qui ressemble un peu \u00e0 la partie conditionnelle d'un op\u00e9rateur if. Dans le code, cela serait identifi\u00e9 dans la deuxi\u00e8me colonne pour les n\u0153uds de prise de d\u00e9cision, mais au lieu de rechercher une condition sp\u00e9cifique \u00e0 ex\u00e9cuter (Is Ball Left Of Paddle), il \u00e9value l'expression conditionnelle et renvoie true ou false en cons\u00e9quence. Cela est r\u00e9alis\u00e9 avec des langages de script comme Lua ou Angelscript. Avec eux, le d\u00e9veloppeur peut prendre des objets dans son jeu (ball et paddle) et cr\u00e9er des variables qui seront disponibles dans le sc\u00e9nario (ball.position). En outre, le langage de script est plus simple que le C++. Il ne n\u00e9cessite pas une \u00e9tape de compilation compl\u00e8te, ce qui le rend id\u00e9al pour un ajustement rapide de la logique de jeu et permet aux \u00ab non-programmeurs \u00bb de cr\u00e9er eux-m\u00eames les fonctions n\u00e9cessaires.<\/p>\n<p>Dans l'exemple ci-dessus, le langage de script est utilis\u00e9 uniquement pour \u00e9valuer une expression conditionnelle, mais il peut \u00e9galement \u00eatre utilis\u00e9 pour des actions. Par exemple, Move Paddle Right peut devenir un op\u00e9rateur de script (ball.position.x += 10). Ainsi, l'action peut \u00e9galement \u00eatre d\u00e9termin\u00e9e dans le script, sans avoir besoin de programmer Move Paddle Right.<\/p>\n<p>On peut aller encore plus loin et \u00e9crire compl\u00e8tement un arbre de d\u00e9cision dans un langage de script. Cela serait du code sous forme d'op\u00e9rateurs conditionnels hardcod\u00e9s, mais ils seraient dans des fichiers de script externes, ce qui signifie qu'ils peuvent \u00eatre modifi\u00e9s sans recompiler l'ensemble du programme. Souvent, il est possible de changer le fichier de script pendant que le jeu est en cours, pour tester rapidement diff\u00e9rentes r\u00e9actions de l'IA.<\/p>\n<h3>R\u00e9agir aux \u00e9v\u00e9nements<\/h3>\n<p>\nLes exemples ci-dessus conviennent parfaitement \u00e0 Pong. Ils ex\u00e9cutent en continu un cycle Sense\/Think\/Act et agissent en fonction du dernier \u00e9tat du monde. Mais dans des jeux plus complexes, il faut r\u00e9agir \u00e0 des \u00e9v\u00e9nements particuliers, et non \u00e9valuer tout en m\u00eame temps. Pong n'est donc plus un bon exemple. Choisissons un autre. <\/p>\n<p>Imaginez un shooter o\u00f9 les ennemis sont immobiles jusqu'\u00e0 ce qu'ils d\u00e9tectent le joueur, apr\u00e8s quoi ils agissent en fonction de leur \u00ab sp\u00e9cialisation \u00bb : certains vont foncer, tandis que d'autres attaqueront \u00e0 distance. C'est toujours un syst\u00e8me r\u00e9actif de base \u2014 \u00ab si le joueur est vu, alors fais quelque chose \u00bb \u2014 mais il peut \u00eatre logiquement divis\u00e9 en un \u00e9v\u00e9nement Player Seen (joueur vu) et une r\u00e9action (choisissez une r\u00e9ponse et ex\u00e9cutez-la).<\/p>\n<p>Cela nous ram\u00e8ne au cycle Sense\/Think\/Act. Nous pouvons coder la partie Sense, qui v\u00e9rifiera \u00e0 chaque image si l'IA voit le joueur. S'il ne le voit pas, rien ne se passe, mais s'il le voit, un \u00e9v\u00e9nement Player Seen est cr\u00e9\u00e9. Le code aura une section distincte qui indiquera : \u00ab lorsque l'\u00e9v\u00e9nement Player Seen se produit, fais \u00bb, o\u00f9  est la r\u00e9ponse dont vous avez besoin pour appeler les parties Think et Act. Ainsi, vous configurerez les r\u00e9actions \u00e0 l'\u00e9v\u00e9nement Player Seen : pour un personnage \u00ab rushant \u00bb \u2014 ChargeAndAttack, et pour un tireur d'\u00e9lite \u2014 HideAndSnipe. Ces liaisons peuvent \u00eatre cr\u00e9\u00e9es dans un fichier de donn\u00e9es pour une \u00e9dition rapide, sans avoir \u00e0 recompilation. Et ici aussi, nous pouvons utiliser un langage de script.<\/p>\n<h2>Prendre des d\u00e9cisions complexes<\/h2>\n<p>\nBien que les syst\u00e8mes de r\u00e9action simples soient tr\u00e8s efficaces, il existe de nombreuses situations o\u00f9 ils ne suffisent pas. Parfois, il est n\u00e9cessaire de prendre diff\u00e9rentes d\u00e9cisions en fonction de ce que fait l'agent \u00e0 ce moment pr\u00e9cis, mais repr\u00e9senter cela en tant que condition est difficile. Il existe parfois trop de conditions pour les repr\u00e9senter efficacement dans un arbre de d\u00e9cision ou un script. Parfois, il est n\u00e9cessaire d'\u00e9valuer \u00e0 l'avance comment la situation va \u00e9voluer avant de prendre une d\u00e9cision sur la prochaine \u00e9tape. Pour r\u00e9soudre ces probl\u00e8mes, des approches plus complexes sont n\u00e9cessaires.<\/p>\n<h3>Machine \u00e0 \u00e9tats finis<\/h3>\n<p>\nUne machine \u00e0 \u00e9tats finis ou FSM (finite state machine) est un moyen de dire que notre agent se trouve actuellement dans l'un de plusieurs \u00e9tats possibles et qu'il peut passer d'un \u00e9tat \u00e0 un autre. Ces \u00e9tats sont au nombre d\u00e9termin\u00e9 \u2014 d'o\u00f9 le nom. Le meilleur exemple de la vie quotidienne est le feu de circulation. Dans diff\u00e9rents endroits, il y a diff\u00e9rentes s\u00e9quences de lumi\u00e8res, mais le principe est le m\u00eame \u2014 chaque \u00e9tat repr\u00e9sente quelque chose (arr\u00eatez, allez, etc.). Un feu de circulation est toujours dans un seul \u00e9tat \u00e0 tout moment et passe d'un \u00e9tat \u00e0 un autre sur la base de r\u00e8gles simples.<\/p>\n<p>Avec les NPC dans les jeux, c'est une histoire similaire. Prenons par exemple un garde avec les \u00e9tats suivants :<\/p>\n<ul>\n<li>Patrouillant (Patrolling).<\/li>\n<li>Attaquant (Attacking).<\/li>\n<li>Fuyant (Fleeing).<\/li>\n<\/ul>\n<p>\nEt avec ces conditions pour changer son \u00e9tat :<\/p>\n<ul>\n<li>Si le garde voit un ennemi, il attaque.<\/li>\n<li>Si le garde attaque, mais ne voit plus l'ennemi, il revient \u00e0 sa patrouille.<\/li>\n<li>Si le garde attaque, mais est gravement bless\u00e9, il s'enfuit.<\/li>\n<\/ul>\n<p>\nVous pouvez \u00e9galement \u00e9crire des op\u00e9rateurs if avec une variable d'\u00e9tat pour la sentinelle et diverses v\u00e9rifications : y a-t-il un ennemi \u00e0 proximit\u00e9, quel est le niveau de sant\u00e9 du PNJ, etc. Ajoutons encore quelques \u00e9tats.<\/p>\n<ul>\n<li>Inactivit\u00e9 (Idling) \u2014 entre les patrouilles.<\/li>\n<li>Recherche (Searching) \u2014 lorsque l'ennemi aper\u00e7u s'est cach\u00e9.<\/li>\n<li>Demander de l'aide (Finding Help) \u2014 lorsqu'un ennemi est aper\u00e7u mais trop fort pour \u00eatre combattu seul.<\/li>\n<\/ul>\n<p>\nLes choix pour chacun d'eux sont limit\u00e9s \u2014 par exemple, la sentinelle n'ira pas chercher un ennemi cach\u00e9 si sa sant\u00e9 est basse.<\/p>\n<p>En fin de compte, une longue liste &laquo; si &lt;x \u0438 y, \u043d\u043e \u043d\u0435 z&gt;, alors &lt;p&gt;&raquo; peut devenir trop encombrante. Il est donc n&eacute;cessaire de formaliser une m&eacute;thode qui nous permette de garder &agrave; l&#039;esprit les &eacute;tats et les transitions entre ces &eacute;tats. Pour ce faire, prenons en compte tous les &eacute;tats et, sous chaque &eacute;tat, notons dans une liste toutes les transitions vers d&#039;autres &eacute;tats, ainsi que les conditions n&eacute;cessaires pour celles-ci.<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/ba4c401aa20de3d22d2478cba5a4b1ec.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nVoici un tableau des transitions d'\u00e9tats \u2014 une mani\u00e8re complexe de repr\u00e9senter un FSM. Dessinons un diagramme pour obtenir un aper\u00e7u complet de l'\u00e9volution du comportement des PNJ.<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/b4182359983cf573872dacc575af13dc.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLe diagramme refl\u00e8te l'essence de la prise de d\u00e9cision pour cet agent en fonction de la situation actuelle. Chaque fl\u00e8che montre la transition entre les \u00e9tats, si la condition \u00e0 c\u00f4t\u00e9 d'elle est vraie.<\/p>\n<p>\u00c0 chaque mise \u00e0 jour, nous v\u00e9rifions l'\u00e9tat actuel de l'agent, consultons la liste des transitions, et si les conditions pour une transition sont remplies, il adopte un nouvel \u00e9tat. Par exemple, \u00e0 chaque image, nous v\u00e9rifions si le chronom\u00e8tre de 10 secondes a expir\u00e9, et si oui, alors de l'\u00e9tat Idling, la sentinelle passe \u00e0 l'\u00e9tat Patrolling. De la m\u00eame mani\u00e8re, l'\u00e9tat Attacking v\u00e9rifie la sant\u00e9 de l'agent \u2014 si elle est basse, il passe \u00e0 l'\u00e9tat Fleeing.<\/p>\n<p>C'est le traitement des transitions entre les \u00e9tats, mais qu'en est-il du comportement associ\u00e9 aux \u00e9tats eux-m\u00eames ? Pour la mise en \u0153uvre du comportement r\u00e9el pour un \u00e9tat particulier, il existe g\u00e9n\u00e9ralement deux types de \u00ab crochets \u00bb o\u00f9 nous assignons des actions au FSM :<\/p>\n<ul>\n<li>Des actions que nous effectuons p\u00e9riodiquement pour l'\u00e9tat actuel.<\/li>\n<li>Des actions que nous entreprenons lors d'une transition d'un \u00e9tat \u00e0 un autre.<\/li>\n<\/ul>\n<p>\nExemples pour le premier type. L'\u00e9tat Patrolling d\u00e9placera l'agent le long de la route de patrouille \u00e0 chaque image. L'\u00e9tat Attacking essaiera de commencer une attaque ou de passer \u00e0 un \u00e9tat lorsque cela est possible \u00e0 chaque image.<\/p>\n<p>Pour le deuxi\u00e8me type, consid\u00e9rons le passage \u00ab si l'ennemi est visible et que l'ennemi est trop puissant, alors passer \u00e0 l'\u00e9tat Finding Help. L'agent doit choisir o\u00f9 demander de l'aide et conserver cette information afin que l'\u00e9tat Finding Help sache o\u00f9 s'adresser. Une fois l'aide trouv\u00e9e, l'agent retourne \u00e0 l'\u00e9tat Attacking. \u00c0 ce moment-l\u00e0, il voudra informer un alli\u00e9 de la menace, ce qui peut entra\u00eener l'action NotifyFriendOfThreat.<\/p>\n<p>Encore une fois, nous pouvons envisager ce syst\u00e8me \u00e0 travers le prisme du cycle Sense\/Think\/Act. Sense se mat\u00e9rialise dans les donn\u00e9es utilis\u00e9es par la logique de transition. Think consiste en les transitions disponibles dans chaque \u00e9tat. Act est r\u00e9alis\u00e9 par les actions entreprises p\u00e9riodiquement au sein d'un \u00e9tat ou lors des transitions entre \u00e9tats.<\/p>\n<p>Parfois, l'interrogation continue des conditions de transition peut \u00eatre co\u00fbteuse. Par exemple, si chaque agent effectue des calculs complexes \u00e0 chaque image pour d\u00e9terminer s'il voit des ennemis et s'il peut passer de l'\u00e9tat Patrolling \u00e0 Attacking, cela prendra beaucoup de temps processeur. <\/p>\n<p>Des changements importants dans l'\u00e9tat du monde peuvent \u00eatre consid\u00e9r\u00e9s comme des \u00e9v\u00e9nements qui seront trait\u00e9s au fur et \u00e0 mesure de leur apparition. Au lieu que le FSM v\u00e9rifie chaque image la condition de transition \u00ab mon agent peut-il voir le joueur ? \u00bb, on peut configurer un syst\u00e8me s\u00e9par\u00e9 pour effectuer les v\u00e9rifications moins fr\u00e9quemment (par exemple, 5 fois par seconde). Le r\u00e9sultat g\u00e9n\u00e9rera Player Seen lorsque la v\u00e9rification passe. <\/p>\n<p>Cela est transmis au FSM, qui doit maintenant passer \u00e0 la condition Player Seen event received et r\u00e9agir en cons\u00e9quence. Le comportement final est le m\u00eame, \u00e0 l'exception d'un l\u00e9ger retard presque imperceptible avant la r\u00e9ponse. Cependant, les performances se sont am\u00e9lior\u00e9es gr\u00e2ce \u00e0 la s\u00e9paration d'une partie de Sense dans une partie distincte du programme.<\/p>\n<h3>Machine \u00e0 \u00e9tats finis hi\u00e9rarchique<\/h3>\n<p>\nCependant, travailler avec de grands FSM n'est pas toujours pratique. Si nous voulons \u00e9largir l'\u00e9tat d'attaque, en le rempla\u00e7ant par des \u00e9tats distincts MeleeAttacking (combat rapproch\u00e9) et RangedAttacking (combat \u00e0 distance), nous devrons modifier les transitions de tous les autres \u00e9tats qui m\u00e8nent \u00e0 l'\u00e9tat Attacking (actuels et futurs).<\/p>\n<p>Vous avez s\u00fbrement remarqu\u00e9 qu'il y a beaucoup de transitions dupliqu\u00e9es dans notre exemple. La plupart des transitions dans l'\u00e9tat Idling sont identiques \u00e0 celles dans l'\u00e9tat Patrolling. Il serait bien de ne pas se r\u00e9p\u00e9ter, surtout si nous ajoutons davantage d'\u00e9tats similaires. Il est logique de regrouper Idling et Patrolling sous un \u00e9tiquetage commun de \u00ab non-combattant \u00bb, o\u00f9 il n'y a qu'un ensemble g\u00e9n\u00e9ral de transitions vers des \u00e9tats combattants. Si nous consid\u00e9rons cette \u00e9tiquette comme un \u00e9tat, alors Idling et Patrolling deviendront des sous-\u00e9tats. Un exemple d'utilisation d'une table de transitions distincte pour le nouveau sous-\u00e9tat non-combattant :<\/p>\n<p><i>\u00c9tats principaux :<\/i><br \/>\n<img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/d86dd918acbe81b9bf22c2fb34aecee3.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\n<i>\u00c9tat hors combat :<\/i><br \/>\n<img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/9d5bc2053010a32c5f68d7f0192c04ed.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEt sous forme de diagramme :<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/0ccf95ecafa9ce2a6ea5b5b9833ddc4f.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nC'est le m\u00eame syst\u00e8me, mais avec un nouvel \u00e9tat non-combattant qui inclut Idling et Patrolling. Avec chaque \u00e9tat contenant un FSM avec des sous-\u00e9tats (et ces sous-\u00e9tats contenant \u00e0 leur tour leurs propres FSM \u2014 et ainsi de suite autant de fois que n\u00e9cessaire), nous obtenons une Machine \u00e0 \u00c9tats Finis Hi\u00e9rarchique ou HFSM. En regroupant l'\u00e9tat non-combattant, nous avons \u00e9limin\u00e9 beaucoup de transitions redondantes. Nous pouvons faire la m\u00eame chose pour tout nouvel \u00e9tat avec des transitions communes. Par exemple, si \u00e0 l'avenir nous d\u00e9veloppons l'\u00e9tat Attacking en sous-\u00e9tats MeleeAttacking et MissileAttacking, ils seront des sous-\u00e9tats se d\u00e9pla\u00e7ant l'un entre l'autre en fonction de la distance \u00e0 l'ennemi et de la disponibilit\u00e9 de munitions. Au final, des mod\u00e8les de comportement complexes et des sous-mod\u00e8les de comportement peuvent \u00eatre repr\u00e9sent\u00e9s avec un minimum de transitions dupliqu\u00e9es.<\/p>\n<h3>Arbre des comportements<\/h3>\n<p>\nAvec HFSM, des combinaisons complexes de comportements sont cr\u00e9\u00e9es de mani\u00e8re simple. Cependant, il y a une petite difficult\u00e9 : la prise de d\u00e9cision sous forme de r\u00e8gles de transition est \u00e9troitement li\u00e9e \u00e0 l'\u00e9tat actuel. Et dans de nombreux jeux, c\u2019est exactement ce dont on a besoin. Une utilisation soigneuse de la hi\u00e9rarchie des \u00e9tats peut r\u00e9duire le nombre de r\u00e9p\u00e9titions lors des transitions. Mais parfois, des r\u00e8gles doivent fonctionner ind\u00e9pendamment de l'\u00e9tat dans lequel vous vous trouvez ou qui s'appliquent presque dans tous les \u00e9tats. Par exemple, si la sant\u00e9 de l'agent tombe \u00e0 25 %, vous voudrez qu'il s'enfuie, peu importe s'il \u00e9tait en combat, inactif ou en train de parler \u2014 vous devrez ajouter cette condition \u00e0 chaque \u00e9tat. Et si votre designer souhaite ensuite modifier le seuil de sant\u00e9 basse de 25 % \u00e0 10 %, il faudra s'y replonger.<\/p>\n<p>Id\u00e9alement, cette situation n\u00e9cessite un syst\u00e8me dans lequel les d\u00e9cisions \u00ab quel \u00e9tat adopter \u00bb se trouvent en dehors des \u00e9tats eux-m\u00eames, permettant ainsi de modifier un seul endroit sans toucher aux conditions de transition. C'est ici que se pr\u00e9sentent les arbres de comportement.<\/p>\n<p>Il existe plusieurs mani\u00e8res de les r\u00e9aliser, mais l'essentiel est \u00e0 peu pr\u00e8s le m\u00eame et ressemble \u00e0 un arbre de d\u00e9cision : l'algorithme commence par un n\u0153ud \u00ab racine \u00bb, et dans l'arbre se trouvent des n\u0153uds repr\u00e9sentant soit des d\u00e9cisions, soit des actions. Cependant, il y a quelques diff\u00e9rences cl\u00e9s :<\/p>\n<ul>\n<li>\u00c0 pr\u00e9sent, les n\u0153uds renvoient l'une des trois valeurs : Succeeded (si le travail est effectu\u00e9), Failed (si l'ex\u00e9cution est impossible) ou Running (si elle est toujours en cours et qu'il n'y a pas de r\u00e9sultat final).<\/li>\n<li>Il n'y a plus de n\u0153uds de d\u00e9cision pour choisir entre deux alternatives. \u00c0 la place, il y a des n\u0153uds Decorator, qui ont un seul n\u0153ud enfant. S'ils r\u00e9ussissent, ils ex\u00e9cutent leur unique n\u0153ud enfant.<\/li>\n<li>Les n\u0153uds effectuant des actions renvoient la valeur Running pour signifier que des actions sont en cours.<\/li>\n<\/ul>\n<p>\nCet ensemble limit\u00e9 de n\u0153uds peut \u00eatre combin\u00e9 pour cr\u00e9er une grande vari\u00e9t\u00e9 de mod\u00e8les de comportement complexes. Imaginons un HFSM de garde de l'exemple pr\u00e9c\u00e9dent sous forme d'arbre de comportement :<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/5eaa5c725e4ada8285f16f95bb206d53.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAvec cette structure, il ne devrait pas y avoir de transition explicite entre les \u00e9tats Idling\/Patrolling et l'\u00e9tat Attacking ou tout autre. Si l'ennemi est visible et que la sant\u00e9 du personnage est basse, l'ex\u00e9cution s'arr\u00eatera au n\u0153ud Fleeing, peu importe quel n\u0153ud il ex\u00e9cutait pr\u00e9c\u00e9demment \u2014 Patrolling, Idling, Attacking ou tout autre.<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/e1c1dcc2055174aa7cfa846364b1709a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLes arbres de comportement sont complexes \u2014 il existe de nombreuses fa\u00e7ons de les composer, et trouver la bonne combinaison de d\u00e9corateurs et de n\u0153uds composites peut \u00e9galement poser probl\u00e8me. Il y a aussi des questions sur la fr\u00e9quence des v\u00e9rifications de l'arbre \u2014 voulons-nous le parcourir \u00e0 chaque \u00e9tape ou seulement lorsque l'une des conditions change ? Comment conserver l'\u00e9tat li\u00e9 aux n\u0153uds \u2014 comment savoir quand nous avons \u00e9t\u00e9 dans l'\u00e9tat Idling pendant 10 secondes ou comment conna\u00eetre quels n\u0153uds ont \u00e9t\u00e9 ex\u00e9cut\u00e9s la derni\u00e8re fois pour g\u00e9rer correctement la s\u00e9quence ?<\/p>\n<p>C'est pourquoi il existe de nombreuses r\u00e9alisations. Par exemple, dans certains syst\u00e8mes, des n\u0153uds d\u00e9corateurs peuvent avoir remplac\u00e9 les d\u00e9corateurs int\u00e9gr\u00e9s. Ils r\u00e9\u00e9valuent l'arbre lorsque les conditions du d\u00e9corateur changent, aident \u00e0 se connecter aux n\u0153uds et fournissent des mises \u00e0 jour p\u00e9riodiques.<\/p>\n<h3>Syst\u00e8me bas\u00e9 sur l'utilit\u00e9<\/h3>\n<p>\nCertain games have a variety of mechanics. It's desirable for them to utilize the advantages of simple and general transition rules, but not necessarily in the form of a complete behavior tree. Instead of having a clear set of choices or a tree of possible actions, it's easier to explore all actions and select the most appropriate one for the moment.<\/p>\n<p>A utility-based system will help with this. It's a system where the agent has multiple actions and chooses which to execute based on the relative utility of each. Here, utility is an arbitrary measure of how important or desirable performing that action is for the agent. <\/p>\n<p>Based on the calculated utility of the action given the current state and environment, the agent can check and choose the most appropriate different state at any time. This is similar to an FSM, except that transitions are determined by an evaluation for each potential state, including the current one. Note that we choose the most useful action for transitioning (or stay if we have already performed it). For greater variety, this can be a weighted but random choice from a small list.<\/p>\n<p>The system assigns an arbitrary range of utility values \u2014 for example, from 0 (not desirable at all) to 100 (completely desirable). Each action has a number of parameters that affect the computation of this value. Returning to our guard example:<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/085fb2c197bde93d78455d18e63c9c25.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nTransitions between actions are ambiguous \u2014 any state can follow any other. The priorities of actions are reflected in the returned utility values. If an enemy is visible, and this enemy is strong, while the character's health is low, both Fleeing and FindingHelp will return high non-zero values. However, FindingHelp will always be higher. Similarly, non-combat actions never return more than 50, so they will always be below combat actions. This must be considered when creating actions and calculating their utility.<\/p>\n<p>Dans notre exemple, les actions retournent soit une valeur constante fixe, soit l'une des deux valeurs fixes. Un syst\u00e8me plus r\u00e9aliste suppose le retour d'une \u00e9valuation \u00e0 partir d'une plage continue de valeurs. Par exemple, l'action Fuir retourne des valeurs d'utilit\u00e9 plus \u00e9lev\u00e9es lorsque la sant\u00e9 de l'agent est faible, tandis que l'action Attaquer retourne des valeurs plus basses lorsque l'ennemi est trop fort. En raison de cela, l'action Fuir a la priorit\u00e9 sur Attaquer dans toute situation o\u00f9 l'agent estime qu'il n'a pas assez de sant\u00e9 pour vaincre l'adversaire. Cela permet d'ajuster les priorit\u00e9s des actions en fonction d'un certain nombre de crit\u00e8res, rendant cette approche plus flexible et variable que l'arbre de comportement ou FSM.<\/p>\n<p>Chaque action a de nombreuses conditions pour le calcul du programme. Celles-ci peuvent \u00eatre \u00e9crites dans un langage de script ou sous forme de s\u00e9rie de formules math\u00e9matiques. Dans The Sims, qui mod\u00e9lise la routine quotidienne d'un personnage, un niveau suppl\u00e9mentaire de calculs est ajout\u00e9 \u2014 l'agent re\u00e7oit une s\u00e9rie de \u00ab motivations \u00bb influen\u00e7ant les \u00e9valuations d'utilit\u00e9. Si le personnage a faim, il ressentira un besoin croissant de nourriture, et le r\u00e9sultat de l'action Manger augmentera jusqu'\u00e0 ce que le personnage l'ex\u00e9cute, r\u00e9duisant ainsi son niveau de faim et ramenant la valeur Manger \u00e0 z\u00e9ro. <\/p>\n<p>L'id\u00e9e de choisir des actions sur la base d'un syst\u00e8me d'\u00e9valuation est assez simple, c'est pourquoi un syst\u00e8me bas\u00e9 sur l'utilit\u00e9 peut \u00eatre utilis\u00e9 comme partie des processus de prise de d\u00e9cision de l'IA, plut\u00f4t que comme un remplacement complet. Un arbre de d\u00e9cision peut demander une \u00e9valuation de l'utilit\u00e9 de deux n\u0153uds enfants et choisir le plus \u00e9lev\u00e9. De m\u00eame, un arbre de comportement peut avoir un n\u0153ud composite Utilit\u00e9 pour \u00e9valuer l'utilit\u00e9 des actions afin de d\u00e9cider quel \u00e9l\u00e9ment enfant ex\u00e9cuter.<\/p>\n<h2>Mouvement et navigation<\/h2>\n<p>\nDans les exemples pr\u00e9c\u00e9dents, nous avions une plateforme que nous d\u00e9placions vers la gauche ou vers la droite, et un garde qui patrouillait ou attaquait. Mais comment traitons-nous exactement le mouvement d'un agent sur une p\u00e9riode d\u00e9finie ? Comment d\u00e9finissons-nous la vitesse, comment \u00e9vitons-nous les obstacles, et comment planifions-nous un itin\u00e9raire si atteindre la destination est plus compliqu\u00e9 que de se d\u00e9placer tout droit ? Voyons cela de plus pr\u00e8s.<\/p>\n<h3>Gestion<\/h3>\n<p>\nAu d\u00e9part, nous allons consid\u00e9rer que chaque agent a une valeur de vitesse, qui inclut \u00e0 quel point il se d\u00e9place et dans quelle direction. Elle peut \u00eatre mesur\u00e9e en m\u00e8tres par seconde, kilom\u00e8tres par heure, pixels par seconde, etc. En rappelant le cycle Sens\/Think\/Agir, nous pouvons imaginer qu'une partie de la pens\u00e9e choisit la vitesse, tandis qu'une partie de l'action applique cette vitesse \u00e0 l'agent. En g\u00e9n\u00e9ral, les jeux disposent d'un syst\u00e8me physique qui ex\u00e9cute cette t\u00e2che pour vous, en examinant la valeur de la vitesse de chaque objet et en l'ajustant. Par cons\u00e9quent, nous pouvons laisser l'IA avec une seule t\u00e2che \u2014 d\u00e9terminer quelle vitesse l'agent doit avoir. S'il est connu o\u00f9 l'agent doit se rendre, il faut le d\u00e9placer dans la bonne direction \u00e0 une vitesse d\u00e9finie. Une \u00e9quation tr\u00e8s triviale :<\/p>\n<p><i>desired_travel = destination_position \u2013 agent_position<\/i><\/p>\n<p>Imaginez un monde en 2D. L'agent est situ\u00e9 au point (-2,-2), la destination se trouve quelque part au nord-est au point (30, 20), et le chemin n\u00e9cessaire pour que l'agent y arrive est (32, 22). Supposons que ces positions soient mesur\u00e9es en m\u00e8tres \u2014 si nous prenons la vitesse de l'agent \u00e0 5 m\u00e8tres par seconde, nous allons mettre \u00e0 l'\u00e9chelle notre vecteur de d\u00e9placement et obtenir une vitesse d'environ (4,12, 2,83). Avec ces param\u00e8tres, l'agent arriverait \u00e0 destination presque apr\u00e8s 8 secondes.<\/p>\n<p>Les valeurs peuvent \u00eatre recalcul\u00e9es \u00e0 tout moment. Si l'agent \u00e9tait \u00e0 mi-chemin de la destination, le d\u00e9placement serait de la moiti\u00e9 de la distance, mais comme la vitesse maximale de l'agent est de 5 m\/s (nous l'avons d\u00e9cid\u00e9 plus haut), la vitesse restera la m\u00eame. Cela fonctionne aussi pour des cibles en mouvement, permettant \u00e0 l'agent d'apporter de petits ajustements au fur et \u00e0 mesure de leur d\u00e9placement.<\/p>\n<p>Mais nous voulons plus de variabilit\u00e9 \u2014 par exemple, augmenter progressivement la vitesse pour simuler un personnage passant d'un \u00e9tat stationnaire \u00e0 la course. On peut en faire de m\u00eame \u00e0 la fin avant de s'arr\u00eater. Ces fonctionnalit\u00e9s sont connues sous le nom de comportements de direction, chacun d'eux ayant des noms sp\u00e9cifiques : Seek (recherche), Flee (fuite), Arrival (arriv\u00e9e), etc. L'id\u00e9e est que les forces d'acc\u00e9l\u00e9ration peuvent \u00eatre appliqu\u00e9es \u00e0 la vitesse de l'agent, en fonction de la comparaison de la position de l'agent et de sa vitesse actuelle avec la destination, afin d'utiliser diff\u00e9rentes mani\u00e8res de se d\u00e9placer vers l'objectif.<\/p>\n<p>Chaque comportement a un objectif l\u00e9g\u00e8rement diff\u00e9rent. Seek et Arrival sont des m\u00e9thodes pour d\u00e9placer un agent vers un point de destination. Obstacle Avoidance (\u00e9viter les obstacles) et Separation (s\u00e9paration) ajustent le mouvement de l'agent pour contourner les obstacles sur le chemin vers l'objectif. Alignment (alignement) et Cohesion (coh\u00e9sion) maintiennent les agents ensemble lors de leurs d\u00e9placements. Un certain nombre de comportements de direction diff\u00e9rents peuvent \u00eatre combin\u00e9s pour obtenir un seul vecteur de chemin en tenant compte de tous les facteurs. Un agent utilisant les comportements Arrival, Separation et Obstacle Avoidance pour s'\u00e9loigner des murs et d'autres agents. Cette approche fonctionne bien dans des lieux ouverts sans d\u00e9tails superflus. <\/p>\n<p>Dans des conditions plus difficiles, la combinaison de diff\u00e9rents comportements fonctionne moins bien : par exemple, un agent peut se retrouver coinc\u00e9 dans un mur \u00e0 cause d'un conflit entre Arrival et Obstacle Avoidance. Il est donc n\u00e9cessaire d'envisager des options plus complexes que la simple addition de toutes les valeurs. Une m\u00e9thode consiste \u00e0 consid\u00e9rer le mouvement dans diff\u00e9rentes directions et \u00e0 choisir la meilleure option au lieu d'additionner les r\u00e9sultats de chaque comportement. <\/p>\n<p>Cependant, dans un environnement complexe avec des impasses et le choix de la direction \u00e0 prendre, nous aurons besoin de quelque chose de plus avanc\u00e9.<\/p>\n<h3>Recherche de chemin<\/h3>\n<p>\nLes comportements de direction conviennent parfaitement pour le d\u00e9placement simple sur un terrain d\u00e9gag\u00e9 (terrain de football ou ar\u00e8ne), o\u00f9 atteindre l'point A \u00e0 B est un chemin direct avec de l\u00e9g\u00e8res d\u00e9viations autour des obstacles. Pour des itin\u00e9raires plus complexes, nous avons besoin de pathfinding (recherche de chemin), qui est une m\u00e9thode d'exploration du monde et de d\u00e9cision sur l'itin\u00e9raire \u00e0 travers celui-ci.<\/p>\n<p>La m\u00e9thode la plus simple consiste \u00e0 superposer une grille sur chaque carr\u00e9 adjacent \u00e0 l'agent et \u00e0 \u00e9valuer dans lesquels il est permis de se d\u00e9placer. Si l'un d'eux est un point de destination, suivez le parcours depuis celui-ci \u00e0 chaque carr\u00e9 jusqu'\u00e0 revenir au d\u00e9but. C'est le chemin. Sinon, r\u00e9p\u00e9tez le processus avec les autres carr\u00e9s les plus proches jusqu'\u00e0 ce que vous trouviez la destination ou que vous manquiez de carr\u00e9s (ce qui signifie qu'il n'y a pas de chemin possible). Ce qui est formellement connu sous le nom de recherche en largeur (ou Breadth-First Search, BFS). \u00c0 chaque \u00e9tape, elle examine dans toutes les directions (d'o\u00f9 le nom \u00ab largeur \u00bb). L'espace de recherche ressemble \u00e0 un front d'onde qui se d\u00e9place jusqu'\u00e0 atteindre le point recherch\u00e9 - la zone de recherche s'\u00e9tend \u00e0 chaque \u00e9tape jusqu'\u00e0 ce qu'elle atteigne le point final, apr\u00e8s quoi il est possible de retracer le chemin jusqu'au d\u00e9but.<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/d367e62bc53033b05388538649853a41.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEn cons\u00e9quence, vous obtiendrez une liste de carr\u00e9s qui compose le chemin n\u00e9cessaire. C'est ce qu'on appelle le chemin (d'o\u00f9 le terme pathfinding) - une liste des lieux que l'agent visitera en se dirigeant vers la destination.<\/p>\n<p>\u00c9tant donn\u00e9 que nous connaissons la position de chaque carr\u00e9 dans le monde, nous pouvons utiliser les comportements de pilotage (steering behaviours) pour se d\u00e9placer le long du chemin - du n\u0153ud 1 au n\u0153ud 2, puis du n\u0153ud 2 au n\u0153ud 3, et ainsi de suite. La solution la plus simple consiste \u00e0 se diriger vers le centre du carr\u00e9 suivant, mais il est encore pr\u00e9f\u00e9rable de s'arr\u00eater au milieu de l'ar\u00eate entre le carr\u00e9 actuel et le suivant. Cela permet \u00e0 l'agent de couper les angles lors des virages serr\u00e9s.<\/p>\n<p>L'algorithme BFS a aussi ses inconv\u00e9nients - il explore autant de carr\u00e9s dans la \u00ab mauvaise \u00bb direction que dans la \u00ab bonne \u00bb. C'est l\u00e0 qu'intervient un algorithme plus complexe appel\u00e9 A* (A star). Il fonctionne de la m\u00eame mani\u00e8re, mais au lieu d'explorer aveugl\u00e9ment les carr\u00e9s voisins (puis les voisins des voisins, et ainsi de suite), il collecte les n\u0153uds dans une liste et les trie de mani\u00e8re \u00e0 ce que le prochain n\u0153ud explor\u00e9 soit toujours celui qui m\u00e8nera au chemin le plus court. Les n\u0153uds sont tri\u00e9s en fonction d'une heuristique qui prend en compte deux choses : le \u00ab co\u00fbt \u00bb du chemin hypoth\u00e9tique vers le carr\u00e9 souhait\u00e9 (y compris les frais de d\u00e9placement) et une \u00e9valuation de la distance entre ce carr\u00e9 et la destination (orientant la recherche dans la bonne direction).<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/1cab4f53fa5af6b31d352c7bcf453d7e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCet exemple montre qu'un agent explore un carr\u00e9 \u00e0 la fois, choisissant \u00e0 chaque fois le voisin le plus prometteur. Le chemin obtenu est le m\u00eame que celui de l'algorithme BFS, mais moins de carr\u00e9s ont \u00e9t\u00e9 examin\u00e9s au cours du processus, ce qui a une grande importance pour les performances du jeu.<\/p>\n<h3>Mouvement sans grille<\/h3>\n<p>\nMais la plupart des jeux ne sont pas bas\u00e9s sur une grille, et souvent, il est impossible d'en cr\u00e9er une sans compromettre le r\u00e9alisme. Des compromis sont n\u00e9cessaires. Quelle devrait \u00eatre la taille des carr\u00e9s ? Trop grands, et ils ne pourront pas correctement repr\u00e9senter de petits couloirs ou virages, trop petits, il y aura trop de carr\u00e9s \u00e0 rechercher, ce qui prendra beaucoup de temps.<\/p>\n<p>La premi\u00e8re chose \u00e0 comprendre est que la grille nous donne un graphe de n\u0153uds connect\u00e9s. Les algorithmes A* et BFS fonctionnent en r\u00e9alit\u00e9 sur des graphes et ne se soucient pas du tout de notre grille. Nous pourrions placer des n\u0153uds \u00e0 n'importe quel endroit dans le monde du jeu : tant qu'il existe une connexion entre deux n\u0153uds li\u00e9s, ainsi qu'entre le point de d\u00e9part et le point d'arriv\u00e9e et au moins un des n\u0153uds, l'algorithme fonctionnera aussi bien qu'auparavant. Cela est souvent appel\u00e9 un syst\u00e8me de points de passage (waypoint), car chaque n\u0153ud repr\u00e9sente une position significative dans le monde, pouvant faire partie de n'importe quel nombre de chemins hypoth\u00e9tiques.<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/d87e9d4bb2a2fc713d32abc158506eaa.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Exemple 1 : un n\u0153ud dans chaque carr\u00e9. La recherche commence \u00e0 partir du n\u0153ud o\u00f9 se trouve l'agent et se termine au n\u0153ud du carr\u00e9 souhait\u00e9.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/b535a5db805efdc427d7c5724b866982.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Exemple 2 : un ensemble de n\u0153uds plus r\u00e9duit (points de passage). La recherche commence dans le carr\u00e9 avec l'agent, passe par le nombre n\u00e9cessaire de n\u0153uds, puis continue jusqu'\u00e0 la destination.<\/i><\/p>\n<p>C'est un syst\u00e8me assez flexible et puissant. Mais une certaine prudence est n\u00e9cessaire dans les d\u00e9cisions concernant o\u00f9 et comment placer les points de passage, autrement les agents pourraient tout simplement ne pas voir le point le plus proche et ne pas pouvoir commencer leur chemin. Ce serait plus facile si nous pouvions automatiquement placer des points de passage en fonction de la g\u00e9om\u00e9trie du monde.<\/p>\n<p>C'est l\u00e0 qu'appara\u00eet la navigation mesh ou navmesh (grille de navigation). Il s'agit g\u00e9n\u00e9ralement d'une grille 2D de triangles superpos\u00e9e \u00e0 la g\u00e9om\u00e9trie du monde \u2014 partout o\u00f9 il est permis \u00e0 l'agent de se d\u00e9placer. Chacun des triangles de la grille devient un n\u0153ud dans le graphe et a jusqu'\u00e0 trois triangles adjacents, qui deviennent des n\u0153uds voisins dans le graphe. <\/p>\n<p>Cette image est un exemple du moteur Unity \u2014 il a analys\u00e9 la g\u00e9om\u00e9trie du monde et cr\u00e9\u00e9 un navmesh (en bleu clair sur l'image). Chaque polygone dans le navmesh correspond \u00e0 une zone o\u00f9 un agent peut se tenir ou se d\u00e9placer d'un polygone \u00e0 un autre. Dans cet exemple, les polygones sont plus petits que les \u00e9tages sur lesquels ils se trouvent \u2014 cela a \u00e9t\u00e9 fait pour prendre en compte les dimensions de l'agent, qui pourraient s'\u00e9tendre au-del\u00e0 de sa position nominale.<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/845705ba7b9a9d469203aedf7942da41.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNous pouvons rechercher un chemin \u00e0 travers cette grille en utilisant \u00e0 nouveau l'algorithme A*. Cela nous donnera pratiquement le chemin id\u00e9al dans un monde qui tient compte de toute la g\u00e9om\u00e9trie tout en \u00e9vitant les n\u0153uds superflus et la cr\u00e9ation de points de passage.<\/p>\n<p>La recherche de chemin est un sujet trop vaste pour \u00eatre couvert en un seul article. Si vous souhaitez l'explorer plus en d\u00e9tail, vous pouvez vous r\u00e9f\u00e9rer au <noindex><a rel=\"nofollow\" href=\"https:\/\/www.redblobgames.com\/pathfinding\/a-star\/introduction.html\">site d'Amith Patel<\/a><\/noindex>.<\/p>\n<h2>Planification<\/h2>\n<p>\nNous avons d\u00e9couvert avec la recherche de chemin que parfois, il ne suffit pas de choisir une direction et de progresser \u2014 nous devons choisir un chemin et faire plusieurs tournants pour atteindre notre destination. Nous pouvons r\u00e9sumer cette id\u00e9e : atteindre un objectif ce n'est pas simplement le prochain pas, mais une s\u00e9quence enti\u00e8re o\u00f9, parfois, il est n\u00e9cessaire de regarder un peu plus loin pour savoir ce qu'il faut faire en premier. Cela s'appelle la planification. La recherche de chemin peut \u00eatre consid\u00e9r\u00e9e comme un des plusieurs compl\u00e9ments \u00e0 la planification. Du point de vue de notre cycle Sense\/Think\/Act, c'est l\u00e0 que la partie Think planifie plusieurs parties Act pour le futur.<\/p>\n<p>Prenons l'exemple d'un jeu de cartes Magic : The Gathering. Nous commen\u00e7ons avec cet ensemble de cartes en main :<\/p>\n<ul>\n<li>Swamp \u2014 g\u00e9n\u00e8re 1 mana noir (carte de terrain).<\/li>\n<li>Forest \u2014 g\u00e9n\u00e8re 1 mana vert (carte de terrain).<\/li>\n<li>Fugitive Wizard \u2014 n\u00e9cessite 1 mana bleu pour \u00eatre invoqu\u00e9.<\/li>\n<li>Elvish Mystic \u2014 n\u00e9cessite 1 mana vert pour \u00eatre invoqu\u00e9.<\/li>\n<\/ul>\n<p>\nNous ignorons les trois cartes restantes pour simplifier. Selon les r\u00e8gles, un joueur est autoris\u00e9 \u00e0 jouer 1 carte de terrain par tour, il peut \u00ab taper \u00bb cette carte pour en extraire du mana, puis utiliser des sorts (y compris l'invocation d'une cr\u00e9ature) en fonction de la quantit\u00e9 de mana. Dans cette situation, un joueur humain sait qu'il doit jouer Forest, \u00ab taper \u00bb 1 mana vert, puis invoquer Elvish Mystic. Mais comment un IA de jeu pourrait-elle en d\u00e9duire cela ?<\/p>\n<h3>Planification simple<\/h3>\n<p>\nL'approche triviale consiste \u00e0 essayer chaque action \u00e0 tour de r\u00f4le jusqu'\u00e0 ce qu'il ne reste plus d'options appropri\u00e9es. En regardant les cartes, l'IA constate qu'elle peut jouer un Swamp. Et elle le joue. Y a-t-il d'autres actions possibles \u00e0 ce tour ? Elle ne peut pas invoquer Elvish Mystic ou Fugitive Wizard, car leur invocation n\u00e9cessite respectivement de la mana verte et bleue, tandis que Swamp ne fournit que de la mana noire. De plus, elle ne pourra pas jouer Forest car elle a d\u00e9j\u00e0 jou\u00e9 Swamp. Ainsi, l'IA a agi selon les r\u00e8gles, mais de mani\u00e8re peu efficace. Cela peut \u00eatre am\u00e9lior\u00e9.<\/p>\n<p>La planification peut d\u00e9terminer une liste d'actions qui m\u00e8nent le jeu \u00e0 l'\u00e9tat souhait\u00e9. Tout comme chaque case sur le chemin avait des voisins (dans la recherche de chemin), chaque action dans le plan a \u00e9galement des voisins ou des successeurs. Nous pouvons explorer ces actions et les actions suivantes jusqu'\u00e0 ce que nous atteignions l'\u00e9tat d\u00e9sir\u00e9.<\/p>\n<p>Dans notre exemple, le r\u00e9sultat souhait\u00e9 est \u00ab invoquer une cr\u00e9ature si possible \u00bb. Au d\u00e9but du tour, nous ne voyons que deux actions possibles autoris\u00e9es par les r\u00e8gles du jeu :<\/p>\n<p><i>1. Jouer un Swamp (r\u00e9sultat : Swamp en jeu)<br \/>\n2. Jouer un Forest (r\u00e9sultat : Forest en jeu)<\/i><\/p>\n<p>Chaque action prise peut entra\u00eener d'autres actions et en fermer d'autres, encore une fois en fonction des r\u00e8gles du jeu. Imaginez que nous avons jou\u00e9 Swamp \u2014 cela \u00e9liminera Swamp comme option suivante (puisque nous l'avons d\u00e9j\u00e0 jou\u00e9) et cela \u00e9liminera \u00e9galement Forest (car selon les r\u00e8gles, on ne peut jouer qu'une seule carte de terrain par tour). Apr\u00e8s cela, l'IA ajoute comme prochaine \u00e9tape \u2014 obtenir 1 mana noire, car il n'y a pas d'autres options. Si elle avance et choisit de Taper le Swamp, elle obtiendra 1 mana noire et ne pourra rien en faire.<\/p>\n<p><i>1. Jouer un Swamp (r\u00e9sultat : Swamp en jeu)<br \/>\n 1.1 \u00ab Taper \u00bb Swamp (r\u00e9sultat : Swamp \u00ab tap\u00e9 \u00bb, +1 mana noire)<br \/>\n Pas d'actions disponibles \u2013 FIN<br \/>\n2. Jouer un Forest (r\u00e9sultat : Forest en jeu)<\/i><\/p>\n<p>La liste des actions est devenue courte, nous sommes bloqu\u00e9s. Nous r\u00e9p\u00e9tons le processus pour l'action suivante. Nous jouons un Forest, ouvrons l'action \u00ab obtenir 1 mana verte \u00bb, qui \u00e0 son tour ouvrira une troisi\u00e8me action \u2014 invoquer Elvish Mystic.<\/p>\n<p><i>1. Jouer un Swamp (r\u00e9sultat : Swamp en jeu)<br \/>\n 1.1 \u00ab Taper \u00bb Swamp (r\u00e9sultat : Swamp \u00ab tap\u00e9 \u00bb, +1 mana noire)<br \/>\n Pas d'actions disponibles \u2013 FIN<br \/>\n2. Jouer un Forest (r\u00e9sultat : Forest en jeu)<br \/>\n 2.1 \u00ab Taper \u00bb Forest (r\u00e9sultat : Forest \u00ab tap\u00e9 \u00bb, +1 mana verte)<br \/>\n 2.1.1 Invoquer Elvish Mystic (r\u00e9sultat : Elvish Mystic en jeu, -1 mana verte)<br \/>\n Pas d'actions disponibles \u2013 FIN<\/i><\/p>\n<p>Enfin, nous avons explor\u00e9 toutes les actions possibles et trouv\u00e9 un plan pour invoquer une cr\u00e9ature.<\/p>\n<p>C'est un exemple tr\u00e8s simplifi\u00e9. Il est pr\u00e9f\u00e9rable de choisir le meilleur plan possible plut\u00f4t qu'un plan qui r\u00e9pond simplement \u00e0 certains crit\u00e8res. En r\u00e8gle g\u00e9n\u00e9rale, les plans potentiels peuvent \u00eatre \u00e9valu\u00e9s en fonction du r\u00e9sultat final ou du b\u00e9n\u00e9fice total de leur ex\u00e9cution. On peut se donner 1 point pour jouer une carte de terrain et 3 points pour invoquer une cr\u00e9ature. Jouer Swamp donnerait 1 point. Et jouer Forest \u2192 Tap the Forest \u2192 invoquer Elvish Mystic donnerait imm\u00e9diatement 4 points. <\/p>\n<p>Voici comment fonctionne la planification dans Magic: The Gathering, mais cette logique s'applique \u00e9galement dans d'autres situations. Par exemple, d\u00e9placer un pion pour d\u00e9gager de l'espace pour le mouvement d'un fou aux \u00e9checs. Ou se cacher derri\u00e8re un mur pour pouvoir tirer en toute s\u00e9curit\u00e9 dans XCOM. En gros, vous avez compris l'id\u00e9e.<\/p>\n<h3>Planification am\u00e9lior\u00e9e<\/h3>\n<p>\nParfois, il y a trop d'actions potentielles \u00e0 consid\u00e9rer pour examiner chaque option possible. Pour revenir \u00e0 l'exemple de Magic: The Gathering : supposons qu'il y ait plusieurs cartes de terrain et de cr\u00e9atures en jeu et dans votre main - le nombre de combinaisons de mouvements peut se chiffrer par dizaines. Il existe plusieurs solutions \u00e0 ce probl\u00e8me.<\/p>\n<p>La premi\u00e8re m\u00e9thode est le backward chaining (cha\u00eenage invers\u00e9). Au lieu d'examiner toutes les combinaisons, il est pr\u00e9f\u00e9rable de commencer par le r\u00e9sultat final et d'essayer de trouver un chemin direct. Au lieu d'aller de la racine de l'arbre \u00e0 une feuille sp\u00e9cifique, nous allons dans l'autre sens - de la feuille \u00e0 la racine. Cette m\u00e9thode est plus simple et plus rapide.<\/p>\n<p>Si l'adversaire a 1 point de vie, on peut trouver un plan pour \u00ab infliger 1 point de d\u00e9g\u00e2ts ou plus \u00bb. Pour y parvenir, il faut respecter une s\u00e9rie de conditions : <\/p>\n<p>1. Les d\u00e9g\u00e2ts peuvent \u00eatre inflig\u00e9s par un sort - il doit \u00eatre dans votre main.<br \/>\n2. Pour jouer le sort, il faut de la mana.<br \/>\n3. Pour obtenir de la mana, il faut jouer une carte de terrain.<br \/>\n4. Pour jouer une carte de terrain, il faut l'avoir dans votre main.<\/p>\n<p>Une autre m\u00e9thode est le best-first search (recherche du meilleur premier). Au lieu d'examiner tous les chemins, nous choisissons le plus appropri\u00e9. Ce processus donne souvent un plan optimal sans co\u00fbts excessifs en recherche. A* est une forme de recherche du meilleur premier - en explorant les chemins les plus prometteurs d\u00e8s le d\u00e9part, il peut d\u00e9j\u00e0 trouver le meilleur chemin sans avoir besoin de v\u00e9rifier les autres options.<\/p>\n<p>Une variante int\u00e9ressante et de plus en plus populaire de la recherche par meilleur d'abord est la recherche d'arbre de Monte Carlo. Au lieu de deviner quels plans sont les meilleurs lors du choix de chaque action suivante, l'algorithme choisit des successeurs al\u00e9atoires \u00e0 chaque \u00e9tape, jusqu'\u00e0 ce qu'il atteigne la fin (lorsque le plan m\u00e8ne \u00e0 une victoire ou une d\u00e9faite). Le r\u00e9sultat final est ensuite utilis\u00e9 pour augmenter ou diminuer l'\u00e9valuation du \u00ab poids \u00bb des options pr\u00e9c\u00e9dentes. En r\u00e9p\u00e9tant ce processus plusieurs fois, l'algorithme donne une bonne estimation de la meilleure prochaine \u00e9tape, m\u00eame si la situation change (si l'adversaire prend des mesures pour entraver le joueur). <\/p>\n<p>Dans l'histoire de la planification dans les jeux, on ne peut pas \u00e9viter le Goal-Oriented Action Planning ou GOAP (planification d'actions orient\u00e9es vers un but). C'est une m\u00e9thode largement utilis\u00e9e et discut\u00e9e, mais en dehors de quelques d\u00e9tails distinctifs, c'est essentiellement une m\u00e9thode de r\u00e9troaction dont nous avons parl\u00e9 pr\u00e9c\u00e9demment. Si la t\u00e2che est \u00ab d\u00e9truire le joueur \u00bb, et que le joueur est derri\u00e8re une couverture, le plan peut \u00eatre le suivant : d\u00e9truit avec une grenade \u2192 s'en saisir \u2192 lancer.<\/p>\n<p>Il y a g\u00e9n\u00e9ralement plusieurs objectifs, chacun avec sa propre priorit\u00e9. Si l'objectif de plus haute priorit\u00e9 ne peut pas \u00eatre atteint (aucune combinaison d'actions ne cr\u00e9e le plan \u00ab d\u00e9truire le joueur \u00bb, car le joueur n'est pas visible), l'IA reviendra aux objectifs de priorit\u00e9 inf\u00e9rieure.<\/p>\n<h2>Apprentissage et adaptation<\/h2>\n<p>\nNous avons d\u00e9j\u00e0 \u00e9voqu\u00e9 que l'IA de jeu utilise g\u00e9n\u00e9ralement peu l'apprentissage automatique, car cela ne convient pas \u00e0 la gestion des agents en temps r\u00e9el. Mais cela ne signifie pas qu'il n'y a rien \u00e0 emprunter dans ce domaine. Nous voulons un adversaire dans un shooter dont on peut apprendre quelque chose. Par exemple, conna\u00eetre les meilleures positions sur la carte. Ou un adversaire dans un jeu de combat qui bloquerait les combos souvent utilis\u00e9s par le joueur, incitant \u00e0 utiliser d'autres. Ainsi, l'apprentissage automatique dans de telles situations peut \u00eatre tr\u00e8s utile.<\/p>\n<h3>Statistiques et probabilit\u00e9s<\/h3>\n<p>\nAvant de passer \u00e0 des exemples complexes, examinons jusqu'o\u00f9 nous pouvons aller en prenant quelques mesures simples et en les utilisant pour prendre des d\u00e9cisions. Par exemple, dans une strat\u00e9gie en temps r\u00e9el, comment pouvons-nous d\u00e9terminer si un joueur peut lancer une attaque dans les premi\u00e8res minutes du jeu et quelle d\u00e9fense pr\u00e9parer contre cela ? Nous pouvons \u00e9tudier l'exp\u00e9rience pass\u00e9e du joueur pour comprendre quelle pourrait \u00eatre sa r\u00e9action future. Commen\u00e7ons par le fait que nous n'avons pas de telles donn\u00e9es de base, mais nous pouvons les collecter : chaque fois que l'IA joue contre un humain, elle peut enregistrer le temps de la premi\u00e8re attaque. Apr\u00e8s quelques sessions, nous obtiendrons la moyenne du temps avant que le joueur attaque \u00e0 l'avenir.<\/p>\n<p>Les valeurs moyennes ont aussi un probl\u00e8me : si un joueur a attaqu\u00e9 20 fois en mode rush et jou\u00e9 lentement 20 fois, les valeurs pertinentes seront quelque part au milieu, ce qui ne nous sera d'aucune utilit\u00e9. L'une des solutions consiste \u00e0 limiter les donn\u00e9es d'entr\u00e9e : nous pouvons prendre en compte les 20 derni\u00e8res actions.<\/p>\n<p>Une approche similaire est utilis\u00e9e pour \u00e9valuer la probabilit\u00e9 de certaines actions, en supposant que les pr\u00e9f\u00e9rences pass\u00e9es du joueur demeureront les m\u00eames \u00e0 l'avenir. Si un joueur nous attaque cinq fois avec un boule de feu, deux fois avec un \u00e9clair et une fois au corps \u00e0 corps, il est \u00e9vident qu'il pr\u00e9f\u00e8re la boule de feu. Extrapolons et observons la probabilit\u00e9 d'utilisation de diff\u00e9rentes armes : boule de feu = 62,5 %, \u00e9clair = 25 % et corps \u00e0 corps = 12,5 %. Notre IA de jeu doit se pr\u00e9parer \u00e0 se d\u00e9fendre contre le feu.<\/p>\n<p>Une autre m\u00e9thode int\u00e9ressante consiste \u00e0 utiliser le Naive Bayes Classifier (classificateur na\u00eff de Bayes) pour \u00e9tudier de grandes quantit\u00e9s de donn\u00e9es d'entr\u00e9e et classifier la situation afin que l'IA r\u00e9agisse de la mani\u00e8re appropri\u00e9e. Les classificateurs bay\u00e9siens sont surtout connus pour leur utilisation dans les filtres anti-spam des e-mails. Ils analysent les mots, les comparent \u00e0 l\u00e0 o\u00f9 ces mots apparaissaient auparavant (dans des spams ou non), et tirent des conclusions sur les courriers entrants. Nous pouvons faire la m\u00eame chose m\u00eame avec moins de donn\u00e9es d'entr\u00e9e. Sur la base de toute l'information utile que l'IA observe (par exemple, quels unit\u00e9s ennemies ont \u00e9t\u00e9 cr\u00e9\u00e9es, ou quels sorts ils utilisent, ou quelles technologies ils ont recherch\u00e9es), et du r\u00e9sultat final (guerre ou paix, attaquer ou d\u00e9fendre, etc.) \u2014 nous choisirons le comportement appropri\u00e9 pour l'IA.<\/p>\n<p>Tous ces moyens d'apprentissage sont suffisants, mais il est pr\u00e9f\u00e9rable de les utiliser en fonction des donn\u00e9es provenant des tests. L'IA apprendra \u00e0 s'adapter aux diff\u00e9rentes strat\u00e9gies utilis\u00e9es par vos testeurs. Une IA qui s'adapte au joueur apr\u00e8s la sortie peut devenir trop pr\u00e9visible ou, au contraire, trop difficile \u00e0 battre.<\/p>\n<h3>Adaptation bas\u00e9e sur des valeurs<\/h3>\n<p>\n\u00c9tant donn\u00e9 le contenu de notre monde de jeu et de ses r\u00e8gles, nous pouvons modifier l'ensemble des valeurs qui influencent la prise de d\u00e9cision, plut\u00f4t que de simplement utiliser les donn\u00e9es d'entr\u00e9e. Voici comment proc\u00e9der :<\/p>\n<ul>\n<li>Laissons l'IA collecter des donn\u00e9es sur l'\u00e9tat du monde et les \u00e9v\u00e9nements cl\u00e9s durant le jeu (comme mentionn\u00e9 ci-dessus).<\/li>\n<li>Modifions quelques valeurs cl\u00e9s (value) en fonction de ces donn\u00e9es.<\/li>\n<li>Impl\u00e9mentons nos d\u00e9cisions, bas\u00e9es sur le traitement ou l'\u00e9valuation de ces valeurs.<\/li>\n<\/ul>\n<p>\nPar exemple, l'agent a plusieurs pi\u00e8ces \u00e0 choisir sur la carte d'un jeu de tir \u00e0 la premi\u00e8re personne. Chaque pi\u00e8ce a sa propre valeur, qui d\u00e9termine combien elle est d\u00e9sirable \u00e0 visiter. L'IA choisit al\u00e9atoirement la pi\u00e8ce vers laquelle aller, en se basant sur la valeur. Ensuite, l'agent se souvient dans quelle pi\u00e8ce il a \u00e9t\u00e9 tu\u00e9 et diminue sa valeur (la probabilit\u00e9 qu'il y retourne). La situation inverse est \u00e9galement valable : si l'agent \u00e9limine de nombreux ennemis, la valeur de la pi\u00e8ce augmente.<\/p>\n<h3>Mod\u00e8le de Markov<\/h3>\n<p>\nQue se passerait-il si nous utilisions les donn\u00e9es collect\u00e9es pour faire des pr\u00e9visions ? Si nous m\u00e9morisons chaque pi\u00e8ce o\u00f9 nous avons vu un joueur pendant une certaine p\u00e9riode, nous pourrons pr\u00e9dire dans quelle pi\u00e8ce le joueur pourrait se d\u00e9placer. En suivant et enregistrant les mouvements des joueurs dans les pi\u00e8ces (values), nous pouvons les pr\u00e9voir.<\/p>\n<p>Prenons trois pi\u00e8ces : rouge, verte et bleue. Et aussi les observations que nous avons enregistr\u00e9es en visionnant la session de jeu :<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/6e90a365b72a176c36c9a14213baaafc.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nLe nombre d'observations pour chaque pi\u00e8ce est presque \u00e9gal \u2014 o\u00f9 \u00e9tablir un bon endroit pour une embuscade, nous ne savons toujours pas. La collecte de statistiques est \u00e9galement compliqu\u00e9e par le respawn des joueurs, qui apparaissent uniform\u00e9ment sur toute la carte. Mais les donn\u00e9es concernant la prochaine pi\u00e8ce dans laquelle ils entrent apr\u00e8s leur apparition sur la carte sont d\u00e9j\u00e0 utiles.<\/p>\n<p>On voit que la salle verte satisfait les joueurs \u2014 la plupart des personnes passant de la salle rouge \u00e0 celle-ci y restent, dont 50 % y restent par la suite. En revanche, la salle bleue ne rencontre pas ce succ\u00e8s, elle est rarement fr\u00e9quent\u00e9e et ceux qui la visitent ne s'y attardent pas. <\/p>\n<p>Cependant, les donn\u00e9es nous r\u00e9v\u00e8lent quelque chose de plus important \u2014 lorsque le joueur se trouve dans la salle bleue, la salle suivante o\u00f9 nous le verrons probablement sera rouge, et non verte. Bien que la salle verte soit plus populaire que la rouge, la situation change si le joueur se trouve dans la bleue. L'\u00e9tat suivant (c'est-\u00e0-dire la salle dans laquelle le joueur va passer) d\u00e9pend de l'\u00e9tat pr\u00e9c\u00e9dent (c'est-\u00e0-dire la salle dans laquelle le joueur se trouve actuellement). Gr\u00e2ce \u00e0 l'\u00e9tude des d\u00e9pendances, nous ferons des pr\u00e9visions plus pr\u00e9cises que si nous comptions simplement les observations ind\u00e9pendamment les unes des autres.<\/p>\n<p>La pr\u00e9vision de l'\u00e9tat futur bas\u00e9e sur les donn\u00e9es de l'\u00e9tat pass\u00e9 est appel\u00e9e mod\u00e8le de Markov (Markov model), et de tels exemples (avec des salles) sont appel\u00e9s cha\u00eenes de Markov. Comme les mod\u00e8les repr\u00e9sentent la probabilit\u00e9 de changements entre \u00e9tats successifs, ils sont visualis\u00e9s sous forme de FSM avec une probabilit\u00e9 autour de chaque transition. Auparavant, nous avons utilis\u00e9 des FSM pour repr\u00e9senter l'\u00e9tat comportemental dans lequel se trouvait l'agent, mais ce concept s'applique \u00e0 tout \u00e9tat, qu'il soit li\u00e9 ou non \u00e0 l'agent. Dans ce cas, les \u00e9tats repr\u00e9sentent la salle occup\u00e9e par l'agent :<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/edb32dff7a3298b19c3fa4d66f48e9f4.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nC'est une version simple de la repr\u00e9sentation de la probabilit\u00e9 relative des changements d'\u00e9tats, donnant \u00e0 l'IA une certaine capacit\u00e9 \u00e0 pr\u00e9dire l'\u00e9tat suivant. Il est possible de pr\u00e9voir plusieurs \u00e9tapes \u00e0 l'avance.<\/p>\n<p>Si le joueur se trouve dans la salle verte, il y a 50 % de chances qu'il y reste lors de la prochaine observation. Mais quelle est la probabilit\u00e9 qu'il y soit encore m\u00eame apr\u00e8s ? Il n'y a pas seulement la chance que le joueur soit rest\u00e9 dans la salle verte apr\u00e8s deux observations, mais aussi la chance qu'il soit parti et revenu. Voici un nouveau tableau prenant en compte les nouvelles donn\u00e9es :<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/f87afff68b066a879661e37f68654ae2.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nOn peut voir que la probabilit\u00e9 de voir le joueur dans la salle verte apr\u00e8s deux observations sera de 51 % \u2014 21 % qu'il provienne de la salle rouge, 5 % qu'il ait visit\u00e9 la salle bleue entre les deux, et 25 %, qu'il ne quitte pas du tout la salle verte.<\/p>\n<p>Le tableau est un simple outil visuel : la proc\u00e9dure n\u00e9cessite seulement de multiplier les probabilit\u00e9s \u00e0 chaque \u00e9tape. Cela signifie que vous pouvez regarder loin dans le futur avec une seule condition : nous supposons que la chance d'entrer dans une pi\u00e8ce d\u00e9pend uniquement de la pi\u00e8ce actuelle. Cela s'appelle la propri\u00e9t\u00e9 de Markov (Markov Property) : l'\u00e9tat futur d\u00e9pend uniquement de l'\u00e9tat pr\u00e9sent. Mais ce n'est pas toujours exact. Les joueurs peuvent changer de d\u00e9cisions en fonction d'autres facteurs : le niveau de sant\u00e9 ou le nombre de munitions. \u00c9tant donn\u00e9 que nous ne prenons pas en compte ces valeurs, nos pr\u00e9visions seront moins pr\u00e9cises.<\/p>\n<h3>N-Grams<\/h3>\n<p>\nQue dire de l'exemple d'un jeu de combat et de la pr\u00e9vision des combos d'un joueur ? C'est exactement la m\u00eame chose ! Mais au lieu d'un seul \u00e9tat ou \u00e9v\u00e9nement, nous allons explorer des s\u00e9quences enti\u00e8res qui composent le coup combo.<\/p>\n<p>Une des fa\u00e7ons de le faire est de conserver chaque entr\u00e9e (par exemple, Kick, Punch ou Block) dans un tampon et d'enregistrer tout le tampon sous forme d'\u00e9v\u00e9nement. Ainsi, lorsqu'un joueur appuie plusieurs fois sur Kick, Kick, Punch pour ex\u00e9cuter une attaque SuperDeathFist, le syst\u00e8me IA stocke toutes les entr\u00e9es dans le tampon et se souvient des trois derni\u00e8res entr\u00e9es utilis\u00e9es \u00e0 chaque \u00e9tape.<\/p>\n<p><img decoding=\"async\" alt=\"Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants\" src=\"\/wp-content\/uploads\/2019\/11\/9a95226ae155dca5e45a66d4440f3cd4.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n(Les lignes en gras sont celles o\u00f9 le joueur d\u00e9clenche l'attaque SuperDeathFist.)<\/p>\n<p>L'IA verra toutes les options lorsque le joueur a choisi Kick, suivi d'un autre Kick, puis remarquera que la prochaine entr\u00e9e est toujours Punch. Cela permettra \u00e0 l'agent de pr\u00e9dire le combo SuperDeathFist et de le bloquer si c'est possible.<\/p>\n<p>Ces s\u00e9quences d'\u00e9v\u00e9nements sont appel\u00e9es N-grams, o\u00f9 N est le nombre d'\u00e9l\u00e9ments stock\u00e9s. Dans l'exemple pr\u00e9c\u00e9dent, il s'agissait d'un trigramme (3-gram), ce qui signifie que les deux premi\u00e8res entr\u00e9es sont utilis\u00e9es pour pr\u00e9dire la troisi\u00e8me. Ainsi, dans un 5-gram, les quatre premi\u00e8res entr\u00e9es pr\u00e9disent la cinqui\u00e8me, et ainsi de suite.<\/p>\n<p>Le d\u00e9veloppeur doit choisir soigneusement la taille des N-grams. Un nombre N plus petit n\u00e9cessite moins de m\u00e9moire, mais stocke \u00e9galement une histoire plus courte. Par exemple, un bigram (2-gram) enregistrera Kick, Kick ou Kick, Punch, mais ne pourra pas stocker Kick, Kick, Punch, donc l'IA ne r\u00e9agira pas au combo SuperDeathFist.<\/p>\n<p>D'un autre c\u00f4t\u00e9, des nombres plus grands n\u00e9cessitent plus de m\u00e9moire et il sera plus difficile pour l'IA d'apprendre, car il y aura beaucoup plus d'options possibles. Si vous aviez trois entr\u00e9es possibles : Kick, Punch ou Block, et que nous avons utilis\u00e9 un 10-gram, cela repr\u00e9senterait environ 60 000 variations diff\u00e9rentes.<\/p>\n<p>Le mod\u00e8le de bigramme est une cha\u00eene de Markov simple : chaque paire \u00ab \u00e9tat pr\u00e9c\u00e9dent \/ \u00e9tat actuel \u00bb constitue un bigramme, et vous pouvez pr\u00e9dire le second \u00e9tat bas\u00e9 sur le premier. Les trigrammes et les N-grammes de plus grande taille peuvent \u00e9galement \u00eatre consid\u00e9r\u00e9s comme des cha\u00eenes de Markov, o\u00f9 tous les \u00e9l\u00e9ments (sauf le dernier dans le N-gramme) forment ensemble le premier \u00e9tat, et le dernier \u00e9l\u00e9ment est le second. Un exemple avec un combat montre la chance de passer de l'\u00e9tat Kick et Kick \u00e0 l'\u00e9tat Kick et Punch. En consid\u00e9rant plusieurs enregistrements de l'historique d'entr\u00e9e comme une seule unit\u00e9, nous transformons essentiellement la s\u00e9quence d'entr\u00e9e en une partie d'un tout. Cela nous donne une propri\u00e9t\u00e9 de Markov, nous permettant d'utiliser des cha\u00eenes de Markov pour pr\u00e9dire l'entr\u00e9e suivante et deviner quel coup combo sera le suivant.<\/p>\n<h2>Conclusion<\/h2>\n<p>\nNous avons discut\u00e9 des outils et des approches les plus courants dans le d\u00e9veloppement de l'intelligence artificielle. Nous avons \u00e9galement examin\u00e9 les situations dans lesquelles ils doivent \u00eatre appliqu\u00e9s et o\u00f9 ils sont particuli\u00e8rement utiles. <\/p>\n<p>Cela devrait suffire pour comprendre les concepts de base de l'IA dans les jeux. Mais, bien s\u00fbr, ce n'est pas tous les m\u00e9thodes. Parmi les m\u00e9thodes moins populaires mais tout aussi efficaces, il y a :<\/p>\n<ul>\n<li>des algorithmes d'optimisation, y compris la mont\u00e9e en colline, la descente du gradient et les algorithmes g\u00e9n\u00e9tiques<\/li>\n<li>des algorithmes de recherche \/ planification comp\u00e9titifs (minimax et \u00e9lagage alpha-b\u00eata)<\/li>\n<li>des m\u00e9thodes de classification (perceptrons, r\u00e9seaux de neurones et machines \u00e0 vecteurs de soutien)<\/li>\n<li>des syst\u00e8mes pour le traitement de la perception et de la m\u00e9moire des agents<\/li>\n<li>des approches architecturales pour l'IA (syst\u00e8mes hybrides, sous-ensembles d'architectures et autres mani\u00e8res de superposer des syst\u00e8mes IA)<\/li>\n<li>des outils d'animation (planification et coordination des mouvements)<\/li>\n<li>des facteurs de performance (niveau de d\u00e9tail, algorithmes anytime et timeslicing)<\/li>\n<\/ul>\n<p>\nRessources Internet sur le sujet :<\/p>\n<p>1. Sur GameDev.net, il y a <noindex><a rel=\"nofollow\" href=\"https:\/\/www.gamedev.net\/articles\/programming\/artificial-intelligence\/\">une section avec des articles et des tutoriels sur l'IA<\/a><\/noindex>, ainsi que <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> contient de nombreuses pr\u00e9sentations et articles sur un large \u00e9ventail de sujets li\u00e9s au d\u00e9veloppement de l'IA de jeu.<br \/>\n3. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.gdcvault.com\/\">Le GDC Vault<\/a><\/noindex> inclut des sujets du sommet GDC AI, dont beaucoup sont disponibles gratuitement.<br \/>\n4. Des mat\u00e9riaux utiles peuvent \u00e9galement \u00eatre trouv\u00e9s sur le site <noindex><a rel=\"nofollow\" href=\"http:\/\/gameai.com\/\">AI Game Programmers Guild<\/a><\/noindex>.<br \/>\n5. Tommy Thompson, un chercheur en IA et d\u00e9veloppeur de jeux, r\u00e9alise des vid\u00e9os sur la cha\u00eene YouTube <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/user\/tthompso\">AI and Games<\/a><\/noindex> expliquant et \u00e9tudiant l'IA dans les jeux commerciaux.<\/p>\n<p>Livres sur le sujet :<\/p>\n<p>1. La s\u00e9rie de livres Game AI Pro est une collection d'articles courts expliquant comment impl\u00e9menter des fonctionnalit\u00e9s sp\u00e9cifiques ou r\u00e9soudre des probl\u00e8mes particuliers.<\/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 : Sagesse rassembl\u00e9e des professionnels de l'IA de jeu<\/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 : Sagesse rassembl\u00e9e des professionnels de l'IA de jeu<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/amzn.to\/2KF4irS\">Game AI Pro 3 : Sagesse rassembl\u00e9e des professionnels de l'IA de jeu<\/a><\/noindex><\/p>\n<p>2. La s\u00e9rie AI Game Programming Wisdom est le pr\u00e9d\u00e9cesseur de la s\u00e9rie Game AI Pro. Elle contient des m\u00e9thodes plus anciennes, mais presque toutes restent pertinentes m\u00eame aujourd'hui.<\/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\">Intelligence artificielle : Une approche moderne<\/a><\/noindex> \u2014 c'est l'un des textes de base pour quiconque souhaite comprendre le domaine g\u00e9n\u00e9ral de l'intelligence artificielle. Ce livre ne traite pas du d\u00e9veloppement de jeux \u2014 il enseigne les bases de l'IA.<br \/>\n<br \/>Source : <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\/fr\/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=\"fr_FR\" \/>\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\/fr\/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\udd47Comment cr\u00e9er une IA de jeu : guide pour les d\u00e9butants | ProHoster","description":"Je suis tomb\u00e9 sur un mat\u00e9riel int\u00e9ressant sur.","canonical_url":"https:\/\/prohoster.info\/fr\/blog\/news\/kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"fr_FR","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\/fr\/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\/fr\/wp-json\/wp\/v2\/posts\/52118","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/comments?post=52118"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/52118\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media?parent=52118"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/categories?post=52118"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/tags?post=52118"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}