Activité pratique

Durée2h30

Consignes globales

Cette activité pratique a pour but de vous préparer au projet PyRat. Elle consiste en deux grandes parties :

  • Vous allez installer le logiciel et écrire votre premier programme pour vous déplacer dans le labyrinthe. Vous allez également mettre en place un dépôt Git, afin de travailler efficacement en groupe.

  • Puis, vous serez guidé(e)s dans l’écriture de votre premier programme PyRat.

Cette mise en place peut être assez longue, mais elle est essentielle pour bien attaquer le projet. Si vous ne parvenez pas à tout faire dans la séance, terminez en dehors avant la prochaine.

N’oubliez pas que nous pouvons vous aider entre les séance via le serveur Discord du cours. Vous devriez dès à présent le rejoindre si ça n’est pas déjà fait.

Contenu de l’activité

1 — Où trouver PyRat ?

Le plus important à connaître est le site principal du logiciel PyRat, qui centralise tous les éléments de prise en main :

  • Documentation : Cette page regroupe les éléments de documentation sur comment installer et utiliser PyRat. La documentation présente aussi l’API PyRat, c’est à dire les fonctions fournies par la bibliothèque. Nous y avons également ajouté quelques tutoriels, qui constitueront la base de cette activité pratique.

    Information

    Comme pour la plupart des logiciels que vous rencontrerez dans votre vie, la documentation de PyRat est rédigée en anglais. Si vous passez par des outils de traduction automatique, il peut arriver d’observer des petites différences avec les termes utilisés dans le cours. N’hésitez pas à en discuter avec nous.

    Important

    Autre remarque, le code de PyRat est également rédigé en anglais. Dans ce projet, nous vous demandons de produire vos codes, commentaires et documentations en anglais également. C’est une pratique essentielle dans le métier d’ingénieur, où vous serez amené(e)s à travailler dans des contextes internationaux.

Voici également quelques liens secondaires, qui pourront vous être utiles plus tard :

  • PyPI : La page de référence pour l’installation de PyRat via pip.

  • GitHub : Ce dépôt GitHub contient les codes sources du logiciel PyRat. Quand nous travaillons à une nouvelle version du logiciel, c’est là que nos modifications sont publiées.

  • GitHub issues : Les issues GitHub sont une sorte de forum, où sont discutés les possibles problèmes rencontrés par les utilisateurs lors de l’installation ou l’utilisation du logiciel. C’est une bonne pratique de consulter cette page si vous rencontrez des difficultés.

2 — Préparer l’environnement du projet

Dans cette section, nous allons préparer l’environnement de travail pour le projet PyRat. Pour cela, nous allons créer l’arborescence de dossiers suivante.

ueinfos5                # Là où vous stockez vos fichiers du cours d'informatique (adaptez à votre organisation)
|_ projet               # Un sous-dossier pour le projet PyRat (à créer dès maintenant)
|_ |_ venv_projet       # L'environnement virtuel (créé en 2.1)
|_ |_ pyrat_workspace   # Le workspace PyRat (créé en 2.2)
|_ |_ |_ games
|_ |_ |_ players
|_ |_ |_ README.md      # Le fichier de description du projet (créé en 2.3.2)
|_ |_ |_ .gitignore     # Un fichier qui indique à Git quoi synchroniser (créé en 2.3.3)
|_ ...
À faire

Créez un dossier projet vide là où vous stockez vos fichiers de cours d’informatique. Puis, ouvrez un terminal et naviguez jusqu’à ce dossier.

Dans ce projet, nous allons travailler avec l’IDE VSCode. Vous pouvez en utiliser un autre si vous préférez, il vous suffira d’adapter les instructions.

1.1 — Créer un environnement virtuel Python

Afin de faciliter la séparation des dépendances d’un projet à l’autre, Python impose de passer par un environnement virtuel pour l’installation de bibliothèques logicielles. Nous allons installer PyRat dans un tel environnement.

À faire

En utilisant le terminal ouvert précédemment, créez un environnement virtuel Python dans le dossier projet (par exemple nommé venv_projet). Puis, activez cet environnement virtuel.

2.2 — Télécharger et installer PyRat

