legend/
legend/area/
legend/player/
/***************************************************************************
 *  God Wars Mud copyright (C) 1994, 1995, 1996 by Richard Woolcock        *
 *                                                                         *
 *  Legend of Chrystancia copyright (C) 1999, 2000, 2001 by Matthew Little *
 *  This mud is NOT to be copied in whole or in part, or to be run without *
 *  the permission of Matthew Little. Nobody else has permission to        *
 *  authorise the use of this code.                                        *
 ***************************************************************************/

/******************************************************************************
 Snippet: Soundex parser.
 Author:  Richard Woolcock (aka KaVir).
 Date:    20th December 2000.
 ******************************************************************************
 This code is copyright (C) 2000 by Richard Woolcock.  It may be used and
 distributed freely, as long as you don't remove this copyright notice.
 ******************************************************************************/

/******************************************************************************
 Required library files.
 ******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "merc.h"

/******************************************************************************
 Local literals
 ******************************************************************************/

#define KEY_SIZE 4 /* Size of the soundex key */

/******************************************************************************
 Local operation prototypes.
 ******************************************************************************/

static char LetterConversion ( char chLetter );

/******************************************************************************
 Global operations.
 ******************************************************************************/

/* Function: GetSoundexKey
 *
 * This function determines a soundex key from the string argument and returns 
 * the address of the key (which is stored in a static variable).  Because the 
 * most common use of the soundex key is to compare it with _another_ soundex 
 * key, this function uses two internal storage buffers, which are alternated 
 * between every time the function is called.
 *
 * The function takes one parameter, as follows:
 *
 * szTxt: A pointer to the string from which the soundex key is calculated.
 *
 * The return value is a pointer to the soundex key string.
 */
char *GetSoundexKey( const char *szTxt )
{
   int iOldIndex = 0; /* Loop index for the old (szTxt) string */
   int iNewIndex = 0; /* Loop index for the new (s_a_chSoundex) string */
   static char s_a_chSoundex[2][KEY_SIZE+1]; /* Stores the new string */
   static unsigned iSoundex; /* Determines which s_a_chSoundex is used */

   iSoundex++; /* Switch to the other s_a_chSoundex array */

   s_a_chSoundex[iSoundex%2][0] = '\0'; /* Clear any previous data */

   /* Copy the first character without conversion */
   if ( ( s_a_chSoundex[iSoundex%2][iNewIndex++] = tolower(szTxt[iOldIndex++]) ) )
   {
      do /* Loop through szTxt */
      {
         char chLetter; /* Stores the soundex value of a letter */

         /* Double/triple/etc letters are treated as single letters */
         while ( tolower(szTxt[iOldIndex]) == tolower(szTxt[iOldIndex+1]) )
         {
            iOldIndex++;
            continue;
         }

         /* Convert the letter into its soundex value and store it */
         chLetter = LetterConversion((char)tolower(szTxt[iOldIndex]));

         /* Ignore NUL and 0 characters and only store KEY_SIZE characters */
         if ( chLetter != '\0' && chLetter != '0' && iNewIndex < KEY_SIZE )
         {
            /* Store the soundex value */
            s_a_chSoundex[iSoundex%2][iNewIndex++] = chLetter;
         }
      }
      while ( szTxt[iOldIndex++] != '\0' );

      /* If less than KEY_SIZE characters were copied, buffer with zeros */
      while ( iNewIndex < KEY_SIZE )
      {
         s_a_chSoundex[iSoundex%2][iNewIndex++] = '0';
      }

      /* Add the NUL terminator to the end of the soundex string */
      s_a_chSoundex[iSoundex%2][iNewIndex] = '\0';
   }

   /* Return the address of the soundex string */
   return ( s_a_chSoundex[iSoundex%2] );
}

/* Function: SoundexMatch
 *
 * This function compares two soundex keys and returns a percentage match.
 *
 * The function takes two parameters, as follows:
 *
 * szFirst:  A pointer to the first soundex key.
 * szSecond: A pointer to the second soundex key.
 *
 * The return value is an integer which contains the percentage match.
 */
int SoundexMatch( char *szFirst, char *szSecond )
{
   int iMatch = 0; /* Number of matching characters found */
   int iMax   = 0; /* Total number of characters compared */

   /* Make sure that both strings are of the correct size */
   if ( strlen( szFirst ) == KEY_SIZE && strlen( szSecond ) == KEY_SIZE )
   {
      int i; /* Loop counter */

      /* Loop through both strings */
      for ( i = 0; i < KEY_SIZE; i++ )
      {
         /* If either of the values are not NUL */
         if ( szFirst[i] != '0' || szSecond[i] != '0' )
         {
            iMax++; /* Increment the maximum */
         }

         /* If BOTH values are not NUL */
         if ( szFirst[i] != '0' && szSecond[i] != '0' )
         {
            /* Check for a match */
            if ( szFirst[i] == szSecond[i] )
            {
               iMatch++; /* A match was found */
            }
         }
      }
   }

   /* Return the percentage match */
   return ( iMatch * 100 / iMax );
}

