/**************************************************************************r
* 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>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "merc.h"
#include "magic.h"
#include "tables.h"
#include "db.h"
#include "lookup.h"
/*
* Locals.
*/
MOB_INDEX_DATA * mob_index;
OBJ_INDEX_DATA * obj_index;
ROOM_INDEX_DATA * room_index;
DRM_INDEX_DATA * drm_index;
char * string_hash [MAX_KEY_HASH];
AREA_DATA * area_first;
AREA_DATA * area_last;
char * string_space;
char * top_string;
char str_empty [1];
int addlev;
bool changelev;
extern int first_object;
extern int first_mobile;
extern int first_room;
extern int last_object;
extern int last_mobile;
extern int last_room;
extern int newmin;
extern int newmax;
extern int newvnum;
extern bool changevnum;
/*
* Memory management.
* Increase MAX_STRING if you have too.
* Tune the others only if you understand what you're doing.
*/
#define MAX_STRING 300032
#define MAX_PERM_BLOCK 131072
#define MAX_MEM_LIST 12
void * rgFreeList [MAX_MEM_LIST];
int nAllocString;
int sAllocString;
int nAllocPerm;
int sAllocPerm;
/*
* Semi-locals.
*/
bool fBootDb;
FILE * fpArea;
char strArea[MAX_INPUT_LENGTH];
/* returns material number */
int material_lookup (const char *name)
{
return 0;
}
bool is_number ( char *arg )
{
if ( *arg == '\0' )
return FALSE;
if ( *arg == '+' || *arg == '-' )
arg++;
for ( ; *arg != '\0'; arg++ )
{
if ( !isdigit( *arg ) )
return FALSE;
}
return TRUE;
}
int skill_lookup( const char *name )
{
int sn;
for ( sn = 0; sn < MAX_SKILL; sn++ )
{
if ( skill_table[sn].name == NULL )
break;
if ( LOWER(name[0]) == LOWER(skill_table[sn].name[0])
&& !str_prefix( name, skill_table[sn].name ) )
return sn;
}
return -1;
}
int class_lookup (const char *name)
{
int class;
for ( class = 0; class < MAX_CLASS; class++)
{
if (LOWER(name[0]) == LOWER(class_table[class].name[0])
&& !str_prefix( name,class_table[class].name))
return class;
}
return -1;
}
/* returns race number */
int race_lookup (const char *name)
{
int race;
for ( race = 0; race_table[race].name != NULL; race++)
{
if (LOWER(name[0]) == LOWER(race_table[race].name[0])
&& !str_prefix( name,race_table[race].name))
return race;
}
return 0;
}
int liq_lookup (const char *name)
{
int liq;
for ( liq = 0; liq_table[liq].liq_name != NULL; liq++)
{
if (LOWER(name[0]) == LOWER(liq_table[liq].liq_name[0])
&& !str_prefix(name,liq_table[liq].liq_name))
return liq;
}
return -1;
}
int weapon_lookup (const char *name)
{
int type;
for (type = 0; weapon_table[type].name != NULL; type++)
{
if (LOWER(name[0]) == LOWER(weapon_table[type].name[0])
&& !str_prefix(name,weapon_table[type].name))
return type;
}
return -1;
}
int weapon_type (const char *name)
{
int type;
for (type = 0; weapon_table[type].name != NULL; type++)
{
if (LOWER(name[0]) == LOWER(weapon_table[type].name[0])
&& !str_prefix(name,weapon_table[type].name))
return weapon_table[type].type;
}
return WEAPON_EXOTIC;
}
int attack_lookup (const char *name)
{
int att;
for ( att = 0; attack_table[att].name != NULL; att++)
{
if (LOWER(name[0]) == LOWER(attack_table[att].name[0])
&& !str_prefix(name,attack_table[att].name))
return att;
}
return 0;
}
int item_lookup(const char *name)
{
int type;
for (type = 0; item_table[type].name != NULL; type++)
{
if (LOWER(name[0]) == LOWER(item_table[type].name[0])
&& !str_prefix(name,item_table[type].name))
return item_table[type].type;
}
return -1;
}
char *item_name(int item_type)
{
int type;
for (type = 0; item_table[type].name != NULL; type++)
if (item_type == item_table[type].type)
return item_table[type].name;
return "none";
}
char *weapon_name( int weapon_type)
{
int type;
for (type = 0; weapon_table[type].name != NULL; type++)
if (weapon_type == weapon_table[type].type)
return weapon_table[type].name;
return "exotic";
}
bool is_class_obj(OBJ_DATA *obj)
{
return obj->class;
}
void set_def( void )
{
if (!changevnum)
{
newvnum = area_first->min_vnum;
newmin = area_first->min_vnum;
newmax = area_first->max_vnum;
} else {
newvnum -= area_first->min_vnum;
newmin = area_first->min_vnum + newvnum;
newmax = area_first->max_vnum + newvnum;
}
return;
}
void default_mobs( void )
{
MOB_INDEX_DATA *pMobIndex;
int vnum;
printf("Converting MOBILES.\n");
for (vnum = first_mobile; vnum <= last_mobile; vnum++ )
{
if ( ( pMobIndex = get_mob_index( vnum ) ) != NULL )
{
int numa, numb, avg, level, value;
if (changelev)
{
pMobIndex->level += addlev;
if (pMobIndex->level < 0)
pMobIndex->level = 0;
if (pMobIndex->level > 110)
pMobIndex->level = 110;
}
numa = number_range(pMobIndex->level, pMobIndex->level+8);
numb = number_range(pMobIndex->level, pMobIndex->level+8);
avg = (numa+numb)/2;
pMobIndex->hit[DICE_NUMBER] = moblev_table[avg].hpdice;
pMobIndex->hit[DICE_TYPE] = moblev_table[avg].hpsides;
pMobIndex->hit[DICE_BONUS] = moblev_table[avg].hpbonus;
numa = number_range(pMobIndex->level, pMobIndex->level+8);
numb = number_range(pMobIndex->level, pMobIndex->level+8);
avg = (numa+numb)/2;
pMobIndex->mana[DICE_NUMBER] = moblev_table[avg].hpdice;
pMobIndex->mana[DICE_TYPE] = moblev_table[avg].hpsides;
pMobIndex->mana[DICE_BONUS] = moblev_table[avg].hpbonus;
numa = number_range(pMobIndex->level, pMobIndex->level+8);
numb = number_range(pMobIndex->level, pMobIndex->level+8);
avg = (numa+numb)/2;
pMobIndex->damage[DICE_NUMBER] = moblev_table[avg].damdice;
pMobIndex->damage[DICE_TYPE] = moblev_table[avg].damsides;
pMobIndex->damage[DICE_BONUS] = moblev_table[avg].dambonus;
level = pMobIndex->level + 4;
numa = number_range(0, 6);
numb = number_range(0, 6);
avg = (numa+numb)/2;
value = ((moblev_table[level].mobac + 3) - avg) * 10;
pMobIndex->ac[AC_PIERCE] = value;
numa = number_range(0, 6);
numb = number_range(0, 6);
avg = (numa+numb)/2;
value = ((moblev_table[level].mobac + 3) - avg) * 10;
pMobIndex->ac[AC_BASH] = value;
numa = number_range(0, 6);
numb = number_range(0, 6);
avg = (numa+numb)/2;
value = ((moblev_table[level].mobac + 3) - avg) * 10;
pMobIndex->ac[AC_SLASH] = value;
numa = number_range(0, 6);
numb = number_range(0, 6);
avg = (numa+numb)/2;
value = ((moblev_table[level].mobac + 7) - avg) * 10;
pMobIndex->ac[AC_EXOTIC] = value;
}
}
return;
}
void find_exits( void )
{
ROOM_INDEX_DATA *pRoomIndex;
int vnum;
printf("Finding external exits.\n");
for (vnum = last_room; vnum >= first_room; vnum--)
{
if ( ( pRoomIndex = get_room_index( vnum ) ) != NULL )
{
int door;
for ( door = 11; door >= 0; door--)
{
EXIT_DATA *pexit;
if ( ( pexit = pRoomIndex->exit[door] ) != NULL)
{
ROOM_INDEX_DATA *pRoom;
if ( ( pRoom = get_room_index( pexit->u1.vnum ) ) == NULL )
{
EXEX_DATA *pexex;
pexex = alloc_perm( sizeof(*pexex) );
pexex->vnum = pRoomIndex->vnum;
pexex->to_vnum = pexit->u1.vnum;
pexex->direction = door;
if (changevnum)
{
pexex->vnum += newvnum;
if ((pexex->to_vnum >= area_first->min_vnum)
&& (pexex->to_vnum <= area_first->max_vnum))
{
pexex->to_vnum += newvnum;
}
}
if (exit_list != NULL)
{
pexex->next = exit_list;
}
exit_list = pexex;
}
}
}
}
}
return;
}
void show_exits( void )
{
EXEX_DATA *pexex;
printf("\nThe following external exits were found:\n");
for (pexex = exit_list; pexex != NULL; pexex = pexex->next)
{
int direct;
printf("\tRoom vnum #%d ", pexex->vnum);
direct = pexex->direction;
if (direct > 5)
{
printf(" evil");
direct -= 6;
}
if (direct == 0)
printf(" north (D%d)", pexex->direction);
else if (direct == 1)
printf(" east (D%d)", pexex->direction);
else if (direct == 2)
printf(" south (D%d)", pexex->direction);
else if (direct == 3)
printf(" west (D%d)", pexex->direction);
else if (direct == 4)
printf(" up (D%d)", pexex->direction);
else if (direct == 5)
printf(" down (D%d)", pexex->direction);
printf(" to room vnum #%d\n", pexex->to_vnum);
}
printf("\n");
return;
}
void default_objs( void )
{
OBJ_INDEX_DATA *pObjIndex;
int vnum;
printf("Converting OBJECTS.\n");
for (vnum = first_object; vnum <= last_object; vnum++ )
{
if ( ( pObjIndex = get_obj_index( vnum ) ) != NULL )
{
int numa, numb, avg, level, value;
switch(pObjIndex->item_type)
{
case ITEM_EXIT:
case ITEM_PIT:
case ITEM_DRINK_CON:
case ITEM_FOUNTAIN:
case ITEM_TREASURE:
case ITEM_FURNITURE:
case ITEM_TRASH:
case ITEM_KEY:
case ITEM_FOOD:
case ITEM_MONEY:
case ITEM_CORPSE_NPC:
case ITEM_CORPSE_PC:
case ITEM_MAP:
case ITEM_ROOM_KEY:
case ITEM_GEM:
case ITEM_JUKEBOX:
case ITEM_PASSBOOK:
break;
case ITEM_SCROLL:
case ITEM_WAND:
case ITEM_STAFF:
case ITEM_POTION:
case ITEM_PILL:
if (changelev)
{
pObjIndex->level += addlev;
if (pObjIndex->level < 0)
pObjIndex->level = 0;
if (pObjIndex->level > 110)
pObjIndex->level = 110;
pObjIndex->value[0] += addlev;
if (pObjIndex->value[0] < 0)
pObjIndex->value[0] = 0;
if (pObjIndex->value[0] > 110)
pObjIndex->value[0] = 110;
}
break;
case ITEM_WEAPON:
if (changelev)
{
pObjIndex->level += addlev;
if (pObjIndex->level < 0)
pObjIndex->level = 0;
if (pObjIndex->level > 110)
pObjIndex->level = 110;
}
numa = number_range(pObjIndex->level, pObjIndex->level+6);
numb = number_range(pObjIndex->level, pObjIndex->level+6);
avg = (numa+numb)/2;
pObjIndex->value[1] = objlev_table[avg].weapdice;
pObjIndex->value[2] = objlev_table[avg].weapsides;
break;
case ITEM_ARMOR:
if (changelev)
{
pObjIndex->level += addlev;
if (pObjIndex->level < 0)
pObjIndex->level = 0;
if (pObjIndex->level > 110)
pObjIndex->level = 110;
}
level = pObjIndex->level + 3;
numa = number_range(0, 4);
numb = number_range(0, 4);
avg = (numa+numb)/2;
value = ((objlev_table[level].armorac - 2) + avg);
pObjIndex->value[0] = value;
numa = number_range(0, 6);
numb = number_range(0, 6);
avg = (numa+numb)/2;
value = ((objlev_table[level].armorac - 2) + avg);
pObjIndex->value[1] = value;
numa = number_range(0, 6);
numb = number_range(0, 6);
avg = (numa+numb)/2;
value = ((objlev_table[level].armorac - 2) + avg);
pObjIndex->value[2] = value;
numa = number_range(0, 6);
numb = number_range(0, 6);
avg = (numa+numb)/2;
value = ((objlev_table[level].armorac - 6) + avg);
pObjIndex->value[3] = value;
break;
default:
if (changelev)
{
pObjIndex->level += addlev;
if (pObjIndex->level < 0)
pObjIndex->level = 0;
if (pObjIndex->level > 110)
pObjIndex->level = 110;
}
break;
}
}
}
return;
}
/* checks mob format */
bool is_old_mob(CHAR_DATA *ch)
{
if (ch->pIndexData == NULL)
return FALSE;
else if (ch->pIndexData->new_format)
return FALSE;
return TRUE;
}
/*
* See if a string is one of the names of an object.
*/
/*
bool is_name( const char *str, char *namelist )
{
char name[MAX_INPUT_LENGTH];
for ( ; ; )
{
namelist = one_argument( namelist, name );
if ( name[0] == '\0' )
return FALSE;
if ( !str_cmp( str, name ) )
return TRUE;
}
}
*/
bool is_name ( char *str, char *namelist )
{
char name[MAX_INPUT_LENGTH], part[MAX_INPUT_LENGTH];
char *list, *string;
string = str;
/* we need ALL parts of string to match part of namelist */
for ( ; ; ) /* start parsing string */
{
str = one_argument(str,part);
if (part[0] == '\0' )
return TRUE;
/* check to see if this is part of namelist */
list = namelist;
for ( ; ; ) /* start parsing namelist */
{
list = one_argument(list,name);
if (name[0] == '\0') /* this name was not found */
return FALSE;
if (!str_prefix(string,name))
return TRUE; /* full pattern match */
if (!str_prefix(part,name))
break;
}
}
}
bool is_exact_name ( char *str, char *namelist )
{
char name[MAX_INPUT_LENGTH], part[MAX_INPUT_LENGTH];
char *list, *string;
string = str;
/* we need ALL parts of string to match part of namelist */
for ( ; ; ) /* start parsing string */
{
str = one_argument(str,part);
if (part[0] == '\0' )
return TRUE;
/* check to see if this is part of namelist */
list = namelist;
for ( ; ; ) /* start parsing namelist */
{
list = one_argument(list,name);
if (name[0] == '\0') /* this name was not found */
return FALSE;
if (!str_cmp(string,name))
return TRUE; /* full pattern match */
if (!str_cmp(part,name))
break;
}
}
}
char *wear_bit_name(int wear_flags)
{
static char buf[512];
buf [0] = '\0';
if (wear_flags & ITEM_TAKE ) strcat(buf, " take");
if (wear_flags & ITEM_WEAR_FINGER ) strcat(buf, " finger");
if (wear_flags & ITEM_WEAR_NECK ) strcat(buf, " neck");
if (wear_flags & ITEM_WEAR_BODY ) strcat(buf, " torso");
if (wear_flags & ITEM_WEAR_HEAD ) strcat(buf, " head");
if (wear_flags & ITEM_WEAR_LEGS ) strcat(buf, " legs");
if (wear_flags & ITEM_WEAR_FEET ) strcat(buf, " feet");
if (wear_flags & ITEM_WEAR_HANDS ) strcat(buf, " hands");
if (wear_flags & ITEM_WEAR_ARMS ) strcat(buf, " arms");
if (wear_flags & ITEM_WEAR_SHIELD ) strcat(buf, " shield");
if (wear_flags & ITEM_WEAR_ABOUT ) strcat(buf, " body");
if (wear_flags & ITEM_WEAR_WAIST ) strcat(buf, " waist");
if (wear_flags & ITEM_WEAR_WRIST ) strcat(buf, " wrist");
if (wear_flags & ITEM_WIELD ) strcat(buf, " wield");
if (wear_flags & ITEM_HOLD ) strcat(buf, " hold");
if (wear_flags & ITEM_WEAR_FLOAT ) strcat(buf, " float");
if (wear_flags & ITEM_WEAR_FACE ) strcat(buf, " face");
if (wear_flags & ITEM_NO_SAC ) strcat(buf, " no_sac");
return ( buf[0] != '\0' ) ? buf+1 : "none";
}
char *room_bit_name(int room_flags)
{
static char buf[512];
buf [0] = '\0';
if (room_flags & ROOM_DARK ) strcat(buf, " dark");
if (room_flags & ROOM_NO_MOB ) strcat(buf, " no_mob");
if (room_flags & ROOM_INDOORS ) strcat(buf, " indoors");
if (room_flags & ROOM_PRIVATE ) strcat(buf, " private");
if (room_flags & ROOM_SAFE ) strcat(buf, " safe");
if (room_flags & ROOM_SOLITARY ) strcat(buf, " solitary");
if (room_flags & ROOM_PET_SHOP ) strcat(buf, " pet_shop");
if (room_flags & ROOM_NO_RECALL ) strcat(buf, " no_recall");
if (room_flags & ROOM_IMP_ONLY ) strcat(buf, " imp");
if (room_flags & ROOM_GODS_ONLY ) strcat(buf, " gods");
if (room_flags & ROOM_HEROES_ONLY ) strcat(buf, " heroes");
if (room_flags & ROOM_NEWBIES_ONLY ) strcat(buf, " newbies");
if (room_flags & ROOM_LAW ) strcat(buf, " law");
if (room_flags & ROOM_CLAN_ENT ) strcat(buf, " clan_ent");
if (room_flags & ROOM_NOWHERE ) strcat(buf, " nowhere");
if (room_flags & ROOM_LOCKED ) strcat(buf, " locked");
return ( buf[0] != '\0' ) ? buf+1 : "none";
}
char *form_bit_name(int form_flags)
{
static char buf[512];
buf[0] = '\0';
if (form_flags & FORM_POISON ) strcat(buf, " poison");
else if (form_flags & FORM_EDIBLE ) strcat(buf, " edible");
if (form_flags & FORM_MAGICAL ) strcat(buf, " magical");
if (form_flags & FORM_INSTANT_DECAY ) strcat(buf, " instant_rot");
if (form_flags & FORM_OTHER ) strcat(buf, " other");
if (form_flags & FORM_ANIMAL ) strcat(buf, " animal");
if (form_flags & FORM_SENTIENT ) strcat(buf, " sentient");
if (form_flags & FORM_UNDEAD ) strcat(buf, " undead");
if (form_flags & FORM_CONSTRUCT ) strcat(buf, " construct");
if (form_flags & FORM_MIST ) strcat(buf, " mist");
if (form_flags & FORM_INTANGIBLE ) strcat(buf, " intangible");
if (form_flags & FORM_BIPED ) strcat(buf, " biped");
if (form_flags & FORM_CENTAUR ) strcat(buf, " centaur");
if (form_flags & FORM_INSECT ) strcat(buf, " insect");
if (form_flags & FORM_SPIDER ) strcat(buf, " spider");
if (form_flags & FORM_CRUSTACEAN ) strcat(buf, " crustacean");
if (form_flags & FORM_WORM ) strcat(buf, " worm");
if (form_flags & FORM_BLOB ) strcat(buf, " blob");
if (form_flags & FORM_MAMMAL ) strcat(buf, " mammal");
if (form_flags & FORM_BIRD ) strcat(buf, " bird");
if (form_flags & FORM_REPTILE ) strcat(buf, " reptile");
if (form_flags & FORM_SNAKE ) strcat(buf, " snake");
if (form_flags & FORM_DRAGON ) strcat(buf, " dragon");
if (form_flags & FORM_AMPHIBIAN ) strcat(buf, " amphibian");
if (form_flags & FORM_FISH ) strcat(buf, " fish");
if (form_flags & FORM_COLD_BLOOD ) strcat(buf, " cold_blooded");
return ( buf[0] != '\0' ) ? buf+1 : "none";
}
char *part_bit_name(int part_flags)
{
static char buf[512];
buf[0] = '\0';
if (part_flags & PART_HEAD ) strcat(buf, " head");
if (part_flags & PART_ARMS ) strcat(buf, " arms");
if (part_flags & PART_LEGS ) strcat(buf, " legs");
if (part_flags & PART_HEART ) strcat(buf, " heart");
if (part_flags & PART_BRAINS ) strcat(buf, " brains");
if (part_flags & PART_GUTS ) strcat(buf, " guts");
if (part_flags & PART_HANDS ) strcat(buf, " hands");
if (part_flags & PART_FEET ) strcat(buf, " feet");
if (part_flags & PART_FINGERS ) strcat(buf, " fingers");
if (part_flags & PART_EAR ) strcat(buf, " ears");
if (part_flags & PART_EYE ) strcat(buf, " eyes");
if (part_flags & PART_LONG_TONGUE ) strcat(buf, " long_tongue");
if (part_flags & PART_EYESTALKS ) strcat(buf, " eyestalks");
if (part_flags & PART_TENTACLES ) strcat(buf, " tentacles");
if (part_flags & PART_FINS ) strcat(buf, " fins");
if (part_flags & PART_WINGS ) strcat(buf, " wings");
if (part_flags & PART_TAIL ) strcat(buf, " tail");
if (part_flags & PART_CLAWS ) strcat(buf, " claws");
if (part_flags & PART_FANGS ) strcat(buf, " fangs");
if (part_flags & PART_HORNS ) strcat(buf, " horns");
if (part_flags & PART_SCALES ) strcat(buf, " scales");
return ( buf[0] != '\0' ) ? buf+1 : "none";
}
char *weapon_bit_name(int weapon_flags)
{
static char buf[512];
buf[0] = '\0';
if (weapon_flags & WEAPON_FLAMING ) strcat(buf, " flaming");
if (weapon_flags & WEAPON_FROST ) strcat(buf, " frost");
if (weapon_flags & WEAPON_VAMPIRIC ) strcat(buf, " vampiric");
if (weapon_flags & WEAPON_SHARP ) strcat(buf, " sharp");
if (weapon_flags & WEAPON_VORPAL ) strcat(buf, " vorpal");
if (weapon_flags & WEAPON_TWO_HANDS ) strcat(buf, " two-handed");
if (weapon_flags & WEAPON_SHOCKING ) strcat(buf, " shocking");
if (weapon_flags & WEAPON_POISON ) strcat(buf, " poison");
return ( buf[0] != '\0' ) ? buf+1 : "none";
}
char *cont_bit_name( int cont_flags)
{
static char buf[512];
buf[0] = '\0';
if (cont_flags & CONT_CLOSEABLE ) strcat(buf, " closable");
if (cont_flags & CONT_PICKPROOF ) strcat(buf, " pickproof");
if (cont_flags & CONT_CLOSED ) strcat(buf, " closed");
if (cont_flags & CONT_LOCKED ) strcat(buf, " locked");
return (buf[0] != '\0' ) ? buf+1 : "none";
}
char *off_bit_name(int off_flags)
{
static char buf[512];
buf[0] = '\0';
if (off_flags & OFF_AREA_ATTACK ) strcat(buf, " area attack");
if (off_flags & OFF_BACKSTAB ) strcat(buf, " backstab");
if (off_flags & OFF_BASH ) strcat(buf, " bash");
if (off_flags & OFF_BERSERK ) strcat(buf, " berserk");
if (off_flags & OFF_DISARM ) strcat(buf, " disarm");
if (off_flags & OFF_DODGE ) strcat(buf, " dodge");
if (off_flags & OFF_FADE ) strcat(buf, " fade");
if (off_flags & OFF_FAST ) strcat(buf, " fast");
if (off_flags & OFF_FEED ) strcat(buf, " feed");
if (off_flags & OFF_KICK ) strcat(buf, " kick");
if (off_flags & OFF_KICK_DIRT ) strcat(buf, " kick_dirt");
if (off_flags & OFF_PARRY ) strcat(buf, " parry");
if (off_flags & OFF_RESCUE ) strcat(buf, " rescue");
if (off_flags & OFF_TAIL ) strcat(buf, " tail");
if (off_flags & OFF_TRIP ) strcat(buf, " trip");
if (off_flags & OFF_CRUSH ) strcat(buf, " crush");
if (off_flags & OFF_CLAN_GUARD ) strcat(buf, " clan_guard");
if (off_flags & ASSIST_ALL ) strcat(buf, " assist_all");
if (off_flags & ASSIST_ALIGN ) strcat(buf, " assist_align");
if (off_flags & ASSIST_RACE ) strcat(buf, " assist_race");
if (off_flags & ASSIST_PLAYERS ) strcat(buf, " assist_players");
if (off_flags & ASSIST_GUARD ) strcat(buf, " assist_guard");
if (off_flags & ASSIST_VNUM ) strcat(buf, " assist_vnum");
return ( buf[0] != '\0' ) ? buf+1 : "none";
}
char *one_argument( char *argument, char *arg_first )
{
char cEnd;
while ( isspace(*argument) )
argument++;
cEnd = ' ';
if ( *argument == '\'' || *argument == '"' )
cEnd = *argument++;
while ( *argument != '\0' )
{
if ( *argument == cEnd )
{
argument++;
break;
}
*arg_first = LOWER(*argument);
arg_first++;
argument++;
}
*arg_first = '\0';
while ( isspace(*argument) )
argument++;
return argument;
}
int slot_lookup( int slot )
{
extern bool fBootDb;
int sn;
if ( slot <= 0 )
return -1;
for ( sn = 0; sn < MAX_SKILL; sn++ )
{
if ( slot == skill_table[sn].slot )
return sn;
}
if ( fBootDb )
{
bug( "Slot_lookup: bad slot %d.", slot );
abort( );
}
return -1;
}
/*
* Translates mob virtual number to its mob index struct.
* Hash table lookup.
*/
MOB_INDEX_DATA *get_mob_index( int vnum )
{
MOB_INDEX_DATA *pMobIndex;
for ( pMobIndex = mob_index;
pMobIndex != NULL;
pMobIndex = pMobIndex->next )
{
if ( pMobIndex->vnum == vnum )
return pMobIndex;
}
return NULL;
}
/*
* Translates obj virtual number to its obj index struct.
* Hash table lookup.
*/
OBJ_INDEX_DATA *get_obj_index( int vnum )
{
OBJ_INDEX_DATA *pObjIndex;
for ( pObjIndex = obj_index;
pObjIndex != NULL;
pObjIndex = pObjIndex->next )
{
if ( pObjIndex->vnum == vnum )
return pObjIndex;
}
return NULL;
}
/*
* Translates dream virtual number to its dream index struct.
* Hash table lookup.
*/
DRM_INDEX_DATA *get_drm_index( int vnum )
{
DRM_INDEX_DATA *pDrmIndex;
for ( pDrmIndex = drm_index;
pDrmIndex != NULL;
pDrmIndex = pDrmIndex->next )
{
if ( pDrmIndex->vnum == vnum )
return pDrmIndex;
}
return NULL;
}
/*
* Translates room virtual number to its room index struct.
* Hash table lookup.
*/
ROOM_INDEX_DATA *get_room_index( int vnum )
{
ROOM_INDEX_DATA *pRoomIndex;
for ( pRoomIndex = room_index;
pRoomIndex != NULL;
pRoomIndex = pRoomIndex->next )
{
if ( pRoomIndex->vnum == vnum )
return pRoomIndex;
}
return NULL;
}
/*
* Read a letter from a file.
*/
char fread_letter( FILE *fp )
{
char c;
do
{
c = getc( fp );
}
while ( isspace(c) );
return c;
}
/*
* Read a number from a file.
*/
int fread_number( FILE *fp )
{
int number;
bool sign;
char c;
do
{
c = getc( fp );
}
while ( isspace(c) );
number = 0;
sign = FALSE;
if ( c == '+' )
{
c = getc( fp );
}
else if ( c == '-' )
{
sign = TRUE;
c = getc( fp );
}
if ( !isdigit(c) )
{
bug( "Fread_number: bad format.", 0 );
exit( 1 );
}
while ( isdigit(c) )
{
number = number * 10 + c - '0';
c = getc( fp );
}
if ( sign )
number = 0 - number;
if ( c == '|' )
number += fread_number( fp );
else if ( c != ' ' )
ungetc( c, fp );
return number;
}
long fread_flag( FILE *fp)
{
int number;
char c;
bool negative = FALSE;
do
{
c = getc(fp);
}
while ( isspace(c));
if (c == '-')
{
negative = TRUE;
c = getc(fp);
}
number = 0;
if (!isdigit(c))
{
while (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))
{
number += flag_convert(c);
c = getc(fp);
}
}
while (isdigit(c))
{
number = number * 10 + c - '0';
c = getc(fp);
}
if (c == '|')
number += fread_flag(fp);
else if ( c != ' ')
ungetc(c,fp);
if (negative)
return -1 * number;
return number;
}
long flag_convert(char letter )
{
long bitsum = 0;
char i;
if ('A' <= letter && letter <= 'Z')
{
bitsum = 1;
for (i = letter; i > 'A'; i--)
bitsum *= 2;
}
else if ('a' <= letter && letter <= 'z')
{
bitsum = 67108864; /* 2^26 */
for (i = letter; i > 'a'; i --)
bitsum *= 2;
}
return bitsum;
}
/*
* Read and allocate space for a string from a file.
* These strings are read-only and shared.
* Strings are hashed:
* each string prepended with hash pointer to prev string,
* hash code is simply the string length.
* this function takes 40% to 50% of boot-up time.
*/
char *fread_string( FILE *fp )
{
char *plast;
char c;
plast = top_string + sizeof(char *);
if ( plast > &string_space[MAX_STRING - MAX_STRING_LENGTH] )
{
bug( "Fread_string: MAX_STRING %d exceeded.", MAX_STRING );
exit( 1 );
}
/*
* Skip blanks.
* Read first char.
*/
do
{
c = getc( fp );
}
while ( isspace(c) );
if ( ( *plast++ = c ) == '~' )
return &str_empty[0];
for ( ;; )
{
/*
* Back off the char type lookup,
* it was too dirty for portability.
* -- Furey
*/
switch ( *plast = getc(fp) )
{
default:
plast++;
break;
case EOF:
/* temp fix */
bug( "Fread_string: EOF", 0 );
return NULL;
/* exit( 1 ); */
break;
case '\n':
plast++;
*plast++ = '\r';
break;
case '\r':
break;
case '~':
plast++;
{
union
{
char * pc;
char rgc[sizeof(char *)];
} u1;
int ic;
int iHash;
char *pHash;
char *pHashPrev;
char *pString;
plast[-1] = '\0';
iHash = UMIN( MAX_KEY_HASH - 1, plast - 1 - top_string );
for ( pHash = string_hash[iHash]; pHash; pHash = pHashPrev )
{
for ( ic = 0; ic < sizeof(char *); ic++ )
u1.rgc[ic] = pHash[ic];
pHashPrev = u1.pc;
pHash += sizeof(char *);
if ( top_string[sizeof(char *)] == pHash[0]
&& !strcmp( top_string+sizeof(char *)+1, pHash+1 ) )
return pHash;
}
if ( fBootDb )
{
pString = top_string;
top_string = plast;
u1.pc = string_hash[iHash];
for ( ic = 0; ic < sizeof(char *); ic++ )
pString[ic] = u1.rgc[ic];
string_hash[iHash] = pString;
nAllocString += 1;
sAllocString += top_string - pString;
return pString + sizeof(char *);
}
else
{
return str_dup( top_string + sizeof(char *) );
}
}
}
}
}
char *fread_string_eol( FILE *fp )
{
static bool char_special[256-EOF];
char *plast;
char c;
if ( char_special[EOF-EOF] != TRUE )
{
char_special[EOF - EOF] = TRUE;
char_special['\n' - EOF] = TRUE;
char_special['\r' - EOF] = TRUE;
}
plast = top_string + sizeof(char *);
if ( plast > &string_space[MAX_STRING - MAX_STRING_LENGTH] )
{
bug( "Fread_string: MAX_STRING %d exceeded.", MAX_STRING );
exit( 1 );
}
/*
* Skip blanks.
* Read first char.
*/
do
{
c = getc( fp );
}
while ( isspace(c) );
if ( ( *plast++ = c ) == '\n')
return &str_empty[0];
for ( ;; )
{
if ( !char_special[ ( *plast++ = getc( fp ) ) - EOF ] )
continue;
switch ( plast[-1] )
{
default:
break;
case EOF:
bug( "Fread_string_eol EOF", 0 );
exit( 1 );
break;
case '\n': case '\r':
{
union
{
char * pc;
char rgc[sizeof(char *)];
} u1;
int ic;
int iHash;
char *pHash;
char *pHashPrev;
char *pString;
plast[-1] = '\0';
iHash = UMIN( MAX_KEY_HASH - 1, plast - 1 - top_string );
for ( pHash = string_hash[iHash]; pHash; pHash = pHashPrev )
{
for ( ic = 0; ic < sizeof(char *); ic++ )
u1.rgc[ic] = pHash[ic];
pHashPrev = u1.pc;
pHash += sizeof(char *);
if ( top_string[sizeof(char *)] == pHash[0]
&& !strcmp( top_string+sizeof(char *)+1, pHash+1 ) )
return pHash;
}
if ( fBootDb )
{
pString = top_string;
top_string = plast;
u1.pc = string_hash[iHash];
for ( ic = 0; ic < sizeof(char *); ic++ )
pString[ic] = u1.rgc[ic];
string_hash[iHash] = pString;
nAllocString += 1;
sAllocString += top_string - pString;
return pString + sizeof(char *);
}
else
{
return str_dup( top_string + sizeof(char *) );
}
}
}
}
}
/*
* Read to end of line (for comments).
*/
void fread_to_eol( FILE *fp )
{
char c;
do
{
c = getc( fp );
}
while ( c != '\n' && c != '\r' );
do
{
c = getc( fp );
}
while ( c == '\n' || c == '\r' );
ungetc( c, fp );
return;
}
/*
* Read one word (into static buffer).
*/
char *fread_word( FILE *fp )
{
static char word[MAX_INPUT_LENGTH];
char *pword;
char cEnd;
do
{
cEnd = getc( fp );
}
while ( isspace( cEnd ) );
if ( cEnd == '\'' || cEnd == '"' )
{
pword = word;
}
else
{
word[0] = cEnd;
pword = word+1;
cEnd = ' ';
}
for ( ; pword < word + MAX_INPUT_LENGTH; pword++ )
{
*pword = getc( fp );
if ( cEnd == ' ' ? isspace(*pword) : *pword == cEnd )
{
if ( cEnd == ' ' )
ungetc( *pword, fp );
*pword = '\0';
return word;
}
}
bug( "Fread_word: word too long.", 0 );
exit( 1 );
return NULL;
}
/*
* Allocate some ordinary memory,
* with the expectation of freeing it someday.
*/
void *alloc_mem( int sMem )
{
void *pMem;
int *magic;
int iList;
sMem += sizeof(*magic);
for ( iList = 0; iList < MAX_MEM_LIST; iList++ )
{
if ( sMem <= rgSizeList[iList] )
break;
}
if ( iList == MAX_MEM_LIST )
{
bug( "Alloc_mem: size %d too large.", sMem );
exit( 1 );
}
if ( rgFreeList[iList] == NULL )
{
pMem = alloc_perm( rgSizeList[iList] );
}
else
{
pMem = rgFreeList[iList];
rgFreeList[iList] = * ((void **) rgFreeList[iList]);
}
magic = (int *) pMem;
*magic = MAGIC_NUM;
pMem += sizeof(*magic);
return pMem;
}
/*
* Free some memory.
* Recycle it back onto the free list for blocks of that size.
*/
void free_mem( void *pMem, int sMem )
{
int iList;
int *magic;
pMem -= sizeof(*magic);
magic = (int *) pMem;
if (*magic != MAGIC_NUM)
{
bug("Attempt to recyle invalid memory of size %d.",sMem);
bug((char*) pMem + sizeof(*magic),0);
return;
}
*magic = 0;
sMem += sizeof(*magic);
for ( iList = 0; iList < MAX_MEM_LIST; iList++ )
{
if ( sMem <= rgSizeList[iList] )
break;
}
if ( iList == MAX_MEM_LIST )
{
bug( "Free_mem: size %d too large.", sMem );
exit( 1 );
}
* ((void **) pMem) = rgFreeList[iList];
rgFreeList[iList] = pMem;
return;
}
/*
* Allocate some permanent memory.
* Permanent memory is never freed,
* pointers into it may be copied safely.
*/
void *alloc_perm( int sMem )
{
static char *pMemPerm;
static int iMemPerm;
void *pMem;
while ( sMem % sizeof(long) != 0 )
sMem++;
if ( sMem > MAX_PERM_BLOCK )
{
bug( "Alloc_perm: %d too large.", sMem );
exit( 1 );
}
if ( pMemPerm == NULL || iMemPerm + sMem > MAX_PERM_BLOCK )
{
iMemPerm = 0;
if ( ( pMemPerm = calloc( 1, MAX_PERM_BLOCK ) ) == NULL )
{
perror( "Alloc_perm" );
exit( 1 );
}
}
pMem = pMemPerm + iMemPerm;
iMemPerm += sMem;
nAllocPerm += 1;
sAllocPerm += sMem;
return pMem;
}
/*
* Duplicate a string into dynamic memory.
* Fread_strings are read-only and shared.
*/
char *str_dup( const char *str )
{
char *str_new;
if ( str[0] == '\0' )
return &str_empty[0];
if ( str >= string_space && str < top_string )
return (char *) str;
str_new = alloc_mem( strlen(str) + 1 );
strcpy( str_new, str );
return str_new;
}
/*
* Free a string.
* Null is legal here to simplify callers.
* Read-only shared strings are not touched.
*/
void free_string( char *pstr )
{
if ( pstr == NULL
|| pstr == &str_empty[0]
|| ( pstr >= string_space && pstr < top_string ) )
return;
free_mem( pstr, strlen(pstr) + 1 );
return;
}
/*
* Generate a random number.
*/
int number_range( int from, int to )
{
int power;
int number;
if (from == 0 && to == 0)
return 0;
if ( ( to = to - from + 1 ) <= 1 )
return from;
for ( power = 2; power < to; power <<= 1 )
;
while ( ( number = number_mm() & (power -1 ) ) >= to )
;
return from + number;
}
/*
* Generate a percentile roll.
*/
int number_percent( void )
{
int percent;
while ( (percent = number_mm() & (128-1) ) > 99 )
;
return 1 + percent;
}
/*
* Generate a random door.
*/
int number_door( void )
{
int door;
while ( ( door = number_mm() & (8-1) ) > 11)
;
return door;
}
int number_bits( int width )
{
return number_mm( ) & ( ( 1 << width ) - 1 );
}
/*
* I've gotten too many bad reports on OS-supplied random number generators.
* This is the Mitchell-Moore algorithm from Knuth Volume II.
* Best to leave the constants alone unless you've read Knuth.
* -- Furey
*/
/* I noticed streaking with this random number generator, so I switched
back to the system srandom call. If this doesn't work for you,
define OLD_RAND to use the old system -- Alander */
#if defined (OLD_RAND)
static int rgiState[2+55];
#endif
long number_mm( void )
{
#if defined (OLD_RAND)
int *piState;
int iState1;
int iState2;
int iRand;
piState = &rgiState[2];
iState1 = piState[-2];
iState2 = piState[-1];
iRand = (piState[iState1] + piState[iState2])
& ((1 << 30) - 1);
piState[iState1] = iRand;
if ( ++iState1 == 55 )
iState1 = 0;
if ( ++iState2 == 55 )
iState2 = 0;
piState[-2] = iState1;
piState[-1] = iState2;
return iRand >> 6;
#else
return random() >> 6;
#endif
}
/*
* Roll some dice.
*/
int dice( int number, int size )
{
int idice;
int sum;
switch ( size )
{
case 0: return 0;
case 1: return number;
}
for ( idice = 0, sum = 0; idice < number; idice++ )
sum += number_range( 1, size );
return sum;
}
/*
* Simple linear interpolation.
*/
int interpolate( int level, int value_00, int value_32 )
{
return value_00 + level * (value_32 - value_00) / 32;
}
/*
* Removes the tildes from a string.
* Used for player-entered strings that go into disk files.
*/
void smash_tilde( char *str )
{
for ( ; *str != '\0'; str++ )
{
if ( *str == '~' )
*str = '-';
}
return;
}
/*
* Compare strings, case insensitive.
* Return TRUE if different
* (compatibility with historical functions).
*/
bool str_cmp( const char *astr, const char *bstr )
{
if ( astr == NULL )
{
bug( "Str_cmp: null astr.", 0 );
return TRUE;
}
if ( bstr == NULL )
{
bug( "Str_cmp: null bstr.", 0 );
return TRUE;
}
for ( ; *astr || *bstr; astr++, bstr++ )
{
if ( LOWER(*astr) != LOWER(*bstr) )
return TRUE;
}
return FALSE;
}
/*
* Compare strings, case insensitive, for prefix matching.
* Return TRUE if astr not a prefix of bstr
* (compatibility with historical functions).
*/
bool str_prefix( const char *astr, const char *bstr )
{
if ( astr == NULL )
{
bug( "Strn_cmp: null astr.", 0 );
return TRUE;
}
if ( bstr == NULL )
{
bug( "Strn_cmp: null bstr.", 0 );
return TRUE;
}
for ( ; *astr; astr++, bstr++ )
{
if ( LOWER(*astr) != LOWER(*bstr) )
return TRUE;
}
return FALSE;
}
/*
* Compare strings, case sensitive, for prefix matching.
* Return TRUE if astr not a prefix of bstr
* (compatibility with historical functions).
*/
bool str_prefix_c( const char *astr, const char *bstr )
{
if ( astr == NULL )
{
bug( "Strn_cmp: null astr.", 0 );
return TRUE;
}
if ( bstr == NULL )
{
bug( "Strn_cmp: null bstr.", 0 );
return TRUE;
}
for ( ; *astr; astr++, bstr++ )
{
if ( *astr != *bstr )
return TRUE;
}
return FALSE;
}
/*
* Compare strings, case insensitive, for match anywhere.
* Returns TRUE is astr not part of bstr.
* (compatibility with historical functions).
*/
bool str_infix( const char *astr, const char *bstr )
{
int sstr1;
int sstr2;
int ichar;
char c0;
if ( ( c0 = LOWER(astr[0]) ) == '\0' )
return FALSE;
sstr1 = strlen(astr);
sstr2 = strlen(bstr);
for ( ichar = 0; ichar <= sstr2 - sstr1; ichar++ )
{
if ( c0 == LOWER(bstr[ichar]) && !str_prefix( astr, bstr + ichar ) )
return FALSE;
}
return TRUE;
}
/*
* Compare strings, case sensitive, for match anywhere.
* Returns TRUE is astr not part of bstr.
* (compatibility with historical functions).
*/
bool str_infix_c( const char *astr, const char *bstr )
{
int sstr1;
int sstr2;
int ichar;
char c0;
if ( ( c0 = astr[0] ) == '\0' )
return FALSE;
sstr1 = strlen(astr);
sstr2 = strlen(bstr);
for ( ichar = 0; ichar <= sstr2 - sstr1; ichar++ )
{
if ( c0 == bstr[ichar] && !str_prefix_c( astr, bstr + ichar ) )
return FALSE;
}
return TRUE;
}
/*
* Replace a substring in a string, case insensitive...Russ Walsh
* looks for bstr within astr and replaces it with cstr.
*/
char *str_replace( char *astr, char *bstr, char *cstr )
{
char newstr[MAX_STRING_LENGTH];
char buf[MAX_STRING_LENGTH];
bool found = FALSE;
int sstr1, sstr2;
int ichar, jchar;
char c0, c1, c2;
if ( ( ( c0 = LOWER(astr[0]) ) == '\0' )
|| ( ( c1 = LOWER(bstr[0]) ) == '\0' )
|| ( ( c2 = LOWER(cstr[0]) ) == '\0' ) )
return astr;
if (str_infix(bstr, astr) )
return astr;
/* make sure we don't start an infinite loop */
if (!str_infix(bstr, cstr) )
return astr;
sstr1 = strlen(astr);
sstr2 = strlen(bstr);
jchar = 0;
if (sstr1 < sstr2)
return astr;
for ( ichar = 0; ichar <= sstr1 - sstr2; ichar++ )
{
if ( c1 == LOWER(astr[ichar]) && !str_prefix( bstr, astr + ichar ) )
{
found = TRUE;
jchar = ichar;
ichar = sstr1;
}
}
if (found)
{
buf[0] = '\0';
for ( ichar = 0; ichar < jchar; ichar++ )
{
sprintf(newstr, "%c", astr[ichar]);
strcat(buf, newstr);
}
strcat(buf, cstr);
for ( ichar = jchar + sstr2; ichar < sstr1; ichar++ )
{
sprintf(newstr, "%c", astr[ichar]);
strcat(buf, newstr);
}
sprintf(astr, "%s", str_replace(buf, bstr, cstr) );
return astr;
}
return astr;
}
/*
* Replace a substring in a string, case sensitive...Russ Walsh
* looks for bstr within astr and replaces it with cstr.
*/
char *str_replace_c( char *astr, char *bstr, char *cstr )
{
char newstr[MAX_STRING_LENGTH];
char buf[MAX_STRING_LENGTH];
bool found = FALSE;
int sstr1, sstr2;
int ichar, jchar;
char c0, c1, c2;
if ( ( ( c0 = astr[0] ) == '\0' )
|| ( ( c1 = bstr[0] ) == '\0' )
|| ( ( c2 = cstr[0] ) == '\0' ) )
return astr;
if (str_infix_c(bstr, astr) )
return astr;
/* make sure we don't start an infinite loop */
if (!str_infix_c(bstr, cstr) )
return astr;
sstr1 = strlen(astr);
sstr2 = strlen(bstr);
jchar = 0;
if (sstr1 < sstr2)
return astr;
for ( ichar = 0; ichar <= sstr1 - sstr2; ichar++ )
{
if ( c1 == astr[ichar] && !str_prefix_c( bstr, astr + ichar ) )
{
found = TRUE;
jchar = ichar;
ichar = sstr1;
}
}
if (found)
{
buf[0] = '\0';
for ( ichar = 0; ichar < jchar; ichar++ )
{
sprintf(newstr, "%c", astr[ichar]);
strcat(buf, newstr);
}
strcat(buf, cstr);
for ( ichar = jchar + sstr2; ichar < sstr1; ichar++ )
{
sprintf(newstr, "%c", astr[ichar]);
strcat(buf, newstr);
}
sprintf(astr, "%s", str_replace_c(buf, bstr, cstr) );
return astr;
}
return astr;
}
/*
* Compare strings, case insensitive, for suffix matching.
* Return TRUE if astr not a suffix of bstr
* (compatibility with historical functions).
*/
bool str_suffix( const char *astr, const char *bstr )
{
int sstr1;
int sstr2;
sstr1 = strlen(astr);
sstr2 = strlen(bstr);
if ( sstr1 <= sstr2 && !str_cmp( astr, bstr + sstr2 - sstr1 ) )
return FALSE;
else
return TRUE;
}
/*
* Returns an initial-capped string.
*/
char *capitalize( const char *str )
{
static char strcap[MAX_STRING_LENGTH];
int i;
for ( i = 0; str[i] != '\0'; i++ )
strcap[i] = LOWER(str[i]);
strcap[i] = '\0';
strcap[0] = UPPER(strcap[0]);
return strcap;
}
/*
* Reports a bug.
*/
void bug( const char *str, int param )
{
char buf[MAX_STRING_LENGTH];
if ( fpArea != NULL )
{
int iLine;
int iChar;
if ( fpArea == stdin )
{
iLine = 0;
}
else
{
iChar = ftell( fpArea );
fseek( fpArea, 0, 0 );
for ( iLine = 0; ftell( fpArea ) < iChar; iLine++ )
{
while ( getc( fpArea ) != '\n' )
;
}
fseek( fpArea, iChar, 0 );
}
sprintf( buf, "[*****] FILE: %s LINE: %d", strArea, iLine );
log_string( buf );
/* RT removed because we don't want bugs shutting the mud
if ( ( fp = fopen( "shutdown.txt", "a" ) ) != NULL )
{
fprintf( fp, "[*****] %s\n", buf );
fclose( fp );
}
*/
}
strcpy( buf, "[*****] BUG: " );
sprintf( buf + strlen(buf), str, param );
log_string( buf );
/* RT removed due to bug-file spamming
fclose( fpReserve );
if ( ( fp = fopen( BUG_FILE, "a" ) ) != NULL )
{
fprintf( fp, "%s\n", buf );
fclose( fp );
}
fpReserve = fopen( NULL_FILE, "r" );
*/
return;
}
/*
* Writes a string to the log.
*/
void log_string( const char *str )
{
fprintf( stderr, "%s\n", str );
return;
}
/*
* This function is here to aid in debugging.
* If the last expression in a function is another function call,
* gcc likes to generate a JMP instead of a CALL.
* This is called "tail chaining."
* It hoses the debugger call stack for that call.
* So I make this the last call in certain critical functions,
* where I really need the call stack to be right for debugging!
*
* If you don't understand this, then LEAVE IT ALONE.
* Don't remove any calls to tail_chain anywhere.
*
* -- Furey
*/
void tail_chain( void )
{
return;
}