SmaugWizard/Backup/
SmaugWizard/Backup/L/
SmaugWizard/Boards/
SmaugWizard/Building/
SmaugWizard/Corpses/
SmaugWizard/Councils/
SmaugWizard/Deity/
SmaugWizard/Gods/
SmaugWizard/MudProgs/
SmaugWizard/Player/L/
SmaugWizard/Src/
SmaugWizard/Src/res/
/****************************************************************************
 * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame      |				*
 * -----------------------------------------------------------|   \\._.//	*
 * SmaugWiz (C) 1998 by Russ Pillsbury (Windows NT version)   |   (0...0)	*
 * -----------------------------------------------------------|    ).:.(	*
 * SMAUG (C) 1994, 1995, 1996 by Derek Snider                 |    {o o}	*
 * -----------------------------------------------------------|   / ' ' \	*
 * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus,      |~'~.VxvxV.~'~*
 * Scryn, Swordbearer, Rennard, Tricops, and Gorog.           |				*
 * ------------------------------------------------------------------------ *
 * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael        *
 * Chastain, Michael Quan, and Mitchell Tse.                                *
 * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,          *
 * Michael Seifert, Hans Henrik Staerfeldt, Tom Madsen, and Katja Nyboe.    *
 * ------------------------------------------------------------------------ *
 *                           Deity handling module                          *
 ****************************************************************************/

// Put together by Rennard for Realms of Despair.  Brap on...

#include	"stdafx.h"
#include	"smaug.h"
#include	"Smaugx.h"
#include	"mobiles.h"
#include	"objects.h"
#include	"rooms.h"
#include	"races.h"
#include	"deity.h"
#include	"class.h"
#include	"SmaugWizDoc.h"
#include	"SmaugFiles.h"
#include	"descriptor.h"
#include	"character.h"
#include	"sysdata.h"

CDeityData		*first_deity;
CDeityData		*last_deity;

// local routines
BOOL	load_deity_file (const char *fname);
void	write_deity_list ();


// Get pointer to deity structure from deity name
CDeityData *get_deity (const char* name)
{
	CDeityData *deity;

	for (deity = first_deity; deity; deity = deity->GetNext ())
		if (!str_cmp (name, deity->GetName ()))
			return deity;
	return NULL;
}


void write_deity_list ()
{
	CDeityData	*tdeity;
	FILE		*fp;

	fclose (fpReserve);
	fp = fopen (FileTable.GetName (SM_DEITY_LIST), "w");
	if (!fp)
		bug ("FATAL: cannot open deity.lst for writing!\n\r", 0);
	else {
		for (tdeity = first_deity; tdeity; tdeity = tdeity->GetNext ())
			fprintf (fp, "%s\n", tdeity->GetName ());
		fprintf (fp, "$\n");
		fclose (fp);
	}
	fpReserve = fopen (FileTable.GetName (SM_NULL_FILE), "r");
}


