/*************************************************************************** * 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-1996 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@efn.org) * * Gabrielle Taylor * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * ***************************************************************************/ #if defined(macintosh) #include <types.h> #include <time.h> #else #include <sys/types.h> #if !defined(WIN32) #include <sys/time.h> #endif #endif #include <stdio.h> #include <string.h> #include <stdlib.h> #include "merc.h" #include "recycle.h" #include "events.h" #include "clan.h" #define STANDARD_ALLOCMEM(type, name) \ type * name ## _free; \ int name ## _created; \ int name ## _allocated; \ \ type * new_ ## name( void ) \ { \ type * temp; \ static type tZero; \ \ if ( name ## _free ) \ { \ temp = name ## _free; \ name ## _free = name ## _free->next; \ } \ else \ { \ temp = alloc_mem( sizeof(*temp) ); \ name ## _allocated++; \ } \ \ *temp = tZero; \ \ name ## _created++; \ \ return temp; \ } #define STANDARD_FREEMEM(type, name) \ int name ## _freed; \ \ void free_ ## name( type * temp ) \ { \ temp->next = name ## _free; \ name ## _free = temp; \ name ## _freed++; \ } #define VAL_ALLOCMEM(type, name) \ type * name ## _free; \ int name ## _created; \ int name ## _allocated; \ \ type * new_ ## name( void ) \ { \ type * temp; \ static type tZero; \ \ if ( name ## _free ) \ { \ temp = name ## _free; \ name ## _free = name ## _free->next; \ } \ else \ { \ temp = alloc_mem( sizeof(*temp) ); \ name ## _allocated++; \ } \ \ *temp = tZero; \ \ VALIDATE(temp); \ \ name ## _created++; \ \ return temp; \ } #define VAL_FREEMEM(type, name) \ int name ## _freed; \ \ void free_ ## name( type * temp ) \ { \ if (!IS_VALID(temp)) \ return; \ \ INVALIDATE(temp); \ temp->next = name ## _free; \ name ## _free = temp; \ name ## _freed++; \ } #define allocfunc(a,b) \ STANDARD_ALLOCMEM(a,b) \ STANDARD_FREEMEM(a,b) #define allocfunc_val(a,b) \ VAL_ALLOCMEM(a,b) \ VAL_FREEMEM(a,b) #include "allocfunc.h" #undef allocfunc #undef allocfunc_val /* stuff for recyling notes */ NOTE_DATA *note_free; NOTE_DATA *new_note() { NOTE_DATA *note; if (note_free == NULL) note = alloc_perm(sizeof(*note)); else { note = note_free; note_free = note_free->next; } VALIDATE(note); return note; } void free_note(NOTE_DATA *note) { if (!IS_VALID(note)) return; free_string( note->text ); free_string( note->subject ); free_string( note->to_list ); free_string( note->date ); free_string( note->sender ); INVALIDATE(note); note->next = note_free; note_free = note; } bool *new_gknown( void ) { bool *temp; int i; temp = mud_malloc( sizeof( bool ) * MAX_GROUP ); for ( i = 0; i < MAX_GROUP; ++i ) temp[i] = FALSE; return temp; } void free_gknown( bool *temp ) { free(temp); temp = NULL; return; } /* stuff for recycling ban structures */ BAN_DATA *ban_free; BAN_DATA *new_ban(void) { static BAN_DATA ban_zero; BAN_DATA *ban; if (ban_free == NULL) ban = alloc_perm(sizeof(*ban)); else { ban = ban_free; ban_free = ban_free->next; } *ban = ban_zero; VALIDATE(ban); ban->name = &str_empty[0]; return ban; } void free_ban(BAN_DATA *ban) { if (!IS_VALID(ban)) return; free_string(ban->name); INVALIDATE(ban); ban->next = ban_free; ban_free = ban; } /* stuff for recycling descriptors */ DESCRIPTOR_DATA *descriptor_free; DESCRIPTOR_DATA *new_descriptor(void) { static DESCRIPTOR_DATA d_zero; DESCRIPTOR_DATA *d; if (descriptor_free == NULL) d = alloc_perm(sizeof(*d)); else { d = descriptor_free; descriptor_free = descriptor_free->next; } *d = d_zero; VALIDATE(d); /* d->connected = CON_GET_NAME; */ d->connected = CON_GET_NEWANSI; d->showstr_head = NULL; d->showstr_point = NULL; d->outsize = 2000; d->pEdit = NULL; /* OLC */ d->pString = NULL; /* OLC */ d->editor = 0; /* OLC */ d->outbuf = alloc_mem( d->outsize ); d->ident = str_dup( "???" ); d->ifd = -1; d->ipid = -1; d->term = 0; d->events = NULL; return d; } void free_descriptor(DESCRIPTOR_DATA *d) { EVENT *ev, *ev_next; if (!IS_VALID(d)) return; for (ev = d->events; ev; ev = ev_next ) { ev_next = ev->nextitem; event_delete( ev ); } free_string( d->host ); free_string( d->ident ); /* identd */ free_string( d->username ); free_string( d->ftp.data ); free_string( d->ftp.filename ); free_mem( d->outbuf, d->outsize ); INVALIDATE(d); d->next = descriptor_free; descriptor_free = d; } /* stuff for recycling gen_data */ GEN_DATA *gen_data_free; bool *new_sk_chosen( void ) { bool *temp; int i; temp = mud_malloc( sizeof(bool) * MAX_SKILL ); for ( i = 0; i < MAX_SKILL; ++i ) temp[i] = 0; return temp; } void free_sk_chosen( bool *temp ) { free(temp); temp = NULL; return; } GEN_DATA *new_gen_data(void) { static GEN_DATA gen_zero; GEN_DATA *gen; if (gen_data_free == NULL) gen = alloc_perm(sizeof(*gen)); else { gen = gen_data_free; gen_data_free = gen_data_free->next; } *gen = gen_zero; gen->skill_chosen = new_sk_chosen(); gen->group_chosen = new_gknown(); VALIDATE(gen); return gen; } void free_gen_data(GEN_DATA *gen) { if (!IS_VALID(gen)) return; free_sk_chosen(gen->skill_chosen); free_gknown(gen->group_chosen); INVALIDATE(gen); gen->next = gen_data_free; gen_data_free = gen; } /* stuff for recycling extended descs */ EXTRA_DESCR_DATA *extra_descr_free; EXTRA_DESCR_DATA *new_extra_descr(void) { EXTRA_DESCR_DATA *ed; if (extra_descr_free == NULL) ed = alloc_perm(sizeof(*ed)); else { ed = extra_descr_free; extra_descr_free = extra_descr_free->next; } ed->keyword = &str_empty[0]; ed->description = &str_empty[0]; VALIDATE(ed); return ed; } void free_extra_descr(EXTRA_DESCR_DATA *ed) { if (!IS_VALID(ed)) return; free_string(ed->keyword); free_string(ed->description); INVALIDATE(ed); ed->next = extra_descr_free; extra_descr_free = ed; } /* stuff for recycling affects */ AFFECT_DATA *affect_free; AFFECT_DATA *new_affect(void) { static AFFECT_DATA af_zero; AFFECT_DATA *af; if (affect_free == NULL) af = alloc_perm(sizeof(*af)); else { af = affect_free; affect_free = affect_free->next; } *af = af_zero; VALIDATE(af); return af; } void free_affect(AFFECT_DATA *af) { if (!IS_VALID(af)) return; INVALIDATE(af); af->next = affect_free; affect_free = af; } /* stuff for recycling objects */ OBJ_DATA *obj_free; OBJ_DATA *new_obj(void) { static OBJ_DATA obj_zero; OBJ_DATA *obj; if (obj_free == NULL) obj = alloc_perm(sizeof(*obj)); else { obj = obj_free; obj_free = obj_free->next; } *obj = obj_zero; VALIDATE(obj); obj_event_add( obj, number_range( PULSE_TICK * 3 / 4, PULSE_TICK * 5 / 4 ), NULL, obj_update_event ); return obj; } void free_obj(OBJ_DATA *obj) { AFFECT_DATA *paf, *paf_next; EXTRA_DESCR_DATA *ed, *ed_next; EVENT *ev, *ev_next; if (!IS_VALID(obj)) return; for (paf = obj->affected; paf != NULL; paf = paf_next) { paf_next = paf->next; free_affect(paf); } obj->affected = NULL; for (ed = obj->extra_descr; ed != NULL; ed = ed_next ) { ed_next = ed->next; free_extra_descr(ed); } obj->extra_descr = NULL; for (ev = obj->events; ev; ev=ev_next) { ev_next=ev->nextitem; event_delete(ev); } free_string( obj->name ); free_string( obj->description ); free_string( obj->short_descr ); free_string( obj->owner ); INVALIDATE(obj); obj->next = obj_free; obj_free = obj; } /* stuff for recyling characters */ CHAR_DATA *char_free; CHAR_DATA *new_char (void) { static CHAR_DATA ch_zero; CHAR_DATA *ch; int i; if (char_free == NULL) ch = alloc_perm(sizeof(*ch)); else { ch = char_free; char_free = char_free->next; } *ch = ch_zero; VALIDATE(ch); ch->name = &str_empty[0]; ch->short_descr = &str_empty[0]; ch->long_descr = &str_empty[0]; ch->description = &str_empty[0]; ch->material = &str_empty[0]; ch->logon = current_time; for (i = 0; i < 4; i++) ch->armor[i] = 100; ch->position = POS_STANDING; ch->hit = 20; ch->max_hit = 20; ch->mana = 100; ch->max_mana = 100; ch->move = 100; ch->max_move = 100; ch->events = NULL; for (i = 0; i < MAX_STATS; i ++) { ch->perm_stat[i] = 13; ch->mod_stat[i] = 0; // para que? } char_event_add( ch, number_range( PULSE_TICK * 3 / 4, PULSE_TICK * 5 / 4 ), (void *) ch->id, char_update_event ); return ch; } sh_int *new_learned( void ) { sh_int *temp; int i; temp = mud_malloc( sizeof( sh_int ) * MAX_SKILL ); for ( i = 0; i < MAX_SKILL; ++i ) temp[i] = 0; return temp; } void free_learned( sh_int *temp ) { free(temp); temp = NULL; return; } void free_char (CHAR_DATA *ch) { OBJ_DATA *obj; OBJ_DATA *obj_next; AFFECT_DATA *paf; AFFECT_DATA *paf_next; EVENT *ev, *ev_next; MEM_DATA *mem, *mem_next; FIGHT_DATA * fd, * fd_next; if (!IS_VALID(ch)) return; if (IS_NPC(ch)) mobile_count--; for (ev = ch->events; ev; ev = ev_next ) { ev_next = ev->nextitem; event_delete( ev ); } for ( mem = ch->memory; mem; mem = mem_next ) { mem_next = mem->next; extract_mem( ch, mem ); } for ( fd = ch->fdata; fd; fd = fd_next ) { fd_next = fd->next; free_fdata( fd ); } for (obj = ch->carrying; obj != NULL; obj = obj_next) { obj_next = obj->next_content; extract_obj(obj, TRUE); } for (paf = ch->affected; paf != NULL; paf = paf_next) { paf_next = paf->next; affect_remove(ch,paf); } free_string(ch->name); free_string(ch->short_descr); free_string(ch->long_descr); free_string(ch->description); free_string(ch->material); if (ch->mprog_target != NULL) free_entity(ch->mprog_target); if (ch->pnote != NULL) free_note(ch->pnote); if (ch->pcdata != NULL) free_pcdata(ch->pcdata); if (ch->level_data != NULL) free_level_data(ch->level_data); if (ch->ent) free_entity(ch->ent); ch->next = char_free; char_free = ch; INVALIDATE(ch); return; } PC_DATA *pcdata_free; PC_DATA *new_pcdata(void) { static PC_DATA pcdata_zero; PC_DATA *pcdata; if (pcdata_free == NULL) pcdata = alloc_perm(sizeof(*pcdata)); else { pcdata = pcdata_free; pcdata_free = pcdata_free->next; } *pcdata = pcdata_zero; /* for (alias = 0; alias < MAX_ALIAS; alias++) { pcdata->alias[alias] = NULL; pcdata->alias_sub[alias] = NULL; } for (alias = 0; alias < MAX_IGNORE; alias++) pcdata->ignore[alias] = NULL; */ // se supone que no necesitamos esto? pcdata->buffer = new_buf(); pcdata->learned = new_learned(); pcdata->group_known = new_gknown(); VALIDATE(pcdata); return pcdata; } void free_pcdata(PC_DATA *pcdata) { int alias; struct prob_data *prob; BANK_DATA *bank; if (!IS_VALID(pcdata)) return; free_string(pcdata->pwd); free_string(pcdata->bamfin); free_string(pcdata->bamfout); free_string(pcdata->title); free_string(pcdata->who_text); free_string(pcdata->mensaje); free_string(pcdata->prompt); free_string(pcdata->prefix); free_buf(pcdata->buffer); free_learned(pcdata->learned); free_gknown(pcdata->group_known); while( (bank = pcdata->bank) ) extract_bank(pcdata, bank); while( (prob = pcdata->prohibido) ) { pcdata->prohibido = pcdata->prohibido->next; free_string( prob->comando ); free( prob ); } for (alias = 0; alias < MAX_ALIAS; alias++) { free_string(pcdata->alias[alias]); free_string(pcdata->alias_sub[alias]); } for (alias = 0; alias < MAX_IGNORE; alias++) free_string(pcdata->ignore[alias]); INVALIDATE(pcdata); pcdata->next = pcdata_free; pcdata_free = pcdata; return; } /* stuff for setting ids */ long last_pc_id; long last_mob_id; long get_pc_id(void) { int val; val = (current_time <= last_pc_id) ? last_pc_id + 1 : current_time; last_pc_id = val; return val; } long get_mob_id(void) { last_mob_id++; return last_mob_id; } int top_memory = 0; /* procedures and constants needed for buffering */ BUFFER *buf_free; /* buffer sizes */ const int buf_size[MAX_BUF_LIST] = { 16,32,64,128,256,1024,2048,4096,8192,16384 }; /* local procedure for finding the next acceptable size */ /* -1 indicates out-of-boundary error */ int get_size (int val) { int i; for (i = 0; i < MAX_BUF_LIST; i++) if (buf_size[i] >= val) { return buf_size[i]; } return -1; } BUFFER *new_buf() { BUFFER *buffer; if (buf_free == NULL) buffer = alloc_perm(sizeof(*buffer)); else { buffer = buf_free; buf_free = buf_free->next; } buffer->next = NULL; buffer->state = BUFFER_SAFE; buffer->size = get_size(BASE_BUF); buffer->string = alloc_mem(buffer->size); buffer->string[0] = '\0'; VALIDATE(buffer); return buffer; } BUFFER *new_buf_size(int size) { BUFFER *buffer; if (buf_free == NULL) buffer = alloc_perm(sizeof(*buffer)); else { buffer = buf_free; buf_free = buf_free->next; } buffer->next = NULL; buffer->state = BUFFER_SAFE; buffer->size = get_size(size); if (buffer->size == -1) { bug("new_buf: buffer size %d too large.",size); exit(1); } buffer->string = alloc_mem(buffer->size); buffer->string[0] = '\0'; VALIDATE(buffer); return buffer; } void free_buf(BUFFER *buffer) { if (!IS_VALID(buffer)) return; free_mem(buffer->string,buffer->size); buffer->string = NULL; buffer->size = 0; buffer->state = BUFFER_FREED; INVALIDATE(buffer); buffer->next = buf_free; buf_free = buffer; } bool add_buf(BUFFER *buffer, char *string) { int len; char *oldstr; int oldsize; oldstr = buffer->string; oldsize = buffer->size; if (buffer->state == BUFFER_OVERFLOW) /* don't waste time on bad strings! */ return FALSE; len = strlen(buffer->string) + strlen(string) + 1; while (len >= buffer->size) /* increase the buffer size */ { buffer->size = get_size(buffer->size + 1); { if (buffer->size == -1) /* overflow */ { buffer->size = oldsize; buffer->state = BUFFER_OVERFLOW; bug("buffer overflow past size %d",buffer->size); return FALSE; } } } if (buffer->size != oldsize) { buffer->string = alloc_mem(buffer->size); strcpy(buffer->string,oldstr); free_mem(oldstr,oldsize); } strcat(buffer->string,string); return TRUE; } void clear_buf(BUFFER *buffer) { buffer->string[0] = '\0'; buffer->state = BUFFER_SAFE; } char *buf_string(BUFFER *buffer) { return buffer->string; } /* stuff for recycling mobprograms */ MPROG_LIST *mprog_free; MPROG_LIST *new_mprog(void) { static MPROG_LIST mp_zero; MPROG_LIST *mp; if (mprog_free == NULL) mp = alloc_perm(sizeof(*mp)); else { mp = mprog_free; mprog_free=mprog_free->next; } *mp = mp_zero; mp->vnum = 0; mp->trig_type = 0; mp->code = str_dup(""); VALIDATE(mp); return mp; } void free_mprog(MPROG_LIST *mp) { if (!IS_VALID(mp)) return; INVALIDATE(mp); mp->next = mprog_free; mprog_free = mp; } MEM_DATA *find_memory( MEM_DATA *memory, long id ) { MEM_DATA *temp; for ( temp = memory; temp; temp = temp->next ) if ( temp->id == id ) return temp; return NULL; } void extract_bank( PC_DATA *pcdata, BANK_DATA *bank ) { if ( pcdata->bank == bank ) { pcdata->bank = pcdata->bank->next; free_bank(bank); } else { BANK_DATA *prev; for ( prev = pcdata->bank; prev; prev = prev->next ) if ( prev->next == bank ) break; if ( !prev ) { bugf( "Extract_bank : prev no encontrado!", 0 ); return; } prev->next = bank->next; free_bank(bank); } return; } HELP_DATA * help_free; HELP_DATA * new_help ( void ) { HELP_DATA * help; if ( help_free ) { help = help_free; help_free = help_free->next; } else help = alloc_perm( sizeof( *help ) ); return help; } void free_help(HELP_DATA *help) { free_string(help->keyword); free_string(help->text); help->next = help_free; help_free = help; } void petition_delete( PETITION_DATA *pet ) { extern PETITION_DATA * petition_list; PETITION_DATA * tmp; if ( pet == petition_list ) petition_list = petition_list->next; else { for ( tmp = petition_list; tmp; tmp = tmp->next ) if ( tmp->next == pet ) break; if ( !tmp ) { bugf( "petition_delete : pet inexistente, char %s", pet->name ); return; } tmp->next = pet->next; } free_petition( pet ); return; }