1stMud/CVS/
1stMud/area/CVS/
1stMud/backup/CVS/
1stMud/bin/
1stMud/bin/CVS/
1stMud/bin/extras/
1stMud/bin/extras/CVS/
1stMud/data/CVS/
1stMud/data/i3/CVS/
1stMud/doc/1stMud/
1stMud/doc/1stMud/CVS/
1stMud/doc/CVS/
1stMud/doc/Diku/
1stMud/doc/Diku/CVS/
1stMud/doc/MPDocs/CVS/
1stMud/doc/Merc/CVS/
1stMud/doc/Rom/
1stMud/doc/Rom/CVS/
1stMud/log/CVS/
1stMud/notes/
1stMud/notes/CVS/
1stMud/player/CVS/
1stMud/player/backup/CVS/
1stMud/player/deleted/CVS/
1stMud/src/CVS/
1stMud/src/config/CVS/
1stMud/src/h/CVS/
1stMud/src/o/CVS/
1stMud/win/CVS/
/**************************************************************************
*  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
*  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
*                                                                         *
*  Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael         *
*  Chastain, Michael Quan, and Mitchell Tse.                              *
*                                                                         *
*  In order to use any part of this Merc Diku Mud, you must comply with   *
*  both the original Diku license in 'license.doc' as well the Merc       *
*  license in 'license.txt'.  In particular, you may not remove either of *
*  these copyright notices.                                               *
*                                                                         *
*  Much time and thought has gone into this software and you are          *
*  benefiting.  We hope that you share your changes too.  What goes       *
*  around, comes around.                                                  *
***************************************************************************
*       ROM 2.4 is copyright 1993-1998 Russ Taylor                        *
*       ROM has been brought to you by the ROM consortium                 *
*           Russ Taylor (rtaylor@hypercube.org)                           *
*           Gabrielle Taylor (gtaylor@hypercube.org)                      *
*           Brian Moore (zump@rom.org)                                    *
*       By using this code, you have agreed to follow the terms of the    *
*       ROM license, in the file Rom24/doc/rom.license                    *
***************************************************************************
*          1stMud ROM Derivative (c) 2001-2004 by Markanth                *
*            http://www.firstmud.com/  <markanth@firstmud.com>            *
*         By using this code you have agreed to follow the term of        *
*             the 1stMud license in ../doc/1stMud/LICENSE                 *
***************************************************************************/

#include "merc.h"
#include "interp.h"
#include "telnet.h"
#include "recycle.h"
#include "tables.h"
#include "vnums.h"
#include "special.h"

Proto (bool check_playing, (Descriptor *, const char *));
Proto (bool check_reconnect, (Descriptor *, const char *, bool));

Do_Fun (nanny_help)
{
  HelpData *pHelp;
  Buffer *output;
  char argall[MAX_INPUT_LENGTH], argone[MAX_INPUT_LENGTH];
  int level;

  output = new_buf ();

  if (NullStr (argument))
    argument = "summary";


  argall[0] = '\0';
  while (!NullStr (argument))
    {
      argument = one_argument (argument, argone);
      if (!NullStr (argall))
	strcat (argall, " ");
      strcat (argall, argone);
    }

  for (pHelp = help_first; pHelp != NULL; pHelp = pHelp->next)
    {
      level = (pHelp->level < 0) ? -1 * pHelp->level - 1 : pHelp->level;

      if (level > get_trust (ch) || pHelp->category != HELP_CREATION)
	continue;

      if (is_name (argall, pHelp->keyword))
	{

	  bprint (output, help_text (pHelp->text));
	  break;
	}
    }

  if (!pHelp)
    chprintlnf (ch, "{cNo help on %s.{x", argall);
  else
    sendpage (ch, buf_string (output));
  free_buf (output);
}

Nanny_Fun (HANDLE_CON_GET_TERM)
{
  switch (argument[0])
    {
    case 'y':
    case 'Y':
      SetBit (d->desc_flags, DESC_COLOR);
      d_println (d, "{?Color {cEnabled...{x");
      break;
    case 'n':
    case 'N':
      RemBit (d->desc_flags, DESC_COLOR);
      d_println (d, "Color Disabled...");
      break;
    case 't':
    case 'T':
      d_printlnf (d, NEWLINE "This text should be " ESC
		  "[%d;%dmGREEN" CL_DEFAULT "." NEWLINE
		  "This text should be " ESC "[%d;%dmRED"
		  CL_DEFAULT ".", CL_BRIGHT, FG_GREEN, CL_BRIGHT, FG_RED);
      d_println (d, NEWLINE "Did you see color? (Y)es, (N)o, (T)est: ");
      return;
    default:
      d_println (d, "Please answer (Y)es, (N)o, (T)est: ");
      return;
    }
  show_greeting (d);
  d->connected = CON_GET_NAME;
}

