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/
/* player.c */
/* $Id: player.c,v 1.17 1993/09/07 18:24:24 nils Exp $ */

#include "db.h"
#include "config.h"
#include "interface.h"
#include "externs.h"
#include "credits.h"
#include "player.h"
#include "admin.h"
#include "nalloc.h"
#ifdef USE_SPACE /* Added by MM */
#include "space.h"
#endif
extern NALLOC *db_strings;

dbref connect_player(name,password)
     char *name;
     char *password;
{
  dbref player;
  /*    long tt;
	char *s; */

  player = lookup_player(name);
  if(player == NOTHING || Typeof(player)!=TYPE_PLAYER)
    return NOTHING;
  if(*Pass(player)
     /*       &&strcmp(Pass(player), password)*/
     && (strcmp(Pass(player), password) || !strncmp(Pass(player),"XX",2)) &&
     strcmp(crypt(password,"XX"),Pass(player))
     ) return NOTHING;
  
/*        time(&tt);
	s=ctime(&tt);
	s[strlen(s)-1]=0; 
	* compare to last connect see if player gets salary *
	if ((strncmp(atr_get(player,A_LAST),s,10)!=0) &&
             has_pow(player, POW_MEMBER))
	  giveto(player,PAY_CHECK);
	notify(player,tprintf("Last login: %s",atr_get(player,A_LAST))); 
	atr_add(player,A_LAST,s);  */
  
  return player;
}

dbref create_guest(name, password)
     char *name;
     char *password;
{
  dbref player;
  char key[10];
  
  /* make sure that old guest id's don't hang around! */
  player = lookup_player(name);
  if ( player != NOTHING )
    destroy_player(player);
  
  /* make new player */
  player = create_player(name, password,CLASS_GUEST);
  if ( player == NOTHING ) {
    log_error("failed in create_player");
    return NOTHING;
  }
  
  /* reclass as guest */
/*  db[player].flags &= ~TYPE_MASK;*/
  /*  db[player].flags |= TYPE_GUEST;*/
  
  /* lock guest to him/her-self */
  sprintf(key, "#%d", player);
  atr_add(player, A_LOCK, key);
  
  /* set guest's description */
  atr_add(player, A_DESC,
	  "A guest player!  Please be courteous and helpful.");
  
  return player;
}

/* extra precaution just in case a regular
   player is passed somehow to this routine */
void destroy_guest(guest)
     dbref guest;
{
  if(!Guest(guest))
    return;
  
  destroy_player(guest);
}


char *class_to_name();


dbref create_player(name,password,class)
     char *name;
     char *password;
     int class;
{
  dbref player;
  
  if(!ok_player_name(name) || !ok_password(password)) {
    log_error("failed in name check");
    report();
    return NOTHING;
  }
  
  /* else he doesn't already exist, create him */
  player = new_object();
  
  /* initialize everything */
  SET(db[player].name,name);
  db[player].location = PLAYER_START;
  db[player].link = PLAYER_START;
  db[player].owner = player;
  /*  db[player].flags = TYPE_TRIALPL;*/
  db[player].flags=TYPE_PLAYER | PLAYER_NEWBIE | SEE_OK;
  db[player].pows=malloc(sizeof(ptype)*2);
  db[player].pows[0] =CLASS_GUEST;	/* re@class later. */
  db[player].pows[1] = 0;
  s_Pass(player,crypt(password,"XX"));
  giveto(player,START_BONUS); /* starting bonus */
  #ifdef RESTRICTED_BUILDING
  atr_add(player, A_RQUOTA, "0");
  atr_add(player, A_QUOTA, "0");
  #else
  atr_add(player, A_RQUOTA, START_QUOTA);
  atr_add(player, A_QUOTA, START_QUOTA);
  #endif
  /* link him to PLAYER_START */
  PUSH(player, db[PLAYER_START].contents);
  
  add_player(player);
  if(class!=CLASS_GUEST) {
    do_force(GOD, tprintf("#%d",player), "+channel +public");
    parse_que(GOD,tprintf("@class #%d=%s\n",player,class_to_name(class)),GOD); /* this can put in the powers. */
  }
  return player;
}

