diff --git a/README.md b/README.md index 6f67073..1becaaf 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ C'est un projet de fin de Licence L1 en Informatique à UPEC, la création d'un - La partie **PROBLÈME ET SOLUTION RENCONTRÉES** -## AVANT TOUT : Comment lancer le jeu. +## AVANT TOUT : Comment lancer le jeu Pour lancer le jeu, nous pouvons utiliser les addons de vscode en appuyant sur ***run*** sur la methode **main**. @@ -35,6 +35,7 @@ Les commandes pour le makefile : - `Make run` : il va uniquement lancer l'interpréteur java (Attention à ne pas supprimer le bin avant) Pour lancer le jeu en multijoueur avec Makefile (mot1 et mot2 sont des mots à changer en fonction du canal): + - `Make channel=mot1 adversaire=mot2` : compile tout le programme et le lance en multijoueur. - `Make run channel=mot1 adversaire=mot2` : lance uniquement le programme en multijoueur. @@ -42,6 +43,67 @@ Sur windows, vous avez une autre option que personnellement je vous encourage, c - `run.bat mot1 mot2` : il va uniquement lancer `Make channel=mot1 adversaire=mot2` et en même temps lancer `chcp 65001` qui va mettre l'utf-8. +## Fichier de configuration + +- Le fichier de configuration sert à créer une partie sans recompiler en `.class` le programme. Étant en format xml, il ressemble à des balises html et donc plus facile à comprendre. + +Pour que le programme comprenne le fichier xml, il doit y avoir des balises spécifiques: + +- `Configuration` est la racine du programme, il a comme attribut n pour la taille du snake. Exemple : + + ```xml + + ``` + +- `Map` est la balise principale pour la gestion de la carte du jeu. Il y a comme attribut la taille x et y de la carte. Il permet aussi de placer les balises fraises et des murs. Exemple : + + ```xml + + ``` + +- `Fraise` et `Wall` sont des balises pour placer une fraise ou un mur avec comme attributs x et y. Exemple : + + ```xml + + + ``` + +- `Personnage` est la balise principale pour la gestion des personnages du jeu. Il permet de placer des balises IA, Robot et Player. Exemple : + + ```xml + + ``` + +- `Player`, `Robot` et `IA` sont des balises pour placer des personnages avec des attributs comme name, x et y. Sur la balise IA, on doit aussi mettre QTable avec le dossier ou le fichier qui sert a stocker l'apprentissage de l'IA. Exemple : + + ```xml + + + + ``` + +**Exemple de configuration :** + +```xml + + + + + + + + + + + + + + + + +``` + +`` # JEU et GAMEPLAY @@ -66,7 +128,6 @@ Le channel récupère les données contenues sur le channel qui y est dédié (l Nous avons testé Channel à distance sur 2 machines et la partie s'est déroulée correctement. - # IA (Q-Learning) ## - Explications @@ -95,11 +156,14 @@ Ce calcul sera la valeur de toutes les actions que l'IA va enregistrer dans sa b - $Q(s_t, a_t)$ : est la valeur de Q actuelle, il contient $s_t$ qui l'état et $a_t$ qui est l'action de Q. - $\alpha$ : est le taux d'apprentissage, c'est lui qui détermine si on doit écraser les valeurs ou non. + - $R_t$ : est la récompense de l'action, si c'est une bonne action ou non. + - $\gamma$ : est l'importance des futures récompenses. + - $\max(Q(s_{t+1}, a))$ : est la valeur maximale de Q du prochain tour parmi toute sa base de donnée. -## Resultat : +## Resultat : ![IA](res/video/ia_solo_15min_apprentissage.gif) @@ -116,7 +180,7 @@ Quand elle est coincée et qu'aucune des cases l'entourant n'est un choix possib Les choix qu'elle fait sont donc partiellement aléatoires et évitent essentiellement une mort au coup suivant. -# GRAPHIQUE +# GRAPHIQUE Nous avons utiliser le terminal pour faire notre parti graphique avec de l'utf-8, il est très important d'activer l'utf-8 sur les terminaux avant de lancer le jeu car vous pourrez avoir des problèmes comme des "?". @@ -129,7 +193,7 @@ Cependant, grâce à lui j'ai énormément appris et son aide m'a souvent été Je trouve notre projet bien construit, utilisant des moyens adaptés à chacuns des points du jeu. La division des classes est pertinente et les commentaires apportent une grande plus-value à ceux qui voudrait l'utiliser. -## - Impressions GUEZO Loïc +## - Impressions GUEZO Loïc: Durant ce projet, j'ai pu tester et apprendre de nouvelles choses. J'ai pu aussi "tester" à gérer une "mini équipe" (on etait que 2). Mon camarade s'est quand même bien débrouillé comparé à notre différence de penser et comment gérer les problèmes. diff --git a/src/Main.java b/src/Main.java index 2540970..e2a1628 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,13 +1,7 @@ -import java.io.File; -import java.io.ObjectInputFilter.Config; -import java.util.ArrayList; - import configuration.ConfigGame; import game.Terminal; import game.environnement.*; import personnage.*; -import personnage.IAQLearning.QTable; -import tests.IATest; public class Main { /** diff --git a/src/conf.xml b/src/conf.xml index a322037..f2c6f58 100644 --- a/src/conf.xml +++ b/src/conf.xml @@ -1,22 +1,13 @@ - - + - - - - - - - + - - - + \ No newline at end of file diff --git a/src/configuration/ConfigGame.java b/src/configuration/ConfigGame.java index f280eb5..71750ad 100644 --- a/src/configuration/ConfigGame.java +++ b/src/configuration/ConfigGame.java @@ -23,21 +23,27 @@ public class ConfigGame { try { FileReaderXml fileReaderXml = new FileReaderXml(path); this.data = fileReaderXml.getElements(); + + if (this.data.get("Configuration") == null || this.data == null) { + System.err.println("Erreur: le fichier de configuration est introuvable."); + System.exit(-1); + } + } catch (IOException | SAXException | ParserConfigurationException e) { e.printStackTrace(); } } public Map getMap() { - ArrayList> mapList = data.get("Map.Coordinate"); + ArrayList> mapList = data.get("Configuration.Map"); - if (data.get("Configuration.Map") == null) { + if (mapList == null) { System.err.println("Erreur: La balise Map est introuvable."); System.exit(-1); } if (mapList.size() != 1) { - System.err.println("Erreur: Plusieurs Coordonnées trouvées."); + System.err.println("Erreur: Plusieurs ou Aucune Coordonnées trouvées."); System.exit(-1); } @@ -52,13 +58,13 @@ public class ConfigGame { } public int getN() { - ArrayList> n; + HashMap n; - if ((n = data.get("Configuration.Size")) == null) { + if ((n = data.get("Configuration").get(0)).isEmpty()) { return 4; } - return Integer.parseInt(n.get(0).get("n")); + return Integer.parseInt(n.get("n")); } public Personnage[] getPersonnages() { diff --git a/src/configuration/FileReaderXml.java b/src/configuration/FileReaderXml.java index 3ab0a70..97f1657 100644 --- a/src/configuration/FileReaderXml.java +++ b/src/configuration/FileReaderXml.java @@ -36,36 +36,39 @@ public class FileReaderXml { protected HashMap>> getElements() { HashMap>> elementsMap = new HashMap<>(); - NodeList nodeList = document.getDocumentElement().getChildNodes(); + Node nodeList = document.getDocumentElement(); readElements(elementsMap, nodeList); - + return elementsMap; } - private void readElements(HashMap>> elementsMap, NodeList nodeList) { - for (int i = 0; i < nodeList.getLength(); i++) { - Node childNodeList = nodeList.item(i); + private void readElements(HashMap>> elementsMap, Node currentNode) { + if (currentNode.getNodeType() == Node.ELEMENT_NODE) { + HashMap attributeMap = new HashMap<>(); + NamedNodeMap attributes = currentNode.getAttributes(); + for (int j = 0; j < attributes.getLength(); j++) { + Node attribute = attributes.item(j); + attributeMap.put(attribute.getNodeName(), attribute.getNodeValue()); + } + + String parentNodeName, fullNodeName; + + if ((parentNodeName = currentNode.getParentNode().getNodeName()).charAt(0) == '#') { + fullNodeName = currentNode.getNodeName(); + } else { + fullNodeName = parentNodeName + "." + currentNode.getNodeName(); + } - if (childNodeList.getNodeType() == Node.ELEMENT_NODE) { - HashMap attributeMap = new HashMap<>(); - NamedNodeMap attributes = childNodeList.getAttributes(); - for (int j = 0; j < attributes.getLength(); j++) { - Node attribute = attributes.item(j); - attributeMap.put(attribute.getNodeName(), attribute.getNodeValue()); - } + if (!elementsMap.containsKey(fullNodeName)) { + elementsMap.put(fullNodeName, new ArrayList<>()); + } - String fullNodeName = childNodeList.getParentNode().getNodeName() + "." + childNodeList.getNodeName(); - - if (!elementsMap.containsKey(fullNodeName)) { - elementsMap.put(fullNodeName, new ArrayList<>()); - } - - elementsMap.get(fullNodeName).add(attributeMap); - - if (childNodeList.hasChildNodes()) { - readElements(elementsMap, childNodeList.getChildNodes()); - } + elementsMap.get(fullNodeName).add(attributeMap); + + NodeList childNodes = currentNode.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + readElements(elementsMap, childNodes.item(i)); } } } diff --git a/src/tests/IATest.java b/src/tests/IATest.java index 6e35995..f490462 100644 --- a/src/tests/IATest.java +++ b/src/tests/IATest.java @@ -3,8 +3,6 @@ package tests; import java.io.File; import java.util.Arrays; -import display.Display; -import game.environnement.Grid; import game.environnement.Map; import personnage.IA; import personnage.Personnage; diff --git a/src/tests/XmlReaderTest.java b/src/tests/XmlReaderTest.java index 73a1aa9..dfd6f4d 100644 --- a/src/tests/XmlReaderTest.java +++ b/src/tests/XmlReaderTest.java @@ -5,8 +5,6 @@ import configuration.ConfigGame; public class XmlReaderTest { public static void main(String[] args) { ConfigGame configXml = new ConfigGame(null); - System.out.println(configXml.getPersonnages()); - System.out.println(configXml.getN()); System.out.println(configXml.getMap()); } }