%  WARPLAN - the STRIPS problem
% <strips_classic>

add(  at( robot, P ),  goto1( P, _R )  ).
add(  nextto( robot, X ),  goto2( X, _R )  ).
add(  nextto( X, Y ),  pushto( X, Y, _R )  ).
add(  nextto( Y, X ),  pushto( X, Y, _R )  ).
add(  status( S, on ),  turnon( S )  ).
add(  on( robot, B ),  climbon( B )  ).
add(  onfloor,  climboff( _B )  ).
add(  inroom( robot,  R2 ),  gothrough( _D, _R1, R2 )  ).

del(  at( X, _Z ),  U  )    :-    moved( X, U  ).
del(  nextto( Z, robot ),  U  )    :-    !,   del(  nextto( robot, Z ),  U  ).
del(  nextto( robot,  X ),  pushto( X, _Y, _R )  )    :-    !,   fail.
del(  nextto( robot,  B ),  climbon( B )  )    :-    !,   fail.
del(  nextto( robot,  B ),  climboff( B )  )    :-    !,   fail.
del(  nextto( X, _Z ),  U  )    :-    moved(  X,  U  ).
del(  nextto( _Z, X ),  U  )    :-    moved(  X,  U  ).
del(  on( X, _Z ),  U  )   :-   moved(  X,  U  ).
del(  onfloor,  climbon( _B )  ).
del(  inroom( robot, _Z ),  gothrough( _D, _R1, _R2 )  ).
del(  status( S, _Z ),  turnon( S )  ).

moved(  robot,  goto1( _P, _R )  ).
moved(  robot,  goto2( _X, _R )  ).
moved(  robot,  pushto( _X, _Y, _R )  ).
moved(  X,  pushto( X, _Y, _R )  ).
moved(  robot,  climbon( _B )  ).
moved(  robot,  climboff( _B )  ).
moved(  robot,  gothrough( _D, _R1, _R2)  ).

can(  goto1( P, R ),
	locinroom( P, R )  &  inroom( robot, R )  &  onfloor  ).
can(  goto2( X, R ),
	inroom( X, R )  &  inroom( robot, R )  &  onfloor  ).
can(  turnon( lightswitch(S) ),
	on( robot, box(1) )  &  nextto( box(1), lightswitch(S) )  ).
can(  pushto( X, Y, R ),
	pushable( X )  &  inroom( Y, R )  &  inroom( X, R )  &
	nextto( robot, X )  &  onfloor  ).
can(  gothrough( D, R1, R2 ),
	connects( D, R1, R2 )  &  inroom( robot, R1 )  &
	nextto( robot, D )  &  onfloor  ).
can(  climboff( box(B) ),  on( robot, box(B) )  ).
can(  climbon( box(B) ),  nextto( robot, box(B) )  &  onfloor  ).

always(  inroom( D, R1 )  )    :-    always(  connects( D, R1, _R2 )  ).
always(  connects( D, R2, R1 )  )    :-    connects1(  D, R1, R2  ).
always(  connects( D, R1, R2 )  )    :-    connects1(  D, R1, R2  ).
always(  pushable( box(_N) )  ).
always(  locinroom( point(N), room(1) )  )    :-    range(  N, 1, 5  ).
always(  locinroom( point(6), room(4) )  ).
always(  inroom( lightswitch(1), room(1) )  ).
always(  at( lightswitch(1), point(4) )  ).

connects1(  door(N), room(N), room(5)  )    :-    range(  N, 1, 4  ).

range(  M, M, _  ).
range(  M, L, N  )    :-
	L  <  N,    L1  is  L + 1,    range(  M, L1, N  ).

imposs(  at( X, Y )  &  at( X, Z )  &  notequal( Y, Z )  ).

given(  strips1,  at( box(N), point(N) )  )    :-    range(  N, 1, 3  ).
given(  strips1,  at( robot, point(5) )  ).
given(  strips1,  inroom( box(N), room(1) )  )    :-    range(  N, 1, 3  ).
given(  strips1,  onfloor  ).
given(  strips1,  status( lightswitch(1), off )  ).
given(  strips1,  inroom( robot, room(1) )  ).

% A few tests.
p( X )  :-  plans( X, strips1 ).

wait :-  see( user ),  display( '<press "return" to continue>' ),
         rdch( _ ),    seen.

:-   p( at( robot, point(5) ) ),  wait.
:-   p( at( robot, point(1) ) & at( robot, point(2) ) ),  wait.
:-   p( at( robot, point(4) ) ),  wait.
:-   p( status( lightswitch(1), on ) ),  wait.
:-   p( at(robot, point(6) ) ),  wait.
:-   p( nextto( box(1), box(2) ) & nextto( box(3), box(2) ) ),  wait.
:-   p( inroom( robot, room(2) ) ), wait.
:-   p( status( lightswitch(1), on ) & inroom( robot, room(2) ) ),  wait.
:-   p( inroom( robot, room(2) ) & status( lightswitch(1), on ) ),  wait.
:-   p( nextto( box(2), box(3) ) & nextto( box(3), door(1) ) &
        status( lightswitch(1), on ) & nextto( box(1), box(2) ) &
        inroom( robot, room(2) ) ),  wait.
end.
