asgard/
asgard/.settings/
asgard/area/
asgard/data/clans/
asgard/data/clans/history/
asgard/data/rosters/
asgard/src/notice/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, 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.                                               *
 *                                                                         *
 *  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-1995 Russ Taylor			   *
 *	ROM has been brought to you by the ROM consortium		   *
 *	    Russ Taylor (rtaylor@pacinfo.com)				   *
 *	    Gabrielle Taylor (gtaylor@pacinfo.com)			   *
 *	    Brian Moore (rom@rom.efn.org)				   *
 *	By using this code, you have agreed to follow the terms of the	   *
 *	ROM license, in the file Rom24/doc/rom.license			   *
 ***************************************************************************/

/*************************************************************************** 
 *       ROT 1.4 is copyright 1996-1997 by Russ Walsh                       *
 *       By using this code, you have agreed to follow the terms of the     *
 *       ROT license, in the file doc/rot.license                           *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#include <time.h>
#else
#include <sys/types.h>
#include <errno.h>		
#include <unistd.h>		
#include <sys/time.h>
#endif
#include <malloc.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "merc.h"
#include "recycle.h"
#include "lookup.h"
#include "tables.h"
#include "newclan.h"
#include "newquest.h"
#include "achievements.h"

#if !defined(macintosh)
extern int _filbuf(FILE *);
#endif

int rename(const char *oldfname, const char *newfname);

char *initial(const char *str)
{
	static char strint[MAX_STRING_LENGTH];

	strint[0] = LOWER( str[ 0 ] );
	return strint;

}

char *print_flags(int flag)
{
	int count, pos = 0;
	static char buf[52];

	for (count = 0; count < 32; count++)
	{
		if (IS_SET(flag,1<<count))
		{
			if (count < 26)
				buf[pos] = 'A' + count;
			else
				buf[pos] = 'a' + (count - 26);
			pos++;
		}
	}

	if (pos == 0)
	{
		buf[pos] = '0';
		pos++;
	}

	buf[pos] = '\0';

	return buf;
}

/*
 * Array of containers read for proper re-nesting of objects.
 */
#define MAX_NEST        150
static OBJ_DATA * rgObjNest[MAX_NEST];

/*
 * Local functions.
 */
void fwrite_char( CHAR_DATA *ch, FILE *fp );

/* New DB style */
void save_chararacter_full( CHAR_DATA *ch );
// -- Saves Following:
//    - PLAYER
//    - PSTATIC
//    - POBJECTS

void fwrite_obj( CHAR_DATA *ch, OBJ_DATA *obj, FILE *fp, int iNest, bool locker );
void fwrite_pet( CHAR_DATA *pet, FILE *fp);
void fread_char( CHAR_DATA *ch, FILE *fp );
			
void fread_pet( CHAR_DATA *ch, FILE *fp );
void fread_obj( CHAR_DATA *ch, FILE *fp, bool locker );
void fread_char_reroll( CHAR_DATA *ch, FILE *fp );
void generate_baseHMVP( CHAR_DATA *ch );
int focus_hp( CHAR_DATA *ch, int state );
int focus_mana( CHAR_DATA *ch, int state );
int focus_move( CHAR_DATA *ch, int state );

/*
 * Save a character and inventory.
 * Would be cool to save NPC's too for quest purposes,
 *   some of the infrastructure is provided.
 */

//Obj code here bree
void save_char_obj(CHAR_DATA *ch)
{
	char strsave[MAX_INPUT_LENGTH];
	FILE *fp;

	if (IS_NPC(ch))
		return;

	if (ch->desc != NULL && ch->desc->original != NULL)
		ch = ch->desc->original;

#if defined(unix)
	/* create god log */
	if (IS_IMMORTAL(ch) || ch->level >= LEVEL_IMMORTAL)
	{
		sprintf(strsave, "%s%s", GOD_DIR, capitalize(ch->name));
		if ((fp = fopen(strsave, "w")) == NULL)
		{
			printf_debug("Save_char_obj: fopen");
			perror(strsave);
		}

		fprintf(fp, "Lev %2d Trust %2d  %s%s\n", ch->level, get_trust(ch),
				ch->name, ch->pcdata->title);
		fclose(fp);
	}
#endif

	/* player files parsed directories by Yaz 4th Realm */
#if !defined( macintosh )
	sprintf(strsave, "%s%s%s%s", PLAYER_DIR, initial(ch->name), "/",
			capitalize(ch->name));
#else
	sprintf( strsave, "%s%s", PLAYER_DIR, capitalize( ch->name ) );
#endif
	if ((fp = get_temp_file()) == NULL)
	{
		printf_debug("Save_char_obj: fopen");
		perror(strsave);
	}
	else
	{
		fwrite_char(ch, fp);
		if (ch->carrying != NULL)
			fwrite_obj(ch, ch->carrying, fp, 0, FALSE);
		/* save the pets */
		if (ch->pet != NULL)
			fwrite_pet(ch->pet, fp);
		fprintf(fp, "#END\n");
	}
	close_write_file(strsave);
	if (ch->pcdata && ch->pcdata->roster)
		save_roster_data(ch->pcdata->roster);
	return;
}

/*
 * Write the char.
 */
