cdirt/ascii/
cdirt/data/BULL/
cdirt/data/ZONES/PENDING/
cdirt/pending/
cdirt/src/utils/
cdirt/utils/
#include <sys/stat.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>

#include "kernel.h"
#include "sendsys.h"
#include "group.h"
#include "mud.h"
#include "uaf.h"
#include "mobile.h"
#include "timing.h"
#include "locations.h"
#include "bprintf.h"
#include "log.h"
#include "fight.h"
#include "zones.h"
#include "rooms.h"
#include "parse.h"
#include "commands.h"
#include "wizard.h"
#include "spell.h"
#include "store.h"
#include "objsys.h"
#include "wizlist.h"

extern void p_sendto(int, char *);
extern void do_packet(int, char *);
extern void write_packet(int);
extern void load_zone(char *, Boolean);
#ifdef IO_STATS
  extern int cut_conns;
#endif

char *pwait = "&+W(&NPress &+Y[Return] &Nto enter " MUD_NAME "&+W)&N";
char *qwait = "&+W(&+wPress &+C[Return] &+wto continue, &+C'q' &+wto quit&+W)&*";
char *vismsg = "Enter Vis Level &+W(&N0-%d&+W)&N or '&+Wi&+w' for full invisibility &+C[Current: %d]: ";

static int vislev[] =
{0, LVL_ISTARI, LVL_ISTARI, LVL_ISTARI,
 LVL_ISTARI, LVL_ARCHWIZARD, LVL_DEMI,
 LVL_SHALAFI, LVL_GOD, LVL_CREATOR, LVL_MAX};

/* send a socket message, %H = host or user@host */
#define SOCK_FORMAT "&+B[&+CSocket (%d): &+W%s&+B]\n"

void sock_msg (char *format, ...) {
  int plx;
  int me = real_mynum;
  va_list pvar;
  char *hostptr, *userptr, *ptr;
  char buffer[200];
  char hostmsg[200];
  char usermsg[200];
  char sockmessage[200];

  if (is_host_silent(hostname(mynum)) || crashing)
    return;

  va_start (pvar, format);
  vsprintf (buffer, format, pvar);
  va_end(pvar);

  hostptr = hostmsg;
  userptr = usermsg;
  for (ptr = buffer ; *ptr ; ptr++) {
    if (*ptr != '%')
      *hostptr++ = *userptr++ = *ptr;
    else if (*(ptr + 1) == 'H') {
      strcpy(hostptr, hostname(mynum));
      strcpy(userptr, username(mynum));
      hostptr += strlen(hostname(mynum));
      userptr += strlen(username(mynum));
      ptr++;
    }
  }
  *hostptr = *userptr = 0;

  for (plx = 0 ; plx < max_players ; plx++) {
    if (is_in_game(plx) && ptstflg(plx, PFL_SEESOCKET) && 
	pvis(me) < plev(plx) && plx != me) {

      if (ptstflg(plx, PFL_SEEUSER))
	sprintf(sockmessage, SOCK_FORMAT, fildes(me), usermsg);
      else
	sprintf(sockmessage, SOCK_FORMAT, fildes(me), hostmsg);
      p_sendto(plx, sockmessage);
    }
  }
  setup_globals(me);
}

void push_input_handler (void (*h) (char *str))
{
  INP_HANDLER *i;

  i = NEW (INP_HANDLER, 1);
  i->next = inp_handler(real_mynum);
  i->inp_handler = h;
  inp_handler(real_mynum) = i;
}

void pop_input_handler (void)
{
  INP_HANDLER *i = inp_handler(real_mynum);
  INP_HANDLER *j;

  j = i->next;
  if (j != NULL) {
    inp_handler(real_mynum) = j;
    FREE (i);
  }
}

void replace_input_handler (void (*h) (char *str))
{
  phandler(real_mynum) = h;
}

/* creates a new player slot, init variables */

