.. raw:: html .. role:: greenbox .. role:: whitebox .. _05characters: Ajouter des personnages non joueurs =================================== L'objectif de cette partie est d'ajouter des personnages dans les différents lieux de la map, et de permettre au joueur d'interagir avec eux. Par la suite, ces personnages seront appelés des personnages non joueurs (PNJ). GitHub stuff ------------ Ouvrir la ``[REPOSITORY_HOMEPAGE]`` et démarrer le codespace associé : :greenbox:`Code` :greenbox:`Codespaces` A partir du terminal du codespace, récupérer la dernière version du jeu depuis votre dépôt :: $ git pull Utiliser l'extension ``GitLens`` pour examiner l'historique des commits, et en particulier les différences entre la version actuelle et la version précédente. Créer un PNJ ------------ Tous les personnages non joueurs auront des caractéristiques communes. Il est donc intéressant de créer une classe ``Character`` qui permettra de les instancier. .. note:: On pourrait remarquer que la classe ``Character`` est très similaire à la classe ``Player``. En effet, le joueur et les personnages non joueurs ont un nom, une description, un lieu dans lequel ils sont, une façon de se déplacer, etc. On pourrait donc imaginer que les classes ``Character`` et ``Player`` héritent d'une même classe mère qui contiendrait les attributs/méthodes communs aux deux classes. C'est un développement intéressant qu'on pourra aborder de façon optionnelle plus tard. .. admonition:: A faire Créer un fichier ``character.py`` dans le répertoire ``v5``. Ce fichier contiendra la classe ``Character``. Cette classe sera utilisée pour représenter les différents personnages non joueurs. Elle contiendra les attributs suivants : - ``name`` : le nom du personnage ; - ``description`` : la description du personnage ; - ``current_room`` : le lieu où se trouve le personnage ; - ``msgs`` : une liste des messages à afficher lorsque le joueur interroge le personnage non joueur. Comme pour les lieux et les items, on a besoin d'une représentation textuelle des personnages non joueurs. .. admonition:: A faire Redéfinir la méthode ``__str__()`` pour qu'elle retourne une représentation textuelle du personnage. Un exemple:: >>> from room import Room >>> forest = Room("Forest", "une forêt enchantée. Vous entendez une brise légère à travers la cime des arbres.") >>> gandalf = Character("Gandalf", "un magicien blanc", forest, ["Abracadabra !"]) >>> print(gandalf) Gandalf : un magicien blanc Intégrer les PNJ à la map ------------------------- Pour intégrer les personnages non joueurs dans le jeu, il faut pouvoir les associer aux lieux, à l'image de ce qu'on a fait pour la classe ``Item``. .. quiz:: quizz-01 :title: Intégrer les personnages non joueurs #. :quiz:`{"type":"FB","answer":"Room", "size":15}` Quelle est la classe concernée par cette modification ? #. :quiz:`{"type":"FB","answer":"dict", "size":15}` Quelle est le type d'objet le plus adaptée pour réaliser l'association ? .. admonition:: A faire Modifier la classe identifiée ci dessus pour qu'elle contienne un attribut ``characters`` qui référence les personnages non joueurs présents dans le lieu. Cette structure de données doit être initialisée à vide. Elle sera renseignée depuis la classe ``Game``, dans la fonction ``setup()``, comme on l'a fait pour les items. .. admonition:: A faire La commande ``look`` permettant d'observer l'environnement du lieu où se trouve le joueur doit maintenant permettre d'afficher, non seulement les items, mais également les personnages non joueurs présents dans le lieu. .. quiz:: quizz-02 :title: Modifier la méthode adéquate #. :quiz:`{"type":"FB","answer":"Room", "size":15}` Quelle est la classe concernée par cette modification ? #. :quiz:`{"type":"FB","answer":"get_inventory", "size":15}` Quelle est la méthode de cette classe concernée par cette modification ? Modifier la méthode identifiée ci dessus pour produire un affichage des items et des personnages non joueurs présents dans le lieu. Un exemple d'exécution est donné ci dessous:: > look On voit: - shield : un bouclier léger et résistant (1 kg) - Gandalf : un magicien blanc Déplacer les PNJ ---------------- Pour donner un peu de dynamisme au jeu, on va faire en sorte que les personnages non joueurs se déplacent d'un lieu à l'autre. .. admonition:: A faire Pour cela, on va créer une méthode ``move()`` sans paramètres, qui fonctionne de la façon suivante. A chaque tour de jeu : - le personnage non joueur a une chance sur deux de se déplacer ou de rester sur place ; - s'il se déplace, il va dans une pièce adjacente au hasard. .. tip:: La fonction ``random.choice()`` permet de choisir un élément au hasard dans une liste selon une loi de probabilité uniforme. Par exemple, pour choisir un élément au hasard dans une liste ``l`` on peut écrire ``random.choice(l)``. La méthode ``move()`` doit retourner ``True`` si le personnage non joueur s'est déplacé, et ``False`` sinon. Maintenant que le jeu est dynamique (les personnages non joueurs se déplacent), il est intéressant de pouvoir vérifier le bon déroulement du jeu, au fur et à mesure de son exécution. .. admonition:: A faire Créer une variable booléenne ``DEBUG`` dans ``game.py`` pour contrôler l'affichage. Si cette variable est ``True``, alors le jeu affiche les messages de débogage placés judicieusement dans les classes/méthodes dont on veut contrôler le fonctionnement. Sinon, il n'affiche que les messages de l'utilisateur. Cette variable devra être importée dans les modules pour lesquels on souhaite contrôler l'affichage des messages de débogage. Par exemple, on pourra écrire dans le module concerné:: from game import DEBUG ... if DEBUG: print("DEBUG: message") Interagir avec les PNJ ---------------------- Pour l'intérêt du jeu, le joueur doit pouvoir interagir avec les personnages non joueurs. Pour cela, on va créer une command ``talk `` déclenchant une action ``talk()`` sur le personnage non joueur passé en argument. Cette action devra appeler une méthode ``get_msg()`` définie dans la classe appropriée. .. quiz:: quizz-03 :title: Faire parler le PNJ #. :quiz:`{"type":"FB","answer":"Character", "size":15}` Quel est la classe concernée par l'ajout de la méthode ``get_msg()`` ? .. admonition:: A faire Créer la méthode ``get_msg()`` dans la classe identifiée ci dessus. Cette méthode doit afficher cycliquement les messages associés au personnage non joueur. Ce qui signifie qu'il faudra garder la mémoire des messages déjà affichés, et ne plus les afficher lors des appels suivants à cette méthode. .. tip:: Pour cela, on pourra utiliser la méthode ``pop(i)`` de la classe ``list`` qui permet de supprimer et retourner le ième élément d'une liste. Par exemple, pour supprimer et retourner le premier élément de la liste ``l``, on peut écrire ``l.pop(0)``. Si on crée un PNJ de la façon suivante:: gandalf = Character("Gandalf", "un magicien blanc", forest, ["Je suis Gandalf", "Abracadabra !"]) L'exécution doit produire un résultat similaire à:: > talk gandalf Je suis Gandalf > talk gandalf Abracadabra ! > talk gandalf Je suis Gandalf En choisissant astucieusement les items et les lieux où se trouvent les personnages non joueurs, on peut créer des situations de jeu intéressantes. On peut imaginer que le personnage non joueur ne parle qu'après avoir trouvé un objet particulier. Ou donne un indice pour trouver (ou interagir avec) un objet ou un autre personnage non joueur. Ces situations nécessitent des développements supplémentaires. La suite... ----------- A cette étape, votre dépôt doit contenir les seuls fichiers suivants : - ``actions.py`` - ``character.py`` - ``command.py`` - ``game.py`` - ``item.py`` - ``player.py`` - ``room.py`` Le jeu doit être fonctionnel et avoir intégré les consignes précédentes. La commande :: $ python game.py doit pouvoir permettre d'activer la fonction ``back`` sans erreur. GitHub stuff ------------ Enregistrer les modifications apportées aux fichiers dans le repo local au codespace :: $ git add . $ git commit -m "Ajouter des personnages non joueurs" Pour référencer plus facilement cette version dans le futur, créer un tag :: $ git tag v5 Synchroniser votre codespace avec votre dépôt GitHub :: $ git push Vérifier que les modifications sont bien présentes dans le dépôt GitHub.