Nanny_Fun (HANDLE_CON_GET_NAME)
{
  CharData *ch;
  bool fOld;
  NameProfile *nl;

  Proto (NameProfile * profile_lookup, (int));
  Proto (char *genname, (NameProfile *));

  if (NullStr (argument))
    {
      d_println (d,
		 "You can't have a blank name, type 'list' to list name generator profiles,"
		 NEWLINE
		 "<#> to generate a list of names based on profile number '#'"
		 NEWLINE
		 "'quit' to disconnect, or type your characters name - try again.");
      d_print (d, mud_info.login_prompt);
      return;
    }
  else if (!str_cmp (argument, "quit"))
    {
      close_socket (d);
      return;
    }
  else if (!str_cmp (argument, "list"))
    {
      int count = 0;

      d_println (d, "{RNAME GENERATOR PROFILES{x");
      for (nl = name_profile_first; nl; nl = nl->next)
	{
	  d_printlnf (d, "{W%2d{c> %s{x", ++count, nl->title);
	}
      d_println (d, "{cEnter a profile number to view generated names:{x");
      return;
    }
  else if (is_number (argument))
    {
      int count = 0, i;
      int profile_num = atoi (argument);
      Column Cd;

      if (profile_num < 1 || profile_num > top_name_profile
	  || (nl = profile_lookup (profile_num)) == NULL)
	{
	  d_printlnf (d, "{cInvalid profile number {W%d{c.{x", profile_num);
	  d_println (d, "{RNAME GENERATOR PROFILES{x");
	  for (nl = name_profile_first; nl; nl = nl->next)
	    {
	      d_printlnf (d, "{W%2d{c> %s{x", ++count, nl->title);
	    }
	  d_println (d,
		     "{cEnter a profile number to view generated names:{x");
	  return;
	}

      set_cols (&Cd, NULL, 4, COLS_DESC, d);
      d_printlnf (d, "{RNAME GENERATOR - %s{x", strupper (nl->title));
      for (i = 0; i < 60; i++)
	{
	  print_cols (&Cd, capitalize (genname (nl)));
	}
      cols_nl (&Cd);

      d_println (d, "{cPlease enter your name:{x");
      d_println
	(d,
	 "{c(to view a list of profiles, type 'list' or enter a profile number){x");
      return;
    }
  else if (!check_parse_name (argument))
    {
      d_println (d, "{cIllegal name, try another.{x" NEWLINE "Name: {x");
      return;
    }

  fOld = load_char_obj (d, argument);
  ch = d->character;

  if (IsSet (ch->act, PLR_DENY))
    {
      logf ("Denying access to %s@%s.", argument, d->host);
      d_println (d, "{cYou are {Rdenied{c access.{x");
      close_socket (d);
      return;
    }

  if (check_ban (d->host, BAN_PERMIT) && !IsSet (ch->act, PLR_PERMIT))
    {
      d_println (d, "{cYour site has been {Rbanned{c from this mud.{x");
      close_socket (d);
      return;
    }

  if (check_reconnect (d, argument, false))
    {
      fOld = true;
    }
  else
    {
      if (IsSet (mud_info.mud_flags, MUD_WIZLOCK) && !IsImmortal (ch))
	{
	  d_println (d, "{cThe game is {Rwizlocked{c.{x");
	  close_socket (d);
	  return;
	}
    }

  if (fOld)
    {

      d_write (d, echo_off_str, 0);
      d_println (d, "{cPassword: {x");
      d->connected = CON_GET_OLD_PASSWORD;
      d->wrong_password_count = 0;
      return;
    }
  else
    {

      if (IsSet (mud_info.mud_flags, MUD_NEWLOCK))
	{
	  d_println (d, "{cThe game is {Rnewlocked{c.{x");
	  close_socket (d);
	  return;
	}

      if (check_ban (d->host, BAN_NEWBIES))
	{
	  d_println (d, "{cNew players are not allowed from your site.{x");
	  close_socket (d);
	  return;
	}

      d_printlnf (d, "{cDid I get that right, %s ({WY{c/{WN{c)? {x",
		  capitalize (argument));
      d->connected = CON_CONFIRM_NEW_NAME;
      return;
    }
}

Nanny_Fun (HANDLE_CON_GET_OLD_PASSWORD)
{
  CharData *ch = CH (d);

  if (str_casecmp (crypt (argument, ch->pcdata->pwd), ch->pcdata->pwd))
    {
      d_print (d, "{cWrong password");
      if (++d->wrong_password_count < 3)
	{
	  d_println (d, " - try again.");
	  d_println (d, "{cPassword: {x");
	  d_println (d, echo_off_str);
	  return;
	}
      else
	{
	  d_println (d, ".");
	}
      close_socket (d);
      return;
    }

  d_write (d, echo_on_str, 0);

  if (check_playing (d, ch->name))
    return;

  if (check_reconnect (d, ch->name, true))
    return;

  new_wiznet (ch, d->host, WIZ_SITES, true, get_trust (ch),
	      "$N@$t has connected.");

  set_desc_flags (d);
  if (IsImmortal (ch))
    {
      d_print
	(d,
	 "{cWould you like to login ({WW{c)izinvis, ({WI{c)ncognito, "
	 "({WB{c)oth, or ({WN{c)ormal?{x" NEWLINE
	 "{c(Include a level number to specify what level){x");
      d->connected = CON_GET_WIZ;
    }
  else
    {
      do_function (ch, &nanny_help, "motd");
      d->connected = CON_READ_MOTD;
    }
}

Nanny_Fun (HANDLE_CON_GET_WIZ)
{
  CharData *ch = CH (d);
  char arg[MIL];
  int wizlevel = Range (LEVEL_IMMORTAL, ch->level, MAX_LEVEL);

  argument = one_argument (argument, arg);

  if (!NullStr (argument) && is_number (argument))
    wizlevel = Range (LEVEL_IMMORTAL, atoi (argument), MAX_LEVEL);
  switch (tolower (*arg))
    {
    case 'w':
      ch->invis_level = wizlevel;
      ch->incog_level = 0;
      break;
    case 'i':
      ch->incog_level = wizlevel;
      ch->invis_level = 0;
      break;
    case 'b':
      ch->incog_level = wizlevel;
      ch->invis_level = wizlevel;
      break;
    default:
    case 'n':
      ch->incog_level = 0;
      ch->invis_level = 0;
      break;
    }
  do_function (ch, &nanny_help, "imotd");
  d->connected = CON_READ_MOTD;
}

