/
Sapphire/bin/
Sapphire/db/
Sapphire/db/OLC_rooms/
Sapphire/db/abi/
Sapphire/db/em_src/
Sapphire/db/helps/
Sapphire/db/helps/emman/ifunc/
Sapphire/db/npcs/Tatt/
Sapphire/db/objects/Tatt/
Sapphire/db/q_data/
Sapphire/db/rooms/Tatt/
Sapphire/doc/
Sapphire/doc/em/
Sapphire/etc/
Sapphire/src/abic/
Sapphire/src/areacon/
Sapphire/src/client/
Sapphire/src/embc/
Sapphire/src/emi/
Sapphire/src/emi/test/
Sapphire/src/include/
Sapphire/src/sapphire/em/
Sapphire/src/tcon/
/*
 * Copyright (C) 1995-1997 Christopher D. Granz
 *
 * This header may not be removed.
 *
 * Refer to the file "License" included in this package for further
 * information and before using any of the following.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <stdarg.h>
#include <unistd.h>

#include "sapphire.h"


/*
 * Functions
 */

/*
 * Adds a character the character linked list (ppCharList.)
 */
void char_to_list( CHAR_DATA *pChar )
{
    int iHash         = ( IS_NPC( pChar )
                        ? ( pChar->pNPCData->pNPCIndex->iNumber
                        % iHashListSize ) : 0 );

    pChar->pNext      = ppCharList[iHash];
    ppCharList[iHash] = pChar;
}


/*
 * Put a character into a room.
 */
void char_to_room( CHAR_DATA *pChar, ROOM_INDEX_DATA *pRoom )
{
    pChar->pInRoom     = pRoom;
    pChar->pNextInRoom = pRoom->pPeople;
    pRoom->pPeople     = pChar;
}


/*
 * Remove a character from the character list (ppCharList.)
 */
void char_from_list( CHAR_DATA *pChar )
{
    int iHash                = ( IS_NPC( pChar )
                               ? ( pChar->pNPCData->pNPCIndex->iNumber
                               % iHashListSize ) : 0 );

    if ( pChar == ppCharList[iHash] )
        ppCharList[iHash]    = pChar->pNext;
    else
    {
        CHAR_DATA *pPrev;

        for ( pPrev = ppCharList[iHash]; pPrev; pPrev = pPrev->pNext )
        {
            if ( pPrev->pNext == pChar )
            {
                pPrev->pNext = pChar->pNext;
                break;
            }
        }
#ifdef DEBUG
        if ( pPrev == NULL )
            wcdebug( "Character not found." );
#endif
    }

    pChar->pNext             = NULL;
}


/*
 * Take a character out of a room.
 */
void char_from_room( CHAR_DATA *pChar )
{
    if ( pChar->pInRoom == NULL )
        return;

    if ( pChar == pChar->pInRoom->pPeople )
        pChar->pInRoom->pPeople    = pChar->pNextInRoom;
    else
    {
        CHAR_DATA *pPrev;

        for ( pPrev = pChar->pInRoom->pPeople; pPrev;
          pPrev = pPrev->pNextInRoom )
        {
            if ( pPrev->pNextInRoom == pChar )
            {
                pPrev->pNextInRoom = pChar->pNextInRoom;
                break;
            }
        }
#ifdef DEBUG
        if ( pPrev == NULL )
            wcdebug( "Character not found." );
#endif
    }

    pChar->pInRoom                 = NULL;
    pChar->pNextInRoom             = NULL;
}


/*
 * Adds an object to the object linked list (ppObjList.)
 */
void obj_to_list( OBJ_DATA *pObj )
{
    int iHash        = ( pObj->pObjIndex->iNumber % iHashListSize );

    pObj->pNext      = ppObjList[iHash];
    ppObjList[iHash] = pObj;
}


/*
 * Put an object in a room.
 */
void obj_to_room( OBJ_DATA *pObj, ROOM_INDEX_DATA *pRoom )
{
    pObj->pInRoom      = pRoom;
    pObj->pNextContent = pRoom->pContents;
    pRoom->pContents   = pObj;
}


/*
 * Give an object to a character.
 */
void obj_to_char( OBJ_DATA *pObj, CHAR_DATA *pChar )
{
    pObj->pCarriedBy   = pChar;
    pObj->pNextContent = pChar->pInven;
    pChar->pInven      = pObj;
}


