/* $Header: /belch_a/users/rearl/tinymuck/src/RCS/look.c,v 1.17 90/10/06 19:04:30 rearl Exp $ */ /* * $Log: look.c,v $ * Revision 1.17 90/10/06 19:04:30 rearl * Fixed a typo in @# handling. * * Revision 1.16 90/10/06 16:32:49 rearl * Fixes for 2.2 distribution. * * Revision 1.15 90/09/28 12:24:13 rearl * Fixed small bug with disappearing descriptions... * * Revision 1.14 90/09/18 08:00:02 rearl * Took out FILTER. Fixed @find. * * Revision 1.13 90/09/16 04:42:25 rearl * Preparation code added for disk-based MUCK. * * Revision 1.12 90/09/15 22:25:59 rearl * Added argument passing to MUF from @#. COMPRESS fix for this as well. * * Revision 1.11 90/09/13 06:27:38 rearl * Argument passing with @# added. * * Revision 1.10 90/08/27 03:29:34 rearl * Added environment support. * * Revision 1.9 90/08/11 04:05:21 rearl * *** empty log message *** * * Revision 1.8 90/08/06 02:35:27 rearl * Oopsie, changed controls() back to can_link(). * * Revision 1.7 90/08/05 03:19:33 rearl * Redid matching routines. * * Revision 1.6 90/08/02 18:53:09 rearl * Changed can_link() to controls(). Everyone controls an unlinked exit. * * Revision 1.5 90/07/30 00:09:55 rearl * Added @owned command, lists everything you own, or for wizards, * everything owned by the specified player (including exits) * * Revision 1.4 90/07/29 21:19:17 rearl * Fixed examine-description brain damage. * * Revision 1.3 90/07/29 17:39:30 rearl * Fixed various things such as ROOM programs, examine bug, examine * of programs now shows location, etc. * * Revision 1.2 90/07/23 03:12:10 casie * Cleaned up various gcc warnings. * * Revision 1.1 90/07/19 23:03:52 casie * Initial revision * * */ #include "copyright.h" #include "config.h" /* commands which look at things */ #include <ctype.h> #include "db.h" #include "params.h" #include "interface.h" #include "match.h" #include "externs.h" #include "strings.h" #define EXEC_SIGNAL '@' /* Symbol which tells us what we're looking at * is an execution order and not a message. */ /* prints owner of something */ static void print_owner(dbref player, dbref thing) { char buf[BUFFER_LEN]; switch(Typeof(thing)) { case TYPE_PLAYER: sprintf(buf, "%s is a player.", NAME(thing)); break; case TYPE_ROOM: case TYPE_THING: case TYPE_EXIT: case TYPE_PROGRAM: sprintf(buf, "Owner: %s", NAME(OWNER(thing))); break; #ifdef RECYCLE case TYPE_GARBAGE: sprintf(buf, "%s is garbage.", NAME(thing)); break; #endif } notify(player, buf); } void exec_or_notify(dbref player, dbref thing, const char *message) { const char *p; p = get_uncompress(message); if (*p == EXEC_SIGNAL) { int i; i = atoi(++p); for (; *p && !isspace(*p); p++) ; if (*p) p++; if ((Typeof(i) != TYPE_PROGRAM) || DBFETCH(player)->run) { if (*p) { if(index(p, '\\')) { char buff[BUFFER_LEN]; strcpy(buff, p); p = buff; while(index(p, '\\') && (*(1 + index(p, '\\')) == 'n')) { *index(p, '\\') = '\0'; notify(player, p); p += strlen(p); p += 2; }; if(*p) notify (player, p); } else notify(player, p); } else notify(player, "You see nothing special."); } else { strcpy(match_args, p); (void) interp(player, i, thing); if (!(DBFETCH(player)->run -> pc)) { free((void *) DBFETCH(player)->run); DBSTORE(player, run, 0); } } } else { if(index(p, '\\')) { char buff[BUFFER_LEN]; strcpy(buff, p); p = buff; while(index(p, '\\') && (*(1 + index(p, '\\')) == 'n')) { *index(p,'\\') = '\0'; notify(player,p); p += strlen(p); p += 2; }; if(*p) notify(player, p); } else notify(player, p); } } static void look_exits(dbref player, dbref loc, const char *exits_name) { dbref thing; int flag = 1; char buf[BUFFER_LEN]; strcpy(buf, exits_name); DOLIST(thing, DBFETCH(loc)->exits) { if(!(FLAGS(thing)&DARK)) { if (flag == 0) strcat(buf, ", "); /* don't put a comma before the first exit */ strcat(buf, NAME(thing)); flag = 0; if(index(buf, ';')) *index(buf, ';') ='\0'; } } if(strcmp(buf, exits_name)) notify(player, buf); } static void look_contents(dbref player, dbref loc, const char *contents_name) { dbref thing; dbref can_see_loc; /* check to see if he can see the location */ can_see_loc = (!(Dark(loc) || Murky(loc)) || controls(player, loc)); /* check to see if there is anything there */ DOLIST(thing, DBFETCH(loc)->contents) { if(can_see(player, thing, can_see_loc)) { /* something exists! show him everything */ notify(player, contents_name); DOLIST(thing, DBFETCH(loc)->contents) { if(can_see(player, thing, can_see_loc)) { notify(player, unparse_object(player, thing)); } } break; /* we're done */ } } } static void look_simple(dbref player, dbref thing) { if(get_attr(thing, "Desc")) { exec_or_notify(player, thing, get_attr(thing, "Desc")); } else { notify(player, "You see nothing special."); } if(get_attr(thing, "Odesc")) { sprintf(buf,"%s %s", NAME(player), get_attr(thing, "Odesc")); notify_except(DBFETCH(getloc(player))->contents, player, pronoun_substitute(player, buf, thing)); } if(get_attr(thing, "Adesc")) { trigobj(thing, get_attr(thing, "Adesc"), player); } look_contents(player, thing, "Contents:"); } void look_room(dbref player, dbref loc) { /* tell him the name, and the number if he can link to it */ notify(player, unparse_object(player, loc)); /* tell him the description */ if(get_attr(loc, "Idesc")) { exec_or_notify(player, loc, get_attr(loc,"idesc")); } else if(get_attr(loc, "Desc")) { exec_or_notify(player, loc, get_attr(loc, "Desc")); } if(get_attr(loc, "Odesc")) { sprintf(buf,"%s %s", NAME(player), get_attr(loc, "Odesc")); notify_except(DBFETCH(getloc(player))->contents, player, pronoun_substitute(player, buf, loc)); } if(get_attr(loc, "Adesc")) { trigobj(loc, get_attr(loc, "Adesc"), player); } /* tell him the appropriate messages if he has the key */ if(Typeof(loc) == TYPE_ROOM) { /* we don't wanna see the osucc on an object. */ can_doit(player, loc, 0); if (!(FLAGS(loc)&DARK)) look_exits(player,loc,"Obvious exits: "); } /* tell him the contents */ look_contents(player, loc, "Contents:"); } void do_look_around(dbref player) { dbref loc; if((loc = getloc(player)) == NOTHING) return; look_room(player, loc); } void do_look_at(dbref player, const char *name) { dbref thing; struct match_data md; if(*name == '\0') { if((thing = getloc(player)) != NOTHING) { look_room(player, thing); } } else { /* look at a thing here */ init_match(player, name, NOTYPE, &md); match_all_exits(&md); match_neighbor(&md); match_possession(&md); if(Arch(player)) { match_absolute(&md); match_player(&md); } match_here(&md); match_me(&md); if((thing = noisy_match_result(&md)) != NOTHING) { switch(Typeof(thing)) { case TYPE_ROOM: if (getloc(player) != thing && !can_link_to(player, TYPE_ROOM, thing)) { notify(player, "Permission denied."); } else { look_room(player, thing); } break; default: look_simple(player, thing); break; } } } } void do_examine(dbref player, const char *name) { dbref thing; char buf[BUFFER_LEN]; dbref content; dbref exit; int i; struct match_data md; if(*name == '\0') { if((thing = getloc(player)) == NOTHING) return; } else { /* look it up */ init_match(player, name, NOTYPE, &md); match_all_exits(&md); match_neighbor(&md); match_possession(&md); match_absolute(&md); match_player(&md); match_here(&md); match_me(&md); /* get result */ if((thing = noisy_match_result(&md)) == NOTHING) return; } if(!can_link(player, thing) && !(FLAGS(thing)&VISIBLE) && !Arch(player)) { print_owner(player, thing); return; } switch(Typeof(thing)) { case TYPE_ROOM: sprintf(buf, "%s Owner: %s Parent: ", unparse_object(player, thing), NAME(OWNER(thing))); strcat(buf, unparse_object(player, DBFETCH(thing)->location)); break; case TYPE_THING: sprintf(buf, "%s Owner: %s Value: %d", unparse_object(player, thing), NAME(OWNER(thing)), DBFETCH(thing)->sp.thing.value); break; case TYPE_PLAYER: sprintf(buf, "%s Owner: %s Pennies: %d ", unparse_object(player, thing), NAME(OWNER(thing)), DBFETCH(thing)->sp.player.pennies); break; case TYPE_EXIT: case TYPE_PROGRAM: #ifdef RECYCLE case TYPE_GARBAGE: #endif sprintf(buf, "%s Owner: %s", unparse_object(player, thing), NAME(OWNER(thing))); break; } notify(player, buf); #ifdef VERBOSE_EXAMINE sprintf(buf,"Flags: %s",unparse_flag(FLAGS(thing))); notify(player, buf); #endif /* VERBOSE_EXAMINE */ sprintf(buf, "Key: %s", unparse_boolexp(player, DBFETCH(thing)->key)); notify(player, buf); /* show him the attributes */ if (DBFETCH(thing)->attributes) { struct plist *a; char buf[BUFFER_LEN]; sprintf(buf, "Attributes('%c'):", PROP_WIZARD); notify(player, buf); for (a = DBFETCH(thing) -> attributes; a; a = a -> next) { strncpy(buf, (a -> type) + 1, BUFFER_LEN - 1); strncat(buf, ": ", BUFFER_LEN - 1); strncat(buf, get_uncompress(a -> class), BUFFER_LEN - 1); notify(player, buf); } } /* show him the properties */ if (DBFETCH(thing)->properties) { struct plist *p; char buf[BUFFER_LEN]; notify(player, "Properties:"); for (p = DBFETCH(thing) -> properties; p; p = p -> next) { strncpy(buf, p -> type, BUFFER_LEN - 1); strncat(buf, ": ", BUFFER_LEN - 1); strncat(buf, get_uncompress(p -> class), BUFFER_LEN - 1); notify(player, buf); } } /* show him the contents */ if(DBFETCH(thing)->contents != NOTHING) { notify(player, "Contents:"); DOLIST(content, DBFETCH(thing)->contents) { notify(player, unparse_object(player, content)); } } switch(Typeof(thing)) { case TYPE_ROOM: /* tell him about exits */ if(DBFETCH(thing)->exits != NOTHING) { notify(player, "Exits:"); DOLIST(exit, DBFETCH(thing)->exits) { notify(player, unparse_object(player, exit)); } } else { notify(player, "No exits."); } /* print dropto if present */ if(DBFETCH(thing)->link != NOTHING) { sprintf(buf, "Dropped objects go to: %s", unparse_object(player, DBFETCH(thing)->link)); notify(player, buf); } break; case TYPE_THING: /* print home */ sprintf(buf, "Home: %s", unparse_object(player, DBFETCH(thing)->link)); /* home */ notify(player, buf); /* print location if player can link to it */ if(DBFETCH(thing)->location != NOTHING && (controls(player, DBFETCH(thing)->location) || can_link_to(player, NOTYPE, DBFETCH(thing)->location))) { sprintf(buf, "Location: %s", unparse_object(player, DBFETCH(thing)->location)); notify(player, buf); } /* print thing's actions, if any */ if(DBFETCH(thing)->exits != NOTHING) { notify(player, "Actions/exits:"); DOLIST(exit, DBFETCH(thing)->exits) { notify(player, unparse_object(player, exit)); } } else { notify(player, "No actions attached."); } break; case TYPE_PLAYER: /* print home */ sprintf(buf, "Home: %s", unparse_object(player, DBFETCH(thing)->link)); /* home */ notify(player, buf); /* print location if player can link to it */ if(DBFETCH(thing)->location != NOTHING && (controls(player, DBFETCH(thing)->location) || can_link_to(player, NOTYPE, DBFETCH(thing)->location))) { sprintf(buf, "Location: %s", unparse_object(player, DBFETCH(thing)->location)); notify(player, buf); } /* print player's actions, if any */ if(DBFETCH(thing)->exits != NOTHING) { notify(player, "Actions/exits:"); DOLIST(exit, DBFETCH(thing)->exits) { notify(player, unparse_object(player, exit)); } } else { notify(player, "No actions attached."); } break; case TYPE_EXIT: if (DBFETCH(thing)->location != NOTHING) { sprintf(buf, "Source: %s", unparse_object(player, DBFETCH(thing)->location)); notify(player, buf); } /* print destinations */ if (DBFETCH(thing)->sp.exit.ndest == 0) break; for (i = 0; i < DBFETCH(thing)->sp.exit.ndest; i++) { switch( (DBFETCH(thing)->sp.exit.dest)[i]) { case NOTHING: break; case HOME: notify(player, "Destination: *HOME*"); break; default: sprintf(buf, "Destination: %s", unparse_object(player, (DBFETCH(thing)->sp.exit.dest)[i])); notify(player, buf); break; } } break; case TYPE_PROGRAM: if (DBFETCH(thing)->sp.program.siz) sprintf(buf, "Program compiled size: %d", DBFETCH(thing)->sp.program.siz); else sprintf(buf, "Program not compiled."); notify(player, buf); /* print location if player can link to it */ if(DBFETCH(thing)->location != NOTHING && (controls(player, DBFETCH(thing)->location) || can_link_to(player, NOTYPE, DBFETCH(thing)->location))) { sprintf(buf, "Location: %s", unparse_object(player, DBFETCH(thing)->location)); notify(player, buf); } break; default: /* do nothing */ break; } } void do_score(dbref player) { char buf[BUFFER_LEN]; sprintf(buf, "You have %d %s.", DBFETCH(player)->sp.player.pennies, DBFETCH(player)->sp.player.pennies == 1 ? "penny" : "pennies"); notify(player, buf); } void do_inventory(dbref player) { dbref thing; if((thing = DBFETCH(player)->contents) == NOTHING) { notify(player, "You aren't carrying anything."); } else { notify(player, "You are carrying:"); DOLIST(thing, thing) { notify(player, unparse_object(player, thing)); } } do_score(player); } void do_owned(dbref player, const char *name, const char *filter) { dbref i, victim = 0; object_flag_type type_check = 0; object_flag_type flags_check = 0; int x, y, flag; struct match_data md; const char *type_codes = "R-EPF"; char temp[2]; if(!payfor(player, LOOKUP_COST)) { notify(player, "You don't have enough pennies."); return; } if(*name) if((victim = lookup_player(name)) == NOTHING) { init_match(player, name, NOTYPE, &md); match_me(&md); match_absolute(&md); match_player(&md); if((victim = match_result(&md)) == NOTHING) { notify(player, "I can't find that player."); return; } } if(victim && !controls(player, victim)) { notify(player, "Permission denied."); return; } for(x = 0; x < strlen(filter); x++) { flag = 0; for(y = 0; y < 5 && !flag; y++) if(filter[x] == type_codes[y]) { type_check |= filter_type(y); flag++; } if(!flag) { sprintf(temp, "%c", filter[x]); flags_check |= lookup_flag(temp); } } for(i = 0; i < db_top; i++) if(controls(player, i)) { flag = 1; if(victim) if(OWNER(i) != victim) flag = 0; if(flags_check && flag) if((FLAGS(i)&flags_check) != flags_check) flag = 0; if(type_check && flag) if(!(filter_type(Typeof(i))&type_check)) flag = 0; if(flag) notify(player, unparse_object(player, i)); } notify(player, "***End of List***"); } void do_find(dbref player, const char *name, const char *who) { dbref i, victim = 0; int flag; struct match_data md; if(!payfor(player, LOOKUP_COST)) { notify(player, "You don't have enough pennies."); return; } if(*who) if((victim = lookup_player(who)) == NOTHING) { init_match(player, who, NOTYPE, &md); match_me(&md); match_absolute(&md); match_player(&md); if((victim = match_result(&md)) == NOTHING) { notify(player, "I can't find that player."); return; } } if(victim && !controls(player, victim)) { notify(player, "Permission denied."); return; } for(i = 0; i < db_top; i++) if(controls(player, i)) { flag = 1; if (victim) if(OWNER(i) != victim) flag = 0; if (flag && *name) if(!string_match(NAME(i), name)) flag = 0; if(flag) notify(player, unparse_object(player, i)); } notify(player, "***End of List***"); } void do_trace(dbref player, const char *name, int depth) { dbref thing; int i; struct match_data md; init_match(player, name, NOTYPE, &md); match_absolute(&md); match_here(&md); match_me(&md); match_neighbor(&md); match_possession(&md); if ((thing = noisy_match_result(&md)) == NOTHING || thing == AMBIGUOUS) return; if(!depth) depth=30; /* Otherwise this'd crash the game */ for (i = 0; (!depth || i < depth) && thing != NOTHING; i++) { if (controls(player, thing) || can_link_to(player, NOTYPE, thing)) notify(player, unparse_object(player, thing)); else notify(player, "**Missing**"); thing = DBFETCH(thing)->location; } notify(player, "***End of List***"); }