// Save a deity's data to its data file
void save_deity (CDeityData *deity)
{
	FILE	*fp;

	if (!deity) {
		bug ("save_deity: null deity pointer!", 0);
		return;
	}

	if (! deity->IsValidName ()) {
		bug ("save_deity: Deity has no name", 0);
		return;
	}

	fclose (fpReserve);
	if (! (fp = fopen (FileTable.MakeDeityName (deity->GetName ()), "w"))) {
		bug ("save_deity: fopen", 0);
		perror (deity->GetName ());
	} else {
		fprintf (fp, "#DEITY\n");
		// Note: Filename is not needed since the deity name is used as
		// the filename in SmaugWiz, but left in for compatibility.
		fprintf (fp, "Filename		%s~\n",	deity->GetName ());
		fprintf (fp, "Name		%s~\n",	deity->GetName ());
		fprintf (fp, "Description	%s~\n",	deity->description);
		fprintf (fp, "Alignment		%d\n",	deity->alignment);
		fprintf (fp, "Worshippers	%d\n",	deity->worshippers);
		fprintf (fp, "Flee		%d\n",	deity->flee);
		fprintf (fp, "Flee_npcrace	%d\n",	deity->flee_npcrace);
		fprintf (fp, "Flee_npcfoe	%d\n",	deity->flee_npcfoe);
		fprintf (fp, "Kill		%d\n",	deity->kill);
		fprintf (fp, "Kill_npcrace	%d\n",	deity->kill_npcrace);
		fprintf (fp, "Kill_npcfoe	%d\n",	deity->kill_npcfoe);
		fprintf (fp, "Kill_magic	%d\n",	deity->kill_magic);
		fprintf (fp, "Sac		%d\n",	deity->sac);
		fprintf (fp, "Bury_corpse	%d\n",	deity->bury_corpse);
		fprintf (fp, "Aid_spell		%d\n",	deity->aid_spell);
		fprintf (fp, "Aid		%d\n",	deity->aid);
		fprintf (fp, "Steal		%d\n",	deity->steal);
		fprintf (fp, "Backstab		%d\n",	deity->backstab);
		fprintf (fp, "Die		%d\n",	deity->die);
		fprintf (fp, "Die_npcrace	%d\n",	deity->die_npcrace);
		fprintf (fp, "Die_npcfoe	%d\n",	deity->die_npcfoe);
		fprintf (fp, "Spell_aid		%d\n",	deity->spell_aid);
		fprintf (fp, "Dig_corpse	%d\n",	deity->dig_corpse);
		fprintf (fp, "Scorpse		%d\n",	deity->scorpse);
		fprintf (fp, "Savatar		%d\n",	deity->savatar);
		fprintf (fp, "Sdeityobj		%d\n",	deity->sdeityobj);
		fprintf (fp, "Srecall		%d\n",	deity->srecall);
		fprintf (fp, "Race		%d\n",	deity->GetRace ());
		fprintf (fp, "Class		%d\n",	deity->GetClass ());
		fprintf (fp, "Element		%d\n",	deity->element);
		fprintf (fp, "Sex		%d\n",	deity->sex);
		fprintf (fp, "Avatar		%d\n",	deity->avatar);
		fprintf (fp, "Deityobj		%d\n",	deity->deityobj);
		fprintf (fp, "Affected		%s\n",
			NCCP deity->m_Affected.PrintVector ());
		fprintf (fp, "Npcrace		%d\n",	deity->npcrace);
		fprintf (fp, "Npcfoe		%d\n",	deity->npcfoe);
		fprintf (fp, "Suscept		%d\n",	deity->suscept);
		fprintf (fp, "End\n\n");
		fprintf (fp, "#END\n");
		fclose (fp);
	}
	fpReserve = fopen (FileTable.GetName (SM_NULL_FILE), "r");
}


#if defined (KEY)
#undef KEY
#endif

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

// Read in actual deity data
void CDeityData::Read (FILE *fp)
{
	char	buf [MAX_STRING_LENGTH];
	char	*word, *pLine;
	BOOL	fMatch;

	for (;;) {
		fMatch = FALSE;
		if (! feof (fp)) {
			pLine = fread_line (fp);
			word = ParseWord (pLine);
		}
		else word = "End";

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

		  case 'A':
			if (! str_cmp (word, "Affected")) {
				m_Affected.Parse (pLine);
				fMatch = TRUE;
				break;
			}
			KEY ("Aid",			aid,			ParseNumber (pLine));
			KEY ("Aid_spell",	aid_spell,		ParseNumber (pLine));
			KEY ("Alignment",	alignment,		ParseNumber (pLine));
			KEY ("Avatar",		avatar,			ParseNumber (pLine));
			break;

		  case 'B':
			KEY ("Backstab",	backstab,		ParseNumber (pLine));
			KEY ("Bury_corpse",	bury_corpse,	ParseNumber (pLine));
			break;

		  case 'C':
			KEY ("Class",		m_Class,		ParseNumber (pLine));	
			break;

		  case 'D':
			KEY ("Deityobj",	deityobj,		ParseNumber (pLine));
			KEY ("Description",	description,	ParseString (pLine, fp));
			KEY ("Die",			die,			ParseNumber (pLine));
			KEY ("Die_npcrace",	die_npcrace,	ParseNumber (pLine));
			KEY ("Die_npcfoe",	die_npcfoe,		ParseNumber (pLine));
			KEY ("Dig_corpse",	dig_corpse,		ParseNumber (pLine));
			break;

		  case 'E':
			if (!str_cmp (word, "End")) {
				if (!GetName ())
					SetName (STRALLOC (""));
				if (!description)
					description = STRALLOC ("");
				return;
			}
			KEY ("Element",		element,		ParseNumber (pLine));
			break;

		  case 'F':
			// Filename not used for SmaugWiz, discard it.
			if (! str_cmp (word, "Filename")) {
				fMatch = TRUE;
			}
//			KEY ("Filename",	filename,		ParseStringNohash (pLine, fp));
			KEY ("Flee",		flee,			ParseNumber (pLine)); 
			KEY ("Flee_npcrace",flee_npcrace,	ParseNumber (pLine));
			KEY ("Flee_npcfoe",	flee_npcfoe,	ParseNumber (pLine));
			break;

		  case 'K':
			KEY ("Kill",		kill,			ParseNumber (pLine));
			KEY ("Kill_npcrace",kill_npcrace,	ParseNumber (pLine));
			KEY ("Kill_npcfoe",	kill_npcfoe,	ParseNumber (pLine));
			KEY ("Kill_magic",	kill_magic,		ParseNumber (pLine));
			break;

		  case 'N':
			KEY ("Name",		m_pName,	ParseString (pLine, fp));
			KEY ("Npcfoe",		npcfoe,		ParseNumber (pLine));
			KEY ("Npcrace",		npcrace,	ParseNumber (pLine));
			break;

		  case 'R':
			KEY ("Race",		m_Race,			ParseNumber (pLine));
			break;

		  case 'S':
			KEY ("Sac",			sac,			ParseNumber (pLine));
			KEY ("Savatar",		savatar,		ParseNumber (pLine));
			KEY ("Scorpse",		scorpse,		ParseNumber (pLine));
			KEY ("Sdeityobj",	sdeityobj,		ParseNumber (pLine));
			KEY ("Srecall",		srecall,		ParseNumber (pLine));
			KEY ("Sex",			sex,			ParseNumber (pLine));
			KEY ("Spell_aid",   spell_aid,		ParseNumber (pLine));
			KEY ("Steal",		steal,			ParseNumber (pLine));
			KEY ("Suscept",		suscept,		ParseNumber (pLine));
			break;

		  case 'W':
			KEY ("Worshippers",	worshippers,	ParseNumber (pLine));
			break;
		}

		if (!fMatch) {
			sprintf (buf, "CDeityData::Read: no match: %s", word);
			bug (buf, 0);
		}
	}
}


