/* This software is Copyright 1989, 1990, 1992, 1993 by various individuals. Please see the accompanying file COPYRIGHT for details. */ #include #include #include "db.h" #include "defs.h" #include "prims.h" #include "config.h" #include "params.h" #include "strings.h" #include "externs.h" #include "property.h" #include "interface.h" /* flagnames[] is used for long-name flag lists and for looking up multi-character flag names for @set and MUF; flagname1s[] is used for single-character flag lists and for looking up one-character flag names for @set and MUF. */ /* The order of these tables doesn't matter much, except that in flagnames[], for any given bit, more specific entries should come before less specific. Also, in each table, the order flags will come out in when displayed is the same as their order in the table, so by the Principle of Least Surprise, the two tables should match, at the very least. */ struct flagname flagnames[] = { { GFLAG, 0, 0, "God" }, { WFLAG, 0, 0, "Wizard" }, { QFLAG, 0, 0, "Quell" }, { NFLAG, TYPE_MASK, TYPE_ROOM, "NoInventory" }, { NFLAG, TYPE_MASK, TYPE_EXIT, "Noisy" }, { NFLAG, TYPE_MASK, TYPE_PLAYER, "NoInventory" }, { NFLAG, 0, 0, "NFlag" }, { SFLAG, TYPE_MASK, TYPE_ROOM, "Sticky" }, { SFLAG, TYPE_MASK, TYPE_THING, "Sticky" }, { SFLAG, TYPE_MASK, TYPE_EXIT, "Sticky" }, #ifdef SILENT_PLAYERS { SFLAG, TYPE_MASK, TYPE_PLAYER, "Silent" }, #endif { SFLAG, TYPE_MASK, TYPE_PROGRAM, "SetUID" }, { SFLAG, 0, 0, "SFlag" }, { DFLAG, TYPE_MASK, TYPE_ROOM, "Dark" }, { DFLAG, TYPE_MASK, TYPE_THING, "Dark" }, { DFLAG, TYPE_MASK, TYPE_EXIT, "Dark" }, { DFLAG, TYPE_MASK, TYPE_PLAYER, "Dark" }, { DFLAG, TYPE_MASK, TYPE_PROGRAM, "Debug" }, { DFLAG, 0, 0, "DFlag" }, { LFLAG, 0, 0, "Link_OK" }, { MFLAG, TYPE_MASK|WIZARD, TYPE_PLAYER|WIZARD, "Monitor" }, { MFLAG, TYPE_MASK|WIZARD, TYPE_PLAYER, "Mucker" }, { MFLAG, TYPE_MASK, TYPE_PROGRAM, "Mucker" }, { MFLAG, 0, 0, "MFlag" }, { BFLAG, TYPE_MASK|WIZARD, TYPE_PLAYER|WIZARD, "Busy" }, { BFLAG, TYPE_MASK|ROYALTY, TYPE_PLAYER|ROYALTY, "Busy" }, { BFLAG, TYPE_MASK|WIZARD|ROYALTY, TYPE_PLAYER, "Builder" }, { BFLAG, TYPE_MASK, TYPE_PROGRAM, "Builder" }, { BFLAG, 0, 0, "BFlag" }, { OFLAG, TYPE_MASK, TYPE_PLAYER, "Observe" }, { OFLAG, 0, 0, "Ownable" }, { FFLAG, TYPE_MASK, TYPE_EXIT, "FullName" }, { FFLAG, TYPE_MASK, TYPE_PLAYER, "FollowStatus" }, { FFLAG, TYPE_MASK, TYPE_PROGRAM, "FinalStack" }, { FFLAG, 0, 0, "FFlag" }, { JFLAG, 0, 0, "Jump_OK" }, { HFLAG, TYPE_MASK, TYPE_ROOM, "Haven" }, { HFLAG, TYPE_MASK, TYPE_EXIT, "Hear" }, { HFLAG, TYPE_MASK, TYPE_PLAYER, "Haven" }, { HFLAG, 0, 0, "HFlag" }, { AFLAG, TYPE_MASK|WIZARD, TYPE_EXIT|WIZARD, "Autostart" }, { AFLAG, TYPE_MASK, TYPE_PLAYER, "Author" }, { AFLAG, 0, 0, "Abode" }, { TFLAG, TYPE_MASK, TYPE_ROOM, "Tap" }, { TFLAG, TYPE_MASK, TYPE_PLAYER, "Tap" }, { TFLAG, TYPE_MASK, TYPE_PROGRAM, "TriggerUID" }, { TFLAG, 0, 0, "TFlag" }, { VFLAG, 0, 0, "Visual" }, { UFLAG, TYPE_MASK, TYPE_EXIT, "Unconnected" }, { UFLAG, TYPE_MASK, TYPE_PLAYER, "Unseen" }, { UFLAG, TYPE_MASK, TYPE_PROGRAM, "Unlistable" }, { UFLAG, TYPE_MASK, TYPE_DAEMON, "Unkillable" }, { UFLAG, 0, 0, "UFlag" }, { IFLAG, TYPE_MASK, TYPE_ROOM, "InContents" }, { IFLAG, TYPE_MASK, TYPE_EXIT, "Individual" }, { IFLAG, TYPE_MASK, TYPE_PLAYER, "Interactive" }, { IFLAG, TYPE_MASK, TYPE_DAEMON, "Interactive" }, { IFLAG, 0, 0, "IFlag" }, { PFLAG, TYPE_MASK, TYPE_EXIT, "Prefix" }, { PFLAG, 0, 0, "PFlag" }, { CFLAG, 0, 0, "CFlag" }, { EFLAG, TYPE_MASK, TYPE_EXIT, "Exact" }, { EFLAG, 0, 0, "EFlag" }, { KFLAG, 0, 0, "Keep" }, { RFLAG, 0, 0, "Royal" }, { XFLAG, 0, 0, "XFlag" }, { YFLAG, 0, 0, "YFlag" }, { ZFLAG, 0, 0, "ZFlag" }, { INTERNAL, TYPE_MASK, TYPE_PLAYER, "ILineNum" }, { INTERNAL, 0, 0, "Internal" }, { 0 } }; /* all the flag names here - the single letters - must be lowercase! */ struct flagname1 flagname1s[] = { { GFLAG, 'g' }, { WFLAG, 'w' }, { QFLAG, 'q' }, { NFLAG, 'n' }, { SFLAG, 's' }, { DFLAG, 'd' }, { LFLAG, 'l' }, { MFLAG, 'm' }, { BFLAG, 'b' }, { OFLAG, 'o' }, { FFLAG, 'f' }, { JFLAG, 'j' }, { HFLAG, 'h' }, { AFLAG, 'a' }, { TFLAG, 't' }, { VFLAG, 'v' }, { UFLAG, 'u' }, { IFLAG, 'i' }, { PFLAG, 'p' }, { CFLAG, 'c' }, { EFLAG, 'e' }, { KFLAG, 'k' }, { RFLAG, 'r' }, { XFLAG, 'x' }, { YFLAG, 'y' }, { ZFLAG, 'z' }, { 0 } }; object_flag_type lookup_flag_by_name(const char *n, dbref relativeto) { int i; object_flag_type rf; if (n[1]) { if (relativeto == NOTHING) { for (i=0;flagnames[i].flag;i++) { if (string_prefix(flagnames[i].name,n)) { return(flagnames[i].flag); } } } else { rf = FLAGS(relativeto); for (i=0;flagnames[i].flag;i++) { if ( ((rf & flagnames[i].othermask) == flagnames[i].otherval) && string_prefix(flagnames[i].name,n) ) { return(flagnames[i].flag); } } } } else { char fnch; fnch = DOWNCASE(n[0]); for (i=0;flagname1s[i].flag;i++) { if (flagname1s[i].name == fnch) { return(flagname1s[i].flag); } } } return(0); } /*static*/ const char *unparse_flags(dbref thing) { static char buf[BUFFER_LEN]; char *p; const char *type_codes = "ROEPFDGN"; int i; object_flag_type f; p = &buf[0]; if (Typeof(thing) != TYPE_THING) *p++ = type_codes[Typeof(thing)]; f = FLAGS(thing); for (i=0;f&&flagname1s[i].flag;i++) { if (f & flagname1s[i].flag) { f &= ~flagname1s[i].flag; *p++ = flagname1s[i].name; } } *p = '\0'; return(&buf[0]); } const char *unparse_owner(dbref loc) { if (OWNER(loc) == NOTHING) return(""); return(NAME(OWNER(loc))); } const char *unparse_object(dbref player, dbref loc) { static char buf[BUFFER_LEN]; if (loc == NOTHING) return("*NOTHING*"); if (loc == HOME) return("*HOME*"); if (loc == BUILTIN) return("*BUILTIN*"); if ( ( (FLAGS(loc) & VISUAL) || ( (Typeof(loc) != TYPE_PLAYER) && (FLAGS(loc) & OWNABLE) ) || can_link_to(player,NOTYPE,loc) ) #ifdef SILENT_PLAYERS && !(FLAGS(player) & SILENT) #endif /* SILENT_PLAYERS */ ) { /* show everything */ if (FLAGS(player) & AUTHOR) { sprintf(&buf[0],"%s(#%d%s %s)", NAME(loc), (int)loc, unparse_flags(loc), unparse_owner(loc) ); } else { sprintf(&buf[0],"%s(#%d%s)", NAME(loc), (int)loc, unparse_flags(loc) ); } return(&buf[0]); } else { /* show only the name (and maybe owner) */ if (FLAGS(player) & AUTHOR) { sprintf(&buf[0],"%s(%s)",NAME(loc),unparse_owner(loc)); return(&buf[0]); } else { return(NAME(loc)); } } } #define OVERFLOW 512 static char boolexp_buf[BUFFER_LEN]; static char *buftop; static dbref boolexp_player; static void unparse_boolexp1(struct boolexp *b, boolexp_type outer_type) { if ((buftop-boolexp_buf) > (BUFFER_LEN-OVERFLOW)) { strcpy(buftop,"... (ovflw)"); buftop += strlen(buftop); } else { if (b == TRUE_BOOLEXP) { if (boolexp_player != NOTHING) { strcpy(buftop,"*UNLOCKED*"); buftop += strlen(buftop); } } else { switch (b->type) { case BOOLEXP_AND: if (outer_type == BOOLEXP_NOT) { *buftop++ = '('; } unparse_boolexp1(b->u.dyad.sub1,b->type); *buftop++ = AND_TOKEN; unparse_boolexp1(b->u.dyad.sub2,b->type); if (outer_type == BOOLEXP_NOT) { *buftop++ = ')'; } break; case BOOLEXP_OR: if ((outer_type == BOOLEXP_NOT) || (outer_type == BOOLEXP_AND)) { *buftop++ = '('; } unparse_boolexp1(b->u.dyad.sub1,b->type); *buftop++ = OR_TOKEN; unparse_boolexp1(b->u.dyad.sub2,b->type); if ((outer_type == BOOLEXP_NOT) || (outer_type == BOOLEXP_AND)) { *buftop++ = ')'; } break; case BOOLEXP_NOT: *buftop++ = '!'; unparse_boolexp1(b->u.monad,b->type); break; case BOOLEXP_OBJ: if (boolexp_player == NOTHING) { sprintf(buftop,"#%d",b->u.obj.thing); } else { strcpy(buftop,unparse_object(boolexp_player,b->u.obj.thing)); } buftop += strlen(buftop); if (b->u.obj.param) { sprintf(buftop,"'%s",b->u.obj.param); buftop += strlen(buftop); } break; case BOOLEXP_PROP: { char *t; strcpy(buftop,lockprop_name(b->u.prop)); buftop += strlen(buftop); *buftop++ = ':'; t = lockprop_value(b->u.prop); strcpy(buftop,t); free(t); buftop += strlen(buftop); } break; default: abort(); break; } } } } const char *unparse_boolexp(dbref player, struct boolexp *b) { boolexp_player = player; buftop = &boolexp_buf[0]; unparse_boolexp1(b,BOOLEXP_OBJ); *buftop++ = '\0'; return(&boolexp_buf[0]); } const char *unparse_boolexp_lock(struct boolexp *b) { boolexp_player = NOTHING; buftop = &boolexp_buf[0]; unparse_boolexp1(b,BOOLEXP_OBJ); *buftop++ = '\0'; return(&boolexp_buf[0]); }