/* $Id: recycle.c,v 1.666 2004/09/20 10:49:52 shrike Exp $ */ /************************************************************************************ * Copyright 2004 Astrum Metaphora consortium * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * * * ************************************************************************************/ /************************************************************************************ * ANATOLIA 2.1 is copyright 1996-1997 Serdar BULUT, Ibrahim CANPUNAR * * ANATOLIA has been brought to you by ANATOLIA consortium * * Serdar BULUT {Chronos} bulut@rorqual.cc.metu.edu.tr * * Ibrahim Canpunar {Asena} canpunar@rorqual.cc.metu.edu.tr * * Murat BICER {KIO} mbicer@rorqual.cc.metu.edu.tr * * D.Baris ACAR {Powerman} dbacar@rorqual.cc.metu.edu.tr * * By using this code, you have agreed to follow the terms of the * * ANATOLIA license, in the file Anatolia/anatolia.licence * ***********************************************************************************/ /************************************************************************************ * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ************************************************************************************/ /************************************************************************************ * ROM 2.4 is copyright 1993-1995 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@pacinfo.com) * * Gabrielle Taylor (gtaylor@pacinfo.com) * * Brian Moore (rom@rom.efn.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * *************************************************************************************/ /************************************************************************************ * Copyright (c) 1998 fjoe <fjoe@iclub.nsu.ru> * * All rights reserved. * * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * 1. Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * * SUCH DAMAGE. * ************************************************************************************/ #include <sys/types.h> // Welesh : compat #if !defined (WIN32) #include <sys/time.h> #include <regex.h> #else #include "compat\regex-win32\regex.h" #endif #include <stdio.h> #include <string.h> #include <stdlib.h> #include "merc.h" #include "db/db.h" /* stuff for recycling extended descs */ extern int top_ed; extern void free_contacts(CHAR_DATA *ch); extern void nuke_slaves (CHAR_DATA *ch); ED_DATA *ed_new(void) { ED_DATA *ed; ed = calloc(1, sizeof(*ed)); top_ed++; return ed; } ED_DATA *ed_new2(const ED_DATA *ed, const char* name) { ED_DATA *ed2 = ed_new(); ed2->keyword = str_dup(ed->keyword); ed2->description = mlstr_printf(ed->description, name); return ed2; } ED_DATA *ed_dup(const ED_DATA *ed) { ED_DATA *ned = ed_new(); ned->keyword = str_dup(ed->keyword); ned->description = mlstr_dup(ed->description); return ned; } void ed_free(ED_DATA *ed) { if (!ed) return; free_string(ed->keyword); mlstr_free(ed->description); free(ed); top_ed--; } void ed_fread(FILE *fp, ED_DATA **edp) { ED_DATA *ed = ed_new(); ed->keyword = fread_string(fp); ed->description = mlstr_fread(fp); SLIST_ADD(ED_DATA, *edp, ed); } void ed_fwrite(FILE *fp, ED_DATA *ed) { fprintf(fp, "E\n%s~\n", fix_string(ed->keyword)); mlstr_fwrite(fp, NULL, ed->description); } AFFECT_DATA *aff_new(void) { return calloc(1, sizeof(AFFECT_DATA)); } AFFECT_DATA *aff_dup(const AFFECT_DATA *paf) { AFFECT_DATA *naf = aff_new(); naf->where = paf->where; naf->type = paf->type; naf->level = paf->level; naf->duration = paf->duration; naf->location = paf->location; naf->modifier = paf->modifier; naf->bitvector = paf->bitvector; return naf; } void aff_free(AFFECT_DATA *af) { free(af); } OBJ_DATA *free_obj_list; OBJ_DATA *new_obj(void) { OBJ_DATA *obj; if (free_obj_list) { obj = free_obj_list; free_obj_list = free_obj_list->next; memset(obj, '\0', sizeof(*obj)); } else obj = calloc(1, sizeof(*obj)); return obj; } void free_obj(OBJ_DATA *obj) { AFFECT_DATA *paf, *paf_next; ED_DATA *ed, *ed_next; KEY_DATA *key, *key_next; if (!obj) return; for (paf = obj->affected; paf; paf = paf_next) { paf_next = paf->next; aff_free(paf); } obj->affected = NULL; for (ed = obj->ed; ed != NULL; ed = ed_next ) { ed_next = ed->next; ed_free(ed); } obj->ed = NULL; if (obj->keys) { // loop thru the keys and free the allocated memory for ( key = obj->keys; key != NULL; key = key_next) { key_next = key->next; free_key(key); } } free_string(obj->name); obj->name = NULL; mlstr_free(obj->description); obj->description = NULL; mlstr_free(obj->short_descr); obj->short_descr = NULL; free_string(obj->owner); obj->owner = NULL; free_string(obj->material); obj->material = NULL; obj->next = free_obj_list; free_obj_list = obj; } CHAR_DATA *free_char_list; CHAR_DATA *new_char (void) { CHAR_DATA *ch; int i; if (free_char_list) { ch = free_char_list; free_char_list = free_char_list->next; memset(ch, '\0', sizeof(*ch)); } else ch = calloc(1, sizeof(*ch)); ch->remembered_rooms.nsize = sizeof(memento_t); ch->remembered_rooms.nstep = 4; ch->remembered_objects.nsize = sizeof(memento_t); ch->remembered_objects.nstep = 4; ch->remembered_mobs.nsize = sizeof(memento_t); ch->remembered_mobs.nstep = 4; ch->remembered_people.nsize = sizeof(memento_t); ch->remembered_people.nstep = 4; RESET_FIGHT_TIME(ch); ch->last_death_time = -1; ch->prefix = str_empty; ch->lines = PAGELEN; ch->logon = current_time; ch->hit = 20; ch->max_hit = 20; ch->mana = 100; ch->max_mana = 100; ch->move = 100; ch->max_move = 100; ch->psp = 10; ch->position = POS_STANDING; for (i = 0; i < 4; i++) ch->armor[i] = 100; for (i = 0; i < MAX_STATS; i++) ch->perm_stat[i] = 13; for (i = 0; i < MAX_DAM; i++) ch->resists[i] = 0; ch->immunes = 0; free_contacts(ch); ch->doppel = ch; return ch; } extern int mobile_count; void free_char(CHAR_DATA *ch) { OBJ_DATA *obj; OBJ_DATA *obj_next; AFFECT_DATA *paf; AFFECT_DATA *paf_next; if (!ch) return; if (IS_NPC(ch)) mobile_count--; for (obj = ch->carrying; obj; obj = obj_next) { obj_next = obj->next_content; extract_obj_nocount(obj); } for (paf = ch->affected; paf; paf = paf_next) { paf_next = paf->next; affect_remove(ch,paf); } ch->affected = NULL; nuke_slaves (ch); free_string(ch->name); ch->name = NULL; mlstr_free(ch->short_descr); ch->short_descr = NULL; mlstr_free(ch->long_descr); ch->long_descr = NULL; mlstr_free(ch->description); ch->description = NULL; mlstr_free(ch->listen_data); ch->listen_data = NULL; free_string(ch->prompt); ch->prompt = NULL; free_string(ch->prefix); ch->prefix = NULL; free_string(ch->material); ch->material = NULL; free_string(ch->in_mind); ch->in_mind = NULL; #ifdef IMC imc_freechardata(ch); #endif #ifdef I3 free_i3chardata(ch); #endif free_pcdata(ch->pcdata); ch->pcdata = NULL; free_contacts(ch); ch->doppel = NULL; varr_free(&ch->remembered_rooms); varr_free(&ch->remembered_objects); varr_free(&ch->remembered_mobs); varr_free(&ch->remembered_people); ch->next = free_char_list; free_char_list = ch; if (ch->in_room != NULL) { // fuck this, it wouldn't help //bug("BINGO! free_char: ch->in_room != NULL (%d)", ch->in_room->vnum); } } CHAR_EXPLORED_DATA * new_char_explored_data(void) { CHAR_EXPLORED_DATA *explored_data; explored_data = calloc(1, sizeof(*explored_data)); explored_data->name = str_empty; return explored_data; } void free_char_explored_data(CHAR_EXPLORED_DATA *explored_data) { CHAR_EXPLORED_DATA *curr_area; CHAR_EXPLORED_DATA *next_area; if (!explored_data) return; for (curr_area = explored_data; curr_area;) { next_area = curr_area->next; free_string(curr_area->name); free(curr_area); curr_area = next_area; } } PC_DATA * new_pcdata(void) { PC_DATA * pcdata; int i; pcdata = calloc(1, sizeof(*pcdata)); pcdata->buffer = buf_new(-1); pcdata->learned.nsize = sizeof(pcskill_t); pcdata->learned.nstep = 8; pcdata->pwd = str_empty; pcdata->bamfin = str_empty; pcdata->bamfout = str_empty; pcdata->title = str_empty; pcdata->pretitle = str_empty; pcdata->twitlist = str_empty; pcdata->linked_list = str_empty; pcdata->granted = str_empty; pcdata->host = str_empty; pcdata->last_login = str_empty; pcdata->marryed = str_empty; pcdata->proposal = str_empty; pcdata->prog_vars = str_empty; pcdata->last_divorce = -1; pcdata->last_marry = -1; for (i = 0; i < 6; ++i) pcdata->rusnames[i] = NULL; return pcdata; } void free_pcdata(PC_DATA *pcdata) { int alias; if (!pcdata) return; varr_free(&pcdata->learned); free_string(pcdata->pwd); free_string(pcdata->bamfin); free_string(pcdata->bamfout); free_string(pcdata->title); free_string(pcdata->pretitle); free_string(pcdata->twitlist); free_string(pcdata->linked_list); free_string(pcdata->granted); free_string(pcdata->host); free_string(pcdata->last_login); free_string(pcdata->marryed); free_string(pcdata->proposal); free_string(pcdata->prog_vars); buf_free(pcdata->buffer); /* in this function ALL of the explored areas are being released */ free_char_explored_data(pcdata->explored_areas); for (alias = 0; alias < MAX_ALIAS; alias++) { free_string(pcdata->alias[alias]); free_string(pcdata->alias_sub[alias]); } free(pcdata); } /* stuff for setting ids */ long last_pc_id; long last_mob_id; long last_obj_id; long get_pc_id(void) { return last_pc_id = (current_time <= last_pc_id) ? last_pc_id + 1 : current_time; } long get_mob_id(void) { last_mob_id++; return last_mob_id; } long get_obj_id(void) { last_obj_id++; return last_obj_id; } MPTRIG *mptrig_new(int type, const char *phrase, int vnum) { const char *p; MPTRIG *mptrig; mptrig = calloc(1, sizeof(*mptrig)); mptrig->type = type; mptrig->vnum = vnum; mptrig->phrase = str_dup(phrase); for (p = mptrig->phrase; *p; p++) if (ISUPPER(*p)) { SET_BIT(mptrig->flags, TRIG_CASEDEP); break; } if ((type == TRIG_ACT || type == TRIG_SPEECH) && phrase[0] == '*') { int errcode; int cflags = REG_EXTENDED | REG_NOSUB; SET_BIT(mptrig->flags, TRIG_REGEXP); if (!IS_SET(mptrig->flags, TRIG_CASEDEP)) cflags |= REG_ICASE; mptrig->extra = malloc(sizeof(regex_t)); errcode = regcomp(mptrig->extra, phrase+1, cflags); if (errcode) { char buf[MAX_STRING_LENGTH]; regerror(errcode, mptrig->extra, buf, sizeof(buf)); log_printf("bad MOB trigger for vnum %d (phrase '%s'): %s", vnum, phrase, buf); } } return mptrig; } void mptrig_add(MOB_INDEX_DATA *mob, MPTRIG *mptrig) { SET_BIT(mob->mptrig_types, mptrig->type); SLIST_ADD(MPTRIG, mob->mptrig_list, mptrig); } void mptrig_fix(MOB_INDEX_DATA *mob) { MPTRIG *mptrig; for (mptrig = mob->mptrig_list; mptrig; mptrig = mptrig->next) SET_BIT(mob->mptrig_types, mptrig->type); } void mptrig_free(MPTRIG *mp) { if (!mp) return; if (IS_SET(mp->flags, TRIG_REGEXP)) { regfree(mp->extra); free(mp->extra); } free_string(mp->phrase); free(mp); } /*-------------------------- OBJ Sections -----------------*/ void optrig_add(OBJ_INDEX_DATA *obj, MPTRIG *optrig) { SET_BIT(obj->oprog_flags, optrig->type); SLIST_ADD(MPTRIG, obj->oprogs, optrig); } MPTRIG *optrig_new(int type, const char *phrase, int vnum) { const char *p; MPTRIG *optrig; optrig = calloc(1, sizeof(*optrig)); optrig->type = type; optrig->vnum = vnum; optrig->phrase = str_dup(phrase); for (p = optrig->phrase; *p; p++) if (ISUPPER(*p)) { SET_BIT(optrig->flags, TRIG_CASEDEP); break; } if ((type == TRIG_ACT || type == TRIG_SPEECH) && phrase[0] == '*') { int errcode; int cflags = REG_EXTENDED | REG_NOSUB; SET_BIT(optrig->flags, TRIG_REGEXP); if (!IS_SET(optrig->flags, TRIG_CASEDEP)) cflags |= REG_ICASE; optrig->extra = malloc(sizeof(regex_t)); errcode = regcomp(optrig->extra, phrase+1, cflags); if (errcode) { char buf[MAX_STRING_LENGTH]; regerror(errcode, optrig->extra, buf, sizeof(buf)); log_printf("bad OBJ trigger for vnum %d (phrase '%s'): %s", vnum, phrase, buf); } } return optrig; } void optrig_fix(OBJ_INDEX_DATA *obj) { MPTRIG *optrig; for (optrig = obj->oprogs; optrig; optrig = optrig->next) SET_BIT(obj->oprog_flags, optrig->type); } void optrig_free(MPTRIG *op) { if (!op) return; if (IS_SET(op->flags, TRIG_REGEXP)) { regfree(op->extra); free(op->extra); } free_string(op->phrase); free(op); } /*-------------------------- OBJ Sections -----------------*/ void rptrig_add(ROOM_INDEX_DATA *room, MPTRIG *rptrig) { SET_BIT(room->rprog_flags, rptrig->type); SLIST_ADD(MPTRIG, room->rprogs, rptrig); } MPTRIG *rptrig_new(int type, const char *phrase, int vnum) { const char *p; MPTRIG *rptrig; rptrig = calloc(1, sizeof(*rptrig)); rptrig->type = type; rptrig->vnum = vnum; rptrig->phrase = str_dup(phrase); for (p = rptrig->phrase; *p; p++) if (ISUPPER(*p)) { SET_BIT(rptrig->flags, TRIG_CASEDEP); break; } if ((type == TRIG_ACT || type == TRIG_SPEECH) && phrase[0] == '*') { int errcode; int cflags = REG_EXTENDED | REG_NOSUB; SET_BIT(rptrig->flags, TRIG_REGEXP); if (!IS_SET(rptrig->flags, TRIG_CASEDEP)) cflags |= REG_ICASE; rptrig->extra = malloc(sizeof(regex_t)); errcode = regcomp(rptrig->extra, phrase+1, cflags); if (errcode) { char buf[MAX_STRING_LENGTH]; regerror(errcode, rptrig->extra, buf, sizeof(buf)); log_printf("bad ROOM trigger for vnum %d (phrase '%s'): %s", vnum, phrase, buf); } } return rptrig; } void rptrig_fix(ROOM_INDEX_DATA *room) { MPTRIG *rptrig; for (rptrig = room->rprogs; rptrig; rptrig = rptrig->next) SET_BIT(room->rprog_flags, rptrig->type); } void rptrig_free(MPTRIG *rp) { if (!rp) return; if (IS_SET(rp->flags, TRIG_REGEXP)) { regfree(rp->extra); free(rp->extra); } free_string(rp->phrase); free(rp); }