/
LIB3/
LIB3/D/ADMIN/
LIB3/D/ADMIN/OBJ/
LIB3/D/ADMIN/ROOM/W/
LIB3/D/HOME/
LIB3/D/HOME/CITY/ARENA/
LIB3/D/HOME/CITY/ITEMS/
LIB3/D/HOME/CITY/POSTOFFI/
LIB3/DOC/
LIB3/GLOBAL/SPECIAL/
LIB3/GLOBAL/VIRTUAL/
LIB3/NET/
LIB3/NET/CONFIG/
LIB3/NET/DAEMON/CHARS/
LIB3/NET/GOPHER/
LIB3/NET/INHERIT/
LIB3/NET/OBJ/
LIB3/NET/SAVE/
LIB3/NET/VIRTUAL/
LIB3/OBJ/B_DAY/
LIB3/OBJ/HANDLERS/TERM_TYP/
LIB3/PLAYERS/B/
LIB3/PLAYERS/N/
LIB3/ROOM/
LIB3/SAVE/
LIB3/SAVE/BOARDS/
LIB3/SAVE/ENVIRON/
LIB3/SAVE/POST/
LIB3/STD/COMMANDS/SHADOWS/
LIB3/STD/CREATOR/
LIB3/STD/DOM/
LIB3/STD/EFFECTS/
LIB3/STD/EFFECTS/HEALING/
LIB3/STD/EFFECTS/OTHER/
LIB3/STD/EFFECTS/POISONS/
LIB3/STD/ENVIRON/
LIB3/STD/GUILDS/
LIB3/STD/LIQUIDS/
LIB3/STD/ROOM/
LIB3/STD/TRIGGER/SHADOW/
LIB3/W/
LIB3/W/BANNOR/
LIB3/W/NEWSTYLE/
/*                                                           */
/* WIZLIST : 2-24-94   By: Rastafan @ New Moon               */
/*                                                           */
/* This is a refined 'who' or 'finger' command that shows    */
/* useful data about all online users.  It also sorts the    */
/* users by 'level', with all creators and Lords above all   */
/* players.  Logins are also shown at the bottom of the list. */
/* Sort_array() is the primary sorting routine that is used, */
/* however, quicksort() can be used if desired.  This was    */
/* done for CPU tests and possible speed saving.             */
/*                                                           */

#include "living.h"

/* Function declaration for the quicksort routine.           */
void    quicksort( int l, int r );

/* The following two variables are global, used with         */
/* Quicksort for sorting the list.                           */
static string *lines;
static int *sort_list;