void fwrite_char(CHAR_DATA *ch, FILE *fp)
{
	AFFECT_DATA *paf;
	GRANT_DATA *gran;
	int sn, pos;
	int ut;

	fprintf(fp, "#%s\n", IS_NPC(ch) ? "MOB" : "PLAYER");

	fprintf(fp, "Name %s~\n", ch->name);
	fprintf(fp, "Id   %ld\n", ch->id);
	fprintf(fp, "LogO %ld\n", current_time);
	fprintf(fp, "Vers %d\n", 5);
	if (ch->short_descr[0] != '\0')
		fprintf(fp, "ShD  %s~\n", ch->short_descr);
	if (ch->long_descr[0] != '\0')
		fprintf(fp, "LnD  %s~\n", ch->long_descr);
	if (ch->description[0] != '\0')
		fprintf(fp, "Desc %s~\n", ch->description);
	if (ch->prompt != NULL
			|| !str_cmp(ch->prompt, "<%g/%H{chp %n/%M{cmp %w/%V{cmv {Y${W%P {C%X{Wtnl{x> "))
		fprintf(fp, "Prom %s~\n", ch->prompt);
	fprintf(fp, "Race %s~\n", race_table[ch->race].name);

	fprintf(fp, "Deity %s~\n", (god_table[ch->god].name));
	if (ch->color != 0)
		fprintf(fp, "Color %d\n", ch->color);
	if (ch->color_auc != 0)
		fprintf(fp, "Coauc %d\n", ch->color_auc);
	if (ch->color_cgo != 0)
		fprintf(fp, "Cocgo %d\n", ch->color_cgo);
	if (ch->color_cla != 0)
		fprintf(fp, "Cocla %d\n", ch->color_cla);
	if (ch->color_con != 0)
		fprintf(fp, "Cocon %d\n", ch->color_con);
	if (ch->color_dis != 0)
		fprintf(fp, "Codis %d\n", ch->color_dis);
	if (ch->color_fig != 0)
		fprintf(fp, "Cofig %d\n", ch->color_fig);
	if (ch->color_gos != 0)
		fprintf(fp, "Cogos %d\n", ch->color_gos);
	if (ch->color_gra != 0)
		fprintf(fp, "Cogra %d\n", ch->color_gra);
	if (ch->color_gte != 0)
		fprintf(fp, "Cogte %d\n", ch->color_gte);
	if (ch->color_imm != 0)
		fprintf(fp, "Coimm %d\n", ch->color_imm);
	if (ch->color_mob != 0)
		fprintf(fp, "Comob %d\n", ch->color_mob);
	if (ch->color_mus != 0)
		fprintf(fp, "Comus %d\n", ch->color_mus);
	if (ch->color_opp != 0)
		fprintf(fp, "Coopp %d\n", ch->color_opp);
	if (ch->color_qgo != 0)
		fprintf(fp, "Coqgo %d\n", ch->color_qgo);
	if (ch->color_que != 0)
		fprintf(fp, "Coque %d\n", ch->color_que);
	if (ch->color_quo != 0)
		fprintf(fp, "Coquo %d\n", ch->color_quo);
	if (ch->color_roo != 0)
		fprintf(fp, "Coroo %d\n", ch->color_roo);
	if (ch->color_say != 0)
		fprintf(fp, "Cosay %d\n", ch->color_say);
	if (ch->color_sho != 0)
		fprintf(fp, "Cosho %d\n", ch->color_sho);
	if (ch->color_tel != 0)
		fprintf(fp, "Cotel %d\n", ch->color_tel);
	if (ch->color_wit != 0)
		fprintf(fp, "Cowit %d\n", ch->color_wit);
	if (ch->color_wiz != 0)
		fprintf(fp, "Cowiz %d\n", ch->color_wiz);
	fprintf(fp, "Sex  %d\n", ch->sex);
	fprintf(fp, "Clas %s~\n", class_table[ch->class].name);
	fprintf(fp, "Levl %d\n", ch->level);
	fprintf(fp, "Tier %d\n", ch->pcdata->tier);
	if (ch->trust != 0)
		fprintf(fp, "Tru  %d\n", ch->trust);
	fprintf(fp, "Sec  %d\n", ch->pcdata->security); /* OLC */
	fprintf(fp, "Plyd %d\n", ch->played + (int) (current_time - ch->logon));
	if (!IS_NPC(ch))
		fprintf(fp, "Not  %ld %ld %ld %ld %ld %ld %ld\n",
				ch->pcdata->last_note, ch->pcdata->last_idea,
				ch->pcdata->last_penalty, ch->pcdata->last_news,
				ch->pcdata->last_changes, ch->pcdata->last_weddings,
				ch->pcdata->last_quotes);
	fprintf(fp, "Scro %d\n", ch->lines);
	fprintf(fp, "Room %d\n", (ch->in_room == get_room_index(ROOM_VNUM_LIMBO)
			&& ch->was_in_room != NULL) ? ch->was_in_room->vnum : ch->in_room
			== NULL ? 3001 : ch->in_room->vnum);

	fprintf(fp, "HMV  %d %d %d %d %d %d\n", ch->hit, ch->max_hit, ch->mana,
			ch->max_mana, ch->move, ch->max_move);
	if (ch->platinum > 0)
		fprintf(fp, "Plat %ld\n", ch->platinum);
	else
		fprintf(fp, "Plat %d\n", 0);
	if (ch->gold > 0)
		fprintf(fp, "Gold %ld\n", ch->gold);
	else
		fprintf(fp, "Gold %d\n", 0);
	if (ch->silver > 0)
		fprintf(fp, "Silv %ld\n", ch->silver);
	else
		fprintf(fp, "Silv %d\n", 0);
	fprintf(fp, "Bal  %ld %ld %ld %ld\n", ch->balance[0] > 0 ? ch->balance[0]
			: 0, ch->balance[1] > 0 ? ch->balance[1] : 0,
			ch->balance[2] > 0 ? ch->balance[2] : 0,
			ch->balance[3] > 0 ? ch->balance[3] : 0);
	fprintf(fp, "Exp  %ld\n", ch->exp);
	if (ch->act != 0)
		fprintf(fp, "Act  %s\n", print_flags(ch->act));
	fprintf(fp, "Stance     %d %d %d %d %d %d %d %d %d %d %d\n", ch->stance[0],
			ch->stance[1], ch->stance[2], ch->stance[3], ch->stance[4],
			ch->stance[5], ch->stance[6], ch->stance[7], ch->stance[8],
			ch->stance[9], ch->stance[10]);

	if (ch->affected_by != 0)
		fprintf(fp, "AfBy %s\n", print_flags(ch->affected_by));
	if (ch->shielded_by != 0)
		fprintf(fp, "ShBy %s\n", print_flags(ch->shielded_by));
	fprintf(fp, "Comm %s\n", print_flags(ch->comm));
	if (ch->wiznet)
		fprintf(fp, "Wizn %s\n", print_flags(ch->wiznet));
	if (ch->invis_level)
		fprintf(fp, "Invi %d\n", ch->invis_level);
	if (ch->incog_level)
		fprintf(fp, "Inco %d\n", ch->incog_level);
	if (ch->ghost_level)
		fprintf(fp, "Ghos %d\n", ch->ghost_level);
	fprintf(fp, "Pos  %d\n", ch->position == POS_FIGHTING ? POS_STANDING
			: ch->position);
	if (ch->practice != 0)
		fprintf(fp, "Prac %d\n", ch->practice);
	if (ch->train != 0)
		fprintf(fp, "Trai %d\n", ch->train);
	if (ch->saving_throw != 0)
		fprintf(fp, "Save  %d\n", ch->saving_throw);
	fprintf(fp, "Alig  %d\n", ch->alignment);
	if (ch->hitroll != 0)
		fprintf(fp, "Hit   %d\n", ch->hitroll);
	if (ch->damroll != 0)
		fprintf(fp, "Dam   %d\n", ch->damroll);
	fprintf(fp, "ACs %d %d %d %d\n", ch->armor[0], ch->armor[1], ch->armor[2],
			ch->armor[3]);
	if (ch->wimpy != 0)
		fprintf(fp, "Wimp  %d\n", ch->wimpy);
	fprintf(fp, "Attr %d %d %d %d %d\n",

	ch->perm_stat[STAT_STR], ch->perm_stat[STAT_INT], ch->perm_stat[STAT_WIS],
			ch->perm_stat[STAT_DEX], ch->perm_stat[STAT_CON]);

	fprintf(fp, "AMod %d %d %d %d %d\n", ch->mod_stat[STAT_STR],
			ch->mod_stat[STAT_INT], ch->mod_stat[STAT_WIS],
			ch->mod_stat[STAT_DEX], ch->mod_stat[STAT_CON]);

	if (IS_NPC(ch))
	{
		fprintf(fp, "Vnum %d\n", ch->pIndexData->vnum);
	}
	else
	{
		fprintf(fp, "Pass %s~\n", ch->pcdata->pwd);
		if (ch->pcdata->bamfin[0] != '\0')
			fprintf(fp, "Bin  %s~\n", ch->pcdata->bamfin);
		if (ch->pcdata->bamfout[0] != '\0')
			fprintf(fp, "Bout %s~\n", ch->pcdata->bamfout);
		if (IS_IMMORTAL(ch) && ch->pcdata->identity[0] != '\0')
			fprintf(fp, "Iden %s~\n", ch->pcdata->identity);
		if (ch->pcdata->immskll[0] != '\0')
			fprintf(fp, "Imsk %s~\n", ch->pcdata->immskll);
		if (ch->pcdata->who_descr[0] != '\0')
			fprintf(fp, "Whod %s~\n", ch->pcdata->who_descr);
		fprintf(fp, "Titl %s~\n", ch->pcdata->title);
		if (ch->pcdata->pretit)
			fprintf(fp, "Pretit %s~\n", ch->pcdata->pretit);
		/*        if (ch->pcdata->colour_name == '\0')
		 ch->pcdata->colour_name = str_dup(ch->name);
		 fprintf( fp, "ClrName %s~\n",   ch->pcdata->colour_name ); */
		if (ch->pcdata->usr_ttl)
			ut = 1;
		else
			ut = 0;
		fprintf(fp, "UsrTtl %d\n", ut);
		fprintf(fp, "Pnts %d\n", ch->pcdata->points);
		fprintf(fp, "TSex %d\n", ch->pcdata->true_sex);
		fprintf(fp, "LLev %d\n", ch->pcdata->last_level);
		fprintf(fp, "Reca %d\n", ch->pcdata->recall);
	//	fprintf(fp, "HMVP %d %d %d\n", ch->pcdata->perm_hit,
	//			ch->pcdata->perm_mana, ch->pcdata->perm_move);
		fprintf(fp, "BaseHMVP %d %d %d\n", ch->pcdata->base_hit,
				ch->pcdata->base_mana, ch->pcdata->base_move);
		fprintf(fp, "Cnd  %d %d %d %d\n", ch->pcdata->condition[0],
				ch->pcdata->condition[1], ch->pcdata->condition[2],
				ch->pcdata->condition[3]);

		if (ch->questpoints != 0)
			fprintf(fp, "QuestPnts %d\n", ch->questpoints);

		fprintf(fp, "QState %d\n", ch->qstate);
		fprintf(fp, "QTarget %d\n", ch->qtarget);
		fprintf(fp, "QTimer %d\n", ch->qtimer);
		fprintf(fp, "QMVnum %d\n", ch->qmvnum);
		fprintf(fp, "QRoom %d\n", ch->qroom);

		/* write forgets */
		for (pos = 0; pos < MAX_FORGET; pos++)
		{
			if (ch->pcdata->forget[pos] == NULL)
				break;

			fprintf(fp, "Forge %s~\n", ch->pcdata->forget[pos]);
		}

		/* write dupes */
		for (pos = 0; pos < MAX_DUPES; pos++)
		{
			if (ch->pcdata->dupes[pos] == NULL)
				break;

			fprintf(fp, "Dupes %s~\n", ch->pcdata->dupes[pos]);
		}

		/* write alias */
		for (pos = 0; pos < MAX_ALIAS; pos++)
		{
			if (ch->pcdata->alias[pos] == NULL || ch->pcdata->alias_sub[pos]
					== NULL)
				break;

			fprintf(fp, "Alias %s %s~\n", ch->pcdata->alias[pos],
					ch->pcdata->alias_sub[pos]);
		}

		for (sn = 0; sn < MAX_SKILL; sn++)
		{
			if (skill_table[sn].name != NULL && ch->pcdata->learned[sn] > -1)
			{
				fprintf(fp, "Sk %d '%s'\n", ch->pcdata->learned[sn],
						skill_table[sn].name);
			}
		}

		for (sn = 0; sn < MAX_SKILL; sn++)
		{
			if (skill_table[sn].name != NULL && ch->pcdata->learnlvl[sn] > -1)
			{
				fprintf(fp, "Sklvl %d '%s'\n", ch->pcdata->learnlvl[sn],
						skill_table[sn].name);
			}
		}

		fprintf(fp, "Power %d %d %d\n", ch->pcdata->power[POWER_KILLS],
				ch->pcdata->power[POWER_POINTS], ch->pcdata->power[POWER_LEVEL]);

		fprintf(fp, "Focus2 %ld %ld %ld %ld %ld %ld %ld %ld %ld\n",
				ch->pcdata->focus[COMBAT_POWER],
				ch->pcdata->focus[COMBAT_DEFENSE],
				ch->pcdata->focus[COMBAT_AGILITY],
				ch->pcdata->focus[COMBAT_TOUGHNESS],
				ch->pcdata->focus[MAGIC_POWER],
				ch->pcdata->focus[MAGIC_ABILITY],
				ch->pcdata->focus[MAGIC_DEFENSE],
				ch->pcdata->focus[CURRENT_FOCUS],
				ch->pcdata->focus[MAGIC_RESONANCE]);

		if (ch->plyr != 0)
			fprintf(fp, "Plyr  %s\n", print_flags(ch->plyr));
		if (str_cmp(ch->ghost, ""))
			fprintf(fp, "Ghost %s~\n", ch->ghost);
		if (ch->ghost_timer > 0)
			fprintf(fp, "GTime %d\n", ch->ghost_timer);
		if (ch->toughness > 0)
			fprintf(fp, "Tough %d\n", ch->toughness);
		if (ch->pcdata->status > 0)
			fprintf(fp, "Status %d\n", ch->pcdata->status);

		fprintf(fp, "Mtype %d %d %d %d %d %d\n", ch->magic[MAGIC_WHITE],
				ch->magic[MAGIC_RED], ch->magic[MAGIC_BLUE],
				ch->magic[MAGIC_GREEN], ch->magic[MAGIC_BLACK],
				ch->magic[MAGIC_ORANGE]);

		for (gran = ch->pcdata->granted; gran != NULL; gran = gran->next)
			fprintf(fp, "Grant '%s' %d\n", gran->name, gran->duration);

		if (ch->mpstates) {
			MPSTATE *mpstate;
			for (mpstate = ch->mpstates; mpstate != NULL; mpstate = mpstate->next)
				fprintf(fp, "MPSt %d %d\n", mpstate->mobvnum, mpstate->state);
		}

		// Achievement info.
		for (pos = 0; pos < ACH_MAX; ++pos)
			fprintf(fp, "AchM %lu\n", ch->pcdata->achievement_metrics[pos]);
		const ACH_DEFINITION *def;
		for (def = achievements_table; def->name != NULL; ++def) {
			if (ach_unlocked(ch, def))
				fprintf(fp, "AchD %s\n", def->save_name);
		}
	}

	for (paf = ch->affected; paf != NULL; paf = paf->next)
	{
		if (paf->type < 0 || paf->type >= MAX_SKILL)
			continue;

		fprintf(fp, "Affc '%s' %3d %3d %3d %3d %3d %10d\n",
				skill_table[paf->type].name, paf->where, paf->level,
				paf->duration, paf->modifier, paf->location, paf->bitvector);

	}
	fprintf(fp, "End\n\n");

	if (ch->locker != NULL)
		fwrite_obj(ch, ch->locker, fp, 0, TRUE);
	if (IS_SET(ch->act, PLR_REROLL ))
		fprintf(fp, "#END\n");
	return;
}

/* write a pet */
void fwrite_pet(CHAR_DATA *pet, FILE *fp)
{
	AFFECT_DATA *paf;

	fprintf(fp, "#PET\n");

	fprintf(fp, "Vnum %d\n", pet->pIndexData->vnum);

	fprintf(fp, "Name %s~\n", pet->name);
	fprintf(fp, "LogO %ld\n", current_time);
	if (pet->short_descr != pet->pIndexData->short_descr)
		fprintf(fp, "ShD  %s~\n", pet->short_descr);
	if (pet->long_descr != pet->pIndexData->long_descr)
		fprintf(fp, "LnD  %s~\n", pet->long_descr);
	if (pet->description != pet->pIndexData->description)
		fprintf(fp, "Desc %s~\n", pet->description);
	if (pet->race != pet->pIndexData->race)
		fprintf(fp, "Race %s~\n", race_table[pet->race].name);
	fprintf(fp, "Sex  %d\n", pet->sex);
	if (pet->level != pet->pIndexData->level)
		fprintf(fp, "Levl %d\n", pet->level);
	fprintf(fp, "HMV  %d %d %d %d %d %d\n", pet->hit, pet->max_hit, pet->mana,
			pet->max_mana, pet->move, pet->max_move);
	if (pet->platinum > 0)
		fprintf(fp, "Plat %ld\n", pet->platinum);
	if (pet->gold > 0)
		fprintf(fp, "Gold %ld\n", pet->gold);
	if (pet->silver > 0)
		fprintf(fp, "Silv %ld\n", pet->silver);
	if (pet->exp > 0)
		fprintf(fp, "Exp  %ld\n", pet->exp);
	if (pet->act != pet->pIndexData->act)
		fprintf(fp, "Act  %s\n", print_flags(pet->act));
	if (pet->affected_by != pet->pIndexData->affected_by)
		fprintf(fp, "AfBy %s\n", print_flags(pet->affected_by));
	if (pet->shielded_by != pet->pIndexData->shielded_by)
		fprintf(fp, "ShBy %s\n", print_flags(pet->shielded_by));
	if (pet->comm != 0)
		fprintf(fp, "Comm %s\n", print_flags(pet->comm));
	fprintf(fp, "Pos  %d\n", pet->position = POS_FIGHTING ? POS_STANDING
			: pet->position);
	if (pet->saving_throw != 0)
		fprintf(fp, "Save %d\n", pet->saving_throw);
	if (pet->alignment != pet->pIndexData->alignment)
		fprintf(fp, "Alig %d\n", pet->alignment);
	if (pet->hitroll != pet->pIndexData->hitroll)
		fprintf(fp, "Hit  %d\n", pet->hitroll);
	if (pet->damroll != pet->pIndexData->damage[DICE_BONUS])
		fprintf(fp, "Dam  %d\n", pet->damroll);
	fprintf(fp, "ACs  %d %d %d %d\n", pet->armor[0], pet->armor[1],
			pet->armor[2], pet->armor[3]);
	fprintf(fp, "Attr %d %d %d %d %d\n", pet->perm_stat[STAT_STR],
			pet->perm_stat[STAT_INT], pet->perm_stat[STAT_WIS],
			pet->perm_stat[STAT_DEX], pet->perm_stat[STAT_CON]);
	fprintf(fp, "AMod %d %d %d %d %d\n", pet->mod_stat[STAT_STR],
			pet->mod_stat[STAT_INT], pet->mod_stat[STAT_WIS],
			pet->mod_stat[STAT_DEX], pet->mod_stat[STAT_CON]);

	for (paf = pet->affected; paf != NULL; paf = paf->next)
	{
		if (paf->type < 0 || paf->type >= MAX_SKILL)
			continue;

		fprintf(fp, "Affc '%s' %3d %3d %3d %3d %3d %10d\n",
				skill_table[paf->type].name, paf->where, paf->level,
				paf->duration, paf->modifier, paf->location, paf->bitvector);
	}

	fprintf(fp, "End\n");
	return;
}

