%%% farmer, goose, grain, fox problem
%% sides of the river are named thisSide and farSide
%% Entities in the story are named farmer, goose, grain, and fox
%% initial state is named initState
%% many predicates take an argument Bound, which is a number giving
%% the max depth to go to in trying to prove the predicate
%% the only action is cross(X) where X is one of fox, goose, grain, or
%% farmer. It means that the farmer crosses the river with X. If
%% X is farmer, he crosses by himself.
% otherside(S1, S2) if S1 is the other side from S2
otherside(thisSide, farSide).
otherside(farSide, thisSide).
% oppositeSides(X, Y, State, Bound) if X and Y are on opposite
% sides of the river from each other is state State.
oppositeSides(X, Y, State, Bound):-
onside(Side, X, State, Bound),
otherside(Side, Side2),
onside(Side2, Y, State, Bound).
% onside(Side, Entity, State, Bound) if Entity is on side Side in state State
% initial state
onside(thisSide, farmer, initState, Bound).
onside(thisSide, goose, initState, Bound).
onside(thisSide, grain, initState, Bound).
onside(thisSide, fox, initState, Bound).
% effect axioms
onside(Side, farmer,result(cross(goose),State), Bound):-
Bound>0,
Lower is Bound - 1,
otherside(Side, Side2),
onside(Side2, farmer,State,Lower),
onside(Side2, goose,State,Lower).
onside(Side, farmer,result(cross(fox),State), Bound):-
Bound>0,
Lower is Bound - 1,
otherside(Side, Side2),
onside(Side2, farmer,State,Lower),
onside(Side2, fox,State,Lower),
oppositeSides(goose, grain, State, Lower). % precondition for act
% if goose and grain are not on opposite sides before
% the cross is done, then either before or after the
% act they will have been alone together which is
% not allowed.
onside(Side, farmer,result(cross(farmer),State), Bound):-
Bound>0,
Lower is Bound - 1,
otherside(Side, Side2),
onside(Side2, farmer,State,Lower),
oppositeSides(goose, fox, State, Lower), % precondition for act
oppositeSides(goose, grain, State, Lower). % precondition for act
onside(Side, farmer,result(cross(grain),State), Bound):-
Bound>0,
Lower is Bound - 1,
otherside(Side, Side2),
onside(Side2, farmer,State,Lower),
onside(Side2, grain,State,Lower),
oppositeSides(goose, fox, State, Lower). % precondition for act
onside(Side, goose,result(cross(goose),State), Bound):-
Bound>0,
Lower is Bound - 1,
otherside(Side, Side2),
onside(Side2, farmer,State,Lower),
onside(Side2, goose,State,Lower).
onside(Side, fox,result(cross(fox),State), Bound):-
Bound>0,
Lower is Bound - 1,
otherside(Side, Side2),
onside(Side2, farmer,State,Lower),
onside(Side2, fox,State,Lower),
oppositeSides(goose, grain, State, Lower). % precondition for act
onside(Side, grain,result(cross(grain),State), Bound):-
Bound>0,
Lower is Bound - 1,
otherside(Side, Side2),
onside(Side2, farmer,State,Lower),
onside(Side2, grain,State,Lower),
oppositeSides(goose, fox, State, Lower). % precondition for act
% frame axiom for cross
onside(Side, X,result(cross(Y),State), Bound):-
\+(X=Y),
\+(X=farmer),
Bound>0,
Lower is Bound - 1,
onside(Side, X,State,Lower).
% solve(State, Bound) solves the puzzle using iterative deepening starting
% with depth Bound
solve(State,Bound):- onside(farSide, farmer,State, Bound),
onside(farSide, grain, State, Bound),
onside(farSide, goose,State, Bound),
onside(farSide, fox,State, Bound).
solve(State, Bound):-
Higher is Bound + 1,
print('trying bound '),
print(Bound),
nl,
solve(State,Higher).
% solve(State) finds a state in which puzzle is solved.
solve(State):- solve(State, 1).