/*___________________________________________________________________________*
)()( DalekenMUD 1.12 (C) 2000 )()(
`][' by Martin Thomson, Lee Brooks, `]['
|| Ken Herbert and David Jacques ||
|| ----------------------------------------------------------------- ||
|| Envy Diku Mud improvements copyright (C) 1994 by Michael Quan, ||
|| David Love, Guilherme 'Willie' Arnold, and Mitchell Tse. ||
|| Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael ||
|| Chastain, Michael Quan, and Mitchell Tse. ||
|| Original Diku Mud copyright (C) 1990, 1991 ||
|| by Sebastian Hammer, Michael Seifert, Hans Henrik St{rfeldt, ||
|| Tom Madsen, and Katja Nyboe. ||
|| ----------------------------------------------------------------- ||
|| Any use of this software must follow the licenses of the ||
|| creators. 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. ||
|| ----------------------------------------------------------------- ||
|| mem.c ||
|| Memory management/recycling code, basically a set of C++ style ||
|| "constructors" and "destructors" for most datatypes. ||
*_/<>\_________________________________________________________________/<>\_*/
#include "mud.h"
#include "olc.h"
#include "event.h"
#include "db.h"
/* from event.c */
void event_remove_global args( ( EVENT *e ) );
/*
* Globals
*/
ALIAS_DATA *alias_free;
AREA_DATA *area_free;
EXTRA_DESCR_DATA *extra_descr_free;
EXIT_DATA *exit_free;
ROOM_INDEX_DATA *room_index_free;
OBJ_INDEX_DATA *obj_index_free;
SHOP_DATA *shop_free;
MOB_INDEX_DATA *mob_index_free;
RESET_DATA *reset_free;
HELP_DATA *help_free;
QUEST_DATA *quest_free;
MPROG_VAR *mpvar_free;
RELIGION_DATA *religion_free;
RELIGION_SKILL *religion_skill_free;
CLAN_DATA *clan_free;
NOTE_DATA *note_free;
BAN_DATA *ban_free;
POSE_DATA *pose_free;
PLANE_DATA *plane_free;
MPROG_DATA *mprog_free;
MPROG_GLOBAL *mprog_global_free;
HIGHEST_ENTRY *highent_free;
TEXT_BLOCK *text_block_free;
extern HELP_DATA *help_last;
SOCIAL_DATA *social_free;
extern RELIGION_DATA *religion_last;
extern CLAN_DATA *clan_last;
/*****************************************************************************
Name: new_reset_data
Purpose: Creates and clears a reset structure.
****************************************************************************/
RESET_DATA *new_reset_data( void )
{
RESET_DATA *pReset;
if( !reset_free )
{
pReset = alloc_perm( sizeof( *pReset ) );
top_reset++;
}
else
{
pReset = reset_free;
reset_free = reset_free->next;
}
pReset->next = NULL;
pReset->command = 'X';
pReset->arg1 = 0;
pReset->arg2 = 0;
return pReset;
}
/*****************************************************************************
Name: free_reset_data
Purpose: Clears and deletes a reset structure.
****************************************************************************/
void free_reset_data( RESET_DATA *pReset )
{
pReset->next = reset_free;
reset_free = pReset;
return;
}
/*****************************************************************************
Name: new_area
Purpose: Creates and clears a new area structure.
****************************************************************************/
AREA_DATA *new_area( void )
{
AREA_DATA *pArea;
char buf[MAX_INPUT_LENGTH];
if( !area_free )
{
pArea = alloc_perm( sizeof( *pArea ) );
top_area++;
}
else
{
pArea = area_free;
area_free = area_free->next;
}
pArea->next = NULL;
pArea->name = str_dup( "New area" );
pArea->plane = plane_lookup( "unfinished" );
pArea->recall = ROOM_VNUM_TEMPLE;
pArea->area_flags = AREA_ADDED;
pArea->security = 1;
pArea->builders = str_dup( "None" );
pArea->lvnum = 0;
pArea->uvnum = 0;
pArea->age = 15;
pArea->nplayer = 0;
pArea->nmobile = 0;
pArea->order = NULL;
pArea->token_room = 0;
pArea->vnum = top_area - 1; /* OLC 1.1b */
sprintf( buf, "area%d.are", pArea->vnum );
pArea->filename = str_dup( buf );
pArea->description = &str_empty[0];
pArea->repop = &str_empty[0];
return pArea;
}
/*****************************************************************************
Name: free_area
Purpose: Clears and deletes an area structure.
****************************************************************************/
void free_area( AREA_DATA *pArea )
{
free_string( pArea->name );
free_string( pArea->filename );
free_string( pArea->builders );
while( pArea->events )
{
EVENT *tmp;
tmp = pArea->events;
pArea->events = tmp->next_local;
event_remove_global( tmp );
free_event( tmp );
}
pArea->next = area_free->next;
area_free = pArea;
return;
}
/*
* Memory note: since exits can be freed without knowing which room they
* belong to, there should be some way for an exit to refer to the room it is
* in. In order to do this, I have reused the vnum variable which is
* originally used when first creating exits. Instead of being the vnum of
* the room it points to it now is the vnum of the room it is from so exits
* can refer back to where they came from without the need for more pointers.
* The need for this back reference is not initially apparent except when you
* have to remove an exit from some unknown room which points to your room.
* Hence all new exits have to have this reference so they too can be freed.
* --Symposium
*/
EXIT_DATA *new_exit()
{
EXIT_DATA *pExit;
if( !exit_free )
{
pExit = alloc_perm( sizeof( *pExit ) );
top_exit++;
}
else
{
pExit = exit_free;
exit_free = exit_free->next;
}
pExit->to_room = NULL;
pExit->exit_info = 0;
pExit->key = -1;
pExit->keyword = &str_empty[0];;
pExit->description = &str_empty[0];;
pExit->rs_flags = 0;
pExit->next = exit_list;
exit_list = pExit;
return pExit;
}
void free_exit( EXIT_DATA * pExit )
{
EXIT_DATA *ex;
ROOM_INDEX_DATA *room;
int door;
free_string( pExit->keyword );
free_string( pExit->description );
/* remove it from the exit list */
if( pExit == exit_list )
{
exit_list = exit_list->next;
}
else
{
for( ex = exit_list; ex; ex = ex->next )
{
if( ex->next == pExit )
{
ex->next = pExit->next;
break;
}
}
}
/* remove it from it's room */
room = get_room_index( pExit->vnum );
if( !room )
{
bug( "Exit with no return adress for in_room." );
pExit->next = exit_free;
exit_free = pExit;
return;
}
for( door = 0; door < MAX_DIR; door++ )
{
if( room->exit[door] == pExit )
room->exit[door] = NULL;
}
pExit->next = exit_free;
exit_free = pExit;
return;
}
EXTRA_DESCR_DATA *new_extra_descr( void )
{
EXTRA_DESCR_DATA *pExtra;
if( !extra_descr_free )
{
pExtra = alloc_perm( sizeof( *pExtra ) );
top_ed++;
}
else
{
pExtra = extra_descr_free;
extra_descr_free = extra_descr_free->next;
}
pExtra->keyword = &str_empty[0];
pExtra->description = &str_empty[0];
pExtra->next = NULL;
return pExtra;
}
void free_extra_descr( EXTRA_DESCR_DATA * pExtra )
{
free_string( pExtra->keyword );
free_string( pExtra->description );
pExtra->next = extra_descr_free;
extra_descr_free = pExtra;
return;
}
ROOM_INDEX_DATA *new_room_index( void )
{
ROOM_INDEX_DATA *pRoom;
int door;
if( !room_index_free )
{
pRoom = alloc_perm( sizeof( *pRoom ) );
top_room++;
}
else
{
pRoom = room_index_free;
room_index_free = room_index_free->next;
}
pRoom->next = NULL;
pRoom->people = NULL;
pRoom->contents = NULL;
pRoom->extra_descr = NULL;
pRoom->area = NULL;
for( door = 0; door < MAX_DIR; door++ )
pRoom->exit[door] = NULL;
pRoom->name = &str_empty[0];
pRoom->description = &str_empty[0];
pRoom->vnum = 0;
pRoom->room_flags = 0;
pRoom->light = 0;
pRoom->sector_type = 0;
pRoom->mudprogs = NULL;
return pRoom;
}
void free_room_index( ROOM_INDEX_DATA *pRoom )
{
int i;
EXTRA_DESCR_DATA *pExtra, *pExtra_next;
RESET_DATA *pReset, *pReset_next;
ROOM_INDEX_DATA *room1, *room2;
EXIT_DATA *ex, *ex_next;
free_string( pRoom->name );
free_string( pRoom->description );
free_mprog( pRoom->mudprogs );
pRoom->mudprogs = NULL;
/* clear exits on both sides */
for( i = 0; i < MAX_DIR; i++ )
{
if( pRoom->exit[i] )
free_exit( pRoom->exit[i] );
}
for( ex = exit_list; ex; ex = ex_next )
{
ex_next = ex->next;
if( ex->to_room == pRoom )
free_exit( ex );
}
/* clear extra descriptions and resets */
for( pExtra = pRoom->extra_descr; pExtra; pExtra = pExtra_next )
{
pExtra_next = pExtra->next;
free_extra_descr( pExtra );
}
pRoom->extra_descr = NULL;
for( pReset = pRoom->reset_first; pReset; pReset = pReset_next )
{
pReset_next = pReset->next;
free_reset_data( pReset );
}
pRoom->reset_first = NULL;
/* events */
while( pRoom->events )
{
EVENT *tmp;
tmp = pRoom->events;
pRoom->events = tmp->next_local;
event_remove_global( tmp );
free_event( tmp );
}
/* take it off the list */
room1 = room_index_hash[pRoom->vnum % MAX_KEY_HASH];
if( pRoom == room1 )
{
room_index_hash[pRoom->vnum % MAX_KEY_HASH] = room1->next;
}
else
{
for( room2 = room1; room2; room2 = room2->next )
{
if( room2->next == pRoom )
{
room2->next = pRoom->next;
break;
}
}
if( !room2 )
{
bug( "Trying to free a room not on the list." );
}
}
pRoom->next = room_index_free;
room_index_free = pRoom;
return;
}
AFFECT_DATA *new_affect( void )
{
AFFECT_DATA *pAf;
if( !affect_free )
{
pAf = alloc_perm( sizeof( *pAf ) );
top_affect++;
}
else
{
pAf = affect_free;
affect_free = affect_free->next;
}
pAf->next = NULL;
pAf->location = 0;
pAf->modifier = 0;
pAf->type = 0;
pAf->level = 0;
pAf->duration = 0;
vzero( pAf->bitvector );
return pAf;
}
void free_affect( AFFECT_DATA *pAf )
{
pAf->next = affect_free;
affect_free = pAf;
return;
}
SHOP_DATA *new_shop( void )
{
SHOP_DATA *pShop;
int buy;
if( !shop_free )
{
pShop = alloc_perm( sizeof( *pShop ) );
top_shop++;
}
else
{
pShop = shop_free;
shop_free = shop_free->next;
}
pShop->next = NULL;
for( buy = 0; buy < MAX_TRADE; buy++ )
pShop->buy_type[buy] = 0;
pShop->profit_buy = 100;
pShop->profit_sell = 100;
pShop->open_hour = 0;
pShop->close_hour = 23;
return pShop;
}
void free_shop( SHOP_DATA * pShop )
{
if( !pShop )
return;
pShop->next = shop_free;
shop_free = pShop;
return;
}
OBJ_INDEX_DATA *new_obj_index( void )
{
OBJ_INDEX_DATA *pObj;
int value;
if( !obj_index_free )
{
pObj = alloc_perm( sizeof( *pObj ) );
top_obj_index++;
}
else
{
pObj = obj_index_free;
obj_index_free = obj_index_free->next;
}
pObj->next = NULL;
pObj->extra_descr = NULL;
pObj->affected = NULL;
pObj->area = NULL;
pObj->name = str_dup( "no name" );
pObj->short_descr = str_dup( "(no short description)" );
pObj->description = str_dup( "(no description)" );
pObj->vnum = 0;
pObj->item_type = ITEM_TRASH;
pObj->extra_flags = 0;
pObj->wear_flags = 0;
pObj->count = 0;
pObj->weight = 0;
pObj->cost = 0;
pObj->condition = 1000;
pObj->reset_chance = 1000;
for( value = 0; value < 4; value++ )
pObj->value[value] = 0;
pObj->mudprogs = NULL;
return pObj;
}
void free_obj_index( OBJ_INDEX_DATA * pObj )
{
OBJ_INDEX_DATA *obj1, *obj2;
EXTRA_DESCR_DATA *pExtra, *pExtra_next;
AFFECT_DATA *pAf, *pAf_next;
free_string( pObj->name );
free_string( pObj->short_descr );
free_string( pObj->description );
free_mprog( pObj->mudprogs );
pObj->mudprogs = NULL;
for( pAf = pObj->affected; pAf; pAf = pAf_next )
{
pAf_next = pAf->next;
free_affect( pAf );
}
for( pExtra = pObj->extra_descr; pExtra; pExtra = pExtra_next )
{
pExtra_next = pExtra->next;
free_extra_descr( pExtra );
}
obj1 = obj_index_hash[pObj->vnum % MAX_KEY_HASH];
if( pObj == obj1 )
{
obj_index_hash[pObj->vnum % MAX_KEY_HASH] = obj1->next;
}
else
{
for( obj2 = obj1; obj2; obj2 = obj2->next )
{
if( obj2->next == pObj )
{
obj2->next = pObj->next;
break;
}
}
if( !obj2 )
{
bug( "Trying to free an object not on the list." );
}
}
pObj->next = obj_index_free;
obj_index_free = pObj;
return;
}
MOB_INDEX_DATA *new_mob_index( void )
{
MOB_INDEX_DATA *pMob;
if( !mob_index_free )
{
pMob = alloc_perm( sizeof( *pMob ) );
top_mob_index++;
}
else
{
pMob = mob_index_free;
mob_index_free = mob_index_free->next;
}
pMob->next = NULL;
pMob->spec_fun = 0;
pMob->pShop = NULL;
pMob->area = NULL;
pMob->name = str_dup( "no name" );
pMob->short_descr = str_dup( "(no short description)" );
pMob->long_descr = str_dup( "(no long description)\n\r" );
pMob->description = &str_empty[0];
pMob->vnum = 0;
pMob->count = 0;
pMob->killed = 0;
pMob->sex = 0;
pMob->level = 0;
vset( pMob->act, ACT_IS_NPC );
vzero( pMob->affected_by );
pMob->alignment = 0;
pMob->reset_chance = 1000;
pMob->mudprogs = NULL;
return pMob;
}
void free_mob_index( MOB_INDEX_DATA * pMob )
{
MOB_INDEX_DATA *mb1, *mb2;
free_string( pMob->name );
free_string( pMob->short_descr );
free_string( pMob->long_descr );
free_string( pMob->description );
free_mprog( pMob->mudprogs );
pMob->mudprogs = NULL;
free_shop( pMob->pShop );
mb1 = mob_index_hash[pMob->vnum % MAX_KEY_HASH];
if( pMob == mb1 )
{
mob_index_hash[pMob->vnum % MAX_KEY_HASH] = mb1->next;
}
else
{
for( mb2 = mb1; mb2; mb2 = mb2->next )
{
if( mb2->next == pMob )
{
mb2->next = pMob->next;
break;
}
}
if( !mb2 )
{
bug( "Trying to free a mob not on the list." );
}
}
pMob->next = mob_index_free;
mob_index_free = pMob;
return;
}
MPROG_DATA *new_mprog( void )
{
MPROG_DATA *mprg;
if( !mprog_free )
{
top_mprog++;
mprg = (MPROG_DATA *) alloc_perm( sizeof( MPROG_DATA ) );
}
else
{
mprg = mprog_free;
mprog_free = mprg->next;
}
mprg->type = 0;
mprg->arglist = str_dup( "0" );
mprg->comlist = str_dup( "" );
return mprg;
}
void free_mprog( MPROG_DATA *mprg )
{
MPROG_DATA *next;
for( ; mprg; mprg = next )
{
next = mprg->next;
free_string( mprg->arglist );
free_string( mprg->comlist );
mprg->next = mprog_free;
mprog_free = mprg;
}
return;
}
MPROG_GLOBAL *new_mprog_global( void )
{
MPROG_GLOBAL *mprg;
if( !mprog_global_free )
{
top_mprog_global++;
mprg = (MPROG_GLOBAL *) alloc_perm( sizeof( MPROG_GLOBAL ) );
}
else
{
mprg = mprog_global_free;
mprog_global_free = mprg->next;
}
mprg->vnum = 0;
mprg->area = NULL;
mprg->type = 0;
mprg->allowed = 0;
mprg->arglist = str_dup( "0" );
mprg->comlist = str_dup( "" );
return mprg;
}
void free_mprog_global( MPROG_GLOBAL *mprg )
{
MPROG_GLOBAL *prev;
if( mprg == global_progs[mprg->vnum % MPROG_GLOBAL_HASH] )
global_progs[mprg->vnum % MPROG_GLOBAL_HASH] = mprg->next;
else
{
for( prev = global_progs[mprg->vnum % MPROG_GLOBAL_HASH];
prev; prev = prev->next )
if( prev->next == mprg )
break;
if( !prev )
{
bug( "Disconnected global prog passed to free_mprog_global." );
return;
}
prev->next = mprg->next;
}
free_string( mprg->arglist );
free_string( mprg->comlist );
mprg->next = mprog_global_free;
mprog_global_free = mprg;
return;
}
void add_social( SOCIAL_DATA *social )
{
int iHash;
for( iHash = 0; social->name[iHash]; iHash++ )
social->name[iHash] = LOWER( social->name[iHash] );
if( social->name[0] < 'a' || social->name[0] > 'z' )
iHash = 0;
else
iHash = ( social->name[0] - 'a' ) + 1;
if( social_table[iHash] == NULL
|| strcmp( social->name, social_table[iHash]->name ) < 0 )
{
social->next = social_table[iHash];
social_table[iHash] = social;
}
else
{
SOCIAL_DATA *prev;
for( prev = social_table[iHash]; prev && prev->next;
prev = prev->next )
{
if( strcmp( social->name, social_table[iHash]->name ) < 0 )
break;
}
if( prev )
{
social->next = prev->next;
prev->next = social;
}
}
}
SOCIAL_DATA *new_social( char *name )
{
SOCIAL_DATA *soc;
if( !social_free )
{
top_social++;
soc = (SOCIAL_DATA *) alloc_perm( sizeof( SOCIAL_DATA ) );
}
else
{
soc = social_free;
social_free = soc->next;
}
soc->name = str_dup( name );
soc->char_no_arg = &str_empty[0];
soc->others_no_arg = &str_empty[0];
soc->char_found = &str_empty[0];
soc->others_found = &str_empty[0];
soc->vict_found = &str_empty[0];
soc->char_auto = &str_empty[0];
soc->others_auto = &str_empty[0];
if( name != NULL )
{
add_social( soc );
}
else
{
soc->next = social_table[0];
social_table[0] = soc;
}
top_social++;
return soc;
}
void free_social( SOCIAL_DATA * soc )
{
SOCIAL_DATA *soc2;
int iHash;
free_string( soc->name );
free_string( soc->char_no_arg );
free_string( soc->others_no_arg );
free_string( soc->char_found );
free_string( soc->others_found );
free_string( soc->vict_found );
free_string( soc->char_auto );
free_string( soc->others_auto );
if( soc->name[0] < 'a' || soc->name[0] > 'z' )
iHash = 0;
else
iHash = ( soc->name[0] - 'a' ) + 1;
if( soc == social_table[iHash] )
{
social_table[iHash] = soc->next;
}
else
{
for( soc2 = social_table[iHash]; soc2; soc2 = soc2->next )
{
if( soc2->next == soc )
break;
}
if( !soc2 )
{
bug( "Social not on the list." );
soc->next = social_free;
social_free = soc;
return;
}
soc2->next = soc->next;
}
soc->next = social_free;
social_free = soc;
}
HELP_DATA *new_help( void )
{
HELP_DATA *pHelp;
if( !help_free )
{
pHelp = (HELP_DATA *) alloc_perm( sizeof( *pHelp ) );
}
else
{
pHelp = help_free;
help_free = pHelp->next;
}
pHelp->area = NULL;
pHelp->level = 0;
pHelp->keyword = &str_empty[0];
pHelp->text = &str_empty[0];
if( !help_first )
help_first = pHelp;
if( help_last )
help_last->next = pHelp;
help_last = pHelp;
pHelp->next = NULL;
top_help++;
return pHelp;
}
void free_help( HELP_DATA * pHelp )
{
HELP_DATA *hlp;
free_string( pHelp->keyword );
free_string( pHelp->text );
if( pHelp == help_first )
{
help_first = pHelp->next;
}
else
{
for( hlp = help_first; hlp; hlp = hlp->next )
{
if( hlp->next == pHelp )
break;
}
if( !hlp )
{
bug( "Help not on the list." );
pHelp->next = help_free;
help_free = pHelp;
return;
}
hlp->next = pHelp->next;
}
pHelp->next = help_free;
help_free = pHelp;
}
QUEST_DATA *new_quest()
{
QUEST_DATA *qq;
if( quest_free )
{
qq = quest_free;
quest_free = quest_free->next;
}
else
{
qq = alloc_perm( sizeof( *qq ) );
}
qq->score = 0;
qq->time = 15;
qq->target = NULL;
qq->type = QUEST_NONE;
return qq;
}
void free_quest( QUEST_DATA *qq )
{
switch( qq->type )
{
case QUEST_NONE:
case QUEST_ITEM:
case QUEST_KILL:
case QUEST_BODY_PART:
break;
case QUEST_RACE_CORPSE:
free_mem( qq->target, sizeof( struct quest_race_corpse ) );
break;
case QUEST_OBJ_MATERIAL:
free_mem( qq->target, sizeof( struct quest_obj_material ) );
break;
default:
bug( "Freeing a quest with unknown quest %d.", qq->type );
break;
}
qq->next = quest_free;
quest_free = qq;
}
MPROG_VAR *new_mpvar( void )
{
MPROG_VAR *var;
if( !mpvar_free )
{
var = alloc_perm( sizeof( MPROG_VAR ) );
}
else
{
var = mpvar_free;
mpvar_free = var->next;
}
var->name = str_dup( "" );
var->value = str_dup( "" );
return var;
}
void free_mpvar( MPROG_VAR * var )
{
free_string( var->name );
free_string( var->value );
var->next = mpvar_free;
mpvar_free = var;
return;
}
RELIGION_DATA *new_religion_data( void )
{
RELIGION_DATA *new_rel;
char buf[MAX_INPUT_LENGTH];
if( !religion_free )
{
new_rel = (RELIGION_DATA *)alloc_perm( sizeof( RELIGION_DATA ) );
top_religion++;
}
else
{
new_rel = religion_free;
religion_free = new_rel->next;
}
new_rel->name = str_dup( "new religion" );
new_rel->god_name = str_dup( "GOD" );
sprintf( buf, "relig%d.rel", top_religion );
new_rel->token = 0;
new_rel->sac_events = 0;
new_rel->align_min = 0;
new_rel->align_max = 0;
new_rel->skills = NULL;
if( !religion_first )
religion_first = new_rel;
if( religion_last )
religion_last->next = new_rel;
religion_last = new_rel;
return new_rel;
}
void free_religion_data( RELIGION_DATA *rel )
{
RELIGION_DATA *prev;
RELIGION_SKILL *ski1, *ski2;
free_string( rel->name );
free_string( rel->god_name );
for( ski1 = rel->skills; ski1; ski1 = ski2 )
{
ski2 = ski1->next;
free_religion_skill( ski1 );
}
if( religion_first == rel )
{
religion_first = rel->next;
if( religion_last == rel )
religion_last = NULL;
}
else
{
for( prev = religion_first; prev; prev = prev->next )
if( prev->next == rel )
break;
if( !prev )
bug( "free_religion_data: religion not on list." );
else
{
if( religion_last == rel )
{
religion_last = prev;
}
prev->next = rel->next;
}
}
rel->next = religion_free;
}
RELIGION_SKILL *new_religion_skill( )
{
RELIGION_SKILL *ski;
if( !religion_skill_free )
ski = (RELIGION_SKILL *)alloc_perm( sizeof( RELIGION_SKILL ) );
else
{
ski = religion_skill_free;
religion_skill_free = ski->next;
}
ski->sn = -1;
ski->level = RANK_OVERLORD;
return ski;
}
void free_religion_skill( RELIGION_SKILL *ski )
{
ski->next = religion_skill_free;
religion_skill_free = ski;
}
POSE_DATA *new_pose_data()
{
POSE_DATA *pose;
if( !pose_free )
{
pose = (POSE_DATA *)alloc_perm( sizeof( POSE_DATA ) );
top_pose++;
}
else
{
pose = pose_free;
pose_free = pose_free->next;
}
pose->to_char = str_dup( "You pose." );
pose->to_room = str_dup( "$n poses." );
return pose;
}
void free_pose_data( POSE_DATA *pose )
{
free_string( pose->to_char );
free_string( pose->to_room );
pose->next = pose_free;
pose_free = pose;
}
CLAN_DATA *new_clan_data()
{
CLAN_DATA *new_clan;
char buf[MAX_INPUT_LENGTH];
if( !clan_free )
{
new_clan = (CLAN_DATA *)alloc_perm( sizeof( CLAN_DATA ) );
top_clan++;
}
else
{
new_clan = clan_free;
clan_free = new_clan->next;
}
sprintf( buf, "clan%d.cln", top_clan );
new_clan->name = str_dup( "new clan" );
new_clan->motto = str_dup( "" );
new_clan->description = str_dup( "" );
new_clan->overlord = str_dup( "" );
new_clan->chieftains = str_dup( "" );
new_clan->enemies = str_dup( "" );
new_clan->recall = ROOM_VNUM_TEMPLE;
new_clan->karma = 10;
if( !clan_first )
clan_first = new_clan;
if( clan_last )
clan_last->next = new_clan;
clan_last = new_clan;
return new_clan;
}
void free_clan_data( CLAN_DATA *clan )
{
CLAN_DATA *prev;
free_string( clan->name );
free_string( clan->motto );
free_string( clan->description );
free_string( clan->overlord );
free_string( clan->chieftains );
free_string( clan->enemies );
if( clan == clan_first )
{
clan_first = clan->next;
if( clan_last == clan )
clan_last = NULL;
}
else
{
for( prev = clan_first; prev; prev = prev->next )
if( prev->next == clan )
break;
if( !prev )
bug( "free_clan_data: clan not on list." );
else
{
prev->next = clan->next;
if( clan_last == clan )
clan_last = prev;
}
}
clan->next = clan_free;
clan_free = clan;
}
/*
* Create an instance of an alias
*/
ALIAS_DATA *new_alias( void )
{
ALIAS_DATA *al;
if( !alias_free )
return alloc_perm( sizeof( ALIAS_DATA ) );
al = alias_free;
alias_free = alias_free->next;
al->name = &str_empty[0];
al->command = &str_empty[0];
return al;
}
void free_alias( ALIAS_DATA *al )
{
free_string( al->name );
free_string( al->command );
al->next = alias_free;
alias_free = al;
return;
}
/*
* Create an instance of a plane.
* Randomise time and weather.
*/
PLANE_DATA *new_plane( void )
{
PLANE_DATA *pl;
if( !plane_free )
return (PLANE_DATA *)alloc_perm( sizeof( PLANE_DATA ) );
pl = plane_free;
plane_free = plane_free->next;
pl->name = &str_empty[0];
pl->next = plane_list;
plane_list = pl;
pl->time.hour = number_range( 0, 23 );
pl->time.day = number_range( 0, 34 );
pl->time.month = number_range( 0, 16 );
pl->time.year = number_bits( 30 );
if( pl->time.hour < 5 )
pl->weather.sunlight = SUN_DARK;
else if( pl->time.hour < 6 )
pl->weather.sunlight = SUN_RISE;
else if( pl->time.hour < 19 )
pl->weather.sunlight = SUN_LIGHT;
else if( pl->time.hour < 20 )
pl->weather.sunlight = SUN_SET;
else
pl->weather.sunlight = SUN_DARK;
pl->weather.change = 0;
pl->weather.mmhg = 960;
if( pl->time.month >= 7 && pl->time.month <= 12 )
pl->weather.mmhg += number_range( 1, 50 );
else
pl->weather.mmhg += number_range( 1, 80 );
if( pl->weather.mmhg <= 980 )
pl->weather.sky = SKY_LIGHTNING;
else if( pl->weather.mmhg <= 1000 )
pl->weather.sky = SKY_RAINING;
else if( pl->weather.mmhg <= 1020 )
pl->weather.sky = SKY_CLOUDY;
else
pl->weather.sky = SKY_CLOUDLESS;
return pl;
}
void free_plane( PLANE_DATA *pl )
{
free_string( pl->name );
while( pl->events )
{
EVENT *tmp;
tmp = pl->events;
pl->events = tmp->next_local;
event_remove_global( tmp );
free_event( tmp );
}
if( pl == plane_list )
{
plane_list = pl->next;
}
else
{
PLANE_DATA *prev;
for( prev = plane_list; prev; prev = prev->next )
if( prev->next == pl )
break;
if( !prev )
bug( "free_plane: plane not on list." );
else
prev->next = pl->next;
}
pl->next = plane_free;
plane_free = pl;
return;
}
HIGHEST_ENTRY *new_highent( )
{
HIGHEST_ENTRY *ent;
if( highent_free )
{
ent = highent_free;
highent_free = ent->next;
}
else
ent = alloc_perm( sizeof( HIGHEST_ENTRY ) );
ent->name = &str_empty[0];
return ent;
}
void free_highent( HIGHEST_ENTRY *ent )
{
free_string( ent->name );
ent->next = highent_free;
highent_free = ent;
}
TEXT_BLOCK *new_text_block( int size )
{
TEXT_BLOCK *block, *prev = NULL;
if( text_block_free )
{
for( block = text_block_free; block; block = block->next )
{
if( block->size >= size )
break;
prev = block;
}
if( block )
{
if( prev )
prev->next = block->next;
else
text_block_free = block->next;
return block;
}
}
block = alloc_perm( sizeof( TEXT_BLOCK ) );
/* Round the size up to the next 128 bytes for simplicity. */
if( size % 128 != 0 )
{
size >>= 7;
++size;
size = size << 7;
}
block->str = alloc_perm( size );
block->size = size;
top_text_block++;
size_text_block += size + sizeof( TEXT_BLOCK );
return block;
}
void free_text_block( TEXT_BLOCK *block )
{
TEXT_BLOCK *prev;
if( text_block_free == NULL || text_block_free->size > block->size )
{
block->next = text_block_free;
text_block_free = block;
}
else
{
for( prev = text_block_free; prev && prev->next; prev = prev->next )
if( prev->next->size > block->size )
break;
if( !prev )
{
bug( "free_text_block: wierd stuff happening." );
return;
}
block->next = prev->next;
prev->next = block;
}
}