À présent, nous allons installer la bibliothèque PyRat dans l’environnement virtuel venv_projet activé précédemment.

À faire

Trouvez la page décrivant l’installation dans la documentation de PyRat, et suivez les instructions. En cas de soucis, n’hésitez pas à appeler votre enseignant(e).

Une fois PyRat installé, démarrez VSCode, et ouvrez le dossier projet. Via l’arborescence à gauche, ouvrez le fichier games/sample_game.py. Comme venv_projet apparaît dans les dossiers ouverts, VSCode détectera votre environnement virtuel, et vous proposera de l’utiliser automatiquement :

2.3 — Préparer le travail en groupe

Avant de démarrer cette activité pratique, vous avez dû former un trinôme. Si ça n’est pas le cas, faites le maintenant, et informez votre enseignant(e) de sa composition.

On suppose également que vous avez déjà tous créé un compte sur Gitlab ou Github, et créé une clé SSH. Si ça n’est pas le cas, revoilà le lien de la page sur le travail collaboratif avec Git vue en environnement.

2.3.1 — Mise en place du dépôt Git

À présent, nous allons faire en sorte que vous puissiez synchroniser votre dossier pyrat_workspace entre vous.

À faire

Une fois votre trinôme constitué, choisissez l’un(e) d’entre vous (appelons cette personne “Boss” le temps de cette section pour vous motiver à prendre ce rôle :) ), puis suivez les instructions ci-dessous.

  1. Le/la boss crée un projet Git (privé, sans README.md (décochez la case)), via Gitlab ou Github.

  2. Le/la boss initialise ce dépôt grâce aux commandes suivantes :

    # Dans un terminal, placez vous dans le dossier pyrat_workspace
    # Adaptez avec le bon chemin
    cd /chemin/vers/pyrat_workspace
    
    # Initialisez Git dans le dossier courant
    git init --initial-branch=main
    
    # Ajoutez le dépôt existant
    # Adaptez avec la bonne adresse
    git remote add origin https://adresse.de.mon.depot.git
    
    # Ajoutez tous les fichiers du pyrat_workspace
    git add .
    
    # Créez un commit avec le nouveau contenu
    git commit -m "Initialisation du dépôt avec le workspace"
    
    # Poussez vers le serveur
    git push -u origin main
  3. Le/la boss invite les autres étudiants du groupe comme collaborateurs du projet via l’interface de Gitlab ou Github.

    Information

    C’est fini pour le boss (jusqu’à l’étape 5) ! Passons aux autres étudiant(e)s du groupe.

  4. Chaque étudiant(e) non-boss supprime le dossier pyrat_workspace créé par PyRat pendant l’installation. Puis, chacun(e) clone le dépôt au même endroit avec les commandes suivante :

    # Dans un terminal, placez vous dans le dossier qui contenait le pyrat_workspace que vous venez de supprimer
    # Adaptez avec le bon chemin
    cd /chemin/vers/le/dossier/qui/contenait/pyrat_workspace
    
    # Clonez le dépôt
    # Adaptez avec la bonne adresse
    git clone https://adresse.de.mon.depot.git pyrat_workspace

    Cette commande devrait créer un nouveau dossier pyrat_workspace là où se trouvait celui que vous avez supprimé.

    Important

    Attention à ce que ce nouveau dossier soit bien au même endroit et s’appelle bien pyrat_workspace. La raison est que ce chemin a été ajouté dans le PATH par PyRat, ce qui permettra à vos codes Python de s’importer facilement.

    Information

    C’est tout pour les non-boss ! Les instructions restantes concernent tout le monde.

  5. Vérifiez que vous avez bien le bon pyrat_workspace dans votre workspace VSCode.
    Pour vous en rendre compte, cliquez sur le menu Source control à gauche. Vous devriez voir que VSCode a automatiquement détecté votre dépôt Git, et vous propose de gérer vos add, commit, push, etc. directement via son interface.

  6. Vérifiez que PyRat marche bien. Démarrez le script sample_game.py dans le dossier pyrat_workspace/games et exécutez le. Vous devriez voir une partie de PyRat se lancer, comme précédemment.

