mux2.0/
mux2.0/game/bin/
mux2.0/game/data/
mux2.0/src/tools/
// flags.cpp - flag manipulation routines.
//
// $Id: flags.cpp,v 1.6 2000/08/09 07:03:20 sdennis Exp $ 
//
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include "externs.h"

#include "db.h"
#include "mudconf.h"
#include "command.h"
#include "flags.h"
#include "alloc.h"
#include "powers.h"

extern void FDECL(cf_log_notfound, (dbref, char *, const char *, char *));

#ifndef STANDALONE

/*
 * ---------------------------------------------------------------------------
 * * fh_any: set or clear indicated bit, no security checking
 */

int fh_any(dbref target, dbref player, FLAG flag, int fflags, int reset)
{
    // Never let God drop his/her own wizbit.
    //
    if (  God(target)
       && reset
       && (flag == WIZARD)
       && !(fflags & FLAG_WORD2)
       && !(fflags & FLAG_WORD3))
    {
        notify(player, "You cannot make God mortal.");
        return 0;
    }
    
    // Otherwise we can go do it.
    //
    if (fflags & FLAG_WORD3)
    {
        if (reset)
            s_Flags3(target, Flags3(target) & ~flag);
        else
            s_Flags3(target, Flags3(target) | flag);
    }
    else if (fflags & FLAG_WORD2)
    {
        if (reset)
            s_Flags2(target, Flags2(target) & ~flag);
        else
            s_Flags2(target, Flags2(target) | flag);
    }
    else
    {
        if (reset)
            s_Flags(target, Flags(target) & ~flag);
        else
            s_Flags(target, Flags(target) | flag);
    }
    return 1;
}

/*
 * ---------------------------------------------------------------------------
 * * fh_god: only GOD may set or clear the bit
 */

int fh_god(dbref target, dbref player, FLAG flag, int fflags, int reset)
{
    if (!God(player))
        return 0;
    return (fh_any(target, player, flag, fflags, reset));
}

/*
 * ---------------------------------------------------------------------------
 * * fh_wiz: only WIZARDS (or GOD) may set or clear the bit
 */

int fh_wiz(dbref target, dbref player, FLAG flag, int fflags, int reset)
{
    if (!Wizard(player) && !God(player))
        return 0;
    return (fh_any(target, player, flag, fflags, reset));
}

/*
 * ---------------------------------------------------------------------------
 * * fh_wizroy: only WIZARDS, ROYALTY, (or GOD) may set or clear the bit
 */

int fh_wizroy(dbref target, dbref player, FLAG flag, int fflags, int reset)
{
    if (!WizRoy(player) && !God(player))
        return 0;
    return (fh_any(target, player, flag, fflags, reset));
}

/*
 * ---------------------------------------------------------------------------
 * * fh_restrict_player (renamed from fh_fixed): Only Wizards can set
 * * this on players, but ordinary players can set it on other types
 * * of objects.
 */
int fh_restrict_player
(
    dbref target,
    dbref player,
    FLAG flag,
    int fflags,
    int reset
)
{
    if (  isPlayer(target)
       && !Wizard(player)
       && !God(player))
    {
        return 0;
    }
    return fh_any(target, player, flag, fflags, reset);
}

/* ---------------------------------------------------------------------------
 * fh_privileged: You can set this flag on a non-player object, if you
 * yourself have this flag and are a player who owns themselves (i.e.,
 * no robots). Only God can set this on a player.
 */
int fh_privileged
(
    dbref target,
    dbref player,
    FLAG flag,
    int fflags,
    int reset
)
{
    int has_it;
    
    if (!God(player))
    {
        if (!isPlayer(player) || (player != Owner(player)))
        {
            return 0;
        }
        if (isPlayer(target))
        {
            return 0;
        }
        
        if (fflags & FLAG_WORD3)
        {
            has_it = (Flags3(player) & flag) ? 1 : 0;
        }
        else if (fflags & FLAG_WORD2)
        {
            has_it = (Flags2(player) & flag) ? 1 : 0;
        }
        else
        {
            has_it = (Flags(player) & flag) ? 1 : 0;
        }
        
        if (!has_it)
        {
            return 0;
        }
    }
    return fh_any(target, player, flag, fflags, reset);
}

