/* flags.c - flag manipulation routines */ #include "autoconf.h" #include "copyright.h" #ifndef lint static char RCSid[] = "$Id: flags.c,v 1.8 1995/03/21 00:00:19 ambar Exp $"; USE(RCSid); #endif #include "externs.h" #include "command.h" #include "flags.h" #include "alloc.h" #ifndef STANDALONE /* --------------------------------------------------------------------------- * fh_any: set or clear indicated bit, no security checking */ int fh_any(target, player, flag, fflags, reset) dbref target, player; FLAG flag; int fflags, reset; { if (fflags & FLAG_EXT) { if (reset) s_Flags2(target, Flags2(target) & ~flag); else s_Flags2(target, Flags2(target) | flag); } else { if (reset) s_Flags(target, Flags(target) & ~flag); else s_Flags(target, Flags(target) | flag); } return 1; } /* --------------------------------------------------------------------------- * fh_god: only GOD may set or clear the bit */ int fh_god(target, player, flag, fflags, reset) dbref target, player; FLAG flag; int fflags, reset; { if (!God(player)) return 0; return (fh_any(target, player, flag, fflags, reset)); } /* --------------------------------------------------------------------------- * fh_wiz: only WIZARDS (or GOD) may set or clear the bit */ int fh_wiz(target, player, flag, fflags, reset) dbref target, player; FLAG flag; int fflags, reset; { if (!Wizard(player) & !God(player)) return 0; return (fh_any(target, player, flag, fflags, reset)); } /* --------------------------------------------------------------------------- * fh_inherit: only players may set or clear this bit. */ int fh_inherit(target, player, flag, fflags, reset) dbref target, player; FLAG flag; int fflags, reset; { if (!Inherits(player)) return 0; return (fh_any(target, player, flag, fflags, reset)); } /* --------------------------------------------------------------------------- * fh_wiz_bit: Only GOD may set/clear this bit on others. */ int fh_wiz_bit(target, player, flag, fflags, reset) dbref target, player; FLAG flag; int fflags, reset; { if (!God(player)) return 0; if (God(target) && reset) { notify(player, "You cannot make yourself mortal."); return 0; } return (fh_any(target, player, flag, fflags, reset)); } /* --------------------------------------------------------------------------- * fh_player_bit: Can set and reset this on everything but players. */ int fh_player_bit(target, player, flag, fflags, reset) dbref target, player; FLAG flag; int fflags, reset; { if (isPlayer(target)) return 0; return (fh_any(target, player, flag, fflags, reset)); } /* --------------------------------------------------------------------------- * fh_dark_bit: manipulate the dark bit. Nonwizards may not set on players. */ int fh_dark_bit(target, player, flag, fflags, reset) dbref target, player; FLAG flag; int fflags, reset; { if (!reset && isPlayer(target) && (!Wizard(player) && !God(player))) return 0; return (fh_any(target, player, flag, fflags, reset)); } /* --------------------------------------------------------------------------- * fh_going_bit: manipulate the going bit. Non-gods may only clear on rooms. */ int fh_going_bit(target, player, flag, fflags, reset) dbref target, player; FLAG flag; int fflags, reset; { if (isRoom(target) && Going(target) && reset) { notify(player, "Your room has been spared from destruction."); return (fh_any(target, player, flag, fflags, reset)); } if (!God(player)) return 0; return (fh_any(target, player, flag, fflags, reset)); } /* --------------------------------------------------------------------------- * fh_hear_bit: set or clear bits that affect hearing. */ int fh_hear_bit(target, player, flag, fflags, reset) dbref target, player; FLAG flag; int fflags, reset; { int could_hear; could_hear = Hearer(target); fh_any(target, player, flag, fflags, reset); handle_ears(target, could_hear, Hearer(target)); return 1; } FLAGENT gen_flags[] = { {"ABODE", ABODE, 'A', FLAG_EXT, 0, fh_any}, {"BUILDER", BUILDER, 'B', FLAG_EXT, 0, fh_wiz}, {"CHOWN_OK", CHOWN_OK, 'C', 0, 0, fh_any}, {"DARK", DARK, 'D', 0, 0, fh_dark_bit}, {"FLOATING", FLOATING, 'F', FLAG_EXT, 0, fh_any}, {"GOING", GOING, 'G', 0, CA_NO_DECOMP, fh_going_bit}, {"HAVEN", HAVEN, 'H', 0, 0, fh_any}, {"INHERIT", INHERIT, 'I', 0, 0, fh_inherit}, {"JUMP_OK", JUMP_OK, 'J', 0, 0, fh_any}, {"KEY", KEY, 'K', FLAG_EXT, 0, fh_any}, {"LINK_OK", LINK_OK, 'L', 0, 0, fh_any}, {"MONITOR", MONITOR, 'M', 0, 0, fh_hear_bit}, {"NOSPOOF", NOSPOOF, 'N', 0, CA_WIZARD, fh_any}, {"OPAQUE", OPAQUE, 'O', 0, 0, fh_any}, {"QUIET", QUIET, 'Q', 0, 0, fh_any}, {"STICKY", STICKY, 'S', 0, 0, fh_any}, {"TRACE", TRACE, 'T', 0, 0, fh_any}, {"UNFINDABLE", UNFINDABLE, 'U', FLAG_EXT, 0, fh_any}, {"VISUAL", VISUAL, 'V', 0, 0, fh_any}, {"WIZARD", WIZARD, 'W', 0, 0, fh_wiz_bit}, {"ANSI", ANSI, 'X', FLAG_EXT, 0, fh_any}, {"PARENT_OK", PARENT_OK, 'Y', FLAG_EXT, 0, fh_any}, {"ZONE", ZONE_PARENT, 'Z', FLAG_EXT, 0, fh_any}, {"AUDIBLE", HEARTHRU, 'a', 0, 0, fh_hear_bit}, {"BOUNCE", BOUNCE, 'b', FLAG_EXT, 0, fh_any}, {"CONNECTED", CONNECTED, 'c', FLAG_EXT, CA_NO_DECOMP, fh_god}, {"DESTROY_OK", DESTROY_OK, 'd', 0, 0, fh_any}, {"ENTER_OK", ENTER_OK, 'e', 0, 0, fh_any}, {"HALTED", HALT, 'h', 0, 0, fh_any}, {"IMMORTAL", IMMORTAL, 'i', 0, 0, fh_wiz}, {"TICKLER", TICKLER, 'k', FLAG_EXT, 0, fh_god}, {"LIGHT", LIGHT, 'l', FLAG_EXT, 0, fh_any}, {"MYOPIC", MYOPIC, 'm', 0, 0, fh_any}, {"PUPPET", PUPPET, 'p', 0, 0, fh_hear_bit}, {"TERSE", TERSE, 'q', 0, 0, fh_any}, {"ROBOT", ROBOT, 'r', 0, 0, fh_player_bit}, {"SAFE", SAFE, 's', 0, 0, fh_any}, {"TRANSPARENT", SEETHRU, 't', 0, 0, fh_any}, {"SUSPECT", SUSPECT, 'u', FLAG_EXT, CA_WIZARD, fh_wiz}, {"VERBOSE", VERBOSE, 'v', 0, 0, fh_any}, {"SLAVE", SLAVE, 'x', FLAG_EXT, CA_WIZARD, fh_wiz}, {"CONTROL_OK", CONTROL_OK, 'z', 0, 0, fh_any}, {"COMMANDS", HAS_COMMANDS, '$', FLAG_EXT, 0, fh_any}, {"NOBLEED", NOBLEED, '-', FLAG_EXT, 0, fh_any}, {"STOP", STOP_MATCH, '!', FLAG_EXT, 0, fh_wiz}, {"HAS_STARTUP", HAS_STARTUP, '+', 0, CA_GOD | CA_NO_DECOMP, fh_god}, {"HAS_FORWARDLIST", HAS_FWDLIST, '&', FLAG_EXT, CA_GOD | CA_NO_DECOMP, fh_god}, {"HAS_LISTEN", HAS_LISTEN, '@', FLAG_EXT, CA_GOD | CA_NO_DECOMP, fh_god}, #ifdef PUEBLO_SUPPORT {"HTML", HTML, 'w', FLAG_EXT, 0, fh_any}, #endif /* PUEBLO_SUPPORT */ {NULL, 0, ' ', 0, 0, NULL}}; #endif /* STANDALONE */ OBJENT object_types[8] = { {"ROOM", 'R', CA_PUBLIC, OF_CONTENTS | OF_EXITS | OF_DROPTO | OF_HOME}, {"THING", ' ', CA_PUBLIC, OF_CONTENTS | OF_LOCATION | OF_EXITS | OF_HOME}, {"EXIT", 'E', CA_PUBLIC, 0}, {"PLAYER", 'P', CA_PUBLIC, OF_CONTENTS | OF_LOCATION | OF_EXITS | OF_HOME | OF_OWNER}, {"TYPE4", '?', CA_PUBLIC, OF_CONTENTS | OF_LOCATION | OF_EXITS | OF_HOME | OF_OWNER}, {"TYPE5", '+', CA_GOD, 0}, {"TYPE6", '-', CA_GOD, 0}, {"GARBAGE", '*', CA_GOD, 0}}; #ifndef STANDALONE /* --------------------------------------------------------------------------- * init_flagtab: initialize flag hash tables. */ void NDECL(init_flagtab) { FLAGENT *fp; char *nbuf, *np, *bp; hashinit(&mudstate.flags_htab, 67); nbuf = alloc_sbuf("init_flagtab"); for (fp = gen_flags; fp->flagname; fp++) { for (np = nbuf, bp = (char *) fp->flagname; *bp; np++, bp++) *np = ToLower(*bp); *np = '\0'; hashadd(nbuf, (int *) fp, &mudstate.flags_htab); } free_sbuf(nbuf); } /* --------------------------------------------------------------------------- * display_flags: display available flags. */ void display_flagtab(player) dbref player; { char *buf, *bp; FLAGENT *fp; bp = buf = alloc_lbuf("display_flagtab"); safe_str((char *) "Flags:", buf, &bp); for (fp = gen_flags; fp->flagname; 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->flagname, buf, &bp); safe_chr('(', buf, &bp); safe_chr(fp->flaglett, buf, &bp); safe_chr(')', buf, &bp); } notify(player, buf); free_lbuf(buf); } FLAGENT * find_flag(thing, flagname) dbref thing; char *flagname; { char *cp; /* Make sure the flag name is valid */ for (cp = flagname; *cp; cp++) *cp = ToLower(*cp); return (FLAGENT *) hashfind(flagname, &mudstate.flags_htab); } /* --------------------------------------------------------------------------- * flag_set: Set or clear a specified flag on an object. */ void flag_set(target, player, flag, key) dbref target, player; char *flag; int key; { FLAGENT *fp; int negate, result; /* Trim spaces, and handle the negation character */ negate = 0; while (*flag && isspace(*flag)) flag++; if (*flag == '!') { negate = 1; flag++; } while (*flag && isspace(*flag)) flag++; /* Make sure a flag name was specified */ if (*flag == '\0') { if (negate) notify(player, "You must specify a flag to clear."); else notify(player, "You must specify a flag to set."); return; } fp = find_flag(target, flag); if (fp == NULL) { notify(player, "I don't understand that flag."); return; } /* Invoke the flag handler, and print feedback */ result = fp->handler(target, player, fp->flagvalue, fp->flagflag, negate); if (!result) notify(player, "Permission denied."); else if (!(key & SET_QUIET) && !Quiet(player)) notify(player, (negate ? "Cleared." : "Set.")); return; } /* --------------------------------------------------------------------------- * decode_flags: converts a flags word into corresponding letters. */ char * decode_flags(player, flagword, flag2word) dbref player; FLAG flagword, flag2word; { char *buf, *bp; FLAGENT *fp; int flagtype; FLAG fv; buf = bp = alloc_sbuf("decode_flags"); *bp = '\0'; if (!Good_obj(player)) { strcpy(buf, "#-2 ERROR"); return buf; } flagtype = (flagword & TYPE_MASK); if (object_types[flagtype].lett != ' ') { safe_chr(object_types[flagtype].lett, buf, &bp); } for (fp = gen_flags; fp->flagname; fp++) { if (fp->flagflag & FLAG_EXT) fv = flag2word; else fv = flagword; if (fv & fp->flagvalue) { if ((fp->listperm & CA_WIZARD) && !Wizard(player)) continue; if ((fp->listperm & CA_GOD) && !God(player)) continue; /* don't show CONNECT on dark wizards to mortals */ if ((flagtype == TYPE_PLAYER) && (fp->flagvalue == CONNECTED) && ((flagword & (WIZARD | DARK)) == (WIZARD | DARK)) && !Wizard(player)) continue; safe_chr(fp->flaglett, buf, &bp); } } *bp = '\0'; return buf; } /* --------------------------------------------------------------------------- * has_flag: does object have flag visible to player? */ int has_flag(player, it, flagname) dbref player, it; char *flagname; { FLAGENT *fp; FLAG fv; fp = find_flag(it, flagname); if (fp == NULL) return 0; if (fp->flagflag & FLAG_EXT) fv = Flags2(it); else fv = Flags(it); if (fv & fp->flagvalue) { if ((fp->listperm & CA_WIZARD) && !Wizard(player)) return 0; if ((fp->listperm & CA_GOD) && !God(player)) return 0; /* don't show CONNECT on dark wizards to mortals */ if (isPlayer(it) && (fp->flagflag & FLAG_EXT) && (fp->flagvalue == CONNECTED) && ((Flags(it) & (WIZARD | DARK)) == (WIZARD | DARK)) && !Wizard(player)) return 0; return 1; } return 0; } /* --------------------------------------------------------------------------- * flag_description: Return an mbuf containing the type and flags on thing. */ char * flag_description(player, target) dbref player, target; { char *buff, *bp; FLAGENT *fp; int otype; FLAG fv; /* Allocate the return buffer */ otype = Typeof(target); bp = buff = alloc_mbuf("flag_description"); /* Store the header strings and object type */ safe_mb_str((char *) "Type: ", buff, &bp); safe_mb_str((char *) object_types[otype].name, buff, &bp); safe_mb_str((char *) " Flags:", buff, &bp); if (object_types[otype].perm != CA_PUBLIC) { return buff; } /* Store the type-invariant flags */ for (fp = gen_flags; fp->flagname; fp++) { if (fp->flagflag & FLAG_EXT) fv = Flags2(target); else fv = Flags(target); if (fv & fp->flagvalue) { if ((fp->listperm & CA_WIZARD) && !Wizard(player)) continue; if ((fp->listperm & CA_GOD) && !God(player)) continue; /* don't show CONNECT on dark wizards to mortals */ if (isPlayer(target) && (fp->flagvalue == CONNECTED) && ((Flags(target) & (WIZARD | DARK)) == (WIZARD | DARK)) && !Wizard(player)) continue; safe_mb_chr(' ', buff, &bp); safe_mb_str((char *) fp->flagname, buff, &bp); } } return buff; } /* --------------------------------------------------------------------------- * Return an lbuf containing the name and number of an object */ char * unparse_object_numonly(target) dbref target; { char *buf; buf = alloc_lbuf("unparse_object_numonly"); if (target == NOTHING) { strcpy(buf, "*NOTHING*"); } else if (target == HOME) { strcpy(buf, "*HOME*"); } else if (!Good_obj(target)) { sprintf(buf, "*ILLEGAL*(#%d)", target); } else { sprintf(buf, "%s(#%d)", Name(target), target); } return buf; } /* --------------------------------------------------------------------------- * Return an lbuf pointing to the object name and possibly the db# and flags */ char * unparse_object(player, target, obey_myopic) dbref player, target; int obey_myopic; { char *buf, *fp; int exam; buf = alloc_lbuf("unparse_object"); if (target == NOTHING) { strcpy(buf, "*NOTHING*"); } else if (target == HOME) { strcpy(buf, "*HOME*"); } else if (!Good_obj(target)) { sprintf(buf, "*ILLEGAL*(#%d)", target); } else { if (obey_myopic) exam = MyopicExam(player, target); else exam = Examinable(player, target); if (exam || (Flags(target) & (CHOWN_OK | JUMP_OK | LINK_OK | DESTROY_OK)) || (Flags2(target) & ABODE)) { /* show everything */ fp = unparse_flags(player, target); sprintf(buf, "%s(#%d%s)", Name(target), target, fp); free_sbuf(fp); } else { /* show only the name. */ strcpy(buf, Name(target)); } } return buf; } /* --------------------------------------------------------------------------- * convert_flags: convert a list of flag letters into its bit pattern. * Also set the type qualifier if specified and not already set. */ int convert_flags(player, flaglist, fset, p_type) dbref player; char *flaglist; FLAGSET *fset; FLAG *p_type; { int i, handled; char *s; FLAG flag1mask, flag2mask, type; FLAGENT *fp; flag1mask = flag2mask = 0; type = NOTYPE; for (s = flaglist; *s; s++) { handled = 0; /* Check for object type */ for (i = 0; (i <= 7) && !handled; i++) { if ((object_types[i].lett == *s) && !(((object_types[i].perm & CA_WIZARD) && !Wizard(player)) || ((object_types[i].perm & CA_GOD) && !God(player)))) { if ((type != NOTYPE) && (type != i)) { notify(player, tprintf("%c: Conflicting type specifications.", *s)); return 0; } type = i; handled = 1; } } /* Check generic flags */ if (handled) continue; for (fp = gen_flags; (fp->flagname) && !handled; fp++) { if ((fp->flaglett == *s) && !(((fp->listperm & CA_WIZARD) && !Wizard(player)) || ((fp->listperm & CA_GOD) && !God(player)))) { if (fp->flagflag & FLAG_EXT) flag2mask |= fp->flagvalue; else flag1mask |= fp->flagvalue; handled = 1; } } if (!handled) { notify(player, tprintf("%c: Flag unknown or not valid for specified object type", *s)); return 0; } } /* return flags to search for and type */ (*fset).word1 = flag1mask; (*fset).word2 = flag2mask; *p_type = type; return 1; } /* --------------------------------------------------------------------------- * decompile_flags: Produce commands to set flags on target. */ void decompile_flags(player, thing, thingname) dbref player, thing; char *thingname; { FLAG f1, f2; FLAGENT *fp; /* Report generic flags */ f1 = Flags(thing); f2 = Flags2(thing); for (fp = gen_flags; fp->flagname; fp++) { /* Skip if we shouldn't decompile this flag */ if (fp->listperm & CA_NO_DECOMP) continue; /* Skip if this flag is not set */ if (fp->flagflag & FLAG_EXT) { if (!(f2 & fp->flagvalue)) continue; } else { if (!(f1 & fp->flagvalue)) continue; } /* Skip if we can't see this flag */ if (!check_access(player, fp->listperm)) continue; /* We made it this far, report this flag */ notify(player, tprintf("@set %s=%s", thingname, fp->flagname)); } } /* Guest - is the given dbref one of the Guest characters? */ #ifdef __STDC__ int Guest(dbref thing) #else int Guest(thing) dbref thing; #endif { int i; for (i = 0; i < mudconf.num_guests; i++) if (Owner(thing) == mudconf.guest_chars[i]) return 1; return 0; } #endif /* STANDALONE */