2.3.2 — Ajout d’un fichier README.md

Dans tout projet informatique, il est important d’avoir un petit fichier qui explique succinctement (ou pas) à quoi sert le projet. On appelle ce fichier un “README”, et on y trouve généralement les adresses de contact des auteurs, les instructions d’utilisation du projet, etc.

Sur les dépôts Git, ce fichier s’appelle classiquement README.md, car on rédige son contenu en Markdown, un langage permettant de formater du texte. Si vous avez déjà utilisé des outils comme Discord, (ou Mattermost, Slack, etc.), c’est généralement ce langage qui est utilisé pour mettre du texte en gras, italique, etc.

À faire

Choisissez l’un(e) d’entre vous qui n’était pas le/la Boss, et appelons cet étudiant(e) “Big Boss” (le temps de cette section, ne prenez pas la grosse tête tout de suite). Puis, suivez les instructions ci-dessous.

  1. Le/la Big Boss crée un fichier README.md dans son workspace PyRat, comme indiqué plus haut.

  2. Une fois le fichier créé, le/la Big Boss y copie-colle le texte suivant (changez les éléments entre <...> par le bon contenu), et sauvegarde le fichier.

    # Description
    
    This is the repository of a PyRat workspace created following instructions [https://hub.imt-atlantique.fr/ueinfo-fise1a/s5/project/session1/practical](provided here).
    It is used to store the codes developed during the PyRat project by the aforementioned students during year 1 at IMT Atlantique.
    
    - <First name> <Name> <mail@imt-atlantique.fr>
    - <First name> <Name> <mail@imt-atlantique.fr>
    - <First name> <Name> <mail@imt-atlantique.fr>
    
    # Repository documentation
    
    <You can write stuff here later>

À présent, votre objectif est de manipuler Git (via l’interface VSCode ou la ligne de commande) pour que :

  • Le fichier README.md apparaisse sur le dépôt.
  • Chaque étudiant du groupe ait une vue locale à jour du dépôt dans son workspace.
2.3.3 — Ajout d’un fichier .gitignore

Quand on réalise un projet avec Git, il faut uniquement versionner les fichiers intéressants (le code, la documentation, éventuellement certaines données, etc.), mais pas les fichiers qui permettent l’exécution du projet (environnement virtuel, fichiers temporaires, etc.).

Pour cela, on peut mettre à la racine du dépôt un fichier nommé .gitignore, dans lequel on liste tous les fichiers et dossiers à ignorer par Git.

À faire

L’étudiant(e) qui n’a pas encore dirigé le groupe devient le/la Méga Boss. Puis, suivez les instructions ci-dessous.

  • Le/la Méga Boss télécharge ce fichier .gitignore standard pour Python, le place dans son dossier pyrat_workspace, comme indiqué plus haut, puis le renomme en .gitignore.

  • Puis, en vous inspirant de ce que vous avez fait pour le fichier README.md plus haut, arrangez vous pour que :

    • Le fichier .gitignore apparaisse sur le dépôt.
    • Chaque étudiant du groupe ait une vue locale à jour du dépôt dans son workspace.

3 — C’est parti !

3.1 — Se familiariser avec PyRat

A ce stade, tout est prêt pour commencer le projet ! Découvrons à présent en quoi consiste le logiciel PyRat. Avant d’attaquer la création de programmes PyRat, étudiez les liens suivants :

  • Découverte de PyRat : Ce lien présente PyRat dans les grandes lignes, à savoir le contenu de pyrat_workspace et de la bibliothèque Python pyrat-game, les élements de jeu, etc.

  • Tutoriels de base : Sur cette page, nous vous proposons quelques tutoriels à suivre, qui détaillent les programmes PyRat fournis par défaut dans le pyrat_workspace, et vous expliquent comment customiser les éléments de jeu.

3.2 — Votre premier programme PyRat

L’objectif de cette activité pratique est d’écrire vos premiers codes PyRat, c’est à dire :

  • Un joueur, sous la forme d’un fichier héritant de la classe Player, décrit dans un fichier du dossier pyrat_workspace/players.
  • Un script, qui lance une partie avec votre joueur, décrit dans un fichier du dossier pyrat_workspace/games.
3.2.1 — Description de la stratégie

Le programme que nous allons écrire est une amélioration de Random4, décrit dans le tutoriel sur les programmes RandomX.

L’un des problèmes de Random4 (que Random3 avait déjà) est que, si le rat arrive dans une zone du labyrinthe où il a visité toutes les cases voisines, il tente de rejoindre une case non visitée en se déplaçant aléatoirement. À partir de là, le rat reprend sa stratégie d’exploration.

On pourrait améliorer cet aspect du programme en gardant en mémoire notre trajectoire, c’est à dire la suite de cases parcourues jusqu’au tour en cours. Ainsi, en arrivant sur une case dont on a déjà visité toutes les cases voisines, il suffirait de revenir en arrière le long de la trajectoire parcourue. Si on arrive sur une case dont on a déjà visité tous les voisins, on recommence, etc. À un moment, à force de revenir sur ses pas, le rat finira par arriver sur une case ayant au moins une case voisine inexplorée, et pourra reprendre sa quête de fromage.

3.2.2 — Création du joueur
À faire

Faites une copie du fichier Random4.py (dans le dossier players), et renommez le nouveau fichier Random5.py (dans le même dossier). Faites toutes les modifications nécessaires pour que ce nouveau fichier décrive une classe nommée Random5.

Ne vous préoccupez pas du comportement du joueur pour le moment, on cherche juste à créer un programme utilisable qui ne crashe pas.

3.2.3 — Création de la partie
À faire

Créez un fichier visualize_random5.py dans le dossier games de votre pyrat_workspace. Ce fichier doit effectuer les opérations détaillées ci-dessous.

  1. Importer la classe Random5 que vous venez de créer.

  2. Créer une partie de PyRat (une instance de la classe Game), contenant 1 morceau de fromage. Pensez aussi à mettre une valeur élevée à l’argument trace_length pour vérifier plus tard que le rat revient bien sur ses traces.

  3. Instancier un joueur de la classe Random5, et l’ajouter à la partie.

  4. Démarrer la partie.

Information

Inspirez vous des tutoriels PyRat, ainsi que des exemples donnés par défaut dans pyrat_workspace/games.

3.2.4 — Implémentez la stratégie
À faire

Maintenant que vous avez un script visualize_random5.py qui lance une partie de PyRat avec le joueur Random5, adaptez le code de Random5.py pour que le rat suive la stratégie décrite plus haut.

N’hésitez pas à lancer régulièrement votre script visualize_random5.py, par exemple pour afficher la trajectoire parcourue, ou pour vérifier que votre code ne crashe pas.

Vous devriez obtenir un rat qui se comporte comme suit. En particulier, il ne devrait pas aller dans des culs de sac (amélioration apportée par Random4), et devrait revenir sur ses pas quand toutes les cases voisines sont déjà visitées.

3.2.5 — Évaluez la stratégie

Maintenant que vous avez une nouvelle stratégie, il faut se poser la question de si elle est vraiment efficace. Pour cela, une approche possible est de la comparer à d’autres méthodes.

À faire

Adaptez le script evaluate_random_players.py fourni à la fin du tutoriel pour ajouter votre joueur Random5 aux quatre autres.

Quelles conclusions tirez-vous ? Discutez-en avec votre enseignant(e) !

Pour aller plus loin

4 — Le joueur Random6

4.1 — Description de la stratégie

Quand Random5 arrive à un croisement amenant à plusieurs cases voisines non visitées, le rat choisit une case aléatoirement parmi celles-ci et s’y dirige.

Imaginons le cas trivial où il n’y a aucun mur, on se dit alors que les directions se rapprochant le plus du fromage (à vol d’oiseau) sont les plus intéressantes. Comme en PyRat on bouge sur une grille, mieux vaut aller vers le nord ou l’est si le fromage est au nord-est. Une stratégie intéressante serait alors de trier les cases voisines non visitées par ordre croissant de distance au fromage, et de privilégier la première.

À faire

Quel est l’impact du nombre de murs sur cette stratégie et son intérêt par rapport à une orientation aléatoire ?

4.2 — Implémentez et évaluez la stratégie

À faire

En vous inspirant de ce que vous avez fait pour Random5, créez un joueur Random6 (et un script dans games pour le tester), qui implémente la stratégie guidée par l’emplacement du fromage.

Vous devriez observer quelque chose comme ça :

À faire

Puis, complétez le script evaluate_random_players.py pour ajouter votre joueur Random6 aux cinq autres. Un avis sur les résultats observés ?

4.3 — Les cas limites

On se posait précédemment la question de si le nombre de murs pouvait poser problème.

À faire

Faites varier ce nombre pour évaluer la densité au delà de laquelle Random6 n’est pas significativement meilleur que Random5. Le plus efficace est de créer un script dans le dossier games pour tester ça dans une boucle qui augmente progressivement la densité de murs.

On avait déjà parlé de significativité dans le tutoriel, n’hésitez pas à relire cette partie.

4.4 — Remarques

Si vous avez suivi toutes les étapes, vous devriez vous rendre compte que votre programme ne comporte plus d’aléatoire du tout !

À faire

Pensez à faire un peu de ménage dans les dépendances de votre fichier Random6.py (qui est du coup assez mal nommé) en enlevant import random.

Une autre remarque est que la distance Euclidéenne utilisée pour trier les voisins non visités ne prend pas en compre la topologie du labyrinthe, ni la boue. Cela s’observe dans la vidéo plus haut, où on voit bien que la portion de chemin 82 -> 95 -> 94 aurait été plus courte que 82 -> 81 -> 94. Il faudra donc passer à des stratégies plus intelligentes pour trouver des chemins plus courts.

Pour aller encore plus loin

5 — Le joueur Random7

La plupart du temps, le fromage va se trouver en diagonale par rapport au rat (par exemple au nord-ouest). Conceptuellement, dans un labyrinthe sans murs, ça ne change pas grand chose d’aller au nord puis à l’ouest, ou d’aller à l’ouest puis au nord. La boue dans le labyrinthe change toutefois cette équivalence. C’est un phénomène que nous avons décrit dans les remarques sur Random6 plus haut.

On pourrait donc améliorer Random6 comme suit : si deux actions réduisent la distance au fromage, on privilégie celle qui amène à la case suivante en un minimum de tours.

À faire

Comme précédemment, créez un joueur Random7 qui implémente cette stratégie, ainsi qu’un script pour lancer une partie avec.

À faire

Puis, complétez le script evaluate_random_players.py pour l’ajouter aux autres. Est-ce que cet ajout améliore significativement les performances moyennes par rapport à Random6 ?

6 — Suivre le mur

On dit parfois que quand on est perdu dans un labyrinthe, il suffit de poser une main sur un mur, et d’avancer sans jamais décoller sa main. On teste ?

À faire

Prenez quelques minutes pour essayer d’imaginer les cas où cette stratégie peut fonctionner, pour partir d’une case et arriver au morceau de fromage.

Une fois que vous avez identifié ce qui marche, créez un script dans games pour créer ce contexte, puis créez un joueur pour réaliser cette stratégie.

7 — Factoriser tout ça

Maintenant que vous avez codé 7 programmes aléatoires, vous devez vous apercevoir qu’il y a un certain nombre de redondances dans vos codes. En particulier, la fonction remove_dead_ends(...) introduite à partir de Random4 apparaît probablement dans tous les fichiers développés par la suite, vu que ce pré-traitement est relativement indépendant de la stratégie de déplacement.

Maintenant, imaginons que vous découvriez une erreur dans le code de cette fonction. Pour la corriger, il va falloir fouiller dans tous vos fichiers pour changer toutes les copies de remove_dead_ends(...). C’est problématique, car vous allez perdre du temps, et peut-être introduire de nouvelles erreurs sans faire exprès…

À faire

Prenez un moment pour réfléchir aux contenus de vos programmes aléatoires. Comment pourriez-vous exploiter le paradigme orienté objet pour mieux organiser tout ça ? Est-ce que votre nouvelle organisation permet également de factoriser des éléments développés pour le programme qui suit le mur ?