/* ************************************************************************
*   File: players.c                                     Part of CircleMUD *
*  Usage: Player loading/saving and utility routines                      *
*                                                                         *
*  All rights reserved.  See license.doc for complete information.        *
*                                                                         *
*  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
*  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
************************************************************************ */

#include "conf.h"
#include "sysdep.h"

#include "structs.h"
#include "utils.h"
#include "db.h"
#include "handler.h"
#include "pfdefaults.h"
#include "dg_scripts.h"
#include "comm.h"
#include "genmob.h"
#include "dbz.h"

#define LOAD_HIT	0
#define LOAD_MANA	1
#define LOAD_MOVE	2
#define LOAD_STRENGTH	3

/* local functions */
void build_player_index(void);
void save_etext(struct char_data *ch);
int sprintascii(char *out, bitvector_t bits);
void tag_argument(char *argument, char *tag);
void load_affects(FILE *fl, struct char_data *ch);
void load_skills(FILE *fl, struct char_data *ch);
void load_HMVS(struct char_data *ch, const char *line, int mode);

/* external fuctions */
bitvector_t asciiflag_conv(char *flag);
void save_char_vars(struct char_data *ch);
void strip_cr(char *buffer);

/* 'global' vars */
struct player_index_element *player_table = NULL;	/* index to plr file	 */
int top_of_p_table = 0;		/* ref to top of table		 */
int top_of_p_file = 0;		/* ref of size of p file	 */
long top_idnum = 0;		/* highest idnum in use		 */


/* external ASCII Player Files vars */
extern struct pclean_criteria_data pclean_criteria[];


/* ASCII Player Files - set this TRUE if you want poofin/poofout
   strings saved in the pfiles
 */
#define ASCII_SAVE_POOFS  TRUE


/*************************************************************************
*  stuff related to the player index					 *
*************************************************************************/


/* new version to build player index for ASCII Player Files */
/* generate index table for the player file */
void build_player_index(void)
{
  int rec_count = 0, i;
  FILE *plr_index;
  char index_name[40], line[256], bits[64];
  char arg2[80];

  sprintf(index_name, "%s%s", LIB_PLRFILES, INDEX_FILE);
  if (!(plr_index = fopen(index_name, "r"))) {
    top_of_p_table = -1;
    log("No player index file!  First new char will be IMP!");
    return;
  }

  while (get_line(plr_index, line))
    if (*line != '~')
      rec_count++;
  rewind(plr_index);

  if (rec_count == 0) {
    player_table = NULL;
    top_of_p_table = -1;
    return;
  }

  CREATE(player_table, struct player_index_element, rec_count);
  for (i = 0; i < rec_count; i++) {
    get_line(plr_index, line);
    sscanf(line, "%ld %s %d %s %d", &player_table[i].id, arg2,
      &player_table[i].level, bits, (int *)&player_table[i].last);
    CREATE(player_table[i].name, char, strlen(arg2) + 1);
    strcpy(player_table[i].name, arg2);
    player_table[i].flags = asciiflag_conv(bits);
    top_idnum = MAX(top_idnum, player_table[i].id);
  }

  fclose(plr_index);
  top_of_p_file = top_of_p_table = i - 1;
}


/*
 * Create a new entry in the in-memory index table for the player file.
 * If the name already exists, by overwriting a deleted character, then
 * we re-use the old position.
 */
int create_entry(char *name)
{
  int i, pos;

  if (top_of_p_table == -1) {	/* no table */
    CREATE(player_table, struct player_index_element, 1);
    pos = top_of_p_table = 0;
  } else if ((pos = get_ptable_by_name(name)) == -1) {	/* new name */
    i = ++top_of_p_table + 1;

    RECREATE(player_table, struct player_index_element, i);
    pos = top_of_p_table;
  }

  CREATE(player_table[pos].name, char, strlen(name) + 1);

  /* copy lowercase equivalent of name to table field */
  for (i = 0; (player_table[pos].name[i] = LOWER(name[i])); i++)
	/* Nothing */;

  /* clear the bitflag in case we have garbage data */
  player_table[pos].flags = 0;

  return (pos);
}


/* This function necessary to save a seperate ASCII player index */
void save_player_index(void)
{
  int i;
  char index_name[50], bits[64];
  FILE *index_file;

  sprintf(index_name, "%s%s", LIB_PLRFILES, INDEX_FILE);
  if (!(index_file = fopen(index_name, "w"))) {
    log("SYSERR: Could not write player index file");
    return;
  }

  for (i = 0; i <= top_of_p_table; i++)
    if (*player_table[i].name) {
      sprintascii(bits, player_table[i].flags);
      fprintf(index_file, "%ld %s %d %s %ld\n", player_table[i].id,
	player_table[i].name, player_table[i].level, *bits ? bits : "0",
	player_table[i].last);
    }
  fprintf(index_file, "~\n");

  fclose(index_file);
}


void free_player_index(void)
{
  int tp;

  if (!player_table)
    return;

  for (tp = 0; tp <= top_of_p_table; tp++)
    if (player_table[tp].name)
      free(player_table[tp].name);

  free(player_table);
  player_table = NULL;
  top_of_p_table = 0;
}


long get_ptable_by_name(const char *name)
{
  int i;

  for (i = 0; i <= top_of_p_table; i++)
    if (!str_cmp(player_table[i].name, name))
      return (i);

  return (-1);
}


long get_id_by_name(const char *name)
{
  int i;

  for (i = 0; i <= top_of_p_table; i++)
    if (!str_cmp(player_table[i].name, name))
      return (player_table[i].id);

  return (-1);
}


char *get_name_by_id(long id)
{
  int i;

  for (i = 0; i <= top_of_p_table; i++)
    if (player_table[i].id == id)
      return (player_table[i].name);

  return (NULL);
}


/*************************************************************************
*  stuff related to the save/load player system				 *
*************************************************************************/


#define NUM_OF_SAVE_THROWS	5

