/**************************************************************************
* 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);
}
}
struct sector_color_type
{
int bit;
const char *display_color;
char display_symbol;
};
const struct sector_color_type sector_color_table[] = {
{SECT_INSIDE, "{w", 'o'},
{SECT_CITY, "{w", 'o'},
{SECT_FIELD, "{G", '*'},
{SECT_FOREST, "{g", '*'},
{SECT_HILLS, "{y", '*'},
{SECT_MOUNTAIN, "{W", '@'},
{SECT_WATER_SWIM, "{B", '='},
{SECT_WATER_NOSWIM, "{b", '='},
{SECT_UNUSED, "{w", 'o'},
{SECT_AIR, "{C", '~'},
{SECT_DESERT, "{y", '+'},
{SECT_MAX, "{w", 'o'}
};
const char *get_sector_color(int sector)
{
int looper;
for (looper = 0;; looper++)
if ((sector_color_table[looper].bit == sector)
|| (sector_color_table[looper].bit == SECT_MAX))
break;
return (sector_color_table[looper].display_color);
}
char get_sector_symbol(int sector)
{
int looper;
for (looper = 0;; looper++)
if ((sector_color_table[looper].bit == sector)
|| (sector_color_table[looper].bit == SECT_MAX))
break;
return (sector_color_table[looper].display_symbol);
}
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 = get_sector_symbol(ch->in_room->sector_type);
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), "%s%c",
get_sector_color(ch->in_room->sector_type),
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);
}
}