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