Nanny_Fun (HANDLE_CON_BREAK_CONNECT)
{
  CharData *ch = CH (d);
  Descriptor *d_old, *pd_next;

  switch (*argument)
    {
    case 'y':
    case 'Y':
      for (d_old = descriptor_first; d_old != NULL; d_old = pd_next)
	{
	  pd_next = d_old->next;
	  if (d_old == d || d_old->character == NULL)
	    continue;

	  if (str_cmp (ch->name, CH (d_old)->name))
	    continue;

	  close_socket (d_old);
	}
      if (check_reconnect (d, ch->name, true))
	return;
      d_println (d, "{cReconnect attempt failed.{x" NEWLINE "{cName: ");
      if (d->character != NULL)
	{
	  free_char (d->character);

	  d->character = NULL;
	}
      d->connected = CON_GET_NAME;
      break;

    case 'n':
    case 'N':
      d_println (d, "{cName: {x");
      if (d->character != NULL)
	{
	  free_char (d->character);

	  d->character = NULL;
	}
      d->connected = CON_GET_NAME;
      break;

    default:
      d_println (d, "{cPlease type ({WY{c)es or ({WN{c)o: {x");
      break;
    }
}

Nanny_Fun (HANDLE_CON_CONFIRM_NEW_NAME)
{
  CharData *ch = CH (d);

  switch (*argument)
    {
    case 'y':
    case 'Y':
      d_printlnf (d,
		  "{cWelcome to {R%s{c!" NEWLINE
		  "{cGive me a password for {W%s{c: {x", mud_info.name,
		  ch->name);
      d_write (d, echo_off_str, 0);
      d->connected = CON_GET_NEW_PASSWORD;
      break;

    case 'n':
    case 'N':
      d_println (d, "{cOk, what IS it, then? {x");
      free_char (d->character);

      d->character = NULL;
      d->connected = CON_GET_NAME;
      break;

    default:
      d_println (d, "{cPlease type ({WY{c)es or ({WN{c)o: {x");
      break;
    }
}

Nanny_Fun (HANDLE_CON_GET_NEW_PASSWORD)
{
  CharData *ch = CH (d);
  const char *pwdnew;
  const char *p;

  if (strlen (argument) < 5)
    {
      d_println (d,
		 "{cPassword must be at least five characters long."
		 NEWLINE "{cPassword: {x");
      return;
    }

  pwdnew = crypt (argument, ch->name);
  for (p = pwdnew; *p != '\0'; p++)
    {
      if (*p == '~')
	{
	  d_println (d,
		     "{cNew password not acceptable, try again." NEWLINE
		     "{cPassword: {x");
	  return;
	}
    }

  replace_str (&ch->pcdata->pwd, pwdnew);
  d_println (d, "{cPlease retype password: {x");
  d->connected = CON_CONFIRM_NEW_PASSWORD;
}

void
send_race_info (Descriptor * d)
{
  RaceData *race;

  d_println (d, NEWLINE "{cThe following races are available:{x");
  d_printlnf (d, "{W%s{x", draw_line (CH (d), "{w-{W-", 0));
  for (race = race_first; race; race = race->next)
    {
      if (!race->pc_race)
	continue;
      d_printlnf (d, "{c\t%s{x", race->name);
    }
  d_printlnf (d, "{W%s", draw_line (CH (d), "{w-{W-", 0));
  d_printlnf (d, "{cFor more information, use help. (i.e. 'help %s'){x",
	      race_first->name);
}

Nanny_Fun (HANDLE_CON_CONFIRM_NEW_PASSWORD)
{
  CharData *ch = CH (d);

  if (str_casecmp (crypt (argument, ch->pcdata->pwd), ch->pcdata->pwd))
    {
      d_println (d,
		 "{cPasswords don't match.{x" NEWLINE
		 "{cRetype password: {x");
      d->connected = CON_GET_NEW_PASSWORD;
      return;
    }

  d_write (d, echo_on_str, 0);
  send_race_info (d);
  d_println (d, "{cWhat is your race? {x");
  d->connected = CON_GET_NEW_RACE;
}

Nanny_Fun (HANDLE_CON_GET_NEW_RACE)
{
  CharData *ch = CH (d);
  char arg[MAX_INPUT_LENGTH];
  RaceData *race;
  int i;

  one_argument (argument, arg);

  if (!str_cmp (arg, "help"))
    {
      argument = one_argument (argument, arg);
      if (NullStr (argument))
	do_function (ch, &nanny_help, "race help");
      else
	do_function (ch, &nanny_help, argument);
      d_println (d,
		 NEWLINE
		 "{cWhat is your race (help for more information)? {x");
      return;
    }

  race = race_lookup (argument);

  if (race == NULL || !race->pc_race)
    {
      d_println (d, "{cThat is not a valid race.{x");
      send_race_info (d);
      return;
    }

  if (IsRemort (ch) && ch->race != race)
    {
      d_printlnf (d, "{cYou are now a {R%s{c forever.{x", ch->race->name);
      ch->pcdata->stay_race = true;
    }

  ch->race = race;

  for (i = 0; i < STAT_MAX; i++)
    ch->perm_stat[i] = race->stats[i];
  ch->affected_by = ch->affected_by | race->aff;
  ch->imm_flags = ch->imm_flags | race->imm;
  ch->res_flags = ch->res_flags | race->res;
  ch->vuln_flags = ch->vuln_flags | race->vuln;
  ch->form = race->form;
  ch->parts = race->parts;


  for (i = 0; i < MAX_RACE_SKILL; i++)
    {
      if (race->skills[i] == NULL)
	break;
      group_add (ch, race->skills[i], false);
    }

  ch->pcdata->points = race->points;
  ch->size = race->size;

  d_printlnf (d, "{cYou are now a {W%s{c.", race->name);

  d_println (d,
	     NEWLINE
	     "{cWhat is your sex ({WM{c)ale/({WF{c)emale/({WN{c)eutral? {x");
  d->connected = CON_GET_NEW_SEX;
}