/*
 * ---------------------------------------------------------------------------
 * * fh_inherit: only players may set or clear this bit.
 */

int fh_inherit(dbref target, dbref player, FLAG flag, int fflags, int reset)
{
    if (!Inherits(player))
        return 0;
    return (fh_any(target, player, flag, fflags, reset));
}

/*
 * ---------------------------------------------------------------------------
 * * fh_dark_bit: manipulate the dark bit. Nonwizards may not set on players.
 */

int fh_dark_bit(dbref target, dbref player, FLAG flag, int fflags, int reset)
{
    if (  !reset
       && isPlayer(target)
       && !(  (target == player)
           && Can_Hide(player))
       && !Wizard(player)
       && !God(player))
    {
        return 0;
    }
    return fh_any(target, player, flag, fflags, reset);
}

/*
 * ---------------------------------------------------------------------------
 * * fh_going_bit: manipulate the going bit.  Non-gods may only clear on rooms.
 */

int fh_going_bit(dbref target, dbref player, FLAG flag, int fflags, int reset)
{
    if (  Going(target)
       && reset
       && (Typeof(target) != TYPE_GARBAGE))
    {
        notify(player, "Your object has been spared from destruction.");
        return fh_any(target, player, flag, fflags, reset);
    }
    if (!God(player))
    {
        return 0;
    }

    // Even God should not be allowed set protected dbrefs GOING.
    //
    if (  !reset
       && (  target == 0
          || target == God(target)
          || target == mudconf.start_home
          || target == mudconf.start_room
          || target == mudconf.default_home
          || target == mudconf.master_room))
    {
        return 0;
    }
    return fh_any(target, player, flag, fflags, reset);
}

/*
 * ---------------------------------------------------------------------------
 * * fh_hear_bit: set or clear bits that affect hearing.
 */

int fh_hear_bit(dbref target, dbref player, FLAG flag, int fflags, int reset)
{
    int could_hear;

    if (isPlayer(target) && (flag & MONITOR))
    {
        if (Can_Monitor(player))
            fh_any(target, player, flag, fflags, reset);
        else
            return 0;
    }

    could_hear = Hearer(target);
    fh_any(target, player, flag, fflags, reset);
    handle_ears(target, could_hear, Hearer(target));
    return 1;
}

/* ---------------------------------------------------------------------------
 * fh_player_bit: Can set and reset this on everything but players.
 */
int fh_player_bit
(
    dbref target,
    dbref player,
    FLAG flag,
    int fflags,
    int reset
)
{
    if (isPlayer(target))
    {
        return 0;
    }
    return fh_any(target, player, flag, fflags, reset);
}

/* ---------------------------------------------------------------------------
 * fh_staff: only STAFF, WIZARDS, ROYALTY, (or GOD) may set or clear
 * the bit.
 */
int fh_staff
(
    dbref target,
    dbref player,
    FLAG flag,
    int fflags,
    int reset
)
{
    if (!Staff(player) && !God(player))
        return 0;
    return (fh_any(target, player, flag, fflags, reset));
}