void destroy_player(player)
     dbref player;
{
  dbref loc, thing;
  
  /* destroy all of the player's things/exits/rooms */
  for(thing = 0; thing < db_top; thing++) {
    if ( db[thing].owner == player && thing != player) {
      moveto(thing, NOTHING);
      switch (Typeof(thing)) {
      case TYPE_PLAYER:
      case TYPE_THING:
	do_empty(thing);
	break;
      case TYPE_EXIT:
	loc = find_entrance(thing);
	s_Exits(loc,remove_first(Exits(loc), thing));
	do_empty(thing);
	break;
      case TYPE_ROOM:
	db[thing].flags |= GOING;
	break;
      }
    }
  }
  
  /* if guest player, free guest number slot for future use */
  if(Guest(player))
    mark_free(atoi(&db[player].name[strlen(GUEST_PREFIX)]));
  
  boot_off(player);		/* disconnect player (just making sure) :) */
  do_halt(player, "");	/* halt processes ? */
  moveto(player, NOTHING);	/* send it to nowhere */
  delete_player(player);	/* remove player from player list */
  do_empty(player);		/* destroy player-object */
}

void do_pcreate(creator, player_name, player_password)
     dbref creator;
     char *player_name;
     char *player_password;
{
  dbref player;
  
  if ( ! power(creator, POW_PCREATE) )  {
    notify(creator, "You don't have the authority to do that.");
    return;
  }
  
  if (lookup_player(player_name) != NOTHING) {
    notify(creator, tprintf("there is already a %s",unparse_object(creator,lookup_player(player_name))));
    return;
  }

  if (!ok_player_name(player_name)) {
    notify(creator, tprintf("illegal player name '%s'",player_name));
    return;
  }

  player = create_player(player_name, player_password,CLASS_VISITOR);
  if (player == NOTHING) {
    notify(creator, tprintf("failure creating '%s'", player_name));
    return;
  }
  
  notify(creator, tprintf("New player '%s' created with password '%s'",
			  player_name, player_password));
  log_sensitive(tprintf("%s pcreated %s with password %s",unparse_object_a(GOD,creator),unparse_object_a(GOD,player), player_password));
}

void do_password(player,old,newobj)
     dbref player;
 char *old;
 char *newobj;
{
  if ( ! has_pow (player,NOTHING,POW_MEMBER) ) {
    notify(player,
	   tprintf("Only registered %s users may change their passwords.",
		   MUSE_NAME));
    return;
  }
  
  if(!*Pass(player) || 
     (strcmp(old, Pass(player)) && strcmp(crypt(old,"XX"),Pass(player)))) {
    notify(player, "Sorry");
  } else if(!ok_password(newobj)) {
    notify(player, "Bad new password.");
  } else {
    s_Pass(player,crypt(newobj,"XX"));
    notify(player, "Password changed.");
  }
}