/* new load_char reads ASCII Player Files */
/* Load a char, TRUE if loaded, FALSE if not */
int load_char(const char *name, struct char_data *ch)
{
  int id, i;
  FILE *fl;
  char fname[40];
  char buf[128], buf2[128], line[MAX_INPUT_LENGTH + 1], tag[6];

  if ((id = get_ptable_by_name(name)) < 0)
    return (-1);
  else {
    if (!get_filename(fname, sizeof(fname), PLR_FILE, player_table[id].name))
      return (-1);
    if (!(fl = fopen(fname, "r"))) {
      mudlog(NRM, LVL_GOD, TRUE, "SYSERR: Couldn't open player file %s", fname);
      return (-1);
    }

    /* character initializations */
    /* initializations necessary to keep some things straight */
    ch->affected = NULL;
    GET_SEX(ch) = PFDEF_SEX;
    GET_CLASS(ch) = PFDEF_CLASS;
    GET_LEVEL(ch) = PFDEF_LEVEL;
    GET_HEIGHT(ch) = PFDEF_HEIGHT;
    GET_WEIGHT(ch) = PFDEF_WEIGHT;
    GET_LOADROOM(ch) = PFDEF_LOADROOM;
    GET_INVIS_LEV(ch) = PFDEF_INVISLEV;
    GET_FREEZE_LEV(ch) = PFDEF_FREEZELEV;
    GET_BAD_PWS(ch) = PFDEF_BADPWS;
    GET_EXP(ch) = PFDEF_EXP;
    GET_POWERLEVEL(ch) = PFDEF_POWERLEVEL;
    GET_CURRENTPL(ch) = PFDEF_CURRENTPL;
    GET_KI(ch) = PFDEF_KI;
    GET_CURRENTKI(ch) = PFDEF_CURRENTKI;
    for (i = 0; i < AF_ARRAY_MAX; i++)
      AFF_FLAGS(ch)[i] = PFDEF_AFFFLAGS;
    for (i = 0; i < PM_ARRAY_MAX; i++)
      PLR_FLAGS(ch)[i] = PFDEF_PLRFLAGS;
    for (i = 0; i < PR_ARRAY_MAX; i++)
      PRF_FLAGS(ch)[i] = PFDEF_PREFFLAGS;

// Attributes
    ch->real_abils.strength = PFDEF_STRENGTH;
    ch->real_abils.stamina = PFDEF_STAMINA;
    ch->real_abils.spirit = PFDEF_SPIRIT;
    ch->real_abils.appearance = PFDEF_APPEARANCE;
    ch->real_abils.wits = PFDEF_WITS;
    ch->real_abils.intelligence = PFDEF_INTELLIGENCE;
    ch->real_abils.perception = PFDEF_PERCEPTION;
    ch->real_abils.speed = PFDEF_SPEED;
    ch->real_abils.agility = PFDEF_AGILITY;

// Abilities
	ch->real_abils.alertness = PFDEF_ALERTNESS;
	ch->real_abils.academics = PFDEF_ACADEMICS;
	ch->real_abils.athletics = PFDEF_ATHLETICS;
	ch->real_abils.firearms = PFDEF_FIREARMS;
	ch->real_abils.computer = PFDEF_COMPUTER;
	ch->real_abils.martialarts = PFDEF_MARTIALARTS;
	ch->real_abils.investigation = PFDEF_INVESTIGATION;
	ch->real_abils.dodge = PFDEF_DODGE;
	ch->real_abils.melee = PFDEF_MELEE;
	ch->real_abils.medicine = PFDEF_MEDICINE;
	ch->real_abils.intimidation = PFDEF_INTIMIDATION;
	ch->real_abils.leadership = PFDEF_LEADERSHIP;
	ch->real_abils.pilot = PFDEF_PILOT;
	ch->real_abils.stealth = PFDEF_STEALTH;
	ch->real_abils.subterfuge = PFDEF_SUBTERFUGE;
	ch->real_abils.block = PFDEF_BLOCK;
        ch->real_abils.reflect = PFDEF_REFLECT;
        ch->real_abils.meditate = PFDEF_MEDITATE;
        ch->real_abils.auraskill = PFDEF_AURASKILL;
        ch->real_abils.galacticlore = PFDEF_GALACTICLORE;
        ch->real_abils.spacecraft = PFDEF_SPACECRAFT;
        ch->real_abils.kiknowledge = PFDEF_KIKNOWLEDGE;
        ch->real_abils.training = PFDEF_TRAINING; 
        ch->real_abils.counter = PFDEF_COUNTER;
        
        ch->real_abils.spiritpoints = PFDEF_SPIRITPOINTS;
        ch->real_abils.actionpoints = PFDEF_ACTIONPOINTS;
	ch->real_abils.creationpoints = PFDEF_CREATIONPOINTS;
        ch->real_abils.abilpoints = PFDEF_ABILPOINTS;
	ch->real_abils.bgpoints = PFDEF_BGPOINTS;
        ch->real_abils.votes = PFDEF_VOTES;
        ch->real_abils.strcounter = PFDEF_STRCOUNTER;
        ch->real_abils.spdcounter = PFDEF_SPDCOUNTER;
        ch->real_abils.stmcounter = PFDEF_STMCOUNTER;
        ch->real_abils.agicounter = PFDEF_AGICOUNTER;
        ch->real_abils.sprcounter = PFDEF_SPRCOUNTER;
        ch->real_abils.witscounter = PFDEF_WITSCOUNTER;
        ch->real_abils.percounter = PFDEF_PERCOUNTER;


	// Willpower and Virtues and damage

	 ch->real_abils.courage = PFDEF_COURAGE;
	 ch->real_abils.selfcontrol = PFDEF_SELFCONTROL;
	 ch->real_abils.conscience = PFDEF_CONSCIENCE;
	 ch->real_abils.willpower = PFDEF_WILLPOWER;
	 ch->real_abils.usedwillpower = PFDEF_USEDWILLPOWER;



	// Backgrounds

   ch->real_abils.mentor  = PFDEF_MENTOR;
   ch->real_abils.cronies = PFDEF_CRONIES;
   ch->real_abils.resources  = PFDEF_RESOURCES;
   ch->real_abils.allies  = PFDEF_ALLIES;
   ch->real_abils.spaceship = PFDEF_SPACESHIP;
   ch->real_abils.dojo  = PFDEF_DOJO;
   ch->real_abils.rank = PFDEF_RANK;
   ch->real_abils.renown  = PFDEF_RENOWN;
   ch->real_abils.bloodline  = PFDEF_BLOODLINE;


    GET_OLC_ZONE(ch) = PFDEF_OLC;
    GET_HOST(ch) = NULL;
    GET_PAGE_LENGTH(ch) = PFDEF_PAGELENGTH;

    while (get_line(fl, line)) {
      tag_argument(line, tag);

      switch (*tag) {
      case 'A':
if (!strcmp(tag, "Act ")) {
         if (sscanf(line, "%s %s %s %s", f1, f2, f3, f4) == 4) {
          PLR_FLAGS(ch)[0] = asciiflag_conv(f1);
          PLR_FLAGS(ch)[1] = asciiflag_conv(f2);
          PLR_FLAGS(ch)[2] = asciiflag_conv(f3);
          PLR_FLAGS(ch)[3] = asciiflag_conv(f4);
        } else
          PLR_FLAGS(ch)[0] = asciiflag_conv(line);
      } else if (!strcmp(tag, "Aff ")) {
        if (sscanf(line, "%s %s %s %s", f1, f2, f3, f4) == 4) {
          AFF_FLAGS(ch)[0] = asciiflag_conv(f1);
          AFF_FLAGS(ch)[1] = asciiflag_conv(f2);
          AFF_FLAGS(ch)[2] = asciiflag_conv(f3);
          AFF_FLAGS(ch)[3] = asciiflag_conv(f4);
        } else 
          AFF_FLAGS(ch)[0] = asciiflag_conv(line);	
	}
	if (!strcmp(tag, "Affs")) 	load_affects(fl, ch);

        else if (!strcmp(tag, "Appe"))  ch->real_abils.appearance  = atoi(line);
        else if (!strcmp(tag, "Aler"))  ch->real_abils.alertness   = atoi(line);
        else if (!strcmp(tag, "Acad"))  ch->real_abils.academics   = atoi(line);
        else if (!strcmp(tag, "Agil"))  ch->real_abils.agility = atoi(line);
        else if (!strcmp(tag, "Acpt"))  ch->real_abils.actionpoints = atoi(line);
        else if (!strcmp(tag, "Alli"))  ch->real_abils.allies   = atoi(line);
        else if (!strcmp(tag, "Athl"))  ch->real_abils.athletics   = atoi(line);
        else if (!strcmp(tag, "Aurs"))  ch->real_abils.auraskill   = atoi(line);
        else if (!strcmp(tag, "Aura"))  GET_AURA(ch)           = strdup(line);
        else if (!strcmp(tag, "Abpt"))  ch->real_abils.abilpoints = atoi(line);
        else if (!strcmp(tag, "Agic"))  ch->real_abils.agicounter = atoi(line);
 	break;

      case 'B':
	     if (!strcmp(tag, "Badp"))	GET_BAD_PWS(ch)		= atoi(line);
	else if (!strcmp(tag, "Brth"))	ch->player.time.birth	= atol(line);
        else if (!strcmp(tag, "Back"))  ch->player.background   = fread_string(fl, buf2);
        else if (!strcmp(tag, "Bloc"))  ch->real_abils.block   = atoi(line);
        else if (!strcmp(tag, "Bloo"))  ch->real_abils.bloodline  = atoi(line);
        else if (!strcmp(tag, "Bgpt"))  ch->real_abils.bgpoints = atoi(line);

	break;

      case 'C':
	if (!strcmp(tag, "Clas"))	GET_CLASS(ch)		= atoi(line);
        else if (!strcmp(tag, "Comp"))  ch->real_abils.computer = atoi(line);
        else if (!strcmp(tag, "Coun"))  ch->real_abils.counter    = atoi(line);
        else if (!strcmp(tag, "Cour"))  ch->real_abils.courage  = atoi(line);
        else if (!strcmp(tag, "Cupl"))  GET_CURRENTPL(ch)      = atoi(line);
        else if (!strcmp(tag, "Cron"))  ch->real_abils.cronies  = atoi(line);
        else if (!strcmp(tag, "Cons"))  ch->real_abils.conscience  = atoi(line);
        else if (!strcmp(tag, "Cage"))  GET_CHARAGE(ch)         = strdup(line);
        else if (!strcmp(tag, "Crpt"))  ch->real_abils.creationpoints = atoi(line);
	break;

      case 'D':
	     if (!strcmp(tag, "Desc"))	ch->player.description	= fread_string(fl, buf2);
        else if (!strcmp(tag, "Dodg"))  ch->real_abils.dodge   = atoi(line);
        else if (!strcmp(tag, "Dojo"))  ch->real_abils.dojo   = atoi(line);
        else if (!strcmp(tag, "Doin"))  GET_DOING(ch)           = strdup(line);
	break;

      case 'E':
	     if (!strcmp(tag, "Exp "))	GET_EXP(ch)		= atoi(line);
	break;

      case 'F':
	     if (!strcmp(tag, "Frez"))	GET_FREEZE_LEV(ch)	= atoi(line);
        else if (!strcmp(tag, "Fafr"))  GET_FAMILYFRIENDS(ch)         = strdup(line);
        else if (!strcmp(tag, "Fire"))  ch->real_abils.firearms   = atoi(line);
        else if (!strcmp(tag, "Fla1"))  GET_FLAW1(ch)         = strdup(line);
        else if (!strcmp(tag, "Fla2"))  GET_FLAW2(ch)         = strdup(line);
        else if (!strcmp(tag, "Fla3"))  GET_FLAW3(ch)         = strdup(line);
        else if (!strcmp(tag, "Fla4"))  GET_FLAW4(ch)         = strdup(line);
        else if (!strcmp(tag, "Fla5"))  GET_FLAW5(ch)         = strdup(line);
        else if (!strcmp(tag, "Fla6"))  GET_FLAW6(ch)         = strdup(line);
        else if (!strcmp(tag, "Fla7"))  GET_FLAW7(ch)         = strdup(line);
	break;

      case 'G':
          if (!strcmp(tag, "Galr"))  ch->real_abils.galacticlore  = atoi(line);
          else if (!strcmp(tag, "Goal"))  GET_GOALS(ch)         = strdup(line);
	break;

      case 'H':
	     if (!strcmp(tag, "Hit "))	load_HMVS(ch, line, LOAD_HIT);
	else if (!strcmp(tag, "Hite"))	GET_HEIGHT(ch)		= atoi(line);
	else if (!strcmp(tag, "Host"))	GET_HOST(ch)		= strdup(line);
        else if (!strcmp(tag, "Hplt"))  GET_HOMEPLANET(ch)         = strdup(line);
	break;

      case 'I':
	     if (!strcmp(tag, "Id  "))	GET_IDNUM(ch)		= atol(line);
        else if (!strcmp(tag, "Inte"))  ch->real_abils.intelligence = atoi(line);
	else if (!strcmp(tag, "Invs"))	GET_INVIS_LEV(ch)	= atoi(line);
        else if (!strcmp(tag, "Inve"))  ch->real_abils.investigation   = atoi(line);
        else if (!strcmp(tag, "Inti"))  ch->real_abils.intimidation   = atoi(line);
        else if (!strcmp(tag, "Inf1"))  GET_INFO1(ch)         = strdup(line);
        else if (!strcmp(tag, "Inf2"))  GET_INFO2(ch)         = strdup(line);
        else if (!strcmp(tag, "Inf3"))  GET_INFO3(ch)         = strdup(line);
        else if (!strcmp(tag, "Inf4"))  GET_INFO4(ch)         = strdup(line);
        else if (!strcmp(tag, "Inf5"))  GET_INFO5(ch)         = strdup(line);
        else if (!strcmp(tag, "Inf6"))  GET_INFO6(ch)         = strdup(line);
        else if (!strcmp(tag, "Inf7"))  GET_INFO7(ch)         = strdup(line);
        else if (!strcmp(tag, "Inf8"))  GET_INFO8(ch)         = strdup(line);
        else if (!strcmp(tag, "Inf9"))  GET_INFO9(ch)         = strdup(line);
        else if (!strcmp(tag, "Inf0")) GET_INFO10(ch)         = strdup(line);
        else if (!strcmp(tag, "Imf1"))  GET_IMMINFO1(ch)         = strdup(line);
        else if (!strcmp(tag, "Imf2"))  GET_IMMINFO2(ch)         = strdup(line);
        else if (!strcmp(tag, "Imf3"))  GET_IMMINFO3(ch)         = strdup(line);
        else if (!strcmp(tag, "Imf4"))  GET_IMMINFO4(ch)         = strdup(line);
        else if (!strcmp(tag, "Imf5"))  GET_IMMINFO5(ch)         = strdup(line);
        else if (!strcmp(tag, "Imf6"))  GET_IMMINFO6(ch)         = strdup(line);
        else if (!strcmp(tag, "Imf7"))  GET_IMMINFO7(ch)         = strdup(line);
        else if (!strcmp(tag, "Imf8"))  GET_IMMINFO8(ch)         = strdup(line);
        else if (!strcmp(tag, "Imf9"))  GET_IMMINFO9(ch)         = strdup(line);
        else if (!strcmp(tag, "Imf0"))  GET_IMMINFO10(ch)         = strdup(line);
	break;
 
      case 'K':
            if (!strcmp(tag, "Kico"))  ch->real_abils.kicontrol  = atoi(line);
       else if (!strcmp(tag, "Kikn"))  ch->real_abils.kiknowledge  = atoi(line);
       else if (!strcmp(tag, "Kiii"))  GET_KI(ch)      = atoi(line);
       else if (!strcmp(tag, "Kicu"))  GET_CURRENTKI(ch)      = atoi(line);
         
      case 'L':
	     if (!strcmp(tag, "Last"))	ch->player.time.logon	= atol(line);
	else if (!strcmp(tag, "Levl"))	GET_LEVEL(ch)		= atoi(line);
        else if (!strcmp(tag, "Ledr"))  ch->real_abils.leadership   = atoi(line);
	break;

      case 'M':
        if (!strcmp(tag, "Mele"))  ch->real_abils.melee   = atoi(line);
        else if (!strcmp(tag, "Mart"))  ch->real_abils.martialarts  = atoi(line);
        else if (!strcmp(tag, "Medi"))  ch->real_abils.medicine    = atoi(line);
        else if (!strcmp(tag, "Medt"))  ch->real_abils.meditate    = atoi(line);
        else if (!strcmp(tag, "Ment"))  ch->real_abils.mentor    = atoi(line);
        else if (!strcmp(tag, "Mer1"))  GET_MERIT1(ch)         = strdup(line);
   	else if (!strcmp(tag, "Mer2"))  GET_MERIT2(ch)         = strdup(line);
	else if (!strcmp(tag, "Mer3"))  GET_MERIT3(ch)         = strdup(line);
	else if (!strcmp(tag, "Mer4"))  GET_MERIT4(ch)         = strdup(line);
	else if (!strcmp(tag, "Mer5"))  GET_MERIT5(ch)         = strdup(line);
	else if (!strcmp(tag, "Mer6"))  GET_MERIT6(ch)         = strdup(line);
        else if (!strcmp(tag, "Mer7"))  GET_MERIT7(ch)         = strdup(line);
	break;

      case 'N':
	     if (!strcmp(tag, "Name"))	GET_PC_NAME(ch)	= strdup(line);
        else if (!strcmp(tag, "Not1"))  GET_NOTE1(ch)         = strdup(line);
        else if (!strcmp(tag, "Not2"))  GET_NOTE2(ch)         = strdup(line);
        else if (!strcmp(tag, "Not3"))  GET_NOTE3(ch)         = strdup(line);
        else if (!strcmp(tag, "Not4"))  GET_NOTE4(ch)         = strdup(line);
        else if (!strcmp(tag, "Not5"))  GET_NOTE5(ch)         = strdup(line);
        else if (!strcmp(tag, "Not6"))  GET_NOTE6(ch)         = strdup(line);
        else if (!strcmp(tag, "Not7"))  GET_NOTE7(ch)         = strdup(line);
        else if (!strcmp(tag, "Not8"))  GET_NOTE8(ch)         = strdup(line);
        else if (!strcmp(tag, "Not9"))  GET_NOTE9(ch)         = strdup(line);
        else if (!strcmp(tag, "Not0"))  GET_NOTE10(ch)         = strdup(line);
	break;

      case 'O':
             if (!strcmp(tag, "Olc"))  GET_OLC_ZONE(ch) = atoi(line);
        break;

      case 'P':
             if (!strcmp(tag, "Page"))  GET_PAGE_LENGTH(ch) = atoi(line);
	else if (!strcmp(tag, "Pass"))	strcpy(GET_PASSWD(ch), line);
        else if (!strcmp(tag, "Perc"))  ch->real_abils.perception = atoi(line);
        else if (!strcmp(tag, "Pilo"))  ch->real_abils.pilot   = atoi(line);
	else if (!strcmp(tag, "Plyd"))	ch->player.time.played	= atoi(line);
 #ifdef ASCII_SAVE_POOFS
	else if (!strcmp(tag, "PfIn"))	POOFIN(ch)		= strdup(line);
	else if (!strcmp(tag, "PfOt"))	POOFOUT(ch)		= strdup(line);
 #endif
	else if (!strcmp(tag, "Pref"))	PRF_FLAGS(ch)		= asciiflag_conv(line);
//        else if (!strcmp(tag, "Pwrs"))  PWR_FLAGS(ch)           = asciiflag_conv(line);
        else if (!strcmp(tag, "Powr"))  GET_POWERLEVEL(ch)      = atoi(line);
        else if (!strcmp(tag, "Pow1"))  GET_POWER1(ch)         = strdup(line);
        else if (!strcmp(tag, "Pow2"))  GET_POWER2(ch)         = strdup(line);
        else if (!strcmp(tag, "Pow3"))  GET_POWER3(ch)         = strdup(line);
        else if (!strcmp(tag, "Pow4"))  GET_POWER4(ch)         = strdup(line);
        else if (!strcmp(tag, "Pow5"))  GET_POWER5(ch)         = strdup(line);
        else if (!strcmp(tag, "Pow6"))  GET_POWER6(ch)         = strdup(line);
        else if (!strcmp(tag, "Pow7"))  GET_POWER7(ch)         = strdup(line);
        else if (!strcmp(tag, "Pow8"))  GET_POWER8(ch)         = strdup(line);
        else if (!strcmp(tag, "Pow9"))  GET_POWER9(ch)         = strdup(line);
        else if (!strcmp(tag, "Po10"))  GET_POWER10(ch)         = strdup(line);
        else if (!strcmp(tag, "Po11"))  GET_POWER11(ch)         = strdup(line);
        else if (!strcmp(tag, "Po12"))  GET_POWER12(ch)         = strdup(line);
        else if (!strcmp(tag, "Po13"))  GET_POWER13(ch)         = strdup(line);
        else if (!strcmp(tag, "Po14"))  GET_POWER14(ch)         = strdup(line);
        else if (!strcmp(tag, "Po15"))  GET_POWER15(ch)         = strdup(line);
        else if (!strcmp(tag, "Po16"))  GET_POWER16(ch)         = strdup(line);
        else if (!strcmp(tag, "Po17"))  GET_POWER17(ch)         = strdup(line);
        else if (!strcmp(tag, "Po18"))  GET_POWER18(ch)         = strdup(line);
        else if (!strcmp(tag, "Pict"))  GET_PICTURE(ch)         = strdup(line);
        else if (!strcmp(tag, "Perc"))  ch->real_abils.percounter = atoi(line);
	break;

      case 'Q':
        if (!strcmp(tag, "Quot"))  GET_QUOTE(ch)         = strdup(line);

      case 'R':
	     if (!strcmp(tag, "Room"))	GET_LOADROOM(ch)	= atoi(line);
        else if (!strcmp(tag, "Rodc"))  GET_ROOMDESC(ch)           = strdup(line);
        else if (!strcmp(tag, "Refl"))  ch->real_abils.reflect    = atoi(line);
        else if (!strcmp(tag, "Reso"))  ch->real_abils.resources    = atoi(line);
        else if (!strcmp(tag, "Reno"))  ch->real_abils.renown    = atoi(line);
        else if (!strcmp(tag, "Rank"))  ch->real_abils.rank    = atoi(line);

	break;

      case 'S':
	     if (!strcmp(tag, "Sex "))	GET_SEX(ch)		= atoi(line);
        else if (!strcmp(tag, "Stre"))  ch->real_abils.strength = atoi(line);
        else if (!strcmp(tag, "Stam"))  ch->real_abils.stamina  = atoi(line);
        else if (!strcmp(tag, "Sped"))  ch->real_abils.speed = atoi(line);
        else if (!strcmp(tag, "Stea"))  ch->real_abils.stealth   = atoi(line);
        else if (!strcmp(tag, "Spir"))  ch->real_abils.spirit = atoi(line);
        else if (!strcmp(tag, "Sbtr"))  ch->real_abils.subterfuge   = atoi(line);
        else if (!strcmp(tag, "Scie"))  ch->real_abils.science   = atoi(line);
        else if (!strcmp(tag, "Spas"))  ch->real_abils.spaceship    = atoi(line);
        else if (!strcmp(tag, "Self"))  ch->real_abils.selfcontrol  = atoi(line);
        else if (!strcmp(tag, "Spac"))  ch->real_abils.spacecraft   = atoi(line);
        else if (!strcmp(tag, "Sppt"))  ch->real_abils.spiritpoints = atoi(line);
        else if (!strcmp(tag, "Sta1"))  GET_LOOKSTATUS(ch)           = strdup(line);
        else if (!strcmp(tag, "Strc"))  ch->real_abils.strcounter = atoi(line);
        else if (!strcmp(tag, "Spdc"))  ch->real_abils.spdcounter = atoi(line);
        else if (!strcmp(tag, "Stmc"))  ch->real_abils.stmcounter = atoi(line);
        else if (!strcmp(tag, "Sprc"))  ch->real_abils.sprcounter = atoi(line);
	break;

      case 'T':
	if (!strcmp(tag, "Titl"))	GET_TITLE(ch)		= strdup(line);
        else if (!strcmp(tag, "Trai"))  ch->real_abils.training  = atoi(line);
        else if (!strcmp(tag, "Thso"))  GET_THEMESONG(ch)         = strdup(line);
	break;

     case 'U':
            if (!strcmp(tag, "Udwp"))  ch->real_abils.usedwillpower = atoi(line);
        break;

     case 'V':
           if (!strcmp(tag, "Vote"))  GET_VOTES(ch)       =  atoi(line);

      case 'W':
	     if (!strcmp(tag, "Wate"))	GET_WEIGHT(ch)		= atoi(line);
        else if (!strcmp(tag, "Wits"))  ch->real_abils.wits     = atoi(line);
        else if (!strcmp(tag, "Will"))  ch->real_abils.willpower = atoi(line);
        else if (!strcmp(tag, "Witc"))  ch->real_abils.witscounter = atoi(line);
	break;

      default:
	sprintf(buf, "SYSERR: Unknown tag %s in pfile %s", tag, name);
      }
    }
  }

  affect_total(ch);

  /* initialization for imms */
  if (GET_LEVEL(ch) >= LVL_IMMORT) {
  }
  fclose(fl);
  return(id);
}