FLAGENT gen_flags[] =
{ 
    {"ABODE",           ABODE,        'A',    FLAG_WORD2, 0,                    fh_any},
    {"ANSI",            ANSI,         'X',    FLAG_WORD2, 0,                    fh_any},
    {"AUDITORIUM",      AUDITORIUM,   'b',    FLAG_WORD2, 0,                    fh_any},
    {"COMPRESS",        COMPRESS,     '.',    FLAG_WORD2, 0,                    fh_any},
    {"CHOWN_OK",        CHOWN_OK,     'C',    0,          0,                    fh_any},
    {"HAS_DAILY",       HAS_DAILY,    '*',    FLAG_WORD2, CA_GOD|CA_NO_DECOMP,  fh_god},
    {"PLAYER_MAILS",    PLAYER_MAILS, 'B',    FLAG_WORD2, CA_GOD|CA_NO_DECOMP,  fh_god},
    {"DARK",            DARK,         'D',    0,          0,                    fh_dark_bit},
    {"FLOATING",        FLOATING,     'F',    FLAG_WORD2, 0,                    fh_any},
    {"GAGGED",          GAGGED,       'j',    FLAG_WORD2, 0,                    fh_wiz},
    {"GOING",           GOING,        'G',    0,          CA_NO_DECOMP,         fh_going_bit},
    {"HAVEN",           HAVEN,        'H',    0,          0,                    fh_any},
    {"HEAD",            HEAD_FLAG,    '?',    FLAG_WORD2, 0,                    fh_wiz},
    {"INHERIT",         INHERIT,      'I',    0,          0,                    fh_inherit},
    {"JUMP_OK",         JUMP_OK,      'J',    0,          0,                    fh_any},
    {"KEY",             KEY,          'K',    FLAG_WORD2, 0,                    fh_any},
    {"LINK_OK",         LINK_OK,      'L',    0,          0,                    fh_any},
    {"MONITOR",         MONITOR,      'M',    0,          0,                    fh_hear_bit},
    {"NOSPOOF",         NOSPOOF,      'N',    0,          0,                    fh_any},
    {"OPAQUE",          TM_OPAQUE,    'O',    0,          0,                    fh_any},
    {"QUIET",           QUIET,        'Q',    0,          0,                    fh_any},
    {"STAFF",           STAFF,        'w',    FLAG_WORD2, 0,                    fh_wiz},
    {"STICKY",          STICKY,       'S',    0,          0,                    fh_any},
    {"TRACE",           TRACE,        'T',    0,          0,                    fh_any},
    {"UNFINDABLE",      UNFINDABLE,   'U',    FLAG_WORD2, 0,                    fh_any},
    {"VISUAL",          VISUAL,       'V',    0,          0,                    fh_any},
    {"VACATION",        VACATION,     '|',    FLAG_WORD2, 0,                    fh_restrict_player},
    {"WIZARD",          WIZARD,       'W',    0,          0,                    fh_god},
    {"PARENT_OK",       PARENT_OK,    'Y',    FLAG_WORD2, 0,                    fh_any},
    {"ROYALTY",         ROYALTY,      'Z',    0,          0,                    fh_wiz},
    {"FIXED",           FIXED,        'f',    FLAG_WORD2, 0,                    fh_restrict_player}, 
    {"UNINSPECTED",     UNINSPECTED,  'g',    FLAG_WORD2, 0,                    fh_wizroy},
    {"NO_COMMAND",      NO_COMMAND,   'n',    FLAG_WORD2, 0,                    fh_any},
    {"NOBLEED",         NOBLEED,      '-',    FLAG_WORD2, 0,                    fh_any},
    {"AUDIBLE",         HEARTHRU,     'a',    0,          0,                    fh_hear_bit},
    {"CONNECTED",       CONNECTED,    'c',    FLAG_WORD2, CA_NO_DECOMP,         fh_god},
    {"DESTROY_OK",      DESTROY_OK,   'd',    0,          0,                    fh_any},
    {"ENTER_OK",        ENTER_OK,     'e',    0,          0,                    fh_any},
    {"HALTED",          HALT,         'h',    0,          0,                    fh_any},
    {"IMMORTAL",        IMMORTAL,     'i',    0,          0,                    fh_wiz},
    {"LIGHT",           LIGHT,        'l',    FLAG_WORD2, 0,                    fh_any},
    {"MYOPIC",          MYOPIC,       'm',    0,          0,                    fh_any},
    {"PUPPET",          PUPPET,       'p',    0,          0,                    fh_hear_bit},
    {"TERSE",           TERSE,        'q',    0,          0,                    fh_any},
    {"ROBOT",           ROBOT,        'r',    0,          0,                    fh_player_bit},
    {"SAFE",            SAFE,         's',    0,          0,                    fh_any},
    {"TRANSPARENT",     SEETHRU,      't',    0,          0,                    fh_any},
    {"SUSPECT",         SUSPECT,      'u',    FLAG_WORD2, CA_WIZARD,            fh_wiz},
    {"VERBOSE",         VERBOSE,      'v',    0,          0,                    fh_any},
    {"SLAVE",           SLAVE,        'x',    FLAG_WORD2, CA_WIZARD,            fh_wiz},
    {"HAS_STARTUP",     HAS_STARTUP,  '+',    0,          CA_GOD|CA_NO_DECOMP,  fh_god},
    {"HAS_FORWARDLIST", HAS_FWDLIST,  '&',    FLAG_WORD2, CA_GOD|CA_NO_DECOMP,  fh_god},
    {"HAS_LISTEN",      HAS_LISTEN,   '@',    FLAG_WORD2, CA_GOD|CA_NO_DECOMP,  fh_god},
    {"HTML",            HTML,         '(',    FLAG_WORD2, 0,                    fh_any},
#ifdef WOD_REALMS
    {"OBF",             OBF,          'o',    FLAG_WORD3, CA_ADMIN|CA_STAFF,    fh_wizroy},
    {"HSS",             HSS,          'k',    FLAG_WORD3, CA_ADMIN|CA_STAFF,    fh_wizroy},
    {"UMBRA",           UMBRA,        'y',    FLAG_WORD3, CA_ADMIN|CA_STAFF,    fh_wizroy},
    {"SHROUD",          SHROUD,       '$',    FLAG_WORD3, CA_ADMIN|CA_STAFF,    fh_wizroy},
    {"MATRIX",          MATRIX,       '/',    FLAG_WORD3, CA_ADMIN|CA_STAFF,    fh_wizroy},
    {"MEDIUM",          MEDIUM,       '^',    FLAG_WORD3, CA_ADMIN|CA_STAFF,    fh_wizroy},
    {"DEAD",            DEAD,         '_',    FLAG_WORD3, CA_ADMIN|CA_STAFF,    fh_wizroy},
    {"FAE",             FAE,          '0',    FLAG_WORD3, CA_ADMIN|CA_STAFF,    fh_wizroy},
    {"CHIMERA",         CHIMERA,      '1',    FLAG_WORD3, CA_ADMIN|CA_STAFF,    fh_wizroy},
    {"PEERING",         PEERING,      '2',    FLAG_WORD3, CA_ADMIN|CA_STAFF,    fh_wizroy},
#endif
    { NULL,             0,            ' ',    0,          0,                    NULL}
};

