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.    *
 ****************************************************************************/
// Social.cpp

#include	"stdafx.h"
#include	"smaug.h"
#include	"Smaugx.h"
#include	"social.h"
#include	"SmaugFiles.h"

#if defined (KEY)
#undef KEY
#endif

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


BOOL CSocialType::Read (FILE* fp)
{
	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 'C':
			KEY ("CharNoArg", char_no_arg, ParseStringNohash (pLine, fp));
			KEY ("CharFound", char_found, ParseStringNohash (pLine, fp));
			KEY ("CharAuto", char_auto,	ParseStringNohash (pLine, fp));
			break;

		  case 'E':
			if (! str_cmp (word, "End")) {
				if (! m_pName) {
					bug ("Fread_social: Name not found");
					return FALSE;
				}
				if (! char_no_arg) {
					bug ("Fread_social: CharNoArg not found");
					return FALSE;
				}
				return TRUE;
			}
			break;

		  case 'N':
			KEY ("Name", m_pName, ParseStringNohash (pLine, fp));
			break;

		  case 'O':
			KEY ("OthersNoArg", others_no_arg, ParseStringNohash (pLine, fp));
			KEY ("OthersFound", others_found, ParseStringNohash (pLine, fp));
			KEY ("OthersAuto", others_auto, ParseStringNohash (pLine, fp));
			break;

		  case 'V':
			KEY ("VictFound", vict_found, ParseStringNohash (pLine, fp));
			break;
		}
		
		if (!fMatch)
			bug ("CSocialType::Read: no match: %s", word);
	}
}


// Save a social to disk
void CSocialType::Write (FILE* fp)
{
	fprintf (fp, "#SOCIAL\n");
	fprintf (fp, "Name        %s~\n", m_pName);

	fprintf (fp, "CharNoArg   %s~\n", char_no_arg);
	if (others_no_arg) then fprintf (fp, "OthersNoArg %s~\n", others_no_arg);
	if (char_found) then fprintf (fp, "CharFound   %s~\n", char_found);
	if (others_found) then fprintf (fp, "OthersFound %s~\n", others_found);
	if (vict_found) then fprintf (fp, "VictFound   %s~\n", vict_found);
	if (char_auto) then fprintf (fp, "CharAuto    %s~\n", char_auto);
	if (others_auto) then fprintf (fp, "OthersAuto  %s~\n", others_auto);
	fprintf (fp, "End\n\n");
}


CSocialType *CSocialTable::Find (char* name)
{
	CSocialType *social;

	int		hash = GetHash (name [0]);

	for (social = GetSocial (hash); social; social = social->GetNext ())
		if (!str_prefix (name, social->GetName ()))
			return social;

	return NULL;
}




CSocialType::~CSocialType ()
{
	delete [] m_pName;
	delete [] char_no_arg;
	delete [] others_no_arg;
	delete [] char_found;
	delete [] others_found;
	delete [] vict_found;
	delete [] char_auto;
	delete [] others_auto;
}




void CSocialTable::Load ()
{
	FILE	*fp;
	char	*pLine;

	if ((fp = fopen (FileTable.GetName (SM_SOCIAL_FILE), "r")) != NULL) {
		for (;;) {
			char	letter;
			char	*word;

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

			if (letter == '*')
				continue;

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

			word = ParseWord (pLine);
			if (! str_cmp (word, "SOCIAL")) {
				CSocialType		*pSoc = new CSocialType;
				if (pSoc->Read (fp)) then Add (pSoc);
				else delete pSoc;
			}
			else if (! str_cmp (word, "END"))
				break;
			else {
				bug ("CSocialTable::Load: bad section.");
				continue;
			}
		}
		fclose (fp);
	} else {
		bug ("Cannot open socials.dat");
		ThrowSmaugException (SE_SOCIAL);
	}
}


// Add a social to the social index table			-Thoric
// Hashed and insert sorted
void CSocialTable::Add (CSocialType *social)
{
    if (!social) {
		bug ("Add_social: NULL social", 0);
		return;
    }

    if (!social->m_pName) {
		bug ("Add_social: NULL social->name", 0);
		return;
    }

    if (!social->char_no_arg) {
		bug ("Add_social: NULL social->char_no_arg", 0);
		return;
    }

    // make sure the name is all lowercase
	int x;
    for  (x = 0; social->m_pName [x] != '\0'; x++)
		social->m_pName [x] = LOWER (social->m_pName [x]);

    int		hash = GetHash (social->m_pName [0]);

    CSocialType		*tmp, *prev;
	if ((prev = tmp = m_sa [hash]) == NULL) {
		social->SetNext (m_sa [hash]);
		m_sa [hash] = social;
		return;
    }

    for (; tmp; tmp = tmp->GetNext ()) {
		if ((x=strcmp (social->m_pName, tmp->m_pName)) == 0) {
			bug ("Add_social: trying to add duplicate name to bucket %d",
				hash);
			delete social;
			return;
		}
		else if (x < 0) {
			if  (tmp == m_sa [hash]) {
				social->SetNext (m_sa [hash]);
				m_sa [hash] = social;
				return;
			}
			prev->SetNext (social);
			social->SetNext (tmp);
			return;
		}
		prev = tmp;
    }

    // add to end
    prev->SetNext (social);
    social->SetNext (NULL);
}


// Remove a social from it's hash index				-Thoric
void CSocialTable::Unlink (CSocialType *social)
{
    CSocialType	*tmp, *tmp_next;

    if (!social) {
		bug ("CSocialTable::Unlink: NULL social", 0);
		return;
    }

    int		hash = GetHash (social->GetName ()[0]);

    if (social == (tmp = m_sa [hash])) {
		m_sa [hash] = tmp->GetNext ();
		return;
    }

	for (; tmp; tmp = tmp_next) {
		tmp_next = tmp->GetNext ();
		if (social == tmp_next) {
			tmp->SetNext (tmp_next->GetNext ());
			break;
		}
	}
}


void CSocialTable::Write ()
{
    FILE		*fp;

    if ((fp = fopen (FileTable.GetName (SM_SOCIAL_FILE), "w")) == NULL) {
		bug ("Cannot open socials.dat for writing", 0);
		perror (SOCIAL_FILE);
		return;
    }

	for (int hash = 0; hash < MAX_SOCIALS; ++hash) {
		CSocialType	*pSoc = GetSocial (hash);
		while (pSoc) {
			pSoc->Write (fp);
			pSoc = pSoc->GetNext ();
		}
	}

    fprintf (fp, "#END\n");
    fclose (fp);
}


void CSocialTable::RemoveAll ()
{
	CSocialType *pNsoc, *pSocial;
	for (int hash = 0; hash < MAX_SOCIALS; ++hash) {
		pSocial = GetSocial (hash);
		while (pSocial) {
			pNsoc = pSocial->GetNext ();
			delete pSocial;
			pSocial = pNsoc;
		}
	}
	Empty ();			// clear the table
}


CSocialTable::~CSocialTable ()
{
	RemoveAll ();
}