%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Towers of Hanoi (adapted from DLV-complex example)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%------ Initial settings
number_of_moves(100).
largest_disc(4).
%------ Initial state
initial_state(towers(l(4,l(3,l(2,l(1,nil)))),nil,nil)).
% ------ Goal state
goal(towers(nil, nil, l(4,l(3,l(2,l(1,nil)))))).
% ------ all discs involved ------
disc(1..X) :- largest_disc(X).
% ------ legal stacks ------
legalStack(nil).
legalStack(l(T,nil)) :- disc(T).
legalStack(l(T,l(T1,S))) :- legalStack(l(T1,S)), disc(T), T > T1.
% ------ possible moves ------
possible_state(0,towers(S1,S2,S3)) :- initial_state(towers(S1,S2,S3)).
possible_state(I,towers(S1,S2,S3)) :- possible_move(I,T,towers(S1,S2,S3)), legalStack(S1), legalStack(S2), legalStack(S3).
% From stack one to stack two.
possible_move(I+1,towers(l(X,S1),S2,S3),towers(S1,l(X,S2),S3)) :- possible_state(I,towers(l(X,S1),S2,S3)),
legalMoveNumber(I), legalStack(l(X,S2)).
% From stack one to stack three.
possible_move(I+1,towers(l(X,S1),S2,S3),towers(S1,S2,l(X,S3))) :- possible_state(I,towers(l(X,S1),S2,S3)),
legalMoveNumber(I), legalStack(l(X,S3)).
% From stack two to stack one.
possible_move(I+1,towers(S1,l(X,S2),S3),towers(l(X,S1),S2,S3)) :- possible_state(I,towers(S1,l(X,S2),S3)),
legalMoveNumber(I), legalStack(l(X,S1)).
% From stack two to stack three.
possible_move(I+1,towers(S1,l(X,S2),S3),towers(S1,S2,l(X,S3))) :- possible_state(I,towers(S1,l(X,S2),S3)),
legalMoveNumber(I), legalStack(l(X,S3)).
% From stack three to stack one.
possible_move(I+1,towers(S1,S2,l(X,S3)),towers(l(X,S1),S2,S3)) :- possible_state(I,towers(S1,S2,l(X,S3))),
legalMoveNumber(I), legalStack(l(X,S1)).
% From stack three to stack two.
possible_move(I+1,towers(S1,S2,l(X,S3)),towers(S1,l(X,S2),S3)) :- possible_state(I,towers(S1,S2,l(X,S3))),
legalMoveNumber(I), legalStack(l(X,S2)).
%------ actual moves ------
% a solution exists if and only if there is a "possible_move"
% leading to the goal.
% in this case, starting from the goal, we proceed backward
% to the initial state to single out the full set of moves.
% Choose from the possible moves.
move(I,towers(S1,S2,S3)) :- goal(towers(S1,S2,S3)), possible_state(I,towers(S1,S2,S3)).
move(I-1,towers(S1,S2,S3)) :- move(I,towers(A1,A2,A3)),
possible_move(I,towers(S1,S2,S3),towers(A1,A2,A3)),
not nomove(I-1,towers(S1,S2,S3)).
nomove(I-1,towers(S1,S2,S3)) :- move(I,towers(A1,A2,A3)),
possible_move(I,towers(S1,S2,S3),towers(A1,A2,A3)),
not move(I-1,towers(S1,S2,S3)).
%------ precisely one move at each step ------
moveStepI(I) :- move(I,T).
:- legalMoveNumber(I), not moveStepI(I).
:- legalMoveNumber(I), move(I,T1), move(I,T2), T1!=T2.
legalMoveNumber(0).
legalMoveNumber(I+1) :- legalMoveNumber(I), number_of_moves(J), I < J.
#hide.
#show move/2.
back