% Prolog doesn't know anything at first. "true" and "false" are
% just arbitrary words. We need to use them by way of the operations
% "not", "xor", and "implies", so we'll define those using truth tables:
not(true, false).
not(false, true).

xor(false, false, false).
xor(false, true, true).
xor(true, false, true).
xor(true, true, false).

implies(false, false, true).
implies(false, true, true).
implies(true, false, false).
implies(true, true, true).

% Now, let's write down what we were given...

% Statement 1a is true iff (there is a king) implies (there is an ace).
stmt_1a(HasKing, HasAce, Result) :-
    implies(HasKing, HasAce, Result).

% Statement 1b is true iff (there is not a king) implies (there is an ace).
stmt_1b(HasKing, HasAce, Result) :-
    implies(DoesntHaveKing, HasAce, Result),
        not(DoesntHaveKing, HasKing).

% Statement 1 is true iff (statement 1a) xor (statement 1b) is true.
stmt_1(HasKing, HasAce, Result) :-
    xor(Stmt1ATrue, Stmt1BTrue, Result),
    stmt_1a(HasKing, HasAce, Stmt1ATrue),
    stmt_1b(HasKing, HasAce, Stmt1BTrue).

% Statement 2 is true iff there is a king.
stmt_2(HasKing, _HasAce, Result) :-
    Result = HasKing.

% Finally: we can say we've found a valid assignment (true/false values for
% HasKing and HasAce) if they satisfy both of the given statements.

satisfied(HasKing, HasAce) :-
    stmt_1(HasKing, HasAce, true),
    stmt_2(HasKing, HasAce, true).

% Now let's ask Prolog our question: for what values of HasKing and HasAce
% is the statement satisfied?

:- satisfied(HasKing, HasAce),
	write('Has king: '), write(HasKing), nl,
	write('Has ace: '), write(HasAce), nl,
	write('--------------'), nl,
	% Marking this as a failure causes Prolog to backtrack,
	% so if there were multiple solutions, we'd see each of them.
	fail;
	write('No more solutions!'), halt.