/***************************************************************************
* 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. *
* *
* _/ _/_/_/ _/ _/ _/ ACK! MUD is modified *
* _/_/ _/ _/ _/ _/ Merc2.0/2.1/2.2 code *
* _/ _/ _/ _/_/ _/ (c)Stephen Dooley 1994 *
* _/_/_/_/ _/ _/ _/ "This mud has not been *
* _/ _/ _/_/_/ _/ _/ _/ tested on animals." *
* *
* *
* 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. *
***************************************************************************/
#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include <stdarg.h>
#include "merc.h"
#include "hash.h"
#include "ssm.h"
#include <unistd.h> /* for execl */
#include <sys/wait.h>
#include <errno.h>
#include <signal.h>
#include "imc-config.h" /* for vsnprintf support -- Alty */
#if !defined(macintosh)
extern int _filbuf args( (FILE *) );
#endif
/*
* Globals.
*/
char bug_buf [2*MAX_INPUT_LENGTH];
char log_buf [2*MAX_INPUT_LENGTH];
KILL_DATA kill_table [MAX_LEVEL];
TIME_INFO_DATA time_info;
WEATHER_DATA weather_info;
bool booting_up;
bool mem_log;
sh_int gsn_martial_arts;
sh_int gsn_stake;
sh_int gsn_dualwield;
sh_int gsn_stun;
sh_int gsn_feed;
sh_int gsn_knee;
sh_int gsn_shadow;
sh_int gsn_appraise;
sh_int gsn_climb;
sh_int gsn_find_doors;
sh_int gsn_bash;
sh_int gsn_smash;
sh_int gsn_notrip;
sh_int gsn_nodisarm;
sh_int gsn_trip;
sh_int gsn_dirt;
sh_int gsn_fourth_attack;
sh_int gsn_shield_block;
sh_int gsn_beserk;
sh_int gsn_circle;
sh_int gsn_backstab;
sh_int gsn_dodge;
sh_int gsn_hide;
sh_int gsn_hunt;
sh_int gsn_peek;
sh_int gsn_pick_lock;
sh_int gsn_sneak;
sh_int gsn_steal;
sh_int gsn_punch;
sh_int gsn_headbutt;
sh_int gsn_disarm;
sh_int gsn_enhanced_damage;
sh_int gsn_kick;
sh_int gsn_parry;
sh_int gsn_rescue;
sh_int gsn_second_attack;
sh_int gsn_third_attack;
sh_int gsn_blindness;
sh_int gsn_charm_person;
sh_int gsn_curse;
sh_int gsn_invis;
sh_int gsn_mass_invis;
sh_int gsn_poison;
sh_int gsn_sleep;
sh_int gsn_disguise;
sh_int gsn_instruct;
sh_int gsn_adrenaline;
sh_int gsn_frenzy;
sh_int gsn_emotion_control;
sh_int gsn_fifth_attack;
sh_int gsn_sixth_attack;
sh_int gsn_target;
sh_int gsn_charge;
sh_int gsn_unit_tactics;
sh_int gsn_imprint;
sh_int gsn_scent;
sh_int gsn_mount;
sh_int gsn_scout;
sh_int gsn_decapitate;
extern bool auto_quest;
extern COUNCIL_DATA super_councils[MAX_SUPER];
/*
* Locals.
*/
MOB_INDEX_DATA * mob_index_hash [MAX_KEY_HASH];
OBJ_INDEX_DATA * obj_index_hash [MAX_KEY_HASH];
ROOM_INDEX_DATA * room_index_hash [MAX_KEY_HASH];
char * string_hash [MAX_KEY_HASH];
AREA_DATA * area_used[MAX_AREAS];
AREA_DATA * area_load;
/*
* replaced for SSM
*/
#if 0
char * string_space = NULL;
char * top_string = NULL;
char str_empty [1] = { 0 };
#endif
extern char str_empty[1];
extern long sOverFlowString;
extern long nOverFlowString;
extern bool Full;
int top_affect;
int top_area;
int top_ed;
int top_exit;
int top_help;
int top_mob_index;
int top_obj_index;
int top_reset;
int top_room;
int top_shop;
/*
* MOBprogram locals
*/
int mprog_name_to_type args( ( char* name ) );
void mprog_file_read args( ( char *f,
MOB_INDEX_DATA *pMobIndex ) );
void load_mobprogs args( ( FILE* fp ) );
void mprog_read_programs args( ( FILE* fp,
MOB_INDEX_DATA *pMobIndex ) );
/*
* Memory management.
* Increase MAX_STRING if you have too.
* Tune the others only if you understand what you're doing.
*/
#if 0
#define MAX_STRING 2097152
/*#define MAX_PERM_BLOCK 131072
#define MAX_MEM_LIST 12
void * rgFreeList [MAX_MEM_LIST];
const int rgSizeList [MAX_MEM_LIST] =
{
16, 32, 64, 128, 256, 1024, 2048, 4096, 8192, 16384, 32768-64, 65536-16
};*/
int nAllocString;
int sAllocString;
#endif
extern long nAllocString;
extern long sAllocString;
int nAllocPerm;
int sAllocPerm;
extern long MAX_STRING;
void init_string_space(void);
void boot_done(void);
/*
* Semi-locals.
*/
bool fBootDb;
FILE * fpArea;
char strArea[MAX_INPUT_LENGTH];
/*
* Local booting procedures.
*/
void init_mm args( ( void ) );
void load_area args( ( FILE *fp ) );
void load_helps args( ( FILE *fp ) );
void load_mobiles args( ( FILE *fp ) );
void load_objects args( ( FILE *fp ) );
void load_resets args( ( FILE *fp ) );
void load_rooms args( ( FILE *fp ) );
void load_shops args( ( FILE *fp ) );
void load_specials args( ( FILE *fp ) );
void load_objfuns args( ( FILE *fp ) );
void load_notes args( ( void ) );
void load_gold args( ( void ) );
void load_corpses args( ( void ) );
void load_marks args( ( void ) );
void load_bans args( ( void ) );
void load_brands args( ( void ) );
void fix_exits args( ( void ) );
void check_resets args( ( void ) );
void reset_area args( ( AREA_DATA * pArea ) );
void copyover_recover args( ( void ) );
#define SHOW_AREA \
if (!previous_bug) \
{ \
bug (" In %s.",(int) pArea->filename); \
previous_bug=1; \
}
/*
* Big mama top level function.
*/
void boot_db( bool fCopyOver )
{
int a;
/*
* Init some data space stuff.
*/
#if 0
{
if ( ( string_space = calloc( 1, MAX_STRING ) ) == NULL )
{
bug( "Boot_db: can't alloc %d string space.", MAX_STRING );
exit( 1 );
}
top_string = string_space;
fBootDb = TRUE;
}
#endif
init_string_space();
fBootDb=TRUE;
send_to_descrips( "Initialising Ack! Mud. Please Wait....\n\r" );
/*
* Init random number generator.
*/
{
init_mm( );
}
/*
* Set time and weather.
*/
{
long lhour, lday, lmonth;
lhour = (current_time - 650336715)
/ (PULSE_TICK / PULSE_PER_SECOND);
time_info.hour = lhour % 24;
lday = lhour / 24;
time_info.day = lday % 35;
lmonth = lday / 35;
time_info.month = lmonth % 17;
time_info.year = lmonth / 17;
time_info.moon = 0;
weather_info.moon_loc = MOON_DOWN;
weather_info.moon_phase = number_range( MOON_NEW, MOON_FULL );
if ( time_info.hour < 5 ) weather_info.sunlight = SUN_DARK;
else if ( time_info.hour < 6 ) weather_info.sunlight = SUN_RISE;
else if ( time_info.hour < 19 ) weather_info.sunlight = SUN_LIGHT;
else if ( time_info.hour < 20 ) weather_info.sunlight = SUN_SET;
else weather_info.sunlight = SUN_DARK;
weather_info.change = 0;
weather_info.mmhg = 960;
if ( time_info.month >= 7 && time_info.month <=12 )
weather_info.mmhg += number_range( 1, 50 );
else
weather_info.mmhg += number_range( 1, 80 );
if ( weather_info.mmhg <= 980 ) weather_info.sky = SKY_LIGHTNING;
else if ( weather_info.mmhg <= 1000 ) weather_info.sky = SKY_RAINING;
else if ( weather_info.mmhg <= 1020 ) weather_info.sky = SKY_CLOUDY;
else weather_info.sky = SKY_CLOUDLESS;
}
/*
* Initialize Supernatural Councils
*/
{
sh_int index;
char buf[MAX_STRING_LENGTH];
for (index = SUPER_NONE; index < MAX_SUPER; index++ )
{
super_councils[index].first_member = NULL;
super_councils[index].last_member = NULL;
super_councils[index].quorum = FALSE;
super_councils[index].council_time = 0;
switch ( index )
{
case SUPER_NONE : sprintf( buf, "%s", "ORDINARIES" );
break;
case SUPER_VAMP : sprintf( buf, "%s", "@@rJUSTICARS@@N" );
break;
default: sprintf( buf, "%s", "NONE" );
break;
}
super_councils[index].council_name = str_dup( buf );
}
}
/*
* Assign gsn's for skills which have them.
*/
{
int sn;
for ( sn = 0; sn < MAX_SKILL; sn++ )
{
if ( skill_table[sn].pgsn != 0 )
*skill_table[sn].pgsn = sn;
}
}
/* Clear list of used areas */
for (a=0; a< MAX_AREAS; a++)
{
area_used[a]=NULL;
}
/*
* Read in clan data table
*/
{
extern POL_DATA politics_data;
FILE *clanfp;
char clan_file_name[MAX_STRING_LENGTH];
sh_int x,y;
char buf[MAX_STRING_LENGTH];
sprintf( clan_file_name, "%s", CLAN_FILE );
sprintf( buf, "Loading %s\n\r", clan_file_name);
monitor_chan( buf, MONITOR_CLAN );
if ( ( clanfp = fopen( clan_file_name, "r" ) ) == NULL )
{
bug( "Save Clan Table: fopen", 0 );
perror( "failed open of clan_table.dat in load_clan_table" );
}
else
{
fpArea = clanfp;
sprintf( strArea, "%s", clan_file_name );
for (x = 1; x < MAX_CLAN; x++ )
{
for (y = 1; y < MAX_CLAN ; y++ )
{
politics_data.diplomacy[x][y] = fread_number( clanfp );
}
}
for (x = 1; x < MAX_CLAN ; x++ )
{
politics_data.treasury[x] = fread_number( clanfp) ;
}
for (x = 1; x < MAX_CLAN; x++ )
{
for (y = 1; y < MAX_CLAN ; y++ )
{
politics_data.end_current_state[x][y] = fread_number( clanfp );
}
}
fclose( clanfp );
}
fpArea = NULL;
sprintf( buf, "Done Loading %s\n\r", clan_file_name);
monitor_chan( buf, MONITOR_CLAN );
}
/*
* Read in all the socials.
*/
{
load_social_table( );
}
/*
* Read in all the area files.
*/
{
FILE *fpList;
send_to_descrips( "Reading Area Files...\n\r" );
if ( ( fpList = fopen( AREA_LIST, "r" ) ) == NULL )
{
perror( AREA_LIST );
kill( getpid(), SIGQUIT );
}
for ( ; ; )
{
strcpy( strArea, fread_word( fpList ) );
if ( strArea[0] == '$' )
break;
if ( strArea[0] == '-' )
{
fpArea = stdin;
}
else
{
if ( ( fpArea = fopen( strArea, "r" ) ) == NULL )
{
log_string( strArea );
kill( getpid(), SIGQUIT );
}
}
for ( ; ; )
{
char *word;
if ( fread_letter( fpArea ) != '#' )
{
bug( "Boot_db: # not found.", 0 );
kill( getpid(), SIGQUIT );
}
word = fread_word( fpArea );
if ( word[0] == '$' ) break;
else if ( !str_cmp( word, "AREA" ) ) load_area (fpArea);
else if ( !str_cmp( word, "HELPS" ) ) load_helps (fpArea);
else if ( !str_cmp( word, "MOBILES" ) ) load_mobiles (fpArea);
else if ( !str_cmp( word, "MOBPROGS" ) ) load_mobprogs(fpArea);
else if ( !str_cmp( word, "OBJECTS" ) ) load_objects (fpArea);
else if ( !str_cmp( word, "RESETS" ) ) load_resets (fpArea);
else if ( !str_cmp( word, "ROOMS" ) ) load_rooms (fpArea);
else if ( !str_cmp( word, "SHOPS" ) ) load_shops (fpArea);
else if ( !str_cmp( word, "SPECIALS" ) ) load_specials(fpArea);
else if ( !str_cmp( word, "OBJFUNS" ) ) load_objfuns (fpArea);
else
{
bug( "Boot_db: bad section name.", 0 );
exit( 1 );
}
}
if ( fpArea != stdin )
fclose( fpArea );
fpArea = NULL;
}
fclose( fpList );
}
/*
* Fix up exits.
* MAG Mod: Check resets. (Allows loading objects of later areas.)
* MAG Mod: Load gold for areas.
* Declare db booting over.
* Reset all areas once.
* Load up the notes file.
* Set the MOBtrigger.
*/
{
send_to_descrips( "Fixing Exits......" );
fix_exits( );
send_to_descrips( "Done.\n\r" );
fBootDb = FALSE;
send_to_descrips( "Checking Resets..." );
check_resets();
send_to_descrips( "Done.\n\r" );
/* load_gold(); */
send_to_descrips( "Updating Areas...." );
area_update( );
send_to_descrips( "Done.\n\r" );
load_notes( );
MOBtrigger = TRUE;
load_corpses( );
booting_up = TRUE;
load_marks( );
booting_up = FALSE;
save_marks( );
load_bans( );
load_rulers( );
load_brands( );
}
#if defined(SOEBLD)
auto_quest = FALSE;
#else
auto_quest = TRUE;
#endif
if (fCopyOver)
{
extern bool disable_timer_abort;
disable_timer_abort = TRUE;
copyover_recover();
disable_timer_abort = FALSE;
}
return;
}
/*
* Snarf an 'area' header line.
*/
void load_area( FILE *fp )
{
AREA_DATA *pArea;
char letter;
int a;
GET_FREE(pArea, area_free);
pArea->first_reset = NULL;
pArea->last_reset = NULL;
pArea->name = fread_string( fp );
pArea->age = 15;
pArea->reset_rate = 15;
pArea->nplayer = 0;
pArea->offset = 0;
/* MAG Mod */
pArea->modified = 0;
pArea->min_vnum = 0;
pArea->max_vnum = MAX_VNUM;
pArea->area_num = 0;
pArea->filename = str_dup(strArea);
pArea->owner = str_empty;
pArea->can_read = str_dup("all");
pArea->can_write = str_dup("all");
pArea->level_label = str_dup("{?? ??}");
pArea->keyword = str_dup("none");
pArea->reset_msg = str_dup( "You hear the screams of the Dead within your head." );
pArea->min_level = 0;
pArea->max_level = 0;
pArea->gold = 0;
pArea->flags = 0;
pArea->first_area_room = NULL;
pArea->last_area_room = NULL;
pArea->first_area_help_text = NULL;
pArea->last_area_help_text = NULL;
pArea->first_area_object = NULL;
pArea->last_area_object = NULL;
pArea->first_area_mobile = NULL;
pArea->last_area_mobile = NULL;
pArea->first_area_shop = NULL;
pArea->last_area_shop = NULL;
pArea->first_area_specfunc = NULL;
pArea->last_area_specfunc = NULL;
pArea->first_area_mobprog = NULL;
/* MAG Mod for optionals additions to area headers. */
for (;;)
{
letter=fread_letter(fp);
if (letter=='#')
{
ungetc(letter,fp);
break;
}
switch (letter)
{
case 'F':
pArea->reset_rate = fread_number(fp);
break;
case 'O':
pArea->owner = fread_string(fp);
break;
case 'U':
free_string( pArea->reset_msg );
pArea->reset_msg = fread_string(fp);
break;
case 'R':
free_string(pArea->can_read);
pArea->can_read = fread_string(fp);
break;
case 'W':
free_string(pArea->can_write);
pArea->can_write = fread_string(fp);
break;
case 'P':
SET_BIT(pArea->flags,AREA_PAYAREA);
fread_to_eol(fp);
break;
case 'M':
SET_BIT(pArea->flags,AREA_NO_ROOM_AFF);
fread_to_eol(fp);
break;
case 'X':
pArea->offset = fread_number(fp);
break;
case 'V':
pArea->min_vnum = fread_number(fp);
pArea->max_vnum = fread_number(fp);
break;
case 'N':
pArea->area_num = fread_number(fp);
break;
case 'T':
SET_BIT(pArea->flags,AREA_TELEPORT);
fread_to_eol(fp);
break;
case 'B':
SET_BIT(pArea->flags,AREA_BUILDING);
fread_to_eol(fp);
break;
case 'S':
SET_BIT(pArea->flags, AREA_NOSHOW );
fread_to_eol(fp);
break;
case 'K':
free_string(pArea->keyword);
pArea->keyword = fread_string(fp);
break;
case 'L':
free_string(pArea->level_label);
pArea->level_label = fread_string(fp);
break;
case 'I':
pArea->min_level = fread_number(fp);
pArea->max_level = fread_number(fp);
break;
}
}
if ( pArea->area_num == 0 )
{
/* Find a unique area number */
for (a=0; a < MAX_AREAS; a++)
if (area_used[a]==NULL)
break;
pArea->area_num = a;
}
area_used[pArea->area_num]=pArea;
area_load = pArea;
LINK(pArea, first_area, last_area, next, prev);
top_area++;
return;
}
/*
* Snarf a help section.
*/
void load_helps( FILE *fp )
{
HELP_DATA *pHelp;
BUILD_DATA_LIST *pList;
for ( ; ; )
{
GET_FREE(pHelp, help_free);
pHelp->level = fread_number( fp );
pHelp->keyword = fread_string( fp );
if ( pHelp->keyword[0] == '$' )
break;
pHelp->text = fread_string( fp );
/* greeting text handled in comm.c now -S- */
LINK(pHelp, first_help, last_help, next, prev);
/* MAG Mod */
GET_FREE(pList, build_free);
pList->data = pHelp;
LINK(pList, area_load->first_area_help_text,
area_load->last_area_help_text, next, prev);
top_help++;
}
return;
}
void load_corpses( void )
{
FILE *corpsefp;
char corpse_file_name[MAX_STRING_LENGTH];
char buf[MAX_STRING_LENGTH];
sprintf( corpse_file_name, "%s", CORPSE_FILE );
sprintf( buf, "Loading %s\n\r", corpse_file_name);
monitor_chan( buf, MONITOR_CLAN );
if ( ( corpsefp = fopen( corpse_file_name, "r" ) ) == NULL )
{
bug( "Load corpse Table: fopen", 0 );
perror( "failed open of corpse_table.dat in load_corpse_table" );
}
else
{
fpArea = corpsefp;
sprintf( strArea, "%s", corpse_file_name );
for ( ; ; )
{
char letter;
char *word;
letter = fread_letter( corpsefp );
if ( letter == '*' )
{
fread_to_eol( corpsefp );
continue;
}
if ( letter != '#' )
{
monitor_chan( "Load_char_obj: # not found.",MONITOR_BAD );
break;
}
word = fread_word( corpsefp );
if ( !str_cmp( word, "OBJECT" ) )
fread_corpse( corpsefp );
else if ( !str_cmp( word, "END" ) )
break;
else
{
monitor_chan( "Load_char_obj: bad section.", MONITOR_BAD );
break;
}
}
}
fclose( corpsefp );
fpArea = NULL;
sprintf( buf, "Done Loading %s\n\r", corpse_file_name);
monitor_chan( buf, MONITOR_CLAN );
}
/*
* Load marked rooms
*
*/
void load_marks( void )
{
FILE *marksfp;
char marks_file_name[MAX_STRING_LENGTH];
char buf[MAX_STRING_LENGTH];
sprintf( marks_file_name, "%s", MARKS_FILE );
sprintf( buf, "Loading %s\n\r", marks_file_name);
monitor_chan( buf, MONITOR_CLAN );
if ( ( marksfp = fopen( marks_file_name, "r" ) ) == NULL )
{
bug( "Load marks Table: fopen", 0 );
perror( "failed open of marks_table.dat in load_marks_table" );
}
else
{
fpArea = marksfp;
sprintf( strArea, "%s", marks_file_name );
for ( ; ; )
{
/* char letter; */
char *word;
int rvnum = 0;
MARK_DATA *mark;
/* letter = fread_letter( marksfp );
if ( letter == '*' )
{
fread_to_eol( marksfp );
continue;
}
if ( letter != '#' )
{
monitor_chan( "Load_marks: # not found.",MONITOR_BAD );
break;
}
*/
word = fread_string( marksfp );
if ( !str_cmp( word, "#MARK" ) )
{
GET_FREE( mark, mark_free );
rvnum = fread_number( marksfp );
mark->message = fread_string( marksfp );
mark->author = fread_string( marksfp );
mark->duration = fread_number( marksfp );
mark->type = fread_number( marksfp );
mark_to_room( rvnum, mark );
free_string( word );
}
else if ( !str_cmp( word, "#END" ) )
{
free_string( word );
break;
}
else
{
free_string( word );
monitor_chan( "Load_marks: bad section.", MONITOR_BAD );
break;
}
}
fclose( marksfp );
fpArea = NULL;
sprintf( buf, "Done Loading %s\n\r", marks_file_name);
monitor_chan( buf, MONITOR_CLAN );
}
}
void load_bans( void )
{
FILE *bansfp;
char bans_file_name[MAX_STRING_LENGTH];
char buf[MAX_STRING_LENGTH];
sprintf( bans_file_name, "%s", BANS_FILE );
sprintf( buf, "Loading %s\n\r", bans_file_name);
monitor_chan( buf, MONITOR_CLAN );
if ( ( bansfp = fopen( bans_file_name, "r" ) ) == NULL )
{
bug( "Load bans Table: fopen", 0 );
perror( "failed open of bans_table.dat in load_bans_table" );
}
else
{
fpArea = bansfp;
sprintf( strArea, "%s", bans_file_name );
for ( ; ; )
{
char *word;
BAN_DATA *pban;
word = fread_string( bansfp );
if ( !str_cmp( word, "#BAN" ) )
{
sh_int get_bool = FALSE;
GET_FREE( pban, ban_free );
get_bool = fread_number( bansfp );
if ( get_bool == 1 )
pban->newbie = TRUE;
else
pban->newbie = FALSE;
pban->name = fread_string( bansfp );
pban->banned_by = fread_string( bansfp );
LINK( pban, first_ban, last_ban, next, prev );
free_string( word );
}
else if ( !str_cmp( word, "#END" ) )
{
free_string( word );
break;
}
else
{
free_string( word );
monitor_chan( "Load_bans: bad section.", MONITOR_BAD );
break;
}
}
fclose( bansfp );
fpArea = NULL;
sprintf( buf, "Done Loading %s\n\r", bans_file_name);
monitor_chan( buf, MONITOR_CLAN );
}
}
/*
* Snarf a mob section.
*/
void load_mobiles( FILE *fp )
{
MOB_INDEX_DATA *pMobIndex;
BUILD_DATA_LIST *pList;
for ( ; ; )
{
sh_int vnum;
char letter;
int iHash;
letter = fread_letter( fp );
if ( letter != '#' )
{
bug( "Load_mobiles: # not found.", 0 );
hang( "Loading Mobiles in db.c" );
}
vnum = fread_number( fp );
if ( vnum == 0 )
break;
fBootDb = FALSE;
if ( get_mob_index( vnum ) != NULL )
{
bug( "Load_mobiles: vnum %d duplicated.", vnum );
hang( "Loading Mobiles in db.c" );
}
fBootDb = TRUE;
GET_FREE(pMobIndex, mid_free);
pMobIndex->vnum = vnum;
pMobIndex->area = area_load;
pMobIndex->player_name = fread_string( fp );
pMobIndex->short_descr = fread_string( fp );
pMobIndex->long_descr = fread_string( fp );
pMobIndex->description = fread_string( fp );
pMobIndex->long_descr[0] = UPPER(pMobIndex->long_descr[0]);
pMobIndex->description[0] = UPPER(pMobIndex->description[0]);
pMobIndex->act = fread_number( fp ) | ACT_IS_NPC;
pMobIndex->affected_by = fread_number( fp );
pMobIndex->pShop = NULL;
pMobIndex->alignment = fread_number( fp );
letter = fread_letter( fp );
pMobIndex->level = number_fuzzy( fread_number( fp ) );
pMobIndex->sex = fread_number( fp );
pMobIndex->ac_mod = fread_number( fp ); /* read */
pMobIndex->hr_mod = fread_number( fp ); /* in the */
pMobIndex->dr_mod = fread_number( fp ); /* modifiers */
if ( letter != 'S' )
{
bug( "Load_mobiles: vnum %d non-S.", vnum );
hang( "Loading Mobiles in db.c" );
}
/* The "new" additions to mobs start with a !*/
letter=fread_letter(fp);
if ( letter == '!' )
{
pMobIndex->class = fread_number( fp );
pMobIndex->clan = fread_number( fp );
pMobIndex->race = fread_number( fp );
pMobIndex->position = POS_STANDING;
fread_number( fp ); /* position */
pMobIndex->skills = fread_number( fp );
pMobIndex->cast = fread_number( fp );
pMobIndex->def = fread_number( fp );
}
else
ungetc( letter, fp );
letter=fread_letter( fp );
if (letter=='>')
{
ungetc(letter,fp);
mprog_read_programs(fp,pMobIndex);
}
else
ungetc(letter,fp);
iHash = vnum % MAX_KEY_HASH;
SING_TOPLINK(pMobIndex, mob_index_hash[iHash], next);
/* MAG Mod */
GET_FREE(pList, build_free);
pList->data = pMobIndex;
LINK(pList, area_load->first_area_mobile, area_load->last_area_mobile,
next, prev);
top_mob_index++;
kill_table[URANGE(0, pMobIndex->level, MAX_LEVEL-1)].number++;
}
return;
}
/*
* Snarf an obj section.
*/
void load_objects( FILE *fp )
{
OBJ_INDEX_DATA *pObjIndex;
BUILD_DATA_LIST *pList;
for ( ; ; )
{
sh_int vnum;
char letter;
int iHash;
letter = fread_letter( fp );
if ( letter != '#' )
{
bug( "Load_objects: # not found.", 0 );
hang( "Loading Objects in db.c" );
}
vnum = fread_number( fp );
if ( vnum == 0 )
break;
fBootDb = FALSE;
if ( get_obj_index( vnum ) != NULL )
{
bug( "Load_objects: vnum %d duplicated.", vnum );
hang( "Loading Objects in db.c" );
}
fBootDb = TRUE;
GET_FREE(pObjIndex, oid_free);
pObjIndex->vnum = vnum;
pObjIndex->area = area_load;
pObjIndex->name = fread_string( fp );
pObjIndex->short_descr = fread_string( fp );
pObjIndex->description = fread_string( fp );
pObjIndex->short_descr[0] = LOWER(pObjIndex->short_descr[0]);
pObjIndex->description[0] = UPPER(pObjIndex->description[0]);
pObjIndex->item_type = fread_number( fp );
pObjIndex->extra_flags = fread_number( fp );
pObjIndex->wear_flags = fread_number( fp );
pObjIndex->item_apply = fread_number( fp );
pObjIndex->value[0] = fread_number( fp );
pObjIndex->value[1] = fread_number( fp );
pObjIndex->value[2] = fread_number( fp );
pObjIndex->value[3] = fread_number( fp );
pObjIndex->weight = fread_number( fp );
pObjIndex->cost = 0;
if ( pObjIndex->item_type == ITEM_POTION )
SET_BIT(pObjIndex->extra_flags, ITEM_NODROP);
for ( ; ; )
{
char letter;
letter = fread_letter( fp );
if ( letter == 'A' )
{
AFFECT_DATA *paf;
GET_FREE(paf, affect_free);
paf->type = -1;
paf->duration = -1;
paf->location = fread_number( fp );
paf->modifier = fread_number( fp );
paf->bitvector = 0;
paf->caster = NULL;
LINK(paf, pObjIndex->first_apply, pObjIndex->last_apply,
next, prev);
top_affect++;
}
else if ( letter == 'E' )
{
EXTRA_DESCR_DATA *ed;
GET_FREE(ed, exdesc_free);
ed->keyword = fread_string( fp );
ed->description = fread_string( fp );
LINK(ed, pObjIndex->first_exdesc, pObjIndex->last_exdesc,
next, prev);
top_ed++;
}
else if ( letter == 'L' )
{
pObjIndex->level = fread_number( fp );
}
else
{
ungetc( letter, fp );
break;
}
}
/*
* Translate spell "slot numbers" to internal "skill numbers."
*/
switch ( pObjIndex->item_type )
{
case ITEM_PILL:
case ITEM_POTION:
case ITEM_SCROLL:
pObjIndex->value[1] = slot_lookup( pObjIndex->value[1] );
pObjIndex->value[2] = slot_lookup( pObjIndex->value[2] );
pObjIndex->value[3] = slot_lookup( pObjIndex->value[3] );
break;
case ITEM_STAFF:
case ITEM_WAND:
pObjIndex->value[3] = slot_lookup( pObjIndex->value[3] );
break;
}
iHash = vnum % MAX_KEY_HASH;
SING_TOPLINK(pObjIndex, obj_index_hash[iHash], next);
/* MAG Mod */
GET_FREE(pList, build_free);
pList->data = pObjIndex;
LINK(pList, area_load->first_area_object, area_load->last_area_object,
next, prev);
top_obj_index++;
}
return;
}
/*
* Snarf a reset section.
*/
/* Spec: it isn't obvious how this works, so I'll add a comment here.
*
* load_resets only allows resets that are placed in current rooms - this is
* the reset_ok code here. It does _not_ check the validity of room and object
* vnums. It handles linking the resets into the appropriate room-reset-list
* for OLC.
*
* check_resets is called after all areas are loaded. It checks that all
* resets point to valid mobs and object and spits errors as necessary. It
* does _not_ touch the room lists any more!
*/
void load_resets( FILE *fp )
{
RESET_DATA *pReset= NULL;
BUILD_DATA_LIST * pList = NULL;
ROOM_INDEX_DATA *last_mob_room;
ROOM_INDEX_DATA *last_obj_room;
last_mob_room=NULL;
last_obj_room=NULL;
if ( area_load == NULL )
{
bug( "Load_resets: no #AREA seen yet.", 0 );
hang( "Loading Resets in db.c" );
}
for ( ; ; )
{
ROOM_INDEX_DATA *pRoomIndex;
/* EXIT_DATA *pexit; unused? */
char letter;
/* Temp values to hold reset, while we see if valid*/
char Tcommand;
int Tifflag;
int Targ1;
int Targ2;
int Targ3;
bool reset_ok;
reset_ok = FALSE;
if ( ( letter = fread_letter( fp ) ) == 'S' )
break;
if ( letter == '*' )
{
fread_to_eol( fp );
continue;
}
Tcommand = letter;
/* MAG Mod */
Tifflag = fread_number( fp ); /* Not used */
Targ1 = fread_number( fp );
Targ2 = fread_number( fp );
Targ3 = (letter == 'G' || letter == 'R')
? 0 : fread_number( fp );
pRoomIndex=NULL; /* Set it to check for room numbers */
/*
* Validate parameters.
* We're calling the index functions for the side effect.
*/
switch ( letter )
{
default:
bug( "Load_resets: bad command '%c'.", letter );
reset_ok = FALSE;
break;
case 'A': reset_ok = FALSE; break; /* obsolete reset, discard */
case 'M':
if ( ( pRoomIndex = get_room_index( Targ3 ) ) != NULL )
{
reset_ok = TRUE;
last_mob_room = pRoomIndex;
}
break;
case 'O':
if ( ( pRoomIndex = get_room_index( Targ3) ) != NULL )
{
reset_ok = TRUE;
last_obj_room = pRoomIndex;
}
break;
case 'P': /* apparently these resets are no longer in use */
/* if ( last_obj_room )
{
pRoomIndex = last_obj_room;
reset_ok = TRUE;
} */
break;
case 'G':
case 'E':
if ( last_mob_room )
{
pRoomIndex = last_mob_room;
reset_ok = TRUE;
}
break;
case 'D':
if ( ( pRoomIndex = get_room_index( Targ1) ) != NULL )
{
reset_ok = TRUE;
}
break;
case 'R':
if ( ( pRoomIndex = get_room_index( Targ1) ) != NULL )
{
reset_ok = TRUE;
}
break;
}
if ( reset_ok ) /* i.e. only add if reset is valid. */
{
GET_FREE(pReset, reset_free);
pReset->command = Tcommand;
pReset->arg1 = Targ1;
pReset->arg2 = Targ2;
pReset->arg3 = Targ3;
pReset->notes = fsave_to_eol( fp );
LINK(pReset, area_load->first_reset, area_load->last_reset,
next, prev);
top_reset++;
GET_FREE(pList, build_free);
pList->data = pReset;
LINK( pList, pRoomIndex->first_room_reset,
pRoomIndex->last_room_reset, next, prev );
}
}
return;
}
/*
* Snarf a room section.
*/
void load_rooms( FILE *fp )
{
ROOM_INDEX_DATA *pRoomIndex;
BUILD_DATA_LIST *pList;
if ( area_load == NULL )
{
bug( "Load_rooms: no #AREA seen yet.", 0 );
hang( "Loading Rooms in db.c" );
}
for ( ; ; )
{
sh_int vnum;
char letter;
int door;
int iHash;
letter = fread_letter( fp );
if ( letter != '#' )
{
bug( "Load_rooms: # not found.", 0 );
hang( "Loading Rooms in db.c" );
}
vnum = fread_number( fp );
if ( vnum == 0 )
break;
fBootDb = FALSE;
if ( get_room_index( vnum ) != NULL )
{
bug( "Load_rooms: vnum %d duplicated.", vnum );
hang( "Loading Rooms in db.c" );
}
fBootDb = TRUE;
GET_FREE(pRoomIndex, rid_free);
pRoomIndex->first_person = NULL;
pRoomIndex->last_person = NULL;
pRoomIndex->first_content = NULL;
pRoomIndex->last_content = NULL;
pRoomIndex->first_exdesc = NULL;
pRoomIndex->last_exdesc = NULL;
pRoomIndex->area = area_load;
pRoomIndex->vnum = vnum;
pRoomIndex->name = fread_string( fp );
pRoomIndex->description = fread_string( fp );
pRoomIndex->room_flags = fread_number( fp );
pRoomIndex->sector_type = fread_number( fp );
pRoomIndex->light = 0;
pRoomIndex->affected_by = ROOM_BV_NONE;
pRoomIndex->first_room_affect = NULL;
pRoomIndex->last_room_affect = NULL;
for ( door = 0; door <= 5; door++ )
pRoomIndex->exit[door] = NULL;
pRoomIndex->first_room_reset = NULL; /* MAG Mod */
pRoomIndex->last_room_reset = NULL;
for ( ; ; )
{
letter = fread_letter( fp );
if ( letter == 'S' )
break;
if ( letter == 'D' )
{
EXIT_DATA *pexit;
int locks;
door = fread_number( fp );
if ( door < 0 || door > 5 )
{
bug( "Fread_rooms: vnum %d has bad door number.", vnum );
hang( "Loading Rooms in db.c" );
}
GET_FREE(pexit, exit_free);
pexit->description = fread_string( fp );
pexit->keyword = fread_string( fp );
pexit->exit_info = 0;
locks = fread_number( fp );
pexit->key = fread_number( fp );
pexit->vnum = fread_number( fp );
/* -S- Mod: exit_flags now saved as-is, with EX_CLOSED and
EX_LOCKED filtered out. If locks is 2, it's from an
'old' area, so handle it, otherwise just set exit_info.
This allows new exit flags to be easily added. :)
(Impossible for new area to have locks = 2(closed) */
if ( locks == 2 )
pexit->exit_info = EX_ISDOOR | EX_PICKPROOF;
else
pexit->exit_info = locks;
pRoomIndex->exit[door] = pexit;
top_exit++;
}
else if ( letter == 'E' )
{
EXTRA_DESCR_DATA *ed;
GET_FREE(ed, exdesc_free);
ed->keyword = fread_string( fp );
ed->description = fread_string( fp );
LINK(ed, pRoomIndex->first_exdesc, pRoomIndex->last_exdesc,
next, prev);
top_ed++;
}
else
{
bug( "Load_rooms: vnum %d has flag not 'DES'.", vnum );
hang( "Loading Rooms in db.c" );
}
}
iHash = vnum % MAX_KEY_HASH;
SING_TOPLINK(pRoomIndex, room_index_hash[iHash], next);
/* MAG Mod */
GET_FREE(pList, build_free);
pList->data = pRoomIndex;
LINK(pList, area_load->first_area_room, area_load->last_area_room,
next, prev);
top_room++;
}
return;
}
/*
* Snarf a shop section.
*/
void load_shops( FILE *fp )
{
SHOP_DATA *pShop;
BUILD_DATA_LIST *pList;
for ( ; ; )
{
MOB_INDEX_DATA *pMobIndex;
int iTrade;
int keeper;
keeper = fread_number(fp);
if ( keeper == 0 )
break;
GET_FREE(pShop, shop_free);
pShop->keeper = keeper;
for ( iTrade = 0; iTrade < MAX_TRADE; iTrade++ )
pShop->buy_type[iTrade] = fread_number( fp );
pShop->profit_buy = fread_number( fp );
pShop->profit_sell = fread_number( fp );
pShop->open_hour = fread_number( fp );
pShop->close_hour = fread_number( fp );
fread_to_eol( fp );
pMobIndex = get_mob_index( pShop->keeper );
pMobIndex->pShop = pShop;
/* MAG Mod */
GET_FREE(pList, build_free);
pList->data = pShop;
LINK(pList, area_load->first_area_shop, area_load->last_area_shop,
next, prev);
LINK(pShop, first_shop, last_shop, next, prev);
top_shop++;
}
return;
}
/*
* Snarf spec proc declarations.
*/
void load_specials( FILE *fp )
{
for ( ; ; )
{
MOB_INDEX_DATA *pMobIndex;
char letter;
switch ( letter = fread_letter( fp ) )
{
default:
bug( "Load_specials: letter '%c' not *, M, or S.", letter );
hang( "Loading Specials in db.c" );
case 'S':
return;
case '*':
break;
case 'M':
pMobIndex = get_mob_index ( fread_number ( fp ) );
pMobIndex->spec_fun = spec_lookup ( fread_word ( fp ) );
if ( pMobIndex->spec_fun == 0 )
{
bug( "Load_specials(mob): 'M': vnum %d.", pMobIndex->vnum );
}
else
{
BUILD_DATA_LIST *pList;
/* MAG Mod */
GET_FREE(pList, build_free);
pList->data = pMobIndex;
LINK(pList, area_load->first_area_specfunc,
area_load->last_area_specfunc, next, prev);
}
break;
}
/* NB. Comments will not be saved when using areasave - MAG. */
fread_to_eol( fp );
}
}
/* Snarf objfun declarations. -S- */
void load_objfuns( FILE *fp )
{
for ( ; ; )
{
OBJ_INDEX_DATA *pObj;
char letter;
switch ( letter = fread_letter( fp ) )
{
default:
bug( "Load_objfuns: letter '%c' not *, O or S.", letter );
hang( "Loading Objfuns in db.c" );
case 'S':
return;
case '*':
break;
case 'O': /* -S- mod => obj_funs */
pObj = get_obj_index( fread_number ( fp ) );
pObj->obj_fun = obj_fun_lookup( fread_word ( fp ) );
if ( pObj->obj_fun == 0 )
{
bug( "Load_specials(obj): 'X': vnum %d.", pObj->vnum );
}
else
{
BUILD_DATA_LIST *pList;
GET_FREE(pList, build_free);
pList->data = pObj;
LINK(pList, area_load->first_area_objfunc,
area_load->last_area_objfunc, next, prev);
}
break;
}
/* NB. Comments will not be saved when using areasave - MAG. */
fread_to_eol( fp );
}
}
/*
* Snarf notes file.
*/
void load_notes( void )
{
FILE *fp;
if ( ( fp = fopen( NOTE_FILE, "r" ) ) == NULL )
return;
for ( ; ; )
{
NOTE_DATA *pnote;
char letter;
do
{
letter = getc( fp );
if ( feof(fp) )
{
fclose( fp );
return;
}
}
while ( isspace(letter) );
ungetc( letter, fp );
GET_FREE(pnote, note_free);
if ( str_cmp( fread_word( fp ), "sender" ) )
break;
pnote->sender = fread_string( fp );
if ( str_cmp( fread_word( fp ), "date" ) )
break;
pnote->date = fread_string( fp );
if ( str_cmp( fread_word( fp ), "stamp" ) )
break;
pnote->date_stamp = fread_number( fp );
if ( str_cmp( fread_word( fp ), "to" ) )
break;
pnote->to_list = fread_string( fp );
if ( str_cmp( fread_word( fp ), "subject" ) )
break;
pnote->subject = fread_string( fp );
if ( str_cmp( fread_word( fp ), "text" ) )
break;
pnote->text = fread_string( fp );
LINK(pnote, first_note, last_note, next, prev);
}
strcpy( strArea, NOTE_FILE );
fpArea = fp;
bug( "Load_notes: bad key word.", 0 );
hang( "Loading Notes in db.c" );
return;
}
/*
* Translate all room exits from virtual to real.
* Has to be done after all rooms are read in.
* Check for bad reverse exits.
*/
void fix_exits( void )
{
/* extern const sh_int rev_dir []; */
char buf[MAX_STRING_LENGTH];
ROOM_INDEX_DATA *pRoomIndex;
/* ROOM_INDEX_DATA *to_room;*/
EXIT_DATA *pexit;
/* EXIT_DATA *pexit_rev;*/
int iHash;
int door;
for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
{
for ( pRoomIndex = room_index_hash[iHash];
pRoomIndex != NULL;
pRoomIndex = pRoomIndex->next )
{
bool fexit;
fexit = FALSE;
for ( door = 0; door <= 5; door++ )
{
if ( ( pexit = pRoomIndex->exit[door] ) != NULL )
{
if ( ( pexit->vnum <= 0 )
|| ( get_room_index( pexit->vnum ) == NULL ) )
{
sprintf( buf, "Bad exit vnum %d in room %d", pexit->vnum,
pRoomIndex->vnum);
bug( buf, 0 );
free_string( pexit->description );
free_string( pexit->keyword );
PUT_FREE( pexit, exit_free );
pRoomIndex->exit[door] = NULL;
/* pexit->to_room = NULL; */
}
else
{
fexit = TRUE;
pexit->to_room = get_room_index( pexit->vnum );
}
}
}
if ( !fexit )
SET_BIT( pRoomIndex->room_flags, ROOM_NO_MOB );
}
}
/*
for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
{
for ( pRoomIndex = room_index_hash[iHash];
pRoomIndex != NULL;
pRoomIndex = pRoomIndex->next )
{
for ( door = 0; door <= 5; door++ )
{
if ( ( pexit = pRoomIndex->exit[door] ) != NULL
&& ( to_room = pexit->to_room ) != NULL
&& ( pexit_rev = to_room->exit[rev_dir[door]] ) != NULL
&& pexit_rev->to_room != pRoomIndex )
{
sprintf( buf, "Fix_exits: %d:%d -> %d:%d -> %d.",
pRoomIndex->vnum, door,
to_room->vnum, rev_dir[door],
(pexit_rev->to_room == NULL)
? 0 : pexit_rev->to_room->vnum );
bug( buf, 0 );
}
}
}
} */
return;
}
/* Load up gold into areas */
void load_gold( void )
{
FILE * fpArea;
int area_num;
int gold;
AREA_DATA * pArea;
fpArea=fopen("area.gld","r");
if (fpArea==NULL)
{
bug("Could not open area.gld for reading.",0);
return;
}
for ( ; ; )
{
area_num=fread_number(fpArea);
if (area_num==-1)
break;
gold=fread_number(fpArea);
if ( (pArea=area_used[area_num]) != NULL)
pArea->gold=gold;
}
fclose(fpArea);
}
/* Spec: see the comments on load_resets about what check_resets does */
#define VALID_RESET 0
#define INVAL_ROOM 1
#define INVAL_OBJ 2
#define INVAL_MOB 3
#define INVAL_GEN 4
void check_resets( void )
{
AREA_DATA *pArea;
RESET_DATA *pReset;
RESET_DATA *nextReset;
ROOM_INDEX_DATA *last_mob_room;
int previous_bug = 0;
for ( pArea = first_area; pArea; pArea = pArea->next )
{
last_mob_room = NULL;
for ( pReset = pArea->first_reset; pReset; pReset = nextReset )
{
ROOM_INDEX_DATA *pRoomIndex = NULL;
EXIT_DATA *pexit;
int ValReset = VALID_RESET;
nextReset = pReset->next;
switch( pReset->command )
{
default:
SHOW_AREA;
bug( "Load_resets: bad command '%c'.", pReset->command );
ValReset = INVAL_GEN;
break;
case 'A': /* obsolete.. */
if ( !get_room_index(pReset->arg1) )
ValReset = INVAL_ROOM;
break;
case 'M':
if ( !get_mob_index(pReset->arg1) )
ValReset = INVAL_MOB;
if ( !(last_mob_room = get_room_index(pReset->arg3)) )
ValReset = INVAL_ROOM;
break;
case 'O':
if ( !get_obj_index(pReset->arg1) )
ValReset = INVAL_OBJ;
if ( !get_room_index(pReset->arg3) )
ValReset = INVAL_ROOM;
break;
case 'P': /* obsolete.. */
if ( !get_obj_index(pReset->arg1) || !get_obj_index(pReset->arg3) )
ValReset = INVAL_OBJ;
break;
case 'G':
case 'E':
if ( !get_obj_index(pReset->arg1) )
ValReset = INVAL_OBJ;
if ( !last_mob_room )
ValReset = INVAL_ROOM;
break;
case 'D':
if ( !(pRoomIndex=get_room_index(pReset->arg1)) )
{
ValReset = INVAL_ROOM;
break;
}
if ( pReset->arg2 < 0 || pReset->arg2 > 5 ||
!(pexit = pRoomIndex->exit[pReset->arg2]) ||
!IS_SET(pexit->exit_info, EX_ISDOOR) )
{
SHOW_AREA;
bug( "Check_resets: 'D': exit %d not door.", pReset->arg2 );
ValReset = INVAL_GEN;
}
if ( pReset->arg3 < 0 || pReset->arg3 > 2 )
{
SHOW_AREA;
bug( "Check_resets: 'D': bad 'locks': %d.", pReset->arg3 );
ValReset = INVAL_GEN;
}
break;
case 'R':
if ( !(pRoomIndex = get_room_index(pReset->arg1)) )
{
ValReset = INVAL_ROOM;
break;
}
if ( pReset->arg2 < 0 || pReset->arg2 > 5 )
{
SHOW_AREA;
bug( "Check_resets: 'R': bad exit %d.", pReset->arg2 );
ValReset = INVAL_GEN;
}
break;
}
if ( ValReset != VALID_RESET )
{
char buf[128];
switch(ValReset)
{
case INVAL_ROOM: sprintf(buf, "Invalid room for reset: "); break;
case INVAL_OBJ: sprintf(buf, "Invalid obj for reset: "); break;
case INVAL_MOB: sprintf(buf, "Invalid mob for reset: "); break;
case INVAL_GEN:
default: sprintf(buf, "Invalid arg for reset: "); break;
}
SHOW_AREA;
sprintf(buf+strlen(buf), "%c %d %d %d %d.", pReset->command,
pReset->ifflag, pReset->arg1, pReset->arg2, pReset->arg3);
bug(buf, 0);
UNLINK(pReset, pArea->first_reset, pArea->last_reset, next, prev);
PUT_FREE(pReset, reset_free);
}
/* Spec: We do _not_ want to insert resets into the room list here,
* its all handled in load_resets. Removed.
else
if ( pRoomIndex )
{
BUILD_DATA_LIST *pList;
GET_FREE(pList, build_free);
pList->data = pReset;
LINK(pList, pRoomIndex->first_room_reset,
pRoomIndex->last_room_reset, next, prev);
}
*
*/
}
}
return;
}
/*
* Repopulate areas periodically.
*/
void area_update( void )
{
AREA_DATA *pArea;
for ( pArea = first_area; pArea != NULL; pArea = pArea->next )
{
CHAR_DATA *pch;
/* if ( ++pArea->age < 3 )
continue;
*/
pArea->age++;
/*
* Check for PC's.
*/
if ( ( pArea->nplayer > 0 ) && ( pArea->age >= ( pArea->reset_rate - 1 ) ) )
{
for ( pch = first_char; pch != NULL; pch = pch->next )
{
if ( !IS_NPC(pch)
&& IS_AWAKE(pch)
&& pch->in_room != NULL
&& pch->in_room->area == pArea )
{
char reset_buf[MSL];
sprintf( reset_buf, "%s\n\r", pArea->reset_msg );
send_to_char( reset_buf, pch );
}
}
}
/*
* Check age and reset.
* Note: Mud School resets every 3 minutes (not 15).
*/
if ( ( ( pArea->nplayer == 0 ) && ( pArea->age >= 5 ) )
|| ( pArea->age >= pArea->reset_rate ) )
{
reset_area( pArea );
pArea->age = UMIN( pArea->reset_rate -1, number_range( 0, 3 ) );
}
}
return;
}
/*
* Reset one area.
*/
void reset_area( AREA_DATA *pArea )
{
RESET_DATA *pReset;
CHAR_DATA *mob;
char buf[MAX_STRING_LENGTH];
bool last;
int level;
int previous_bug=0;
sprintf( buf, "Area Reset called for %s.", pArea->name );
monitor_chan( buf, MONITOR_AREA_UPDATE );
mob = NULL;
last = TRUE;
level = 0;
for ( pReset = pArea->first_reset; pReset != NULL; pReset = pReset->next )
{
ROOM_INDEX_DATA *pRoomIndex;
MOB_INDEX_DATA *pMobIndex;
OBJ_INDEX_DATA *pObjIndex;
OBJ_INDEX_DATA *pObjToIndex;
EXIT_DATA *pexit;
OBJ_DATA *obj;
OBJ_DATA *obj_to;
sh_int num_allowed = 2;
switch ( pReset->command )
{
default:
bug( "Reset_area: bad command %c.", pReset->command );
break;
case 'A':
break;
case 'M':
if ( ( pMobIndex = get_mob_index( pReset->arg1 ) ) == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'M': bad vnum %d.", pReset->arg1 );
continue;
}
if ( ( pRoomIndex = get_room_index( pReset->arg3 ) ) == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'R': bad vnum %d.", pReset->arg3 );
continue;
}
level = pMobIndex->level;
if ( pMobIndex->count >= pReset->arg2 )
{
last = FALSE;
break;
}
mob = create_mobile( pMobIndex );
/*
* Check for pet shop.
*/
{
ROOM_INDEX_DATA *pRoomIndexPrev;
pRoomIndexPrev = get_room_index( pRoomIndex->vnum - 1 );
if ( pRoomIndexPrev != NULL
&& IS_SET(pRoomIndexPrev->room_flags, ROOM_PET_SHOP) )
SET_BIT(mob->act, ACT_PET);
}
if ( room_is_dark( pRoomIndex ) )
SET_BIT(mob->affected_by, AFF_INFRARED);
if (mob->in_room != NULL)
char_to_room(mob, mob->in_room);
else
char_to_room( mob, pRoomIndex );
level = URANGE( 0, mob->level - 2, LEVEL_HERO );
last = TRUE;
break;
case 'O':
if ( ( pObjIndex = get_obj_index( pReset->arg1 ) ) == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'O': bad vnum %d.", pReset->arg1 );
continue;
}
if ( ( pRoomIndex = get_room_index( pReset->arg3 ) ) == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'R': bad vnum %d.", pReset->arg3 );
continue;
}
num_allowed = ( ( pReset->arg2 == 0 ) ? 2 : pReset->arg2 - 1);
if ( ( count_obj_room( pObjIndex, pRoomIndex->first_content ) > num_allowed )
|| ( ( count_obj_room( pObjIndex, pRoomIndex->first_content ) > 0 )
&& ( ( pObjIndex->item_type == ITEM_BOARD )
|| ( pObjIndex->item_type == ITEM_FOUNTAIN )
|| ( pObjIndex->item_type == ITEM_FURNITURE )
|| ( pObjIndex->item_type == ITEM_PORTAL )
|| ( pObjIndex->item_type == ITEM_PIECE )
|| ( pObjIndex->extra_flags == ITEM_RARE ) ) )
)
{
last = FALSE;
break;
}
obj = create_object( pObjIndex, number_fuzzy( level ) );
obj_to_room( obj, pRoomIndex );
if ( ( IS_SET( obj->extra_flags, ITEM_RARE ) )
&& !( ( number_percent() < 2 )
&& ( number_percent() < 8 ) )
)
{
extract_obj( obj );
}
if ( ( IS_SET( pRoomIndex->room_flags, ROOM_NO_REPOP ) )
&& ( pRoomIndex->first_person != NULL ) )
{
extract_obj( obj );
}
last = TRUE;
break;
case 'P':
if ( ( pObjIndex = get_obj_index( pReset->arg1 ) ) == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'P': bad vnum %d.", pReset->arg1 );
continue;
}
if ( ( pObjToIndex = get_obj_index( pReset->arg3 ) ) == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'P': bad vnum %d.", pReset->arg3 );
continue;
}
if ( pArea->nplayer > 0
|| ( obj_to = get_obj_type( pObjToIndex ) ) == NULL
|| count_obj_list( pObjIndex, obj_to->first_in_carry_list ) > 0 )
{
last = FALSE;
break;
}
obj = create_object( pObjIndex, number_fuzzy( obj_to->level ) );
/* if ( ( IS_SET( obj->extra_flags, ITEM_RARE ) )
&& ( number_percent() < 1 )
&& ( number_percent() < 50 ) )
{
obj_to_obj( obj, obj_to );
}
else
{
extract_obj( obj );
} */
obj_to_obj( obj, obj_to );
last = TRUE;
break;
case 'G':
case 'E':
if ( ( pObjIndex = get_obj_index( pReset->arg1 ) ) == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'E' or 'G': bad vnum %d.", pReset->arg1 );
continue;
}
if ( !last )
break;
if ( mob == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'E' or 'G': null mob for vnum %d.",
pReset->arg1 );
last = FALSE;
break;
}
if ( mob->pIndexData->pShop != NULL )
{
int olevel;
switch ( pObjIndex->item_type )
{
default: olevel = 0; break;
case ITEM_PILL: olevel = number_range( 0, 10 ); break;
case ITEM_POTION: olevel = number_range( 0, 10 ); break;
case ITEM_SCROLL: olevel = number_range( 5, 15 ); break;
case ITEM_WAND: olevel = number_range( 10, 20 ); break;
case ITEM_STAFF: olevel = number_range( 15, 25 ); break;
case ITEM_ARMOR: olevel = number_range( 5, 15 ); break;
case ITEM_WEAPON: olevel = number_range( 5, 15 ); break;
}
obj = create_object( pObjIndex, olevel );
SET_BIT( obj->extra_flags, ITEM_INVENTORY );
}
else
{
obj = create_object( pObjIndex, number_fuzzy( level ) );
}
obj_to_char( obj, mob );
if ( pReset->command == 'E' )
equip_char( mob, obj, pReset->arg3 );
last = TRUE;
break;
case 'D':
if ( ( pRoomIndex = get_room_index( pReset->arg1 ) ) == NULL )
{
bug( "Reset_area: 'D': bad vnum %d.", pReset->arg1 );
continue;
}
if ( ( pexit = pRoomIndex->exit[pReset->arg2] ) == NULL )
break;
switch ( pReset->arg3 )
{
case 0:
REMOVE_BIT( pexit->exit_info, EX_CLOSED );
REMOVE_BIT( pexit->exit_info, EX_LOCKED );
break;
case 1:
SET_BIT( pexit->exit_info, EX_CLOSED );
REMOVE_BIT( pexit->exit_info, EX_LOCKED );
break;
case 2:
SET_BIT( pexit->exit_info, EX_CLOSED );
SET_BIT( pexit->exit_info, EX_LOCKED );
break;
}
last = TRUE;
break;
case 'R':
if ( ( pRoomIndex = get_room_index( pReset->arg1 ) ) == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'R': bad vnum %d.", pReset->arg1 );
continue;
}
{
int d0;
int d1;
for ( d0 = 0; d0 < pReset->arg2 - 1; d0++ )
{
d1 = number_range( d0, pReset->arg2-1 );
pexit = pRoomIndex->exit[d0];
pRoomIndex->exit[d0] = pRoomIndex->exit[d1];
pRoomIndex->exit[d1] = pexit;
}
}
break;
}
}
return;
}
/* Nasty hack to get back the address of a loaded mob */
extern CHAR_DATA * loaded_mob_addr;
/*
* Create an instance of a mobile.
*/
CHAR_DATA *create_mobile( MOB_INDEX_DATA *pMobIndex )
{
CHAR_DATA *mob;
int level;
char buf[255];
if ( pMobIndex == NULL )
{
bug( "Create_mobile: NULL pMobIndex.", 0 );
hang( "Create Mobile in db.c" );
}
if ( IS_SET(pMobIndex->act,ACT_INTELLIGENT) )
{
/* Only load one with the same name */
#if !defined(machintosh) && !defined(MSDOS)
sprintf(buf,"%s n%i",pMobIndex->player_name,pMobIndex->count+1);
#else
sprintf(buf,"n%i %s",pMobIndex->count+1,pMobIndex->player_name);
#endif
/*
if (load_char_obj(NULL,buf)==TRUE)
{
loaded_mob_addr->next = char_list;
char_list = loaded_mob_addr;
pMobIndex->count++;
check_free_mem();
return loaded_mob_addr;
} */
}
GET_FREE(mob, char_free);
clear_char( mob );
mob->pIndexData = pMobIndex;
if (IS_SET(pMobIndex->act,ACT_INTELLIGENT))
mob->name = str_dup(buf);
else
mob->name = str_dup(pMobIndex->player_name);
mob->short_descr = str_dup(pMobIndex->short_descr);
mob->long_descr = str_dup(pMobIndex->long_descr);
mob->description = str_dup(pMobIndex->description);
mob->switched = FALSE;
mob->old_body = NULL;
mob->spec_fun = pMobIndex->spec_fun;
mob->sitting = NULL;
mob->prompt = str_dup("<%h %m %v> ");
mob->first_shield = NULL;
mob->last_shield = NULL;
/* Changed exp value for mobs */
level = ( pMobIndex->level );
mob->level = level;
mob->act = pMobIndex->act;
mob->affected_by = pMobIndex->affected_by;
mob->alignment = pMobIndex->alignment;
mob->sex = pMobIndex->sex;
mob->ac_mod = pMobIndex->ac_mod;
mob->hr_mod = pMobIndex->hr_mod;
mob->dr_mod = pMobIndex->dr_mod;
/* mob->move_to = NO_VNUM; */
mob->armor = interpolate( mob->level/2, 100, -100 );
mob->max_hit = mob->level * 15 + number_range(
mob->level * mob->level / 2,
mob->level * mob->level / 1 );
mob->hit = mob->max_hit;
mob->exp = exp_for_mobile( mob->level, mob );
mob->intell_exp = 0;
/* mana for mobs... */
mob->max_mana = level * 25;
mob->mana = level * 25;
mob->skills = pMobIndex->skills;
mob->cast = pMobIndex->cast;
mob->def = pMobIndex->def;
mob->class = pMobIndex->class;
mob->clan = pMobIndex->clan;
mob->race = pMobIndex->race;
mob->position = POS_STANDING;
mob->is_quitting = FALSE;
mob->extract_timer = -1;
mob->in_room = NULL; /* to distinguish between loaded mobs */
/* and creted mobs */
/*
* Insert in list.
*/
mob->next = NULL;
mob->prev = NULL;
LINK(mob, first_char, last_char, next, prev);
pMobIndex->count++;
return mob;
}
/*
* Create an instance of an object.
*/
OBJ_DATA *create_object( OBJ_INDEX_DATA *pObjIndex, int level )
{
static OBJ_DATA obj_zero;
OBJ_DATA *obj;
AFFECT_DATA *af;
AFFECT_DATA *new_af;
int new_cost;
if ( level < 0 )
level = 1;
if ( pObjIndex == NULL )
{
bug( "Create_object: NULL pObjIndex.", 0 );
hang( "Creating Objext in db.c" );
}
GET_FREE(obj, obj_free);
*obj = obj_zero;
obj->pIndexData = pObjIndex;
obj->in_room = NULL;
if ( pObjIndex->level < 3 )
{
if ( pObjIndex->level == 2 )
{
obj->level = 1;
}
else
{
obj->level = level;
}
}
else
{
obj->level = pObjIndex->level;
}
obj->wear_loc = -1;
obj->name = str_dup(pObjIndex->name);
obj->short_descr = str_dup(pObjIndex->short_descr);
obj->description = str_dup(pObjIndex->description);
obj->item_type = pObjIndex->item_type;
obj->extra_flags = pObjIndex->extra_flags;
obj->wear_flags = pObjIndex->wear_flags;
obj->item_apply = pObjIndex->item_apply;
obj->obj_fun = pObjIndex->obj_fun;
obj->first_in_room = NULL;
obj->next_in_room = NULL;
obj->last_in_room = NULL;
obj->prev_in_room = NULL;
obj->first_in_carry_list = NULL;
obj->next_in_carry_list = NULL;
obj->last_in_carry_list = NULL;
obj->prev_in_carry_list = NULL;
obj->first_content = NULL;
obj->next_content = NULL;
obj->last_content = NULL;
obj->prev_content = NULL;
obj->in_obj = NULL;
/* We want to copy pObjIndex->affected to obj->index */
for ( af = pObjIndex->first_apply; af != NULL; af = af->next )
{
/* Create new_af, or use a free_affect */
GET_FREE(new_af, affect_free);
/* Now initialize the contents of new_af */
new_af->type = -1;
new_af->duration = -1;
new_af->location = af->location;
new_af->modifier = af->modifier;
new_af->bitvector = 0;
new_af->caster = NULL;
LINK(new_af, obj->first_apply, obj->last_apply, next, prev);
}
obj->value[0] = pObjIndex->value[0];
obj->value[1] = pObjIndex->value[1];
obj->value[2] = pObjIndex->value[2];
obj->value[3] = pObjIndex->value[3];
obj->weight = pObjIndex->weight;
new_cost = get_item_value( obj );
if ( IS_SET( obj->extra_flags, ITEM_REMORT ) )
new_cost *= 2;
if ( IS_SET( obj->extra_flags, ITEM_ADEPT ) )
new_cost *= 3;
if ( IS_SET( obj->extra_flags, ITEM_RARE ) )
new_cost *= 10;
obj->cost = new_cost;
if (obj->item_type == ITEM_FOOD )
obj->cost /= 200;
obj->cost = UMAX( 10, obj->cost );
obj->condition = 100; /* New, so in tip-top condition */
/*
* Mess with object properties.
*/
switch ( obj->item_type )
{
default:
bugf( "create_object: vnum %d bad type %d.", pObjIndex->vnum,
obj->item_type );
break;
case ITEM_SPELL_MATRIX:
case ITEM_ENCHANTMENT:
case ITEM_LIGHT:
case ITEM_BEACON:
case ITEM_TREASURE:
case ITEM_FURNITURE:
case ITEM_TRASH:
case ITEM_CLUTCH: break;
case ITEM_CONTAINER:
obj->wear_flags = ITEM_TAKE;
case ITEM_DRINK_CON:
case ITEM_BOARD:
case ITEM_KEY:
case ITEM_FOOD:
case ITEM_BOAT:
case ITEM_CORPSE_NPC:
case ITEM_CORPSE_PC:
case ITEM_FOUNTAIN:
case ITEM_PORTAL:
case ITEM_PIECE:
case ITEM_SOUL:
case ITEM_TRIGGER:
case ITEM_STAKE:
break;
case ITEM_SCROLL:
obj->value[0] = number_fuzzy( obj->value[0] );
break;
case ITEM_WAND:
case ITEM_STAFF:
obj->value[0] = number_fuzzy( obj->value[0] );
obj->value[1] = number_fuzzy( obj->value[1] );
obj->value[2] = obj->value[1];
break;
case ITEM_WEAPON:
obj->value[1] = number_fuzzy( number_fuzzy( 1 * level / 8 + 3 ) );
obj->value[2] = number_fuzzy( number_fuzzy( 3 * level / 8 + 4 ) );
break;
case ITEM_ARMOR:
obj->value[0] = number_fuzzy( level / 12 + 4 );
break;
case ITEM_POTION:
case ITEM_PILL:
obj->value[0] = number_fuzzy( number_fuzzy( obj->value[0] ) );
break;
case ITEM_MONEY:
obj->value[0] = obj->cost;
break;
}
LINK(obj, first_obj, last_obj, next, prev);
pObjIndex->count++;
return obj;
}
/*
* Clear a new character.
*/
void clear_char( CHAR_DATA *ch )
{
static CHAR_DATA ch_zero;
*ch = ch_zero;
ch->name = &str_empty[0];
ch->short_descr = &str_empty[0];
ch->long_descr = &str_empty[0];
ch->long_descr_orig = &str_empty[0];
ch->description = &str_empty[0];
ch->prompt = &str_empty[0];
ch->last_note = 0;
ch->logon = current_time;
ch->armor = 100;
ch->position = POS_STANDING;
ch->practice = 21;
ch->hit = 20;
ch->max_hit = 20;
ch->mana = 100;
ch->max_mana = 100;
ch->move = 100;
ch->sitting = NULL;
ch->max_move = 100;
ch->act_build = 0;
ch->build_vnum = -1;
ch->sentence = 0;
ch->switched = FALSE;
ch->old_body = NULL;
ch->first_shield = NULL;
ch->last_shield = NULL;
ch->stunTimer = 0;
/* ch->pcdata->recall_vnum = 3001; */
return;
}
/*
* Free a character.
*/
void free_char( CHAR_DATA *ch )
{
MPROG_ACT_LIST *mpact;
CHAR_DATA *rch;
int cnt;
ch->is_quitting = TRUE;
while ( ch->first_carry != NULL )
extract_obj( ch->first_carry );
while ( ch->first_affect != NULL )
affect_remove( ch, ch->first_affect );
while ( (mpact = ch->first_mpact) != NULL )
{
ch->first_mpact = mpact->next;
free_string(mpact->buf);
PUT_FREE(mpact, mpact_free);
}
for ( rch = first_char; rch; rch = rch->next )
{
AFFECT_DATA *paf;
if ( rch->master == ch )
rch->master = NULL;
if ( rch->leader == ch )
rch->leader = NULL;
if ( rch->fighting == ch )
rch->fighting = NULL;
if ( rch->reply == ch )
rch->reply = NULL;
if ( rch->hunting == ch )
{
if ( IS_NPC(rch) && !IS_NPC(ch) )
{
free_string(rch->searching);
rch->searching = str_dup(ch->name);
}
else if ( !IS_NPC(rch) )
{
send_to_char( "@@RYou seem to have lost your prey.\n\r", rch );
}
end_hunt(rch);
}
if ( rch->hunt_for == ch )
rch->hunt_for = NULL;
if ( rch->old_body == ch )
{
do_return(rch, "");
rch->old_body = NULL;
}
for ( mpact = rch->first_mpact; mpact; mpact = mpact->next )
{
if ( mpact->ch == ch )
mpact->ch = NULL;
if ( mpact->vo == ch )
mpact->vo = NULL;
}
for ( paf = rch->first_affect; paf; paf = paf->next )
if ( paf->caster == ch )
paf->caster = NULL;
}
{
ROOM_INDEX_DATA *room;
int rvnum;
ROOM_AFFECT_DATA *raf;
for ( rvnum = 0; rvnum < MAX_KEY_HASH; rvnum++ )
for ( room = room_index_hash[rvnum]; room; room = room->next )
for ( raf = room->first_room_affect; raf; raf = raf->next )
if ( raf->caster == ch )
raf->caster = NULL;
}
free_string( ch->name );
free_string( ch->short_descr );
free_string( ch->long_descr );
free_string( ch->long_descr_orig );
free_string( ch->description );
free_string( ch->prompt );
free_string( ch->old_prompt );
free_string(ch->searching);
free_string( ch->target );
if ( ch->pnote )
{
free_string( ch->pnote->text );
free_string( ch->pnote->date );
free_string( ch->pnote->to_list );
free_string( ch->pnote->sender );
free_string( ch->pnote->subject );
PUT_FREE(ch->pnote, note_free);
}
if ( ch->current_brand )
{
free_string( ch->current_brand->branded);
free_string( ch->current_brand->branded_by);
free_string( ch->current_brand->dt_stamp);
free_string( ch->current_brand->message);
free_string( ch->current_brand->priority);
PUT_FREE( ch->current_brand, brand_data_free );
}
if ( ch->pcdata != NULL )
{
free_string( ch->pcdata->pwd );
free_string( ch->pcdata->bamfin );
free_string( ch->pcdata->room_enter );
free_string( ch->pcdata->room_exit );
free_string( ch->pcdata->bamfout );
free_string( ch->pcdata->immskll );
free_string( ch->pcdata->title );
free_string( ch->pcdata->host );
free_string( ch->pcdata->header );
free_string( ch->pcdata->message );
free_string( ch->pcdata->who_name );
free_string( ch->pcdata->lastlogin );
for ( cnt = 0; cnt < MAX_ALIASES; cnt++ )
{
free_string( ch->pcdata->alias_name[cnt] );
free_string( ch->pcdata->alias[cnt] );
}
for ( cnt = 0; cnt < MAX_IGNORES ; cnt++ )
{
free_string( ch->pcdata->ignore_list[cnt] );
}
free_string( ch->pcdata->rreply );
free_string( ch->pcdata->rreply_name );
free_string( ch->pcdata->load_msg );
free_string( ch->pcdata->pedit_state );
for ( cnt = 0; cnt < 5 ; cnt++ )
{
free_string( ch->pcdata->pedit_string[cnt] );
}
PUT_FREE(ch->pcdata, pcd_free);
}
PUT_FREE(ch, char_free);
return;
}
/*
* Get an extra description from a list.
*/
char *get_extra_descr( const char *name, EXTRA_DESCR_DATA *ed )
{
for ( ; ed != NULL; ed = ed->next )
{
if ( is_name( name, ed->keyword ) )
return ed->description;
}
return NULL;
}
/*
* 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_hash[vnum % MAX_KEY_HASH];
pMobIndex != NULL;
pMobIndex = pMobIndex->next )
{
if ( pMobIndex->vnum == vnum )
return pMobIndex;
}
if ( fBootDb )
{
bug( "Get_mob_index: bad vnum %d.", vnum );
hang( "Get mob index in db.c" );
}
return NULL;
}
/*
* Translates mob 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_hash[vnum % MAX_KEY_HASH];
pObjIndex != NULL;
pObjIndex = pObjIndex->next )
{
if ( pObjIndex->vnum == vnum )
return pObjIndex;
}
if ( fBootDb )
{
bug( "Get_obj_index: bad vnum %d.", vnum );
hang( "Get Object Index in db.c" );
}
return NULL;
}
/*
* Translates mob 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_hash[vnum % MAX_KEY_HASH];
pRoomIndex != NULL;
pRoomIndex = pRoomIndex->next )
{
if ( pRoomIndex->vnum == vnum )
return pRoomIndex;
}
if ( fBootDb )
{
bug( "Get_room_index: bad vnum %d.", vnum );
/* exit( 1 ); */
}
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) )
{
char error_buf[MSL];
sprintf( error_buf, "%c", c );
bug_string( "Fread_number: looking for a digit, found a %s.", error_buf );
hang( "Error in fread_number" );
}
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;
}
#if 0
/*
* 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 );
hang( "Fread String in db.c" );
}
/*
* 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:
bug( "Fread_string: EOF", 0 );
/* exit( 1 ); */
ungetc('~',fp);
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 *) );
}
}
}
}
}
#endif
/*
* Read to end of line (for comments).
*/
/* Spec: fixed to handle EOF more gracefully */
void fread_to_eol( FILE *fp )
{
char c;
do
{
c = getc( fp );
}
while ( c != '\n' && c != '\r' && c != EOF );
while ( c == '\n' || c == '\r' )
{
c = getc( fp );
}
if (c==EOF)
{
bugf("fread_to_eol: EOF");
return;
}
ungetc( c, fp );
return;
}
/* Same as above, but returns the rest of the line */
/* Spec: fixed to handle EOF more gracefully */
char * fsave_to_eol( FILE *fp )
{
char string[MAX_INPUT_LENGTH+1];
int a;
char c;
a=0;
do
{
string[a++] = getc(fp);
}
while (a < MAX_INPUT_LENGTH && string[a-1] != '\n' &&
string[a-1]!='\r' && string[a-1] != EOF);
if (string[a-1]==EOF)
{
bugf("fsave_to_eol: EOF");
string[a-1]=0;
return str_dup(string);
}
if (a==MAX_INPUT_LENGTH)
fread_to_eol(fp);
else
{
c= string[a-1];
while ( c == '\n' || c== '\r' )
c = getc(fp);
if (c==EOF)
bugf("fsave_to_eol: EOF");
else
ungetc(c,fp);
}
string[a]='\0';
return str_dup(string);
}
/*
* Read one word (into static buffer).
*/
char *fread_word( FILE *fp )
{
static char word[MAX_INPUT_LENGTH];
char *pword;
char cEnd;
do
{
if ( feof(fp) )
{
bug("fread_word: EOF encountered on read.\n\r",0);
if ( fBootDb )
kill( getpid(), SIGQUIT );
strcpy(word, "");
return word;
}
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++ )
{
if ( feof(fp) )
{
bug("fread_word: EOF encountered on read.\n\r",0);
if ( fBootDb )
kill( getpid(), SIGQUIT );
*pword = '\0';
return word;
}
*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 );
kill( getpid(), SIGQUIT );
return NULL;
}
void *_getmem(int size, const char *caller, int log)
{
void *mem;
if ( !(mem = malloc(size)) )
{
fprintf(stderr, "Out of memory.\n");
raise(SIGSEGV);
}
memset(mem, 0, size);
if (log&&mem_log)
logf("getmem(%d)=%p from %s", size, mem, caller);
return mem;
}
#if 0
void *getmem(int size)
{
void *mem;
if ( !(mem = calloc(1, size)) )
{
fprintf(stderr, "Out of memory; size %d requested.\n", size);
raise(SIGSEGV);
}
nAllocPerm++;
sAllocPerm += size;
memset(mem, 0, size);
return mem;
}
void dispose(void *mem, int size)
{
if ( !mem )
return;
nAllocPerm--;
sAllocPerm -= size;
free(mem);
return;
}
#endif
#if 0
/*
* Duplicate a string into dynamic memory.
* Fread_strings are read-only and shared.
*/
#define STRING_FREELIST
#ifdef STRING_FREELIST
#define MAX_SIZE_LIST 13
static const int sizelist[MAX_SIZE_LIST] =
{ 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768 };
struct text_data
{
struct text_data *next;
char *text;
};
static struct text_data *text_free[MAX_SIZE_LIST] =
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL };
static struct text_data *tdf_free = NULL;
#endif
char *str_dup( const char *str )
{
char *str_new;
#ifdef STRING_FREELIST
sh_int size;
int len;
#endif
if ( !str || !*str )
return &str_empty[0];
if ( str >= string_space && str < top_string )
return (char *) str;
#ifdef STRING_FREELIST
len = strlen(str)+1;
for ( size = 0; size < MAX_SIZE_LIST; size++ )
if ( len < sizelist[size] )
break;
if ( size < MAX_SIZE_LIST )
{
if ( text_free[size] != NULL )
{
struct text_data *tdf = text_free[size];
text_free[size] = tdf->next;
str_new = tdf->text;
tdf->next = tdf_free;
tdf_free = tdf;
}
else
str_new = getmem( sizelist[size] );
}
else
str_new = getmem( len );
#else
str_new = getmem( strlen(str) + 1 );
#endif
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 )
{
#ifdef STRING_FREELIST
sh_int size;
int len;
#endif
if ( pstr == NULL
|| pstr == &str_empty[0]
|| ( pstr >= string_space && pstr < top_string ) )
return;
#ifdef STRING_FREELIST
len = strlen(pstr)+1;
for ( size = 0; size < MAX_SIZE_LIST; size++ )
if ( len < sizelist[size] )
break;
if ( size < MAX_SIZE_LIST )
{
struct text_data *tdf;
if ( tdf_free )
{
tdf = tdf_free;
tdf_free = tdf->next;
}
else
tdf = getmem(sizeof(*tdf));
tdf->text = pstr;
tdf->next = text_free[size];
text_free[size] = tdf;
}
else
dispose( pstr, len );
#else
dispose( pstr, strlen(pstr)+1 );
#endif
return;
}
#endif
void do_areas( CHAR_DATA *ch, char *argument )
{
char buf[MAX_STRING_LENGTH];
char msg[MAX_STRING_LENGTH];
char arg1[MSL];
sh_int foo;
AREA_DATA *pArea;
bool fall = FALSE;
argument = one_argument( argument, arg1 );
if ( !str_cmp( arg1, "all" ) )
fall = TRUE;
sprintf( buf,
"@@W" mudnamecolor " AREA LISTING\n\r" );
safe_strcat( MAX_STRING_LENGTH, buf,
"+-------+------------+------------------------------------------------+\n\r" );
safe_strcat( MAX_STRING_LENGTH, buf,
"| @@yLevel@@W | | |\n\r" );
safe_strcat( MAX_STRING_LENGTH, buf,
"| @@yrange@@W | @@yAuthor@@W | @@yName of Area@@W |\n\r" );
safe_strcat( MAX_STRING_LENGTH, buf,
"+-------+------------+------------------------------------------------+\n\r" );
foo = 0;
for ( pArea = first_area; pArea != NULL; pArea = pArea->next )
{
if ( ( IS_SET( pArea->flags, AREA_NOSHOW ) )
|| ( IS_SET( pArea->flags, AREA_BUILDING ) ) )
continue; /* for non-finished areas - don't show */
if ( ( !fall )
&& ( ( pArea->min_level > ( get_psuedo_level( ch ) ) )
|| ( pArea->max_level < ( get_psuedo_level( ch ) ) ) ) )
continue;
foo++;
sprintf( msg, " %s %12s %s\n\r",
pArea->level_label,
capitalize( pArea->owner ),
pArea->name);
safe_strcat( MAX_STRING_LENGTH, buf, msg );
}
sprintf( msg, "@@R%d Areas listed.\n\r@@N Type areas all to list the entire "
mudnamecolor " realm.\n\r@@N", foo );
safe_strcat( MAX_STRING_LENGTH, buf, msg );
send_to_char( buf, ch );
return;
}
void perm_update( )
{
/* output perm usage to log file */
FILE *po;
char *strtime;
po = fopen( "perm.out", "a" );
strtime = ctime( ¤t_time );
strtime[strlen(strtime)-1] = '\0';
fprintf( po, "%s :: Perms %5d blocks of %7d bytes.\n\r",
strtime, nAllocPerm, sAllocPerm );
fclose( po );
return;
}
void do_memory( CHAR_DATA *ch, char *argument )
{
char buf[MAX_STRING_LENGTH];
if (!str_cmp(argument, "defrag"))
{
send_to_char("Defragmenting SSM heap.", ch);
logf("SSM: %s called defrag_heap.", ch->name);
defrag_heap();
return;
}
if (!str_cmp(argument, "log"))
{
if (get_trust(ch) < MAX_LEVEL)
{
send_to_char("Not at your level.\n\r", ch);
return;
}
if (mem_log)
{
mem_log=FALSE;
send_to_char("Memory logging is now OFF.\n\r", ch);
logf("%s turned off memory logging", ch->name);
return;
}
else
{
mem_log=TRUE;
send_to_char("Memory logging is now ON.. remember to turn it off!\n\r",
ch);
logf("%s turned on memory logging", ch->name);
return;
}
}
sprintf( buf, "Affects %5d\n\r", top_affect ); send_to_char( buf, ch );
sprintf( buf, "Areas %5d\n\r", top_area ); send_to_char( buf, ch );
sprintf( buf, "ExDes %5d\n\r", top_ed ); send_to_char( buf, ch );
sprintf( buf, "Exits %5d\n\r", top_exit ); send_to_char( buf, ch );
sprintf( buf, "Helps %5d\n\r", top_help ); send_to_char( buf, ch );
sprintf( buf, "Mobs %5d\n\r", top_mob_index ); send_to_char( buf, ch );
sprintf( buf, "Objs %5d\n\r", top_obj_index ); send_to_char( buf, ch );
sprintf( buf, "Resets %5d\n\r", top_reset ); send_to_char( buf, ch );
sprintf( buf, "Rooms %5d\n\r", top_room ); send_to_char( buf, ch );
sprintf( buf, "Shops %5d\n\r", top_shop ); send_to_char( buf, ch );
#if 0
sprintf( buf, "Strings %5d strings of %7d bytes (max %d).\n\r",
nAllocString, sAllocString, MAX_STRING );
#endif
sprintf(buf, "Shared String Info:\n\r");
send_to_char(buf, ch);
sprintf(buf, "Strings %5ld strings of %7ld bytes (max %ld).\n\r",
nAllocString, sAllocString, MAX_STRING);
send_to_char(buf, ch);
sprintf(buf, "Overflow Strings %5ld strings of %7ld bytes.\n\r",
nOverFlowString, sOverFlowString);
send_to_char(buf, ch);
if (Full)
{
send_to_char("Shared String Heap is full, increase MAX_STRING.\n\r", ch);
sprintf(buf, "Overflow high-water-mark is %ld bytes.\n\r",
hwOverFlow);
send_to_char(buf, ch);
}
sprintf( buf, "Perms %5d blocks of %7d bytes.\n\r",
nAllocPerm, sAllocPerm );
send_to_char( buf, ch );
return;
}
void do_status( CHAR_DATA *ch, char *argument )
{
char buf[MAX_STRING_LENGTH];
send_to_char( " Status Report for Ack! Mud:\n\r", ch );
send_to_char( " ---------------------------\n\r\n\r", ch );
do_time( ch, "" );
send_to_char( "\n\r", ch );
send_to_char( "The following counts are for *distinct* mobs/objs/rooms, not a count\n\r" , ch);
send_to_char( "of how many are actually in the game at this time.\n\r", ch );
send_to_char( "NB. Areas count will include areas used as help files.\n\r\n\r", ch );
sprintf( buf, "Areas %5d\n\r", top_area ); send_to_char( buf, ch );
sprintf( buf, "Helps %5d\n\r", top_help ); send_to_char( buf, ch );
sprintf( buf, "Mobs %5d\n\r", top_mob_index ); send_to_char( buf, ch );
sprintf( buf, "Objs %5d\n\r", top_obj_index ); send_to_char( buf, ch );
sprintf( buf, "Rooms %5d\n\r", top_room ); send_to_char( buf, ch );
return;
}
/*
* Stick a little fuzz on a number.
*/
int number_fuzzy( int number )
{
switch ( number_bits( 2 ) )
{
case 0: number -= 1; break;
case 3: number += 1; break;
}
return UMAX( 1, number );
}
/*
* Generate a random number.
*/
int number_range( int from, int to )
{
int power;
int number;
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) ) > 5 )
;
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
*/
static int rgiState[2+55];
void init_mm( )
{
int *piState;
int iState;
piState = &rgiState[2];
piState[-2] = 55 - 55;
piState[-1] = 55 - 24;
piState[0] = ((int) current_time) & ((1 << 30) - 1);
piState[1] = 1;
for ( iState = 2; iState < 55; iState++ )
{
piState[iState] = (piState[iState-1] + piState[iState-2])
& ((1 << 30) - 1);
}
return;
}
int number_mm( void )
{
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;
}
/*
* 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 )
{
int count = 0;
bool notrunc = FALSE;
if ( astr == NULL )
{
/* bug( "Str_cmp: null astr.", 0 ); */
return TRUE;
}
if ( bstr == NULL )
{
/* bug( "Str_cmp: null bstr.", 0 ); */
return TRUE;
}
if ( *astr == '^' )
{
notrunc = TRUE;
astr++;
}
if ( *bstr == '^' )
{
notrunc = TRUE;
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 ( !notrunc )
if ( *astr == '*' && count )
return FALSE;
if ( LOWER(*astr) != LOWER(*bstr) )
return TRUE;
count++;
}
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 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 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;
}
/*
* Append a string to a file.
*/
void append_file( CHAR_DATA *ch, char *file, char *str )
{
FILE *fp;
if ( IS_NPC(ch) || str[0] == '\0' )
return;
fclose( fpReserve );
if ( ( fp = fopen( file, "a" ) ) == NULL )
{
perror( file );
send_to_char( "Could not open the file!\n\r", ch );
}
else
{
fprintf( fp, "[%5d] %s: %s\n",
ch->in_room ? ch->in_room->vnum : 0, ch->name, str );
fclose( fp );
}
fpReserve = fopen( NULL_FILE, "r" );
return;
}
/*
* Nice little functions that limit the amount of typing you have to do with
* each and every log File entry and bug report.---Flar
*/
void bugf (char * fmt, ...)
{
char buf [MSL];
va_list args;
va_start (args, fmt);
vsnprintf (buf, sizeof(buf), fmt, args);
va_end (args);
bug (buf, 0);
}
void logf (char * fmt, ...)
{
char buf [2*MSL];
va_list args;
va_start (args, fmt);
vsnprintf (buf, sizeof(buf), fmt, args);
va_end (args);
log_string (buf);
}
/*
* Reports a bug.
*/
void bug( const char *str, int param )
{
char buf[MAX_STRING_LENGTH];
FILE *fp;
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 );
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 );
fclose( fpReserve );
if ( ( fp = fopen( BUG_FILE, "a" ) ) != NULL )
{
fprintf( fp, "%s\n", buf );
fclose( fp );
}
fpReserve = fopen( NULL_FILE, "r" );
return;
}
void bug_string( const char *str, const char *str2)
{
char buf[MAX_STRING_LENGTH];
FILE *fp;
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 );
if ( ( fp = fopen( "shutdown.txt", "a" ) ) != NULL )
{
fprintf( fp, "[*****] %s\n", buf );
fclose( fp );
}
}
strcpy( buf, "[*****] BUG: " );
sprintf( buf + strlen(buf), str, str2 );
log_string( buf );
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 )
{
char *strtime;
strtime = ctime( ¤t_time );
strtime[strlen(strtime)-1] = '\0';
fprintf( stderr, "%s :: %s\n", strtime, 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;
}
/*
* MOBprogram code block
*/
/* the functions */
/* This routine transfers between alpha and numeric forms of the
* mob_prog bitvector types. This allows the use of the words in the
* mob/script files.
*/
int mprog_name_to_type (name) char* name;
{
if (!str_cmp(name,"in_file_prog")) return IN_FILE_PROG;
if (!str_cmp(name,"act_prog")) return ACT_PROG;
if (!str_cmp(name,"speech_prog")) return SPEECH_PROG;
if (!str_cmp(name,"rand_prog")) return RAND_PROG;
if (!str_cmp(name,"fight_prog")) return FIGHT_PROG;
if (!str_cmp(name,"hitprcnt_prog")) return HITPRCNT_PROG;
if (!str_cmp(name,"death_prog")) return DEATH_PROG;
if (!str_cmp(name,"entry_prog")) return ENTRY_PROG;
if (!str_cmp(name,"greet_prog")) return GREET_PROG;
if (!str_cmp(name,"all_greet_prog")) return ALL_GREET_PROG;
if (!str_cmp(name,"give_prog")) return GIVE_PROG;
if (!str_cmp(name,"bribe_prog")) return BRIBE_PROG;
return(ERROR_PROG);
}
/* Had to redo mobprog loading to work with double linked lists. -- Altrag */
void mprog_file_read(char *f, MOB_INDEX_DATA *pMobIndex)
{
MPROG_DATA *mprog;
FILE *fp;
char letter;
char name[128];
char *permf;
int type;
sprintf(name, "%s%s", MOB_DIR, f);
if ( !(fp = fopen(name, "r")) )
{
bug("Mob: %d couldn't opne mobprog file.", pMobIndex->vnum);
return;
}
permf = str_dup(f);
for ( ; ; )
{
if ( (letter = fread_letter(fp)) == '|' )
break;
else if ( letter != '>' )
{
bug("Mprog_file_read: Invalid letter mob %d.", pMobIndex->vnum);
return;
}
switch( (type = fread_number(fp)) )
{
case ERROR_PROG:
bug("Mob %d: in file prog error.", pMobIndex->vnum);
return;
case IN_FILE_PROG:
bug("Mob %d: nested in file progs.", pMobIndex->vnum);
return;
default:
SET_BIT(pMobIndex->progtypes, type);
GET_FREE(mprog, mprog_free);
mprog->type = type;
mprog->arglist = fread_string(fp);
fread_to_eol(fp);
mprog->comlist = fread_string(fp);
fread_to_eol(fp);
mprog->filename = permf;
break;
}
}
fclose(fp);
return;
}
void load_mobprogs(FILE *fp)
{
char letter;
MOB_INDEX_DATA *iMob;
int value;
for ( ; ; )
switch ( LOWER(letter = fread_letter(fp)) )
{
default:
bug("Load_mobprogs: bad command '%c'.", letter);
fread_to_eol(fp);
break;
case 's':
fread_to_eol(fp);
return;
case '*':
fread_to_eol(fp);
break;
case 'm':
value = fread_number(fp);
if ( !(iMob = get_mob_index(value)) )
{
bug( "Load_mobprogs: vnum %d doesn't exist.", value );
fread_to_eol(fp);
break;
}
mprog_file_read(fread_word(fp), iMob);
fread_to_eol(fp);
break;
}
return;
}
void mprog_read_programs( FILE *fp, MOB_INDEX_DATA *pMobIndex )
{
MPROG_DATA *mprog;
char letter;
int type;
for ( ; ; )
{
if ( (letter = fread_letter(fp)) == '|' )
break;
else if ( letter != '>' )
{
bug( "Load_mobiles: vnum %d MOBPROG char", pMobIndex->vnum );
ungetc(letter, fp);
return;
}
type = mprog_name_to_type(fread_word(fp));
switch(type)
{
case ERROR_PROG:
bug( "Load_mobiles: vnum %d MOBPROG type.", pMobIndex->vnum );
fread_to_eol(fp);
return;
case IN_FILE_PROG:
mprog_file_read(fread_string(fp), pMobIndex);
fread_to_eol(fp);
break;
default:
SET_BIT(pMobIndex->progtypes, type);
GET_FREE(mprog, mprog_free);
mprog->type = type;
mprog->arglist = fread_string(fp);
fread_to_eol(fp);
mprog->comlist = fread_string(fp);
fread_to_eol(fp);
LINK(mprog, pMobIndex->first_mprog, pMobIndex->last_mprog, next, prev);
break;
}
}
return;
}
void safe_strcat(int max_len,char * dest,char * source)
{
int a;
char c;
char * orig_dest;
char * orig_source;
if (dest == NULL && source == NULL)
return;
if (dest == NULL)
{
fprintf(stderr,"safe_strcat: Null dest string for source : %s\n",source);
return;
}
if (source == NULL)
{
fprintf(stderr,"safe_strcat: NULL source for dest : %s\n",dest);
return;
}
orig_dest=dest;
orig_source=source;
while (*dest !='\0') /* Check to see if dest is already over limit. */
dest++;
a=dest-orig_dest;
if ( a > max_len )
{
fprintf(stderr,"WARNING: dest string already too long:\nsource: %s\ndest: %s\n",source,orig_dest);
return;
}
if ( a == max_len )
{
fprintf(stderr,"safe_strcat: string too long, source is : %s\n",orig_source);
return;
}
while ( (c = *(source++)) != 0 )
{
*(dest++)=c;
a++;
if ( a == max_len )
{
*(--dest)='\0';
fprintf(stderr,"safe_strcat: string too long, source is : %s\n",orig_source);
return;
}
}
*dest='\0';
return;
}
void message_update( void )
{
RESET_DATA *pReset;
AREA_DATA *pArea;
ROOM_INDEX_DATA *pRoom;
CHAR_DATA *ch;
for ( pArea = first_area; pArea != NULL; pArea = pArea->next )
{
for ( pReset = pArea->first_reset; pReset != NULL; pReset = pReset->next )
{
if ( pReset->command != 'A' )
continue;
if ( ( pRoom = get_room_index( pReset->arg1 ) ) == NULL )
{
bug( "message_update, no room %d found.", pReset->arg1 );
continue;
}
for ( ch=pRoom->first_person; ch != NULL; ch = ch->next_in_room )
if ( ch->level >= pReset->arg2 && ch->level <= pReset->arg3 )
send_to_char( pReset->notes, ch );
}
}
return;
}