/****************************************************************************
* [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 ();
}