/
area/city/
area/crypts/
area/guilds/
area/psuedowild/
area/religion/
data/documents/MPDocs/
data/html/
data/mobprogs/
data/quest/
data/world/
data/world/_utilities/
data/world/images/
design/html/
notes/
player/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,    *
 *  Michael Seifert, Hans Henrik Strfeldt, Tom Madsen, and Katja Nyboe.    *
 *                                     *
 *  Merc Diku Mud improvments 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.                           *
 *                                     *
 *  Thanks to abaddon for proof-reading our comm.c and pointing out bugs.  *
 *  Any remaining bugs are, of course, our work, not his.  :)          *
 *                                     *
 *  Much time and thought has gone into this software and you are      *
 *  benefitting.  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             *
****************************************************************************/

/****************************************************************************
 *   This file is just the stock nanny() function ripped from comm.c. It    *
 *   seems to be a popular task for new mud coders, so what the heck?       *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#include <sys/time.h>
#endif

#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>        /* OLC -- for close read write etc */
#include <stdarg.h>        /* printf_to_char */

#include "merc.h"
#include "interp.h"
#include "recycle.h"
#include "tables.h"
#include "md5.h"
#include "class.h"
#include "player.h"
void nanny_message(DESCRIPTOR_DATA * dsock, int state);

#if    defined(unix)
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "telnet.h"
extern const char echo_off_str[];
extern const char echo_on_str[];
extern const char go_ahead_str[];
#endif


#if defined(unix)
void game_loop_unix args ((int control));
int init_socket args ((int port));
void init_descriptor args ((int control));
bool read_from_descriptor args ((DESCRIPTOR_DATA * d));
bool write_to_descriptor args ((int desc, char *txt, int length));
#endif

/*
 *  * Other local functions (OS-independent).
 *   */
bool check_parse_name args ((char *name));
bool check_reconnect args ((DESCRIPTOR_DATA * d, char *name, bool fConn));
bool check_playing args ((DESCRIPTOR_DATA * d, char *name));

/*
 * Global variables.
 */
extern DESCRIPTOR_DATA *descriptor_list;    /* All open descriptors     */
extern DESCRIPTOR_DATA *d_next;    /* Next descriptor in loop  */
extern FILE *fpReserve;        /* Reserved file handle     */
extern bool god;            /* All new chars are gods!  */
extern bool merc_down;            /* Shutdown     */
extern bool wizlock;            /* Game is wizlocked    */
extern bool newlock;            /* Game is newlocked    */
extern char str_boot_time[MAX_INPUT_LENGTH];
extern time_t current_time;        /* time of this pulse */


#define std send_to_desc

#define ptc printf_to_char

/*
 * Deal with sockets that haven't logged in yet.
 */
