/****************************************************************************
* [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. *
****************************************************************************/
// commands.cpp
#include "stdafx.h"
#include "smaug.h"
#include "Smaugx.h"
#include "commands.h"
#include "SmaugFiles.h"
void CCmdType::SetName (char* n)
{
// make sure the name is all lowercase
for (int x = 0; n [x] != '\0'; ++x)
n [x] = LOWER (n [x]);
m_pName = n;
}
#if defined (KEY)
#undef KEY
#endif
#define KEY(literal,field,value) \
if (!str_cmp (word, literal)) { \
field = value; \
fMatch = TRUE; \
break; \
}
BOOL CCmdType::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 ("Code", do_fun, skill_function (ParseWord (pLine)));
break;
case 'E':
if (! str_cmp (word, "End")) {
if (! m_pName) {
bug ("CCmdType::Read: Name not found");
return FALSE;
}
if (! do_fun) {
bug ("CCmdType::Read: Function not found");
return FALSE;
}
return TRUE;
}
break;
case 'L':
KEY ("Level", level, ParseNumber (pLine));
KEY ("Log", log, ParseNumber (pLine));
break;
case 'N':
KEY ("Name", m_pName, ParseStringNohash (pLine, fp));
break;
case 'P':
KEY ("Position", position, ParseNumber (pLine));
break;
}
if (!fMatch)
bug ("CCmdType::Read: no match: %s", word);
}
ASSERT (0);
return FALSE; // should never get here
}
void CCmdType::Write (FILE* fp)
{
fprintf (fp, "#COMMAND\n");
fprintf (fp, "Name %s~\n", m_pName);
fprintf (fp, "Code %s\n", skill_name (do_fun));
fprintf (fp, "Position %d\n", position);
fprintf (fp, "Level %d\n", level);
fprintf (fp, "Log %d\n", log);
fprintf (fp, "End\n\n");
}
CCmdType *CCommandTable::Find (char *command)
{
CCmdType *cmd;
int hash = GetHash (command [0]);
for (cmd = m_ct [hash]; cmd; cmd = cmd->GetNext ())
if (! str_prefix (command, cmd->GetName ()))
return cmd;
return NULL;
}
// Remove a command from it's hash index -Thoric
void CCommandTable::Unlink (CCmdType *command)
{
CCmdType *tmp, *tmp_next;
if (!command) {
bug ("Unlink_command NULL command", 0);
return;
}
int hash = GetHash (command->GetName ()[0]);
if (command == (tmp = GetCommand (hash))) {
m_ct [hash] = tmp->GetNext ();
return;
}
for (; tmp; tmp = tmp_next) {
tmp_next = tmp->GetNext ();
if (command == tmp_next) {
tmp->SetNext (tmp_next->GetNext ());
return;
}
}
}
// Add a command to the command hash table -Thoric
void CCommandTable::Add (CCmdType *command)
{
CCmdType *tmp, *prev;
if (!command) {
bug ("CCommandTable::Add: NULL command", 0);
return;
}
if (!command->GetName ()) {
bug ("CCommandTable::Add: NULL command->name", 0);
return;
}
if (!command->do_fun) {
bug ("CCommandTable::Add: NULL command->do_fun", 0);
return;
}
int hash = GetHash (command->GetName ()[0]);
if ((prev = tmp = GetCommand (hash)) == NULL) {
command->SetNext (GetCommand (hash));
m_ct [hash] = command;
return;
}
// add to the END of the list
for (; tmp; tmp = tmp->GetNext ())
if (!tmp->GetNext ()) {
tmp->SetNext (command);
command->SetNext (NULL);
}
}
void CCommandTable::Load ()
{
FILE *fp;
char *pLine;
if ((fp = fopen (FileTable.GetName (SM_COMMAND_FILE), "r")) != NULL) {
for (;;) {
char letter;
char *word;
pLine = fread_line (fp);
letter = *pLine++;
if (letter == '*')
continue;
if (letter != '#') {
bug ("CCommandTable::Load: # not found.");
break;
}
word = ParseWord (pLine);
if (! str_cmp (word, "COMMAND")) {
CCmdType *pCmd = new CCmdType;
if (pCmd->Read (fp)) then Add (pCmd);
else delete pCmd;
}
else if (! str_cmp (word, "END"))
break;
else {
bug ("CCommandTable::Load: bad section.");
continue;
}
}
fclose (fp);
} else {
bug ("Cannot open commands.dat");
ThrowSmaugException (SE_COMMAND);
}
}
// Save the commands to disk
void CCommandTable::Save ()
{
FILE *fp;
CCmdType *command;
if ((fp=fopen (FileTable.GetName (SM_COMMAND_FILE), "w")) == NULL) {
bug ("CCommandTable::Save: Cannot open commands.dat for writing", 0);
perror (COMMAND_FILE);
return;
}
for (int hash = 0; hash < MAX_COMMANDS; ++hash) {
for (command = GetCommand (hash); command;
command = command->GetNext ()) {
command->Write (fp);
}
}
fprintf (fp, "#END\n");
fclose (fp);
}
void CCommandTable::RemoveAll ()
{
CCmdType *pNcmd, *pCmd;
for (int hash = 0; hash < MAX_COMMANDS; ++hash) {
pCmd = GetCommand (hash);
while (pCmd) {
pNcmd = pCmd->GetNext ();
delete pCmd;
pCmd = pNcmd;
}
}
Empty ();
}