btmux-0.6-rc4/doc/
btmux-0.6-rc4/event/
btmux-0.6-rc4/game/
btmux-0.6-rc4/game/maps/
btmux-0.6-rc4/game/mechs/
btmux-0.6-rc4/game/text/help/
btmux-0.6-rc4/game/text/help/cat_faction/
btmux-0.6-rc4/game/text/help/cat_inform/
btmux-0.6-rc4/game/text/help/cat_misc/
btmux-0.6-rc4/game/text/help/cat_mux/
btmux-0.6-rc4/game/text/help/cat_mux/cat_commands/
btmux-0.6-rc4/game/text/help/cat_mux/cat_functions/
btmux-0.6-rc4/game/text/help/cat_templates/
btmux-0.6-rc4/game/text/wizhelp/
btmux-0.6-rc4/include/
btmux-0.6-rc4/misc/
btmux-0.6-rc4/python/
btmux-0.6-rc4/src/hcode/btech/
btmux-0.6-rc4/tree/
/*
 * flags.c - flag manipulation routines 
 */

#include "copyright.h"
#include "config.h"

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

/**
 * Sets or clears the indicated bit, no security checking.
 * @param target The target object for setting/unsetting
 * @param player The object who is setting/unsetting
 * @param fflags ??
 * @param reset If 1, we're resetting the flag 
 */
int fh_any(dbref target, dbref player, FLAG flag, int fflags, int reset)
{
	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;
}								/* end fh_and() */

/**
 * Function to block out non-GOD for setting or clearing a bit.
 * @param target Target object for setting/unsetting
 * @param player The object that is setting/unsetting
 * @param flag The flag to be manipulated
 * @param fflags ??
 * @param reset If 1, we're resetting the flag 
 */
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));
}								/* end fh_god() */

/**
 * Blocks out non-WIZARDS setting or clearing a bit.
 * @param target Target object for setting/unsetting
 * @param player The object that is setting/unsetting
 * @param flag The flag to be manipulated
 * @param fflags ??
 * @param reset If 1, we're resetting the flag
 */
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));
}								/* end fh_wiz() */

/**
 * Only allows the bit to be set on players by WIZARDS.
 * @param target Target object for setting/unsetting
 * @param player The object that is setting/unsetting
 * @param flag The flag to be manipulated
 * @param fflags ??
 * @param reset If 1, we're resetting the flag
 */
int fh_fixed(dbref target, dbref player, FLAG flag, int fflags, int reset)
{
	if(isPlayer(target))
		if(!Wizard(player) && !God(player))
			return 0;

	return (fh_any(target, player, flag, fflags, reset));
}								/* end fh_fixed() */

/**
 * Only allows WIZARDS, ROYALTY, (or GOD) to set or clear the bit.
 * @param target Target object for setting/unsetting
 * @param player The object that is setting/unsetting
 * @param flag The flag to be manipulated
 * @param fflags ??
 * @param reset If 1, we're resetting the flag
 */

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

/**
 * Only allows players to set or clear this bit.
 * @param target Target object for setting/unsetting
 * @param player The object that is setting/unsetting
 * @param flag The flag to be manipulated
 * @param fflags ??
 * @param reset If 1, we're resetting the flag
 */
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));
}								/* end fh_inherit() */

/**
 * Only allows GOD to set/clear this bit. Used for WIZARD flag.
 * @param target Target object for setting/unsetting
 * @param player The object that is setting/unsetting
 * @param flag The flag to be manipulated
 * @param fflags ??
 * @param reset If 1, we're resetting the flag
 */
int fh_wiz_bit(dbref target, dbref player, FLAG flag, int fflags, int reset)
{
	if(!God(player))
		return 0;
	if(God(target) && reset) {
		notify(player, "You cannot make yourself mortal.");
		return 0;
	}

	return (fh_any(target, player, flag, fflags, reset));
}								/* end fh_wiz_bit() */

/**
 * Manipulates the dark bit. Non-Wizards may not set on players.
 * @param target Target object for setting/unsetting
 * @param player The object that is setting/unsetting
 * @param flag The flag to be manipulated
 * @param fflags ??
 * @param reset If 1, we're resetting the flag
 */
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));
}								/* end fh_dark_bit() */

