1stMUD/corefiles/
1stMUD/gods/
1stMUD/player/
1stMUD/win32/
1stMUD/win32/ROM/
/**************************************************************************
*  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
*  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
*                                                                         *
*  Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael         *
*  Chastain, Michael Quan, and Mitchell Tse.                              *
*                                                                         *
*  In order to use any part of this Merc Diku Mud, you must comply with   *
*  both the original Diku license in 'license.doc' as well the Merc       *
*  license in 'license.txt'.  In particular, you may not remove either of *
*  these copyright notices.                                               *
*                                                                         *
*  Much time and thought has gone into this software and you are          *
*  benefiting.  We hope that you share your changes too.  What goes       *
*  around, comes around.                                                  *
***************************************************************************
*       ROM 2.4 is copyright 1993-1998 Russ Taylor                        *
*       ROM has been brought to you by the ROM consortium                 *
*           Russ Taylor (rtaylor@hypercube.org)                           *
*           Gabrielle Taylor (gtaylor@hypercube.org)                      *
*           Brian Moore (zump@rom.org)                                    *
*       By using this code, you have agreed to follow the terms of the    *
*       ROM license, in the file Rom24/doc/rom.license                    *
***************************************************************************
*       1stMUD ROM Derivative (c) 2001-2002 by Ryan Jennings              *
*            http://1stmud.dlmud.com/  <r-jenn@shaw.ca>                   *
***************************************************************************/
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "tables.h"
#include "lookup.h"
#include "interp.h"
#include "olc.h"
#include "recycle.h"
#include "db.h"

struct savetable_type
{
	char *field;
	int type_field;
	void *puntero_field;
	const void *argument;
	const void *argument2;
};

#define FIELD_STRING			0
#define FIELD_FUNCION_INT_TO_STR	1
#define FIELD_LONG_ARRAY        2
#define FIELD_FLAGSTRING		3
#define FIELD_INT			4
#define FIELD_FLAGVECTOR		5
#define FIELD_BOOL			6
#define FIELD_INT_ARRAY		7
#define FIELD_STRING_ARRAY		8
#define FIELD_INT_FLAGSTRING    9
#define FIELD_BOOL_ARRAY		10
#define FIELD_INUTIL			11
#define FIELD_INT_ALLOC_ARRAY   12
#define FIELD_LONG              13
#define FIELD_STRING_ARRAY_NULL 14

typedef char *STR_FUNC (void *);
typedef bool STR_READ_FUNC (void *, const char *);

CMD_DATA cmd;
SKILL_DATA sk;
RACE_DATA race;
GROUP_DATA grp;
CLASS_DATA cls;
SOCIAL_DATA soc;
CLAN_DATA clan;
STAT_DATA stat;
BAN_DATA ban;

const char *do_fun_name (DO_FUN *);
DO_FUN *do_fun_lookup (const char *);

const char *skill_gsn_name (int *);
int *gsn_lookup (const char *);

const char *spell_fun_name (SPELL_FUN *);
SPELL_FUN *spell_lookup (const char *);

const char *do_fun_str (void *temp)
{
	DO_FUN **fun = (DO_FUN **) temp;

	return do_fun_name (*fun);
}

const char *position_str (void *temp)
{
	int *flags = (int *) temp;

	return position_table[*flags].name;
}

const char *size_str (void *temp)
{
	int *size = (int *) temp;

	return size_table[UMAX (0, *size)].name;
}

const char *race_str (void *temp)
{
	int *raza = (int *) temp;

	return race_table[*raza].name;
}

const char *pgsn_str (void *temp)
{
	int **pgsn = (int **) temp;

	return skill_gsn_name (*pgsn);
}

const char *spell_fun_str (void *temp)
{
	SPELL_FUN **spfun = (SPELL_FUN **) temp;

	return spell_fun_name (*spfun);
}

bool do_fun_read (void *temp, char *arg)
{
	DO_FUN **fun = (DO_FUN **) temp;

	*fun = do_fun_lookup (arg);

	return TRUE;
}

bool position_read (void *temp, char *arg)
{
	int *posic = (int *) temp;
	int ffg = position_lookup (arg);

	*posic = UMAX (0, ffg);

	if (ffg == -1)
		return FALSE;
	else
		return TRUE;
}

bool size_read (void *temp, char *arg)
{
	int *size = (int *) temp;
	int ffg = size_lookup (arg);

	*size = UMAX (0, ffg);

	if (ffg == -1)
		return FALSE;
	else
		return TRUE;
}

bool pgsn_read (void *temp, char *arg)
{
	int **pgsn = (int **) temp;
	int *blah = gsn_lookup (arg);

	*pgsn = blah;

	return !str_cmp (arg, "") || blah != NULL;
}

bool spell_fun_read (void *temp, char *arg)
{
	SPELL_FUN **spfun = (SPELL_FUN **) temp;
	SPELL_FUN *blah = spell_lookup (arg);

	*spfun = blah;

	return !str_cmp (arg, "") || blah != NULL;
}

