/* predicates.c */
#include "os.h"
#include "copyright.h"
/* Predicates for testing various conditions */
#include "config.h"
#include "externs.h"
#include "db.h"
#include "interface.h"
#include "externs.h"
#include "match.h"
char *tprintf (char *fmt, ...)
{
static char buff[BUFFER_LEN];
va_list args;
va_start (args, fmt);
(void) vsprintf (buff, fmt, args);
va_end (args);
buff[BUFFER_LEN - 1] = '\0';
return (buff);
}
int can_link_to (dbref who, dbref where)
{
return ((where >= 0 && where <= db_top) &&
(controls (who, where) || (db[where].flags & LINK_OK)));
}
int could_doit (dbref player, dbref thing)
{
/* no if puppet trys to get key */
if ((Typeof (player) != TYPE_PLAYER) &&
((Typeof (thing) == TYPE_THING) && (db[thing].flags & THING_KEY) ||
(Typeof (thing) == TYPE_EXIT) && (db[thing].flags & EXIT_KEY)))
return 0;
if (Typeof (thing) != TYPE_ROOM && db[thing].location == NOTHING)
return 0;
return (eval_boolexp (player, db[thing].key, thing, 0, BASICLOCK));
}
void
did_it (dbref player, dbref thing, char *what, char *def, char *owhat,
char *odef, char *awhat, dbref loc)
{
ATTR *d;
char tbuf1[BUFFER_LEN], tbuf2[BUFFER_LEN];
loc = (loc == NOTHING) ? db[player].location : loc;
if (loc == NOTHING)
return;
/* message to player */
if (what && *what) {
d = atr_get (thing, what);
if (d) {
strcpy (tbuf2, uncompress (d->value));
strcpy (tbuf1, pronoun_substitute (thing, tbuf2, thing));
notify (player, tbuf1);
} else if (def && *def)
notify (player, def);
}
/* message to neighbors */
if (!Dark (player)) {
if (owhat && *owhat) {
d = atr_get (thing, owhat);
if (d) {
strcpy (tbuf2, uncompress (d->value));
strcpy (tbuf1, pronoun_substitute (player, tbuf2, thing));
notify_except2 (db[loc].contents, player, thing,
tprintf ("%s %s", db[player].name, tbuf1));
} else {
if (odef && *odef) {
notify_except2 (db[loc].contents, player, thing,
tprintf ("%s %s", db[player].name, odef));
}
}
}
}
/* do the action attribute */
if (awhat && *awhat && (d = atr_get (thing, awhat))) {
ATTR *b;
strcpy (tbuf1, uncompress (d->value));
parse_que (thing, tbuf1, player);
/* check if object has # of charges */
b = atr_get (thing, "CHARGES");
if (b) {
int num = atoi (b->value);
if (num) {
(void) atr_add (thing, "CHARGES", tprintf ("%d", num - 1),
db[b->creator].owner, NOTHING);
} else if (!(d = atr_get (thing, "RUNOUT")))
return;
strcpy (tbuf2, uncompress (d->value));
parse_que (thing, tbuf2, player);
}
}
}
int can_see (dbref player, dbref thing, int can_see_loc)
{
/*
* 1) your own body isn't listed in a 'look' 2) exits aren't listed in a
* 'look' 3) unconnected (sleeping) players aren't listed in a 'look'
*/
if (player == thing ||
Typeof (thing) == TYPE_EXIT ||
((Typeof (thing) == TYPE_PLAYER) &&
!IS (thing, TYPE_PLAYER, PLAYER_CONNECT)))
return 0;
/* if the room is lit, you can see any non-dark objects */
else if (can_see_loc)
return (!Dark (thing));
/* otherwise room is dark and you can't see a thing */
else
return 0;
}
int controls (dbref who, dbref what)
{
/* Wizard controls everything */
/* owners control their stuff */
return (what >= 0 && what <= db_top &&
(Wizard (who) || (db[who].owner == db[what].owner) ||
((db[what].zone != NOTHING) &&
(eval_boolexp (who, db[getzone (what)].enterkey, what,
0, ENTERLOCK)))));
}
int can_link (dbref who, dbref what)
{
return ((Typeof (what) == TYPE_EXIT && db[what].location == NOTHING)
|| controls (who, what));
}
int can_pay_fees (dbref who, int pennies)
{
#ifdef QUOTA
int pay_quota ();
#endif /* QUOTA */
/* can't charge till we've verified building quota */
if (!Wizard (who) && !Wizard (db[who].owner) &&
Pennies (db[who].owner) < pennies) {
notify (who, tprintf ("Sorry, you don't have enough %s.", MONIES));
return 0;
}
/* check building quota */
#ifdef QUOTA
if (!pay_quota (who, QUOTA_COST)) {
notify (who, "Sorry, your building quota has run out.");
return 0;
}
#endif /* QUOTA */
/* charge */
payfor (who, pennies);
return 1;
}
void giveto (dbref who, dbref pennies)
{
/* wizards don't need pennies */
if (Wizard (who) || Wizard (db[who].owner))
return;
who = db[who].owner;
s_Pennies (who, Pennies (who) + pennies);
}
int payfor (dbref who, int cost)
{
dbref tmp;
if (Wizard (who) || Wizard (db[who].owner))
return 1;
else if ((tmp = Pennies (db[who].owner)) >= cost) {
s_Pennies (db[who].owner, tmp - cost);
return 1;
} else
return 0;
}
#ifdef QUOTA
void add_quota (dbref who, int payment)
{
ATTR *a;
/* wizards don't need a quota */
if (Wizard (who) || Wizard (db[who].owner))
return;
a = atr_get (who, "RQUOTA");
(void) atr_add (who, "RQUOTA",
tprintf ("%d", ((a) ?
(atoi (uncompress (a->value))) + payment : payment)), GOD, NOTHING);
}
int pay_quota (dbref who, int cost)
{
int quota = 0;
ATTR *a;
/* wizards don't need a quota */
if (Wizard (who) || Wizard (db[who].owner))
return 1;
/* determine quota */
a = atr_get (db[who].owner, "RQUOTA");
if (a)
quota = atoi (uncompress (a->value));
/* enough to build? */
quota -= cost;
if (quota < 0)
return 0;
/* doc the quota */
(void) atr_add (who, "RQUOTA", tprintf ("%d", quota), GOD, NOTHING);
return 1;
}
#endif /* QUOTA */
int ok_name (const char *name)
{
while (name && *name && isspace ((int)*name))
name++;
return (name
&& *name
&& *name != LOOKUP_TOKEN
&& *name != NUMBER_TOKEN
&& *name != NOT_TOKEN && !index (name, ARG_DELIMITER)
&& !index (name, AND_TOKEN)
&& !index (name, OR_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 ((int)*scan) && !isspace ((int)*scan))) { /* was isgraph(*scan) */
return 0;
}
}
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 ((int)*scan) && !isspace ((int)*scan))) {
return 0;
}
}
return 1;
}
static void sstrcat (char *string, char *app)
{
char *s;
char tbuf1[BUFFER_LEN];
if ((strlen (app) + strlen (string)) >= BUFFER_LEN)
return;
sprintf (tbuf1, "%s", app);
for (s = tbuf1; *s; s++)
if ((*s == ',') || (*s == ';'))
*s = ' ';
strcat (string, tbuf1);
}
static char *percent_sub (dbref player, char *str, dbref privs)
{
static const char *subjective[3] = { "it", "she", "he" };
static const char *possessive[3] = { "its", "her", "his" };
static const char *objective[3] = { "it", "her", "him" };
static char result[BUFFER_LEN];
int gend;
ATTR *a, *r;
if (*str == '_') {
r = atr_get (privs, str + 1);
if (r) {
if ((r->flags & AF_DARK) || ((r->flags & AF_WIZARD) && !Wizard (privs)))
return (char *) "";
sprintf (result, "%s", uncompress (r->value));
return result;
} else
return (char *) "";
} else {
*result = '\0';
switch (str[0]) {
case 's':
case 'S':
case 'p':
case 'P':
case 'o':
case 'O':
a = atr_get (player, "SEX");
if (!a)
gend = 0;
else {
switch (*uncompress (a->value)) {
case 'M':
case 'm':
gend = 2;
break;
case 'W':
case 'w':
case 'F':
case 'f':
gend = 1;
break;
default:
gend = 0;
}
}
break;
default:
gend = 0;
}
switch (str[0]) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (!wptr[str[0] - '0'])
return (char *) "";
else
return (wptr[str[0] - '0']);
/*NOTREACHED*/ break;
case 's':
case 'S':
sprintf (result, "%s", subjective[gend]);
break;
case 'p':
case 'P':
sprintf (result, "%s", possessive[gend]);
break;
case 'o':
case 'O':
sprintf (result, "%s", objective[gend]);
break;
case 'n':
case 'N':
sprintf (result, db[player].name);
break;
case 'r':
case 'R':
return (char *) "\n";
/*NOTREACHED*/ break;
case 'b':
case 'B':
return (char *) " ";
/*NOTREACHED*/ break;
case 't':
case 'T':
return (char *) "\t";
/*NOTREACHED*/ break;
case 'v':
case 'V':
case 'w':
case 'W':
case 'x':
case 'X':
if (!isalpha ((int)str[1]))
return str;
r = atr_get (privs, str);
if (r) {
sprintf (result, "%s", uncompress (r->value));
return result;
} else
return (char *) "";
/*NOTREACHED*/ break;
default:
return str;
/*NOTREACHED*/ break;
}
if (isupper ((int)*str) && islower ((int)result[0]))
result[0] = toupper ((int)result[0]);
else if (islower ((int)*str) && isupper ((int)result[0]))
result[0] = tolower ((int)result[0]);
return result;
}
}
/*
* pronoun_substitute()
*
* %-type substitutions for pronouns
*
* %s/%S for subjective pronouns (he/she/it, He/She/It) %o/%O for objective
* pronouns (him/her/it, Him/Her/It) %p/%P for possessive pronouns
* (his/her/its, His/Her/Its) %n/%N for the player's name. %r for a newline.
* %<attrib_name> for the attribute value.
*/
char *pronoun_substitute (dbref player, const char *str, dbref privs /* object whose privs are used */
)
{
static char buf[BUFFER_LEN];
char temp[BUFFER_LEN];
char *r, *q;
if ((privs < 0) || privs >= db_top)
return (char *) "";
if ((player < 0) || player >= db_top)
return (char *) "";
if (strlen (str) > BUFFER_LEN - 1)
return (char *) "";
r = buf;
*r = '\0';
while (*str) {
switch (*str) {
case '[':
str++;
exec ((char**)&str, temp, privs, player, 0);
if (strlen (buf) + strlen (temp) < BUFFER_LEN)
strcat (buf, temp);
r += strlen (temp);
if (*str == ']')
str++;
break;
case '%':
switch (*(str + 1)) {
case '%':
if (r - buf < BUFFER_LEN - 1)
*r++ = '%';
str += 2;
break;
case '[':
if (r - buf < BUFFER_LEN - 1)
*r++ = '[';
str += 2;
break;
case '#':
str += 2;
sprintf (temp, "#%d", player);
sstrcat (buf, temp);
r += strlen (temp);
break;
case '_':
str += 2;
temp[0] = '_';
for (q = temp + 1;
(*str && (isalnum ((int)*str) || *str == '_' || *str == '-'));
*q++ = *str++);
*q = '\0';
q = percent_sub (player, temp, privs);
sstrcat (buf, q);
r += strlen (q);
break;
case '!':
str += 2;
sprintf (temp, "#%d", privs);
sstrcat (buf, temp);
r += strlen (temp);
break;
default:
str++; /* strip off the leading % sign before calling %sub */
temp[0] = *str;
if (*str == 'v' || *str == 'w' || *str == 'x' ||
*str == 'V' || *str == 'W' || *str == 'X') {
str++;
temp[1] = *str;
temp[2] = '\0';
} else
temp[1] = '\0';
str++;
q = percent_sub (player, temp, privs);
sstrcat (buf, q);
r += strlen (q);
}
break;
default:
if (r - buf < BUFFER_LEN - 1) {
*r++ = *str;
*r = '\0';
}
str++;
}
}
*r = '\0';
return buf;
}
/* for lack of better place the @switch code is here */
void do_switch (dbref player, char *exp, char *argv[], dbref cause)
{
int any = 0, a, c;
char *ptrsrv[10];
if (!argv[1])
return;
for (c = 0; c < 10; c++)
ptrsrv[c] = wptr[c];
/* now try a wild card match of buff with stuff in coms */
for (a = 1; (a < (MAX_ARG - 1)) && argv[a] && argv[a + 1]; a += 2)
if (wild_match (argv[a], exp)) {
any = 1;
for (c = 0; c < 10; c++)
wptr[c] = ptrsrv[c];
parse_que (player, argv[a + 1], cause);
}
for (c = 0; c < 10; c++)
wptr[c] = ptrsrv[c];
if ((a < MAX_ARG) && !any && argv[a])
parse_que (player, argv[a], cause);
}
dbref is_possess (dbref player, char *arg1)
{
dbref result1, result;
char *place, *temp;
if (!(place = index (arg1, ' ')))
return NOTHING;
temp = place;
temp++;
*place = '\0';
place--;
place--;
if (*place != '\'')
return NOTHING;
*place = '\0';
init_match (player, arg1, NOTYPE);
match_neighbor ();
match_possession ();
result1 = match_result ();
if (result1 == NOTHING || result1 == AMBIGUOUS)
return result1;
init_match (result1, temp, NOTYPE);
match_possession ();
result = match_result ();
return result;
}
void
page_return (dbref player, dbref target, char *type, char *message, char *def)
{
ATTR *d;
char tbuf1[BUFFER_LEN], tbuf2[BUFFER_LEN];
struct tm *ptr;
time_t t;
if (message && *message) {
d = atr_get (target, message);
if (d) {
strcpy (tbuf2, uncompress (d->value));
strcpy (tbuf1, pronoun_substitute (target, tbuf2, target));
t = time (NULL);
ptr = localtime (&t);
notify (player, tprintf ("%s message from %s: %s", type,
db[target].name, tbuf1));
notify (target, tprintf ("[%d:%02d] %s message sent to %s.",
ptr->tm_hour, ptr->tm_min, type, db[player].name));
} else if (def && *def)
notify (player, def);
}
}
int nearby (dbref obj1, dbref obj2)
{
/* returns 1 if obj1 is "nearby" object2. "Nearby" is defined as: */
/* obj1 is in the same room as obj2, obj1 is being carried by */
/* obj2, obj1 is carrying obj2. Returns 0 if object isn't nearby */
/* and -1 if the input is invalid. */
if ((obj1 == NOTHING) || (obj2 == NOTHING))
return -1;
if ((Typeof (obj1) != TYPE_THING) && (Typeof (obj1) != TYPE_PLAYER))
return -1;
if ((Typeof (obj2) != TYPE_THING) && (Typeof (obj2) != TYPE_PLAYER))
return -1;
if (db[obj1].location == db[obj2].location)
return 1;
else if (db[obj1].location == obj2)
return 1;
else if (db[obj2].location == obj1)
return 1;
else
return 0;
}
int find_flag (char *p, dbref thing)
{
int f = 0;
if (thing == NOTHING)
return -1;
switch (Typeof (thing)) {
case TYPE_THING:
if (string_prefix ("KEY", p))
f = THING_KEY;
if (string_prefix ("SAFE", p))
f = THING_SAFE;
if (string_prefix ("IMMORTAL", p))
f = THING_IMMORTAL;
if (string_prefix ("VERBOSE", p))
f = THING_VERBOSE;
if (string_prefix ("DESTROY_OK", p))
f = THING_DEST_OK;
if (string_prefix ("PUPPET", p))
f = THING_PUPPET;
if (string_prefix ("THING", p))
f = TYPE_THING;
break;
case TYPE_EXIT:
if (string_prefix ("KEY", p))
f = EXIT_KEY;
if (string_prefix ("TRANSPARENT", p))
f = EXIT_TRANSPARENT;
if (string_prefix ("EXIT", p))
f = TYPE_EXIT;
break;
case TYPE_PLAYER:
#ifdef RESTRICTED_BUILDING
if (string_prefix ("BUILDER", p))
f = PLAYER_BUILD;
#endif /* RESTRICTED_BUILDING */
if (string_prefix ("GAGGED", p))
f = PLAYER_GAGGED;
if (string_prefix ("SUSPECT", p))
f = PLAYER_SUSPECT;
if (string_prefix ("UNFINDABLE", p))
f = PLAYER_DARK;
if (string_prefix ("PLAYER", p))
f = TYPE_PLAYER;
if (string_prefix ("CONNECTED", p))
f = PLAYER_CONNECT;
break;
case TYPE_ROOM:
if (string_prefix ("TEMPLE", p))
f = ROOM_TEMPLE;
if (string_prefix ("ABODE", p))
f = ROOM_ABODE;
if (string_prefix ("JUMP_OK", p))
f = ROOM_JUMP_OK;
if (string_prefix ("LINK_OK", p))
f = LINK_OK;
if (string_prefix ("FLOATING", p))
f = ROOM_FLOATING;
if (string_prefix ("NO_TEL", p))
f = ROOM_NO_TEL;
if (string_prefix ("ROOM", p))
f = TYPE_ROOM;
break;
}
if (!f) {
#ifdef DESTROY
if (string_prefix ("GOING", p)) {
f = GOING;
#endif /* DESTROY */
} else if (string_prefix ("DARK", p)) {
f = DARK;
} else if (string_prefix ("STICKY", p)) {
f = STICKY;
} else if (string_prefix ("WIZARD", p)) {
f = WIZARD;
#ifdef ROYALTY_FLAG
} else if (string_prefix ("ROYALTY", p)) {
f = ROYALTY;
#endif
} else if (string_prefix ("ENTER_OK", p)) {
f = ENTER_OK;
} else if (string_prefix ("CHOWN_OK", p)) {
f = CHOWN_OK;
} else if (string_prefix ("VISUAL", p)) {
f = VISUAL;
} else if (string_prefix ("OPAQUE", p)) {
f = OPAQUE;
} else if (string_prefix ("NOSPOOF", p)) {
f = NOSPOOF;
#ifdef INHERIT_FLAG
} else if (string_prefix ("INHERIT", p)) {
f = INHERIT;
#endif
} else if (string_prefix ("HAVEN", p)) {
f = HAVEN;
} else if (string_prefix ("HALT", p)) {
f = HALT;
} else if (string_prefix ("QUIET", p)) {
f = QUIET;
} else if (string_prefix ("TERSE", p)) {
f = TERSE;
} else {
f = 0;
}
}
return f;
}