/*
 * Remove an object from the object linked list (pObjList.)
 */
void obj_from_list( OBJ_DATA *pObj )
{
    int iHash                = ( pObj->pObjIndex->iNumber
                               % iHashListSize );

    if ( pObj == ppObjList[iHash] )
        ppObjList[iHash]     = pObj->pNext;
    else
    {
        OBJ_DATA *pPrev;

        for ( pPrev = ppObjList[iHash]; pPrev; pPrev = pPrev->pNext )
        {
            if ( pPrev->pNext == pObj )
            {
                pPrev->pNext = pObj->pNext;
                break;
            }
        }
#ifdef DEBUG
        if ( pPrev == NULL )
            wcdebug( "Object not found." );
#endif
    }

    pObj->pNext              = NULL;
}


/*
 * Take an object out of a room.
 */
void obj_from_room( OBJ_DATA *pObj )
{
    if ( pObj->pInRoom == NULL )
        return;

    if ( pObj == pObj->pInRoom->pContents )
        pObj->pInRoom->pContents    = pObj->pNextContent;
    else
    {
        OBJ_DATA *pPrev;

        for ( pPrev = pObj->pInRoom->pContents; pPrev;
          pPrev = pPrev->pNextContent )
        {
            if ( pPrev->pNextContent == pObj )
            {
                pPrev->pNextContent = pObj->pNextContent;
                break;
            }
        }
#ifdef DEBUG
        if ( pPrev == NULL )
            wcdebug( "Object not found." );
#endif
    }

    pObj->pInRoom                   = NULL;
    pObj->pNextContent              = NULL;
}


/*
 * Take an object away from a character.
 */
void obj_from_char( OBJ_DATA *pObj )
{
    if ( pObj->pCarriedBy == NULL )
        return;

    if ( pObj == pObj->pCarriedBy->pInven )
        pObj->pCarriedBy->pInven    = pObj->pNextContent;
    else
    {
        OBJ_DATA *pPrev;

        for ( pPrev = pObj->pCarriedBy->pInven; pPrev;
          pPrev = pPrev->pNextContent )
        {
            if ( pPrev->pNextContent == pObj )
            {
                pPrev->pNextContent = pObj->pNextContent;
                break;
            }
        }
#ifdef DEBUG
        if ( pPrev == NULL )
            wcdebug( "Object not found." );
#endif
    }

    pObj->pCarriedBy                = NULL;
    pObj->pNextContent              = NULL;
}


/*
 * Take an object out of an object.
 */
void obj_from_obj( OBJ_DATA *pObj )
{
    if ( pObj->pInObj == NULL )
        return;

    if ( pObj == pObj->pInObj->pContains )
        pObj->pInObj->pContains     = pObj->pNextContent;
    else
    {
        OBJ_DATA *pPrev;

        for ( pPrev = pObj->pInObj->pContains; pPrev;
          pPrev = pPrev->pNextContent )
        {
            if ( pPrev->pNextContent == pObj )
            {
                pPrev->pNextContent = pObj->pNextContent;
                break;
            }
        }
#ifdef DEBUG
        if ( pPrev == NULL )
            wcdebug( "Object not found." );
#endif
    }

    pObj->pInObj                    = NULL;
    pObj->pNextContent              = NULL;
}


/*
 * Create some random stats.
 */
void roll_stats( STAT_DATA *pStats )
{
    int iTotal;

    pStats->iStatStr      = random_range( 20, 85 );
    pStats->iStatInt      = random_range( 20, 85 );
    pStats->iStatWis      = random_range( 20, 85 );
    pStats->iStatDex      = random_range( 20, 85 );
    pStats->iStatCon      = random_range( 20, 85 );
    pStats->iStatCha      = random_range( 20, 85 );
    pStats->iStatLuc      = random_range( 20, 85 );
    pStats->iStatHP       = ( random_range( 30, 200 ) + pStats->iStatCon
                            / 4 );
    pStats->iStatMP       = ( random_range( 30, 200 ) + pStats->iStatWis
                            / 4 );
    pStats->iStatMV       = ( random_range( 30, 200 ) + pStats->iStatDex
                            / 4 );

    /*
     * Make sure the stats are not to high.
     */
    iTotal                = ( pStats->iStatStr + pStats->iStatInt
                            + pStats->iStatWis + pStats->iStatDex
                            + pStats->iStatCon + pStats->iStatCha
                            + pStats->iStatLuc + pStats->iStatHP
                            + pStats->iStatMP + pStats->iStatMV );

    while ( iTotal > 700 )
    {
        if ( pStats->iStatStr > 25 )
            pStats->iStatStr -= 5;

        if ( pStats->iStatInt > 25 )
            pStats->iStatInt -= 5;

        if ( pStats->iStatWis > 25 )
            pStats->iStatWis -= 5;

        if ( pStats->iStatDex > 25 )
            pStats->iStatDex -= 5;

        if ( pStats->iStatCon > 25 )
            pStats->iStatCon -= 5;

        if ( pStats->iStatCha > 25 )
            pStats->iStatCha -= 5;

        if ( pStats->iStatLuc > 25 )
            pStats->iStatLuc -= 5;

        if ( pStats->iStatHP > 35 )
            pStats->iStatHP  -= 5;

        if ( pStats->iStatMP > 35 )
            pStats->iStatMP  -= 5;

        if ( pStats->iStatMV > 35 )
            pStats->iStatMV  -= 5;

        iTotal           -= 50;
    }
}