/******************************************************************************
 Local operations.
 ******************************************************************************/

/* Function: LetterConversion
 *
 * This function converts a single letter into it's appropriate soundex value.
 *
 * The function takes one parameter, as follows:
 *
 * chLetter: The letter to be converted.
 *
 * The return value is a single character which contains the converted value.
 */
static char LetterConversion( char chLetter )
{
   const char * kszSoundexData = "01230120022455012623010202";
   char chResult; /* Store the soundex value, or NUL */

   if ( islower(chLetter) )
   {
      /* Determine the soundex value associated with the letter */
      chResult = kszSoundexData[ (chLetter - 'a') ];
   }
   else /* it's not a lowercase letter */
   {
      /* NUL means there is no associated soundex value */
      chResult = '\0';
   }

   /* Return the soundex value, or NUL if there isn't one */
   return ( chResult );
}

bool check_help_soundex (char *argument, CHAR_DATA * ch)
{
   HELP_DATA *pHelp;
   char arg[MAX_INPUT_LENGTH];
   char keyword[MAX_INPUT_LENGTH];
   char buf[MAX_STRING_LENGTH];
   char *str;
   bool found = FALSE;
   int i = 0;
         
   one_argument (argument, arg);
          
   if (arg[0] == '\0')
      return FALSE;
   buf[0] = '\0';
   sprintf (buf + strlen (buf), "%s\n\r",
            generate_banner ("Help Not Found", 80, "#C"));
   sprintf (buf + strlen (buf),
            " The helpfile you asked for did not exist, perhaps one of the following entries\n\r");
   sprintf (buf + strlen (buf),
            " are what you are looking for. The list contains all helpfiles that are spelled\n\r");
   sprintf (buf + strlen (buf),
            " roughly the same as or contains the keyword '#7%s#n'\n\n\r",
            argument);
       
   for (pHelp = help_first; pHelp; pHelp = pHelp->next)
   {
      bool match = FALSE;
      str = pHelp->keyword;
      str = one_argument (str, keyword);
    
      if (pHelp->level > ch->level)
         continue;
   
      if (SoundexMatch (GetSoundexKey (arg), GetSoundexKey (keyword)) > 75)
         match = TRUE;
      else
      {
         while (keyword[0] != '\0')
         {   
            if (!str_prefix (argument, keyword))
            {
               match = TRUE;
               break; 
            }
            str = one_argument (str, keyword);
         }
      }
   
      if (match)
      {
         found = TRUE;
         sprintf (buf + strlen (buf), "  %-22.22s%s", keyword,
                  (++i % 3) ? "  " : "\n\r");
      }
   }                  
   
   sprintf (buf + strlen (buf), "%s\n\r%s\n\r", (i % 3) ? "\n" : "",
            generate_banner ("", 80, "#C"));
   if (found)
      send_to_char (buf, ch);
      
   return found;
}
void oldcheck_help_soundex(char *argument, CHAR_DATA *ch)
{
  HELP_DATA *pHelp;
  char buf[MAX_STRING_LENGTH];
  char tbuf[MAX_STRING_LENGTH];
  char arg[MAX_INPUT_LENGTH];
  char keyword[MAX_INPUT_LENGTH];
  char *str;
  bool found = FALSE;

  one_argument(argument, arg);

  if (arg[0] == '\0') return;

  sprintf(buf, "#wTrying soundex...#n\n\r");
  for (pHelp = help_first; pHelp; pHelp = pHelp->next)
  {
    if (pHelp->level > ch->level) continue;

    str = pHelp->keyword;
    str = one_argument(str, keyword);
    while (keyword[0] != '\0')
    {
      if (SoundexMatch(GetSoundexKey(arg), GetSoundexKey(keyword)) > 75)
      {
        found = TRUE;
        sprintf(tbuf, "  #c%s#n", keyword);
        strcat(buf, tbuf);
      }
      str = one_argument(str, keyword);
    }
  }
  strcat(buf, "\n\r");
  if (found) send_to_char(buf, ch);
  else
      send_to_char("#wNo similar sounding help topics were found.#n\n\r", ch);
}