const struct savetable_type cmdsavetable[] = {
	{"name", FIELD_STRING, (void *) &cmd.name, NULL, NULL},

	{"do_fun", FIELD_FUNCION_INT_TO_STR, (void *) &cmd.do_fun, (const void *) do_fun_str,
	 (const void *) do_fun_read},
	{"position", FIELD_FUNCION_INT_TO_STR, (void *) &cmd.position,
	 (const void *) position_str, (const void *) position_read},
	{"level", FIELD_INT, (void *) &cmd.level, NULL, NULL},

	{"log", FIELD_FLAGSTRING, (void *) &cmd.log, (const void *) log_flags,
	 NULL},
	{"show", FIELD_BOOL, (void *) &cmd.show, NULL, NULL},
	{NULL, 0, NULL, NULL, NULL}
};

const struct savetable_type skillsavetable[] = {
	{"name", FIELD_STRING, (void *) &sk.name, NULL, NULL},

	{"levels", FIELD_INT_ALLOC_ARRAY, (void *) &sk.skill_level,
	 (const void *) &maxClass, (const void *) (LEVEL_IMMORTAL + 1)},
	{"ratings", FIELD_INT_ALLOC_ARRAY, (void *) &sk.rating,
	 (const void *) &maxClass, (const void *) 0},
	{"spell_fun", FIELD_FUNCION_INT_TO_STR, (void *) &sk.spell_fun,
	 (const void *) spell_fun_str, (const void *) spell_fun_read},

	{"target", FIELD_INT_FLAGSTRING, (void *) &sk.target,
	 (const void *) target_flags, NULL},

	{"minimum_position", FIELD_FUNCION_INT_TO_STR,

	 (void *) &sk.minimum_position, (const void *) position_str,
	 (const void *) position_read},
	{"pgsn", FIELD_FUNCION_INT_TO_STR, (void *) &sk.pgsn,
	 (const void *) pgsn_str,
	 (const void *) pgsn_read},
	{"min_mana", FIELD_INT, (void *) &sk.min_mana, NULL, NULL},
	{"beats", FIELD_INT, (void *) &sk.beats, NULL, NULL},
	{"noun_damage", FIELD_STRING, (void *) &sk.noun_damage, NULL, NULL},
	{"msg_off", FIELD_STRING, (void *) &sk.msg_off, NULL, NULL},
	{"msg_obj", FIELD_STRING, (void *) &sk.msg_obj, NULL, NULL},
	{NULL, 0, NULL, NULL, NULL}
};

const struct savetable_type racesavetable[] = {
	{"race", FIELD_STRING, (void *) &race.name, NULL, NULL},
	{"pc", FIELD_BOOL, (void *) &race.pc_race, NULL, NULL},
	{"act", FIELD_FLAGVECTOR, (void *) &race.act, NULL, NULL},
	{"aff", FIELD_FLAGVECTOR, (void *) &race.aff, NULL, NULL},
	{"off", FIELD_FLAGVECTOR, (void *) &race.off, NULL, NULL},
	{"imm", FIELD_FLAGVECTOR, (void *) &race.imm, NULL, NULL},
	{"res", FIELD_FLAGVECTOR, (void *) &race.res, NULL, NULL},
	{"vuln", FIELD_FLAGVECTOR, (void *) &race.vuln, NULL, NULL},
	{"form", FIELD_FLAGVECTOR, (void *) &race.form, NULL, NULL},
	{"parts", FIELD_FLAGVECTOR, (void *) &race.parts, NULL, NULL},
	{"who", FIELD_STRING, (void *) &race.who_name, NULL, NULL},
	{"points", FIELD_INT, (void *) &race.points, NULL, NULL},

	{"classx", FIELD_INT_ALLOC_ARRAY, (void *) &race.class_mult,
	 (const void *) &maxClass, (const void *) 100},
	{"skills", FIELD_STRING_ARRAY_NULL, (void *) &race.skills,
	 (const void *) 5, NULL},

	{"stats", FIELD_INT_ARRAY, (void *) &race.stats, (const void *) MAX_STATS,
	 (const void *) 13},

	{"mstats", FIELD_INT_ARRAY, (void *) &race.max_stats,
	 (const void *) MAX_STATS, (const void *) 25},

	{"size", FIELD_FUNCION_INT_TO_STR, (void *) &race.size, (const void *) size_str,
	 (const void *) size_read},
	{NULL, 0, NULL, NULL, NULL}
};

const struct savetable_type groupsavetable[] = {
	{"name", FIELD_STRING, (void *) &grp.name, NULL, NULL},
	{"ratings", FIELD_INT_ALLOC_ARRAY, (void *) &grp.rating,
	 (const void *) &maxClass, (const void *) 0},
	{"spells", FIELD_STRING_ARRAY_NULL, (void *) &grp.spells,
	 (const void *) MAX_IN_GROUP, NULL},
	{NULL, 0, NULL, NULL, NULL}
};