/**
 * Manipulates the going bit.
 * @param target Target object for setting/unsetting
 * @param player The object that is setting/unsetting
 * @param flag The flag to be manipulated
 * @param fflags ??
 * @param reset If 1, we're resetting the flag
 */
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;

	return (fh_any(target, player, flag, fflags, reset));
}								/* end fh_going_bit() */

/**
 * Sets or clears bits that affect hearing.
 * @param target Target object for setting/unsetting
 * @param player The object that is setting/unsetting
 * @param flag The flag to be manipulated
 * @param fflags ??
 * @param reset If 1, we're resetting the flag
 */
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;
}								/* end fh_hear_bit() */

/**
 * Sets or clears bits that affect xcode in glue.h.
 * @param target Target object for setting/unsetting
 * @param player The object that is setting/unsetting
 * @param flag The flag to be manipulated
 * @param fflags ??
 * @param reset If 1, we're resetting the flag
 */
int fh_xcode_bit(dbref target, dbref player, FLAG flag, int fflags, int reset)
{
	int got_xcode;
	int new_xcode;

	got_xcode = Hardcode(target);
	fh_wiz(target, player, flag, fflags, reset);
	new_xcode = Hardcode(target);
	handle_xcode(player, target, got_xcode, new_xcode);

	return 1;
}								/* end fh_xcode_bit() */

/** 
 * Alphabetized flag listing 
 * 0 = Flag's visible name
 * 1 = Flag's bit representation
 * 2 = Flag's letter alias
 * 3 = Flag's wordspace
 * 4 = Who may see the flag (0 = all) 
 * 5 = Permissions
 */