/*
 * Write an object and its contents.
 */
void fwrite_obj(CHAR_DATA *ch, OBJ_DATA *obj, FILE *fp, int iNest, bool locker)
{
	EXTRA_DESCR_DATA *ed;
	AFFECT_DATA *paf;

	/*
	 * Slick recursion to write lists backwards,
	 *   so loading them will load in forwards order.
	 */

	if (obj->next_content != NULL)
		fwrite_obj(ch, obj->next_content, fp, iNest, locker);

	/*
	 * Castrate storage characters.
	 */
	//if ( (ch->level < obj->level - 5 && obj->level > 19    changes here BOOYABREE
	// if ( (obj->item_type != ITEM_CONTAINER
	//&&  obj->item_type != ITEM_PIT))
	// ||   obj->item_type == ITEM_KEY
	// ||   (obj->item_type == ITEM_MAP && !obj->value[0]))
	//	return;

	/* KEYS WILL NOW DISAPPEAR ON LOG OUT AGAIN by Dusk */

	if (obj->item_type == ITEM_KEY)
		return;

	if (locker)
		fprintf(fp, "#LOCKER\n");
	else
		fprintf(fp, "#O\n");
	fprintf(fp, "Vnum %d\n", obj->pIndexData->vnum);
	if (!obj->pIndexData->new_format)
		fprintf(fp, "Oldstyle\n");
	if (obj->enchanted)
		fprintf(fp, "Enchanted\n");
	fprintf(fp, "Nest %d\n", iNest);

	/* these data are only used if they do not match the defaults */

	if (obj->name != obj->pIndexData->name)
		fprintf(fp, "Name %s~\n", obj->name);
	if (obj->short_descr != obj->pIndexData->short_descr)
		fprintf(fp, "ShD  %s~\n", obj->short_descr);
	if (obj->description != obj->pIndexData->description)
		fprintf(fp, "Desc %s~\n", obj->description);
	if (obj->extra_flags != obj->pIndexData->extra_flags)
		fprintf(fp, "ExtF %d\n", obj->extra_flags);
	if (obj->wear_flags != obj->pIndexData->wear_flags)
		fprintf(fp, "WeaF %d\n", obj->wear_flags);
	if (obj->item_type != obj->pIndexData->item_type)
		fprintf(fp, "Ityp %d\n", obj->item_type);
	if (obj->weight != obj->pIndexData->weight)
		fprintf(fp, "Wt   %d\n", obj->weight);
	if (obj->condition != obj->pIndexData->condition)
		fprintf(fp, "Cond %d\n", obj->condition);

	/* variable data */

	fprintf(fp, "Wear %d\n", obj->wear_loc);
	if (obj->level != obj->pIndexData->level)
		fprintf(fp, "Lev  %d\n", obj->level);
	if (obj->tier_level != 0)
		fprintf(fp, "TierLevel %d\n", obj->tier_level);
	if (obj->timer != 0)
		fprintf(fp, "Time %d\n", obj->timer);
	fprintf(fp, "Cost %d\n", obj->cost);
	if (obj->value[0] != obj->pIndexData->value[0] || obj->value[1]
			!= obj->pIndexData->value[1] || obj->value[2]
			!= obj->pIndexData->value[2] || obj->value[3]
			!= obj->pIndexData->value[3] || obj->value[4]
			!= obj->pIndexData->value[4])
		fprintf(fp, "Val  %d %d %d %d %d\n", obj->value[0], obj->value[1],
				obj->value[2], obj->value[3], obj->value[4]);

	if (obj->maker != NULL)
		fprintf(fp, "Makr %s~\n", obj->maker);

	if (obj->owner != NULL)
		fprintf(fp, "Ownr %s~\n", obj->owner);

	switch (obj->item_type)
	{
	case ITEM_POTION:
	case ITEM_SCROLL:
		if (obj->value[1] > 0)
		{
			fprintf(fp, "Spell 1 '%s'\n", skill_table[obj->value[1]].name);
		}

		if (obj->value[2] > 0)
		{
			fprintf(fp, "Spell 2 '%s'\n", skill_table[obj->value[2]].name);
		}

		if (obj->value[3] > 0)
		{
			fprintf(fp, "Spell 3 '%s'\n", skill_table[obj->value[3]].name);
		}

		break;

	case ITEM_PILL:
	case ITEM_STAFF:
	case ITEM_WAND:
		if (obj->value[3] > 0)
		{
			fprintf(fp, "Spell 3 '%s'\n", skill_table[obj->value[3]].name);
		}

		break;
	}

	for (paf = obj->affected; paf != NULL; paf = paf->next)
	{
		if (paf->type < 0 || paf->type >= MAX_SKILL)
		{
			fprintf(fp, "Affc 'none' %3d %3d %3d %3d %3d %10d\n", paf->where,
					paf->level, paf->duration, paf->modifier, paf->location,
					paf->bitvector);

		}
		else
		{
			fprintf(fp, "Affc '%s' %3d %3d %3d %3d %3d %10d\n",
					skill_table[paf->type].name, paf->where, paf->level,
					paf->duration, paf->modifier, paf->location, paf->bitvector);
		}
	}

	for (ed = obj->extra_descr; ed != NULL; ed = ed->next)
	{
		fprintf(fp, "ExDe %s~ %s~\n", ed->keyword, ed->description);
	}

	// PRINT PK LOOTING DATA
	if (obj->loot_timer > 0)
	{
		fprintf(fp, "LootX %d\n", obj->loot_timer);
		fprintf(fp, "LootR %s~\n", obj->looted_by);
		fprintf(fp, "LootD %s~\n", obj->looted_from);
	}
	// SIGNAL END OF OBJECT DATA
	fprintf(fp, "End\n\n");

	if (obj->contains != NULL)
		fwrite_obj(ch, obj->contains, fp, iNest + 1, locker);

	return;
}

bool load_ch_obj_nodesc(CHAR_DATA *ch, char *name) {
	char strsave[MAX_INPUT_LENGTH];
	char buf[100];
	FILE *fp;
	bool found;
	int stat;

	ch->name = str_dup(name);
	ch->id = get_pc_id();
	ch->race = race_lookup("human");
	ch->act = PLR_NOSUMMON;
	ch->comm = COMM_COMBINE | COMM_PROMPT | COMM_STORE;
	ch->prompt = str_dup("<%g/%H{chp %n/%M{cmp %w/%V{cmv {Y${W%P {C%X{Wtnl{x> ");
	ch->pcdata->confirm_delete = FALSE;
	ch->pcdata->pwd = str_dup("");
	ch->pcdata->bamfin = str_dup("");
	ch->pcdata->bamfout = str_dup("");
	ch->pcdata->identity = str_dup("");
	ch->pcdata->immskll = str_dup("");
	ch->pcdata->who_descr = str_dup("");
	ch->pcdata->title = str_dup("");
	ch->pcdata->pretit = str_dup("");
	/*    ch->pcdata->colour_name             = str_dup( "" ); */
	ch->pcdata->usr_ttl = FALSE;
	ch->gladiator = NULL;
	ch->pcdata->tier = 1;
	for (stat = 0; stat < MAX_STATS; stat++)
		ch->perm_stat[stat] = 13;
	ch->pcdata->condition[COND_THIRST] = 48;
	ch->pcdata->condition[COND_FULL] = 48;
	ch->pcdata->condition[COND_HUNGER] = 48;
	ch->pcdata->security = 0; /* OLC */
	ch->pload = NULL; /* Skyn */
	ch->pcdata->power[POWER_KILLS] = 0; /* Highlander */
	ch->pcdata->power[POWER_POINTS] = 0;
	ch->pcdata->power[POWER_LEVEL] = 0;
	ch->ghost = str_dup("");
	ch->ghost_timer = -1;
	ch->regen_rate = 0;
	ch->mana_regen_rate = 0;
	ch->toughness = 0;
	ch->pcdata->status = 0;
	for (stat = 0; stat < 6; stat++)
		ch->magic[stat] = 1;

	for (stat = 1; stat < 11; stat++)
		ch->stance[stat] = 1;

	/* Sets all skills to not learned before read of what they know */
	for (stat = 0; stat < MAX_SKILL; stat++)
		ch->pcdata->learned[stat] = -1;

	ch->morph = NULL;
	ch->morph_form[0] = 0;
	ch->pcdata->granted = NULL;

	found = FALSE;

#if defined(unix)
	/* decompress if .gz file exists */
	/* player files parsed directories by Yaz 4th Realm */
#if !defined( macintosh )
	sprintf(strsave, "%s%s%s%s%s", PLAYER_DIR, initial(name), "/", capitalize(
			name), ".gz");
#else
	sprintf( strsave, "%s%s%s", PLAYER_DIR, capitalize( name ), ".gz" );
#endif
	if ((fp = fopen(strsave, "r")) != NULL)
	{
		fclose(fp);
		sprintf(buf, "gzip -dfq %s", strsave);
		system(buf);
	}
#endif

	/* player files parsed directories by Yaz 4th Realm */
#if !defined( macintosh )
	sprintf(strsave, "%s%s%s%s", PLAYER_DIR, initial(name), "/", capitalize(
			name));
#else
	sprintf( strsave, "%s%s", PLAYER_DIR, capitalize( name ) );
#endif
	if ((fp = fopen(strsave, "r")) != NULL)
	{
		int iNest;

		for (iNest = 0; iNest < MAX_NEST; iNest++)
			rgObjNest[iNest] = NULL;

		found = TRUE;
		for (;;)
		{
			char letter;
			char *word;

			letter = fread_letter(fp);
			if (letter == '*')
			{
				fread_to_eol(fp);
				continue;
			}

			if (letter != '#')
			{
				printf_debug("Load_char_obj: # not found.");
				break;
			}

			word = fread_word(fp);
			if (!str_cmp(word, "PLAYER")) {
				fread_char(ch, fp);
				if (ch->pcdata->base_hit == 0)
					generate_baseHMVP(ch);
			}
			else if (!str_cmp(word, "OBJECT") || !str_cmp(word, "O"))
				fread_obj(ch, fp, FALSE);
			else if (!str_cmp(word, "PET"))
				fread_pet(ch, fp);
			else if (!str_cmp(word, "LOCKER"))
				fread_obj(ch, fp, TRUE);
			else if (!str_cmp(word, "END"))
				break;
			else
			{
				printf_debug("Load_char_obj: bad section: \"%s\".", word);
				break;
			}
		}

		fclose(fp);

	}

	/* initialize race */
	if (found)
	{
		int i;

		if (ch->race == 0)
			ch->race = race_lookup("human");

		ch->size = pc_race_table[ch->race].size;
		ch->dam_type = 17; /*punch */

		for (i = 0; i < 5; i++)
		{
			if (pc_race_table[ch->race].skills[i] == NULL)
				break;
			group_add(ch, pc_race_table[ch->race].skills[i], FALSE);
		}
		ch->affected_by = ch->affected_by | race_table[ch->race].aff;
		ch->shielded_by = ch->shielded_by | race_table[ch->race].shd;
		ch->imm_flags = ch->imm_flags | race_table[ch->race].imm;
		ch->res_flags = ch->res_flags | race_table[ch->race].res;
		ch->vuln_flags = ch->vuln_flags | race_table[ch->race].vuln;
		ch->form = race_table[ch->race].form;
		ch->parts = race_table[ch->race].parts;
	}

	/* RT initialize skills */

	if (found && ch->version < 2) /* need to add the new skills */
	{
		ch->pcdata->learned[gsn_recall] = 50;
	}

	/* fix levels */
	if (found && ch->version < 3 && (ch->level > 35 || ch->trust > 35))
	{
		switch (ch->level)
		{
		case (40):
			ch->level = 60;
			break; /* imp -> imp */
		case (39):
			ch->level = 58;
			break; /* god -> supreme */
		case (38):
			ch->level = 56;
			break; /* deity -> god */
		case (37):
			ch->level = 53;
			break; /* angel -> demigod */
		}

		switch (ch->trust)
		{
		case (40):
			ch->trust = 60;
			break; /* imp -> imp */
		case (39):
			ch->trust = 58;
			break; /* god -> supreme */
		case (38):
			ch->trust = 56;
			break; /* deity -> god */
		case (37):
			ch->trust = 53;
			break; /* angel -> demigod */
		case (36):
			ch->trust = 51;
			break; /* hero -> hero */
		}
	}

	/* ream gold */
	if (found && ch->version < 4)
	{
		ch->gold /= 100;
	}

	reset_char(ch);

	return found;
}

