/* $Header: /belch_a/users/rearl/tinymuck/src/RCS/predicates.c,v 1.8 90/09/18 08:01:39 rearl Exp $ */
/*
* $Log: predicates.c,v $
* Revision 1.8 90/09/18 08:01:39 rearl
* Fixed a few broken things.
*
* Revision 1.7 90/09/16 04:42:42 rearl
* Preparation code added for disk-based MUCK.
*
* Revision 1.6 90/09/10 02:22:30 rearl
* Fixed some calls to pronoun_substitute.
*
* Revision 1.5 90/08/27 03:32:49 rearl
* Major changes on several predicates, usage...
*
* Revision 1.4 90/08/15 03:07:34 rearl
* Macroified some things. Took out #ifdef GENDER.
*
* Revision 1.3 90/08/06 02:46:30 rearl
* Put can_link() back in. Added restricted() for flags.
* With #define GOD_PRIV, sub-wizards can no longer set other
* players to Wizard.
*
* Revision 1.2 90/08/02 18:54:04 rearl
* Fixed controls() to return TRUE if exit is unlinked. Everyone
* controls an unlinked exit. Got rid of can_link().
*
* Revision 1.1 90/07/19 23:03:58 casie
* Initial revision
*
*
*/
#include "copyright.h"
#include "config.h"
/* Predicates for testing various conditions */
#include <ctype.h>
#include "db.h"
#include "interface.h"
#include "params.h"
#include "externs.h"
int can_hear(dbref who)
{
return (notify_internal(who, NULL)
|| ((FLAGS(who)&PUPPET) && Typeof(who) != TYPE_PLAYER)
|| get_attr(who,"listen"));
}
int can_link_to(dbref who, object_flag_type what_type, dbref where)
{
if (where == HOME) return 1;
switch (what_type) {
case TYPE_GARBAGE:
return 0;
break;
case TYPE_EXIT:
return (controls(who, where) || (FLAGS(where) & LINK_OK));
/*NOTREACHED*/
break;
case TYPE_PLAYER:
return (Typeof(where) == TYPE_ROOM && (controls(who, where)
|| Linkable(where)));
/*NOTREACHED*/
break;
case TYPE_ROOM:
case TYPE_THING:
return ((Typeof(where) == TYPE_ROOM || Typeof(where) == TYPE_PLAYER)
&& (controls(who, where) || Linkable(where)));
/*NOTREACHED*/
break;
case NOTYPE:
#ifdef ABODE
return (controls(who, where) || ((!(Typeof(where) == TYPE_PLAYER)) && (FLAGS(where) & ABODE)) || (FLAGS(where) & LINK_OK));
#else /* ABODE */
return (controls(who, where) || (FLAGS(where) & LINK_OK));
#endif /* ABODE */
/*NOTREACHED*/
break;
}
return 0;
}
int can_link(dbref who, dbref what)
{
return (controls(who, what) || ((Typeof(what) == TYPE_EXIT)
&& DBFETCH(what)->sp.exit.ndest == 0));
}
int could_doit(dbref player, dbref thing)
{
if(Typeof(thing) == TYPE_EXIT && DBFETCH(thing)->sp.exit.ndest == 0) {
return 0;
}
return(eval_boolexp (player, DBFETCH(thing)->key, thing));
}
int can_doit(dbref player, dbref thing, const char *default_fail_msg)
{
dbref loc;
char buf[BUFFER_LEN];
if((loc = getloc(player)) == NOTHING) return 0;
if(!could_doit(player, thing)) {
/* can't do it */
if(get_attr(thing, "Fail")) {
exec_or_notify(player, thing, get_attr(thing, "Fail"));
} else if(default_fail_msg) {
notify(player, default_fail_msg);
}
if(get_attr(thing, "Ofail") && !Dark(player)) {
sprintf(buf, "%s %s", NAME(player),
pronoun_substitute(player, get_attr(thing, "Ofail"), thing));
notify_except(DBFETCH(loc)->contents, player, buf);
}
if(get_attr(thing, "Afail")) {
trigobj(thing,get_attr(thing, "Afail"),NOTHING);
}
return 0;
} else {
/* can do it */
if(get_attr(thing, "Succ")) {
exec_or_notify(player, thing, get_attr(thing, "Succ"));
}
if(get_attr(thing, "Osucc") && !Dark(player)) {
sprintf(buf, "%s %s", NAME(player),
pronoun_substitute(player, get_attr(thing, "Osucc"), thing));
notify_except(DBFETCH(loc)->contents, player, buf);
}
if(get_attr(thing, "Asucc")) {
trigobj(thing, get_attr(thing, "Asucc"), NOTHING);
}
return 1;
}
}
int can_see(dbref player, dbref thing, int can_see_loc)
{
if (player == thing || Typeof(thing) == TYPE_EXIT
|| Typeof(thing) == TYPE_ROOM) return 0;
if (can_see_loc) {
switch (Typeof(thing)) {
case TYPE_PROGRAM:
return((FLAGS(thing) & LINK_OK) || controls(player, thing) ||
controls(player, DBFETCH(thing)->location));
default:
return (!Dark(thing) || controls(player, thing));
}
} else {
/* can't see loc */
return player == OWNER(thing);
}
}
int controls(dbref who, dbref what)
{
/* Wizard players control everything */
/* Wizard objects control everything except wizard players */
/* Architects control everything except wizard objects */
/* owners control their stuff */
/* objects (not players) with the same owner control each other */
/* No one controls garbage */
if (Typeof(what) == TYPE_GARBAGE) return 0;
if(FLAGS(who)&QUELL) return 0;
if(who == OWNER(what)) return 1;
switch(Typeof(who)) {
case TYPE_PLAYER:
#ifdef GOD_PRIV
if(is_god(who)) return 1;
if(Wizard(who))
return (!is_god(what));
#else
if(Wizard(who)) return 1;
#endif /* GOD_PRIV */
if(Arch(who))
return (!(FLAGS(what)&WIZARD));
break;
case TYPE_THING:
if(Typeof(what) == TYPE_PLAYER) {
if(Arch(who))
return (!(FLAGS(what)&WIZARD));
}
else {
if(what == OWNER(who)) return 0;
if((OWNER(who) == OWNER(what)) && !(FLAGS(what)&WIZARD))
return 1;
if(Wizard(who))
return 1;
if(Arch(who))
return(!(FLAGS(what)&WIZARD));
}
break;
default:
return 0;
}
return 0;
}
int restricted(dbref player, dbref thing, object_flag_type flag)
{
switch (flag) {
case ARCHITECT:
return (!Wizard(player) && (Typeof(thing) != TYPE_ROOM));
break;
case DARK:
return (!(Arch(player))
&& (Typeof(thing) == TYPE_PLAYER)); /* no dark players. */
/*NOTREACHED*/
break;
case MUCKER:
return (!Wizard(player) && ((Typeof(thing) == TYPE_PROGRAM)
|| (Typeof(thing) == TYPE_PLAYER)));
case BUILDER:
return (!Wizard(player));
/*NOTREACHED*/
break;
case WIZARD:
if (Wizard(player) || God(player)) {
if(player != global_cause ||
player != global_trigger) return 1; /* @force, or something similar */
#ifdef GOD_PRIV
return ((Typeof(thing) == TYPE_PLAYER) && !God(player));
#else /* !GOD_PRIV */
return !Wizard(player);
#endif /* GOD_PRIV */
} else return 1;
/*NOTREACHED*/
break;
case STICKY:
return ((Typeof(thing)==TYPE_PROGRAM) && !(Arch(player) && Mucker(player)));
break;
default:
return 0;
/*NOTREACHED*/
break;
}
}
int payfor(dbref who, int cost)
{
if(Arch(who)) {
return 1;
} else if(DBFETCH(who)->sp.player.pennies >= cost) {
DBFETCH(who)->sp.player.pennies -= cost;
DBDIRTY(who);
return 1;
} else {
return 0;
}
}
int word_start (const char *str, const char let)
{
int chk;
for (chk = 1; *str; str++) {
if (chk && *str == let) return 1;
chk = *str == ' ';
}
return 0;
}
int ok_name(const char *name)
{
return (name
&& *name
&& *name != LOOKUP_TOKEN
&& *name != NUMBER_TOKEN
&& !index(name, ARG_DELIMITER)
&& !index(name, AND_TOKEN)
&& !index(name, OR_TOKEN)
&& !word_start(name, NOT_TOKEN)
&& string_compare(name, "me")
&& string_compare(name, "home")
&& string_compare(name, "here"));
}
int ok_player_name(const char *name)
{
const char *scan;
if(!ok_name(name) || strlen(name) > PLAYER_NAME_LIMIT) return 0;
for(scan = name; *scan; scan++) {
if(!(isprint(*scan) && !isspace(*scan))) { /* was isgraph(*scan) */
return 0;
}
}
/* lookup name to avoid conflicts */
return (lookup_player(name) == NOTHING);
}
int ok_password(const char *password)
{
const char *scan;
if(*password == '\0') return 0;
for(scan = password; *scan; scan++) {
if(!(isprint(*scan) && !isspace(*scan))) {
return 0;
}
}
return 1;
}
int is_ok(dbref what)
{
if(what < 0) {
return 0;
} else {
return(Typeof(what) != TYPE_GARBAGE);
}
}
int Builder(dbref x)
{
return(Arch(x) || FLAGS(x)&BUILDER);
}
int Arch(dbref x)
{
return(Wizard(x) ||
((Typeof(x) != TYPE_ROOM) &&
(FLAGS(x)&ARCHITECT && !(FLAGS(x)&QUELL))));
}
int God(dbref x)
{ return is_god(x); }
int Wizard(dbref x)
{ return (FLAGS(x)&WIZARD && !(FLAGS(x)&QUELL)); }
int Mucker(dbref x)
{
return((Typeof(x) == TYPE_PLAYER) && (Wizard(x) || FLAGS(x)&MUCKER));
}
int Murky(dbref x)
{
return(((Typeof(x) == TYPE_ROOM) || (Typeof(x) == TYPE_THING)
|| (Typeof(x) == TYPE_EXIT)) &&
FLAGS(x)&MUCKER);
}
char *check_func(const char *x) { return alloc_string (x); }
#ifdef HAVEN
int Haven(dbref x) {return FLAGS(x)&HAVEN;}
#endif /* HAVEN */
int Halted(dbref x)
{
return FLAGS(x)&HALTED;
}
int Dark(dbref x)
{
if(Typeof(x) == TYPE_PLAYER && !notify_internal(x,NULL))
return 1;
if((Typeof(x) != TYPE_ROOM)
&& (FLAGS(DBFETCH(x)->location)&DARK)) return 1;
return (FLAGS(x)&DARK);
}
int Silent(dbref x)
{
return((Typeof(x) == TYPE_PLAYER) && (FLAGS(x)&STICKY));
}
int Paranoid(dbref x)
{
return((Typeof(x) == TYPE_PLAYER) && (FLAGS(x)&PUPPET));
}
#define MAX_FUN_ARGS 50
void do_switch(dbref player, char *arg1, char *arg2, dbref cause)
{
char *arg[MAX_FUN_ARGS], *ptrsrv[10];
char buff[BUFFER_LEN];
char *p;
int x = 0, a = 0, any = 0;
const char *delimit = ",";
exec(&arg1, buff, player, cause, 0);
arg[0] = alloc_ec_string(buff);
for(x = 1; x < MAX_FUN_ARGS; x++)
{
arg[x] = NULL;
p = (char *) parse_up(&arg2, delimit);
if(p)
arg[x] = alloc_ec_string(p);
}
if(!arg[1])
return;
for(x = 0; x < 10; x++)
ptrsrv[x] = wptr[x];
for(x = 1; x < (MAX_FUN_ARGS - 1) && arg[x] && arg[x + 1]; x += 2)
if(wild_match(arg[x], arg[0])) {
any = 1;
for(a = 0; a < 10; a++)
wptr[a] = ptrsrv[a];
trigobj(player, trash_braces(arg[x + 1]), cause);
}
if(x < MAX_FUN_ARGS && !any && arg[x])
{
for(a = 0; a < 10; a++)
wptr[a] = ptrsrv[a];
trigobj(player, trash_braces(arg[x]), cause);
}
}