Carré coloré, petit jeu en Forth, le début

Je lisais un de ces nombreux anciens livres présentant des petits jeux à recopier en BASIC : « Astounding Games for your Apple Computer ». Et de fil en aiguille, ou d'errance mentale, probablement parce que je développe un Forth sur Famicom, j'en suis arrivé à cette évidence : adapter au moins l'un de ces programmes en Forth.

Tous les jeux ne sont pas très bons dans ce livre, même si ce type de jeux m'amusait bien à l'époque, c'était probablement en grande partie par le côté découverte et émerveillement. La sélection fut donc rude, mais mon choix est finalement tombé sur « Rainbow Square Dance », page 32, présenté comme un Rubik's Cube à plat (une grille plutôt qu'un cube donc)

Le jeu

Sur une grille de 5 par 5 cases colorées, le but est de ramener l'état à un damier où chaque ligne est d'une seule couleur. Il est possible à chaque tour de jeu de « pousser » une ligne ou une colonne. Toutes les cases poussées passent à la position suivante (dans le sens de la poussée) et la pièce qui sort de la grille est replacée en première position. Si vous connaissez le jeu de plateau « Labyrinthe », c'est le même principe.

Bien entendu, puisque c'est un puzzle à résoudre, il faut partir d'une solution aléatoire. Mais pas trop, afin d'être certain que la grille puisse être résolue. Pour cela, en début de jeu, le programme effectue une série de poussées aléatoires (de manière cachée), ce qui donne l'état initial du jeu.

Le programme

Je ne vais pas recopier le programme BASIC ici. Après tout, il est indiqué dans le livre que le contenu ne peut pas être reproduit, ce qui est plutôt cocasse pour un livre qui présente des listings à recopier sur son ordinateur... (il est bien spécifié que le contenu ne peut pas être stocké sur un support électronique, c'est incroyable).

Mais en voici l'analyse, facilitée par une bonne structuration du programme. Ce n'était pas toujours le cas dans les listings d'époque. Dans ce livre, ça se lit assez bien.

Lignes 10 à 120

  • initialisation du tableau (5x5) avec les 5 couleurs (prises depuis des DATA)
  • initialisation d'un tableau (10x7) avec la « police de caractères » des 10 chiffres

Plus exactement, le tableau est initialisé par un DIM(5,5), ce qui en fait un tableau 6 par 6 puisque la borne est incluse et le premier index est 0. Cet espace supplémentaire sert d'ailleurs lors de la poussée.

La police de caractère des 10 chiffres est un affichage spécifique à l'Apple II et est une définition classique de caractère avec une série de 7 octets représentant donc, j'imagine, des caractères de 7 lignes de 8 pixels.

Lignes 200 à 260

  • affichage d'un carré coloré en fonction de la ligne et colonne

La fonction va chercher la couleur dans le tableau lui-même. C'est concis, mais pas flexible si on veut une animation sur des machines qui le peuvent. Un manque clair de séparation des responsabilités, mais, hé, on est sur du BASIC des années 80 sur micro 8 bits.

Lignes 300 à 430

  • affichage de l'écran avec passage en mode haute résolution.
  • affichage des « coordonnées » des lignes et colonnes (de 1 à 5 pour les lignes, de 6 à 0 pour les colonnes)
  • double boucle pour afficher toutes les cases.

Lignes 500 à 600

  • affichage d'un caractère (de 0 à 9) à un emplacement de l'écran.

La routine se sert des données de caractères dans le deuxième tableau pour tracer les caractères.

Lignes 700 à 750

  • effectue 20 mouvements aléatoires pour initialiser la grille du jeu.

Lignes 800 à 960

  • effectue un mouvement horizontal (lignes 830+) ou vertical (lignes 900+)
  • décalage du tableau d'une position en utilisant l'emplacement à l'indice 0 du tableau

L'affichage des cases est mis à jour pendant le mouvement. C'est plus concis que d'avoir séparé le mouvement et l'affichage, certes.

Lignes 1000 à 1080

  • programme principal
  • affiche l'écran
  • prépare (mélange) la grille
  • en boucle
  • demande et valide l'entrée du joueur
  • effectue le mouvement demandé

Et non, il n'y a pas de détection de résolution du puzzle. Le jeu ne s'arrête jamais.

Lignes 2000 à 2100

  • les DATA (5 couleurs et polices des caractères)

En Forth !

Grâce à la structure du programme BASIC, transcrire en mots Forth est facilité. J'ai pu faire ça sur papier (enfin, papier électronique). Donc, je ne sais pas encore si ça marche, mais voici le plan :

Initialisation

  • INIT.GRID ( - grid ) : initialisation du damier (avec ALLOT). Voir pour les couleurs en fonction de la machine.
  • INIT.CHARS ( - ) : si besoin comme pour l'Apple, sinon, rien.
  • INIT.GAME ( - grid ) : appelle les deux INIT. précédents

Affichage

  • .CSQUARE ( x y c - ) : affiche un carré à la position écran donnée
  • G>S ( r c - x y ) : transforme une coordonnée (row,column) de la grille en coordonnées (x,y) pour l'écran
  • .DIGIT ( x y n - ) : affiche un caractère n à la position écran donnée
  • T>S ( r c - x y ) : transforme une coordonnée (row,column) de l'écran en coordonnées (x,y) pour l'écran
  • .SCREEN ( - ) : affichage complet de l'écran

Mouvements

  • PUSH.ROW ( grid n - ) : pousse le rang n de la grille (en mettant à jour l'affichage)
  • PUSH.COL ( grid n - ) : pousse la colonne n de la grille (en mettant à jour l'affichage)
  • PUSH ( grid n - ) : pousse un rang ou une colonne de la grille (en fonction du numéro passé)
  • SHUFFLE.GRID ( grid n - ) : effectue n mouvements dans la grille

Interactions

  • INPUT.VALID? ( n - b ) : renvoi 0 si l'entrée du joueur n'est pas valide
  • INPUT ( - n ) : demande une entrée valide du joueur
  • GAME : le programme principal

Bon, sur quoi ?

J'avais commencé des tests avec gforth sur PC récent après avoir trouvé un binding SDL. L'idée était de pouvoir itérer rapidement dans un environnement moderne. Mais rapidement, je suis tombé sur deux problèmes :

  1. gforth, c'est autrement plus évolué que Fig-Forth dont j'ai l'habitude. Très. Beaucoup trop pour cet exercice.
  2. corollaire du premier point : ça ne m'amusait pas.

Je me suis donc tourné vers les machines 8 bits, à la recherche du croisement entre une machine qui puisse afficher 8 couleurs simultanées et avec un Forth doté de capacités graphiques. Pour les machines, j'ai rapidement limité au MSX et à l'Amstrad CPC. Mais le MSX n'a pas une offre Forth qui convienne (pas d'accès graphique simple à mettre en oeuvre).

C'est donc vers le Forth Abersoft de l'Amstrad CPC que je me dirige. Après quelques tests, c'est un Fig-Forth avec accès aux capacités graphiques et sonores de la machine. Ça me semble bien.

L'idée est cependant d'avoir des mots qui soient adaptables facilement d'une machine à une autre. Exercice que je tenterai par la suite.

Bon ben... yapuka

À la prochaine !

Photo du livre cité