/*				APPENDIX A
			Section A.3 A Blocks World Example
*/

:- set_flag(print_depth,100).
:- pragma(debug).
/* :- nodbgcomp. */
:- set_flag(all_dynamic, on).
:- dynamic(p/1).

/* This program has to build (non-deterministically) one of the two towers 
                r               p
                o               a
                m      or       r
                e               i
                                s
given several blocks with letters  r, o, m, e, p, a, r, i. 
There is no block with ``p''.
Final positions of other blocks can be arbitrary.   */

/*  Primitive Action Declarations  */

primitive_action(moveToTable(X)).
primitive_action(move(X,Y)).

/*  Action Precondition Axioms  */

poss(move(X,Y),S) :- clear(X,S), clear(Y,S), not X = Y.
poss(moveToTable(X),S) :- clear(X,S), not ontable(X,S).


/*  Successor State Axioms  */ 

on(X,Y,do(A,S)) :- A = move(X,Y) ;
                   on(X,Y,S), A \= moveToTable(X), A \= move(X,Z).

ontable(X,do(A,S)) :- A = moveToTable(X) ; 
                      ontable(X,S), A \= move(X,Y).

clear(X,do(A,S)) :- (A = move(Y,Z) ; A = moveToTable(Y)), on(Y,X,S) ;
                    clear(X,S), A \= move(Y,X). 

/* Initial Situation: everything is on table and clear.    */
r(r1).   r(r2).             o(o1).  o(o2).  o(o3).
m(m1). m(m2).               e(e1).  e(e2).

/* There is no block with the letter "p"  */
a(a1).  i(i1).  i(i2).   s(s7).

ontable(r1,s0).  ontable(r2,s0).
ontable(o1,s0).  ontable(o2,s0).  ontable(o3,s0).
ontable(m1,s0).  ontable(m2,s0).
ontable(e1,s0).  ontable(e2,s0). 
ontable(s7,s0).  
ontable(a1,s0). 
ontable(i1,s0).  ontable(i2,s0).   
ontable(n,s0).  ontable(f,s0). 

clear(r1,s0).  clear(r2,s0).
clear(o1,s0).  clear(o2,s0).  clear(o3,s0).
clear(m1,s0).  clear(m2,s0).
clear(e1,s0).  clear(e2,s0). 
clear(s7,s0).
clear(a1,s0). 
clear(i1,s0).  clear(i2,s0).    
clear(n,s0).
clear(f,s0).

build :- doEM((tower : ?(goal)), s0, S).

proc(tower,
             makeParis # makeRome).

proc(makeParis,
    pi(b0, ?(s(b0) & ontable(b0) & clear(b0)) :  
        pi(b1, ?(i(b1)) : move(b1,b0) :
            pi(b2, ?(r(b2)) : move(b2,b1) :
                pi(b3, ?(a(b3)) : move(b3,b2) :
                    pi(b4, ?(p(b4)) : move(b4,b3))))))).

proc(makeRome,
    pi(b0, ?(e(b0) & ontable(b0) & clear(b0)) :
        pi(b1, ?(m(b1)) : move(b1,b0) :
            pi(b2, ?(o(b2)) : move(b2,b1) : 
                pi(b3, ?(r(b3)) : move(b3,b2)))))).


goal(S) :-  p(Y1), a(Y2), r(Y3), i(Y4), s(Y5), ontable(Y5,S),
            on(Y4,Y5,S), on(Y3,Y4,S), on(Y2,Y3,S), on(Y1,Y2,S), clear(Y1,S);
            r(X1), o(X2), m(X3), e(X4), 
            ontable(X4,S), on(X3,X4,S), on(X2,X3,S), on(X1,X2,S), clear(X1,S).


  restoreSitArg(ontable(X),S,ontable(X,S)).
  restoreSitArg(on(X,Y),S,on(X,Y,S)).
  restoreSitArg(clear(X),S,clear(X,S)).
  restoreSitArg(goal,S,goal(S)).