void do_nuke(player,name)
     dbref player;
 char *name;
{
  dbref victim;
  
  /*    if ( RLevel(player) < TYPE_ADMIN )*/
  if((!power(player,POW_NUKE)) || (Typeof(player)!=TYPE_PLAYER)) {
    notify(player, "This is a restricted command.");
    return;
  }
  
  init_match(player, name, TYPE_PLAYER);
  match_neighbor();
  match_absolute();
  match_player();
  if((victim = noisy_match_result()) == NOTHING) return;
  
  if(Typeof(victim) != TYPE_PLAYER) {
    notify(player, "You can only nuke players!");
  } else if( ! controls(player, victim,POW_NUKE) ) {
    notify(player, "You don't have the authority to do that.");
  } else if(owns_stuff(victim)) {
    notify(player, "You must @wipeout their junk first.");
  } else {
    /* get rid of that guy, destroy him */
    while(boot_off(victim)); /* boot'm off lotsa times! */
    do_halt(victim,"");
    delete_player(victim);
    db[victim].flags = TYPE_THING;
    db[victim].owner = GOD;
    destroy_obj(victim, atoi(DEFAULT_DOOMSDAY));
    
    notify(player, tprintf("%s - nuked.", db[victim].name));
    log_sensitive(tprintf("%s(#%d) executed: @nuke %s(#%d)",
			  db[player].name, player, db[victim].name, victim));
  }
}
ptype name_to_pow(nam)
     char *nam;
{
  int k;
  for(k=0;k<NUM_POWS;k++)
    if(!string_compare(powers[k].name,nam))
      return powers[k].num;
  return 0;
}
char *pow_to_name(pow)
     ptype pow;
{
  int k;
  for(k=0;k<NUM_POWS;k++)
    if(powers[k].num==pow)
      return powers[k].name;
  return "<unknown power>";
}
char *get_class(player)
     dbref player;
{
  extern char *type_to_name();
  
  if(Typeof(player)==TYPE_PLAYER)
    return class_to_name(*db[player].pows);
  else
    return type_to_name(Typeof(player));
}
void do_checkpows();
/* reclassify player */
void do_class(player, arg1, class)
     dbref player;
     char *arg1;
     char *class;
{
  int i, newlevel;
  dbref who;
  
  if ( *arg1 == '\0' )
    who = player;
  else  {
    init_match(player, arg1, TYPE_PLAYER);
    match_me();
    match_player();
    match_neighbor();
    match_absolute();
    if ( (who = noisy_match_result()) == NOTHING )
      return;
  }
  if(Typeof(who) != TYPE_PLAYER) {
    notify(player,"Aint a player. Quit that animist stuff.");
    return;
  }
  if ( *class == '\0' )  {
    if (!power(player,POW_WHO)) {
      notify(player,"permission denied.");
      return;
    }
    /* above search restricts this result to a PLAYER class */
    class = get_class(who);
    
    notify(player, tprintf("%s is %s %s", db[who].name,
			   (*class == 'O' || *class == 'A') ? "an" : "a", class));
    return;
  }
  
  /* find requested level assignment */
  i=name_to_class(class);
  if ( i==0) {
    notify(player, tprintf("'%s': no such classification", class));
    return;
  }
  newlevel = i;
  
  /* insure player has the power to make that assignment */
  /* GOD can reclass without restriction.  Directors can
     reclass people from any lower rank to any other lower
     rank.  No other class may use this command. */
  log_sensitive(tprintf("%s tried to: @class %s=%s",unparse_object(player,player),
			arg1,class));
  if (!has_pow(player,who,POW_CLASS)
       || (Typeof(player)!=TYPE_PLAYER)
       || ((newlevel >= db[player].pows[0]) && !God(player))) {
    notify(player, "You don't have the authority to do that.");
    return;
  }
  
  /* GOD must remain a director.  This is a safety feature. */
  if ( who == GOD && newlevel != CLASS_DIR)  {
    notify(player,
	   tprintf("Sorry, player #%d cannot resign ir position.",
		   GOD));
    return;
  }
  log_sensitive(tprintf("%s executed: @class %s=%s",unparse_object(player,player),
			arg1,class));
  /*  db[who].flags &= ~TYPE_MASK;
      db[who].flags |= newlevel;*/
  notify(player, tprintf("%s is now reclassified as: %s",
			 db[who].name, class_to_name(newlevel)));
  notify(who, tprintf("You have been reclassified as: %s",
		      class_to_name(newlevel)));
  if(!db[who].pows) {
    db[who].pows=malloc(sizeof(ptype)*2);
    db[who].pows[1]=0;
  }
  db[who].pows[0]=newlevel;
  for(i=0;i<NUM_POWS;i++)
    set_pow(who,powers[i].num,powers[i].init[class_to_list_pos(newlevel)]);
  do_checkpows();
}