#endif  /* STANDALONE */

OBJENT object_types[8] =
{
    {"ROOM",    'R', CA_PUBLIC, OF_CONTENTS|OF_EXITS|OF_DROPTO|OF_HOME},
    {"THING",   ' ', CA_PUBLIC, OF_CONTENTS|OF_LOCATION|OF_EXITS|OF_HOME|OF_SIBLINGS},
    {"EXIT",    'E', CA_PUBLIC, OF_SIBLINGS},
    {"PLAYER",  'P', CA_PUBLIC, OF_CONTENTS|OF_LOCATION|OF_EXITS|OF_HOME|OF_OWNER|OF_SIBLINGS},
    {"TYPE5",   '+', CA_GOD,    0},
    {"GARBAGE", '-', CA_PUBLIC, OF_CONTENTS|OF_LOCATION|OF_EXITS|OF_HOME|OF_SIBLINGS},
    {"GARBAGE", '#', CA_GOD,    0}
};

#ifndef STANDALONE

/*
 * ---------------------------------------------------------------------------
 * * init_flagtab: initialize flag hash tables.
 */

void NDECL(init_flagtab)
{
    char *nbuf = alloc_sbuf("init_flagtab");
    for (FLAGENT *fp = gen_flags; fp->flagname; fp++)
    {
        strncpy(nbuf, fp->flagname, SBUF_SIZE);
        nbuf[SBUF_SIZE-1] = '\0';
        _strlwr(nbuf);
        hashaddLEN(nbuf, strlen(nbuf), (int *)fp, &mudstate.flags_htab);
    }
    free_sbuf(nbuf);
}

