/* dbutils.c */ #include "copyright.h" #include "config.h" #include <stdio.h> #include <ctype.h> #include "teeny.h" #include "db.h" #include "case.h" /* * This is the only file in the mud directory that knows about the index. Use * EXTREME caution when modifing the routines in this file. */ extern struct dsc **main_index; extern int total_objects; extern int actual_objects; static void find_object(); int controls(player, obj) int player; int obj; { if (obj == -3) return 1; /* everyone controls HOME */ if (player < 0 || player > total_objects || main_index[player] == NULL) { warning("controls", "called with nonexistant player"); return 0; } if (obj < 0 || obj > total_objects || main_index[obj] == NULL) { warning("controls", "called with nonexistant object"); return 0; } if (WizP(main_index[player])) return 1; if (DSC_OWNER(main_index[obj]) == player) return 1; return 0; } static void find_object(player, name, type) int player; char *name; int type; { register int i, j, len; register char *str; extern char cmdwork[]; for (i = 0; i < total_objects; i++) { if (main_index[i] == NULL) continue; if (((type != -1) && ((DSC_FLAGS(main_index[i]) & TYPE_MASK) != type)) || (type == -1 && isexit(i))) continue; if (!controls(player, i)) continue; str = DSC_NAME(main_index[i]); if (str == NULL) { fprintf(stderr, "find_object: obj (#%d) has NULL name.\n", i); continue; } if (PlayerP(main_index[i])) { if (name != (char *) 0) for (j = 0; name[j] && str[j] && DOWNCASE(name[j]) == DOWNCASE(str[j]); j++); if ((name == (char *) 0) || isspace(str[j])) { if ((len = stuff_name(player, i, cmdwork, BUFFSIZ - 3)) == -1) { strcpy(cmdwork, "<spammed name>\r\n"); } else { cmdwork[len] = '\r'; cmdwork[len + 1] = '\n'; cmdwork[len + 2] = '\0'; } notify_player(player, cmdwork); } } else { if ((name == (char *) 0) || strstr_CI(str, name)) { if ((len = stuff_name(player, i, cmdwork, BUFFSIZ - 3)) == -1) { strcpy(cmdwork, "<spammed name>\r\n"); } else { cmdwork[len] = '\r'; cmdwork[len + 1] = '\n'; cmdwork[len + 2] = '\0'; } notify_player(player, cmdwork); } } } notify_player(player, "***End of list***\r\n"); } voidfunc do_owned(player, argone, argtwo) int player; char *argone; char *argtwo; { int len, matchfor, i, type; extern char cmdwork[]; if (!iswiz(player)) { notify_player(player, "Only a Wizard may look at the owners list.\r\n"); return; } if (!argone || !*argone) { notify_player(player, "I need a player name.\r\n"); return; } if ((matchfor = resolve_player(player, argone, 1)) == -1) { notify_player(player, "I can't find that person.\r\n"); return; } type = -1; if (argtwo && *argtwo) { parse_type(argtwo, &type); if(type == -1) { notify_player(player, "@owned <player> [=<type>] where type is {e,p,r,t}\r\n"); return; } } for (i = 0; i < total_objects; i++) { if (main_index[i] == NULL) continue; if (DSC_OWNER(main_index[i]) != matchfor) continue; /* they own this object */ if (type != -1) { if ((DSC_FLAGS(main_index[i]) & TYPE_MASK) != type) continue; } if ((len = stuff_name(player, i, cmdwork, BUFFSIZ - 3)) == -1) { strcpy(cmdwork, "<spammed name>\r\n"); } else { cmdwork[len] = '\r'; cmdwork[len + 1] = '\n'; cmdwork[len + 2] = '\0'; } notify_player(player, cmdwork); } notify_player(player, "***End of list***\r\n"); } int chownall(oldowner, newowner) register int oldowner; register int newowner; { int i, count = 0; if (!exists_object(oldowner) || !exists_object(newowner)) { warning("chownall", "called with nonexistant object as an argument"); return 0; } for (i = 0; i < total_objects; i++) { if (main_index[i] == NULL) continue; if (DSC_OWNER(main_index[i]) == oldowner) { DSC_OWNER(main_index[i]) = newowner; count++; } } return count; } voidfunc do_find(player, argone, argtwo) int player; char *argone; char *argtwo; { int type; if (!argone || !*argone) argone = (char *) 0; type = -1; if (argtwo && *argtwo) { parse_type(argtwo, &type); if(type == -1) { notify_player(player, "@find <string> [=<type>] where type is {e,p,r,t}\r\n"); return; } } find_object(player, argone, type); } #define COUNT_OBJ(x) \ (((matchfor != -2)&&(DSC_OWNER(main_index[x])==matchfor)) || matchfor == -2) #define STATS_FRMT \ "%d object%s = %d room%s, %d exit%s, %d thing%s, %d player%s (%d garbage).\r\n" voidfunc do_stats(player, arg) int player; char *arg; { extern char cmdwork[]; int matchfor; if (!arg || !*arg) { matchfor = -2; } else { if ((matchfor = resolve_player(player, arg, iswiz(player))) == -1) { notify_player(player, "I can't find that person.\r\n"); return; } if ((matchfor != player) && !iswiz(player)) { notify_player(player, "You can't stat other players!\r\n"); return; } /* matchfor should now contain a valid player number */ } if (!iswiz(player) && matchfor == -2) { sprintf(cmdwork, "The universe contains %d objects.\r\n", actual_objects); notify_player(player, cmdwork); } else { register int i; register int exits = 0; register int rooms = 0; register int players = 0; register int things = 0; register int total = 0; for (i = 0; i < total_objects; i++) { if (main_index[i] == NULL) continue; if (ExitP(main_index[i])) { if (COUNT_OBJ(i)) { total++; exits++; } continue; } if (RoomP(main_index[i])) { if (COUNT_OBJ(i)) { rooms++; total++; } continue; } if (PlayerP(main_index[i])) { if (COUNT_OBJ(i)) { total++; players++; } continue; } if (ThingP(main_index[i])) { if (COUNT_OBJ(i)) { total++; things++; } continue; } } sprintf(cmdwork, STATS_FRMT, total, (total == 1) ? "" : "s", rooms, (rooms == 1) ? "" : "s", exits, (exits == 1) ? "" : "s", things, (things == 1) ? "" : "s", players, (players == 1) ? "" : "s", (matchfor == -2) ? total_objects - actual_objects : 0); notify_player(player, cmdwork); if (iswiz(player) && matchfor == -2) { extern int cache_usage; extern int cache_size; sprintf(cmdwork, "Cache usage: %d of %d.\r\n", cache_usage, cache_size); notify_player(player, cmdwork); } } } #undef COUNT_OBJ #undef STATS_FRMT /* fix up destinations/homes/dropto's that point at non existant objects */ void zap_destinations(oldobj) int oldobj; { register int i; for (i = 0; i < total_objects; i++) { if ((main_index[i] == NULL) || (DSC_HOME(main_index[i]) != oldobj)) continue; switch (DSC_FLAGS(main_index[i]) & TYPE_MASK) { case TYP_PLAYER: DSC_HOME(main_index[i]) = STARTING_LOC; break; case TYP_THING: DSC_HOME(main_index[i]) = /* link to owners home */ DSC_HOME(main_index[DSC_OWNER(main_index[i])]); break; case TYP_ROOM: DSC_DROPTO(main_index[i]) = -1; /* unlink */ break; case TYP_EXIT: DSC_DESTINATION(main_index[i]) = -1; /* unlink */ break; default: /* fuckit */ fprintf(stderr, "warning: object #%d is unknown type.\n", i); } } } int recycleobj(obj) int obj; { int loc; int list, next; int total = 0; if (!exists_object(obj)) return 0; if (PlayerP(main_index[obj])) return 0; if (get_int_elt(obj, LOC, &loc) == -1) goto recbomb; if (RoomP(main_index[obj])) { /* Nuke the exits. Ownership? Who cares. */ if (get_int_elt(obj, EXITS, &list) == -1) goto recbomb; while (list != -1) { next = DSC_NEXT(main_index[list]); destroy_obj(list); total++; list = next; } /* Try to send everything here home. Nuke what's left */ /* I.E. Anything homed here will get nuked. BOOM! */ if (get_int_elt(obj, CONTENTS, &list) == -1) goto recbomb; while (list != -1) { next = DSC_NEXT(main_index[list]); /* If this is a player homed here, set home to zero */ if (PlayerP(main_index[list])) { if (DSC_HOME(main_index[list]) == obj) { DSC_HOME(main_index[list]) = STARTING_LOC; } } if (PlayerP(main_index[list])) { char *name, *p; char ch; name = DSC_NAME(main_index[list]); for (p = name; *p && *p != ' '; p++); ch = *p; *p = '\0'; notify_player(list, "You feel a wrenching sensation...\r\n"); send_home(list, obj); notify_oall(list, name); notify_oall(list, " has arrived.\r\n"); *p = ch; do_look(list, (char *) NULL); } else { send_home(list, obj); } list = next; } if (get_int_elt(obj, CONTENTS, &list) == -1) goto recbomb; while (list != -1) { next = DSC_NEXT(main_index[list]); destroy_obj(list); total++; list = next; } /* nuke the room itself. */ destroy_obj(obj); total++; /* Skip over the DB checking all exits, and unlinking the */ /* ones that come here. */ zap_destinations(obj); } else if (ExitP(main_index[obj])) { list_drop(obj, loc, 0); destroy_obj(obj); total++; } else if (ThingP(main_index[obj])) { list_drop(obj, loc, 1); zap_destinations(obj); if (get_int_elt(obj, CONTENTS, &list) == -1) goto recbomb; while (list != -1) { /* send objects home */ next = DSC_NEXT(main_index[list]); send_home(list, obj); list = next; } if (get_int_elt(obj, EXITS, &list) == -1) goto recbomb; while (list != -1) { /* nuke exits */ next = DSC_NEXT(main_index[list]); destroy_obj(list); total++; list = next; } destroy_obj(obj); total++; } else { warning("recycleobj", "unknown object type"); goto recbomb; } return total; recbomb: return -1; } /* recycle everything owned by obj, *except* obj */ int purgepossessions(obj) int obj; { register int i; int ret, total = 0; if (!exists_object(obj)) { warning("purgepossessions", "called with nonexistant object"); return 0; } for (i = 0; i < total_objects; i++) { if (main_index[i] == NULL) continue; if ((i == obj) || (DSC_OWNER(main_index[i]) != obj)) continue; /* nuke this, what ever it is */ ret = recycleobj(i); if (ret > 0) total += ret; } return total; } /* * Matches a player. This is kind of expensive CPU wise. */ int match_player(name) register char *name; { register int i, j; register char *player; for (i = 0; i < total_objects; i++) { if (main_index[i] == NULL || !PlayerP(main_index[i])) continue; player = DSC_NAME(main_index[i]); if (!player || !*player) { warning("match_player", "player with null name found"); continue; } for (j = 0; name[j] && player[j] && (DOWNCASE(name[j]) == DOWNCASE(player[j])); j++); if ((player[j] == ' ') && (name[j] == '\0')) return (i); } return (-1); } int autotoadcheck(player) int player; { char *desc, *name, *p; register int i; register int total = 0; extern char cmdwork[]; /* Is player guest? */ if (player == GUEST) return TRUE; /* Does the player have a desc? */ if (get_str_elt(player, DESC, &desc) == -1) { warning("autotoadcheck", "bad desc elt"); notify_bad(player); return TRUE; } if (desc != NULL) return TRUE; /* Does the player own any property? (@stat > 1) */ for (i = 0; i < total_objects; i++) { if (main_index[i] == NULL) continue; if (DSC_OWNER(main_index[i]) == player) total++; } if (total > 1) return TRUE; /* Player has failed both tests. Toad the bastard. */ if (get_str_elt(player, NAME, &name) == -1) { warning("autotoadcheck", "bad name elt"); notify_bad(player); return TRUE; } if (name != NULL) { for (p = cmdwork; *name && !isspace(*name);) { *p++ = *name++; } *p = '\0'; } notify_player(player, "Are you just here to litter the db, or what? Man!\r\n"); do_toad(GOD,cmdwork,NULL); if (recycleobj(player) < 1) warning("autotoadcheck", "couldn't recycle the toad"); return FALSE; } /* autotoadcheck */