const struct savetable_type classsavetable[] = {
	{"name", FIELD_STRING, (void *) &cls.name, NULL, NULL},
	{"whoname", FIELD_STRING, (void *) &cls.who_name, NULL, NULL},
	{"prime", FIELD_INT, (void *) &cls.attr_prime, NULL, NULL},
	{"weapon", FIELD_LONG, (void *) &cls.weapon, NULL, NULL},

	{"guild", FIELD_LONG_ARRAY, (void *) &cls.guild,
	 (const void *) MAX_GUILD, NULL},
	{"adept", FIELD_INT, (void *) &cls.skill_adept, NULL, NULL},
	{"thac0", FIELD_INT, (void *) &cls.thac0_00, NULL, NULL},
	{"thac32", FIELD_INT, (void *) &cls.thac0_32, NULL, NULL},
	{"minhp", FIELD_INT, (void *) &cls.hp_min, NULL, NULL},
	{"maxhp", FIELD_INT, (void *) &cls.hp_max, NULL, NULL},
	{"fmana", FIELD_BOOL, (void *) &cls.fMana, NULL, NULL},
	{"basegrp", FIELD_STRING, (void *) &cls.base_group, NULL, NULL},
	{"defaultgrp", FIELD_STRING, (void *) &cls.default_group, NULL, NULL},
	{NULL, 0, NULL, NULL, NULL}
};

const struct savetable_type socialsavetable[] = {
	{"name", FIELD_STRING, (void *) &soc.name, NULL, NULL},
	{"cnoarg", FIELD_STRING, (void *) &soc.char_no_arg, NULL, NULL},
	{"onoarg", FIELD_STRING, (void *) &soc.others_no_arg, NULL, NULL},
	{"cfound", FIELD_STRING, (void *) &soc.char_found, NULL, NULL},
	{"ofound", FIELD_STRING, (void *) &soc.others_found, NULL, NULL},
	{"vfound", FIELD_STRING, (void *) &soc.vict_found, NULL, NULL},
	{"cnotfound", FIELD_STRING, (void *) &soc.char_not_found, NULL, NULL},
	{"cauto", FIELD_STRING, (void *) &soc.char_auto, NULL, NULL},
	{"oauto", FIELD_STRING, (void *) &soc.others_auto, NULL, NULL},
	{NULL, 0, NULL, NULL, NULL}
};

const struct savetable_type clansavetable[] = {
	{"name", FIELD_STRING, (void *) &clan.name, NULL, NULL},
	{"whoname", FIELD_STRING, (void *) &clan.who_name, NULL, NULL},
	{"hall", FIELD_LONG, (void *) &clan.hall, NULL, NULL},
	{"indep", FIELD_BOOL, (void *) &clan.independent, NULL, NULL},
	{NULL, 0, NULL, NULL, NULL}
};

const struct savetable_type statsavetable[] = {
	{"name", FIELD_STRING, (void *) &stat.name, NULL, NULL},

	{"stats", FIELD_LONG_ARRAY, (void *) &stat.gamestat,
	 (const void *) MAX_GAMESTAT, (const void *) 0},
	{NULL, 0, NULL, NULL, NULL}
};

const struct savetable_type bansavetable[] = {
	{"name", FIELD_STRING, (void *) &ban.name, NULL, NULL},
	{"level", FIELD_INT, (void *) &ban.level, NULL, NULL},
	{"flags", FIELD_FLAGVECTOR, (void *) &ban.ban_flags, NULL, NULL},
	{NULL, 0, NULL, NULL, NULL}
};

