Code:
*/
/*
* All source files are set up for 'vi' with shiftwidth=4, tabstop=8.
*/
/**/
#include "include.h"
/* global variables */
int server_hook;
char randomStateBuffer[STATELEN];
struct random_data randData;
/*
* main.c Main entry point for Phantasia
*/
/***************************************************************************
/ FUNCTION NAME: main()
/
/ FUNCTION: initialize state, and call main process
/
/ AUTHOR: E. A. Estes, 12/4/85
/ MODIFIED: Brian Kelly, 4/6/99
/
/ ARGUMENTS:
/ int argc - argument count
/ char **argv - argument vector
/
/ RETURN VALUE: none
/
/ MODULES CALLED: monstlist(), checkenemy(), activelist(),
/ throneroom(), checkbattle(), readmessage(), changestats(), writerecord()
,
/ tradingpost(), adjuststats(), recallplayer(), displaystats(), checktampe
red(),
/ fabs(), rollnewplayer(), time(), exit(), sqrt(), floor(), wmove(),
/ signal(), strcat(), purgeoldplayers(), getuid(), isatty(), wclear(),
/ strcpy(), system(), altercoordinates(), cleanup(), waddstr(), procmain()
,
/ playinit(), leavegame(), localtime(), getanswer(), neatstuff(), initials
tate(),
/ scorelist(), titlelist()
/
/ GLOBAL INPUTS: *Login, Throne, Wizard, Player, *stdscr, Changed, Databuf[],
/ Fileloc, Stattable[]
/
/ GLOBAL OUTPUTS: Wizard, Player, Changed, Fileloc, Timeout, *Statptr
/
/ DESCRIPTION:
/ Process arguments, initialize program, and loop forever processing
/ player input.
/
****************************************************************************/
main(argc, argv)
int argc;
char *argv[];
{
/* set up the main server structure */
struct server_t server;
/* set up a signal structre */
struct sigaction sigAct;
/* set the program to run */
server.run_level = RUN_SERVER;
/* process arguments */
while (--argc && (*++argv)[0] == '-')
{
switch ((*argv)[1])
{
/* purge character file */
case 'c':
Do_purge_characters();
break;
/* initialize, then bring down server */
case 'q':
server.run_level = FAST_SHUTDOWN;
break;
/* purge scoreboard file */
case 's':
Do_purge_scoreboard();
break;
default: /* for all other answers */
printf("usage: phantasia [-c][-q][-s]\n");
printf(" -c: Purge character roster\n");
printf(" -q: Quit as soon as possible\n");
printf(" -s: Purge scoreboard\n");
exit(1);
}
}
/* block SIGINT, SIGTERM, SIGIO, SIGALRM and SIGUSR1 til we're ready */
sigemptyset(&sigAct.sa_mask);
sigaddset(&sigAct.sa_mask, SIGINT);
sigaddset(&sigAct.sa_mask, SIGTERM);
sigaddset(&sigAct.sa_mask, SIGIO);
sigaddset(&sigAct.sa_mask, SIGALRM);
sigaddset(&sigAct.sa_mask, SIGUSR1);
/* this routine will block for created threads as well */
if (pthread_sigmask(SIG_BLOCK, &sigAct.sa_mask, NULL) < 0) {
printf("Error blocking signals.\n");
exit(1);
}
/* set up structures, variables and files */
Init_server(&server);
/* run the main loop */
Do_main_loop(&server);
/* destroy structures and close files */
Do_close(&server);
Do_log(SERVER_LOG, "Server is shut down.\n");
exit(0); /* thanks for playing */
}
/***************************************************************************
/ FUNCTION NAME: Do_main_loop(struct server_t *server)
/
/ FUNCTION: initialize state, and call main process
/
/ AUTHOR: Brian Kelly, 4/12/99
/
/ ARGUMENTS:
/ struct server_t *s - address of the sever's main data structure
/
/ RETURN VALUE: none
/
/ MODULES CALLED: monstlist(), checkenemy(), activelist(),
/ throneroom(), checkbattle(), readmessage(), changestats(), writerecord()
,
/ tradingpost(), adjuststats(), recallplayer(), displaystats(), checktampe
red(),
/ fabs(), rollnewplayer(), time(), exit(), sqrt(), floor(), wmove(),
/ signal(), strcat(), purgeoldplayers(), getuid(), isatty(), wclear(),
/ strcpy(), system(), altercoordinates(), cleanup(), waddstr(), procmain()
,
/ playinit(), leavegame(), localtime(), getanswer(), neatstuff(), initials
tate(),
/ scorelist(), titlelist()
/
/ DESCRIPTION:
/ Process arguments, initialize program, and loop forever processing
/ player input.
/
****************************************************************************/
Do_main_loop(struct server_t *s)
{
sigset_t sigMask;
struct it_combat_t *combat_ptr;
struct game_t *game_ptr, **game_ptr_ptr;
struct event_t *event_ptr;
int error, theSignal;
time_t shutdownStart;
char error_msg[SZ_ERROR_MESSAGE];
sprintf(error_msg, "Server started up. pid=%d\n",
s->realm.serverPid);
Do_log(SERVER_LOG, error_msg);
sigemptyset(&sigMask);
sigaddset(&sigMask, SIGINT);
sigaddset(&sigMask, SIGTERM);
sigaddset(&sigMask, SIGIO);
/*
sigaddset(&sigMask, SIGALRM);
*/
sigaddset(&sigMask, SIGUSR1);
while (s->run_level != FAST_SHUTDOWN) {
/* wait for a signal to do anything */
sigwait(&sigMask, &theSignal);
/*
sleep(.1);
theSignal = SIGIO;
*/
/* on SIGIO, check for new connections and inactive games */
if (theSignal == SIGIO) {
/* if we're not shutting down check for new connections */
if (s->run_level == RUN_SERVER) {
error = Do_accept_connections(s);
if (error) {
sprintf(error_msg,
"[0.0.0.0:%d] Do_accept_connections returned an error of %d.\n",
s->realm.serverPid, error);
Do_log_error(error_msg);
server_hook = SHUTDOWN;
}
}
}
/* a SIGUSER says to clean up a thread */
else if (theSignal == SIGUSR1) {
/* check for inactive games */
Do_lock_mutex(&s->realm.realm_lock);
game_ptr_ptr = &s->realm.games;
while (*game_ptr_ptr != NULL) {
if ((*game_ptr_ptr)->cleanup_thread) {
game_ptr = *game_ptr_ptr;
*game_ptr_ptr = game_ptr->next_game;
close(game_ptr->the_socket);
pthread_join(game_ptr->the_thread, NULL);
Do_destroy_mutex(&game_ptr->events_in_lock);
free((void *)game_ptr);
--s->num_games;
}
else {
game_ptr_ptr = &((*game_ptr_ptr)->next_game);
}
}
Do_unlock_mutex(&s->realm.realm_lock);
}
/* SIGTERM shuts the server down quickly */
else if (theSignal == SIGTERM) {
server_hook = FAST_SHUTDOWN;
}
/* SIGIO is a normal shutdown */
else if (theSignal == SIGINT) {
server_hook = SHUTDOWN;
}
else {
sprintf(error_msg,
"[0.0.0.0:%d] sigwait caught bad signal %d in Do_main_loop.\n",
s->realm.serverPid, theSignal);
Do_log_error(error_msg);
}
/* check to see if a thread wants the server down */
if (server_hook != s->run_level) {
if (server_hook == LEISURE_SHUTDOWN && s->num_games == 0) {
Do_log(SERVER_LOG, "Starting a leisure shutdown.\n");
server_hook = SHUTDOWN;
shutdownStart = time(NULL);
}
/* if requested to die now */
else if (server_hook == HARD_SHUTDOWN) {
Do_log(SERVER_LOG, "Hard shutdown ordered. Exiting Now.\n");
/* hasta la vista, baby */
exit(0);
}
/* check for a quick shutdown */
else if (server_hook == FAST_SHUTDOWN) {
Do_log(SERVER_LOG, "Starting a fast shutdown.\n");
s->run_level = FAST_SHUTDOWN;
}
/* normal shutdown */
else if (server_hook == SHUTDOWN) {
Do_log(SERVER_LOG, "Starting a normal shutdown.\n");
s->run_level = SHUTDOWN;
shutdownStart = time(NULL);
}
}
/* If shutting down, quit if nobody's on or time's expired */
if (s->run_level == SHUTDOWN && (s->num_games == 0 ||
time(NULL) - shutdownStart > 300)) {
s->run_level = FAST_SHUTDOWN;
}
}
return;
}
/***************************************************************************
/ FUNCTION NAME: Do_start_thread(struct client_t *c)
/
/ FUNCTION: Handle thread startup
/
/ AUTHOR: Brian Kelly, 4/23/99
/
/ ARGUMENTS:
/ struct client_t *c - structure containing all thread info
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/ Process arguments, initialize program, and loop forever processing
/ player input.
/
****************************************************************************/
Do_start_thread(struct client_t *c)
{
int error;
char error_msg[SZ_ERROR_MESSAGE], string_buffer[SZ_LINE];
char *out;
struct sigaction sigAct;
struct event_t *eventPtr;
/* set the thread's process id */
Do_lock_mutex(&c->realm->realm_lock);
c->game->clientPid = getpid();
Do_unlock_mutex(&c->realm->realm_lock);
/* record this connection */
sprintf(c->connection_id, "?:%s:%d", c->IP, c->game->clientPid);
sprintf(error_msg, "[%s] Connection on socket %d.\n",
c->connection_id, c->socket);
Do_log(CONNECTION_LOG, error_msg);
/* set the socket so I/O notifies this thread */
if (fcntl(c->socket, F_SETOWN, c->game->clientPid) < 0) {
sprintf(error_msg,
"Thread %d returned an error on fcntl F_SETOWN.\n",
c->socket);
Do_log_error(error_msg);
Do_send_error(c, error_msg);
c->run_level = EXIT_THREAD;
c->socket_up = FALSE;
}
if (fcntl(c->socket, F_SETFL, O_ASYNC) < 0) {
sprintf(error_msg,
"Thread %d returned an error on fcntl F_SETFL.\n",
c->socket);
Do_log_error(error_msg);
Do_send_error(c, error_msg);
c->run_level = EXIT_THREAD;
c->socket_up = FALSE;
}
/* handshake the client */
Do_handshake(c);
/* see if this socket should be rejected */
Do_check_tags(c);
/* modify stats from this ip - (checks for excessive connections) */
Do_tally_ip(c, TRUE, 0);
/* find all the current players and list them */
Do_lock_mutex(&c->realm->realm_lock);
Do_starting_spec(c);
c->game->sendEvents = TRUE;
Do_unlock_mutex(&c->realm->realm_lock);
/* call the main thread loop */
Do_thread_loop(c);
/* clean up any events we may have */
Do_lock_mutex(&c->realm->realm_lock);
c->game->sendEvents = FALSE;
Do_unlock_mutex(&c->realm->realm_lock);
Do_check_events_in(c);
/* pull death name out of limbo if necessary */
if (c->previousName[0] != '\0') {
Do_release_name(c, c->previousName);
}
/* clean up socket connection */
if (c->socket_up) {
Do_send_int(c, CLOSE_CONNECTION_PACKET);
Do_send_buffer(c);
}
/* log the connection */
sprintf(error_msg, "[%s] Leaving the game after %d seconds.\n",
c->connection_id, time(NULL) - c->date_connected);
Do_log(CONNECTION_LOG, &error_msg);
/* tell the server to clean up */
c->game->cleanup_thread = TRUE;
free((void *) c);
kill(c->realm->serverPid, SIGUSR1);
/* leave the game */
pthread_exit(0);
}
/***************************************************************************
/ FUNCTION NAME: Do_thread_loop(struct client_t *c)
/
/ FUNCTION: The main loop for threads
/
/ AUTHOR: Brian Kelly, 4/23/99
/
/ ARGUMENTS:
/ struct client_t *c - structure containing all thread info
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/ Process arguments, initialize program, and loop forever processing
/ player input.
/
****************************************************************************/
Do_thread_loop(struct client_t *c)
{
char error_msg[SZ_ERROR_MESSAGE];
/* start the main loop */
while (c->run_level != EXIT_THREAD) {
/* make characters log in first */
if (c->run_level == SIGNING_IN) {
/* print out the title page */
Do_title_page(c);
/* have the user log in */
Do_get_account(c);
/* see if the game is shutting down */
Do_shutdown_check(c);
}
/* if the player has no character - get one */
if (c->run_level == CHAR_SELECTION) {
/* empty out the player strcture */
Do_init_player(c);
/* Get a character */
Do_get_character(c);
}
if (c->run_level == PLAY_GAME) {
/* approve the entrance */
Do_approve_entrance(c);
}
/* if ready to play, enter the game */
if (c->run_level == PLAY_GAME) {
/* announce character entrance */
Do_entering_character(c);
/* play the game */
Do_play_loop(c);
/* remove the character from play */
Do_leaving_character(c);
}
/* see if the character needs to be saved */
if (c->run_level == SAVE_AND_CONTINUE ||
c->run_level == SAVE_AND_EXIT) {
Do_handle_save(c);
}
/* regardless, remove the backup */
else {
Do_backup_save(c, FALSE);
}
/* ask if player wishes to go again */
if (c->run_level == GO_AGAIN) {
/* ask if the player wants to continue */
Do_ask_continue(c);
}
/* see if the game is shutting down */
Do_shutdown_check(c);
}
return;
}
/***************************************************************************
/ FUNCTION NAME: Do_play_loop(struct client_t *c)
/
/ FUNCTION: Default activity when no events are pending
/
/ AUTHOR: Brian Kelly, 4/23/99
/
/ ARGUMENTS:
/ struct client_t *c - structure containing all thread info
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/ Process arguments, initialize program, and loop forever processing
/ player input.
/
****************************************************************************/
Do_play_loop(struct client_t *c)
{
struct event_t *event_ptr;
while (c->run_level == PLAY_GAME
|| (c->events != NULL && c->player.energy > 0)) {
/* age the player */
Do_age(c);
/* if there are events to handle */
if (c->events != NULL) {
/* remove the next event */
event_ptr = c->events;
c->events = event_ptr->next_event;
/* take care of it */
Do_handle_event(c, event_ptr);
}
else {
/* If no events, start a new turn */
Do_game_turn(c);
/* check for monsters, guru's, etc. */
if (!c->player.cloaked
&& (c->wizard < 3)
&& (c->player.location == PL_REALM || c->player.location == PL_EDGE)
&& (c->run_level == PLAY_GAME))
Do_random_events(c);
}
/* file any events from outside the thread */
Do_check_events_in(c);
/* see if the game is shutting down */
Do_shutdown_check(c);
/* if the socket is down, leave the game */
if (!c->socket_up && c->run_level == PLAY_GAME) {
c->run_level = SAVE_AND_EXIT;
}
}
return;
}
/***************************************************************************
/ FUNCTION NAME: Do_game_turn(struct client_t *c)
/
/ FUNCTION: Default activity when no events are pending
/
/ AUTHOR: E. A. Estes, 12/4/85
/ Brian Kelly, 5/8/99
/
/ ARGUMENTS:
/ struct client_t *c - structure containing all thread info
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/ Process arguments, initialize program, and loop forever processing
/ player input.
/
****************************************************************************/
Do_game_turn(struct client_t *c)
{
struct event_t *event_ptr;
struct button_t buttons; /* input */
long ch;
int rc;
int loop;
char string_buffer[SZ_LINE];
double dtemp;
bool postFlag;
float ftemp;
if (c->player.location == PL_EDGE) {
Do_send_line(c,
"An old wooden sign here says, 'This is the edge of the realm.\n");
Do_send_line(c, "I would strongly advise going no further.'\n");
}
/* see if the player is on a trading post and not cloaked */
postFlag = FALSE;
if (fabs(c->player.x) == fabs(c->player.y) && c->player.location !=
PL_THRONE && !c->player.cloaked) {
dtemp = sqrt(fabs(c->player.x)/100.0);
if (floor(dtemp) == dtemp) {
postFlag = TRUE;
Do_send_line(c, "You stand in front of a trading post.\n");
}
}
Do_clear_buttons(&buttons, 0);
/*
if (c->player.special_type != SC_VALAR) {
*/
strcpy(buttons.button[0], "Rest\n");
/*
}
*/
/* print status line */
strcpy(buttons.button[1], "Move To\n");
buttons.compass = TRUE;
strcpy(buttons.button[2], "Info\n");
strcpy(buttons.button[7], "Quit\n");
/*
examine
rest
do nothing
*/
if (postFlag) {
strcpy(buttons.button[3], "Enter Post\n");
} else if (!c->player.cloaked && c->player.location == PL_REALM) {
strcpy(buttons.button[3], "Hunt\n");
}
if (c->player.cloaked) {
strcpy(buttons.button[4], "Uncloak\n");
}
else if (c->player.level >= MEL_CLOAK && c->player.magiclvl >= ML_CLOAK) {
strcpy(buttons.button[4], "Cloak\n");
}
/*
if (c->player.level >= MEL_TELEPORT && c->player.magiclvl >= ML_TELEPORT &&
c->player.special_type != SC_VALAR) {
*/
if (c->player.level >= MEL_TELEPORT && c->player.magiclvl >= ML_TELEPORT &&
!c->player.cloaked) {
strcpy(buttons.button[5], "Teleport\n");
}
if (c->wizard == 2) {
strcpy(buttons.button[6], "Cantrip\n");
}
else if (c->wizard > 3) {
strcpy(buttons.button[6], "Administrate\n");
}
else if (c->wizard) {
strcpy(buttons.button[6], "Moderate\n");
}
else if (c->player.location == PL_THRONE && c->player.special_type
== SC_STEWARD && !c->player.cloaked) {
strcpy(buttons.button[6], "Enact\n");
}
else if (c->player.location == PL_THRONE && c->player.special_type
== SC_KING && !c->player.cloaked) {
strcpy(buttons.button[6], "Decree\n");
}
else if ((c->player.special_type == SC_COUNCIL || c->player.special_type
== SC_EXVALAR) && !c->player.cloaked) {
strcpy(buttons.button[6], "Intervene\n");
}
else if (c->player.special_type == SC_VALAR && !c->player.cloaked) {
strcpy(buttons.button[6], "Command\n");
}
else if (c->player.level < 10) {
strcpy(buttons.button[6], "Help\n");
}
if (Do_buttons(c, &ch, &buttons) != S_NORM) {
Do_send_clear(c);
return;
}
Do_send_clear(c);
/* if the valar asks to move, change his request to a null */
/*
if (c->player.special_type == SC_VALAR && (ch == 0 || (ch >= 8 &&
ch != 12))) {
ch = 127;
}
*/
/* create an event to handle the player action */
event_ptr = (struct event_t *) Do_create_event();
event_ptr->to = c->game;
event_ptr->from = c->game;
switch (ch) {
case 8: /* move north-west */
event_ptr->type = MOVE_EVENT;
event_ptr->arg1 = c->player.x - Do_anglemove(c);
event_ptr->arg2 = c->player.y + Do_anglemove(c);
event_ptr->arg3 = A_SPECIFIC;
break;
case 9: /* move up/north */
event_ptr->type = MOVE_EVENT;
event_ptr->arg1 = c->player.x;
event_ptr->arg2 = c->player.y + Do_maxmove(c);
event_ptr->arg3 = A_SPECIFIC;
break;
case 10: /* move north-east */
event_ptr->type = MOVE_EVENT;
event_ptr->arg1 = c->player.x + Do_anglemove(c);
event_ptr->arg2 = c->player.y + Do_anglemove(c);
event_ptr->arg3 = A_SPECIFIC;
break;
case 11: /* move left/west */
event_ptr->type = MOVE_EVENT;
event_ptr->arg1 = c->player.x - Do_maxmove(c);
event_ptr->arg2 = c->player.y;
event_ptr->arg3 = A_SPECIFIC;
break;
case 13: /* move right/east */
event_ptr->type = MOVE_EVENT;
event_ptr->arg1 = c->player.x + Do_maxmove(c);
event_ptr->arg2 = c->player.y;
event_ptr->arg3 = A_SPECIFIC;
break;
case 14: /* move south-west */
event_ptr->type = MOVE_EVENT;
event_ptr->arg1 = c->player.x - Do_anglemove(c);
event_ptr->arg2 = c->player.y - Do_anglemove(c);
event_ptr->arg3 = A_SPECIFIC;
break;
case 15: /* move down/south */
event_ptr->type = MOVE_EVENT;
event_ptr->arg1 = c->player.x;
event_ptr->arg2 = c->player.y - Do_maxmove(c);
event_ptr->arg3 = A_SPECIFIC;
break;
case 16: /* move south-west */
event_ptr->type = MOVE_EVENT;
event_ptr->arg1 = c->player.x + Do_anglemove(c);
event_ptr->arg2 = c->player.y - Do_anglemove(c);
event_ptr->arg3 = A_SPECIFIC;
break;
case 1: /* move */
if (Do_coords_dialog(c, &event_ptr->arg1, &event_ptr->arg2,
"Where do you wish to move to?\n")) {
break;
}
Do_distance(c->player.x, event_ptr->arg1, c->player.y,
event_ptr->arg2, &dtemp);
if (dtemp > Do_maxmove(c)) {
Do_send_line(c, "That's too far to move in 1 step. Get closer by using the compass buttons in the lower-right corner.\n");
Do_more(c);
Do_send_clear(c);
}
else {
event_ptr->type = MOVE_EVENT;
event_ptr->arg3 = A_SPECIFIC;
}
break;
/* get information */
case 2:
event_ptr->type = INFORMATION_EVENT;
break;
case 7: /* good-bye */
c->run_level = SAVE_AND_CONTINUE;
break;
case 4: /* cloak */
if (c->player.cloaked || (c->player.level >= MEL_CLOAK &&
c->player.magiclvl >= ML_CLOAK)) {
event_ptr->type = CLOAK_EVENT;
}
break;
case 5: /* teleport */
event_ptr->type = TELEPORT_EVENT;
event_ptr->arg2 = FALSE; /* not Gwaihir */
if (c->player.location == PL_THRONE) {
event_ptr->arg3 = FALSE; /* teleport costs no mana */
}
else {
event_ptr->arg3 = TRUE; /* teleport costs mana */
}
break;
case 6: /* decree and intervention */
/* cantrips handled first since all other actions are available
off the cantrip menu */
if (c->wizard == 2) {
event_ptr->type = CANTRIP_EVENT;
}
else if (c->wizard > 3) {
event_ptr->type = ADMINISTRATE_EVENT;
}
else if (c->wizard) {
event_ptr->type = MODERATE_EVENT;
}
/* see if the player is allowed to enact */
else if (c->player.special_type == SC_STEWARD && c->player.location
== PL_THRONE && !c->player.cloaked) {
event_ptr->type = ENACT_EVENT;
}
/* see if the player is allowed to decree */
else if (c->player.special_type == SC_KING && c->player.location
== PL_THRONE && !c->player.cloaked) {
event_ptr->type = DECREE_EVENT;
}
else if ((c->player.special_type == SC_COUNCIL ||
c->player.special_type == SC_EXVALAR) && !c->player.cloaked) {
event_ptr->type = INTERVENE_EVENT;
}
else if (c->player.special_type == SC_VALAR && !c->player.cloaked) {
event_ptr->type = COMMAND_EVENT;
}
else if (c->player.level < 10) {
event_ptr->type = HELP_EVENT;
}
break;
case 3: /* hunt */
/* the valar cannot call monsters and no monsters on throne */
/* being cloaked is right out too */
if (postFlag) {
event_ptr->type = TRADING_EVENT;
} else if (!c->player.cloaked && c->player.location == PL_REALM) {
Do_sin(c, .001);
event_ptr->type = MONSTER_EVENT;
event_ptr->arg1 = MONSTER_CALL;
event_ptr->arg3 = SM_RANDOM; /* pick a monster normally */
}
break;
case 0:
case 12: /* rest */
event_ptr->type = REST_EVENT;
break;
/* default: NULL_EVENT stupid people deserve no reward */
}
if (event_ptr->type != NULL_EVENT) {
Do_handle_event(c, event_ptr);
}
else {
free((void *)event_ptr);
}
return;
}
/***************************************************************************
/ FUNCTION NAME: Do_random_events(struct client_t *c)
/
/ FUNCTION: Default activity when no events are pending
/
/ AUTHOR: Brian Kelly, 8/17/99
/
/ ARGUMENTS:
/ struct client_t *c - structure containing all thread info
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/ Process arguments, initialize program, and loop forever processing
/ player input.
/
****************************************************************************/
Do_random_events(struct client_t *c)
{
struct event_t *event_ptr;
/* to shred "backups" */
if ((c->player.quickness == 0)
&& (RND() >= .1 * c->player.degenerated)) {
event_ptr = (struct event_t *)Do_create_event();
event_ptr->type = MONSTER_EVENT;
event_ptr->arg1 = MONSTER_RANDOM;
event_ptr->arg3 = 16;
Do_file_event(c, event_ptr);
}
if (c->player.blind && RND() <= 0.0075) {
Do_send_line(c, "You've regained your sight!\n");
c->player.blind = FALSE;
/* update the player description */
Do_lock_mutex(&c->realm->realm_lock);
Do_player_description(c);
Do_unlock_mutex(&c->realm->realm_lock);
Do_more(c);
Do_send_clear(c);
}
if (RND() <= 0.0133) {
Do_send_self_event(c, MEDIC_EVENT);
}
if (RND() <= 0.0075) {
Do_send_self_event(c, GURU_EVENT);
}
if (RND() <= 0.005) {
event_ptr = (struct event_t *)Do_create_event();
event_ptr->type = PLAGUE_EVENT;
event_ptr->arg3 = 0;
Do_file_event(c, event_ptr);
}
if (RND() <= 0.0075) {
Do_send_self_event(c, VILLAGE_EVENT);
}
if (c->player.level < 3000) {
if (RND() <= 0.0033 + (c->player.level * .00000125)) {
Do_send_self_event(c, TAX_EVENT);
}
} else if (RND() <= 0.0033) {
Do_send_self_event(c, TAX_EVENT);
}
if (RND() <= 0.015) {
event_ptr = (struct event_t *)Do_create_event();
event_ptr->type = TREASURE_EVENT;
event_ptr->arg1 = c->player.circle;
event_ptr->arg3 = 1;
Do_file_event(c, event_ptr);
}
if (RND() <= 0.0075) {
event_ptr = (struct event_t *)Do_create_event();
event_ptr->type = TREASURE_EVENT;
event_ptr->arg1 = c->player.circle;
event_ptr->arg3 = 2;
Do_file_event(c, event_ptr);
}
if (RND() <= 0.20) {
event_ptr = (struct event_t *)Do_create_event();
event_ptr->type = MONSTER_EVENT;
event_ptr->arg1 = MONSTER_RANDOM;
event_ptr->arg3 = SM_RANDOM;
Do_file_event(c, event_ptr);
}
}