/*
 * ---------------------------------------------------------------------------
 * * display_flags: display available flags.
 */

void display_flagtab(dbref player)
{
    char *buf, *bp;
    FLAGENT *fp;

    bp = buf = alloc_lbuf("display_flagtab");
    safe_str((char *)"Flags:", buf, &bp);
    for (fp = gen_flags; fp->flagname; fp++) {
        if ((fp->listperm & CA_WIZARD) && !Wizard(player))
            continue;
        if ((fp->listperm & CA_GOD) && !God(player))
            continue;
        safe_chr(' ', buf, &bp);
        safe_str((char *)fp->flagname, buf, &bp);
        safe_chr('(', buf, &bp);
        safe_chr(fp->flaglett, buf, &bp);
        safe_chr(')', buf, &bp);
    }
    *bp = '\0';
    notify(player, buf);
    free_lbuf(buf);
}

char *MakeCanonicalFlagName
(
    const char *pName,
    int *pnName,
    BOOL *pbValid
)
{
    static char buff[SBUF_SIZE];
    char *p = buff;
    int nName = 0;

    while (*pName && nName < SBUF_SIZE)
    {
        *p = Tiny_ToLower[(unsigned char)*pName];
        p++;
        pName++;
        nName++;
    }
    *p = '\0';
    if (nName < SBUF_SIZE)
    {
        *pnName = nName;
        *pbValid = TRUE;
        return buff;
    }
    else
    {
        *pnName = 0;
        *pbValid = FALSE;
        return NULL;
    }
}

FLAGENT *find_flag(dbref thing, char *flagname)
{
    // Convert flagname to canonical lowercase format.
    //
    int nName;
    BOOL bValid;
    char *pName = MakeCanonicalFlagName(flagname, &nName, &bValid);
    FLAGENT *fe = NULL;
    if (bValid)
    {
        fe = (FLAGENT *)hashfindLEN(pName, nName, &mudstate.flags_htab);
    }
    return fe;
}

/*
 * ---------------------------------------------------------------------------
 * * flag_set: Set or clear a specified flag on an object. 
 */

void flag_set(dbref target, dbref player, char *flag, int key)
{
    FLAGENT *fp;
    int negate, result;

    /*
     * Trim spaces, and handle the negation character 
     */

    negate = 0;
    while (Tiny_IsSpace[(unsigned char)*flag])
        flag++;

    if (*flag == '!')
    {
        negate = 1;
        flag++;
    }
    while (Tiny_IsSpace[(unsigned char)*flag])
        flag++;

    // Make sure a flag name was specified.
    //
    if (*flag == '\0')
    {
        if (negate)
            notify(player, "You must specify a flag to clear.");
        else
            notify(player, "You must specify a flag to set.");
        return;
    }
    fp = find_flag(target, flag);
    if (fp == NULL)
    {
        notify(player, "I don't understand that flag.");
        return;
    }
    /*
     * Invoke the flag handler, and print feedback 
     */

    result = fp->handler(target, player, fp->flagvalue, fp->flagflag, negate);
    if (!result)
        notify(player, "Permission denied.");
    else if (!(key & SET_QUIET) && !Quiet(player))
        notify(player, (negate ? "Cleared." : "Set."));
    return;
}

/*
 * ---------------------------------------------------------------------------
 * * decode_flags: converts a flags word into corresponding letters.
 */