void nanny (DESCRIPTOR_DATA * d, char *argument)
{
    DESCRIPTOR_DATA *d_old, *d_next;
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *ch;
    char *pwdnew;
    char *p;
    int iClass, race, i, weapon;
    bool fOld;
    extern int mud_telnetga, mud_ansicolor;
    int iVoice, iHair, iBirthsign, iEye, iHeight, iWeight;
    int next_state;

    /* Delete leading spaces UNLESS character is writing a note */
    if (d->connected != CON_NOTE_TEXT)
    {
        while ( isspace(*argument) )
            argument++;
    }
    ch = d->character;

    switch (d->connected)
    {

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

    case CON_ANSI:
        if (argument[0] == '\0' || UPPER (argument[0]) == 'Y')
        {
        d->ansi = TRUE;
        send_to_desc ("{RAnsi enabled!{x\n\r", d);
        d->connected = CON_GET_NAME;
        {
            extern char *help_greeting;
            if (help_greeting[0] == '.')
            send_to_desc (help_greeting + 1, d);
            else
            send_to_desc (help_greeting, d);
        }
        break;
        }

        if (UPPER (argument[0]) == 'N')
        {
        d->ansi = FALSE;
        send_to_desc ("Ansi disabled!\n\r", d);
        d->connected = CON_GET_NAME;
        {
            extern char *help_greeting;
            if (help_greeting[0] == '.')
            send_to_desc (help_greeting + 1, d);
            else
            send_to_desc (help_greeting, d);
        }
        break;
        }
        else
        {
        send_to_desc ("Do you want ANSI? (Y/n) ", d);
        return;
        }


    case CON_GET_NAME:
        if (argument[0] == '\0')
        {
        close_socket (d);
        return;
        }

        argument[0] = UPPER (argument[0]);
        if (!check_parse_name (argument))
        {
        send_to_desc ("Illegal name, try another.\n\rName: ", d);
        return;
        }

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

        if (IS_SET (ch->act, PLR_DENY))
        {
        sprintf (log_buf, "Denying access to %s@%s.", argument,
             d->host);
        log_string (log_buf);
        send_to_desc ("You are denied access.\n\r", d);
        close_socket (d);
        return;
        }

        if (check_ban (d->host, BAN_PERMIT)
        && !IS_SET (ch->act, PLR_PERMIT))
        {
        send_to_desc ("Your site has been banned from this mud.\n\r",
                  d);
        close_socket (d);
        return;
        }

        if (check_reconnect (d, argument, FALSE))
        {
        fOld = TRUE;
        }
        else
        {
        if (wizlock && !IS_IMMORTAL (ch))
        {
            send_to_desc ("The game is wizlocked.\n\r", d);
            close_socket (d);
            return;
        }
        }

        if (fOld)
        {
        /* Old player */
        send_to_desc ("Password: ", d);
        write_to_buffer (d, echo_off_str, 0);
        d->connected = CON_GET_OLD_PASSWORD;
        return;
        }
        else
        {
        /* New player */
        if (newlock)
        {
            send_to_desc ("The game is newlocked.\n\r", d);
            close_socket (d);
            return;
        }

        if (check_ban (d->host, BAN_NEWBIES))
        {
            send_to_desc
            ("New players are not allowed from your site.\n\r",
             0);
            close_socket (d);
            return;
        }

        sprintf (buf, "Did I get that right, %s (Y/N)? ", argument);
        send_to_desc (buf, d);
        d->connected = CON_CONFIRM_NEW_NAME;
        return;
        }
        break;

    case CON_GET_OLD_PASSWORD:
#if defined(unix)
        write_to_buffer (d, "\n\r", 2);
#endif

        if (str_cmp( rom_crypt( argument ), ch->pcdata->pwd ) )
        {
        send_to_desc ("Wrong password.\n\r", d);
        close_socket (d);
        return;
        }

        write_to_buffer (d, echo_on_str, 0);

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

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

        sprintf (log_buf, "%s@%s has connected.", ch->name, d->host);
        log_string (log_buf);
        wiznet (log_buf, NULL, NULL, WIZ_SITES, 0, get_trust (ch));

        if (ch->desc->ansi)
        SET_BIT (ch->act, PLR_COLOUR);
        else
        REMOVE_BIT (ch->act, PLR_COLOUR);

        if (IS_IMMORTAL (ch))
        {
        do_function (ch, &do_help, "imotd");
        d->connected = CON_READ_IMOTD;
        }
        else
        {
        do_function (ch, &do_help, "motd");
        d->connected = CON_READ_MOTD;
        }
        break;

/* RT code for breaking link */

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

            if (str_cmp (ch->name, d_old->original ?
                     d_old->original->name : d_old->
                     character->name))
                continue;

            close_socket (d_old);
            }
            if (check_reconnect (d, ch->name, TRUE))
            return;
            send_to_desc ("Reconnect attempt failed.\n\rName: ", d);
            if (d->character != NULL)
            {
            free_char (d->character);
            d->character = NULL;
            }
            d->connected = CON_GET_NAME;
            break;

        case 'n':
        case 'N':
            send_to_desc ("Name: ", d);
            if (d->character != NULL)
            {
            free_char (d->character);
            d->character = NULL;
            }
            d->connected = CON_GET_NAME;
            break;

        default:
            send_to_desc ("Please type Y or N? ", d);
            break;
        }
        break;

    case CON_CONFIRM_NEW_NAME:
        switch (*argument)
        {
        case 'y':
        case 'Y':
            sprintf (buf,
                 "New character.\n\rGive me a password for %s: %s",
                 ch->name, echo_off_str);
            send_to_desc (buf, d);
            d->connected = CON_GET_NEW_PASSWORD;
            if (ch->desc->ansi)
            SET_BIT (ch->act, PLR_COLOUR);
            break;

        case 'n':
        case 'N':
            send_to_desc ("Ok, what IS it, then? ", d);
            free_char (d->character);
            d->character = NULL;
            d->connected = CON_GET_NAME;
            break;

        default:
            send_to_desc ("Please type Yes or No? ", d);
            break;
        }
        break;

    case CON_GET_NEW_PASSWORD:
#if defined(unix)
        write_to_buffer (d, "\n\r", 2);
#endif

        if (strlen (argument) < 5)
        {
        send_to_desc
            ("Password must be at least five characters long.\n\rPassword: ",
             d);
        return;
        }

        pwdnew = rom_crypt( argument );
        for (p = pwdnew; *p != '\0'; p++)
        {
        if (*p == '~')
        {
            send_to_desc
            ("New password not acceptable, try again.\n\rPassword: ",
             d);
            return;
        }
        }

        free_string (ch->pcdata->pwd);
        ch->pcdata->pwd = str_dup (pwdnew);
        send_to_desc ("Please retype password: ", d);
        d->connected = CON_CONFIRM_NEW_PASSWORD;
        break;

    case CON_CONFIRM_NEW_PASSWORD:
