/ circle3.1 / src / handler.c
handler.c
   1  /* ************************************************************************
   2  *   File: handler.c                                     Part of CircleMUD *
   3  *  Usage: internal funcs: moving and finding chars/objs                   *
   4  *                                                                         *
   5  *  All rights reserved.  See license.doc for complete information.        *
   6  *                                                                         *
   7  *  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
   8  *  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
   9  ************************************************************************ */
  10  
  11  #include "conf.h"
  12  #include "sysdep.h"
  13  
  14  
  15  #include "structs.h"
  16  #include "utils.h"
  17  #include "comm.h"
  18  #include "db.h"
  19  #include "handler.h"
  20  #include "interpreter.h"
  21  #include "spells.h"
  22  
  23  /* local vars */
  24  int extractions_pending = 0;
  25  
  26  /* external vars */
  27  extern struct char_data *combat_list;
  28  extern const char *MENU;
  29  
  30  /* local functions */
  31  int apply_ac(struct char_data *ch, int eq_pos);
  32  void update_object(struct obj_data *obj, int use);
  33  void update_char_objects(struct char_data *ch);
  34  
  35  /* external functions */
  36  int invalid_class(struct char_data *ch, struct obj_data *obj);
  37  void remove_follower(struct char_data *ch);
  38  void clearMemory(struct char_data *ch);
  39  ACMD(do_return);
  40  
  41  char *fname(const char *namelist)
  42  {
  43    static char holder[30];
  44    char *point;
  45  
  46    for (point = holder; isalpha(*namelist); namelist++, point++)
  47      *point = *namelist;
  48  
  49    *point = '\0';
  50  
  51    return (holder);
  52  }
  53  
  54  
  55  int isname(const char *str, const char *namelist)
  56  {
  57    const char *curname, *curstr;
  58  
  59    curname = namelist;
  60    for (;;) {
  61      for (curstr = str;; curstr++, curname++) {
  62        if (!*curstr && !isalpha(*curname))
  63  	return (1);
  64  
  65        if (!*curname)
  66  	return (0);
  67  
  68        if (!*curstr || *curname == ' ')
  69  	break;
  70  
  71        if (LOWER(*curstr) != LOWER(*curname))
  72  	break;
  73      }
  74  
  75      /* skip to next name */
  76  
  77      for (; isalpha(*curname); curname++);
  78      if (!*curname)
  79        return (0);
  80      curname++;			/* first char of new name */
  81    }
  82  }
  83  
  84  
  85  
  86  void affect_modify(struct char_data *ch, byte loc, sbyte mod, 
  87                     bitvector_t bitv, bool add)
  88  {
  89    if (add)
  90      SET_BIT(AFF_FLAGS(ch), bitv);
  91    else {
  92      REMOVE_BIT(AFF_FLAGS(ch), bitv);
  93      mod = -mod;
  94    }
  95  
  96    switch (loc) {
  97    case APPLY_NONE:
  98      break;
  99  
 100    case APPLY_STR:
 101      GET_STR(ch) += mod;
 102      break;
 103    case APPLY_DEX:
 104      GET_DEX(ch) += mod;
 105      break;
 106    case APPLY_INT:
 107      GET_INT(ch) += mod;
 108      break;
 109    case APPLY_WIS:
 110      GET_WIS(ch) += mod;
 111      break;
 112    case APPLY_CON:
 113      GET_CON(ch) += mod;
 114      break;
 115    case APPLY_CHA:
 116      GET_CHA(ch) += mod;
 117      break;
 118  
 119    case APPLY_CLASS:
 120      /* ??? GET_CLASS(ch) += mod; */
 121      break;
 122  
 123    /*
 124     * My personal thoughts on these two would be to set the person to the
 125     * value of the apply.  That way you won't have to worry about people
 126     * making +1 level things to be imp (you restrict anything that gives
 127     * immortal level of course).  It also makes more sense to set someone
 128     * to a class rather than adding to the class number. -gg
 129     */
 130  
 131    case APPLY_LEVEL:
 132      /* ??? GET_LEVEL(ch) += mod; */
 133      break;
 134  
 135    case APPLY_AGE:
 136      ch->player.time.birth -= (mod * SECS_PER_MUD_YEAR);
 137      break;
 138  
 139    case APPLY_CHAR_WEIGHT:
 140      GET_WEIGHT(ch) += mod;
 141      break;
 142  
 143    case APPLY_CHAR_HEIGHT:
 144      GET_HEIGHT(ch) += mod;
 145      break;
 146  
 147    case APPLY_MANA:
 148      GET_MAX_MANA(ch) += mod;
 149      break;
 150  
 151    case APPLY_HIT:
 152      GET_MAX_HIT(ch) += mod;
 153      break;
 154  
 155    case APPLY_MOVE:
 156      GET_MAX_MOVE(ch) += mod;
 157      break;
 158  
 159    case APPLY_GOLD:
 160      break;
 161  
 162    case APPLY_EXP:
 163      break;
 164  
 165    case APPLY_AC:
 166      GET_AC(ch) += mod;
 167      break;
 168  
 169    case APPLY_HITROLL:
 170      GET_HITROLL(ch) += mod;
 171      break;
 172  
 173    case APPLY_DAMROLL:
 174      GET_DAMROLL(ch) += mod;
 175      break;
 176  
 177    case APPLY_SAVING_PARA:
 178      GET_SAVE(ch, SAVING_PARA) += mod;
 179      break;
 180  
 181    case APPLY_SAVING_ROD:
 182      GET_SAVE(ch, SAVING_ROD) += mod;
 183      break;
 184  
 185    case APPLY_SAVING_PETRI:
 186      GET_SAVE(ch, SAVING_PETRI) += mod;
 187      break;
 188  
 189    case APPLY_SAVING_BREATH:
 190      GET_SAVE(ch, SAVING_BREATH) += mod;
 191      break;
 192  
 193    case APPLY_SAVING_SPELL:
 194      GET_SAVE(ch, SAVING_SPELL) += mod;
 195      break;
 196  
 197    default:
 198      log("SYSERR: Unknown apply adjust %d attempt (%s, affect_modify).", loc, __FILE__);
 199      break;
 200  
 201    } /* switch */
 202  }
 203  
 204  
 205  
 206  /* This updates a character by subtracting everything he is affected by */
 207  /* restoring original abilities, and then affecting all again           */
 208  void affect_total(struct char_data *ch)
 209  {
 210    struct affected_type *af;
 211    int i, j;
 212  
 213    for (i = 0; i < NUM_WEARS; i++) {
 214      if (GET_EQ(ch, i))
 215        for (j = 0; j < MAX_OBJ_AFFECT; j++)
 216  	affect_modify(ch, GET_EQ(ch, i)->affected[j].location,
 217  		      GET_EQ(ch, i)->affected[j].modifier,
 218  		      GET_OBJ_AFFECT(GET_EQ(ch, i)), FALSE);
 219    }
 220  
 221  
 222    for (af = ch->affected; af; af = af->next)
 223      affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE);
 224  
 225    ch->aff_abils = ch->real_abils;
 226  
 227    for (i = 0; i < NUM_WEARS; i++) {
 228      if (GET_EQ(ch, i))
 229        for (j = 0; j < MAX_OBJ_AFFECT; j++)
 230  	affect_modify(ch, GET_EQ(ch, i)->affected[j].location,
 231  		      GET_EQ(ch, i)->affected[j].modifier,
 232  		      GET_OBJ_AFFECT(GET_EQ(ch, i)), TRUE);
 233    }
 234  
 235  
 236    for (af = ch->affected; af; af = af->next)
 237      affect_modify(ch, af->location, af->modifier, af->bitvector, TRUE);
 238  
 239    /* Make certain values are between 0..25, not < 0 and not > 25! */
 240  
 241    i = (IS_NPC(ch) || GET_LEVEL(ch) >= LVL_GRGOD) ? 25 : 18;
 242  
 243    GET_DEX(ch) = MAX(0, MIN(GET_DEX(ch), i));
 244    GET_INT(ch) = MAX(0, MIN(GET_INT(ch), i));
 245    GET_WIS(ch) = MAX(0, MIN(GET_WIS(ch), i));
 246    GET_CON(ch) = MAX(0, MIN(GET_CON(ch), i));
 247    GET_CHA(ch) = MAX(0, MIN(GET_CHA(ch), i));
 248    GET_STR(ch) = MAX(0, GET_STR(ch));
 249  
 250    if (IS_NPC(ch)) {
 251      GET_STR(ch) = MIN(GET_STR(ch), i);
 252    } else {
 253      if (GET_STR(ch) > 18) {
 254        i = GET_ADD(ch) + ((GET_STR(ch) - 18) * 10);
 255        GET_ADD(ch) = MIN(i, 100);
 256        GET_STR(ch) = 18;
 257      }
 258    }
 259  }
 260  
 261  
 262  
 263  /* Insert an affect_type in a char_data structure
 264     Automatically sets apropriate bits and apply's */
 265  void affect_to_char(struct char_data *ch, struct affected_type *af)
 266  {
 267    struct affected_type *affected_alloc;
 268  
 269    CREATE(affected_alloc, struct affected_type, 1);
 270  
 271    *affected_alloc = *af;
 272    affected_alloc->next = ch->affected;
 273    ch->affected = affected_alloc;
 274  
 275    affect_modify(ch, af->location, af->modifier, af->bitvector, TRUE);
 276    affect_total(ch);
 277  }
 278  
 279  
 280  
 281  /*
 282   * Remove an affected_type structure from a char (called when duration
 283   * reaches zero). Pointer *af must never be NIL!  Frees mem and calls
 284   * affect_location_apply
 285   */
 286  void affect_remove(struct char_data *ch, struct affected_type *af)
 287  {
 288    struct affected_type *temp;
 289  
 290    if (ch->affected == NULL) {
 291      core_dump();
 292      return;
 293    }
 294  
 295    affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE);
 296    REMOVE_FROM_LIST(af, ch->affected, next);
 297    free(af);
 298    affect_total(ch);
 299  }
 300  
 301  
 302  
 303  /* Call affect_remove with every spell of spelltype "skill" */
 304  void affect_from_char(struct char_data *ch, int type)
 305  {
 306    struct affected_type *hjp, *next;
 307  
 308    for (hjp = ch->affected; hjp; hjp = next) {
 309      next = hjp->next;
 310      if (hjp->type == type)
 311        affect_remove(ch, hjp);
 312    }
 313  }
 314  
 315  
 316  
 317  /*
 318   * Return TRUE if a char is affected by a spell (SPELL_XXX),
 319   * FALSE indicates not affected.
 320   */
 321  bool affected_by_spell(struct char_data *ch, int type)
 322  {
 323    struct affected_type *hjp;
 324  
 325    for (hjp = ch->affected; hjp; hjp = hjp->next)
 326      if (hjp->type == type)
 327        return (TRUE);
 328  
 329    return (FALSE);
 330  }
 331  
 332  
 333  
 334  void affect_join(struct char_data *ch, struct affected_type *af,
 335  		      bool add_dur, bool avg_dur, bool add_mod, bool avg_mod)
 336  {
 337    struct affected_type *hjp, *next;
 338    bool found = FALSE;
 339  
 340    for (hjp = ch->affected; !found && hjp; hjp = next) {
 341      next = hjp->next;
 342  
 343      if ((hjp->type == af->type) && (hjp->location == af->location)) {
 344        if (add_dur)
 345  	af->duration += hjp->duration;
 346        if (avg_dur)
 347  	af->duration /= 2;
 348  
 349        if (add_mod)
 350  	af->modifier += hjp->modifier;
 351        if (avg_mod)
 352  	af->modifier /= 2;
 353  
 354        affect_remove(ch, hjp);
 355        affect_to_char(ch, af);
 356        found = TRUE;
 357      }
 358    }
 359    if (!found)
 360      affect_to_char(ch, af);
 361  }
 362  
 363  
 364  /* move a player out of a room */
 365  void char_from_room(struct char_data *ch)
 366  {
 367    struct char_data *temp;
 368  
 369    if (ch == NULL || IN_ROOM(ch) == NOWHERE) {
 370      log("SYSERR: NULL character or NOWHERE in %s, char_from_room", __FILE__);
 371      exit(1);
 372    }
 373  
 374    if (FIGHTING(ch) != NULL)
 375      stop_fighting(ch);
 376  
 377    if (GET_EQ(ch, WEAR_LIGHT) != NULL)
 378      if (GET_OBJ_TYPE(GET_EQ(ch, WEAR_LIGHT)) == ITEM_LIGHT)
 379        if (GET_OBJ_VAL(GET_EQ(ch, WEAR_LIGHT), 2))	/* Light is ON */
 380  	world[IN_ROOM(ch)].light--;
 381  
 382    REMOVE_FROM_LIST(ch, world[IN_ROOM(ch)].people, next_in_room);
 383    IN_ROOM(ch) = NOWHERE;
 384    ch->next_in_room = NULL;
 385  }
 386  
 387  
 388  /* place a character in a room */
 389  void char_to_room(struct char_data *ch, room_rnum room)
 390  {
 391    if (ch == NULL || room == NOWHERE || room > top_of_world)
 392      log("SYSERR: Illegal value(s) passed to char_to_room. (Room: %d/%d Ch: %p",
 393  		room, top_of_world, ch);
 394    else {
 395      ch->next_in_room = world[room].people;
 396      world[room].people = ch;
 397      IN_ROOM(ch) = room;
 398  
 399      if (GET_EQ(ch, WEAR_LIGHT))
 400        if (GET_OBJ_TYPE(GET_EQ(ch, WEAR_LIGHT)) == ITEM_LIGHT)
 401  	if (GET_OBJ_VAL(GET_EQ(ch, WEAR_LIGHT), 2))	/* Light ON */
 402  	  world[room].light++;
 403  
 404      /* Stop fighting now, if we left. */
 405      if (FIGHTING(ch) && IN_ROOM(ch) != IN_ROOM(FIGHTING(ch))) {
 406        stop_fighting(FIGHTING(ch));
 407        stop_fighting(ch);
 408      }
 409    }
 410  }
 411  
 412  
 413  /* give an object to a char   */
 414  void obj_to_char(struct obj_data *object, struct char_data *ch)
 415  {
 416    if (object && ch) {
 417      object->next_content = ch->carrying;
 418      ch->carrying = object;
 419      object->carried_by = ch;
 420      IN_ROOM(object) = NOWHERE;
 421      IS_CARRYING_W(ch) += GET_OBJ_WEIGHT(object);
 422      IS_CARRYING_N(ch)++;
 423  
 424      /* set flag for crash-save system, but not on mobs! */
 425      if (!IS_NPC(ch))
 426        SET_BIT(PLR_FLAGS(ch), PLR_CRASH);
 427    } else
 428      log("SYSERR: NULL obj (%p) or char (%p) passed to obj_to_char.", object, ch);
 429  }
 430  
 431  
 432  /* take an object from a char */
 433  void obj_from_char(struct obj_data *object)
 434  {
 435    struct obj_data *temp;
 436  
 437    if (object == NULL) {
 438      log("SYSERR: NULL object passed to obj_from_char.");
 439      return;
 440    }
 441    REMOVE_FROM_LIST(object, object->carried_by->carrying, next_content);
 442  
 443    /* set flag for crash-save system, but not on mobs! */
 444    if (!IS_NPC(object->carried_by))
 445      SET_BIT(PLR_FLAGS(object->carried_by), PLR_CRASH);
 446  
 447    IS_CARRYING_W(object->carried_by) -= GET_OBJ_WEIGHT(object);
 448    IS_CARRYING_N(object->carried_by)--;
 449    object->carried_by = NULL;
 450    object->next_content = NULL;
 451  }
 452  
 453  
 454  
 455  /* Return the effect of a piece of armor in position eq_pos */
 456  int apply_ac(struct char_data *ch, int eq_pos)
 457  {
 458    int factor;
 459  
 460    if (GET_EQ(ch, eq_pos) == NULL) {
 461      core_dump();
 462      return (0);
 463    }
 464  
 465    if (!(GET_OBJ_TYPE(GET_EQ(ch, eq_pos)) == ITEM_ARMOR))
 466      return (0);
 467  
 468    switch (eq_pos) {
 469  
 470    case WEAR_BODY:
 471      factor = 3;
 472      break;			/* 30% */
 473    case WEAR_HEAD:
 474      factor = 2;
 475      break;			/* 20% */
 476    case WEAR_LEGS:
 477      factor = 2;
 478      break;			/* 20% */
 479    default:
 480      factor = 1;
 481      break;			/* all others 10% */
 482    }
 483  
 484    return (factor * GET_OBJ_VAL(GET_EQ(ch, eq_pos), 0));
 485  }
 486  
 487  int invalid_align(struct char_data *ch, struct obj_data *obj)
 488  {
 489    if (OBJ_FLAGGED(obj, ITEM_ANTI_EVIL) && IS_EVIL(ch))
 490      return TRUE;
 491    if (OBJ_FLAGGED(obj, ITEM_ANTI_GOOD) && IS_GOOD(ch))
 492      return TRUE;
 493    if (OBJ_FLAGGED(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch))
 494      return TRUE;
 495    return FALSE;
 496  }
 497  
 498  void equip_char(struct char_data *ch, struct obj_data *obj, int pos)
 499  {
 500    int j;
 501  
 502    if (pos < 0 || pos >= NUM_WEARS) {
 503      core_dump();
 504      return;
 505    }
 506  
 507    if (GET_EQ(ch, pos)) {
 508      log("SYSERR: Char is already equipped: %s, %s", GET_NAME(ch),
 509  	    obj->short_description);
 510      return;
 511    }
 512    if (obj->carried_by) {
 513      log("SYSERR: EQUIP: Obj is carried_by when equip.");
 514      return;
 515    }
 516    if (IN_ROOM(obj) != NOWHERE) {
 517      log("SYSERR: EQUIP: Obj is in_room when equip.");
 518      return;
 519    }
 520    if (invalid_align(ch, obj) || invalid_class(ch, obj)) {
 521      act("You are zapped by $p and instantly let go of it.", FALSE, ch, obj, 0, TO_CHAR);
 522      act("$n is zapped by $p and instantly lets go of it.", FALSE, ch, obj, 0, TO_ROOM);
 523      /* Changed to drop in inventory instead of the ground. */
 524      obj_to_char(obj, ch);
 525      return;
 526    }
 527  
 528    GET_EQ(ch, pos) = obj;
 529    obj->worn_by = ch;
 530    obj->worn_on = pos;
 531  
 532    if (GET_OBJ_TYPE(obj) == ITEM_ARMOR)
 533      GET_AC(ch) -= apply_ac(ch, pos);
 534  
 535    if (IN_ROOM(ch) != NOWHERE) {
 536      if (pos == WEAR_LIGHT && GET_OBJ_TYPE(obj) == ITEM_LIGHT)
 537        if (GET_OBJ_VAL(obj, 2))	/* if light is ON */
 538  	world[IN_ROOM(ch)].light++;
 539    } else
 540      log("SYSERR: IN_ROOM(ch) = NOWHERE when equipping char %s.", GET_NAME(ch));
 541  
 542    for (j = 0; j < MAX_OBJ_AFFECT; j++)
 543      affect_modify(ch, obj->affected[j].location,
 544  		  obj->affected[j].modifier,
 545  		  GET_OBJ_AFFECT(obj), TRUE);
 546  
 547    affect_total(ch);
 548  }
 549  
 550  
 551  
 552  struct obj_data *unequip_char(struct char_data *ch, int pos)
 553  {
 554    int j;
 555    struct obj_data *obj;
 556  
 557    if ((pos < 0 || pos >= NUM_WEARS) || GET_EQ(ch, pos) == NULL) {
 558      core_dump();
 559      return (NULL);
 560    }
 561  
 562    obj = GET_EQ(ch, pos);
 563    obj->worn_by = NULL;
 564    obj->worn_on = -1;
 565  
 566    if (GET_OBJ_TYPE(obj) == ITEM_ARMOR)
 567      GET_AC(ch) += apply_ac(ch, pos);
 568  
 569    if (IN_ROOM(ch) != NOWHERE) {
 570      if (pos == WEAR_LIGHT && GET_OBJ_TYPE(obj) == ITEM_LIGHT)
 571        if (GET_OBJ_VAL(obj, 2))	/* if light is ON */
 572  	world[IN_ROOM(ch)].light--;
 573    } else
 574      log("SYSERR: IN_ROOM(ch) = NOWHERE when unequipping char %s.", GET_NAME(ch));
 575  
 576    GET_EQ(ch, pos) = NULL;
 577  
 578    for (j = 0; j < MAX_OBJ_AFFECT; j++)
 579      affect_modify(ch, obj->affected[j].location,
 580  		  obj->affected[j].modifier,
 581  		  GET_OBJ_AFFECT(obj), FALSE);
 582  
 583    affect_total(ch);
 584  
 585    return (obj);
 586  }
 587  
 588  
 589  int get_number(char **name)
 590  {
 591    int i;
 592    char *ppos;
 593    char number[MAX_INPUT_LENGTH];
 594  
 595    *number = '\0';
 596  
 597    if ((ppos = strchr(*name, '.')) != NULL) {
 598      *ppos++ = '\0';
 599      strlcpy(number, *name, sizeof(number));
 600      strcpy(*name, ppos);	/* strcpy: OK (always smaller) */
 601  
 602      for (i = 0; *(number + i); i++)
 603        if (!isdigit(*(number + i)))
 604  	return (0);
 605  
 606      return (atoi(number));
 607    }
 608    return (1);
 609  }
 610  
 611  
 612  
 613  /* Search a given list for an object number, and return a ptr to that obj */
 614  struct obj_data *get_obj_in_list_num(int num, struct obj_data *list)
 615  {
 616    struct obj_data *i;
 617  
 618    for (i = list; i; i = i->next_content)
 619      if (GET_OBJ_RNUM(i) == num)
 620        return (i);
 621  
 622    return (NULL);
 623  }
 624  
 625  
 626  
 627  /* search the entire world for an object number, and return a pointer  */
 628  struct obj_data *get_obj_num(obj_rnum nr)
 629  {
 630    struct obj_data *i;
 631  
 632    for (i = object_list; i; i = i->next)
 633      if (GET_OBJ_RNUM(i) == nr)
 634        return (i);
 635  
 636    return (NULL);
 637  }
 638  
 639  
 640  
 641  /* search a room for a char, and return a pointer if found..  */
 642  struct char_data *get_char_room(char *name, int *number, room_rnum room)
 643  {
 644    struct char_data *i;
 645    int num;
 646  
 647    if (!number) {
 648      number = &num;
 649      num = get_number(&name);
 650    }
 651  
 652    if (*number == 0)
 653      return (NULL);
 654  
 655    for (i = world[room].people; i && *number; i = i->next_in_room)
 656      if (isname(name, i->player.name))
 657        if (--(*number) == 0)
 658  	return (i);
 659  
 660    return (NULL);
 661  }
 662  
 663  
 664  
 665  /* search all over the world for a char num, and return a pointer if found */
 666  struct char_data *get_char_num(mob_rnum nr)
 667  {
 668    struct char_data *i;
 669  
 670    for (i = character_list; i; i = i->next)
 671      if (GET_MOB_RNUM(i) == nr)
 672        return (i);
 673  
 674    return (NULL);
 675  }
 676  
 677  
 678  
 679  /* put an object in a room */
 680  void obj_to_room(struct obj_data *object, room_rnum room)
 681  {
 682    if (!object || room == NOWHERE || room > top_of_world)
 683      log("SYSERR: Illegal value(s) passed to obj_to_room. (Room #%d/%d, obj %p)",
 684  	room, top_of_world, object);
 685    else {
 686      object->next_content = world[room].contents;
 687      world[room].contents = object;
 688      IN_ROOM(object) = room;
 689      object->carried_by = NULL;
 690      if (ROOM_FLAGGED(room, ROOM_HOUSE))
 691        SET_BIT(ROOM_FLAGS(room), ROOM_HOUSE_CRASH);
 692    }
 693  }
 694  
 695  
 696  /* Take an object from a room */
 697  void obj_from_room(struct obj_data *object)
 698  {
 699    struct obj_data *temp;
 700  
 701    if (!object || IN_ROOM(object) == NOWHERE) {
 702      log("SYSERR: NULL object (%p) or obj not in a room (%d) passed to obj_from_room",
 703  	object, IN_ROOM(object));
 704      return;
 705    }
 706  
 707    REMOVE_FROM_LIST(object, world[IN_ROOM(object)].contents, next_content);
 708  
 709    if (ROOM_FLAGGED(IN_ROOM(object), ROOM_HOUSE))
 710      SET_BIT(ROOM_FLAGS(IN_ROOM(object)), ROOM_HOUSE_CRASH);
 711    IN_ROOM(object) = NOWHERE;
 712    object->next_content = NULL;
 713  }
 714  
 715  
 716  /* put an object in an object (quaint)  */
 717  void obj_to_obj(struct obj_data *obj, struct obj_data *obj_to)
 718  {
 719    struct obj_data *tmp_obj;
 720  
 721    if (!obj || !obj_to || obj == obj_to) {
 722      log("SYSERR: NULL object (%p) or same source (%p) and target (%p) obj passed to obj_to_obj.",
 723  	obj, obj, obj_to);
 724      return;
 725    }
 726  
 727    obj->next_content = obj_to->contains;
 728    obj_to->contains = obj;
 729    obj->in_obj = obj_to;
 730  
 731    for (tmp_obj = obj->in_obj; tmp_obj->in_obj; tmp_obj = tmp_obj->in_obj)
 732      GET_OBJ_WEIGHT(tmp_obj) += GET_OBJ_WEIGHT(obj);
 733  
 734    /* top level object.  Subtract weight from inventory if necessary. */
 735    GET_OBJ_WEIGHT(tmp_obj) += GET_OBJ_WEIGHT(obj);
 736    if (tmp_obj->carried_by)
 737      IS_CARRYING_W(tmp_obj->carried_by) += GET_OBJ_WEIGHT(obj);
 738  }
 739  
 740  
 741  /* remove an object from an object */
 742  void obj_from_obj(struct obj_data *obj)
 743  {
 744    struct obj_data *temp, *obj_from;
 745  
 746    if (obj->in_obj == NULL) {
 747      log("SYSERR: (%s): trying to illegally extract obj from obj.", __FILE__);
 748      return;
 749    }
 750    obj_from = obj->in_obj;
 751    REMOVE_FROM_LIST(obj, obj_from->contains, next_content);
 752  
 753    /* Subtract weight from containers container */
 754    for (temp = obj->in_obj; temp->in_obj; temp = temp->in_obj)
 755      GET_OBJ_WEIGHT(temp) -= GET_OBJ_WEIGHT(obj);
 756  
 757    /* Subtract weight from char that carries the object */
 758    GET_OBJ_WEIGHT(temp) -= GET_OBJ_WEIGHT(obj);
 759    if (temp->carried_by)
 760      IS_CARRYING_W(temp->carried_by) -= GET_OBJ_WEIGHT(obj);
 761  
 762    obj->in_obj = NULL;
 763    obj->next_content = NULL;
 764  }
 765  
 766  
 767  /* Set all carried_by to point to new owner */
 768  void object_list_new_owner(struct obj_data *list, struct char_data *ch)
 769  {
 770    if (list) {
 771      object_list_new_owner(list->contains, ch);
 772      object_list_new_owner(list->next_content, ch);
 773      list->carried_by = ch;
 774    }
 775  }
 776  
 777  
 778  /* Extract an object from the world */
 779  void extract_obj(struct obj_data *obj)
 780  {
 781    struct obj_data *temp;
 782  
 783    if (obj->worn_by != NULL)
 784      if (unequip_char(obj->worn_by, obj->worn_on) != obj)
 785        log("SYSERR: Inconsistent worn_by and worn_on pointers!!");
 786    if (IN_ROOM(obj) != NOWHERE)
 787      obj_from_room(obj);
 788    else if (obj->carried_by)
 789      obj_from_char(obj);
 790    else if (obj->in_obj)
 791      obj_from_obj(obj);
 792  
 793    /* Get rid of the contents of the object, as well. */
 794    while (obj->contains)
 795      extract_obj(obj->contains);
 796  
 797    REMOVE_FROM_LIST(obj, object_list, next);
 798  
 799    if (GET_OBJ_RNUM(obj) != NOTHING)
 800      (obj_index[GET_OBJ_RNUM(obj)].number)--;
 801    free_obj(obj);
 802  }
 803  
 804  
 805  
 806  void update_object(struct obj_data *obj, int use)
 807  {
 808    if (GET_OBJ_TIMER(obj) > 0)
 809      GET_OBJ_TIMER(obj) -= use;
 810    if (obj->contains)
 811      update_object(obj->contains, use);
 812    if (obj->next_content)
 813      update_object(obj->next_content, use);
 814  }
 815  
 816  
 817  void update_char_objects(struct char_data *ch)
 818  {
 819    int i;
 820  
 821    if (GET_EQ(ch, WEAR_LIGHT) != NULL)
 822      if (GET_OBJ_TYPE(GET_EQ(ch, WEAR_LIGHT)) == ITEM_LIGHT)
 823        if (GET_OBJ_VAL(GET_EQ(ch, WEAR_LIGHT), 2) > 0) {
 824  	i = --GET_OBJ_VAL(GET_EQ(ch, WEAR_LIGHT), 2);
 825  	if (i == 1) {
 826  	  send_to_char(ch, "Your light begins to flicker and fade.\r\n");
 827  	  act("$n's light begins to flicker and fade.", FALSE, ch, 0, 0, TO_ROOM);
 828  	} else if (i == 0) {
 829  	  send_to_char(ch, "Your light sputters out and dies.\r\n");
 830  	  act("$n's light sputters out and dies.", FALSE, ch, 0, 0, TO_ROOM);
 831  	  world[IN_ROOM(ch)].light--;
 832  	}
 833        }
 834  
 835    for (i = 0; i < NUM_WEARS; i++)
 836      if (GET_EQ(ch, i))
 837        update_object(GET_EQ(ch, i), 2);
 838  
 839    if (ch->carrying)
 840      update_object(ch->carrying, 1);
 841  }
 842  
 843  
 844  /* Extract a ch completely from the world, and leave his stuff behind */
 845  void extract_char_final(struct char_data *ch)
 846  {
 847    struct char_data *k, *temp;
 848    struct descriptor_data *d;
 849    struct obj_data *obj;
 850    int i;
 851  
 852    if (IN_ROOM(ch) == NOWHERE) {
 853      log("SYSERR: NOWHERE extracting char %s. (%s, extract_char_final)",
 854          GET_NAME(ch), __FILE__);
 855      exit(1);
 856    }
 857  
 858    /*
 859     * We're booting the character of someone who has switched so first we
 860     * need to stuff them back into their own body.  This will set ch->desc
 861     * we're checking below this loop to the proper value.
 862     */
 863    if (!IS_NPC(ch) && !ch->desc) {
 864      for (d = descriptor_list; d; d = d->next)
 865        if (d->original == ch) {
 866  	do_return(d->character, NULL, 0, 0);
 867          break;
 868        }
 869    }
 870  
 871    if (ch->desc) {
 872      /*
 873       * This time we're extracting the body someone has switched into
 874       * (not the body of someone switching as above) so we need to put
 875       * the switcher back to their own body.
 876       *
 877       * If this body is not possessed, the owner won't have a
 878       * body after the removal so dump them to the main menu.
 879       */
 880      if (ch->desc->original)
 881        do_return(ch, NULL, 0, 0);
 882      else {
 883        /*
 884         * Now we boot anybody trying to log in with the same character, to
 885         * help guard against duping.  CON_DISCONNECT is used to close a
 886         * descriptor without extracting the d->character associated with it,
 887         * for being link-dead, so we want CON_CLOSE to clean everything up.
 888         * If we're here, we know it's a player so no IS_NPC check required.
 889         */
 890        for (d = descriptor_list; d; d = d->next) {
 891          if (d == ch->desc)
 892            continue;
 893          if (d->character && GET_IDNUM(ch) == GET_IDNUM(d->character))
 894            STATE(d) = CON_CLOSE;
 895        }
 896        STATE(ch->desc) = CON_MENU;
 897        write_to_output(ch->desc, "%s", MENU);
 898      }
 899    }
 900  
 901    /* On with the character's assets... */
 902  
 903    if (ch->followers || ch->master)
 904      die_follower(ch);
 905  
 906    /* transfer objects to room, if any */
 907    while (ch->carrying) {
 908      obj = ch->carrying;
 909      obj_from_char(obj);
 910      obj_to_room(obj, IN_ROOM(ch));
 911    }
 912  
 913    /* transfer equipment to room, if any */
 914    for (i = 0; i < NUM_WEARS; i++)
 915      if (GET_EQ(ch, i))
 916        obj_to_room(unequip_char(ch, i), IN_ROOM(ch));
 917  
 918    if (FIGHTING(ch))
 919      stop_fighting(ch);
 920  
 921    for (k = combat_list; k; k = temp) {
 922      temp = k->next_fighting;
 923      if (FIGHTING(k) == ch)
 924        stop_fighting(k);
 925    }
 926    /* we can't forget the hunters either... */
 927    for (temp = character_list; temp; temp = temp->next)
 928      if (HUNTING(temp) == ch)
 929        HUNTING(temp) = NULL;
 930  
 931    char_from_room(ch);
 932  
 933    if (IS_NPC(ch)) {
 934      if (GET_MOB_RNUM(ch) != NOTHING)	/* prototyped */
 935        mob_index[GET_MOB_RNUM(ch)].number--;
 936      clearMemory(ch);
 937    } else {
 938      save_char(ch);
 939      Crash_delete_crashfile(ch);
 940    }
 941  
 942    /* If there's a descriptor, they're in the menu now. */
 943    if (IS_NPC(ch) || !ch->desc)
 944      free_char(ch);
 945  }
 946  
 947  
 948  /*
 949   * Q: Why do we do this?
 950   * A: Because trying to iterate over the character
 951   *    list with 'ch = ch->next' does bad things if
 952   *    the current character happens to die. The
 953   *    trivial workaround of 'vict = next_vict'
 954   *    doesn't work if the _next_ person in the list
 955   *    gets killed, for example, by an area spell.
 956   *
 957   * Q: Why do we leave them on the character_list?
 958   * A: Because code doing 'vict = vict->next' would
 959   *    get really confused otherwise.
 960   */
 961  void extract_char(struct char_data *ch)
 962  {
 963    if (IS_NPC(ch))
 964      SET_BIT(MOB_FLAGS(ch), MOB_NOTDEADYET);
 965    else
 966      SET_BIT(PLR_FLAGS(ch), PLR_NOTDEADYET);
 967  
 968    extractions_pending++;
 969  }
 970  
 971  
 972  /*
 973   * I'm not particularly pleased with the MOB/PLR
 974   * hoops that have to be jumped through but it
 975   * hardly calls for a completely new variable.
 976   * Ideally it would be its own list, but that
 977   * would change the '->next' pointer, potentially
 978   * confusing some code. Ugh. -gg 3/15/2001
 979   *
 980   * NOTE: This doesn't handle recursive extractions.
 981   */
 982  void extract_pending_chars(void)
 983  {
 984    struct char_data *vict, *next_vict, *prev_vict;
 985  
 986    if (extractions_pending < 0)
 987      log("SYSERR: Negative (%d) extractions pending.", extractions_pending);
 988  
 989    for (vict = character_list, prev_vict = NULL; vict && extractions_pending; vict = next_vict) {
 990      next_vict = vict->next;
 991  
 992      if (MOB_FLAGGED(vict, MOB_NOTDEADYET))
 993        REMOVE_BIT(MOB_FLAGS(vict), MOB_NOTDEADYET);
 994      else if (PLR_FLAGGED(vict, PLR_NOTDEADYET))
 995        REMOVE_BIT(PLR_FLAGS(vict), PLR_NOTDEADYET);
 996      else {
 997        /* Last non-free'd character to continue chain from. */
 998        prev_vict = vict;
 999        continue;
1000      }
1001  
1002      extract_char_final(vict);
1003      extractions_pending--;
1004  
1005      if (prev_vict)
1006        prev_vict->next = next_vict;
1007      else
1008        character_list = next_vict;
1009    }
1010  
1011    if (extractions_pending > 0)
1012      log("SYSERR: Couldn't find %d extractions as counted.", extractions_pending);
1013  
1014    extractions_pending = 0;
1015  }
1016  
1017  
1018  /* ***********************************************************************
1019  * Here follows high-level versions of some earlier routines, ie functions*
1020  * which incorporate the actual player-data                               *.
1021  *********************************************************************** */
1022  
1023  
1024  struct char_data *get_player_vis(struct char_data *ch, char *name, int *number, int inroom)
1025  {
1026    struct char_data *i;
1027    int num;
1028  
1029    if (!number) {
1030      number = &num;
1031      num = get_number(&name);
1032    }
1033  
1034    for (i = character_list; i; i = i->next) {
1035      if (IS_NPC(i))
1036        continue;
1037      if (inroom == FIND_CHAR_ROOM && IN_ROOM(i) != IN_ROOM(ch))
1038        continue;
1039      if (str_cmp(i->player.name, name)) /* If not same, continue */
1040        continue;
1041      if (!CAN_SEE(ch, i))
1042        continue;
1043      if (--(*number) != 0)
1044        continue;
1045      return (i);
1046    }
1047  
1048    return (NULL);
1049  }
1050  
1051  
1052  struct char_data *get_char_room_vis(struct char_data *ch, char *name, int *number)
1053  {
1054    struct char_data *i;
1055    int num;
1056  
1057    if (!number) {
1058      number = &num;
1059      num = get_number(&name);
1060    }
1061  
1062    /* JE 7/18/94 :-) :-) */
1063    if (!str_cmp(name, "self") || !str_cmp(name, "me"))
1064      return (ch);
1065  
1066    /* 0.<name> means PC with name */
1067    if (*number == 0)
1068      return (get_player_vis(ch, name, NULL, FIND_CHAR_ROOM));
1069  
1070    for (i = world[IN_ROOM(ch)].people; i && *number; i = i->next_in_room)
1071      if (isname(name, i->player.name))
1072        if (CAN_SEE(ch, i))
1073  	if (--(*number) == 0)
1074  	  return (i);
1075  
1076    return (NULL);
1077  }
1078  
1079  
1080  struct char_data *get_char_world_vis(struct char_data *ch, char *name, int *number)
1081  {
1082    struct char_data *i;
1083    int num;
1084  
1085    if (!number) {
1086      number = &num;
1087      num = get_number(&name);
1088    }
1089  
1090    if ((i = get_char_room_vis(ch, name, number)) != NULL)
1091      return (i);
1092  
1093    if (*number == 0)
1094      return get_player_vis(ch, name, NULL, 0);
1095  
1096    for (i = character_list; i && *number; i = i->next) {
1097      if (IN_ROOM(ch) == IN_ROOM(i))
1098        continue;
1099      if (!isname(name, i->player.name))
1100        continue;
1101      if (!CAN_SEE(ch, i))
1102        continue;
1103      if (--(*number) != 0)
1104        continue;
1105  
1106      return (i);
1107    }
1108    return (NULL);
1109  }
1110  
1111  
1112  struct char_data *get_char_vis(struct char_data *ch, char *name, int *number, int where)
1113  {
1114    if (where == FIND_CHAR_ROOM)
1115      return get_char_room_vis(ch, name, number);
1116    else if (where == FIND_CHAR_WORLD)
1117      return get_char_world_vis(ch, name, number);
1118    else
1119      return (NULL);
1120  }
1121  
1122  
1123  struct obj_data *get_obj_in_list_vis(struct char_data *ch, char *name, int *number, struct obj_data *list)
1124  {
1125    struct obj_data *i;
1126    int num;
1127  
1128    if (!number) {
1129      number = &num;
1130      num = get_number(&name);
1131    }
1132  
1133    if (*number == 0)
1134      return (NULL);
1135  
1136    for (i = list; i && *number; i = i->next_content)
1137      if (isname(name, i->name))
1138        if (CAN_SEE_OBJ(ch, i))
1139  	if (--(*number) == 0)
1140  	  return (i);
1141  
1142    return (NULL);
1143  }
1144  
1145  
1146  /* search the entire world for an object, and return a pointer  */
1147  struct obj_data *get_obj_vis(struct char_data *ch, char *name, int *number)
1148  {
1149    struct obj_data *i;
1150    int num;
1151  
1152    if (!number) {
1153      number = &num;
1154      num = get_number(&name);
1155    }
1156  
1157    if (*number == 0)
1158      return (NULL);
1159  
1160    /* scan items carried */
1161    if ((i = get_obj_in_list_vis(ch, name, number, ch->carrying)) != NULL)
1162      return (i);
1163  
1164    /* scan room */
1165    if ((i = get_obj_in_list_vis(ch, name, number, world[IN_ROOM(ch)].contents)) != NULL)
1166      return (i);
1167  
1168    /* ok.. no luck yet. scan the entire obj list   */
1169    for (i = object_list; i && *number; i = i->next)
1170      if (isname(name, i->name))
1171        if (CAN_SEE_OBJ(ch, i))
1172  	if (--(*number) == 0)
1173  	  return (i);
1174  
1175    return (NULL);
1176  }
1177  
1178  
1179  struct obj_data *get_obj_in_equip_vis(struct char_data *ch, char *arg, int *number, struct obj_data *equipment[])
1180  {
1181    int j, num;
1182  
1183    if (!number) {
1184      number = &num;
1185      num = get_number(&arg);
1186    }
1187  
1188    if (*number == 0)
1189      return (NULL);
1190  
1191    for (j = 0; j < NUM_WEARS; j++)
1192      if (equipment[j] && CAN_SEE_OBJ(ch, equipment[j]) && isname(arg, equipment[j]->name))
1193        if (--(*number) == 0)
1194          return (equipment[j]);
1195  
1196    return (NULL);
1197  }
1198  
1199  
1200  int get_obj_pos_in_equip_vis(struct char_data *ch, char *arg, int *number, struct obj_data *equipment[])
1201  {
1202    int j, num;
1203  
1204    if (!number) {
1205      number = &num;
1206      num = get_number(&arg);
1207    }
1208  
1209    if (*number == 0)
1210      return (-1);
1211  
1212    for (j = 0; j < NUM_WEARS; j++)
1213      if (equipment[j] && CAN_SEE_OBJ(ch, equipment[j]) && isname(arg, equipment[j]->name))
1214        if (--(*number) == 0)
1215          return (j);
1216  
1217    return (-1);
1218  }
1219  
1220  
1221  const char *money_desc(int amount)
1222  {
1223    int cnt;
1224    struct {
1225      int limit;
1226      const char *description;
1227    } money_table[] = {
1228      {          1, "a gold coin"				},
1229      {         10, "a tiny pile of gold coins"		},
1230      {         20, "a handful of gold coins"		},
1231      {         75, "a little pile of gold coins"		},
1232      {        200, "a small pile of gold coins"		},
1233      {       1000, "a pile of gold coins"		},
1234      {       5000, "a big pile of gold coins"		},
1235      {      10000, "a large heap of gold coins"		},
1236      {      20000, "a huge mound of gold coins"		},
1237      {      75000, "an enormous mound of gold coins"	},
1238      {     150000, "a small mountain of gold coins"	},
1239      {     250000, "a mountain of gold coins"		},
1240      {     500000, "a huge mountain of gold coins"	},
1241      {    1000000, "an enormous mountain of gold coins"	},
1242      {          0, NULL					},
1243    };
1244  
1245    if (amount <= 0) {
1246      log("SYSERR: Try to create negative or 0 money (%d).", amount);
1247      return (NULL);
1248    }
1249  
1250    for (cnt = 0; money_table[cnt].limit; cnt++)
1251      if (amount <= money_table[cnt].limit)
1252        return (money_table[cnt].description);
1253  
1254    return ("an absolutely colossal mountain of gold coins");
1255  }
1256  
1257  
1258  struct obj_data *create_money(int amount)
1259  {
1260    struct obj_data *obj;
1261    struct extra_descr_data *new_descr;
1262    char buf[200];
1263  
1264    if (amount <= 0) {
1265      log("SYSERR: Try to create negative or 0 money. (%d)", amount);
1266      return (NULL);
1267    }
1268    obj = create_obj();
1269    CREATE(new_descr, struct extra_descr_data, 1);
1270  
1271    if (amount == 1) {
1272      obj->name = strdup("coin gold");
1273      obj->short_description = strdup("a gold coin");
1274      obj->description = strdup("One miserable gold coin is lying here.");
1275      new_descr->keyword = strdup("coin gold");
1276      new_descr->description = strdup("It's just one miserable little gold coin.");
1277    } else {
1278      obj->name = strdup("coins gold");
1279      obj->short_description = strdup(money_desc(amount));
1280      snprintf(buf, sizeof(buf), "%s is lying here.", money_desc(amount));
1281      obj->description = strdup(CAP(buf));
1282  
1283      new_descr->keyword = strdup("coins gold");
1284      if (amount < 10)
1285        snprintf(buf, sizeof(buf), "There are %d coins.", amount);
1286      else if (amount < 100)
1287        snprintf(buf, sizeof(buf), "There are about %d coins.", 10 * (amount / 10));
1288      else if (amount < 1000)
1289        snprintf(buf, sizeof(buf), "It looks to be about %d coins.", 100 * (amount / 100));
1290      else if (amount < 100000)
1291        snprintf(buf, sizeof(buf), "You guess there are, maybe, %d coins.",
1292  	      1000 * ((amount / 1000) + rand_number(0, (amount / 1000))));
1293      else
1294        strcpy(buf, "There are a LOT of coins.");	/* strcpy: OK (is < 200) */
1295      new_descr->description = strdup(buf);
1296    }
1297  
1298    new_descr->next = NULL;
1299    obj->ex_description = new_descr;
1300  
1301    GET_OBJ_TYPE(obj) = ITEM_MONEY;
1302    GET_OBJ_WEAR(obj) = ITEM_WEAR_TAKE;
1303    GET_OBJ_VAL(obj, 0) = amount;
1304    GET_OBJ_COST(obj) = amount;
1305    obj->item_number = NOTHING;
1306  
1307    return (obj);
1308  }
1309  
1310  
1311  /* Generic Find, designed to find any object/character
1312   *
1313   * Calling:
1314   *  *arg     is the pointer containing the string to be searched for.
1315   *           This string doesn't have to be a single word, the routine
1316   *           extracts the next word itself.
1317   *  bitv..   All those bits that you want to "search through".
1318   *           Bit found will be result of the function
1319   *  *ch      This is the person that is trying to "find"
1320   *  **tar_ch Will be NULL if no character was found, otherwise points
1321   * **tar_obj Will be NULL if no object was found, otherwise points
1322   *
1323   * The routine used to return a pointer to the next word in *arg (just
1324   * like the one_argument routine), but now it returns an integer that
1325   * describes what it filled in.
1326   */
1327  int generic_find(char *arg, bitvector_t bitvector, struct char_data *ch,
1328  		     struct char_data **tar_ch, struct obj_data **tar_obj)
1329  {
1330    int i, found, number;
1331    char name_val[MAX_INPUT_LENGTH];
1332    char *name = name_val;
1333  
1334    *tar_ch = NULL;
1335    *tar_obj = NULL;
1336  
1337    one_argument(arg, name);
1338  
1339    if (!*name)
1340      return (0);
1341    if (!(number = get_number(&name)))
1342      return (0);
1343  
1344    if (IS_SET(bitvector, FIND_CHAR_ROOM)) {	/* Find person in room */
1345      if ((*tar_ch = get_char_room_vis(ch, name, &number)) != NULL)
1346        return (FIND_CHAR_ROOM);
1347    }
1348  
1349    if (IS_SET(bitvector, FIND_CHAR_WORLD)) {
1350      if ((*tar_ch = get_char_world_vis(ch, name, &number)) != NULL)
1351        return (FIND_CHAR_WORLD);
1352    }
1353  
1354    if (IS_SET(bitvector, FIND_OBJ_EQUIP)) {
1355      for (found = FALSE, i = 0; i < NUM_WEARS && !found; i++)
1356        if (GET_EQ(ch, i) && isname(name, GET_EQ(ch, i)->name) && --number == 0) {
1357  	*tar_obj = GET_EQ(ch, i);
1358  	found = TRUE;
1359        }
1360      if (found)
1361        return (FIND_OBJ_EQUIP);
1362    }
1363  
1364    if (IS_SET(bitvector, FIND_OBJ_INV)) {
1365      if ((*tar_obj = get_obj_in_list_vis(ch, name, &number, ch->carrying)) != NULL)
1366        return (FIND_OBJ_INV);
1367    }
1368  
1369    if (IS_SET(bitvector, FIND_OBJ_ROOM)) {
1370      if ((*tar_obj = get_obj_in_list_vis(ch, name, &number, world[IN_ROOM(ch)].contents)) != NULL)
1371        return (FIND_OBJ_ROOM);
1372    }
1373  
1374    if (IS_SET(bitvector, FIND_OBJ_WORLD)) {
1375      if ((*tar_obj = get_obj_vis(ch, name, &number)))
1376        return (FIND_OBJ_WORLD);
1377    }
1378  
1379    return (0);
1380  }
1381  
1382  
1383  /* a function to scan for "all" or "all.x" */
1384  int find_all_dots(char *arg)
1385  {
1386    if (!strcmp(arg, "all"))
1387      return (FIND_ALL);
1388    else if (!strncmp(arg, "all.", 4)) {
1389      strcpy(arg, arg + 4);	/* strcpy: OK (always less) */
1390      return (FIND_ALLDOT);
1391    } else
1392      return (FIND_INDIV);
1393  }