/************************************************************************ Realms of Aurealis James Rhone aka Vall of RoA freeall.c Code which frees up everything the mud allocates during runtime. (In theory.) Useful for linking to dmalloc to track memory leaks and such. Also: general freeing code, yanked out of db.c during the great db.c splitup of January 1997. ******** 100% completely original code ******** *** BE AWARE OF ALL RIGHTS AND RESERVATIONS *** ******** 100% completely original code ******** All rights reserved henceforth. Please note that no guarantees are associated with any code from Realms of Aurealis. All code which has been released to the general public has been done so with an 'as is' pretense. RoA is based on both Diku and CircleMUD and ALL licenses from both *MUST* be adhered to as well as the RoA license. *** Read, Learn, Understand, Improve *** *************************************************************************/ #include "conf.h" #include "sysdep.h" #include "structures.h" #include "utils.h" #include "db.h" #include "comm.h" #include "handler.h" #include "mudlimits.h" #include "magic.h" #include "mail.h" #include "interpreter.h" #include "quest.h" #include "affect.h" #include "lists.h" #include "global.h" #include "htown.h" #include "thief.h" // internal functions void free_this_mob(int i); void free_obj_proto(int i); void free_banned_list(void); void free_bufpools(void); int free_this_zone(int i); // external freeing functions void free_the_boards(void); void free_room_affects(struct room_affect_type *head); void reset_mob_proto(int rnum); // external variables used extern struct pc_special_data dummy; // dummy declared in db.c for mobs extern struct pc_special_data dummy_mob; extern struct message_list fight_messages[MAX_MESSAGES]; extern struct htown_data htowns[]; // globals, ptable names, fight messages, etc void free_up_globals(void) { FREENULL(races); FREENULL(title0); FREENULL(title1); FREENULL(title2); FREENULL(title3); FREENULL(title4); FREENULL(title5); FREENULL(news); FREENULL(credits); FREENULL(credit_sequence); FREENULL(motd); FREENULL(imotd); FREENULL(info); FREENULL(wizlist); FREENULL(immlist); FREENULL(policies); FREENULL(handbook); FREENULL(background); FREENULL(welcome); FREENULL(start); FREENULL(currency_name); FREENULL(currency_name_plural); FREENULL(longmudname); FREENULL(shortmudname); FREENULL(MENU); FREENULL(VTMENU); FREENULL(impname); FREENULL(cimpname); FREENULL(aimpname); FREENULL(godname); FREENULL(avtrname); FREENULL(trustedname); FREENULL(ambassname); FREENULL(spico_path); FREENULL(www_page); FREENULL(www_mailto); FREENULL(www_contact_name); FREENULL(RoA_version); FREENULL(OLC_version); } void free_wear_offs(void) { int i; for (i = 0; i < MAX_SPELLS; i++) FREENULL(spell_info[i].wear_off); } void free_htowns(void) { int i; for (i = 0; i < MAX_HTOWNS && htowns[i].name && *htowns[i].name; i++) { FREENULL(htowns[i].name); } } // free up the combat messages void free_up_messages(void) { int i; struct message_type *messages, *temp; for (i=0; i < MAX_MESSAGES; i++) while (fight_messages[i].msg) { FREENULL(fight_messages[i].msg->die_msg.attacker_msg); FREENULL(fight_messages[i].msg->die_msg.victim_msg); FREENULL(fight_messages[i].msg->die_msg.room_msg); FREENULL(fight_messages[i].msg->miss_msg.attacker_msg); FREENULL(fight_messages[i].msg->miss_msg.victim_msg); FREENULL(fight_messages[i].msg->miss_msg.room_msg); FREENULL(fight_messages[i].msg->hit_msg.attacker_msg); FREENULL(fight_messages[i].msg->hit_msg.victim_msg); FREENULL(fight_messages[i].msg->hit_msg.room_msg); FREENULL(fight_messages[i].msg->god_msg.attacker_msg); FREENULL(fight_messages[i].msg->god_msg.victim_msg); FREENULL(fight_messages[i].msg->god_msg.room_msg); messages = fight_messages[i].msg; REMOVE_FROM_LIST(messages, fight_messages[i].msg, next); free(messages); } } void free_quests(void) { int qnum; qslot *qptr; qnum = 0; while (qarray[qnum].qname && qnum < NUM_QUESTS) { qptr = &qarray[qnum]; FREENULL(qptr->qname); FREENULL(qptr->qdesc); FREENULL(qptr->char_notification); FREENULL(qptr->zone_notification); FREENULL(qptr->world_notification); qnum++; } } void free_bufpools(void) { extern struct txt_block *bufpool; struct txt_block *b, *temp; while ((b = bufpool)) { REMOVE_FROM_LIST(b, bufpool, next); FREENULL(b->text); FREENULL(b); } } // added trap freeing 4/10/98 -jtrhone trap *free_traps(trap *head) { trap *ths, *temp; while((ths = head)) { REMOVE_FROM_LIST(ths, head, next); FREENULL(ths); } return NULL; } /* goes thru an extra descrip list and waxes each member along with ptr to it -roa */ exdescdata *free_extra_descrips(exdescdata *head) { exdescdata *ths, *temp; while((ths = head)) { REMOVE_FROM_LIST(ths, head, next); FREENULL(ths->keyword); FREENULL(ths->description); FREENULL(ths); } return NULL; } /* goes thru an alias list and waxes each member along with ptr to it -roa */ struct alias *free_alias_list(struct alias *head) { struct alias *ths, *temp; while((ths = head)) { REMOVE_FROM_LIST(ths, head, next); FREENULL(ths->alias); FREENULL(ths->replacement); FREENULL(ths); } return NULL; } // wax a TRIG list on a char struct mtrig_type *free_mtriggers(struct mtrig_type *head) { struct mtrig_type *ths, *temp; while ((ths = head)) { REMOVE_FROM_LIST(ths, head, next); FREENULL(ths->trigger); FREENULL(ths->reaction); FREENULL(ths); } return NULL; } // wax a TRIG list on a room rtrig *free_rtriggers(rtrig *head) { rtrig *ths, *temp; while ((ths = head)) { REMOVE_FROM_LIST(ths, head, next); FREENULL(ths->trigger); FREENULL(ths->reaction); FREENULL(ths); } return NULL; } /* this frees up all the names allocated in the ptable name field */ void free_ptable_names(void) { int i; for (i=0; i <= top_of_p_table; i++) FREENULL(player_table[i].name); FREENULL(player_table); } void clear_and_remove_auction(aucdata *aptr) { aucdata *temp = NULL; if (aptr == auction_ptr) { auction_ptr = aptr->next; FREENULL(aptr); return; } REMOVE_FROM_LIST(aptr, auction_ptr, next); FREENULL(aptr); } void free_auctions(void) { aucdata *a; while ((a = auction_ptr)) clear_and_remove_auction(a); } void free_plshops(void) { plshop *ptr, *temp; while ((ptr = pls_global)) { REMOVE_FROM_LIST(ptr, pls_global, global_next); FREENULL(ptr); } } void free_IdList(IdList *list) { IdList *ptr, *temp; while ((ptr = list)) { REMOVE_FROM_LIST(ptr, list, next); FREENULL(ptr); } } /* release memory allocated for a char struct */ // now free sound_file if not matching proto... 2/21/98 -jtrhone void free_char(chdata *ch) { int i, j; TRIGS(ch) = free_mtriggers(TRIGS(ch)); GET_ALIASES(ch) = free_alias_list(GET_ALIASES(ch)); // 3/18/98, must free these now too -jtrhone free_IdList(ch->gagged); ch->gagged = NULL; // Free concealed and revealed structures. 03/22/98 -callahan free_IdList(ch->concealed); ch->concealed = NULL; free_IdList(ch->revealed); ch->revealed = NULL; while (ch->affected) affect_remove(ch, ch->affected); if ((ch->pc_specials) && (ch->pc_specials != &dummy_mob)) { FREENULL(ch->pc_specials); if (IS_NPC(ch)) log("SYSERR: Mob had pc_specials allocated!"); } if (!IS_NPC(ch) || (IS_NPC(ch) && GET_MOB_RNUM(ch) == -1)) { /* if this is a player, or a non-prototyped non-player, free all */ FREENULL(ch->player.name); FREENULL(ch->player.title); FREENULL(ch->player.afk_str); // 05/04/98 -callahan FREENULL(ch->player.short_descr); FREENULL(ch->player.long_descr); FREENULL(ch->player.description); } else if ((i = GET_MOB_RNUM(ch)) > -1) { /* otherwise, free strings only if the string is not pointing at proto */ if (ch->player.name && ch->player.name != mob_proto[i].player.name) free(ch->player.name); if (ch->player.title && ch->player.title != mob_proto[i].player.title) free(ch->player.title); // 05/04/98 -callahan if (ch->player.afk_str && ch->player.afk_str != mob_proto[i].player.afk_str) free(ch->player.afk_str); if (ch->player.short_descr && ch->player.short_descr != mob_proto[i].player.short_descr) free(ch->player.short_descr); if (ch->player.long_descr && ch->player.long_descr != mob_proto[i].player.long_descr) free(ch->player.long_descr); if (ch->player.description && ch->player.description != mob_proto[i].player.description) free(ch->player.description); if (ch->npc_specials.walkIn && ch->npc_specials.walkIn != mob_proto[i].npc_specials.walkIn) free(ch->npc_specials.walkIn); if (ch->npc_specials.walkOut && ch->npc_specials.walkOut != mob_proto[i].npc_specials.walkOut) free(ch->npc_specials.walkOut); if (ch->npc_specials.shop_data && ch->npc_specials.shop_data != mob_proto[i].npc_specials.shop_data) free(ch->npc_specials.shop_data); if (ch->npc_specials.sound_file && ch->npc_specials.sound_file != mob_proto[i].npc_specials.sound_file) free(ch->npc_specials.sound_file); for (j = 0; j < 5; j++) if (ch->npc_specials.strs[j] && ch->npc_specials.strs[j] != mob_proto[i].npc_specials.strs[j]) { FREENULL(ch->npc_specials.strs[j]); } // DO NOT free MPROC_CUR on a MOBPROC, // cause its used to point to MPROC_BEG MPROC_CUR(ch) = NULL; } if (ch->skills) { FREENULL(ch->skills); if (IS_NPC(ch)) log("NPC had skills array allocated."); } if (ch->gskills) { FREENULL(ch->gskills); if (IS_NPC(ch)) log("NPC had gskills array allocated."); } FREENULL(TARGET_CHAR(ch)); FREENULL(TARGET_OBJ(ch)); free(ch); } /* this function purges every mob / player loaded in game */ void purge_all_mobs(void) { int i = 0; while (character_list) { i++; extract_char(character_list); } #ifdef DEBUG_MAX sprintf(buf, "SYSUPD: %d chars freed.", i); mudlog(buf, BUG, LEV_IMM, TRUE); #endif } /* this frees up every mobile in the proto list */ void free_up_mobs(void) { chdata *ch; int i = 0; int j; while (i < top_of_mobt) { ch = &mob_proto[i]; if ((ch->pc_specials) && (ch->pc_specials != &dummy_mob)) { FREENULL(ch->pc_specials); log("SYSERR: Mob Proto pc_specials allocated!"); } FREENULL(ch->player.name); FREENULL(ch->player.title); FREENULL(ch->player.afk_str); // 05/04/98 -callahan FREENULL(ch->player.short_descr); FREENULL(ch->player.long_descr); FREENULL(ch->player.description); FREENULL(ch->npc_specials.walkIn); FREENULL(ch->npc_specials.walkOut); FREENULL(ch->npc_specials.sound_file); FREENULL(ch->npc_specials.shop_data); for (j = 0; j < 5; j++) FREENULL(ch->npc_specials.strs[j]); MPROC_CUR(ch) = NULL; // do NOT free strs[5] i++; } /* now free up the mob_proto list itself */ free(mob_proto); free(mob_index); } /* release memory allocated for a char struct */ /* REGARDLESS of proto stuff, cause its used for skipped mob protos */ void free_this_mob(int proto) { chdata *ch; int j; ch = &mob_proto[proto]; if ((ch->pc_specials) && (ch->pc_specials != &dummy_mob)) { FREENULL(ch->pc_specials); if (IS_NPC(ch)) log("SYSERR: Mob had pc_specials allocated!"); } FREENULL(GET_NAME(ch)); FREENULL(ch->player.title); FREENULL(ch->player.afk_str); // 05/04/98 -callahan FREENULL(ch->player.short_descr); FREENULL(ch->player.long_descr); FREENULL(ch->player.description); FREENULL(ch->npc_specials.walkIn); FREENULL(ch->npc_specials.walkOut); FREENULL(ch->npc_specials.sound_file); FREENULL(ch->npc_specials.shop_data); // do NOT free strs[5], its used to point to strs[4] for (j = 0; j < 5; j++) FREENULL(ch->npc_specials.strs[j]); MPROC_CUR(ch) = NULL; // now NULL out all information and reset to default reset_mob_proto(proto); } /* this function purges every object loaded in game */ void purge_all_objs(void) { int i = 0; while (object_list) { i++; extract_obj(object_list); } #ifdef DEBUG_MAX sprintf(buf, "SYSUPD: %d objs freed.", i); mudlog(buf, BUG, LEV_IMM, TRUE); #endif } void purge_descriptors(void) { int i = 0; while (descriptor_list) { i++; close_socket(descriptor_list); } #ifdef DEBUG_MAX sprintf(buf, "SYSUPD: %d descriptors freed.", i); mudlog(buf, BUG, LEV_IMM, TRUE); #endif } /* this frees up every object in the proto list */ void free_up_objs(void) { int i = 0; while (i < top_of_objt) { free_obj_proto(i); i++; } free(obj_proto); free(obj_index); } /* release memory allocated for an obj struct */ void free_obj(obdata *obj) { int nr; // wax the traps, 4/10/98 -jtrhone TRAPS(obj) = free_traps(TRAPS(obj)); // bugfix, do not treat instruments any differently than other objects with // respect to freeing... only free strings if they // a) dont belong to a proto or // b) are different from the protos strings (in the case of instrums... they have // differing strings than protos...) 5/13/98 - jtrhone if ((nr = GET_OBJ_RNUM(obj)) <= -1) { FREENULL(obj->name); FREENULL(obj->description); FREENULL(obj->shdesc); FREENULL(obj->actdesc); FREENULL(obj->wear_mesg); FREENULL(obj->rem_mesg); FREENULL(obj->weap_sing); FREENULL(obj->weap_plur); obj->exdesc = free_extra_descrips(obj->exdesc); } else { if (obj->name && obj->name != obj_proto[nr].name) free(obj->name); if (obj->description && obj->description != obj_proto[nr].description) free(obj->description); if (obj->shdesc && obj->shdesc != obj_proto[nr].shdesc) free(obj->shdesc); if (obj->actdesc && obj->actdesc != obj_proto[nr].actdesc) free(obj->actdesc); if (obj->wear_mesg && obj->wear_mesg != obj_proto[nr].wear_mesg) free(obj->wear_mesg); if (obj->rem_mesg && obj->rem_mesg != obj_proto[nr].rem_mesg) free(obj->rem_mesg); if (obj->weap_sing && obj->weap_sing != obj_proto[nr].weap_sing) free(obj->weap_sing); if (obj->weap_plur && obj->weap_plur != obj_proto[nr].weap_plur) free(obj->weap_plur); if (obj->exdesc && obj->exdesc != obj_proto[nr].exdesc) obj->exdesc = free_extra_descrips(obj->exdesc); } free(obj); } /* release memory allocated for an obj struct */ /* do so REGARDLESS of proto, its used to free a skipped proto -roa */ void free_obj_proto(int i) { obdata *obj = &obj_proto[i]; FREENULL(obj->name); FREENULL(obj->description); FREENULL(obj->shdesc); FREENULL(obj->actdesc); FREENULL(obj->wear_mesg); FREENULL(obj->rem_mesg); FREENULL(obj->weap_sing); FREENULL(obj->weap_plur); obj->exdesc = free_extra_descrips(obj->exdesc); } /* waxes one rooms descrips, and extra descriptions, including DIRs string data */ void free_this_room(int i) { int dir; FREENULL(world[i].name); FREENULL(world[i].description); for (dir = 0; dir < 5; dir++) FREENULL(world[i].randoms[dir]); world[i].exdesc = free_extra_descrips(world[i].exdesc); free_room_affects(world[i].room_affects); world[i].room_affects = NULL; // wax the traps, 4/10/98 -jtrhone TRAPS(&world[i]) = free_traps(TRAPS(&world[i])); /* free the directions off each room */ // UPDATE 2/15/97, no longer free the direction itself // just free the strings off it -jtrhone roa for (dir = 0; dir < NUM_OF_DIRS; dir++) if(DIR(i, dir)) { FREENULL(DIR(i, dir)->exit_descr); FREENULL(DIR(i, dir)->keyword); // Exit messages. 03/24/98 -callahan FREENULL(DIR(i, dir)->enter); FREENULL(DIR(i, dir)->oenter); FREENULL(DIR(i, dir)->drop); FREENULL(DIR(i, dir)->odrop); // wax the traps, 4/10/98 -jtrhone TRAPS(DIR(i, dir)) = free_traps(TRAPS(DIR(i, dir))); } // now free triggers 6/5/98 -jtrhone RTRIGS(&world[i]) = free_rtriggers(RTRIGS(&world[i])); FREENULL(RPROC_BEG(&world[i])); RPROC_CUR(&world[i]) = NULL; FREENULL(RTARGET_CHAR(&world[i])); FREENULL(RTARGET_OBJ(&world[i])); } /* release the strings of all the rooms in this zone */ /* also release the zones comlist */ // now also free sound_file 2/21/98 -jtrhone int free_this_zone(int i) { int rroom, vroom, vbase, vtop; if (ZONE_FLAGGED(i, Z_LOCKED)) { sprintf(buf, "SYSERR: attempted free of locked zone (%d).",i); mudlog(buf, BRF, LEV_IMM, TRUE); return (0); } for (vroom = 0; vroom < 4; vroom++) { FREENULL(zone_table[i].seasons[vroom].sunrise); FREENULL(zone_table[i].seasons[vroom].daytime); FREENULL(zone_table[i].seasons[vroom].sunset); FREENULL(zone_table[i].seasons[vroom].nighttime); } FREENULL(zone_table[i].sound_file); FREENULL(zone_table[i].comlist); // rooms in zone range from XXX00 to XXX99 vbase = i * 100; vtop = vbase + 99; for (vroom = vbase; vroom <= vtop; vroom++) if ((rroom = real_room(vroom)) >= 0) free_this_room(rroom); SET_ZONE_FREED(i); return(1); } /* this function frees up rooms/dirs/extra descrips on rooms/randoms */ // also free sound_file now 2/20/98 -jtrhone void free_up_world(void) { rmdata *temp; int i = 0, dir; while (i < top_of_world) { temp = &world[i]; FREENULL(temp->name); FREENULL(temp->description); for (dir = 0; dir < 5; dir++) FREENULL(temp->randoms[dir]); temp->exdesc = free_extra_descrips(temp->exdesc); free_room_affects(temp->room_affects); temp->room_affects = NULL; // wax the traps, 4/10/98 -jtrhone TRAPS(temp) = free_traps(TRAPS(temp)); /* free the directions off each room */ for (dir = 0; dir < NUM_OF_DIRS; dir++) if(DIR(i, dir)) { FREENULL(DIR(i, dir)->exit_descr); FREENULL(DIR(i, dir)->keyword); // Exit messages. 03/24/98 -callahan FREENULL(DIR(i, dir)->enter); FREENULL(DIR(i, dir)->oenter); FREENULL(DIR(i, dir)->drop); FREENULL(DIR(i, dir)->odrop); // wax the traps, 4/10/98 -jtrhone TRAPS(DIR(i, dir)) = free_traps(TRAPS(DIR(i, dir))); free(DIR(i, dir)); } FREENULL(temp->sound_file); // now free triggers 6/5/98 -jtrhone RTRIGS(&world[i]) = free_rtriggers(RTRIGS(&world[i])); FREENULL(RPROC_BEG(&world[i])); RPROC_CUR(&world[i]) = NULL; FREENULL(RTARGET_CHAR(&world[i])); FREENULL(RTARGET_OBJ(&world[i])); i++; } /* all the descrips are freed now lets free world array */ free(world); world = NULL; } /* free_the_mud calls every purge function and frees up everything the mud had allocated (save a couple things, like plrmail) */ void free_the_mud(void) { int zon = 0; int i; free_the_boards(); free_up_messages(); free_up_globals(); purge_all_mobs(); purge_descriptors(); // get rid of players ... 3/7/98 -jtrhone purge_all_objs(); free_up_mobs(); free_up_objs(); free_up_world(); free_ptable_names(); free_banned_list(); free_bufpools(); free_auctions(); free_quests(); free_wear_offs(); free_plshops(); free_htowns(); while (zon < NUM_ZONES) { FREENULL(zone_table[zon].name); for (i = 0; i < 4; i++) { FREENULL(zone_table[zon].seasons[i].sunrise); FREENULL(zone_table[zon].seasons[i].daytime); FREENULL(zone_table[zon].seasons[i].sunset); FREENULL(zone_table[zon].seasons[i].nighttime); } FREENULL(zone_table[zon].comlist); FREENULL(zone_table[zon].sound_file); zon++; } }