muse1.7b4/
muse1.7b4/config/
muse1.7b4/doc/
muse1.7b4/run/
muse1.7b4/run/db/
muse1.7b4/src/
muse1.7b4/src/db/
muse1.7b4/src/files/
muse1.7b4/src/io/
muse1.7b4/src/prog/
muse1.7b4/src/util/
/* look.c */
/* $Id: look.c,v 1.18 1993/09/18 19:03:42 nils Exp $ */

/* commands which look at things */

#include "db.h"
#include "config.h"
#include "interface.h"
#include "match.h"
#include "externs.h"

static void look_exits(player,loc,exit_name)
     dbref player;
     dbref loc;
 char *exit_name;
{
  dbref thing;
  char buff[1024];
  char *e=buff;
  int flag=0;
  /* make sure location is a room */
  /*  if(db[loc].flags & DARK)
      return;*/
  for(thing=Exits(loc);(thing!=NOTHING) && (Dark(thing));thing=db[thing].next);
  if (thing==NOTHING)
    return;
/*  notify(player,exit_name);*/
  for(thing=Exits(loc);thing!=NOTHING;thing=db[thing].next)
    if(!(Dark(loc)) ||
       (IS(thing,TYPE_EXIT,EXIT_LIGHT) && controls(thing,loc,
						   POW_MODIFY)))
      if (!(Dark(thing)))
	/* chop off first exit alias to display */
	{
	 char *s;
	  if(!flag) {
	    notify(player,exit_name);
	    flag++;
	  }
	  if (db[thing].name && ((e-buff)<1000))
	    {
	      for(s=db[thing].name;*s && (*s!=';') && (e-buff<1000);*e++= *s++);
	      *e++=' ';
	      *e++=' ';
	    }
	}
  *e++=0;
  if(*buff)
    notify(player,buff);
}


static void look_contents(player,loc,contents_name)
     dbref player;
     dbref loc;
 char *contents_name;
{
  dbref thing;
  dbref can_see_loc;
  
  /* check to see if he can see the location */
  /* patched so that player can't see in dark rooms even if
     owned by that player.  (he must use examine command) */
  can_see_loc = ! Dark(loc);

  /* check to see if there is anything there */
  DOLIST(thing, db[loc].contents) {
    if(can_see(player, thing, can_see_loc)) {
      /* something exists!  show him everything */
      notify(player, contents_name);
      DOLIST(thing, db[loc].contents) {
	if(can_see(player, thing, can_see_loc)) {
	  notify(player, unparse_object(player, thing));
	}
      }
      break;              /* we're done */
    }
  }
}

static struct all_atr_list *all_attributes_internal (thing, myop, myend, dep)
     dbref thing;
     struct all_atr_list *myop;
     struct all_atr_list *myend;
     int dep;
{
  ALIST *k;
  struct all_atr_list *tmp;
  int i;
  extern NALLOC *glurp;

  for (k=db[thing].list; k; k=AL_NEXT(k))
    if (AL_TYPE(k) && ((dep==0)||(AL_TYPE(k)->flags&AF_INHERIT))) {
      for (tmp = myop; tmp; tmp=tmp->next)
	if (tmp->type == AL_TYPE(k))
	  break;
      if (tmp)
	continue;		/* there's already something with this type. */
      if (!myop) {
	myop = myend = na_alloc (glurp, sizeof(struct all_atr_list));
	myop->next = NULL;
      } else {
	struct all_atr_list *foo;
	foo = na_alloc(glurp, sizeof(struct all_atr_list));
	foo->next = myop;
	myop = foo;
      }
      myop->type = AL_TYPE(k);
      myop->value = AL_STR(k);
      myop->numinherit = dep;
    }
  for (i=0; db[thing].parents && db[thing].parents[i]!=NOTHING; i++) {
    if (myend)
      myop = all_attributes_internal (db[thing].parents[i], myop, myend, dep+1);
    else
      myop = all_attributes_internal (db[thing].parents[i], 0, 0, dep+1);
    while (myend && myend->next)
      myend = myend->next;
  }
  return myop;
}

struct all_atr_list *all_attributes (thing)
     dbref thing;
{
  return all_attributes_internal (thing, 0, 0, 0); /* start with 0 depth */
}

