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é :

Code 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.

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.

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.

  1. Quelle est la classe concernée par cette modification ?

  2. Quelle est le type d’objet le plus adaptée pour réaliser l’association ?

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.

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.

  1. Quelle est la classe concernée par cette modification ?

  2. 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.

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.

Astuce

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.

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 <someone> 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.

  1. Quel est la classe concernée par l’ajout de la méthode get_msg() ?

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.

Astuce

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.