1/* The Morning After a Party, by Takumi Kumagai. */
    2
    3:- dynamic i_am_at/1, at/2, holding/1, timeLeft/1.    4:- retractall(at(_, _)), retractall(i_am_at(_)), retractall(holding(_)), retractall(timeLeft(_)).    5
    6:- write('You wake up in your livingroom with a headache.'),nl.    7:- write('That''s right. You partied all night last night, and the house is a mess!'),nl,nl.    8
    9:- write('You get a glass of water and take a look at your smartphone.'),nl.   10:- write('You see a text message from your girlfriend saying she is very excited about the date.'),nl,nl.   11
   12:- write('Now you remember you have a date with your girlfriend today'),nl.   13:- write('and realize you have to leave in 10 minutes to make it to the date on time.'),nl,nl.   14
   15:- write('Since you are feeling very sick, it takes you one minute to crawl from one room to another.'),nl.   16:- write('You have to find your car key, and get to your car in the garage.'),nl.   17
   18i_am_at(livingroom).
   19
   20timeLeft(10).
   21
   22path(livingroom, u, bedroom).
   23path(bedroom, d, livingroom).
   24
   25path(livingroom, d, basement).
   26path(basement, u, livingroom).
   27
   28path(livingroom, n, closet) :- holding(closetKey).
   29path(livingroom, n, closet) :- write('The closed appears to be locked'), nl, !, fail.
   30path(closet, s, livingroom).
   31
   32path(livingroom, s, garage).
   33path(garage, n, livingroom).
   34
   35path(livingroom, e, bathroom).
   36path(bathroom, w, livingroom).
   37
   38
   39at(closetKey, bedroom).
   40at(carKey, box).
   41
   42/* These rules describe how to pick up an object. */
   43
   44
   45take(X) :-
   46        holding(X),
   47        write('You''re already holding it!'),
   48        !, nl.
   49
   50take(X) :-
   51        i_am_at(Place),
   52        at(X, Place),
   53        retract(at(X, Place)),
   54        assert(holding(X)),
   55        write('OK.'),
   56        !, nl.
   57
   58take(_) :-
   59        write('I don''t see it here.'),
   60        nl.
   61
   62
   63/* These rules describe how to put down an object. */
   64
   65drop(X) :-
   66        holding(X),
   67        i_am_at(Place),
   68        retract(holding(X)),
   69        assert(at(X, Place)),
   70        write('OK.'),
   71        !, nl.
   72
   73drop(_) :-
   74        write('You aren''t holding it!'),
   75        nl.
   76
   77
   78/* These rules define the direction letters as calls to go/1. */
   79
   80n :- go(n).
   81
   82s :- go(s).
   83
   84e :- go(e).
   85
   86w :- go(w).
   87
   88u :- go(u).
   89
   90d :- go(d).
   91
   92
   93/* This rule tells how to move in a given direction. */
   94
   95go(_) :-
   96		timeLeft(X),
   97		X =:= 0,        
   98		write('You have ran out of time. You lose.'), nl,
   99        finish, !.
  100		
  101
  102go(Direction) :-
  103		i_am_at(Here),
  104        path(Here, Direction, There),
  105		timeLeft(X),
  106		retract(timeLeft(X)),
  107		decrement(X,Y),
  108		assert(timeLeft(Y)),
  109        retract(i_am_at(Here)),
  110        assert(i_am_at(There)),
  111        write('You have '), write(Y), write(' minutes left'), nl,
  112        !, describe(There).
  113
  114go(_) :-
  115		timeLeft(X),
  116		write('You can''t go that way.'),nl,
  117        write('You have '), write(X), write(' minutes left').
  118
  119
  120decrement(X,Y) :- 
  121		Y is X-1.
  122		
  123/* This rule tells how to look about you. */
  124
  125look :-
  126        i_am_at(Place),
  127        describe(Place),
  128        nl,
  129        notice_objects_at(Place),
  130        nl.
  131
  132open :-
  133		i_am_at(closet),
  134		retract(at(carKey, box)),
  135		assert(holding(carKey)),
  136		write('You now have a car key!'),
  137		nl,!.
  138		
  139open :- 
  140		write('There is nothing to open here!'), nl.
  141		
  142		
  143
  144/* These rules set up a loop to mention all the objects
  145   in your vicinity. */
  146
  147notice_objects_at(Place) :-
  148        at(X, Place),
  149        write('There is a '), write(X), write(' here.'), nl,
  150        fail.
  151
  152notice_objects_at(_).
  153
  154i :-
  155		holding(X),
  156		write('you have a '), write(X), write('.'), nl,
  157		fail.
  158i.
  159
  160
  161/* This rule tells how to die. */
  162
  163die :-
  164        finish.
  165
  166
  167/* Under UNIX, the "halt." command quits Prolog but does not
  168   remove the output window. On a PC, however, the window
  169   disappears before the final output can be seen. Hence this
  170   routine requests the user to perform the final "halt." */
  171
  172finish :-
  173        nl,
  174        write('The game is over. Please enter the "halt." command.'),
  175        nl.
  176
  177
  178/* This rule just writes out game instructions. */
  179
  180instructions :-
  181        nl,
  182        write('Enter commands using standard Prolog syntax.'), nl,
  183        write('Available commands are:'), nl,
  184        write('start.             		-- to start the game.'), nl,
  185        write('n.  s.  e.  w.  u.  d.		-- to go in that direction.'), nl,
  186        write('take(Object).		-- to pick up an object.'), nl,
  187        write('drop(Object).		-- to put down an object.'), nl,
  188        write('look.			-- to look around you again.'), nl,
  189        write('open.			-- to open a box, if there is any.'), nl,
  190        write('instructions.		-- to see this message again.'), nl,
  191        write('halt.			-- to end the game and quit.'), nl,
  192        write('i.			-- to see the items you have.'), nl,
  193        nl.
  194
  195
  196/* This rule prints out instructions and tells where you are. */
  197
  198start :-
  199        instructions,
  200        look.
  201
  202
  203/* These rules describe the various rooms.  Depending on
  204   circumstances, a room may have more than one description. */
  205
  206describe(livingroom) :- write('You are in livingroom.'), nl.
  207describe(bedroom) :- write('You are in bedroom.'), nl.
  208describe(basement) :- write('You are in basement.'), nl.
  209describe(closet) :- 
  210		holding(carKey),
  211		write('You are in closet.'), nl.
  212describe(closet) :- write('There is a box. You don''t remember what is in it.'), nl.		
  213describe(garage) :-
  214        holding(carKey),
  215        write('You are in garage. You see your car. Now you can drive out from your garage and make it to the date!'), nl,
  216        write('You won the game.'), nl,
  217        finish, !.
  218describe(garage) :- 
  219		write('You are in garage. You see your car, but you don''t have the key.'), nl.
  220describe(bathroom) :- write('You are in bathroom.'), nl