1/* Out of Inferno, Muruo Liu. */
    2:- dynamic i_am_at/1, at/2, holding/1, timer/1.    3:- retractall(at(_, _)), retractall(i_am_at(_)), retractall(locked(_)).    4/* The place I am at at the beginning*/
    5i_am_at(bedroom).
    6
    7/* The remaining timer*/
    8timer(20).
    9locked(1).
   10/* define the path between different rooms*/
   11path(livingroom, s, bedroom).
   12path(livingroom, n, bathroom).
   13path(livingroom, w, door).
   14path(livingroom, e, studyroom).
   15path(bedroom, n, livingroom).
   16path(bathroom, s, livingroom).
   17path(door, e, livingroom).
   18path(studyroom, w, livingroom).
   19
   20
   21
   22
   23/* define the things at different places*/
   24at(key1, bedroom).
   25at(key2, bathroom).
   26at(browser, studyroom).
   27at(gun, livingroom).
   28at(television, livingroom).
   29at(safe, livingroom).
   30
   31/* define movable things*/
   32movable(key1).
   33movable(key2).
   34movable(gun).
   35movable(bullets).
   36movable(cable).
   37movable(code).
   40unmovable(television).
   41unmovable(safe).
   42unmovable(browser).
   43
   44/* define the actions taken when taking different direction*/
   45n :- go(n).
   46
   47s :- go(s).
   48
   49e :- go(e).
   50
   51w :- go(w).
   52
   53
   54/* actions taken when moving*/
   55go(Direction) :-
   56        i_am_at(Here),
   57        path(Here, Direction, There),
   58        retract(i_am_at(Here)),
   59        assert(i_am_at(There)),
   60        retract(timer(T)),
   61        Tn is T - 1,
   62        assert(timer(Tn)),
   63        look, !, check.
   64        
   65
   66go(_) :-
   67        write('You cannot go that way'), nl.
   68getTime(J) :- retract(timer(N)), J is N, assert(timer(N)).
   69/* take a look at the room and see things at there*/
   70look :-
   71        i_am_at(Place),
   72        describe(Place),
   73        nl,
   74        notice_object_at(Place), !,
   75        nl.
   76
   77/* print out which room it is*/
   78describe(Place) :-
   79        write('I am at '), write(Place).
   80
   81/* print out the things in the room*/
   82notice_object_at(Place) :-
   83        at(X, Place),
   84        write('There is a '), write(X), write(' here.'), nl,
   85        fail.
   86notice_object_at(_).
   87
   88notice_object_at(_).
   89
   90/* take movable things*/
   91take(X) :-
   92        movable(X),
   93        i_am_at(Place),
   94        at(X, Place),
   95        retract(at(X, Place)),
   96        assert(holding(X)),
   97        write('OK.'),
   98        !, nl.
   99
  100take(X) :-
  101        unmovable(X),
  102        i_am_at(Place),
  103        at(X, Place),
  104        write('It is unmovable, so you cannot take it. You can only use it.'),
  105        !, nl.
  106
  107take(X) :-
  108        holding(X),
  109        write('You have hold it!'), !, nl.
  110
  111take(_) :-
  112        write('I don''t see it here.'),
  113        nl.
  114
  115/* use things*/
  116use(browser) :-
  117        holding(browser),
  118        write('Find nothing!'), nl.
  119
  120use(browser) :-
  121        holding(key1),
  122        holding(key2),
  123        i_am_at(studyroom),
  124        assert(at(cable, studyroom)),
  125        retract(timer(T)),
  126        Tn is T - 1,
  127        assert(timer(Tn)),
  128        write('Find a cable!'), nl, !,
  129        check.
  130
  131use(browser) :-
  132        i_am_at(studyroom),
  133        write('Nothing happens. The browser is locked and you need two keys to open it.'),
  134        retract(timer(T)),
  135        Tn is T - 1,
  136        assert(timer(Tn)), !,
  137        nl, check.
  138use(browser) :-
  139        holding(browser),
  140        write('Find nothing!'), nl.
  141
  142use(television) :- 
  143        holding(code),
  144        write('Find nothing!'), nl.
  145
  146use(television) :-
  147        holding(cable),
  148        i_am_at(livingroom),
  149        assert(at(code, livingroom)),
  150        retract(timer(T)),
  151        Tn is T - 1,
  152        assert(timer(Tn)),
  153        write('Find a code!'), nl, !,
  154        check.
  155
  156use(television) :-
  157        i_am_at(livingroom),
  158        retract(timer(T)),
  159        Tn is T - 1,
  160        assert(timer(Tn)),
  161        write('Nothing happens. The cable of the TV is missing.'), !,
  162        nl, check.
  163
  164use(safe) :-
  165        holding(bullets),
  166        write('Find nothing!'), nl.
  167
  168use(safe) :-
  169        holding(code),
  170        i_am_at(livingroom),
  171        assert(at(bullets, livingroom)),
  172        retract(timer(T)),
  173        Tn is T - 1,
  174        assert(timer(Tn)),
  175        write('Find some bullets!'), nl, !,
  176        check.
  177
  178use(safe) :-
  179        i_am_at(livingroom),
  180        retract(timer(T)),
  181        Tn is T - 1,
  182        assert(timer(Tn)),
  183        write('Nothing happens. The safe needs some code to open.'), !,
  184        nl, check.
  185
  186use(gun) :-
  187        holding(gun),
  188        holding(bullets),
  189        i_am_at(door), !,
  190        retract(locked(_)),
  191        assert(locked(0)),
  192        write('The lock has been broken!'), nl.
  193
  194use(gun) :-
  195        holding(gun),
  196        retract(timer(T)),
  197        Tn is T - 1,
  198        assert(timer(Tn)),
  199        write('Nothing happens. Don''t do silly thing.'), nl, !,
  200        check.
  201
  202use(gun) :-
  203        retract(timer(T)),
  204        Tn is T - 1,
  205        assert(timer(Tn)),
  206        write('You have no gun yet!'), nl, !,
  207        check.
  208
  209use(X) :-
  210       holding(X),
  211       retract(timer(T)),
  212       Tn is T - 1,
  213       assert(timer(Tn)),
  214       write('Nothing happens.'), !,
  215       nl, check.
  216
  217use(X) :-
  218       movable(X),
  219       retract(timer(T)),
  220       Tn is T - 1,
  221       assert(timer(Tn)),
  222       write('Nothing happens.'), !,
  223       nl, check.
  224
  225use(_) :-
  226       write('I don''t see it here.'),
  227       retract(timer(T)),
  228       Tn is T - 1,
  229       assert(timer(Tn)), !,
  230       nl, check.
  231
  232/* drop things*/
  233drop(X) :-
  234        holding(X),
  235        i_am_at(Place),
  236        retract(holding(X)),
  237        assert(at(X, Place)),
  238        write('OK.'),
  239        !, nl.
  240
  241drop(_) :-
  242        write('You aren''t holding it!'),
  243        nl.
  244
  245
  246
  247/* gameover*/
  248gameover :-
  249        write('Game Over. You have run out of timer'), nl.
  250
  251/* check whether timer has run out*/
  252check :-
  253        getTime(N), N < 1, gameover, Y is N, assert(timer(Y)).
  254check :-
  255        getTime(N), N >= 1, write('You still have time!'), nl.
  256/* win*/
  257win :-
  258        write('Congratulations! You have escaped!'), nl.
  259
  260/* Under UNIX, the "halt." command quits Prolog but does not
  261   remove the output window. On a PC, however, the window
  262   disappears before the final output can be seen. Hence this
  263   routine requests the user to perform the final "halt." */
  264
  265/* instructions of the game*/
  266instructions :-
  267        nl,
  268        write('Enter commands using standard Prolog syntax.'), nl,
  269        write('Available commands are:'), nl,
  270        write('start.             -- to start the game.'), nl,
  271        write('n.  s.  e.  w.     -- to go in that direction. Every successful walk will consume timer'), nl,
  272        write('take(Object).      -- to pick up a movable object.'), nl,
  273        write('drop(Object).      -- to put down an object.'), nl,
  274        write('use(Object).       -- to use an unmovable item. Each action of use will consume timer, no matter whether it is a proper use.'), nl,
  275        write('look.              -- to look around you again.'), nl,
  276        write('instructions.      -- to see this message again.'), nl,
  277        write('halt.              -- to end the game and quit.'), nl,
  278        write('getTime.           -- to get the remaining time.'), nl,
  279        write('route.             -- to get the places you can go to and their directions.'), nl,
  280        write('itemList.          -- to get the things you are holding.'), nl,
  281        write('openTheDoor.       -- open the door.'), nl.
  282
  283/* the background of the game*/
  284background :- 
  285        write('You are trapped in big fire. '), nl, 
  286        write('What makes things worse is that the door is locked. '), nl,
  287        write('You have to find a way to escape in limited time! Good Luck!'), nl.
  288
  289/* open the door*/
  290openTheDoor :-
  291        i_am_at(door),
  292        locked(0),
  293        win.
  294
  295openTheDoor :-
  296        i_am_at(door),
  297        locked(1),
  298        write('The door has been locked! You cannot get out of here now!'), nl.
  299
  300openTheDoor :-
  301        write('The door is not here!'), nl.
  302
  303
  304/* start the game */
  305start :-
  306      background,
  307      instructions,
  308      look.
  309
  310/* get the item you are holding*/
  311itemList :- 
  312       holding(X),
  313       write('I am holding a '), write(X), nl,
  314       fail.
  315
  316itemList.
  317
  318/* get the places you can go to and their directions*/
  319route :- 
  320       i_am_at(Here),
  321       path(Here, X, Y),
  322       write('press ') , write(X), write('. '), write('and you can reach '), write(Y), 
  323       nl, fail.
  324
  325route