/***************************************************************************
* 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 *
***************************************************************************/
/***************************************************************************
* ROT 1.4 is copyright 1996-1997 by Russ Walsh *
* By using this code, you have agreed to follow the terms of the *
* ROT license, in the file doc/rot.license *
***************************************************************************/
#if defined(macintosh)
#include <types.h>
#include <time.h>
#else
#include <sys/types.h>
#include <sys/time.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "merc.h"
#include "recycle.h"
/* 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;
}
/* 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 wizlist structures */
WIZ_DATA *wiz_free;
WIZ_DATA *new_wiz ( void )
{
static WIZ_DATA wiz_zero;
WIZ_DATA *wiz;
if ( wiz_free == NULL )
wiz = alloc_perm ( sizeof ( *wiz ) );
else
{
wiz = wiz_free;
wiz_free = wiz_free->next;
}
*wiz = wiz_zero;
VALIDATE ( wiz );
wiz->name = &str_empty[0];
return wiz;
}
void free_wiz ( WIZ_DATA * wiz )
{
if ( !IS_VALID ( wiz ) )
return;
free_string ( wiz->name );
INVALIDATE ( wiz );
wiz->next = wiz_free;
wiz_free = wiz;
}
/* stuff for recycling clanlist structures */
CLN_DATA *cln_free;
CLN_DATA *new_cln ( void )
{
static CLN_DATA cln_zero;
CLN_DATA *cln;
if ( cln_free == NULL )
cln = alloc_perm ( sizeof ( *cln ) );
else
{
cln = cln_free;
cln_free = cln_free->next;
}
*cln = cln_zero;
VALIDATE ( cln );
cln->name = &str_empty[0];
return cln;
}
MBR_DATA *mbr_free;
MBR_DATA *new_mbr ( void )
{
static MBR_DATA mbr_zero;
MBR_DATA *mbr;
if ( mbr_free == NULL )
mbr = alloc_perm ( sizeof ( *mbr ) );
else
{
mbr = mbr_free;
mbr_free = mbr_free->next;
}
*mbr = mbr_zero;
VALIDATE ( mbr );
mbr->name = &str_empty[0];
return mbr;
}
void free_mbr ( MBR_DATA * mbr )
{
if ( !IS_VALID ( mbr ) )
return;
free_string ( mbr->name );
INVALIDATE ( mbr );
mbr->next = mbr_free;
mbr_free = mbr;
}
/* 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->showstr_head = NULL;
d->showstr_point = NULL;
d->outsize = 2000;
d->ansi = TRUE;
d->outbuf = alloc_mem ( d->outsize );
return d;
}
void free_descriptor ( DESCRIPTOR_DATA * d )
{
if ( !IS_VALID ( d ) )
return;
free_string ( d->host );
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;
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;
VALIDATE ( gen );
return gen;
}
void free_gen_data ( GEN_DATA * gen )
{
if ( !IS_VALID ( gen ) )
return;
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 );
return obj;
}
void free_obj ( OBJ_DATA * obj )
{
AFFECT_DATA *paf, *paf_next;
EXTRA_DESCR_DATA *ed, *ed_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;
free_string ( obj->name );
free_string ( obj->description );
free_string ( obj->short_descr );
free_string ( obj->owner );
free_string ( obj->killer );
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->prompt = &str_empty[0];
ch->prefix = &str_empty[0];
ch->die_descr = &str_empty[0];
ch->say_descr = &str_empty[0];
ch->material = &str_empty[0];
ch->logon = current_time;
ch->lines = PAGELEN;
for ( i = 0; i < 4; i++ )
ch->armor[i] = 100;
ch->position = POS_STANDING;
ch->hit = 100;
ch->max_hit = 100;
ch->mana = 100;
ch->max_mana = 100;
ch->move = 100;
ch->max_move = 100;
for ( i = 0; i < MAX_STATS; i++ )
{
ch->perm_stat[i] = 13;
ch->mod_stat[i] = 0;
}
return ch;
}
void free_char ( CHAR_DATA * ch )
{
OBJ_DATA *obj;
OBJ_DATA *obj_next;
AFFECT_DATA *paf;
AFFECT_DATA *paf_next;
if ( !IS_VALID ( ch ) )
return;
if ( IS_NPC ( ch ) )
mobile_count--;
for ( obj = ch->carrying; obj != NULL; obj = obj_next )
{
obj_next = obj->next_content;
extract_obj ( obj );
}
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->prompt );
free_string ( ch->prefix );
free_string ( ch->die_descr );
free_string ( ch->say_descr );
free_string ( ch->material );
if ( ch->pcdata != NULL )
free_pcdata ( ch->pcdata );
ch->next = char_free;
char_free = ch;
INVALIDATE ( ch );
return;
}
PC_DATA *pcdata_free;
PC_DATA *new_pcdata ( void )
{
int alias;
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_FORGET; alias++ )
{
pcdata->forget[alias] = NULL;
}
for ( alias = 0; alias < MAX_DUPES; alias++ )
{
pcdata->dupes[alias] = NULL;
}
pcdata->buffer = new_buf ( );
VALIDATE ( pcdata );
return pcdata;
}
void free_pcdata ( PC_DATA * pcdata )
{
int alias;
if ( !IS_VALID ( pcdata ) )
return;
free_string ( pcdata->pwd );
free_string ( pcdata->bamfin );
free_string ( pcdata->bamfout );
free_string ( pcdata->who_descr );
free_string ( pcdata->title );
free_string ( pcdata->spouse );
free_string ( pcdata->socket );
free_buf ( pcdata->buffer );
for ( alias = 0; alias < MAX_ALIAS; alias++ )
{
free_string ( pcdata->alias[alias] );
free_string ( pcdata->alias_sub[alias] );
}
for ( alias = 0; alias < MAX_FORGET; alias++ )
{
free_string ( pcdata->forget[alias] );
}
for ( alias = 0; alias < MAX_DUPES; alias++ )
{
free_string ( pcdata->dupes[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;
}
MEM_DATA *mem_data_free;
/* procedures and constants needed for buffering */
BUFFER *buf_free;
MEM_DATA *new_mem_data ( void )
{
MEM_DATA *memory;
if ( mem_data_free == NULL )
memory = alloc_mem ( sizeof ( *memory ) );
else
{
memory = mem_data_free;
mem_data_free = mem_data_free->next;
}
memory->next = NULL;
memory->id = 0;
memory->reaction = 0;
memory->when = 0;
VALIDATE ( memory );
return memory;
}
void free_mem_data ( MEM_DATA * memory )
{
if ( !IS_VALID ( memory ) )
return;
memory->next = mem_data_free;
mem_data_free = memory;
INVALIDATE ( memory );
}
/* buffer sizes */
const int buf_size[MAX_BUF_LIST] = {
16, 32, 64, 128, 256, 1024, 2048, 4096, 8192, 16384, 32768, 65536
};
/* 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 );
quit ( 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_empty[0];
mp->trig_phrase = &str_empty[0];
VALIDATE ( mp );
return mp;
}
void free_mprog ( MPROG_LIST * mp )
{
if ( !IS_VALID ( mp ) )
return;
free_string ( mp->code );
free_string ( mp->trig_phrase );
INVALIDATE ( mp );
mp->next = mprog_free;
mprog_free = mp;
}
/* Stuff for recycling imm/auction shit */
AUCTION_DATA *auction_free;
AUCTION_DATA *new_auction ( void )
{
static AUCTION_DATA auc_zero;
AUCTION_DATA *auction;
if ( auction_free == NULL )
auction = alloc_perm ( sizeof ( *auction ) );
else
{
auction = auction_free;
auction_free = auction_free->next;
}
*auction = auc_zero;
VALIDATE ( auction );
return auction;
}
void free_auction ( AUCTION_DATA * auction )
{
if ( !IS_VALID ( auction ) )
return;
auction->current_bid = 0;
auction->gold_held = 0;
auction->high_bidder = NULL;
auction->item = NULL;
auction->min_bid = 0;
auction->owner = NULL;
auction->status = 0;
INVALIDATE ( auction );
auction->next = auction_free;
auction_free = auction;
}