void load_struct (FILE * fp, void *typebase,
				  const struct savetable_type *table, void *puntero)
{
	const char *word;
	const struct savetable_type *temp;
	flag_t *pentero;
	const char **pstring;
	const char *string;
	int *pint;
	int **array;
	long *plong;
	STR_READ_FUNC *function;
	struct flag_type *flagtable;
	bool found = FALSE;
	bool *pbool;
	int cnt = 0, i;

	while (str_cmp ((word = fread_word (fp)), "#END"))
	{
		for (temp = table; !IS_NULLSTR (temp->field); temp++)
		{
			if (!str_cmp (word, temp->field))
			{
				switch (temp->type_field)
				{
				case FIELD_STRING:
					pstring =
						(const char **) ((int) temp->puntero_field -
										 (int) typebase + (int) puntero);
					*pstring = fread_string (fp);
					found = TRUE, cnt++;
					break;

				case FIELD_INT:
					pint =
						(int *) ((int) temp->puntero_field - (int) typebase +
								 (int) puntero);
					*pint = fread_number (fp);
					found = TRUE, cnt++;
					break;

				case FIELD_LONG:
					plong =
						(long *) ((int) temp->puntero_field - (int) typebase +
								  (int) puntero);
					*plong = fread_number (fp);
					found = TRUE, cnt++;
					break;

				case FIELD_FUNCION_INT_TO_STR:
					function = (STR_READ_FUNC *) temp->argument2;
					string = fread_string (fp);
					pint =
						(int *) ((int) temp->puntero_field - (int) typebase +
								 (int) puntero);
					if ((*function) (pint, string) == FALSE)
						bugf ("field %s invalid, string %s",
							  temp->field, string);
					free_string (string);
					found = TRUE, cnt++;
					break;

				case FIELD_FLAGSTRING:
					flagtable = (struct flag_type *) temp->argument;
					pentero =
						(flag_t *) ((int) temp->puntero_field -
									(int) typebase + (int) puntero);
					string = fread_string (fp);
					if ((*pentero = flag_value (flagtable, string)) ==
						NO_FLAG)
						*pentero = 0;
					free_string (string);
					found = TRUE, cnt++;
					break;

				case FIELD_INT_FLAGSTRING:
					flagtable = (struct flag_type *) temp->argument;
					pint =
						(int *) ((int) temp->puntero_field - (int) typebase +
								 (int) puntero);
					string = fread_string (fp);
					if ((*pint = flag_value (flagtable, string)) == NO_FLAG)
						*pint = 0;
					free_string (string);
					found = TRUE, cnt++;
					break;

				case FIELD_FLAGVECTOR:
					pentero =
						(flag_t *) ((int) temp->puntero_field -
									(int) typebase + (int) puntero);
					*pentero = fread_flag (fp);
					found = TRUE, cnt++;
					break;

				case FIELD_BOOL:
					pbool =
						(bool *) ((int) temp->puntero_field - (int) typebase +
								  (int) puntero);
					string = fread_word (fp);
					*pbool = str_cmp (string, "FALSE") ? TRUE : FALSE;
					found = TRUE, cnt++;
					break;

				case FIELD_INT_ARRAY:
					pint =
						(int *) ((int) temp->puntero_field - (int) typebase +
								 (int) puntero);
					i = 0;
					while (str_cmp ((string = fread_word (fp)), "@"))
					{
						if (i == (int) temp->argument)
							bugf
								("field_shint_array %s has excess elements",
								 temp->field);
						else
							pint[i++] = (int) atoi (string);
					}
					while (i < (int) temp->argument)
						pint[i++] = (int) temp->argument2;
					found = TRUE, cnt++;
					break;

				case FIELD_INT_ALLOC_ARRAY:
					array =
						(int **) ((int) temp->puntero_field - (int) typebase +
								  (int) puntero);
					i = 0;
					alloc_mem (*array, int, *(int *) temp->argument);
					while (str_cmp ((string = fread_word (fp)), "@"))
					{
						if (i == *(int *) temp->argument)
							bugf
								("field_shint_array %s has excess elements",
								 temp->field);
						else
							(*array)[i++] = (int) atoi (string);
					}
					while (i < *(int *) temp->argument)
						(*array)[i++] = (int) temp->argument2;
					found = TRUE, cnt++;
					break;

				case FIELD_LONG_ARRAY:
					plong =
						(long *) ((int) temp->puntero_field - (int) typebase +
								  (int) puntero);
					i = 0;
					while (str_cmp ((string = fread_word (fp)), "@"))
					{
						if (i == (int) temp->argument)
							bugf
								("field_shint_array %s has excess elements",
								 temp->field);
						else
							plong[i++] = (long) atol (string);
					}
					while (i < (int) temp->argument)
						plong[i++] = (long) temp->argument2;
					found = TRUE, cnt++;
					break;

				case FIELD_STRING_ARRAY:
				case FIELD_STRING_ARRAY_NULL:
					pstring =
						(const char **) ((int) temp->puntero_field -
										 (int) typebase + (int) puntero);
					i = 0;
					while (str_cmp ((string = fread_string (fp)), "@"))
					{
						if (i == (int) temp->argument)
							bugf
								("field_string_array %s has excess elements.",
								 temp->field);
						else
							pstring[i++] = string;
					}
					while (i < (int) temp->argument)
						pstring[i++] = NULL;
					found = TRUE, cnt++;
					break;


				case FIELD_INUTIL:
					fread_to_eol (fp);
					found = TRUE, cnt++;
					break;

				case FIELD_BOOL_ARRAY:
					pbool =
						(bool *) ((int) temp->puntero_field - (int) typebase +
								  (int) puntero);
					i = 0;
					while (str_cmp ((string = fread_word (fp)), "@"))
					{
						if ((temp->argument != NULL
							 && i == (int) temp->argument)
							|| (temp->argument == NULL
								&& temp->argument2 != NULL
								&& i == *((int *) temp->argument2)))
							bugf
								("field_bool_array %s has excess elements",
								 temp->field);
						else
							pbool[i++] = (bool) atoi (string);
					}
					found = TRUE, cnt++;
					break;
				}				// switch
				if (found == TRUE)
					break;
			}					// if
		}						// for

		if (found == FALSE)
		{
			bugf ("word %s not found", word);
			fread_to_eol (fp);
		}
		else
			found = FALSE;
	}							// while
}