void look_atr(player,allatrs)
     dbref player;
     struct all_atr_list *allatrs;
{
  long cl;
  ATTR *attr;

  attr = allatrs->type;
  if ( attr->flags & AF_DATE ) {
    cl = atol(uncompress(allatrs->value));
    notify(player,tprintf("%s:%s",unparse_attr(attr, allatrs->numinherit),
			  mktm(cl,"D",player)));
  } else
    if (attr->flags & AF_LOCK)
      notify(player,
	     tprintf("%s:%s",unparse_attr(attr, allatrs->numinherit),
		     unprocess_lock(player,uncompress(allatrs->value))));
    else if (attr->flags & AF_FUNC)
      notify(player,
	     tprintf("%s():%s",unparse_attr(attr, allatrs->numinherit),
		     uncompress(allatrs->value)));
    else
      notify(player,
	     tprintf("%s:%s",unparse_attr(attr, allatrs->numinherit),
		     uncompress(allatrs->value)));
}

void look_atrs(player,thing)
     dbref player;
     dbref thing;
{
  struct all_atr_list *allatrs;
  ATTR *attr;

  for (allatrs = all_attributes(thing); allatrs; allatrs=allatrs->next) {
    if ((allatrs->type!=A_DESC) &&
	(attr=allatrs->type) &&
	can_see_atr(player, thing, attr))
      look_atr(player,allatrs);
   }
}

static void look_simple(player,thing,doatrs)
     dbref player;
     dbref thing;
     int doatrs;
{
  Access(thing);
  if (controls(player,thing,POW_EXAMINE) || (db[thing].flags & SEE_OK))
    notify(player,unparse_object(player,thing));
  /*    if(*Desc(thing)) {
        notify(player, Desc(thing));
	} else {
        notify(player, "You see nothing special.");
	}*/
  if (doatrs)
    did_it(player,thing,A_DESC,"You see nothing special.",A_ODESC,NULL,A_ADESC);
  else
    did_it(player,thing,A_DESC,"You see nothing special.",NULL,NULL,NULL);
  if (Typeof(thing)==TYPE_EXIT)
    if (db[thing].flags & OPAQUE)
      if (db[thing].link != NOTHING) {
	notify(player,tprintf("You peer through to %s...",db[db[thing].link].name));
	did_it (player, db[thing].link, A_DESC, "You see nothing on the other side.",doatrs?A_ODESC:NULL,NULL,doatrs?A_ADESC:NULL);
	look_contents(player, db[thing].link, "You also notice:");
      }
}

void look_room(player,loc)
     dbref player;
     dbref loc;
{
  char *s;
  /* tell him the name, and the number if he can link to it */
  notify(player, unparse_object(player, loc));
  if (Typeof(loc)!=TYPE_ROOM)
    {
      did_it(player, loc, A_IDESC, NULL, NULL, NULL, NULL);
    }
  /* tell him the description */
  /*     if(*Desc(loc)) notify(player, Desc(loc));*/
  else {
    if (!(db[player].flags & PLAYER_TERSE)) {
      if (*(s=atr_get(get_zone_first(player),A_IDESC)) && !(db[loc].flags & OPAQUE)) 
      notify(player,s);
      did_it(player,loc,A_DESC,NULL,A_ODESC,NULL,A_ADESC);
    }
  }
  /* tell him the appropriate messages if he has the key */
  if (Typeof(loc)==TYPE_ROOM)
    {
      if (could_doit(player,loc,A_LOCK))
	did_it(player,loc,A_SUCC,NULL,A_OSUCC,NULL,A_ASUCC);
      else
	did_it(player,loc,A_FAIL,NULL,A_OFAIL,NULL,A_AFAIL);
    }
  
  /* tell him the contents */
  look_contents(player, loc, "Contents:");
  look_exits(player,loc,"Obvious exits:");
}

void do_look_around(player)
     dbref player;
{
  dbref loc;
  
  if((loc = getloc(player)) == NOTHING) return;
  look_room(player, loc);
}

