1stMUD/corefiles/
1stMUD/gods/
1stMUD/player/
1stMUD/win32/
1stMUD/win32/ROM/
/**************************************************************************
*  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-2002 by Ryan Jennings              *
*            http://1stmud.dlmud.com/  <r-jenn@shaw.ca>                   *
***************************************************************************/
#if defined(WIN32)
#include <time.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "merc.h"
#include "interp.h"
#include "telnet.h"
#include "recycle.h"
#include "lookup.h"

bool check_playing args((DESCRIPTOR_DATA * d, const char *name));
bool check_parse_name args((const char *name));
bool check_reconnect args((DESCRIPTOR_DATA * d, const char *name, bool fConn));
bool wizlock;					/* Game is wizlocked        */
bool newlock;					/* Game is newlocked        */

void handle_con_get_term(DESCRIPTOR_DATA * d, const char *argument)
{
	switch (argument[0])
	{
	case 'y':
	case 'Y':
		SET_BIT(d->d_flags, DESC_COLOUR);
		write_to_buffer(d, "{cColour Enabled...{x\n\r", 0);
		break;
	case 'n':
	case 'N':
		REMOVE_BIT(d->d_flags, DESC_COLOUR);
		write_to_buffer(d, "Colour Disabled...\n\r", 0);
		break;
	case 't':
	case 'T':
		write_to_buffer(d,
						"\n\rThis text should be " CB_GREEN
						"GREEN" C_CLEAR
						".\n\rThis text should be " CB_RED "RED"
						C_CLEAR ".\n\r", 0);
		write_to_buffer(d, "\n\rDid you see colour? (Y)es, (N)o, (T)est: ", 0);
		return;
	default:
		write_to_buffer(d, "Please answer (Y)es, (N)o, (T)est: ", 0);
		return;
	}
	show_greeting(d);
	d->connected = CON_GET_NAME;
}

void handle_con_get_name(DESCRIPTOR_DATA * d, const char *argument)
{
	CHAR_DATA *ch;
	bool fOld;
	char buf[MAX_STRING_LENGTH];

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

	//argument[0] = UPPER (argument[0]);
	if (!check_parse_name(argument))
	{
		write_to_buffer(d, "Illegal name, try another.\n\rName: ", 0);
		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);
		write_to_buffer(d, "You are denied access.\n\r", 0);
		close_socket(d);
		return;
	}

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

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

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

		if (check_ban(d->host, BAN_NEWBIES))
		{
			write_to_buffer(d,
							"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)? ", capitalize(argument));
		write_to_buffer(d, buf, 0);
		d->connected = CON_CONFIRM_NEW_NAME;
		return;
	}
}

void handle_con_get_old_password(DESCRIPTOR_DATA * d, const char *argument)
{
	CHAR_DATA *ch = CH(d);

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

	if (strcmp(crypt(argument, ch->pcdata->pwd), ch->pcdata->pwd))
	{
		write_to_buffer(d, "Wrong password.\n\r", 0);
		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 (IS_IMMORTAL(ch))
	{
		do_function(ch, &do_oldhelp, "imotd");
		d->connected = CON_READ_IMOTD;
	}
	else
	{
		do_function(ch, &do_oldhelp, "motd");
		d->connected = CON_READ_MOTD;
	}
	set_desc_flags(d);
}

void handle_con_break_connect(DESCRIPTOR_DATA * d, const char *argument)
{
	CHAR_DATA *ch = CH(d);
	DESCRIPTOR_DATA *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,
				 d_old->original ? d_old->original->name : d_old->character->
				 name))
				continue;

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

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

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