/* remove ^M's from file output */
/* There may be a similar function in Oasis (and I'm sure
   it's part of obuild).  Remove this if you get a
   multiple definition error or if it you want to use a
   substitute
*/
void kill_ems(char *str)
{
  char *ptr1, *ptr2, *tmp;

  tmp = str;
  ptr1 = str;
  ptr2 = str;

  while (*ptr1) {
    if ((*(ptr2++) = *(ptr1++)) == '\r')
      if (*ptr1 == '\r')
	ptr1++;
  }
  *ptr2 = '\0';
}


/*
 * write the vital data of a player to the player file
 *
 * And that's it! No more fudging around with the load room.
 */
/* This is the ASCII Player Files save routine */
void save_char(struct char_data * ch)
{
  FILE *fl;
  char f1[128], f2[128], f3[128], f4[128];
  int i, id, save_index = FALSE;
  struct affected_type *aff, tmp_aff[MAX_AFFECT];
  struct obj_data *char_eq[NUM_WEARS];

  if (IS_NPC(ch) || GET_PFILEPOS(ch) < 0)
    return;

  /*
   * If ch->desc is not null, then we need to update some session data
   * before saving.
   */
  if (ch->desc) {
    if (ch->desc->host && *ch->desc->host) {
      if (!GET_HOST(ch))
        GET_HOST(ch) = strdup(ch->desc->host);
      else if (GET_HOST(ch) && !strcmp(GET_HOST(ch), ch->desc->host)) {
        free(GET_HOST(ch));
        GET_HOST(ch) = strdup(ch->desc->host);
      }
    }

    /*
     * We only update the time.played and time.logon if the character
     * is playing.
     */
    if (STATE(ch->desc) == CON_PLAYING) {
      ch->player.time.played += time(0) - ch->player.time.logon;
      ch->player.time.logon = time(0);
    }
  }

  if (!get_filename(fname, sizeof(fname), PLR_FILE, GET_NAME(ch)))
    return;
  if (!(fl = fopen(fname, "w"))) {
    mudlog(NRM, LVL_GOD, TRUE, "SYSERR: Couldn't open player file %s for write", fname);
    return;
  }

  /* remove affects from eq and spells (from char_to_store) */
  /* Unaffect everything a character can be affected by */

  for (i = 0; i < NUM_WEARS; i++) {
    if (GET_EQ(ch, i)) {
      char_eq[i] = unequip_char(ch, i);
#ifndef NO_EXTRANEOUS_TRIGGERS
      remove_otrigger(char_eq[i], ch);
#endif
}
    else
      char_eq[i] = NULL;
  }

  for (aff = ch->affected, i = 0; i < MAX_AFFECT; i++) {
    if (aff) {
      tmp_aff[i] = *aff;
      tmp_aff[i].next = 0;
      aff = aff->next;
    } else {
      tmp_aff[i].type = 0;	/* Zero signifies not used */
      tmp_aff[i].duration = 0;
      tmp_aff[i].modifier = 0;
      tmp_aff[i].location = 0;
      tmp_aff[i].bitvector = 0;
      tmp_aff[i].next = 0;
    }
  }
  save_char_vars(ch);

  /*
   * remove the affections so that the raw values are stored; otherwise the
   * effects are doubled when the char logs back in.
   */

  while (ch->affected)
    affect_remove(ch, ch->affected);

  if ((i >= MAX_AFFECT) && aff && aff->next)
    log("SYSERR: WARNING: OUT OF STORE ROOM FOR AFFECTED TYPES!!!");

  ch->aff_abils = ch->real_abils;

  /* end char_to_store code */

  if (GET_NAME(ch))				fprintf(fl, "Name: %s\n", GET_NAME(ch));
  if (GET_PASSWD(ch))				fprintf(fl, "Pass: %s\n", GET_PASSWD(ch));
  if (GET_TITLE(ch))				fprintf(fl, "Titl: %s\n", GET_TITLE(ch));
  if (GET_MERIT1(ch))                           fprintf(fl, "Mer1: %s\n", GET_MERIT1(ch));
  if (GET_FLAW1(ch))                            fprintf(fl, "Fla1: %s\n", GET_FLAW1(ch));
  if (GET_MERIT2(ch))                           fprintf(fl, "Mer2: %s\n", GET_MERIT2(ch));
  if (GET_FLAW2(ch))                            fprintf(fl, "Fla2: %s\n", GET_FLAW2(ch));
  if (GET_MERIT3(ch))                           fprintf(fl, "Mer3: %s\n", GET_MERIT3(ch));
  if (GET_FLAW3(ch))                            fprintf(fl, "Fla3: %s\n", GET_FLAW3(ch));
  if (GET_MERIT4(ch))                           fprintf(fl, "Mer4: %s\n", GET_MERIT4(ch));
  if (GET_FLAW4(ch))                            fprintf(fl, "Fla4: %s\n", GET_FLAW4(ch));
  if (GET_MERIT5(ch))                           fprintf(fl, "Mer5: %s\n", GET_MERIT5(ch));
  if (GET_FLAW5(ch))                            fprintf(fl, "Fla5: %s\n", GET_FLAW5(ch));
  if (GET_MERIT6(ch))                           fprintf(fl, "Mer6: %s\n", GET_MERIT6(ch));
  if (GET_FLAW6(ch))                            fprintf(fl, "Fla6: %s\n", GET_FLAW6(ch));
  if (GET_MERIT7(ch))                           fprintf(fl, "Mer7: %s\n", GET_MERIT7(ch));
  if (GET_FLAW7(ch))                            fprintf(fl, "Fla7: %s\n", GET_FLAW7(ch));
  if (GET_INFO1(ch))                            fprintf(fl, "Inf1: %s\n", GET_INFO1(ch));
  if (GET_INFO2(ch))                            fprintf(fl, "Inf2: %s\n", GET_INFO2(ch));
  if (GET_INFO3(ch))                            fprintf(fl, "Inf3: %s\n", GET_INFO3(ch));
  if (GET_INFO4(ch))                            fprintf(fl, "Inf4: %s\n", GET_INFO4(ch));
  if (GET_INFO5(ch))                            fprintf(fl, "Inf5: %s\n", GET_INFO5(ch));
  if (GET_INFO6(ch))                            fprintf(fl, "Inf6: %s\n", GET_INFO6(ch));
  if (GET_INFO7(ch))                            fprintf(fl, "Inf7: %s\n", GET_INFO7(ch));
  if (GET_INFO8(ch))                            fprintf(fl, "Inf8: %s\n", GET_INFO8(ch));
  if (GET_INFO9(ch))                            fprintf(fl, "Inf9: %s\n", GET_INFO9(ch));
  if (GET_INFO10(ch))                            fprintf(fl, "Inf0: %s\n", GET_INFO10(ch));
  if (GET_IMMINFO1(ch))                            fprintf(fl, "Imf1: %s\n", GET_IMMINFO1(ch));
  if (GET_IMMINFO2(ch))                            fprintf(fl, "Imf2: %s\n", GET_IMMINFO2(ch));
  if (GET_IMMINFO3(ch))                            fprintf(fl, "Imf3: %s\n", GET_IMMINFO3(ch));
  if (GET_IMMINFO4(ch))                            fprintf(fl, "Imf4: %s\n", GET_IMMINFO4(ch));
  if (GET_IMMINFO5(ch))                            fprintf(fl, "Imf5: %s\n", GET_IMMINFO5(ch));
  if (GET_IMMINFO6(ch))                            fprintf(fl, "Imf6: %s\n", GET_IMMINFO6(ch));
  if (GET_IMMINFO7(ch))                            fprintf(fl, "Imf7: %s\n", GET_IMMINFO7(ch));
  if (GET_IMMINFO8(ch))                            fprintf(fl, "Imf8: %s\n", GET_IMMINFO8(ch));
  if (GET_IMMINFO9(ch))                            fprintf(fl, "Imf9: %s\n", GET_IMMINFO9(ch));
  if (GET_IMMINFO10(ch))                            fprintf(fl, "Imf0: %s\n", GET_IMMINFO10(ch));
  if (GET_DOING(ch))                            fprintf(fl, "Doin: %s\n", GET_DOING(ch));
  if (GET_AURA(ch))                             fprintf(fl, "Aura: %s\n", GET_AURA(ch));
  if (GET_LOOKSTATUS(ch))                             fprintf(fl, "Sta1: %s\n", GET_LOOKSTATUS(ch));
  if (GET_ROOMDESC(ch))                             fprintf(fl, "Rodc: %s\n", GET_ROOMDESC(ch));
  if (GET_NOTE1(ch))                            fprintf(fl, "Not1: %s\n", GET_NOTE1(ch));
  if (GET_NOTE2(ch))                            fprintf(fl, "Not2: %s\n", GET_NOTE2(ch));
  if (GET_NOTE3(ch))                            fprintf(fl, "Not3: %s\n", GET_NOTE3(ch));
  if (GET_NOTE4(ch))                            fprintf(fl, "Not4: %s\n", GET_NOTE4(ch));
  if (GET_NOTE5(ch))                            fprintf(fl, "Not5: %s\n", GET_NOTE5(ch));
  if (GET_NOTE6(ch))                            fprintf(fl, "Not6: %s\n", GET_NOTE6(ch));
  if (GET_NOTE7(ch))                            fprintf(fl, "Not7: %s\n", GET_NOTE7(ch));
  if (GET_NOTE8(ch))                            fprintf(fl, "Not8: %s\n", GET_NOTE8(ch));
  if (GET_NOTE9(ch))                            fprintf(fl, "Not9: %s\n", GET_NOTE9(ch));
  if (GET_NOTE10(ch))                            fprintf(fl, "Not0: %s\n", GET_NOTE10(ch));
  if (GET_POWER1(ch))                            fprintf(fl, "Pow1: %s\n", GET_POWER1(ch));
  if (GET_POWER2(ch))                            fprintf(fl, "Pow2: %s\n", GET_POWER2(ch));
  if (GET_POWER3(ch))                            fprintf(fl, "Pow3: %s\n", GET_POWER3(ch));
  if (GET_POWER4(ch))                            fprintf(fl, "Pow4: %s\n", GET_POWER4(ch));
  if (GET_POWER5(ch))                            fprintf(fl, "Pow5: %s\n", GET_POWER5(ch));
  if (GET_POWER6(ch))                            fprintf(fl, "Pow6: %s\n", GET_POWER6(ch));
  if (GET_POWER7(ch))                            fprintf(fl, "Pow7: %s\n", GET_POWER7(ch));
  if (GET_POWER8(ch))                            fprintf(fl, "Pow8: %s\n", GET_POWER8(ch));
  if (GET_POWER9(ch))                            fprintf(fl, "Pow9: %s\n", GET_POWER9(ch));
  if (GET_POWER10(ch))                            fprintf(fl, "Po10: %s\n", GET_POWER10(ch));
  if (GET_POWER11(ch))                            fprintf(fl, "Po11: %s\n", GET_POWER11(ch));
  if (GET_POWER12(ch))                            fprintf(fl, "Po12: %s\n", GET_POWER12(ch));
  if (GET_POWER13(ch))                            fprintf(fl, "Po13: %s\n", GET_POWER13(ch));
  if (GET_POWER14(ch))                            fprintf(fl, "Po14: %s\n", GET_POWER14(ch));
  if (GET_POWER15(ch))                            fprintf(fl, "Po15: %s\n", GET_POWER15(ch));
  if (GET_POWER16(ch))                            fprintf(fl, "Po16: %s\n", GET_POWER16(ch));
  if (GET_POWER17(ch))                            fprintf(fl, "Po17: %s\n", GET_POWER17(ch));
  if (GET_POWER18(ch))                            fprintf(fl, "Po18: %s\n", GET_POWER18(ch));
  if (GET_CHARAGE(ch))                            fprintf(fl, "Cage: %s\n", GET_CHARAGE(ch));
  if (GET_HOMEPLANET(ch))                            fprintf(fl, "Hplt: %s\n", GET_HOMEPLANET(ch));
  if (GET_THEMESONG(ch))                            fprintf(fl, "Thso: %s\n", GET_THEMESONG(ch));
  if (GET_PICTURE(ch))                            fprintf(fl, "Pict: %s\n", GET_PICTURE(ch));
  if (GET_QUOTE(ch))                            fprintf(fl, "Quot: %s\n", GET_QUOTE(ch));
  if (GET_FAMILYFRIENDS(ch))                            fprintf(fl, "Fafr: %s\n", GET_FAMILYFRIENDS(ch));
  if (GET_GOALS(ch))                            fprintf(fl, "Goal: %s\n", GET_GOALS(ch));

  if (ch->player.description && *ch->player.description) {
    strcpy(buf, ch->player.description);
    kill_ems(buf);
    strip_cr(buf);
    fprintf(fl, "Desc:\n%s~\n", buf);
}

  if (ch->player.description2 && *ch->player.description2) {
    strcpy(buf, ch->player.description2);
    kill_ems(buf);
    fprintf(fl, "Des2:\n%s~\n", buf);
}

  if (ch->player.description3 && *ch->player.description3) {
    strcpy(buf, ch->player.description3);
    kill_ems(buf);
    fprintf(fl, "Des3:\n%s~\n", buf);
}

  if (ch->player.description4 && *ch->player.description4) {
    strcpy(buf, ch->player.description4);
    kill_ems(buf);
    fprintf(fl, "Des4:\n%s~\n", buf);
}

  if (ch->player.background && *ch->player.background) {
    strcpy(buf, ch->player.background);
    kill_ems(buf);
    fprintf(fl, "Back:\n%s~\n", buf);

  }



#ifdef ASCII_SAVE_POOFS
  if (POOFIN(ch))				fprintf(fl, "PfIn: %s\n", POOFIN(ch));
  if (POOFOUT(ch))				fprintf(fl, "PfOt: %s\n", POOFOUT(ch));
#endif
  if (GET_SEX(ch)	   != PFDEF_SEX)	fprintf(fl, "Sex : %d\n", GET_SEX(ch)); 
  if (GET_CLASS(ch)	   != PFDEF_CLASS)	fprintf(fl, "Clas: %d\n", GET_CLASS(ch)); 
  if (GET_LEVEL(ch)	   != PFDEF_LEVEL)	fprintf(fl, "Levl: %d\n", GET_LEVEL(ch));

  fprintf(fl, "Id  : %ld\n", GET_IDNUM(ch));
  fprintf(fl, "Brth: %ld\n", ch->player.time.birth);
  fprintf(fl, "Plyd: %d\n",  ch->player.time.played);
  fprintf(fl, "Last: %ld\n", ch->player.time.logon);

  if (GET_HOST(ch))				fprintf(fl, "Host: %s\n", GET_HOST(ch));
  if (GET_HEIGHT(ch)	   != PFDEF_HEIGHT)	fprintf(fl, "Hite: %d\n", GET_HEIGHT(ch));
  if (GET_WEIGHT(ch)	   != PFDEF_HEIGHT)	fprintf(fl, "Wate: %d\n", GET_WEIGHT(ch));

  if (PLR_FLAGS(ch)	   != PFDEF_PLRFLAGS) {
    sprintascii(bits, PLR_FLAGS(ch));		fprintf(fl, "Act : %s\n", bits);
  }
  if (AFF_FLAGS(ch)	   != PFDEF_AFFFLAGS) {
    sprintascii(bits, AFF_FLAGS(ch));		fprintf(fl, "Aff : %s\n", bits);
  }
  if (PRF_FLAGS(ch)	   != PFDEF_PREFFLAGS) {
    sprintascii(bits, PRF_FLAGS(ch));		fprintf(fl, "Pref: %s\n", bits);
  }

//  if (PWR_FLAGS(ch)        != PFDEF_PWRFLAGS) {
//    sprintascii(bits, PWR_FLAGS(ch));           fprintf(fl, "Pwrs: %s\n", bits);
//  }

  if (GET_FREEZE_LEV(ch)   != PFDEF_FREEZELEV)	fprintf(fl, "Frez: %d\n", GET_FREEZE_LEV(ch));
  if (GET_INVIS_LEV(ch)	   != PFDEF_INVISLEV)	fprintf(fl, "Invs: %d\n", GET_INVIS_LEV(ch));
  if (GET_LOADROOM(ch)	   != PFDEF_LOADROOM)	fprintf(fl, "Room: %d\n", GET_LOADROOM(ch));

  if (GET_BAD_PWS(ch)	   != PFDEF_BADPWS)	fprintf(fl, "Badp: %d\n", GET_BAD_PWS(ch));

  if (GET_STRENGTH(ch)              != PFDEF_STRENGTH)            fprintf(fl, "Stre : %d\n", GET_STRENGTH(ch));
  if (GET_STAMINA(ch)               != PFDEF_STAMINA)             fprintf(fl, "Stam : %d\n", GET_STAMINA(ch));
  if (GET_SPIRIT(ch)              != PFDEF_SPIRIT)            fprintf(fl, "Spir : %d\n", GET_SPIRIT(ch));
  if (GET_APPEARANCE(ch)            != PFDEF_APPEARANCE)          fprintf(fl, "Appe : %d\n", GET_APPEARANCE(ch));
  if (GET_WITS(ch)                  != PFDEF_WITS)                fprintf(fl, "Wits : %d\n", GET_WITS(ch));
  if (GET_INTELLIGENCE(ch)          != PFDEF_INTELLIGENCE)        fprintf(fl, "Inte : %d\n", GET_INTELLIGENCE(ch));
  if (GET_PERCEPTION(ch)            != PFDEF_PERCEPTION)          fprintf(fl, "Perc : %d\n", GET_PERCEPTION(ch));
  if (GET_AGILITY(ch)               != PFDEF_AGILITY)             fprintf(fl, "Agil : %d\n", GET_AGILITY(ch));
  if (GET_SPEED(ch)            != PFDEF_SPEED)          fprintf(fl, "Sped : %d\n", GET_SPEED(ch));


  if (GET_COURAGE(ch)            != PFDEF_COURAGE)          fprintf(fl, "Cour : %d\n", GET_COURAGE(ch));
  if (GET_SELFCONTROL(ch)        != PFDEF_SELFCONTROL)      fprintf(fl, "Self : %d\n", GET_SELFCONTROL(ch));
  if (GET_CONSCIENCE(ch)         != PFDEF_CONSCIENCE)       fprintf(fl, "Cons : %d\n", GET_CONSCIENCE(ch));
  if (GET_WILLPOWER(ch)          != PFDEF_WILLPOWER)        fprintf(fl, "Will : %d\n", GET_WILLPOWER(ch));
  if (GET_USEDWILLPOWER(ch)      != PFDEF_USEDWILLPOWER)    fprintf(fl, "Udwp : %d\n", GET_USEDWILLPOWER(ch));

  if (GET_BACKGROUND_MENTOR(ch)     != PFDEF_MENTOR)           fprintf(fl, "Ment : %d\n", GET_BACKGROUND_MENTOR(ch));
  if (GET_BACKGROUND_CRONIES(ch)     != PFDEF_CRONIES)           fprintf(fl, "Cron : %d\n", GET_BACKGROUND_CRONIES(ch));
  if (GET_BACKGROUND_RESOURCES(ch)     != PFDEF_RESOURCES)           fprintf(fl, "Reso : %d\n", GET_BACKGROUND_RESOURCES(ch));
  if (GET_BACKGROUND_ALLIES(ch)     != PFDEF_ALLIES)           fprintf(fl, "Alli : %d\n", GET_BACKGROUND_ALLIES(ch));
  if (GET_BACKGROUND_SPACESHIP(ch)     != PFDEF_SPACESHIP)           fprintf(fl, "Spas : %d\n", GET_BACKGROUND_SPACESHIP(ch));
  if (GET_BACKGROUND_DOJO(ch)     != PFDEF_DOJO)           fprintf(fl, "Dojo : %d\n", GET_BACKGROUND_DOJO(ch));
  if (GET_BACKGROUND_RANK(ch)     != PFDEF_RANK)           fprintf(fl, "Rank : %d\n", GET_BACKGROUND_RANK(ch));
  if (GET_BACKGROUND_RENOWN(ch)     != PFDEF_RENOWN)           fprintf(fl, "Reno : %d\n", GET_BACKGROUND_RENOWN(ch));
  if (GET_BACKGROUND_BLOODLINE(ch)     != PFDEF_BLOODLINE)           fprintf(fl, "Bloo : %d\n", GET_BACKGROUND_BLOODLINE(ch));


  if (GET_ABIL_ALERTNESS(ch)               != PFDEF_ALERTNESS)             fprintf(fl, "Aler : %d\n", GET_ABIL_ALERTNESS(ch));  
  if (GET_ABIL_ACADEMICS(ch)               != PFDEF_ACADEMICS)             fprintf(fl, "Acad : %d\n", GET_ABIL_ACADEMICS(ch));
  if (GET_ABIL_ATHLETICS(ch)               != PFDEF_ATHLETICS)             fprintf(fl, "Athl : %d\n", GET_ABIL_ATHLETICS(ch));
  if (GET_ABIL_FIREARMS(ch)               != PFDEF_FIREARMS)             fprintf(fl, "Fire : %d\n", GET_ABIL_FIREARMS(ch));
  if (GET_ABIL_COMPUTER(ch)               != PFDEF_COMPUTER)             fprintf(fl, "Comp : %d\n", GET_ABIL_COMPUTER(ch));
  if (GET_ABIL_INVESTIGATION(ch)               != PFDEF_INVESTIGATION)             fprintf(fl, "Inve : %d\n", GET_ABIL_INVESTIGATION(ch));
  if (GET_ABIL_DODGE(ch)               != PFDEF_DODGE)             fprintf(fl, "Dodg : %d\n", GET_ABIL_DODGE(ch));
  if (GET_ABIL_MELEE(ch)                != PFDEF_MELEE)              fprintf(fl, "Mele : %d\n", GET_ABIL_MELEE(ch));
  if (GET_ABIL_MEDICINE(ch)             != PFDEF_MEDICINE)           fprintf(fl, "Medi : %d\n", GET_ABIL_MEDICINE(ch));
  if (GET_ABIL_INTIMIDATION(ch)         != PFDEF_INTIMIDATION)       fprintf(fl, "Inti : %d\n", GET_ABIL_INTIMIDATION(ch));
  if (GET_ABIL_LEADERSHIP(ch)           != PFDEF_LEADERSHIP)         fprintf(fl, "Ledr : %d\n", GET_ABIL_LEADERSHIP(ch));
  if (GET_ABIL_PILOT(ch)                != PFDEF_PILOT)              fprintf(fl, "Pilo : %d\n", GET_ABIL_PILOT(ch));
  if (GET_ABIL_STEALTH(ch)              != PFDEF_STEALTH)            fprintf(fl, "Stea : %d\n", GET_ABIL_STEALTH(ch));
  if (GET_ABIL_SUBTERFUGE(ch)           != PFDEF_SUBTERFUGE)         fprintf(fl, "Sbtr : %d\n", GET_ABIL_SUBTERFUGE(ch));
  if (GET_ABIL_SCIENCE(ch)              != PFDEF_SCIENCE)            fprintf(fl, "Scie : %d\n", GET_ABIL_SCIENCE(ch));
  if (GET_ABIL_AURA(ch)              != PFDEF_AURASKILL)            fprintf(fl, "Aurs : %d\n", GET_ABIL_AURA(ch));
  if (GET_ABIL_BLOCK(ch)              != PFDEF_BLOCK)            fprintf(fl, "Bloc : %d\n", GET_ABIL_BLOCK(ch));
  if (GET_ABIL_GALACTICLORE(ch)              != PFDEF_GALACTICLORE)            fprintf(fl, "Galr : %d\n", GET_ABIL_GALACTICLORE(ch));
  if (GET_ABIL_KICONTROL(ch)              != PFDEF_KICONTROL)            fprintf(fl, "Kico : %d\n", GET_ABIL_KICONTROL(ch));
  if (GET_ABIL_KIKNOWLEDGE(ch)              != PFDEF_KIKNOWLEDGE)            fprintf(fl, "Kikn : %d\n", GET_ABIL_KIKNOWLEDGE(ch));
  if (GET_ABIL_MARTIALARTS(ch)              != PFDEF_MARTIALARTS)            fprintf(fl, "Mart : %d\n", GET_ABIL_MARTIALARTS(ch));
  if (GET_ABIL_MEDITATE(ch)              != PFDEF_MEDITATE)            fprintf(fl, "Medt : %d\n", GET_ABIL_MEDITATE(ch));
  if (GET_ABIL_REFLECT(ch)              != PFDEF_REFLECT)            fprintf(fl, "Refl : %d\n", GET_ABIL_REFLECT(ch));
  if (GET_ABIL_COUNTER(ch)              != PFDEF_COUNTER)            fprintf(fl, "Coun : %d\n", GET_ABIL_COUNTER(ch));
  if (GET_ABIL_SPACECRAFT(ch)              != PFDEF_SPACECRAFT)            fprintf(fl, "Spac : %d\n", GET_ABIL_SPACECRAFT(ch)); 
  if (GET_SPIRITPOINTS(ch)              != PFDEF_SPIRITPOINTS)            fprintf(fl, "Sppt : %d\n", GET_SPIRITPOINTS(ch));
  if (GET_ACTIONPOINTS(ch)              != PFDEF_ACTIONPOINTS)            fprintf(fl, "Acpt : %d\n", GET_ACTIONPOINTS(ch));
  if (GET_ABIL_TRAINING(ch)              != PFDEF_TRAINING)            fprintf(fl, "Trai : %d\n", GET_ABIL_TRAINING(ch));
  if (GET_CREATIONPOINTS(ch)              != PFDEF_CREATIONPOINTS)            fprintf(fl, "Crpt : %d\n", GET_CREATIONPOINTS(ch));
  if (GET_ABILPOINTS(ch)              != PFDEF_ABILPOINTS)            fprintf(fl, "Abpt : %d\n", GET_ABILPOINTS(ch));
  if (GET_BGPOINTS(ch)                != PFDEF_BGPOINTS)              fprintf(fl, "Bgpt : %d\n", GET_BGPOINTS(ch));
  if (GET_VOTES(ch)   		        != PFDEF_VOTES)         fprintf(fl, "Vote : %d\n", GET_VOTES(ch));

/*
  if (GET_STRCOUNTER(ch)              != PFDEF_STRCOUNTER)            fprintf(fl, "Strc : %d\n", GET_STRCOUNTER(ch));
  if (GET_SPDCOUNTER(ch)              != PFDEF_SPDCOUNTER)            fprintf(fl, "Spdc : %d\n", GET_SPRCOUNTER(ch));
  if (GET_STMCOUNTER(ch)              != PFDEF_STMCOUNTER)            fprintf(fl, "Stmc : %d\n", GET_STMCOUNTER(ch));
  if (GET_SPRCOUNTER(ch)              != PFDEF_SPRCOUNTER)            fprintf(fl, "Sprc : %d\n", GET_SPRCOUNTER(ch));
  if (GET_WITSCOUNTER(ch)             != PFDEF_WITSCOUNTER)           fprintf(fl, "Witc : %d\n", GET_WITSCOUNTER(ch));
  if (GET_PERCOUNTER(ch)              != PFDEF_PERCOUNTER)            fprintf(fl, "Perc : %d\n", GET_PERCOUNTER(ch));
  if (GET_AGICOUNTER(ch)              != PFDEF_AGICOUNTER)            fprintf(fl, "Agic : %d\n", GET_AGICOUNTER(ch));
*/
  if (GET_POWERLEVEL(ch)  != PFDEF_POWERLEVEL)            fprintf(fl, "Powr : %d\n", GET_POWERLEVEL(ch));
  if (GET_CURRENTPL(ch)  != PFDEF_CURRENTPL)            fprintf(fl, "Cupl : %d\n", GET_CURRENTPL(ch));
  if (GET_KI(ch)          != PFDEF_KI)                    fprintf(fl, "Kiii : %d\n", GET_KI(ch));
  if (GET_CURRENTKI(ch)   != PFDEF_CURRENTKI)             fprintf(fl, "Kicu : %d\n", GET_CURRENTKI(ch));

  if (GET_EXP(ch)	   != PFDEF_EXP)	fprintf(fl, "Exp : %d\n", GET_EXP(ch));
  if (GET_OLC_ZONE(ch)     != PFDEF_OLC)        fprintf(fl, "Olc : %d\n", GET_OLC_ZONE(ch));
  if (GET_PAGE_LENGTH(ch)  != PFDEF_PAGELENGTH) fprintf(fl, "Page: %d\n", GET_PAGE_LENGTH(ch));

  /* Save skills */
  if (GET_LEVEL(ch) < LVL_IMMORT) {
    fprintf(fl, "Skil:\n");
    for (i = 1; i <= MAX_SKILLS; i++) {
     if (GET_SKILL(ch, i))
	fprintf(fl, "%d %d\n", i, GET_SKILL(ch, i));
    }
    fprintf(fl, "0 0\n");
  }

  /* Save affects */
  if (tmp_aff[0].type > 0) {
    fprintf(fl, "Affs:\n");
    for (i = 0; i < MAX_AFFECT; i++) {
      aff = &tmp_aff[i];
      if (aff->type)
	fprintf(fl, "%d %d %d %d %d\n", aff->type, aff->duration,
	  aff->modifier, aff->location, (int)aff->bitvector);
    }
    fprintf(fl, "0 0 0 0 0\n");
  }

  fclose(fl);

  /* more char_to_store code to restore affects */

  /* add spell and eq affections back in now */
  for (i = 0; i < MAX_AFFECT; i++) {
    if (tmp_aff[i].type)
      affect_to_char(ch, &tmp_aff[i]);
  }

  for (i = 0; i < NUM_WEARS; i++) {
    if (char_eq[i])
#ifndef NO_EXTRANEOUS_TRIGGERS
        if (wear_otrigger(char_eq[i], ch, i))
#endif
    equip_char(ch, char_eq[i], i);
#ifndef NO_EXTRANEOUS_TRIGGERS
          else
          obj_to_char(char_eq[i], ch);
#endif
  }

  /* end char_to_store code */
 
  if ((id = get_ptable_by_name(GET_NAME(ch))) < 0)
    return;

  /* update the player in the player index */
  if (player_table[id].level != GET_LEVEL(ch)) {
    save_index = TRUE;
    player_table[id].level = GET_LEVEL(ch);
  }
  if (player_table[id].last != ch->player.time.logon) {
    save_index = TRUE;
    player_table[id].last = ch->player.time.logon;
  }
  i = player_table[id].flags;
  if (PLR_FLAGGED(ch, PLR_DELETED))
    SET_BIT(player_table[id].flags, PINDEX_DELETED);
  else
    REMOVE_BIT(player_table[id].flags, PINDEX_DELETED);
  if (PLR_FLAGGED(ch, PLR_NODELETE) || PLR_FLAGGED(ch, PLR_CRYO))
    SET_BIT(player_table[id].flags, PINDEX_NODELETE);
  else
    REMOVE_BIT(player_table[id].flags, PINDEX_NODELETE);

  if (PLR_FLAGGED(ch, PLR_FROZEN) || PLR_FLAGGED(ch, PLR_NOWIZLIST))
    SET_BIT(player_table[id].flags, PINDEX_NOWIZLIST);
  else
    REMOVE_BIT(player_table[id].flags, PINDEX_NOWIZLIST);

  if (player_table[id].flags != i || save_index)
    save_player_index();
}