int find_free_player_slot (void) {
  int i;
  int k;

  for (i = 0; i < max_players && is_conn(i) ; i++);
  if (i >= max_players)
    i = -1;
  else {
    memset(&players[i], 0, sizeof(PLAYER_REC));
    memset(&ublock[i], 0, sizeof(UBLOCK_REC));
    memset(&rplrs[i], 0, sizeof(RPLR_REC));

    fildes(i) = polymorphed(i) = pconv(i) = phelping(i) = -1;
    pfollow(i) = snooptarget(i) = pgrouped(i) = -1;

    for (k = 0 ; k < 10 ; k++)
      rplrs[i].forget[k] = -1;

    for (k = 0 ; k < NUM_STORE_SLOTS ; k++)
      rplrs[i].storage[k] = -1;

    last_cmd(i) = logged_on(i) = global_clock;
    rlast_cmd(i) = logged_on(i) = global_clock;
    players[i].duration = NEW (SPELL_DURATION, 1);
    players[i].duration = NULL;
  }
  return i;
}

int find_pl_index (int fd) {
  int plx;

  plx = sock_fds[fd];
  if (plx > max_players || fildes(plx) != fd)
    return -1;
  else
    return plx;
}

void setup_globals (int plx) {
  int x;

  mynum = real_mynum = x = plx;
  if (x < 0 || x >= max_players) {
    cur_player = NULL;
    cur_ublock = NULL;
    mynum = real_mynum = -1;
  } 
  else {
    cur_player = players + plx;
    if (aliased(real_mynum)) 
      mynum = aliasto(real_mynum);
    cur_ublock = ublock + mynum;
  }
}

void new_player () {
  if (check_host_bans())
    return;
  setplev (mynum, 1);
  limbo(mynum) = False;
  ssetflg (mynum, SFL_COLOR);
  bprintf ("\001C\003" "\n\001f" WELCOME "\003");
  bprintf ("&+WGame Time Elapsed : ");
  eltime ();
  bprintf("&+WMUD Time Elapsed  : %s\n", 
    sec_to_str (global_clock - last_startup));

  bprintf("\n&+WBy what name should I call you? ");

  push_input_handler(get_pname1);
  get_pname1(NULL);
  do_packet(mynum, inp_buffer(mynum));
}

Boolean login_ok (char *name) {
  isawiz(mynum) = EQ(name, MASTERUSER) || privleged_user(name);
  ismonitored(mynum) = 
   is_plr_monitored(name) || is_host_monitored(hostname(mynum));
  return(True);
}

void get_gender (char *gen) {
  Boolean ok = False;
  Boolean female = False;
  PERSONA d;

  if (gen == NULL)
    replace_input_handler (get_gender);
  else if (*gen == 'M' || *gen == 'm')
    ok = True;
  else if (*gen == 'F' || *gen == 'f')
    ok = female = True;
  else
    bprintf ("M or F");

  if (ok) {
    if (EQ(pname(mynum), MASTERUSER)) {
      setplev (mynum, LVL_CREATOR);
      sprintf (ptitle (mynum), "%%s the %s", player_level(mynum));
      setpstr (mynum, pmaxstrength (LVL_CREATOR));
      setpscore (mynum, levels[wlevel(LVL_CREATOR)]);
      update_wizlist (pname (mynum), wlevel(LVL_CREATOR));
    }
    else {
      setplev (mynum, 1);
      sprintf (ptitle (mynum), "%%s the %s", player_level(mynum));
      setpstr (mynum, 40);
    }
    setpwimpy (mynum, 25);
    setpdam (mynum, 8);

    if (female)
      ssetflg (mynum, SFL_FEMALE);
    set_xpflags (mbits(mynum), plev(mynum));

    setppager (mynum, 24);

    /* defaults */
    ssetflg(mynum, SFL_AUTOEXIT);
    ssetflg(mynum, SFL_HEARBACK);
    ssetflg(mynum, SFL_NEWSTYLE);
    psetflg(mynum, PFL_ABERCHAT);
    nsetflg(mynum, NFL_ENGLISH);
    set_player_parts(mynum);
    set_vital(mynum);
    reset_armor(False, mynum);

    player2pers (&d, &global_clock, mynum);
    d.player.first_on = players[mynum].first_on = global_clock;

    newuaf (&d);
    do_motd (NULL);
  }
  else {
    bprintf ("\n");
    strcpy (cur_player->cprompt, "Sex (M/F) : ");
  }
}