void handle_con_confirm_new_name(DESCRIPTOR_DATA * d, const char *argument)
{
	CHAR_DATA *ch = CH(d);
	char buf[MSL];

	switch (*argument)
	{
	case 'y':
	case 'Y':
		sprintf(buf,
				"New character.\n\rGive me a password for %s: %s",
				ch->name, echo_off_str);
		write_to_buffer(d, buf, 0);
		d->connected = CON_GET_NEW_PASSWORD;
		break;

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

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

void handle_con_get_new_password(DESCRIPTOR_DATA * d, const char *argument)
{
	CHAR_DATA *ch = CH(d);
	const char *pwdnew;
	const char *p;

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

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

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

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

void handle_con_confirm_new_password(DESCRIPTOR_DATA * d, const char *argument)
{
	CHAR_DATA *ch = CH(d);
	int race;

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

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

	write_to_buffer(d, echo_on_str, 0);
	write_to_buffer(d, "The following races are available:\n\r  ", 0);
	for (race = 0; race < maxRace; race++)
	{
		if (!race_table[race].pc_race)
			continue;
		write_to_buffer(d, race_table[race].name, 0);
		write_to_buffer(d, " ", 1);
	}
	write_to_buffer(d, "\n\r", 0);
	write_to_buffer(d, "What is your race (help for more information)? ", 0);
	d->connected = CON_GET_NEW_RACE;
}

void handle_con_get_new_race(DESCRIPTOR_DATA * d, const char *argument)
{
	CHAR_DATA *ch = CH(d);
	char arg[MAX_INPUT_LENGTH];
	int race, i;

	one_argument(argument, arg);

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

	race = race_lookup(argument);

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

	if (IS_SET(ch->act, PLR_REMORT) && ch->race != race)
	{
		char buf[MSL];

		sprintf(buf, "You are now a %s forever.\n\r",
				race_table[ch->race].name);
		write_to_buffer(d, buf, 0);
		ch->pcdata->stay_race = TRUE;
	}

	ch->race = race;
	/* initialize stats */
	for (i = 0; i < MAX_STATS; i++)
		ch->perm_stat[i] = 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 (race_table[race].skills[i] == NULL)
			break;
		group_add(ch, race_table[race].skills[i], FALSE);
	}
	/* add cost */
	ch->pcdata->points = race_table[race].points;
	ch->size = race_table[race].size;

	write_to_buffer(d, "What is your sex (M/F)? ", 0);
	d->connected = CON_GET_NEW_SEX;
}

void handle_con_get_new_sex(DESCRIPTOR_DATA * d, const char *argument)
{
	CHAR_DATA *ch = CH(d);
	int iClass;
	char buf[MSL];

	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:
		write_to_buffer(d, "That's not a sex.\n\rWhat IS your sex? ", 0);
		return;
	}

	strcpy(buf, "Select a class [");
	for (iClass = 0; iClass < maxClass; iClass++)
	{
		if (is_class(ch, iClass))
			continue;

		if (iClass > 0)
			strcat(buf, " ");
		strcat(buf, class_table[iClass].name);
	}
	strcat(buf, "]: ");
	write_to_buffer(d, buf, 0);
	d->connected = CON_GET_NEW_CLASS;
}

void handle_con_get_new_class(DESCRIPTOR_DATA * d, const char *argument)
{
	CHAR_DATA *ch = CH(d);
	int iClass = class_lookup(argument);

	if (iClass == -1)
	{
		write_to_buffer(d, "That's not a class.\n\rWhat IS your class? ", 0);
		return;
	}
	/* check to see if person is already a class */
	if (is_class(ch, iClass))
	{
		char buf[MSL];

		sprintf(buf, "You are already part %s. Try another!\n\r",
				class_table[iClass].name);
		write_to_buffer(d, buf, 0);
		return;
	}

	/* Set the class. */
	ch->Class[number_classes(ch)] = iClass;
	ch->Class[number_classes(ch) + 1] = -1;
	/* Last class is ALWAYS -1 */

	if (!IS_SET(ch->act, PLR_REMORT))
	{
		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));

		write_to_buffer(d, "\n\r", 2);
		write_to_buffer(d, "You may be good, neutral, or evil.\n\r", 0);
		write_to_buffer(d, "Which alignment (G/N/E)? ", 0);
		d->connected = CON_GET_ALIGNMENT;
	}
	else
	{
		/* send remorts to customization */
		write_to_buffer(d, "\n\r", 2);
		ch->gen_data = new_gen_data();
		ch->gen_data->points_chosen = ch->pcdata->points;
		add_base_groups(ch);
		ch->pcdata->learned[gsn_recall] =
			UMAX(50, ch->pcdata->learned[gsn_recall]);
		write_to_buffer(d, "Do you wish to customize this character?\n\r", 0);
		write_to_buffer(d,
						"Customization takes time, but allows a wider range of skills and abilities.\n\r",
						0);
		write_to_buffer(d, "Customize (Y/N)? ", 0);
		d->connected = CON_DEFAULT_CHOICE;
	}
}

