1/* Dragon Fire, by Yaou Wang. */
    2
    3:- dynamic i_am_at/1, at/2, holding/1, money/1, cost/2, alive/1.    4:- retractall(at(_, _)), retractall(i_am_at(_)), retractall(alive(_)).    5
    6/* These are the initial conditions of the game. */
    7
    8money(100).
    9
   10i_am_at(home).
   11
   12path(home, n, closet) :- holding(key).
   13path(home, n, closet) :-
   14      write('The door seems to be locked... you seem to have left the key somewhere...'), nl,
   15      !, fail.
   16path(home, s, field).
   17path(closet, s, home).
   18path(field, n, home).
   19path(home, e, town).
   20path(town, w, home).
   21path(town, n, shop).
   22path(town, e, mountain).
   23path(town, s, forrest).
   24path(shop, s, town).
   25path(forrest, n, town).
   26path(forrest, s, unicorn).
   27path(unicorn, n, forrest).
   28path(mountain, w, town).
   29path(mountain, e, dragon).
   30path(dragon, w, mountain).
   31
   32at(translator, shop).
   33at(dress, shop).
   34at(ring, shop).
   35at(necklace, shop).
   36at(sword, shop).
   37at(key, field).
   38
   39alive(unicorn).
   40alive(dragon).
   41
   42cost(sword, 50).
   43cost(translator, 1000).
   44cost(dress, 500).
   45cost(ring, 1000).
   46cost(necklace, 1050).
   47
   48/* These rules govern how to buy things with money (the limited resource) */
   49
   50affordable(X, Money, Leftover) :-
   51      cost(X, Cost),
   52      Money > Cost, Leftover is Money - Cost.
   53
   54buy(X) :-
   55      holding(X),
   56      write('You''re already holding it!'),
   57      !, nl.
   58
   59buy(X) :-
   60      at(X, shop),
   61      i_am_at(shop),
   62      cost(X, Cost),
   63      money(Money),
   64      affordable(X, Money, Leftover),
   65      retract(money(Money)),
   66      assert(money(Leftover)),
   67      retract(cost(X,Cost)),
   68      take(X),
   69      write('You have bought it!'), nl,
   70      write('You now have '), write(Leftover), write(' dollars left.'),
   71      !, nl.
   72
   73buy(_) :-
   74      i_am_at(shop),
   75      write('You can''t afford it!'), nl, !, fail.
   76
   77buy(_) :-
   78      write('There is nothing to buy!'), nl, !, fail.
   79
   80/* These rules describe how to pick up an object. */
   81
   82take(X) :-
   83        i_am_at(shop),
   84	at(X, shop),
   85	cost(X, _),
   86        write('You have to buy it!'),
   87        nl, !, fail.
   88
   89take(X) :-
   90        holding(X),
   91        write('You''re already holding it!'),
   92        !, nl.
   93
   94take(X) :-
   95        i_am_at(Place),
   96        at(X, Place),
   97        retract((at(X, Place))),
   98        assert(holding(X)),
   99        write('OK.'),
  100        !, nl.
  101
  102take(_) :-
  103        write('I don''t see it here.'),
  104        nl, !, fail.
  105
  106
  107/* These rules describe how to put down an object. */
  108
  109drop(X) :-
  110        holding(X),
  111        i_am_at(Place),
  112        retract(holding(X)),
  113        assert(at(X, Place)),
  114        write('OK.'),
  115        !, nl.
  116
  117drop(_) :-
  118        write('You aren''t holding it!'),
  119        nl.
  120
  121/* The inventory command */
  122
  123i :-
  124        holding(X),
  125        write('You are holding a '), write(X), nl,
  126        fail.
  127i.
  128
  129/* Checks how much money you have */
  130
  131wallet :-
  132        money(X),
  133        write('You have '), write(X), write(' gold coins in your wallet.'), nl.
  134
  135/* These rules define the direction letters as calls to go/1. */
  136
  137n :- go(n).
  138
  139s :- go(s).
  140
  141e :- go(e).
  142
  143w :- go(w).
  144
  145
  146/* This rule tells how to move in a given direction. */
  147
  148go(Direction) :-
  149        i_am_at(Here),
  150        path(Here, Direction, There),
  151        retract(i_am_at(Here)),
  152        assert(i_am_at(There)),
  153        !, look.
  154
  155go(_) :-
  156        write('You can''t go that way.').
  157
  158
  159/* This rule tells how to look about you. */
  160
  161look :-
  162        i_am_at(Place),
  163        describe(Place),
  164        nl,
  165        notice_objects_at(Place),
  166        nl.
  167
  168
  169/* These rules set up a loop to mention all the objects
  170   in your vicinity. */
  171
  172notice_objects_at(Place) :-
  173        at(X, Place),
  174        write('There is a '), write(X), write(' here.'), nl,
  175        fail.
  176
  177notice_objects_at(shop) :-
  178        at(X, shop),
  179        cost(X, Y),
  180        write('The '), write(X), write(' costs '),
  181        write(Y), write(' gold coins.'), nl,
  182        fail.
  183
  184notice_objects_at(_).
  185
  186/* These rules tell how to handle killing the dragon and the unicorn */
  187
  188kill :-
  189        i_am_at(unicorn),
  190        retract(alive(unicorn)),
  191        write('You have caught the unicorn off-guard and killed it!'), nl,
  192        write('However, before dying the unicorn cast a curse to this'), nl,
  193        write('land and you have been hit! You are now cursed to forever'), nl,
  194        write('roam this land in a mindless state.'), nl,
  195        die, !.
  196
  197kill :-
  198        i_am_at(dragon),
  199        alive(dragon),
  200        holding(magic_sword),
  201        retract(alive(dragon)),
  202        assert(holding(crown)),
  203        write('A great battle ensues and you try to attack the dragon on all'), nl,
  204        write('sides. The dragon flew to the sky and showered fireballs on you!'), nl,
  205        write('With one desperate attempt you threw your enchanted sword with all'), nl,
  206        write('your force and... behold! It penetrated the head of the dragon!'), nl,
  207        write('You have slain the dragon with your magical sword! From its'), nl,
  208        write('liar you have retrieved the lost crown.'), nl, !.
  209
  210kill :-
  211        i_am_at(dragon),
  212        alive(dragon),
  213        holding(sword),
  214        write('You slashed the dragon with your sword, but it is too dull to have'), nl,
  215        write('any effects! The dragon, now full of fury, killed you with its sharp'), nl,
  216        write('claws!'), nl, die, !.
  217
  218kill :-
  219        i_am_at(dragon),
  220        alive(dragon),
  221        write('You have awakened and provoked the dragon. Your weak body with no'), nl,
  222        write('magical protection is no match for the dragon! With a big breath of'), nl,
  223        write('fire you are burnt alive.'), nl,
  224        die, !.
  225
  226kill :-
  227        i_am_at(dragon),
  228        write('You cannot kill something that is already dead.'), nl, !.
  229
  230kill :-
  231        write('There is nothing here to attack.'), nl.
  232
  233/* This rule tells how to die. */
  234
  235die :-
  236        write('You have died and lost the game.'), nl,
  237        !, finish.
  238
  239
  240/* Under UNIX, the "halt." command quits Prolog but does not
  241   remove the output window. On a PC, however, the window
  242   disappears before the final output can be seen. Hence this
  243   routine requests the user to perform the final "halt." */
  244
  245finish :-
  246        nl,
  247        write('The game is over. Please enter the "halt." command.'),
  248        nl.
  249
  250
  251/* This rule just writes out game instructions. */
  252
  253instructions :-
  254        nl,
  255        write('Enter commands using standard Prolog syntax.'), nl,
  256        write('Available commands are:'), nl,
  257        write('start.             -- to start the game.'), nl,
  258        write('n.  s.  e.  w.     -- to go in that direction.'), nl,
  259        write('buy(Object).       -- to purchase an object with your money.'), nl,
  260        write('take(Object).      -- to pick up an object.'), nl,
  261        write('drop(Object).      -- to put down an object.'), nl,
  262        write('i.                 -- to see what you are currently holding.'), nl,
  263        write('wallet.            -- to see how much money you have in your wallet.'), nl,
  264        write('kill.              -- to attack an enemy.'), nl,
  265        write('look.              -- to look around you again.'), nl,
  266        write('instructions.      -- to see this message again.'), nl,
  267        write('halt.              -- to end the game and quit.'), nl,
  268        nl.
  269
  270
  271/* This rule prints out instructions and tells where you are. */
  272
  273start :-
  274        instructions,
  275        look.
  276
  277
  278/* These rules describe the various rooms.  Depending on
  279   circumstances, a room may have more than one description. */
  280
  281describe(home) :-
  282        write('You are now comfortably in your home. To the north'), nl,
  283        write('is a little closet that you have not opened for a'), nl,
  284        write('while. To the south is the field that you have plowed.'), nl,
  285        write('To the east is the center of the town that you live in.'), nl,
  286        write('The town you live in is terrorized by a new dragon that'), nl,
  287        write('has arrived on the scene, killed the king, and took'), nl,
  288        write('the royal crown to the mountain. You, as the best'), nl,
  289        write('warrior in town, wants to kill the dragon and be hailed'), nl,
  290        write('as the hero of all time.'), nl.
  291
  292describe(field) :-
  293        write('You are in the field of corn that you have planted.'), nl,
  294        write('To the north is your own home.'), nl.
  295
  296describe(closet) :-
  297	money(X),
  298	Y is 1000 + X,
  299        retract(money(X)),
  300        assert(money(Y)),
  301        write('Turns out you hid all your savings in your closet! You'), nl,
  302        write('have found 1000 gold coins!'), nl.
  303
  304describe(town) :-
  305        holding(crown),
  306        write('Congratulations! You have successfully returned the crown'), nl,
  307        write('back to the town and killed the dragon. You will be hailed'), nl,
  308        write('as the greatest hero!'), nl,
  309        write('You have won the game!'), nl,
  310        finish, !.
  311
  312describe(town) :-
  313        write('You are now at the town center. To the north of you is the'), nl,
  314        write('town''s only shop. To the south of you is a wild forrest.'), nl,
  315        write('To the east of you is the tall mountain where the dragon is.'), nl,
  316        write('To the west of you is your own home. Rumor is spread here'), nl,
  317        write('that you need a magical sword to successfully slay the dragon'), nl,
  318        write('and also that there is a magical unicorn south of the forrest'), nl,
  319        write('that can help enchant any weapon.'), nl.
  320
  321describe(shop) :-
  322        write('You are now in a little shop. To the south of you is the'), nl,
  323        write('town center.'), nl.
  324
  325describe(forrest) :-
  326        write('This is a magical forrest. To the south is a glowing unicorn.'), nl,
  327        write('To the north is the town center.'), nl.
  328
  329describe(unicorn) :-
  330        holding(translator),
  331        holding(sword),
  332        retract(holding(sword)),
  333        assert(holding(magic_sword)),
  334        write('With the magical translator the unicorn understood your need'), nl,
  335        write('and enchanted your sword with magic! Go north to return to the'), nl,
  336        write('forrest.'), nl, !.
  337
  338describe(unicorn) :-
  339        holding(translator),
  340        write('With the magical translator the unicorn understood your need.'), nl,
  341        write('Please get a weapon so he can enchant it. Go north to return to'), nl,
  342        write('the forrest.'), nl, !.
  343
  344describe(unicorn) :-
  345        write('You cannot communicate with the unicorn! Maybe the translator at'), nl,
  346        write('the shop will help... Go north to return to the forrest.'), nl.
  347
  348describe(mountain) :-
  349        alive(dragon),
  350        write('You are standing now on top of a windy and dark mountain. To the'), nl,
  351        write('west is the path down to the town. To your east sleeps a giant'), nl,
  352        write('dragon.'), nl, !.
  353
  354describe(mountain) :-
  355        write('You are standing now on top of a windy and dark mountain. To the'), nl,
  356        write('west is the path down to the town. To your east is a dead body of'), nl,
  357        write('a giant dragon.'), nl.
  358
  359describe(dragon) :-
  360        alive(dragon),
  361        write('You are face to face with a sleeping dragon... it is the largest'), nl,
  362        write('creature you have ever seen. To escape to the mountain peak, go west.'), nl, !.
  363
  364describe(dragon) :-
  365        write('You are standing on top of a dead dragon. Its body heat is still'), nl,
  366        write('rising into the air. Go west to go back to the mountain peak.'), nl