void modify_stats( STAT_DATA *pStats, int iRace )
{
    int i;

    for ( i = 0; rRaceTable[i].pName[0] != '\0'; i++ )
    {
        if ( rRaceTable[i].iNumber == iRace )
        {
            if ( pStats->iStatStr < 80 )
                pStats->iStatStr += rRaceTable[i].iStatModifiers[0];

            if ( pStats->iStatInt < 80 )
                pStats->iStatInt += rRaceTable[i].iStatModifiers[1];

            if ( pStats->iStatWis < 80 )
                pStats->iStatWis += rRaceTable[i].iStatModifiers[2];

            if ( pStats->iStatDex < 80 )
                pStats->iStatDex += rRaceTable[i].iStatModifiers[3];

            if ( pStats->iStatCon < 80 )
                pStats->iStatCon += rRaceTable[i].iStatModifiers[4];

            if ( pStats->iStatCha < 80 )
                pStats->iStatCha += rRaceTable[i].iStatModifiers[5];

            if ( pStats->iStatLuc < 80 )
                pStats->iStatLuc += rRaceTable[i].iStatModifiers[6];

            break;
        }
    }
}


/*
 * This function (format_string()) was taken from Jason Dinkel's OLC
 * for Envy.  Thus, credit for this function goes to him rather then
 * myself.
 */
