Ink est un excellent langage pour écrire des histoires, mais ce que nous avons vu jusqu’à maintenant nous permettrait difficilement de simuler un monde (par rapport à Inform 7, par exemple). Les listes ink ont été créé pour remédier à cela (au moins en partie, car ink reste principalement utilisé pour de la narration).

Il s’agit d’une récente fonctionnalité (et aussi la dernière qu’il nous reste à voir), et sûrement la plus complexe du langage (mais rien d’insurmontable !).

Notre première liste

Une liste dans ink est simplement une énumération de mots, que l’on crée avec le mot-clef LIST.

LIST emplacement = foret, plaine, desert, ocean

Le code ci-dessus crée une variable nommée emplacement, susceptible de contenir quatre valeurs différentes (foret, plaine, desert ou ocean). Il ne reste plus qu’à lui donner l’une de ces valeurs, quelque part au début de l’histoire. On peut bien évidemment la changer en cours de partie.

LIST emplacement = foret, plaine, desert, ocean

// La variable « emplacement » aura comme valeur « plaine ».
~ emplacement = plaine

*   [Voyager vers le désert]
    Votre prochaine destination : le désert.
    ~ emplacement = desert // On change l'emplacement, qui est maintenant le désert.

Et bien entendu, pour que tout cela puisse servir à quelque chose, on peut tester la valeur de la liste :

// On ne peut couper du bois qu'en forêt.
*   {emplacement == foret} [Couper du bois]

Et enfin, lorsque l’on déclare la liste, il est possible de mettre l’une des valeurs entre parenthèses pour indiquer que celle-ci est la valeur initiale. Si l’on écrit ceci :

LIST emplacement = foret, (plaine), desert, ocean

Alors il n’y a pas besoin d’initialiser la liste avec ~ emplacement = plaine, elle aura cette valeur dès le départ.

Quelques explications

Entrons maintenant plus en détails sur ce que nous venons de faire.

Le mot-clef LIST fait plusieurs choses à la fois. Il crée une variable (emplacement dans notre exemple), mais aussi les valeurs, représentées par des mots, qu’elle pourra avoir (comme ocean).

On aurait pu, dans ce cas-ci, se passer des listes et simplement représenter les endroits par des nombres ou du texte (1 pour la forêt et 2 pour la plaine, ou "forêt" pour la forêt et "plaine" pour la plaine). Cependant, utiliser une liste a beaucoup d’avantages, que nous verrons surtout dans de prochains articles. Disons qu’au moins, une liste nous permet de ne pas avoir à nous remémorer chaque nombre ou chaîne que l’on aurait pu utiliser à la place.

Un avertissement dédié aux programmeurs : les listes ink ne sont pas analogues aux listes que l’on peut trouver dans d’autres langages de programmation (comme le Python). Elles ne sont pas des tableaux pouvant contenir d’autres valeurs arbitraires comme des nombres ou des chaînes de caractères, mais des listes de valeurs possibles. Elles s’apparentent donc plus aux types énumérés (aussi appelées énumérations).

Réutiliser des listes

Dans notre premier exemple, nous avons créé une liste qui pouvait prendre comme valeurs divers endroits, afin de modéliser l’emplacement du joueur. Imaginons que nous voulons également modéliser l’emplacement de divers autres objets ou personnages. Faudra-t-il créer plusieurs listes ? La réponse est non. Comme écrit plus haut, en tapant LIST emplacement = foret, plaine..., nous créons à la fois une variable et une liste de valeurs possibles. Il ne nous reste donc plus qu’à créer d’autres variables contenant ces valeurs, sans avoir à recréer ces valeurs elles-mêmes !

C’est peut-être un peu confus ; voici un exemple.

// On crée la variable emplacement avec les valeurs qu'elle pourra contenir.
LIST emplacement = foret, (plaine), desert, ocean

// On crée d'autres variables qui contiendront des endroits.
VAR nemesis = foret
VAR dirigeable = desert

On dispose ici d’une liste de valeurs (foret, plaine, etc.) et de trois variables (emplacement qui contient plaine, nemesis qui contient foret et dirigeable qui contient desert). Et on peut faire la même chose que tout à l’heure avec ces trois variables : changer leur valeur et les tester.