// Load a deity file
BOOL load_deity_file (const char *fname)
{
	CDeityData	*deity;
	FILE		*fp;
	BOOL		found;
	char		*pLine;

	found = FALSE;

	if ((fp = fopen (FileTable.MakeDeityName (fname), "r"))) {
		for (;;) {
			char	letter;
			char	*word;

			pLine = fread_line (fp);
			letter = *pLine++;

			if (letter == '*')
				continue;

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

			word = ParseWord (pLine);
			if (! str_cmp (word, "DEITY")) {
				deity = new CDeityData;
				deity->Read (fp);
				LINK (deity, first_deity, last_deity);
				found = TRUE;
				break;
			} else {
				bug ("Load_deity_file: bad section: %s.", word);
				break;
			}
		}
		fclose (fp);
	}

	return found;
}


// Load in all the deity files
void load_deities ()
{
	FILE	*fp;
	char	*pFname, *pLine;

	first_deity = NULL;
	last_deity  = NULL;

	gpDoc->LogString ("Loading deities...", LOG_BOOT);

	if (! (fp = fopen (FileTable.GetName (SM_DEITY_LIST), "r"))) {
		perror (FileTable.GetName (SM_DEITY_LIST));
		ThrowSmaugException (SE_DEITY);
	}

	while (! feof (fp)) {
		pLine = fread_line (fp);
		pFname = ParseWord (pLine);
		if (pFname [0] == '$') then break;
		gpDoc->LogString (pFname, LOG_BOOT);

		if (! load_deity_file (pFname))
			bug ("Cannot load deity file: %s", pFname);
	}	
	fclose (fp);
}