void
send_class_info (Descriptor * d)
{
  int iClass;

  d_println (d, NEWLINE "{cThe following classes are available:{x");
  d_printlnf (d, "{W%s{x", draw_line (CH (d), "{w-{W-", 0));
  for (iClass = 0; iClass < top_class; iClass++)
    {
      if (is_class (d->character, iClass))
	continue;
      d_printlnf (d, "{c\t%s{x", ClassName (d->character, iClass));
    }
  d_printlnf (d, "{W%s{x", draw_line (CH (d), "{w-{W-", 0));
  d_printlnf (d, "{cFor more information, use help. (i.e. 'help %s'){x",
	      class_table[0].name[0]);
}

Nanny_Fun (HANDLE_CON_GET_NEW_SEX)
{
  CharData *ch = CH (d);

  switch (toupper (argument[0]))
    {
    case 'M':
      d_println (d, "{cYou are now {Wmale{c.");
      ch->sex = SEX_MALE;
      ch->pcdata->true_sex = SEX_MALE;
      break;
    case 'F':
      d_println (d, "{cYou are now {Wfemale{c.");
      ch->sex = SEX_FEMALE;
      ch->pcdata->true_sex = SEX_FEMALE;
      break;
    case 'N':
      d_println (d, "{cYou are now {Wneutral{c.");
      ch->sex = SEX_NEUTRAL;
      ch->pcdata->true_sex = SEX_NEUTRAL;
      break;
    default:
      d_println (d, "{cThat's not a sex.{x" NEWLINE "{cWhat IS your sex? {x");
      return;
    }

  send_class_info (d);
  d_printlnf (d, "{cWhat is your %sclass? {x", IsRemort (ch) ? "next " : "");
  d->connected = CON_GET_NEW_CLASS;
}


int
roll_a_stat (CharData * ch, int pStat)
{
  int percent, bonus, low, high;

  if (!ch || !ch->race->pc_race)
    return number_range (13, 22);

  percent = number_percent ();
  if (percent > 99)
    bonus = 2;
  else if (percent > 95)
    bonus = 1;
  else if (percent < 5)
    bonus = -1;
  else if (percent < 1)
    bonus = -2;
  else
    bonus = 0;

  high = ch->race->max_stats[pStat] - (3 - bonus);
  low = ch->race->stats[pStat] - (3 - bonus);
  return number_range (low, high);
}

void
roll_stats (CharData * ch)
{
  int i;

  for (i = 0; i < STAT_MAX; i++)
    ch->perm_stat[i] = roll_a_stat (ch, i);
}

void
init_gen_data (Descriptor * d)
{
  int i;

  CharData *ch = CH (d);

  ch->gen_data = new_gen_data ();
  ch->gen_data->points_chosen = ch->pcdata->points;
  d_println (d, NEWLINE "{cYou may now roll your stats.{x" NEWLINE);
  roll_stats (ch);
  for (i = 0; i < STAT_MAX; i++)
    d_printf (d, "{c%.3s {W%02d {x", capitalize (stat_types[i].name),
	      ch->perm_stat[i]);
  d_println (d, "{c  Keep? ({WY{c/{WN{c) {x");
}

Nanny_Fun (HANDLE_CON_GET_NEW_CLASS)
{
  CharData *ch = CH (d);
  char arg[MIL];
  int iClass;

  one_argument (argument, arg);
  iClass = class_lookup (arg);

  if (iClass == -1)
    {
      if (!str_cmp (arg, "help"))
	{
	  argument = one_argument (argument, arg);
	  if (NullStr (argument))
	    do_function (ch, &nanny_help, "class help");
	  else
	    do_function (ch, &nanny_help, argument);
	  d_printlnf (d, NEWLINE "{cWhat IS your %sclass? {x",
		      IsRemort (ch) ? "next " : "");
	  return;
	}
      d_println (d, "{cInvalid class.{x");
      send_class_info (d);
      d_printlnf (d, "{cWhat IS your %sclass? {x",
		  IsRemort (ch) ? "next " : "");
      return;
    }

  if (is_class (ch, iClass))
    {
      d_printlnf (d, "{cYou are already part {W%s{c. Try another!{x",
		  ClassName (ch, iClass));
      return;
    }


  ch->Class[ch->Class[CLASS_COUNT]] = iClass;
  ch->Class[CLASS_COUNT] += 1;
  ch->Class[ch->Class[CLASS_COUNT]] = -1;


  d_printlnf (d, "{cYou are now a {W%s{c.", class_long (ch));
  if (!IsRemort (ch))
    {
      wiznet ("Newbie alert! $N sighted.", ch, NULL, WIZ_NEWBIE, false, 0);
      new_wiznet (ch, d->host, WIZ_SITES, true, get_trust (ch),
		  "$N@$t new player.");
      mud_info.stats.newbies++;
      d_println (d,
		 NEWLINE
		 "{cYou may now choose a general alignment of your character.{x");
      d_println (d,
		 "{cWhich alignment ({WG{c)ood/({WN{c)eutral/({WE{c)vil? {x");
      d->connected = CON_GET_ALIGNMENT;
    }
  else
    {

      init_gen_data (d);
      d->connected = CON_ROLL_STATS;
    }
}