void save_struct (FILE * fp, void *typebase,
				  const struct savetable_type *table, void *puntero)
{
	const struct savetable_type *temp;
	const char **pstring;
	int *pint;
	long *plong;
	int **array;
	STR_FUNC *function;
	const char *string;
	flag_t *pentero;
	bool *pbool;
	const struct flag_type *flagtable;
	int cnt = 0, i;

	for (temp = table; !IS_NULLSTR (temp->field); temp++)
	{
		switch (temp->type_field)
		{
		default:
			bugf ("type_field %d invalid, field %s",
				  temp->type_field, temp->field);
			break;

		case FIELD_STRING:
			pstring =
				(const char **) ((int) temp->puntero_field - (int) typebase +
								 (int) puntero);
			fprintf (fp, "%s\t\t%s~\n", temp->field,
					 IS_NULLSTR (*pstring) ? "" : *pstring);
			break;

		case FIELD_INT:
			pint =
				(int *) ((int) temp->puntero_field - (int) typebase +
						 (int) puntero);
			fprintf (fp, "%s\t\t%d\n", temp->field, *pint);
			break;

		case FIELD_LONG:
			plong =
				(long *) ((int) temp->puntero_field - (int) typebase +
						  (int) puntero);
			fprintf (fp, "%s\t\t%ld\n", temp->field, *plong);
			break;

		case FIELD_FUNCION_INT_TO_STR:
			function = (STR_FUNC *) temp->argument;
			pint =
				(int *) ((int) temp->puntero_field - (int) typebase +
						 (int) puntero);
			string = (*function) ((void *) pint);
			fprintf (fp, "%s\t\t%s~\n", temp->field, string);
			break;

		case FIELD_FLAGSTRING:
			flagtable = (struct flag_type *) temp->argument;
			pentero =
				(flag_t *) ((int) temp->puntero_field - (int) typebase +
							(int) puntero);
			fprintf (fp, "%s\t\t%s~\n", temp->field,
					 flag_string (flagtable, *pentero));
			break;

		case FIELD_INT_FLAGSTRING:
			flagtable = (struct flag_type *) temp->argument;
			pint =
				(int *) ((int) temp->puntero_field - (int) typebase +
						 (int) puntero);
			fprintf (fp, "%s\t\t%s~\n", temp->field,
					 flag_string (flagtable, *pint));
			break;

		case FIELD_FLAGVECTOR:
			pentero =
				(flag_t *) ((int) temp->puntero_field - (int) typebase +
							(int) puntero);
			fprintf (fp, "%s\t\t%s\n", temp->field, fwrite_flags (*pentero));
			break;

		case FIELD_BOOL:
			pbool =
				(bool *) ((int) temp->puntero_field - (int) typebase +
						  (int) puntero);
			fprintf (fp, "%s\t\t%s\n", temp->field,
					 (*pbool == TRUE) ? "TRUE" : "FALSE");
			break;

		case FIELD_INT_ARRAY:
			pint =
				(int *) ((int) temp->puntero_field - (int) typebase +
						 (int) puntero);
			fprintf (fp, "%s\t\t", temp->field);
			for (i = 0; i < (int) temp->argument; i++)
				fprintf (fp, "%d ", pint[i]);
			fprintf (fp, "@\n");
			break;

		case FIELD_INT_ALLOC_ARRAY:
			array =
				(int **) ((int) temp->puntero_field - (int) typebase +
						  (int) puntero);
			fprintf (fp, "%s\t\t", temp->field);
			for (i = 0; i < *(int *) temp->argument; i++)
				fprintf (fp, "%d ", (*array)[i]);
			fprintf (fp, "@\n");
			break;

		case FIELD_LONG_ARRAY:
			plong =
				(long *) ((int) temp->puntero_field - (int) typebase +
						  (int) puntero);
			fprintf (fp, "%s\t\t", temp->field);
			for (i = 0; i < (int) temp->argument; i++)
				fprintf (fp, "%ld ", plong[i]);
			fprintf (fp, "@\n");
			break;

		case FIELD_STRING_ARRAY:
			pstring =
				(const char **) ((int) temp->puntero_field - (int) typebase +
								 (int) puntero);
			fprintf (fp, "%s\t\t", temp->field);
			for (i = 0; i < (int) temp->argument; i++)
				fprintf (fp, "%s~ ",
						 !IS_NULLSTR (pstring[i]) ? pstring[i] : "");
			fprintf (fp, "@~\n");
			break;

		case FIELD_STRING_ARRAY_NULL:
			pstring =
				(const char **) ((int) temp->puntero_field - (int) typebase +
								 (int) puntero);
			fprintf (fp, "%s\t\t", temp->field);
			for (i = 0; i < (int) temp->argument && !IS_NULLSTR (pstring[i]);
				 i++)
				fprintf (fp, "%s~ ",
						 !IS_NULLSTR (pstring[i]) ? pstring[i] : "");
			fprintf (fp, "@~\n");
			break;

		case FIELD_BOOL_ARRAY:
			pbool =
				(bool *) ((int) temp->puntero_field - (int) typebase +
						  (int) puntero);
			fprintf (fp, "%s\t\t", temp->field);
			for (i = 0;
				 i <
				 (temp->argument ? (int) temp->argument : *(int *) temp->
				  argument2); i++)
				fprintf (fp, "%d ", pbool[i] == TRUE ? 1 : 0);
			fprintf (fp, "@\n");
			break;

		case FIELD_INUTIL:
			break;
		}

		cnt++;
	}
};


void save_commands (void)
{
	FILE *fp;
	int i;
#if !defined(WIN32)
	const char *TEMPFILE = DATA_DIR "commands_tmp";

	fp = file_open (TEMPFILE, "w");
#else
	fp = file_open (COMMAND_FILE, "w");
#endif

	if (!fp)
	{
		perror ("save_commands");
		file_close (fp);
		return;
	}

	fprintf (fp, "%d\n\n", maxCommands);

	for (i = 0; i < maxCommands; ++i)
	{
		fprintf (fp, "#COMMAND\n");
		save_struct (fp, &cmd, cmdsavetable, &cmd_table[i]);
		fprintf (fp, "#END\n\n");
	}

	file_close (fp);
#if !defined(WIN32)
	rename (TEMPFILE, COMMAND_FILE);
#endif
}