void do_setdeity (CCharacter *ch, char *argument)
{
	char		arg1 [MAX_INPUT_LENGTH];
	char		arg2 [MAX_INPUT_LENGTH];
	char		arg3 [MAX_INPUT_LENGTH];
	CDeityData	*deity;
	int			value;

	if (ch->IsNpc ()) {
		ch->SendText ("Huh?\n\r");
		return;
	}

	switch (ch->GetSubstate ()) {
      default:
		break;
 
	  case SUB_RESTRICTED:
		ch->SendText ("You cannot do this while in another command.\n\r");
		return;

	  case SUB_DEITYDESC:  
		deity = (CDeityData *) ch->dest_buf;
		STRFREE (deity->description);
		deity->description = ch->GetEditBuffer ();
		ch->StopEditing ();
		save_deity (deity);
		ch->SetSubstate (ch->tempnum);
		return;
    }

	argument = one_argument (argument, arg1);
	argument = one_argument (argument, arg2);

	if (arg1[0] == '\0') {
		ch->SendText ("Usage: setdeity <deity> <field> <toggle>\n\r");
		ch->SendText ("\n\rField being one of:\n\r");
		ch->SendText ("filename name description type alignment worshippers npcfoe\n\r");
		ch->SendText ("deityobj race npcrace class element avatar sex affected suscept\n\r");
		ch->SendText ("\n\rFavor adjustments:\n\r");
		ch->SendText ("flee flee_npcrace kill kill_npcrace kill_magic\n\r");
		ch->SendText ("die die_npcrace dig_corpse bury_corpse spell_aid\n\r");
		ch->SendText ("steal backstab aid aid_spell sac kill_npcfoe\n\r");
		ch->SendText ("die_npcfoe flee_npcfoe\n\r");
		ch->SendText ("\n\rFavor requirements for supplicate:\n\r");
		ch->SendText ("scorpse savatar sdeityobj srecall\n\r");
		return;
	}

	deity = get_deity (arg1);
	if (!deity) {
		ch->SendText ("No such deity.\n\r");
		return;
	}

	if (!strcmp (arg2, "name")) {
		STRFREE (deity->GetName ());
		deity->SetName (STRALLOC (argument));
		save_deity (deity);
		write_deity_list ();
		ch->SendText ("Done.\n\r");
		return;
	}

	if (! strcmp (arg2, "description")) {
		if (ch->GetSubstate () == SUB_REPEATCMD)
			ch->tempnum = SUB_REPEATCMD;
		else
			ch->tempnum = SUB_NONE;

		ch->SetSubstate (SUB_DEITYDESC);
		ch->dest_buf = deity;
		start_editing (ch, deity->description);
		return;
	}

	if (!strcmp (arg2, "alignment")) {
		deity->alignment = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "flee")) {
		deity->flee = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "flee_npcrace")) {
		deity->flee_npcrace = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "flee_npcfoe")) {
		deity->flee_npcfoe = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "kill")) {
		deity->kill = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "kill_npcrace")) {
		deity->kill_npcrace = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "kill_npcfoe")) {
		deity->kill_npcfoe = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "kill_magic")) {
		deity->kill_magic = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "sac")) {
		deity->sac = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "bury_corpse")) {
		deity->bury_corpse = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "aid_spell")) {
		deity->aid_spell = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "aid")) {
		deity->aid = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "steal")) {
		deity->steal = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "backstab")) {
		deity->backstab = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "die")) {
		deity->die = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "die_npcrace")) {
		deity->die_npcrace = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "die_npcfoe")) {
		deity->die_npcfoe = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "spell_aid")) {
		deity->spell_aid = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "dig_corpse")) {
		deity->dig_corpse = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "scorpse")) {
		deity->scorpse = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "savatar")) {
		deity->savatar = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "sdeityobj")) {
		deity->sdeityobj = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "srecall")) {
		deity->srecall = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "worshippers")) {
		deity->worshippers = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "deityobj")) {
		deity->deityobj = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "race")) {
		CRaceData	*pRace = RaceTable.Find (argument);
		if (pRace)
			deity->SetRace (pRace->GetRace ());
		else
			deity->SetRace (-1);

		save_deity (deity);
		ch->SendTextf ("Deity race set to %s.\n\r",
			deity->GetRace () == -1 ? "all" : argument);
		return;
	}

	if (!strcmp (arg2, "npcrace")) {
		value = RaceTable.GetNpcRace (argument);
		if (value < 0) value = atoi (argument);
		if ((value < 0) || (value >= MAX_NPC_RACE)) {
			ch->SendText ("Invalid npc race.\n\r");
			return;
		}	
		deity->npcrace = value;
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "npcfoe")) {
		value = RaceTable.GetNpcRace (argument);
		if (value < 0) value = atoi (argument);
		if ((value < 0) || (value >= MAX_NPC_RACE)) {
			ch->SendText ("Invalid npc race.\n\r");
			return;
		}
		deity->npcfoe = value;
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "class")) {
		deity->SetClass (atoi (argument));
		if ((deity->GetClass () < 0) || (deity->GetClass () >= ClassTable.GetCount ()))
			deity->SetClass (-1);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "suscept")) {
		BOOL fMatch = FALSE;

		while (argument[0] != '\0') {
			argument = one_argument (argument, arg3);
			if (!str_cmp (arg3, "none")) {
				fMatch = TRUE;
				deity->suscept = 0;
			} else {
				value = get_risflag (arg3);
				if (value < 0 || value > 31)
					ch->SendTextf ("Unknown flag: %s\n\r", arg3);
				else {
					TOGGLE_BIT (deity->suscept, 1 << value);
					fMatch = TRUE;
				}
			}
		}

		if (fMatch) ch->SendTextf ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "element")) {
		BOOL fMatch = FALSE;

		while (argument[0] != '\0') {
			argument = one_argument (argument, arg3);
			if (!str_cmp (arg3, "none")) {
				fMatch = TRUE;
				deity->element = 0;
			} else {
				value = get_risflag (arg3);
				if (value < 0 || value > 31)
				ch->SendTextf ("Unknown flag: %s\n\r", arg3);
				else {
					TOGGLE_BIT (deity->element, 1 << value);  
					fMatch = TRUE;
				}
			}
		}

		if (fMatch) ch->SendTextf ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "avatar")) {
		deity->avatar = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "sex")) {
		deity->sex = atoi (argument);
		ch->SendText ("Done.\n\r");
		save_deity (deity);
		return;
	}

	if (!strcmp (arg2, "affected")) {
		BOOL fMatch = FALSE;

		while (argument[0] != '\0') {
			argument = one_argument (argument, arg3);
			if (!str_cmp (arg3, "none")) {
				fMatch = TRUE;
				deity->m_Affected.Empty ();
			} else {
				value = get_aflag (arg3);
				if (value < 0 || value > 31)
					ch->SendTextf ("Unknown flag: %s\n\r", arg3);
				else {
					deity->ToggleAffected (value);
					fMatch = TRUE;
				}
			}
		}

		if (fMatch) ch->SendTextf ("Done.\n\r");
		save_deity (deity);
		return;
    }

	do_setdeity (ch, "");
}


