/*****  Un semplice pianificatore forward ****************/


/**** le transizioni, predicato move aperto   ********/

/*   piano(out: MosseDaFare):   MosseDaFare è un piano dallo stato iniziale
     soluzione(in: S,in: StatiPercorsi,out: MosseDaFare);  S è lo stato
     raggiunto partendo da quello iniziale attraverso StatiPercorsi,
     MosseDaFare sono un piano da S ad un goal
*/

piano(P) :-  init(S),
             soluzione(S,[S],P).

soluzione(S,_,[]) :- goal(S).
soluzione(S1,LS,[M|P]):- move(S1,M,S2),
                         not(member(S2,LS)),
                         soluzione(S2,[S2|LS],P).


/***** Una reppresentazione del problema dei missionari e cannibali ******/

/****** Gli stati ************************************************************
 stato(L,CS,MS,CD,MD) ground:   L =1:  riva sinistra
                                L = -1: riva destra
                                CS, MS:  cannibali e missionari sulla riva sinistra
                                CD, MD: cannibali e missionari sulla destra
*******************************************************************************/

stato(st(_,CS,MS,CD,MD)) :- CS+CD=:=3, 0 =< CS, 0 =< CD, 
                            CS =:= MS, CD =:= MD ,
                            MS =\= 0, MD =\= 0.
stato(st(_,CS,MS,CD,MD)) :- CS+CD=:=3, 0 =< CS, 0 =< CD, 
                           (MS =:= 0,MD=:=3; MD =:= 0,MS =:= 3).
                           
/************** le azioni ********************************************
  tr(R,I,J)  traghetto I cannibali e J missionari dalla riva R
  ********************************************************************/

tr(_,I,J) :- I=2,J=0;
             I=1,J=0;
             I=1,J=1;
             I=0,J=1;
             I=0,J=2.

/********************** le mosse ********************************************/

move(st(L,CS,MS,CD,MD), tr(L,I,J), st(L1,CS1,MS1,CD1,MD1)) :-
                                    tr(L,I,J),
                                    L1 is - L,
                                    CS1 is CS - L*I,
                                    MS1 is MS - L*J,
                                    CD1 is CD + L*I,
                                    MD1 is  MD + L*J,
                                    stato(st(L1,CS1,MS1,CD1,MD1)).


/***** stato iniziale e goal **********************************************/

init(st(1,3,3,0,0)).
goal(st(-1,0,0,3,3)).

/*********************** esecuzione del piano (simulata a video) *********/

exec(P) :- init(S),
           writeln(S),
           exec(P,S).

exec([],_):- writeln(fatto).
exec([X|P],S) :- write(X), 
                 move(S,X,S1), 
                 writeln(S1), 
                 exec(P,S1).

                                    