void do_look_at(player,arg1)
     dbref player;
 char *arg1;
{
  dbref thing, thing2;
  char *s, *p;
  char *name=arg1; /* so we don't mangle it */
  
  if(*name == '\0') {
    if((thing = getloc(player)) != NOTHING) {
      look_room(player, thing);
    }
  } else {
    /* look at a thing here */
    init_match(player, name, NOTYPE);
    match_exit();
    match_neighbor();
    match_possession();
    if(power(player, POW_REMOTE)) {
      match_absolute();
      match_player();
    }
    match_here();
    match_me();
    
    switch(thing = match_result()) {
    case NOTHING:
      for(s = name; *s && *s != ' '; s++);
      if (!*s) {
	notify(player,tprintf(NOMATCH_PATT,arg1));
	return;
      }
      p = name;
      if ((*(s - 1) == 's' && *(s - 2) == '\'' && *(s - 3) != 's') ||
	  (*(s - 1) == '\'' && *(s - 2) == 's')) {
	
	if (*(s - 1) == 's') *(s - 2) = '\0';
	else *(s - 1) = '\0';
	name = s + 1;
	init_match(player, p, TYPE_PLAYER);
	match_neighbor();
	match_possession();
	switch (thing=match_result()) {
	case NOTHING:
	  notify(player,tprintf(NOMATCH_PATT,arg1));
	  break;
	case AMBIGUOUS:
	  notify(player,AMBIGUOUS_MESSAGE);
	  break;
	default:
	  init_match(thing, name, TYPE_THING);
	  match_possession();
	  switch(thing2 = match_result()) {
	  case NOTHING:
	    notify(player,tprintf(NOMATCH_PATT,arg1));
	    break;
	  case AMBIGUOUS:
	    notify(player,AMBIGUOUS_MESSAGE);
	    break;
	  default:
	    if ((db[thing].flags & OPAQUE)
		&& !power(player, POW_EXAMINE)) {
	      notify(player, tprintf(NOMATCH_PATT,name));
	    } else {
	      look_simple(player, thing2, 0);
	    }
	  }
	}
      }
      else
	notify(player, tprintf(NOMATCH_PATT,arg1));
      break;
    case AMBIGUOUS:
      notify(player,AMBIGUOUS_MESSAGE);
      break;
    default:
      switch(Typeof(thing)) {
      case TYPE_ROOM:
	look_room(player, thing);
	look_atrs(player,thing);
	break;
      case TYPE_THING:
      case TYPE_PLAYER:
	look_simple(player, thing, 1);
	/*look_atrs(player,thing);*/
	if (controls(player, thing, POW_EXAMINE) ||
	    !(db[thing].flags & OPAQUE) ||
	    power(player, POW_EXAMINE)){
	  look_contents(player, thing, "Carrying:");
	}
	break;
      default:
	look_simple(player, thing, 1);
	/*look_atrs(player,thing);*/
	break;
      }
    }
  }
}

