/* predicates.c */
#include "copyright.h"
/* Predicates for testing various conditions */
#include <stdio.h>
#include <varargs.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include "config.h"
#include "externs.h"
#include "db.h"
#include "interface.h"
#include "externs.h"
char *pronoun_substitute();
char *tprintf(va_alist)
va_dcl
{
static char buff[BUFFER_LEN];
va_list args;
char *fmt;
va_start(args);
fmt = va_arg(args, char *);
(void)vsprintf(buff, fmt, args);
buff[BUFFER_LEN - 1] = '\0';
return (buff);
}
int can_link_to(who, where)
dbref who;
dbref where;
{
return ((where >= 0 && where <= db_top) &&
(controls(who, where) ||
(db[where].flags & LINK_OK)));
}
int could_doit(player, thing)
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(player, thing, what, def, owhat, odef, awhat, loc)
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", (int) db[player].name, (int) 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(player, thing, can_see_loc)
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(who, what)
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(who, what)
dbref who;
dbref what;
{
return ((Typeof(what) == TYPE_EXIT && db[what].location == NOTHING)
|| controls(who, what));
}
int can_pay_fees(who, pennies)
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(who, pennies)
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(who, cost)
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(who, payment)
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(who, cost)
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(name)
const char *name;
{
while(name && *name && isspace(*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(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;
}
}
return(lookup_player(name) == NOTHING);
}
int ok_password(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;
}
void sstrcat(string, app)
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);
}
char *percent_sub(player, str, privs)
dbref player;
char *str;
dbref privs;
{
const static char *subjective[3] = {"it", "she", "he"};
const static char *possessive[3] = {"its", "her", "his"};
const static 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(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(*str) && islower(result[0]))
result[0] = toupper(result[0]);
else if(islower(*str) && isupper(result[0]))
result[0] = tolower(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(player, str, privs)
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(&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(*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(player, exp, argv, cause)
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(player,arg1)
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(player, target, type, message, def)
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(obj1, obj2)
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 (p, thing)
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;
}