# Projet de Programmation 2 - Simulateur de fourmi

## Rapport de projet

### Présentation du groupe et étapes du travail

Les personnes qui composent ce groupe de travail sont:
- Dimitri LEREVEREND
- Lucas DE-MEYER
- Pablo ESPANA GUTIERREZ
- Jade GARCIA BOURREE.

Dans notre équipe, le travail a bien été réparti dans le groupe. Nous avons d'abord tous les quatre commencé à réfléchir à la structure de données et du programme avant de nous lancer. Nous nous sommes ensuite répartis les rôles intuitivement: lorsque quelqu'un finissait une tâche il entamait une autre parmi la liste des choses à faire ou bien il aidait ses camarades.

Dans un second temps, lorsque les codes commençaient à affluer, Dimitri et Jade se sont occupé de debugguer la simulation pendant que Pablo et Lucas se consacraient à l'animation. Cette étape a été un peu plus longue que prévu.

Le troisième jour, comme Lucas devait partir, il s'est occupé (entre autres) de faire de nouveaux "skins" pour l'animation tandis que le reste du groupe finissait le travail (à savoir fixer les bugs restants, faire le menu de début de jeu, améliorer l'affichage et ses options, nettoyer le code, faire la partie III...). À ce moment là, nous avons choisi la façon dont nous allions traiter la partie III du sujet. Pour cela nous proposons le mode de simulation "debug" qui permet de suivre une fourmi au cours d'une simulation. Le détail est expliqué dans une partie ultérieure de ce fichier.

### *Simulation*

Cette partie ne contient pas d'interface graphique. On a fait quelque chose d'un peu plus fort que ce qui était demandé en ajoutant un nombre d'équipe possible variable. On peut avoir entre une et vingt-six équipes différentes. Les bases des fourmis dans les maps sont alors encodées en ASCII par les lettres en minuscules (entre a et z). Chaque lettre représente une fourmilière. Il faut penser à mettre le même nombre de stratégie que ce qu'il y a de fourmilières et à utiliser les lettres dans l'ordre (pas 'a', 'c' sans le 'b' par exemple).

De plus, par souci de respecter les anciennes maps, les codages de fourmilières avec '+' et '-' sont toujours reconnus et fonctionnent pour deux joueurs.

Cependant, on notera que la ligne de commande pour lancer la simulation est **Simulator.java monde.world strat1.brain ... stratN.brain**.

**Nos outils pour cette partie:**

Pour réaliser la simulation nous avons crée de nouvelles classes et de nouveaux objets.

#### la classe abstraite **MapObject**:

Elle va représenter tous les objets qui sont sur la map (fourmis, bases, cailloux et marqueurs) avec certaines de leur caractérisations. Les attributs sont là pour faciliter la manipulation des objets dans notre code et les méthodes pour tester la nature d'un objet.

#### la classe **Ant**

Elle regroupera toutes les fourmis d'une simulation et étend la classe MapObject. Chaque fourmi possède:
- un accès au programme de sa fourmilière: *prog*
- une mémorisation de la liste d'instructions courante (bloc) qu'elle doit exécuter : *currentBlock*
- une mémorisation de la prochaine instruction qu'elle doit exécuter (numéro de la ligne du bloc courant) : *currentLine*
- un booléen pour savoir si elle possède de la nourriture sur elle (notamment pour les conditions type "FoeWithFood" et "FriendWithFood") : *hasFood*
- un compteur qui représente la fatigue de la fourmi (pour avoir un temps d'attente de quatorze tours à la suite d'un move) : *sleepCounter*
- des tableaux directionnels pour faire les changements d'orientations ou de direction de la fourmi : *dx* et *dy*

Avant chaque exécution d'instruction, la fourmi doit vérifier qu'elle ne soit pas tuée grâce à la fonction : *IsCercled*. Pour être parfaitement honnête il y a un problème lorsque une fourmi meurt car la liste sur laquelle on itère perd un élément avant qu'elle ne soit parcourue en entier. Cependant l'erreur est rattrapée et cela ne change pas la suite de la simulation. Nous n'avons pas eu le temps de résoudre le problème.

#### La classe **Base**

Cette classe sert à garder en mémoire la position des bases dans la map et à savoir à quelle fourmilière appartient une case. Elle servira notamment à faire la mise à jour des scores des joueurs. Elle étend la classe MapObject.

#### La classe **Cell**

Cette classe est très riche car elle est essentielle à la simulation.

Une cell est une case de la map. Chaque case possède:
- un objet de type marker qui contient les marqueurs de la case pour toutes les fourmis : *marker*
- un object de type Food qui contient l'information de la nourriture sur la case et permet d'appliquer les fonctions sur la nourriture (Pick, Drop, mise à jour des scores).
- une liste d'objets qui sont en transit (ou définitivement) sur la cellule. Ils peuvent être de différentes natures: fourmi (au plus une par case), caillou ou base : *content*

Remarque: la gestion de ces attributs n'est pas forcément la plus logique ou la plus optimisée qui soit. En effet on aurait pu se passer de *content* et mieux spécifier les attributs. Nous avons manqué de temps pour tout changer.

Toutes les méthodes attachées à la classe **Cell** servent à tester des conditions, à traiter les cellules (initialisation et mise à jour) ou à obtenir de l'information sur l'état de la cellule.

#### La classe **FoodObject**

Cette classe est tout simplement une représentation de la nourriture sur la carte. Elle contient des méthodes utilisées par les fourmis. Elle étend la classe MapObject.

#### La classe **Marker**

Cette classe étend la classe MapObject. Elle permet de connaître les marqueurs sur une cellule donnée. Chaque objet de type marqueur possède:
- un tableau (de taille le nombre d'équipe sur le plateau) pour indiquer si une équipe a un marqueur actif : *empty*. La i-ème case est 'true' si la i-ème équipe n'a pas de marqueur actif et 'false' s'il y en a au moins un. Ce tableau est utile pour les conditions de type 'FoeMarker' : *markerList*
- un tableau à deux dimensions pour stocker les marqueurs. Chaque équipe possède une ligne du tableau. La i-ème colonne représente le i-ème bit de marqueur au sol.
- une mémoire du nombre d'équipe en jeux (pour les méthodes et la création des tableaux) : *nbTeamMax*

Remarque: la deuxième variable est appelée list alors que c'est un tableau... Et on aurait pu stocker des booléens à la place des entiers 0 ou 1 dans le tableau *markerList*.

#### La classe **RockObject**

Cette classe est tout simplement une représentation des cailloux sur la carte. Elle contient des méthodes utilisées par les fourmis. Elle étend la classe MapObject.

#### La classe **World**s

Cette classe est une classe générale qui représente le monde (sous-entendu carte, numérotation des fourmis, temps et score). Dans la simulation il y a un unique objet de ce type. Les attributs de cette classe sont:
- la taille de la carte : *sizex*, *sizey*
- le tableau a deux dimensions des cellules qui représente la carte et ses objets: *map*
- une liste de fourmis qui permet de traiter à chaque tour les fourmis dans le bon ordre *antFamily*
- le compteur entier de temps *time*
- un tableau des scores. La i-ème case est le score de la i-ème fourmilière. *score*


### Animation

On notera que la ligne de commande pour lancer la simulation est **Main.java monde.world strat1.brain ... stratN.brain**.

À l'origine, nous avions un rêve. Dans celui-ci, le jeu disposait d'un menu. Dans ce menu, nous pouvions tout choisir. Dans ce choix, nous étions libre d'exprimer notre créativité. Nous pouvions alors choisir des skins, tant pour notre fourmi favorite que pour des rochers. Les fourmis pouvaient alors être des abeilles ou des petits chat, et les rochers des shurikens. Le tout devait se dérouler enchanté par une douce musique. Toutefois, les contraintes de la réalité (et principalement de temps), nous on mis à mal. Nous nous somme donc battus, afin de réaliser ce rêve au maximum.


Cette partie consistait principalement en la création d'un canvas, sur lequel on place les boutons, qui eux même déclenchent l'animation.
Toute l'animation est gérée par la classe Main, dans laquelle on crée tout les objets.
Nous avons également crée un package *ant.sprite*, dans lequel nous avons placés tous nos skins des différents objets. Ces derniers sont en fait des ensembles de Points.

Dans Main, nous avons une boucle *AnimationTimer* qui permet de gérer l'affichage du canvas. Au départ, ce canvas sert à choisir les apparences des fourmis. Ainsi, nous affichons autant de fourmis qu'il y a de joueurs et nous permettons à l'utilisateur de changer chacune des apparences grâce aux touches Z Q S D.
Une fois les apparences choisies et le bouton *Let's go* appuyé, le canvas s'efface et laisse place au terrain de jeu. À chaque itération du simulateur, le programme va attendre un certain temps (dépendant de la vitesse choisie par l'utilisateur) puis mettre à jour les graphiques. Tout comme un dessin animé, tout est effacé puis redessiné à chaque itération. Nous n'avons pas remarqué de problèmes de perfomances nous incitant à changer cette méthode.

#### Les objets "Skin"

Ces objets servent uniquement à l'affichage. FoodSkin, RockSkin et AntSkins permettent également de changer d'apparences selon paramètre donné en entrée.


#### Le package *ant.sprite*

Ce package contient les skins des objets pour l'animation (**RockSkin**, **AntSkins**, **Heaxagon**, **FoodSkin**) et des classes définissant des fonctions sur les formes dont héritent les skins (**Polygon**, **Circle**, **Point**, **Shape**).

Le choix des skins pour les différents joueurs se fait par les touches 'z', 'q', 's' et 'd'.

#### Let's go
L'animation est gérée une fois le deuxième bouton *button2* sélectionné, nommé sagement *Let's go*. On commence par créer un monde de type *World* en appelant *Simulator* sur les arguments, c'est-à-dire la carte et les stratégies. Grâce à ce monde, on peut dessiner tous les objets des *Cell* dans l'ordre pour faire apparaître le plateau initial. En effet, on parcourt le tableau pour dessiner le contenu de chaque cellule une par une. Ensuite, à chaque période de temps, on appelle *updateStep* pour mettre à jour la simulation, et ainsi, on met à jour les objets du *World*. Pour afficher le nouveau plateau, de la même que l'exemple de *Asteroids* ou dans les anciens dessins-animés, on dessine un rectangle par dessus l'ancien plateau pour redessiner un nouveau plateau correspondant au nouveau monde.
Ensuite, de nouveaux boutons sont aussi affichés afin de contrôler le zoom (*+* et *-*) et la vitesse (*<<* et *>>*).


### Débogage

Afin de déboguer un code de fourmi, nous avons pensé à l'idée de pouvoir sélectionner une fourmi particulière dans le simulateur et de pouvoir avoir accès aux instructions qu'elle exécute. Nous avons donc une variable *targetedAnts*, qui correspond soit au numéro de la fourmi choisie (indice dans la liste AntFamily), soit à un nombre négatif si le mode débogage est désactivé (par défaut). Ainsi, à l'aide de 2 boutons, l'utilisateur change cette variable afin de changer les points de vue des différentes fourmis durant la partie. La fourmi est mise en surbrillance sur le terrain de jeu afin de pouvoir la suivre en parallèle. Tout cela se réalise dans la boucle qui itère sur les fourmis en jeu.

Nous aurions également voulu pouvoir "remonter dans le temps" afin de pouvoir revoir certaines actions pour mieux les analyser. Pour cela, nous aurions fait une liste de "mondes", enregistrés toutes les centaines d'itérations, afin de pouvoir naviguer parmi ces configurations passés avec des boutons puis relancer le simulateur. Par faute de temps, nous n'avons malheureusement pas pu réaliser cette idée (et parce que cette méthode aurait été trop gourmande en espace).

### Remarques
- Nous n'avons pas touché aux fichiers du dossier *syntax*. Il aurait été possible de fusion certains d'entre eux avec ceux que nous avons crée dans le dossier "object" mais cela n'a pas été notre priorité.
- Nous avons recodé nos propres listes (utilisé ce qu'on avait fait en TP) et oublié de les rechanger après. C'est complètement bête de notre part et nous nous excusons de cet oubli.

### Conclusion
Nous avons réussi à faire ce qui était attendu nous sommes donc assez fiers de notre travail accompli.

De plus nous avons ajouté quelques options sympathiques à notre travail à savoir: pouvoir jouer à plus de deux équipes, pouvoir sélectionner son équipement personnalisé dans le jeu et nous étions vraiment à deux doigts de réussir à mettre une musique en fond de tâche.
