/**************************************************************************
* 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>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
char map_chars[5] = "|-|-";
char lcolor = 'x';
#define MAXDEPTH 4
#define MAPX 10
#define MAPY 8
#define BOUNDARY(x, y) (((x) < 0) || ((y) < 0) || \
((x) > MAPX) || ((y) > MAPY)) \
struct map_type
{
char symbol;
vnum_t vnum;
int depth;
flag_t info;
bool up;
bool dn;
};
typedef struct map_type MAP_DATA;
MAP_DATA map[MAPX + 1][MAPY + 1];
void get_exit_dir (int dir, int *x, int *y, int xorig, int yorig)
{
switch (dir)
{
case 0:
*x = xorig;
*y = yorig - 1;
break;
case 1:
*x = xorig + 1;
*y = yorig;
break;
case 2:
*x = xorig;
*y = yorig + 1;
break;
case 3:
*x = xorig - 1;
*y = yorig;
break;
default:
*x = -1;
*y = -1;
break;
}
}
void clear_coord (int x, int y)
{
map[x][y].symbol = ' ';
map[x][y].vnum = 0;
map[x][y].depth = 0;
map[x][y].up = FALSE;
map[x][y].dn = FALSE;
map[x][y].info = 0;
}
void clear_room (int x, int y)
{
int dir, exitx, exity;
for (dir = DIR_NORTH; dir <= DIR_WEST; dir++)
{
get_exit_dir (dir, &exitx, &exity, x, y);
if (!BOUNDARY (exitx, exity))
clear_coord (exitx, exity);
}
}
void map_exits (CHAR_DATA * ch, ROOM_INDEX_DATA * pRoom, int x, int y,
int depth)
{
int door;
int exitx = 0, exity = 0;
int roomx = 0, roomy = 0;
EXIT_DATA *pExit;
if (!can_see_room (ch, pRoom))
return;
map[x][y].symbol = 'o';
map[x][y].vnum = pRoom->vnum;
map[x][y].depth = depth;
map[x][y].dn = FALSE;
map[x][y].up = FALSE;
if (!IS_NPC (ch) && getbit (ch->pcdata->explored, pRoom->vnum))
{
map[x][y].info = pRoom->room_flags;
if (pRoom->exit[DIR_DOWN] != NULL)
map[x][y].dn = TRUE;
if (pRoom->exit[DIR_UP] != NULL)
map[x][y].up = TRUE;
}
if (depth >= MAXDEPTH)
return;
for (door = DIR_NORTH; door <= DIR_DOWN; door++)
{
if ((pExit = pRoom->exit[door]) == NULL)
continue;
if (pExit->u1.to_room == NULL)
continue;
if (!can_see_room (ch, pExit->u1.to_room))
continue;
get_exit_dir (door, &exitx, &exity, x, y);
get_exit_dir (door, &roomx, &roomy, exitx, exity);
if (BOUNDARY (exitx, exity) || BOUNDARY (roomx, roomy))
continue;
if ((map[roomx][roomy].vnum != 0)
&& (map[roomx][roomy].vnum != pExit->u1.to_room->vnum)
/* only clear exits and rooms of higher depth */
&& map[roomx][roomy].depth > depth && depth < MAXDEPTH)
{
clear_room (roomx, roomy);
}
if (depth == MAXDEPTH)
continue;
map[exitx][exity].depth = depth;
map[exitx][exity].vnum = pExit->u1.to_room->vnum;
map[exitx][exity].symbol = map_chars[door];
map[exitx][exity].info = pExit->exit_info;
if ((depth < MAXDEPTH)
&& ((map[roomx][roomy].vnum == pExit->u1.to_room->vnum)
|| (map[roomx][roomy].vnum == 0)))
{
depth++;
map_exits (ch, pExit->u1.to_room, roomx, roomy, depth + 1);
depth--;
}
}
}
void reformat_desc (char *desc)
{
char *p;
unsigned int l, m;
char buf[MSL * 2];
l = 0;
m = 0;
buf[0] = '\0';
if (desc[0] == '\0')
return;
/* remove all \n & \r */
for (m = 0; m <= strlen (desc); m++)
if (desc[m] == '\n' || desc[m] == '\r')
desc[m] = ' ';
/* remove multiple spaces */
for (p = desc; *p != '\0'; p++)
{
if (*p == ' ' && *(p + 1) == ' ')
{
buf[l] = *p;
l++;
do
{
p++;
}
while (*p == ' ');
}
buf[l] = *p;
l++;
}
buf[l] = '\0';
sprintf (desc, buf);
return;
}
unsigned int get_line (char *desc, unsigned int max_len)
{
unsigned int m;
unsigned int l;
char buf[MSL];
if (strlen (desc) <= max_len)
return 0;
buf[0] = '\0';
l = 0;
for (m = 0; m <= strlen (desc); m++)
{
if (desc[m] == ANSI_KEY)
m += 2;
else if (desc[m] == ANSI_CUSTOM)
{
while (desc[m] != ANSI_END)
m++;
m++;
}
l++;
if (l > max_len)
break;
}
for (l = m; l > 0; l--)
{
if (desc[l] == ANSI_KEY)
{
lcolor = desc[l + 1];
break;
}
}
for (l = m; l > 0; l--)
if (desc[l] == ' ')
break;
return l + 1;
}
void show_map (CHAR_DATA * ch, char *text)
{
char buf[MSL * 2];
int x, y, pos;
char *p;
bool alldesc = FALSE;
int rcnt = areacount (ch);
double rooms = (double) (arearooms (ch));
double percent = (double) rcnt / (rooms / 100);
int maxlen = (ch->desc
&& ch->desc->scr_width > 0) ? ch->desc->scr_width - 2 : 78;
int maplen = maxlen - 15;
if (IS_NULLSTR (text))
alldesc = TRUE;
pos = 0;
p = text;
buf[0] = '\0';
lcolor = 'x';
if (IS_NPC (ch) || IS_SET (ch->in_room->room_flags, ROOM_NOEXPLORE))
sprintf (buf, "{R+------------+{%c ", lcolor);
else
sprintf (buf, "{R+-----[{x%3.0f%%{R]+{%c ", percent, lcolor);
if (!alldesc)
{
pos = get_line (p, maplen);
if (pos > 0)
{
strncat (buf, p, pos);
p += pos;
}
else
{
strcat (buf, p);
alldesc = TRUE;
}
}
strcat (buf, "\n\r");
for (y = 0; y <= MAPY; y++)
{
strcat (buf, "{R|{x");
for (x = 0; x <= MAPX; x++)
{
if (map[x][y].symbol == 'o')
{
if (map[x][y].up && map[x][y].dn)
map[x][y].symbol = 'O';
if (!map[x][y].up && map[x][y].dn)
map[x][y].symbol = 'D';
if (map[x][y].up && !map[x][y].dn)
map[x][y].symbol = 'U';
}
sprintf (buf + strlen (buf), "%c", map[x][y].symbol);
}
strcat (buf, "{R| {");
strcat (buf, &lcolor);
if (!alldesc)
{
pos = get_line (p, maplen);
if (pos > 0)
{
strncat (buf, p, pos);
p += pos;
}
else
{
strcat (buf, p);
alldesc = TRUE;
}
}
strcat (buf, "\n\r");
}
strcat (buf, "{R+-----------+{");
strcat (buf, &lcolor);
strcat (buf, " ");
if (!alldesc)
{
pos = get_line (p, maplen);
if (pos > 0)
{
strncat (buf, p, pos);
p += pos;
}
else
{
strcat (buf, p);
alldesc = TRUE;
}
}
if (!alldesc)
{
do
{
pos = get_line (p, maxlen);
if (pos > 0)
{
strncat (buf, p, pos);
p += pos;
}
else
{
strcat (buf, p);
alldesc = TRUE;
}
}
while (!alldesc);
}
chprintln (ch, buf);
}
void draw_map (CHAR_DATA * ch, const char *desc)
{
int x, y;
static char buf[MSL];
sprintf (buf, desc);
reformat_desc (buf);
for (y = 0; y <= MAPY; y++)
{
for (x = 0; x <= MAPX; x++)
{
clear_coord (x, y);
}
}
x = MAPX / 2;
y = MAPY / 2;
map[x][y].vnum = ch->in_room->vnum;
map[x][y].depth = 0;
map_exits (ch, ch->in_room, x, y, 0);
map[x][y].symbol = 'X';
show_map (ch, buf);
}
CH_CMD (do_automap)
{
if (IS_NPC (ch))
return;
if (IS_SET (ch->act, PLR_AUTOMAP))
{
chprintln (ch, "Automap removed.");
REMOVE_BIT (ch->act, PLR_AUTOMAP);
}
else
{
chprintln (ch, "Automap on.");
SET_BIT (ch->act, PLR_AUTOMAP);
}
}