<div class="notebook">
<div class="nb-cell program" data-background="true" name="p1">
tap(From, To, ToNew) :-
From \= 0,
Total is From + To,
ToNew is mod(Total, 5).
split(0, 4, 2).
split(4, 0, 2).
split(0, 2, 1).
split(2, 0, 1).
lost(0, 0).
% get_next(hand(TopLeft,TopRight,BottomLeft,BottomRight,Turn), Next, Seen)
% calculates the Next unSeen state given it is Turn's move
get_next(hand(TL,TR,BL,BR,bottom), Next, Seen) :- tap(BL,TL,TL_New), Next=hand(TL_New,TR,BL,BR,top), \+member(Next,Seen).
get_next(hand(TL,TR,BL,BR,bottom), Next, Seen) :- tap(BR,TR,TR_New), Next=hand(TL,TR_New,BL,BR,top), \+member(Next,Seen).
get_next(hand(TL,TR,BL,BR,bottom), Next, Seen) :- tap(BL,TR,TR_New), Next=hand(TL,TR_New,BL,BR,top), \+member(Next,Seen).
get_next(hand(TL,TR,BL,BR,bottom), Next, Seen) :- tap(BR,TL,TL_New), Next=hand(TL_New,TR,BL,BR,top), \+member(Next,Seen).
get_next(hand(TL,TR,BL,BR,top), Next, Seen) :- tap(TL,BL,BL_New), Next=hand(TL,TR,BL_New,BR,bottom), \+member(Next,Seen).
get_next(hand(TL,TR,BL,BR,top), Next, Seen) :- tap(TR,BR,BR_New), Next=hand(TL,TR,BL,BR_New,bottom), \+member(Next,Seen).
get_next(hand(TL,TR,BL,BR,top), Next, Seen) :- tap(TR,BL,BL_New), Next=hand(TL,TR,BL_New,BR,bottom), \+member(Next,Seen).
get_next(hand(TL,TR,BL,BR,top), Next, Seen) :- tap(TL,BR,BR_New), Next=hand(TL,TR,BL,BR_New,bottom), \+member(Next,Seen).
get_next(hand(TL,TR,BL,BR,bottom), Next, Seen) :- split(BL,BR,S), Next=hand(TL,TR,S,S,top), \+member(Next,Seen).
get_next(hand(TL,TR,BL,BR,top), Next, Seen) :- split(TL,TR,S), Next=hand(S,S,BL,BR,bottom), \+member(Next,Seen).
% current player already won
forced_win(hand(TL,TR,_,_,bottom), _) :- lost(TL, TR), !.
forced_win(hand(_,_,BL,BR,top), _) :- lost(BL, BR), !.
% current player can win in a single move
forced_win(hand(TL,TR,BL,BR,bottom), Seen) :-
\+ lost(BL, BR),
get_next(hand(TL,TR,BL,BR,bottom), hand(TL_2,TR_2,BL,BR,top), Seen),
lost(TL_2, TR_2),
!.
forced_win(hand(TL,TR,BL,BR,top), Seen) :-
\+ lost(TL, TR),
get_next(hand(TL,TR,BL,BR,top), hand(TL,TR,BL_2,BR_2,bottom), Seen),
lost(BL_2, BR_2),
!.
% current player has a branch that always ends in a win
forced_win(H1, Seen) :-
% can the current player choose a move...
get_next(H1, H2, Seen),
append(Seen, H1, NewSeen),
% s.t. all of the opponent's possible moves result in a forced win?
setof(H3, get_next(H2, H3, NewSeen), Hs),
forall(member(H, Hs), forced_win(H, NewSeen)),
!.
% My Code
%xmove(Hand, N, Newhand)
xmove(hand(TL,TR,BL,BR,bottom), L, Newhand).
xmove(hand(TL,TR,BL,BR,bottom), R, Newhand).
xmove(hand(TL,TR,BL,BR,bottom), S, Newhand).
playo :- explain, playfrom([1,1,1,1]).
explain :-
write('You play X by either writing L to tap on the left hand or for the right or S to split.'),
nl,
display([1,1,1,1]).
playfrom(Hand) :- read(N),
xmove(Hand, N, Newhand),
display(Newhand),
orespond(Newhand, Newnewhand),
display(Newnewhand),
playfrom(Newnewhand).
</div>
<div class="nb-cell query" name="q1">
% verifying that get_next/3 works
setof(X, get_next(hand(1,1,2,0,bottom),X,[]), Xs), length(Xs, _).
</div>
<div class="nb-cell query" name="q2">
% bottom has already won because top is dead
forced_win(hand(0,0,1,2,bottom), []).
</div>
<div class="nb-cell query" name="q3">
% bottom can win in one move
forced_win(hand(3,0,1,2,bottom), []).
</div>
<div class="nb-cell query" name="q4">
% bottom can win in two moves
forced_win(hand(0,1,2,2,bottom), []).
</div>
<div class="nb-cell query" name="q5">
% is there a forced win for first player?
forced_win(hand(1,1,1,1,top), []).
</div>
<div class="nb-cell query" name="q6">
% is there a forced win for second player?
forced_win(hand(1,1,1,1,bottom), []).
</div>
</div>