void save_etext(struct char_data *ch)
{
/* this will be really cool soon */
}


/* Separate a 4-character id tag from the data it precedes */
void tag_argument(char *argument, char *tag)
{
  char *tmp = argument, *ttag = tag, *wrt = argument;
  int i;

  for (i = 0; i < 4; i++)
    *(ttag++) = *(tmp++);
  *ttag = '\0';
  
  while (*tmp == ':' || *tmp == ' ')
    tmp++;

  while (*tmp)
    *(wrt++) = *(tmp++);
  *wrt = '\0';
}

/*************************************************************************
*  stuff related to the player file cleanup system			 *
*************************************************************************/

/*
 * remove_player() removes all files associated with a player who is
 * self-deleted, deleted by an immortal, or deleted by the auto-wipe
 * system (if enabled).
 */ 
void remove_player(int pfilepos)
{
  char fname[40];
  int i;

  if (!*player_table[pfilepos].name)
    return;

  /* Unlink all player-owned files */
  for (i = 0; i < MAX_FILES; i++) {
    if (get_filename(fname, sizeof(fname), i, player_table[pfilepos].name))
      unlink(fname);
  }

  log("PCLEAN: %s Lev: %d Last: %s",
	player_table[pfilepos].name, player_table[pfilepos].level,
	asctime(localtime(&player_table[pfilepos].last)));
  player_table[pfilepos].name[0] = '\0';
  save_player_index();
}