char *decode_flags(dbref player, FLAG flagword, FLAG flag2word, FLAG flag3word)
{
    char *buf, *bp;
    FLAGENT *fp;
    int flagtype;
    FLAG fv;

    buf = bp = alloc_sbuf("decode_flags");
    *bp = '\0';

    if (!Good_obj(player))
    {
        StringCopy(buf, "#-2 ERROR");
        return buf;
    }
    flagtype = (flagword & TYPE_MASK);
    if (object_types[flagtype].lett != ' ')
    {
        safe_sb_chr(object_types[flagtype].lett, buf, &bp);
    }

    for (fp = gen_flags; fp->flagname; fp++)
    {
        if (fp->flagflag & FLAG_WORD3)
        {
            fv = flag3word;
        }
        else if (fp->flagflag & FLAG_WORD2)
        {
            fv = flag2word;
        }
        else
        {
            fv = flagword;
        }
        if (fv & fp->flagvalue)
        {
            if ((fp->listperm & CA_WIZARD) && !Wizard(player))
            {
                continue;
            }
            if ((fp->listperm & CA_GOD) && !God(player))
            {
                continue;
            }

            // Don't show CONNECT on dark wizards to mortals 
            //
            if (  isPlayer(player)
               && (fp->flagvalue == CONNECTED)
               && (fp->flagflag & FLAG_WORD2)
               && ((flagword & (WIZARD | DARK)) == (WIZARD | DARK))
               && !Wizard(player))
            {
                continue;
            }
            safe_sb_chr(fp->flaglett, buf, &bp);
        }
    }

    *bp = '\0';
    return buf;
}

/*
 * ---------------------------------------------------------------------------
 * * has_flag: does object have flag visible to player?
 */

int has_flag(dbref player, dbref it, char *flagname)
{
    FLAGENT *fp = find_flag(it, flagname);
    if (!fp)
    {
        return 0;
    }

    FLAG fv;
    if (fp->flagflag & FLAG_WORD3)
    {
        fv = Flags3(it);
    }
    else if (fp->flagflag & FLAG_WORD2)
    {
        fv = Flags2(it);
    }
    else
    {
        fv = Flags(it);
    }

    if (fv & fp->flagvalue)
    {
        if ((fp->listperm & CA_WIZARD) && !Wizard(player))
        {
            return 0;
        }
        if ((fp->listperm & CA_GOD) && !God(player))
        {
            return 0;
        }

        // Don't show CONNECT on dark wizards to mortals 
        //
        if (  isPlayer(it)
           && (fp->flagvalue == CONNECTED)
           && (fp->flagflag & FLAG_WORD2)
           && ((Flags(it) & (WIZARD | DARK)) == (WIZARD | DARK))
           && !Wizard(player))
        {
            return 0;
        }
        return 1;
    }
    return 0;
}

/*
 * ---------------------------------------------------------------------------
 * * flag_description: Return an mbuf containing the type and flags on thing.
 */

char *flag_description(dbref player, dbref target)
{
    char *buff, *bp;
    FLAGENT *fp;
    int otype;
    FLAG fv;

    // Allocate the return buffer.
    //
    otype = Typeof(target);
    bp = buff = alloc_mbuf("flag_description");

    // Store the header strings and object type.
    //
    safe_mb_str((char *)"Type: ", buff, &bp);
    safe_mb_str((char *)object_types[otype].name, buff, &bp);
    safe_mb_str((char *)" Flags:", buff, &bp);
    if (object_types[otype].perm != CA_PUBLIC)
    {
        *bp = '\0';
        return buff;
    }

    // Store the type-invariant flags.
    //
    for (fp = gen_flags; fp->flagname; fp++)
    {
        if (fp->flagflag & FLAG_WORD3)
            fv = Flags3(target);
        else if (fp->flagflag & FLAG_WORD2)
            fv = Flags2(target);
        else
            fv = Flags(target);

        if (fv & fp->flagvalue) 
        {
            if ((fp->listperm & CA_WIZARD) && !Wizard(player))
                continue;
            if ((fp->listperm & CA_GOD) && !God(player))
                continue;
            /*
             * don't show CONNECT on dark wizards to mortals 
             */
            if (  isPlayer(target)
               && (fp->flagvalue == CONNECTED)
               && (fp->flagflag & FLAG_WORD2)
               && ((Flags(target) & (WIZARD | DARK)) == (WIZARD | DARK))
               && !Wizard(player))
            {
                continue;
            }
            safe_mb_chr(' ', buff, &bp);
            safe_mb_str((char *)fp->flagname, buff, &bp);
        }
    }

    // Terminate the string, and return the buffer to the caller.
    //
    *bp = '\0';
    return buff;
}

