/* San Diego Zoo.
%%http://www.sandiegozoo.org/Xbytes/a-reptiles.html */
:- asserta(user(unknown)).
:- dynamic history/1.
:- retractall(history(_)).

%%%Age
process_text([young], Output) :-
    user(unknown),
    asserta(user(young)),
    retractall(user(unknown)),
    newquestion(Temp), append(['Ok we will now start.'], Temp, Output).  

process_text([old], Output) :-
    user(unknown),
    asserta(user(old)),
    retractall(user(unknown)),
    newquestion(Temp), append(['Ok we will now start.'], Temp, Output).  

process_text([new,user], Output) :-
    retractall(user(X)),
    asserta(user(unknown)),
    retractall(history(_)),
    grapher(clear),
    Output = ['You"ll be asked a series of questions and you"ll receive an electric shock for mistakes.
Are you young or old?'].

process_text(_, [write,young,or,old]) :-
    user(unknown).
    
%%% Process input, look for a question:
process_text(Input, Output) :-
    keyword(Input, Action, Arg),
    do(Action, Arg, Temp),
    flatten(Temp, Temp2),
%    append(Temp2, ['.'], Temp3),
    history(question(_, _, Text)),
    append(Temp2, Text, Output), flush.
    
%%% Process input, look for an answer:  
process_text(Input, Output) :-
%   answerkeyword(Input, Arg),
    checkanswer(Input),
    newquestion(Temp), append(['Well done.'],Temp, Output).

%%%Give a hint:
process_text(Input, Output) :-
    user(young),
%   answerkeyword(Input, Arg),
    givehint(Input, Temp),
    flatten(Temp, Output), flush.

process_text(Input, Output) :-
    user(young),
    grapher(clear),
    grapher(node('Mistake', bitmap('shock.jpg'))),
    history(question(_, _, Temp)),
    append(['Wrong;', you, will, now, receive, a, 'shock. '], Temp, Output).

process_text(Input, Output) :-
    user(old),
    grapher(clear),
    grapher(node('Mistake', bitmap('shock.jpg'))),
    newquestion(Temp),
    append(['Wrong;', you, will, now, receive, a, 'shock. '], Temp, Output).



checkanswer([Arg]) :-
    history(question(Question, Animal, _)),
    Question = taxonomy,
    animal(Arg, Animal).

checkanswer([Arg]) :-
    history(question(Question, Animal, _)),
    Question = property,
    findall(H, property(Animal, H), X),
    member(Arg, X).

givehint(Arg, [it,is,a,subtype,of,Hint]) :-
    history(question(Question, Animal, _)),
    Question = taxonomy,
    hierarchy(Hint, Arg).
    
givehint(Arg, [an,example,of,a,property,of,this,animal,is,Hint]) :-
    history(question(Question, Animal, _)),
    Question = property,
    property(Arg, Hint).

newquestion(Text) :-
    findall(Y, animal(_, Y), X),
    length(X, Z1), Z is random(Z1), nth0(Z, X, Animal),
    Z2 is random(2), Z2 = 1,
    not(history(question(taxonomy, Animal, _))),
    Text = ['What',is,the,Animal,'the subtype of?'],
    asserta(history(question(taxonomy, Animal, Text))).

newquestion(Text) :-
    findall(Y, animal(_, Y), X),
    length(X, Z1), Z is random(Z1), nth0(Z, X, Animal),
    property(Animal, _),
    not(history(question(property, Animal, _))),
    Text = ['What',is,special,about,the,Animal,'?','Tell',me,one,property,you,'know.'],
    asserta(history(question(property, Animal, Text))).

%%% Draw history:

draw:-  findall(arc(A, 'and then', arrows:=second), user(A),Arcs),
    grapher([mode(step), Arcs, persist]).

%%% Parse Input:
answerkeyword([_,Animal,is,a,Arg|_], Arg) :- history(question(_, Animal, _)).
answerkeyword([_Animal,belongs,to,the,Arg|_], Arg) :- history(question(_, Animal, _)).
answerkeyword([Animal,is,a,Arg|_], Arg) :- history(question(_, Animal, _)).
answerkeyword([Animal,belongs,to,the,Arg], Arg) :- history(question(_, Animal, _)).
answerkeyword([_,Animal,Arg], Arg) :- history(question(_, Animal, _)).
answerkeyword([Animal,Arg], Arg) :- history(question(_, Animal, _)).

keyword([how|Input], route, Arg) :-
    parse(Input, route, Arg).
keyword([where|Input], where, Arg) :-
    parse(Input, where, Arg).
keyword([what|Input], specific, Arg) :-
    parse(Input, specific, Arg).
keyword([what|Input], hierarchy, Arg) :-
    parse(Input, hierarchy, Arg).
keyword([what|Input], content, Arg) :-
    parse(Input, content, Arg).
%keyword([what|Input], inherited, Arg) :-
%   parse(Input, inherited, Arg).
keyword([what|Input], taxonomy, Arg) :-
    parse(Input, taxonomy, Arg).

%parse([is, _, Arg|_], inherited, [Arg]).
parse([is, _, Arg|_], hierarchy, [Arg]).
parse([is, _, Arg|_], where, [Arg]).

parse([of, _, Arg|_], specific, [Arg]).
parse([about, _, Arg|_], specific, [Arg]).
parse([animals, _, in, this,zoo|_], content, _).
parse([taxonomy|_], taxonomy, _).

parse([from, _, Arg, to, _, Arg2|_], route, [Arg, Arg2]).

%parse([special|Input], specific, Arg) :-
%   parse(Input, specific, Arg).

%ignore this word
parse([_|Input], Action, Arg) :-
    parse(Input, Action, Arg).

drawallicons([]).
drawallicons([X|Animals]) :-
    concat(icon, X, Y),
    concat(Y, '.jpg', Z),
    grapher(node(X, bitmap(Z))),
    drawallicons(Animals).

%Actions
do(hierarchy, [X], ['The',X,is,a,Out1,which,is,a,Out2,'.']) :-
    grapher(clear),
    animal(Out1, X),
    hierarchy(Out2, Out1),
    concat(X, '.jpg', Y),
    grapher(node(X, bitmap(Y))).

do(specific, [X], Output) :-
    grapher(clear),
    getproperties(X, Temp, _),
    append(['The',X, 'has the following things that are special:'], [Temp,'.'], Output),
    concat(X, '.jpg', Y),
    grapher(node(X, bitmap(Y))).

do(inherited, [X], Output) :-
    grapher(clear),
    getproperties(X, _, Temp),
    append([the, X], [Temp,'.'], Output),
    concat(X, '.jpg', Y),
    grapher(node(X, bitmap(Y))).

do(route, [X,Y], Route) :-
    grapher(clear),
    route(X, Y, Route),
    grapher(node('Zoo Map', bitmap('zoo.jpg'))).

do(where, [X], [the,X,is,at,cage,Y,',',Z]) :-
    grapher(clear),
    location(X, Y, Z),
    grapher(node('Zoo Map', bitmap('zoo.jpg'))).
    
do(content, _, ['The following animals live is this zoo:', X]):-
    grapher(clear),
    findall(Y, animal(_,Y), X),
    drawallicons(X),
    grapher([layout]).
do(taxonomy, _, ['The graph shows the taxonomy of all animals in the zoo']) :-
    grapher(clear),
    findall(arc(A, B, 'is a', arrows:=second), animal(B,A), Arcs),
    findall(arc(B, C, 'is a', arrows:=second), hierarchy(C,B),Arcs1),
    append(Arcs,Arcs1,Arcs2),
    grapher([mode(step), Arcs2, persist]),
    grapher(layout),
    grapher(layout),
    grapher(layout),
    grapher(layout).

%do(content, _, ['The following animals live is this zoo:', X]):-
%   findall(node(Y,bitmap(C)), animal(_,Y), X),
%   findall(node(A,_),X,B),
%   concat(A,'.jpg',C),
%   grapher([mode(step),X,persist]).



%%% Data: Hierarchy of types.
hierarchy(god, animal).

hierarchy(animal, mammal).
hierarchy(animal, non_mammal).

hierarchy(mammal, monotremes).
hierarchy(mammal, marsupial).
hierarchy(mammal, placental).

hierarchy(non_mammal, bird).
hierarchy(non_mammal, amphibian).
hierarchy(non_mammal, reptile).

hierarchy(reptile, turtles).
hierarchy(reptile, lizards).
hierarchy(reptile, crocodiles).

%%% Data: List of properties for each type
property(god, omniscient).
property(god, omnipotent).
property(god, allLoving).
% [note: God's properties can not be inherited.]

property(mammal, vertebrate).
property(mammal, endoterm).
property(mammal, hair).
property(mammal, milk).

property(non_mammal, eggs).
property(non_mammal, verbetrate).

property(marsupial,pouch).

property(placental,placenta).

property(bird, endothermic).
property(bird, feathers).
property(amphibian, ectothermic).
property(amphibian, metamorphosis).
property(reptile, ectothermic).
property(reptile, scale).

%properties for specific animals.
property(frog, 'rolling tongue').
property(frog, jumps).
property(frog, swims).

property(wolf, dangerous).
property(chameleon, automagic_camouflage).
property(boa, strangles).
property(tortoise, slow).

property(flamingo, rose).
property(leopard, fast).
property(kangaroo, bounces).
property(koala, food_bamboo).
property(tasmanian_devil, cartoon_hero).
property(homo_erectus, erect).
property(owl, good_sight).
property(eagle, lonely).
property(salamander, slippery).
property(gecko, wall_crawler).
property(python, poisenous).
property(terrapin, bites).
property(alligator, big_mouth).

%%% Data: List of animals in each type
animal(monotremes,duckbilled_platypus).

animal(marsupial, koala).
animal(marsupial, kangaroo).
animal(marsupial, tasmanian_devil).

animal(placental, homo_erectus).
animal(placental, leopard).
animal(placental, wolf).

animal(bird, flamingo).
animal(bird, owl).
animal(bird, eagle).

animal(amphibian, frog).
animal(amphibian, salamander).

animal(reptile, python).
animal(reptile, boa).
animal(turtles, tortoise).
animal(turtles, terrapin).
animal(lizards, gecko).
animal(lizards, chameleon).
animal(crocodiles, alligator).

%%%Locations: each cage is part of a matrix, ranging from 1,1 to n,n.
location(exit,0,0).
location(entrance,0,0).
location(tasmanian_devil,1,1).
location(koala,1,2).
location(kangaroo,1,3).
location('duck-billed platypus',1,4).

location(homo_erectus,2,1).
location(leopard,2,2).
location(wolf,2,3).
location(frog,2,4).

location(flamingo,3,1).
location(owl,3,2).
location(eagle,3,3).
location(salamander,3,4).

location(boa, 4, 1).
location(python, 4, 2).
location(gecko, 4, 3).
location(chameleon, 4, 4).

location(tortoise, 5, 1).
location(terrapin, 5, 2).
location(alligator, 5, 3).


%%%Get a list of properties for a given animal, with inheritance.
getproperties(Name, Specific, Inherited) :-
    animal(CurrentNode, Name),
    specificproperties(Name, Accu, Specific),
    inheritproperties(Name, CurrentNode, Accu, Inherited), !.

%Find specific properties of animal
specificproperties(Name, [], Answer) :-
    property(Name, X),
    specificproperties(Name, [X], Answer).

specificproperties(Name, List, Answer) :-
    property(Name, X),
    not(member(X, List)),
    specificproperties(Name, [X|List], Answer).

specificproperties(_, List, List).

%Inherit properties from parent types
inheritproperties(_, god, List, List).

inheritproperties(Name, CurrentNode, [], Answer) :-
    property(CurrentNode, X),
    inheritproperties(Name, CurrentNode, [X], Answer).

inheritproperties(Name, CurrentNode, List, Answer) :-
    property(CurrentNode, X),
    not(member(X, List)),
    %X \= H,
    inheritproperties(Name, CurrentNode, [X|List], Answer).

%Find parent hierarchy (bottom-up)
inheritproperties(Name, CurrentNode, List, Answer) :-
    hierarchy(NewNode, CurrentNode),
    inheritproperties(Name, NewNode, List, Answer).

    

%%%Find route
route(AnimalA, AnimalB, [start,at,the,AnimalA,'-',X,and,Y,you,are,at,the,AnimalB]) :-
    location(AnimalA, Xa, Ya),
    location(AnimalB, Xb, Yb),
    routeX(Xa, Xb, X),
    routeY(Ya, Yb, Y).
    
routeX(Xa, Xb, Walkthisway) :-
    Xb = Xa,
    Walkthisway = ''.
    
routeX(Xa, Xb, Walkthisway) :-
    Xb > Xa,
    Xc is Xb - Xa,
    Walkthisway = [go, Xc, cages, east].

routeX(Xa, Xb, Walkthisway) :-
    Xb < Xa,
    Xc is Xa - Xb,
    Walkthisway = [go, Xc, cages, west].
    
routeY(Ya, Yb, Walkthisway) :-
    Yb = Ya,
    Walkthisway = ''.
    
routeY(Ya, Yb, Walkthisway) :-
    Yb > Ya,
    Yc is Yb - Ya,
    Walkthisway = [go,south,Yc,'cages.'].

routeY(Ya, Yb, Walkthisway) :-
    Yb < Ya,
    Yc is Ya - Yb,
    Walkthisway = [go, north,Yc,'cages.'].  

%dysfunctional code:
%%%Find all animals with given properties
findanimals(Properties, Animals) :-
    findanimals(god, _, Properties, [], Animals), !.

%Check for match
findanimals(CurrentNode, CurrentAnimal, Properties, Accu, List) :-
    %animal(CurrentNode, CurrentAnimal),
    animal(CurrentNode, CurrentAnimal),
    not(member(CurrentAnimal, Accu)),
    getproperties(CurrentAnimal, X, Y),
    append(X, Y, Z),
    subset(Properties, Z),
    findanimals(CurrentNode, CurrentAnimal, Properties, [CurrentAnimal|Accu], List).
    
%Next animal
findanimals(CurrentNode, CurrentAnimal, Properties, Accu, List) :-
    animal(CurrentNode, NewAnimal),
    not(CurrentAnimal = NewAnimal),
    findanimals(CurrentNode, NewAnimal, Properties, Accu, List).
    
%Next node in hierarchy (top-down):
findanimals(CurrentNode, _, Properties, Accu, List) :-
    hierarchy(CurrentNode, NewNode),
    findanimals(NewNode, _, Properties, Accu, List).


%%%Find AnimalNew 1 propertie  tegelijk zoeken
 
findanimalsnew(Properties,Animals):- 
        findanimalsnew(Properties,Animals,_), 
        writeln(Animals),fail. 
 
findanimalsnew(Properties,Animals,_):- 
        property(Animals,Properties), 
        animal(_,Animals). 
 
findanimalsnew(Properties,Animals,_):- 
        property(TempAnimals,Properties), 
        animal(TempAnimals,Animals). 
 
findanimalsnew(Properties,Animals,_):- 
        property(TempAnimals,Properties), 
        hierarchy(TempAnimals,Temp2Animals), 
        animal(Temp2Animals,Animals). 
 
findanimalsnew(Properties,Animals,_):- 
        property(TempAnimals,Properties), 
        hierarchy(TempAnimals,Temp2Animals), 
        hierarchy(Temp2Animals,Temp3Animals), 
        animal(Temp3Animals,Animals). 
 
%%findanimalsnew([X|Properties],Animals,_);- 
         
 
