PROGRAM ESCARGOTS;

(* Pour l'‚nonc‚ du programme, voir la proc‚dure AVERTIS.
   Programme semblable … la course de chevaux, sinon que ‡a va moins vite.
   Pour les commentaires g‚n‚raux, se reporter donc … ce programme.
   Quelques petites fioritures ont toutefois ‚t‚ apport‚es et elles sont
   comment‚es aux endroits strat‚giques.
   Bien entendu, … vous de choisir la m‚thode qui vous convient le mieux,
   il n'y a pas d'obligation du moment que le programme tourne correctement. *)

USES CRT;

(* 8 cases correspondant aux 8 dossards des 8 escargots *)
TYPE INT8 = ARRAY [1..8] OF SHORTINT;

VAR  ESCARGOT,           (* Pour noter l'ordre d'arriv‚e de chaque escargot *)
     PARIDOUBLE: INT8;   (* Pour noter la place d'arriv‚e pari‚e par l'utilisateur *)
     ORDRE,              (* Qui signalera si le pari est gagn‚ dans l'ordre *)
     DESORDRE: BOOLEAN;  (* Qui signalera si le pari est gagn‚ dans le d‚sordre *)

PROCEDURE AVERTIS;
          BEGIN
          WRITELN ('Le programme simule une course de 8 escargots');
          WRITELN ('L''utilisateur peut faire un pari sur les 2 premiers arrivants.');
          END;

PROCEDURE INITIALISE (VAR ESCARGOT, PARIDOUBLE: INT8);
          VAR i: INTEGER;

          BEGIN
(* 0 dans la case signale que l'escargot n'est pas encore arriv‚ (dans ESCARGOT)
   ou que l'escargot n'a pas encore ‚t‚ pari‚ … l'arriv‚e (dans PARIDOUBLE) *)
          FOR i := 1 TO 8 DO
              BEGIN
              ESCARGOT   [i] := 0;
              PARIDOUBLE [i] := 0;
              END;
          END;

PROCEDURE PARIE (VAR PARIDOUBLE: INT8);
          VAR i, NUMERO: SHORTINT;

          BEGIN
          (* 2 escargots … jouer *)
          FOR i := 1 TO 2 DO
              BEGIN
              WRITE ('Quel escargot franchira-il le ',i,'ø la ligne d''arriv‚e ? ');
              READLN (NUMERO);
              (* On v‚rifie si l'escargot fait bien partie de la course avant de v‚rifier... *)
              WHILE (NUMERO < 1) OR (NUMERO > 8) DO
                    BEGIN
                    WRITE ('Pas d''escargot portant ce dossard, entre un autre num‚ro : ');
                    READLN (NUMERO);
                    END;
              (* ...s'il n'a pas ‚t‚ d‚j… jou‚ par l'utilisateur *)
              IF PARIDOUBLE [NUMERO] > 0 THEN
                 BEGIN
                 WRITELN ('Ce num‚ro a d‚j… ‚t‚ pari‚, recommence ton choix');
                 (* D‚cr‚menter i va permettre de recommencer la boucle FOR avec le mˆme num‚ro *)
                 DEC (i);
                 END
              ELSE
                 (* On prend note du pari en mettant l'ordre d'arriv‚e chez l'escargot choisi *)
                 PARIDOUBLE [NUMERO] := i;
              END;
          END;

PROCEDURE COURSE_FOLLE (VAR ESCARGOT: INT8; DEBUT, FIN: SHORTINT);
          (* La course s'effectue en deux phases. D'abord l'arriv‚e de 2 escargots
             et ensuite l'arriv‚e des 6 autres. Les valeurs attribu‚es … DEBUT et FIN
             figurent dans le programme principal au moment de l'appel de COURSE_FOLLE *)
          VAR i, NUMERO: SHORTINT;

          BEGIN
          FOR i := DEBUT TO FIN DO
              BEGIN
              REPEAT
                    NUMERO := RANDOM (8) + 1;
              (* On n'accepte le num‚ro que quand il y a toujours 0 dans la case
                 de l'escargot correspondant, signe qu'il n'est pas encore arriv‚ *)
              UNTIL ESCARGOT [NUMERO] = 0;
              (* On note l'ordre d'arriv‚e au num‚ro de l'escargot tir‚ au sort *)
              ESCARGOT [NUMERO] := i;
              WRITELN ('Arriv‚(e) en ',i,'ø position : l''escargot(e) ',NUMERO);
              END;
          END;

PROCEDURE VERIFIE (ESCARGOT, PARIDOUBLE: INT8; VAR ORDRE, DESORDRE: BOOLEAN);
          VAR i, COMPTE_0: INTEGER;

          (* C'est dans cette proc‚dure que quelques fioritures ont ‚t‚ introduites *)
          BEGIN
          COMPTE_0 := 0;
          ORDRE := TRUE;
          FOR i := 1 TO 8 DO
              BEGIN
              (* ORDRE ne restera … vrai que s'il ‚tait … vrai ET que la case i de
                 ESCARGOT est ‚gale … la case i de PARIDOUBLE. Des qu'il y aura 1 seule
                 diff‚rence, ORDRE deviendra faux et la fonction ET ne donnera plus jamais
                 qu'un r‚sultat faux. ORDRE ne restera donc … vrai que si les 8 cases sont
                 totalement toutes identiques 2 … 2 *)
              ORDRE := ORDRE AND (ESCARGOT [i] = PARIDOUBLE [i]);
              IF (ESCARGOT [i] = 0) AND (PARIDOUBLE [i] = 0) THEN
                 INC (COMPTE_0);
                 END;
          (* Pour le d‚sordre, il faut qu'il y ait les 6 cases laiss‚es … 0 qui soient
             au mˆme endroit dans les 2 tableaux. C'est ce qu'on compte dans le second
             IF de la boucle FOR. Ci-dessous, DESORDRE ne sera … vrai que si la valeur
             contenue dans COMPTE_0 est ‚gale … 6, sinon, DESORDRE sera … faux
             (COMPTE_0 = 6 est une expression bool‚enne puisque sont r‚sultat ne peut
             donner que vrai ou faux (on n'est pas un petit peu enceinte!)) *)
          DESORDRE := COMPTE_0 = 6;
          END;

PROCEDURE RESULTATS (ORDRE, DESORDRE: BOOLEAN);
          BEGIN
          (* Si ORDRE est … vrai, DESORDRE l'est aussi, mais, trŠs finement,
             on n'acc‚dera … DESORDRE que si ORDRE est … faux. *)
          IF ORDRE THEN
             WRITELN ('Braaaavoooo!!! Tu as gagn‚ dans l''ordre.')
          ELSE
             IF DESORDRE THEN
                WRITELN ('Pas maaaal du touuut!! Tu as gagn‚ dans le d‚drosre (d‚sordre de d‚sordre)')
             ELSE
                WRITELN ('Pffffft! Encore perdu...');
          END;

BEGIN (* du programme principal *)
CLRSCR;
AVERTIS;
INITIALISE (ESCARGOT, PARIDOUBLE);
PARIE (PARIDOUBLE);
COURSE_FOLLE (ESCARGOT, 1, 2);
VERIFIE (ESCARGOT, PARIDOUBLE, ORDRE, DESORDRE);
COURSE_FOLLE (ESCARGOT, 3, 8);
RESULTATS (ORDRE, DESORDRE);
READLN;
END.
