/* ************************************************************************ * File: handler.c Part of CircleMUD * * Usage: internal funcs: moving and finding chars/objs * * * * All rights reserved. See license.doc for complete information. * * * * Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University * * CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. * ************************************************************************ */ #include "conf.h" #include "sysdep.h" #include "structs.h" #include "utils.h" #include "character.h" #include "comm.h" #include "db.h" #include "handler.h" #include "interpreter.h" #include "spells.h" #include "log.h" #include "room.h" #include "item.h" /* local functions */ int apply_ac(charData_t *ch, int eq_pos); void update_object(itemData_t *obj, int use); void update_char_objects(charData_t *ch); /* external functions */ void remove_follower(charData_t *ch); char *fname(const char *namelist) { static char holder[30]; char *point; for (point = holder; isalpha(*namelist); namelist++, point++) *point = *namelist; *point = '\0'; return (holder); } bool isfullname(const char *str, const char *namelist) { const char *curname, *curstr; curname = namelist; for (;;) { for (curstr = str;; curstr++, curname++) { if (!*curstr && !isalpha(*curname)) return (TRUE); if (!*curname) return (FALSE); if (!*curstr || *curname == ' ') break; if (LOWER(*curstr) != LOWER(*curname)) break; } /* skip to next name */ for (; isalpha(*curname); curname++); if (!*curname) return (FALSE); curname++; /* first char of new name */ } } int isname(const char *str, const char *namelist) { if (str == NULL) { log("isname(): invalid 'str' string."); } else if (namelist == NULL) { log("isname(): invalid 'namelist' string."); } else { /* Declare a buffer to copy the name list. */ char buf[MAX_STRING_LENGTH]; /* Declare an iterator variable. */ register char *p = NULL; /* Copy the name list because strtok is destructive. */ strlcpy(buf, namelist, MAX_INPUT_LENGTH); /* Iterate the copied name list searching for matches. */ for (p = strtok(buf, " \t"); p && *p != '\0'; p = strtok(NULL, " \t")) { if (p && is_abbrev(str, p)) return (TRUE); } } return (FALSE); } void effectData_modify(charData_t *ch, byte loc, sbyte mod, bitvector_t bitv, bool add) { if (add) SET_BIT(AFF_FLAGS(ch), bitv); else { REMOVE_BIT(AFF_FLAGS(ch), bitv); mod = -mod; } switch (loc) { case APPLY_NONE: break; case APPLY_STR: GET_STR(ch) += mod; break; case APPLY_DEX: GET_DEX(ch) += mod; break; case APPLY_INT: GET_INT(ch) += mod; break; case APPLY_WIS: GET_WIS(ch) += mod; break; case APPLY_CON: GET_CON(ch) += mod; break; case APPLY_CHA: GET_CHA(ch) += mod; break; case APPLY_CLASS: /* ??? GET_CLASS(ch) += mod; */ break; /* * My personal thoughts on these two would be to set the person to the * value of the apply. That way you won't have to worry about people * making +1 level things to be imp (you restrict anything that gives * immortal level of course). It also makes more sense to set someone * to a class rather than adding to the class number. -gg */ case APPLY_LEVEL: /* ??? GET_LEVEL(ch) += mod; */ break; case APPLY_AGE: ch->player.time.birth -= (mod * SECS_PER_MUD_YEAR); break; case APPLY_WEIGHT: GET_WEIGHT(ch) += mod; break; case APPLY_HEIGHT: GET_HEIGHT(ch) += mod; break; case APPLY_MANA: GET_MAX_MANA(ch) += mod; break; case APPLY_HIT: GET_MAX_HIT(ch) += mod; break; case APPLY_MOVE: GET_MAX_MOVE(ch) += mod; break; case APPLY_GOLD: break; case APPLY_EXP: break; case APPLY_AC: GET_AC(ch) += mod; break; case APPLY_HITROLL: GET_HITROLL(ch) += mod; break; case APPLY_DAMROLL: GET_DAMROLL(ch) += mod; break; case APPLY_SAVING_PARA: GET_SAVE(ch, SAVING_PARA) += mod; break; case APPLY_SAVING_ROD: GET_SAVE(ch, SAVING_ROD) += mod; break; case APPLY_SAVING_PETRI: GET_SAVE(ch, SAVING_PETRI) += mod; break; case APPLY_SAVING_BREATH: GET_SAVE(ch, SAVING_BREATH) += mod; break; case APPLY_SAVING_SPELL: GET_SAVE(ch, SAVING_SPELL) += mod; break; default: log("SYSERR: Unknown apply adjust %d attempt (%s, effectData_modify).", loc, __FILE__); break; } /* switch */ } /* This updates a character by subtracting everything he is affected by */ /* restoring original abilities, and then affecting all again */ void effectData_total(charData_t *ch) { effectData_t *af; int i, j; for (i = 0; i < NUM_WEARS; i++) { if (GET_EQ(ch, i)) for (j = 0; j < MAX_ITEM_AFFECT; j++) effectData_modify(ch, GET_EQ(ch, i)->affected[j].location, GET_EQ(ch, i)->affected[j].modifier, GET_ITEM_AFFECT(GET_EQ(ch, i)), FALSE); } for (af = ch->affected; af; af = af->next) effectData_modify(ch, af->location, af->modifier, af->bitvector, FALSE); ch->aff_abils = ch->real_abils; for (i = 0; i < NUM_WEARS; i++) { if (GET_EQ(ch, i)) for (j = 0; j < MAX_ITEM_AFFECT; j++) effectData_modify(ch, GET_EQ(ch, i)->affected[j].location, GET_EQ(ch, i)->affected[j].modifier, GET_ITEM_AFFECT(GET_EQ(ch, i)), TRUE); } for (af = ch->affected; af; af = af->next) effectData_modify(ch, af->location, af->modifier, af->bitvector, TRUE); /* Make certain values are between 0..25, not < 0 and not > 25! */ i = (IS_NPC(ch) || GET_AUTH(ch) >= AUTH_OWNER) ? 25 : 18; GET_DEX(ch) = MAX(0, MIN(GET_DEX(ch), i)); GET_INT(ch) = MAX(0, MIN(GET_INT(ch), i)); GET_WIS(ch) = MAX(0, MIN(GET_WIS(ch), i)); GET_CON(ch) = MAX(0, MIN(GET_CON(ch), i)); GET_CHA(ch) = MAX(0, MIN(GET_CHA(ch), i)); GET_STR(ch) = MAX(0, GET_STR(ch)); if (IS_NPC(ch)) { GET_STR(ch) = MIN(GET_STR(ch), i); } else { if (GET_STR(ch) > 18) { i = GET_ADD(ch) + ((GET_STR(ch) - 18) * 10); GET_ADD(ch) = MIN(i, 100); GET_STR(ch) = 18; } } } /* Insert an affect_type in a char_data structure Automatically sets apropriate bits and apply's */ void effectData_toChar(charData_t *ch, effectData_t *af) { effectData_t *affected_alloc; CREATE(affected_alloc, effectData_t, 1); *affected_alloc = *af; affected_alloc->next = ch->affected; ch->affected = affected_alloc; effectData_modify(ch, af->location, af->modifier, af->bitvector, TRUE); effectData_total(ch); } /* * Remove an affected_type structure from a char (called when duration * reaches zero). Pointer *af must never be NIL! Frees mem and calls * affect_location_apply */ void effectData_remove(charData_t *ch, effectData_t *af) { effectData_t *temp; if (ch->affected == NULL) { core_dump(); return; } effectData_modify(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); effectData_total(ch); } /* Call effectData_remove with every spell of spelltype "skill" */ void effectData_fromChar(charData_t *ch, int type) { effectData_t *hjp, *next; for (hjp = ch->affected; hjp; hjp = next) { next = hjp->next; if (hjp->type == type) effectData_remove(ch, hjp); } } /* * Return TRUE if a char is affected by a spell (SPELL_XXX), * FALSE indicates not affected. */ bool affected_by_spell(charData_t *ch, int type) { effectData_t *hjp; for (hjp = ch->affected; hjp; hjp = hjp->next) if (hjp->type == type) return (TRUE); return (FALSE); } void effectData_join(charData_t *ch, effectData_t *af, bool add_dur, bool avg_dur, bool add_mod, bool avg_mod) { effectData_t *hjp, *next; bool found = FALSE; for (hjp = ch->affected; !found && hjp; hjp = next) { next = hjp->next; if ((hjp->type == af->type) && (hjp->location == af->location)) { if (add_dur) af->duration += hjp->duration; if (avg_dur) af->duration /= 2; if (add_mod) af->modifier += hjp->modifier; if (avg_mod) af->modifier /= 2; effectData_remove(ch, hjp); effectData_toChar(ch, af); found = TRUE; } } if (!found) effectData_toChar(ch, af); } /* give an object to a char */ void itemData_toChar(itemData_t *object, charData_t *ch) { if (object && ch) { object->nextContent = ch->carrying; ch->carrying = object; object->carriedBy = ch; IN_ROOM(object) = NULL; IS_CARRYING_W(ch) += GET_ITEM_WEIGHT(object); IS_CARRYING_N(ch)++; /* set flag for crash-save system, but not on mobs! */ if (!IS_NPC(ch)) SET_BIT(PLR_FLAGS(ch), PLR_CRASH); } else log("SYSERR: NULL obj (%p) or char (%p) passed to itemData_toChar.", object, ch); } /* take an object from a char */ void itemData_fromChar(itemData_t *object) { itemData_t *temp; if (object == NULL) { log("SYSERR: NULL object passed to itemData_fromChar."); return; } REMOVE_FROM_LIST(object, object->carriedBy->carrying, nextContent); /* set flag for crash-save system, but not on mobs! */ if (!IS_NPC(object->carriedBy)) SET_BIT(PLR_FLAGS(object->carriedBy), PLR_CRASH); IS_CARRYING_W(object->carriedBy) -= GET_ITEM_WEIGHT(object); IS_CARRYING_N(object->carriedBy)--; object->carriedBy = NULL; object->nextContent = NULL; } /* Return the effect of a piece of armor in position eq_pos */ int apply_ac(charData_t *ch, int eq_pos) { int factor; if (GET_EQ(ch, eq_pos) == NULL) { core_dump(); return (0); } if (!(GET_ITEM_TYPE(GET_EQ(ch, eq_pos)) == ITEM_ARMOR)) return (0); switch (eq_pos) { case WEAR_BODY: factor = 3; break; /* 30% */ case WEAR_HEAD: factor = 2; break; /* 20% */ case WEAR_LEGS: factor = 2; break; /* 20% */ default: factor = 1; break; /* all others 10% */ } return (factor * GET_ITEM_VAL(GET_EQ(ch, eq_pos), 0)); } bool invalid_align(charData_t *ch, itemData_t *obj) { if (ITEM_FLAGGED(obj, ITEM_ANTI_EVIL) && IS_EVIL(ch)) return (TRUE); if (ITEM_FLAGGED(obj, ITEM_ANTI_GOOD) && IS_GOOD(ch)) return (TRUE); if (ITEM_FLAGGED(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch)) return (TRUE); return (FALSE); } int get_number(char **name) { int i; char *ppos; char number[MAX_INPUT_LENGTH]; *number = '\0'; if ((ppos = strchr(*name, '.')) != NULL) { *ppos++ = '\0'; strlcpy(number, *name, sizeof(number)); strcpy(*name, ppos); /* strcpy: OK (always smaller) */ for (i = 0; *(number + i); i++) if (!isdigit(*(number + i))) return (0); return (atoi(number)); } return (1); } /* search a room for a char, and return a pointer if found.. */ charData_t *get_char_room(char *name, int *number, roomData_t *room) { charData_t *i; int num; if (!number) { number = # num = get_number(&name); } if (*number == 0) return (NULL); for (i = room->people; i && *number; i = i->next_in_room) if (isname(name, i->player.name)) if (--(*number) == 0) return (i); return (NULL); } /* search all over the world for a char num, and return a pointer if found */ charData_t *get_char_num(mobileVnum_t nr) { /* charData_t *i; for (i = character_list; i; i = i->next) if (GET_MOB_RNUM(i) == nr) return (i); */ return (NULL); } /* put an object in a room */ void itemData_toRoom(itemData_t *object, roomData_t *room) { if (!object || room == NULL) log("SYSERR: Illegal value(s) passed to itemData_toRoom."); else { object->nextContent = room->contents; room->contents = object; IN_ROOM(object) = room; object->carriedBy = NULL; if (ROOM_FLAGGED(room, ROOM_HOUSE)) SET_BIT(ROOM_FLAGS(room), ROOM_HOUSE_CRASH); } } /* Take an object from a room */ void itemData_fromRoom(itemData_t *object) { itemData_t *temp; if (!object || IN_ROOM(object) == NULL) { log("SYSERR: NULL object (%p) or obj not in a room passed to itemData_fromRoom", object); return; } REMOVE_FROM_LIST(object, object->room->contents, nextContent); if (ROOM_FLAGGED(IN_ROOM(object), ROOM_HOUSE)) SET_BIT(ROOM_FLAGS(IN_ROOM(object)), ROOM_HOUSE_CRASH); IN_ROOM(object) = NULL; object->nextContent = NULL; } /* put an object in an object (quaint) */ void itemData_toItem(itemData_t *obj, itemData_t *obj_to) { itemData_t *tmp_obj; if (!obj || !obj_to || obj == obj_to) { log("SYSERR: NULL object (%p) or same source (%p) and target (%p) obj passed to itemData_toItem.", obj, obj, obj_to); return; } obj->nextContent = obj_to->contains; obj_to->contains = obj; obj->inObj = obj_to; for (tmp_obj = obj->inObj; tmp_obj->inObj; tmp_obj = tmp_obj->inObj) GET_ITEM_WEIGHT(tmp_obj) += GET_ITEM_WEIGHT(obj); /* top level object. Subtract weight from inventory if necessary. */ GET_ITEM_WEIGHT(tmp_obj) += GET_ITEM_WEIGHT(obj); if (tmp_obj->carriedBy) IS_CARRYING_W(tmp_obj->carriedBy) += GET_ITEM_WEIGHT(obj); } /* remove an object from an object */ void itemData_fromItem(itemData_t *obj) { itemData_t *temp, *obj_from; if (obj->inObj == NULL) { log("SYSERR: (%s): trying to illegally extract obj from obj.", __FILE__); return; } obj_from = obj->inObj; REMOVE_FROM_LIST(obj, obj_from->contains, nextContent); /* Subtract weight from containers container */ for (temp = obj->inObj; temp->inObj; temp = temp->inObj) GET_ITEM_WEIGHT(temp) -= GET_ITEM_WEIGHT(obj); /* Subtract weight from char that carries the object */ GET_ITEM_WEIGHT(temp) -= GET_ITEM_WEIGHT(obj); if (temp->carriedBy) IS_CARRYING_W(temp->carriedBy) -= GET_ITEM_WEIGHT(obj); obj->inObj = NULL; obj->nextContent = NULL; } /* Set all carriedBy to point to new owner */ void object_list_new_owner(itemData_t *list, charData_t *ch) { if (list) { object_list_new_owner(list->contains, ch); object_list_new_owner(list->nextContent, ch); list->carriedBy = ch; } } /* Extract an object from the world */ void itemData_extract(itemData_t *obj) { itemData_t *temp; if (obj->wornBy != NULL) if (char_unequipItem(obj->wornBy, obj->wornOn) != obj) log("SYSERR: Inconsistent wornBy and worn_on pointers!!"); if (IN_ROOM(obj) != NULL) itemData_fromRoom(obj); else if (obj->carriedBy) itemData_fromChar(obj); else if (obj->inObj) itemData_fromItem(obj); /* Get rid of the contents of the object, as well. */ while (obj->contains) itemData_extract(obj->contains); REMOVE_FROM_LIST(obj, object_list, next); if (obj->prototype != NULL) (obj->prototype->number)--; free_obj(obj); } void update_object(itemData_t *obj, int use) { if (GET_ITEM_TIMER(obj) > 0) GET_ITEM_TIMER(obj) -= use; if (obj->contains) update_object(obj->contains, use); if (obj->nextContent) update_object(obj->nextContent, use); } void update_char_objects(charData_t *ch) { int i; if (GET_EQ(ch, WEAR_LIGHT) != NULL) if (GET_ITEM_TYPE(GET_EQ(ch, WEAR_LIGHT)) == ITEM_LIGHT) if (GET_ITEM_VAL(GET_EQ(ch, WEAR_LIGHT), 2) > 0) { i = --GET_ITEM_VAL(GET_EQ(ch, WEAR_LIGHT), 2); if (i == 1) { send_to_char(ch, "Your light begins to flicker and fade.\r\n"); act("$n's light begins to flicker and fade.", FALSE, ch, 0, 0, TO_ROOM); } else if (i == 0) { send_to_char(ch, "Your light sputters out and dies.\r\n"); act("$n's light sputters out and dies.", FALSE, ch, 0, 0, TO_ROOM); ch->room->light--; } } for (i = 0; i < NUM_WEARS; i++) if (GET_EQ(ch, i)) update_object(GET_EQ(ch, i), 2); if (ch->carrying) update_object(ch->carrying, 1); } /* *********************************************************************** * Here follows high-level versions of some earlier routines, ie functions* * which incorporate the actual player-data *. *********************************************************************** */ charData_t *get_player_vis(charData_t *ch, char *name, int *number, int inroom) { charData_t *i; int num; if (!number) { number = # num = get_number(&name); } for (i = character_list; i; i = i->next) { if (IS_NPC(i)) continue; if (inroom == FIND_CHAR_ROOM && IN_ROOM(i) != IN_ROOM(ch)) continue; if (str_cmp(i->player.name, name)) /* If not same, continue */ continue; if (!CAN_SEE(ch, i)) continue; if (--(*number) != 0) continue; return (i); } return (NULL); } charData_t *get_char_room_vis(charData_t *ch, char *name, int *number) { charData_t *i; int num; if (!number) { number = # num = get_number(&name); } /* JE 7/18/94 :-) :-) */ if (!str_cmp(name, "self") || !str_cmp(name, "me")) return (ch); /* 0.<name> means PC with name */ if (*number == 0) return (get_player_vis(ch, name, NULL, FIND_CHAR_ROOM)); for (i = ch->room->people; i && *number; i = i->next_in_room) if (isname(name, i->player.name)) if (CAN_SEE(ch, i)) if (--(*number) == 0) return (i); return (NULL); } charData_t *get_char_world_vis(charData_t *ch, char *name, int *number) { charData_t *i; int num; if (!number) { number = # num = get_number(&name); } if ((i = get_char_room_vis(ch, name, number)) != NULL) return (i); if (*number == 0) return get_player_vis(ch, name, NULL, 0); for (i = character_list; i && *number; i = i->next) { if (IN_ROOM(ch) == IN_ROOM(i)) continue; if (!isname(name, i->player.name)) continue; if (!CAN_SEE(ch, i)) continue; if (--(*number) != 0) continue; return (i); } return (NULL); } charData_t *get_char_vis(charData_t *ch, char *name, int *number, int where) { if (where == FIND_CHAR_ROOM) return get_char_room_vis(ch, name, number); else if (where == FIND_CHAR_WORLD) return get_char_world_vis(ch, name, number); else return (NULL); } itemData_t *get_item_in_list_vis(charData_t *ch, char *name, int *number, itemData_t *list) { itemData_t *i; int num; if (!number) { number = # num = get_number(&name); } if (*number == 0) return (NULL); for (i = list; i && *number; i = i->nextContent) if (isname(name, i->name)) if (CAN_SEE_ITEM(ch, i)) if (--(*number) == 0) return (i); return (NULL); } /* search the entire world for an object, and return a pointer */ itemData_t *get_item_vis(charData_t *ch, char *name, int *number) { itemData_t *i; int num; if (!number) { number = # num = get_number(&name); } if (*number == 0) return (NULL); /* scan items carried */ if ((i = get_item_in_list_vis(ch, name, number, ch->carrying)) != NULL) return (i); /* scan room */ if ((i = get_item_in_list_vis(ch, name, number, ch->room->contents)) != NULL) return (i); /* ok.. no luck yet. scan the entire obj list */ for (i = object_list; i && *number; i = i->next) if (isname(name, i->name)) if (CAN_SEE_ITEM(ch, i)) if (--(*number) == 0) return (i); return (NULL); } itemData_t *get_item_in_equip_vis(charData_t *ch, char *arg, int *number, itemData_t *equipment[]) { int j, num; if (!number) { number = # num = get_number(&arg); } if (*number == 0) return (NULL); for (j = 0; j < NUM_WEARS; j++) if (equipment[j] && CAN_SEE_ITEM(ch, equipment[j]) && isname(arg, equipment[j]->name)) if (--(*number) == 0) return (equipment[j]); return (NULL); } int get_item_pos_in_equip_vis(charData_t *ch, char *arg, int *number, itemData_t *equipment[]) { int j, num; if (!number) { number = # num = get_number(&arg); } if (*number == 0) return (-1); for (j = 0; j < NUM_WEARS; j++) if (equipment[j] && CAN_SEE_ITEM(ch, equipment[j]) && isname(arg, equipment[j]->name)) if (--(*number) == 0) return (j); return (-1); } const char *money_desc(int amount) { int cnt; struct { int limit; const char *description; } money_table[] = { { 1, "a gold coin" }, { 10, "a tiny pile of gold coins" }, { 20, "a handful of gold coins" }, { 75, "a little pile of gold coins" }, { 200, "a small pile of gold coins" }, { 1000, "a pile of gold coins" }, { 5000, "a big pile of gold coins" }, { 10000, "a large heap of gold coins" }, { 20000, "a huge mound of gold coins" }, { 75000, "an enormous mound of gold coins" }, { 150000, "a small mountain of gold coins" }, { 250000, "a mountain of gold coins" }, { 500000, "a huge mountain of gold coins" }, { 1000000, "an enormous mountain of gold coins" }, { 0, NULL }, }; if (amount <= 0) { log("SYSERR: Try to create negative or 0 money (%d).", amount); return (NULL); } for (cnt = 0; money_table[cnt].limit; cnt++) if (amount <= money_table[cnt].limit) return (money_table[cnt].description); return ("an absolutely colossal mountain of gold coins"); } itemData_t *create_money(int amount) { itemData_t *obj; extraDescData_t *new_descr; char buf[200]; if (amount <= 0) { log("SYSERR: Try to create negative or 0 money. (%d)", amount); return (NULL); } obj = create_obj(); CREATE(new_descr, extraDescData_t, 1); if (amount == 1) { obj->name = strdup("coin gold"); obj->shortDescription = strdup("a gold coin"); obj->description = strdup("One miserable gold coin is lying here."); new_descr->keyword = strdup("coin gold"); new_descr->description = strdup("It's just one miserable little gold coin."); } else { obj->name = strdup("coins gold"); obj->shortDescription = strdup(money_desc(amount)); snprintf(buf, sizeof(buf), "%s is lying here.", money_desc(amount)); obj->description = strdup(CAP(buf)); new_descr->keyword = strdup("coins gold"); if (amount < 10) snprintf(buf, sizeof(buf), "There are %d coins.", amount); else if (amount < 100) snprintf(buf, sizeof(buf), "There are about %d coins.", 10 * (amount / 10)); else if (amount < 1000) snprintf(buf, sizeof(buf), "It looks to be about %d coins.", 100 * (amount / 100)); else if (amount < 100000) snprintf(buf, sizeof(buf), "You guess there are, maybe, %d coins.", 1000 * ((amount / 1000) + rand_number(0, (amount / 1000)))); else strcpy(buf, "There are a LOT of coins."); /* strcpy: OK (is < 200) */ new_descr->description = strdup(buf); } new_descr->next = NULL; obj->exDescription = new_descr; GET_ITEM_TYPE(obj) = ITEM_MONEY; GET_ITEM_WEAR(obj) = ITEM_WEAR_TAKE; GET_ITEM_VAL(obj, 0) = amount; GET_ITEM_COST(obj) = amount; obj->vnum = NOTHING; obj->prototype = NULL; return (obj); } /* Generic Find, designed to find any object/character * * Calling: * *arg is the pointer containing the string to be searched for. * This string doesn't have to be a single word, the routine * extracts the next word itself. * bitv.. All those bits that you want to "search through". * Bit found will be result of the function * *ch This is the person that is trying to "find" * **tar_ch Will be NULL if no character was found, otherwise points * **tar_obj Will be NULL if no object was found, otherwise points * * The routine used to return a pointer to the next word in *arg (just * like the one_argument routine), but now it returns an integer that * describes what it filled in. */ int generic_find(char *arg, bitvector_t bitvector, charData_t *ch, charData_t **tar_ch, itemData_t **tar_obj) { int i, found, number; char name_val[MAX_INPUT_LENGTH]; char *name = name_val; *tar_ch = NULL; *tar_obj = NULL; one_argument(arg, name); if (!*name) return (0); if (!(number = get_number(&name))) return (0); if (IS_SET(bitvector, FIND_CHAR_ROOM)) { /* Find person in room */ if ((*tar_ch = get_char_room_vis(ch, name, &number)) != NULL) return (FIND_CHAR_ROOM); } if (IS_SET(bitvector, FIND_CHAR_WORLD)) { if ((*tar_ch = get_char_world_vis(ch, name, &number)) != NULL) return (FIND_CHAR_WORLD); } if (IS_SET(bitvector, FIND_ITEM_EQUIP)) { for (found = FALSE, i = 0; i < NUM_WEARS && !found; i++) if (GET_EQ(ch, i) && isname(name, GET_EQ(ch, i)->name) && --number == 0) { *tar_obj = GET_EQ(ch, i); found = TRUE; } if (found) return (FIND_ITEM_EQUIP); } if (IS_SET(bitvector, FIND_ITEM_INV)) { if ((*tar_obj = get_item_in_list_vis(ch, name, &number, ch->carrying)) != NULL) return (FIND_ITEM_INV); } if (IS_SET(bitvector, FIND_ITEM_ROOM)) { if ((*tar_obj = get_item_in_list_vis(ch, name, &number, ch->room->contents)) != NULL) return (FIND_ITEM_ROOM); } if (IS_SET(bitvector, FIND_ITEM_WORLD)) { if ((*tar_obj = get_item_vis(ch, name, &number))) return (FIND_ITEM_WORLD); } return (0); } /* a function to scan for "all" or "all.x" */ int find_all_dots(char *arg) { if (!strcmp(arg, "all")) return (FIND_ALL); else if (!strncmp(arg, "all.", 4)) { strcpy(arg, arg + 4); /* strcpy: OK (always less) */ return (FIND_ALLDOT); } else return (FIND_INDIV); }