Il est possible de créer des listes différentes avec des valeurs ayant le même nom :

LIST emplacement = foret, plaine, desert, ocean
LIST outil = tournevis, marteau, foret
VAR nemesis = foret

La troisième ligne va causer une erreur, car ink ne peut pas deviner s’il s’agit de la forêt définie dans la première liste ou du foret définie dans la deuxième liste. Pour résoudre cela, il faut préciser le nom que l’on a utilisé en créant la liste :

VAR nemesis = emplacement.foret

Ici, emplacement n’a pas de signification particulière. Il est simplement là pour indiquer à ink qu’il s’agit de l’emplacement foret, et non de l’outil foret. Si vous n’êtes par trop certain d’avoir compris, ou que vous voulez éviter ce genre d’ambiguïté, il vous suffit de ne pas utiliser de mots identiques pour les valeurs de listes.

Des listes comme des nombres

En vérité, l’ordre dans lequel on définit une liste est important. En effet, pour ink, les valeurs d’une liste sont équivalents à des nombres. Cela signifie qu’on peut les comparer comme des nombres ou les augmenter.

LIST jour = lundi, mardi, (mercredi), jeudi, vendredi, samedi, dimanche

-> routine

=== routine ===

Il est {jour}.

+   [attendre]
    { jour < dimanche:
        ~ jour++
    - else:
        ~ jour = lundi
    }
    -> routine

Cet exemple fait plusieurs choses :

  • Tout d’abord, on crée une liste pour les jours de la semaine, puis on dévie l’histoire.
  • Dans le nœud routine, on affiche d’abord le jour actuel (mercredi au début). Il va s’afficher en mot tel qu’on l’a défini. Voici un autre avantage par rapport à l’utilisation directe de nombres (1 pour lundi, 2 pour mardi, etc.).
  • C’est dans l’option que ça devient intéressant. Comme en interne ink considère les éléments d’une liste comme des nombres, on peut les comparer. Si jour est « inférieur » à dimanche (c’est-à-dire s’il est avant dimanche), alors on « incrémente » jour (on passe au jour suivant). Sinon, on revient à lundi. Attention, il faut avoir la condition, car incrémenter une liste quand on est à sa fin (dimanche ici) ne la fera pas revenir au début.
  • Il est bon de savoir qu’on peut si on le souhaite augmenter le jour d’un autre autre nombre pour faire avancer le temps plus vite (~ jour += 3) ou effectuer une soustraction pour remonter le temps.

Enfin, il est possible de convertir des valeurs en nombre et vice-versa.

Pour le premier, il faut utiliser la fonction LIST_VALUE, fournie par ink :

Nous somme le jour {LIST_VALUE(jeudi)}

Affichera « Nous sommes le jour 4 » (les listes commencent à 1). Cela peut parfois être utile, par exemple pour indiquer combien de jours il reste à la semaine :

Il reste {LIST_VALUE(dimanche) - LIST_VALUE(jour)} jours à la semaine.

Pour l’inverse, il faut utiliser le nom de la liste comme s’il s’agissait d’une fonction :

Le jour 3 est {jour(3)} // Ce sera mercredi.

Cela peut servir lorsque l’on veut faire des calculs compliqués, puis les convertir en une certaine valeur.

La fin ?

Il y a beaucoup de matière à appréhender dans cet article. La morale ici, c’est que les listes permettent d’avoir des variables pouvant prendre un certain nombre de valeurs nommées (que l’on pourra afficher et manipuler facilement), plutôt que d’utiliser des nombres ou des textes arbitraires.

Comme d’habitude, le mieux est d’expérimenter ! Si vous voyez que des variables simples comme des nombres ne suffisent pas à modéliser votre récit, alors il se peut que vous ayez besoin des listes.

Et c’est loin d’être la fin ! Les listes sont bien plus puissantes qu’elle ne le paraissent, mais ce sera pour un prochain tutoriel. Ce sera aussi plus compliqué, alors préparez-vous !