1/* The Finder--an adventure game for CIS 554, by Jemale Lockett.
    2   Consult this file and issue the command: start. */
    3
    4:- dynamic i_am_at/1, at/2, holding/1, stick_count/1, carrying/1, distracted/1, hand_count/1, wearing_backpack/0, headphones_returned/0, watch_returned/0, bandana_returned/0.    5:- retractall(at(_, _)), retractall(i_am_at(_)),
    6	retractall(stick_count(_)), retractall(carrying(_)), retractall(distracted(_)), retractall(hand_count(_)),
    7	retractall(wearing_backpack), retractall(headphones_returned), retractall(watch_returned), retractall(holding(_)),
    8	retractall(bandana_returned).    9i_am_at(porch).
   10
   11dog(pomeranian).
   12  at(pomeranian, park).
   13dog(pitbull).
   14  at(pitbull, barber).
   15dog(rottweiler).
   16  at(rottweiler, barber).
   17dog(bull_terrier).
   18  at(bull_terrier, britton).
   19dog(german_shepard).
   20  at(german_shepard, anders_driveway).
   21
   22/*Facts detailing the world*/
   23
   24/*GAME MAP*/			     /*These number correspond to paths on a drawn out map*/
   25path(porch, n, anders).              /*1*/
   26  path(anders, s, porch).
   27
   28path(porch, s, house):- watch_returned, headphones_returned.               /*2*/
   29path(porch, s, house):- write('You can''t go inside yet!'), nl, !, fail.
   30  path(house, n, porch).
   31
   32path(porch, e, garage).              /*3*/
   33  path(garage, w, porch).
   34
   35path(porch, w, britton).             /*4*/
   36  path(britton, e, porch).
   37
   38path(anders, w, anders_driveway).    /*5*/
   39  path(anders_driveway, e, anders).
   40
   41path(anders, e, barber).            %6
   42  path(barber, w, anders ).         %7
   43
   44path(anders, n, anders_shed).
   45  path(anders_shed, s, anders).
   46
   47
   48path(barber, n, deli):- distracted(pitbull).
   49path(barber, n, deli):- write('There is a pitbull in front of the store driving away business.'), nl, !, fail.
   50  path(deli, s, barber).
   51
   52path(barber, e, gas_station):- distracted(rottweiler).
   53path(barber, e, gas_station):- write('There''s a really mean looking rottweiler you don''t want to mess with'), nl, !, fail.
   54  path(gas_station, w, barber).
   55
   56path(anders_driveway, s, britton).
   57  path(britton, n, anders_driveway).
   58
   59path(anders_driveway, n, lot):- distracted(german_shepard).
   60path(anders_driveway, n, lot):- write('The Anders'' german shepard is blocking the way.'), nl, !, fail.
   61  path(lot, s, anders_driveway).
   62
   63path(britton, w, knoll):- distracted(bull_terrier).              %8
   64path(britton, w, knoll):- write('There''s a bull terrier who has this territory marked.'), nl, !, fail.
   65
   66  path(knoll, e, britton).
   67
   68path(britton, s, britton_garage).          %9
   69  path(britton_garage, n, britton).
   70
   71
   72
   73path(knoll, w, park_entrance).  %10
   74  path(park_entrance, e, knoll).
   75
   76path(park_entrance, n, park):- (holding(bandana); carrying(bandana); bandana_returned).
   77path(park_entrance, n, park):-  write('There''s a group of kids blocking the entrance to the park.'),nl,
   78                                write('They tell you to retrieve the bandana of one of the kids who'), nl,
   79				write('lost it getting a haircut'), nl, !,  fail.
   80
   81  path(park, s, park_entrance).
   82
   83path(park, n, swings):- distracted(pomeranian).
   84path(park, n, swings):- write('There''s a cute little pomeranian that you''ll scare to death if you go near the swings'), nl, !,  fail.
   85  path(swings, s, park).
   86
   87path(park, w, trees).
   88path(trees, e, park).
   89
   90
   91
   92/* ITEM LOCATIONS */
   93
   94%at(watch, swings).
   95at(crowbar, garage).
   96at(backpack, anders_shed).
   97at(tape, britton_garage).
   98at(bandana, barber).
   99at(special_bandana, gas_station).
  100%at(meat, deli).
  101at(headphones, knoll).
  102
  103
  104at(stick, trees).
  105at(stick, anders_driveway).
  106at(stick, porch).
  107
  108%at(rotweiler, park).
  109%at(pitbull, park).
  110
  111/* Variables */
  112stick_count(0).
  113hand_count(0). %number of items in hands, max 2
  114
  115
  116
  117
  118/* These rules describe how to pick up an object. */
  119take(stick):-
  120	i_am_at(Place),
  121	at(stick, Place),
  122	hand_count(X),
  123	X < 2, !,
  124	retract(at(stick, Place)),
  125	assert(holding(stick)),
  126
  127	%increase hand count
  128	Y is X + 1,
  129	retract(hand_count(X)),
  130	assert(hand_count(Y)),
  131
  132	%increase stick count
  133	stick_count(Z),
  134	A is Z + 1,
  135	retract(stick_count(Z)),
  136	assert(stick_count(A)),
  137
  138	write('Picked up a stick in hands'),
  139	assert(at(stick, trees)), !,
  140	nl.
  141
  142take(stick) :-
  143	i_am_at(Place),
  144	at(stick, Place), /* sticks can be in multiple places*/
  145	wearing_backpack, !,
  146
  147	%increase stick count
  148	stick_count(X),
  149	Y is X + 1,
  150	retract(stick_count(X)),
  151	assert(stick_count(Y)),
  152
  153	retract(at(stick, Place)),
  154	assert(carrying(stick)),
  155	write('Put stick in backpack'),
  156	assert(at(stick, trees)), !,
  157
  158	nl.
  159
  160take(stick) :-
  161	write('Either it\'s not here or you don''t have room for it'), nl, !,  fail.
  162
  163take(backpack):-
  164	i_am_at(Place),
  165	at(backpack, Place),
  166
  167	hand_count(X),
  168	X < 2, !,
  169	retract(hand_count(X)),
  170	Y is X + 1,
  171	assert(hand_count(Y)),
  172
  173	retract(at(backpack, Place)),
  174	assert(holding(backpack)),
  175	write('Aquired the backpack but a strap is broken.'), nl.
  176
  177take(backpack):-
  178	write('You don''t have enough hands'), !, nl, fail.
  179
  180take(X) :-
  181        holding(X),
  182        write('You''re already holding it!'),
  183        !, nl.
  184
  185take(X) :-
  186        i_am_at(Place),
  187        at(X, Place),
  188	%check if space
  189	hand_count(A),
  190	A < 2,!,
  191        retract(at(X, Place)),
  192        assert(holding(X)),
  193
  194	%increase hand count
  195        hand_count(Y),
  196	Z is Y + 1,
  197	retract(hand_count(Y)),
  198	assert(hand_count(Z)),
  199
  200        write('OK.'),
  201        !, nl.
  202take(X) :-
  203        i_am_at(Place),
  204        at(X, Place),
  205	%backpack is functional?
  206	wearing_backpack, !,
  207        retract(at(X, Place)),
  208        assert(carrying(X)),
  209        write('OK.'),
  210        !, nl.
  211
  212take(_) :-
  213        write('Your hands may be full or the item is missing.'),
  214        nl.
  215
  216
  217/* These rules describe how to put down an object. */
  218
  219drop(X) :-
  220        holding(X),
  221	X = stick,
  222	%fix hand_count
  223	hand_count(Y),
  224	retract(hand_count(Y)),
  225	Z is Y - 1,
  226	assert(hand_count(Z)),
  227
  228        i_am_at(Place),
  229        retract(holding(X)),
  230        assert(at(X, Place)),
  231        write('OK.'),
  232        !,
  233
  234	stick_count(A),
  235	B is A - 1,
  236	retract(stick_count(A)),
  237	assert(stick_count(B)),
  238	nl.
  239
  240drop(X) :-
  241        holding(X),
  242
  243	%fix hand_count
  244	hand_count(Y),
  245	retract(hand_count(Y)),
  246	Z is Y - 1,
  247	assert(hand_count(Z)),
  248
  249        i_am_at(Place),
  250        retract(holding(X)),
  251        assert(at(X, Place)),
  252        write('OK.'),
  253        !,
  254	nl.
  255
  256drop(_) :-
  257        write('You aren''t holding it!'),
  258        nl.
  259
  260
  261/* These rules define the direction letters as calls to go/1. */
  262
  263n :- go(n).
  264
  265s :- go(s).
  266
  267e :- go(e).
  268
  269w :- go(w).
  270
  271
  272/* This rule tells how to move in a given direction. */
  273
  274go(Direction) :-
  275        i_am_at(Here),
  276        path(Here, Direction, There),
  277        retract(i_am_at(Here)),
  278        assert(i_am_at(There)),
  279        !, look.
  280
  281go(_) :-
  282        write('You can''t go that way.').
  283
  284
  285/* This rule tells how to look about you. */
  286
  287look :-
  288        i_am_at(Place),
  289        describe(Place),
  290        nl,
  291        notice_objects_at(Place),
  292        nl.
  293
  294
  295/* These rules set up a loop to mention all the objects
  296   in your vicinity. */
  297
  298notice_objects_at(Place) :-
  299        at(X, Place),
  300	\+dog(X),
  301        write('There is a '), write(X), write(' here.'), nl,
  302        fail.
  303
  304notice_objects_at(_).
  305
  306
  307/* This rule tells how to get rid of sticks*/
  308throw_stick :-
  309	holding(stick), !,
  310	write('throwing stick...'), nl,
  311	%fix stick count
  312	retract(stick_count(X)),
  313	Y is X - 1,
  314	assert(stick_count(Y)),
  315
  316	%remove stick
  317        retract(holding(stick)),
  318	hand_count(A),
  319	B is A - 1,
  320	retract(hand_count(A)),
  321	assert(hand_count(B)),
  322
  323	distract_dog,
  324	write('You threw a stick. You now have '), write(Y),
  325	write(' sticks left'), nl.
  326
  327throw_stick :-
  328	carrying(stick), !,
  329	write('throwing stick...'), nl,
  330	%fix stick count
  331	retract(stick_count(X)),
  332	Y is X - 1,
  333	assert(stick_count(Y)),
  334
  335	%remove stick
  336	retract(carrying(stick)),
  337
  338	distract_dog,
  339	write('You threw a stick. You now have '), write(Y),
  340	write(' sticks left'), nl.
  341
  342
  343throw_stick :- write('You don''t have any sticks!'), nl, fail.
  344
  345distract_dog :-
  346	i_am_at(Place),
  347	nl,
  348	at(X, Place),
  349	dog(X), !,
  350	assert(distracted(X)).
  351
  352distract_dog:- write('no dog here.'), nl, !.
  353
  354/* List the Items in Inventory */
  355
  356i:-
  357	inventory.
  358
  359inventory:-
  360	holding(X),
  361	write(X), write(' in hand.'),  nl,
  362	fail.
  363
  364inventory:-
  365	carrying(Y),
  366	write(Y), write(' in backpack.'), nl,
  367	fail.
  368
  369inventory:- write('That''s all you have'), nl.
  370
  371/* This rule tells how to die. */
  372
  373die :-
  374        finish.
  375
  376
  377/* Under UNIX, the "halt." command quits Prolog but does not
  378   remove the output window. On a PC, however, the window
  379   disappears before the final output can be seen. Hence this
  380   routine requests the user to perform the final "halt." */
  381
  382finish :-
  383        nl,
  384        write('The game is over. Please enter the "halt." command.'),
  385        nl.
  386
  387
  388/* This rule just writes out game instructions. */
  389
  390instructions :-
  391        nl,
  392        write('Enter commands using standard Prolog syntax.'), nl,
  393        write('Available commands are:'), nl,
  394        write('start.             -- to start the game.'), nl,
  395        write('n.  s.  e.  w.     -- to go in that direction.'), nl,
  396        write('take(Object).      -- to pick up an object.'), nl,
  397	write('inventory. (or i.) -- to see your inventory.'), nl,
  398        write('drop(Object).      -- to put down an object.'), nl,
  399	write('use(Object).	  -- to use an object.'), nl,
  400	write('throw_stick.	  -- to throw a stick.'), nl,
  401        write('look.              -- to look around you again.'), nl,
  402        write('instructions.      -- to see this message again.'), nl,
  403        write('halt.              -- to end the game and quit.'), nl,
  404        nl.
  405
  406
  407/* This rule prints out instructions and tells where you are. */
  408
  409start :-
  410        instructions,
  411        look.
  412
  413
  414/* These rules describe the various rooms.  Depending on
  415   circumstances, a room may have more than one description. */
  416describe(porch) :- headphones_returned,
  417		   watch_returned, !,
  418		   write('All items returned! You can enter home if you want.'), nl.
  419
  420describe(porch) :- write('You are on your front porch because your.'), nl,
  421		   write('mother wants you to be active.'),nl,
  422		   write('You\'ve decided to become The Finder'), nl,
  423		   write('finding and returning objects for people.'),nl,
  424		   write('You can return to your precious internet'), nl,
  425		   write('when you\'ve found and returned 3 items to their'), nl,
  426		   write('rightful owners.'), nl,
  427		   write('To the north is the Anders home, to the west is the'),nl,
  428		   write('Brittons. To the east is your own garage.'), nl.
  429
  430describe(anders) :- holding(watch), !,
  431		    write('Watch returned!'), nl,
  432		    retract(holding(watch)),
  433		    assert(watch_returned).
  434
  435describe(anders) :- carrying(watch), !,
  436		    write('Watch returned!'), nl,
  437		    retract(carrying(watch)),
  438		    assert(watch_returned).
  439
  440
  441describe(anders) :- write('You are at the Anders home. Jeremy tells you'), nl,
  442                    write('that he lost hiw watch at the park. He mentions'), nl,
  443                    write('not to go past the german shepard in the driveway.'), nl,
  444		    write('Their driveway is to the west, and their shed is'), nl,
  445		    write('straight ahead to the north. Exit to the'), nl,
  446		    write('east of the house to head to the barbershop.'), nl.
  447
  448
  449
  450describe(britton) :- holding(headphones), !,
  451	             write('Headphones returned!'), nl,
  452		     retract(holding(headphones)),
  453                     assert(headphones_returned).
  454
  455describe(britton) :- carrying(headphones), !,
  456	             write('Headphones returned!'), nl,
  457		     retract(carrying(headphones)),
  458                     assert(headphones_returned).
  459
  460
  461describe(britton) :- write('You are at the Britton home. Brittany tries to'), nl,
  462	             write('get you to leave because she is too'), nl,
  463                     write('busy looking for her headphones she lost.'), nl,
  464		     write('To the west is a grassy knoll and to the south is the Brittons'' garage.').
  465
  466
  467describe(knoll) :- write('You are on a grassy knoll. To the west is the entrance to the local park.'), nl.
  468
  469describe(britton_garage):- write('You are in the Britton garage. There''s not much here.'), nl.
  470
  471
  472describe(park_entrance):-holding(bandana), !,
  473	                 write('Bandana returned! You may enter park (n.)'), nl,
  474			 assert(bandana_returned),
  475			 retract(holding(bandana)).
  476
  477describe(park_entrance):-carrying(bandana), !,
  478	                 write('Bandana returned! You may enter park (n.)'), nl,
  479			 assert(bandana_returned),
  480			 retract(carrying(bandana)).
  481
  482describe(park_entrance) :- write('You are at the entrance to the park, which is to the north.'), nl.
  483
  484describe(park) :- write('You are at the park. There are trees to the west and swings to the north.'), nl.
  485
  486describe(garage) :- write('You are in your garage'), nl.
  487
  488describe(anders_shed):- write('You are in the Anders shed.'), nl.
  489
  490describe(anders_driveway):- write('You are in the Anders driveway. There'), nl,
  491			    write('appears to be an empty lot to the north'),nl,
  492			    write('and the Britton house to the south.'), nl.
  493
  494describe(lot):- write('There is nothing here. You should have listened to Jeremy.'), nl.
  495
  496
  497describe(barber):- write('You are at the barber but you don''t'), nl,
  498                   write('really need a haircut...'), nl,
  499	           write('There is a deli to the north and a gas_station to the east.'), nl.
  500
  501describe(gas_station):- write('You are at the gas station.'), nl.
  502
  503describe(deli) :- write('You are in the deli.'), nl, receive_meat.
  504
  505describe(trees):- write('You are at the trees.'), nl.
  506
  507describe(swings):- write('You are at the swings.'), nl.
  508
  509describe(house):-write('You made it back into the house! But you had so'), nl,
  510	         write('much fun retrieving things that you''re gonna go'), nl,
  511		 write('out and continue doing it! Look out for later chapters'), nl,
  512		 write('where things get bigger and better (think Uncharted!)'),
  513		 finish.
  514
  515receive_meat :-
  516	wearing_backpack,
  517	assert(carrying(meat)),
  518	write('receiving meat'), nl.
  519
  520receive_meat :- write('No room for meat being given').
  521
  522
  523use(swings) :-
  524	     write('You don''t see the watch so decide to take a swing'), nl,
  525	     write('As you''re swinging higher and higher you notice'), nl,
  526	     write('that there is a glimmer atop the swingset. It''s'), nl,
  527	     write('Jeremy''s watch! You''ve retrieved it!'), nl,
  528	     assert(carrying(watch)).
  529
  530use(stick) :- throw_stick, !.
  531
  532use(tape) :- holding(tape),
  533	     holding(backpack),
  534	     !,
  535	     retract(holding(backpack)),
  536	     assert(wearing_backpack),
  537	     retract(holding(tape)),
  538	     assert(carrying(tape)),
  539	     %fix hand count
  540	     hand_count(X),
  541	     retract(hand_count(X)),
  542	     Y is X - 2,
  543	     assert(hand_count(Y)),
  544
  545	     write('Now wearing backpack'), nl.
  546use(Object) :-
  547	write('Using object'), nl