void
send_deity_info (Descriptor * d)
{
  DeityData *i;
  int e;

  d_println (d, NEWLINE "{cDeities available for worship:{x");
  d_printlnf (d, "{W%s", draw_line (CH (d), "{w-{W-", 0));
  for (e = ETHOS_LAWFUL_GOOD; e != ETHOS_CHAOTIC_EVIL; e--)
    {
      for (i = deity_first; i; i = i->next)
	{
	  if (i->ethos != (ethos_t) e)
	    continue;

	  d_printlnf (d, "{c\t%-12s (%s): %s{x", i->name,
		      flag_string (ethos_types, i->ethos), i->desc);
	}
    }
  d_printlnf (d, "{W%s", draw_line (CH (d), "{w-{W-", 0));
  d_printlnf (d, "{cFor more information, use help. (i.e. 'help %s'){x",
	      deity_first->name);
}

Nanny_Fun (HANDLE_CON_GET_ALIGNMENT)
{
  CharData *ch = CH (d);

  switch (toupper (argument[0]))
    {
    case 'G':
      d_println (d, "{cYou are now {Wgood{c.{x");
      ch->alignment = 750;
      break;
    case 'N':
      d_println (d, "{cYou are now {Yneutral{c.{x");
      ch->alignment = 0;
      break;
    case 'E':
      d_println (d, "{cYou are now {Revil{c.{x");
      ch->alignment = -750;
      break;
    default:
      d_println (d, "{cThat's not a valid alignment.{x");
      d_println (d,
		 "{cWhich alignment ({WG{c)ood/({WN{c)eutral/({WE{c)vil? {x");
      return;
    }

  send_deity_info (d);
  d_println (d, "{cWhat deity would you like to worship?{x");
  d->connected = CON_GET_DEITY;
  return;
}

void
send_timezone_info (Descriptor * d)
{
  int i;

  d_println (d,
	     NEWLINE
	     "{cPlease choose a timezone closest to where you live:{x");
  d_printlnf (d, "{W%s", draw_line (CH (d), "{w-{W-", 0));
  for (i = 0; i < MAX_TZONE; i++)
    {
      d_printlnf (d, "{c\t{W%5s{c - %9s - %s{x", tzone_table[i].name,
		  str_time (current_time, i, "%I:%M:%S %p"),
		  tzone_table[i].zone);
    }
  d_printlnf (d, "{W%s", draw_line (CH (d), "{w-{W-", 0));
  d_printlnf (d, "{cFor more information, use help. (i.e. 'help %s'){x",
	      tzone_table[0].name);
}

Nanny_Fun (HANDLE_CON_GET_DEITY)
{
  char arg[MIL];
  DeityData *i;
  CharData *ch = CH (d);

  one_argument (argument, arg);

  if (!str_cmp (arg, "help"))
    {
      argument = one_argument (argument, arg);
      if (NullStr (argument))
	{
	  send_deity_info (d);
	  d_println (d, "{cWhat deity would you like to worship? {x");
	}
      else
	do_function (ch, &do_help, argument);
      d_println (d, "{cWhat deity would you like to worship? {x");
      return;
    }
  i = deity_lookup (argument);

  if (i == NULL)
    {
      send_deity_info (d);
      d_println (d, "{cWhat deity would you like to worship? {x");
      return;
    }
  ch->deity = i;
  d_printlnf (d, "{cYou now worship {W%s{c.{x", ch->deity->name);

  send_timezone_info (d);
  d_println (d, "{cWhat time zone do you live in? {x");
  d->connected = CON_GET_TIMEZONE;
  return;
}

Nanny_Fun (HANDLE_CON_GET_TIMEZONE)
{
  int i;
  char arg[MIL];
  CharData *ch = CH (d);

  one_argument (argument, arg);

  if (NullStr (arg))
    {
      send_timezone_info (d);
      d_println (d, "{cWhat time zone do you live in? {x");
      return;
    }
  if (!str_cmp (arg, "help"))
    {
      d_printlnf (d,
		  "{cTime zones around the world are split up into %d areas,",
		  MAX_TZONE);
      d_printlnf (d,
		  "{ceach relating to Greenwich Mean Time (GMT) which is %s.{x",
		  str_time (-1, tzone_lookup ("GMT"), "%I:%M:%S %p"));
      d_println (d, "{cWhat time zone do you live in? {x");
      return;
    }
  i = tzone_lookup (argument);

  if (i == -1)
    {
      d_println (d,
		 "{cThat is not a valid time zone, please enter the full time zone name. (ex. GMT-5)");
      d_println (d, "{cWhat time zone do you live in? {x");
      return;
    }

  ch->pcdata->timezone = i;
  d_printlnf (d, "{cYour time zone is now %s %s (%s) {x",
	      tzone_table[i].zone, tzone_table[i].name,
	      str_time (current_time, i, "%I:%M:%S %p"));
  d_println (d, NULL);

  if (IsSet (d->desc_flags, DESC_TELOPT_NAWS))
    {
      init_gen_data (d);
      d->connected = CON_ROLL_STATS;
    }
  else
    {
      d_println (d,
		 "{cThis mud makes use of formating text to your screen size, your client does not");
      d_println (d,
		 "support auto-negotation so you may now enter a screen size manually.  The default");
      d_printlnf (d, "screen is %d columns by %d lines.{x" NEWLINE,
		  DEFAULT_SCR_WIDTH, DEFAULT_SCR_HEIGHT);
      d_printlnf (d,
		  "{cHow many columns (width) does your clients screen have roughly? (%d){x",
		  DEFAULT_SCR_WIDTH);
      d->connected = CON_GET_SCR_WIDTH;
    }
}