void do_nopow_class(player, arg1, class)
     dbref player;
     char *arg1;
     char *class;
{
  int i, newlevel;
  dbref who;
  
  if ( *arg1 == '\0' )
    who = player;
  else  {
    init_match(player, arg1, TYPE_PLAYER);
    match_me();
    match_player();
    match_neighbor();
    match_absolute();
    if ( (who = noisy_match_result()) == NOTHING )
      return;
  }
  if(Typeof(who) != TYPE_PLAYER) {
    notify(player,"Aint a player. Quit that animist stuff.");
    return;
  }
  if ( *class == '\0' )  {
    /* above search restricts this result to a PLAYER class */
    class = get_class(who);
    
    notify(player, tprintf("%s is %s %s", db[who].name,
			   (*class == 'O' || *class == 'A') ? "an" : "a", class));
    return;
  }
  
  /* find requested level assignment */
  i=name_to_class(class);
  if ( i==0) {
    notify(player, tprintf("'%s': no such classification", class));
    return;
  }
  newlevel = i;
  
  /* insure player has the power to make that assignment */
  /* GOD can reclass without restriction.  Directors can
     reclass people from any lower rank to any other lower
     rank.  No other class may use this command. */
  log_sensitive(tprintf("%s tried to: @nopow_class %s=%s",unparse_object(player,player),
			arg1,class));
  if (!has_pow(player,who,POW_CLASS)
       || (Typeof(player)!=TYPE_PLAYER)
       || (((newlevel >= db[player].pows[0]) ||
	    (db[who].pows && db[who].pows[0]>newlevel)) && !God(player))) {
    notify(player, "You don't have the authority to do that.");
    return;
  }
  
  /* GOD must remain a director.  This is a safety feature. */
  if ( who == GOD && newlevel != CLASS_DIR)  {
    notify(player,
	   tprintf("Sorry, player #%d cannot resign eir position.",
		   GOD));
    return;
  }
  log_sensitive(tprintf("%s executed: @nopow_class %s=%s",unparse_object(player,player),
			arg1,class));
  /*  db[who].flags &= ~TYPE_MASK;
      db[who].flags |= newlevel;*/
  notify(player, tprintf("%s is now reclassified as: %s",
			 db[who].name, class_to_name(newlevel)));
  notify(who, tprintf("You have been reclassified as: %s",
		      class_to_name(newlevel)));
  if(!db[who].pows) {
    db[who].pows=malloc(sizeof(ptype)*2);
    db[who].pows[1]=0;
  }
  db[who].pows[0]=newlevel;
}

void do_checkpows(player,who)
     dbref player;
     dbref who;
{
  dbref k;
  int i;
  /* not used anymore */
  return;
  for(k=0;k<db_top;k++)
    if(db[k].owner==who && k != who)
      for(i=0;i<NUM_POWS;i++) {
	if(get_pow(who,i)<get_pow(k,i)) {
	  notify(player,tprintf("%s has %s; downgrading it.",unparse_object(player,k),
				pow_to_name(i)));
	  set_pow(k,i,get_pow(who,i));
	}
      }
}

