% making Move in State1 results in State2;
% move( State1, Move, State2)

% representing the current state
% state( MonkeyHorizontal, MonkeyVertical, BoxPosition, HasBanana)

%Our goal is to get the banana.

goal(state(_,_,_,has)).

%Our start state...

start(state(atfloor,onfloor,atwindow,hasnot)).

%This is how we can get from state1 to state2:

canget( S,[]) :- goal(S).             % base case
canget( State1,[Act|Rest])  :-        % general case
  move( State1, Act, State2),         % Do something
  canget( State2,Rest).               % Repeat

%The knowledge base:

move( state( middle, onbox, middle, hasnot),   % Before move
      grasp,                                   % Grasp banana
      state( middle, onbox, middle, has) ).    % After move
move( state( P, onfloor, P, H),
      climb,                                   % Climb box
      state( P, onbox, P, H) ). 
move( state( P1, onfloor, P1, H),
      push( P1, P2),                           % Push box from P1 to P2
      state( P2, onfloor, P2, H) ).
move( state( P1, onfloor, B, H),
      walk( P1, P2),                           % Walk from P1 to P2
      state( P2, onfloor, B, H) ).

%Main program:

main :- start(S0), canget(S0,  Steps),
        forall(member(Step,Steps), (print(Step),nl)).



dfid(Max) :- 
	start(S0),
	between(1,Max,Depth), % on backtracking, Depth=1,2,3,...
	length(Steps,Depth),  % Steps is a list of size Depth
	print(leash(Steps)),nl,
	canget(S0,Steps),
	print(Depth),nl,
    forall(member(Step,Steps), (tab(4),print(Step),nl)).

