shadow/
shadow/data/command/
shadow/data/help/
shadow/data/religion/
shadow/data/skill/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/ 

/***************************************************************************
*       ROM 2.4 is copyright 1993-1998 Russ Taylor                         *
*       ROM has been brought to you by the ROM consortium                  *
*           Russ Taylor (rtaylor@hypercube.org)                            *
*           Gabrielle Taylor (gtaylor@hypercube.org)                       *
*           Brian Moore (zump@rom.org)                                     *
*       By using this code, you have agreed to follow the terms of the     *
*       ROM license, in the file Rom24/doc/rom.license                     *
***************************************************************************/

/********************************************************************************
 * Stat List code copyright 1999-2001                                           *
 * Markanth : dlmud@dlmud.com                                                   *
 * Devil's Lament : dlmud.com port 3778                                         *
 * Web Page : http://www.dlmud.com                                              *
 *                                                                              *
 * All I ask in return is that you give me credit on your mud somewhere         *
 * or email me if you use it.                                                   *
 ********************************************************************************/

/* Improvements by Synon for ShadowStorm */

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "merc.h"
#include "recycle.h"
#include "interp.h"
#include "const.h"

STAT_DATA *stat_list;
void show_stats args((CHAR_DATA * ch, int type));

void save_statlist(void)
{
    STAT_DATA *pstat;
    FILE *fp;
    bool found = FALSE;
    int i;

    if ((fp = file_open(STAT_FILE, "w")) == NULL)
    {
	perror(STAT_FILE);
    }

    fprintf(fp, "#%d\n", MAX_GAMESTAT);

    for (pstat = stat_list; pstat != NULL; pstat = pstat->next)
    {
	found = TRUE;
	fprintf(fp, "%s ", pstat->name);
	for (i = 0; i < MAX_GAMESTAT; i++)
	    fprintf(fp, "%ld ", pstat->gamestat[i]);
	fprintf(fp, "\n");
    }

    file_close(fp);
    if (!found)
	unlink(STAT_FILE);
}

void load_statlist(void)
{
   FILE *fp;
   STAT_DATA *stat_last;
   int i,
   maxStat = 0;

   if ( file_exists( STAT_FILE ) )
   {
       fp = file_open(STAT_FILE, "r");

       fscanf(fp, "#%d\n", &maxStat);

       stat_last = NULL;

       for (;;)
       {
	    STAT_DATA *pstat;

	    if (feof(fp))
	    {
	        fclose(fp);
	        return;
	    }

	    pstat = new_stat_data();
	    pstat->name = str_dup(fread_word(fp));
	    for (i = 0; i < maxStat; i++)
	    pstat->gamestat[i] = fread_number(fp);
	    fread_to_eol(fp);

	    if (stat_list == NULL)
	    stat_list = pstat;
	    else
	    stat_last->next = pstat;
	    stat_last = pstat;
       }
   }
}

void update_statlist(CHAR_DATA * ch, bool del)
{
    STAT_DATA *prev;
    STAT_DATA *curr;
    int i;

    if (IS_NPC(ch) || IS_IMMORTAL(ch))
	return;

    prev = NULL;

    for (curr = stat_list; curr != NULL; prev = curr, curr = curr->next)
    {
	if (!str_cmp(ch->name, curr->name))
	{
	    if (prev == NULL)
		stat_list = stat_list->next;
	    else
		prev->next = curr->next;

	    free_stat_data(curr);
	    save_statlist();
	}
    }

    if (del || IS_IMMORTAL(ch) || IS_NPC(ch))
    {
	return;
    }

    curr = new_stat_data();
    curr->name = str_dup(ch->name);
    for (i = 0; i < MAX_GAMESTAT; i++)
        curr->gamestat[i] = ch->pcdata->gamestat[i];

    curr->next = stat_list;
    stat_list = curr;
    save_statlist();
    return;
}