void load_commands (void)
{
	FILE *fp;
	static CMD_DATA emptycmd;
	int i = 0, largo;
	const char *word;

	fp = file_open (COMMAND_FILE, "r");

	if (fp == NULL)
	{
		perror ("load_commands ");
		file_close (fp);
		return;
	}

	largo = fread_number (fp);

	maxCommands = largo;

	alloc_mem (cmd_table, CMD_DATA, largo + 1);

	for (i = 0; i <= largo; i++)
		cmd_table[i] = emptycmd;

	i = 0;

	while (TRUE)
	{
		word = fread_word (fp);

		if (str_cmp (word, "#COMMAND"))
		{
			bugf ("word %s", word);
			file_close (fp);
			return;
		}

		load_struct (fp, &cmd, cmdsavetable, &cmd_table[i++]);

		if (i == largo)
		{
			file_close (fp);
			cmd_table[i].name = str_dup (str_empty);
			return;
		}
	}
}

void save_skills (void)
{
	FILE *fp;
	int i;
#if !defined(WIN32)
	const char *TEMPFILE = DATA_DIR "skills_tmp";

	fp = file_open (TEMPFILE, "w");
#else
	fp = file_open (SKILL_FILE, "w");
#endif

	if (!fp)
	{
		bug ("save_skills: NULL fp", 0);
		file_close (fp);
		return;
	}

	fprintf (fp, "%d\n", maxSkill);

	for (i = 0; i < maxSkill; ++i)
	{
		fprintf (fp, "#SKILL\n");
		save_struct (fp, &sk, skillsavetable, &skill_table[i]);
		fprintf (fp, "#END\n\n");
	}

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

	file_close (fp);
#if !defined(WIN32)
	rename (TEMPFILE, SKILL_FILE);
#endif
}

void load_skills (void)
{
	FILE *fp;
	static SKILL_DATA skzero;
	int i = 0;
	const char *word;

	fp = file_open (SKILL_FILE, "r");

	if (!fp)
	{
		bug ("load_skills: Unable to open " SKILL_FILE " to load skills.", 0);
		exit (1);
	}

	fscanf (fp, "%d\n", &maxSkill);

	alloc_mem (skill_table, SKILL_DATA, maxSkill + 1);

	if (!skill_table)
	{
		bugf ("Error! Skill_table == NULL, MAX_SKILL : %d", maxSkill);
		exit (1);
	}

	for (;;)
	{
		word = fread_word (fp);

		if (!str_cmp (word, "#!"))
			break;

		if (str_cmp (word, "#SKILL"))
		{
			bugf ("word doesn't exist (%s)", word);
			exit (1);
		}

		if (i >= maxSkill)
		{
			bug ("load_skills: number greater than maxSkill", 0);
			exit (1);
		}

		skill_table[i] = skzero;
		load_struct (fp, &sk, skillsavetable, &skill_table[i++]);
	}

	skill_table[maxSkill].name = NULL;

	file_close (fp);
}

void save_races (void)
{
	FILE *fp;
	RACE_DATA *temp;
	int cnt = 0;
#if !defined(WIN32)
	const char *TEMPFILE = DATA_DIR "races_tmp";

	fp = file_open (TEMPFILE, "w");
#else
	fp = file_open (RACE_FILE, "w");
#endif

	if (!fp)
	{
		perror ("save_races : fopen");
		return;
	}

	for (temp = race_table; !IS_NULLSTR (temp->name); temp = temp++)
	{
		cnt++;
	}

	fprintf (fp, "%d\n", cnt);

	for (temp = race_table; !IS_NULLSTR (temp->name); temp = temp++)
	{
		fprintf (fp, "#RACE\n");
		save_struct (fp, &race, racesavetable, temp);
		fprintf (fp, "#END\n\n");
	}

	file_close (fp);

#if !defined(WIN32)
	rename (TEMPFILE, RACE_FILE);
#endif

}

void load_races (void)
{
	FILE *fp;
	const char *word;
	int i;

	fp = file_open (RACE_FILE, "r");

	if (!fp)
	{
		perror ("load_races");
		return;
	}

	maxRace = fread_number (fp);

	alloc_mem (race_table, RACE_DATA, maxRace + 1);

	i = 0;

	while (TRUE)
	{
		word = fread_word (fp);

		if (str_cmp (word, "#RACE"))
		{
			bugf ("word %s", word);
			file_close (fp);
			return;
		}

		load_struct (fp, &race, racesavetable, &race_table[i++]);

		if (i == maxRace)
		{
			file_close (fp);
			race_table[i].name = NULL;

			return;
		}
	}
}

