Un jeu d’aventure bien aligné ou justifié

Il est important de bien soigner la présentation de vos jeux d’aventures. Si vous n’y prenez garde, vous risquez de retrouver cela :

Une présentation bof, qui n’incite pas à poursuivre l’aventure.

Pas très lisible, n’est-ce pas ? (on peut même dire que c’est moche). Les mots sont coupés au delà de la 40ème colonne, sans tenir compte des règles usuelles de présentations des documents.

Dans cet article, nous allons voir comment afficher un texte avec un alignement à gauche, sans couper les mots, ou un alignement justifié. Avec une subroutine en BASIC !

Prototypage en Python

Pour mettre au point l’algorithme, mieux vaut utiliser un langage structuré. Python conviendra parfaitement pour cet exercice. Voici le programme fancy_print.py téléchargeable sous la forme d’une archive au format tar :

Pour extraire le fichier source de l’archive tar :

  • Sous Linux, saisir la commande tar xvf fancy_print.tar
  • Sous Windows, utiliser 7Zip, qui reconnaît ce format d’archive

Le résultat de l’exécution du programme figure ci-après. La largeur est fixée à 40 colonnes et le texte contenu dans la variable msg est affiché avec un alignement à gauche puis avec un alignement justifié.

dom@laptop-dom:~/dev$ ./fancy_print.py 
VOUS VOUS TROUVEZ DANS     UNE PIECE
SOMBRE AVEC DES BRUITS ETRANGES. AU 
NORD IL Y A UNE PORTE   EN FER. TOUS
CECI EST FORT PERTURBANT CAR CELA NE
CORRESPOND PAS AU PLAN.

VOUS   VOUS   TROUVEZ  DANS   UNE  PIECE
SOMBRE  AVEC  DES  BRUITS  ETRANGES.  AU
NORD  IL  Y  A UNE  PORTE  EN  FER. TOUS
CECI  EST  FORT PERTURBANT  CAR  CELA NE
CORRESPOND PAS AU PLAN.
Fonctionnement du programme fancy_print.py

Le programme comporte deux fonctions :

def fancy_print(msg, nb_col, justified):

Cette fonction affiche le texte contenu dans msg dans le nombre de colonnes spécifiées par nb_col, en effectuant un alignement à gauche ou un alignement justifié (si justified est positionné à True). Les caractères blanc en début de texte sont tout d’abord supprimés, puis le programme découpe le message en blocs de nb_col caractères. En partant de la fin de ce bloc de texte, le programme retrouve la position du dernier espace, qui fixera la fin du bloc de texte à afficher, de façon à ne pas couper un mot. Puis le bloc suivant est analysé, et ainsi de suite jusqu’au dernier.

def justify_text(msg, nb_col):

Cette fonction va justifier une ligne de texte msg sur le nombre de colonnes spécifié par nb_col. Ce paramètre doit être supérieur à la longueur du message à afficher, sans quoi il ne sera pas pris en compte. Tout d’abord, le programme compte le nombre d’espaces et le nombre de mots. Il calcule ensuite le nombre moyen d’espaces entre deux mots (qui n’est pas forcément un nombre entier), puis répartit les espaces entre les mots de façon à rester au plus près de l’espace moyen.

Conversion en BASIC

Voici l’équivalent en BASIC standard du programme fancy_print.py précédent :

Convertir un programme d’un langage structuré en BASIC des années 80 est un exercice intéressant. Voici quelques clés :

  • Fonctions :
Fonction en Python (appel et définition)Subroutine en BASIC (appel et définition)
fancy_print(msg, NB_COLUMN, False)100 M$ = "VOUS VOUS TROUVEZ DANS UNE PIECE TRES SOMBRE AVEC DES BRUITS ETRANGES. AU NORD SE TROUVE UNE PORTE EN FER.": GOSUB 10000
def fancy_print(msg, nb_col, jst):
msg_length = len(msg)
# instructions
return
9999 REM <--- SUB FANCY PRINT M$ --->
10000 LM = LEN(M$)

....
10500 RETURN
Les fonctions n’existent pas en BASIC où elles sont remplacées par des appels à des subroutines par l’instruction GOSUB. Les paramètres d’appel sont replacés par l’affectation de variables globales.
  • instructions if…else :
instruction if…else en PythonEquivalent en BASIC
if (justified ):
....justify_text(msg[idx_begin:idx_end], nb_col)

else :
....print(msg[idx_begin:idx_end])

idx_begin = idx_end + 1
10090 IF JU = 1 THEN MM$ = MID$(M$, IB, IE-IB): GOSUB 10200: GOTO 10100

10094 REM <--- ELSE --->
10095 PRINT MID$(M$, IB, IE-IB);

10100 IB = IE + 1
S’il y a bien une instruction if dans les différentes variantes des BASIC old school, la plupart n’ont pas de else.
  • Boucle while :
boucles while en PythonEquivalents en BASIC
while (idx_end < msg_length ):
....# instructions
....
....

....
# On est sorti du while
10020 IF (IE < LM + 1) THEN 10030
10021 GOTO 10150
...
...
10140 GOTO 10020
10150 REM < on est sorti du while >
while ((idx_end > idx_begin) and msg[idx_end] != " ") ):
....idx_end -= 1
10070 IF (IE > IB) AND (MID$(M$,IE,1) <> " ") THEN IE = IE - 1: GOTO 10070
Le while n’existe pas en BASIC basique et est à remplacer par des IF et des GOTO
Intégration à vos programmes

En principe, l’intégration à vos programmes BASIC est simple. Il faut copier le code à partir de la ligne 10000 dans votre propre programme. Il est également nécessaire d’initialiser les variables CL (nombre de colonnes) et JU (flag indiquant que le texte sera justifié si vaut 1).

Pour appeler la subroutine, insérez une ligne de code du type :

100 M$ = "VOUS VOUS TROUVEZ DANS UNE PIECE TRES SOMBRE AVEC DES BRUITS ETRANGES. AU NORD SE TROUVE UNE PORTE EN FER.": GOSUB 10000

Voici le résultat sous Apple II :

texte justifié
On peut continuer cette aventure bien présentée !
Remarque importante :

le code des deux subroutines (lignes 10000 à 10500) contient de nombreuses variables. Il faut prendre garde à ce que votre propre programme n’utilise pas des variables de même nom ! Si c’est le cas, cela risque d’engendrer des bugs très difficiles à corriger. N’oubliez pas qu’en BASIC des années 80, toutes les variables ont une portée globale ! S’il y a conflit de noms de variables, il suffit de les renommer.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.