char *flag_description(thing)
     dbref thing;
{
  static char buf[BUFFER_LEN];
  
  strcpy(buf, "Type: ");
  switch(Typeof(thing)) {
  case TYPE_ROOM:
    strcat(buf, "Room");
    break;
  case TYPE_EXIT:
    strcat(buf, "Exit");
    break;
  case TYPE_THING:
    strcat(buf, "Thing");
    break;
  case TYPE_PLAYER:
    strcat(buf, "Player");
    break;
  default:
    strcat(buf, "***UNKNOWN TYPE***");
    break;
  }
  
  if(db[thing].flags & ~TYPE_MASK) {
    /* print flags */
    strcat(buf, "      Flags:");
#ifdef DESTROY
    if(db[thing].flags & GOING) strcat(buf," going");
#endif /* DESTROY */
    if(db[thing].flags & PUPPET) strcat(buf," puppet");
    if(db[thing].flags & STICKY) strcat(buf," sticky");
    if(db[thing].flags & DARK) strcat(buf," dark");
    if(db[thing].flags & LINK_OK) strcat(buf," link_ok");
    if(db[thing].flags & HAVEN) strcat(buf," haven");
    if(db[thing].flags & CHOWN_OK) strcat(buf," chown_ok");
    if(db[thing].flags & ENTER_OK) strcat(buf," enter_ok");
    if(db[thing].flags & SEE_OK) strcat(buf," visible");
    if(db[thing].flags & OPAQUE) strcat(buf,(Typeof(thing)==TYPE_EXIT)?" transparent":" opaque");
    if(db[thing].flags & INHERIT_POWERS) strcat(buf," inherit");
    if(db[thing].flags & QUIET) strcat(buf," quiet");
    if(db[thing].flags & BEARING) strcat(buf," bearing");
    switch(Typeof(thing)) {
    case TYPE_PLAYER:
      if(db[thing].flags & PLAYER_SLAVE) strcat(buf," slave");
      if(db[thing].flags & PLAYER_CONNECT) strcat(buf," connected");
      if(db[thing].flags & PLAYER_TERSE) strcat(buf," terse");
      if(db[thing].flags & PLAYER_MORTAL) strcat(buf," mortal");
      if(db[thing].flags & PLAYER_NO_WALLS) strcat(buf," no_walls");
      break;
    case TYPE_EXIT:
      if(db[thing].flags & EXIT_LIGHT) strcat(buf," light");
      break;
    case TYPE_THING:
      if(db[thing].flags & THING_KEY) strcat(buf," key");
      if(db[thing].flags & THING_DEST_OK) strcat(buf," destroy_ok");
      if(db[thing].flags & THING_SACROK) strcat(buf," x_ok");
      if(db[thing].flags & THING_LIGHT) strcat(buf," light");
      break;
    case TYPE_ROOM:
      if(db[thing].flags&ROOM_TEMPLE) strcat(buf," temple");
      if(db[thing].flags&ROOM_JUMP_OK) strcat(buf," jump_ok");
      if(db[thing].flags&ROOM_AUDITORIUM) strcat(buf," auditorium");
      if(db[thing].flags&ROOM_FLOATING) strcat(buf," floating");
#ifdef USE_SPACE
      if(db[thing].flags&ROOM_ZEROG) strcat(buf," zerog");
#endif
      break;
    }
  }
  return buf;
}
void do_examine(player,name)
     dbref player;
     char *name;
{
  dbref thing;
  dbref content;
  dbref exit;
  dbref enter;
  char *rq, *rqm, *cr, *crm, buf[10];
  int pos=0;
  struct all_atr_list attr_entry;

  if(*name == '\0') {
    if((thing = getloc(player)) == NOTHING) return;
  } else {
    if (strchr(name, '/')) {
      if (!parse_attrib(player,name,&thing,&(attr_entry.type),0)) 
	notify(player, "No match.");
      else if (!can_see_atr(player, thing, attr_entry.type)) {
	notify(player, "Permission denied.");
      } else {
	attr_entry.value = atr_get(thing, attr_entry.type);
	attr_entry.numinherit = 0; /* could find this, prob'ly not worth it */
	look_atr(player,&attr_entry);
      }
      return;
    }
    /* look it up */
    init_match(player, name, NOTYPE);
    match_exit();
    match_neighbor();
    match_possession();
    match_absolute();
    /* only Wizards can examine other players */
    if( has_pow(player,NOTHING, POW_EXAMINE) || has_pow(player, NOTHING,POW_REMOTE))
      match_player();
    /*      if(db[thing].flags & UNIVERSAL)
	    match_absolute(); */
    match_here();
    match_me();
    
    /* get result */
    if((thing = noisy_match_result()) == NOTHING) return;
  }
  
  if ((! can_link(player, thing, POW_EXAMINE)  &&
      ! (db[thing].flags & SEE_OK))) { 
    char buf2[BUFFER_LEN];
    
    strcpy(buf2, unparse_object(player, thing));
    notify(player, tprintf("%s is owned by %s",
			   buf2, unparse_object(player, db[thing].owner)));
    look_atrs(player,thing);	/* only show osee attributes */
    /* check to see if there is anything there */
    /* as long as he owns what is there */
    DOLIST(content, db[thing].contents) {
      if ( can_link(player, content, POW_EXAMINE) ) {
	notify(player, "Contents:");
	DOLIST(content, db[thing].contents) {
	  if( can_link(player, content, POW_EXAMINE) ) {
	    notify(player, unparse_object(player, content));
	  }
	}
	break;          /* we're done */
      }
    }
    return;
  }
  notify(player, unparse_object(player, thing));
  if (*Desc(thing) && can_see_atr (player, thing, A_DESC))
    notify(player,Desc(thing));
  
  rq = rqm = "";
  sprintf(buf, "%d", Pennies(thing));
  cr = buf;
  crm = "  Credits: ";
  if ( Typeof(thing) == TYPE_PLAYER )  {
    if ( Robot(thing) )
      cr = crm = "";
    else  {
      if (inf_mon(thing)) cr = "INFINITE";
      rqm = "  Quota-Left: ";
      if (inf_quota(thing))
	rq = "INFINITE";
      else  {
	rq = atr_get(thing, A_RQUOTA);
	if ( atoi(rq) <= 0 )
	  rq = "NONE";
      }
    }
  }
  notify(player, tprintf( "Owner: %s%s%s%s%s",
			 db[db[thing].owner].name, crm, cr, rqm, rq));
  notify(player,flag_description(thing));
  if (db[thing].zone != NOTHING)
    notify(player, tprintf("Zone: %s", unparse_object(player,db[thing].zone)));
  notify(player, tprintf("Created: %s",
			 db[thing].create_time?
			 mktm(db[thing].create_time,"D",player):"never"));
  notify(player, tprintf("Modified: %s",
			 db[thing].mod_time?
			 mktm(db[thing].mod_time,"D",player):"never"));
  if (db[thing].parents && *db[thing].parents != NOTHING) {
    char obuf[1000],buf[1000];
    int i;

    strcpy(obuf,"Parents:");
    for (i=0; db[thing].parents[i]!=NOTHING; i++) {
      sprintf(buf," %s",unparse_object(player, db[thing].parents[i]));
      if (strlen(buf)+strlen(obuf)>900) {
	notify(player, obuf);
	strcpy(obuf, buf+1);
      } else
	strcat(obuf, buf);
    }
    notify(player, obuf);
  }
  if (db[thing].atrdefs) {
    ATRDEF *k;
    notify(player, "Attribute definitions:");
    for (k=db[thing].atrdefs; k; k=k->next) {
      char buf[1000];
      sprintf(buf,"  %s%s%c", k->a.name, (k->a.flags & AF_FUNC) ? "()" : "",
	      (k->a.flags)?':':'\0');
      if (k->a.flags & AF_WIZARD)
	strcat(buf, " wizard");
      if (k->a.flags & AF_UNIMP)
	strcat(buf, " unsaved");
      if (k->a.flags & AF_OSEE)
	strcat(buf, " osee");
      if (k->a.flags & AF_INHERIT)
	strcat(buf, " inherit");
      if (k->a.flags & AF_DARK)
	strcat(buf, " dark");
      if (k->a.flags & AF_DATE)
	strcat(buf, " date");
      if (k->a.flags & AF_LOCK)
	strcat(buf, " lock");
      if (k->a.flags & AF_FUNC)
	strcat(buf, " function");
      notify(player, buf);
    }
  }
  look_atrs(player,thing);
  
  /* show him the contents */
  if(db[thing].contents != NOTHING) {
    notify(player, "Contents:");
    DOLIST(content, db[thing].contents) {
      notify(player, unparse_object(player, content));
    }
  }
  fflush(stdout);
  switch(Typeof(thing)) {
  case TYPE_ROOM:
    /* tell him about entrances */
    for (enter=0; enter<db_top; enter++)
      if(Typeof(enter) == TYPE_EXIT && db[enter].link == thing) {
	if (pos == 0) notify(player, "Entrances:");
        pos=1;
	notify(player, unparse_object(player, enter));
      }
      if (pos == 0) notify(player, "No Entrances.");

    /* tell him about exits */
    if(Exits(thing) != NOTHING) {
      notify(player, "Exits:");
      DOLIST(exit, Exits(thing)) {
	notify(player, unparse_object(player, exit));
      }
    } else {
      notify(player, "No exits.");
    }
    
    /* print dropto if present */
    if(db[thing].link != NOTHING) {
      notify(player,
	     tprintf( "Dropped objects go to: %s",
		     unparse_object(player, db[thing].link)));
    }
    break;
  case TYPE_THING:
  case TYPE_PLAYER:
    /* print home */
    notify(player,
	   tprintf( "Home: %s",
		   unparse_object(player, db[thing].link))); /* home */
    /* print location if player can link to it */
    if(db[thing].location != NOTHING
       && (controls(player, db[thing].location,POW_EXAMINE) ||
	   controls(player,thing,POW_EXAMINE)
	   || can_link_to(player, db[thing].location, POW_EXAMINE))) {
      notify(player,
	     tprintf( "Location: %s",
		     unparse_object(player, db[thing].location)));
    }
    if(Typeof(thing)==TYPE_THING) {
    for (enter=0; enter<db_top; enter++)
      if(Typeof(enter) == TYPE_EXIT && db[enter].link == thing) {
	if (pos == 0) notify(player, "Entrances:");
        pos=1;
	notify(player, unparse_object(player, enter));
      }
    }
    if(Typeof(thing)==TYPE_THING && db[thing].exits != NOTHING) {
      notify(player,"Exits:");
      DOLIST(exit,db[thing].exits) {
	notify(player,unparse_object(player,exit));
      }
    }
    break;
  case TYPE_EXIT:
    /* Print source */
    notify(player,tprintf("Source: %s",
			  unparse_object(player,db[thing].location)));
    /* print destination */
    switch(db[thing].link) {
    case NOTHING:
      break;
    case HOME:
      notify(player, "Destination: *HOME*");
      break;
    default:
      notify(player,
	     tprintf("Destination: %s",
		     unparse_object(player, db[thing].link)));
      break;
    }
    break;
  default:
    /* do nothing */
    break;
  }
}