void save_groups (void)
{
	FILE *fp;
	int i;
#if !defined(WIN32)
	const char *TEMPFILE = DATA_DIR "groups_tmp";

	fp = file_open (TEMPFILE, "w");
#else
	fp = file_open (GROUP_FILE, "w");
#endif

	if (!fp)
	{
		bug ("save_groups: NULL fp", 0);
		file_close (fp);
		return;
	}

	fprintf (fp, "%d\n", maxGroup);

	for (i = 0; i < maxGroup; ++i)
	{
		fprintf (fp, "#GROUP\n");
		save_struct (fp, &grp, groupsavetable, &group_table[i]);
		fprintf (fp, "#END\n\n");
	}

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

	file_close (fp);
#if !defined(WIN32)
	rename (TEMPFILE, GROUP_FILE);
#endif
}

void load_groups (void)
{
	FILE *fp;
	static GROUP_DATA grpzero;
	int i = 0;
	const char *word;

	fp = file_open (GROUP_FILE, "r");

	if (!fp)
	{
		bug ("load_groups: Unable to open " GROUP_FILE " to load groups.", 0);
		exit (1);
	}

	fscanf (fp, "%d\n", &maxGroup);

	alloc_mem (group_table, GROUP_DATA, maxGroup + 1);

	if (!group_table)
	{
		bugf ("Error! Group_table == NULL, MAX_GROUP : %d", maxGroup);
		exit (1);
	}

	for (;;)
	{
		word = fread_word (fp);

		if (!str_cmp (word, "#!"))
			break;

		if (str_cmp (word, "#GROUP"))
		{
			bugf ("word doesn't exist (%s)", word);
			exit (1);
		}

		if (i >= maxGroup)
		{
			bug ("load_groups: number greater than maxGroup", 0);
			exit (1);
		}

		group_table[i] = grpzero;
		load_struct (fp, &grp, groupsavetable, &group_table[i++]);
	}

	group_table[maxGroup].name = NULL;

	file_close (fp);
}

void save_classes (void)
{
	FILE *fp;
	int i;
#if !defined(WIN32)
	const char *TEMPFILE = DATA_DIR "class_tmp";

	fp = file_open (TEMPFILE, "w");
#else
	fp = file_open (CLASS_FILE, "w");
#endif

	if (!fp)
	{
		bug ("save_classes: NULL fp", 0);
		file_close (fp);
		return;
	}

	fprintf (fp, "%d\n", maxClass);

	for (i = 0; i < maxClass; ++i)
	{
		fprintf (fp, "#CLASS\n");
		save_struct (fp, &cls, classsavetable, &class_table[i]);
		fprintf (fp, "#END\n\n");
	}

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

	file_close (fp);
#if !defined(WIN32)
	rename (TEMPFILE, CLASS_FILE);
#endif
}

void load_classes (void)
{
	FILE *fp;
	static CLASS_DATA clszero;
	int i = 0;
	const char *word;

	fp = file_open (CLASS_FILE, "r");

	if (!fp)
	{
		bug ("load_classes: Unable to open " CLASS_FILE " to load classes.",
			 0);
		exit (1);
	}

	fscanf (fp, "%d\n", &maxClass);

	alloc_mem (class_table, CLASS_DATA, maxClass + 1);

	if (!class_table)
	{
		bugf ("Error! Class_table == NULL, MAX_CLASS : %d", maxClass);
		exit (1);
	}

	for (;;)
	{
		word = fread_word (fp);

		if (!str_cmp (word, "#!"))
			break;

		if (str_cmp (word, "#CLASS"))
		{
			bugf ("word doesn't exist (%s)", word);
			exit (1);
		}

		if (i >= maxClass)
		{
			bug ("load_classes: number greater than maxClass", 0);
			exit (1);
		}

		class_table[i] = clszero;
		load_struct (fp, &cls, classsavetable, &class_table[i++]);
	}

	class_table[maxClass].name = NULL;

	file_close (fp);
}

void save_social_table (void)
{
	FILE *fp;
	int i;
#if !defined(WIN32)
	const char *TEMPFILE = DATA_DIR "social_tmp";

	fp = file_open (TEMPFILE, "w");
#else
	fp = file_open (SOCIAL_FILE, "w");
#endif

	if (!fp)
	{
		bug ("save_socials: NULL fp", 0);
		file_close (fp);
		return;
	}

	fprintf (fp, "%d\n", maxSocial);

	for (i = 0; i < maxSocial; ++i)
	{
		fprintf (fp, "#SOCIAL\n");
		save_struct (fp, &soc, socialsavetable, &social_table[i]);
		fprintf (fp, "#END\n\n");
	}

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

	file_close (fp);
#if !defined(WIN32)
	rename (TEMPFILE, SOCIAL_FILE);
#endif
}

void load_social_table (void)
{
	FILE *fp;
	static SOCIAL_DATA socialzero;
	int i = 0;
	const char *word;

	fp = file_open (SOCIAL_FILE, "r");

	if (!fp)
	{
		bug ("load_socials: Unable to open " SOCIAL_FILE " to load socials.",
			 0);
		exit (1);
	}

	fscanf (fp, "%d\n", &maxSocial);

	alloc_mem (social_table, SOCIAL_DATA, maxSocial + 1);

	if (!social_table)
	{
		bugf ("Error! Social_table == NULL, MAX_SOCIAL : %d", maxSocial);
		exit (1);
	}

	for (;;)
	{
		word = fread_word (fp);

		if (!str_cmp (word, "#!"))
			break;

		if (str_cmp (word, "#SOCIAL"))
		{
			bugf ("word doesn't exist (%s)", word);
			exit (1);
		}

		if (i >= maxSocial)
		{
			bug ("load_socials: number greater than maxSocial", 0);
			exit (1);
		}

		social_table[i] = socialzero;
		load_struct (fp, &soc, socialsavetable, &social_table[i++]);
	}

	social_table[maxSocial].name = NULL;

	file_close (fp);
}

