home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / games / tinymud2.zip / MOVE.C < prev    next >
C/C++ Source or Header  |  1990-09-02  |  9KB  |  332 lines

  1. #include "copyright.h"
  2.  
  3. #include "db.h"
  4. #include "config.h"
  5. #include "interface.h"
  6. #include "match.h"
  7. #include "externs.h"
  8.  
  9. void moveto(dbref what, dbref where)
  10. {
  11.     dbref loc;
  12.  
  13.     /* remove what from old loc */
  14.     if((loc = db[what].location) != NOTHING) {
  15.     db[loc].contents = remove_first(db[loc].contents, what);
  16.     }
  17.  
  18.     /* test for special cases */
  19.     switch(where) {
  20.       case NOTHING:
  21.     db[what].location = NOTHING;
  22.     return;            /* NOTHING doesn't have contents */
  23.       case HOME:
  24.     where = db[what].exits;    /* home */
  25.     break;
  26.     }
  27.  
  28.     /* now put what in where */
  29.     PUSH(what, db[where].contents);
  30.  
  31.     db[what].location = where;
  32. }
  33.  
  34. static void send_contents(dbref loc, dbref dest)
  35. {
  36.     dbref first;
  37.     dbref rest;
  38.  
  39.     first = db[loc].contents;
  40.     db[loc].contents = NOTHING;
  41.  
  42.     /* blast locations of everything in list */
  43.     DOLIST(rest, first) {
  44.     db[rest].location = NOTHING;
  45.     }
  46.  
  47.     while(first != NOTHING) {
  48.     rest = db[first].next;
  49.     if(Typeof(first) != TYPE_THING) {
  50.         moveto(first, loc);
  51.     } else {
  52.         moveto(first, (db[first].flags & STICKY) ? HOME : dest);
  53.     }
  54.     first = rest;
  55.     }
  56.  
  57.     db[loc].contents = reverse(db[loc].contents);
  58. }
  59.  
  60. void maybe_dropto(dbref loc, dbref dropto)
  61. {
  62.     dbref thing;
  63.  
  64.     if(loc == dropto) return;    /* bizarre special case */
  65.  
  66.     /* check for players */
  67.     DOLIST(thing, db[loc].contents) {
  68.     if(Typeof(thing) == TYPE_PLAYER) return;
  69.     }
  70.     
  71.     /* no players, send everything to the dropto */
  72.     send_contents(loc, dropto);
  73. }
  74.  
  75. void enter_room(dbref player, dbref loc)
  76. {
  77.     dbref old;
  78.     dbref dropto;
  79.     char buf[BUFFER_LEN];
  80.  
  81.     /* check for room == HOME */
  82.     if(loc == HOME) loc = db[player].exits; /* home */
  83.  
  84.     /* get old location */
  85.     old = db[player].location;
  86.  
  87.     /* check for self-loop */
  88.     /* self-loops don't do move or other player notification */
  89.     /* but you still get autolook and penny check */
  90.     if(loc != old) {
  91.  
  92.     if(old != NOTHING) {
  93.         /* notify others unless DARK */
  94.         if(!Dark(old) && !Dark(player)) {
  95.         sprintf(buf, "%s has left.", db[player].name);
  96.         notify_except(db[old].contents, player, buf);
  97.         }
  98.     }
  99.  
  100.     /* go there */
  101.     moveto(player, loc);
  102.  
  103.     /* if old location has STICKY dropto, send stuff through it */
  104.     if(old != NOTHING
  105.        && (dropto = db[old].location) != NOTHING
  106.        && (db[old].flags & STICKY)) {
  107.         maybe_dropto(old, dropto);
  108.     }
  109.  
  110.     /* tell other folks in new location if not DARK */
  111.     if(!Dark(loc) && !Dark(player)) {
  112.         sprintf(buf, "%s has arrived.", db[player].name);
  113.         notify_except(db[loc].contents, player, buf);
  114.     }
  115.     }
  116.  
  117.     /* autolook */
  118.     look_room(player, loc);
  119.  
  120.     /* check for pennies */
  121.     if(!controls(player, loc)
  122.        && db[player].pennies <= MAX_PENNIES
  123.        && random() % PENNY_RATE == 0) {
  124.     notify(player, "You found a penny!");
  125.     db[player].pennies++;
  126.     }
  127. }
  128.         
  129. void send_home(dbref thing)
  130. {
  131.     switch(Typeof(thing)) {
  132.       case TYPE_PLAYER:
  133.     /* send his possessions home first! */
  134.     /* that way he sees them when he arrives */
  135.     send_contents(thing, HOME);
  136.     enter_room(thing, db[thing].exits); /* home */
  137.     break;
  138.       case TYPE_THING:
  139.     moveto(thing, db[thing].exits);    /* home */
  140.     break;
  141.       default:
  142.     /* no effect */
  143.     break;
  144.     }
  145. }
  146.     
  147. int can_move(dbref player, const char *direction)
  148. {
  149.     if(!string_compare(direction, "home")) return 1;
  150.  
  151.     /* otherwise match on exits */
  152.     init_match(player, direction, TYPE_EXIT);
  153.     match_exit();
  154.     return(last_match_result() != NOTHING);
  155. }
  156.  
  157. void do_move(dbref player, const char *direction)
  158. {
  159.     dbref exit;
  160.     dbref loc;
  161.     char buf[BUFFER_LEN];
  162.  
  163.     if(!string_compare(direction, "home")) {
  164.     /* send him home */
  165.     /* but steal all his possessions */
  166.     if((loc = db[player].location) != NOTHING) {
  167.         /* tell everybody else */
  168.         sprintf(buf, "%s goes home.", db[player].name);
  169.         notify_except(db[loc].contents, player, buf);
  170.     }
  171.     /* give the player the messages */
  172.     notify(player, "There's no place like home...");
  173.     notify(player, "There's no place like home...");
  174.     notify(player, "There's no place like home...");
  175.     notify(player, "You wake up back home, without your possessions.");
  176.     send_home(player);
  177.     } else {
  178.     /* find the exit */
  179.     init_match_check_keys(player, direction, TYPE_EXIT);
  180.     match_exit();
  181.     switch(exit = match_result()) {
  182.       case NOTHING:
  183.         notify(player, "You can't go that way.");
  184.         break;
  185.       case AMBIGUOUS:
  186.         notify(player, "I don't know which way you mean!");
  187.         break;
  188.       default:
  189.         /* we got one */
  190.         /* check to see if we got through */
  191.         if(can_doit(player, exit, "You can't go that way.")) {
  192.         enter_room(player, db[exit].location);
  193.         }
  194.         break;
  195.     }
  196.     }
  197. }
  198.  
  199. void do_get(dbref player, const char *what)
  200. {
  201.     dbref loc;
  202.     dbref thing;
  203.  
  204.     init_match_check_keys(player, what, TYPE_THING);
  205.     match_neighbor();
  206.     match_exit();
  207.     if(Wizard(player)) match_absolute(); /* the wizard has long fingers */
  208.  
  209.     if((thing = noisy_match_result()) != NOTHING) {
  210.     if(db[thing].location == player) {
  211.         notify(player, "You already have that!");
  212.         return;
  213.     }
  214.     switch(Typeof(thing)) {
  215.       case TYPE_THING:
  216.         if(can_doit(player, thing, "You can't pick that up.")) {
  217.         moveto(thing, player);
  218.         notify(player, "Taken.");
  219.         }
  220.         break;
  221.       case TYPE_EXIT:
  222.         if(!controls(player, thing)) {
  223.         notify(player, "You can't pick that up.");
  224.         } else if(db[thing].location != NOTHING) {
  225.         notify(player, "You can't pick up a linked exit.");
  226. #ifdef RESTRICTED_BUILDING
  227.         } else if(!Builder(player)) {
  228.         notify(player, "Only authorized builders may pick up exits.");
  229. #endif /* RESTRICTED_BUILDING */
  230.         } else {
  231.         /* take it out of location */
  232.         if((loc = getloc(player)) == NOTHING) return;
  233.         if(!member(thing, db[loc].exits)) {
  234.             notify(player,
  235.                "You can't pick up an exit from another room.");
  236.             return;
  237.         }
  238.         db[loc].exits = remove_first(db[loc].exits, thing);
  239.         PUSH(thing, db[player].contents);
  240.         db[thing].location = player;
  241.         notify(player, "Exit taken.");
  242.         }
  243.         break;
  244.       default:
  245.         notify(player, "You can't take that!");
  246.         break;
  247.     }
  248.     }
  249. }
  250.  
  251. void do_drop(dbref player, const char *name)
  252. {
  253.     dbref loc;
  254.     dbref thing;
  255.     char buf[BUFFER_LEN];
  256.     int reward;
  257.  
  258.     if((loc = getloc(player)) == NOTHING) return;    
  259.  
  260.     init_match(player, name, TYPE_THING);
  261.     match_possession();
  262.  
  263.     switch(thing = match_result()) {
  264.       case NOTHING:
  265.     notify(player, "You don't have that!");
  266.     break;
  267.       case AMBIGUOUS:
  268.     notify(player, "I don't know which you mean!");
  269.     break;
  270.       default:
  271.     if(db[thing].location != player &&
  272.        !(Typeof(thing) == TYPE_EXIT) && db[thing].location == NOTHING) {
  273.         /* Should not ever happen. */
  274.         notify(player, "You can't drop that.");
  275.     } else if(Typeof(thing) == TYPE_EXIT) {
  276.         /* special behavior for exits */
  277.         if(!controls(player, loc)) {
  278.         notify(player, "You can't put an exit down here.");
  279.         return;
  280.         }
  281.         /* else we can put it down */
  282.         moveto(thing, NOTHING); /* take it out of the pack */
  283.         PUSH(thing, db[loc].exits);
  284.         notify(player, "Exit dropped.");
  285.     } else if(db[loc].flags & TEMPLE) {
  286.         /* sacrifice time */
  287.         send_home(thing);
  288.         sprintf(buf,
  289.             "%s is consumed in a burst of flame!", db[thing].name);
  290.         notify(player, buf);
  291. #ifndef TINKER
  292.         sprintf(buf, "%s sacrifices %s.", db[player].name, db[thing].name);
  293. #else   TINKER
  294.         sprintf(buf, "%s donates %s.", db[player].name, db[thing].name);
  295. #endif  TINKER
  296.         notify_except(db[loc].contents, player, buf);
  297.  
  298.         /* check for reward */
  299.         if(!controls(player, thing)) {
  300.         reward = db[thing].pennies;
  301.         if(reward < 1 || db[player].pennies > MAX_PENNIES) {
  302.             reward = 1;
  303.         } else if(reward > MAX_OBJECT_ENDOWMENT) {
  304.             reward = MAX_OBJECT_ENDOWMENT;
  305.         }
  306.  
  307.         db[player].pennies += reward;
  308.         sprintf(buf,
  309.             "You have received %d %s for your donation.",
  310.             reward,
  311.             reward == 1 ? "penny" : "pennies");
  312.         notify(player, buf);
  313.         }
  314.     } else if(db[thing].flags & STICKY) {
  315.         send_home(thing);
  316.         notify(player, "Dropped.");
  317.     } else if(db[loc].location != NOTHING && !(db[loc].flags & STICKY)) {
  318.         /* location has immediate dropto */
  319.         moveto(thing, db[loc].location);
  320.         notify(player, "Dropped.");
  321.     } else if((db[thing].flags & DARK) && !can_link_to(player,Typeof(thing),loc)) {
  322.         notify(player, "You cannot drop that DARK object here.");
  323.     } else {
  324.         moveto(thing, loc);
  325.         notify(player, "Dropped.");
  326.         sprintf(buf, "%s dropped %s.", db[player].name, db[thing].name);
  327.         notify_except(db[loc].contents, player, buf);
  328.     }
  329.     break;
  330.     }
  331. }
  332.