void do_showdeity (CCharacter *ch, char *argument)
{
	CDeityData	*deity;

	if (ch->IsNpc ()) {
		ch->SendText ("Huh?\n\r");
		return;
	}

	if (argument [0] == '\0') {
		ch->SendText ("Usage: showdeity <deity>\n\r");
		return;
	}

	deity = get_deity (argument);
	if (! deity) {
		ch->SendText ("No such deity.\n\r");
		return;
	}

	ch->SendTextf ("Deity: %s\n\rDescription:\n\r%s\n\r", deity->GetName (),
		deity->description);
	ch->SendTextf ("Alignment: %-6dNpcrace: %-9sNpcfoe: %s\n\r",
		deity->alignment,
		RaceTable.GetNpcRaceName (deity->npcrace),
		RaceTable.GetNpcRaceName (deity->npcfoe));

	ch->SendTextf ("Race: %-11sClass: %-11sSex: %s\n\r", 
		deity->GetRace () == -1 ?
			"all" : RaceTable.GetNpcRaceName (deity->GetRace ()),
		deity->GetClass () == -1 ?
			"all" : ClassTable.GetNpcClassName (deity->GetClass ()),
		deity->sex == -1 ? "all" :
			deity->sex == SEX_MALE ? "male" :
				deity->sex == SEX_FEMALE ? "female" : "neutral");

	ch->SendTextf ("Object: %-9dAvatar: %-10dWorshippers: %d\n\r", 
		deity->deityobj, deity->avatar, deity->worshippers);
	ch->SendTextf ("\n\rAffected: %s\n\r",
		NCCP deity->m_Affected.PrintString ());
	ch->SendTextf ("Suscept: %s\n\r", flag_string (deity->suscept, ris_flags));
	ch->SendTextf ("Element: %s\n\r", flag_string (deity->element, ris_flags));

	ch->SendTextf ("\n\rFlee: %-11dFlee_npcrace: %-4dKill_npcrace: "
		"%-4dKill: %d\n\r", deity->flee, deity->flee_npcrace,
		deity->kill_npcrace, deity->kill);

	ch->SendTextf ("Kill_magic: %-5dSac: %-13dBury_corpse: %-5dAid_spell: "
		"%d\n\r", deity->kill_magic, deity->sac, deity->bury_corpse, 
		deity->aid_spell);

	ch->SendTextf ("Aid: %-12dSteal: %-11dBackstab: %-8dDie: %d\n\r", 
		deity->aid, deity->steal, deity->backstab, deity->die);

	ch->SendTextf ("Die_npcrace: %-4dDig_corpse: %-6dSpell_aid: %-7dKill_npcfoe: %d\n\r",
		deity->die_npcrace, deity->dig_corpse, deity->spell_aid, deity->kill_npcfoe);

	ch->SendTextf ("Die_npcfoe: %-5dFlee_npcfoe: %d\n\r", 
		deity->die_npcfoe, deity->flee_npcfoe);

	ch->SendTextf ("\n\rScorpse: %-8dSavatar: %-9dSdeityobj: %-7d"
		"Srecall: %d\n\r", deity->scorpse, deity->savatar,
		deity->sdeityobj, deity->srecall);
}