void do_score(player)
     dbref player;
{
  
  notify(player,
	 tprintf("You have %d %s.",
		 Pennies(player),
		 Pennies(player) == 1 ? "Credit" : "Credits"));
}

void do_inventory(player)
     dbref player;
{
  dbref thing;
  
  if((thing = db[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_find(player,name)
     dbref player;
 char *name;
{
  dbref i;
  
  if(!payfor(player, FIND_COST)) {
    notify(player, "You don't have enough Credits.");
  } else {
    for(i = 0; i < db_top; i++) {
      if(Typeof(i) != TYPE_EXIT
	 && (power(player,POW_EXAMINE) || db[i].owner==db[player].owner)
	 && (!*name || string_match(db[i].name, name))) {
	notify(player, unparse_object(player, i));
      }
    }
    notify(player, "***End of List***");
  }
}

void print_atr_match(thing, player, str)
     dbref thing;
     dbref player;
     char *str;
{
  struct all_atr_list *ptr;
  for(ptr=all_attributes(thing);ptr;ptr=ptr->next)
    if ((ptr->type!=0) && !(ptr->type->flags & AF_LOCK) &&
	((*ptr->value=='!') || (*ptr->value=='$'))) {
      /* decode it */
      char buff[1024];
      char *s;

      strncpy(buff,uncompress(ptr->value),1024);
      /* search for first un escaped : */
      for(s=buff+1;*s && (*s!=':');s++);
      if (!*s)
	continue;
      *s++=0;
      if (wild_match(buff+1,str)) {
	if (controls(player, thing, POW_SEEATR))
	  notify(player,tprintf(" %s/%s: %s",unparse_object(player,thing),unparse_attr(ptr->type, ptr->numinherit), buff+1));
	else
	  notify(player,tprintf(" %s",unparse_object(player,thing)));
      }
    }
}

/* check the current location for bugs */
void do_sweep(player, arg1)
     dbref player;
     char *arg1;
{
  dbref zon;
  if (*arg1) {
    dbref i;
    notify(player,tprintf("All places that respond to %s:",arg1));
    for (i=db[db[player].location].contents; i != NOTHING; i=db[i].next)
      if (Typeof(i) != TYPE_PLAYER || i == player)
	print_atr_match(i, player, arg1);
    for (i=db[player].contents; i != NOTHING; i=db[i].next)
      if (Typeof(i) != TYPE_PLAYER || i == player)
	print_atr_match(i, player, arg1);
    print_atr_match(db[player].location, player, arg1);
    for (i=db[db[player].location].exits; i != NOTHING; i=db[i].next)
      if (Typeof(i) != TYPE_PLAYER || i == player)
	print_atr_match(i, player, arg1);
    print_atr_match(db[player].zone, player, arg1);
    if (db[player].zone != db[0].zone)
      print_atr_match(db[0].zone, player, arg1);
  } else {
    dbref here=db[player].location;
    dbref test;
    test=here;
    if (here==NOTHING)
      return;
    if (Dark(here)) {
      notify(player,"Sorry it is dark here; you can't search for bugs");
      return;
    }
    notify(player, "Sweeping...");
    DOZONE(zon, player)
      if (Hearer(zon)) {
	notify(player, "Zone:");
	break;
      }
    DOZONE(zon, player)
      if (Hearer(zon)) {
	notify(player, "Zone:");
	notify(player,tprintf("  %s =%s.",db[zon].name,
			      eval_sweep(db[here].zone))); }
    if (Hearer(here)) {
      notify(player, "Room:");
      notify(player,tprintf("  %s =%s.",db[here].name,
			    eval_sweep(here))); }
    for(test=db[test].contents;test!=NOTHING;test=db[test].next)
      if (Hearer(test)) {
	notify(player, "Contents:");
	break;
      }
    test=here;
    for(test=db[test].contents;test!=NOTHING;test=db[test].next)
      if (Hearer(test))
	notify(player,tprintf("  %s =%s.",db[test].name,
			      eval_sweep(test)));
    test=here;
    for(test=db[test].exits;test!=NOTHING;test=db[test].next)
      if (Hearer(test)) {
	notify(player, "Exits:");
	break;
      }
    test=here;
    for(test=db[test].exits;test!=NOTHING;test=db[test].next)
      if (Hearer(test))
	notify(player,tprintf("  %s =%s.",db[test].name,
			      eval_sweep(test)));
    for(test=db[player].contents;test!=NOTHING;test=db[test].next)
      if (Hearer(test)) {
	notify(player, "Inventory:");
	break;
      }
    for(test=db[player].contents;test!=NOTHING;test=db[test].next)
      if (Hearer(test))
	notify(player,tprintf("  %s =%s.",db[test].name,
			      eval_sweep(test)));
    notify(player, "Done.");
  }
}

void do_whereis(player, name)
     dbref player;
 char *name;
{
  dbref thing;
  
  if(*name == '\0') {
    notify(player,"You must specify a valid player name.");
    return;
  }
  if ((thing = lookup_player(name)) == NOTHING || Typeof(thing)!=TYPE_PLAYER) {
    notify(player,tprintf("%s does not seem to exist.",name));
    return;
  }
  /*
    init_match(player, name, TYPE_PLAYER);
    match_player();
    match_exit();
    match_neighbor();
    match_possession();
    match_absolute();
    match_me();
    */
  
  if(db[thing].flags & DARK) {
    notify(player,tprintf("%s wishes to have some privacy.",db[thing].name));
    if(!could_doit(player,thing,A_LPAGE))
      notify(thing,
	     tprintf("%s tried to locate you and failed.",
		     unparse_object(thing,player)));
    return;
  }
  notify(player,
	 tprintf("%s is at: %s.", db[thing].name,
		 unparse_object(player,db[thing].location)));
  if(!could_doit(player,thing,A_LPAGE))
    notify(thing,
	   tprintf("%s has just located your position.",
		   unparse_object(thing,player)));
  return;
  
}

void do_laston(player, name)
     dbref player;
     char *name;
{
  char *attr;
  dbref thing;
  long tim;
  
  if(*name == '\0') {
    notify(player,"You must specify a valid player name.");
    return;
  } 
  
  if ((thing = lookup_player(name)) == NOTHING || Typeof(thing)!=TYPE_PLAYER) {
    notify(player,tprintf("%s does not seem to exist.",name));
    return;
  }
  
  attr = atr_get(thing, A_LAST);
  tim = atol(attr);
  if (!tim)
    notify(player, tprintf("%s has never logged on.", db[thing].name));
  else
    notify(player, tprintf("%s was last logged on: %s.",
      db[thing].name, mktm(tim, "D", player)));

  return;
}

char *eval_sweep(thing)
  dbref thing;
{
  static char sweep_str[30];
  strcpy(sweep_str, "\0");
  if (Live_Player(thing)) strcat(sweep_str, " player");
  if (Live_Puppet(thing)) strcat(sweep_str, " puppet");
  if (Commer(thing)) strcat(sweep_str, " commands");
  if (Listener(thing)) strcat(sweep_str, " messages");
  return sweep_str;
}

/* End look.c */