/*___________________________________________________________________________* )()( 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; } }