Nanny_Fun (HANDLE_CON_GET_SCR_WIDTH)
{
  int sz;
  char arg[MIL];
  CharData *ch = CH (d);

  argument = one_argument (argument, arg);

  if (!NullStr (arg))
    {
      sz = atoi (arg);

      if (sz < 10 || sz > 250)
	{
	  d_println (d,
		     "{cPlease keep your screen width between 10 and 250 columns.{x");
	  return;
	}
      d->scr_width = sz;
      ch->columns = sz;
    }
  d_println (d, draw_line (ch, "{`-{W=", 0));
  d_println (d, NULL);
  d_println (d,
	     "{cBased on the above line, is your screen width set to your satisfaction? ({WY{c/{WN{c) ");
  d->connected = CON_CONFIRM_SCR_WIDTH;
}

Nanny_Fun (HANDLE_CON_CONFIRM_SCR_WIDTH)
{
  switch (toupper (argument[0]))
    {
    case 'Y':
      d_printlnf (d, "{W%d {cscreen columns set.{x", d->scr_width);
      d_printlnf (d,
		  "{cHow many lines (height) does your clients screen have? (%d){x",
		  DEFAULT_SCR_HEIGHT);
      d->connected = CON_GET_SCR_LINES;
      break;
    case 'N':
      d_printlnf (d,
		  "{cHow many columns (width) does your clients screen have roughly? (%d){x",
		  DEFAULT_SCR_WIDTH);
      d->connected = CON_GET_SCR_WIDTH;
      break;
    default:
      d_println (d, "{cYes or No?{x");
      break;
    }
}

Nanny_Fun (HANDLE_CON_GET_SCR_LINES)
{
  int sz;
  char arg[MIL];
  CharData *ch = CH (d);

  argument = one_argument (argument, arg);

  if (!NullStr (arg))
    {
      sz = atoi (arg);

      if (sz < 10 || sz > 250)
	{
	  d_println (d,
		     "{cPlease keep your screen height between 10 and 250 lines.{x");
	  return;
	}

      d->scr_height = sz;
      ch->lines = sz;
    }
  d_printlnf (d, "{W%d {cscreen lines set.{x", d->scr_height);
  init_gen_data (d);
  d->connected = CON_ROLL_STATS;
}

Nanny_Fun (HANDLE_CON_ROLL_STATS)
{
  CharData *ch = CH (d);
  int i;

  switch (tolower (argument[0]))
    {
    case 'y':
      ch->gen_data->rerolls = 1;
      group_add (ch, "rom basics", false);
      add_base_groups (ch);
      ch->pcdata->learned[gsn_recall] = 50;
      d_println (d, "{cDo you wish to customize this character?{x");
      d_println (d,
		 "{cCustomization takes time, but allows a wider range of skills and abilities.{x");
      d_println (d, "{cCustomize ({WY{c/{WN{c)? {x");
      d->connected = CON_DEFAULT_CHOICE;
      break;
    case 'n':
      if (ch->gen_data->rerolls >= 10)
	{
	  d_println (d, NEWLINE
		     "You cannot reroll forever. Your stuck with what you have.{x");
	  d_println (d, NULL);
	  group_add (ch, "rom basics", false);
	  add_base_groups (ch);
	  ch->pcdata->learned[gsn_recall] = 50;
	  d_println (d, "{cDo you wish to customize this character?{x");
	  d_println (d,
		     "Customization takes time, but allows a wider range of skills and abilities.");
	  d_println (d, "{cCustomize ({WY{c/{WN{c)? {x");
	  d->connected = CON_DEFAULT_CHOICE;
	  break;
	}
      ch->gen_data->rerolls++;

      roll_stats (ch);
      d_printlnf (d, "{cYou have {W%d{c re-rolls remaining.{x",
		  (11 - ch->gen_data->rerolls));
      for (i = 0; i < STAT_MAX; i++)
	d_printf (d, "{c%.3s {W%02d {x", capitalize (stat_types[i].name),
		  ch->perm_stat[i]);
      d_println (d, "{c  Keep? ({WY{c/{WN{c) {x");
      break;
    default:
      d_println (d, "{cYes or No?{x");
      break;
    }
}

void
send_weapon_info (Descriptor * d)
{
  CharData *ch = CH (d);
  int i;

  free_gen_data (ch->gen_data);
  d_println (d, "{cPlease pick a weapon from the following choices:{x");
  for (i = 0; weapon_table[i].name != NULL; i++)
    if (ch->pcdata->learned[*weapon_table[i].gsn] > 0)
      d_printlnf (d, "{c\t%s{x", weapon_table[i].name);
  d_println (d, "{cYour choice? {x");
}