/*
 * ---------------------------------------------------------------------------
 * * Return an lbuf containing the name and number of an object
 */

char *unparse_object_numonly(dbref target)
{
    char *buf;

    buf = alloc_lbuf("unparse_object_numonly");
    if (target < 0)
    {
        strcpy(buf, aszSpecialDBRefNames[-target]);
    }
    else if (!Good_obj(target))
    {
        sprintf(buf, "*ILLEGAL*(#%d)", target);
    }
    else
    {
        sprintf(buf, "%s(#%d)", Name(target), target);
    }
    return buf;
}

/*
 * ---------------------------------------------------------------------------
 * * Return an lbuf pointing to the object name and possibly the db# and flags
 */
char *unparse_object(dbref player, dbref target, int obey_myopic)
{
    char *buf, *fp;
    int exam;

    buf = alloc_lbuf("unparse_object");
    if (target < 0)
    {
        strcpy(buf, aszSpecialDBRefNames[-target]);
    }
    else if (!Good_obj(target))
    {
        sprintf(buf, "*ILLEGAL*(#%d)", target);
    }
    else
    {
        if (obey_myopic)
        {
            exam = MyopicExam(player, target);
        }
        else
        {
            exam = Examinable(player, target);
        }
        if (  exam
           || (Flags(target) & (CHOWN_OK | JUMP_OK | LINK_OK | DESTROY_OK))
           || (Flags2(target) & ABODE))
        {
            // show everything
            //
            fp = unparse_flags(player, target);
            sprintf(buf, "%s(#%d%s)", Name(target), target, fp);
            free_sbuf(fp);
        }
        else
        {
            // show only the name.
            //
            strcpy(buf, Name(target));
        }
    }
    return buf;
}

/* ---------------------------------------------------------------------------
* cf_flag_access: Modify who can set a flag.
*/

CF_HAND(cf_flag_access)
{
    TINY_STRTOK_STATE tts;
    Tiny_StrTokString(&tts, str);
    Tiny_StrTokControl(&tts, " \t=,");
    char *fstr = Tiny_StrTokParse(&tts);
    char *permstr = Tiny_StrTokParse(&tts);
    
    if (!fstr || !*fstr)
    {
        return -1;
    }
    
    FLAGENT *fp;
    if ((fp = find_flag(GOD, fstr)) == NULL)
    {
        cf_log_notfound(player, cmd, "No such flag", fstr);
        return -1;
    }
    
    // Don't change the handlers on special things.
    //
    if (  (fp->handler != fh_any)
       && (fp->handler != fh_wizroy)
       && (fp->handler != fh_wiz)
       && (fp->handler != fh_god)
       && (fp->handler != fh_restrict_player)
       && (fp->handler != fh_privileged))
    {
        STARTLOG(LOG_CONFIGMODS, "CFG", "PERM");
        log_text((char *) "Cannot change access for flag: ");
        log_text((char *) fp->flagname);
        ENDLOG;
        return -1;
    }
    
    if (!strcmp(permstr, (char *) "any"))
    {
        fp->handler = fh_any;
    }
    else if (!strcmp(permstr, (char *) "royalty"))
    {
        fp->handler = fh_wizroy;
    }
    else if (!strcmp(permstr, (char *) "wizard"))
    {
        fp->handler = fh_wiz;
    }
    else if (!strcmp(permstr, (char *) "god"))
    {
        fp->handler = fh_god;
    }
    else if (!strcmp(permstr, (char *) "restrict_player"))
    {
        fp->handler = fh_restrict_player;
    }
    else if (!strcmp(permstr, (char *) "privileged"))
    {
        fp->handler = fh_privileged;
    }
    else if (!strcmp(permstr, (char *) "staff"))
    {
        fp->handler = fh_staff;
    }
    else
    {
        cf_log_notfound(player, cmd, "Flag access", permstr);
        return -1;
    }
    return 0;
}