FLAGENT gen_flags[] = {
	{"ABODE", ABODE, 'A',
	 FLAG_WORD2, 0, fh_any}
	,
	{"ANSI", ANSI, 'X',
	 FLAG_WORD2, 0, fh_any}
	,
	{"ANSIMAP", ANSIMAP, 'P',
	 FLAG_WORD2, 0, fh_any}
	,
	{"AUDIBLE", HEARTHRU, 'a',
	 0, 0, fh_hear_bit}
	,
	{"AUDITORIUM", AUDITORIUM, 'b',
	 FLAG_WORD2, 0, fh_any}
	,
	{"COMPRESS", COMPRESS, '.',
	 FLAG_WORD2, 0, fh_any}
	,
	{"CONNECTED", CONNECTED, 'c',
	 FLAG_WORD2, CA_NO_DECOMP, fh_god}
	,
	{"CHOWN_OK", CHOWN_OK, 'C',
	 0, 0, fh_any}
	,
	{"DARK", DARK, 'D',
	 0, 0, fh_dark_bit}
	,
	{"DESTROY_OK", DESTROY_OK, 'd',
	 0, 0, fh_any}
	,
	{"ENTER_OK", ENTER_OK, 'e',
	 0, 0, fh_any}
	,
	{"FIXED", FIXED, 'f',
	 FLAG_WORD2, 0, fh_fixed}
	,
	{"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}
	,
	{"HALTED", HALT, 'h',
	 0, 0, fh_any}
	,
	{"HAS_DAILY", HAS_DAILY, '*',
	 FLAG_WORD2, CA_GOD | CA_NO_DECOMP, fh_god}
	,
	{"HAS_FORWARDLIST", HAS_FWDLIST, '&',
	 FLAG_WORD2, CA_GOD | CA_NO_DECOMP, fh_god}
	,
	{"HAS_HOURLY", HAS_HOURLY, '*',
	 FLAG_WORD2, CA_GOD | CA_NO_DECOMP, fh_god}
	,
	{"HAS_LISTEN", HAS_LISTEN, '@',
	 FLAG_WORD2, CA_GOD | CA_NO_DECOMP, fh_god}
	,
	{"HAS_STARTUP", HAS_STARTUP, '+',
	 0, CA_GOD | CA_NO_DECOMP, fh_god}
	,
	{"HAVEN", HAVEN, 'H',
	 0, 0, fh_any}
	,
	{"HEAD", HEAD_FLAG, '?',
	 FLAG_WORD2, 0, fh_wiz}
	,
	{"BLIND", BLIND, '(',
	 FLAG_WORD2, 0, fh_any}
	,
	{"IMMORTAL", IMMORTAL, 'i',
	 0, 0, fh_wiz}
	,
	{"IN_CHARACTER", IN_CHARACTER, '#',
	 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}
	,
	{"LIGHT", LIGHT, 'l',
	 FLAG_WORD2, 0, fh_any}
	,
	{"LINK_OK", LINK_OK, 'L',
	 0, 0, fh_any}
	,
	{"MONITOR", MONITOR, 'M',
	 0, 0, fh_hear_bit}
	,
	{"MULTIOK", MULTIOK, 'y',
	 FLAG_WORD2, CA_WIZARD, fh_wiz}
	,
	{"MYOPIC", MYOPIC, 'm',
	 0, 0, fh_any}
	,
	{"NOBLEED", NOBLEED, '-',
	 FLAG_WORD2, 0, fh_any}
	,
	{"NO_COMMAND", NO_COMMAND, 'n',
	 FLAG_WORD2, 0, fh_any}
	,
	{"NOSPOOF", NOSPOOF, 'N',
	 0, 0, fh_any}
	,
	{"OPAQUE", OPAQUE, 'O',
	 0, 0, fh_any}
	,
	{"PARENT_OK", PARENT_OK, 'Y',
	 FLAG_WORD2, 0, fh_any}
	,
	{"PLAYER_MAILS", PLAYER_MAILS, 'B',
	 FLAG_WORD2, CA_GOD | CA_NO_DECOMP, fh_god}
	,
	{"PUPPET", PUPPET, 'p',
	 0, 0, fh_hear_bit}
	,
	{"QUIET", QUIET, 'Q',
	 0, 0, fh_any}
	,
	{"ROBOT", ROBOT, 'r',
	 0, 0, fh_any}
	,
	{"ROYALTY", ROYALTY, 'Z',
	 0, 0, fh_wiz}
	,
	{"SAFE", SAFE, 's',
	 0, 0, fh_any}
	,
	{"SLAVE", SLAVE, 'x',
	 FLAG_WORD2, CA_WIZARD, fh_wiz}
	,
	{"STAFF", STAFF, 'w',
	 FLAG_WORD2, 0, fh_wiz}
	,
	{"STICKY", STICKY, 'S',
	 0, 0, fh_wiz}
	,
	{"SUSPECT", SUSPECT, 'u',
	 FLAG_WORD2, CA_WIZARD, fh_wiz}
	,
	{"TERSE", TERSE, 'q',
	 0, 0, fh_any}
	,
	{"TRACE", TRACE, 'T',
	 0, 0, fh_any}
	,
	{"TRANSPARENT", SEETHRU, 't',
	 0, 0, fh_any}
	,
	{"UNFINDABLE", UNFINDABLE, 'U',
	 FLAG_WORD2, 0, fh_any}
	,
	{"UNINSPECTED", UNINSPECTED, 'g',
	 FLAG_WORD2, 0, fh_wizroy}
	,
	{"VERBOSE", VERBOSE, 'v',
	 0, 0, fh_any}
	,
	{"VISUAL", VISUAL, 'V',
	 0, 0, fh_any}
	,
	{"VACATION", VACATION, '|',
	 FLAG_WORD2, 0, fh_fixed}
	,
	{"WIZARD", WIZARD, 'W',
	 0, 0, fh_wiz_bit}
	,
	{"XCODE", HARDCODE, 'X',
	 FLAG_WORD2, 0, fh_xcode_bit}
	,
	{"ZOMBIE", ZOMBIE, 'z',
	 FLAG_WORD2, CA_WIZARD, fh_wiz}
	,
	{NULL, 0, ' ',
	 0, 0, NULL}
};

/** 
 * Listing of valid object types 
 */
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}
};

/**
 * Initializes flag hash tables.
 */
void init_flagtab(void)
{
	FLAGENT *fp;
	char *nbuf, *np, *bp;

	hashinit(&mudstate.flags_htab, 100 * HASH_FACTOR);
	nbuf = alloc_sbuf("init_flagtab");

	for(fp = gen_flags; fp->flagname; fp++) {
		for(np = nbuf, bp = (char *) fp->flagname; *bp; np++, bp++)
			*np = ToLower(*bp);
		*np = '\0';
		hashadd(nbuf, (int *) fp, &mudstate.flags_htab);
	}

	free_sbuf(nbuf);
}								/* end init_flagtab() */