void do_makedeity (CCharacter *ch, char *argument)
{
	if (!argument || argument[0] == '\0') {
		ch->SendText ("Usage: makedeity <deity name>\n\r");
		return;
	}

	CDeityData	*deity = new CDeityData;

	LINK (deity, first_deity, last_deity);
	deity->SetName (STRALLOC (argument));
	deity->description = STRALLOC ("");
	save_deity (deity);
	write_deity_list ();
}


void do_devote (CCharacter *ch, char *argument)
{
	char		arg [MAX_INPUT_LENGTH];
	CDeityData	*deity;

	if (ch->IsNpc ()) {
		ch->SendText ("Huh?\n\r");
		return;
	}

	if (ch->GetLevel () < 10) {
		ch->SendText ("You are not yet prepared for such devotion.\n\r");
		return;
	}

	argument = one_argument (argument, arg);

	if (arg [0] == '\0') {
		ch->SendText ("Devote yourself to which deity?\n\r");
		return;
	}

	if (! str_cmp (arg, "none")) {
		CAffectData		af;
		if (! ch->GetPcData ()->deity) {
			ch->SendText ("You have already chosen to worship no deities.\n\r");
			return;
		}

		--ch->GetPcData ()->deity->worshippers;
		ch->GetPcData ()->favor = -2500;
		ch->SetMentalState (-80);
		ch->SendText ("A terrible curse afflicts you as you forsake a deity!\n\r");
		ch->ClrAffectBits (ch->GetPcData ()->deity->m_Affected);
		ch->ClrResist (ch->GetPcData ()->deity->element);
		ch->ClrSusceptible (ch->GetPcData ()->deity->suscept);
		affect_strip (ch, gsn_blindness);

		af.type         = gsn_blindness;
		af.location     = APPLY_HITROLL;
		af.modifier     = -4;
		af.duration     = (short) (50 * DUR_CONV);
		af.bitvector	= AFF_BLIND;
		affect_to_char (ch, &af);
		save_deity (ch->GetPcData ()->deity);
		ch->SendText ("You cease to worship any deity.\n\r");
		ch->GetPcData ()->deity = NULL;
		STRFREE (ch->GetPcData ()->GetDeityName ());
		ch->GetPcData ()->SetDeityName (STRALLOC (""));
		save_char_obj (ch);
		return;
	}

	deity = get_deity (arg);
	if (! deity) {
		ch->SendText ("No such deity holds weight on this world.\n\r");
		return;
	}

	if (ch->GetPcData ()->deity) {
		ch->SendText ("You are already devoted to a deity.\n\r");
		return;
	}

	if ((deity->GetClass () != -1)
	  && (deity->GetClass () != ch->GetClass ())) {
		ch->SendText (
			"That deity will not accept your worship due to your class.\n\r");
		return;
	}

	if ((deity->sex != -1) && (deity->sex != ch->GetSex ())) {
		ch->SendText ("That deity will not accept worshippers of your sex.\n\r");
		return;
	}

	if ((deity->GetRace () != -1) && (deity->GetRace () != ch->GetRace ())) {
		ch->SendText ("That deity will not accept worshippers of your race.\n\r");
		return;
	}

	STRFREE (ch->GetPcData ()->GetDeityName ());
	ch->GetPcData ()->SetDeityName (QUICKLINK (deity->GetName ()));
	ch->GetPcData ()->deity = deity;

	ch->SetAffectBits (ch->GetPcData ()->deity->m_Affected);
	ch->SetResist (ch->GetPcData ()->deity->element);
	ch->SetSusceptible (ch->GetPcData ()->deity->suscept);

	act (AT_MAGIC, "Body and soul, you devote yourself to $t!",
		ch, ch->GetPcData ()->GetDeityName (), NULL, TO_CHAR);
	++ch->GetPcData ()->deity->worshippers;
	save_deity (ch->GetPcData ()->deity);
	save_char_obj (ch);
}


void do_deities (CCharacter *ch, char *argument)
{
    CDeityData *deity;
    int count = 0;

    if (argument[0] == '\0')
    {
	set_char_color (AT_NOTE, ch);
	ch->SendText ("For detailed information on a deity, try deities <deity>.\n\r");
	ch->SendText ("\n\rDeity			Worshippers\n\r");
	for (deity = first_deity; deity; deity = deity->GetNext ())
	{
	   ch->SendTextf ("%-14s	%19d\n\r", deity->GetName (), deity->worshippers);
	   count++;
	}
	
	if (!count)
	{
	   ch->SendText ("There are no deities on this world.\n\r");
	   return;
	}
	return;
     }

    deity = get_deity (argument);
    if (!deity)
    {
	ch->SendText ("That deity does not exist.\n\r");
	return;
    }

    set_char_color (AT_NOTE, ch);
    ch->SendTextf ("Deity: %s\n\rDescription:\n\r%s", deity->GetName (), deity->description);
    return;
}