/*
 * Load a char and inventory into a new ch structure.
 */
bool load_char_obj(DESCRIPTOR_DATA *d, char *name)
{
	CHAR_DATA *ch;

	ch = new_char();
	ch->pcdata = new_pcdata();

//	ch->pcdata->base_hit = ch->max_hit;
//	ch->pcdata->base_mana = ch->max_mana;
//	ch->pcdata->base_move = ch->max_move;

	d->character = ch;
	ch->desc = d;
	bool found = load_ch_obj_nodesc(ch, name);

	if (found && ch->qstate != QSTATE_NONE)
	{
		OBJ_DATA *questobj;
		ROOM_INDEX_DATA *room;
		if (ch->qstate == QSTATE_OBJ) {
			for (questobj = object_list; questobj != NULL; questobj = questobj->next) {
				if (questobj->pIndexData->vnum == ch->qtarget
				&&	!str_cmp(questobj->owner, ch->name))
					break;
			}
			if (questobj == NULL) {
				if ((room = get_room_index(ch->qroom)) != NULL) {
					if ((questobj = create_object(get_obj_index(ch->qtarget), ch->level)) != NULL) {
						free_string(questobj->owner);
						questobj->owner = str_dup(ch->name);
						obj_to_room(questobj, room);
					}
				}
			}
		}
		send_to_char("YOU ARE STILL ON A QUEST!\n\r", ch);
	}

	// Do the reset here
	update_class_bits(ch);
	reset_char(ch);
	update_roster(ch, FALSE);

	return found;
}

/*
 * Check a player name for duplicate
 */
bool check_char_exist(char *name)
{
	char strsave[MAX_INPUT_LENGTH];
	char buf[100];
	FILE *fp;
	bool found;

	found = FALSE;

#if defined(unix)
	/* decompress if .gz file exists */
	/* player files parsed directories by Yaz 4th Realm */
#if !defined( macintosh )
	sprintf(strsave, "%s%s%s%s%s", PLAYER_DIR, initial(name), "/", capitalize(
			name), ".gz");
#else
	sprintf( strsave, "%s%s%s", PLAYER_DIR, capitalize( name ), ".gz" );
#endif
	if ((fp = fopen(strsave, "r")) != NULL)
	{
		fclose(fp);
		sprintf(buf, "gzip -dfq %s", strsave);
		system(buf);
	}
#endif

	/* player files parsed directories by Yaz 4th Realm */
#if !defined( macintosh )
	sprintf(strsave, "%s%s%s%s", PLAYER_DIR, initial(name), "/", capitalize(
			name));
#else
	sprintf( strsave, "%s%s", PLAYER_DIR, capitalize( name ) );
#endif
	if ((fp = fopen(strsave, "r")) != NULL)
	{
		fclose(fp);
		found = TRUE;
	}

	if (is_name(
			name,
			"all auto immortal immortals self someone something the you demise balance circle loner honor"))
	{
		found = TRUE;
	}
	if (get_clan_by_name(name) != NULL)
		found = TRUE;
	if (!str_infix("immortal", name))
		found = TRUE;
	if (!str_infix(" ", name))
		found = TRUE;
	if (!str_infix("fuck", name))
		found = TRUE;
	if (!str_infix("shit", name))
		found = TRUE;
	if (!str_infix("asshole", name))
		found = TRUE;
	if (!str_infix("pussy", name))
		found = TRUE;
	/*
	 * Length restrictions.
	 */

	if (strlen(name) < 2)
		found = TRUE;

#if defined(MSDOS)
	if ( strlen(name) > 8 )
	found = TRUE;
#endif

#if defined(macintosh) || defined(unix)
	if (strlen(name) > 12)
		found = TRUE;
#endif

	{
		char *pc;
		bool fIll, adjcaps = FALSE, cleancaps = FALSE;
		int total_caps = 0;

		fIll = TRUE;
		for (pc = name; *pc != '\0'; pc++)
		{
			if (!isalpha(*pc))
				found = TRUE;

			if (isupper(*pc)) /* ugly anti-caps hack */
			{
				if (adjcaps)
					cleancaps = TRUE;
				total_caps++;
				adjcaps = TRUE;
			}
			else
				adjcaps = FALSE;

			if (LOWER(*pc) != 'i' && LOWER(*pc) != 'l')
				fIll = FALSE;
		}

		if (fIll)
			found = TRUE;

		if (cleancaps || (total_caps > (strlen(name)) / 2 && strlen(name) < 3))
			found = TRUE;
	}

	/*
	 * Prevent players from being named after mobs.
	 */
	{
		extern MOB_INDEX_DATA *mob_index_hash[MAX_KEY_HASH];
		MOB_INDEX_DATA *pMobIndex;
		int iHash;

		for (iHash = 0; iHash < MAX_KEY_HASH; iHash++)
		{
			for (pMobIndex = mob_index_hash[iHash]; pMobIndex != NULL; pMobIndex
					= pMobIndex->next)
			{
				if (is_name(name, pMobIndex->player_name))
					found = TRUE;
			}
		}
	}

	return found;
}

bool load_char_reroll(DESCRIPTOR_DATA *d, char *name)
{
	CHAR_DATA *ch;
	bool found;
	int stat;
	char strsave[MAX_INPUT_LENGTH];
	char buf[100];
	FILE *fp;

	ch = new_char();
	ch->pcdata = new_pcdata();

	d->character = ch;
	ch->desc = d;
	ch->name = str_dup(name);
	ch->id = get_pc_id();
	ch->race = race_lookup("human");
	ch->act = PLR_NOSUMMON;
	ch->comm = COMM_COMBINE | COMM_PROMPT | COMM_STORE;
	ch->prompt = str_dup("<%g/%H{chp %n/%M{cmp %w/%V{cmv {Y${W%P {C%X{Wtnl{x> ");
	ch->pcdata->confirm_delete = FALSE;
	ch->pcdata->pwd = str_dup("");
	ch->pcdata->bamfin = str_dup("");
	ch->pcdata->bamfout = str_dup("");
	ch->pcdata->immskll = str_dup("");
	ch->pcdata->who_descr = str_dup("");
	ch->pcdata->title = str_dup("");
	ch->pcdata->pretit = str_dup("");
	/*    ch->pcdata->colour_name             = str_dup( "" ); */
	ch->pcdata->usr_ttl = FALSE;
	ch->gladiator = NULL;
	ch->pcdata->tier = 1;
	for (stat = 0; stat < MAX_STATS; stat++)
		ch->perm_stat[stat] = 13;
	ch->pcdata->condition[COND_THIRST] = 48;
	ch->pcdata->condition[COND_FULL] = 48;
	ch->pcdata->condition[COND_HUNGER] = 48;
	ch->pload = NULL; /* Skyn */
	ch->pcdata->power[POWER_KILLS] = 0; /* Highlander */
	ch->pcdata->power[POWER_POINTS] = 0;
	ch->pcdata->power[POWER_LEVEL] = 0;
	ch->ghost = str_dup("");
	ch->ghost_timer = -1;
	ch->regen_rate = 0;
	ch->mana_regen_rate = 0;
	ch->morph = NULL;
	ch->morph_form[0] = 0;
	ch->toughness = 0;

	for (stat = 0; stat < 6; stat++)
		ch->magic[stat] = 1;

	for (stat = 1; stat < 11; stat++)
		ch->stance[stat] = 1;

	/* Sets all skills to not learned before read of what they know */
	for (stat = 0; stat < MAX_SKILL; stat++)
		ch->pcdata->learned[stat] = -1;

	found = FALSE;

	/* Now....read in the proper values here....avoid headache */

#if defined(unix)
	/* decompress if .gz file exists */
	/* player files parsed directories by Yaz 4th Realm */
#if !defined( macintosh )
	sprintf(strsave, "%s%s%s%s%s", PLAYER_DIR, initial(name), "/", capitalize(
			name), ".gz");
#else
	sprintf( strsave, "%s%s%s", PLAYER_DIR, capitalize( name ), ".gz" );
#endif
	if ((fp = fopen(strsave, "r")) != NULL)
	{
		fclose(fp);
		sprintf(buf, "gzip -dfq %s", strsave);
		system(buf);
	}
#endif

	/* player files parsed directories by Yaz 4th Realm */
#if !defined( macintosh )
	sprintf(strsave, "%s%s%s%s", PLAYER_DIR, initial(name), "/", capitalize(
			name));
#else
	sprintf( strsave, "%s%s", PLAYER_DIR, capitalize( name ) );
#endif
	if ((fp = fopen(strsave, "r")) != NULL)
	{
		int iNest;

		for (iNest = 0; iNest < MAX_NEST; iNest++)
			rgObjNest[iNest] = NULL;

		found = TRUE;
		for (;;)
		{
			char letter;
			char *word;

			letter = fread_letter(fp);
			if (letter == '*')
			{
				fread_to_eol(fp);
				continue;
			}

			if (letter != '#')
			{
				printf_debug("Load_char_obj: # not found.");
				break;
			}

			word = fread_word(fp);
			if (!str_cmp(word, "PLAYER"))
				fread_char_reroll(ch, fp);
			else if (!str_cmp(word, "LOCKER"))
				fread_obj(ch, fp, TRUE);
			else if (!str_cmp(word, "END"))
				break;
			else
			{
				printf_debug("Load_char_reroll: bad section.");
				break;
			}
		}
		fclose(fp);
	}

	return found;
}

/*
 * Read in a char.
 */

#if defined(KEY)
#undef KEY
#endif

#define KEY( literal, field, value ) \
				if ( !str_cmp( word, literal ) ) \
				{ \
				    field  = value; \
				    fMatch = TRUE; \
				    break; \
				}