void do_empower(player,whostr,powstr)
     dbref player;
 char *whostr,*powstr;
{
  ptype pow;
  ptype powval;
  dbref who;
  int k;
  char *i;
  if(Typeof(player)!=TYPE_PLAYER) { 
    notify(player,"You're not a player, silly!");
    return;
  }
  i=strchr(powstr,':');
  if(!i) {
    notify(player,"Badly formed power specification. need powertype:powerval");
    return;
  }
  *(i++) = '\0';

  if(!string_compare(i,"yes"))
    powval=PW_YES;
  else if(!string_compare(i,"no"))
    powval=PW_NO;
  else if(!string_compare(i,"yeseq"))
    powval=PW_YESEQ;
  else if(!string_compare(i,"yeslt"))
    powval=PW_YESLT;
  else {
    notify(player,"The power value must be one of yes, no, yeseq, or yeslt");
    return;
  }
  pow=name_to_pow(powstr);
  if(!pow) {
    notify(player,tprintf("unknown power: %s",powstr));
    return;
  }
  who=match_thing(player,whostr);
  if(who==NOTHING)
    return;
  if(Typeof(who)!=TYPE_PLAYER) {
    notify(player,"ain't a player.");
    return;
  }
  if(!has_pow(player,who,POW_SETPOW)) {
    notify(player,"permission denied.");
    return;
  }
  if(get_pow(player,pow)<powval && !God(player)) {
    notify(player,"But you yourself don't have that power!");
    return;
  }
#ifdef USE_SPACE /* Power check added my Michael Majere */
  if(pow==POW_SPACE && who != SPACE_LORD) {
    notify(player, "There is already an Overlord of space.");
    return;
  }
#endif
  for(k=0;k<NUM_POWS;k++)
    if(powers[k].num==pow)
      if(powers[k].max[class_to_list_pos(*db[db[who].owner].pows)]>=powval) {
	set_pow(who,pow,powval);
        log_sensitive(tprintf("%s(%d) granted %s(%d) power %s, level %s",
          db[player].name, (int)player, db[who].name, (int)who, powstr, i));
	if(powval!=PW_NO) {
	  notify(who,tprintf("You have been given the power of %s.",pow_to_name(pow)));
	  notify(player,tprintf("%s has been given the power of %s.",db[who].name,pow_to_name(pow)));
	}
	switch(powval) {
	case PW_YES:
	  notify(who,"You can use it on anyone");
	  break;
	case PW_YESEQ:
	  notify(who,"You can use it on people your class and under");
	  break;
	case PW_YESLT:
	  notify(who,"You can use it on people under your class");
	  break;
	case PW_NO:
	  notify(who,tprintf("Your power of %s has been removed.",pow_to_name(pow)));
	  notify(player,tprintf("%s's power of %s has been removed.",db[who].name,pow_to_name(pow)));
	  break;
	}
	do_checkpows(player,who);
	return;
      } else {
	notify(player,"Sorry, that is beyond the maximum for that level.");
	return;
      }
  notify(player,"Internal error. Help.");
}
void do_powers(player,whostr)
     dbref player;
 char *whostr;
{
  dbref who;
  int k;
  who=match_thing(player,whostr);
  if(who==NOTHING)
    return;
  if(Typeof(who)!=TYPE_PLAYER) {
    notify(player,"ain't a player.{");
    return;
  }
  if(!controls(player,who,POW_EXAMINE)) {
    notify(player,"permission denied.");
    return;
  }
  notify(player,tprintf("%s's powers:",db[who].name));
  for(k=0;k<NUM_POWS;k++) {
    ptype m;
    char *l="";

    m=get_pow(who,powers[k].num);
    switch(m) {
    case PW_YES:		/* stay "". */
      break;
    case PW_YESLT:
      l="for lower classes";
      break;
    case PW_YESEQ:
      l="for equal and lower classes";
      break;
    case PW_NO:
      continue;
    }
    if(l) {
      notify(player,tprintf("  %s (%s) %s",powers[k].description,powers[k].name,
			    l));
    }
  }
  notify(player,"-- end of list --");
}
int old_to_new_class(lev)
     int lev;
{
  switch(lev) {
  case 0x8:
    return CLASS_GUEST;
  case 0x9:
    return CLASS_VISITOR;
  case 0xA:
    return CLASS_CITIZEN;
  case 0xB:
    return CLASS_JUNOFF;
  case 0xC:
    return CLASS_OFFICIAL;
  case 0xD:
    return CLASS_BUILDER;
  case 0xE:
    return CLASS_ADMIN;
  case 0xF:
    return CLASS_DIR;
  default:
    return CLASS_VISITOR;
  }
}
void do_money(player, arg1, arg2)
     dbref player;
     char *arg1, *arg2;
{
  int amt, assets;
  dbref who;
  char *credits, buf[20];
  dbref total;
  int obj[NUM_OBJ_TYPES];
  int pla[NUM_CLASSES];
  
  if ( *arg1 == '\0' )
    who = player;
  else  {
    init_match(player, arg1, TYPE_PLAYER);
    match_me();
    match_player();
    match_neighbor();
    match_absolute();
    if ( (who = noisy_match_result()) == NOTHING )
      return;
  }
  
  if ( ! power(player, POW_EXAMINE) )  {
    if ( *arg2 != '\0' )  {
      notify(player, "You don't have the authority to do that.");
      return;
    }
    
    if ( player != who )  {
      notify(player,
	     "You need a search warrant to do that.");
      return;
    }
  }
  
  /* calculate assets */
  calc_stats(who, &total, obj, pla);
  assets = obj[TYPE_EXIT]*EXIT_COST +		/* exits */
    obj[TYPE_THING] * OBJECT_COST +	/* things (objects) */
      obj[TYPE_ROOM] * ROOM_COST +	/* rooms */
	(obj[TYPE_PLAYER]-1) * ROBOT_COST;	/* robots */
  
  /* calculate credits */
  if (inf_mon(who)) {
    amt = 0;
    credits = "UNLIMITED";
  }
  else  {
    amt = Pennies(who);
    sprintf(buf, "%d credits.", amt);
    credits = buf;
  }
  
  notify(player, tprintf("Cash...........: %s", credits));
  notify(player, tprintf("Material Assets: %d credits.", assets));
  notify(player, tprintf("Total Net Worth: %d credits.", assets+amt));
  notify(player, " ");
  notify(player, "Note: material assets calculation is only an approximation (for now).");
}

