/
mudtem/
mudtem/area/scripts/
mudtem/bin/
mudtem/log/
mudtem/player/
mudtem/slang/autoconf/
mudtem/slang/doc/
mudtem/slang/doc/OLD/help/
mudtem/slang/doc/internal/
mudtem/slang/doc/text/
mudtem/slang/doc/tm/tools/
mudtem/slang/examples/
mudtem/slang/modules/
mudtem/slang/slsh/
mudtem/slang/slsh/lib/
mudtem/slang/slsh/scripts/
mudtem/slang/src/mkfiles/
mudtem/slang/src/util/
mudtem/src/CVS/
mudtem/src/include/
mudtem/src/include/CVS/
mudtem/src/var/CVS/
/***************************************************************************
 *  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;
}