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