Side note : this is self taught.
:-dynamic (location/2),(here/1),(have/1),(turned_off/1),(turned_on/1).
%%%%%%%%%%%%%%%%%%%%%%%%%RULES AND FACTS%%%%%%%%%%%%%%%%%%%%%%%%%
%%Fact defining the Rooms
room(kitchen).
room(office).
room(hall).
room('dining room').
room(cellar).
location(object(desk,big), office).
location(object(apple,small), kitchen).
location(object(flashlight,small), desk).
location(object('washing machine',big), cellar).
location(object(nani,small), 'washing machine').
location(object(broccoli,small), kitchen).
location(object(crackers,small), kitchen).
location(object(computer,big), office).
door(office,hall).
door(kitchen,office).
door(hall,'dining room').
door(kitchen,cellar).
door('dining room',kitchen).
%%Fact for Items that are edible.
edible(apple).
edible(crackers).
tastes_yucky(broccoli).
turned_off(flashlight).
here(kitchen).
where_food(X,Y) :-
location(object(X,small),Y),
edible(X).
where_food(X,Y) :-
location(object(X,small),Y),
tastes_yucky(X).
%%%where_food(_).
connect(X,Y) :- door(X,Y).
connect(X,Y) :- door(Y,X).
look_in(Area):- location(object(X,_),Area),is_contained_in(X,Area),write(X),nl,fail.
look_in(_).%%This will unify with anything and will always return true.
list_things(Place) :-
location(object(X,_), Place),
tab(2),
write(X),nl,
fail.
list_things(_).%%This clause will match with anything and it will return true
%%List connection between two places
list_connections(Place) :-
connect(Place, X),
tab(2),
write(X),
nl,
fail.
list_connections(_).
look :-
here(Place),
write('You are in the '), write(Place), nl,
write('You can see:'), nl,
list_things(Place),
write('You can go to:'), nl,
list_connections(Place).
move(Place):- retract(here(X)),asserta(here(Place)).
%%Move the player to the desired location
goto(Place):-
puzzle(goto(Place)),
can_go(Place),
move(Place),
look.
can_go(Place):-
here(X),
connect(X, Place).
can_go(Place):- write('You can''t get to the '),write(Place),write(' from here.'), nl,fail.
can_take(X) :- here(Place),location(object(X,small),_),is_contained_in(X,Place).
can_take(X) :- here(Place),location(object(X,big),Place),write('The '),write(X),write(' is too big'),nl,fail.
can_take(X) :- here(Place),not(location(object(X,_),Place)),write('There is no '),write(X),write(' here'),nl,fail.
take_object(X):- retract(location(object(X,_),_)),asserta(have(X)),write('taken'), nl,!.
take(X):- can_take(X),take_object(X).
eat(X) :- have(X),edible(X),retract(have(X)),write('You have eaten the '),write(X),!.
eat(X) :- have(X),tastes_yucky(X),retract(have(X)),write('Ehhhh, tastes yucky'),!.
eat(X) :- not(edible(X)),write('You cannot eat that'),nl,!.
eat(X) :- not(have(X)),write('You do not have the '),write(X),write(' to eat'),nl,fail.
drop(X) :- here(Place),retract(have(X)),asserta(location(object(X,_,_,_),Place)),write('Dropped').
items_I_have :- have(X),tab(2),write(X),nl,fail.
items_I_have.
inventory :- have(X),write('You have'),nl,items_I_have.
inventory :- not(have(_)), write('There is nothing here'),nl.
%%Check for items hiden within other items.
is_contained_in(T1,T2) :- location(object(T1,_),T2).
is_contained_in(T1,T2) :- location(object(X,_),T2),is_contained_in(T1,X).
turn_on(flashlight) :- have(flashlight),retract(turned_off(flashlight)),asserta(turned_on(flashlight)),write('Flashlight is on').
turn_on(flashlight) :- not(have(flashlight)),write('You do not have a flashlight'),nl,fail.
turn_off(flashlight) :- have(flashlight),retract(turned_on(flashlight)),asserta(turned_off(flashlight)),write('Flashlight is off').
puzzle(goto(cellar)):- have(flashlight),turned_on(flashlight),!.
puzzle(goto(cellar)):-
write('It\'s too dark, you can\'t go in there'),nl,!, fail.
puzzle(_).
command_loop:-
write('Welcome to Nani Search'), nl,
repeat,
write('>nani> '),
read(X),get_command(X),
do(X), nl,
end_condition(X).
end_condition(end).
end_condition(_) :-
have(nani),
write('Congratulations, you have found nani and now you can rest safe and easy').
do(goto(X)):-goto(X),!.
do(go(X)):-goto(X),!.
do(inventory):-inventory,!.
do(look):-look,!.
do(look_in(X)) :- look_in(X),!.
do(take(X)) :- take(X),!.
do(drop(X)) :- drop(X),!.
do(eat(X)) :- eat(X),!.
do(turn_on(flashlight)) :- turn_on(flashlight),!.
do(turn_off(flashlight)) :- turn_off(flashlight),!.
do(items_I_have) :- items_I_have,!.
do(end).
do(_) :- write('Invalid Command'),!.
get_command(C) :-
read_list(L),
command(CL,L),
C =.. CL, !.
get_command(_) :-
write('I don''t understand'), nl, fail.
command([V])--> verb(V).
command([goto, Place]) --> noun(place, Place).
command([V,O]) -->
verb(Object_Type,V),
object(Object_Type, O).
verb(place, goto) --> [go,to].
verb(place, goto) --> [go].
verb(place, goto) --> [move,to].
verb(place, goto) --> [X],{room(X)}.
verb(place, goto) --> [dining,room].
verb(thing, take) --> [take].
verb(thing, drop) --> [drop].
verb(thing, drop) --> [put].
verb(thing, turn_on) --> [turn,on].
verb(look) --> [look].
verb(look) --> [look,around].
verb(inventroy) --> [bag].
verb(inventory) --> [inventory].
verb(end) --> [end].
verb(end) --> [quit].
verb(end) --> [good,bye].
det --> [the].
det --> [a].
det --> [an].
object(Type, N) -->
det,
noun(Type, N).
object(Type, N) -->
noun(Type, N).
noun(place, R) --> [R],{room(R)}.
noun(place, 'dining room') --> [dining,room].
noun(thing, T) --> [T],{location(object(T,_),_)}.
noun(thing, T) --> [T],{have(T)}.
noun(thing, 'washing machine') --> [washing,machine].
noun(thing, flashlight) --> [light], {have(flashlight)}.
%read a line of words from the user
read_list(L) :-
write('> '),
read_line(CL),
wordlist(L,CL,[]), !.
read_line(L) :-
get0(C),
buildlist(C,L).
buildlist(13,[]) :- !.
buildlist(C,[C|X]) :-
get0(C2),
buildlist(C2,X).
wordlist([X|Y]) --> word(X), whitespace, wordlist(Y).
wordlist([X]) --> whitespace, wordlist(X).
wordlist([X]) --> word(X).
wordlist([X]) --> word(X), whitespace.
word(W) --> charlist(X), {name(W,X)}.
charlist([X|Y]) --> chr(X), charlist(Y).
charlist([X]) --> chr(X).
chr(X) --> [X],{X>=48}.
whitespace --> whsp, whitespace.
whitespace --> whsp.
whsp --> [X], {X<48}.