/*
 * ---------------------------------------------------------------------------
 * * convert_flags: convert a list of flag letters into its bit pattern.
 * * Also set the type qualifier if specified and not already set.
 */

int convert_flags(dbref player, char *flaglist, FLAGSET *fset, FLAG *p_type)
{
    int i, handled;
    char *s;
    FLAG flag1mask, flag2mask, flag3mask, type;
    FLAGENT *fp;

    flag1mask = flag2mask = flag3mask = 0;
    type = NOTYPE;

    for (s = flaglist; *s; s++) {
        handled = 0;

        /*
         * Check for object type 
         */

        for (i = 0; (i <= 7) && !handled; i++) {
            if ((object_types[i].lett == *s) &&
                !(((object_types[i].perm & CA_WIZARD) &&
                   !Wizard(player)) ||
                  ((object_types[i].perm & CA_GOD) &&
                   !God(player)))) {
                if ((type != NOTYPE) && (type != i)) {
                    notify(player,
                           tprintf("%c: Conflicting type specifications.",
                               *s));
                    return 0;
                }
                type = i;
                handled = 1;
            }
        }

        /*
         * Check generic flags 
         */

        if (handled)
            continue;
        for (fp = gen_flags; (fp->flagname) && !handled; fp++) {
            if ((fp->flaglett == *s) &&
                !(((fp->listperm & CA_WIZARD) &&
                   !Wizard(player)) ||
                  ((fp->listperm & CA_GOD) &&
                   !God(player)))) {
                if (fp->flagflag & FLAG_WORD3)
                    flag3mask |= fp->flagvalue;
                else if (fp->flagflag & FLAG_WORD2)
                    flag2mask |= fp->flagvalue;
                else
                    flag1mask |= fp->flagvalue;
                handled = 1;
            }
        }

        if (!handled) {
            notify(player,
                   tprintf("%c: Flag unknown or not valid for specified object type",
                       *s));
            return 0;
        }
    }

    /*
     * return flags to search for and type 
     */

    (*fset).word1 = flag1mask;
    (*fset).word2 = flag2mask;
    (*fset).word3 = flag3mask;
    *p_type = type;
    return 1;
}

/*
 * ---------------------------------------------------------------------------
 * * decompile_flags: Produce commands to set flags on target.
 */

void decompile_flags(dbref player, dbref thing, char *thingname)
{
    FLAG f1, f2, f3;
    FLAGENT *fp;

    /*
     * Report generic flags 
     */

    f1 = Flags(thing);
    f2 = Flags2(thing);
    f3 = Flags3(thing);
    
    for (fp = gen_flags; fp->flagname; fp++) {

        /*
         * Skip if we shouldn't decompile this flag 
         */

        if (fp->listperm & CA_NO_DECOMP)
            continue;

        /*
         * Skip if this flag is not set 
         */

        if (fp->flagflag & FLAG_WORD3) {
            if (!(f3 & fp->flagvalue))
                continue;
        } else if (fp->flagflag & FLAG_WORD2) {
            if (!(f2 & fp->flagvalue))
                continue;
        } else {
            if (!(f1 & fp->flagvalue))
                continue;
        }

        /*
         * Skip if we can't see this flag 
         */

        if (!check_access(player, fp->listperm))
            continue;

        /*
         * We made it this far, report this flag 
         */

        notify(player, tprintf("@set %s=%s", strip_ansi(thingname), fp->flagname));
    }
}

#endif /*
    * STANDALONE 
    */