src/predicates.c

Go to the documentation of this file.
00001 #include "copyright.h"
00002 #include "config.h"
00003 
00004 #include <signal.h>
00005 #include "mudconf.h"
00006 #include "config.h"
00007 #include "db.h"
00008 #include "interface.h"
00009 #include "externs.h"
00010 #include "match.h"
00011 #include "command.h"
00012 #include "alloc.h"
00013 #include "attrs.h"
00014 #include "powers.h"
00015 #include "ansi.h"
00016 #include "patchlevel.h"
00017 #include "htab.h"
00018 
00019 extern dbref match_thing(dbref, char *);
00020 extern int do_command(DESC *, char *);
00021 extern void dump_database(void);
00022 extern void dump_restart_db(void);
00023 
00024 #ifdef NEED_VSPRINTF_DCL
00025 extern char *vsprintf(char *, char *, va_list);
00026 
00027 #endif
00028 
00029 #ifdef STDC_HEADERS
00030 char *tprintf(const char *format, ...)
00031 #else
00032 char *tprintf(va_alist)
00033          va_dcl
00034 #endif
00035 {
00036         static char buff[LBUF_SIZE];
00037         va_list ap;
00038 
00039 #ifdef STDC_HEADERS
00040         va_start(ap, format);
00041 #else
00042         const char *format;
00043 
00044         va_start(ap);
00045         format = va_arg(ap, char *);
00046 
00047 #endif
00048         vsnprintf(buff, LBUF_SIZE, format, ap);
00049         va_end(ap);
00050         buff[LBUF_SIZE - 1] = '\0';
00051         return buff;
00052 }
00053 
00054 #ifdef STDC_HEADERS
00055 void safe_tprintf_str(char *str, char **bp, const char *format, ...)
00056 #else
00057 void safe_tprintf_str(va_alist)
00058          va_dcl
00059 #endif
00060 {
00061         static char buff[LBUF_SIZE];
00062         va_list ap;
00063 
00064 #ifdef STDC_HEADERS
00065         va_start(ap, format);
00066 #else
00067         char *str;
00068         char **bp;
00069         const char *format;
00070 
00071         va_start(ap);
00072         str = va_arg(ap, char *);
00073         bp = va_arg(ap, char **);
00074         format = va_arg(ap, char *);
00075 
00076 #endif
00077         /*
00078          * Sigh, don't we wish _all_ vsprintf's returned int... 
00079          */
00080 
00081         vsnprintf(buff, LBUF_SIZE, format, ap);
00082         va_end(ap);
00083         buff[LBUF_SIZE - 1] = '\0';
00084         safe_str(buff, str, bp);
00085         **bp = '\0';
00086 }
00087 
00091 dbref insert_first(dbref head, dbref thing)
00092 {
00093         s_Next(thing, head);
00094         return thing;
00095 }
00096 
00097 /*
00098  * Removes first object from a list
00099  */
00100 dbref remove_first(dbref head, dbref thing)
00101 {
00102         dbref prev;
00103 
00104         if(head == thing)
00105                 return (Next(thing));
00106 
00107         DOLIST(prev, head) {
00108                 if(Next(prev) == thing) {
00109                         s_Next(prev, Next(thing));
00110                         return head;
00111                 }
00112         }
00113         return head;
00114 }
00115 
00119 dbref reverse_list(dbref list)
00120 {
00121         dbref newlist, rest;
00122 
00123         newlist = NOTHING;
00124         while (list != NOTHING) {
00125                 rest = Next(list);
00126                 s_Next(list, newlist);
00127                 newlist = list;
00128                 list = rest;
00129         }
00130         return newlist;
00131 }
00132 
00136 int member(dbref thing, dbref list)
00137 {
00138         DOLIST(list, list) {
00139                 if(list == thing)
00140                         return 1;
00141         }
00142         return 0;
00143 }
00144 
00148 int is_integer(char *str)
00149 {
00150         while (*str && isspace(*str))
00151                 str++;                                  /*
00152                                                                  * Leading spaces 
00153                                                                  */
00154         if(*str == '-') {                       /*
00155                                                                  * Leading minus 
00156                                                                  */
00157                 str++;
00158                 if(!*str)
00159                         return 0;                       /*
00160                                                                  * but not if just a minus 
00161                                                                  */
00162         }
00163         if(!isdigit(*str))                      /*
00164                                                                  * Need at least 1 integer 
00165                                                                  */
00166                 return 0;
00167         while (*str && isdigit(*str))
00168                 str++;                                  /*
00169                                                                  * The number (int) 
00170                                                                  */
00171         while (*str && isspace(*str))
00172                 str++;                                  /*
00173                                                                  * Trailing spaces 
00174                                                                  */
00175         return (*str ? 0 : 1);
00176 }
00177 
00181 int is_number(char *str)
00182 {
00183         int got_one;
00184 
00185         while (*str && isspace(*str))
00186                 str++;                                  /*
00187                                                                  * Leading spaces 
00188                                                                  */
00189         if(*str == '-') {                       /*
00190                                                                  * Leading minus 
00191                                                                  */
00192                 str++;
00193                 if(!*str)
00194                         return 0;                       /*
00195                                                                  * but not if just a minus 
00196                                                                  */
00197         }
00198         got_one = 0;
00199         if(isdigit(*str))
00200                 got_one = 1;                    /*
00201                                                                  * Need at least one digit 
00202                                                                  */
00203         while (*str && isdigit(*str))
00204                 str++;                                  /*
00205                                                                  * The number (int) 
00206                                                                  */
00207         if(*str == '.')
00208                 str++;                                  /*
00209                                                                  * decimal point 
00210                                                                  */
00211         if(isdigit(*str))
00212                 got_one = 1;                    /*
00213                                                                  * Need at least one digit 
00214                                                                  */
00215         while (*str && isdigit(*str))
00216                 str++;                                  /*
00217                                                                  * The number (fract) 
00218                                                                  */
00219         while (*str && isspace(*str))
00220                 str++;                                  /*
00221                                                                  * Trailing spaces 
00222                                                                  */
00223         return ((*str || !got_one) ? 0 : 1);
00224 }
00225 
00226 int could_doit(dbref player, dbref thing, int locknum)
00227 {
00228         char *key;
00229         dbref aowner;
00230         int aflags, doit;
00231 
00232         /*
00233          * no if nonplayer trys to get key 
00234          */
00235 
00236         if(!isPlayer(player) && Key(thing)) {
00237                 return 0;
00238         }
00239         if(Pass_Locks(player))
00240                 return 1;
00241 
00242         key = atr_get(thing, locknum, &aowner, &aflags);
00243         doit = eval_boolexp_atr(player, thing, thing, key);
00244         free_lbuf(key);
00245         return doit;
00246 }
00247 
00248 int can_see(dbref player, dbref thing, int can_see_loc)
00249 {
00250         /*
00251          * Don't show if all the following apply: * Sleeping players should * 
00252          * 
00253          * *  * * not be seen. * The thing is a disconnected player. * The
00254          * player * is  *  * * not a puppet. 
00255          */
00256 
00257         if(mudconf.dark_sleepers && isPlayer(thing) && !Connected(thing) &&
00258            !Puppet(thing)) {
00259                 return 0;
00260         }
00261         /*
00262          * You don't see yourself or exits 
00263          */
00264 
00265         if((player == thing) || isExit(thing)) {
00266                 return 0;
00267         }
00268         /*
00269          * If loc is not dark, you see it if it's not dark or you control it.
00270          * * * * * If loc is dark, you see it if you control it.  Seeing your
00271          * * own * * * dark objects is controlled by mudconf.see_own_dark. *
00272          * In * dark *  * locations, you also see things that are LIGHT and
00273          * !DARK. 
00274          */
00275 
00276         if(can_see_loc) {
00277                 return (!Dark(thing) || (mudconf.see_own_dark &&
00278                                                                  MyopicExam(player, thing)));
00279         } else {
00280                 return ((Light(thing) && !Dark(thing)) || (mudconf.see_own_dark &&
00281                                                                                                    MyopicExam(player,
00282                                                                                                                           thing)));
00283         }
00284 }
00285 
00286 static int pay_quota(dbref who, int cost)
00287 {
00288         dbref aowner;
00289         int quota, aflags;
00290         char buf[20], *quota_str;
00291 
00292         /*
00293          * If no cost, succeed 
00294          */
00295 
00296         if(cost <= 0)
00297                 return 1;
00298 
00299         /*
00300          * determine quota 
00301          */
00302 
00303         quota = atoi(quota_str = atr_get(Owner(who), A_RQUOTA, &aowner, &aflags));
00304         free_lbuf(quota_str);
00305 
00306         /*
00307          * enough to build?  Wizards always have enough. 
00308          */
00309 
00310         quota -= cost;
00311         if((quota < 0) && !Free_Quota(who) && !Free_Quota(Owner(who)))
00312                 return 0;
00313 
00314         /*
00315          * dock the quota 
00316          */
00317         sprintf(buf, "%d", quota);
00318         atr_add_raw(Owner(who), A_RQUOTA, buf);
00319 
00320         return 1;
00321 }
00322 
00323 int canpayfees(dbref player, dbref who, int pennies, int quota)
00324 {
00325         if(!Wizard(who) && !Wizard(Owner(who)) && !Free_Money(who) &&
00326            !Free_Money(Owner(who)) && (Pennies(Owner(who)) < pennies)) {
00327                 if(player == who) {
00328                         notify_printf(player, "Sorry, you don't have enough %s.",
00329                                                   mudconf.many_coins);
00330                 } else {
00331                         notify_printf(player,
00332                                                   "Sorry, that player doesn't have enough %s.",
00333                                                   mudconf.many_coins);
00334                 }
00335                 return 0;
00336         }
00337         if(mudconf.quotas) {
00338                 if(!pay_quota(who, quota)) {
00339                         if(player == who) {
00340                                 notify(player, "Sorry, your building contract has run out.");
00341                         } else {
00342                                 notify(player,
00343                                            "Sorry, that player's building contract has run out.");
00344                         }
00345                         return 0;
00346                 }
00347         }
00348         payfor(who, pennies);
00349         return 1;
00350 }
00351 
00352 int payfor(dbref who, int cost)
00353 {
00354         dbref tmp;
00355 
00356         if(Wizard(who) || Wizard(Owner(who)) || Free_Money(who) ||
00357            Free_Money(Owner(who)) || Immortal(who) || Immortal(Owner(who))) {
00358                 return 1;
00359         }
00360         who = Owner(who);
00361         if((tmp = Pennies(who)) >= cost) {
00362                 s_Pennies(who, tmp - cost);
00363                 return 1;
00364         }
00365         return 0;
00366 }
00367 
00368 void add_quota(dbref who, int payment)
00369 {
00370         dbref aowner;
00371         int aflags;
00372         char buf[20], *quota;
00373 
00374         quota = atr_get(who, A_RQUOTA, &aowner, &aflags);
00375         sprintf(buf, "%d", atoi(quota) + payment);
00376         free_lbuf(quota);
00377         atr_add_raw(who, A_RQUOTA, buf);
00378 }
00379 
00383 void giveto(dbref who, int pennies)
00384 {
00385         if(Wizard(who) || Wizard(Owner(who)) || Free_Money(who) ||
00386            Free_Money(Owner(who)) || Immortal(who) || Immortal(Owner(who))) {
00387                 return;
00388         }
00389         who = Owner(who);
00390         s_Pennies(who, Pennies(who) + pennies);
00391 }
00392 
00393 int ok_name(const char *name)
00394 {
00395         const char *cp;
00396         char new[LBUF_SIZE];
00397 
00398         /* Disallow pure ANSI names */
00399         strncpy(new, name, LBUF_SIZE-1);
00400         if(strlen(strip_ansi_r(new,name,strlen(name))) == 0)
00401                 return 0;
00402 
00403         /* Disallow leading spaces */
00404 
00405         if(isspace(*name))
00406                 return 0;
00407 
00408         /*
00409          * Only printable characters 
00410          */
00411 
00412         for(cp = name; cp && *cp; cp++) {
00413                 if((!isprint(*cp)) && (*cp != ESC_CHAR))
00414                         return 0;
00415         }
00416 
00417         /*
00418          * Disallow trailing spaces 
00419          */
00420         cp--;
00421         if(isspace(*cp))
00422                 return 0;
00423 
00424         /*
00425          * Exclude names that start with or contain certain magic cookies 
00426          */
00427 
00428         return (name && *name && *name != LOOKUP_TOKEN && *name != NUMBER_TOKEN
00429                         && *name != NOT_TOKEN && !index(name, ARG_DELIMITER) &&
00430                         !index(name, AND_TOKEN) && !index(name, OR_TOKEN) &&
00431                         string_compare(name, "me") && string_compare(name, "home") &&
00432                         string_compare(name, "here"));
00433 }
00434 
00435 int ok_player_name(const char *name)
00436 {
00437         const char *cp, *good_chars;
00438 
00439         /*
00440          * No leading spaces 
00441          */
00442 
00443         if(isspace(*name))
00444                 return 0;
00445 
00446         /*
00447          * Not too long and a good name for a thing 
00448          */
00449 
00450         if(!ok_name(name) || (strlen(name) >= PLAYER_NAME_LIMIT))
00451                 return 0;
00452 
00453         if(mudconf.name_spaces)
00454                 good_chars = " `$_-.,'";
00455         else
00456                 good_chars = "`$_-.,'";
00457 
00458         /*
00459          * Make sure name only contains legal characters 
00460          */
00461 
00462         for(cp = name; cp && *cp; cp++) {
00463                 if(isalnum(*cp))
00464                         continue;
00465                 if((!index(good_chars, *cp)) || (*cp == ESC_CHAR))
00466                         return 0;
00467         }
00468         return 1;
00469 }
00470 
00471 int ok_attr_name(const char *attrname)
00472 {
00473         const char *scan;
00474 
00475         if(!isalpha(*attrname))
00476                 return 0;
00477         for(scan = attrname; *scan; scan++) {
00478                 if(isalnum(*scan))
00479                         continue;
00480                 if(!(index("'?!`/-_.@#$^&~=+<>()%", *scan)))
00481                         return 0;
00482         }
00483         return 1;
00484 }
00485 
00486 int ok_password(const char *password)
00487 {
00488         const char *scan;
00489 
00490         if(*password == '\0')
00491                 return 0;
00492 
00493         for(scan = password; *scan; scan++) {
00494                 if(!(isprint(*scan) && !isspace(*scan))) {
00495                         return 0;
00496                 }
00497         }
00498 
00499         /*
00500          * Needed.  Change it if you like, but be sure yours is the same. 
00501          */
00502         if((strlen(password) == 13) && (password[0] == 'X') &&
00503            (password[1] == 'X'))
00504                 return 0;
00505 
00506         return 1;
00507 }
00508 
00512 void handle_ears(dbref thing, int could_hear, int can_hear)
00513 {
00514         char *buff, *bp;
00515         int gender;
00516         static const char *poss[5] = { "", "its", "her", "his", "their" };
00517 
00518         if(!could_hear && can_hear) {
00519                 buff = alloc_lbuf("handle_ears.grow");
00520                 StringCopy(buff, Name(thing));
00521                 if(isExit(thing)) {
00522                         for(bp = buff; *bp && (*bp != ';'); bp++);
00523                         *bp = '\0';
00524                 }
00525                 gender = get_gender(thing);
00526                 notify_checked(thing, thing,
00527                                            tprintf("%s grow%s ears and can now hear.", buff,
00528                                                            (gender == 4) ? "" : "s"),
00529                                            (MSG_ME | MSG_NBR | MSG_LOC | MSG_INV));
00530                 free_lbuf(buff);
00531         } else if(could_hear && !can_hear) {
00532                 buff = alloc_lbuf("handle_ears.lose");
00533                 StringCopy(buff, Name(thing));
00534                 if(isExit(thing)) {
00535                         for(bp = buff; *bp && (*bp != ';'); bp++);
00536                         *bp = '\0';
00537                 }
00538                 gender = get_gender(thing);
00539                 notify_checked(thing, thing,
00540                                            tprintf("%s lose%s %s ears and become%s deaf.", buff,
00541                                                            (gender == 4) ? "" : "s", poss[gender],
00542                                                            (gender == 4) ? "" : "s"),
00543                                            (MSG_ME | MSG_NBR | MSG_LOC | MSG_INV));
00544                 free_lbuf(buff);
00545         }
00546 }
00547 
00548 /*
00549  * for lack of better place the @switch code is here 
00550  */
00551 void do_switch(dbref player, dbref cause, int key, char *expr, char *args[],
00552                            int nargs, char *cargs[], int ncargs)
00553 {
00554         int a, any;
00555         char *buff, *bp, *str;
00556 
00557         if(!expr || (nargs <= 0))
00558                 return;
00559 
00560         if(key == SWITCH_DEFAULT) {
00561                 if(mudconf.switch_df_all)
00562                         key = SWITCH_ANY;
00563                 else
00564                         key = SWITCH_ONE;
00565         }
00566         /*
00567          * now try a wild card match of buff with stuff in coms 
00568          */
00569 
00570         any = 0;
00571         buff = bp = alloc_lbuf("do_switch");
00572         for(a = 0; (a < (nargs - 1)) && args[a] && args[a + 1]; a += 2) {
00573                 bp = buff;
00574                 str = args[a];
00575                 exec(buff, &bp, 0, player, cause, EV_FCHECK | EV_EVAL | EV_TOP,
00576                          &str, cargs, ncargs);
00577                 *bp = '\0';
00578                 if(wild_match(buff, expr)) {
00579                         wait_que(player, cause, 0, NOTHING, 0, args[a + 1], cargs,
00580                                          ncargs, mudstate.global_regs);
00581                         if(key == SWITCH_ONE) {
00582                                 free_lbuf(buff);
00583                                 return;
00584                         }
00585                         any = 1;
00586                 }
00587         }
00588         free_lbuf(buff);
00589         if((a < nargs) && !any && args[a])
00590                 wait_que(player, cause, 0, NOTHING, 0, args[a], cargs, ncargs,
00591                                  mudstate.global_regs);
00592 }
00593 
00594 void do_addcommand(dbref player, dbref cause, int key, char *name,
00595                                    char *command)
00596 {
00597         CMDENT *old, *cmd;
00598         ADDENT *add, *nextp;
00599 
00600         dbref thing;
00601         int atr;
00602         char *s;
00603 
00604         if(!*name) {
00605                 notify(player, "Sorry.");
00606                 return;
00607         }
00608         if(!parse_attrib(player, command, &thing, &atr) || (atr == NOTHING)) {
00609                 notify(player, "No such attribute.");
00610                 return;
00611         }
00612 
00613         /* Let's make this case insensitive... */
00614 
00615         for(s = name; *s; s++) {
00616                 *s = tolower(*s);
00617         }
00618 
00619         old = (CMDENT *) hashfind(name, &mudstate.command_htab);
00620 
00621         if(old && (old->callseq & CS_ADDED)) {
00622 
00623                 /* If it's already found in the hash table, and it's being
00624                    added using the same object and attribute... */
00625 
00626                 for(nextp = (ADDENT *) old->handler; nextp != NULL;
00627                         nextp = nextp->next) {
00628                         if((nextp->thing == thing) && (nextp->atr == atr)) {
00629                                 notify_printf(player, "%s already added.", name);
00630                                 return;
00631                         }
00632                 }
00633 
00634                 /* else tack it on to the existing entry... */
00635 
00636                 add = (ADDENT *) malloc(sizeof(ADDENT));
00637                 add->thing = thing;
00638                 add->atr = atr;
00639                 add->name = (char *) strdup(name);
00640                 add->next = (ADDENT *) old->handler;
00641                 old->handler = (void *) add;
00642         } else {
00643                 if(old) {
00644                         /* Delete the old built-in and rename it __name */
00645                         hashdelete(name, &mudstate.command_htab);
00646                 }
00647 
00648                 cmd = (CMDENT *) malloc(sizeof(CMDENT));
00649 
00650                 cmd->cmdname = (char *) strdup(name);
00651                 cmd->switches = NULL;
00652                 cmd->perms = 0;
00653                 cmd->extra = 0;
00654                 if(old && (old->callseq & CS_LEADIN)) {
00655                         cmd->callseq = CS_ADDED | CS_ONE_ARG | CS_LEADIN;
00656                 } else {
00657                         cmd->callseq = CS_ADDED | CS_ONE_ARG;
00658                 }
00659                 add = (ADDENT *) malloc(sizeof(ADDENT));
00660                 add->thing = thing;
00661                 add->atr = atr;
00662                 add->name = (char *) strdup(name);
00663                 add->next = NULL;
00664                 cmd->handler = (void *) add;
00665 
00666                 hashadd(name, (int *) cmd, &mudstate.command_htab);
00667 
00668                 if(old) {
00669                         /* Fix any aliases of this command. */
00670                         hashreplall((int *) old, (int *) cmd, &mudstate.command_htab);
00671                         hashadd(tprintf("__%s", name), (int *) old,
00672                                         &mudstate.command_htab);
00673                 }
00674         }
00675 
00676         /* We reset the one letter commands here so you can overload them */
00677 
00678         set_prefix_cmds();
00679         notify_printf(player, "%s added.", name);
00680 }
00681 
00682 void do_listcommands(dbref player, dbref cause, int key, char *name)
00683 {
00684         CMDENT *old;
00685         ADDENT *nextp;
00686         int didit = 0;
00687 
00688         char *s, *keyname;
00689 
00690         /* Let's make this case insensitive... */
00691 
00692         for(s = name; *s; s++) {
00693                 *s = tolower(*s);
00694         }
00695 
00696         if(*name) {
00697                 old = (CMDENT *) hashfind(name, &mudstate.command_htab);
00698 
00699                 if(old && (old->callseq & CS_ADDED)) {
00700 
00701                         /* If it's already found in the hash table, and it's being
00702                            added using the same object and attribute... */
00703 
00704                         for(nextp = (ADDENT *) old->handler; nextp != NULL;
00705                                 nextp = nextp->next) {
00706                                 notify_printf(player, "%s: #%d/%s", nextp->name,
00707                                                           nextp->thing,
00708                                                           ((ATTR *) atr_num(nextp->atr))->name);
00709                         }
00710                 } else {
00711                         notify_printf(player, "%s not found in command table.", name);
00712                 }
00713                 return;
00714         } else {
00715                 for(keyname = hash_firstkey(&mudstate.command_htab);
00716                         keyname != NULL; keyname = hash_nextkey(&mudstate.command_htab)) {
00717 
00718                         old = (CMDENT *) hashfind(keyname, &mudstate.command_htab);
00719 
00720                         if(old && (old->callseq & CS_ADDED)) {
00721 
00722                                 for(nextp = (ADDENT *) old->handler; nextp != NULL;
00723                                         nextp = nextp->next) {
00724                                         if(strcmp(keyname, nextp->name))
00725                                                 continue;
00726                                         notify_printf(player, "%s: #%d/%s", nextp->name,
00727                                                                   nextp->thing,
00728                                                                   ((ATTR *) atr_num(nextp->atr))->name);
00729                                         didit = 1;
00730                                 }
00731                         }
00732                 }
00733         }
00734         if(!didit)
00735                 notify(player, "No added commands found in command table.");
00736 }
00737 
00738 void do_delcommand(dbref player, dbref cause, int key, char *name,
00739                                    char *command)
00740 {
00741         CMDENT *old, *cmd;
00742         ADDENT *prev = NULL, *nextp;
00743 
00744         dbref thing;
00745         int atr;
00746         char *s;
00747 
00748         if(!*name) {
00749                 notify(player, "Sorry.");
00750                 return;
00751         }
00752 
00753         if(*command) {
00754                 if(!parse_attrib(player, command, &thing, &atr) || (atr == NOTHING)) {
00755                         notify(player, "No such attribute.");
00756                         return;
00757                 }
00758         }
00759 
00760         /* Let's make this case insensitive... */
00761 
00762         for(s = name; *s; s++) {
00763                 *s = tolower(*s);
00764         }
00765 
00766         old = (CMDENT *) hashfind(name, &mudstate.command_htab);
00767 
00768         if(old && (old->callseq & CS_ADDED)) {
00769                 if(!*command) {
00770                         for(prev = (ADDENT *) old->handler; prev != NULL; prev = nextp) {
00771                                 nextp = prev->next;
00772                                 /* Delete it! */
00773                                 free(prev->name);
00774                                 free(prev);
00775                         }
00776                         hashdelete(name, &mudstate.command_htab);
00777                         if((cmd =
00778                                 (CMDENT *) hashfind(tprintf("__%s", name),
00779                                                                         &mudstate.command_htab)) != NULL) {
00780                                 hashdelete(tprintf("__%s", name), &mudstate.command_htab);
00781                                 hashadd(name, (int *) cmd, &mudstate.command_htab);
00782                                 hashreplall((int *) old, (int *) cmd, &mudstate.command_htab);
00783                         }
00784                         free(old);
00785                         set_prefix_cmds();
00786                         notify(player, "Done.");
00787                         return;
00788                 } else {
00789                         for(nextp = (ADDENT *) old->handler; nextp != NULL;
00790                                 nextp = nextp->next) {
00791                                 if((nextp->thing == thing) && (nextp->atr == atr)) {
00792                                         /* Delete it! */
00793                                         free(nextp->name);
00794                                         if(!prev) {
00795                                                 if(!nextp->next) {
00796                                                         hashdelete(name, &mudstate.command_htab);
00797                                                         if((cmd =
00798                                                                 (CMDENT *) hashfind(tprintf("__%s",
00799                                                                                                                         name),
00800                                                                                                         &mudstate.
00801                                                                                                         command_htab)) != NULL) {
00802                                                                 hashdelete(tprintf("__%s", name),
00803                                                                                    &mudstate.command_htab);
00804                                                                 hashadd(name, (int *) cmd,
00805                                                                                 &mudstate.command_htab);
00806                                                                 hashreplall((int *) old, (int *) cmd,
00807                                                                                         &mudstate.command_htab);
00808                                                         }
00809                                                         free(old);
00810                                                 } else {
00811                                                         old->handler = (void *) nextp->next;
00812                                                         free(nextp);
00813                                                 }
00814                                         } else {
00815                                                 prev->next = nextp->next;
00816                                                 free(nextp);
00817                                         }
00818                                         set_prefix_cmds();
00819                                         notify(player, "Done.");
00820                                         return;
00821                                 }
00822                                 prev = nextp;
00823                         }
00824                         notify(player, "Command not found in command table.");
00825                 }
00826         } else {
00827                 notify(player, "Command not found in command table.");
00828         }
00829 }
00830 
00837 void handle_prog(DESC * d, char *message)
00838 {
00839         DESC *all;
00840         char *cmd;
00841         dbref aowner;
00842         int aflags, i;
00843 
00844         /*
00845          * Allow the player to pipe a command while in interactive mode. 
00846          */
00847 
00848         if(*message == '|') {
00849                 do_command(d, message + 1);
00850                 /* Use telnet protocol's GOAHEAD command to show prompt */
00851                 if(d->program_data != NULL)
00852                         queue_string(d, tprintf("%s>%s \377\371", ANSI_HILITE,
00853                                                                         ANSI_NORMAL));
00854                 return;
00855         }
00856         cmd = atr_get(d->player, A_PROGCMD, &aowner, &aflags);
00857         wait_que(d->program_data->wait_cause, d->player, 0, NOTHING, 0, cmd,
00858                          (char **) &message, 1, (char **) d->program_data->wait_regs);
00859 
00860         /* First, set 'all' to a descriptor we find for this player */
00861 
00862         //all = (DESC *) nhashfind(d->player, &mudstate.desc_htab);
00863         all = (DESC *) rb_find(mudstate.desctree, (void *) d->player);
00864 
00865         for(i = 0; i < MAX_GLOBAL_REGS; i++) {
00866                 free_lbuf(all->program_data->wait_regs[i]);
00867         }
00868         free(all->program_data);
00869 
00870         /* Set info for all player descriptors to NULL */
00871 
00872         DESC_ITER_PLAYER(d->player, all)
00873                 all->program_data = NULL;
00874 
00875         atr_clr(d->player, A_PROGCMD);
00876         free_lbuf(cmd);
00877 }
00878 
00879 void do_quitprog(dbref player, dbref cause, int key, char *name)
00880 {
00881         DESC *d;
00882         dbref doer;
00883         int i, isprog = 0;
00884 
00885         if(*name) {
00886                 doer = match_thing(player, name);
00887         } else {
00888                 doer = player;
00889         }
00890 
00891         if(!(Prog(player) || Prog(Owner(player))) && (player != doer)) {
00892                 notify(player, "Permission denied.");
00893                 return;
00894         }
00895         if(!isPlayer(doer) || !Good_obj(doer)) {
00896                 notify(player, "That is not a player.");
00897                 return;
00898         }
00899         if(!Connected(doer)) {
00900                 notify(player, "That player is not connected.");
00901                 return;
00902         }
00903         DESC_ITER_PLAYER(doer, d) {
00904                 if(d->program_data != NULL) {
00905                         isprog = 1;
00906                 }
00907         }
00908 
00909         if(!isprog) {
00910                 notify(player, "Player is not in an @program.");
00911                 return;
00912         }
00913 //    d = (DESC *) nhashfind(doer, &mudstate.desc_htab);
00914         d = (DESC *) rb_find(mudstate.desctree, &doer);
00915 
00916         for(i = 0; i < MAX_GLOBAL_REGS; i++) {
00917                 free_lbuf(d->program_data->wait_regs[i]);
00918         }
00919         free(d->program_data);
00920 
00921         /* Set info for all player descriptors to NULL */
00922 
00923         DESC_ITER_PLAYER(doer, d)
00924                 d->program_data = NULL;
00925 
00926         atr_clr(doer, A_PROGCMD);
00927         notify(player, "@program cleared.");
00928         notify(doer, "Your @program has been terminated.");
00929 }
00930 
00931 void do_prog(dbref player, dbref cause, int key, char *name, char *command)
00932 {
00933         DESC *d;
00934         PROG *program;
00935         int i, atr, aflags;
00936         dbref doer, thing, aowner;
00937         ATTR *ap;
00938         char *attrib, *msg;
00939 
00940         if(!name || !*name) {
00941                 notify(player, "No players specified.");
00942                 return;
00943         }
00944         doer = match_thing(player, name);
00945 
00946         if(!(Prog(player) || Prog(Owner(player))) && (player != doer)) {
00947                 notify(player, "Permission denied.");
00948                 return;
00949         }
00950         if(!isPlayer(doer) || !Good_obj(doer)) {
00951                 notify(player, "That is not a player.");
00952                 return;
00953         }
00954         if(!Connected(doer)) {
00955                 notify(player, "That player is not connected.");
00956                 return;
00957         }
00958         msg = command;
00959         attrib = parse_to(&msg, ':', 1);
00960 
00961         if(msg && *msg) {
00962                 notify(doer, msg);
00963         }
00964         parse_attrib(player, attrib, &thing, &atr);
00965         if(atr != NOTHING) {
00966                 if(!atr_get_info(thing, atr, &aowner, &aflags)) {
00967                         notify(player, "Attribute not present on object.");
00968                         return;
00969                 }
00970                 ap = atr_num(atr);
00971                 if(God(player) || (!God(thing) &&
00972                                                    See_attr(player, thing, ap, aowner, aflags) &&
00973                                                    (Wizard(player) || (aowner == Owner(player))))) {
00974                         atr_add_raw(doer, A_PROGCMD, atr_get_raw(thing, atr));
00975                 } else {
00976                         notify(player, "Permission denied.");
00977                         return;
00978                 }
00979         } else {
00980                 notify(player, "No such attribute.");
00981                 return;
00982         }
00983 
00984         /*
00985          * Check to see if the cause already has an @prog input pending 
00986          */
00987         DESC_ITER_PLAYER(doer, d) {
00988                 if(d->program_data != NULL) {
00989                         notify(player, "Input already pending.");
00990                         return;
00991                 }
00992         }
00993 
00994         program = (PROG *) malloc(sizeof(PROG));
00995         program->wait_cause = player;
00996         for(i = 0; i < MAX_GLOBAL_REGS; i++) {
00997                 program->wait_regs[i] = alloc_lbuf("prog_regs");
00998                 StringCopy(program->wait_regs[i], mudstate.global_regs[i]);
00999         }
01000 
01001         /*
01002          * Now, start waiting. 
01003          */
01004         DESC_ITER_PLAYER(doer, d) {
01005                 d->program_data = program;
01006 
01007                 /*
01008                  * Use telnet protocol's GOAHEAD command to show prompt 
01009                  */
01010                 queue_string(d, tprintf("%s>%s \377\371", ANSI_HILITE, ANSI_NORMAL));
01011         }
01012 
01013 }
01014 
01018 void do_restart(dbref player, dbref cause, int key)
01019 {
01020         if(key && mudstate.dumping) {
01021                 notify(player, "Dumping. Please try again later.");
01022                 return;
01023         }
01024 
01025         ResetSpecialObjects();
01026         raw_broadcast(0, "Game: Restart by %s, please wait.",
01027                                   Name(Owner(player)));
01028         shutdown_services();
01029 
01030         STARTLOG(LOG_ALWAYS, "WIZ", "RSTRT") {
01031                 log_text((char *) "Restart by ");
01032                 log_name(player);
01033                 ENDLOG;
01034         } dump_database_internal(DUMP_RESTART);
01035 
01036         dump_restart_db();
01037     dump_restart_db_xdr();
01038         execl(mudstate.executable_path, mudstate.executable_path,
01039                   mudconf.config_file, NULL);
01040 }
01041 
01045 void do_comment(dbref player, dbref cause, int key)
01046 {
01047 }
01048 
01049 static dbref promote_dflt(dbref old, dbref new)
01050 {
01051         switch (new) {
01052         case NOPERM:
01053                 return NOPERM;
01054         case AMBIGUOUS:
01055                 if(old == NOPERM)
01056                         return old;
01057                 else
01058                         return new;
01059         }
01060 
01061         if((old == NOPERM) || (old == AMBIGUOUS))
01062                 return old;
01063 
01064         return NOTHING;
01065 }
01066 
01067 dbref match_possessed(dbref player, dbref thing, char *target, dbref dflt,
01068                                           int check_enter)
01069 {
01070         dbref result, result1;
01071         int control;
01072         char *buff, *start, *place, *s1, *d1, *temp;
01073 
01074         /*
01075          * First, check normally 
01076          */
01077 
01078         if(Good_obj(dflt))
01079                 return dflt;
01080 
01081         /*
01082          * Didn't find it directly.  Recursively do a contents check 
01083          */
01084 
01085         start = target;
01086         while (*target) {
01087 
01088                 /*
01089                  * Fail if no ' characters 
01090                  */
01091 
01092                 place = target;
01093                 target = (char *) index(place, '\'');
01094                 if((target == NULL) || !*target)
01095                         return dflt;
01096 
01097                 /*
01098                  * If string started with a ', skip past it 
01099                  */
01100 
01101                 if(place == target) {
01102                         target++;
01103                         continue;
01104                 }
01105                 /*
01106                  * If next character is not an s or a space, skip past 
01107                  */
01108 
01109                 temp = target++;
01110                 if(!*target)
01111                         return dflt;
01112                 if((*target != 's') && (*target != 'S') && (*target != ' '))
01113                         continue;
01114 
01115                 /*
01116                  * If character was not a space make sure the following * * * 
01117                  * 
01118                  * * character is a space. 
01119                  */
01120 
01121                 if(*target != ' ') {
01122                         target++;
01123                         if(!*target)
01124                                 return dflt;
01125                         if(*target != ' ')
01126                                 continue;
01127                 }
01128                 /*
01129                  * Copy the container name to a new buffer so we can * * * *
01130                  * terminate it. 
01131                  */
01132 
01133                 buff = alloc_lbuf("is_posess");
01134                 for(s1 = start, d1 = buff; *s1 && (s1 < temp); *d1++ = (*s1++));
01135                 *d1 = '\0';
01136 
01137                 /*
01138                  * Look for the container here and in our inventory.  Skip *
01139                  * * * * past if we can't find it. 
01140                  */
01141 
01142                 init_match(thing, buff, NOTYPE);
01143                 if(player == thing) {
01144                         match_neighbor();
01145                         match_possession();
01146                 } else {
01147                         match_possession();
01148                 }
01149                 result1 = match_result();
01150 
01151                 free_lbuf(buff);
01152                 if(!Good_obj(result1)) {
01153                         dflt = promote_dflt(dflt, result1);
01154                         continue;
01155                 }
01156                 /*
01157                  * If we don't control it and it is either dark or opaque, *
01158                  * * * * skip past. 
01159                  */
01160 
01161                 control = Controls(player, result1);
01162                 if((Dark(result1) || Opaque(result1)) && !control) {
01163                         dflt = promote_dflt(dflt, NOTHING);
01164                         continue;
01165                 }
01166                 /*
01167                  * Validate object has the ENTER bit set, if requested 
01168                  */
01169 
01170                 if((check_enter) && !Enter_ok(result1) && !control) {
01171                         dflt = promote_dflt(dflt, NOPERM);
01172                         continue;
01173                 }
01174                 /*
01175                  * Look for the object in the container 
01176                  */
01177 
01178                 init_match(result1, target, NOTYPE);
01179                 match_possession();
01180                 result = match_result();
01181                 result =
01182                         match_possessed(player, result1, target, result, check_enter);
01183                 if(Good_obj(result))
01184                         return result;
01185                 dflt = promote_dflt(dflt, result);
01186         }
01187         return dflt;
01188 }
01189 
01193 void parse_range(char **name, dbref * low_bound, dbref * high_bound)
01194 {
01195         char *buff1, *buff2;
01196 
01197         buff1 = *name;
01198         if(buff1 && *buff1)
01199                 *name = parse_to(&buff1, ',', EV_STRIP_TS);
01200         if(buff1 && *buff1) {
01201                 buff2 = parse_to(&buff1, ',', EV_STRIP_TS);
01202                 if(buff1 && *buff1) {
01203                         while (*buff1 && isspace(*buff1))
01204                                 buff1++;
01205                         if(*buff1 == NUMBER_TOKEN)
01206                                 buff1++;
01207                         *high_bound = atoi(buff1);
01208                         if(*high_bound >= mudstate.db_top)
01209                                 *high_bound = mudstate.db_top - 1;
01210                 } else {
01211                         *high_bound = mudstate.db_top - 1;
01212                 }
01213                 while (*buff2 && isspace(*buff2))
01214                         buff2++;
01215                 if(*buff2 == NUMBER_TOKEN)
01216                         buff2++;
01217                 *low_bound = atoi(buff2);
01218                 if(*low_bound < 0)
01219                         *low_bound = 0;
01220         } else {
01221                 *low_bound = 0;
01222                 *high_bound = mudstate.db_top - 1;
01223         }
01224 }
01225 
01226 int parse_thing_slash(dbref player, char *thing, char **after, dbref * it)
01227 {
01228         char *str;
01229 
01230         /*
01231          * get name up to / 
01232          */
01233         for(str = thing; *str && (*str != '/'); str++);
01234 
01235         /*
01236          * If no / in string, return failure 
01237          */
01238 
01239         if(!*str) {
01240                 *after = NULL;
01241                 *it = NOTHING;
01242                 return 0;
01243         }
01244         *str++ = '\0';
01245         *after = str;
01246 
01247         /*
01248          * Look for the object 
01249          */
01250 
01251         init_match(player, thing, NOTYPE);
01252         match_everything(MAT_EXIT_PARENTS);
01253         *it = match_result();
01254 
01255         /*
01256          * Return status of search 
01257          */
01258 
01259         return (Good_obj(*it));
01260 }
01261 
01262 extern NAMETAB lock_sw[];
01263 
01264 int get_obj_and_lock(dbref player, char *what, dbref * it, ATTR ** attr,
01265                                          char *errmsg, char **bufc)
01266 {
01267         char *str, *tbuf;
01268         int anum;
01269 
01270         tbuf = alloc_lbuf("get_obj_and_lock");
01271         StringCopy(tbuf, what);
01272         if(parse_thing_slash(player, tbuf, &str, it)) {
01273 
01274                 /*
01275                  * <obj>/<lock> syntax, use the named lock 
01276                  */
01277 
01278                 anum = search_nametab(player, lock_sw, str);
01279                 if(anum < 0) {
01280                         free_lbuf(tbuf);
01281                         safe_str("#-1 LOCK NOT FOUND", errmsg, bufc);
01282                         return 0;
01283                 }
01284         } else {
01285 
01286                 /*
01287                  * Not <obj>/<lock>, do a normal get of the default lock 
01288                  */
01289 
01290                 *it = match_thing(player, what);
01291                 if(!Good_obj(*it)) {
01292                         free_lbuf(tbuf);
01293                         safe_str("#-1 NOT FOUND", errmsg, bufc);
01294                         return 0;
01295                 }
01296                 anum = A_LOCK;
01297         }
01298 
01299         /*
01300          * Get the attribute definition, fail if not found 
01301          */
01302 
01303         free_lbuf(tbuf);
01304         *attr = atr_num(anum);
01305         if(!(*attr)) {
01306                 safe_str("#-1 LOCK NOT FOUND", errmsg, bufc);
01307                 return 0;
01308         }
01309         return 1;
01310 }
01311 
01316 dbref where_is(dbref what)
01317 {
01318         dbref loc;
01319 
01320         if(!Good_obj(what))
01321                 return NOTHING;
01322 
01323         switch (Typeof(what)) {
01324         case TYPE_PLAYER:
01325         case TYPE_THING:
01326                 loc = Location(what);
01327                 break;
01328         case TYPE_EXIT:
01329                 loc = Exits(what);
01330                 break;
01331         default:
01332                 loc = NOTHING;
01333                 break;
01334         }
01335         return loc;
01336 }
01337 
01342 dbref where_room(dbref what)
01343 {
01344         int count;
01345 
01346         for(count = mudconf.ntfy_nest_lim; count > 0; count--) {
01347                 if(!Good_obj(what))
01348                         break;
01349                 if(isRoom(what))
01350                         return what;
01351                 if(!Has_location(what))
01352                         break;
01353                 what = Location(what);
01354         }
01355         return NOTHING;
01356 }
01357 
01358 int locatable(dbref player, dbref it, dbref cause)
01359 {
01360         dbref loc_it, room_it;
01361         int findable_room;
01362 
01363         /*
01364          * No sense if trying to locate a bad object 
01365          */
01366 
01367         if(!Good_obj(it))
01368                 return 0;
01369 
01370         loc_it = where_is(it);
01371 
01372         /*
01373          * Succeed if we can examine the target, if we are the target, * if * 
01374          * 
01375          * *  * * we can examine the location, if a wizard caused the lookup, 
01376          * * or  * *  * if the target caused the lookup. 
01377          */
01378 
01379         if(Examinable(player, it) || Find_Unfindable(player) ||
01380            (loc_it == player) || ((loc_it != NOTHING) &&
01381                                                           (Examinable(player, loc_it)
01382                                                            || loc_it == where_is(player)))
01383            || Wizard(cause) || (it == cause))
01384                 return 1;
01385 
01386         room_it = where_room(it);
01387         if(Good_obj(room_it))
01388                 findable_room = !Hideout(room_it);
01389         else
01390                 findable_room = 1;
01391 
01392         /*
01393          * Succeed if we control the containing room or if the target is * *
01394          * * * findable and the containing room is not unfindable. 
01395          */
01396 
01397         if(((room_it != NOTHING) && Examinable(player, room_it)) ||
01398            Find_Unfindable(player) || (Findable(it) && findable_room))
01399                 return 1;
01400 
01401         /*
01402          * We can't do it. 
01403          */
01404 
01405         return 0;
01406 }
01407 
01412 int nearby(dbref player, dbref thing)
01413 {
01414         int thing_loc, player_loc;
01415 
01416         if(!Good_obj(player) || !Good_obj(thing))
01417                 return 0;
01418         thing_loc = where_is(thing);
01419         if(thing_loc == player)
01420                 return 1;
01421         player_loc = where_is(player);
01422         if((thing_loc == player_loc) || (thing == player_loc))
01423                 return 1;
01424         return 0;
01425 }
01426 
01430 int exit_visible(dbref exit, dbref player, int key)
01431 {
01432         if(key & VE_LOC_XAM)            // Exam exit's loc
01433                 return 1;
01434         if(Examinable(player, exit))    // Exam exit 
01435                 return 1;
01436         if(Light(exit))                         // Exit is light
01437                 return 1;
01438         if(key & (VE_LOC_DARK | VE_BASE_DARK))
01439                 return 0;                               // Dark loc or base   
01440         if(Dark(exit))                          // Dark exit
01441                 return 0;
01442         return 1;                                       // Default
01443 }
01444 
01448 int exit_displayable(dbref exit, dbref player, int key)
01449 {
01450         if(Dark(exit))                          // Dark exit
01451                 return 0;
01452         if(Light(exit))                         // Light exit
01453                 return 1;
01454         if(key & (VE_LOC_DARK | VE_BASE_DARK))
01455                 return 0;                               // Dark loc or base    
01456         return 1;                                       // Default 
01457 }
01458 
01462 dbref next_exit(dbref player, dbref this, int exam_here)
01463 {
01464         if(isRoom(this))
01465                 return NOTHING;
01466         if(isExit(this) && exam_here)
01467                 return this;
01468 
01469         while ((this != NOTHING) && Dark(this) && !Light(this) &&
01470                    !Examinable(player, this))
01471                 this = Next(this);
01472 
01473         return this;
01474 }
01475 
01479 void did_it(dbref player, dbref thing, int what, const char *def, int owhat,
01480                         const char *odef, int awhat, char *args[], int nargs)
01481 {
01482         char *d, *buff, *act, *charges, *bp, *str;
01483         dbref loc, aowner;
01484         int num, aflags;
01485 
01486         /*
01487          * message to player 
01488          */
01489 
01490         if(what > 0) {
01491                 d = atr_pget(thing, what, &aowner, &aflags);
01492                 if(*d) {
01493                         buff = bp = alloc_lbuf("did_it.1");
01494                         str = d;
01495                         exec(buff, &bp, 0, thing, player,
01496                                  EV_EVAL | EV_FIGNORE | EV_TOP, &str, args, nargs);
01497                         *bp = '\0';
01498                         notify(player, buff);
01499                         free_lbuf(buff);
01500                 } else if(def) {
01501                         notify(player, def);
01502                 }
01503                 free_lbuf(d);
01504         } else if((what < 0) && def) {
01505                 notify(player, def);
01506         }
01507         /*
01508          * message to neighbors 
01509          */
01510 
01511         if((owhat > 0) && Has_location(player) &&
01512            Good_obj(loc = Location(player))) {
01513                 d = atr_pget(thing, owhat, &aowner, &aflags);
01514                 if(*d) {
01515                         buff = bp = alloc_lbuf("did_it.2");
01516                         str = d;
01517                         exec(buff, &bp, 0, thing, player,
01518                                  EV_EVAL | EV_FIGNORE | EV_TOP, &str, args, nargs);
01519                         *bp = '\0';
01520                         if(*buff)
01521                                 notify_except2(loc, player, player, thing, tprintf("%s %s",
01522                                                                                                                                    Name
01523                                                                                                                                    (player),
01524                                                                                                                                    buff));
01525                         free_lbuf(buff);
01526                 } else if(odef) {
01527                         notify_except2(loc, player, player, thing, tprintf("%s %s",
01528                                                                                                                            Name(player),
01529                                                                                                                            odef));
01530                 }
01531                 free_lbuf(d);
01532         } else if((owhat < 0) && odef && Has_location(player) &&
01533                           Good_obj(loc = Location(player))) {
01534                 notify_except2(loc, player, player, thing, tprintf("%s %s",
01535                                                                                                                    Name(player),
01536                                                                                                                    odef));
01537         }
01538         /*
01539          * do the action attribute 
01540          */
01541 
01542         if(awhat > 0) {
01543                 if(*(act = atr_pget(thing, awhat, &aowner, &aflags))) {
01544                         charges = atr_pget(thing, A_CHARGES, &aowner, &aflags);
01545                         if(*charges) {
01546                                 num = atoi(charges);
01547                                 if(num > 0) {
01548                                         buff = alloc_sbuf("did_it.charges");
01549                                         sprintf(buff, "%d", num - 1);
01550                                         atr_add_raw(thing, A_CHARGES, buff);
01551                                         free_sbuf(buff);
01552                                 } else if(*(buff =
01553                                                         atr_pget(thing, A_RUNOUT, &aowner, &aflags))) {
01554                                         free_lbuf(act);
01555                                         act = buff;
01556                                 } else {
01557                                         free_lbuf(act);
01558                                         free_lbuf(buff);
01559                                         free_lbuf(charges);
01560                                         return;
01561                                 }
01562                         }
01563                         free_lbuf(charges);
01564                         wait_que(thing, player, 0, NOTHING, 0, act, args, nargs,
01565                                          mudstate.global_regs);
01566                 }
01567                 free_lbuf(act);
01568         }
01569 }
01570 
01574 void do_verb(dbref player, dbref cause, int key, char *victim_str,
01575                          char *args[], int nargs)
01576 {
01577         dbref actor, victim, aowner;
01578         int what, owhat, awhat, nxargs, restriction, aflags, i;
01579         ATTR *ap;
01580         const char *whatd, *owhatd;
01581         char *xargs[10];
01582 
01583         /*
01584          * Look for the victim 
01585          */
01586 
01587         if(!victim_str || !*victim_str) {
01588                 notify(player, "Nothing to do.");
01589                 return;
01590         }
01591         /*
01592          * Get the victim 
01593          */
01594 
01595         init_match(player, victim_str, NOTYPE);
01596         match_everything(MAT_EXIT_PARENTS);
01597         victim = noisy_match_result();
01598         if(!Good_obj(victim))
01599                 return;
01600 
01601         /*
01602          * Get the actor.  Default is my cause 
01603          */
01604 
01605         if((nargs >= 1) && args[0] && *args[0]) {
01606                 init_match(player, args[0], NOTYPE);
01607                 match_everything(MAT_EXIT_PARENTS);
01608                 actor = noisy_match_result();
01609                 if(!Good_obj(actor))
01610                         return;
01611         } else {
01612                 actor = cause;
01613         }
01614 
01615         /*
01616          * Check permissions. There are two possibilities 
01617          *   1: Player controls both victim and actor. In this case, victim
01618          *      runs his action list. 
01619          *   2: Player controls actor. In this case, victim does not run his
01620          *      action list and any attributes that player cannot read from
01621          *      victim are defaulted.
01622          */
01623 
01624         if(!controls(player, actor)) {
01625                 notify_quiet(player, "Permission denied,");
01626                 return;
01627         }
01628         restriction = !controls(player, victim);
01629 
01630         what = -1;
01631         owhat = -1;
01632         awhat = -1;
01633         whatd = NULL;
01634         owhatd = NULL;
01635         nxargs = 0;
01636 
01637         /*
01638          * Get invoker message attribute 
01639          */
01640 
01641         if(nargs >= 2) {
01642                 ap = atr_str(args[1]);
01643                 if(ap && (ap->number > 0))
01644                         what = ap->number;
01645         }
01646         /*
01647          * Get invoker message default 
01648          */
01649 
01650         if((nargs >= 3) && args[2] && *args[2]) {
01651                 whatd = args[2];
01652         }
01653         /*
01654          * Get others message attribute 
01655          */
01656 
01657         if(nargs >= 4) {
01658                 ap = atr_str(args[3]);
01659                 if(ap && (ap->number > 0))
01660                         owhat = ap->number;
01661         }
01662         /*
01663          * Get others message default 
01664          */
01665 
01666         if((nargs >= 5) && args[4] && *args[4]) {
01667                 owhatd = args[4];
01668         }
01669         /*
01670          * Get action attribute 
01671          */
01672 
01673         if(nargs >= 6) {
01674                 ap = atr_str(args[5]);
01675                 if(ap)
01676                         awhat = ap->number;
01677         }
01678         /*
01679          * Get arguments 
01680          */
01681 
01682         if(nargs >= 7) {
01683                 parse_arglist(victim, actor, args[6], '\0',
01684                                           EV_STRIP_LS | EV_STRIP_TS, xargs, 10, (char **) NULL,
01685                                           0);
01686                 for(nxargs = 0; (nxargs < 10) && xargs[nxargs]; nxargs++);
01687         }
01688         /*
01689          * If player doesn't control both, enforce visibility restrictions 
01690          */
01691 
01692         if(restriction) {
01693                 ap = NULL;
01694                 if(what != -1) {
01695                         atr_get_info(victim, what, &aowner, &aflags);
01696                         ap = atr_num(what);
01697                 }
01698                 if(!ap || !Read_attr(player, victim, ap, aowner, aflags) ||
01699                    ((ap->number == A_DESC) && !mudconf.read_rem_desc &&
01700                         !Examinable(player, victim) && !nearby(player, victim)))
01701                         what = -1;
01702 
01703                 ap = NULL;
01704                 if(owhat != -1) {
01705                         atr_get_info(victim, owhat, &aowner, &aflags);
01706                         ap = atr_num(owhat);
01707                 }
01708                 if(!ap || !Read_attr(player, victim, ap, aowner, aflags) ||
01709                    ((ap->number == A_DESC) && !mudconf.read_rem_desc &&
01710                         !Examinable(player, victim) && !nearby(player, victim)))
01711                         owhat = -1;
01712 
01713                 awhat = 0;
01714         }
01715         /*
01716          * Go do it 
01717          */
01718 
01719         did_it(actor, victim, what, whatd, owhat, owhatd, awhat, xargs, nxargs);
01720 
01721         /*
01722          * Free user args 
01723          */
01724 
01725         for(i = 0; i < nxargs; i++)
01726                 free_lbuf(xargs[i]);
01727 
01728 }

Generated on Mon May 28 04:25:25 2007 for BattletechMUX by  doxygen 1.4.7