%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 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) :- move(B,L,T), #succ(T,T1).

% move(B,L) causes -on(B,L1) if on(B,L1)
-on(B,L,T1) :- move(B,_,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).

% 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)
:- move(B,_,T), move(B1,_,T), B<>B1.

% nonexecutable (move(B,L), move(B1,L1)) if (L<>L1)
:- move(_,L,T), move(_,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
move(B,L,T) v -move(B,L,T) :- block(B), location(L), actiontime(T), not onblock(L,T), not onblock(B,T), B<>L.

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