void send_deity_info(DESCRIPTOR_DATA * d)
{
	int i;
	char buf[MSL];

	write_to_buffer(d, "\n\rDeities Available:\n\r", 0);
	for (i = 0; i < maxDeity; i++)
	{
		sprintf(buf, "\t%-12s : %s\n\r", deity_table[i].name,
				deity_table[i].desc);
		write_to_buffer(d, buf, 0);
	}
	write_to_buffer(d, "\n\r", 2);
}

void handle_con_get_alignment(DESCRIPTOR_DATA * d, const char *argument)
{
	CHAR_DATA *ch = CH(d);

	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:
		write_to_buffer(d, "That's not a valid alignment.\n\r", 0);
		write_to_buffer(d, "Which alignment (G/N/E)? ", 0);
		return;
	}

	send_deity_info(d);
	write_to_buffer(d, "What deity would you like to worship?", 0);
	d->connected = CON_GET_DEITY;
	return;
}

void handle_con_get_deity(DESCRIPTOR_DATA * d, const char *argument)
{
	char arg[MIL];
	int i;
	CHAR_DATA *ch = CH(d);
	char buf[MSL];

	one_argument(argument, arg);

	if (!str_cmp(arg, "help"))
	{
		argument = one_argument(argument, arg);
		if (argument[0] == '\0')
		{
			send_deity_info(d);
			write_to_buffer(d, "What deity would you like to worship?\n\r", 0);
		}
		else
			do_function(ch, &do_help, argument);
		write_to_buffer(d, "What deity would you like to worship?\n\r", 0);
		return;
	}
	i = deity_lookup(argument);

	if (i == -1)
	{
		send_deity_info(d);
		write_to_buffer(d, "What deity would you like to worship?\n\r", 0);
		return;
	}
	ch->deity = i;
	sprintf(buf, "\n\rYou now worship %s.\n\r", deity_table[ch->deity].name);
	write_to_buffer(d, buf, 0);
	write_to_buffer(d, "\n\r", 0);

	group_add(ch, "rom basics", FALSE);
	add_base_groups(ch);
	ch->pcdata->learned[gsn_recall] = 50;
	write_to_buffer(d, "Do you wish to customize this character?\n\r", 0);
	write_to_buffer(d,
					"Customization takes time, but allows a wider range of skills and abilities.\n\r",
					0);
	write_to_buffer(d, "Customize (Y/N)? ", 0);
	d->connected = CON_DEFAULT_CHOICE;
}

void handle_con_default_choice(DESCRIPTOR_DATA * d, const char *argument)
{
	CHAR_DATA *ch = CH(d);
	int i;
	char buf[MSL];

	write_to_buffer(d, "\n\r", 2);
	switch (argument[0])
	{
	case 'y':
	case 'Y':
		ch->gen_data = new_gen_data();
		ch->gen_data->points_chosen = ch->pcdata->points;
		do_function(ch, &do_oldhelp, "group header");
		list_group_costs(ch);
		if (!IS_SET(ch->act, PLR_REMORT))	/* too spammy at tier 6 or 7 */
		{
			write_to_buffer(d, "You already have the following skills:\n\r", 0);
			do_function(ch, &do_skills, "");
		}
		do_function(ch, &do_oldhelp, "menu choice");
		d->connected = CON_GEN_GROUPS;
		break;
	case 'n':
	case 'N':
		add_default_groups(ch);
		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;
	}
}

void handle_con_pick_weapon(DESCRIPTOR_DATA * d, const char *argument)
{
	CHAR_DATA *ch = CH(d);
	int i, weapon;
	char buf[MSL];

	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? ");
		write_to_buffer(d, buf, 0);
		return;
	}

	ch->pcdata->learned[*weapon_table[weapon].gsn] =
		UMAX(40, ch->pcdata->learned[*weapon_table[weapon].gsn]);
	write_to_buffer(d, "\n\r", 2);
	if (IS_SET(ch->act, PLR_REMORT))
	{
		write_to_buffer(d, "Sucessful Remort!\n\r", 0);
		wiznet("Sucessful Remort!  $N sighted.", ch, NULL, 0, 0, 0);
		REMOVE_BIT(ch->comm, COMM_QUIET);
		char_from_room(ch);
		char_to_room(ch, get_room_index(ROOM_VNUM_SCHOOL));
		d->connected = CON_PLAYING;
		act
			("The Priest brings you back to reality, and you feel quite different now...",
			 ch, NULL, NULL, TO_CHAR);
		do_function(ch, &do_outfit, "");
		save_char_obj(ch);
		return;
	}
	do_function(ch, &do_oldhelp, "motd");
	d->connected = CON_READ_MOTD;
}