void do_statlist(CHAR_DATA * ch, char *argument)
{
    int choice;
    char buf[MAX_STRING_LENGTH],
    arg[MAX_INPUT_LENGTH];

    argument = one_argument(argument, arg);

    if (arg[0] == '\0' || !is_number( arg ) )
    {
	send_to_char("             {GOPTIONS AVAILABLE{x\n\r", ch);
        send_to_char("{cO-------------------------------------------O{x\n\r",ch);
	send_to_char("{c|{x     1) Ranking of Player Kills            {c|{x\n\r", ch);
	send_to_char("{c|{x     2) Ranking of Player Deaths           {c|{x\n\r", ch);
	send_to_char("{c|{x     3) Ranking of Mob Kills               {c|{x\n\r", ch);
	send_to_char("{c|{x     4) Ranking of Mob Deaths              {c|{x\n\r", ch);
        if (!IS_IMMORTAL(ch))
        send_to_char("{cO-------------------------------------------O{x\n\r",ch);

        if(IS_IMMORTAL(ch))
        {
	send_to_char("{c|{x     5) <name> - Deletes from statlist     {c|{x\n\r", ch);
        send_to_char("{cO-------------------------------------------O{x\n\r",ch);
        }
	return;
    }

    choice = atoi(arg);

    if ( ( choice == 5 || !str_cmp( arg, "delete" ) ) && IS_IMMORTAL(ch) ) 
    {
	STAT_DATA *prev = NULL;
	STAT_DATA *curr = NULL;
	bool found = FALSE;

	for (curr = stat_list; curr != NULL; prev = curr, curr = curr->next)
	{
	    if (!str_cmp(argument, curr->name))
	    {
		if (prev == NULL)
		    stat_list = stat_list->next;
		else
		    prev->next = curr->next;

		free_stat_data(curr);
		save_statlist();
		found = TRUE;
	    }
	}

	if (!found)
        {

	    sprintf(buf, "Error deleting %s.\n\r", argument);
            send_to_char(buf, ch);
        }
    } 

    else if (choice == 1 || !str_prefix(arg, "pkills"))
         show_stats(ch, PK_KILLS);
    else if (choice == 3 || !str_prefix(arg, "mkills"))
	show_stats(ch, MOB_KILLS);
    else if (choice == 2 || !str_prefix(arg, "pdeaths"))
	show_stats(ch, PK_DEATHS);
    else if (choice == 4 || !str_prefix(arg, "mdeaths"))
	show_stats(ch, MOB_DEATHS);
    else
	do_function(ch, &do_statlist, "");

    return;
}

int compare_type;

int compare_stats (const void *v1, const void *v2)
{
	STAT_DATA *stat1 = *(STAT_DATA **) v1;
	STAT_DATA *stat2 = *(STAT_DATA **) v2;

	if (!stat2)
		return 1;
	if (!stat1)
		return 2;

	return stat2->gamestat[compare_type] - stat1->gamestat[compare_type];
}

int count_statlist ()
{
	STAT_DATA *stat;
	int i = 0;

	for (stat = stat_list; stat != NULL; stat = stat->next)
		i++;

	return i;
}

void show_stats(CHAR_DATA * ch, int type)
{
    STAT_DATA *curr;
    BUFFER *output;
    char buf[MAX_STRING_LENGTH];
    STAT_DATA * *top;
    int count, pos, loop;
    int size = count_statlist();
    bool found = FALSE;
    const char *stat_name[MAX_GAMESTAT] = 
    {
	"PLAYER KILLERS",
	"MOB KILLERS",
	"PK DEATHS",
	"MOB DEATHS"
    };

    output = new_buf (  );
    count = 0;
    pos = 0;
    compare_type = type;

    top = (STAT_DATA **)alloc_mem(size);

    sprintf(buf, "RANKING OF %s", stat_name[type]);
    add_buf(output, buf);
    add_buf(output, "\n\r");
    sprintf(buf, "{R----------------------------{x");
    add_buf(output, buf);
    add_buf(output, "\n\r");
    
    loop = 0;

	for (curr = stat_list; curr != NULL; curr = curr->next)
	{
		top[count] = curr;
		count++;
		found = TRUE;
	}

	if (found)
	{
		qsort (top, count, sizeof (*top), compare_stats);

		for (loop = 0; loop < count; loop++)
		{
			if (loop >= 50)
				break;

			sprintf (buf, "%2d) %-20s [%8ld]    ", loop + 1,
							top[loop]->name, top[loop]->gamestat[type]);
                        add_buf(output, buf);

			if (++pos % 2 == 0)
			{
				add_buf (output, "\n\r");
				pos = 0;
			}
		}
	}

	if (!found)
		add_buf(output, "\n\rNo one found yet.\n\r");
	else if (pos % 2 != 0)
		add_buf (output, "\n\r");
	else
		add_buf(output, "\n\r");
	page_to_char (buf_string (output), ch);
	free_buf (output);
	free_mem (top, size);
	return;
}