/**
 * Displays available flags. Used in @list 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);
}								/* end display_flagtab() */

/**
 * ??
 */
FLAGENT *find_flag(dbref thing, char *flagname)
{
	char *cp;

	/* Make sure the flag name is valid */
	for(cp = flagname; *cp; cp++)
		*cp = ToLower(*cp);

	return (FLAGENT *) hashfind(flagname, &mudstate.flags_htab);
}								/* end find_flag() */

/**
 * Sets or clears a specified flag on an object. 
 * @param target Target object
 * @param player The object doing the setting
 * @paran flag The flag being set/unset
 * @param key Are we @set/quiet'in?
 */
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 (*flag && isspace(*flag))
		flag++;
	if(*flag == '!') {
		negate = 1;
		flag++;
	}
	while (*flag && isspace(*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_printf(player, "%s - %s %s", Name(target), fp->flagname,
					  negate ? "cleared." : "set.");
	return;
}								/* end flag_set() */

/**
 * Converts a flags word into corresponding letters.
 * @param player The invoking object
 * @param flagword ??
 * @param flag2word ??
 * @param flag3word ??
 */
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((flagtype == TYPE_PLAYER) && (fp->flagvalue == CONNECTED)
			   && ((flagword & (WIZARD | DARK)) == (WIZARD | DARK)) &&
			   !Wizard(player))
				continue;
			safe_sb_chr(fp->flaglett, buf, &bp);
		}
	}

	*bp = '\0';
	return buf;
}								/* end decode_flags() */

/**
 * Does object have flag visible to player?
 * @param player The player we're looking for
 * @param target The object with the flag
 * @param flagname The flag in question
 */
int has_flag(dbref player, dbref target, char *flagname)
{
	FLAGENT *fp;
	FLAG fv;

	fp = find_flag(target, flagname);
	if(fp == NULL)
		return 0;

	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))
			return 0;
		if((fp->listperm & CA_GOD) && !God(player))
			return 0;
		/*
		 * don't show CONNECT on dark wizards to mortals 
		 */
		if(isPlayer(target) && (fp->flagvalue == CONNECTED) &&
		   ((Flags(target) & (WIZARD | DARK)) == (WIZARD | DARK)) &&
		   !Wizard(player))
			return 0;
		return 1;
	}
	return 0;
}								/* end has_flag() */

/**
 * Returns an mbuf containing the type and flags on thing.
 * @param player The player to send to
 * @param target The object whose flags we're checking
 */
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) &&
			   ((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;
}								/* end flag_description() */

/**
 * Returns an lbuf containing the name and number of an object.
 * @param target The target object
 */
char *unparse_object_numonly(dbref target)
{
	char *buf;

	buf = alloc_lbuf("unparse_object_numonly");
	if(target == NOTHING) {
		StringCopy(buf, "*NOTHING*");
	} else if(target == HOME) {
		StringCopy(buf, "*HOME*");
	} else if(!Good_obj(target)) {
		sprintf(buf, "*ILLEGAL*(#%d)", target);
	} else {
		sprintf(buf, "%s(#%d)", Name(target), target);
	}
	return buf;
}								/* end unparse_object_numonly() */

/**
 * Returns 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 == NOTHING) {
		StringCopy(buf, "*NOTHING*");
	} else if(target == HOME) {
		StringCopy(buf, "*HOME*");
	} 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%s)", Name(target), target,
					*fp ? ":" : "", fp);
			free_sbuf(fp);
		} else {
			/*
			 * show only the name. 
			 */
			StringCopy(buf, Name(target));
		}
	}
	return buf;
}								/* end unparse_object() */

/**
 * Converts a list of flag letters into its bit pattern.
 * Also set the type qualifier if specified and not already set.
 * @param player The evoking object
 * @param flaglist The list of flags to conver to bit pattern
 * @param fset ??
 * @param p_type ?? 
 */
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_printf(player,
								  "%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_printf(player,
						  "%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;
}								/* end convert_flags() */

/**
 * Produces commands to set flags on target.
 * @param player The evoking object
 * @param thing The target object
 * @param thingname ??
 */
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_printf(player, "@set %s=%s", strip_ansi(thingname),
					  fp->flagname);
	}
}								/* end decompile_flags() */