
/* direttive per SWI-prolog */

:- discontiguous badSituation/1.

:- multifile clear/2,
	on/3,
	ontable/2.

    %  Prolog Clauses for a Simple Blocks World

%  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.

clear(X,do(A,S)) :- (A = move(Y,_) ; A = moveToTable(Y)), on(Y,X,S) ;
                    clear(X,S), not(A = move(Y,X)).
on(X,Y,do(A,S)) :- A = move(X,Y) ;
                   on(X,Y,S), not(A = moveToTable(X)), not(A = move(X,_)).
ontable(X,do(A,S)) :- A = moveToTable(X) ;
                      ontable(X,S), not(A = move(X,_)).

%  Primitive Action Declarations.

primitive_action(move(_,_)).    primitive_action(moveToTable(_)).



    %  Bad Situations for a Simple Blocks World

%  Don't create a bad tower by a move action.

badSituation(do(move(X,Y),S)) :- not(goodTower(X,do(move(X,Y),S))).

%  Don't move anything from a good tower to the table.

badSituation(do(moveToTable(X),S)) :- goodTower(X,S).

/*  Opportunistic rule: If an action can create a good tower, don't
    do a bad-tower-creating moveToTable action.  */

badSituation(do(moveToTable(X),S)) :-
                            not(goodTower(X,do(moveToTable(X),S))),
                            existsActionThatCreatesGoodTower(S).

existsActionThatCreatesGoodTower(S) :-
                       (A = move(Y,_) ; A = moveToTable(Y)),
                       poss(A,S), goodTower(Y,do(A,S)).

%  Canonical ordering of good-tower producing actions.

badSituation(do(move(X1,Y1),do(move(X2,Y2),S))) :- X1 @< X2,
                        poss(move(X1,Y1),S),
                        poss(move(X2,Y2),do(move(X1,Y1),S)).
badSituation(do(move(X1,Y1),do(moveToTable(X2),S))) :- X1 @< X2,
                        poss(move(X1,Y1),S),
                        poss(moveToTable(X2),do(move(X1,Y1),S)),
                        goodTower(X2,do(moveToTable(X2),S)).
badSituation(do(moveToTable(X1),do(move(X2,Y2),S))) :- X1 @< X2,
                        poss(moveToTable(X1),S),
                        poss(move(X2,Y2),do(moveToTable(X1),S)),
                        goodTower(X1,do(moveToTable(X1),S)).
badSituation(do(moveToTable(X1),do(moveToTable(X2),S))) :- X1 @< X2,
                        poss(moveToTable(X1),S),
                        poss(moveToTable(X2),do(moveToTable(X1),S)),
                        goodTower(X1,do(moveToTable(X1),S)),
                        goodTower(X2,do(moveToTable(X2),S)).