void handle_con_gen_groups(DESCRIPTOR_DATA * d, const char *argument)
{
	CHAR_DATA *ch = CH(d);
	char buf[MSL];
	int i;

	chprintln(ch, "");

	if (!str_cmp(argument, "done"))
	{
		if (ch->pcdata->points == race_table[ch->race].points)
		{
			chprintln(ch, "You didn't pick anything.");
			return;
		}

		if (!IS_SET(ch->act, PLR_REMORT)
			&& ch->pcdata->points <= 40 + race_table[ch->race].points)
		{
			chprintlnf(ch,
					   "You must take at least %d points of skills and groups",
					   40 + race_table[ch->race].points);
			return;
		}

		chprintlnf(ch, "Creation points: %d", ch->pcdata->points);
		chprintlnf(ch, "Experience per level: %d",
				   exp_per_level(ch, ch->gen_data->points_chosen));
		if (ch->pcdata->points < 40)
			ch->train = (40 - ch->pcdata->points + 1) / 2;
		free_gen_data(ch->gen_data);
		ch->gen_data = NULL;
		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;
		return;
	}

	if (!parse_gen_groups(ch, argument))
		chprintln(ch,
				  "Choices are: list,learned,premise,add,drop,info,help, and done.");

	do_function(ch, &do_oldhelp, "menu choice");
}

void handle_con_read_imotd(DESCRIPTOR_DATA * d, const char *argument)
{
	CHAR_DATA *ch = CH(d);

	write_to_buffer(d, "\n\r", 2);
	do_function(ch, &do_oldhelp, "motd");
	d->connected = CON_READ_MOTD;
}

void handle_con_read_motd(DESCRIPTOR_DATA * d, const char *argument)
{
	CHAR_DATA *ch = CH(d);
	char buf[MSL];

	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 ROM 2.4.  Please do not feed the mobiles.\n\r",
					0);
	LINK(ch, char_first, char_last, next, prev);
	LINK(ch, player_first, player_last, 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[ch->Class[0]].attr_prime] += 3;

		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;
		sprintf(buf, "the %s", class_table[ch->Class[0]].name);
		set_title(ch, buf);

		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, "");
		do_function(ch, &do_oldhelp, "newbie info");
		chprintln(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));
	}

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

	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);
	}

	do_function(ch, &do_board, "");
	unfinished_quest(ch);
	update_explored(ch);
	checkcorpse(ch);
}

/*
 * Deal with sockets that haven't logged in yet.
 */
void nanny(DESCRIPTOR_DATA * d, const char *argument)
{

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

	switch (d->connected)
	{

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

	case CON_GET_TERM:
		handle_con_get_term(d, argument);
		break;

	case CON_GET_NAME:
		handle_con_get_name(d, argument);
		break;

	case CON_GET_OLD_PASSWORD:
		handle_con_get_old_password(d, argument);
		break;

/* RT code for breaking link */

	case CON_BREAK_CONNECT:
		handle_con_break_connect(d, argument);
		break;

	case CON_CONFIRM_NEW_NAME:
		handle_con_confirm_new_name(d, argument);
		break;

	case CON_GET_NEW_PASSWORD:
		handle_con_get_new_password(d, argument);
		break;

	case CON_CONFIRM_NEW_PASSWORD:
		handle_con_confirm_new_password(d, argument);
		break;

	case CON_GET_NEW_RACE:
		handle_con_get_new_race(d, argument);
		break;

	case CON_GET_NEW_SEX:
		handle_con_get_new_sex(d, argument);
		break;

	case CON_GET_NEW_CLASS:
		handle_con_get_new_class(d, argument);
		break;

	case CON_GET_ALIGNMENT:
		handle_con_get_alignment(d, argument);
		break;

	case CON_GET_DEITY:
		handle_con_get_deity(d, argument);
		break;

	case CON_DEFAULT_CHOICE:
		handle_con_default_choice(d, argument);
		break;

	case CON_PICK_WEAPON:
		handle_con_pick_weapon(d, argument);
		break;

	case CON_GEN_GROUPS:
		handle_con_gen_groups(d, argument);
		break;

	case CON_READ_IMOTD:
		handle_con_read_imotd(d, argument);
		break;

		/* states for new note system, (c)1995-96 erwin@andreasen.org */
		/* 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;					/* subject */

	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:
		handle_con_read_motd(d, argument);
		break;
	}

	return;
}