/*  Function: WIZLIST()                                      */
/*                                                           */
/* This function lists all users in decending order based    */
/* on the following criteria:                                */
/*  High Lords, Lords, Creators sorted by Cre-Grade,         */
/*  Players sorted by Level(including guests which are lev 0) */
/*  and then Logins at the bottom.                           */
/*                                                           */
/* It uses two different ways to sort, depending on if an    */
/* argument is given or not.  If not, it uses sort_array()   */
/* which seems to be faster and is not limited by CPU cycles */
/* if an argument is given, it uses the quicksort algorithm  */
/* which may be faster in some cases, but is limited in CPU  */
/* cycles by the driver.                                     */
/*                                                           */
int     wizlist( string str )
{
    string  ret;		/* A temporary variable for holding return values.      */
    object *obs, g_ob;		/* obs holds the list of all users and g_ob is the      */

    /* guild object for a particular user.                  */
    string  editor, gend, ears, grd, guild, name, race, real_name, tmp1, tmp2;

    /* Editor is a string Yes or No stating if a creator is */
    /* in the editor. Gend is gender, ears is earmuffs, grd */
    /* is the cre-grade, guild is the guild name, name is   */
    /* the persons name, race is their race, real_name is   */
    /* their real name and tmp1 and tmp2 are just place     */
    /* holders for sscanf().                                */
    int     i, j, k, l, m, cgrd, idle;	/* i,j,l,m are all loop variables, k is the  */

    /* number of visible users, cgrd is the      */
    /* actual numerical grade for a creator and  */
    /* is not displayed, idle is the number of   */
    /* seconds a person has been idle.           */

    obs = users();		/* get all users.                            */
    j = sizeof( obs );
    sort_list = allocate( j );	/* Dynamic allocation of memory.             */
    lines = allocate( j );
    for( i = 0; i < j; i++ )
    {
	string  euid;

	if( obs[ i ]->query_invis() && !this_player()->query_creator() )
	    continue;
	if( (int)obs[ i ]->query_invis() == 2 && !this_player()->query_lord() )
	    continue;
	ears = (obs[ i ]->query_earmuffs()? "e" : " ");
	idle = query_idle( obs[ i ] );
	if( obs[ i ]->query_in_editor() )
	    editor = "Yes";
	else
	    editor = "No";
	switch( obs[ i ]->query_gender() )
	{
	    case GENDER_NEUTER:
		gend = "?";
		break;
	    case GENDER_MALE:
		gend = "M";
		break;
	    case GENDER_FEMALE:
		gend = "F";
		break;
	}
	euid = geteuid( obs[ i ] );
	grd = obs[ i ]->query_object_type();
	/*  euid is the players name if they're a creator, PLAYER if they are */
	/*  a player, and Root if they are logging in.                        */
	switch( euid )
	{
	    case "PLAYER":
		euid = " " + obs[ i ]->query_level() + " ";
		sort_list[ k ] = obs[ i ]->query_level();
		break;
	    case "Root":
		euid = "LOGIN";
		sort_list[ k ] = (-1);
		break;
	    default:
		euid = "High";
		cgrd = (int)"/obj/handlers/cregrade"->
		    query_cre_grade( obs[ i ]->query_name() );
		if( grd == "H" )
		    cgrd = 101;
		sort_list[ k ] = cgrd + 1000;
		break;
	}
	/* The following code gets the actual name of the guild, some guilds */
	/* have exceptionally large 'names' and so we don't bother with it   */
	/* and just get the file name of the guild, a one word statement of  */
	/* the guild, like "wizards" or "fighters".                          */
	g_ob = obs[ i ]->query_guild_ob();
	if( g_ob )
	{
	    if( sscanf( g_ob, "%sguilds/%s/%s", tmp1, guild, tmp2 ) != 3 )
		if( sscanf( g_ob, "%sguilds/%s", tmp1, guild ) != 2 )
		    guild = "?";
	}
	else
	    guild = "none";

	race = obs[ i ]->query_race();
	name = (obs[ i ]->query_invis()? "(" + obs[ i ]->query_name() +
		")" : capitalize( (string)obs[ i ]->query_name() ));
	real_name = ((ret = (string)obs[ i ]->query_real_name())? ret : "-");

	/* each 'line' contains all the information we want to print out,    */
	/* followed by a separator 'FOO' and then the 'value' we are sorting */
	/* by.  The value is not printed, it is stripped off when we print.  */
	lines[ k ] =
	    sprintf( 
			" %-2s %-5s %1s%1s %-11.11s %-17.17s %-10.10s %-10.10s %4d %3s FOO %d\n",
			grd, euid, ears, gend, name, real_name, race, guild, idle, editor, sort_list[ k ] );

	k++;
    }
    /* use either quicksort() or sort_array()                               */
    if( str )
	quicksort( 0, k - 1 );
    else
	lines = sort_array( lines, "check_great", this_object() );

    /* setup the output                                                     */
    write( "\n" );
    write( sprintf( "%-3s %-5s %1s%1s %-11.11s %-17.17s %-10.10s %-10.10s %4s %3s\n",
		    "cre", "Level", "E", "G", "Name", "Real Name", "Race", "Guild", "Idle", "Ed?" ) );
    write( "---------------------------------------" +
	   "---------------------------------------\n" );
    for( i = k - 1; i >= 0; i-- )
    {
	sscanf( lines[ i ], "%s FOO %s", lines[ i ], tmp1 );
	write( lines[ i ] + "\n" );
    }
    write( sprintf( "%s %2d %s %s\n", "--------------------------------", k,
		    "People On", "--------------------------------" ) );
    return 1;
}

/*  Function: CHECK_GREAT()                                  */
/*                                                           */
/* This is the function used by sort_array() to determine    */
/* if one line is 'larger' than the other.                   */
int     check_great( string line1, string line2 )
{
    int     a, b;
    string  tmp;

    sscanf( line1, "%s FOO %d", tmp, a );
    sscanf( line2, "%s FOO %d", tmp, b );
    if( a > b )
	return 1;
    else
	return -1;
}

/*  Function: QUICKSORT()                                    */
/*                                                           */
/* This is the quicksort() function as implemented in        */
/* Sedgewicks "Algorithms" book.                             */
/* Some lines have multiple statements on them, this was done */
/* because the statements are intimately related.            */
void    quicksort( int l, int r )
{
    int     v, t, i, j;
    string  ts;

    if( r > l )
    {
	v = sort_list[ r ];
	i = l - 1;
	j = r;
	do
	{
	    do
	    {
		++i;
	    }
	    while( sort_list[ i ] < v );
	    do
	    {
		--j;
	    }
	    while( (sort_list[ j ] > v) && (j > 0) );
	    t = sort_list[ i ];
	    sort_list[ i ] = sort_list[ j ];
	    sort_list[ j ] = t;
	    ts = lines[ i ];
	    lines[ i ] = lines[ j ];
	    lines[ j ] = ts;
	}
	while( j > i );
	sort_list[ j ] = sort_list[ i ];
	sort_list[ i ] = sort_list[ r ];
	sort_list[ r ] = t;
	lines[ j ] = lines[ i ];
	lines[ i ] = lines[ r ];
	lines[ r ] = ts;
	quicksort( l, i - 1 );
	quicksort( i + 1, r );
    }
}