void fread_char(CHAR_DATA *ch, FILE *fp)
{
	char buf[MAX_STRING_LENGTH];
	char *word;
	bool fMatch;
	int count = 0;
	int dcount = 0;
	int fcount = 0;
	int lastlogoff = current_time;
	int percent;
	int ut, dummy;
	int ach_count = 0;

	sprintf(buf, "Loading %s.", ch->name);
	if (strcmp(ch->name, ""))
	{
		printf_system(buf);
	}
	ch->questpoints = 0;

	// Set these now. If not 'up to date' file, they'll be caught and updated later.
	ch->pcdata->base_hit = 0;
	ch->pcdata->base_mana = 0;
	ch->pcdata->base_move = 0;
	for (;;)
	{
		word = feof(fp) ? "End" : fread_word(fp);
		fMatch = FALSE;

		switch (UPPER(word[0]))
		{
		case '*':
			fMatch = TRUE;
			fread_to_eol(fp);
			break;

		case 'A':
			KEY( "Act", ch->act, fread_flag( fp ) )
			;
			KEY( "AffectedBy", ch->affected_by, fread_flag( fp ) )
			;
			KEY( "AfBy", ch->affected_by, fread_flag( fp ) )
			;
			KEY( "Afle", dummy, fread_number( fp ) )
			;
			KEY( "Alos", dummy, fread_number( fp ) )
			;
			KEY( "Alignment", ch->alignment, fread_number( fp ) )
			;
			KEY( "Alig", ch->alignment, fread_number( fp ) )
			;
			KEY( "Awin", dummy, fread_number( fp ) )
			;
			KEY( "Arank", dummy, fread_number( fp ) )
			;

			KEY("AchM", ch->pcdata->achievement_metrics[ach_count++], fread_number(fp));

			if (!str_cmp(word, "AchD")) {
				fMatch = TRUE;
				char *name = fread_word(fp);
				const ACH_DEFINITION *def;
				for (def = achievements_table; def->name != NULL; ++def) {
					if (!str_cmp(name, def->save_name)) {
						ACH_DONE *done = new_ach_done(def);
						done->next = ch->pcdata->achievements_done;
						ch->pcdata->achievements_done = done;
					}
				}
			}

			if (!str_cmp(word, "Alia"))
			{
				if (count >= MAX_ALIAS)
				{
					fread_to_eol(fp);
					fMatch = TRUE;
					break;
				}

				ch->pcdata->alias[count] = str_dup(fread_word(fp));
				ch->pcdata->alias_sub[count] = str_dup(fread_word(fp));
				count++;
				fMatch = TRUE;
				break;
			}

			if (!str_cmp(word, "Alias"))
			{
				if (count >= MAX_ALIAS)
				{
					fread_to_eol(fp);
					fMatch = TRUE;
					break;
				}

				ch->pcdata->alias[count] = str_dup(fread_word(fp));
				ch->pcdata->alias_sub[count] = fread_string(fp);
				count++;
				fMatch = TRUE;
				break;
			}

			if (!str_cmp(word, "AC") || !str_cmp(word, "Armor"))
			{
				fread_to_eol(fp);
				fMatch = TRUE;
				break;
			}
			if (!str_cmp(word, "ACs"))
			{
				int i;

				for (i = 0; i < 4; i++)
					ch->armor[i] = fread_number(fp);
				fMatch = TRUE;
				break;
			}

			if (!str_cmp(word, "AffD"))
			{
				AFFECT_DATA *paf;
				int sn;

				paf = new_affect();

				sn = skill_lookup(fread_word(fp));
				if (sn < 0)
					printf_debug("Fread_char: unknown skill.");
				else
					paf->type = sn;

				paf->level = fread_number(fp);
				paf->duration = fread_number(fp);
				paf->modifier = fread_number(fp);
				paf->location = fread_number(fp);
				paf->bitvector = fread_number(fp);
				paf->next = ch->affected;
				ch->affected = paf;
				fMatch = TRUE;
				break;
			}

			if (!str_cmp(word, "Affc"))
			{
				AFFECT_DATA *paf;
				int sn;

				paf = new_affect();

				sn = skill_lookup(fread_word(fp));
				if (sn < 0)
					printf_debug("Fread_char: unknown skill.");
				else
					paf->type = sn;

				paf->where = fread_number(fp);
				paf->level = fread_number(fp);
				paf->duration = fread_number(fp);
				paf->modifier = fread_number(fp);
				paf->location = fread_number(fp);
				paf->bitvector = fread_number(fp);
				paf->next = ch->affected;
				ch->affected = paf;
				fMatch = TRUE;
				break;
			}

			if (!str_cmp(word, "AttrMod") || !str_cmp(word, "AMod"))
			{
				int stat;
				for (stat = 0; stat < MAX_STATS; stat++)
					ch->mod_stat[stat] = fread_number(fp);
				fMatch = TRUE;
				break;
			}

			if (!str_cmp(word, "AttrPerm") || !str_cmp(word, "Attr"))
			{
				int stat;

				for (stat = 0; stat < MAX_STATS; stat++)
					ch->perm_stat[stat] = fread_number(fp);
				fMatch = TRUE;
				break;
			}
			break;

		case 'B':
			KEY( "Bamfin", ch->pcdata->bamfin, fread_string( fp ) )
			;
			KEY( "Bamfout", ch->pcdata->bamfout, fread_string( fp ) )
			;
			KEY( "Bin", ch->pcdata->bamfin, fread_string( fp ) )
			;
			KEY( "Bout", ch->pcdata->bamfout, fread_string( fp ) )
			;
			KEY( "Bounty", dummy, fread_number( fp ) )
			;
			if (!str_cmp(word, "Bal"))
			{
				ch->balance[0] = fread_number(fp);
				ch->balance[1] = fread_number(fp);
				ch->balance[2] = fread_number(fp);
				ch->balance[3] = fread_number(fp);
				fMatch = TRUE;
				break;
			}
			if (!str_cmp(word, "BaseHMVP"))
			{
				ch->pcdata->base_hit = fread_number(fp);
				ch->pcdata->base_mana = fread_number(fp);
				ch->pcdata->base_move = fread_number(fp);
				fMatch = TRUE;
				break;
			}
			break;

		case 'C':
			if (!str_cmp(word, "Class") || !str_cmp(word, "Cla") || !str_cmp(
					word, "Clas"))
			{
				int sn;
				char *class;

				fMatch = TRUE;
				class = fread_string(fp);
				ch->class = class_lookup(class);

				for (sn = 0; sn < MAX_SKILL; sn++)
					ch->pcdata->learnlvl[sn]
							= skill_table[sn].skill_level[ch->class];
				break;
			}
			int dummy;
			KEY( "Cln", dummy, 0)
			;
			KEY( "ClanRank", dummy, 0)
			;
			KEY( "Clead", dummy, 0)
			;
			/*            KEY( "ClrName",     ch->pcdata->colour_name,fread_string( fp ) ); */
			KEY( "Color", ch->color, fread_number( fp ) )
			;
			KEY( "Coauc", ch->color_auc, fread_number( fp ) )
			;
			KEY( "Cocgo", ch->color_cgo, fread_number( fp ) )
			;
			KEY( "Cocla", ch->color_cla, fread_number( fp ) )
			;
			KEY( "Cocon", ch->color_con, fread_number( fp ) )
			;
			KEY( "Codis", ch->color_dis, fread_number( fp ) )
			;
			KEY( "Cofig", ch->color_fig, fread_number( fp ) )
			;
			KEY( "Cogos", ch->color_gos, fread_number( fp ) )
			;
			KEY( "Cogra", ch->color_gra, fread_number( fp ) )
			;
			KEY( "Cogte", ch->color_gte, fread_number( fp ) )
			;
			KEY( "Coimm", ch->color_imm, fread_number( fp ) )
			;
			KEY( "Comob", ch->color_mob, fread_number( fp ) )
			;
			KEY( "Comus", ch->color_mus, fread_number( fp ) )
			;
			KEY( "Coopp", ch->color_opp, fread_number( fp ) )
			;
			KEY( "Coqgo", ch->color_qgo, fread_number( fp ) )
			;
			KEY( "Coque", ch->color_que, fread_number( fp ) )
			;
			KEY( "Coquo", ch->color_quo, fread_number( fp ) )
			;
			KEY( "Coroo", ch->color_roo, fread_number( fp ) )
			;
			KEY( "Cosay", ch->color_say, fread_number( fp ) )
			;
			KEY( "Cosho", ch->color_sho, fread_number( fp ) )
			;
			KEY( "Cotel", ch->color_tel, fread_number( fp ) )
			;
			KEY( "Cowit", ch->color_wit, fread_number( fp ) )
			;
			KEY( "Cowiz", ch->color_wiz, fread_number( fp ) )
			;

			if (!str_cmp(word, "Condition") || !str_cmp(word, "Cond"))
			{
				ch->pcdata->condition[0] = fread_number(fp);
				ch->pcdata->condition[1] = fread_number(fp);
				ch->pcdata->condition[2] = fread_number(fp);
				fMatch = TRUE;
				break;
			}
			if (!str_cmp(word, "Cnd"))
			{
				ch->pcdata->condition[0] = fread_number(fp);
				ch->pcdata->condition[1] = fread_number(fp);
				ch->pcdata->condition[2] = fread_number(fp);
				ch->pcdata->condition[3] = fread_number(fp);
				fMatch = TRUE;
				break;
			}
			KEY("Comm", ch->comm, fread_flag( fp ) )
			;

			break;

		case 'D':
			KEY( "Damroll", ch->damroll, fread_number( fp ) )
			;
			KEY( "Dam", ch->damroll, fread_number( fp ) )
			;
			KEY( "Deity", ch->god, god_lookup(fread_string(fp)))
			;
			KEY( "Description", ch->description, fread_string( fp ) )
			;
			KEY( "Desc", ch->description, fread_string( fp ) )
			;
			KEY( "Dfle", dummy, fread_number( fp ) )
			;
			if (!str_cmp(word, "Dupes"))
			{
				if (dcount >= MAX_DUPES)
				{
					fread_to_eol(fp);
					fMatch = TRUE;
					break;
				}

				ch->pcdata->dupes[dcount] = fread_string(fp);
				dcount++;
				fMatch = TRUE;
			}
			break;

		case 'E':
			if (!str_cmp(word, "End"))
			{
				/* adjust hp mana move up  -- here for speed's sake */
				percent = (current_time - lastlogoff) * 25 / (2 * 60 * 60);

				percent = UMIN(percent,100);

				if (percent > 0 && !IS_AFFECTED(ch,AFF_POISON)
						&& !IS_AFFECTED(ch,AFF_PLAGUE))
				{
					ch->hit += (ch->max_hit - ch->hit) * percent / 100;
					ch->mana += (ch->max_mana - ch->mana) * percent / 100;
					ch->move += (ch->max_move - ch->move) * percent / 100;
				}
				return;
			}
			KEY( "Exp", ch->exp, fread_number( fp ) )
			;
			break;

		case 'F':
			if (!str_cmp(word, "Focus"))
			{
				ch->pcdata->focus[COMBAT_POWER] = fread_number(fp);
				ch->pcdata->focus[COMBAT_DEFENSE] = fread_number(fp);
				ch->pcdata->focus[COMBAT_AGILITY] = fread_number(fp);
				ch->pcdata->focus[COMBAT_TOUGHNESS] = fread_number(fp);
				ch->pcdata->focus[MAGIC_POWER] = fread_number(fp);
				ch->pcdata->focus[MAGIC_ABILITY] = fread_number(fp);
				ch->pcdata->focus[MAGIC_DEFENSE] = fread_number(fp);
				ch->pcdata->focus[CURRENT_FOCUS] = fread_number(fp);
				ch->pcdata->focus[MAGIC_RESONANCE] = 0;

				fMatch = TRUE;
				break;
			}
			
			if (!str_cmp(word, "Focus2"))
			{
				ch->pcdata->focus[COMBAT_POWER] = fread_number(fp);
				ch->pcdata->focus[COMBAT_DEFENSE] = fread_number(fp);
				ch->pcdata->focus[COMBAT_AGILITY] = fread_number(fp);
				ch->pcdata->focus[COMBAT_TOUGHNESS] = fread_number(fp);
				ch->pcdata->focus[MAGIC_POWER] = fread_number(fp);
				ch->pcdata->focus[MAGIC_ABILITY] = fread_number(fp);
				ch->pcdata->focus[MAGIC_DEFENSE] = fread_number(fp);
				ch->pcdata->focus[CURRENT_FOCUS] = fread_number(fp);
				ch->pcdata->focus[MAGIC_RESONANCE] = fread_number(fp);

				fMatch = TRUE;
				break;
			}			

			if (!str_cmp(word, "Forge"))
			{
				if (fcount >= MAX_FORGET)
				{
					fread_to_eol(fp);
					fMatch = TRUE;
					break;
				}

				ch->pcdata->forget[fcount] = fread_string(fp);
				fcount++;
				fMatch = TRUE;
			}
			break;

		case 'G':
			KEY( "Ghos", ch->ghost_level, fread_number( fp ) )
			;
			KEY( "Ghost", ch->ghost, fread_string( fp ) )
			;
			KEY( "GTime", ch->ghost_timer, fread_number( fp ) )
			;
			KEY( "Gold", ch->gold, fread_number( fp ) )
			;
			if (!str_cmp(word, "Grant"))
			{
				GRANT_DATA *gran = NULL;
				char *name;
				int cmd, duration;

				name = fread_word(fp);
				duration = fread_number(fp);

				for (cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++)
					if (name[0] == cmd_table[cmd].name[0]
							&& is_exact_name(name, cmd_table[cmd].name))
					{
						gran = alloc_mem(sizeof(*gran));
						gran->name = str_dup(name);
						gran->duration = duration;
						gran->next = NULL;
						gran->do_fun = cmd_table[cmd].do_fun;
						gran->level = cmd_table[cmd].level;
						gran->next = ch->pcdata->granted;
						ch->pcdata->granted = gran;
						break;
					}
				if (gran == NULL)
					printf_debug( "Grant: Command %s not found in pfile for %s",
							name, ch->name);
				fMatch = TRUE;
			}
			if (!str_cmp(word, "Group") || !str_cmp(word, "Gr"))
			{
				char *temp;
				temp = fread_word(fp);
				fMatch = TRUE;
			}
			break;

		case 'H':
			KEY( "Hitroll", ch->hitroll, fread_number( fp ) )
			;
			KEY( "Hit", ch->hitroll, fread_number( fp ) )
			;

			if (!str_cmp(word, "HpManaMove") || !str_cmp(word, "HMV"))
			{
				ch->hit = fread_number(fp);
				ch->max_hit = fread_number(fp);
				ch->mana = fread_number(fp);
				ch->max_mana = fread_number(fp);
				ch->move = fread_number(fp);
				ch->max_move = fread_number(fp);
				fMatch = TRUE;
				break;
			}

			if (!str_cmp(word, "HpManaMovePerm") || !str_cmp(word, "HMVP"))
			{
				ch->pcdata->perm_hit = fread_number(fp);
				ch->pcdata->perm_mana = fread_number(fp);
				ch->pcdata->perm_move = fread_number(fp);
				fMatch = TRUE;
				break;
			}


			break;

		case 'I':
			KEY( "Id", ch->id, fread_number( fp ) )
			;
			KEY( "Iden", ch->pcdata->identity, fread_string( fp ) )
			;
			KEY( "Imsk", ch->pcdata->immskll, fread_string( fp ) )
			;
			KEY( "InvisLevel", ch->invis_level, fread_number( fp ) )
			;
			KEY( "Inco", ch->incog_level, fread_number( fp ) )
			;
			KEY( "Invi", ch->invis_level, fread_number( fp ) )
			;
			break;

		case 'L':
			KEY( "LastLevel", ch->pcdata->last_level, fread_number( fp ) )
			;
			KEY( "LLev", ch->pcdata->last_level, fread_number( fp ) )
			;
			KEY( "Level", ch->level, fread_number( fp ) )
			;
			KEY( "Lev", ch->level, fread_number( fp ) )
			;
			KEY( "Levl", ch->level, fread_number( fp ) )
			;
			if (!str_cmp(word, "LogO"))
			{
				lastlogoff = fread_number(fp);
				ch->llogoff = (time_t) lastlogoff;
				fMatch = TRUE;
				break;
			}
			KEY( "LongDescr", ch->long_descr, fread_string( fp ) )
			;
			KEY( "LnD", ch->long_descr, fread_string( fp ) )
			;
			break;
		case 'M':
			KEY( "MorphN", ch->morph, fread_string( fp ) )
			;
			KEY( "MorphD", ch->morph_form[0], fread_number( fp ) )
			;
			if (!str_cmp(word, "Mtype"))
			{
				ch->magic[MAGIC_WHITE] = fread_number(fp);
				ch->magic[MAGIC_RED] = fread_number(fp);
				ch->magic[MAGIC_BLUE] = fread_number(fp);
				ch->magic[MAGIC_GREEN] = fread_number(fp);
				ch->magic[MAGIC_BLACK] = fread_number(fp);
				ch->magic[MAGIC_ORANGE] = fread_number(fp);
				fMatch = TRUE;
				break;
			}
			else if (!str_cmp(word, "MPSt")) {
				MPSTATE *mpstate = new_mpstate();
				mpstate->mobvnum = fread_number(fp);
				mpstate->state = fread_number(fp);
				if (get_mob_index(mpstate->mobvnum) != NULL) {
					mpstate->next = ch->mpstates;
					ch->mpstates = mpstate;
				} else {
					printf_debug("Invalid mpstate vnum %d.", mpstate->mobvnum);
					free_mpstate(mpstate);
				}
				fMatch = TRUE;
				break;
			}
			break;
		case 'N':
			KEY( "Name", ch->name, fread_string( fp ) )
			;
			KEY( "NCln", dummy, 0)
			;
			KEY( "Note", ch->pcdata->last_note, fread_number( fp ) )
			;
			if (!str_cmp(word, "Not"))
			{
				ch->pcdata->last_note = fread_number(fp);
				ch->pcdata->last_idea = fread_number(fp);
				ch->pcdata->last_penalty = fread_number(fp);
				ch->pcdata->last_news = fread_number(fp);
				ch->pcdata->last_changes = fread_number(fp);
				ch->pcdata->last_weddings = fread_number(fp);
				ch->pcdata->last_quotes = fread_number(fp);
				fMatch = TRUE;
				break;
			}
			if (!str_cmp(word, "Notb"))
			{
				ch->pcdata->last_note = fread_number(fp);
				ch->pcdata->last_idea = fread_number(fp);
				ch->pcdata->last_penalty = fread_number(fp);
				ch->pcdata->last_news = fread_number(fp);
				ch->pcdata->last_changes = fread_number(fp);
				ch->pcdata->last_weddings = fread_number(fp);
				fMatch = TRUE;
				break;
			}
			break;

		case 'P':
			KEY( "Password", ch->pcdata->pwd, fread_string( fp ) )
			;
			KEY( "Pass", ch->pcdata->pwd, fread_string( fp ) )
			;
			KEY( "Petit", dummy, 0)
			;
			KEY( "Plat", ch->platinum, fread_number( fp ) )
			;
			KEY( "Played", ch->played, fread_number( fp ) )
			;
			KEY( "Plyd", ch->played, fread_number( fp ) )
			;
			KEY( "Plyr", ch->plyr, fread_flag( fp ) )
			;
			KEY( "Points", ch->pcdata->points, fread_number( fp ) )
			;
			KEY( "Pnts", ch->pcdata->points, fread_number( fp ) )
			;
			KEY( "Position", ch->position, fread_number( fp ) )
			;
			KEY( "Pos", ch->position, fread_number( fp ) )
			;
			KEY( "Pretit", ch->pcdata->pretit, fread_string( fp ) )
			;
			KEY( "Practice", ch->practice, fread_number( fp ) )
			;
			KEY( "Prac", ch->practice, fread_number( fp ) )
			;
			KEY( "Prompt", ch->prompt, fread_string( fp ) )
			;
			KEY( "Prom", ch->prompt, fread_string( fp ) )
			;
			KEY( "Pkil", dummy, fread_number( fp ) )
			;
			KEY( "Pdea", dummy, fread_number( fp ) )
			;
			KEY( "Prank", dummy, fread_number( fp ) )
			;
			if (!str_cmp(word, "Power"))
			{
				ch->pcdata->power[POWER_KILLS] = fread_number(fp);
				ch->pcdata->power[POWER_POINTS] = fread_number(fp);
				ch->pcdata->power[POWER_LEVEL] = fread_number(fp);
				fMatch = TRUE;
				break;
			}
			break;

		case 'Q':
			if (!str_cmp(word, "Qps")) {
				ch->questpoints += 300*fread_number(fp);
				fMatch = TRUE;
				break;
			} else if (!str_cmp(word, "QuestPnts")) {
				ch->questpoints += fread_number(fp);
				fMatch = TRUE;
				break;
			}

			KEY( "QState", ch->qstate, fread_number(fp));
			KEY( "QTarget", ch->qtarget, fread_number(fp));
			KEY( "QTimer", ch->qtimer, fread_number(fp));
			KEY( "QMVnum", ch->qmvnum, fread_number(fp));
			KEY( "QRoom", ch->qroom, fread_number(fp));
			break;

		case 'R':
			KEY( "Race", ch->race,
					race_lookup(fread_string( fp )) )
			;
			KEY( "Rank", dummy, 0)
			;
			KEY( "Reca", ch->pcdata->recall, fread_number( fp ) )
			;

			if (!str_cmp(word, "Room"))
			{
				ch->in_room = get_room_index(fread_number(fp));
				if (ch->in_room == NULL)
					ch->in_room = get_room_index(ROOM_VNUM_LIMBO);
				fMatch = TRUE;
				break;
			}

			break;

		case 'S':
			KEY( "SavingThrow", ch->saving_throw, fread_number( fp ) )
			;
			KEY( "Save", ch->saving_throw, fread_number( fp ) )
			;
			KEY( "Scro", ch->lines, fread_number( fp ) )
			;
			KEY( "Sex", ch->sex, fread_number( fp ) )
			;
			KEY( "ShBy", ch->shielded_by, fread_flag( fp ) )
			;
			KEY( "ShieldedBy", ch->shielded_by, fread_flag( fp ) )
			;
			KEY( "ShortDescr", ch->short_descr, fread_string( fp ) )
			;
			KEY( "ShD", ch->short_descr, fread_string( fp ) )
			;
			KEY( "Sec", ch->pcdata->security, fread_number( fp ) )
			; /* OLC */
			KEY( "Silv", ch->silver, fread_number( fp ) )
			;
			KEY( "Status", ch->pcdata->status, fread_number( fp ) )
			;

			if (!str_cmp(word, "Stance"))
			{
				ch->stance[0] = fread_number(fp);
				ch->stance[1] = fread_number(fp);
				ch->stance[2] = fread_number(fp);
				ch->stance[3] = fread_number(fp);
				ch->stance[4] = fread_number(fp);
				ch->stance[5] = fread_number(fp);
				ch->stance[6] = fread_number(fp);
				ch->stance[7] = fread_number(fp);
				ch->stance[8] = fread_number(fp);
				ch->stance[9] = fread_number(fp);
				ch->stance[10] = fread_number(fp);
				fMatch = TRUE;
				break;
			}

			if (!str_cmp(word, "Skill") || !str_cmp(word, "Sk"))
			{
				int sn;
				int value;
				char *temp;

				value = fread_number(fp);
				temp = fread_word(fp);
				sn = skill_lookup(temp);
				/* sn    = skill_lookup( fread_word( fp ) ); */
				if (sn < 0)
				{
					printf_debug("Fread_char: unknown skill. ");
					printf_debug("Skill %s sn < 0.", temp);
				}
				else
				{
					ch->pcdata->learned[sn] = value;
				}
				fMatch = TRUE;
				break;
			}

			if (!str_cmp(word, "Sklvl"))
			{
				int sn;
				int value;
				char *temp;

				value = fread_number(fp);
				temp = fread_word(fp);
				sn = skill_lookup(temp);
				/* sn    = skill_lookup( fread_word( fp ) ); */
				if (sn < 0)
				{
					printf_debug("Fread_char: unknown skill. ");
					printf_debug("Skill %s sn < 0", temp);
				}
				else
				{
					ch->pcdata->learnlvl[sn] = value;
				}
				fMatch = TRUE;
				break;
			}

			break;

		case 'T':
			KEY( "Tier", ch->pcdata->tier, fread_number( fp ) )
			;
			KEY( "TrueSex", ch->pcdata->true_sex, fread_number( fp ) )
			;
			KEY( "TSex", ch->pcdata->true_sex, fread_number( fp ) )
			;
			KEY( "Trai", ch->train, fread_number( fp ) )
			;
			KEY( "Trust", ch->trust, fread_number( fp ) )
			;
			KEY( "Tru", ch->trust, fread_number( fp ) )
			;
			KEY( "Tough", ch->toughness, fread_number( fp ) )
			;

			if (!str_cmp(word, "Title") || !str_cmp(word, "Titl"))
			{
				ch->pcdata->title = fread_string(fp);
				if (ch->pcdata->title[0] != '.' && ch->pcdata->title[0] != ','
						&& ch->pcdata->title[0] != '!' && ch->pcdata->title[0]
						!= '?')
				{
					sprintf(buf, " %s", ch->pcdata->title);
					free_string(ch->pcdata->title);
					ch->pcdata->title = str_dup(buf);
				}
				fMatch = TRUE;
				break;
			}

			break;

		case 'U':
			if (!str_cmp(word, "UsrTtl"))
			{
				ut = fread_number(fp);
				if (ut == 1)
					ch->pcdata->usr_ttl = TRUE;
				else
					ch->pcdata->usr_ttl = FALSE;
			}
			fMatch = TRUE;
			break;

		case 'V':
			KEY( "Version", ch->version, fread_number ( fp ) )
			;
			KEY( "Vers", ch->version, fread_number ( fp ) )
			;
			if (!str_cmp(word, "Vnum"))
			{
				ch->pIndexData = get_mob_index(fread_number(fp));
				fMatch = TRUE;
				break;
			}
			break;

		case 'W':
			KEY( "Whod", ch->pcdata->who_descr, fread_string( fp ) )
			;
			KEY( "Wimpy", ch->wimpy, fread_number( fp ) )
			;
			KEY( "Wimp", ch->wimpy, fread_number( fp ) )
			;
			KEY( "Wizn", ch->wiznet, fread_flag( fp ) )
			;
			break;
		}

		if (!fMatch)
		{
			findpos(fp, word); // Try this..
			printf_debug("Fread_char: no match on word '%s'.", word);
			fread_to_eol(fp);
		}
	}
}