void save_clans (void)
{
	FILE *fp;
	int i;
#if !defined(WIN32)
	const char *TEMPFILE = DATA_DIR "clan_tmp";

	fp = file_open (TEMPFILE, "w");
#else
	fp = file_open (CLAN_FILE, "w");
#endif

	if (!fp)
	{
		bug ("save_clans: NULL fp", 0);
		file_close (fp);
		return;
	}

	fprintf (fp, "%d\n", maxClan);

	for (i = 0; i < maxClan; ++i)
	{
		fprintf (fp, "#CLAN\n");
		save_struct (fp, &clan, clansavetable, &clan_table[i]);
		fprintf (fp, "#END\n\n");
	}

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

	file_close (fp);
#if !defined(WIN32)
	rename (TEMPFILE, CLAN_FILE);
#endif
}

void load_clans (void)
{
	FILE *fp;
	static CLAN_DATA clanzero;
	int i = 0;
	const char *word;

	fp = file_open (CLAN_FILE, "r");

	if (!fp)
	{
		bug ("load_clans: Unable to open " CLAN_FILE " to load clans.", 0);
		exit (1);
	}

	fscanf (fp, "%d\n", &maxClan);

	alloc_mem (clan_table, CLAN_DATA, maxClan + 1);

	if (!clan_table)
	{
		bugf ("Error! Clan_table == NULL, MAX_CLAN : %d", maxClan);
		exit (1);
	}

	for (;;)
	{
		word = fread_word (fp);

		if (!str_cmp (word, "#!"))
			break;

		if (str_cmp (word, "#CLAN"))
		{
			bugf ("word doesn't exist (%s)", word);
			exit (1);
		}

		if (i >= maxClan)
		{
			bug ("load_clans: number greater than maxClan", 0);
			exit (1);
		}

		clan_table[i] = clanzero;
		load_struct (fp, &clan, clansavetable, &clan_table[i++]);
	}

	clan_table[maxClan].name = NULL;

	file_close (fp);
}

void save_statlist (void)
{
	STAT_DATA *pstat;
	FILE *fp;
#if !defined(WIN32)
	const char *TEMPFILE = DATA_DIR "stats_tmp";

	if ((fp = file_open (TEMPFILE, "w")) == NULL)
#else
	if ((fp = file_open (STAT_FILE, "w")) == NULL)
#endif
	{
		perror (STAT_FILE);
		file_close (fp);
		return;
	}

	for (pstat = stat_list; pstat != NULL; pstat = pstat->next)
	{
		fprintf (fp, "#STAT\n");
		save_struct (fp, &stat, statsavetable, pstat);
		fprintf (fp, "#END\n\n");
	}

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

	file_close (fp);

#if !defined(WIN32)
	rename (TEMPFILE, STAT_FILE);
#endif
}

void load_statlist (void)
{
	FILE *fp;
	STAT_DATA *pstat;
	const char *word;

	fp = file_open (STAT_FILE, "r");

	if (!fp)
		return;

	for (;;)
	{
		word = fread_word (fp);

		if (!str_cmp (word, "#!"))
			break;

		if (str_cmp (word, "#STAT"))
		{
			bugf ("word doesn't exist (%s)", word);
			exit (1);
		}

		pstat = new_stat_data ();
		load_struct (fp, &stat, statsavetable, pstat);
		pstat->next = stat_list;
		stat_list = pstat;
	}
	file_close (fp);
}


void save_bans (void)
{
	BAN_DATA *pban;
	FILE *fp;
#if !defined(WIN32)
	const char *TEMPFILE = DATA_DIR "ban_tmp";

	if ((fp = file_open (TEMPFILE, "w")) == NULL)
#else
	if ((fp = file_open (BAN_FILE, "w")) == NULL)
#endif
	{
		perror (BAN_FILE);
		file_close (fp);
		return;
	}

	for (pban = ban_list; pban != NULL; pban = pban->next)
	{
		fprintf (fp, "#BAN\n");
		save_struct (fp, &ban, bansavetable, pban);
		fprintf (fp, "#END\n\n");
	}

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

	file_close (fp);

#if !defined(WIN32)
	rename (TEMPFILE, BAN_FILE);
	return;
#endif
}

void load_bans (void)
{
	FILE *fp;
	BAN_DATA *pban;
	const char *word;

	fp = file_open (BAN_FILE, "r");

	if (!fp)
		return;

	for (;;)
	{
		word = fread_word (fp);

		if (!str_cmp (word, "#!"))
			break;

		if (str_cmp (word, "#BAN"))
		{
			bugf ("word doesn't exist (%s)", word);
			exit (1);
		}

		pban = new_ban ();
		load_struct (fp, &ban, bansavetable, pban);
		pban->next = ban_list;
		ban_list = pban;
	}
	file_close (fp);
}