char *format_string( char *pOldStr )
{
    char *pOutput = new_buffer( );
    char cBuf[MAX_STRING];
    char cBuf2[MAX_STRING];
    char *pBuf;
    bool bCap;
    int i;

    cBuf[0]                     = '\0';
    cBuf2[0]                    = '\0';
    bCap                        = TRUE;
    i                           = 0;
  
    for ( pBuf = pOldStr; *pBuf; pBuf++ )
    {
        if ( *pBuf == '\n' )
        {
            if ( cBuf[i - 1] != ' ' )
            {
                cBuf[i]         = ' ';
                i++;
            }
        }
        else if ( *pBuf == '\r' )
            ;
        else if ( *pBuf == ' ' )
        {
            if ( cBuf[i - 1] != ' ' )
            {
                cBuf[i]         = ' ';
                i++;
            }
        }
        else if ( *pBuf == ')' )
        {
            if ( cBuf[i - 1] == ' ' && cBuf[ i - 2] == ' '
              && ( cBuf[i - 3] == '.' || cBuf[i - 3] == '?'
              || cBuf[i - 3] == '!' ) )
            {
                cBuf[i - 2]     = ')';
                cBuf[i - 1]     = ' ';
                cBuf[i]         = ' ';
                i++;
            }
            else
            {
                cBuf[i]         = ')';
                i++;
            }
        }
        else if ( *pBuf == '.' || *pBuf == '?' || *pBuf == '!' )
        {
            if ( cBuf[i - 1] == ' ' && cBuf[i - 2] == ' '
              && ( cBuf[i - 3] == '.' || cBuf[i - 3] == '?'
              || cBuf[i - 3] == '!' ) )
            {
                cBuf[i - 2]     = *pBuf;

                if ( *( pBuf + 1 ) != '\"' )
                {
                    cBuf[i - 1] = ' ';
                    cBuf[i]     = ' ';
                    i++;
                }
                else
                {
                    cBuf[i - 1] = '\"';
                    cBuf[i]     = ' ';
                    cBuf[i + 1] = ' ';
                    i          += 2;
                    pBuf++;
                }
            }
            else
            {
                cBuf[i]         = *pBuf;

                if ( *( pBuf + 1 ) != '\"' )
                {
                    cBuf[i + 1] = ' ';
                    cBuf[i + 2] = ' ';
                    i          += 3;
                }
                else
                {
                    cBuf[i + 1] = '\"';
                    cBuf[i + 2] = ' ';
                    cBuf[i + 3] = ' ';
                    i          += 4;
                    pBuf++;
                }
            }

            bCap                = TRUE;
        }
        else
        {
            cBuf[i]             = *pBuf;

            if ( bCap == TRUE )
            {
                bCap            = FALSE;
                cBuf[i]         = UPPER( cBuf[i] );
            }

            i++;
        }
    }

    cBuf[i]                     = '\0';
    strcpy( cBuf2, cBuf );
    pBuf                        = cBuf2;
    cBuf[0]                     = '\0';

    for ( ; ; )
    {
        for ( i = 0; i < 77; i++ )
        {
            if ( ( *( pBuf + i ) ) == 0 )
                break;
        }

        if ( i < 77 )
            break;

        for ( i = ( cBuf[0] ? 76 : 73 ); i; i-- )
        {
            if ( *( pBuf + i ) == ' ' )
                break;
        }

        if ( i != 0 )
        {
            *( pBuf + i )       = '\0';
            strcat( cBuf, pBuf );
            strcat( cBuf, "\n\r" );
            pBuf               += i + 1;

            while ( *pBuf == ' ' )
                pBuf++;
        }
        else
        {
            wcerror( "Format string: No spaces in string." );
            *(pBuf + 75)        = '\0';
            strcat( cBuf, pBuf );
            strcat( cBuf, "-\n\r" );
            pBuf               += 76;
        }
    }

    while ( *( pBuf + i ) && ( *( pBuf + i ) == ' '
      || *( pBuf + i ) == '\n' || *( pBuf + i ) == '\r' ) )
        i--;

    *( pBuf + i + 1 )           = '\0';
    strcat( cBuf, pBuf );

    if ( ( i = ( strlen( cBuf ) - 2 ) ) >= 0 )
    {
        if ( cBuf[i] == '\n' )
            cBuf[i]             = '\0';
    }

    strcpy( pOutput, cBuf );

    return ( pOutput );
}


bool sp_legal_string( char *pStr )
{
    XWORD_DATA *pXWord;

    for ( pXWord = pXWordList; pXWord; pXWord = pXWord->pNext )
    {
        if ( str_infix( pXWord->pWord, pStr ) == TRUE )
            return ( FALSE );
    }

    return ( TRUE );
}


/*
 * See it an object is visable to a character.
 */
bool visable_object( OBJ_DATA *pObj, CHAR_DATA *pChar )
{
    if ( pChar->iLevel == IMP_LEVEL
      || ( ( ( !IS_SET( pObj->fObjFlags, FLAG_OBJECT_INVIS )
      && ( pObj->pInRoom != NULL
      ? !IS_SET( pObj->pInRoom->fRoomFlags, FLAG_ROOM_INVIS ) : 1 ) )
      || IS_SET( pChar->fActFlags, FLAG_ACT_SEE_INVIS ) )
      && has_light( pChar ) == TRUE ) )
        return ( TRUE );

    return ( FALSE );
}


/*
 * See if pChar1 is visable to pChar2.
 */
bool visable_char( CHAR_DATA *pChar1, CHAR_DATA *pChar2 )
{
    if ( pChar2->iLevel == IMP_LEVEL
      || ( ( ( !IS_SET( pChar1->fActFlags, FLAG_ACT_INVIS )
      && ( pChar1->pInRoom != NULL
      ? !IS_SET( pChar1->pInRoom->fRoomFlags, FLAG_ROOM_INVIS ) : 1 ) )
      || IS_SET( pChar2->fActFlags, FLAG_ACT_SEE_INVIS ) )
      && ( has_light( pChar2 ) == TRUE || has_light( pChar1 )
      == TRUE ) ) )
        return ( TRUE );

    return ( FALSE );
}


/*
 * Returns TRUE if pChar has light.  Returns FALSE otherwise.
 */