Nanny_Fun (HANDLE_CON_DEFAULT_CHOICE)
{
  CharData *ch = CH (d);

  d_println (d, NULL);
  switch (toupper (argument[0]))
    {
    case 'Y':
      d_println (d,
		 "{cThe following skills and groups are available to your character:{x");
      d_println (d, "{c(this list may be seen again by typing list){x");
      list_group_costs (ch);
      if (!IsRemort (ch))
	{
	  d_println (d, "{cYou already have the following skills:{x");
	  do_function (ch, &do_skills, "");
	}
      d_println (d,
		 NEWLINE
		 "{cChoice? (add, drop, list, learned, info, lookup, help, premise, done){x ");
      d->connected = CON_GEN_GROUPS;
      break;
    case 'N':
      d_printlnf (d, "{cDefault skill set for %s used.",
		  ClassName (ch, prime_class (ch)));
      add_default_groups (ch);
      send_weapon_info (d);
      d->connected = CON_PICK_WEAPON;
      break;
    default:
      d_println (d, "{cPlease answer ({WY{c/{WN{c)? {x");
      return;
    }
}

Nanny_Fun (HANDLE_CON_PICK_WEAPON)
{
  CharData *ch = CH (d);
  int i, weapon;
  void finish_remort (CharData *);

  weapon = weapon_lookup (argument);
  if (weapon == -1 || ch->pcdata->learned[*weapon_table[weapon].gsn] <= 0)
    {
      d_println (d, "{cThat's not a valid selection. Choices are:{x");
      for (i = 0; weapon_table[i].name != NULL; i++)
	if (ch->pcdata->learned[*weapon_table[i].gsn] > 0)
	  d_printlnf (d, "{c\t%s{x", weapon_table[i].name);
      d_println (d, "{cYour choice? {x");
      return;
    }

  ch->pcdata->learned[*weapon_table[weapon].gsn] =
    Max (40, ch->pcdata->learned[*weapon_table[weapon].gsn]);

  if (IsRemort (ch))
    {
      finish_remort (ch);
    }
  else
    {
      do_function (ch, &nanny_help, "motd");
      d->connected = CON_READ_MOTD;
    }
}

Nanny_Fun (HANDLE_CON_GEN_GROUPS)
{
  CharData *ch = CH (d);

  if (!str_cmp (argument, "done"))
    {
      if (!IsRemort (ch))
	{
	  if (ch->pcdata->points == ch->race->points)
	    {
	      chprintln (ch, "{cYou didn't pick anything.{x");
	      return;
	    }
	}

      ch->pcdata->points = Max (ch->pcdata->points, mud_info.max_points);

      chprintlnf (ch, "{cCreation points: %d{x", ch->pcdata->points);
      chprintlnf (ch, "{cExperience per level: %d{x",
		  exp_per_level (ch, ch->gen_data->points_chosen));
      send_weapon_info (d);
      d->connected = CON_PICK_WEAPON;
      return;
    }

  if (!parse_gen_groups (ch, argument))
    d_println (d,
	       "{cChoices are: (add, drop, list, learned, info, lookup, help, premise, done){x ");
  else
    d_println (d,
	       "{cChoice? (add, drop, list, learned, info, lookup, help, premise, done){x ");
}

Nanny_Fun (HANDLE_CON_READ_IMOTD)
{
  CharData *ch = CH (d);

  do_function (ch, &nanny_help, "motd");
  d->connected = CON_READ_MOTD;
}

Nanny_Fun (HANDLE_CON_READ_MOTD)
{
  CharData *ch = CH (d);
  char buf[MSL];

  if (ch->pcdata == NULL || NullStr (ch->pcdata->pwd))
    {
      d_println (d, "{WWarning! Null password!{x");
      d_println (d, "{WPlease report old password with bug.{x");
      d_println (d, "{WType '{Wpassword null <new password>{c' to fix.{x");
    }

  d_printlnf (d, "{cWelcome to {?%s{c, %s.{x", mud_info.name, ch->name);
  Link (ch, char, next, prev);

  Link (ch, player, next_player, prev_player);
  d->connected = CON_PLAYING;
  reset_char (ch);

  if (ch->level == 0)
    {
      if (ch->Class[0] == -1)
	ch->Class[0] = 0;

      ch->perm_stat[class_table[prime_class (ch)].attr_prime] += 3;

      if (pfiles.count == 0)
	{
	  int sn;

	  ch->level = MAX_LEVEL;
	  ch->pcdata->perm_hit = ch->max_hit = 50000;
	  ch->pcdata->perm_mana = ch->max_mana = 50000;
	  ch->pcdata->perm_move = ch->max_move = 50000;
	  ch->pcdata->security = 9;
	  ch->trust = MAX_LEVEL;
	  for (sn = 0; sn < top_skill; sn++)
	    {
	      if (get_skill (ch, sn) > 0)
		ch->pcdata->learned[sn] = 100;
	    }
#ifndef DISABLE_I3
	  ch->pcdata->i3chardata->i3perm = I3PERM_IMP;
#endif

	  SetBit (ch->act, PLR_HOLYLIGHT);
	  replace_str (&ch->prompt, IMMORTAL_PROMPT);
	  save_char_obj (ch);
	  realloc_mem (pfiles.names, const char *, pfiles.count + 1);

	  pfiles.names[pfiles.count++] = str_dup (ch->name);
	}
      else
	ch->level = 1;

      ch->exp = exp_per_level (ch, ch->pcdata->points);
      ch->hit = ch->max_hit;
      ch->mana = ch->max_mana;
      ch->move = ch->max_move;
      ch->train = 3;
      ch->practice = 5;
      ch->gold = 10;
      sprintf (buf, "the %s %s", ch->race->name,
	       ClassName (ch, prime_class (ch)));
      set_title (ch, buf);

      if (ch->level >= LEVEL_IMMORTAL)
	{
	  char_to_room (ch, get_room_index (ROOM_VNUM_CHAT));
	  chprintlnf (ch,
		      "{RSince you are the first player file on {?%s{R, "
		      "you have been made an {rImplementor{R automatically.",
		      mud_info.name);
	}
      else
	{
	  do_function (ch, &do_outfit, "");
	  obj_to_char (create_object (get_obj_index (OBJ_VNUM_MAP), 0), ch);

	  char_to_room (ch, get_room_index (ROOM_VNUM_SCHOOL));
	  chprintln (ch, NULL);
	  do_function (ch, &nanny_help, "newbie info");
	}
    }
  else if (ch->in_room != NULL)
    {
      char_to_room (ch, ch->in_room);
    }
  else if (IsImmortal (ch))
    {
      char_to_room (ch, get_room_index (ROOM_VNUM_CHAT));
    }
  else
    {
      char_to_room (ch, get_room_index (ROOM_VNUM_TEMPLE));
    }

  announce (ch, INFO_LOGIN, "$n has entered the realms.");
  act ("$n has entered the game.", ch, NULL, NULL, TO_ROOM);

  mud_info.stats.logins++;

  d_println (d, NULL);

  do_function (ch, &do_look, "auto");

  wiznet ("$N has left real life behind.", ch, NULL, WIZ_LOGINS,
	  false, get_trust (ch));

  if (ch->pet != NULL)
    {
      char_to_room (ch->pet, ch->in_room);
      act ("$n has entered the game.", ch->pet, NULL, NULL, TO_ROOM);
    }

  do_function (ch, &do_backup, "check");
  do_function (ch, &do_ncheck, "");
  do_function (ch, &do_count, "");
  unfinished_quest (ch);
  update_explored (ch);
  checkcorpse (ch);
}