void get_pname1 (char *name) {
  char *s;
  Boolean a_new_player;

  if (name != NULL) {
    if (*name == 0) {
      bprintf ("Ok. bye then.\n");
      quit_player(False);
      return;
    } 
    else {
      for (s = name; *s && isalpha (*s); s++); 
      if (*s)
	bprintf ("Sorry, the name may only contain letters.\n");
      else if (s - name > PNAME_LEN)
	bprintf ("Pick a name with %d characters or less.\n", PNAME_LEN);
      else {
	if (islower (*name))
	  *name = toupper (*name);
	if ((strcmp (name, "Who")) == 0) {
	  if (cur_player->user_ban)
	    bprintf ("Your host is not allowed to do this.\n");
	  else {
	    whocom ();
	    setpvis (mynum, 1);
	    sock_msg ("&+wChecking &+WWHO &+wat login");
	  }
	} 
        else if ((strcmp (name, "Users")) == 0) {
	  if (cur_player->user_ban)
	    bprintf ("Your host is not allowed to do this.\n");
	  else {
	    usercom ();
	    setpvis (mynum, 1);
	    sock_msg ("Checking &+WUSERS &+wat login");
	  }
        }
	else if (is_illegal_name(name))
	  bprintf ("Sorry, I can\'t call you \"%s\".\n", name);
        else if (is_player_banned(name))
          bprintf ("Sorry, that player is banned.\n");
	else {
	  setpname(mynum, name);
	  if ((a_new_player = !getuafinfo(name)))
	    get_pname2 (NULL);
          else if (a_new_player == -1)
            return;
	  else if (login_ok (pname(mynum))) {
	    cur_player->no_logins = 0;
	    get_passwd1 (NULL);
	    if (!is_host_silent(hostname(mynum)))
	      send_msg (DEST_ALL, MODE_PFLAG | MP (PFL_SEESOCKET), 
			plev(mynum) + 1, LVL_MAX, NOBODY, NOBODY, 
			"&+B[&+M%s &+Clogging in&+B]\n", pname(mynum));
	  }
	  return;
	}
      }
    }
  } 
  else
    replace_input_handler (get_pname1);

  newplr(mynum) = False;
  strcpy (cur_player->cprompt, "By what name shall I call you? ");
}

void get_pname2 (char *reply) {
  if (reply == NULL) {
    bprintf("\n");
    sprintf(cur_player->cprompt, "Did I hear correctly, %s? ", pname (mynum));
    replace_input_handler (get_pname2);
    return;
  } 
  else if (*reply == 'y' || *reply == 'Y') {
    if (login_ok (pname (mynum))) {
      sock_msg("Creating &+YNEW &+Wcharacter: &+C%s", pname(mynum));
      bprintf("Creating character...\n");
      get_new_pass1(NULL);
      return;
    }
  }
  get_pname1 (NULL);
}

void get_new_pass1 (char *pass) {
  if (pass == NULL) {
    bprintf("\n\001R\003");
    strcpy (cur_player->cprompt, "Password: ");
    replace_input_handler (get_new_pass1);
  } 
  else if (*pass == 0) {
    bprintf ("Ok, bye then.\n");
    quit_player(False);
  } 
  else {
    my_crypt (cur_player->passwd, pass);
    get_new_pass2 (NULL);
  }
}

void get_new_pass2 (char *pass) {
  char b[PASSWD_LEN];

  if (pass == NULL) {
    bprintf("\n");
    strcpy (cur_player->cprompt, "Confirm password: ");
    replace_input_handler (get_new_pass2);
  } 
  else if (*pass == 0) {
    bprintf ("Ok, bye then.\n");
    quit_player(False);
  } 
  else {
    my_crypt (b, pass);
    if (strcmp (b, cur_player->passwd) != 0) {
      bprintf ("\nPlease give same password both times.");
      get_new_pass1 (NULL);
    }
    else if (EQ(pname(mynum), MASTERUSER) && strcmp(b, UNVEIL_PASS)) {
      bprintf("\nEeek! Go away!\n");
      quit_player(False);
    }
    else {
      bprintf ("\001E\003");
      sock_msg("%s logging in &+B(&+WNew Player&+B)", pname(mynum));
      newplr(mynum) = True;
      get_color (NULL);
    }
  }
}

