/* "Sleepy" -- a sample adventure game, by David Matuszek. */
% http://www.csc.vill.edu/~dmatusze/resources/prolog/sleepy.html
/* In standard Prolog, all predicates are "dynamic": they
can be changed during execution. SWI-Prolog requires such
predicates to be specially marked. */
% :- dynamic at/2, i_am_at/1, i_am_holding/1, alive/1,
% lit/1, visible_object/1.
/* This routine is purely for debugging purposes. */
%dump :- listing(at), listing(i_am_at), listing(i_am_holding),
% listing(alive), listing(lit), listing(visible_object).
/* This defines my current location. */
i_am_at(bedroom).
i_am_holding(nothing).
/* These facts describe how the rooms are connected. */
path(bedroom, n, den) :- lit(bedroom).
path(bedroom, n, den) :-
print('You trip over something in the dark.'), nl,
!, fail.
path(den, s, bedroom).
path(bedroom, d, bed).
path(bed, u, bedroom).
% These facts tell where the various objects in the game
% are located.
at(flyswatter, den).
at(fly, bedroom).
at('light switch', den).
at('light switch', bedroom).
/* These facts specify some game-specific information. */
alive(fly).
lit(bedroom).
lit(den).
visible_object('light switch').
/* These rules describe how to pick up an object. */
take(fly) :-
print('It is too fast for you!'), nl,
!, fail.
take('light switch') :-
take(switch).
take(switch) :-
print('It is firmly embedded in the wall!'), nl,
!, fail.
take(X) :-
i_am_holding(X),
print('You are already holding it!'),
nl.
take(X) :-
i_am_at(Place),
at(X, Place),
retract(at(X, Place)),
assert(i_am_holding(X)),
print('OK.'),
nl.
take(_) :-
print('I do not see it here.'),
nl.
/* These rules describe how to put down an object. */
drop(X) :-
i_am_holding(X),
i_am_at(Place),
retract(i_am_holding(X)),
assert(at(X, Place)),
print('OK.'),
nl.
drop(_) :-
print('You are not holding it!'),
nl.
/* These rules define the six direction letters as calls to go/1. */
n :- go(n).
s :- go(s).
e :- go(e).
w :- go(w).
u :- go(u).
d :- go(d).
/* This rule tells how to move in a given direction. */
go(Direction) :-
i_am_at(Here),
path(Here, Direction, There),
retract(i_am_at(Here)),
assert(i_am_at(There)),
look.
go(_) :-
print('You can not go that way.'), nl.
/* This rule tells how to look about you. */
look :-
i_am_at(Place),
describe(Place),
nl,
notice_objects_at(Place),
nl.
/* These rules set up a loop to mention all the objects in your vicinity. */
notice_objects_at(Place) :-
lit(Place),
at(X, Place),
visible_object(X),
print('There is a '), print(X), print(' here.'), nl,
fail.
notice_objects_at(_).
/* These rules are specific to this particular game. */
use(flyswatter) :-
swat(fly).
use(bed) :-
i_am_at(bedroom),
d.
use(bed) :-
print('It is in the bedroom!'), nl,
!, fail.
use(switch) :-
i_am_at(Place),
lit(Place),
off.
use(switch) :-
on.
on :-
i_am_at(bed),
print('You can not reach the light switch from here.'), nl,
!, fail.
on :-
i_am_at(Place),
lit(Place),
print('The lights are already on.'), nl.
on :-
i_am_at(Place),
assert(lit(Place)),
print('The room lights come on.'), nl,
optional_buzz_off,
look.
off :-
i_am_at(bed),
print('You can not reach the light switch from here.'), nl,
!, fail.
off :-
i_am_at(Place),
retract(lit(Place)),
optional_buzz_off,
print('It is now dark in here.'), nl.
off :-
print('The lights are already off.'), nl.
sleep :-
not(i_am_at(bed)),
print('You find it hard to sleep standing up.'), nl,
!, fail.
sleep :-
lit(bedroom),
print('You can not get to sleep with the light on.'), nl,
!, fail.
sleep :-
lit(den),
print('The light from the den is keeping you awake.'), nl,
!, fail.
sleep :-
or(i_am_holding(flyswatter), at(flyswatter, bed)),
print('What? Sleep with a dirty old flyswatter?'), nl,
!, fail.
sleep :-
alive(fly),
print('As soon as you start to doze off, a fly lands'), nl,
print('on your face and wakes you up again.'), nl,
make_visible(fly),
make_visible(flyswatter),
!, fail.
sleep :-
print('Ahhh...you (yawn) made...it...zzzzzzzz.'), nl, nl,
finish.
swat(fly) :-
swat.
swat :-
i_am_at(Place),
not(lit(Place)),
print('You flail aimlessly in the dark!'), nl.
swat :-
not(i_am_holding(flyswatter)),
print('You are not holding the flyswatter.'), nl,
!, fail.
swat :-
not(alive(fly)),
print('He is dead, Jim.'), nl.
swat :-
i_am_at(Place),
not(at(fly, Place)),
print('You swish the flyswatter through the air.'), nl.
/* Have flyswatter, room is lit, fly is here and alive. */
swat :-
buzz_off,
print('The fly escapes into the other room.'), nl.
swat :-
print('Success! You killed that pesky fly!'), nl,
retract(alive(fly)).
swat :- /* For debugging... */
print('You must have forgotten a case!', nl).
make_visible(X) :-
visible_object(X).
make_visible(X) :-
assert(visible_object(X)).
buzz_off :-
at(fly, bedroom),
lit(den),
retract(at(fly, bedroom)),
assert(at(fly, den)).
buzz_off :-
at(fly, den),
lit(bedroom),
retract(at(fly, den)),
assert(at(fly, bedroom)).
optional_buzz_off :-
buzz_off.
optional_buzz_off.
/* Under UNIX, the "halt." command quits Prolog but does not
remove the output window. On a PC, however, the window
disappears before the final output can be seen. Hence this
routine requests the user to perform the final "halt." */
finish :-
nl,
print('The game is over. Please enter the "halt." command.'),
nl.
/* This rule just prints out game instructions. */
instructions :-
nl,
print('Enter commands using standard Prolog syntax.'), nl,
print('Available commands are:'), nl,
print('start. -- to start the game.'), nl,
print('n. s. e. w. u. d. -- to go in that direction.'), nl,
print('take(Object). -- to pick up an object.'), nl,
print('drop(Object). -- to put down an object.'), nl,
print('use(Object). -- to manipulate an object.'), nl,
print('look. -- to look around you again.'), nl,
print('on. off. -- to control the room lights.'), nl,
print('sleep. -- to try to go to sleep.'), nl,
print('instructions. -- to see this message again.'), nl,
print('halt. -- to end the game and quit.'), nl,
nl.
/* This rule prints out instructions and tells where you are. */
start :-
instructions,
look.
/* These rules describe the various rooms. Depending on
circumstances, a room may have more than one description. */
describe(bedroom) :-
lit(bedroom),
print('You are in a bedroom with a large, comfortable bed.'), nl,
print('It has been a long, tiresome day, and you would like'), nl,
print('nothing better than to go to sleep.'), nl.
describe(bedroom) :-
print('You are in your bedroom. It is nice and dark.'), nl.
describe(bed) :-
print('You are in bed, and it feels great!'), nl.
describe(den) :-
lit(den),
print('You are in your den. There is a lot of stuff here,'), nl,
print('but you are too sleepy to care about most of it.'), nl.
describe(den) :-
print('You are in your den. It is dark.'), nl.
/* This is a special form, to call predicates during load time. */
% :- retractall(i_am_holding(_)), start.