/* 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; }