void do_quota(player, arg1, arg2)
     dbref player;
     char *arg1, *arg2;
{
  dbref who;
  char buf[20];
  int owned, limit;
  
  /* Stop attempts to change quota without authority */
  if ( *arg2 )
    if ( ! power(player, POW_SETQUOTA) )  {
      notify(player,
	     "You don't have the authority to change someone's quota!");
      return;
    }
  
  if ( *arg1 == '\0' )
    who = player;
  else 
    if ((who=lookup_player(arg1)) == NOTHING || Typeof(who)!=TYPE_PLAYER) {
      notify(player,"who?");
      return;
    }
  
  if ( Robot(who) )  {
    notify(player, "Robots don't have quotas!");
    return;
  }
  
  /* check players authority to control his target */
  if ( ! controls(player, who, POW_SETQUOTA) )  {
    notify(player, tprintf("You can't %s that player's quota.",
			   (*arg2) ? "change" : "examine"));
    return;
  }
  
  /* count up all owned objects */
  /*
    owned = -1;  * a player is never included in his own quota *
    for ( thing = 0; thing < db_top; thing++ )  {
    if ( db[thing].owner == who )
    if ((db[thing].flags & (TYPE_THING|GOING)) != (TYPE_THING|GOING))
    ++owned;
    }*/
  owned=atoi(atr_get(who,A_QUOTA))-atoi(atr_get(who,A_RQUOTA));
  
  if ( inf_quota (who))
    notify(player, tprintf("Objects: %d   Limit: UNLIMITED", owned));
  else  {
    /* calculate and/or set new limit */
    if ( *arg2 == '\0' )
      limit = owned + atoi(atr_get(who, A_RQUOTA));
    else  {
      limit = atoi(arg2);
      
      /* stored as a relative value */
      sprintf(buf, "%d", limit - owned);
      atr_add(who, A_RQUOTA, buf);
      sprintf(buf, "%d", limit);
      atr_add(who, A_QUOTA, buf);
    }
    
    notify(player, tprintf("Objects: %d   Limit: %d", owned, limit));
  }
}

dbref *match_things (player, list)
     dbref player;
     char *list;
{
  char *x;
  static dbref npl[1000];
  char in[1000];
  char *inp=in;
  if (!*list) {
    notify(player, "You must give a list of things.");
    npl[0] = 0;
    return npl;
  }
  npl[0]=0;
  strcpy(in, list);
  while (inp) {
    x=parse_up(&inp,' ');
    if (!x)
      inp=x;
    else {
      if (*x == '{' && *(strchr(x,'\0')-1) == '}') {
	x++;
	*(strchr(x,'\0')-1) = '\0';
      }
      npl[++npl[0]]=match_thing(player, x);
      if (npl[npl[0]]==NOTHING)
	npl[0]--;
    }
  }
  return npl;
}

dbref *lookup_players(player,list)
     dbref player;
     char *list;
{
  char *x;
  static dbref npl[1000];	/* first is number of them. */
  char in[1000];
  char *inp=in;
  if(!*list) {
    notify(player,"You must give a list of players.");
    npl[0]=0;
    return npl;
  }
  npl[0]=0;
  strcpy(in,list);
  while(inp) {
    x=parse_up(&inp,' ');
    if(!x)
      inp=x;
    else {
      npl[++npl[0]]=lookup_player(x);
      if(npl[npl[0]]==NOTHING) {
	notify(player,tprintf("I don't know who %s is.",x));
	npl[0]--;
      }
    }
  }
  return npl;
}

char *wholev(who,verbose,iswiz)
     dbref who;
     int verbose;
     int iswiz;
{
  extern char *short_class_to_name(),*public_class_to_name();
  extern char *short_public_class_to_name();
  static char buf[50];

  if ( Typeof(who) != TYPE_PLAYER )
    strcpy(buf, "*****");
  else if ( iswiz && verbose )
    strcpy(buf, class_to_name(*db[who].pows));
  else if ( iswiz )
    strcpy(buf, short_class_to_name(*db[who].pows));
  else if ( verbose )
    strcpy(buf, public_class_to_name(*db[who].pows));
  else
    strcpy(buf, short_public_class_to_name(*db[who].pows));
  return buf;
}

void do_misc(player,arg1,arg2)
     dbref player;
     char *arg1,*arg2;
{
}