%%%%%%%%%%%%%%%%% Exercise 5.3 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

:-lib(ic).

:-op(950, xfy, says).
:-op(800, yfx, and).
:-op(900, yfx, or).
:-op(700, fy, not).


code(knave,0).
code(knight,1).
code(spy,2).


native(X) :- X#::0..2.


Native says Sentence :- native(Native), truth(Sentence,V), or(Native#=2,Native#=V,1).


truth(Native is Kind, V) :- native(Native), code(Kind, Code), #=(Native,Code,V).
truth(S1 and S2, V) :- truth(S1,V1), truth(S2,V2), and(V1,V2,V).
truth(S1 or S2, V) :- truth(S1,V1), truth(S2,V2), or(V1,V2,V).
truth(not S, V) :- truth(S,V0), V #\= V0.


%%%%%%%%%%%%%%%%% output %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

portray([],_).
portray([X|R],[Varname|Varnames]) :-
	code(Kind,X), 
	write(Varname), write(' is '), write(Kind), nl, 
	portray(R,Varnames).


%%%%%%%%%%%%%%%%% queries for testing %%%%%%%%%%%%%%%%%%%%%%%%%%%%%


q1 :- A says A is spy, B says A is spy, C says not C is spy, alldifferent([A,B,C]), labeling([A,B,C]), portray([A,B,C],["A","B","C"]).

q2 :- A says A is knave, labeling([A]), portray([A],["A"]).

q3 :- A says A is spy, labeling([A]), portray([A],["A"]).

q4 :- A says (A is knave or not A is spy) and not A is knight, labeling([A]), portray([A],["A"]).
