!Programme tp2.sim compiler par: sim tp2.sim -simwin par: Vincent Petitclerc Kathleen Quesnel date: 8 avril 1997 fonction: Jeu dans lequel il faut amener une grenouille a son nenuphar en passant par un labyrinthe; BEGIN EXTERNAL CLASS dessin; Application CLASS laby; BEGIN REF(button) up, down, left, right, ! Pour changer la direction; stop, ! Pour terminer une partie; demarre, ! Pour terminer les explications; arret_temp, continuer, ! Pour faire une pause et redemarrer; aide, fermer_aide, ! Pour afficher (et fermer) l'aide; scores, fermer_scores, ! Pour afficher (et fermer) les resultats; vit_b, aut_b, temp_b, dimX_b, dimY_b, ! Pour changer les variables; rejoue_b, ! Pour rejouer (affiche ds fenetre de chang. de var.); fin_b; ! Pour terminer le programme; INTEGER x, y, ! La grenouille est en pos. (x,y) ds l'ARRAY; direction, ! Stocke proch. direc. (1=haut, 2=bas, 3=g, 4=dr); oldDir, ! Stocke l'ancienne dir. (pour l'effacer correctement); U, ! Germe pour randint; d, ! Facteur d'echelle (utilise dans tous les tracages); dimx, dimy, ! Le labyrinthe a les dimentions (dimX, dimY); autonom, ! % d'autonomie de la grenouille; first, last, ! Pour le timer: first= 1er clocktime lu, last=dernier clocktime lu; temps, ! Nbre de secondes demandees par l'utilisateur; xfin, yfin, !Stocke la pos. dans l'ARRAY de la cible; etape; ! Indique a refresh quoi redessiner; BOOLEAN finir, !TRUE si on veut sortir de la boucle d'evenements; arret_demande, ! TRUE si c'est le bouton stop qui a arrete la boucle d'evenem.; exterminer, ! TRUE si on desire terminer le programme; jouer; !TRUE si on desire sortir du changement de var.; REF(dessin) Fhelp, Fscores; ! Fenetres d'aide et de resultats; TEXT nom; !Stocke le nom de l'utilisateur (utilise pour I/O scores); REAL t; !temps de pause pour l'animation de la grenouille; CHARACTER Wall = 'X'; !Pour faciliter lecture des procs sur l'ARRAY; CHARACTER ARRAY maze( 1: 63, 1: 63 ); !Tableau stockant le layrinthe; !************** Procedures d'explication au debut du jeu *************; !************** et pour placer les boutons de jeu ********************; PROCEDURE Page_titre( b ); !Affiche la page titre et l'explication; REF (button) b; BEGIN demarre :- MakeButton( "Demarrer" ). PlaceDownLeft; Explication; demarre. wait; demarre. hide; encre( "white" ); Explication; encre( "black" ); END Page_titre; PROCEDURE texte_g(T,y); !Affiche le texte a gauche de la fenetre; VALUE T; TEXT T; INTEGER y; BEGIN INTEGER l; l:=largeur_de_texte(T)//2+5; texte(l,y,T); END texte_g; PROCEDURE Explication; !Affiche les explications de depart; BEGIN INTEGER w,h; SetSize(750,750);pause(1); w:=width//2; h:=height//2; police("helvetica",24); texte(w,h-300, "La grenouille malefique"); police("helvetica",12); texte_g(" Le but de ce jeu est de faire arriver la grenouille au nenuphar le plus rapidement possible.",h-210); texte_g(" Pour deplacer la grenouille, utilisez les fleches du clavier ou cliquez sur les boutons:",h-160); texte_g("haut, bas, droite, gauche.",h-140); texte_g(" Vous pouvez determiner vous meme votre niveau de difficulte en modifiant les points suivants: ",h-90); police("times",14); texte_g(" vitesse:",h-60); police("helvetica",12); texte_g(" Indiquez la vitesse de deplacement de la grenouille, c'est-a-dire le ",h-60); texte_g(" nombre de carres qu'elle peut faire en une seconde. ",h-40); police("times",14); texte_g(" % d'autonomie:",h-20); police("helvetica",12); texte_g(" Indiquez a quel point vous voulez avoir le controle sur votre",h-20); texte_g(" grenouille. NB: a '0' vous avez le plein controle sur votre grenouille, et a '100', ",h); texte_g(" c'est la grenouille a qui tout le controle. ",h+20); police("times",14); texte_g(" Nombre de secondes pour sortir:",h+40); police("helvetica",12); texte_g(" Indiquer le temps limite que vous vous accordez pour ",h+40); texte_g(" pour reussir le jeu. ",h+60); police("times",14); texte_g(" dimension horizontale:",h+80); police("helvetica",12); texte_g(" Indiquer la largeur (entre 3 et 63) de labyrinthe que vous desirez avoir.",h+80); police("times",14); texte_g(" dimension verticale:",h+100); police("helvetica",12); texte_g(" Indiquer la hauteur (entre 3 et 63) de labyrinthe que vous desirez avoir. ",h+100); police("times",14); texte_g(" Jouer:",h+120); police("helvetica",12); texte_g(" lorsque vous etes pret a commencer, cliquez sur jouer et l'ordinateur vous demandera",h+120); texte_g(" de taper votre nom.",h+140); texte_g(" Des valeurs, correspondant a un niveau debutant, ont deja ete affectees pour chaque point.",h+170); texte_g("Pour changer ces valeur et ainsi augmenter le niveau de difficulte, cliquez sur le point a changer",h+190); texte_g("et l'ordinateur vous demandera d'entrer les nouvelles valeurs.",h+210); texte_g(" Si vous desirez avoir de l'aide pendant la partie, cliquez sur le bouton 'Aide'",h+240); texte_g(" Si vous desirez arreter provisoirement pour reflechir, cliquez sur le bouton 'Pause'",h+270); texte_g("Le temps et les resultats seront alors arretes jusqu'a ce que vous cliquiez sur le bouton continuer.",h+290); texte_g(" Si vous desirez consulter vos resultats anterieurs, cliquez sur le bouton 'Resultat'",h+320); END Explication; PROCEDURE Place_boutons (aide, up, down, left, right, stop, arret_temp, scores); !Affiche les boutons mentionnes; NAME aide, up, down, left, right, stop, arret_temp, scores; REF (button) aide, up, down, left, right, stop, arret_temp, scores; BEGIN aide :- MakeButton( "Aide" ). PlaceAt( width - 100, height - 150 ); up :- MakeButton( "Haut" ). PlaceAt( width - 100, height - 110 ); down :- MakeButton( "Bas" ). PlaceAt( width - 100, height - 30 ); left :- MakeButton( "Gauche" ). PlaceAt( width - 140, height - 70 ); right :- MakeButton( "Droite" ). PlaceAt( width - 60, height - 70 ); stop :- Makebutton( "Finir" ). PlaceDownLeft; arret_temp :- Makebutton( "Pause" ). PlaceUpRight; scores :- MakeButton( "Resultats" ). PlaceAt( width - 120, height - 190 ); END Place_boutons; !******* Procedures de generation du labyrinthe et des positions de depart * ******* et d'arrivee, impression *****************************************; PROCEDURE initier_maze( maze ); !Remplit l'array de murs; CHARACTER ARRAY maze; BEGIN INTEGER i, j; U := clocktime; FOR i := 1 STEP 1 UNTIL dimX DO FOR j := 1 STEP 1 UNTIL dimY DO maze( i, j ) := WALL; END initier_maze; PROCEDURE Excavate( x, y, M ); !Creuse un labyrinthe dans l'array; INTEGER x, y; CHARACTER ARRAY M; BEGIN INTEGER i, d, d1; M( x, y ) := ' '; d1 := randint( 1, 4, U ); FOR i := 1 STEP 1 UNTIL 4 DO BEGIN d := mod( d1 + i, 4 ); IF d = 0 AND x < dimX - 1 AND THEN M( x + 2, y ) = Wall THEN BEGIN M( x + 1, y ) := ' '; Excavate( x + 2, y, M ) END ELSE IF d = 1 AND x > 2 AND THEN M( x - 2, y ) = Wall THEN BEGIN M( x - 1, y ) := ' '; Excavate( x - 2, y, M ) END ELSE IF d = 2 AND y < dimY - 1 AND THEN M( x, y + 2 ) = Wall THEN BEGIN M( x, y + 1 ) := ' '; Excavate( x, y + 2, M ) END ELSE IF d = 3 AND y > 2 AND THEN M( x, y - 2 ) = Wall THEN BEGIN M( x, y - 1 ) := ' '; Excavate( x, y - 2, M ) END END; END excavate; PROCEDURE out_fin( x, y ); !Affiche le "nenuphar" en (x,y); INTEGER x, y; BEGIN INTEGER r; r := d // 2 - 1; WHILE r > 0 DO BEGIN cercle( x + d // 2, y + d // 2, r, 0 ); r := r - 2; END; END out_fin; PROCEDURE debutFin( M, x, y, xfin, yfin ); !Genere les points de depart et d'arrivee; NAME x, y, xfin, yfin; !Le point de depart sera stocke dans (x,y); CHARACTER ARRAY M; !et le point d'arrivee dans (xfin,yfin); INTEGER x, y, xfin, yfin; BEGIN BOOLEAN fini; INTEGER d1, d2, ub1, ub2; ub1 := dimX; ub2 := dimY; d1 := randint( 1, ub1, U ); d2 := randint( 1, ub2, U ); WHILE M( d1, d2 ) = Wall DO BEGIN u := clocktime; d1 := randint( 1, ub1, U ); d2 := randint( 1, ub2, U ); END; M( d1, d2 ) := 'F'; !F=fin; xfin := d1; yfin := d2; out_fin( d *( dimX - 2 ) // 2 + d *( d1 -( dimX - 1 ) // 2 ), d *( dimy - 2 ) // 2 + d *( d2 -( dimy - 1 ) // 2 ) ); u := clocktime; d1 := randint( 1, ub1, U ); d2 := randint( 1, ub2, U ); WHILE M( d1, d2 ) = 'F' OR M( d1, d2 ) = Wall DO BEGIN u := clocktime; d1 := randint( 1, ub1, U ); d2 := randint( 1, ub2, U ); END; x := d1; y := d2; END debutFin; PROCEDURE PrintMaze( M ); !Affiche le labyrinthe; CHARACTER ARRAY M; BEGIN INTEGER i, j, xc, yc, x1, y1; xc := d *( dimX - 2 ) // 2; yc := d *( dimY - 2 ) // 2; plume( 2 ); couleur( "gray50" ); !Limite exterieure du labyrinthe: ; rectangle( xc - d *( dimx - 3 ) // 2, yc - d *( dimy - 3 ) // 2, xc + d *( dimx + 3 ) // 2, yc + d *( dimy + 3 ) // 2, 0 ); FOR j := 1 STEP 1 UNTIL dimY DO FOR i := 1 STEP 1 UNTIL dimX DO !afficher bloc selon M(i,j); IF M( i, j ) = Wall THEN BEGIN x1 := xc + d *( i -( dimX - 1 ) // 2 ); y1 := yc + d *( j -( dimy - 1 ) // 2 ); rectangle( x1, y1, x1 + d, y1 + d, 1 ); END; plume( 1 ); END PrintMaze; PROCEDURE Creer_labyrinthe( maze, x, y, xfin, yfin, direction ); !Effectue les operations necessaires pour generer le labyrinthe et le dessiner; NAME x, y, xfin, yfin, direction; CHARACTER ARRAY maze; INTEGER x, y, xfin, yfin, direction; BEGIN initier_maze( maze ); Excavate( 1, 1, maze ); debutFin( maze, x, y, xfin, yfin ); direction := 1; oldDir := 1; Grenouil( x, y, direction );pause(1); direction := 0; PrintMaze( maze ); END Creer_labyrinthe; !******** Procedures de calcul et d'affichage d'horloge, de pause ******* ******** et d'aide *****************************************************; PROCEDURE init_timer( first, last ); !Determine le clocktime correspondant au temps zero; NAME first, last; INTEGER first, last; BEGIN last := first := clocktime; timer_out( first ); END init_timer; PROCEDURE timer_out( last ); !Affiche le timer; INTEGER last; BEGIN texte( width - 50, 50, int_as_text( last - first ) ); END timer_out; PROCEDURE timer( last ); !Change last si necessaire; NAME last; INTEGER last; BEGIN INTEGER cloc, diff; cloc := clocktime; diff := cloc - last; IF diff >= 1 THEN BEGIN Effacer_Rect( width - 70, 40, width, 60 ); last := cloc; timer_out( last ); END; END timer; PROCEDURE arret( first ); !Pour faire une pause et arreter le timer; NAME first; INTEGER first; BEGIN INTEGER t1, t2; arret_temp. hide; continuer :- makebutton( "Continuer" ). placeUpRight; t1 := clocktime; continuer. wait; t2 := clocktime; first := first + t2 - t1; !Change first pour tenir compte du temps ecoule pendant la pause; continuer. hide; arret_temp. show; END; PROCEDURE aider( first ); !Pour afficher la fenetre d'aide; NAME first; INTEGER first; BEGIN PROCEDURE texte_g(T,y); !Affiche le texte a gauche de la fenetre; VALUE T; TEXT T; INTEGER y; BEGIN INTEGER l; l:=largeur_de_texte(T)//2+5; Fhelp.texte(l,y,T); END texte_g; INTEGER t1, t2; Fhelp :- MakeDessin( "Aide" ); etape := 0; INSPECT Fhelp DO BEGIN INTEGER w,h; SetSize(710,370);pause(1); w:=width//2; h:=height//2+50; police("helvetica",12); texte_g(" Le but de ce jeu est de faire arriver la grenouille au nenuphar le plus rapidement possible.",h-210); texte_g(" Pour deplacer la grenouille, utilisez les fleches du clavier ou cliquez sur les boutons:",h-160); texte_g("haut, bas, droite, gauche.",h-140); texte_g(" Si vous desirez arreter provisoirement pour reflechir, cliquez sur le bouton 'Pause'",h-110); texte_g("Le temps et les resultats seront alors arretes jusqu'a ce que vous cliquiez sur le bouton continuer.",h-90); texte_g(" Si vous desirez consulter vos resultats anterieurs, cliquez sur le bouton 'Resultat'",h-70); Fermer_aide :- makebutton( "Fermer" ). placeDownLeft; t1 := clocktime; Fermer_aide. wait; t2 := clocktime; first := first + t2 - t1; END; Fhelp. hide; etape := 3; END aider; !******** Procedures d'interaction avec l'utilisateur: boutons, ********* ******** fleches, demandes de renseignement ****************************; PROCEDURE Button_press( P ); !Pour traiter les pressions de boutons; REF(button) P; BEGIN IF P == up THEN BEGIN oldDir := direction; direction := 1; END; IF P == down THEN BEGIN oldDir := direction; direction := 2; END; IF P == left THEN BEGIN oldDir := direction; direction := 3; END; IF P == right THEN BEGIN oldDir := direction; direction := 4; END; IF P == stop THEN finir := arret_demande := TRUE; IF P == arret_temp THEN arret( first ); IF P == aide THEN aider( first ); IF P == scores THEN lecture( nom, first ); IF P == vit_b THEN change_vit( t ); IF P == aut_b THEN change_aut( autonom ); IF P == temp_b THEN change_temp( temps ); IF P == dimX_b THEN change_dimX( dimX ); IF P == dimY_b THEN change_dimY( dimY ); IF P == rejoue_b THEN jouer := TRUE; IF p == fin_b THEN exterminer := TRUE; END Button_press; PROCEDURE change_vit( vitesse ); !Pour changer la vitesse; NAME vitesse; REAL vitesse; BEGIN REAL v; v := - 1; WHILE v <= 0 DO v := ask_for_real( "Vitesse (cases par sec.): " ); vitesse := 1 / v; effacer_rect( 170, 70, 230, 40 ); texte( 200, 55, int_as_text( v ) & "c/sec" ); END change_vit; PROCEDURE change_aut( aut ); !Pour changer l'autonomie; NAME aut; INTEGER aut; BEGIN INTEGER autonom; !Pour eviter que refresh n'affiche "-1", c'est une autre var qu'on lit d'abord; autonom := - 1; WHILE autonom < 0 OR autonom > 100 DO autonom := ask_for_int( "% d'autonomie (100=autonomie totale):" ); aut:=autonom; effacer_rect( 170, 70 + 33, 230, 40 + 33 ); texte( 200, 55 + 33, int_as_text( aut ) & "%" ); END change_aut; PROCEDURE change_temp( temp ); !Pour changer le temps pour reussir; NAME temp; INTEGER temp; BEGIN INTEGER temps; temps := - 1; WHILE temps <= 0 OR temps > 60 DO temps := ask_for_int( "Nombre de secondes (<=60) pour sortir:" ); temp:=temps; effacer_rect( 170, 70 + 2 * 33, 230, 40 + 2 * 33 ); texte( 200, 55 + 2 * 33, int_as_text( temp ) & "s" ); END change_temp; PROCEDURE change_dimX( dimX ); !Pour changer dimX; NAME dimX; INTEGER dimX; BEGIN INTEGER dim; dim := - 1; WHILE dim <= 1 OR dimX > 63 OR mod( dimX, 2 ) = 0 DO dim := ask_for_int( "Dimension horizontale (nbre impair <=63)" ); d := IF dim >= dimY THEN 675 / dim ELSE 800 / dimY; dimx:=dim; effacer_rect( 170, 70 + 3 * 33, 230, 40 + 3 * 33 ); texte( 200, 55 + 3 * 33, int_as_text( dim ) ); END change_dimX; PROCEDURE change_dimY( dimY ); !Pour changer dimY; NAME dimY; INTEGER dimY; BEGIN INTEGER dim; dim := - 1; WHILE dim <= 1 OR dim > 63 OR mod( dimY, 2 ) = 0 DO dim := ask_for_int( "Dimension verticale (nbre impair <=63)" ); d := IF dimx >= dim THEN 675 / dimX ELSE 800 / dim; dimY:=dim; effacer_rect( 170, 70 + 4 * 33, 230, 40 + 4 * 33 ); texte( 200, 55 + 4 * 33, int_as_text( dimY ) ); END change_dimY; PROCEDURE handle_special_key_down( I ); !Pour gerer les pressions des fleches; INTEGER I; BEGIN direction := IF I = 16Rff52 THEN 1 ELSE IF I = 16Rff54 THEN 2 ELSE IF I = 16Rff51 THEN 3 ELSE IF I = 16Rff53 THEN 4 ELSE 0; END handle_special_key_down; PROCEDURE changer_variables1( vitesse, autonom, temps, dimX, dimY, nom ); !Affiche les boutons pour changer les var et valeurs par defaut la premiere fois; NAME nom; INTEGER autonom, temps, dimX, dimY; REAL vitesse; TEXT nom; BEGIN SetSize( 350, 250 ); pause( 1 ); texte( 200, 20, "Changer...Valeur par defaut" ); vit_b :- Makebutton( "vitesse..." ). PlaceAt( 50, 40 ); texte( 200, 55, int_as_text( entier( 1 / t ) ) & "c/sec" ); aut_b :- MakeButton( "autonomie..." ). PlaceBelow( vit_b ); texte( 200, 55 + 33, int_as_text( autonom ) & "%" ); temp_b :- MakeButton( "temps..." ). PlaceBelow( aut_b ); texte( 200, 55 + 2 * 33, int_as_text( temps ) & "s" ); dimX_b :- MakeButton( "largeur..." ). PlaceBelow( temp_b ); texte( 200, 55 + 3 * 33, int_as_text( dimX ) ); dimY_b :- MakeButton( "hauteur..." ). PlaceBelow( dimX_b ); texte( 200, 55 + 4 * 33, int_as_text( dimY ) ); rejoue_b :- MakeButton( "Jouer" ). PlaceBelow( dimY_b ); WHILE NOT jouer DO handle_pending_events; WHILE nom == NOTEXT DO !Demande le nom obligatoire; nom :- ask_for_text( "Votre nom:" ); vit_b. hide; aut_b. hide; temp_b. hide; dimX_b. hide; dimY_b. hide; rejoue_b. hide; effacer_Rect( 0, 0, width, height ); END changer_variables1; PROCEDURE changer_variables2( vitesse, autonom, temps, dimX, dimY ); !Affiche les boutons pour changer les var et valeurs par defaut pour les "rejoutes"; INTEGER autonom, temps, dimX, dimY; REAL vitesse; BEGIN etape := 2; SetSize( 350, 250 ); pause( 1 ); effacer_Rect( 0, 0, width, height ); aide. hide; up. hide; down. hide; left. hide; right. hide; stop. hide; arret_temp. hide; scores. hide; texte( 200, 20, "Changer...Valeur par defaut" ); vit_b.show; texte( 200, 55, int_as_text( entier( 1 / t ) ) & "c/sec" ); aut_b.show; texte( 200, 55 + 33, int_as_text( autonom ) & "%" ); temp_b.show; texte( 200, 55 + 2 * 33, int_as_text( temps ) & "s" ); dimX_b.show; texte( 200, 55 + 3 * 33, int_as_text( dimX ) ); dimY_b.show; texte( 200, 55 + 4 * 33, int_as_text( dimY ) ); rejoue_b.show; fin_b:- MakeButton( "Terminer" ). PlaceDownRight; WHILE NOT exterminer AND NOT jouer DO handle_pending_events; vit_b. hide; aut_b. hide; temp_b. hide; dimX_b. hide; dimY_b. hide; rejoue_b. hide; fin_b. hide; effacer_Rect( 0, 0, width, height ); etape := 0; IF NOT exterminer THEN BEGIN !Fait ca seulement si on veut rejouer; SetSize( 900, 900 ); pause( 1 ); aide. show; up. show; down. show; left. show; right. show; stop. show; arret_temp. show; scores. show; END; END changer_variables2; !******** Procedures d'animation et de verification interne ********** ******** pour que le jeu continue ou non ****************************; PROCEDURE choix_animal( m, dir, autonom ); !Change dir selon l'auton.; NAME dir; INTEGER dir, autonom; CHARACTER ARRAY m; BEGIN INTEGER u, choix; u := clocktime; choix := randint( 1, 100, u ); IF choix <= autonom THEN BEGIN dir := randint( 1, 4, u ); WHILE mur( m, x, y, dir ) DO dir := randint( 1, 4, u ); END; END choix_animal; PROCEDURE animation( A, oldDir, x, y ); !Effectue un "saut" dans la direction A a partir de (x,y); NAME x, y, oldDir; INTEGER A, oldDir, x, y; BEGIN encre( "white" ); grenouil( x, y, oldDir ); encre( "black" ); IF A = 1 THEN !1=haut, 2=bas, 3=gauche, 4=droite; y := y - 1 ELSE IF A = 2 THEN y := y + 1 ELSE IF A = 3 THEN x := x - 1 ELSE IF A = 4 THEN x := x + 1; Grenouil2( x, y, A ); pause( t / 2 ); encre( "white" ); Grenouil2( x, y, A ); encre( "black" ); Grenouil( x, y, A ); pause( t / 2 ); oldDir := A; END; BOOLEAN PROCEDURE mur( m, x, y, dir ); !Verif. si on touche un mur au proch.depl.; CHARACTER ARRAY m; INTEGER x, y, dir; BEGIN INTEGER xtest, ytest; IF dir = 1 THEN BEGIN ytest := y - 1; xtest := x; END ELSE IF dir = 2 THEN BEGIN ytest := y + 1; xtest := x; END ELSE IF dir = 3 THEN BEGIN xtest := x - 1; ytest := y; END ELSE IF dir = 4 THEN BEGIN xtest := x + 1; ytest := y; END; IF 1 <= xtest AND xtest <= dimX AND 1 <= ytest AND ytest <= dimY THEN mur := m( xtest, ytest ) = wall ELSE mur := TRUE; END; PROCEDURE Grenouil( x, y, dir ); !Dessine gren. en position repos; INTEGER x, y, dir; BEGIN corps( x, y, dir ); pattes1( x, y, dir ); END grenouil; PROCEDURE Grenouil2( x, y, dir ); !Dessine gren. en pos. "saut"; INTEGER x, y, dir; BEGIN corps( x, y, dir ); pattes2( x, y, dir ); END grenouil2; PROCEDURE calcule_centre( xc, yc, u, r ); !Quelques calculs souvent faits avant de dessiner; NAME xc, yc, u, r; INTEGER xc, yc, u, r; BEGIN xc := d *( dimX - 2 ) // 2 + d *( x -( dimX - 1 ) // 2 ) + d // 2; yc := d *( dimY - 2 ) // 2 + d *( y -( dimy - 1 ) // 2 ) + d // 2; u := d // 10; r := 3 * u; END calcule_centre; PROCEDURE corps( x, y, dir ); !Dessine le corps; INTEGER x, y, dir; BEGIN PROCEDURE oeil( x, y ); INTEGER x, y; cercle( xc + u * x, yc + u * y, u // 2, 0 ); PROCEDURE bouche( x1, y1, x2, y2 ); INTEGER x1, y1, x2, y2; ligne( xc + x1 * u, yc + y2 * u, xc + x2 * u, yc + y2 * u ); INTEGER r, u, xc, yc; calcule_centre( xc, yc, u, r ); cercle( xc, yc, r, 0 ); IF dir = 1 THEN BEGIN bouche( - 1, - 2, 1, - 2 ); oeil( 2, - 1 ); oeil( - 2, - 1 ); END ELSE IF dir = 2 THEN BEGIN bouche( - 1, 2, 1, 2 ); oeil( - 2, 1 ); oeil( 2, 1 ); END ELSE IF dir = 3 THEN BEGIN ligne( xc - 2 * u, yc + u, xc - 2 * u, yc - u ); oeil( - 1, 2 ); oeil( - 1, - 2 ); END ELSE IF dir = 4 THEN BEGIN ligne( xc + 2 * u, yc - u, xc + 2 * u, yc + u ); oeil( 1, 2 ); oeil( 1, - 2 ); END; END corps; PROCEDURE pattes1( x, y, dir ); !Dessine les pattes repliees; INTEGER x, y, dir; BEGIN INTEGER r, u, xc, yc; PROCEDURE lign( x1, y1, x2, y2 ); INTEGER x1, y1, x2, y2; ligne( xc + x1 * u, yc + y1 * u, xc + x2 * u, yc + y2 * u ); calcule_centre( xc, yc, u, r ); IF dir = 1 THEN BEGIN lign( 3, 0, 4, - 2 ); lign( 4, - 2, 3, 4 ); lign( 3, 4, 4, 4 ); lign( - 3, 0, - 4, - 2 ); lign( - 4, - 2, - 3, 4 ); lign( - 3, 4, - 4, 4 ); END ELSE IF dir = 2 THEN BEGIN lign( 3, 0, 4, 2 ); lign( 4, 2, 3, - 4 ); lign( 3, - 4, 4, - 4 ); lign( - 3, 0, - 4, 2 ); lign( - 4, 2, - 3, - 4 ); lign( - 3, - 4, - 4, - 4 ); END ELSE IF dir = 3 THEN BEGIN lign( 0, 3, - 2, 4 ); lign( - 2, 4, 4, 3 ); lign( 4, 3, 4, 4 ); lign( 0, - 3, - 2, - 4 ); lign( - 2, - 4, 4, - 3 ); lign( 4, - 3, 4, - 4 ); END ELSE IF dir = 4 THEN BEGIN lign( 0, 3, 2, 4 ); lign( 2, 4, - 4, 3 ); lign( - 4, 3, - 4, 4 ); lign( 0, - 3, 2, - 4 ); lign( 2, - 4, - 4, - 3 ); lign( - 4, - 3, - 4, - 4 ); END END pattes1; PROCEDURE pattes2( x, y, dir ); !Dessine les pattes alongees; INTEGER x, y, dir; BEGIN INTEGER r, u, xc, yc; PROCEDURE lign( x1, y1, x2, y2 ); INTEGER x1, y1, x2, y2; ligne( xc + x1 * u, yc + y1 * u, xc + x2 * u, yc + y2 * u ); calcule_centre( xc, yc, u, r ); IF dir = 1 THEN BEGIN lign( 3, 0, 3, 8 ); lign( 3, 8, 4, 8 ); lign( - 3, 0, - 3, 8 ); lign( - 3, 8, - 4, 8 ); END ELSE IF dir = 2 THEN BEGIN lign( 3, 0, 3, - 8 ); lign( 3, - 8, 4, - 8 ); lign( - 3, 0, - 3, - 8 ); lign( - 3, - 8, - 4, - 8 ); END ELSE IF dir = 3 THEN BEGIN lign( 0, 3, 8, 3 ); lign( 8, 3, 8, 4 ); lign( 0, - 3, 8, - 3 ); lign( 8, - 3, 8, - 4 ); END ELSE IF dir = 4 THEN BEGIN lign( 0, 3, - 8, 3 ); lign( - 8, 3, - 8, 4 ); lign( 0, - 3, - 8, - 3 ); lign( - 8, - 3, - 8, - 4 ); END END pattes1; BOOLEAN PROCEDURE arrivee( m, x, y ); !Teste si la grenouille est sur le nenuphar; CHARACTER ARRAY m; INTEGER x, y; arrivee := IF m( x, y ) = 'F' THEN TRUE ELSE FALSE; PROCEDURE check_time( last, finir ); !Teste si le temps est ecoule; NAME finir; INTEGER last; BOOLEAN finir; BEGIN IF last - first >= temps THEN finir := TRUE; END check_time; PROCEDURE Refresh; ! Rafraichit l'ecran selon l'etape actuelle; BEGIN ! Etape=0 permet d'eviter de rafraichir; IF etape = 1 THEN BEGIN explication; END ELSE IF etape = 2 THEN BEGIN INTEGER v; v := 1 / t; texte( 200, 20, "Changer...Valeur par defaut" ); texte( 200, 55, int_as_text( v ) & "c/sec" ); texte( 200, 55 + 33, int_as_text( autonom ) & "%" ); texte( 200, 55 + 2 * 33, int_as_text( temps ) & "s" ); texte( 200, 55 + 3 * 33, int_as_text( dimX ) ); texte( 200, 55 + 4 * 33, int_as_text( dimY ) ); END ELSE IF etape = 3 THEN BEGIN SetSize( 900, 900 ); pause( 1 ); Grenouil( x, y, direction ); PrintMaze( maze ); out_fin( d *( dimX - 2 ) // 2 + d *( xfin -( dimX - 1 ) // 2 ), d *( dimy - 2 ) // 2 + d *( yfin -( dimy - 1 ) // 2 ) ); END; END Refresh; !************ Procedures traitant fichiers et resultats ****************; PROCEDURE lecture( nom, first ); !Lit les resultats dans le fich. nom, et affiche les stats dans une fenetre; NAME first; INTEGER first; TEXT nom; BEGIN REF( infile ) F; ! =1==> declaration ; INTEGER N, t1, t2, i, max, min, s; Fscores :- MakeDessin( "Resultats anterieurs" ); F :- NEW infile( nom ); ! =2==> creation ; F. open( blanks( 80 ) ); ! =3==> ouverture avec tampon de 80 car ; Fscores. SetSize( 200, 130 ); pause( 1 ); INSPECT Fscores DO BEGIN IF NOT F. lastitem THEN N := F. inint; max := min := s := N; WHILE NOT F. endfile DO BEGIN IF N > max THEN max := N; IF N < min THEN min := N; i := i + 1; IF NOT F. lastitem THEN BEGIN N := F. inint; s := s + n; END; END boucle de lecture; texte( 100, 20, "Maximum:" & int_as_text( max ) ); texte( 100, 40, "Moyenne:" & int_as_text( IF i > 0 THEN S / i ELSE 0 ) ); texte( 100, 60, "Minimum:" & int_as_text( min ) ); texte( 100, 80, "Essais :" & int_as_text( i ) ); fermer_scores :- makebutton( "Fermer" ). placeDownLeft; t1 := clocktime; fermer_scores. wait; t2 := clocktime; first := first + t2 - t1; END; Fscores. hide; F. close; ! =5==> fermeture ; END lecture; PROCEDURE ecriture( nom, N ); !Ecrit le resultat N ds le fichier nom; TEXT nom; INTEGER N; BEGIN REF( outfile ) F;! =1==> declaration ; F :- NEW outfile( nom );! =2==> creation ; F. setaccess( "append" ); F. open( blanks( 40 ) ); ! =3==> ouverture avec tampon de 40 car ; F. outint( N, 0 ); ! =4==>ecriture de N ; F. close; ! =5==> fermeture ; texte( width // 2, height - 20, "Votre resultat: " & int_as_text( n ) ); END ecriture; PROCEDURE Fin_du_jeu ( maze, x, y, arret_demande); ! Agit selon la facon dont le jeu s'est termine; CHARACTER ARRAY maze; INTEGER x,y; BOOLEAN arret_demande; BEGIN IF arrivee( maze, x, y ) THEN BEGIN texte( width // 2, height - 40, "Vous y etes arrive!" ); ecriture( nom, calcul_score( autonom, temps, dimX, dimY ) ); pause( 3 ); END ELSE IF arret_demande THEN BEGIN texte( width // 2, height - 40, "Vous desirez arreter!" ); ecriture( nom, 0 ); pause( 3 ); END ELSE BEGIN texte( width // 2, height - 40, "Votre temps est ecoule!" ); ecriture( nom, 0 ); pause( 3 ); END determiner la fin du jeu; END Fin_du_jeu; INTEGER PROCEDURE calcul_score( autonom, temps, dimX, dimY ); !Calcule le resultat obtenu; INTEGER autonom, temps, dimX, dimY; calcul_score := 10 *( autonom + 1 ) *( dimX * dimY ) *( 61 - temps ); !********************** Programme principal ***************************; !Valeurs par defaut; t := 0.5; autonom := 0; temps := 60; dimX := 15; dimY := 15; d := 675 / dimX; etape := 1; Page_titre( Demarre ); etape := 2; changer_variables1( t, autonom, temps, dimX, dimY, nom ); etape := 0; SetSize( 900, 900 ); pause( 1 ); !Pause pour eviter d'ecrire alors que l'on reSize; Place_boutons (aide, up, down, left, right, stop, arret_temp, scores); WHILE NOT exterminer DO BEGIN !Boucle de jeu etape := 3; finir := FALSE; Creer_labyrinthe( maze, x, y, xfin, yfin, direction ); init_timer( first, last ); WHILE NOT finir DO BEGIN !Boucle de traitement d'evenements; handle_pending_events; choix_animal( maze, direction, autonom ); IF NOT mur( maze, x, y, direction ) THEN animation( direction, oldDir, x, y ); IF arrivee( maze, x, y ) THEN finir := TRUE; timer( last ); check_time( last, finir ); END boucle de traitement d'evenements; Fin_du_jeu ( maze, x, y, arret_demande); jouer := arret_demande:=FALSE; changer_variables2( t, autonom, temps, dimX, dimY ); END boucle de jeu; END Application CLASS laby; NEW laby( "***Labyrinthe***" ); END