void do_supplicate (CCharacter *ch, char *argument)
{
	char	arg [MAX_INPUT_LENGTH];

	one_argument (argument, arg);
	if (ch->IsNpc () || !ch->GetPcData ()->deity) {
		ch->SendText ("You have no deity to supplicate to.\n\r");
		return;
	}

	if (arg [0] == '\0') {
		ch->SendText ("Supplicate for what?\n\r");
		return;
	}

	if (!str_cmp (arg, "corpse") && ! ch->IsPkiller ()) {
		char		buf2 [MAX_STRING_LENGTH];
		char		buf3 [MAX_STRING_LENGTH];
		CObjData	*obj;

		if (ch->GetPcData ()->favor < ch->GetPcData ()->deity->scorpse) {
			ch->SendText ("You are not favored enough for a corpse retrieval.\n\r");
			return;
		}

		sprintf (buf3, " ");
		sprintf (buf2, "the corpse of %s", ch->GetName ());
		BOOL	bFound = FALSE;

		CObjIndexData	&Idx = *OIdxTable.Find (OBJ_VNUM_CORPSE_PC);
		if (! &Idx)
			bug ("do_supplicate: No object index for OBJ_VNUM_CORPSE_PC.");

		else {
			POSITION	pos = Idx.m_ObjList.GetHeadPosition ();
			while (pos) {
				obj = Idx.m_ObjList.GetNext (pos);
				if (obj->in_room && ! str_cmp (buf2, obj->GetShortDescr ())) {
					bFound = TRUE;
					act (AT_MAGIC, "Your corpse appears suddenly, surrounded "
						"by a divine presence...", ch, NULL, NULL, TO_CHAR);		
					act (AT_MAGIC, "$n's corpse appears suddenly, surrounded "
						"by a divine force...", ch, NULL, NULL, TO_ROOM);
					obj_from_room (obj);
					obj = obj_to_room (obj, ch->GetInRoom ());
					ch->GetPcData ()->favor -= ch->GetPcData ()->deity->scorpse;
				}
			}
		}
		if (! bFound) {
			ch->SendText ("No corpse of yours litters the world...\n\r");
			return;
		}
		return;
	}

	if (! str_cmp (arg, "avatar")) {
		CMobIndexData	*pMobIndex;
		CCharacter		*victim;

		if (ch->GetPcData ()->favor < ch->GetPcData ()->deity->savatar) {
			ch->SendText ("You are not favored enough for that.\n\r");
			return;
		}

		if (ch->GetPcData ()->deity->avatar < 1) {
			ch->SendText ("Your deity does not have an avatar to summon.\n\r");
			return;
		}

		pMobIndex = MobTable.GetMob (ch->GetPcData ()->deity->avatar);
		victim = create_mobile (pMobIndex);
		victim->SendToRoom (ch->GetInRoom ());
		act (AT_MAGIC, "$n summons a powerful avatar!", ch, NULL, NULL, TO_ROOM);
		act (AT_MAGIC, "You summon a powerful avatar!", ch, NULL, NULL, TO_CHAR);
		ch->GetPcData ()->favor -= ch->GetPcData ()->deity->savatar;
		return;
	} 

	if (! str_cmp (arg, "object")) {
		CObjData		*obj;
		CObjIndexData	*pObjIndex;

		if (ch->GetPcData ()->favor < ch->GetPcData ()->deity->sdeityobj) {
			ch->SendText ("You are not favored enough for that.\n\r");
			return;
		}

		if (ch->GetPcData ()->deity->deityobj < 1) {
			ch->SendText ("Your deity does not have a sigil of worship.\n\r");
			return;
		}

		pObjIndex = OIdxTable.GetObj (ch->GetPcData ()->deity->deityobj);

		obj = create_object (pObjIndex, ch->GetLevel ());
		if (obj->CanWear (ITEM_TAKE))
			obj = obj_to_char (obj, ch);
		else
			obj = obj_to_room (obj, ch->GetInRoom ());

		act (AT_MAGIC, "$n weaves $p from divine matter!", ch, obj, NULL, TO_ROOM);
		act (AT_MAGIC, "You weave $p from divine matter!", ch, obj, NULL, TO_CHAR);
		ch->GetPcData ()->favor -= ch->GetPcData ()->deity->sdeityobj;
		return;
	}

	if (! str_cmp (arg, "recall")) {
		CRoomIndexData	*location;

		if (ch->GetPcData ()->favor < ch->GetPcData ()->deity->srecall) {
			ch->SendText (
				"You do not have enough favor for such a supplication.\n\r");
			return;
		}

		if (ch->GetInRoom () == RoomTable.GetRoom (SysData.m_RoomHell)) {
			ch->SendText ("You have been forsaken!\n\r");
			return;
		}

		location = NULL;

		if (! ch->IsNpc () && ch->GetPcData ()->GetClan ())
			location = RoomTable.GetRoom (ch->GetPcData ()->GetClan ()->recall);

		if (!ch->IsNpc () && !location && ch->GetLevel () >= 5
			&& ch->IsPkiller ())
				location = RoomTable.GetRoom (3009);

		if (! location)
			location = RoomTable.GetRoom (SysData.m_RoomTemple);

		if (! location) {
			ch->SendText ("You are completely lost.\n\r");
			return;
		}

		act (AT_MAGIC, "$n disappears in a column of divine power.", ch,
			NULL, NULL, TO_ROOM);
		ch->RemoveFromRoom ();
		ch->SendToRoom (location);

		if (ch->mount) {
			ch->mount->RemoveFromRoom ();
			ch->mount->SendToRoom (location);
		}

		act (AT_MAGIC, "$n appears in the room from a column of divine mist.",
			ch, NULL, NULL, TO_ROOM);
		do_look (ch, "auto");
		ch->GetPcData ()->favor -= ch->GetPcData ()->deity->srecall; 
		return;
	}

	ch->SendText ("You cannot supplicate for that.\n\r");
}