bool has_light( CHAR_DATA *pChar )
{
    ROOM_INDEX_DATA *pRoom = pChar->pInRoom;
    OBJ_DATA *pObj;

    if ( pRoom != NULL && !IS_SET( pRoom->fRoomFlags, FLAG_ROOM_DARK ) )
        return ( TRUE );

    for ( pObj = pChar->pInven; pObj != NULL; pObj = pObj->pNextContent )
    {
        if ( IS_SET( pObj->fObjFlags, FLAG_OBJECT_LIT ) )
            return ( TRUE );
    }

    return ( FALSE );
}


/*
 * Returns the weight of all the objects carried by a character (pChar.)
 */
int carry_weight( CHAR_DATA *pChar )
{
    OBJ_DATA *pObj;
    int i  = 0;

    for ( pObj = pChar->pInven; pObj != NULL; pObj = pObj->pNextContent )
        i += pObj->iWeight;

    return ( i );
}


/*
 * Replaces special "prompt symbols" in a string with the currect values.
 */
char *format_prompt( CHAR_DATA *pChar, char *pPrompt )
{
    char *pOutput         = new_buffer( );
    int i, iPos;

    for ( i = 0, iPos = 0; pPrompt[i] != '\0'; i++, iPos++ )
    {
        if ( pPrompt[i] == '%' )
        {
            switch ( pPrompt[++i] )
            {
              case '%' : pOutput[iPos] = '%'; break;
              case 'L' :
              case 'l' :
                  sprintf( &pOutput[iPos], "%d", pChar->iLevel );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'H' :
                  sprintf( &pOutput[iPos], "%d", pChar->pStats->iStatHP );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'h' :
                  sprintf( &pOutput[iPos], "%d", pChar->iHP );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'M' :
                  sprintf( &pOutput[iPos], "%d", pChar->pStats->iStatMP );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'm' :
                  sprintf( &pOutput[iPos], "%d", pChar->iMP );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'V' :
                  sprintf( &pOutput[iPos], "%d", pChar->pStats->iStatMV );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'v' :
                  sprintf( &pOutput[iPos], "%d", pChar->iMV );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'G' :
              case 'g' :
                  sprintf( &pOutput[iPos], "%ld", pChar->iGold );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case '\0': i--;
              default  : iPos--; break;
            }
        }
        else if ( pPrompt[i] == '&' )
        {
            switch ( pPrompt[++i] )
            {
              case '&' : pOutput[iPos] = '&'; break;
              case 'n' :
              case 'N' :
                  strcpy( &pOutput[iPos], make_ansi_code(
                    ANSI_CODEREF_SGR_DSET, "0", NULL, pChar->pTerm ) );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'r' :
                  strcpy( &pOutput[iPos], make_ansi_code(
                    ANSI_CODEREF_SGR_DSET, "0;40;31", NULL,
                    pChar->pTerm ) );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'R' :
                  strcpy( &pOutput[iPos], make_ansi_code(
                    ANSI_CODEREF_SGR_DSET, "0;1;40;31", NULL,
                    pChar->pTerm ) );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'g' :
                  strcpy( &pOutput[iPos], make_ansi_code(
                    ANSI_CODEREF_SGR_DSET, "0;40;32", NULL,
                    pChar->pTerm ) );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'G' :
                  strcpy( &pOutput[iPos], make_ansi_code(
                    ANSI_CODEREF_SGR_DSET, "0;1;40;32", NULL,
                    pChar->pTerm ) );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'y' :
                  strcpy( &pOutput[iPos], make_ansi_code(
                    ANSI_CODEREF_SGR_DSET, "0;40;33", NULL,
                    pChar->pTerm ) );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'Y' :
                  strcpy( &pOutput[iPos], make_ansi_code(
                    ANSI_CODEREF_SGR_DSET, "0;1;40;33", NULL,
                    pChar->pTerm ) );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'b' :
                  strcpy( &pOutput[iPos], make_ansi_code(
                    ANSI_CODEREF_SGR_DSET, "0;40;34", NULL,
                    pChar->pTerm ) );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'B' :
                  strcpy( &pOutput[iPos], make_ansi_code(
                    ANSI_CODEREF_SGR_DSET, "0;1;40;34", NULL,
                    pChar->pTerm ) );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'm' :
                  strcpy( &pOutput[iPos], make_ansi_code(
                    ANSI_CODEREF_SGR_DSET, "0;40;35", NULL,
                    pChar->pTerm ) );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'M' :
                  strcpy( &pOutput[iPos], make_ansi_code(
                    ANSI_CODEREF_SGR_DSET, "0;1;40;35", NULL,
                    pChar->pTerm ) );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'c' :
                  strcpy( &pOutput[iPos], make_ansi_code(
                    ANSI_CODEREF_SGR_DSET, "0;40;36", NULL,
                    pChar->pTerm ) );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'C' :
                  strcpy( &pOutput[iPos], make_ansi_code(
                    ANSI_CODEREF_SGR_DSET, "0;1;40;36", NULL,
                    pChar->pTerm ) );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'w' :
                  strcpy( &pOutput[iPos], make_ansi_code(
                    ANSI_CODEREF_SGR_DSET, "0;40;37", NULL,
                    pChar->pTerm ) );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case 'W' :
                  strcpy( &pOutput[iPos], make_ansi_code(
                    ANSI_CODEREF_SGR_DSET, "0;1;40;37", NULL,
                    pChar->pTerm ) );
                  iPos    = ( strlen( pOutput ) - 1 );
                  break;

              case '\0': i--;
              default  : iPos--; break;
            }
        }
        else
            pOutput[iPos] = pPrompt[i];
    }

    pOutput[iPos]         = '\0';
    strcat( pOutput, make_ansi_code( ANSI_CODEREF_SGR_DSET, "0", NULL,
      pChar->pTerm ) );
    return ( pOutput );
}


