1/* 'A gradstudent's first 45 minutes in Philly', by Dominik Bollmann. */
    2
    3:- dynamic time/1, i_am_at/1, at/2, holding/1.    4:- retractall(time(_)), retractall(leaves(_,_,_)),
    5	retractall(at(_, _)), retractall(i_am_at(_)).    6
    7time(-1).
    8i_am_at(airport).
    9
   10/* the leaves predicate specifies which transportation method leaves
   11 * when and how long it takes. */
   12leaves(subway, 20, 30).
   13leaves(shuttle, _, 25).
   14
   15/* predicates acting on leaves facts. */
   16can_take(Transport, LeavingTime) :-
   17	time(Now), leaves(Transport, LeavingTime, _),
   18	Now < LeavingTime.
   19
   20arrives_on_time(Transport, DurationTime) :-
   21	time(Now), leaves(Transport, _, DurationTime),
   22	X is (Now + DurationTime), (X < 45 ; X =:= 45).
   23
   24/* the map of our game is encoded via paths. */
   25path(airport, n, infodesk).
   26path(infodesk, e, ticketcenter).
   27path(airport, e, sign).
   28
   29path(sign, e, subway) :- holding(subway_ticket), holding(baggage).
   30path(sign, e, subway) :-
   31	holding(subway_ticket),
   32	write('With your subway ticket in your hand, you easily pass '), nl,
   33	write('the subway station entrance door. However, you notice '), nl,
   34	write('that you completely forgot about bringing ... YOUR BAGGAGE! '), nl,
   35	write('Will it still be there where you left it?'), nl, !, fail.
   36path(sign, e, subway) :-
   37	write('You need a valid subway ticket to pass the '), nl,
   38	write('subway entrance.'), nl,
   39	fail.
   40
   41path(sign, n, ticketcenter).
   42path(outside, n, airport).
   43
   44path(pickup, e, outside) :- holding(shuttle_ticket), holding(baggage).
   45path(pickup, e, outside) :-
   46	holding(shuttle_ticket),
   47	write('With your shuttle ticket in your hand, the driver of '), nl,
   48	write('Penn\s pickup service lets you pass. However, you notice '), nl,
   49	write('that you completely forgot about bringing ... YOUR BAGGAGE! '), nl,
   50	write('Will it still be there where you left it?'), nl, !, fail.
   51path(pickup, e, outside) :-
   52	write('In order to use Penn\'s pickup shuttle service, '), nl,
   53	write('the driver requests you to have a ticket. '), nl,
   54	fail.
   55
   56path(dropoff, n, upenn).
   57path(storage, e, dropoff).
   58
   59% make all paths two-way, i.e., undirected.
   60path(X, s, Y) :- path(Y, n, X).
   61path(X, w, Y) :- path(Y, e, X).
   62
   63at(baggage, airport).
   64at(train, subway).
   65at(subway_ticket, ticketcenter).
   66at(pennflyer, infodesk).
   67
   68/* These rules describe how to pick up an object. */
   69
   70/* that clause takes care of a special case of taking an object,
   71   namely, taking the train at the subway station. */
   72take(train) :-
   73	describe(train), finish, !, fail.
   74
   75take(X) :-
   76        holding(X),
   77        write('You''re already holding it!'),
   78        !, nl.
   79
   80take(X) :-
   81        i_am_at(Place),
   82        at(X, Place),
   83        retract(at(X, Place)),
   84	assert(holding(X)),
   85        write('OK.'), nl,
   86	count_time,
   87        !, nl.
   88
   89take(_) :-
   90        write('I don''t see it here. '),
   91        nl.
   92
   93/* These rules describe how to put down an object. */
   94
   95drop(X) :-
   96        holding(X),
   97        i_am_at(Place),
   98	retract(holding(X)),
   99        assert(at(X, Place)),
  100        write('OK.'), nl,
  101	count_time,
  102        !, nl.
  103
  104drop(_) :-
  105        write('You aren''t holding it!'),
  106        nl.
  107
  108investigate(pennflyer) :-
  109	holding(pennflyer),
  110	assert(at(shuttle_ticket, ticketcenter)),
  111	write('Reading the pennflyer in detail you learn that the '), nl,
  112	write('ticket center also sells tickets for Penn''s private '), nl,
  113	write('pickup shuttle service! '), nl, nl,
  114	count_time, nl, !.
  115
  116investigate(Object) :-
  117	holding(Object),
  118	write('Investigating your '), write(Object), write(' doesn''t '), nl,
  119	write('reveal anything interesting.'), nl, nl,
  120	count_time, nl, !.
  121
  122investigate(Object) :-
  123	write('You can''t investigate '), write(Object), write(' because '), nl,
  124	write('you aren''t holding it.'), nl.
  125
  126/* These rules define the direction letters as calls to go/1. */
  127
  128n :- go(n).
  129s :- go(s).
  130e :- go(e).
  131w :- go(w).
  132
  133/* This rule tells how to move in a given direction. */
  134
  135go(Direction) :-
  136        i_am_at(Here),
  137        path(Here, Direction, There),
  138        retract(i_am_at(Here)),
  139        assert(i_am_at(There)),
  140        !, look.
  141
  142go(_) :-
  143        write('You can''t go that way.').
  144
  145
  146/* This rule tells how to look about you. */
  147
  148look :-
  149	count_time, nl,
  150        i_am_at(Place),
  151        describe(Place),
  152        nl,
  153        notice_objects_at(Place),
  154        nl.
  155
  156
  157/* These rules set up a loop to mention all the objects
  158   in your vicinity. */
  159
  160notice_objects_at(Place) :-
  161	at(baggage, Place),
  162	write('Your baggage is here.'), nl,
  163	fail.
  164
  165notice_objects_at(Place) :-
  166        at(X, Place), \+X = baggage,
  167        write('There is a '), write(X), write(' here.'), nl,
  168        fail.
  169
  170notice_objects_at(_).
  171	
  172
  173count_time :-
  174	time(Now), Now < 45,
  175	retract(time(Now)),
  176	NewTime is Now + 1,
  177	assert(time(NewTime)),
  178	X is NewTime + 15,
  179	write('It''s 8:'), write(X), write(' am now.'), nl,
  180	!.
  181
  182count_time :-
  183	write('It''s 9:00 am and the graduate orientation at the SEAS '), nl,
  184	write('school is starting right now. You didn''t make it on time... :-('), nl,
  185	finish, !, fail.
  186
  187i :- inventory.
  188
  189inventory :-
  190	holding(baggage),
  191	write('You''re carrying your baggage with you.'), nl,
  192	fail.
  193
  194inventory :-
  195	holding(Object), \+Object = baggage,
  196	write('You''re holding a '), write(Object), write('.'), nl,
  197	fail.
  198
  199inventory.
  200
  201
  202
  203/* This rule tells how to die. */
  204
  205die :-
  206        finish.
  207
  208
  209/* Under UNIX, the "halt." command quits Prolog but does not
  210   remove the output window. On a PC, however, the window
  211   disappears before the final output can be seen. Hence this
  212   routine requests the user to perform the final "halt." */
  213
  214finish :-
  215        nl,
  216        write('The game is over. Please enter the "halt." command.'),
  217        nl.
  218
  219
  220/* This rule just writes out game instructions. */
  221
  222instructions :-
  223        nl,
  224        write('Enter commands using standard Prolog syntax.'), nl,
  225        write('Available commands are:'), nl,
  226        write('start.               -- to start the game.'), nl,
  227        write('n.  s.  e.  w.       -- to go in that direction.'), nl,
  228        write('take(Object).        -- to pick up an object.'), nl,
  229        write('drop(Object).        -- to put down an object.'), nl,
  230	write('investigate(Object). -- to investigate an object.'), nl,
  231	write('i. inventory.        -- to view your inventory.'), nl,
  232        write('look.                -- to look around you again.'), nl,
  233        write('instructions.        -- to see this message again.'), nl,
  234        write('halt.                -- to end the game and quit.'), nl,
  235        nl,
  236	write('Note: Everything you do takes 1 minute. So choose '), nl,
  237	write('your actions wisely! '), nl,
  238	nl.
  239
  240
  241/* This rule prints out instructions and tells where you are. */
  242
  243start :-
  244	instructions,
  245	describe(start),
  246        look.
  247
  248
  249/* These rules describe the various rooms.  Depending on
  250   circumstances, a room may have more than one description. */
  251
  252describe(start) :-
  253	write('You are D., a new master\'s student at Penn, '), nl,
  254	write('who has just arrived to the airport in Philly '), nl,
  255	write('for the very first time. You don\'t really know '), nl,
  256	write('anything about Philly and in particular on how '), nl,
  257	write('to get around. All you know is that you\'re '), nl,
  258	write('way too late and that you have to be at the '), nl,
  259        write('graduate student introductory meeting held by '), nl,
  260	write('the SEAS school at Penn at 9:00 am. '), nl, nl.
  261
  262describe(airport) :-
  263	write('You are in the main airport hall. Nearby to '), nl,
  264	write('the east you see a big sign showing a subway map; '), nl,
  265	write('moreover, in the distant north you can spot an '), nl,
  266	write('info desk. Also, to the south there is the airport '), nl,
  267	write('exit.'), nl.
  268
  269describe(infodesk) :-
  270	write('You are at the airport\'s info desk. The friendly '), nl,
  271	write('lady tells you that there is a subway line going '), nl,
  272	write('to Penn''s campus. She also tells you that'), nl,
  273	write('you can buy a subway ticket at the nearby ticket '), nl,
  274	write('center, which is located east; to the south is the '), nl,
  275	write('airport hall.'), nl.
  276
  277describe(ticketcenter) :-
  278	write('You\'re at the ticket center. To obtain a ticket, type '), nl,
  279	write('take(some_ticket_type). To the west, is the info desk; to '), nl,
  280	write('the south there is a big subway sign.'), nl.
  281
  282describe(sign) :-
  283	write('You\'re at the subway sign now. It tells you that '), nl,
  284	write('there is a connection going from the airport to '), nl,
  285	write('the Penn campus. To the east nearby you see the '), nl,
  286	write('subway station entrance; to the north you see '), nl,
  287	write('the ticket center; to the west you see the airport '), nl,
  288	write('hall.').
  289
  290describe(subway) :-
  291	can_take(subway, LeavingTime),
  292	write('You\'re at the airport\'s subway station now. '), nl,
  293	write('You easily spot the subway that will take you to '), nl,
  294	write('Penn\'s campus. Unfortunately, however, you notice '), nl,
  295	write('that this subway will leave not earlier than in '), nl,
  296	time(Now), X is (LeavingTime - Now), write(X),
  297	write(' minute(s) from this station and that it will take '), nl,
  298	write('30 minutes in train to arrive at Penn''s campus. So '), nl,
  299	write('So you''re going to be late if you take it!'), nl, !.
  300
  301describe(subway) :-
  302	write('You\'re at the airport\'s subway station now. '), nl,
  303	write('Unfortunately, however, the subway to Penn\'s campus '), nl,
  304	write('already left and there won\'t be another one within '), nl,
  305	write('the next 40 minutes. You better try looking for some '), nl,
  306	write('other transportation method!'), nl.
  307
  308describe(train) :-
  309	write('You enter the train at the airport subway station, '), nl,
  310	write('wait for '),
  311	time(Now), leaves(subway, LeavingTime, _),
  312	X is LeavingTime - Now, write(X),
  313	write(' minutes, and then the subway train finally leaves. '), nl,
  314	write('But as you guessed the ride takes about 30 minutes '), nl,
  315	write('until you get off at Penn\'s campus and there is no '), nl,
  316	write('way to make it to graduate orientation at the SEAS '), nl,
  317	write('school on time anymore :-('), nl.
  318
  319describe(outside) :-
  320	write('You are outside of the airport now. To the north, there '), nl,
  321	write('is the airport hall. To the west you see '), nl,
  322	write('Penn''s personal pickup service that will bring you '), nl,
  323	write('directly to the Penn campus! '), nl.
  324
  325describe(pickup) :-
  326	arrives_on_time(shuttle, DurationTime), time(Now), Y is (Now + DurationTime),
  327	write('You arrive at the Penn shuttle pickup service with '), nl,
  328	write('all your baggage, get into it, and it takes you to Penn''s '), nl,
  329	write('campus in '), write(DurationTime), write(' minutes.'), nl, nl,
  330	write('Perfect! You made it to the SEAS orientation in '), nl,
  331	write(Y), write(' minutes, and even have time to make new friends there '), nl,
  332	write('before orientation starts. Congratulations, you successfully '), nl,
  333	write('completed your first challenge as a graduate student! :-)'), nl,
  334	finish.
  335
  336describe(pickup) :-
  337	write('You arrive at the Penn shuttle pickup service with '), nl,
  338	write('all your baggage, get into it, and it needs '),
  339	leaves(shuttle, _, DurationTime), write(DurationTime), nl, 
  340	write('minutes to arrive at Penn''s campus.'), nl,
  341	write('If you hadn''t procrastinated too much at the airport, that '), nl,
  342	write('would have been sufficient to arrive on time. In your case, '), nl,
  343	write('however, you got to the shuttle service way too late to still '), nl,
  344	write('be on on time at the graduate orientation... :-('),
  345	finish