//***************************************************************************** // // handler.c // // this file contains implementations for all of the "handling" functions; // functions that move things from place to place. e.g. adding and removing // characters from rooms, as well as objects and the like. // //***************************************************************************** #include "mud.h" #include "utils.h" #include "world.h" #include "room.h" #include "exit.h" #include "extra_descs.h" #include "character.h" #include "object.h" #include "body.h" #include "inform.h" #include "hooks.h" #include "handler.h" #include "commands.h" //***************************************************************************** // mandatory modules //***************************************************************************** #include "items/items.h" #include "items/container.h" #include "items/worn.h" #include "scripts/scripts.h" #include "scripts/pymud.h" //***************************************************************************** // obj/char from/to functions //***************************************************************************** void exit_exist(EXIT_DATA *exit) { propertyTablePut(exit_table, exit); } bool exit_exists(EXIT_DATA *exit) { return propertyTableIn(exit_table, exitGetUID(exit)); } void exit_to_game(EXIT_DATA *exit) { if(!exit_exists(exit)) exit_exist(exit); } void obj_exist(OBJ_DATA *obj) { propertyTablePut(obj_table, obj); // also add all contents if(listSize(objGetContents(obj)) > 0) { LIST_ITERATOR *cont_i = newListIterator(objGetContents(obj)); OBJ_DATA *cont = NULL; ITERATE_LIST(cont, cont_i) obj_exist(cont); deleteListIterator(cont_i); } } bool obj_exists(OBJ_DATA *obj) { return propertyTableIn(obj_table, objGetUID(obj)); } void obj_to_game(OBJ_DATA *obj) { if(!obj_exists(obj)) obj_exist(obj); listPut(object_list, obj); // execute all of our to_game hooks hookRun("obj_to_game", hookBuildInfo("obj", obj)); // also add all contents if(listSize(objGetContents(obj)) > 0) { LIST_ITERATOR *cont_i = newListIterator(objGetContents(obj)); OBJ_DATA *cont = NULL; ITERATE_LIST(cont, cont_i) obj_to_game(cont); deleteListIterator(cont_i); } } void room_exist(ROOM_DATA *room) { propertyTablePut(room_table, room); // add contents if(listSize(roomGetContents(room)) > 0) { LIST_ITERATOR *cont_i = newListIterator(roomGetContents(room)); OBJ_DATA *cont = NULL; ITERATE_LIST(cont, cont_i) obj_exist(cont); deleteListIterator(cont_i); } // add its people if(listSize(roomGetCharacters(room)) > 0) { LIST_ITERATOR *ch_i = newListIterator(roomGetCharacters(room)); CHAR_DATA *ch = NULL; ITERATE_LIST(ch, ch_i) char_exist(ch); deleteListIterator(ch_i); } // add its exits LIST *ex_list = roomGetExitNames(room); LIST_ITERATOR *ex_i = newListIterator(ex_list); char *dir = NULL; ITERATE_LIST(dir, ex_i) { exit_exist(roomGetExit(room, dir)); } deleteListIterator(ex_i); deleteListWith(ex_list, free); } bool room_exists(ROOM_DATA *room) { return propertyTableIn(room_table, roomGetUID(room)); } void room_to_game(ROOM_DATA *room) { if(!room_exists(room)) room_exist(room); listPut(room_list, room); // execute all of our to_game hooks hookRun("room_to_game", hookBuildInfo("rm", room)); // add contents if(listSize(roomGetContents(room)) > 0) { LIST_ITERATOR *cont_i = newListIterator(roomGetContents(room)); OBJ_DATA *cont = NULL; ITERATE_LIST(cont, cont_i) obj_to_game(cont); deleteListIterator(cont_i); } // add its people if(listSize(roomGetCharacters(room)) > 0) { LIST_ITERATOR *ch_i = newListIterator(roomGetCharacters(room)); CHAR_DATA *ch = NULL; ITERATE_LIST(ch, ch_i) char_to_game(ch); deleteListIterator(ch_i); } // add its exits, and their room table commands as neccessary LIST *ex_list = roomGetExitNames(room); LIST_ITERATOR *ex_i = newListIterator(ex_list); char *dir = NULL; ITERATE_LIST(dir, ex_i) { exit_to_game(roomGetExit(room, dir)); if(get_cmd_move() != NULL && dirGetNum(dir) == DIR_NONE) { CMD_DATA *old_cmd = nearMapRemove(roomGetCmdTable(room), dir); CMD_DATA *cmd = newPyCmd(dir, get_cmd_move(), "player", TRUE); if(old_cmd != NULL) deleteCmd(old_cmd); cmdAddCheck(cmd, chk_can_move); nearMapPut(roomGetCmdTable(room), dir, NULL, cmd); } } deleteListIterator(ex_i); deleteListWith(ex_list, free); } void char_exist(CHAR_DATA *ch) { propertyTablePut(mob_table, ch); // also add inventory if(listSize(charGetInventory(ch)) > 0) { LIST_ITERATOR *inv_i = newListIterator(charGetInventory(ch)); OBJ_DATA *obj = NULL; ITERATE_LIST(obj, inv_i) obj_exist(obj); deleteListIterator(inv_i); } // and equipped items LIST *eq = bodyGetAllEq(charGetBody(ch)); if(listSize(eq) > 0) { LIST_ITERATOR *eq_i = newListIterator(eq); OBJ_DATA *obj = NULL; ITERATE_LIST(obj, eq_i) obj_exist(obj); deleteListIterator(eq_i); } deleteList(eq); } bool char_exists(CHAR_DATA *ch) { return propertyTableIn(mob_table, charGetUID(ch)); } void char_to_game(CHAR_DATA *ch) { if(!char_exists(ch)) char_exist(ch); listPut(mobile_list, ch); // execute all of our to_game hooks hookRun("char_to_game", hookBuildInfo("ch", ch)); // also add inventory if(listSize(charGetInventory(ch)) > 0) { LIST_ITERATOR *inv_i = newListIterator(charGetInventory(ch)); OBJ_DATA *obj = NULL; ITERATE_LIST(obj, inv_i) obj_to_game(obj); deleteListIterator(inv_i); } // and equipped items LIST *eq = bodyGetAllEq(charGetBody(ch)); if(listSize(eq) > 0) { LIST_ITERATOR *eq_i = newListIterator(eq); OBJ_DATA *obj = NULL; ITERATE_LIST(obj, eq_i) obj_to_game(obj); deleteListIterator(eq_i); } deleteList(eq); } void exit_from_game(EXIT_DATA *exit) { propertyTableRemove(exit_table, exitGetUID(exit)); } void obj_from_game(OBJ_DATA *obj) { // go through all of our fromgame hooks hookRun("obj_from_game", hookBuildInfo("obj", obj)); // also remove everything that is contained within the object if(listSize(objGetContents(obj)) > 0) { LIST_ITERATOR *cont_i = newListIterator(objGetContents(obj)); OBJ_DATA *cont = NULL; ITERATE_LIST(cont, cont_i) obj_from_game(cont); deleteListIterator(cont_i); } listRemove(object_list, obj); propertyTableRemove(obj_table, objGetUID(obj)); } void room_from_game(ROOM_DATA *room) { // go through all of our fromgame hooks hookRun("room_from_game", hookBuildInfo("rm", room)); // also remove all the objects contained within the room if(listSize(roomGetContents(room)) > 0) { LIST_ITERATOR *cont_i = newListIterator(roomGetContents(room)); OBJ_DATA *cont = NULL; ITERATE_LIST(cont, cont_i) obj_from_game(cont); deleteListIterator(cont_i); } // and now all of the characters if(listSize(roomGetCharacters(room)) > 0) { LIST_ITERATOR *ch_i = newListIterator(roomGetCharacters(room)); CHAR_DATA *ch = NULL; ITERATE_LIST(ch, ch_i) char_from_game(ch); deleteListIterator(ch_i); } // remove its exits LIST *ex_list = roomGetExitNames(room); LIST_ITERATOR *ex_i = newListIterator(ex_list); char *dir = NULL; ITERATE_LIST(dir, ex_i) exit_from_game(roomGetExit(room, dir)); deleteListIterator(ex_i); deleteListWith(ex_list, free); listRemove(room_list, room); propertyTableRemove(room_table, roomGetUID(room)); } void char_from_game(CHAR_DATA *ch) { // go through all of our fromgame hooks hookRun("char_from_game", hookBuildInfo("ch", ch)); // also remove inventory if(listSize(charGetInventory(ch)) > 0) { LIST_ITERATOR *inv_i = newListIterator(charGetInventory(ch)); OBJ_DATA *obj = NULL; ITERATE_LIST(obj, inv_i) obj_from_game(obj); deleteListIterator(inv_i); } // and equipped items LIST *eq = bodyGetAllEq(charGetBody(ch)); if(listSize(eq) > 0) { LIST_ITERATOR *eq_i = newListIterator(eq); OBJ_DATA *obj = NULL; ITERATE_LIST(obj, eq_i) obj_from_game(obj); deleteListIterator(eq_i); } deleteList(eq); listRemove(mobile_list, ch); propertyTableRemove(mob_table, charGetUID(ch)); } void obj_from_char(OBJ_DATA *obj) { if(objGetCarrier(obj)) { listRemove(charGetInventory(objGetCarrier(obj)), obj); objSetCarrier(obj, NULL); } } void obj_from_obj(OBJ_DATA *obj) { if(objGetContainer(obj)) { listRemove(objGetContents(objGetContainer(obj)), obj); objSetContainer(obj, NULL); } } void obj_from_room(OBJ_DATA *obj) { if(objGetRoom(obj)) { listRemove(roomGetContents(objGetRoom(obj)), obj); objSetRoom(obj, NULL); } } void obj_to_char(OBJ_DATA *obj, CHAR_DATA *ch) { listPut(charGetInventory(ch), obj); objSetCarrier(obj, ch); } void obj_to_obj(OBJ_DATA *obj, OBJ_DATA *to) { listPut(objGetContents(to), obj); objSetContainer(obj, to); } void obj_to_room(OBJ_DATA *obj, ROOM_DATA *room) { listPut(roomGetContents(room), obj); objSetRoom(obj, room); } void char_from_room(CHAR_DATA *ch) { charSetLastRoom(ch, charGetRoom(ch)); roomRemoveChar(charGetRoom(ch), ch); charSetRoom(ch, NULL); } void char_to_room(CHAR_DATA *ch, ROOM_DATA *room) { if(charGetRoom(ch)) char_from_room(ch); roomAddChar(room, ch); charSetRoom(ch, room); } void char_from_furniture(CHAR_DATA *ch) { objRemoveChar(charGetFurniture(ch), ch); charSetFurniture(ch, NULL); } void char_to_furniture(CHAR_DATA *ch, OBJ_DATA *furniture) { if(charGetFurniture(ch)) char_from_furniture(ch); objAddChar(furniture, ch); charSetFurniture(ch, furniture); } //***************************************************************************** // functions related to equipping and unequipping items //***************************************************************************** bool try_equip(CHAR_DATA *ch, OBJ_DATA *obj, const char *wanted_pos, const char *required_pos) { bool success = FALSE; // if we don't need any specific places, try equipping to our wanted spots if(!required_pos || !*required_pos) success = bodyEquipPosnames(charGetBody(ch), obj, wanted_pos); // if we don't want any specific places, equip to whatever is open else if(!wanted_pos || !*wanted_pos) success = bodyEquipPostypes(charGetBody(ch), obj, required_pos); // otherwise, see if the places we want to equip to match what we need, // and also make sure we're not trying to equip the same position twice else if(!dup_keywords_exist(wanted_pos)) { // build lists of what we want and what we need, and compare char *want_type_list = list_postypes(charGetBody(ch), wanted_pos); LIST *want_types = parse_keywords(want_type_list); LIST *need_types = parse_keywords(required_pos); bool match = TRUE; // make sure we have both wanted and needed positions // and then try to match it all up if(listSize(want_types) != listSize(need_types)) match = FALSE; else { LIST_ITERATOR *need_i = newListIterator(need_types); char *one_need = NULL; // now, make sure that each our our needed positions is represented ITERATE_LIST(one_need, need_i) { char *found = listRemoveWith(want_types, one_need, strcasecmp); // if we found it, free the memory. Otherwise, break out and fail if(found == NULL) break; else free(found); } deleteListIterator(need_i); // make sure we accounted for all of our needed positions match = (listSize(want_types) == 0); } // garbage collection if(want_type_list) free(want_type_list); deleteListWith(want_types, free); deleteListWith(need_types, free); // if we didn't run into problems, try equipping if(match == TRUE) success = bodyEquipPosnames(charGetBody(ch), obj, wanted_pos); } if(success == TRUE) objSetWearer(obj, ch); return success; } bool try_unequip(CHAR_DATA *ch, OBJ_DATA *obj) { if(bodyUnequip(charGetBody(ch), obj)) { objSetWearer(obj, NULL); return TRUE; } return FALSE; } // // unequip everything the character is wearing, and put it to his or her inv // void unequip_all(CHAR_DATA *ch) { LIST *eq = bodyGetAllEq(charGetBody(ch)); OBJ_DATA *obj = NULL; while( (obj = listPop(eq)) != NULL) { if(bodyUnequip(charGetBody(ch), obj)) { objSetWearer(obj, NULL); obj_to_char(obj, ch); } } deleteList(eq); } //***************************************************************************** // // Functions related to generic_find() and find_specific() // //***************************************************************************** // // finds the first argument after "arg". return NULL if nothing is found. // the returned string must be freed afterwards // char *after_arg(char *target, char *arg) { int len = strlen(arg); int t_len = strlen(target); int i = 0; // loop through and find our target for(i = 0; i < len - t_len - 1; i++) { // we've found the target, and there's a space after it if(!strncasecmp(arg+i, target, t_len) && isspace(arg[i+t_len])) { // skip up to past the next space(s) i = i + t_len + 1; while(isspace(arg[i])) i++; // find where the next space or string terminator is int j = i+1; while(!(isspace(arg[j]) || arg[j] == '\0')) j++; // make a buffer to hold the word following our target char buf[j-i+1]; strncpy(buf, arg+i, j-i); buf[j-i] = '\0'; return strdup(buf); } } return NULL; } // // finds the first argument after "at". return NULL if nothing is found. // the returned string must be freed afterwards // char *at_arg(char *arg) { return after_arg("at", arg); } // // finds the first argument after "on". return NULL if nothing is found. // the returned string must be freed afterwards // char *on_arg(char *arg) { return after_arg("on", arg); } // // finds the first argument after "in". return NULL if nothing is found. // the returned string must be freed afterwards // char *in_arg(char *arg) { return after_arg("in", arg); } // // Can find: objects and extra descriptions // void *find_on_char(CHAR_DATA *looker, CHAR_DATA *on, int at_count, const char *at, bitvector_t find_types, bitvector_t find_scope, int *found_type) { int count = 0; // see if it's equipment if(IS_SET(find_types, FIND_TYPE_OBJ)) { LIST *equipment = bodyGetAllEq(charGetBody(on)); count += count_objs(looker, equipment, at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); if(count >= at_count) { if(found_type) *found_type = FOUND_OBJ; OBJ_DATA *obj = find_obj(looker, equipment, at_count, at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); deleteList(equipment); return obj; } else deleteList(equipment); } // see if it's an extra description //*********** // FINISH ME //*********** if(found_type) *found_type = FOUND_NONE; return NULL; } // // Can find: extra descriptions, chars // void *find_on_obj(CHAR_DATA *looker, OBJ_DATA *on, int at_count, const char *at, bitvector_t find_types, bitvector_t find_scope, int *found_type) { int count = 0; // see if it's a character if(IS_SET(find_types, FIND_TYPE_CHAR)) { count = count_chars(looker, objGetUsers(on), at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); if(count >= at_count) { if(found_type) *found_type = FOUND_CHAR; return find_char(looker, objGetUsers(on), at_count, at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); } else at_count -= count; } // see if it's an extra description if(IS_SET(find_types, FIND_TYPE_EDESC)) { count = (objGetEdesc(on, at) != NULL); if(count && at_count == 1) { if(found_type) *found_type = FOUND_EDESC; return edescSetGet(objGetEdescs(on), at); } else at_count--; } if(found_type) *found_type = FOUND_NONE; return NULL; } // // Can find: objects and extra descriptions // void *find_in_obj(CHAR_DATA *looker, OBJ_DATA *in, int at_count, const char *at, int on_count, const char *on, bitvector_t find_types, bitvector_t find_scope, int *found_type) { if(found_type) *found_type = FOUND_NONE; // see if we're looking on anything if(on && *on && on_count > 0) { OBJ_DATA *on_obj = find_obj(looker, objGetContents(in), on_count, on, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); if(!on_obj) return NULL; else return find_on_obj(looker, on_obj, at_count, at, find_types, find_scope, found_type); } else { int count = count_objs(looker, objGetContents(in), at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); if(count >= at_count) { if(found_type) *found_type = FOUND_OBJ; return find_obj(looker, objGetContents(in), at_count, at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); } else return NULL; } } LIST *find_all(CHAR_DATA *looker, const char *at, bitvector_t find_types, bitvector_t find_scope, int *found_type) { if(found_type) *found_type = FOUND_LIST; /************************************************************/ /* FIND ALL OBJS */ /************************************************************/ if(find_types == FIND_TYPE_OBJ) { LIST *obj_list = newList(); // get everything from our inventory if(IS_SET(find_scope, FIND_SCOPE_INV)) { LIST *inv_objs = find_all_objs(looker,charGetInventory(looker), at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); OBJ_DATA *obj = NULL; while( (obj = listPop(inv_objs)) != NULL) if(!listIn(obj_list, obj)) listPut(obj_list, obj); deleteList(inv_objs); } // get everything from the room if(IS_SET(find_scope, FIND_SCOPE_ROOM)) { LIST *room_objs = find_all_objs(looker, roomGetContents(charGetRoom(looker)), at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); OBJ_DATA *obj = NULL; while( (obj = listPop(room_objs)) != NULL) if(!listIn(obj_list, obj)) listPut(obj_list, obj); deleteList(room_objs); } // get everything we are wearing if(IS_SET(find_scope, FIND_SCOPE_WORN)) { // we have to get a list of all eq as an intermediary step, and then // delete the list after we search through it again for everything // that we can see. LIST *equipment = bodyGetAllEq(charGetBody(looker)); LIST *eq_objs = find_all_objs(looker, equipment, at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); deleteList(equipment); OBJ_DATA *obj = NULL; while( (obj = listPop(eq_objs)) != NULL) if(!listIn(obj_list, obj)) listPut(obj_list, obj); deleteList(eq_objs); } // get everything in the world if(IS_SET(find_scope, FIND_SCOPE_WORLD)) { LIST *wld_objs = find_all_objs(looker, object_list, at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); OBJ_DATA *obj = NULL; while( (obj = listPop(wld_objs)) != NULL) if(!listIn(obj_list, obj)) listPut(obj_list, obj); deleteList(wld_objs); } // if we didn't find anything, return NULL if(listSize(obj_list) < 1) { deleteList(obj_list); if(found_type) *found_type = FOUND_NONE; return NULL; } else return obj_list; } /************************************************************/ /* FIND ALL CHARS */ /************************************************************/ else if(find_types == FIND_TYPE_CHAR) { LIST *char_list = newList(); // find everyone in the room if(IS_SET(find_scope, FIND_SCOPE_ROOM)) { LIST *room_chars =find_all_chars(looker, roomGetCharacters(charGetRoom(looker)), at, NULL, (IS_SET(find_scope,FIND_SCOPE_VISIBLE))); CHAR_DATA *ch = NULL; while( (ch = listPop(room_chars)) != NULL) if(!listIn(char_list, ch)) listPut(char_list, ch); deleteList(room_chars); } // find everyone in the world if(IS_SET(find_scope, FIND_SCOPE_WORLD)) { LIST *wld_chars = find_all_chars(looker, mobile_list, at, NULL, (IS_SET(find_scope,FIND_SCOPE_VISIBLE))); CHAR_DATA *ch = NULL; while( (ch = listPop(wld_chars)) != NULL) if(!listIn(char_list, ch)) listPut(char_list, ch); deleteList(wld_chars); } // if we didn't find anything, return NULL if(listSize(char_list) < 1) { deleteList(char_list); if(found_type) *found_type = FOUND_NONE; return NULL; } else return char_list; } /************************************************************/ /* FIND ALL EDESCS */ /************************************************************/ else { if(found_type) *found_type = FOUND_NONE; return NULL; } } void *find_one(CHAR_DATA *looker, int at_count, const char *at, bitvector_t find_types, bitvector_t find_scope, int *found_type) { // find what we're looking AT int count = 0; /************************************************************/ /* PERSONAL SEARCHES */ /************************************************************/ // see if its ourself if(IS_SET(find_types, FIND_TYPE_CHAR) && at_count >= 1 && !strcasecmp(at, "self")) { at_count--; if(at_count == 0) { if(found_type) *found_type = FOUND_CHAR; return looker; } } // search our equipment if(IS_SET(find_scope, FIND_SCOPE_WORN) && IS_SET(find_types, FIND_TYPE_OBJ)) { LIST *equipment = bodyGetAllEq(charGetBody(looker)); count = count_objs(looker, equipment, at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); if(count >= at_count) { if(found_type) *found_type = FOUND_OBJ; OBJ_DATA *obj = find_obj(looker, equipment, at_count, at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); deleteList(equipment); return obj; } else { deleteList(equipment); at_count -= count; } } // seach our inventory if(IS_SET(find_scope, FIND_SCOPE_INV) && IS_SET(find_types, FIND_TYPE_OBJ)) { count = count_objs(looker, charGetInventory(looker), at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); if(count >= at_count) { if(found_type) *found_type = FOUND_OBJ; return find_obj(looker, charGetInventory(looker), at_count, at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); } else at_count -= count; } /************************************************************/ /* LOCAL SEARCHES */ /************************************************************/ // is it our current room? if(IS_SET(find_scope, FIND_SCOPE_ROOM | FIND_SCOPE_WORLD) && IS_SET(find_types, FIND_TYPE_ROOM) && at_count == 1 && !strcasecmp(at, "room")) { if(found_type) *found_type = FOUND_ROOM; return charGetRoom(looker); } // search objects in the room if(IS_SET(find_scope, FIND_SCOPE_ROOM) && IS_SET(find_types, FIND_TYPE_OBJ)) { count = count_objs(looker, roomGetContents(charGetRoom(looker)), at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); if(count >= at_count) { if(found_type) *found_type = FOUND_OBJ; return find_obj(looker, roomGetContents(charGetRoom(looker)), at_count, at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); } else at_count -= count; } // seach the characters in the room if(IS_SET(find_scope, FIND_SCOPE_ROOM) && IS_SET(find_types, FIND_TYPE_CHAR)) { count = count_chars(looker, roomGetCharacters(charGetRoom(looker)), at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); if(count >= at_count) { if(found_type) *found_type = FOUND_CHAR; return find_char(looker, roomGetCharacters(charGetRoom(looker)), at_count, at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); } else at_count -= count; } // search for exits in the room if(IS_SET(find_scope, FIND_SCOPE_ROOM) && IS_SET(find_types, FIND_TYPE_EXIT)) { EXIT_DATA *exit = roomGetExit(charGetRoom(looker), at); // no exit... are we using an abbreviation? if(exit == NULL && (dirGetAbbrevNum(at) != DIR_NONE)) exit = roomGetExit(charGetRoom(looker), dirGetName(dirGetAbbrevNum(at))); // we found one if(exit && (!IS_SET(find_scope, FIND_SCOPE_VISIBLE) || can_see_exit(looker, exit))) { at_count--; if(at_count == 0) { if(found_type) *found_type = FOUND_EXIT; return exit; } } LIST *ex_list = roomGetExitNames(charGetRoom(looker)); LIST_ITERATOR *ex_i = newListIterator(ex_list); char *dir = NULL; ITERATE_LIST(dir, ex_i) { exit = roomGetExit(charGetRoom(looker), dir); if(exitIsName(exit, at)) { if(!IS_SET(find_scope,FIND_SCOPE_VISIBLE) || can_see_exit(looker,exit)){ at_count--; if(at_count == 0) { if(found_type) *found_type = FOUND_EXIT; break; } } } } deleteListIterator(ex_i); deleteListWith(ex_list, free); // we found one if(*found_type != FOUND_NONE) return exit; } // search extra descriptions in the room if(IS_SET(find_scope, FIND_SCOPE_ROOM) && IS_SET(find_types, FIND_TYPE_EDESC)) { count = (roomGetEdesc(charGetRoom(looker), at) != NULL); if(count && at_count == 1) { if(found_type) *found_type = FOUND_EDESC; return edescSetGet(roomGetEdescs(charGetRoom(looker)), at); } else at_count--; } /************************************************************/ /* GLOBAL SEARCHES */ /************************************************************/ // search rooms in the world if(IS_SET(find_scope, FIND_SCOPE_WORLD) && IS_SET(find_types, FIND_TYPE_ROOM) && at_count == 1) { ROOM_DATA *room = worldGetRoom(gameworld, get_fullkey_relative(at, get_key_locale(roomGetClass(charGetRoom(looker))))); if(room != NULL) { if(found_type) *found_type = FOUND_ROOM; return room; } } // search objects in the world if(IS_SET(find_scope, FIND_SCOPE_WORLD) && IS_SET(find_types, FIND_TYPE_OBJ)) { count = count_objs(looker, object_list, at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); if(count >= at_count) { if(found_type) *found_type = FOUND_OBJ; return find_obj(looker, object_list, at_count, at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); } else at_count -= count; } // search characters in the world if(IS_SET(find_scope, FIND_SCOPE_WORLD) && IS_SET(find_types, FIND_TYPE_CHAR)) { count = count_chars(looker, mobile_list, at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); if(count >= at_count) { if(found_type) *found_type = FOUND_CHAR; return find_char(looker, mobile_list, at_count, at, NULL, (IS_SET(find_scope, FIND_SCOPE_VISIBLE))); } else at_count -= count; } // we didn't find anything! if(found_type) *found_type = FOUND_NONE; return NULL; } void *generic_find(CHAR_DATA *looker, const char *arg, bitvector_t find_types, bitvector_t find_scope, bool all_ok, int *found_type) { // make a working buffer... char working_arg[SMALL_BUFFER]; strcpy(working_arg, arg); strip_word(working_arg, "the"); char *at = at_arg(working_arg); char *in = in_arg(working_arg); char *on = on_arg(working_arg); strip_word(working_arg, "at"); strip_word(working_arg, "in"); strip_word(working_arg, "on"); trim(working_arg); // if we don't have an "at", and there's a word we haven't pulled, // pull the first word before a space if(!at && // figure out the difference between the // number of words that exist and the number // of words we've pulled. If it's > 0, we // haven't pulled a word (count_letters(working_arg, ' ', strlen(working_arg)) + 1 - (in != NULL) - (on != NULL)) == 1) { at = strtok(working_arg, " "); at = strdupsafe(at); } // make sure at, in, and on are never NULL // we always want to search by name, and never vnum if(!at) at = strdup(""); if(!on) on = strdup(""); if(!in) in = strdup(""); // do the finding void *val = find_specific(looker, at, on, in, find_types, find_scope, all_ok, found_type); if(at) free(at); if(in) free(in); if(on) free(on); return val; } // // At is what we're looking for // On is the thing we're looking for it on (e.g. "on sword" "on joe") // In is the thing we're looking for it in (e.g. "in hole" "in bag") // void *find_specific(CHAR_DATA *looker, const char *full_at, const char *full_on, const char *full_in, bitvector_t find_types, bitvector_t find_scope, bool all_ok, int *found_type) { // for stuff like 2.sword, all.woman, etc... int at_count = 1; int on_count = 1; int in_count = 1; // the buffers for storing at, in, on separate from their counts char at[SMALL_BUFFER] = ""; char in[SMALL_BUFFER] = ""; char on[SMALL_BUFFER] = ""; // separate the names from their numbers get_count(full_at, at, &at_count); get_count(full_in, in, &in_count); get_count(full_on, on, &on_count); if(found_type) *found_type = FOUND_NONE; // are we trying to find all of something? if(all_ok && at_count == COUNT_ALL && !*on && !*in) return find_all(looker, at, find_types, find_scope, found_type); else if(!*at || at_count == 0) { // we're trying to find what the contents of an item are? // e.g. "look in portal", "look in bag" if(*in && in_count >= 1 && IS_SET(find_types, FIND_TYPE_IN_OBJ)) { void *tgt = NULL; int next_found_type = FOUND_NONE; // for finding in/on stuff char new_at[strlen(in) + 20]; // +20 for digits print_count(new_at, in, in_count); tgt = find_specific(looker, new_at, "", "", find_types, find_scope, all_ok, &next_found_type); // we couldn't find the thing we were trying to look inside if(!tgt) return NULL; // if we got a list of objects back, scrap 'em else if(next_found_type == FOUND_LIST) { deleteList(tgt); return NULL; } // we can only look inside of objects else if(next_found_type != FOUND_OBJ) return NULL; // return what we found else { if(found_type) *found_type = FOUND_IN_OBJ; return tgt; } } // we're just not looking for anything else { if(found_type) *found_type = FOUND_NONE; return NULL; } } else { void *tgt = NULL; // used for finding what we're looking in/on /****************************************************/ /* START LOOK IN */ /****************************************************/ // check out what we're looking in if(*in && in_count > 0) { int next_found_type = FOUND_NONE; // for finding in/on stuff char new_at[strlen(in) + 20]; // +20 for digits print_count(new_at, in, in_count); tgt = find_specific(looker, new_at, "", "", find_types, find_scope, all_ok, &next_found_type); // we couldn't find the thing we were trying to look inside if(!tgt) return NULL; // we have to KILL someone before we can look inside of them ;) else if(next_found_type != FOUND_OBJ) return NULL; // apply another find, narrowing the scope to inside this object else return find_in_obj(looker, tgt, at_count, at, on_count, on, find_types, find_scope, found_type); } /****************************************************/ /* START LOOK ON */ /****************************************************/ // find out what we're looking on else if(*on && on_count > 0) { int next_found_type = FOUND_NONE; char new_at[strlen(on) + 20]; // +20 for digits print_count(new_at, on, on_count); tgt = find_specific(looker, on, "", "", find_types, find_scope, all_ok, &next_found_type); // couldn't find what we were trying to look on if(tgt == NULL) return NULL; else if(next_found_type == FOUND_CHAR) return find_on_char(looker, tgt, at_count, at, find_types, find_scope, found_type); else if(next_found_type == FOUND_OBJ) { return find_on_obj(looker, tgt, at_count, at, find_types, find_scope, found_type); } else return NULL; } /****************************************************/ /* START LOOK AT */ /****************************************************/ return find_one(looker, at_count, at, find_types, find_scope, found_type); } }