/* 
 * If you use this code, please give me credit, or email me   ramki@rmud.net
 * I used a little bit from Taka's GhostMUD, but revised most of it...
 * I hope you like it... just replace   void do_who  in act_info.c with this
 * code, feel free to use it, but just let me know you are...
 */
void do_who( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH], buf2[MAX_STRING_LENGTH];
    BUFFER *output;
    DESCRIPTOR_DATA *d;
    int iClass, iRace, iClan, iLevelLower, iLevelUpper;
    int nNumber, nMatch, immmatch, mortmatch, wlevel;
    bool rgfClass[MAX_CLASS];
    bool rgfRace[MAX_PC_RACE];
    bool rgfClan[MAX_CLAN];
    bool fClassRestrict = FALSE;
    bool fClanRestrict = FALSE;
    bool fClan = FALSE;
    bool fRaceRestrict = FALSE;
    bool fImmortalOnly = FALSE;

/*
* Initalize Variables.
*/

    immmatch = 0;
	mortmatch = 0;
    nNumber = 0;
	nMatch = 0;
    buf[0] = '\0';
    output = new_buf();


    {
	sprintf (buf, "{Y*{c========{b-----------{c========{Y*{R  M{My{Yst{Mi{Rc R{Me{Yal{Mm{Rs  {Y*{c========{b-----------{c========{Y*{x\n\r");
    send_to_char (buf, ch);
    }     
    
    
    /*
     * Set default arguments.
     */
    iLevelLower    = 0;
    iLevelUpper    = MAX_LEVEL;
    for ( iClass = 0; iClass < MAX_CLASS; iClass++ )
        rgfClass[iClass] = FALSE;
    for ( iRace = 0; iRace < MAX_PC_RACE; iRace++ )
        rgfRace[iRace] = FALSE;
    for (iClan = 0; iClan < MAX_CLAN; iClan++)
		rgfClan[iClan] = FALSE;

    /*
     * Parse arguments.
     */
    for ( ;; )
    {
        char arg[MAX_STRING_LENGTH];

        argument = one_argument( argument, arg );
        if ( arg[0] == '\0' )
            break;

        if ( is_number( arg ) )
        {
            switch ( ++nNumber )
            {
            case 1: iLevelLower = atoi( arg ); break;
            case 2: iLevelUpper = atoi( arg ); break;
            default:
                send_to_char( "Only two level numbers allowed.\n\r", ch );
                return;
            }
        }
        else
        {

            /*
             * Look for classes to turn on.
             */
            if ((!str_prefix(arg,"immortals")) || (!str_prefix(arg, "imm")))
            {
                fImmortalOnly = TRUE;
            }
            else
            {
                iClass = class_lookup(arg);
                if (iClass == -1)
                {
                    iRace = race_lookup(arg);

					if (iRace == 0 || iRace >= MAX_PC_RACE)
					{
						if (!str_prefix(arg,"clan"))
							fClan = TRUE;
						else
						{
							iClan = clan_lookup(arg);
							if (iClan)
							{
								fClanRestrict = TRUE;
							   	rgfClan[iClan] = TRUE;
							}
							else
							{
		                       	send_to_char("That's not a valid race, class, or
									clan.\n\r", ch);
                            	return;
							}
						}
					}
                    else
                    {
                        fRaceRestrict = TRUE;
                        rgfRace[iRace] = TRUE;
                    }
                }
                else
                {
                    fClassRestrict = TRUE;
                    rgfClass[iClass] = TRUE;
                }
            }
        }
    } // for

	/*
	 * Count and output the IMMs.
	 */
	sprintf( buf, "{W ___________________{x\n\r");
	add_buf(output,buf);
	sprintf( buf, "{W[{G I m m o r t a l s{W |{x\n\r");
	add_buf(output,buf);
	sprintf( buf, "{W[{c==================={W|{c====================================================={W]{x\n\r");;
	add_buf(output,buf);
	sprintf( buf, "{W[ {GLvl {RRace  {MCls{Y Sex{W ]  Immortal's Name                                    {W|{x\n\r");;
	add_buf(output,buf);
	sprintf( buf, "{W[{c==================={W|{c====================================================={W]{x\n\r");;
	add_buf(output,buf);

	for( wlevel=MAX_LEVEL; wlevel>LEVEL_HERO; wlevel-- )
	{
		for ( d = descriptor_list; d != NULL; d = d->next )
		{
		    CHAR_DATA *wch;
	        char const *class;

	        if ( d->connected != CON_PLAYING || !can_see( ch, d->character ) )
		        continue;

	        wch   = ( d->original != NULL ) ? d->original : d->character;

			if( wch->level != wlevel )
		 	 	continue;

			if (!can_see(ch,wch)  || wch->level < LEVEL_IMMORTAL)
				continue;


	        if ( wch->level < iLevelLower
			    ||   wch->level > iLevelUpper
		        || ( fImmortalOnly  && wch->level < LEVEL_IMMORTAL )
		        || ( fClassRestrict && !rgfClass[wch->class] )
		        || ( fRaceRestrict && !rgfRace[wch->race])
				|| ( fClan && !is_clan(wch))
				|| ( fClanRestrict && !rgfClan[wch->clan]))
		        continue;

	        immmatch++;
	        nMatch++;

	        /*
	         * Figure out what to print for class.
			 */
			class = class_table[wch->class].who_name;
			switch ( wch->level )
			{
			default: break;
	        {
			case MAX_LEVEL - 0 : class = "IMP";     break;
            case MAX_LEVEL - 1 : class = "CRE";     break;
            case MAX_LEVEL - 2 : class = "SUP";     break;
            case MAX_LEVEL - 3 : class = "DEI";     break;
            case MAX_LEVEL - 4 : class = "GOD";     break;
            case MAX_LEVEL - 5 : class = "IMM";     break;
            case MAX_LEVEL - 6 : class = "DEM";     break;
            case MAX_LEVEL - 7 : class = "ANG";     break;
            case MAX_LEVEL - 8 : class = "AVA";     break;
	        }
			}

			/*
			 * Format it up.
			 */
			sprintf( buf, "{W[ {C%3d{G%6s {M%s  %s{W  ] {g %s%s%s%s%s%s%s%s{W%s{x%s\n\r",
		    	wch->level, wch->race < MAX_PC_RACE ? pc_race_table[wch->race].who_name
    			: "     ", class,
    			wch->sex == 0 ? "{GN{x" : wch->sex == 1 ? "{RM{x" : "{MF{x",
				wch->incog_level >= LEVEL_HERO ? "{C({WI{W){x " : "",
				wch->invis_level >= LEVEL_HERO ? "{W({WW{W){x " : "",
				clan_table[wch->clan].who_name,
				IS_SET(wch->act, PLR_MORTAL_LEADER) ? "{W[{gLeader{W] {x" : "",
				IS_SET(wch->comm, COMM_AFK) ? "{W[{RAFK{W]{X " : "",
				IS_SET(wch->act, PLR_KILLER) ? "{W({RK{W){x " : "",
	            IS_SET(wch->act, PLR_THIEF)  ? "{W({RT{W){x "  : "",
	            IS_SET(wch->act, PLR_MARRIED) ? "{W[{MMarried{W]{x "  : "",
				wch->name, IS_NPC(wch) ? "" : wch->pcdata->title );
			add_buf(output,buf);
			    sprintf( buf, "{W[{c==================={W|{c====================================================={W]{x\n\r");;
	add_buf(output,buf);


		}
	}
	/*
	 * Count and output the Morts.
	 */
	sprintf( buf, "{W|{G   M o r t a l s  {W |{x\n\r");
	add_buf(output,buf);
	sprintf( buf, "{W[{c==================={W|{c====================================================={W]{x\n\r");;
	add_buf(output,buf);
	sprintf( buf, "{W| {GLvl{R Race  {MCls{Y Sex{W ]  Mortal's Name{x                                      {W|{x\n\r");;
	add_buf(output,buf);
	sprintf( buf, "{W[{c==================={W|{c====================================================={W]{x\n\r");;
	add_buf(output,buf);

	for( wlevel=LEVEL_HERO; wlevel>0; wlevel-- )
	{
		for ( d = descriptor_list; d != NULL; d = d->next )
	    {
	        CHAR_DATA *wch;
	        char const *class;

	        if ( d->connected != CON_PLAYING || !can_see( ch, d->character ) )
	            continue;

	        wch   = ( d->original != NULL ) ? d->original : d->character;

			if( wch->level != wlevel )
			  	continue;

/*			if (!can_see(ch,wch) || wch->level > ch->level || wch->level > (MAX_LEVEL - 5))
			    continue; */
			if (!can_see(ch,wch))
			    continue;

			if ( wch->level < iLevelLower
		        ||   wch->level > iLevelUpper
		        || ( fImmortalOnly  && wch->level < LEVEL_IMMORTAL )
		        || ( fClassRestrict && !rgfClass[wch->class] )
				|| ( fRaceRestrict && !rgfRace[wch->race])
				|| ( fClan && !is_clan(wch))
				|| ( fClanRestrict && !rgfClan[wch->clan]))
			    continue;

			mortmatch++;
			nMatch++;

			/*
			 * Figure out what to print for class.
			 */
			class = class_table[wch->class].who_name;
			switch ( wch->level )
			{
			default: break;
            {
                case MAX_LEVEL - 9 : class = "{YH{GR{YO{x";     break;
            }
			}

			/*
			 * Format it up.
			 */
			sprintf( buf, "{W[ {C%3d{G%6s {M%s  %s{W  ]  %s%s%s%s%s%s%s{W%s{x%s\n\r",
		    	wch->level, wch->race < MAX_PC_RACE ? pc_race_table[wch->race].who_name
    			: "     ", class,
    			wch->sex == 0 ? "{GN{x" : wch->sex == 1 ? "{RM{x" : "{MF{x",
				clan_table[wch->clan].who_name,
				IS_SET(wch->act, PLR_MORTAL_LEADER) ? " {Y*{W]{x " : "",
				IS_SET(wch->comm, COMM_AFK) ? "{W[{RAFK{W]{X " : "",
				IS_SET(wch->act, PLR_KILLER) ? "{W[{RK{W]{x " : "",
	            IS_SET(wch->act, PLR_THIEF)  ? "{W[{RT{W]{x "  : "",
	            IS_SET(wch->act, PLR_MARRIED) ? "{W[{MMarried{W]{x "  : "",
	            IS_SET(wch->act, PLR_ARENA)  ? "{R[{YARENA{R]{x "  : "",
				wch->name, IS_NPC(wch) ? "" : wch->pcdata->title );
			add_buf(output,buf);

		}
	}

    max_on = UMAX (nMatch, max_on);
    sprintf( buf, "{W[{c==================={W|{c====================================================={W]{x\n\r");;
	add_buf(output,buf);
	sprintf( buf2,
		"\n\r{GTotal connected: {W%d{G\n\r", nMatch);
	add_buf(output,buf2);
	sprintf( buf2,
		"{GImmortals found: {W%d{G\n\r", immmatch);
	add_buf(output,buf2);
	sprintf( buf2,
		"{GMortals found: {W%d\n\r", mortmatch);
	add_buf(output,buf2);
	sprintf( buf2,
		"{GMost found today: {M%d{x\n\r", max_on );
	add_buf(output,buf2);
	page_to_char( buf_string(output), ch );
	free_buf(output);
	return;

}