1stMUD/corefiles/
1stMUD/gods/
1stMUD/notes/
1stMUD/player/
1stMUD/win32/
1stMUD/win32/ROM/
/**************************************************************************
*  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
*  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
*                                                                         *
*  Merc Diku Mud improvements 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          *
*  benefiting.  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                    *
***************************************************************************
*       1stMUD ROM Derivative (c) 2001-2002 by Ryan Jennings              *
*            http://1stmud.dlmud.com/  <r-jenn@shaw.ca>                   *
***************************************************************************/
#include <sys/types.h>
#if !defined(WIN32)
#include <sys/time.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include "merc.h"

int bitcount(char c)
{
	int count = 0;

	if (c & BIT_A)
		count++;
	if (c & BIT_B)
		count++;
	if (c & BIT_C)
		count++;
	if (c & BIT_D)
		count++;
	if (c & BIT_E)
		count++;
	if (c & BIT_F)
		count++;
	if (c & BIT_G)
		count++;
	if (c & BIT_H)
		count++;

	return count;
}

int roomcount(CHAR_DATA * ch)
{
	int pIndex = 0, count = 0;

	if (IS_NPC(ch))
		return top_room;

	for (pIndex = 0; pIndex < MAX_EXPLORE_HASH; pIndex++)
	{
		count += bitcount(ch->pcdata->explored[pIndex]);
	}

	return count;
}

void update_explored(CHAR_DATA * ch)
{
	vnum_t vnum;
	ROOM_INDEX_DATA *pRoom;
	int nMatch = 0;

	for (vnum = 0; nMatch < top_room; vnum++)
	{
		if ((pRoom = get_room_index(vnum)) != NULL)
		{
			nMatch++;
			if (IS_SET(pRoom->room_flags, ROOM_NOEXPLORE)
				&& STR_IS_SET(ch->pcdata->explored, vnum))
				STR_REMOVE_BIT(ch->pcdata->explored, vnum);
		}
		else
		{
			if (STR_IS_SET(ch->pcdata->explored, vnum))
				STR_REMOVE_BIT(ch->pcdata->explored, vnum);
		}
	}
}

int areacount(CHAR_DATA * ch, AREA_DATA * area)
{
	vnum_t pIndex = 0, count = 0;

	if (IS_NPC(ch))
		return top_room;

	if (ch == NULL || area == NULL)
		return 0;

	for (pIndex = area->min_vnum; pIndex <= area->max_vnum; pIndex++)
	{
		count += STR_IS_SET(ch->pcdata->explored, pIndex) ? 1 : 0;
	}

	return count;
}

int arearooms(AREA_DATA * area)
{
	int count = 0;
	vnum_t pIndex = 0;
	ROOM_INDEX_DATA *pRoom;

	if (!area)
		return 0;

	for (pIndex = area->min_vnum; pIndex <= area->max_vnum; pIndex++)
	{
		if ((pRoom = get_room_index(pIndex)) != NULL
			&& !IS_SET(pRoom->room_flags, ROOM_NOEXPLORE))
			count++;
	}

	return count;
}

void fwrite_rle(char *explored, FILE * fp)
{
	vnum_t pIndex;
	int bit = 0;
	int count = 0;

	fprintf(fp, "RoomRLE      %d", bit);

	for (pIndex = 0; pIndex < MAX_VNUM; pIndex++)
	{
		if ((STR_IS_SET(explored, pIndex) ? 1 : 0) == bit)
			count++;
		else
		{
			fprintf(fp, " %d", count);
			count = 1;
			bit = (STR_IS_SET(explored, pIndex)) ? 1 : 0;
		}
	}
	fprintf(fp, " %d -1\n", count);
	return;
}

void fread_rle(char *explored, FILE * fp)
{
	vnum_t pIndex;
	int bit = 0;
	int count = 0;
	vnum_t pos = 0;

	pIndex = 0;

	bit = fread_number(fp);

	for (;;)
	{
		count = fread_number(fp);

		if (count < 0)
			break;
		if (count == 0)
			continue;

		do
		{
			if (bit == 1)
			{
				STR_SET_BIT(explored, pIndex);
			}
			pIndex++;
		}
		while (pIndex < pos + count);
		pos = pIndex;
		bit = (bit == 1) ? 0 : 1;
	}
	return;
}

struct area_index
{
	AREA_DATA *area;
	double percent;
};

typedef struct area_index AREA_INDEX;

int compare_area_explored(const void *v1, const void *v2)
{
	AREA_INDEX area1 = *(AREA_INDEX *) v1;
	AREA_INDEX area2 = *(AREA_INDEX *) v2;

	return (int) (area2.percent - area1.percent);
}

CH_CMD(do_explored)
{
	int line = 1, i = 0, c = 0, rcnt;
	double rooms, percent;
	AREA_DATA *pArea;
	AREA_INDEX *list;

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

	if (IS_NULLSTR(argument))
	{
		rcnt = roomcount(ch);
		rooms = (double) top_explored;
		percent = UMIN((double) rcnt / (rooms / 100), 100);

		chprintf(ch, "ROM has {G%d{x explorable rooms.", top_explored);
		chprintf(ch, "You have explored {G%d (%.2f%%){x of the mud{x", rcnt,
				 percent);

		rcnt = areacount(ch, ch->in_room->area);
		rooms = (double) (arearooms(ch->in_room->area));
		percent = UMIN((double) rcnt / (rooms / 100), 100);

		chprintf(ch, "\n\rThis area has {G%.0f{x explorable rooms.", rooms);
		chprintf(ch, "You have explored {G%d (%.2f%%){x rooms in this area.{x",
				 rcnt, percent);
	}
	else if (is_exact_name(argument, "reset"))
	{
		memset(ch->pcdata->explored, 0, MAX_EXPLORE_HASH);
		chprintln(ch, "Your explored rooms were set to 0.");
	}
	else if (!str_prefix(argument, "list"))
	{
		alloc_mem(list, AREA_INDEX, top_area);

		for (pArea = area_first; pArea != NULL; pArea = pArea->next)
		{
			rcnt = areacount(ch, pArea);
			rooms = (double) (arearooms(pArea));
			percent = UMIN((double) rcnt / (rooms / 100), 100);
			list[i].area = pArea;
			list[i].percent = percent;
			i++;
		}
		qsort(list, i, sizeof(AREA_INDEX), compare_area_explored);

		for (c = 0; c < i; c++)
		{
			pArea = list[c].area;
			percent = list[c].percent;

			chprintf(ch, "{D[{Y%3.0f{y%%{D]{x %-32s", percent, pArea->name);
			if (line >= 2)
			{
				line = 0;
				chprintln(ch, "");
			}
			line++;
		}
		if (line >= 2)
			chprintln(ch, "");
		free_mem(list);
	}
	else
	{
		chprintln(ch, "Syntax: explored        - show current area and world.");
		chprintln(ch,
				  "      : explored list   - list percentages for all areas.");
		chprintln(ch, "      : explored reset  - reset explored rooms.");
	}
}