int count_race( ROOM_INDEX_DATA *pRoom, intt iRace )
{
    CHAR_DATA *pChar;
    int iCount = 0;

    for ( pChar = pRoom->pPeople; pChar; pChar = pChar->pNextInRoom )
    {
        if ( pChar->iRace == iRace )
            iCount++;
    }

    return ( iCount );
}


int count_npcs( ROOM_INDEX_DATA *pRoom, NPC_DATA *pNPCData )
{
    CHAR_DATA *pChar;
    int iCount = 0;

    for ( pChar = pRoom->pPeople; pChar; pChar = pChar->pNextInRoom )
    {
        if ( IS_NPC( pChar )
          && ( pChar->pNPCData->pNPCIndex == pNPCData->pNPCIndex
          || str_compare( pChar->pNPCData->sShortDesc,
          pNPCData->sShortDesc ) == TRUE ) )
            iCount++;
    }

    return ( iCount );
}


void introduce_char( CHAR_DATA *pChar, CHAR_DATA *pIntroduceChar )
{
    KNOWN_PERSON_DATA *pKnownPerson;

    if ( IS_NPC( pChar ) || IS_NPC( pIntroduceChar )
      || IS_GUEST( pIntroduceChar ) || pChar->iLevel >= BUILDER_LEVEL
      || pChar == pIntroduceChar )
        return;

    pKnownPerson              = alloc_mem( sizeof( *pKnownPerson ) );
    pKnownPerson->sName       = save_string( ( IS_NPC( pIntroduceChar )
                                  ? pIntroduceChar->pNPCData->pNameList[0]
                                  : pIntroduceChar->pPCData->sName ) );
    pKnownPerson->tIntroduced = tCurrentTime;

    pKnownPerson->pNext          = pChar->pPCData->pKnownPeople;
    pChar->pPCData->pKnownPeople = pKnownPerson;
}


bool knows_char( CHAR_DATA *pChar, CHAR_DATA *pKnowChar )
{
    KNOWN_PERSON_DATA *pKnownPerson;

    if ( IS_NPC( pChar ) || IS_NPC( pKnowChar ) || IS_GUEST( pKnowChar )
      || pChar->iLevel >= BUILDER_LEVEL || pChar == pKnowChar )
        return ( TRUE );

    for ( pKnownPerson = pChar->pPCData->pKnownPeople; pKnownPerson;
      pKnownPerson = pKnownPerson->pNext )
    {
        if ( str_compare( pKnownPerson->sName,
          ( IS_NPC( pKnowChar ) ? pKnowChar->pNPCData->pNameList[0]
          : pKnowChar->pPCData->sName ) ) == TRUE )
            return ( TRUE );
    }

    return ( FALSE );
}