void generate_baseHMVP(CHAR_DATA *ch)
{
	//int max_hp;
	//max_hp = ch->pcdata->perm_hit;
	char buf[MSL];

	// subtract focus
	ch->pcdata->base_hit = ch->pcdata->perm_hit - focus_hp(ch,2);
	ch->pcdata->base_mana = ch->pcdata->perm_mana - focus_mana(ch,2);
	ch->pcdata->base_move = ch->pcdata->perm_move - focus_move(ch,2);

	if IS_IMMORTAL(ch) {
	sprintf(buf,"Generating base_hit/mana/move values...\n\r");
	send_to_char(buf, ch);
	sprintf(buf,"Focus Deduction: %d, New Base HP/Prior: %d/%d, Focus Add: %d, Total: %d\n\r", focus_hp(ch,2), ch->pcdata->base_hit, ch->pcdata->perm_hit, focus_hp(ch,0), ch->pcdata->base_hit + focus_hp(ch,0));
	send_to_char(buf, ch);
	sprintf(buf,"Focus_deduction: %d, New Base Mana/Prior: %d/%d, Focus Add: %d, Total: %d\n\r", focus_mana(ch,2), ch->pcdata->base_mana, ch->pcdata->perm_mana, focus_mana(ch,0), ch->pcdata->base_mana + focus_mana(ch,0));
	send_to_char(buf, ch);
	sprintf(buf,"Focus Deduction: %d, New Base MV/Prior: %d/%d, Focus_Add: %d, Total: %d\n\r", focus_move(ch,2), ch->pcdata->base_move, ch->pcdata->perm_move, focus_move(ch,0), ch->pcdata->base_move + focus_move(ch,0));
	send_to_char(buf, ch);
	}
}