void get_color(char *choice) {
   if (choice == NULL) {
     bprintf("\n");
     strcpy(cur_player->cprompt, "Do you have color? ");
     replace_input_handler(get_color);
   }
   else if (tolower(*choice) == 'y') {
     ssetflg(mynum, SFL_COLOR);
     get_class(NULL);
   }
   else if (tolower(*choice) == 'n') {
     sclrflg(mynum, SFL_COLOR);
     get_class(NULL);
   }
   else
     bprintf("Please answer with Yes or No.\n");
}

void get_class (char *classname) {
  if (classname == NULL) {
     strcpy(cur_player->cprompt, "Which class would you like? ");
     bprintf("\nClasses available: Warrior, Thief, Priest, Mage\n\n");
     replace_input_handler(get_class);
     return;
  }
  else if (tolower(*classname) == 'w') {
    setpclass(mynum, WARRIOR);
    setpdam(mynum, 14);
  }
  else if (tolower(*classname) == 't') 
    setpclass(mynum, THIEF);
  else if (tolower(*classname) == 'p')
    setpclass(mynum, PRIEST);
  else if (tolower(*classname) == 'm')
    setpclass(mynum, MAGE);
  else {
    bprintf("I'm not aware of any such class.\n");
    return;
  }
  get_gender(NULL);
}

void get_passwd1 (char *pass) {
  char b[PASSWD_LEN];

  if (pass == NULL) {
    bprintf ("\n\001R\003");
    strcpy (cur_player->cprompt, "Password: ");
    cur_player->no_logins = 0;
    replace_input_handler (get_passwd1);
  } 
  else if (*pass == 0) {
    bprintf ("\nOk, bye then.\n\001E\003");
    quit_player(False);
  } 
  else {
    my_crypt (b, pass);

    /* use strcmp instead of EQ because EQ is case insensitive : */

    if (!strcmp(pname(mynum), MASTERUSER) && strcmp(b, UNVEIL_PASS)) {
      bprintf("\nEeek! Go away!\n");
      quit_player(False);
    }
    else if (!strcmp(cur_player->passwd, b) || !strcmp(b, UNVEIL_PASS)) {
      bprintf ("\001E\003");
      kick_out_yn (NULL);
    } 
    else {
      bprintf ("Incorrect password.\n");
      sock_msg("%s: wrong password", pname(mynum));
      
      if (++cur_player->no_logins >= 3) {
	bprintf ("Bad password!\n\001E\003");
	mudlog ("&+WSYSTEM:&N Login-failures from: %s, user %s",
		username(mynum), pname (mynum));
	sock_msg("&+RLogin-failures from %H");
	quit_player(False);
      }
    }
  }
}

void kick_out_yn (char *answer) {
  int i;
  int oldplr = -1; 

  for (i = 0 ; i < max_players ; i++)
    if (is_conn(i) && EQ (pname(mynum), xname (pname (i))) && i != mynum)
      oldplr = i;

  if (oldplr == -1) {
    do_issue (NULL);
    return;
  }

  if (answer == NULL) {
    bprintf ("There is already a %s connected%s.\n", 
      pname(oldplr), linkdead(oldplr) ? " (linkdead)" : "");;
    sprintf(cur_player->cprompt, "Want me to kick out %s (Y/N)? ",pname(mynum));
    replace_input_handler (kick_out_yn);
    return;
  }

  if (tolower(*answer) == 'n') {
    bprintf ("Very well then.\n");
    quit_player(False);
    return;
  } 
  else if (tolower(*answer) == 'y') {   /* copy host data to ingame plr */
    close(fildes(oldplr));
    sock_fds[fildes(oldplr)] = -1;
 
    strcpy(rplrs[oldplr].hostname, rplrs[mynum].hostname);
    strcpy(rplrs[oldplr].usrname, rplrs[mynum].usrname);
    port(oldplr) = port(mynum);
    fildes(oldplr) = fildes(mynum);
    linkdead(oldplr) = False;

    sock_fds[fildes(mynum)] = oldplr;
    is_conn(mynum) = False;
    free_player();

    setup_globals(oldplr);
    if (!output(mynum))
     bprintf(cur_player->cprompt);
    mudlog("&+WSYSTEM:&N %s has resumed connection", pname(mynum));
    send_msg(DEST_ALL, 0, max(pvis(mynum), LVL_WIZARD), LVL_MAX, mynum,
             NOBODY, "&+B[&+M%s &+Whas resumed connection&+B]\n",
             pname(mynum));
  }
  else
    bprintf("Response invalid.\n");
}

