/*------------------------------------------------------------------------\
| db.c : Database Module www.yourmud.org |
| Copyright (C) 2006, Project Argila: Auroness |
| |
| All rights reserved. See Licensing documents included. |
| |
| Based upon Shadows of Isildur RPI Engine |
| Copyright C. W. McHenry [Traithe], 2004 |
| Derived under license from DIKU GAMMA (0.0). |
\------------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <memory.h>
#include <sys/types.h>
#include <sys/time.h>
#include <mysql/mysql.h>
#include <signal.h>
#include "structs.h"
#include "protos.h"
#include "utils.h"
#include "decl.h"
/**************************************************************************
* declarations of most of the 'global' variables *
************************************************************************ */
void schar(CHAR_DATA *ch);
struct strel {
int count;
char *stp;
char *next;
};
struct strel *sht;
int MAX_MEMORY;
int PERM_MEMORY_SIZE;
int MAX_OVERHEAD;
int mob_start_stat = 12;
int run_mult = 10000;
int loud_log = 0;
int mem_allocated = 0;
int mem_freed = 0;
ROOM_DATA *wld_tab [ZONE_SIZE];
OBJ_DATA *obj_tab [ZONE_SIZE];
CHAR_DATA *mob_tab [ZONE_SIZE];
ACCOUNT_DATA *account_list = NULL;
ROLE_DATA *role_list = NULL;
OBJ_DATA *object_list = NULL;
CHAR_DATA *character_list = NULL;
CHAR_DATA *full_mobile_list = NULL;
ROOM_DATA *full_room_list = NULL;
OBJ_DATA *full_object_list = NULL;
MOBPROG_DATA *full_prog_list = NULL;
AFFECTED_TYPE *world_affects = NULL;
BOARD_DATA *full_board_list = NULL;
SECOND_AFFECT *second_affect_list = NULL;
COMBAT_MSG_DATA *cm_list = NULL;
CHAR_DATA *loaded_list = NULL;
QE_DATA *quarter_event_list = NULL;
COMMON_DATA *common_list = NULL;
NEWBIE_HINT *hint_list = NULL;
RANDOM_CH_DATA *random_char_list = NULL;
HELP_DATA *help_list = NULL;
HELP_DATA *bhelp_list = NULL;
TEXT_DATA *text_list = NULL;
TEXT_DATA *document_list = NULL;
CHAR_DATA *free_char_list = NULL;
OBJ_DATA *free_obj_list = NULL;
RECIPE_DATA *recipe_list = NULL;
SUBCRAFT_HEAD_DATA *crafts = NULL;
NAME_SWITCH_DATA *clan_name_switch_list = NULL;
CLAN_DATA *clan_list = NULL;
SITE_INFO *banned_site;
int booting = 1;
int hash_len;
int hash_val;
int knockout; /* Cleanup dead pcs */
char *use_memory_base = NULL;
char *use_memory_top = NULL;
char *use_memory_next = NULL;
char *overhead_base = NULL;
char *overhead_top = NULL;
char *overhead_next = NULL;
char *perm_memory = NULL;
char *perm_memory_top = NULL;
char *perm_memory_next = NULL;
struct hash_data *hash_buckets [NUM_BUCKETS];
char *null_string;
char *emergency_data = NULL;
/* do_hour messes up time, so we keep track of how many times do_hour
was used, so we can make time adjustments. */
int times_do_hour_called = 0;
int next_mob_coldload_id = 0;
int next_pc_coldload_id = 0;/* get_next_pc_coldload_id () */
int next_obj_coldload_id = 0;
int count_max_online = 0;
int count_guest_online = 0;
char *max_online_date;
int MAX_ZONE = 100;
int second_affect_active = 0;
int hash_dup_strings = 0;
int hash_dup_length = 0;
int x1 = 0; /* Debugging variable */
int check_objects;
int check_characters;
long mud_time;
char *mud_time_str = NULL;
int mp_dirty = 0; /* 1 if mob programs need to be written out */
time_t next_hour_update; /* Mud hour pulse (15 min) */
time_t next_minute_update; /* RL minute (1 min) */
int pulse_violence = 8;
REGISTRY_DATA *registry [MAX_REGISTRY];
struct zone_data *zone_table;
int advance_hour_now = 0;
struct message_list fight_messages[MAX_MESSAGES];
extern char BOOT [24];
char BOOT [24];
FILE *fp_log;
FILE *imm_log;
FILE *guest_log;
FILE *sys_log;
struct time_info_data time_info;
struct weather_data weather_info [100];
/* local procedures */
void verify_exits (void);
void boot_zones(void);
void setup_dir(FILE *fl, ROOM_DATA *room, int dir, int type);
ROOM_DATA *allocate_room (int virtual);
char *file_to_string(char *name);
void reset_time(void);
void reload_hints(void);
int change;
int port;
bool Memory_check = FALSE;
/* external refs */
extern struct descriptor_data *descriptor_list;
extern struct msg_data *msg_list;
extern void load_messages(void);
extern void boot_social_messages(void);
ROOM_DATA *vtor (int virtual)
{
static ROOM_DATA *room = NULL;
static int shortcuts = 0;
static int longways = 0;
static int failures = 0;
/* Short cut...caller might want last used room */
if ( room && room->virtual == virtual ) {
shortcuts++;
return room;
}
if ( virtual < 0 )
return NULL;
for ( room = wld_tab [virtual % ZONE_SIZE]; room; room = room->hnext )
if ( room->virtual == virtual ) {
longways++;
return (room);
}
failures++;
return NULL;
}
void add_room_to_hash (ROOM_DATA *add_room)
{
int hash;
ROOM_DATA *troom;
static ROOM_DATA *last_room = NULL;
add_room->lnext = NULL;
if ( booting && last_room )
last_room->lnext = add_room;
else if ( !full_room_list )
full_room_list = add_room;
else {
troom = full_room_list;
while ( troom->lnext )
troom = troom->lnext;
troom->lnext = add_room;
}
last_room = add_room;
hash = add_room->virtual % ZONE_SIZE;
add_room->hnext = wld_tab [hash];
wld_tab [hash] = add_room;
}
CHAR_DATA *vtom (int virtual)
{
CHAR_DATA *mob;
if ( virtual < 0 )
return NULL;
for (mob = mob_tab [virtual % ZONE_SIZE]; mob; mob = mob->mob->hnext)
if ( mob->mob->virtual == virtual )
return (mob);
return NULL;
}
void add_mob_to_hash (CHAR_DATA *add_mob)
{
int hash;
CHAR_DATA *tmob;
static CHAR_DATA *last_mob = NULL;
add_mob->mob->lnext = NULL;
if ( booting && last_mob )
last_mob->mob->lnext = add_mob;
else if ( !full_mobile_list )
full_mobile_list = add_mob;
else {
tmob = full_mobile_list;
while ( tmob->mob->lnext )
tmob = tmob->mob->lnext;
tmob->mob->lnext = add_mob;
}
last_mob = add_mob;
hash = add_mob->mob->virtual % ZONE_SIZE;
add_mob->mob->hnext = mob_tab [hash];
mob_tab [hash] = add_mob;
}
OBJ_DATA *vtoo (int virtual)
{
OBJ_DATA *obj;
if ( virtual < 0 )
return NULL;
for (obj = obj_tab [virtual % ZONE_SIZE]; obj; obj = obj->hnext)
if ( obj->virtual == virtual )
return (obj);
return NULL;
}
void add_obj_to_hash (OBJ_DATA *add_obj)
{
int hash;
OBJ_DATA *tobj;
static OBJ_DATA *last_obj = NULL;
add_obj->lnext = NULL;
if ( booting && last_obj )
last_obj->lnext = add_obj;
else if ( !full_object_list )
full_object_list = add_obj;
else {
tobj = full_object_list;
while ( tobj->lnext )
tobj = tobj->lnext;
tobj->lnext = add_obj;
}
last_obj = add_obj;
hash = add_obj->virtual % ZONE_SIZE;
add_obj->hnext = obj_tab [hash];
obj_tab [hash] = add_obj;
}
/*************************************************************************
* routines for booting the system *
*********************************************************************** */
void boot_db (void)
{
int i;
char buf [MAX_STRING_LENGTH];
/* get the name of the person who rebooted */
mm ("in boot_db");
mud_time = time (NULL);
mob_start_stat = 12;
MAX_MEMORY = 12000000;
PERM_MEMORY_SIZE = 2900000;
MAX_OVERHEAD = 1000000;
system_log ("Initializing read-only memory.", FALSE);
init_memory ();
mm ("post init_memory");
system_log("Beginning database initialization.", FALSE);
system_log("Initialising registry.", FALSE);
setup_registry ();
mm ("post setup_registry");
system_log("Loading dynamic registry.", FALSE);
load_clan_registry ();
mm ("post clan_registry");
system_log("Reloading banned site list.", FALSE);
reload_sitebans();
system_log("Loading special chargen roles.", FALSE);
reload_roles();
system_log ("Loading newbie hints.", FALSE);
reload_hints();
system_log ("Reading external text files.", FALSE);
(void)add_text (&text_list, WIZLIST_FILE, "wizlist");
(void)add_text (&text_list, NEWS_FILE, "news");
(void)add_text (&text_list, GREET_FILE, "greetings");
(void)add_text (&text_list, MAINTENANCE_FILE, "greetings.maintenance");
(void)add_text (&text_list, MENU1_FILE, "menu1");
(void)add_text (&text_list, QSTAT_FILE, "qstat_message");
(void)add_text (&text_list, ACCT_APP_FILE, "account_application");
(void)add_text (&text_list, ACCT_REF_FILE, "account_referral");
(void)add_text (&text_list, ACCT_EMAIL_FILE, "account_email");
(void)add_text (&text_list, ACCT_POLICIES_FILE, "account_policies");
(void)add_text (&text_list, THANK_YOU_FILE, "thankyou");
(void)add_text (&text_list, RACE_SELECT, "race_select");
(void)add_text (&text_list, ROLE_SELECT, "role_select");
(void)add_text (&text_list, SPECIAL_ROLE_SELECT, "special_role_select");
(void)add_text (&text_list, SEX_SELECT, "sex_select");
(void)add_text (&text_list, AGE_SELECT, "age_select");
(void)add_text (&text_list, PLDESC_FILE, "help_pldesc");
(void)add_text (&text_list, PSDESC_FILE, "help_psdesc");
(void)add_text (&text_list, PDESC_FILE, "help_pdesc");
(void)add_text (&text_list, NAME_FILE, "help_name");
(void)add_text (&text_list, PKEYWORDS_FILE, "help_pkeywords");
(void)add_text (&text_list, HEIGHT_FRAME, "height_frame");
(void)add_text (&text_list, LOCATION, "location");
(void)add_text (&text_list, COMMENT_HELP, "comment_help");
(void)add_text (&text_list, SKILL_SELECT, "skill_select");
(void)add_text (&text_list, PROFESSION_SELECT, "professions");
mm ("post file_to_string of files");
system_log("Loading zone table.", FALSE);
boot_zones();
system_log ("Initializing dynamic weather zones.", FALSE);
initialize_weather_zones();
mm ("post boot_zones");
system_log("Resetting the game time:", FALSE);
reset_time();
mm ("post reset_time");
system_log("Loading rooms.", FALSE);
load_rooms();
mm ("post load_rooms");
system_log("Generating hash table for mobile files.", FALSE);
boot_mobiles ();
mm ("post boot_mobiles");
system_log("Generating hash table for object files.", FALSE);
boot_objects();
mm ("post boot_objects");
system_log("Loading craft information.", FALSE);
boot_crafts ();
mm ("post boot_crafts");
system_log("Load mobile triggers (mobprogs).", FALSE);
boot_mobprogs ();
mm ("post boot_mobprogs");
system_log("Loading fight messages.", FALSE);
load_messages();
mm ("post load_messages");
system_log("Loading social messages.", FALSE);
boot_social_messages();
mm ("post boot_social_messages");
system_log ("Reading online record.", FALSE);
load_online_stats();
booting = 0;
system_log ("Reloading persistent tracks.", FALSE);
load_tracks();
if ( port == PLAYER_PORT ) {
system_log ("Loading persistent mobiles...", FALSE);
load_stayput_mobiles();
system_log ("Stocking any new deliveries set since last reboot...", FALSE);
stock_new_deliveries();
}
mm ("post load_save_rooms");
mem_free (overhead_base);
mm ("freed overhead_base");
/******* Never used Is it really needed *******/
emergency_data = malloc (20000);
mm ("Allocated emergency_data");
/***********************************************/
for (i = 0; i < MAX_ZONE; i++)
{
if ( !zone_table [i].cmd )
continue;
if ( port != BUILDER_PORT )
REMOVE_BIT (zone_table [i].flags, Z_FROZEN);
if ( strncmp (zone_table [i].name, "Empty Zone", 10) ) {
snprintf (buf, MAX_STRING_LENGTH, "Performing boot-time reset of %s: %d.", zone_table [i].name, i);
system_log (buf, FALSE);
}
reset_zone (i);
snprintf (buf, MAX_STRING_LENGTH, "loaded zone %d", i);
mm (buf);
}
print_mem_stats (NULL);
system_log ("Boot db -- DONE.", FALSE);
}
void reload_hints(void)
{
NEWBIE_HINT *hint, *thint;
FILE *fp;
char *string;
char buf [MAX_STRING_LENGTH];
hint_list = NULL;
if ( !(fp = fopen("/text/hints", "r")) )
return;
(void)fgets (buf, 256, fp);
while ( 1 ) {
string = fread_string (fp);
if ( !string || !*string )
break;
CREATE (hint, NEWBIE_HINT, 1);
hint->hint = string;
if ( !hint_list )
hint_list = hint;
else {
thint = hint_list;
while ( thint->next )
thint = thint->next;
thint->next = hint;
}
}
fclose (fp);
}
void create_guest_avatar (DESCRIPTOR_DATA *d)
{
CHAR_DATA *ch = NULL, *tch = NULL;
char buf [MAX_STRING_LENGTH];
char buf2 [MAX_STRING_LENGTH];
char account [MAX_STRING_LENGTH];
char tname_buf [MAX_STRING_LENGTH];
char *ipbuf = NULL;
int i = 1;
*buf = '\0';
*buf2 = '\0';
*account = '\0';
*tname_buf = '\0';
if ( !d )
return;
snprintf (account, MAX_STRING_LENGTH, "Guest");
/*
* If we aren't recreating for an already-defined guest handle, find a new
* one either based on matching the IP to an account or counting the number
* of anonymous guests already in-game.
*
* If it's an unidentified guest login, attach the generic "Guest"
* account; otherwise, load up the player's account found for the IP.
*/
if ( !reference_ip (NULL, d->host) | (d->parm == 1)){
for ( tch = character_list; tch; tch = tch->next ) {
if ( tch->deleted )
continue;
if ( !tch->tname )
continue;
if ( strstr (tch->tname, "Special Guest") )
i++;
}
snprintf (account, 6, "Guest");
snprintf (tname_buf, MAX_STRING_LENGTH, "Special Guest %d", i);
}
else {
ipbuf = reference_ip (NULL, d->host);
snprintf (account, MAX_STRING_LENGTH, "%s", ipbuf);
snprintf (tname_buf, MAX_STRING_LENGTH, "%s-Guest", account);
i = 0;
for ( tch = character_list; tch; tch = tch->next ) {
if ( tch->deleted )
continue;
if ( !tch->tname )
continue;
if ( strstr (tch->tname, tname_buf) )
i++;
}
if ( i >= 1 )
snprintf (tname_buf + strlen(tname_buf), MAX_STRING_LENGTH, "%d", i);
}
/** create the guest character description **/
d->account = load_account (account);
d->character = new_char(1);
clear_char (d->character);
d->original = NULL;
ch = d->character;
d->character->pc->create_state = STATE_APPROVED;
d->prompt_mode = 1;
d->character->desc = d;
d->character->pc->owner = d;
d->character->pc->load_count = 1;
ch->race = RACE_HUMAN;
d->character->race = ch->race;
/* Bestow the random traits to the new guest avatar */
randomize_mobile(ch);
if ( ch->pc->account && strlen(ch->pc->account) > 1 )
mem_free (ch->pc->account);
ch->pc->account = str_dup (account);
ch->fight_mode = 2;
ch->clans = add_hash("");
/* Address naming issues with our user's new account handle */
ch->tname = add_hash(tname_buf);
snprintf (buf2, MAX_STRING_LENGTH, "%s %s", ch->name, ch->tname);
if ( ch->name )
mem_free (ch->name);
ch->name = add_hash(buf2);
ch->hit = 100;
ch->max_hit = 100;
ch->move = 100;
ch->max_move = 100;
SET_BIT (d->character->flags, FLAG_GUEST);
if ( d->character->race >= 0 && d->character->race <= 29 ) {
for ( i = 0; i <= MAX_SKILLS; i++ ) {
d->character->skills[i] = 0;
d->character->pc->skills[i] = 0;
}
d->character->speaks =
db_race_table[d->character->race].race_speaks;
d->character->skills [d->character->speaks] =
calc_lookup(d->character, REG_CAP,
db_race_table[d->character->race].race_speaks);
d->character->pc->skills [d->character->speaks] =
calc_lookup(d->character, REG_CAP,
db_race_table[d->character->race].race_speaks);
}
guest_conns++;
if ( ch->description )
mem_free (ch->description);
ch->description = str_dup("Another Guest is here, passing through. Be sure to welcome them!\n");
SET_BIT (ch->plr_flags, NEWBIE_HINTS);
ch->hunger = -1;
ch->thirst = -1;
}
void stock_new_deliveries(void)
{
CHAR_DATA *tch = NULL;
OBJ_DATA *obj = NULL;
ROOM_DATA *room = NULL;
int i = 0;
if ( port != PLAYER_PORT )
return;
for ( tch = character_list; tch; tch = tch->next ) {
if ( tch->deleted )
continue;
if ( !IS_NPC (tch) || !IS_SET (tch->flags, FLAG_KEEPER) || !tch->shop )
continue;
room = vtor (tch->shop->store_vnum);
if ( !room )
continue;
if ( !room->psave_loaded )
load_save_room (room);
for ( i = 0; i < MAX_TRADES_IN; i++ ) {
if ( !get_obj_in_list_num (tch->shop->delivery[i], room->contents) ) {
obj = load_object (tch->shop->delivery[i]);
obj_to_room (obj, room->virtual);
}
}
}
system_log ("New shopkeeper deliveries stocked.", FALSE);
return;
}
void copyover_recovery (void)
{
ROOM_DATA *room = NULL;
MYSQL_RES *result = NULL;
MYSQL_ROW row;
DESCRIPTOR_DATA *d = NULL;
DESCRIPTOR_DATA *td = NULL;
FILE *fp = NULL;
OBJ_DATA *obj = NULL;
AFFECTED_TYPE *af = NULL;
char name [MAX_STRING_LENGTH];
char table_name [MAX_STRING_LENGTH];
char host [MAX_STRING_LENGTH];
char account [MAX_STRING_LENGTH];
char buf [MAX_STRING_LENGTH];
int desc = 0;
int online = 0;
int guest = 0;
int dcheck = 0;
int chkdirect = 0;
int i = 0;
int conn = 0;
int pos = 0;
int count = 0;
char *temp_arg = NULL;
system_log("Soft reboot recovery sequence initiated.", FALSE);
if ( !(fp = fopen (".copyover_data", "r")) ) {
system_log("Copyover file not found! Aborting copyover and shutting down.", TRUE);
abort();
}
descriptor_list = NULL;
for ( ; ; )
{
conn = 0;
fscanf (fp, "%d %s %s %s %d %d", &desc, host, account, name, &pos, &count);
if ( desc == -1 ) {
break;
}
CREATE (d, DESCRIPTOR_DATA, 1);
memset ((char *)d, 0, sizeof (struct descriptor_data));
init_descriptor (d, desc);
/* descriptor_list = d; */
if ( !descriptor_list )
descriptor_list = d;
else for ( td = descriptor_list; td; td = td->next ) {
if ( !td->next ) {
d->next = NULL;
td->next = d;
break;
}
}
if ( d->descriptor > maxdesc )
maxdesc = d->descriptor;
/*
d->character = new_char(1);
clear_char (d->character);
*/
d->host = add_hash(host);
if ( !strstr (name, "Guest") )
d->character = load_pc (name);
else
nanny_create_guest (d, "recreate");
if ( !d->character )
continue;
d->character->desc = d;
d->prompt_mode = 1;
d->connected = -15;
d->character->pc->owner = d;
d->character->pc->last_connect = time(0);
if ( !IS_SET (d->character->flags, FLAG_GUEST) ) {
d->account = load_account (account);
}
if ( !IS_SET (d->character->flags, FLAG_GUEST) && d->account && d->account->color )
d->character->color++;
if ( IS_SET (d->character->flags, FLAG_GUEST) )
d->character->color++;
REMOVE_BIT (d->character->flags, FLAG_ENTERING);
REMOVE_BIT (d->character->flags, FLAG_LEAVING);
pc_to_game (d->character);
if ( !IS_SET (d->character->flags, FLAG_GUEST) ) {
load_char_objs (d->character, GET_NAME(d->character));
if ( !d->character->in_room || d->character->in_room == NOWHERE )
char_to_room (d->character, OOC_LOUNGE);
else
char_to_room (d->character, d->character->in_room);
snprintf (buf, MAX_STRING_LENGTH, "save/player/%c/%s.a", LOWER (*GET_NAME(d->character)), CAP (GET_NAME(d->character)));
if ( !IS_SET (d->character->flags, FLAG_GUEST) )
(void)load_saved_mobiles (d->character, buf);
}
online = 0;
guest = 0;
for ( td = descriptor_list; td; td = td->next ) {
if ( !td->character )
continue;
if ( td->character->pc->level )
continue;
if ( td->character->pc->create_state != 2 )
continue;
if ( td->connected )
continue;
if ( IS_SET (td->character->flags, FLAG_GUEST) ) {
guest++;
}
if ( IS_MORTAL (td->character) && !IS_SET(td->character->flags, FLAG_GUEST) ) {
online++;
}
}
if ( online >= count_max_online ) {
count_max_online = online;
max_online_date = timestr(max_online_date);
}
if ( guest >= count_guest_online ) {
count_guest_online = guest;
}
d->character->pc->last_logon = time(0);
temp_arg = fread_string(fp);
snprintf (table_name, MAX_STRING_LENGTH, "%s", temp_arg);
if ( str_cmp (table_name, "none") ) {
i = 0;
for ( obj = d->character->room->contents; obj; obj = obj->next_content ) {
if ( !str_cmp (table_name, obj->name) ) {
i++;
if ( i == count ) {
magic_add_affect (d->character, MAGIC_SIT_TABLE, -1, 0, 0, 0, 0);
af = get_affect (d->character, MAGIC_SIT_TABLE);
af->a.table.obj = obj;
break;
}
}
}
}
GET_POS (d->character) = pos;
d->connected = CON_PLYNG;
}
fclose(fp);
if ( port == PLAYER_PORT ) {
mysql_safe_query ("SELECT * FROM copyover_doors");
result = mysql_store_result (database);
if ( result && mysql_num_rows(result) ) {
while ( (row = mysql_fetch_row(result)) ) {
if ( !(room = vtor(strtol(row[0], NULL, 10))) )
continue;
if ( !room->dir_option [strtol(row[1], NULL, 10)] )
continue;
dcheck = strtol(row[2], NULL, 10);
chkdirect = strtol(row[1], NULL, 10);
if ( dcheck == 2 ) { /* closed and locked */
SET_BIT (room->dir_option[chkdirect]->exit_info, PASSAGE_CLOSED);
SET_BIT (room->dir_option[chkdirect]->exit_info, PASSAGE_LOCKED);
}
else if ( dcheck == 1 ) { /* closed and unlocked */
SET_BIT (room->dir_option[chkdirect]->exit_info, PASSAGE_CLOSED);
REMOVE_BIT (room->dir_option[chkdirect]->exit_info, PASSAGE_LOCKED);
}
else if ( dcheck == 0 ) { /* open and unlocked */
REMOVE_BIT (room->dir_option[chkdirect]->exit_info, PASSAGE_CLOSED);
REMOVE_BIT (room->dir_option[chkdirect]->exit_info, PASSAGE_LOCKED);
}
}
mysql_free_result (result);
}
mysql_safe_query ("DELETE FROM copyover_doors");
}
}
void reset_time(void)
{
char buf[MAX_STRING_LENGTH];
/* long beginning_of_time = 14336715; */
/* Subtract this by 10800 seconds to advance gametime by 12 hours */
long beginning_of_time = 830615184 - 32743;
int qz[] = { 6, 6, 6, 6, 5, 5, 4, 4, 5, 6, 6, 7 };
int sun_up;
int i = 0;
struct time_info_data mud_time_passed(time_t t2, time_t t1);
next_hour_update = time (0) + ((time (0) - beginning_of_time) % 900);
next_minute_update = time (0);
time_info = mud_time_passed(time(0), beginning_of_time);
sun_up = qz [(int)time_info.month]; /* sunrise is easy */
snprintf (buf, MAX_STRING_LENGTH, " Current Gametime: %dH %dD %dM %dY.",
time_info.hour, time_info.day,
time_info.month, time_info.year);
system_log(buf, FALSE);
if ( time_info.month == 0 || time_info.month == 1 || time_info.month == 11 )
time_info.season = WINTER;
else if (time_info.month < 11 && time_info.month > 7)
time_info.season = AUTUMN;
else if (time_info.month < 8 && time_info.month > 4 )
time_info.season = SUMMER;
else time_info.season = SPRING;
for ( i = 0; i <= 99; i++ ) {
weather_info[i].trend = number(0,15);
weather_info[i].clouds = number(0,3);
if (time_info.season == SUMMER)
weather_info[i].clouds = number(0,1);
weather_info[i].fog = 0;
if ( weather_info[i].clouds > 0 )
weather_info[i].state = number(0,1);
weather_info[i].temperature = seasonal_temp[zone_table[i].weather_type][time_info.month];
weather_info[i].wind_speed = number(0,2);
if (time_info.hour >= sun_up && time_info.hour < sunset[time_info.month]) {
sun_light = 1;
weather_info[i].temperature += 15;
}
else
weather_info[i].temperature -= 15;
}
time_info.holiday = 0;
}
void create_room_zero (void)
{
ROOM_DATA *room;
room = allocate_room (0);
room->zone = 0;
room->name = str_dup ("Heaven");
room->description = str_dup ("You are in heaven.\n");
if ( str_cmp (zone_table [0].name, "Empty Zone") )
return;
zone_table [0].name = str_dup ("Heaven");
zone_table [0].top = 0;
zone_table [0].lifespan = 0;
zone_table [0].reset_mode = 0;
zone_table [0].flags = 0;
zone_table [0].jailer = 0;
zone_table [0].jail_room_num = 0;
zone_table [0].weather_type = 0;
SET_BIT (zone_table [0].flags, Z_FROZEN);
}
void load_rooms (void)
{
FILE *fl;
int zon, flag=0, tmp, sdir;
int virtual_nr;
char *temp, chk[50], errbuf[80], wfile[80];
struct extra_descr_data *new_descr;
struct written_descr_data *w_desc;
struct room_prog *r_prog;
struct secret *r_secret;
struct stat fstatus;
ROOM_DATA *room = NULL;
int i;
for (i = 0; i < ZONE_SIZE; i++) {
wld_tab [i] = NULL;
obj_tab [i] = NULL;
mob_tab [i] = NULL;
}
for (zon = 0; zon < MAX_ZONE; zon++) {
snprintf (wfile, MAX_STRING_LENGTH, "%s/rooms.%d", REGIONS, zon);
if ( stat (wfile, &fstatus) ) {
snprintf (errbuf, MAX_STRING_LENGTH, "Zone %d rooms did not load. Aborting.", zon);
system_log(errbuf, TRUE);
abort();
}
if ( fstatus.st_size == 0 ) {
snprintf (s_buf, MAX_STRING_LENGTH, "ERROR: Corrupt %d.wld :: aborting.",zon);
system_log(s_buf, TRUE);
abort();
}
if ( (fl = fopen (wfile, "r")) == NULL ) {
snprintf (errbuf, MAX_STRING_LENGTH, "Could not load rooms.%d. Aborting.", zon);
system_log(errbuf, TRUE);
abort();
}
do {
fscanf(fl, " #%d\n", &virtual_nr);
temp = fread_string(fl);
if ( !temp )
continue; /* KILLER CDR */
if ((flag=(*temp != '$'))) {
room = allocate_room (virtual_nr);
room->zone = zon;
room->name = temp;
room->description = fread_string(fl);
fscanf (fl, "%d", &tmp);
fscanf (fl, " %d ", &tmp);
room->room_flags = tmp;
/* The STORAGE bit is set when loading in shop keepers */
REMOVE_BIT (room->room_flags, STORAGE);
REMOVE_BIT (room->room_flags, PC_ENTERED);
SET_BIT (room->room_flags, SAVE);
fscanf (fl, " %d ", &tmp);
room->sector_type = tmp;
fscanf (fl, "%d\n", &tmp);
room->deity = tmp;
room->contents = 0;
room->people = 0;
room->light = 0;
for (tmp = 0; tmp <= 5; tmp++)
room->dir_option [tmp] = 0;
room->ex_description = 0;
room->wdesc = 0;
room->prg = 0;
for (tmp = 0; tmp <= 5; tmp++)
room->secrets [tmp] = 0;
for (;;) {
fscanf(fl, " %s \n", chk);
if (*chk == 'D') /* direction field */
setup_dir(fl, room, strtol(chk + 1, NULL, 10), 0);
else if (*chk == 'H') /* Secret (hidden) */
setup_dir(fl, room, strtol(chk + 1, NULL, 10), 1);
else if (*chk == 'T') /* Trapped door */
setup_dir(fl, room, strtol(chk + 1, NULL, 10), 2);
else if (*chk == 'B') /* Trapped hidden door */
setup_dir(fl, room, strtol(chk + 1, NULL, 10), 3);
else if(*chk == 'Q') { /* Secret search desc */
r_secret = get_perm (sizeof (struct secret));
sdir = strtol(chk+1, NULL, 10);
fscanf(fl,"%d\n",&tmp);
r_secret->diff=tmp;
r_secret->stext=fread_string(fl);
room->secrets[sdir]=r_secret;
}
else if (*chk == 'E') /* extra description field */
{
struct extra_descr_data *tmp_extra;
new_descr = get_perm (sizeof (struct extra_descr_data));
new_descr->keyword = fread_string(fl);
new_descr->description = fread_string(fl);
new_descr->next = NULL;
if ( !room->ex_description )
room->ex_description = new_descr;
else {
tmp_extra = room->ex_description;
while ( tmp_extra->next )
tmp_extra = tmp_extra->next;
tmp_extra->next = new_descr;
}
}
else if (*chk == 'W') {
w_desc = get_perm (sizeof (struct written_descr_data));
fscanf(fl,"%d\n",&tmp);
w_desc->language = tmp;
w_desc->description = fread_string(fl);
room->wdesc = w_desc;
}
else if (*chk == 'R'){
larg_setup_room_triggers(fl, room);
}
else if(*chk == 'P') {
struct room_prog *tmp_prg;
r_prog = get_perm (sizeof (struct room_prog));
r_prog->command=fread_string(fl);
r_prog->keys=fread_string(fl);
r_prog->prog=fread_string(fl);
r_prog->next = NULL;
/* Make sure that the room program is stored at
end of the list. This way when the room is
saved, the rprogs get saved in the same order
- Rassilon
*/
if ( !room->prg )
room->prg = r_prog;
else {
tmp_prg = room->prg;
while ( tmp_prg->next )
tmp_prg = tmp_prg->next;
tmp_prg->next = r_prog;
}
}
else if ( *chk == 'A' ) { /* Additional descriptions */
CREATE (room->extra, ROOM_EXTRA_DATA, 1);
for ( i = 0; i < WR_DESCRIPTIONS; i++ ) {
room->extra->weather_desc [i] = fread_string (fl);
if ( !strlen (room->extra->weather_desc [i]) )
room->extra->weather_desc [i] = NULL;
}
for ( i = 0; i < 6; i++ ) {
room->extra->alas [i] = fread_string (fl);
if ( !strlen (room->extra->alas [i]) )
room->extra->alas [i] = NULL;
}
}
else if (*chk == 'S') /* end of current room */
break;
}
}
} while (flag);
fclose (fl);
}
for ( i = 0; i < MAX_ZONE; i++ )
if ( zone_table [i].jail_room_num )
zone_table [i].jail_room = vtor (zone_table [i].jail_room_num);
if ( !vtor (0) )
create_room_zero ();
}
#define MAX_PREALLOC_ROOMS 14000
ROOM_DATA *get_room (void)
{
ROOM_DATA *room;
static ROOM_DATA *prealloc_rooms = NULL;
static int prealloc_rooms_count = 0;
if ( !prealloc_rooms )
CREATE (prealloc_rooms, ROOM_DATA, MAX_PREALLOC_ROOMS);
if ( prealloc_rooms_count >= MAX_PREALLOC_ROOMS )
CREATE (room, ROOM_DATA, 1);
else {
room = prealloc_rooms + prealloc_rooms_count;
prealloc_rooms_count++;
}
return room;
}
ROOM_DATA *allocate_room (int virtual)
{
ROOM_DATA *new_room;
char buf [MAX_STRING_LENGTH];
new_room = get_room ();
new_room->virtual = virtual;
new_room->psave_loaded = 0;
#define CHECK_DOUBLE_DEFS_ROOMS 0
#ifdef CHECK_DOUBLE_DEFS_ROOMS
if ( vtor (virtual) ) {
snprintf (buf, MAX_STRING_LENGTH, "Room %d multiply defined!!", virtual);
system_log(buf, TRUE);
} else
#endif
add_room_to_hash (new_room);
return new_room;
}
void setup_dir (FILE *fl, ROOM_DATA *room, int dir, int type)
{
int tmp2;
room->dir_option [dir] = get_perm (sizeof (struct room_direction_data));
room->dir_option [dir]->general_description = fread_string(fl);
room->dir_option [dir]->keyword = fread_string(fl);
fscanf(fl, " %d ", &tmp2);
if (tmp2 == 1)
room->dir_option[dir]->exit_info = PASSAGE_ISDOOR;
else if (tmp2 == 2)
room->dir_option[dir]->exit_info = PASSAGE_ISDOOR | PASSAGE_PICKPROOF;
else
room->dir_option[dir]->exit_info = 0;
fscanf (fl, " %d ", &room->dir_option [dir]->key);
fscanf (fl, " %d ", &room->dir_option [dir]->pick_penalty);
fscanf(fl, " %d", &room->dir_option [dir]->to_room);
switch (type) {
case 1:
SET_BIT(room->dir_option[dir]->exit_info, PASSAGE_SECRET);
break;
case 2:
SET_BIT(room->dir_option[dir]->exit_info, PASSAGE_TRAP);
break;
case 3:
SET_BIT(room->dir_option[dir]->exit_info, PASSAGE_SECRET);
SET_BIT(room->dir_option[dir]->exit_info, PASSAGE_TRAP);
break;
}
}
/* load the zone table and command tables */
void boot_zones(void)
{
FILE *fl;
int zon;
int cmd_no;
int tmp;
int jail_room_num;
char c;
char *p;
char buf [MAX_STRING_LENGTH];
char zfile [MAX_STRING_LENGTH];
struct stat fstatus;
RESET_AFFECT *ra;
CREATE (zone_table, struct zone_data, MAX_ZONE);
for (zon = 0; zon < MAX_ZONE; zon++) {
snprintf (zfile, MAX_STRING_LENGTH, "%s/resets.%d", REGIONS, zon);
if ( stat (zfile, &fstatus) ) {
snprintf (buf, MAX_STRING_LENGTH, "Zone %d resets did not load.", zon);
system_log(buf, TRUE);
continue;
}
if((fl=fopen(zfile,"r"))==NULL) {
system_log(zfile, TRUE);
perror("boot_zone");
break;
}
fscanf (fl, " #%*d\n");
(void)fread_string (fl);
(void)fgets (buf, 80, fl); /* Zone number header stuff */
(void)fgets (buf, 80, fl);
for ( cmd_no = 1;; ) {
fscanf (fl, " ");
fscanf (fl, "%c", &c);
if ( c == 'S' )
break;
if ( c != '*' )
cmd_no++;
(void)fgets (buf, 80, fl);
}
CREATE (zone_table [zon].cmd, struct reset_com, cmd_no);
zone_table[zon].weather_type = 0;
rewind (fl);
cmd_no = 0;
fscanf (fl, " #%*d\nLead: ");
zone_table [zon].lead = fread_string (fl);
zone_table [zon].name = fread_string (fl);
jail_room_num = 0;
(void)fgets (buf, 80, fl);
(void)fgets (buf, 80, fl);
/* Note: At this point, no rooms have been read in yet */
sscanf (buf, " %d %d %d %ld %d %d",
&zone_table [zon].top,
&zone_table [zon].lifespan,
&zone_table [zon].reset_mode,
&zone_table [zon].flags,
&zone_table [zon].jailer,
&zone_table [zon].jail_room_num);
SET_BIT (zone_table [zon].flags, Z_FROZEN);
/* read the command table */
cmd_no = 0;
for ( ;; ) {
fscanf (fl, " "); /* skip blanks */
fscanf (fl, "%c", &zone_table [zon].cmd [cmd_no].command);
if ( zone_table [zon].cmd [cmd_no].command == 'C' ) {
(void)fgets (buf, 80, fl);
while ( *buf && isspace (buf [strlen (buf) - 1]) )
buf [strlen (buf) - 1] = '\0';
zone_table [zon].cmd [cmd_no].arg1 = (int) str_dup (buf);
cmd_no++;
continue;
}
if ( zone_table [zon].cmd [cmd_no].command == 'R' ) {
fscanf (fl, "%d %d %d %d %d %d %d %d %d %d",
&zone_table [zon].cmd [cmd_no].arg1,
&tmp,
&tmp,
&tmp,
&tmp,
&tmp,
&tmp,
&tmp,
&tmp,
&tmp);
(void)fgets (buf, 80, fl);
cmd_no++;
continue;
}
if ( zone_table [zon].cmd [cmd_no].command == 'm' ) {
fscanf (fl, "%d", &zone_table [zon].cmd [cmd_no].arg1);
if ( zone_table [zon].cmd [cmd_no].arg1 == RESET_REPLY ) {
(void)fgets (buf, MAX_STRING_LENGTH - 100, fl);
buf [strlen (buf) - 1] = '\0'; /* Remove new line */
p = buf;
while ( isspace (*p) )
p++;
zone_table [zon].cmd [cmd_no].arg2 = (int) str_dup (p);
}
else {
system_log("UNKNOWN m type RESET, ignored.", TRUE);
(void)fgets (buf, 80, fl);
}
cmd_no++;
continue;
}
if ( zone_table [zon].cmd [cmd_no].command == 'A' ||
zone_table [zon].cmd [cmd_no].command == 'r' ) {
ra = (RESET_AFFECT *)alloc (sizeof (RESET_AFFECT), 34);
fscanf (fl, "%d %d %d %d %d %d %d",
&ra->type,
&ra->duration,
&ra->modifier,
&ra->location,
&ra->bitvector,
&ra->sn,
&ra->t);
/* putting ra into an in will most certainly create
a migration problem. A migrator should create a
new element in zone_table for ra, and not use arg1 */
zone_table [zon].cmd [cmd_no].arg1 = (int) ra;
(void)fgets (buf, 80, fl);
cmd_no++;
continue;
}
if ( zone_table [zon].cmd [cmd_no].command == 'S' )
break;
if ( zone_table [zon].cmd [cmd_no].command == '*' ) {
(void)fgets (buf, 80, fl); /* skip command */
continue;
}
fscanf(fl, " %d %d %d",
&tmp,
&zone_table [zon].cmd [cmd_no].arg1,
&zone_table [zon].cmd [cmd_no].arg2);
zone_table [zon].cmd [cmd_no].if_flag = tmp;
if ( zone_table [zon].cmd [cmd_no].command == 'M' ||
zone_table [zon].cmd [cmd_no].command == 'O' ||
zone_table [zon].cmd [cmd_no].command == 'E' ||
zone_table [zon].cmd [cmd_no].command == 'P' ||
zone_table [zon].cmd [cmd_no].command == 'a' ||
zone_table [zon].cmd [cmd_no].command == 'D')
fscanf (fl, " %d", &zone_table [zon].cmd [cmd_no].arg3);
if ( zone_table [zon].cmd [cmd_no].command == 'M' ) {
zone_table [zon].cmd [cmd_no].enabled = 1;
fscanf (fl, " %d", &zone_table [zon].cmd [cmd_no].arg4);
}
(void)fgets (buf, 80, fl); /* read comment */
cmd_no++;
}
fclose (fl);
}
}
/*************************************************************************
* stuff related to the save/load player system *
*********************************************************************** */
/* Load a char, TRUE if loaded, FALSE if not */
int load_char_objs(CHAR_DATA *ch, char *name)
{
FILE *pf;
char fbuf[265];
if ( !name ) {
system_log ("BUG: name NULL in load_char_objs: db.c", TRUE);
return 0;
}
else if ( !*name ) {
system_log ("BUG: name empty in load_char_objs: db.c\n", TRUE);
return 0;
}
snprintf(fbuf, MAX_STRING_LENGTH, "save/objs/%c/%s",tolower(*name),name);
if(!(pf=fopen(fbuf,"r"))) {
equip_newbie(ch);
return 0;
}
read_obj_suppliment (ch, pf);
fclose(pf);
return 1;
}
void autosave (void)
{
int save_count = 0;
CHAR_DATA *t;
for (t = character_list; t; t = t->next) {
if ( t->deleted || IS_NPC (t) )
continue;
if ( t->desc && t->desc->connected == CON_PLYNG ) {
save_char (t, TRUE);
save_count++;
}
}
}
void autosave_stayputs (void)
{
FILE *fp;
CHAR_DATA *ch;
if ( !(fp = fopen (STAYPUT_FILE ".new", "w")) ) {
system_log("UNABLE TO OPEN stayput.new FILE!!!", TRUE);
return;
}
for ( ch = character_list; ch; ch = ch->next ) {
if ( ch->deleted )
continue;
if ( IS_SET (ch->act, ACT_STAYPUT) )
save_mobile (ch, fp, "STAYPUT", FALSE);
}
fclose (fp);
system ("mv " STAYPUT_FILE ".new " STAYPUT_FILE);
}
/************************************************************************
* procs of a (more or less) general utility nature *
********************************************************************** */
char *fread_string (FILE *fp)
{
char c;
char string_space [MAX_STRING_LENGTH];
char *plast;
plast = string_space;
while ( isspace ((c = getc (fp))) ) {
*plast++ = c;
if ( c != '\t' && c != ' ' )
plast = string_space;
}
if ( ( *plast++ = c ) == '~' )
return null_string;
for ( ;; ) {
switch ( *plast = getc( fp ) ) {
default:
plast++;
break;
case EOF:
*plast++ = '\0';
system_log ("Fread_string() error.", TRUE);
exit(EXIT_FAILURE);
break;
case '~':
*plast = '\0';
return add_hash (string_space);
}
}
}
char *read_string (char *string)
{
char buf [MAX_STRING_LENGTH];
*buf = '\0';
/* move the pointer to the end of the string */
while ( isspace (*string) ) {
string++;
}
/* is the last character a tilde? */
if ( *string == '~' )
return null_string;
/* read characters and add them to buf, until the tilde is found */
for ( ;; ) {
switch ( *string ) {
default:
string++;
snprintf (buf + strlen(buf), MAX_STRING_LENGTH, "%c", *string);
break;
case '~':
return add_hash (buf);
}
}
}
CHAR_DATA *new_char (int pc_type)
{
CHAR_DATA *ch;
/* NOTE: get_perm gets memory from perm_memory during bootup,
thereafter gets it from malloc.
*/
if ( booting )
ch = get_perm (sizeof (CHAR_DATA));
else
ch = (CHAR_DATA *)alloc ((int)sizeof (CHAR_DATA), 19);
if ( ch->pc )
mem_free (ch->pc);
if ( ch->mob )
mem_free (ch->mob);
if ( pc_type ){
mem_free (ch->pc);
ch->pc = NULL;
}
else{
mem_free (ch->mob);
ch->mob = NULL;
}
ch->hour_affects = NULL;
ch->pc = NULL;
ch->mob = NULL;
if ( pc_type ) {
ch->pc = get_perm (sizeof (PC_DATA));
}
else{
ch->mob = get_perm (sizeof (MOB_DATA));
}
return ch;
}
OBJ_DATA *new_object (void)
{
OBJ_DATA *obj = NULL;
if ( booting )
obj = get_perm ((int)sizeof (OBJ_DATA));
else
obj = (OBJ_DATA *)alloc ((int)sizeof (OBJ_DATA), 18);
return obj;
}
void free_descriptor (DESCRIPTOR_DATA *d)
{
if ( d->host && *d->host )
mem_free (d->host);
if ( d->ip_addr && *d->ip_addr )
mem_free (d->ip_addr);
if ( d->showstr_head && *d->showstr_head )
mem_free (d->showstr_head);
if ( d->header && *d->header )
mem_free (d->header);
if ( d->edit_string && *d->edit_string )
mem_free (d->edit_string);
mem_free (d);
}
void free_account (ACCOUNT_DATA *account)
{
STORED_PC_DATA *pc;
Memory_check = TRUE;
if ( account->name && *account->name ) {
mem_free (account->name);
account->name = NULL;
}
if ( account->pwd && *account->pwd ) {
mem_free (account->pwd);
account->pwd = NULL;
}
if ( account->email && *account->email ) {
mem_free (account->email);
account->email = NULL;
}
if ( account->last_ip && *account->last_ip ) {
mem_free (account->last_ip);
account->last_ip = NULL;
}
while ( account->pc ) {
pc = account->pc->next;
if ( account->pc->name && *account->pc->name )
mem_free (account->pc->name);
mem_free (account->pc);
account->pc = pc;
}
mem_free (account);
Memory_check = FALSE;
account = NULL;
}
/* release memory allocated for a char struct */
void free_char (CHAR_DATA *ch)
{
struct memory_data *mem;
ROLE_DATA *role;
DREAM_DATA *dream;
PC_DATA *pc;
MOB_DATA *mob;
VAR_DATA *var;
ALIAS_DATA *tmp_alias;
Memory_check = TRUE;
if ( ch->pc ) {
while ( ch->pc->aliases ) {
tmp_alias = ch->pc->aliases;
ch->pc->aliases = ch->pc->aliases->next_alias;
alias_free (tmp_alias);
}
}
clear_pmote(ch);
while ( ch->hour_affects )
affect_remove (ch, ch->hour_affects);
while ( ch->pc && ch->pc->dreams ) {
dream = ch->pc->dreams;
ch->pc->dreams = ch->pc->dreams->next;
if ( dream->dream && *dream->dream ) {
mem_free (dream->dream);
dream->dream = NULL;
}
mem_free (dream);
dream = NULL;
}
while ( ch->pc && ch->pc->dreamed ) {
dream = ch->pc->dreamed;
ch->pc->dreamed = ch->pc->dreamed->next;
if ( dream->dream && *dream->dream ) {
mem_free (dream->dream);
dream->dream = NULL;
}
mem_free (dream);
dream = NULL;
}
while ( ch && ch->remembers ) {
mem = ch->remembers;
ch->remembers = mem->next;
if (mem->name && *mem->name){
mem_free (mem->name);
mem->name = NULL;
}
mem_free(mem);
mem = NULL;
}
while ( ch->vartab && ch->vartab->next ) {
var = ch->vartab;
ch->vartab = var->next;
if ( var->name && *var->name ) {
mem_free (var->name);
var->name = NULL;
}
mem_free (var);
var = NULL;
}
if ( ch->pc ) {
if ( (role = ch->pc->special_role) != NULL ) {
if ( role->summary && *role->summary )
mem_free (role->summary);
if ( role->body && *role->body )
mem_free (role->body);
if ( role->date && *role->date )
mem_free (role->date);
if ( role->poster && *role->poster )
mem_free (role->poster);
mem_free (role);
ch->pc->special_role = NULL;
}
if ( ch->pc->account && *ch->pc->account ) {
mem_free (ch->pc->account);
ch->pc->account = NULL;
}
if ( ch->pc->site_lie && *ch->pc->site_lie ) {
mem_free (ch->pc->site_lie);
ch->pc->site_lie = NULL;
}
if ( ch->pc->imm_leave && *ch->pc->imm_leave ) {
mem_free (ch->pc->imm_leave);
ch->pc->imm_leave = NULL;
}
if ( ch->pc->imm_enter && *ch->pc->imm_enter ) {
mem_free (ch->pc->imm_enter);
ch->pc->imm_enter = NULL;
}
if ( ch->pc->creation_comment && *ch->pc->creation_comment ) {
mem_free (ch->pc->creation_comment);
ch->pc->creation_comment = NULL;
}
if ( ch->pc->email_address && *ch->pc->email_address ) {
mem_free (ch->pc->email_address);
ch->pc->email_address = NULL;
}
if ( ch->pc->msg && *ch->pc->msg ) {
mem_free (ch->pc->msg);
ch->pc->msg = NULL;
}
ch->pc->owner = NULL;
}
/*
* for the typical mob proto (loaded at boot time)
* these pointers are in perm memory and do not get
* deleted. however newly minit'd mobs share memory
* that is not protected, so freeing here will corrupt
* the proto if it is not saved.
*/
if (!IS_NPC(ch)){
if ( ch->voice_str && *ch->voice_str ) {
mem_free (ch->voice_str);
ch->voice_str = NULL;
}
if ( ch->travel_str && *ch->travel_str ) {
mem_free (ch->travel_str);
ch->travel_str = NULL;
}
if ( ch->pmote_str && *ch->pmote_str ) {
mem_free (ch->pmote_str);
ch->pmote_str = NULL;
}
if (ch->tname && *ch->tname){
mem_free (ch->tname);
ch->tname = NULL;
}
if (ch->name && *ch->name){
mem_free (ch->name);
ch->name = NULL;
}
if (ch->short_descr && *ch->short_descr){
mem_free (ch->short_descr);
ch->short_descr = NULL;
}
if (ch->long_descr && *ch->long_descr){
mem_free (ch->long_descr);
ch->long_descr = NULL;
}
if (ch->description && *ch->description){
mem_free (ch->description);
ch->description = NULL;
}
}
else{
CHAR_DATA* proto = vtom(ch->mob->virtual);
if (proto){
if (ch->tname && *ch->tname
&& ch->tname != proto->tname){
mem_free (ch->tname);
ch->tname = NULL;
}
if (ch->name && *ch->name
&& ch->name != proto->name){
mem_free (ch->name);
ch->name = NULL;
}
if (ch->short_descr && *ch->short_descr
&& ch->short_descr != proto->short_descr ){
mem_free (ch->short_descr);
ch->short_descr = NULL;
}
if (ch->long_descr && *ch->long_descr
&& ch->long_descr != proto->long_descr){
mem_free (ch->long_descr);
ch->long_descr = NULL;
}
if (ch->description && *ch->description
&& ch->description != proto->description){
mem_free (ch->description);
ch->description = NULL;
}
}
else{
fprintf (stderr,
"Proto not defined for NPC %d?\n",
ch->mob->virtual);
}
}
if ( ch->clans && *ch->clans ) {
mem_free (ch->clans);
ch->clans = NULL;
}
if ( ch->combat_log && *ch->combat_log ) {
mem_free (ch->combat_log);
ch->combat_log = NULL;
}
if ( ch->enemy_direction && *ch->enemy_direction ) {
mem_free (ch->enemy_direction);
ch->enemy_direction = NULL;
}
if ( ch->delay_who && !isdigit(*ch->delay_who) && *ch->delay_who ) {
mem_free (ch->delay_who);
ch->delay_who = NULL;
}
if ( ch->delay_who2 && !isdigit(*ch->delay_who2) && *ch->delay_who2 ) {
mem_free (ch->delay_who2);
ch->delay_who2 = NULL;
}
while ( ch->wounds )
wound_from_char (ch, ch->wounds);
while ( ch->lodged )
lodge_from_char (ch, ch->lodged);
while ( ch->attackers )
attacker_from_char (ch, ch->attackers);
while ( ch->threats )
threat_from_char (ch, ch->threats);
/* Don't erase the pc and mob data structures, since they need
to sit around until cleanup_the_dead pulses. new_char will
clean them up.
*/
pc = ch->pc;
mob = ch->mob;
memset (ch, 0, sizeof (CHAR_DATA));
ch->pc = pc;
ch->mob = mob;
if ( pc )
mem_free (ch->pc);
if ( mob )
mem_free (ch->mob);
mem_free (ch);
ch = NULL;
Memory_check = FALSE;
}
void free_obj (OBJ_DATA *obj)
{
AFFECTED_TYPE *af;
OBJ_DATA *tobj;
WRITING_DATA *writing;
tobj = vtoo (obj->virtual);
/* Make sure these arn't duplicate fields of the prototype */
if ( !tobj || tobj->name != obj->name )
mem_free (obj->name);
if ( !tobj || tobj->short_description != obj->short_description )
mem_free (obj->short_description);
if ( !tobj || tobj->description != obj->description )
mem_free (obj->description);
if ( !tobj || tobj->full_description != obj->full_description )
mem_free (obj->full_description);
if ( !tobj || tobj->var_color != obj->var_color )
mem_free (obj->var_color);
if ( !tobj || tobj->desc_keys != obj->desc_keys )
mem_free (obj->desc_keys);
clear_omote(obj);
obj->short_description = NULL;
obj->description = NULL;
obj->full_description = NULL;
obj->var_color = NULL;
obj->name = NULL;
obj->desc_keys = NULL;
while ( (af = obj->xaffected) ) {
obj->xaffected = af->next;
mem_free (af);
}
while ( obj->wounds )
wound_from_obj (obj, obj->wounds);
while ( obj->lodged )
lodge_from_obj (obj, obj->lodged);
while ( obj->writing ) {
writing = obj->writing;
obj->writing = writing->next_page;
if ( writing->message )
mem_free (writing->message);
if ( writing->author )
mem_free (writing->author);
if ( writing->date )
mem_free (writing->date);
if ( writing->ink )
mem_free (writing->ink);
mem_free (writing);
}
memset (obj, 0, sizeof (OBJ_DATA));
mem_free (obj);
}
/* read contents of a text file, and place in buf */
char *file_to_string(char *name)
{
FILE *fl;
char tmp[MAX_STRING_LENGTH]; /* max size on the string */
char *string;
int num_chars;
if (!(fl = fopen(name, "r")))
{
perror("file-to-string");
string = (char *)alloc (1, 4);
*string = '\0';
return(string);
}
num_chars = fread (tmp, 1, MAX_STRING_LENGTH-1, fl);
tmp [num_chars] = '\0';
string = (char *)alloc (num_chars + 2, 4);
strcpy (string, tmp);
strcat (string, "\r\0");
fclose (fl);
return (string);
}
void clear_char (CHAR_DATA *ch)
{
PC_DATA *pc;
MOB_DATA *temp_mob;
temp_mob = ch->mob;
if (temp_mob){
memset (temp_mob, 0, sizeof(MOB_DATA));
}
pc = ch->pc;
if (pc)
memset (pc, 0, sizeof(PC_DATA));
memset (ch, 0, sizeof(CHAR_DATA));
ch->pc = pc;
ch->mob = temp_mob;
ch->damage = 0;
ch->room = NULL;
ch->in_room = NOWHERE;
ch->was_in_room = NOWHERE;
ch->position = POSITION_STANDING;
ch->default_pos = POSITION_STANDING;
ch->wounds = NULL;
ch->lodged = NULL;
ch->mount = NULL;
ch->following = NULL;
ch->fighting = NULL;
ch->subdue = NULL;
ch->vehicle = NULL;
ch->shop = NULL;
ch->hour_affects = NULL;
ch->equip = NULL;
ch->desc = NULL;
ch->hitcher = NULL;
ch->hitchee = NULL;
ch->aiming_at = NULL;
ch->targeted_by = NULL;
ch->next = NULL;
ch->next_in_room = NULL;
if ( ch->pc ) {
ch->pc->is_guide = 0;
ch->pc->admin_loaded = FALSE;
ch->pc->profession = 0;
}
return;
}
void clear_object (OBJ_DATA *obj)
{
memset (obj, 0, sizeof (OBJ_DATA));
obj->silver = 0;
obj->coppers = 0;
obj->virtual = -1;
obj->in_room = NOWHERE;
obj->wounds = NULL;
obj->lodged = NULL;
obj->description = NULL;
obj->short_description = NULL;
obj->full_description = NULL;
obj->equiped_by = NULL;
obj->carried_by = NULL;
}
void save_char_objs (CHAR_DATA *ch, char *name)
{
FILE *of;
char fbuf [MAX_STRING_LENGTH];
char buf2 [MAX_STRING_LENGTH];
snprintf (fbuf, MAX_STRING_LENGTH, "save/objs/%c/%s", tolower (*name), name);
if ( !IS_NPC (ch) && ch->pc->create_state == STATE_DIED ) {
snprintf (buf2, MAX_STRING_LENGTH, "mv %s %s.died", fbuf, fbuf);
system (buf2);
}
if( !(of = fopen (fbuf, "w")) ) {
snprintf (buf2, MAX_STRING_LENGTH, "ERROR: Opening obj save file. (%s)", ch->tname);
system_log (buf2, TRUE);
return;
}
write_obj_suppliment (ch, of);
fclose (of);
}
/*
* Read a number from a file.
*/
int fread_number( FILE *fp )
{
char c;
long int number;
bool sign;
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 ) ) {
system_log ("Fread_number(): bad format.", TRUE);
abort();
}
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;
}
/*
* 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;
}
}
system_log ("Fread_word(): word too long.", TRUE);
abort();
}
void boot_mobiles (void)
{
char buf [MAX_STRING_LENGTH];
int virtual;
int zone;
FILE *fp;
for ( zone = 0; zone < MAX_ZONE; zone++ ) {
snprintf (buf, MAX_STRING_LENGTH, "%s/mobs.%d", REGIONS, zone);
if ( (fp = fopen (buf, "r")) == NULL )
continue;
while (1) {
if ( !fgets (buf, 81, fp) ) {
system_log("Error reading mob file:", TRUE);
system_log(buf, TRUE);
perror ("Reading mobfile");
abort();
}
if ( *buf == '#' ) {
sscanf (buf, "#%d", &virtual);
(void)fread_mobile (virtual, zone, fp);
} else if ( *buf == '$' )
break;
}
fclose (fp);
}
}
void create_ticket_proto (void)
{
OBJ_DATA *obj;
if ( vtoo (VNUM_TICKET) != NULL )
return;
obj = new_object ();
clear_object (obj);
obj->virtual = VNUM_TICKET;
add_obj_to_hash (obj);
obj->name = add_hash ("ticket small number paper");
obj->short_description = add_hash ("a small ostler's ticket");
obj->description = add_hash ("A small paper ticket with a number "
"is here.");
obj->full_description = null_string;
obj->obj_flags.weight = 1;
obj->obj_flags.type_flag = ITEM_TICKET;
obj->obj_flags.wear_flags = ITEM_TAKE;
obj->in_room = NOWHERE;
}
void create_head_proto (void)
{
OBJ_DATA *obj;
if ( vtoo (VNUM_HEAD) != NULL )
return;
obj = new_object ();
clear_object (obj);
obj->virtual = VNUM_HEAD;
add_obj_to_hash (obj);
obj->name = add_hash ("head");
obj->short_description = add_hash ("a head");
obj->description = add_hash ("A head is here.");
obj->full_description = null_string;
obj->obj_flags.weight = 10;
obj->obj_flags.type_flag = ITEM_HEAD;
obj->obj_flags.wear_flags = ITEM_TAKE | ITEM_HOLD;
obj->in_room = NOWHERE;
}
void create_corpse_proto (void)
{
OBJ_DATA *obj;
if ( vtoo (VNUM_CORPSE) != NULL )
return;
obj = new_object ();
clear_object (obj);
obj->virtual = VNUM_CORPSE;
add_obj_to_hash (obj);
obj->name = add_hash ("corpse");
obj->short_description = add_hash ("a corpse");
obj->description = add_hash ("A corpse is here.");
obj->full_description = null_string;
obj->obj_flags.weight = 1000;
obj->o.container.capacity = 0; /* No keeping things on a corpse */
obj->obj_flags.type_flag = ITEM_CONTAINER;
obj->obj_flags.wear_flags = ITEM_TAKE;
obj->in_room = NOWHERE;
}
void create_statue_proto (void)
{
OBJ_DATA *obj;
if ( vtoo (VNUM_STATUE) != NULL )
return;
obj = new_object ();
clear_object (obj);
obj->virtual = VNUM_STATUE;
add_obj_to_hash (obj);
obj->name = add_hash ("statue");
obj->short_description = add_hash ("a remarkably lifelike statue");
obj->description = add_hash ("A remarkably lifelike statue looms here.");
obj->full_description = null_string;
obj->obj_flags.weight = 1000;
obj->o.container.capacity = 0; /* No keeping things on a statue */
obj->obj_flags.type_flag = ITEM_CONTAINER;
obj->in_room = NOWHERE;
return;
}
void boot_objects (void)
{
char buf [MAX_STRING_LENGTH];
int virtual;
int zone;
int i = 0;
CLAN_DATA *clan;
OBJ_DATA *obj;
FILE *fp;
for ( zone = 0; zone < MAX_ZONE; zone++ ) {
snprintf (buf, MAX_STRING_LENGTH, "%s/objs.%d", REGIONS, zone);
if ( (fp = fopen (buf, "r")) == NULL )
continue;
while (1) {
if ( !fgets (buf, 81, fp) ) {
system_log("Error reading obj file:", TRUE);
perror ("Reading objfile");
abort();
}
if ( *buf == '#' ) {
sscanf (buf, "#%d", &virtual);
(void)fread_object (virtual, zone, fp);
} else if ( *buf == '$' )
break;
}
fclose (fp);
}
for ( clan = clan_list; clan; clan = clan->next ) {
if ( clan->leader_vnum ) {
if ( !(obj = vtoo (clan->leader_vnum)) ) {
snprintf (buf, MAX_STRING_LENGTH, "Note: Clan leader obj %d does not exist for %d.",
clan->leader_vnum, i);
system_log(buf, TRUE);
} else
SET_BIT (obj->obj_flags.extra_flags, ITEM_LEADER);
}
if ( clan->member_vnum ) {
if ( !(obj = vtoo (clan->member_vnum)) ) {
snprintf (buf, MAX_STRING_LENGTH, "Note: Clan member obj %d does not exist for %d.",
clan->member_vnum, i);
system_log(buf, TRUE);
} else
SET_BIT (obj->obj_flags.extra_flags, ITEM_MEMBER);
}
if ( clan->omni_vnum ) {
if ( !(obj = vtoo (clan->omni_vnum)) ) {
snprintf (buf, MAX_STRING_LENGTH, "Note: Clan omni obj %d does not exist for %d.",
clan->omni_vnum, i);
system_log(buf, TRUE);
} else
SET_BIT (obj->obj_flags.extra_flags, ITEM_OMNI);
}
}
create_ticket_proto ();
create_head_proto ();
create_corpse_proto ();
create_statue_proto ();
}
struct hash_data {
int len;
char *string;
struct hash_data *next;
};
void init_memory (void)
{
int i;
if ( !(use_memory_base = (char *)alloc (MAX_MEMORY + PERM_MEMORY_SIZE, 5))) {
perror ("memory allocation");
system_log ("Init_memory() error - unable to malloc.", TRUE);
abort();
}
use_memory_next = use_memory_base;
use_memory_top = use_memory_base + MAX_MEMORY - 1;
perm_memory = use_memory_base + MAX_MEMORY;
perm_memory_next = perm_memory;
perm_memory_top = perm_memory + PERM_MEMORY_SIZE - 1;
for ( i = 0; i < NUM_BUCKETS; i++ )
hash_buckets [i] = NULL;
if ( !(overhead_base = (char *)alloc (MAX_OVERHEAD, 5)) ) {
perror ("memory overhead allocation");
system_log ("Init_memory() error - unable to malloc overhead.", TRUE);
abort();
}
overhead_next = overhead_base;
overhead_top = overhead_base + MAX_OVERHEAD - 1;
null_string = get_perm (1);
*null_string = '\0';
}
char *get_mem (int size)
{
char *allocated_block;
if ( size <= 0 ) {
system_log ("Get_mem() - allocation of negative bytes attempted.", TRUE);
return NULL;
}
if ( use_memory_next + size + 4 > use_memory_top ) {
system_log ("Get_mem() - exceeded allocation limit.", TRUE);
abort();
}
allocated_block = use_memory_next;
use_memory_next += size;
while ( (int) use_memory_next % 4 )
use_memory_next++;
return allocated_block;
}
malloc_t get_perm (int size)
{
char *allocated_block;
static int notified = 0;
if ( !booting )
return malloc (size);
if ( perm_memory_next + size + 4 > perm_memory_top ) {
if ( !notified ) {
printf ("****************Out of perm space.\n");
fflush (stdout);
notified = 1;
}
return malloc (size);
}
allocated_block = perm_memory_next;
perm_memory_next += size;
while ( (int) perm_memory_next % 4 )
perm_memory_next++;
return allocated_block;
}
malloc_t get_overhead (int size)
{
char *allocated_block;
if ( size <= 0 ) {
system_log ("Get_overhead() - attempted to allocate negative or 0 bytes.", TRUE);
return NULL;
}
if ( overhead_next + size + 4 > overhead_top ) {
system_log ("Get_overhead() - exceeded allocation limit.", TRUE);
abort();
}
allocated_block = overhead_next;
overhead_next += size;
while ( (int) overhead_next % 4 )
overhead_next++;
return allocated_block;
}
extern int bytes_allocated;
extern int first_free;
extern int mud_memory;
#ifdef MEMORY_CHECK
extern MEMORY_T *alloc_ptrs [];
MEMORY_T *alloc_ptrs [100000];
int mem_free (malloc_t string)
{
char *p;
MEMORY_T *m;
int entry;
int bytes;
int dtype;
extern int mem_freed;
if ( string >= (malloc_t) use_memory_base &&
string <= (malloc_t) use_memory_top )
return 0;
if ( string >= (malloc_t) perm_memory &&
string <= (malloc_t) perm_memory_top )
return 0;
if ( booting &&
string >= (malloc_t) overhead_base &&
string <= (malloc_t) overhead_top )
return 0;
if ( string == null_string )
return 0;
p = string;
m = (MEMORY_T *) (p - sizeof (MEMORY_T));
dtype = m->dtype;
entry = m->entry;
bytes = m->bytes;
if ( x1 )
printf ("- #%d @ %Xd for %d bytes: %d\n",
entry, (int) p, bytes, dtype);
if ( alloc_ptrs [entry] != m ) {
system_log("Memory deallocation problem.", TRUE);
printf ("Entry : %d\n", entry);
printf ("m : %d\n", (int) (m));
printf ("allocs: %d\n", (int) alloc_ptrs [entry]);
((int *) 0) [-1] = 0;
}
mud_memory -= bytes - sizeof (MEMORY_T);
bytes_allocated -= bytes;
mem_freed += bytes;
first_free--;
((MEMORY_T *) alloc_ptrs [first_free])->entry = entry;
alloc_ptrs [entry] = alloc_ptrs [first_free];
free (m);
return 1;
}
/*
void set_bit (int bit_no)
{
bit_no -= (int) alloc_ptrs [0];
super_map [bit_no / 32] |= 1 << (bit_no % 32);
}
void reset_bit (int bit_no)
{
bit_no -= (int) alloc_ptrs [0];
super_map [bit_no / 32] &= ~(1 << (bit_no % 32));
}
int is_bit_set (int bit_no)
{
bit_no -= (int) alloc_ptrs [0];
return IS_SET (super_map [bit_no / 32], 1 << (bit_no % 32));
}
void clear_bits (void)
{
int i;
for ( i = 0; i < SUPER_SIZE_WORDS; i++ )
super_map [i] = 0;
}
*/
void print_bit_map (void)
{
int i;
unsigned int addr;
int old_addr;
int bytes;
int old_bytes;
FILE *fp;
FILE *fp2;
if ( !(fp = fopen ("map", "w+")) ) {
perror ("map");
system_log("Unable to open 'map'.\n", TRUE);
return;
}
for ( i = 0; i < first_free; i++ ) {
fprintf (fp, "%09d %10d\n",
(unsigned int) alloc_ptrs [i], alloc_ptrs [i]->bytes);
}
fclose (fp);
system ("sort map > map_sort");
if ( !(fp = fopen ("map_sort", "r")) ) {
perror ("map_sort");
system_log("Unable to open 'map_sort'.\n", TRUE);
return;
}
if ( !(fp2 = fopen ("map_sort_x", "w+")) ) {
perror ("map_sort_x");
system_log("Unable to open 'map_sort_x'.\n", TRUE);
return;
}
old_addr = 0;
old_bytes = 0;
while ( fscanf (fp, "%d %d\n", &addr, &bytes) == 2 ) {
fprintf (fp2, "%4d %09d %10d\n",
addr - old_addr - old_bytes,
addr, bytes);
old_addr = addr;
old_bytes = bytes;
}
fclose (fp);
fclose (fp2);
}
void check_memory (void)
{
int i;
int entry;
int bytes;
int check_mud_memory = 0;
int check_bytes_allocated = 0;
int failed = 0;
int dtype;
int objects_in_list = 0;
int characters_in_list = 0;
OBJ_DATA *o;
CHAR_DATA *tch;
MEMORY_T *m;
check_objects = 0;
check_characters = 0;
for ( i = 0; i < first_free; i++ ) {
m = alloc_ptrs [i];
dtype = m->dtype;
entry = m->entry;
bytes = m->bytes;
if ( entry != i ) {
abort();
}
check_mud_memory += bytes - sizeof (MEMORY_T);
check_bytes_allocated += bytes;
if ( dtype == 18 )
check_objects++;
if ( dtype == 19 )
check_characters++;
}
if ( check_mud_memory != mud_memory ) {
failed = 1;
}
if ( check_bytes_allocated != bytes_allocated ) {
failed = 1;
}
if ( failed )
((int *)0)[-1]=0;
for ( o = object_list; o; o = o->next )
objects_in_list++;
for ( tch = character_list; tch; tch = tch->next )
characters_in_list++;
}
#else /* NOVELL */
int mem_free (malloc_t string)
{
if ( string >= (malloc_t) use_memory_base &&
string <= (malloc_t) use_memory_top ) {
return 0;
}
if ( string >= (malloc_t) perm_memory &&
string <= (malloc_t) perm_memory_top ) {
return 0;
}
if ( booting &&
string >= (malloc_t) overhead_base &&
string <= (malloc_t) overhead_top ) {
return 0;
}
if ( string == null_string || string == NULL ) {
return 0;
}
return 1;
}
#endif /* NOVELL */
char *is_hashed (char *string)
{
struct hash_data *hash_entry;
char *tmp_string;
hash_val = 0;
hash_len = 0;
if ( !string ) {
return NULL;
}
tmp_string = string;
while ( *tmp_string ) {
hash_val += (int) *(tmp_string++);
hash_len++;
}
hash_val = hash_val % NUM_BUCKETS;
hash_entry = hash_buckets [hash_val];
while ( hash_entry ) {
if ( hash_entry->len == hash_len &&
!strcmp (string, hash_entry->string) )
return hash_entry->string;
hash_entry = hash_entry->next;
}
return 0;
}
char *add_hash (char *string)
{
struct hash_data *hash_entry;
char *hashed_string = NULL;
if ( !string || !*string )
return null_string;
if ( !booting )
return str_dup(string);
if ( (hashed_string = is_hashed (string)) ) {
hash_dup_strings++;
hash_dup_length += strlen (string);
return hashed_string;
}
hash_entry = get_overhead (sizeof (struct hash_data));
/* hash_len and hash_val are statically maintained */
hash_entry->string = get_mem (hash_len + 1);
strcpy (hash_entry->string, string);
hash_entry->len = hash_len;
hash_entry->next = hash_buckets [hash_val];
hash_buckets [hash_val] = hash_entry;
return (hash_entry->string);
}
char *str_dup (char *this_string)
{
char *ret = NULL;
int temp = 0;
if ( !this_string )
return NULL;
if ( this_string >= use_memory_base && this_string <= use_memory_top )
return this_string;
temp = strlen(this_string)+1;
ret = (char *)alloc ((int)strlen(this_string)+1, 15);
strcpy(ret, this_string);
memcpy (ret, this_string, temp);
return ret;
}
void boot_recipe (void)
{
FILE *fp;
int obj_num;
int i1, i2, i3, i4, i5, i6, i7;
int r1, r2, r3, r4, r5, r6, r7;
RECIPE_DATA *recipe_entry;
RECIPE_DATA *alc_tmp;
char buf [MAX_STRING_LENGTH];
if ( (fp = fopen (RECIPE_FILE, "r")) == NULL ) {
snprintf (buf, MAX_STRING_LENGTH, "NO RECIPE FILE: %s.", RECIPE_FILE);
return;
}
while (1) {
obj_num = i1 = i2 = i3 = i4 = i5 = i6 = i7 = 0;
r1 = r2 = r3 = r4 = r5 = r6 = r7 = 0;
fscanf (fp, "#%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
&obj_num, &i1, &i2, &i3, &i4, &i5, &i6, &i7,
&r1, &r2, &r3, &r4, &r5, &r6, &r7);
if ( !obj_num ) {
fclose (fp);
return;
}
CREATE (recipe_entry, RECIPE_DATA, 1);
recipe_entry->obj_created = obj_num;
recipe_entry->ingredient [0] = i1;
recipe_entry->ingredient [1] = i2;
recipe_entry->ingredient [2] = i3;
recipe_entry->ingredient [3] = i4;
recipe_entry->ingredient [4] = i5;
recipe_entry->ingredient [5] = i6;
recipe_entry->ingredient [6] = i7;
recipe_entry->reuse [0] = r1;
recipe_entry->reuse [1] = r2;
recipe_entry->reuse [2] = r3;
recipe_entry->reuse [3] = r4;
recipe_entry->reuse [4] = r5;
recipe_entry->reuse [5] = r6;
recipe_entry->reuse [6] = r7;
sort_int_array (recipe_entry->ingredient, 7);
recipe_entry->next = NULL;
if ( !recipe_list )
recipe_list = recipe_entry;
else {
alc_tmp = recipe_list;
while ( alc_tmp->next )
alc_tmp = alc_tmp->next;
alc_tmp->next = recipe_entry;
}
}
}
void verify_exits (void)
{
int i;
char buf [MAX_STRING_LENGTH];
ROOM_DATA *room;
for ( room = full_room_list; room; room = room->lnext ) {
for ( i = 0; i < 6; i++ ) {
if ( room->dir_option [i] &&
!vtor (room->dir_option [i]->to_room) ) {
snprintf (buf, MAX_STRING_LENGTH, "Room %d doesn't go %s (%d) to room %d",
room->virtual,
dirs [i],
i,
room->dir_option [i]->to_room);
system_log (buf, TRUE);
}
}
}
}
void load_common_knowledge (void)
{
char *msg;
FILE *fp;
COMMON_DATA *cd;
COMMON_DATA *tcd;
char buf [MAX_STRING_LENGTH];
common_list = NULL;
if ( (fp = fopen (COMMON, "r")) == NULL ) {
snprintf (buf, MAX_STRING_LENGTH, "NO COMMON KNOWLEDGE FILE: %s.", COMMON);
return;
}
(void)fgets (buf, 256, fp);
while ( 1 ) {
msg = fread_string (fp);
if ( !msg || !*msg )
break;
CREATE (cd, COMMON_DATA, 1);
cd->message = msg;
if ( !common_list )
common_list = cd;
else {
tcd = common_list;
while ( tcd->next )
tcd = tcd->next;
tcd->next = cd;
}
}
fclose (fp);
}