/* load a pet from the forgotten reaches */
void fread_pet(CHAR_DATA *ch, FILE *fp)
{
	char *word;
	CHAR_DATA *pet;
	bool fMatch;
	int lastlogoff = current_time;
	int percent;

	int dummy;
	/* first entry had BETTER be the vnum or we barf */
	word = feof(fp) ? "END" : fread_word(fp);
	if (!str_cmp(word, "Vnum"))
	{
		int vnum;

		vnum = fread_number(fp);
		if (get_mob_index(vnum) == NULL)
		{
			printf_debug("Fread_pet: bad vnum %d.", vnum);
			pet = create_mobile(get_mob_index(MOB_VNUM_FIDO));
		}
		else
			pet = create_mobile(get_mob_index(vnum));
	}
	else
	{
		printf_debug("Fread_pet: no vnum in file.");
		pet = create_mobile(get_mob_index(MOB_VNUM_FIDO));
	}

	for (;;)
	{
		word = feof(fp) ? "END" : fread_word(fp);
		fMatch = FALSE;

		switch (UPPER(word[0]))
		{
		case '*':
			fMatch = TRUE;
			fread_to_eol(fp);
			break;

		case 'A':
			KEY( "Act", pet->act, fread_flag(fp))
			;
			KEY( "AfBy", pet->affected_by, fread_flag(fp))
			;
			KEY( "Alig", pet->alignment, fread_number(fp))
			;

			if (!str_cmp(word, "ACs"))
			{
				int i;

				for (i = 0; i < 4; i++)
					pet->armor[i] = fread_number(fp);
				fMatch = TRUE;
				break;
			}

			if (!str_cmp(word, "AffD"))
			{
				AFFECT_DATA *paf;
				int sn;

				paf = new_affect();

				sn = skill_lookup(fread_word(fp));
				if (sn < 0)
					printf_debug("Fread_char: unknown skill.");
				else
					paf->type = sn;

				paf->level = fread_number(fp);
				paf->duration = fread_number(fp);
				paf->modifier = fread_number(fp);
				paf->location = fread_number(fp);
				paf->bitvector = fread_number(fp);
				paf->next = pet->affected;
				pet->affected = paf;
				fMatch = TRUE;
				break;
			}

			if (!str_cmp(word, "Affc"))
			{
				AFFECT_DATA *paf;
				int sn;

				paf = new_affect();

				sn = skill_lookup(fread_word(fp));
				if (sn < 0)
					printf_debug("Fread_char: unknown skill.");
				else
					paf->type = sn;

				paf->where = fread_number(fp);
				paf->level = fread_number(fp);
				paf->duration = fread_number(fp);
				paf->modifier = fread_number(fp);
				paf->location = fread_number(fp);
				paf->bitvector = fread_number(fp);
				paf->next = pet->affected;
				pet->affected = paf;
				fMatch = TRUE;
				break;
			}

			if (!str_cmp(word, "AMod"))
			{
				int stat;

				for (stat = 0; stat < MAX_STATS; stat++)
					pet->mod_stat[stat] = fread_number(fp);
				fMatch = TRUE;
				break;
			}

			if (!str_cmp(word, "Attr"))
			{
				int stat;

				for (stat = 0; stat < MAX_STATS; stat++)
					pet->perm_stat[stat] = fread_number(fp);
				fMatch = TRUE;
				break;
			}
			break;

		case 'C':
			KEY( "Clan", dummy, 0)
			;
			KEY( "Comm", pet->comm, fread_flag(fp))
			;
			break;

		case 'D':
			KEY( "Dam", pet->damroll, fread_number(fp))
			;
			KEY( "Desc", pet->description, fread_string(fp))
			;
			break;

		case 'E':
			if (!str_cmp(word, "End"))
			{
				pet->leader = ch;
				pet->master = ch;
				ch->pet = pet;
				/* adjust hp mana move up  -- here for speed's sake */
				percent = (current_time - lastlogoff) * 25 / (2 * 60 * 60);

				if (percent > 0 && !IS_AFFECTED(ch,AFF_POISON)
						&& !IS_AFFECTED(ch,AFF_PLAGUE))
				{
					percent = UMIN(percent,100);
					pet->hit += (pet->max_hit - pet->hit) * percent / 100;
					pet->mana += (pet->max_mana - pet->mana) * percent / 100;
					pet->move += (pet->max_move - pet->move) * percent / 100;
				}
				return;
			}
			KEY( "Exp", pet->exp, fread_number(fp))
			;
			break;

		case 'G':
			KEY( "Gold", pet->gold, fread_number(fp))
			;
			break;

		case 'H':
			KEY( "Hit", pet->hitroll, fread_number(fp))
			;

			if (!str_cmp(word, "HMV"))
			{
				pet->hit = fread_number(fp);
				pet->max_hit = fread_number(fp);
				pet->mana = fread_number(fp);
				pet->max_mana = fread_number(fp);
				pet->move = fread_number(fp);
				pet->max_move = fread_number(fp);
				fMatch = TRUE;
				break;
			}
			break;

		case 'L':
			KEY( "Levl", pet->level, fread_number(fp))
			;
			KEY( "LnD", pet->long_descr, fread_string(fp))
			;
			KEY( "LogO", lastlogoff, fread_number(fp))
			;
			break;

		case 'N':
			KEY( "Name", pet->name, fread_string(fp))
			;
			break;

		case 'P':
			KEY( "Plat", pet->platinum, fread_number(fp))
			;
			KEY( "Pos", pet->position, fread_number(fp))
			;
			break;

		case 'R':
			KEY( "Race", pet->race, race_lookup(fread_string(fp)))
			;
			break;

		case 'S':
			KEY( "Save", pet->saving_throw, fread_number(fp))
			;
			KEY( "Sex", pet->sex, fread_number(fp))
			;
			KEY( "ShD", pet->short_descr, fread_string(fp))
			;
			KEY( "ShBy", pet->shielded_by, fread_flag(fp))
			;
			KEY( "Silv", pet->silver, fread_number( fp ) )
			;
			break;

			if (!fMatch)
			{
				printf_debug("Fread_pet: no match.");
				fread_to_eol(fp);
			}

		}
	}
}

extern OBJ_DATA *obj_free;