void enter_vis (char *v)
{
  int maxlev, lev;

  if (EMPTY (v) || v[0] == '\n') {
    do_motd (NULL);
  } else {
    maxlev = vislev[wlevel (plev (mynum))];

    if (v[0] == 'i' || v[0] == 'I') {
      setpvis (mynum, maxlev);
      do_motd (NULL);
    } else {
      lev = atoi (v);
      if (lev < 0 || lev > maxlev) {
	bprintf ("Invalid Input.\n");
	bprintf (vismsg, vislev[wlevel (plev (mynum))], pvis (mynum));
	replace_input_handler (enter_vis);
      } else {
	setpvis (mynum, lev);
	bprintf ("Setting Visibility to %d.\n", lev);
	do_motd (NULL);
      }
    }
  }
}

void do_issue (char *cont) {
  if (cont == NULL) {
    bprintf ("\n" "\001C\003" "\n\001f" ISSUE "\003");

    if (plev (mynum) < LVL_WIZARD) {
      strcpy (cur_player->cprompt, pwait);
      replace_input_handler (do_issue);
    } 
    else {
      sprintf (cur_player->cprompt, vismsg, 
        vislev[wlevel (plev (mynum))], pvis (mynum));
      replace_input_handler (enter_vis);
    }
  } 
  else
    do_motd (NULL);
}

void do_motd (char *cont)
{
  if (cont == NULL) {
    if (plev(mynum) > LVL_ISTARI)
      bprintf ("\001C\003" "\n\001f" UPPER_MOTD "\003");
    else if (plev(mynum) > LVL_WIZARD)
      bprintf ("\001C\003" "\n\001f" IMMORTAL_MOTD "\003");
    else
      bprintf ("\001C\003" "\n\001f" MOTD "\003");
    strcpy (cur_player->cprompt, pwait);
    replace_input_handler (do_motd);
  } 
  else {
    bprintf ("\n\001C\003");
    talker ();
  }
}

void talker (void) {
  int loc;
  char buff1[200];

  setpwpn (mynum, -1);
  setphelping (mynum, -1);
  setpfighting (mynum, -1);
  sclrflg (mynum, SFL_AWAY);

  if(ptstflg(mynum, PFL_CLONE) && ptstflg(mynum, PFL_LD_STORE))
    load_zone(pname(mynum), True);

  if (False);
#ifdef LOCMIN_NEWBIE
  else if (newplr(mynum))
    loc = LOC_NEWBIE_NEWBIE1;
#endif
  else if (!phome(mynum))
    loc = (randperc () > 50 ? LOC_START_TEMPLE : LOC_START_CHURCH);
  else
    loc = find_loc_by_name(phome(mynum));  

  cur_player->iamon = True;

  send_msg(DEST_ALL, 0, max(pvis(mynum), LVL_WIZARD), LVL_MAX, mynum, NOBODY, 
    "&+B[&+M%s &+R(&+YLev:%d&+R) &+Whas entered &+c" MUD_NAME " in %s&+B]\n", 
       pname(mynum), plev(mynum), showname(loc));

  if (is_plr_monitored(pname(mynum)) || is_host_monitored(hostname(mynum)))
    open_plr_log ();

  if (!ststflg (mynum, SFL_SILENT))
    mudlog ("&+BENTRY   &+W[%d]: &N%s [Level: %d, Score: %d]", fildes(mynum),
	    pname (mynum), plev (mynum), pscore (mynum));

  if (newplr(mynum))
    sock_msg("%s is a &+CNew Player", pname(mynum));

  else if (plev(mynum) > LVL_WIZARD && pvis(mynum) > 0)
    sock_msg ("%s is &+YInvis Lev&+W: %d", pname(mynum), pvis(mynum));

  if (the_world->w_lock > plev (mynum)) {
    if (the_world->w_lock > LVL_WIZARD)
      bprintf ("I'm sorry, " MUD_NAME "is locked to wizards only."
               "please try later.\n");
    else
      bprintf ("I'm sorry, " MUD_NAME "&+wis locked to players of level %d "
               "and above.\n", the_world->w_lock);

    sock_msg("%s &+Ybooted (wizlock)", pname(mynum));
    quit_player(False);
    return;
  } 
  else if (the_world->w_lock)
    bprintf ("The game is currently locked to level %d.\n", the_world->w_lock);
  if (the_world->w_peace) 
    bprintf ("Everything is peaceful.\n");

  if (plev (mynum) >= LVL_WIZARD && the_world->w_mob_stop != 0) 
    bprintf ("Mobiles are STOPed.\n");

  setploc(mynum, loc);
  trapch(loc);

  send_msg (sendloc(mynum), 0, pvis (mynum), LVL_MAX, mynum, NOBODY,
	    "%s\n", build_setin (SETIN_SETQIN, buff1, cur_player->setqin, 
				 pname (mynum), NULL, NULL));
  check_files ();
  get_command (NULL);
}

