Hier, nous avons commencé à écrire notre première fiction interactive en Inform 6 ; nous avons réussi à créer la première (et unique) pièce du jeu, ainsi qu’un texte introductif. Aujourd’hui, nous allons rajouter quelques petites choses pour en faire un jeu court.
Objets
Comme je l’ai dit hier, la structure de base d’Inform 6 est l’objet. Le premier objet que nous avons créé est une pièce blanche, notre lieu ; nous avons indiqué le nom qui devrait s’afficher, sa description, et le fait que cette pièce soit illuminée. Nous allons créer un objet de plus : ça sera un miroir. Comme hier, nous commençons par créer le miroir, en indiquant son nom et sa description :
Object miroir "miroir" with description "Vous vous regardez dans le miroir. Vous n'avez pas l'air mal en point.";
Il faut également indiquer que le miroir se trouve dans la pièce blanche ; on fait ceci en ajoutant le nom du lieu après le nom complet de l’objet :
Object miroir "miroir" piece with description "Vous vous regardez dans le miroir. Vous n'avez pas l'air mal en point.";
Si l’on fait ceci et qu’on lance le jeu, on obtient :
Vous vous réveillez en sursaut. Autour de vous, du blanc à l'infini. Une pièce complètement blanche… Mon premier programme Inform 6 Par un nouveau programmeur Release 1 / Serial number 170709 / Inform v6.33 Library 6/11 Une pièce blanche Vous ignorez où vous vous trouvez, et comment vous êtes arrivé là. Ce qui est sûr, c'est qu'il n'y a pas beaucoup de choses à voir ici… Vous pouvez voir un miroir. >examiner miroir Vous ne voyez rien de tel, à moins que cela ne soit sans grande importance. >casser miroir Vous ne voyez rien de tel, à moins que cela ne soit sans grande importance.
Que se passe-t-il ? En fait, quand nous avons défini notre miroir, nous n’avons pas indiqué quels mots se référaient au miroir — et Inform 6 ne sait pas les déduire automatiquement. Il faut donc ajouter les mots qui se réfèrent au nom de l’objet, dans la propriété name
:
Object miroir "miroir" piece with description "Vous vous regardez dans le miroir. Vous n'avez pas l'air mal en point.", name 'grand' 'miroir' 'sur' 'pied';
Avec ceci, nous avons :
>examiner grand miroir Vous vous regardez dans le miroir. Vous n'avez pas l'air mal en point.
Pour finir cet objet, nous allons modifier notre code de façon à ce qu’il soit mentionné directement dans la description du lieu. Si l’on ne fait pas ça, Inform ajoute automatiquement la liste des objets présents dans la salle, mais c’est vu comme un peu disgracieux ; ça fait un peu « voici la liste des objets avec lesquels vous avez le droit d’interagir et puis c’est tout », et ça casse un peu notre description d’avant. Nous allons donc donner l’attribut concealed
(caché) à notre objet : l’objet ne sera pas alors mis en évidence par Inform, mais le joueur n’aura quand même pas de problème pour interagir avec. Mais en fait, on peut aussi rajouter un attribut supplémentaire, scenery
(décor) : cet attribut indique que l’objet est non seulement caché, mais qu’il fait également partie des « murs », c’est-à-dire qu’il ne peut pas être pris par le joueur. Ça donne :
Object piece "Une pièce blanche" with description "Vous ignorez où vous vous trouvez, et comment vous êtes arrivé là. Ce qui est sûr, c'est qu'il n'y a pas beaucoup de choses à voir ici... Un grand miroir sur pied se tient devant vous.", has light; Object miroir "miroir" piece with description "Vous vous regardez dans le miroir. Vous n'avez pas l'air mal en point.", name 'grand' 'miroir' 'sur' 'pied', has scenery concealed;
Ajoutons des actions spéciales avec « before »
Nous avons désormais un objet, un grand miroir sur pied ; mais pour l’instant, on ne peut pas faire grand-chose avec lui.
>prendre miroir C’est trop difficile à transporter. >casser miroir La violence n’est pas une solution ici. >entrer dans miroir Vous ne pouvez pas y entrer.
Par défaut, la bibliothèque standard dit « non » ! Il y a quelques exceptions (prendre un objet qui n’est pas scenery
fonctionnera, par exemple), mais elles ne sont pas légion. C’est un des problèmes des jeux avec analyseur syntaxique : si l’auteur n’a pas spécifié le résultat d’une action, le système dira « non » au joueur. C’est frustrant pour le joueur : on lui dit « vas-y, tape n’importe quoi », mais on lui dit également « non, pas ça » des dizaines de fois ! Ainsi, faire un jeu avec analyseur syntaxique demande pas mal de travail à l’auteur, qui doit prévoir tout un tas d’actions, ou regarder ce que ses joueurs ou testeurs essaient.
Ici, nous allons ajouter des réponses pour « casser miroir » (une action logique avec un miroir, sept ans de malheur) et « entrer dans miroir » (une action un peu fantastique, à la Alice au pays des merveilles). Ce qu’il faut faire, en fait, c’est arrêter le système avant qu’il ne fasse ce qu’il fait d’habitude, c’est-à-dire avant qu’il n’affiche la réponse usuelle. Ça se fait en spécifiant une propriété before
dans notre miroir, et en écrivant ce qui se passe pour chacun de ces verbes :
Object miroir "miroir" piece with description "Vous vous regardez dans le miroir. À part une rougeur aux yeux et quelques plumes en désordre, vous n'avez pas l'air mal en point.", name 'grand' 'miroir' 'sur' 'pied', before [; Attack: "Vous vous élancez et donnez un coup de tête au miroir. Malheureusement, celui-ci est plus résistant que vous..."; Enter: "Vous tentez d’entrer dans le miroir, mais il n’a pas l’air d’être magique, et vous vous cognez la tête."; ], has scenery concealed;
Le système vérifie toujours si before
n’indique pas quelque chose pour le verbe actuel avant d’écrire sa réponse par défaut ; ici, nous avons donc ajouté 2 actions où le joueur se cogne la tête.
On peut mettre n’importe quel code dans un before
! Pour les cas simples comme celui-ci, on indique juste la nouvelle réponse ; c’est équivalent à écrire
Attack: print "Vous vous élancez et donnez un coup de tête au miroir. Malheureusement, celui-ci est plus résistant que vous..."; return true;
Ce bout de code veut dire « afficher le texte, puis c’est bon, on a fini, pas besoin d’afficher autre chose » ; ainsi, le jeu affiche votre réponse et n’affiche pas la réponse par défaut, puisque vous lui avez dit que c’était tout. Si vous voulez écrire quelque chose de plus complexe, qui change l’état du jeu ou autre, il faut finir par return true;
si vous voulez court-circuiter la réponse usuelle.
Dans before
, il faut indiquer l’action (en anglais) correspondant au verbe français. En général, c’est simple : Take
, Turn
, Push
, Pull
, Enter
, Attack
, Eat
, Touch
, etc. Si vous avez du mal à savoir quelle action correspond à quel verbe, il suffit d’aller dans FrenchG.h
et de trouver le verbe en français correspondant. S’il n’y est pas, c’est à vous de le définir ! (Voir ci-dessous pour la méthode.)
C’est une bonne gymnastique cérébrale de se demander ce qu’un joueur peut avoir envie de faire avec un objet, pour pouvoir le prendre en compte. Ici, on peut vouloir regarder derrière le miroir, le toucher, le tourner, voire le lécher ! Entraînez-vous et ajoutez des réponses spéciales pour ces verbes !
Victoire, défaite
Le jeu que nous sommes en train d’écrire est un jeu court, très court même : on va dire qu’il va suffire d’une action pour gagner ou perdre. Vu les actions que nous avons prises en compte, disons qu’essayer de casser le miroir fait perdre le jeu, et essayer d’y entrer fait gagner le jeu.
La variable deadflag
est la variable d’Inform qui détermine si l’on est toujours en jeu (dans ce cas, deadflag
contient 0) ou si le joueur a perdu (dans ce cas deadflag
vaut 1) ou gagné (deadflag
vaut 2). Il y a moyen de spécifier plus de fins que cela, mais ça sera pour un autre article !
L’effet est instantané : dès que vous changez la valeur de deadflag en 1 ou 2, le jeu s’arrête et le message de fin est affiché. Donc ici, à l’intérieur des before
, il faut changer la variable après avoir affiché le texte, mais avant le « return » qui signale la fin de la fonction.
Ça donne :
Attack: print "Vous vous élancez et donnez un coup de tête au miroir. Malheureusement, celui-ci est plus résistant que vous..."; deadflag = 1; return true; Enter: print "Mû par une intuition soudaine, vous regardez le miroir de plus près... Et en effet, il s'ouvre, et vous entrez de l'autre côté du miroir..."; deadflag = 2; return true;
Et notre jeu est enfin finissable :
>entrer dans miroir Mû par une intuition soudaine, vous regardez le miroir de plus près... Et en effet, il s'ouvre, et vous entrez de l'autre côté du miroir... *** Vous avez gagné *** Dans cette partie vous avez obtenu 0 sur un score possible de 0, en 1 tour. Voulez-vous RECOMMENCER, CHARGER une partie sauvegardée ou QUITTER ? >
Score
Vous avez sans doute remarqué que le jeu dit à la fin « Vous avez obtenu un score de 0 sur 0 ». C’est assez disgracieux, et nous allons essayer de changer cela.
Par défaut, un jeu en Inform a un score, contenu dans la variable score
. Cependant, au fil des années, de plus en plus de jeux sans score sont apparus, si bien qu’il paraît maintenant optionnel (comparé aux années 80, où c’était un passage obligé). Si vous ne voulez pas de score dans votre jeu, écrivez
Constant NO_SCORE;
avant Include "parser";
.
Si vous en voulez un, vous n’avez rien à changer ; il suffit de changer la variable score
directement pour attribuer des points. Par exemple, nous pouvons donner 5 points pour la fin victorieuse :
Enter: print "Mû par une intuition soudaine, vous regardez le miroir de plus près... Et en effet, il s'ouvre, et vous entrez de l'autre côté du miroir..."; score = 5; deadflag = 2; return true;
Ce qui donne :
>entrer dans miroir Mû par une intuition soudaine, vous regardez le miroir de plus près... Et en effet, il s'ouvre, et vous entrez de l'autre côté du miroir... *** Vous avez gagné *** Dans cette partie vous avez obtenu 5 sur un score possible de 0, en 1 tour. Voulez-vous RECOMMENCER, CHARGER une partie sauvegardée ou QUITTER ? >
Il y a une erreur avec le « 5 sur 0 » ; en fait, il faut spécifier le score maximal du jeu, en déclarant
Constant MAX_SCORE = 5;
avant Include "parser";
.
Il faut déclarer le score maximal vous-même ! Inform ne peut pas le calculer pour vous : vous pourriez avoir plusieurs solutions alternatives, des chemins qui ne rapportent pas le maximum de points, etc. Mais faites alors attention à bien calculer le nombre de points : si vous mettez que le score maximal est de 6 alors qu’on ne peut avoir que 5 points, certains joueurs tourneront en rond pendant des heures à la recherche du point manquant…
Définir ses propres verbes
Terminons ce tutoriel en ajoutant une solution supplémentaire au jeu. Cette solution est inspirée d’un moment culte d’un jeu anglophone, dont je tairai le nom pour ne pas trop gâcher la surprise… Le joueur regarde dans le miroir et se voit, pas trop amoché ; nous allons modifier un peu la description :
Object miroir "miroir" piece with description "Vous vous regardez dans le miroir. À part une rougeur aux yeux et quelques plumes en désordre, vous n'avez pas l'air mal en point.", ...
Grâce à cette description, le joueur doit comprendre qu’il incarne en fait un oiseau ! (Et après tout, il n’y a rien dans Inform qui nous en empêche !) À partir du moment où le joueur est un oiseau, il y a une solution évidente pour s’échapper de la pièce blanche : le joueur peut taper « voler ».
« Voler » n’est pas un verbe standard d’Inform, parce que le joueur en a justement rarement besoin. Il va donc falloir le définir nous-mêmes, en ajoutant un verbe à la grammaire reconnue par le jeu. On fait comme ceci : après l’inclusion de la grammaire française standard, on écrit
Verb 'voler' * ->Voler;
Ceci veut dire qu’on définit la commande « voler », suivie de rien du tout, et que si le joueur tape cette commande, il faudra aller voir dans la fonction VolerSub
.
Attention au piège : si on écrit quelque chose au bout de la flèche, Inform rajoute « Sub » au nom et cherche cette routine-là !
Il reste à définir VolerSub
: on écrit un message, on donne 10 points au joueur, et on dit qu’il a gagné, et c’est fini pour cette fonction :
[ VolerSub ; print "Vous agitez les ailes. Elles n'ont pas l'air d'avoir souffert ! Vous prenez un peu d'élan et volez hors de ce lieu étrange."; score = 10; deadflag = 1; return true; ];
N’oubliez pas de changer le MAX_SCORE
! Et maintenant, le joueur qui entre dans le miroir sait qu’il a gagné, mais n’a pas le maximum de points : il sait qu’il y a une meilleure fin !
Terminé ?
Non, ça ne fait que commencer !
Vous venez de décortiquer votre premier exemple en Inform 6. N’hésitez pas à le modifier, à l’étendre (essayez de rajouter des objets de décor, un lieu derrière le miroir, etc.), et à expérimenter !
Nous parlerons de beaucoup d’aspects d’Inform 6 sur ce site ; vous trouverez également sur le forum beaucoup de sujets relatifs à du code Inform 6, qui pourraient répondre à des questions que vous vous posez. N’hésitez pas également à regarder du code Inform 6 ; la source de tous mes jeux est disponible sur mon site, et il y a aussi la source de tous les jeux de FibreTigre (en général des jeux longs, qui font des choses très intéressantes).
Pour les anglophones, vous trouverez beaucoup d’informations dans l’Inform Beginner’s Guide et l’Inform Designer’s Manual 4, ainsi que sur Internet, et dans le répertoire des codes sources I6 de l’IFArchive.
Tout ceci représente par contre une somme énorme de choses, et c’est peut-être difficile de savoir par où commencer ! Alors revenez bientôt sur ce site pour plus d’articles et de réponses à vos questions pour progresser en Inform 6 !
21 janvier 2021 at 19 h 56
Bonjour je lis actuellement votre tutoriel sur Inform 6 et c’est juste pour dire qu’il est chouette mais une erreur c’est glissée concernant les Deadflag je pense car chez moi le deadflag à 1 correspond à une défaite que le deadflag à 2 à une victoire hors dans le tutoriel c’est le contraire qui est dit (chapître Victoire et Défaite donc) pour le deadflag 0 c’est ok.
23 janvier 2021 at 17 h 04
Bonjour Kitsune ! Et oups, merci, en effet tu as raison ! Je modifie l’article 🙂 N’hésite pas si tu as des questions ou des idées d’articles I6 !