#if defined(unix)
        write_to_buffer (d, "\n\r", 2);
#endif

        if (strcmp (rom_crypt( argument ), ch->pcdata->pwd))
        {
        send_to_desc ("Passwords don't match.\n\rRetype password: ",
                  d);
        d->connected = CON_GET_NEW_PASSWORD;
        return;
        }

        sprintf (log_buf, "%s@%s new player.", ch->name, d->host);
        log_string (log_buf);
        wiznet ("Newbie alert!  $N sighted.", ch, NULL, WIZ_NEWBIE, 0, 0);
        wiznet (log_buf, NULL, NULL, WIZ_SITES, 0, get_trust (ch));
        
        /* Set their last name to start with */
        free_string(ch->last_name);
        ch->last_name = str_dup("smith");
        
        d->connected = STATE_NEW_BASE;
        nanny_message(d, STATE_NEW_BASE);
        
        /*
        write_to_buffer (d, echo_on_str, 0);
        send_to_desc ("The following races are available:\n\r  ", d);
        for (race = 1; race_table[race].name != NULL; race++)
        {
        if (!race_table[race].pc_race)
            break;
        write_to_buffer (d, race_table[race].name, 0);
        write_to_buffer (d, " ", 1);
        }
        write_to_buffer (d, "\n\r", 0);
        send_to_desc ("What is your race (help for more information)? ",
              d);
        d->connected = STATE_NEW_RACE;
        */
        break;

    case STATE_NEW_RACE:
        one_argument (argument, arg);

        if (!strcmp (arg, "help"))
        {
        argument = one_argument (argument, arg);
        if (argument[0] == '\0')
            do_function (ch, &do_help, "race help");
        else
            do_function (ch, &do_help, argument);
        send_to_desc
            ("What is your race (help for more information)? ", d);
        break;
        }

        race = race_lookup (argument);

        if (race == 0 || !race_table[race].pc_race)
        {
        send_to_desc ("That is not a valid race.\n\r", d);
        send_to_desc ("The following races are available:\n\r  ", d);
        for (race = 1; race_table[race].name != NULL; race++)
        {
            if (!race_table[race].pc_race)
            break;
            write_to_buffer (d, race_table[race].name, 0);
            write_to_buffer (d, " ", 1);
        }
        write_to_buffer (d, "\n\r", 0);
        send_to_desc
            ("What is your race? (help for more information) ", d);
        break;
        }

        ch->race = race;
        /* initialize stats */
        for (i = 0; i < MAX_STATS; i++)
            ch->perm_stat[i] = pc_race_table[race].stats[i];
        ch->affected_by = ch->affected_by | race_table[race].aff;
        ch->imm_flags = ch->imm_flags | race_table[race].imm;
        ch->res_flags = ch->res_flags | race_table[race].res;
        ch->vuln_flags = ch->vuln_flags | race_table[race].vuln;
        ch->form = race_table[race].form;
        ch->parts = race_table[race].parts;

        /* add skills */
        for (i = 0; i < 5; i++)
        {
        if (pc_race_table[race].skills[i] == NULL)
            break;
        group_add (ch, pc_race_table[race].skills[i], FALSE);
        }
        /* add cost */
        ch->pcdata->points = pc_race_table[race].points;
        ch->size = pc_race_table[race].size;

        d->connected = STATE_NEW_BASE;
        nanny_message(d, STATE_NEW_BASE);
        break;


    
        
    case CON_GET_NEW_SEX:
        switch (argument[0])
        {
        case 'm':
        case 'M':
            ch->sex = SEX_MALE;
            ch->pcdata->true_sex = SEX_MALE;
            break;
        case 'f':
        case 'F':
            ch->sex = SEX_FEMALE;
            ch->pcdata->true_sex = SEX_FEMALE;
            break;
        default:
            send_to_desc ("That's not a sex.\n\rWhat IS your sex? ",
                  d);
            return;
        }

        d->connected = STATE_NEW_BASE;
        nanny_message(d, STATE_NEW_BASE);
        break;

    /* MAIN CHAR GENERATION */
    case STATE_NEW_BASE:
    {
        if (!str_prefix(argument, "race"))
            next_state = STATE_NEW_RACE;
        else if (!str_prefix(argument, "class"))
            next_state = STATE_NEW_CLASS;
        else if (!str_prefix(argument, "alignment"))
            next_state = STATE_NEW_ALIGN;
        else if (!str_prefix(argument, "gender"))
            next_state = CON_GET_NEW_SEX;
        else if (!str_prefix(argument, "birthsign"))
            next_state = STATE_NEW_BIRTHSIGN;
        else if (!str_prefix(argument, "voice"))
            next_state = STATE_NEW_VOICE;
        else if (!str_prefix(argument, "eyecolour"))
            next_state = STATE_NEW_EYE;
        else if (!str_prefix(argument, "haircolour"))
            next_state = STATE_NEW_HAIR;
        else if (!str_prefix(argument, "height"))
            next_state = STATE_NEW_HEIGHT;
        else if (!str_prefix(argument, "weight"))
            next_state = STATE_NEW_WEIGHT;
        else if (!str_prefix(argument, "lastname"))
            next_state = STATE_NEW_LASTNAME;
        else if (!str_prefix(argument, "done"))
        {
            group_add (ch, "rom basics", FALSE);
            group_add (ch, class_table[ch->class].base_group, FALSE);
            ch->pcdata->learned[gsn_recall] = 100;
            group_add (ch, class_table[ch->class].default_group, TRUE);
            write_to_buffer (d, "\n\r", 2);
            do_function (ch, &do_help, "motd");
            d->connected = CON_READ_MOTD;
            write_to_buffer (d, buf, 0);
            break;
            return;
        }

        else
        {
            d->connected = STATE_NEW_BASE;
            nanny_message(d, STATE_NEW_BASE);
            ptc(ch, "\n\r\n\r{RInvalid Selection. Please Try again.{x\n\r\n\r");
            break;
            return;
        }
        
        d->connected = next_state;
        nanny_message(d, next_state);
        break;
    }
    
    case STATE_NEW_ALIGN:
        if (!str_prefix(argument, "lawfulgood"))
        {
            ch->align_lc    = 2;
            ch->align_ge    = 2;
        }
        else if (!str_prefix(argument, "lawfulneutral"))
        {
            ch->align_lc    = 2;
            ch->align_ge    = 1;
        }
        else if (!str_prefix(argument, "lawfulevil"))
        {
            ch->align_lc    = 2;
            ch->align_ge    = 0;
        }
        else if (!str_prefix(argument, "neutralgood"))
        {
            ch->align_lc    = 1;
            ch->align_ge    = 2;
        }
        else if (!str_prefix(argument, "trueneutral"))
        {
            ch->align_lc    = 1;
            ch->align_ge    = 1;
        }
        else if (!str_prefix(argument, "neutralevil"))
        {
            ch->align_lc    = 1;
            ch->align_ge    = 0;
        }
        else if (!str_prefix(argument, "chaoticgood"))
        {
            ch->align_lc    = 0;
            ch->align_ge    = 2;
        }
        else if (!str_prefix(argument, "chaoticneutral"))
        {
            ch->align_lc    = 0;
            ch->align_ge    = 1;
        }
        else if (!str_prefix(argument, "chaoticevil"))
        {
            ch->align_lc    = 0;
            ch->align_ge    = 0;
        }
        else
        {
            ptc(ch, "Invalid selection, please select again. Remember, dont use any spaces.\n\r");
            break;
            return;
        }
        d->connected = STATE_NEW_BASE;
        nanny_message(d, STATE_NEW_BASE);
        break;
        
    case STATE_NEW_CLASS:
        iClass = class_lookup (argument);

        if (iClass == -1)
        {
        send_to_desc ("That's not a class.\n\rWhat IS your class? ",
                  d);
        return;
        }
        ch->class = iClass;
        d->connected = STATE_NEW_BASE;
        nanny_message(d, STATE_NEW_BASE);
        break;
    case STATE_NEW_VOICE:
        iVoice = voice_lookup(argument);
    
        if (iVoice == -1)
        {
            std("That is not a valid Voice style, please try agaian.\n\r", d);
            return;
        }
        ch->voice   = iVoice;
        d->connected = STATE_NEW_BASE;
        nanny_message(d, STATE_NEW_BASE);
        break;
    case STATE_NEW_HAIR:
        iHair = hair_lookup(argument);
        
        if (iHair == -1)
        {
            std("That is not a valid Hair color, please try agaian.\n\r", d);
            return;
        }
        ch->hair   = iHair;
        d->connected = STATE_NEW_BASE;
        nanny_message(d, STATE_NEW_BASE);
        break;

    case STATE_NEW_EYE:
        iEye = eye_lookup(argument);
        
        if (iEye == -1)
        {
            std("That is not a valid Eye color, please try agaian.\n\r", d);
            return;
        }
        ch->eye   = iEye;
        d->connected = STATE_NEW_BASE;
        nanny_message(d, STATE_NEW_BASE);
        break;
    case STATE_NEW_BIRTHSIGN:
        iBirthsign = birthsign_lookup(argument);
        
        if (iBirthsign == -1)
        {
            std("That is not a valid Birthsign color, please try agaian.\n\r", d);
            return;
        }
        
        ch->birthsign   = iBirthsign;
        d->connected = STATE_NEW_BASE;
        nanny_message(d, STATE_NEW_BASE);
        break;
        


    case STATE_NEW_LASTNAME:
        smash_tilde(argument);
        smash_dollar(argument);
        free_string(ch->last_name);

        ch->last_name   = str_dup(argument);
        d->connected    = STATE_NEW_BASE;
        nanny_message(d, STATE_NEW_BASE);
        break;
        
        
    case STATE_NEW_WEIGHT:
        iWeight = weight_lookup(argument);
        
        if (iWeight == -1)
        {
            std("That is an invalid weight, please select agaian.\n\r", d);
            return;
        }
        
        ch->weight   = iWeight;
        d->connected = STATE_NEW_BASE;
        nanny_message(d, STATE_NEW_BASE);
        break;
        
    case STATE_NEW_HEIGHT:
        iHeight = height_lookup(argument);
        if (iHeight == -1)
        {
            std("That is an invalid height, please select again.\n\r", d);
            return;
        }
        ch->height   = iHeight;
        d->connected = STATE_NEW_BASE;
        nanny_message(d, STATE_NEW_BASE);
        break;

    case CON_GET_ALIGNMENT:
        switch (argument[0])
        {
        case 'g':
        case 'G':
            ch->alignment = 750;
            break;
        case 'n':
        case 'N':
            ch->alignment = 0;
            break;
        case 'e':
        case 'E':
            ch->alignment = -750;
            break;
        default:
            send_to_desc ("That's not a valid alignment.\n\r", d);
            send_to_desc ("Which alignment (G/N/E)? ", d);
            return;
        }

        write_to_buffer (d, "\n\r", 0);

        sprintf (log_buf, "%s@%s new player.", ch->name, d->host);
        log_string (log_buf);
        wiznet ("Newbie alert!  $N sighted.", ch, NULL, WIZ_NEWBIE, 0, 0);
        wiznet (log_buf, NULL, NULL, WIZ_SITES, 0, get_trust (ch));
        break;
    case CON_DEFAULT_CHOICE:
        write_to_buffer (d, "\n\r", 2);
        switch (argument[0])
        {
        case 'n':
        case 'N':
            group_add (ch, class_table[ch->class].default_group,
                   TRUE);
            write_to_buffer (d, "\n\r", 2);
            write_to_buffer (d,
                     "Please pick a weapon from the following choices:\n\r",
                     0);
            buf[0] = '\0';
            for (i = 0; weapon_table[i].name != NULL; i++)
            if (ch->pcdata->learned[*weapon_table[i].gsn] > 0)
            {
                strcat (buf, weapon_table[i].name);
                strcat (buf, " ");
            }
            strcat (buf, "\n\rYour choice? ");
            write_to_buffer (d, buf, 0);
            d->connected = CON_PICK_WEAPON;
            break;
        default:
            write_to_buffer (d, "Please answer (Y/N)? ", 0);
            return;
        }
        break;

    case CON_PICK_WEAPON:
        write_to_buffer (d, "\n\r", 2);
        weapon = weapon_lookup (argument);
        if (weapon == -1
        || ch->pcdata->learned[*weapon_table[weapon].gsn] <= 0)
        {
        write_to_buffer (d,
                 "That's not a valid selection. Choices are:\n\r",
                 0);
        buf[0] = '\0';
        for (i = 0; weapon_table[i].name != NULL; i++)
            if (ch->pcdata->learned[*weapon_table[i].gsn] > 0)
            {
            strcat (buf, weapon_table[i].name);
            strcat (buf, " ");
            }
        strcat (buf, "\n\rYour choice? ");
        group_add (ch, "rom basics", FALSE);
        group_add (ch, class_table[ch->class].base_group, FALSE);
        ch->pcdata->learned[gsn_recall] = 100;
        group_add (ch, class_table[ch->class].default_group, TRUE);
        write_to_buffer (d, "\n\r", 2);
        do_function (ch, &do_help, "motd");
        d->connected = CON_READ_MOTD;
        write_to_buffer (d, buf, 0);
        return;
        }

        ch->pcdata->learned[*weapon_table[weapon].gsn] = 40;
        write_to_buffer (d, "\n\r", 2);
        do_function (ch, &do_help, "motd");
        d->connected = CON_READ_MOTD;
        break;
        
    case CON_GEN_GROUPS:
        break;

    case CON_READ_IMOTD:
        write_to_buffer (d, "\n\r", 2);
        do_function (ch, &do_help, "motd");
        d->connected = CON_READ_MOTD;
        break;

        /* states for new note system, (c)1995-96 erwin@pip.dknet.dk */
        /* ch MUST be PC here; have nwrite check for PC status! */

        case CON_NOTE_TO:
            handle_con_note_to (d, argument);
            break;

        case CON_NOTE_SUBJECT:
            handle_con_note_subject (d, argument);
            break;

        case CON_NOTE_EXPIRE:
            handle_con_note_expire (d, argument);
            break;

        case CON_NOTE_TEXT:
            handle_con_note_text (d, argument);
            break;

        case CON_NOTE_FINISH:
            handle_con_note_finish (d, argument);
            break;

    case CON_READ_MOTD:
        if (ch->pcdata == NULL || ch->pcdata->pwd[0] == '\0')
        {
        write_to_buffer (d, "Warning! Null password!\n\r", 0);
        write_to_buffer (d,
                 "Please report old password with bug.\n\r",
                 0);
        write_to_buffer (d,
                 "Type 'password null <new password>' to fix.\n\r",
                 0);
        }

        write_to_buffer (d,
                 "\n\rWelcome to Vandagard: The Darkness.  Please don't feed the mobiles!\n\r",
                 0);
        ch->next = char_list;
        char_list = ch;
        d->connected = CON_PLAYING;
        reset_char (ch);

        if (ch->level == 0)
        {
            if(mud_ansicolor)
                SET_BIT (ch->act, PLR_COLOUR);
            if(mud_telnetga)
                SET_BIT (ch->comm, COMM_TELNET_GA);
    
            ch->level       = 1;
            ch->exp         = 1;
            ch->hit         = ch->max_hit;
            ch->mana        = ch->max_mana;
            ch->move        = ch->max_move;
            ch->weight      = 1;
            ch->height      = 1;
            ch->gold        = number_range(50, 200);
            ch->silver      = number_range(50, 200);
            sprintf (buf, "the tool.");
            set_title (ch, buf);
            setup_class(ch);
    
            do_function (ch, &do_outfit, "");
    
            char_to_room (ch, get_room_index (ROOM_VNUM_SCHOOL));
            send_to_char ("\n\r", ch);
            do_function (ch, &do_help, "newbie info");
            send_to_char ("\n\r", ch);
        }
        else if (ch->in_room != NULL)
        {
            char_to_room (ch, ch->in_room);
        }
        else if (IS_IMMORTAL (ch))
        {
            char_to_room (ch, get_room_index (ROOM_VNUM_CHAT));
        }
        else
        {
            char_to_room (ch, get_room_index (ROOM_VNUM_TEMPLE));
        }

        act ("$n has entered the game.", ch, NULL, NULL, TO_ROOM);
        do_function (ch, &do_look, "auto");
        do_function (ch, &do_wear, "all");
        wiznet ("$N has left real life behind.", ch, NULL, WIZ_LOGINS, WIZ_SITES, 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);
        }

        send_to_char("\n", ch);
        do_function (ch, &do_board, "");
        war_reset_combo(ch);
        ch->pcdata->msg_buffer_0 = "\0";
        ch->pcdata->msg_buffer_1 = "\0";
        ch->pcdata->msg_buffer_2 = "\0";
        ch->pcdata->msg_buffer_3 = "\0";
        ch->pcdata->msg_buffer_4 = "\0";
        ch->pcdata->msg_buffer_5 = "\0";
        ch->pcdata->msg_buffer_6 = "\0";
        ch->pcdata->msg_buffer_7 = "\0";
        ch->pcdata->msg_buffer_8 = "\0";
        ch->pcdata->msg_buffer_9 = "\0";
        
        break;
    }

    return;
}