void find_exit( CHAR_DATA *pChar, ROOM_INDEX_DATA *pRoom, intt iDir )
{
    KNOWN_EXIT_DATA *pKnownExit;

    if ( IS_NPC( pChar ) || pChar->iLevel >= BUILDER_LEVEL )
        return;

    pKnownExit                  = alloc_mem( sizeof( *pKnownExit ) );
    pKnownExit->pRoom           = pRoom;
    pKnownExit->iDir            = iDir;
    pKnownExit->tDiscovered     = tCurrentTime;

    pKnownExit->pNext           = pChar->pPCData->pKnownExits;
    pChar->pPCData->pKnownExits = pKnownExit;
}


bool knows_exit( CHAR_DATA *pChar, ROOM_INDEX_DATA *pRoom, intt iDir )
{
    KNOWN_EXIT_DATA *pKnownExit;

    if ( IS_NPC( pChar ) || pChar->iLevel >= BUILDER_LEVEL )
        return ( TRUE );

    for ( pKnownExit = pChar->pPCData->pKnownExits; pKnownExit != NULL;
      pKnownExit = pKnownExit->pNext )
    {
        if ( pKnownExit->pRoom == pRoom && pKnownExit->iDir == iDir )
            return ( TRUE );
    }

    return ( FALSE );
}


char *npc_flags_string( flags fNPC )
{
    char *pOutput = new_buffer( );
    int i;
    bool b        = FALSE;

    for ( i = 0; snNPCFlagsTable[i].pName[0] != '\0'; i++ )
    {
        if ( IS_SET( fNPC, snNPCFlagsTable[i].iNumber ) )
        {
            strcat( pOutput, snNPCFlagsTable[i].pName );
            b     = TRUE;
        }
    }

    if ( b == FALSE )
        return ( EMPTY_STRING );
    else
        return ( pOutput );
}


char *part_flags_string( flags fParts )
{
    char *pOutput = new_buffer( );
    int i;
    bool b        = FALSE;

    for ( i = 0; snPartFlagsTable[i].pName[0] != '\0'; i++ )
    {
        if ( IS_SET( fParts, snPartFlagsTable[i].iNumber ) )
        {
            strcat( pOutput, snPartFlagsTable[i].pName );
            b     = TRUE;
        }
    }

    if ( b == FALSE )
        return ( EMPTY_STRING );
    else
        return ( pOutput );
}


char *act_flags_string( flags fAct )
{
    char *pOutput = new_buffer( );
    int i;
    bool b        = FALSE;

    for ( i = 0; snActFlagsTable[i].pName[0] != '\0'; i++ )
    {
        if ( IS_SET( fAct, snActFlagsTable[i].iNumber ) )
        {
            strcat( pOutput, snActFlagsTable[i].pName );
            b     = TRUE;
        }
    }

    if ( b == FALSE )
        return ( EMPTY_STRING );
    else
        return ( pOutput );
}


char *obj_flags_string( flags fObj )
{
    char *pOutput = new_buffer( );
    int i;
    bool b        = FALSE;

    for ( i = 0; snObjectFlagsTable[i].pName[0] != '\0'; i++ )
    {
        if ( IS_SET( fObj, snObjectFlagsTable[i].iNumber ) )
        {
            strcat( pOutput, snObjectFlagsTable[i].pName );
            b     = TRUE;
        }
    }

    if ( b == FALSE )
        return ( EMPTY_STRING );
    else
        return ( pOutput );
}


char *room_flags_string( flags fRoom )
{
    char *pOutput = new_buffer( );
    int i;
    bool b        = FALSE;

    for ( i = 0; snRoomFlagsTable[i].pName[0] != '\0'; i++ )
    {
        if ( IS_SET( fRoom, snRoomFlagsTable[i].iNumber ) )
        {
            strcat( pOutput, snRoomFlagsTable[i].pName );
            b     = TRUE;
        }
    }

    if ( b == FALSE )
        return ( EMPTY_STRING );
    else
        return ( pOutput );
}


char *door_flags_string( flags fDoor )
{
    char *pOutput = new_buffer( );

    if ( IS_SET( fDoor, FLAG_DOOR_CLOSED ) )
        strcat( pOutput, " CLOSED" );

    if ( IS_SET( fDoor, FLAG_DOOR_LOCKED ) )
        strcat( pOutput, " LOCKED" );

    if ( IS_SET( fDoor, FLAG_DOOR_HIDDEN ) )
        strcat( pOutput, " HIDDEN" );

    if ( pOutput[0] == '\0' )
        return ( EMPTY_STRING );
    else
        return ( &pOutput[1] );
}


/*
 * End of misc.c
 */