game/bin/
game/data/
/*
 * powers.c - power manipulation routines 
 */
/*
 * $Id: powers.c,v 1.3 1995/11/22 23:33:17 root Exp $ 
 */

#include "copyright.h"
#include "autoconf.h"

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

#ifndef STANDALONE

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

int ph_any(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
	if (fpowers & POWER_EXT) {
		if (reset)
			s_Powers2(target, Powers2(target) & ~power);
		else
			s_Powers2(target, Powers2(target) | power);
	} else {
		if (reset)
			s_Powers(target, Powers(target) & ~power);
		else
			s_Powers(target, Powers(target) | power);
	}
	return 1;
}

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

int ph_god(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
	if (!God(player))
		return 0;
	return (ph_any(target, player, power, fpowers, reset));
}

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

int ph_wiz(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
	if (!Wizard(player) & !God(player))
		return 0;
	return (ph_any(target, player, power, fpowers, reset));
}

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

int ph_wizroy(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
	if (!WizRoy(player) & !God(player))
		return 0;
	return (ph_any(target, player, power, fpowers, reset));
}

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

int ph_inherit(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
	if (!Inherits(player))
		return 0;
	return (ph_any(target, player, power, fpowers, reset));
}
/* *INDENT-OFF* */
POWERENT gen_powers[] =
{
{(char *)"quota",		POW_CHG_QUOTAS,	0, 0,	ph_wiz},
{(char *)"chown_anything", 	POW_CHOWN_ANY,  0, 0,	ph_wiz},
{(char *)"announce", 		POW_ANNOUNCE,	0, 0,	ph_wiz},
{(char *)"boot",		POW_BOOT,	0, 0,	ph_wiz},
{(char *)"halt",		POW_HALT,	0, 0,	ph_wiz},
{(char *)"control_all",		POW_CONTROL_ALL,0, 0,	ph_god},
{(char *)"expanded_who",	POW_WIZARD_WHO, 0, 0,	ph_wiz},
{(char *)"see_all",		POW_EXAM_ALL,	0, 0,	ph_wiz},
{(char *)"prog",		POW_PROG,	0, 0,	ph_wiz},
{(char *)"find_unfindable",	POW_FIND_UNFIND,0, 0,	ph_wiz},
{(char *)"free_money",		POW_FREE_MONEY, 0, 0,	ph_wiz},
{(char *)"free_quota",		POW_FREE_QUOTA, 0, 0,	ph_wiz},
{(char *)"hide",		POW_HIDE,	0, 0,	ph_wiz},
{(char *)"idle",		POW_IDLE, 	0, 0,	ph_wiz},
{(char *)"search",		POW_SEARCH,	0, 0,	ph_wiz},
{(char *)"long_fingers",	POW_LONGFINGERS,0, 0,	ph_wiz},
{(char *)"comm_all",		POW_COMM_ALL,	0, 0,	ph_wiz},
{(char *)"see_queue",		POW_SEE_QUEUE,	0, 0,	ph_wiz},
{(char *)"see_hidden",		POW_SEE_HIDDEN, 0, 0,	ph_wiz},
{(char *)"monitor",		POW_MONITOR,	0, 0,	ph_wiz},
{(char *)"poll",		POW_POLL,	0, 0,	ph_wiz},
{(char *)"no_destroy",		POW_NO_DESTROY, 0, 0,	ph_wiz},
{(char *)"guest",		POW_GUEST,	0, 0,	ph_god},
{(char *)"set_maint_flags",	POW_SET_MFLAGS, 0, 0,	ph_wiz},
{(char *)"stat_any",		POW_STAT_ANY,	0, 0,	ph_wiz},
{(char *)"steal_money",		POW_STEAL,	0, 0,	ph_wiz},
{(char *)"tel_anywhere",	POW_TEL_ANYWHR, 0, 0,	ph_wiz},
{(char *)"tel_anything",	POW_TEL_UNRST,	0, 0,	ph_wiz},
{(char *)"unkillable",		POW_UNKILLABLE, 0, 0,	ph_wiz},
{(char *)"builder",		POW_BUILDER,	POWER_EXT, 
						   0,	ph_wiz},
{NULL,				0,		0, 0,	0}};

#endif /* STANDALONE */
/* *INDENT-ON* */




#ifndef STANDALONE

/*
 * ---------------------------------------------------------------------------
 * * init_powertab: initialize power hash tables.
 */

