%  Messy Blocks World
%  
%  We select an action, nature selects the outcome.  After each action,
%  we need to check the world to see what nature actually did.
%  
%  What we probably want to end up with: carelessly stack the first
%  few, then carefully stack the last ones.
%  
%  Possible "problem": "messup" outcome (toppling original tower) is
%  probably a fortuitous outcome, so that's what the planner should
%  plan.  Actually, may be that's fine -- first present it without
%  messup, and then with messup and argue that what it does is the
%  right thing in the first place.
%  
%  How many actions do we need???
%  
%  There is no checking against puton(table, ...) and careful(table, ...)
%  and ontable(table, ...).  (Easy enough to add).


% First a couple of auxiliary relations
% 
% The above and below relations

% U is above v
above(U,V,S) <- on(U,V,S) & V \= table.
above(U,V,S) <- V \= table & on(U,W,S) & above(W,V,S).

not_above(U,V,S) <- on(U,table,S) & V \= table.
not_above(U,V,S) <- on(U,W,S) & W \= V & not_above(W,V,S).

% U is below v
below(U,V,S) <- above(V,U,S).
not_below(U,V,S) <- not_above(V,U,S).

%---------------%
%  The Actions  %
%---------------%

% I still think it's weird to put priors on these.

controllable([puton(X,Z,S),
              careful(X,Z,S),
              nothing(X,S)]).

%------------------%
%  puton(X,Z,S)  %
%------------------%

% preconds true
%
% If the preconditions are true, then one of these happen.

random([puton_success(X,S): 0.8,
        puton_topple(X,S): 0.05,
        puton_drop(X,S): 0.15]).

% preconds false
%
% If the preconditions are false, then either nothing happens, or the
% whole tower that x is in topples.  We should really discriminate
% precondition failures much better, but for now, this will do.  (i.e.,
% messup could mean that X is not clear or z is not clear or X is below
% z or X is already on z, etc..

random([puton_same(X,S): 0.8,
        puton_messup(X,S): 0.2]).

% preconditions

puton_preconds(X,Z,S) <- clear(X,S) & clear(Z,S) & X \= Z & X\= table.

not_puton_preconds(table,_,_) <- true.
not_puton_preconds(X,X,_) <- X \= table.
not_puton_preconds(X,Z,S) <-
   block(W) & on(W,X,S) & X\= table.
not_puton_preconds(X,Z,S) <-
   clear(X,S) & block(W) & on(W,Z,S) & X\= table.
%-------- Effects

% preconds true

% It so happens that Y always becomes clear as long as puton is
% possible and attempted.

clear(Y,S+1) <- puton(X,Z,S) & on(X,Y,S) & puton_preconds(X,Z,S) & Y\= table.

clear(table,_) <- true.

% preconds true, success
%
% Success means the normal thing happens

on(X,Z,S+1) <- puton(X,Z,S) & puton_success(X,S)
        & puton_preconds(X,Z,S).
on(U,V,S+1) <- puton(X,Z,S) & puton_success(X,S)
        & puton_preconds(X,Z,S)
        & on(U,V,S) & U \= X.
clear(U,S+1) <- puton(X,Z,S) & puton_success(X,S)
        & puton_preconds(X,Z,S)
        & clear(U,S) & U \= table.

% preconds true, topple
%
% Topple means that the target tower (Z) is toppled (as well as X).

on(W,table,S+1) <- puton(X,Z,S) & puton_topple(X,S)
        & puton_preconds(X,Z,S)
        & below(W,Z,S).
on(X,table,S+1) <- puton(X,Z,S) & puton_topple(X,S)
        & puton_preconds(X,Z,S).
%on(Z,table,S+1) <- puton(X,Z,S) & puton_topple(X,S)
%        & puton_preconds(X,Z,S)& Z \= table.
clear(W,S+1) <- puton(X,Z,S) & puton_topple(X,S)
        & puton_preconds(X,Z,S)
        & below(W,Z,S).
on(U,V,S+1) <- puton(X,Z,S) & puton_topple(X,S)
        & puton_preconds(X,Z,S)
        & on(U,V,S)
        & U \= X
        & not_below(U,Z,S).
clear(U,S+1) <- puton(X,Z,S) & puton_topple(X,S)
        & puton_preconds(X,Z,S)
        & clear(U,S) & U \= table
        & not_below(U,Z,S).

% preconds true, drop
%
% Drop means that we drop the block.  That's it.

on(X,table,S+1) <- puton(X,Z,S) & puton_drop(X,S)
        & puton_preconds(X,Z,S).
on(U,V,S+1) <- puton(X,Z,S) & puton_drop(X,S)
        & puton_preconds(X,Z,S)
        & on(U,V,S)
        & U \= X.
clear(U,S+1) <- puton(X,Z,S) & puton_drop(X,S)
        & puton_preconds(X,Z,S) & U \= table
        & clear(U,S).
% preconds false, same
%
% Same means nothing changes.

on(X,Y,S+1) <-  puton(X,Z,S) & puton_same(X,S)
        & on(X,Y,S)
        & not_puton_preconds(X,Z,S).
clear(X,S+1) <-  puton(X,Z,S) & puton_same(X,S)
        & clear(X,S) & X \= table
        & not_puton_preconds(X,Z,S).

% preconds false, messup
%
% messup means everything in X's tower ends up on the table.

on(X,table,S+1) <- puton(X,Z,S) & puton_messup(X,S)
        & X \= table
        & not_puton_preconds(X,Z,S).
clear(X,S+1) <- puton(X,Z,S) & puton_messup(X,S)
        & X \= table
        & not_puton_preconds(X,Z,S).
on(W,table,S+1) <- puton(X,Z,S) & puton_messup(X,S)
        & (above(W,X,S) ; below(W,X,S))
        & W \= table
        & not_puton_preconds(X,Z,S).
clear(W,S+1) <- puton(X,Z,S) & puton_messup(X,S)
        & (above(W,X,S) ; below(W,X,S))
        & W \= table
        & not_puton_preconds(X,Z,S).
on(U,V,S+1) <-  puton(X,Z,S) & puton_messup(S)
        & on(U,V,S)
        & not_above(U,X,S) 
        & not_below(U,X,S)
        & not_puton_preconds(X,Z,S).
clear(U,S+1) <-  puton(X,Z,S) & puton_messup(S)
        & not_puton_preconds(X,Z,S)& U \= table
        & clear(U,S).


%--------------------%
%  careful(X,Y,Z,S)  %
%--------------------%


%  The axioms for careful are exactly the same as for puton except that
%  the priors over the possible outcomes are different.



%  Initial state:
%
%                 b
%                 c
%          a      d
%      ----------------------

on(a,table,0) <- true.
clear(a,0) <- true.
on(b,c,0) <- true.
on(c,d,0) <- true.
on(d,table,0) <- true.
clear(b,0) <- true.

block(a) <- true.
block(b) <- true.
block(c) <- true.
block(d) <- true.

%  Goal state
%
%  We happen to have a goal state for this domain.

% explain(on(b,a,(0+1)+1),[puton(b,a,0),puton(c,b,0+1)]).
% explain(on(b,X,(0+1)+1),[puton(b,a,0),puton(c,b,0+1)]).
% explain(on(b,a,0+1),[puton(b,a,0)]).

goal(S) <- on(d,c,S)
        & on(c,b,S)
        & on(b,a,S)
        & on(a,table,S)
        & clear(d,S).

%  Utility

utility(U) <- goal(S) & U is 10-S.


% & ~ (goal(t) & t < s)