#define text_to_buffer write_to_buffer
/*
 * nanny_message():
 *
 * Sends block text to descrptor
 * based on current state.
 */
void nanny_message(DESCRIPTOR_DATA * dsock, int state)
{
    CHAR_DATA *ch;
    ch = dsock->character;
    int i, col;
    
    switch(state)
    {   default:
            log_string("*** BUG *** hnc_messages(): Invalid State!");
            return;
            break;
        
        case STATE_NEW_BASE:
            ptc(ch, CLEAR_SCR);
            ptc(ch, "\n\rIf you have any questions, you can vist the website or use the in-game help system\n\rTo use the help system, type {RHELP {w<TOPIC>{x\n\r{chttp://vandagard.slayn.net\n\r");
            ptc(ch,"        Welcome to the Vandagard Character generator.\n\r");
            ptc(ch,"        Please select which option you wish to change.\n\r\n\r");
            ptc(ch,"      Name:        {w%-20s{x  * Voice:       {w%-20s{x\n\r", ch->name, voice_table[ch->voice].name);
            ptc(ch,"    * Last Name:   {w%-20s{x  * Eye Colour:  {w%-20s{x\n\r", ch->last_name, eye_table[ch->eye].name);
            ptc(ch,"    * Race:        {w%-20s{x  * Hair Colour: {w%-20s{x\n\r", race_table[ch->race].name, hair_table[ch->hair].name);
            ptc(ch,"    * Class:       {w%-20s{x  * Height:      {w%-20s{x\n\r", class_table[ch->class].name, height_table[ch->height].name);
            ptc(ch,"    * Alignment:   {w%-20s{x  * Weight:      {w%-20s{x\n\r", alignment_lookup(ch, FALSE), weight_table[ch->weight].name);
            ptc(ch,"    * Gender:      {w%-20s{x  * Facial Hair: {w%-20s{x\n\r", ch->sex == 0 ? "sexless" : ch->sex == 1 ? "male" : "female", "Not Finished");
            ptc(ch,"    * Birthsign:   {w%-20s{x  * Hair Length: {w%-20s{x\n\r", return_birthsign(ch->birthsign), "Not Finished");
            ptc(ch,"\n\r");
            ptc(ch,"        Please select the stat you wish to change...\n\r");
            ptc(ch,"        or type DONE to finish.\n\r");
            ptc(ch,"\n\r\n\r");
            break;
        case STATE_NEW_RACE:
            ptc(ch, CLEAR_SCR);
            text_to_buffer (dsock,"     Please Select a Race:\n", 0);
            for (i = 0; race_table[i].name != NULL; i++)
            {
                if (!race_table[i].pc_race)
                    continue;
                ptc(ch, "{R* {x%-20s ", race_table[i].name);
                if (++col % 2 == 0)
                    ptc(ch, "\n\r");
            }
            ptc(ch, "\n\rIf you have any questions, you can vist the website or use the in-game help system\n\rTo use the help system, type {RHELP {w<TOPIC>{x\n\r{chttp://vandagard.slayn.net\n\r");
            text_to_buffer(dsock,">", 0);
            break;
            
            break;
        case STATE_NEW_VOICE:
            ptc(ch, CLEAR_SCR);
            text_to_buffer(dsock, "     Please select a voice style:\n", 0);
            for (i = 0; voice_table[i].name != NULL; i++)
            {
                ptc(ch, "{R* {x%-20s ", voice_table[i].name);
                if (++col % 2 == 0)
                    ptc(ch, "\n\r");
            }
            ptc(ch, "\n\rIf you have any questions, you can vist the website or use the in-game help system\n\rTo use the help system, type {RHELP {w<TOPIC>{x\n\r{chttp://vandagard.slayn.net\n\r");
            text_to_buffer(dsock,">", 0);
            break;
        case STATE_NEW_HAIR:
            ptc(ch, CLEAR_SCR);
            text_to_buffer(dsock, "     Please select a hair style:\n", 0);
            for (i = 0; hair_table[i].name != NULL; i++)
            {
                ptc(ch, "{R* {x%-20s ", hair_table[i].name);
                if (++col % 2 == 0)
                    ptc(ch, "\n\r");
            }
            ptc(ch, "\n\rIf you have any questions, you can vist the website or use the in-game help system\n\rTo use the help system, type {RHELP {w<TOPIC>{x\n\r{chttp://vandagard.slayn.net\n\r");
            text_to_buffer(dsock,">", 0);
            break;
        case STATE_NEW_EYE:
            ptc(ch, CLEAR_SCR);
            text_to_buffer(dsock, "     Please select a eye style:\n", 0);
            for (i = 0; eye_table[i].name != NULL; i++)
            {
                ptc(ch, "{R* {x%-20s ", eye_table[i].name);
                if (++col % 2 == 0)
                    ptc(ch, "\n\r");
            }
            ptc(ch, "\n\rIf you have any questions, you can vist the website or use the in-game help system\n\rTo use the help system, type {RHELP {w<TOPIC>{x\n\r{chttp://vandagard.slayn.net\n\r");
            text_to_buffer(dsock,">", 0);
            break;
        case STATE_NEW_WEIGHT:
            ptc(ch, CLEAR_SCR);
            text_to_buffer(dsock, "     Please select a weight style:\n", 0);
            for (i = 0; weight_table[i].name != NULL; i++)
            {
                ptc(ch, "{R* {x%-20s ", weight_table[i].name);
                if (++col % 2 == 0)
                    ptc(ch, "\n\r");
            }
            ptc(ch, "\n\rIf you have any questions, you can vist the website or use the in-game help system\n\rTo use the help system, type {RHELP {w<TOPIC>{x\n\r{chttp://vandagard.slayn.net\n\r");
            text_to_buffer(dsock,">", 0);
            break;
        case STATE_NEW_HEIGHT:
            ptc(ch, CLEAR_SCR);
            text_to_buffer(dsock, "     Please select a height style:\n", 0);
            for (i = 0; height_table[i].name != NULL; i++)
            {
                ptc(ch, "{R* {x%-20s ", height_table[i].name);
                if (++col % 2 == 0)
                    ptc(ch, "\n\r");
            }
            ptc(ch, "\n\rIf you have any questions, you can vist the website or use the in-game help system\n\rTo use the help system, type {RHELP {w<TOPIC>{x\n\r{chttp://vandagard.slayn.net\n\r");
            text_to_buffer(dsock,">", 0);
            break;
        case STATE_NEW_BIRTHSIGN:
            ptc(ch, CLEAR_SCR);
            text_to_buffer(dsock, "     Please select which astrological sign you were born under:\n", 0);
            for (i = 0; birthsign_table[i].birthsign != NULL; i++)
            {
                ptc(ch, "{R* {x%-20s ", birthsign_table[i].birthsign);
                if (++col % 2 == 0)
                    ptc(ch, "\n\r");
            }
            ptc(ch, "\n\rIf you have any questions, you can vist the website or use the in-game help system\n\rTo use the help system, type {RHELP {w<TOPIC>{x\n\r{chttp://vandagard.slayn.net\n\r");
            text_to_buffer(dsock,">", 0);
            break;
        case STATE_NEW_CLASS:
            ptc(ch, CLEAR_SCR);
            text_to_buffer(dsock, "Please select a Class:\n", 0);
            text_to_buffer(dsock, "Wizard   - Masters of Magic. Superb spellcasting.\n\r", 0);
            text_to_buffer(dsock, "Priest   - Religious Defenders. Excellent healers.\n\r", 0);
            text_to_buffer(dsock, "Fighter  - Typical man-at-arms. Excels at all melee combat.\n\r", 0);
            text_to_buffer(dsock, "Thief    - Bandits, Rogues. Adept at parting you from your gold.\n\r", 0);
            text_to_buffer(dsock, ">", 0);
            break;
        case CON_GET_NEW_SEX:
            ptc(ch, CLEAR_SCR);
            text_to_buffer(dsock, "\n\r\n\r\n\r", 0);
            text_to_buffer(dsock, "Please Select Your Gender:\n\r\n\r", 0);
            ptc(ch, "{c[{WM{c]{wale or {c[{WF{c]{wemale\n\r\n\r");
            text_to_buffer(dsock, ">", 0);
            break;
        case STATE_NEW_LASTNAME:
            ptc(ch, CLEAR_SCR);
            text_to_buffer(dsock, "\n\r\n\r\n\r", 0);
            text_to_buffer(dsock, "What is your last name?\n\r\n\r", 0);
            text_to_buffer(dsock, "Last names follow the rules of name selection AND cannot include the following:\n\r", 0);
            text_to_buffer(dsock, "Color codes, tildes, dollar signs, any non-alpha character (- and ' are ok)\n\r", 0);
            text_to_buffer(dsock, "If your last name does not fit the theme, or rules, it will be changed to Thri's liking.\n\r", 0);
            text_to_buffer(dsock, ">", 0);
            break;
        case STATE_NEW_ALIGN:
            ptc(ch, CLEAR_SCR);
        
            ptc(ch, "    Please select your Alignment:\n\r");
            ptc(ch, "        It is important to note, Your alignment does not change\n\r");
            ptc(ch, "        through normal gameplay. Only serious events in your\n\r");
            ptc(ch, "        characters life can even possibly change it. Your alignment\n\r");
            ptc(ch, "        should affect your in-game personality to some extend.\n\r");
            ptc(ch, "        If you plan on roleplaying, choose wisely.\n\r");
            ptc(ch, "        Make sure you read up fully on alignment effects on gameplay\n\r");
            ptc(ch, "        on the website at http://vandagard.slayn.net\n\r");
            ptc(ch, "\n\r");
            ptc(ch, "    Lawful Good     - A lawful good character acts as a good person is\n\r");
            ptc(ch, "                    expected or required to act.\n\r");
            ptc(ch, "    Neutral Good    - A neutral good character does the best that a good\n\r");
            ptc(ch, "                    person can do.\n\r");
            ptc(ch, "    Chaotic Good    - A chaotic good character acts as his conscience\n\r");
            ptc(ch, "                    directs him with little regard for what others expect\n\r");
            ptc(ch, "                    of him.\n\r");
            ptc(ch, "    Lawful Neutral  - A lawful neutral character acts as law, tradition, or a\n\r");
            ptc(ch, "                    personal code directs her.\n\r");
            ptc(ch, "    True Neutral    - A neutral character does what seems to be a good idea\n\r");
            ptc(ch, "                    to themselves.\n\r");
            ptc(ch, "    Chaotic Neutral - A chaotic neutral character follows his whims.\n\r");
            ptc(ch, "    Lawful Evil     - A lawful evil villain methodically takes what he wants\n\r");
            ptc(ch, "                    within the limits of his code of conduct without regard\n\r");
            ptc(ch, "                    for whom it hurts.\n\r");
            ptc(ch, "    Neutral Evil    - A neutral evil villain does whatever she can get away with.\n\r");
            ptc(ch, "    Chaotic Evil    - A chaotic evil character does whatever his greed, hatred,\n\r");
            ptc(ch, "                    and lust for destruction drive him to do.\n\r");
            ptc(ch, "                        \n\r");
            ptc(ch, "        Select Wisely. ({RAlso make all selections as one word, for example,\n\r");
            ptc(ch, "        lawful good, you would type '{Ylawfulgood{R'{x)\n\r");
            ptc(ch, ">");
            break;
        
    }
}