Cet article a pour vocation d’expliquer le processus de pensée et de réflexion derrières les IAs de Umbrellads, Jeu de Platformer 3d et Combat, qui a commencé courant Octobre 2019. Cet article prend en compte la situation actuelle des IAs du jeu.
IAs codesignées par Guilhem d’Humières, avec les retours de tout le reste de notre équipe, notamment Léo Marambat Patinote, qui s’est chargé de la programmation du système décrit ci dessous.
Concevoir un système d’intelligences artificielles n’est pas chose aisée, en effet, la première itération est très coûteuse en temps, et risque d’impacter la production durant tout le long du projet, il faut trouver un système modulaire capable de s’adapter aux futurs robots que nous pourrions créer, mais aussi être facilement modifiable, sans impliquer de temps de production supplémentaire. Il s’agit d’une d’une triple entente entre trois partis : Les combat designers (Guilhem et moi même), le programmeur (Léo) et le produceur (poste que j’occupe également).
Pour nos intentions d’IA, nous voulions que tous les ennemis fonctionnent à partir du même système, ainsi, tous les “cerveaux” de nos ennemis utilisent la même structure, qu’on peut ensuite attribuer à des “corps” différents, qui interpréteront les informations différemment. De plus, nous voulions éviter au maximum une intelligence globale, qui gère tous les ennemis d’un combat. C’est une décision assez arbitraire, il aurait probablement été plus malin de gérer tous les ennemis par un seul cerveau, mais nous voulions qu’un maximum de situations différentes puissent émerger, et il nous avait alors semblé logique d’attribuer un cerveau indépendant (ou presque) par ennemi.
Finalement, nous voulions un système qui encourage le joueur à diversifier ses actions, et exploiter tout son kit de compétences (saut, double saut, attaques légères, lourdes, combos, roulade). Il nous fallait donc des ennemis archétypaux, challengeant sur différentes compétences, mais aussi une intelligence artificielle capable de comprendre ce que le joueur était en train de faire, afin que les robots puissent modifier son comportement en fonction.
Voilà, maintenant que les présentations sont faites rentrons dans le vif du sujet : les paramètres des IAs.
Chaque IA possède une valeur en : Agressivité, Défensivité, Ruse, Lucidité et Réactivité. Qui vont lui permettre de réagir différemment aux situations de jeu, et être plus ou moins sensible à certains stimulis.
A cela, s’ajoute les actions des ennemis : chacune de leur action (se déplacer, attaquer, utiliser une compétence, ne rien faire) possède à son tour une valeur d’agressivité, de défensivité et de Ruse. Ainsi, il est possible de déterminer que faire un pas de côté est plus rusé que d’attaquer, et que tel ennemi est rusé, et est donc plus enclin à faire des pas de côté. A cela s’ajoute d’autres paramètres de prise de décision, comme la présence d’un cooldown, ou encore d’un poids initial.
Ensuite, toutes les actions ont leurs paramètres d’actions :
La temporalité : Chaque action dure un temps précis, exprimé en seconde, et est divisé en 3 parties : Une amorce (ou Start-up), Un Climax, et une Recovery. Dans le cadre d’une attaque par exemple, l’Amorce correspond au moment où l’ennemi lève les bras, le climax correspond au moment où les bras s’abattent pour asséner le coup, et la recovery est le temps d’inaction après l’action.
La résilience : c’est à dire à quel point durant l’action le personnage sera protégé des étourdissements et autres annulations d’attaque.
Si il s’agit d’une attaque, alors l’action dispose en plus :
Les dégâts de l’attaque
Sa portée (hitbox)
La déstabilisation de l’attaque : c’est à dire à quel point l’attaque repoussera ou étourdira la cible
Il s’agit ici de quelques un des nombreux paramètres des actions des personnages dans Umbrellads, une liste plus exhaustive sera probablement faite dans le cadre d’un article sur le système de combat.
Donc pour le moment, nous avons un personnage, qui affronte des adversaires dotés de cerveau ainsi que d’actions.
Détermination de Listes d’actions
Première Étape : Phase d’approche
Le joueur possède, autour de lui, de différents points d’ancrage.
Le rond au centre représente le joueur, les points représente les points d’ancrages, ils sont de trois couleurs différentes, correspondant à la distance avec le joueur (layer 0 : le plus proche, layer 2 : le plus loin).
Le robot, si il n’est pas sur un point d’ancrage, choisi dans un premier temps le point d’ancrage sur lequel il aimerait bien se trouver, à condition que : Ce robot ai le droit d’aller sur ce Layer de point d’ancrage (un robot qui a des petits bras ne peut pas aller sur le layer 2 !), mais aussi le robot vérifie qu’aucun autre robot ne soit déjà sur le point, mais aussi qu’aucun robot n’ai décidé de choisir ce point. A cela s’ajoute, évidemment, l’interdiction de choisir ce point si il inaccessible (dans un mur, au dessus du vide).
Le robot a alors une Liste d’actions possibles, que l’on appellera Liste d’approche (principalement du déplacement). On peut y trouver la plupart du temps : Déplacement vers le point, Déplacement à l’inverse du point, Déplacement diagonal avant, etc. Il peut y avoir des doublons : on peut imaginer un déplacement vers l’avant à grande vitesse et qui dure 0.5sec, et un mouvement vers l’avant lent qui dure 2 sec.
Si le robot arrive suffisamment proche de son point d’ancrage, il interrompt son action actuel, et passe à l’étape suivante :
Seconde Étape : Phase de combat rapproché
Le robot a alors accès à une toute nouvelle liste d’action, appelée Liste de Combat.
Celle liste est composée de mouvement, d’attaque, et d’actions annexes. Les mouvements sont ici sur le référentiel joueur : mouvement vers le joueur, mouvement à l’opposée du joueur, etc. Remarquons également que toutes les actions sont autorisées ou non dépendant du layer du point d’ancrage : on peut par exemple imaginer une attaque ne pouvant qu'être lancé sur le layer 0, un déplacement qui ne peut que être effectué sur le layer 1, etc. Une fois de plus, les actions peuvent être très proches mais avoir des variations.
Comment sont choisies les actions ?
Maintenant que les présentations sont faites, rentrons dans le vif du sujet : comment sont choisies les actions ?
Nous utilisons pour Umbrellads un système de poids adaptatif : C’est à dire que chaque action possède une probabilité de sortie dépendant de la situation, et que au moment où l’IA doit choisir une action, elle tire un dé parmis toutes les possibilités, et choisit ainsi l’action.
La formule de poids adaptative est la suivante :
= (P + ( a(A + Pv * L) + d(D + Pd * L) + C * c)) * AC
Chaque terme renvoie ici à un paramètre :
P = poids initial
a = sensibilité de l’action à l'agressivité
A = aggressivité de l’IA
Pv = vulnérabilité du joueur
d = sensibilité de l’action à la défensivité
D = défensivité de l’IA
Pd = danger du joueur
C = Ruse de l’IA
c = sensibilité de l’action à la Ruse.
AC = attaque cancel, voir “Box de danger”.
L = lucidité
Si l’action est une attaque :
Box de danger : durant le start-up d’une attaque du joueur, une hitbox de danger apparaît, pour indiquer aux IAs l’attaque à venir. Lorsque un ennemi est dans cette hitbox de danger, lors de sa prise de décision, la valeur AC est modifié. Voici le calcul de AC :
TR : temps restant au start up du joueur
SUT : temps de start-up de l’attaque de l’IA
OT = TR + TR * Random(-0.5, 0.5) * (1 - lucidity) - SUT
Si OT est positif, AC = 1 + OT + A
Si OT est négatif, on calcule RT
RT = résilience totale - déstabilisation
Si RT est positif : AC = 1 + A - D
Si RT est négatif : AC = 1 - D
Si l’IA n’est pas dans une box de danger, ou que l’action n’a pas de hitbox offensive, AC = 1.
Danger du joueur (Pd) : Si l’IA est dans une box de danger, Pd = 1, sinon, Pd = 0.
Vulnérabilité du joueur (Pv) : Si le joueur est dans un quelconque autre état que Idle/Marche, Pv est égal au temps qu’il reste à l’animation du joueur. Sinon, Pv est égal à 0.
Les actions ne pouvant pas être réalisées (par sur le bon Layer, action en cooldown) ont une probabilité adaptative de zéro.
Cette formule peut sembler un peu abrupt au premier abord, essayons de voir ce qu’elle abrite :
Dégrossissons la formule en 5 parties :
= (P + ( a(A + Pv * L) + d(D + Pd * L) + C * c)) * AC
P renvoie ici au poids initial de l’action
a(A+Pv * L) renvoie à l’implication de l'agressivité au sein de l’action
d(D+Pd * L) renvoie à l’implication de la défensivité au sein de l’action
C * c renvoie à l’implication de la Ruse au sein de l’action
Nous gardons AC pour plus tard.
1. P
P est très simple à comprendre, il s’agit juste du poids initial.
2. a(A + PV * L)
a correspond à l’agressivité de l’action. On multiplie cette valeur par A, qui est l’agressivité du robot (donc, plus un robot est agressif, plus il utiliseras des actions agressives). A cela s’ajoute la vulnérabilité du joueur (noté Pv), c’est la valeur adaptative. On peut considérer que Pv est la raison objective pour laquelle un robot choisirai d’attaquer. En effet, Pv est égal au temps qu’il reste avant que le joueur puisse agir de nouveau. Donc Pv permet au robot de décider d’attaquer au meilleur moment : quand le joueur ne peut pas se défendre.
Finalement, L permet de réduire l'importance de PV : un robot stupide ne pensera pas à agir en fonction de PV.
Remarquons que plus une action est agressive, plus l’impact de PV est grand.
3. d(D + Pd * L)
Très similaire à la formule précédente, mais calculant cette fois le poids de la défensivité. La Valeur adaptative ici est Pd. Pd permet juste de voir si le robot est en danger imminent ou pas. Si c’est le cas, le poids de l’action augmentera grandement, favorisant les actions défensives quand le robot est en danger. Une fois de plus, L permet ici de réduire l’importance de Pd : un robot stupide ne penseras pas à agir en fonction de Pd.
Remarquons que plus une action est défensive, plus l’impact de Pd est grand.
4. C * c
Calcul ici la ruse. Par design, nous voulions que le système puisse détecter en quoi la situation est rusée. Finalement, nous nous sommes ravisés, il n’y a donc pas de valeur adaptative ici.
5. AC
AC permet aux robots d’agir en fonction du temps de leurs propres actions et de celles du joueur, ainsi que d'interpréter de manière cohérente la déstabilisation et la résilience de tous les acteurs d’un combat.
TR : temps restant au start up du joueur
SUT : temps de start-up de l’attaque de l’IA
OT = TR + TR * Random(-0.5, 0.5) * (1 - lucidity) - SUT
Si OT est positif, AC = 1 + OT + A
Comprenons bien ce que cela signifie, si OT est positif, cela veut dire que le robot
sait qu’il a le temps d’effectuer cette action avant que le joueur ne le frappe, on
donne alors un gros bonus au poids final de l’action en donnant une valeur suppérieure à 1 à AC.
Si OT est négatif, on calcule RT
RT = résilience totale - déstabilisation
Si RT est positif : AC = 1 + A - D
Si RT est négatif : AC = 1 - D
Si le robot n’a pas le temps d’effectuer cette action avant que le joueur ne le frappe, alors le robot va vérifier si il ne peut pas simplement décider d’encaisser le coup (sans être déstabilisé) pour pouvoir, à son tour, agresser le joueur. Si en revanche le robot calcul qu’il sera déstabilisé prochainement, on réduit considérablement le poids total de l’action.
Si l’IA n’est pas dans une box de danger, ou que l’action n’a pas de hitbox offensive, AC = 1.
AC est capital dans l’intelligence des robots. En effet, nous voulions que le joueur ait des raisons d’utiliser les combos qu’il utilise. Grâce à ce système, les robots peuvent exploiter les failles d’un joueur qui lance ses attaques au hasard.
Conclusion
Ainsi, le système d’intelligence artificielle de Umbrellads permet de donner une personnalité aux robots, ainsi que de créer des situations excitantes. En revanche, je trouve personnellement le système peu abouti, et étant pour le moment incorporer de manière un peu bancale au jeu. En effet, bien que aujourd’hui déjà, certains robots esquives systématiquement les attaques les plus longues, ou que d’autres décident d’encaisser sans broncher, je pense que le système aurait pu être mieux exploité.
Finalement, si je suis dans le futur amené à concevoir un autre système d’intelligence artificielle, je me plongerai plus profondément dans une intelligence de groupe, avec des ennemis qui agissent plus en groupe et en fonction des autres.
Anecdote : Le système de personnalité des robots (agressif, défensif, rusé) s’est trouvé très utile au sein du projet, en effet, certains robots ont des attributs particuliers (géant, robot électrique, etc.). Il était alors très simple de modifier leurs comportements sans devoir créer un tout nouveau fonctionnement.
Comentarios