% blocksC4.dl with split and cascaded move-pred.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Blocks world domain description in C
% Elementary Actions: move(B,L) for all blocks B and locations L
% Fluents: on(B,L) for all blocks B and locations L

% effect of moving a block

% move(B,L) causes on(B,L)  (for all blocks B and locations L)
on(B,L,T1) :- moveB(B,T), moveL(L,T), #succ(T,T1).

% move(B,L) causes -on(B,L1) if on(B,L1)
-on(B,L,T1) :- moveB(B,T), moveL(_,T), on(B,L,T), #succ(T,T1).


% a block can be moved only when it's clear
% nonexecutable move(B,L) if on(B1,B) (for all blocks B,B1 and locations L)
% :- move(B,L,T), on(B1,B,T).
% pushed into guess


% any two blocks cannot be on the same block at the same time.         
% that means a block cannot be moved to an occupied block:
% nonexecutable move(B,B1) if on(B2,B1) & block(B1)
% :- move(B,B1,T), on(B2,B1,T), block(B1).
% pushed into guess using the following auxiliary predicate:
onblock(B,T) :- on(_,B,T), block(B).

% wherever a block is, it's not anywhere else                          
% caused -on(B,L1) if on(B,L) (for all blocks B, and locations L,L1
%                                where -(L=L1))                         (2)
% assuming a complete initial description this can be skipped !!!



% a block is never on top of itself 
% that means it cannot be moved on top of itself:
% nonexecutable move(B,B). 
% :- move(B,B,T).
% pushed into guess (B<>L).

% no concurrency
% nonexecutable (move(B,L), move(B1,L1)) if (B<>B1)
:- moveB(B,T), moveB(B1,T), B<>B1.
% nonexecutable (move(B,L), move(B1,L1)) if (L<>L1)
:- moveL(L,T), moveL(L1,T), L<>L1.


% inertial on
on(B,L,T1) :- on(B,L,T), not -on(B,L,T1), #succ(T,T1).


%Guess the move
moveB(B,T) v -moveB(B,T) :- block(B), actiontime(T), not onblock(B,T).
moveL(L,T) v -moveL(L,T) :- location(L), not onblock(L,T), B<>L, moveB(B,T).

true.
actiontime(T) :- T < #maxint, #int(T).
location(table) :- true.
location(B) :- block(B).

