Ils nous faut ĂȘtre prĂȘts pour le prochain assaut des extraterrestres ! Et pour cela, rien de mieux que de s’entraĂźner sur un simulateur de robot et d’intelligences artificielles en C++ !
A vos claviers et souris, on commence ici !
Sommaire
Prérequis
- Un ordinateur sous Windows 10 avec les droits administrateur
- De bonnes notions en C++ (partie 1 et 2 du super tuto OpenClassroom)
- De la patience et une volonté de fer pour vaincre les envahisseurs !
NâhĂ©sitez pas Ă me contacter ici pour toutes questions sur les notions de C++. A votre disposition si vous souhaitez aussi des cours particuliers đ
Installation de l’environnement de dĂ©veloppement
On utilisera Code::Blocks comme environnement avec le compilateur mingw téléchargeable depuis ce lien.
Pour bien comprendre comment installer et utiliser l’IDE, je vous renvoie sur le tutoriel d’openclassroom.
Récupération des sources du simulateur
Entrez votre nom, prénom et mail puis cliquer sur le bouton télécharger pour obtenir les sources.
Compilation du projet
Une fois l’archive .zip tĂ©lĂ©chargĂ©e, dĂ©compressez-la, puis ouvrez le fichier j2l-SimulateurIA.workspace via double-clic.
Ouvrez bien le fichier avec l’extension .workspace (et non le fichier projet .cpb). Si l’extension n’est pas visible, dans lâExplorateur de fichiers -> Affichage -> Afficher/Masquer cocher Extensions de nom de fichiers.
Si le double-clic n’ouvre pas automatiquement Code::Blocks, ouvrez Code::Blocks manuellement, puis glisser-dĂ©poser le fichier j2l-SimulateurIA.workspace dans la fenĂȘtre.
Une fois ouvert, dans la fenĂȘtre « Management » vous devriez voir les sources du projet j2l-SimulateurIA, triĂ©es dans 3 dossiers virtuels :
- Agent : Contient les sources de vos classes agents, classes qui devront implĂ©menter lâintelligence artificiel dĂ©crivant comment les entitĂ©s du jeu vont agir de maniĂšre autonome
- Jeu : Contient les variables et fonctions pour interagir avec le jeu ; Vous ne pouvez pas modifier ces sources (les rÚgles du jeu sont impénétrables ^^)
- MoteurRendu : Contient vos classes pour afficher les rendus et animations de vos agents
Pour lancer l’application et voir les agents Ă©voluer dans le jeu, cliquez Build -> Build and run (ou le raccourci clavier F9). Des lignes de commande devraient apparaĂźtre dans la fenĂȘtre « Logs & others », puis l’application devrait dĂ©marrer en plein Ă©cran.
Modifier le comportements des agents
Pour cela, explorons la classe AgentSpecial implémentée dans les fichiers AgentSpecial.cpp et AgentSpecial.hpp.
Dans le fichier header (le fichier d’en-tĂȘte avec l’extension .hpp), vous trouverez les signatures des mĂ©thodes et attributs de la classe AgentSpecial. Tandis que dans le fichier .cpp, vous trouverez l’implĂ©mentation (le code) de chaque fonctions de la classe (les mĂ©thodes).
En général, un header donne les informations aux utilisateurs pour savoir comment utiliser une classe, mais ne livre surtout pas le secret de fabrication caché dans le fichier cpp.
class AgentSpecial:
public j2l::Agent
{
public:
AgentSpecial(int x, int y, int orientation);
virtual ~AgentSpecial() {}
const char* nom() const;
protected:
void quandActualiser();
void quandDistanceFrontaleChange(int ancienneValeur, int nouvelleValeur);
void quandMunitionsChange(int ancienneValeur, int nouvelleValeur);
void quandVieChange(int ancienneValeur, int nouvelleValeur);
void quandPoseChange(int ancienX, int ancienY, int ancienneOrientation, int nouvelX, int nouvelY, int nouvelleOrientation);
};
Les deux premiĂšres lignes indiquent que la classe AgentSpecial hĂ©rite des mĂ©thodes et attributs de la classe Agent, implĂ©mentĂ©e dans l’espace de nom j2l. Cela signifie que cette classe fille contient aussi les mĂ©thodes et attributs de la classe parente Agent, dĂ©finis dans le fichier Agent.hpp.
class Agent
{
public:
Agent(int x, int y, int orientation);
virtual ~Agent() {}
void actualiser(int x, int y, int orientation, int distance, int vie, int munitions, int& ordreX, int& ordreY, int& ordreOrientation, bool& ordreTir);
void orienter(int orientation);
void deplacer(int x, int y);
void tirer(bool tirerOuNon);
int munitionsRestantes() const;
int viesRestantes() const;
int munitionsInitiales() const;
int viesInitiales() const;
int distanceFrontale() const;
int x() const;
int y() const;
int orientation() const;
virtual const char* nom() const;
protected:
virtual void quandActualiser() {}
virtual void quandDistanceFrontaleChange(int ancienneValeur, int nouvelleValeur) {}
virtual void quandMunitionsChange(int ancienneValeur, int nouvelleValeur) {}
virtual void quandVieChange(int ancienneValeur, int nouvelleValeur) {}
virtual void quandPoseChange(int ancienX, int ancienY, int ancienneOrientation, int nouvelX, int nouvelY, int nouvelleOrientation) {}
};
Cependant elle ne pourra accĂ©der qu’aux mĂ©thodes et attributs public et protected (private Ă©tant accessible uniquement Ă lâintĂ©rieur des mĂ©thodes la classe Agent).
ĂlĂ©ments intĂ©ressants, la classe Agent parent dispose de mĂ©thodes virtuelles, ce qui signifie que la classe enfant peut les « surcharger » et redĂ©finir ces propres comportement, par dessus ou Ă la place des mĂ©thodes parentes :
- quandDistanceFrontaleChange() : appelĂ©e Ă chaque tour de jeu, quand l’agent dĂ©tecte un enemi dans son champs de vision
- quandMunitionsChange() : appelĂ©e Ă chaque tour de jeu, quand l’agent perd une munition, signifiant qu’un tir a bien Ă©tĂ© effectuĂ©
- quandVieChange() : appelĂ©e Ă chaque tour de jeu, quand l’agent est sous le feu ennemi
- quandPoseChange() : appelĂ©e Ă chaque tour de jeu, quand l’agent bouge ou change d’orientation
- quandActualiser() : appelée en dernier à chaque tour du jeu
Sachant çela, il ne vous reste plus qu’Ă implĂ©menter le corps des mĂ©thodes suivantes dans le fichier AgentSpecial.cpp, de maniĂšre Ă dĂ©finir un comportement intelligent !
Maintenant, Ă vous de jouer !
Les rĂšgles du jeu
Les agents combattent sur un plateau constitué de 15 lignes (y allant de 0 à 14) et 15 colonnes (x allant de 0 à 14).
Chaque tour du jeu, un agent peut effectuer jusqu’Ă 4 actions en mĂȘme temps parmi les suivantes :
Ces ordres d’actions peuvent ĂȘtre effectuĂ©s en appelant les mĂ©thodes suivantes (depuis les mĂ©thodes surchargĂ©es dans la classe AgentSpecial) :
- tirer() : en passant « true » pour activer tir en rafale, ou false pour désactiver
- déplacer() : en passant les coordonnées de la case destination (attention de bien choisir une case adjacente dans la limite du plateau)
- orienter() : en passant un des quatre points cardinaux (Nord, Sud, Est, Ouest)
Chaque tour de jeu, l’agent reçoit 5 variables actualisĂ©es qui l’informe de son Ă©tat dans son environnement :
Ces donnĂ©es d’Ă©tat peuvent ĂȘtre rĂ©cupĂ©rĂ©es en appelant les mĂ©thodes suivantes (depuis les mĂ©thodes surchargĂ©es dans la classe AgentSpecial) :
- viesRestantes() : renvoie un entier compris entre 0 et VIE_MAX (Ă©gal Ă 100)
- munitionsRestantes() : renvoie un entier compris entre 0 et MUNITIONS_MAX (Ă©gal Ă 10)
- x(), y(): renvoie un entier compris respectivement entre 0 et X_MAX et 0 et Y_MAX
- orientation() : renvoie un des quatre points cardinaux (Nord, Sud, Est, Ouest)
- distanceFrontale() : renvoie la distance Ă un obstacle devant l’agent (0 si pas d’obstacle en vue)
Modifier le comportement des rendus
Dans MoteurRenduAgentSpecial.hpp et MoteurRenduAgentSpecial.cpp
Initialisation du jeu
Dans main.cpp