/**************************************************************************
* 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.");
}
}