%% Facts

child(joanne).
child(lou).
child(ralph).
child(winnie).

animal(grizzly_bear).
animal(moose).
animal(seal).
animal(zebra).

adventure(circus).
adventure(rock_band).
adventure(spaceship).
adventure(train).


solve_friends :- 
	animal(JoanneAnimal), animal(LouAnimal), animal(RalphAnimal),
	animal(WinnieAnimal),
	all_different([JoanneAnimal, LouAnimal, RalphAnimal, WinnieAnimal]),

	adventure(JoanneAdventure), adventure(LouAdventure),
	adventure(RalphAdventure), adventure(WinnieAdventure),
	all_different([JoanneAdventure, LouAdventure, RalphAdventure, WinnieAdventure]),

	Friends = [	friend(joanne, JoanneAnimal, JoanneAdventure),
				friend(lou, LouAnimal, LouAdventure),
				friend(ralph, RalphAnimal, RalphAdventure),
				friend(winnie, WinnieAnimal, WinnieAdventure) ],

	% 1. The seal (who isnt the creation of Joanne or Lou) neither rode to the moon in a spaceship nor took a trip around the world on a magic train. 

	\+ member(friend(joanne, seal, _), Friends),
	\+ member(friend(lou, seal, _), Friends),
	\+ member(friend(_, seal, spaceship), Friends),
	\+ member(friend(_, seal, train), Friends),

	% 2. Joannes imaginary friend (who isnt the grizzly bear) went to the circus. 
	\+ member(friend(joanne, grizzly_bear, _), Friends),
	member(friend(joanne, _, circus), Friends),

	% 3. Winnies imaginary friend is a zebra.
	member(friend(winnie, zebra, _), Friends),

	% 4. The grizzly bear didnt board the spaceship to the moon.
	\+ member(friend(_, grizzly_bear, spaceship), Friends),

	tell(joanne, JoanneAnimal, JoanneAdventure),
    tell(lou, LouAnimal, LouAdventure),
    tell(ralph, RalphAnimal, RalphAdventure),
    tell(winnie, WinnieAnimal, WinnieAdventure).
    
tell(Child, Animal, Adventure) :- write(Child), write(' has an imaginary friend '), 
write(Animal), write(', who they went on an adventure with in a '), write(Adventure), write('.'), nl.


% If the head of the list is in the tail, fail.
all_different([Head|Tail]) :- member(Head, Tail), !, fail.
% Otherwise, check the tail of the list.
all_different([_|Tail]) :- all_different(Tail).
% If there's only one thing in the list, it's fine.
all_different([_]).