% Blocks world coding from the paper 
% Logic Programs with Stable Model Semantics as a Constraint
% Programming Paradigm
%
% Ilkka Niemela
%
% Presented at Computational Aspects of Nonmonotonic Reasoning 
% Special workshop at the 7th International Workshop on Nonmonotonic Reasoning
% Trento, Italy May 30 - June 1, 1998. 
%
% April 10, 1998
% Ilkka.Niemela@hut.fi 
% - allows parallel moves 


% goal predicate
goal(T2) :- time(T1), nextstate(T2,T1), goal(T1).
gl :- time(T), goal(T).

% With this goal conditions 
% goal_condition1(_,_,T),..., goal_conditionN(_,_,T)
% are used as follows:
% goal(T) :- time(T), goal_condition1(_,_,T),..., goal_conditionN(_,_,T).


% operator preconditions
moveop(X,Y,T):- 
	time(T),
	moveable(X),
	block(Y),
	not eq_block(X,Y),
        on_something(X,T),
	not blocked_move(X,Y,T).

:-      covered(X,T),
        moveop(X,Y,T).
:-      covered(Y,T),
        moveop(X,Y,T).


% operator effects
on(X,Y,T2) :- 
	time(T1),
	nextstate(T2,T1),
	moveop(X,Y,T1).

on_something(X,T) :-
	on(X,Z,T).

covered(X,T) :-
	moveable(X),
        on(Z,X,T).

moveable(X) :- 
	block(X), 
	not eq_block(table,X).

% frame axioms
on(X,Y,T2) :-
	time(T1),
	nextstate(T2,T1),
        on(X,Y,T1),
        not moving(X,T1).

moving(X,T) :- 
        moveop(X,Y,T).

% Stop applying operators when the goal has been reached
:-	moveop(X,Y,T),
	moveable(X),
	block(Y),
        goal(T).

% moveop(X,Y,T) is blocked if its not chosed (not moveop(X,Y,T) holds)
blocked_move(X,Y,T) :- 
	time(T),
	moveable(X),
	block(Y),
	not moveop(X,Y,T).

% An object can be moved by one move operation at a time 
:-	moveop(X,Y,T),
	moveable(X),
	block(Y),
	moveop(X,Z,T),
      	not eq_block(Y,Z).

% An object cannot be moved on top of an object that is moved
:-	moveop(X,Y,T),
	moveable(X),
	moving(Y,T).

% Two objects cannot be moved on top of the same object by  
% one move operation at a time 
:-	moveop(X,Y,T),
	moveable(X),
	block(Y),
	not eq_block(Y,table),
	moveop(Z,Y,T),
      	not eq_block(X,Z).

% pruning rules
% do not move blocks from table to table
:- 
	moveop(X,table,T), 
	on(X,table,T).

% do not move a block on top of something and then on the table
:- 
	nextstate(T2,T1),
	moveop(X,Y,T1), 
	moveop(X,table,T2).


% compute 1 {goal, not inco}
gl?

% facts
eq_block(X,X) :- block(X).

block(table).

nextstate(t1,t0).
nextstate(t2,t1).
nextstate(t3,t2).
nextstate(t4,t3).
nextstate(t5,t4).
nextstate(t6,t5).
nextstate(t7,t6).
nextstate(t8,t7).
nextstate(t9,t8).
nextstate(t10,t9).
nextstate(t11,t10).
nextstate(t12,t11).
nextstate(t13,t12).
nextstate(t14,t13).
nextstate(t15,t14).
nextstate(t16,t15).
nextstate(t17,t16).
nextstate(t18,t17).
nextstate(t19,t18).
nextstate(t20,t19).
nextstate(t21,t20).
nextstate(t22,t21).
nextstate(t23,t22).
nextstate(t24,t23).
nextstate(t25,t24).

