/****************************************************************************/

/*               A Z E R T Y O P de P. Greussay, 
                 adapté à Prolog par J-F. Perrot
                                                                              */
/******************************************************************************/

/*   Utilitaires 

printlist([]):- nl.
printlist([T|C]):- write(T),printlist(C).
*/
printlist(L) :- maplist(write, L), nl.
  
/*   L'univers d'AZERTYOP   */

cube(0).
cube(1).
cube(2).
cube(3).
cube(4).

:- dynamic sur/2.
init :- 
    retractall(sur(X, Y)),
	assert(sur(1,0)),
	assert(sur(4,1)),
	assert(sur(2,0)),
	assert(sur(3,0)).

/*  D'abord une boucle infinie d'interaction "toplevel"         */

azer :- init, encore.
encore :-
		nl, printlist(['À vos ordres M\'sieu ! ']), nl, 
       	read(C), exec(C), 
        encore.

/*           Les tâches d'AZERTYOP                            */

exec(fin):- !,printlist(['Au ', revoir]), fail.
exec(montre):- !, montre.
exec(pose(X,Y)):- verifie(X,Y), !, pose(X,Y).
exec(pose(X,Y)):- !, printlist(['Y m\'faut des cubes M\'sieu ! ']).
exec(X):- printlist(['J\'compran pas M\'sieu ! ']),
            tab(15), write(X), nl.

montre:- sur(X,0), write(X), write(' est par terre'), nl, fail.
montre:- sur(X,Y), Y \= 0, write(X), write(' est sur '), write(Y), 
         nl, fail.
montre:- printlist([' Et voila tout !']), nl.

pose(0,X):- !, printlist(['J\'peux pas poser la terre M\'sieu !']), nl.
pose(X,X):- !, printlist(['Ça s\'peut pas M\'sieu !']), nl.
pose(X,Y):- sur(X,Y), !, printlist(['Il y est déjà M\'sieu !']), nl.
pose(X,Y):- degager(X), degager(Y), 
              retract(sur(X,_)), !,    /* pas de back-track sur "retract" */
              assert(sur(X,Y)), chante(X,Y).

chante(X,0) :- !, write('J\'ai posé '), write(X), write(' par terre'), nl.
chante(X,Y) :- write('J\'ai posé '), write(X), write(' sur '), write(Y), nl.
 
degager(0):- !.
degager(X):- sur(Y,X), !, pose(Y,0).
degager(X).

verifie(X,Y):- cube(X), !, verif2(Y).
verifie(X,Y):- printlist([X, ' n\'est pas un cube !']), verif2(Y), fail.
verif2(Y) :- cube(Y), !.
verif2(Y) :- printlist([Y, ' n\'est pas un cube !']), fail.
