      %   Bad situations for an open blocks world.

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

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

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

badSituation(do(moveToTable(X),S)) :- prove(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)) :-
                            prove(-goodTower(X,do(moveToTable(X),S))),
                            existsActionThatCreatesGoodTower(S).

existsActionThatCreatesGoodTower(S) :-
                       (A = move(Y,X) ; A = moveToTable(Y)),
                       poss(A,S), prove(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)),
    prove(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)),
 prove(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)),
 prove(goodTower(X1,do(moveToTable(X1),S)) &
       goodTower(X2,do(moveToTable(X2),S))).