#define NANNY_CASE(state, fun) \
    case state : \
        fun (d, argument); \
        break

void
nanny (Descriptor * d, const char *argument)
{


  if (d->connected != CON_NOTE_TEXT)
    {
      while (isspace (*argument))
	argument++;
    }

  switch (d->connected)
    {

    default:
      bugf ("Nanny: bad d->connected %d.", d->connected);
      close_socket (d);
      return;

      NANNY_CASE (CON_GET_TERM, HANDLE_CON_GET_TERM);

      NANNY_CASE (CON_GET_NAME, HANDLE_CON_GET_NAME);

      NANNY_CASE (CON_GET_OLD_PASSWORD, HANDLE_CON_GET_OLD_PASSWORD);

      NANNY_CASE (CON_GET_WIZ, HANDLE_CON_GET_WIZ);

      NANNY_CASE (CON_BREAK_CONNECT, HANDLE_CON_BREAK_CONNECT);

      NANNY_CASE (CON_CONFIRM_NEW_NAME, HANDLE_CON_CONFIRM_NEW_NAME);

      NANNY_CASE (CON_GET_NEW_PASSWORD, HANDLE_CON_GET_NEW_PASSWORD);

      NANNY_CASE (CON_CONFIRM_NEW_PASSWORD, HANDLE_CON_CONFIRM_NEW_PASSWORD);

      NANNY_CASE (CON_GET_NEW_RACE, HANDLE_CON_GET_NEW_RACE);

      NANNY_CASE (CON_GET_NEW_SEX, HANDLE_CON_GET_NEW_SEX);

      NANNY_CASE (CON_GET_NEW_CLASS, HANDLE_CON_GET_NEW_CLASS);

      NANNY_CASE (CON_GET_ALIGNMENT, HANDLE_CON_GET_ALIGNMENT);

      NANNY_CASE (CON_GET_DEITY, HANDLE_CON_GET_DEITY);

      NANNY_CASE (CON_GET_TIMEZONE, HANDLE_CON_GET_TIMEZONE);

      NANNY_CASE (CON_GET_SCR_WIDTH, HANDLE_CON_GET_SCR_WIDTH);

      NANNY_CASE (CON_CONFIRM_SCR_WIDTH, HANDLE_CON_CONFIRM_SCR_WIDTH);

      NANNY_CASE (CON_GET_SCR_LINES, HANDLE_CON_GET_SCR_LINES);

      NANNY_CASE (CON_ROLL_STATS, HANDLE_CON_ROLL_STATS);

      NANNY_CASE (CON_DEFAULT_CHOICE, HANDLE_CON_DEFAULT_CHOICE);

      NANNY_CASE (CON_PICK_WEAPON, HANDLE_CON_PICK_WEAPON);

      NANNY_CASE (CON_GEN_GROUPS, HANDLE_CON_GEN_GROUPS);

      NANNY_CASE (CON_READ_IMOTD, HANDLE_CON_READ_IMOTD);

      NANNY_CASE (CON_NOTE_TO, HANDLE_CON_NOTE_TO);

      NANNY_CASE (CON_NOTE_SUBJECT, HANDLE_CON_NOTE_SUBJECT);

      NANNY_CASE (CON_NOTE_EXPIRE, HANDLE_CON_NOTE_EXPIRE);

      NANNY_CASE (CON_NOTE_TEXT, HANDLE_CON_NOTE_TEXT);

      NANNY_CASE (CON_NOTE_FINISH, HANDLE_CON_NOTE_FINISH);

      NANNY_CASE (CON_READ_MOTD, HANDLE_CON_READ_MOTD);
    }

  return;
}