start:-
write('Start a new game? y/n'),
nl,
read(Start),
(Start==y -> write('\e[2J'),newgame,nl; halt(0)).
newgame:-
random_member(A1,[yellow,blue,pink,green,purple,orange]),
random_member(B1,[yellow,blue,pink,green,purple,orange]),
random_member(C1,[yellow,blue,pink,green,purple,orange]),
random_member(D1,[yellow,blue,pink,green,purple,orange]),
S=[A1,B1,C1,D1],
%It checks if all the colors generated are different
(all_diff(S)->true;newgame),
%loop for the attempts
dec(10,A1,B1,C1,D1),
%out of loop means you have lost
write('You have lost.'),nl,
write('Code: '),
printlist([A1,B1,C1,D1]),
nl,nl,
start.
all_diff(L) :- \+ (select(X,L,R), member(X,R)).
dec(0,A1,B1,C1,D1).
dec(X,A1,B1,C1,D1) :-
%printlist([A1,B1,C1,D1]),
write('Attempt # '),
Y is abs(X-11),
write(Y),nl,
write('Color 1'),
read(A2),
write('Color 2'),
read(B2),
write('Color 3'),
read(C2),
write('Color 4'),
read(D2),
nl,
I is 0,
%It checks the number of black
% if there is a match increases the count for black
%else: put the different values in two lists, one for the code and one for the guess
(A1==A2 -> J is I + 1; J is I + 0, LA1=[A1],LA2=[A2]),
(B1==B2 -> K is J + 1; K is J + 0, LB1=[B1],LB2=[B2]),
(C1==C2 -> L is K + 1; L is K + 0, LC1=[C1],LC2=[C2]),
(D1==D2 -> Black is L + 1; Black is L + 0, LD1=[D1],LD2=[D2]),
%append the values in the code that didn't match with the guess
append(LA1,LB1,AB1),
append(LC1,LD1,CD1),
append(AB1,CD1,L1),
%append the values in the guess that didn't match with the code
append(LA2,LB2,AB2),
append(LC2,LD2,CD2),
append(AB2,CD2,L2),
%If number of black is 4 means you have won
(Black==4 -> write('You have won.'),nl,
write('Code: '),
printlist([A1,B1,C1,D1]),
nl,nl,
start;
write('Black: '),
write(Black),
%remove duplicate values from the guess list
distinct(L2,R2),
%count the number of common elements in both lists(number of white)
common(L1,R2,White),
write(' White: '),
write(White),
nl,nl,
NewX is X - 1,
dec(NewX,A1,B1,C1,D1)).
member1(X,[H|_]) :- X==H,!.
member1(X,[_|T]) :- member1(X,T).
distinct([],[]).
distinct([H|T],C) :- member1(H,T),!, distinct(T,C).
distinct([H|T],[H|C]) :- distinct(T,C).
common([],Ys,0).
common([X|Xs],Ys,N):- member(X,Ys), common(Xs,Ys,M), N is M+1.
common([X|Xs],Ys,N):- nonmember(X,Ys), common(Xs,Ys,N).
nonmember(Arg,[Arg|_]):-
!,
fail.
nonmember(Arg,[_|Tail]):-
!,
nonmember(Arg,Tail).
nonmember(_,[]).
printlist([]).
printlist([X|Y]) :- write(X),write(' '),printlist(Y).