/*
* init.c - startup/shutdown routines for Phantasia
*/
#include "include.h"
extern int server_hook;
extern randomStateBuffer;
extern randData;
/************************************************************************
/
/ FUNCTION NAME: Do_initialize(struct server_t *server)
/
/ FUNCTION: To initialize the program's variables
/
/ AUTHOR: Brian Kelly, 4/6/99
/
/ ARGUMENTS:
/ struct server_t *s - address of the server's main data strcture
/
/ RETURN VALUE: short error
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ GLOBAL INPUTS: Echo, _iob[], Wizard, *stdscr
/
/ GLOBAL OUTPUTS: _iob[]
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
/ - strip non-printing characters (unless Wizard)
/ - echo, if desired
/ - redraw the screen if CH_REDRAW is entered
/ - read in only 'mx - 1' characters or less characters
/ - nul-terminate string, and throw away newline
/
/ 'mx' is assumed to be at least 2.
/
*************************************************************************/
Init_server(struct server_t *s)
{
char error_msg[SZ_ERROR_MESSAGE];
int error;
struct realm_object_t *object_ptr;
/* seed the random number generator */
initstate_r (time(NULL), (char *)&randomStateBuffer, STATELEN,
(struct random_data *)&randData);
/* initialize realm variables */
server_hook = s->run_level;
s->realm.serverPid = getpid();
s->realm.objects = NULL;
s->realm.games = NULL;
s->realm.king = NULL;
s->realm.valar = NULL;
s->realm.king_flag = FALSE;
s->realm.king_name[0] = '\0';
s->realm.valar_name[0] = '\0';
s->realm.name_limbo = NULL;
s->realm.email_limbo = NULL;
s->realm.connections = NULL;
s->realm.steward_gold = 0;
/* initialize all the realm mutexes */
Do_init_mutex(&s->realm.realm_lock);
Do_init_mutex(&s->realm.backup_lock);
Do_init_mutex(&s->realm.scoreboard_lock);
Do_init_mutex(&s->realm.account_lock);
Do_init_mutex(&s->realm.character_file_lock);
Do_init_mutex(&s->realm.log_file_lock);
Do_init_mutex(&s->realm.network_file_lock);
Do_init_mutex(&s->realm.tag_file_lock);
Do_init_mutex(&s->realm.tagged_file_lock);
Do_init_mutex(&s->realm.history_file_lock);
Do_init_mutex(&s->realm.monster_lock);
Do_init_mutex(&s->realm.object_lock);
Do_init_mutex(&s->realm.kings_gold_lock);
Do_init_mutex(&s->realm.hack_lock);
Do_init_mutex(&s->realm.connections_lock);
/* set the number to tags to the time */
s->realm.nextTagNumber = Do_get_next_tag();
/* load the realm objects and the king's gold */
s->realm.objects = NULL;
error = Do_load_data_file(&s->realm);
/* if there's an error, we can continue, just with no objects */
if (error) {
sprintf(error_msg, "[0.0.0.0:%d] Phantasia will continue with no objects from previous games.\n", s->realm.serverPid);
Do_log_error(error_msg);
/* set kings and stewards gold to zero */
s->realm.kings_gold = 0;
/* only the grail should exist */
while (s->realm.objects != NULL) {
object_ptr = s->realm.objects;
s->realm.objects = object_ptr->next_object;
free((void *)object_ptr);
}
Do_hide_grail(&s->realm, 5000);
Do_hide_trove(&s->realm);
}
/* load the monsters into the realm array */
Do_load_monster_file(&s->realm);
/* load the charstats into the realm array */
Do_load_charstats_file(&s->realm);
/* load the shop items into the realm array */
Do_load_shopitems_file(&s->realm);
/* restore any characters in the backup file */
Do_backup_restore();
/* initialize the server variables */
s->num_games = 0;
/* start up the socket connection */
s->the_socket = Do_init_server_socket();
/* no problems */
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_load_data_file(struct *realm_t)
/
/ FUNCTION: To load saved configuration information
/
/ AUTHOR: Brian Kelly, 4/8/99
/
/ ARGUMENTS:
/ struct realm_t *the_realm - pointer to the realm
/
/ RETURN VALUE: short error
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
/ - strip non-printing characters (unless Wizard)
/ - echo, if desired
/ - redraw the screen if CH_REDRAW is entered
/ - read in only 'mx - 1' characters or less characters
/ - nul-terminate string, and throw away newline
/
/ 'mx' is assumed to be at least 2.
/
*************************************************************************/
int Do_load_data_file(the_realm)
struct realm_t *the_realm;
{
FILE *data_file;
struct realm_object_t *object_ptr;
struct realm_state_t *state_ptr;
char error_msg[SZ_ERROR_MESSAGE];
int error;
int grailCount = 0, troveCount = 0;
state_ptr = (struct realm_state_t *) Do_malloc(SZ_REALM_STATE);
/* open the data file - for king's gold and corpses */
errno = 0;
if ((data_file = fopen(DATA_FILE, "r")) == NULL) {
sprintf(error_msg,
"[0.0.0.0:%d] fopen of %s failed in Do_load_data_file: %s\n",
the_realm->serverPid, DATA_FILE, strerror(errno));
Do_log_error(error_msg);
return DATA_FILE_ERROR;
}
if (fread((void *) state_ptr, SZ_REALM_STATE, 1, data_file) != 1) {
sprintf(error_msg,
"[0.0.0.0:%d] fread of %s failed in Do_load_data_file: %d\n",
the_realm->serverPid, DATA_FILE, ferror(data_file));
Do_log_error(error_msg);
fclose(data_file);
return DATA_FILE_ERROR;
}
the_realm->kings_gold = state_ptr->kings_gold;
strcpy(the_realm->king_name, state_ptr->king_name);
strcpy(the_realm->valar_name, state_ptr->valar_name);
/* destroy the temporary realm state object */
free((void *)state_ptr);
/* first entry is king's gold as double float */
/*
if (fread((void *) &the_realm->kings_gold, sizeof(the_realm->kings_gold),
1, data_file) != 1) {
sprintf(error_msg,
"[0.0.0.0:%d] fread of %s failed in Do_load_data_file: %d\n",
the_realm->serverPid, DATA_FILE, ferror(data_file));
Do_log_error(error_msg);
fclose(data_file);
return DATA_FILE_ERROR;
}
*/
/* all remaining items are realm objects */
/* create a structure to read into */
object_ptr = (struct realm_object_t *) Do_malloc(SZ_REALM_OBJECT);
/* read next object while not at EOF */
while (fread((void *) object_ptr, SZ_REALM_OBJECT, 1, data_file) == 1) {
switch (object_ptr->type) {
case CORPSE:
/* create an strcture to hold the character information */
object_ptr->arg1 = (void *) malloc(SZ_PLAYER);
/* and read in the dead player's information */
if (fread(object_ptr->arg1, SZ_PLAYER, 1, data_file) == 0) {
sprintf(error_msg,
"[0.0.0.0:%d] fread of %s failed in Do_load_data_file(2): %d\n",
the_realm->serverPid, DATA_FILE, ferror(data_file));
Do_log_error(error_msg);
fclose(data_file);
free((void *)object_ptr->arg1);
free((void *)object_ptr);
return DATA_FILE_ERROR;
}
/* used to be CORPSE_LIFE */
if (86400 * sqrt(((struct player_t *) object_ptr->arg1)->level)
< time(NULL) - ((struct player_t *)object_ptr->arg1)->last_load) {
/* delete the object */
free((void *)object_ptr->arg1);
free((void *)object_ptr);
}
else {
/* put the new corpse in the realm object list */
object_ptr->next_object = the_realm->objects;
the_realm->objects = object_ptr;
}
break;
/* if the object is the holy grail, we do nothing special */
case HOLY_GRAIL:
/* put the item in the realm object list */
object_ptr->next_object = the_realm->objects;
the_realm->objects = object_ptr;
++grailCount;
break;
/* if the object is the treasure trove, we do nothing special */
case TREASURE_TROVE:
/* put the item in the realm object list */
object_ptr->next_object = the_realm->objects;
the_realm->objects = object_ptr;
++troveCount;
break;
/* anything else is an error */
default:
sprintf(error_msg,
"[0.0.0.0:%d] bad realm object of type %hd read in Do_load_data_file.\n",
the_realm->serverPid, object_ptr->type);
Do_log_error(error_msg);
fclose(data_file);
free((void *)object_ptr);
return DATA_FILE_ERROR;
}
/* create a new temporary realm object */
object_ptr = (struct realm_object_t *)malloc(SZ_REALM_OBJECT);
}
/* destroy the remaining temporary realm object */
free((void *)object_ptr);
/* if we found no grail, hide a new one */
if (grailCount == 0) {
sprintf(error_msg,
"[0.0.0.0:%d] No grail found in Do_load_data_file. Creating a new one.\n",
the_realm->serverPid);
Do_log_error(error_msg);
Do_hide_grail(the_realm, 5000);
}
else if (grailCount != 1) {
sprintf(error_msg,
"[0.0.0.0:%d] Read in %d grails in Do_load_data_file.\n",
the_realm->serverPid, grailCount);
Do_log_error(error_msg);
return DATA_FILE_ERROR;
}
/* if we found no treasure trove, hide a new one */
if (troveCount == 0) {
sprintf(error_msg, "[0.0.0.0:%d] No treasure trove found in Do_load_data_file. Creating a new one.\n", the_realm->serverPid);
Do_log_error(error_msg);
Do_hide_trove(the_realm);
}
else if (troveCount != 1) {
sprintf(error_msg,
"[0.0.0.0:%d] Read in %d treasure troves in Do_load_data_file.\n",
the_realm->serverPid, troveCount);
Do_log_error(error_msg);
return DATA_FILE_ERROR;
}
return 0; /* no problems */
}
/************************************************************************
/
/ FUNCTION NAME: Do_load_monster_file(struct realm_t *the_realm)
/
/ FUNCTION: To load saved configuration information
/
/ AUTHOR: Brian Kelly, 4/8/99
/
/ ARGUMENTS:
/ struct realm_t *the_realm - pointer to the realm strcture
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
/ - strip non-printing characters (unless Wizard)
/ - echo, if desired
/ - redraw the screen if CH_REDRAW is entered
/ - read in only 'mx - 1' characters or less characters
/ - nul-terminate string, and throw away newline
/
/ 'mx' is assumed to be at least 2.
/
*************************************************************************/
Do_load_monster_file(struct realm_t *the_realm)
{
FILE *monster_file;
char error_msg[SZ_ERROR_MESSAGE];
int i;
/* load monster information */
errno = 0;
/* open the monster file */
if ((monster_file = fopen(MONSTER_FILE, "r")) == NULL) {
sprintf(error_msg,
"[0.0.0.0:%d] fopen of %s failed in Do_load_monster_file: %s\n",
the_realm->serverPid, MONSTER_FILE, strerror(errno));
Do_log_error(error_msg);
exit(MONSTER_FILE_ERROR);
}
/* read each line of the monster file */
for (i = 0; i < NUM_MONSTERS; i++) {
/* read the monster name which is on its own line */
if (fgets(the_realm->monster[i].name, SZ_MONSTER_NAME, monster_file)
== NULL) {
sprintf(error_msg, "[0.0.0.0:%d] fgets of %s failed on call number %d in Do_load_monster_file.\n", the_realm->serverPid, MONSTER_FILE, i);
Do_log_error(error_msg);
exit(MONSTER_FILE_ERROR);
}
/* reEmove trailing blanks */
Do_truncstring(the_realm->monster[i].name);
/* read the stat line for each monster */
if (fscanf(monster_file, "%lf %lf %lf %lf %lf %hd %hd %hd\n",
&the_realm->monster[i].strength, &the_realm->monster[i].brains,
&the_realm->monster[i].speed, &the_realm->monster[i].energy,
&the_realm->monster[i].experience,
&the_realm->monster[i].treasure_type,
&the_realm->monster[i].special_type,
&the_realm->monster[i].flock_percent) != 8) {
/* exit if we didn't read 8 items */
sprintf(error_msg, "[0.0.0.0:%d] fscanf of %s failed on call number %d in Do_load_monster_file.\n", the_realm->serverPid, MONSTER_FILE, i);
Do_log_error(error_msg);
exit(MONSTER_FILE_ERROR);
}
}
/* close the monster file */
fclose(monster_file);
/* all done here */
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_load_charstats_file(struct realm_t *the_realm)
/
/ FUNCTION: To load saved configuration information
/
/ AUTHOR: Brian Kelly, 5/7/99
/
/ ARGUMENTS:
/ struct realm_t *the_realm - pointer to the realm strcture
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
/ - strip non-printing characters (unless Wizard)
/ - echo, if desired
/ - redraw the screen if CH_REDRAW is entered
/ - read in only 'mx - 1' characters or less characters
/ - nul-terminate string, and throw away newline
/
/ 'mx' is assumed to be at least 2.
/
*************************************************************************/
Do_load_charstats_file(struct realm_t *the_realm)
{
FILE *charstats_file;
char error_msg[SZ_ERROR_MESSAGE];
int i;
/* load charstats information */
errno = 0;
/* open the charstats file */
if ((charstats_file = fopen(CHARSTATS_FILE, "r")) == NULL) {
sprintf(error_msg,
"[0.0.0.0:%d] fopen of %s failed Do_load_charstats_file: %s\n",
the_realm->serverPid, CHARSTATS_FILE, strerror(errno));
Do_log_error(error_msg);
exit(CHARSTATS_FILE_ERROR);
}
/* read each line of the monster file */
for (i = 0; i < NUM_CHARS; i++) {
/* read the character name which is on its own line */
if (fgets(the_realm->charstats[i].class_name, SZ_CLASS_NAME,
charstats_file) == NULL) {
sprintf(error_msg, "[0.0.0.0:%d] fgets of %s failed on call number %d in Do_load_charstats_file.\n", the_realm->serverPid, CHARSTATS_FILE, i);
Do_log_error(error_msg);
exit(CHARSTATS_FILE_ERROR);
}
/* reEmove trailing blanks */
Do_truncstring(the_realm->charstats[i].class_name);
/* read the stat line for each monster */
if (fscanf(charstats_file, "%c %lf %lf %lf %lf %d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n",
&the_realm->charstats[i].short_class_name,
&the_realm->charstats[i].max_brains,
&the_realm->charstats[i].max_mana,
&the_realm->charstats[i].weakness,
&the_realm->charstats[i].goldtote,
&the_realm->charstats[i].ring_duration,
&the_realm->charstats[i].quickness.base,
&the_realm->charstats[i].quickness.interval,
&the_realm->charstats[i].quickness.increase,
&the_realm->charstats[i].strength.base,
&the_realm->charstats[i].strength.interval,
&the_realm->charstats[i].strength.increase,
&the_realm->charstats[i].mana.base,
&the_realm->charstats[i].mana.interval,
&the_realm->charstats[i].mana.increase,
&the_realm->charstats[i].energy.base,
&the_realm->charstats[i].energy.interval,
&the_realm->charstats[i].energy.increase,
&the_realm->charstats[i].brains.base,
&the_realm->charstats[i].brains.interval,
&the_realm->charstats[i].brains.increase,
&the_realm->charstats[i].magiclvl.base,
&the_realm->charstats[i].magiclvl.interval,
&the_realm->charstats[i].magiclvl.increase) != 24) {
/* exit if we didn't read 24 items */
sprintf(error_msg, "[0.0.0.0:%d] fscanf of %s failed on call number %d in Do_load_charstats_file.\n", the_realm->serverPid, CHARSTATS_FILE, i);
Do_log_error(error_msg);
exit(CHARSTATS_FILE_ERROR);
}
}
/* close the charstats file */
fclose(charstats_file);
/* all done here */
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_load_shopitems_file(struct realm_t *the_realm)
/
/ FUNCTION: To load saved configuration information
/
/ AUTHOR: Brian Kelly, 6/29/99
/
/ ARGUMENTS:
/ struct realm_t *the_realm - pointer to the realm strcture
/
/ RETURN VALUE: none
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
/ - strip non-printing characters (unless Wizard)
/ - echo, if desired
/ - redraw the screen if CH_REDRAW is entered
/ - read in only 'mx - 1' characters or less characters
/ - nul-terminate string, and throw away newline
/
/ 'mx' is assumed to be at least 2.
/
*************************************************************************/
Do_load_shopitems_file(struct realm_t *the_realm)
{
FILE *shopitems_file;
char error_msg[SZ_ERROR_MESSAGE];
int i;
/* load shopitems information */
errno = 0;
/* open the shopitems file */
if ((shopitems_file = fopen(SHOPITEMS_FILE, "r")) == NULL) {
sprintf(error_msg,
"[0.0.0.0:%d] fopen of %s failed in Do_load_shopitems_file: %s\n",
the_realm->serverPid, SHOPITEMS_FILE, strerror(errno));
Do_log_error(error_msg);
exit(SHOPITEMS_FILE_ERROR);
}
/* read each line of the monster file */
for (i = 0; i < NUM_ITEMS; i++) {
/* read the character name which is on its own line */
if (fgets(the_realm->shop_item[i].item, SZ_ITEMS, shopitems_file)
== NULL) {
sprintf(error_msg, "[0.0.0.0:%d] fgets of %s failed on call number %d in Do_load_shopitems_file.\n", the_realm->serverPid, SHOPITEMS_FILE, i);
Do_log_error(error_msg);
exit(SHOPITEMS_FILE_ERROR);
}
/* reEmove trailing blanks */
Do_truncstring(the_realm->shop_item[i].item);
/* read the stat line for each item */
if (fscanf(shopitems_file, "%lf\n", &the_realm->shop_item[i].cost)
!= 1) {
/* exit if we didn't read 24 items */
sprintf(error_msg, "[0.0.0.0:%d] fscanf of %s failed on call number %d in Do_load_shopitems_file.\n", the_realm->serverPid, SHOPITEMS_FILE, i);
Do_log_error(error_msg);
exit(SHOPITEMS_FILE_ERROR);
}
}
/* close the charstats file */
fclose(shopitems_file);
/* all done here */
return;
}
/************************************************************************
/
/ FUNCTION NAME: void Do_close(struct server_t *server)
/
/ FUNCTION: To close the program's data files
/
/ AUTHOR: Brian Kelly, 4/22/99
/
/ ARGUMENTS:
/ struct server_t *s - address of the server's main data strcture
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
/ - strip non-printing characters (unless Wizard)
/ - echo, if desired
/ - redraw the screen if CH_REDRAW is entered
/ - read in only 'mx - 1' characters or less characters
/ - nul-terminate string, and throw away newline
/
/ 'mx' is assumed to be at least 2.
/
*************************************************************************/
void Do_close(struct server_t *s)
{
FILE *data_file;
struct realm_object_t *object_ptr, *object_ptr2;
struct realm_state_t *state_ptr;
char error_msg[SZ_ERROR_MESSAGE];
int error;
state_ptr = (struct realm_state_t *) Do_malloc(SZ_REALM_STATE);
state_ptr->kings_gold = s->realm.kings_gold;
strcpy(state_ptr->king_name, s->realm.king_name);
strcpy(state_ptr->valar_name, s->realm.valar_name);
/* open the data file - for saving kings, valars, and corpses */
errno = 0;
if ((data_file = fopen(DATA_FILE, "w")) == NULL) {
sprintf(error_msg, "[0.0.0.0:%d] fopen of %s failed in Do_close: %s\n",
s->realm.serverPid, DATA_FILE, strerror(errno));
Do_log_error(error_msg);
exit(DATA_FILE_ERROR);
}
if (fwrite((void *) state_ptr, SZ_REALM_STATE, 1, data_file)
!= 1) {
sprintf(error_msg,
"[0.0.0.0:%d] fwrite of %s's realm state failed in Do_close: %d\n",
s->realm.serverPid, DATA_FILE, ferror(data_file));
Do_log_error(error_msg);
fclose(data_file);
exit(DATA_FILE_ERROR);
}
/* destroy the temporary realm state object */
free((void *)state_ptr);
/* first entry is king's gold as double float */
/*
if (fwrite((void *)&s->realm.kings_gold, sizeof(double), 1, data_file)
!= 1) {
sprintf(error_msg,
"[0.0.0.0:%d] fwrite of %s failed in Do_close: %d\n",
s->realm.serverPid, DATA_FILE, ferror(data_file));
Do_log_error(error_msg);
fclose(data_file);
exit(DATA_FILE_ERROR);
}
*/
/* all remaining items are realm objects */
object_ptr = s->realm.objects;
/* while there is an item in the list of realm objects */
while (object_ptr != NULL) {
/* write the object if it is a corpse, holy grail or treasure */
if (object_ptr->type == HOLY_GRAIL || object_ptr->type == CORPSE ||
object_ptr->type == TREASURE_TROVE) {
/* write the object to the data file */
if (fwrite((void *)object_ptr, SZ_REALM_OBJECT, 1, data_file) !=
1) {
sprintf(error_msg,
"[0.0.0.0:%d] fwrite of %s failed in Do_close(2): %d\n",
s->realm.serverPid, DATA_FILE, ferror(data_file));
Do_log_error(error_msg);
fclose(data_file);
exit(DATA_FILE_ERROR);
}
/* if the object is a corpse object */
if (object_ptr->type == CORPSE) {
/* write the character record with it */
if (fwrite((void *)object_ptr->arg1, SZ_PLAYER, 1, data_file)
!= 1) {
sprintf(error_msg,
"[0.0.0.0:%d] fwrite of %s failed in Do_close(3): %d\n",
s->realm.serverPid, DATA_FILE, ferror(data_file));
Do_log_error(error_msg);
fclose(data_file);
exit(DATA_FILE_ERROR);
}
free((void *)object_ptr->arg1);
}
}
/* point to the next realm object */
object_ptr2 = object_ptr;
object_ptr = object_ptr->next_object;
free((void*)object_ptr2);
}
/* close the data file */
fclose(data_file);
return; /* no problems */
}
/************************************************************************
/
/ FUNCTION NAME: Do_hide_grail(struct *realm_t, int level)
/
/ FUNCTION: To load saved configuration information
/
/ AUTHOR: E. A. Estes, 12/4/85
/ Brian Kelly, 8/17/99
/
/ ARGUMENTS:
/ struct realm_t *the_realm - pointer to the realm
/
/ RETURN VALUE: short error
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
/ - strip non-printing characters (unless Wizard)
/ - echo, if desired
/ - redraw the screen if CH_REDRAW is entered
/ - read in only 'mx - 1' characters or less characters
/ - nul-terminate string, and throw away newline
/
/ 'mx' is assumed to be at least 2.
/
*************************************************************************/
int Do_hide_grail(the_realm, level)
struct realm_t *the_realm;
int level;
{
double distance;
char error_msg[SZ_ERROR_MESSAGE];
/* WARNING: Realm should already be locked when function is called */
/* or it shouldn't matter (startup) */
struct realm_object_t *object_ptr;
object_ptr = the_realm->objects;
while (object_ptr != NULL) {
if (object_ptr->type == HOLY_GRAIL) {
sprintf(error_msg,
"[0.0.0.0:%d] Do_hide_grail found a holy grail already in the realm.",
the_realm->serverPid);
Do_log_error(error_msg);
return;
}
object_ptr = object_ptr->next_object;
}
if (level < 3000) {
level = 3000;
}
/* create a holy grail realm object */
object_ptr = (struct realm_object_t *) Do_malloc(SZ_REALM_OBJECT);
object_ptr->type = HOLY_GRAIL;
/* place grail within point of no return */
for (;;) {
object_ptr->x = 0.0;
object_ptr->y = 0.0;
Do_move_close(&object_ptr->x, &object_ptr->y, 1000000.0);
Do_distance(0.0, object_ptr->x, 0.0, object_ptr->y, &distance);
if (distance >= level * 100) {
break;
}
}
object_ptr->next_object = the_realm->objects;
the_realm->objects = object_ptr;
}
/************************************************************************
/
/ FUNCTION NAME: Do_hide_trove(struct *realm_t)
/
/ FUNCTION: To load saved configuration information
/
/ AUTHOR: E. A. Estes, 12/4/85
/ Brian Kelly, 5/9/01
/
/ ARGUMENTS:
/ struct realm_t *the_realm - pointer to the realm
/
/ RETURN VALUE: short error
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
/ - strip non-printing characters (unless Wizard)
/ - echo, if desired
/ - redraw the screen if CH_REDRAW is entered
/ - read in only 'mx - 1' characters or less characters
/ - nul-terminate string, and throw away newline
/
/ 'mx' is assumed to be at least 2.
/
*************************************************************************/
int Do_hide_trove(struct realm_t *the_realm)
{
double distance;
char error_msg[SZ_ERROR_MESSAGE];
struct realm_object_t *object_ptr;
/* WARNING: Realm should already be locked when function is called */
/* or it shouldn't matter (startup) */
object_ptr = the_realm->objects;
while(object_ptr != NULL) {
if (object_ptr->type == TREASURE_TROVE) {
sprintf(error_msg,
"[0.0.0.0:%d] Do_hide_trove found a trove already in the realm.\n",
the_realm->serverPid);
Do_log_error(error_msg);
return;
}
object_ptr = object_ptr->next_object;
}
/* create a treasure_trove realm object */
object_ptr = (struct realm_object_t *) Do_malloc(SZ_REALM_OBJECT);
object_ptr->type = TREASURE_TROVE;
for (;;) {
object_ptr->x = 0.0;
object_ptr->y = 0.0;
Do_move_close(&object_ptr->x, &object_ptr->y, 1400.0);
Do_distance(0.0, object_ptr->x, 0.0, object_ptr->y, &distance);
if (distance >= 600) {
break;
}
}
object_ptr->next_object = the_realm->objects;
the_realm->objects = object_ptr;
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_backup_restore()
/
/ FUNCTION: To load saved configuration information
/
/ AUTHOR: Brian Kelly, 11/26/99
/
/ ARGUMENTS:
/ struct realm_t *the_realm - pointer to the realm
/
/ RETURN VALUE: short error
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
/ - strip non-printing characters (unless Wizard)
/ - echo, if desired
/ - redraw the screen if CH_REDRAW is entered
/ - read in only 'mx - 1' characters or less characters
/ - nul-terminate string, and throw away newline
/
/ 'mx' is assumed to be at least 2.
/
*************************************************************************/
Do_backup_restore()
{
FILE *backup_file;
FILE *character_file;
struct player_t the_player;
char error_msg[SZ_ERROR_MESSAGE];
int restoreCount = 0;
/* open the backup file */
errno = 0;
if ((backup_file=fopen(BACKUP_FILE, "r")) == NULL) {
/* No backup file? Cool! */
return;
}
/* open the character file */
errno = 0;
if ((character_file=fopen(CHARACTER_FILE, "a")) == NULL) {
sprintf(error_msg,
"[0.0.0.0:?] fopen of %s failed in Do_backup_restore: %s\n",
CHARACTER_FILE, strerror(errno));
Do_log_error(error_msg);
fclose(backup_file);
return;
}
/* read each line of the backup file */
errno = 0;
while (fread((void *)&the_player, SZ_PLAYER, 1, backup_file) == 1) {
/* write the character to the charcter file */
if (fwrite((void *)&the_player, SZ_PLAYER, 1, character_file) != 1) {
sprintf(error_msg,
"[0.0.0.0:?] fwrite of %s failed in Do_backup_restore: %s\n",
CHARACTER_FILE, strerror(errno));
Do_log_error(error_msg);
fclose(backup_file);
fclose(character_file);
return;
}
else {
sprintf(error_msg, "[0.0.0.0:?] %s restored\n", the_player.lcname);
Do_log(SERVER_LOG, error_msg);
Do_log(GAME_LOG, error_msg);
++restoreCount;
}
}
/* delete the old backup file */
remove(BACKUP_FILE);
fclose(backup_file);
fclose(character_file);
if (restoreCount) {
sprintf(error_msg, "Server restored %d characters.\n", restoreCount);
Do_log(SERVER_LOG, error_msg);
}
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_get_next_tag()
/
/ FUNCTION: To load saved configuration information
/
/ AUTHOR: Brian Kelly, 01/18/01
/
/ ARGUMENTS:
/ struct realm_t *the_realm - pointer to the realm
/
/ RETURN VALUE: short error
/
/ MODULES CALLED: wmove(), _filbuf(), clearok(), waddstr(), wrefresh(),
/ wclrtoeol()
/
/ DESCRIPTION:
/ Read a string from the keyboard.
/ This routine is specially designed to:
/
/ - strip non-printing characters (unless Wizard)
/ - echo, if desired
/ - redraw the screen if CH_REDRAW is entered
/ - read in only 'mx - 1' characters or less characters
/ - nul-terminate string, and throw away newline
/
/ 'mx' is assumed to be at least 2.
/
*************************************************************************/
int Do_get_next_tag()
{
FILE *the_file;
char error_msg[SZ_ERROR_MESSAGE];
struct tag_t readTag;
struct tagged_t readTagged;
int lastTagNumber = 0;
if ((the_file=fopen(TAG_FILE, "r")) != NULL) {
/* run through the tag entries */
while (fread((void *)&readTag, SZ_TAG, 1, the_file) == 1) {
/* see if this is the highest numbered tag */
if (readTag.number > lastTagNumber) {
lastTagNumber = readTag.number;
}
}
fclose(the_file);
}
if ((the_file=fopen(TAGGED_FILE, "r")) != NULL) {
/* run through the tag entries */
while (fread((void *)&readTagged, SZ_TAGGED, 1, the_file) == 1) {
/* see if this is the highest numbered tag */
if (readTagged.tagNumber > lastTagNumber) {
lastTagNumber = readTagged.tagNumber;
}
}
fclose(the_file);
}
return lastTagNumber + 1;
}