void NDECL(init_powertab)
{
	POWERENT *fp;
	char *nbuf, *np, *bp;

	hashinit(&mudstate.powers_htab, 30 * HASH_FACTOR);
	nbuf = alloc_sbuf("init_powertab");
	for (fp = gen_powers; fp->powername; fp++) {
		for (np = nbuf, bp = (char *)fp->powername; *bp; np++, bp++)
			*np = ToLower(*bp);
		*np = '\0';
		hashadd(nbuf, (int *)fp, &mudstate.powers_htab);
	}
	free_sbuf(nbuf);
}

/*
 * ---------------------------------------------------------------------------
 * * display_powers: display available powers.
 */

void display_powertab(player)
dbref player;
{
	char *buf, *bp;
	POWERENT *fp;

	bp = buf = alloc_lbuf("display_powertab");
	safe_str((char *)"Powers:", buf, &bp);
	for (fp = gen_powers; fp->powername; 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->powername, buf, &bp);
	}
	*bp = '\0';
	notify(player, buf);
	free_lbuf(buf);
}

POWERENT *find_power(thing, powername)
dbref thing;
char *powername;
{
	char *cp;

	/*
	 * Make sure the power name is valid 
	 */

	for (cp = powername; *cp; cp++)
		*cp = ToLower(*cp);
	return (POWERENT *) hashfind(powername, &mudstate.powers_htab);
}

int decode_power(player, powername, pset)
dbref player;
char *powername;
POWERSET *pset;
{
	POWERENT *pent;

	pset->word1 = 0;
	pset->word2 = 0;

	pent = (POWERENT *) hashfind(powername, &mudstate.powers_htab);
	if (!pent) {
		notify(player, tprintf("%s: Power not found.", powername));
		return 0;
	}
	if (pent->powerpower & POWER_EXT)
		pset->word2 = pent->powervalue;
	else
		pset->word1 = pent->powervalue;

	return 1;
}

/*
 * ---------------------------------------------------------------------------
 * * power_set: Set or clear a specified power on an object. 
 */

void power_set(target, player, power, key)
dbref target, player;
char *power;
int key;
{
	POWERENT *fp;
	int negate, result;

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

	negate = 0;
	while (*power && isspace(*power))
		power++;
	if (*power == '!') {
		negate = 1;
		power++;
	}
	while (*power && isspace(*power))
		power++;

	/*
	 * Make sure a power name was specified 
	 */

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

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


/*
 * ---------------------------------------------------------------------------
 * * has_power: does object have power visible to player?
 */

int has_power(player, it, powername)
dbref player, it;
char *powername;
{
	POWERENT *fp;
	POWER fv;

	fp = find_power(it, powername);
	if (fp == NULL)
		return 0;

	if (fp->powerpower & POWER_EXT)
		fv = Powers2(it);
	else
		fv = Powers(it);

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

/*
 * ---------------------------------------------------------------------------
 * * power_description: Return an mbuf containing the type and powers on thing.
 */

char *power_description(player, target)
dbref player, target;
{
	char *buff, *bp;
	POWERENT *fp;
	int otype;
	POWER fv;

	/*
	 * Allocate the return buffer 
	 */

	otype = Typeof(target);
	bp = buff = alloc_mbuf("power_description");

	/*
	 * Store the header strings and object type 
	 */

	safe_mb_str((char *)"Powers:", buff, &bp);

	for (fp = gen_powers; fp->powername; fp++) {
		if (fp->powerpower & POWER_EXT)
			fv = Powers2(target);
		else
			fv = Powers(target);
		if (fv & fp->powervalue) {
			if ((fp->listperm & CA_WIZARD) && !Wizard(player))
				continue;
			if ((fp->listperm & CA_GOD) && !God(player))
				continue;
			safe_mb_chr(' ', buff, &bp);
			safe_mb_str((char *)fp->powername, buff, &bp);
		}
	}

	/*
	 * Terminate the string, and return the buffer to the caller 
	 */

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


/*
 * ---------------------------------------------------------------------------
 * * decompile_powers: Produce commands to set powers on target.
 */

void decompile_powers(player, thing, thingname)
dbref player, thing;
char *thingname;
{
	POWER f1, f2;
	POWERENT *fp;

	/*
	 * Report generic powers 
	 */

	f1 = Powers(thing);
	f2 = Powers2(thing);

	for (fp = gen_powers; fp->powername; fp++) {

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

		if (fp->listperm & CA_NO_DECOMP)
			continue;

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

		if (fp->powerpower & POWER_EXT) {
			if (!(f2 & fp->powervalue))
				continue;
		} else {
			if (!(f1 & fp->powervalue))
				continue;
		}

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

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

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

		notify(player, tprintf("@power %s=%s", thingname, fp->powername));
	}
}

#endif /*
        * STANDALONE 
        */