void fread_obj(CHAR_DATA *ch, FILE *fp, bool locker)
{
	OBJ_DATA *obj;
	char *word;
	int iNest;
	bool fMatch;
	bool fNest;
	bool fVnum;
	bool first;
	bool new_format; /* to prevent errors */
	bool make_new; /* update object */

	fVnum = FALSE;
	obj = NULL;
	first = TRUE; /* used to counter fp offset */
	new_format = FALSE;
	make_new = FALSE;

	word = feof(fp) ? "End" : fread_word(fp);
	if (!str_cmp(word, "Vnum"))
	{
		int vnum;
		first = FALSE; /* fp will be in right place */

		vnum = fread_number(fp);
		if (get_obj_index(vnum) == NULL)
		{
			printf_debug("Fread_obj: bad vnum %d.", vnum);
			obj = create_object(get_obj_index(OBJ_VNUM_BAG), -1);
			new_format = TRUE;
		}
		else
		{
			obj = create_object(get_obj_index(vnum), -1);
			new_format = TRUE;
		}

	}

	if (obj == NULL) /* either not found or old style */
	{
		obj = new_obj();
		obj->name = str_dup("");
		obj->short_descr = str_dup("");
		obj->description = str_dup("");
	}

	fNest = FALSE;
	fVnum = TRUE;
	iNest = 0;

	for (;;)
	{
		if (first)
			first = FALSE;
		else
			word = feof(fp) ? "End" : fread_word(fp);
		fMatch = FALSE;

		switch (UPPER(word[0]))
		{
		case '*':
			fMatch = TRUE;
			fread_to_eol(fp);
			break;

		case 'A':
			if (!str_cmp(word, "AffD"))
			{
				AFFECT_DATA *paf;
				int sn;

				paf = new_affect();

				sn = skill_lookup(fread_word(fp));
				if (sn < 0)
					paf->type = -1;
				else
					paf->type = sn;

				paf->level = fread_number(fp);
				paf->duration = fread_number(fp);
				paf->modifier = fread_number(fp);
				paf->location = fread_number(fp);
				paf->bitvector = fread_number(fp);
				paf->next = obj->affected;
				obj->affected = paf;
				fMatch = TRUE;
				break;
			}
			if (!str_cmp(word, "Affc"))
			{
				AFFECT_DATA *paf;
				int sn;

				paf = new_affect();

				sn = skill_lookup(fread_word(fp));
				if (sn < 0)
					paf->type = -1;
				else
					paf->type = sn;

				paf->where = fread_number(fp);
				paf->level = fread_number(fp);
				paf->duration = fread_number(fp);
				paf->modifier = fread_number(fp);
				paf->location = fread_number(fp);
				paf->bitvector = fread_number(fp);
				paf->next = obj->affected;
				obj->affected = paf;
				fMatch = TRUE;
				break;
			}
			break;

		case 'C':
			KEY( "Cond", obj->condition, fread_number( fp ) )
			;
			KEY( "Cost", obj->cost, fread_number( fp ) )
			;
			break;

		case 'D':
			KEY( "Description", obj->description, fread_string( fp ) )
			;
			KEY( "Desc", obj->description, fread_string( fp ) )
			;
			break;

		case 'E':

			if (!str_cmp(word, "Enchanted"))
			{
				obj->enchanted = TRUE;
				fMatch = TRUE;
				break;
			}

			KEY( "ExtraFlags", obj->extra_flags, fread_number( fp ) )
			;
			KEY( "ExtF", obj->extra_flags, fread_number( fp ) )
			;

			if (!str_cmp(word, "ExtraDescr") || !str_cmp(word, "ExDe"))
			{
				EXTRA_DESCR_DATA *ed;

				ed = new_extra_descr();

				ed->keyword = fread_string(fp);
				ed->description = fread_string(fp);
				ed->next = obj->extra_descr;
				obj->extra_descr = ed;
				fMatch = TRUE;
			}

			if (!str_cmp(word, "End"))
			{
				if (!fNest || (fVnum && obj->pIndexData == NULL))

				{
					printf_debug("Fread_obj: incomplete object.");
					free_obj(obj);
					return;
				}
				else
				{
					if (!fVnum)
					{
						free_obj(obj);
						obj = create_object(get_obj_index(OBJ_VNUM_DUMMY), 0);
					}

					if (!new_format)
					{
						obj->next = object_list;
						object_list = obj;
						obj->pIndexData->count++;
					}

					if (!obj->pIndexData->new_format && obj->item_type
							== ITEM_ARMOR && obj->value[1] == 0)
					{
						obj->value[1] = obj->value[0];
						obj->value[2] = obj->value[0];
					}
					if (make_new)
					{
						int wear;

						wear = obj->wear_loc;
						extract_obj(obj);

						obj = create_object(obj->pIndexData, 0);
						obj->wear_loc = wear;
					}
					if (iNest == 0 || rgObjNest[iNest] == NULL) {
						if (locker)	// Assume we'll only ever get one locker object.
							ch->locker = obj;
						else
							obj_to_char(obj, ch);
					} else
						obj_to_obj(obj, rgObjNest[iNest - 1]);
					if (obj->pIndexData->vnum == OBJ_VNUM_QDIAMOND)
					{
						ch->platinum++;
						extract_obj(obj);
					}
					return;
				}
			}
			break;

		case 'I':
			KEY( "ItemType", obj->item_type, fread_number( fp ) )
			;
			KEY( "Ityp", obj->item_type, fread_number( fp ) )
			;
			break;

		case 'L':
			KEY( "Level", obj->level, fread_number( fp ) )
			;
			KEY( "Lev", obj->level, fread_number( fp ) )
			;
			KEY( "LootX", obj->loot_timer, fread_number( fp ) )
			;
			KEY ("LootR", obj->looted_by, fread_string( fp ) )
			;
			KEY ("LootD", obj->looted_from, fread_string( fp ) )
			;
			break;

		case 'M':
			KEY( "Makr", obj->maker, fread_string( fp ) );
			break;

		case 'N':
			KEY( "Name", obj->name, fread_string( fp ) )
			;

			if (!str_cmp(word, "Nest"))
			{
				iNest = fread_number(fp);
				if (iNest < 0 || iNest >= MAX_NEST)
				{
					printf_debug("Fread_obj: bad nest %d.", iNest);
				}
				else
				{
					rgObjNest[iNest] = obj;
					fNest = TRUE;
				}
				fMatch = TRUE;
			}
			break;

		case 'O':
			KEY( "Ownr", obj->owner, fread_string( fp ));
			if (!str_cmp(word, "Oldstyle"))
			{
				if (obj->pIndexData != NULL && obj->pIndexData->new_format)
					make_new = TRUE;
				fMatch = TRUE;
			}
			break;

		case 'S':
			KEY( "ShortDescr", obj->short_descr, fread_string( fp ) )
			;
			KEY( "ShD", obj->short_descr, fread_string( fp ) )
			;

			if (!str_cmp(word, "Spell"))
			{
				int iValue;
				int sn;

				iValue = fread_number(fp);
				sn = skill_lookup(fread_word(fp));
				if (iValue < 0 || iValue > 3)
				{
					printf_debug("Fread_obj: bad iValue %d.", iValue);
				}
				else if (sn < 0)
				{
					printf_debug("Fread_obj: unknown skill.");
				}
				else
				{
					obj->value[iValue] = sn;
				}
				fMatch = TRUE;
				break;
			}

			break;

		case 'T':
			KEY( "TierLevel", obj->tier_level, fread_number( fp ) )
			;
			KEY( "Timer", obj->timer, fread_number( fp ) )
			;
			KEY( "Time", obj->timer, fread_number( fp ) )
			;
			break;

		case 'V':
			if (!str_cmp(word, "Values") || !str_cmp(word, "Vals"))
			{
				obj->value[0] = fread_number(fp);
				obj->value[1] = fread_number(fp);
				obj->value[2] = fread_number(fp);
				obj->value[3] = fread_number(fp);
				if (obj->item_type == ITEM_WEAPON && obj->value[0] == 0)
					obj->value[0] = obj->pIndexData->value[0];
				fMatch = TRUE;
				break;
			}

			if (!str_cmp(word, "Val"))
			{
				obj->value[0] = fread_number(fp);
				obj->value[1] = fread_number(fp);
				obj->value[2] = fread_number(fp);
				obj->value[3] = fread_number(fp);
				obj->value[4] = fread_number(fp);
				fMatch = TRUE;
				break;
			}

			if (!str_cmp(word, "Vnum"))
			{
				int vnum;

				vnum = fread_number(fp);
				if ((obj->pIndexData = get_obj_index(vnum)) == NULL)
					printf_debug("Fread_obj: bad vnum %d.", vnum);
				else
					fVnum = TRUE;
				fMatch = TRUE;
				break;
			}
			break;

		case 'W':
			KEY( "WearFlags", obj->wear_flags, fread_number( fp ) )
			;
			KEY( "WeaF", obj->wear_flags, fread_number( fp ) )
			;
			KEY( "WearLoc", obj->wear_loc, fread_number( fp ) )
			;
			KEY( "Wear", obj->wear_loc, fread_number( fp ) )
			;
			KEY( "Weight", obj->weight, fread_number( fp ) )
			;
			KEY( "Wt", obj->weight, fread_number( fp ) )
			;
			break;

		}

		if (!fMatch)
		{
			printf_debug("Fread_obj: no match.");
			fread_to_eol(fp);
		}
	}
	if (obj->pIndexData->vnum == OBJ_VNUM_QDIAMOND)
	{
		ch->platinum++;
		extract_obj(obj);
	}
	if (obj->pIndexData->vnum == OBJ_VNUM_PASSBOOK)
	{
		if (!is_othcomp(obj->value[0], obj->value[1], obj->name))
			extract_obj(obj);
	}
}

void fread_char_reroll(CHAR_DATA *ch, FILE *fp)
{
	char buf[MAX_STRING_LENGTH];
	char *word;
	bool fMatch;
	int dummy;

	ch->pcdata->base_hit = 100;
	ch->pcdata->base_mana = 100;
	ch->pcdata->base_move = 100;

	sprintf(buf, "Loading %s.", ch->name);
	if (strcmp(ch->name, ""))
	{
		printf_system(buf);
	}
	ch->questpoints = 0;
	for (;;)
	{
		word = feof(fp) ? "End" : fread_word(fp);
		fMatch = FALSE;

		switch (UPPER(word[0]))
		{
		case '*':
			fMatch = TRUE;
			fread_to_eol(fp);
			break;

		case 'A':
			KEY( "Arank", dummy, fread_number( fp ) )
			;
			break;

		case 'E':
			if (!str_cmp(word, "End"))
			{
				return;
			}
			break;

		case 'G':
			KEY( "Gold", ch->gold, fread_number( fp ) )
			;
			break;

		case 'M':
			if (!str_cmp(word, "Mtype"))
			{
				ch->magic[MAGIC_WHITE] = fread_number(fp);
				ch->magic[MAGIC_RED] = fread_number(fp);
				ch->magic[MAGIC_BLUE] = fread_number(fp);
				ch->magic[MAGIC_GREEN] = fread_number(fp);
				ch->magic[MAGIC_BLACK] = fread_number(fp);
				ch->magic[MAGIC_ORANGE] = fread_number(fp);
				fMatch = TRUE;
				break;
			}
			break;
		case 'P':
			KEY( "Plat", ch->platinum, fread_number( fp ) )
			;
			KEY( "Pkil", dummy, fread_number( fp ) )
			;
			KEY( "Pdea", dummy, fread_number( fp ) )
			;
			KEY( "Prank", dummy, fread_number( fp ) )
			;
			break;
		case 'Q':
			if (!str_cmp(word, "Qps")) {
				ch->questpoints += 300*fread_number(fp);
				fMatch = TRUE;
				break;
			} else if (!str_cmp(word, "QuestPnts")) {
				ch->questpoints += fread_number(fp);
				fMatch = TRUE;
				break;
			}
			;
			break;
		case 'S':
			KEY( "Silv", ch->silver, fread_number( fp ) )
			;
			KEY( "Status", ch->pcdata->status, fread_number( fp ) )
			;

			if (!str_cmp(word, "Stance"))
			{
				ch->stance[0] = fread_number(fp);
				ch->stance[1] = fread_number(fp);
				ch->stance[2] = fread_number(fp);
				ch->stance[3] = fread_number(fp);
				ch->stance[4] = fread_number(fp);
				ch->stance[5] = fread_number(fp);
				ch->stance[6] = fread_number(fp);
				ch->stance[7] = fread_number(fp);
				ch->stance[8] = fread_number(fp);
				ch->stance[9] = fread_number(fp);
				ch->stance[10] = fread_number(fp);
				fMatch = TRUE;
				break;
			}
			break;

		}

		if (!fMatch)
		{
			/* char lbuf[128];
			 Take this out because we don't want spam
			 sprintf( lbuf, "Fread_char_reroll: no match on word '%s'.", word );
			 bug( lbuf, 0 ); */
			fread_to_eol(fp);
		}
	}
}

void update_class_bits(CHAR_DATA *ch)
{
	if (ch->class == CLASS_MONK)
	{
		SET_BIT(ch->imm_flags,IMM_POISON);
		SET_BIT(ch->res_flags,RES_NEGATIVE);
	}
	if (ch->class == CLASS_DARKPALADIN)
	{
		SET_BIT(ch->imm_flags,IMM_DISEASE);
		SET_BIT(ch->res_flags,RES_HOLY);
	}
}