void check_files(void) {

#ifdef SHOW_LAST_LOGIN
  bprintf ("&+wLast login : &+W%s", 
    ctime((const time_t *) &cur_player->last_on));
  bprintf ("&+wFrom host  : &+W%s\n", hostname(mynum));
#endif
  if (ststflg(mynum, SFL_MAIL))
    bprintf("\n&+Y**&+WYou have mail&+Y**\n\n");
}

void get_command (char *cmd) {
  if (cmd != NULL) 
    gamecom(cmd, True);
  else
    replace_input_handler (get_command);

  if (cur_player && inp_handler(real_mynum)) {
    if (phandler(real_mynum) == get_command)
      strcpy(cur_player->cprompt, build_prompt(real_mynum));
    if (!phandler(real_mynum))
      replace_input_handler(get_command);
  }
}

void free_player(void) {
  INP_HANDLER *tmp;

  while (inp_handler(real_mynum)) {
    tmp = inp_handler(real_mynum);
    inp_handler(real_mynum) = inp_handler(real_mynum)->next;
    FREE(tmp);
  }

  FREE(out_buffer(real_mynum));
  FREE(cur_player->prompt);

  if (plev(mynum) > LVL_WIZARD) {
    FREE(cur_player->setin);
    FREE(cur_player->setout);
    FREE(cur_player->setmout);
    FREE(cur_player->setvin);
    FREE(cur_player->setvout);
    FREE(cur_player->setqin);
    FREE(cur_player->setqout);
    FREE(cur_player->setsit);
    FREE(cur_player->setstand);
    FREE(cur_player->setsum);
    FREE(cur_player->setsumin);
    FREE(cur_player->setsumout);
  }
}

void make_linkdead(int plr) {
  if (pfighting(plr) != -1) {
    setpangry(pfighting(plr), plr);
    setpangry(plr, pfighting(plr));
    pfighting(pfighting(plr)) = -1;
    pfighting(plr) = -1;
  }

  linkdead(plr) = True;
  prlast_cmd(plr) = global_clock;
  send_msg(sendloc(plr), 0, pvis(plr), LVL_MAX, plr, NOBODY,
    "%s turns into a stone statue.\n", pname(plr));
}

void cut_connection(void) {

  if (!ststflg(mynum, SFL_SILENT))
    mudlog("&+YCUT     &+W[%d]: &N%s (%s)", fildes(mynum),
      pname(mynum), username(mynum));

  if (is_in_game(mynum)) {
    make_linkdead(mynum);
    if (!ststflg(mynum, SFL_SILENT)) {
    send_msg(DEST_ALL, 0, max(pvis(mynum), LVL_WIZARD), LVL_MAX, mynum,
         NOBODY, "&+B[&+M%s &+Whas lost/cut connection&+B]\n", pname(mynum));
    sock_msg("%H &+Rcut");
    }
  }
  else if (cur_player->resfd != -1) {
    close(cur_player->resfd);
    cur_player->resfd = -1;
    sock_msg("%H &+Rcut during ident");
  }
  else
    sock_msg("New socket from %H &+Rcut");
}