void clean_pfiles(void)
{
  int i, ci;

  for (i = 0; i <= top_of_p_table; i++) {
    /*
     * We only want to go further if the player isn't protected
     * from deletion and hasn't already been deleted.
     */
    if (!IS_SET(player_table[i].flags, PINDEX_NODELETE) &&
        *player_table[i].name) {
      /*
       * If the player is already flagged for deletion, then go
       * ahead and get rid of him.
       */
      if (IS_SET(player_table[i].flags, PINDEX_DELETED)) {
	remove_player(i);
      } else {
        /*
         * Now we check to see if the player has overstayed his
         * welcome based on level.
         */
	for (ci = 0; pclean_criteria[ci].level > -1; ci++) {
	  if (player_table[i].level <= pclean_criteria[ci].level &&
	      ((time(0) - player_table[i].last) >
	       (pclean_criteria[ci].days * SECS_PER_REAL_DAY))) {
	    remove_player(i);
	    break;
	  }
	}
	/*
         * If we got this far and the players hasn't been kicked out,
         * then he can stay a little while longer.
         */
      }
    }
  }
  /*
   * After everything is done, we should rebuild player_index and
   * remove the entries of the players that were just deleted.
   */
}

void load_affects(FILE *fl, struct char_data *ch)
{
  int num = 0, num2 = 0, num3 = 0, num4 = 0, num5 = 0, i;
  char line[MAX_INPUT_LENGTH + 1];
  struct affected_type af;

  i = 0;
  do {
    get_line(fl, line);
    sscanf(line, "%d %d %d %d %d", &num, &num2, &num3, &num4, &num5);
    if (num > 0) {
      af.type = num;
      af.duration = num2;
      af.modifier = num3;
      af.location = num4;
      af.bitvector = num5;
      affect_to_char(ch, &af);
      i++;
    }
  } while (num != 0);
}


void load_skills(FILE *fl, struct char_data *ch)
{
  int num = 0, num2 = 0;
  char line[MAX_INPUT_LENGTH + 1];

  do {
    get_line(fl, line);
    sscanf(line, "%d %d", &num, &num2);
      if (num != 0)
	GET_SKILL(ch, num) = num2;
  } while (num != 0);
}


void load_HMVS(struct char_data *ch, const char *line, int mode)
{
  int num = 0, num2 = 0;

  sscanf(line, "%d/%d", &num, &num2);

  switch (mode) {
  case LOAD_HIT:
    GET_HIT(ch) = num;
    GET_MAX_HIT(ch) = num2;
    break;

  case LOAD_MANA:
    GET_MANA(ch) = num;
    GET_MAX_MANA(ch) = num2;
    break;

  case LOAD_MOVE:
    GET_MOVE(ch) = num;
    GET_MAX_MOVE(ch) = num2;
    break;

  case LOAD_STRENGTH:
    ch->real_abils.strength = num;
    break;

  }
}