// Internal function to adjust favor.
// Fields are:
// 0 = flee				5 = sac				10 = backstab	
// 1 = flee_npcrace		6 = bury_corpse		11 = die
// 2 = kill				7 = aid_spell		12 = die_npcrace
// 3 = kill_npcrace		8 = aid				13 = spell_aid
// 4 = kill_magic		9 = steal			14 = dig_corpse
// 15 = die_npcfoe		16 = flee_npcfoe	17 = kill_npcfoe
void  adjust_favor (CCharacter *ch, int field, int mod)
{
	if (ch->IsNpc () || !ch->GetPcData ()->deity)   
		return;

	CDeityData	&Di = *ch->GetPcData ()->deity;
	short	&Favor = ch->GetPcData ()->favor;

	if ((ch->GetAlignment () - Di.alignment > 650
	  || ch->GetAlignment () - Di.alignment < -650)
	  && Di.alignment != 0) {	
		Favor -= 2;
		Favor = URANGE (-1000, Favor, 1000);   	
		return;
	}

	if (mod < 1) then mod = 1;

	switch (field) {
	  case 0:  Favor += number_fuzzy (Di.flee / mod);			break;
	  case 1:  Favor += number_fuzzy (Di.flee_npcrace / mod);	break;
	  case 2:  Favor += number_fuzzy (Di.kill / mod);			break;
	  case 3:  Favor += number_fuzzy (Di.kill_npcrace / mod);	break;
	  case 4:  Favor += number_fuzzy (Di.kill_magic / mod);		break;
	  case 5:  Favor += number_fuzzy (Di.sac / mod);			break;
	  case 6:  Favor += number_fuzzy (Di.bury_corpse / mod);	break;
	  case 7:  Favor += number_fuzzy (Di.aid_spell / mod);		break;
	  case 8:  Favor += number_fuzzy (Di.aid / mod);			break;	
	  case 9:  Favor += number_fuzzy (Di.steal / mod);			break;
	  case 10: Favor += number_fuzzy (Di.backstab / mod);		break;
	  case 11: Favor += number_fuzzy (Di.die / mod);			break;
	  case 12: Favor += number_fuzzy (Di.die_npcrace / mod);	break;
	  case 13: Favor += number_fuzzy (Di.spell_aid / mod);		break;
	  case 14: Favor += number_fuzzy (Di.dig_corpse / mod);		break;
	  case 15: Favor += number_fuzzy (Di.die_npcfoe / mod);		break;
	  case 16: Favor += number_fuzzy (Di.flee_npcfoe / mod);	break;
	  case 17: Favor += number_fuzzy (Di.kill_npcfoe / mod);	break;
	}
	Favor = URANGE (-1000, Favor, 1000);
}