/**
    Define maternal relationships.
*/
mother(linda, alice).
mother(linda, michael).
mother(linda, mark).
mother(alice, jake).
mother(alice, emma).
mother(sarah, nancy).
mother(sarah, tom).
mother(chloe, john).
mother(chloe, lisa).
mother(nancy, peter).
mother(nancy, amy).

/**
    Define marriages.
*/
married(robert, linda).
married(alice, bob).
married(michael, sarah).
married(mark, chloe).

/**
    Define males.
*/
male(robert).
male(bob).
male(michael).
male(mark).
male(jake).
male(tom).
male(john).
male(peter).

/**
    Define females.
*/
female(linda).
female(alice).
female(sarah).
female(chloe).
female(emma).
female(nancy).
female(lisa).
female(amy).

/**
    Define ages.
*/
age(robert, 68).
age(linda, 65).
age(alice, 42).
age(bob, 44).
age(michael, 41).
age(sarah, 42).
age(mark, 45).
age(chloe, 43).
age(jake, 15).
age(emma, 12).
age(nancy, 20).
age(tom, 10).
age(john, 20).
age(lisa, 17).
age(peter, 2).
age(amy, 1).

/**
    Inferred relationships.
*/
father(Father, Child) :- male(Father), 
                         (married(Father, Mother); 
                          married(Mother, Father)), 
                         mother(Mother, Child).
parent(Parent, Child) :- mother(Parent, Child); 
                         father(Parent, Child).
sibling(Person1, Person2) :- mother(Mother, Person1), 
                             mother(Mother, Person2), 
                             Person1 \= Person2.
grandparent(Grandparent, Grandchild) :- parent(Grandparent, Child), 
                                        parent(Child, Grandchild).
cousin(Person1, Person2) :- parent(Parent1, Person1), 
                            parent(Parent2, Person2), 
                            Parent1 \= Parent2, 
                            sibling(Parent1, Parent2).
uncle(Uncle, Child) :- male(Uncle), 
                       parent(Parent, Child), 
                       sibling(Uncle, Parent).
aunt(Aunt, Child) :- female(Aunt), 
                     parent(Parent, Child), 
                     sibling(Aunt, Parent).
ancestor(Ancestor, Descendant) :- parent(Ancestor, Descendant); 
                                  (parent(Parent, Descendant), 
                                   ancestor(Ancestor, Parent)).
older_sibling(Older, Younger) :- sibling(Older, Younger), 
                                 age(Older, H1), 
                                 age(Younger, H2), 
                                 H1 > H2.
bigger_brother(Brother, Sibling) :- male(Brother), 
                                    older_sibling(Brother, Sibling).
bigger_sister(Sister, Sibling) :- female(Sister), 
                                  older_sibling(Sister, Sibling).

/**
    Advanced predicates.
*/
brother_in_law(BrotherInLaw, Person) :- male(BrotherInLaw), 
                                        (married(Person, Spouse); 
                                         married(Spouse, Person)), 
                                        sibling(Spouse, BrotherInLaw).
brother_in_law(BrotherInLaw, Person) :- male(BrotherInLaw), 
                                        sibling(Person, Sibling), 
                                        (married(Sibling, BrotherInLaw); 
                                         married(BrotherInLaw, Sibling)).
sister_in_law(SisterInLaw, Person) :- female(SisterInLaw),
                                      (married(Person, Spouse); 
                                       married(Spouse, Person)),
                                      sibling(Spouse, SisterInLaw).
sister_in_law(SisterInLaw, Person) :- female(SisterInLaw),
                                      sibling(Person, Sibling),
                                      (married(Sibling, SisterInLaw); 
                                       married(SisterInLaw, Sibling)).
nth_ancestor(1, Ancestor, Person) :- parent(Ancestor, Person).
nth_ancestor(N, Ancestor, Person) :- N > 1,
                                     parent(Parent, Person),
                                     N1 is N - 1,
                                     nth_ancestor(N1, Ancestor, Parent).
common_ancestor(Person1, Person2, Ancestor) :- ancestor(Ancestor, Person1),
                                               ancestor(Ancestor, Person2),
                                               \+ (ancestor(DirectAncestor, Person1),
                                                   ancestor(DirectAncestor, Person2),
                                                   parent(Ancestor, DirectAncestor)).
common_ancestors(Person1, Person2, AncestorList) :- findall(Ancestor, 
                                                            (ancestor(Ancestor, Person1), 
                                                             ancestor(Ancestor, Person2)), 
                                                            AncestorList).