% Facts

adventure(circus).
adventure('rock band').
adventure(spaceship).
adventure(train).

person(joanne).
person(lou).
person(ralph).
person(winnie).

imaginary_friend('grizzly bear').
imaginary_friend(moose).
imaginary_friend(seal).
imaginary_friend(zebra).


solve :-
    imaginary_friend(JoanneFriend), imaginary_friend(LouFriend), imaginary_friend(RalphFriend), imaginary_friend(WinnieFriend),
    all_different([JoanneFriend, LouFriend, RalphFriend, WinnieFriend]),
    
    adventure(JoanneAdventure), adventure(LouAdventure), adventure(RalphAdventure), adventure(WinnieAdventure),
    all_different([JoanneAdventure, LouAdventure, RalphAdventure, WinnieAdventure]),

    Story = [ story(joanne, JoanneFriend, JoanneAdventure),
              story(lou, LouFriend, LouAdventure),
              story(ralph, RalphFriend, RalphAdventure),
              story(winnie, WinnieFriend, WinnieAdventure) ],

    \+ member(story(joanne, seal, _), Story),
    \+ member(story(lou, seal, _), Story),
    \+ member(story(joanne, 'grizzly bear', _), Story),
    member(story(joanne, _, circus), Story),
    member(story(winnie, zebra, _), Story),

    \+ member(story(_, seal, spaceship), Story),
    \+ member(story(_, seal, train), Story),
    \+ member(story(_, 'grizzly bear', spaceship), Story),

    tell(joanne, JoanneFriend, JoanneAdventure),
    tell(lou, LouFriend, LouAdventure),
    tell(ralph, RalphFriend, RalphAdventure),
    tell(winnie, WinnieFriend, WinnieAdventure).

tell(Person, Friend, Adventure) :- write(Person), write(' and their imaginary friend, the '), write(Friend), write(', had an adventure involving 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([_]).