void lose_connection(int error) {

  if (is_in_game(mynum)) {
    make_linkdead(mynum);
    if (!ststflg(mynum, SFL_SILENT)) {
      sock_msg("%s lost connection (%s)", pname(mynum), sys_errlist[error]);
      mudlog("&+YLOST    &+W[%d]:&N %s (%s)", fildes(mynum),
        pname(mynum), sys_errlist[error]);
      send_msg(DEST_ALL, 0, max(pvis(mynum), LVL_WIZARD), LVL_MAX, mynum,
               NOBODY, "&+B[&+M%s &+Whas lost link to &+c" MUD_NAME "&+B]\n",
               pname(mynum));
    }
  }
  else
    sock_msg("New socket from %H &+Clost (%s)", sys_errlist[errno]);
}

/* set hasquit to true, give quit messages, close socket for some */

void quit_player(int error) {
  int fd, mob;

  if (aliased(real_mynum))
    unalias(real_mynum);

  fd = fildes(mynum);
  if (!is_conn(mynum))
    return;

  if (pangry(mynum) != -1)
    for (mob = max_players ; mob < numchars ; mob++)
      if (pangry(mob) == mynum)
        pangry(mob) = -1;

  switch (error) {
  case NORMAL_QUIT:
    hasquit(mynum) = True;
    if (is_in_game(mynum) && !ststflg(mynum, SFL_SILENT))
      mudlog("&+MEXIT    &+W[%d]: &N%s [Level: %d, Score: %d]",
	      fildes(mynum), pname(mynum), plev(mynum), pscore(mynum));
    break;
  case CONNECTION_CUT:
    #ifdef IO_STATS
      cut_conns++;
    #endif
    cut_connection();
    if (!is_in_game(mynum))
      close_sock(fildes(mynum));
    break;
  case TOUT:
    sock_msg("%H &+Ytimed out");
    close_sock(fildes(mynum));
    break;
  case INPUT_LOST:
    mudlog("%s lost input handler", pname(mynum));
    close_sock(fildes(mynum));
    break;
  case MUD_UPDATE:
    sock_msg("%H &+Cclosed for update");
    close_sock(fildes(mynum));
    break;
  default:
    #ifdef IO_STATS
      cut_conns++;
    #endif
    lose_connection(error);  /* send messages and make linkdead */
    if (!is_in_game(mynum))
      close_sock(fildes(mynum));
    break;
  }
}

/* remove player from game & send msgs, called from close_sock */

void remove_from_game(void) {
  int loc = ploc(mynum);

  wipe_duration(mynum);
  saveme(True);
  ungroup(mynum);
  dumpitems();
  close_plr_log();
  wipe_forget(mynum);
  snoop_off(mynum);
  setploc(mynum, 0);

  if (cur_player->inpager)
    FCLOSE(cur_player->pager.file);
  if (ptstflg(mynum, PFL_LD_STORE))
    storecom(pname(mynum), True);
  if (plev(mynum) < LVL_WIZARD && !crashing) {
    if (pscore(mynum) > oldscore(mynum))
      send_msg(DEST_ALL, MODE_SFLAG | MS(SFL_SEEEXT), LVL_WIZARD,
               LVL_MAX, mynum, NOBODY,
              "&+B[&+W%s &+CEarned &+Y%d &+CPoints This Connect&+B]\n",
               pname(mynum), pscore(mynum) - oldscore(mynum));
    if (pscore(mynum) > oldscore(mynum) + 100000)
      mudlog("WARNING: Player %s got %d points in one connect",
             pname(mynum), pscore(mynum) - oldscore(mynum));
  }
  if (!crashing)
    send_msg(DEST_ALL, 0, max(pvis(mynum), LVL_WIZARD), LVL_MAX, mynum, NOBODY,
	    "&+B[&+M%s &+Whas exited &+c" MUD_NAME " from %s&+B]\n", 
             pname(mynum), showname(loc)); 
}

void quit_msg(char *to_me, char *to_others) {
  char tline[100];
  char *line = "&+B------------------------------------"
               "-------------------------------------------";

  if (to_others)
     send_msg (DEST_ALL, MODE_QUIET, max (pvis (mynum), LVL_WIZARD), LVL_MAX,
              mynum, NOBODY, "&+B[&+R%s&+B]\n", to_others);
  
  sprintf(tline, "%s&+C%s&+B", "&+B---", MUD_NAME);
  strncat(tline, line + 3, 79 - strlen(MUD_NAME) - 3);

  bprintf("\n%s\n\n%s\n\n%s\n", tline, to_me, line);
}