/************************************************************************/
/* mlkesl@stthomas.edu =====> Ascii Automapper utility */
/* Let me know if you use this. Give a newbie some _credit_, */
/* at least I'm not asking how to add classes... */
/* Also, if you fix something could ya send me mail about, thanks */
/* PLEASE mail me if you use this or like it, that way I will keep it up*/
/************************************************************************/
#include "merc.h"
#include "mapper.h"
int door_marks[4][2] ={ {-1, 0},{ 0, 1},{ 1, 0},{ 0,-1} };
int offsets[4][2] ={ {-2, 0},{ 0, 2},{ 2, 0},{ 0,-2} };
#define SECT_HERE SECT_MAX
#define SECT_UNSEEN (SECT_MAX + 1)
#define SECT_BLOCKED (SECT_UNSEEN + 1)
#define SECT_TOP (SECT_BLOCKED + 1)
const struct map_info_type door_info[] =
{
{ DOOR_LOCKED, "`R" , "#`n", "`f","Locked door" },
{ DOOR_OPEN, "`W" , "#`n", "`f","Open door" },
{ DOOR_CLOSED, "`r" , "#`n", "`f","Closed Door" },
{ DOOR_NS, "`W" , "|`n", "`f","N/S Exit" },
{ DOOR_EW, "`W" , "-`n", "`f","E/W Exit" },
{ DOOR_HIDDEN, "`n", " `n" "`f", "Hidden" },
{ DOOR_NULL, "`n", " ", "`f","Invalid" }
};
const struct map_info_type map_info[] =
{
{ SECT_BLOCKED, "`m", "~`n", "", "blocked" },
{ SECT_UNSEEN, "`K"," `n", "", "unknown" },
{ SECT_HERE, "`W", "*`n", "", "you!" },
{ SECT_CITY, "`w`i", " `n", "", "city" },
{ SECT_FIELD, "`G`i", " `n", "", "field" },
{ SECT_FOREST, "`2", " `n", "`W", "forest" },
{ SECT_HILLS, "`3", " `n", "`W","hills" },
{ SECT_MOUNTAIN, "`1", " `n", "", "mountain" },
{ SECT_WATER_SWIM,"`B`i", " `n", "", "shallow water" },
{ SECT_WATER_NOSWIM, "`4", " `n", "", "deep running water" },
{ SECT_UNDERWATER, "`4", " `n", "", "under water" },
{ SECT_AIR, "`C`i", " `n", "","air" },
{ SECT_DESERT, "`Y`i", " `n", "","desert" },
{ SECT_INSIDE, "`K`i", " `n", "","inside" },
{ SECT_SPACE, "`K`i", " `n", "", "space" },
{ SECT_TOP, "`y", "~`n", "","bad sector type" }
};
char * get_sector_display( int sector )
{
sh_int looper;
for ( looper = 0; ; looper++ )
if ( ( map_info[looper].sector_type == sector )
|| ( map_info[looper].sector_type == SECT_TOP ) )
break;
return ( map_info[looper].display_code );
}
char * get_sector_color( int sector )
{
sh_int looper;
for ( looper = 0; ; looper++ )
if ( ( map_info[looper].sector_type == sector )
|| ( map_info[looper].sector_type == SECT_TOP ) )
break;
return ( map_info[looper].display_color );
}
char * get_invert_color( int sector )
{
sh_int looper;
for ( looper = 0; ; looper++ )
if ( ( map_info[looper].sector_type == sector )
|| ( map_info[looper].sector_type == SECT_TOP ) )
break;
return ( map_info[looper].invert_color );
}
char * get_door_display( int door )
{
sh_int looper;
for ( looper = 0; ; looper++ )
if ( ( door_info[looper].sector_type == door )
|| ( door_info[looper].sector_type == DOOR_NULL ) )
break;
return ( door_info[looper].display_code );
}
char * get_door_color( int door )
{
sh_int looper;
for ( looper = 0; ; looper++ )
if ( ( door_info[looper].sector_type == door )
|| ( door_info[looper].sector_type == DOOR_NULL ) )
break;
return ( door_info[looper].display_color );
}
char * get_sector_name( int sector )
{
sh_int looper;
for ( looper = 0; ; looper++ )
if ( ( map_info[looper].sector_type == sector )
|| ( map_info[looper].sector_type == SECT_TOP ) )
break;
return ( map_info[looper].desc );
}
/*
* This code written by Altrag for Ack!Mud
*/
#define iseol(c) ((c)=='\n' || (c)=='\r')
/* Like one_argument but saves case, and if len isnt NULL, fills it in
* with the length. Also accounts for color. Does NOT account for
* quoted text. */
char *break_arg(char *str, char *first_arg, int bufsize, int max, int *buflen, int *len)
{
int slen=0;
char *arg;
while (isspace(*str))
++str;
if (*str=='\\' && str[1]=='b' && str[2]=='r')
{
strcpy(first_arg, "\n\r");
if (buflen)
*buflen=0;
if (len)
*len=0;
str+=3;
while (isspace(*str))
++str;
return str;
}
arg=first_arg;
while (*str && arg-first_arg<bufsize && slen<max)
{
if (isspace(*str))
{
++str;
break;
}
else if (*str=='`' && str[1]=='`' && str[2]!='\0')
{
if (arg-first_arg>=max-3)
break;
*arg++=*str++;
*arg++=*str++;
*arg++=*str++;
}
else if (*str=='\\' && str[1]=='b' && str[2]=='r')
break;
else
{
*arg++=*str++;
++slen;
}
}
*arg='\0';
if (len)
*len=slen;
if (buflen)
*buflen=arg-first_arg;
while (isspace(*str))
++str;
return str;
}
char *string_justify(char *str, int len, int width, int numwords, int *rlen)
{
static char buf[MSL];
char arg[MAX_INPUT_LENGTH];
int minspaces = numwords-1;
int spaces_needed;
float space_ratio, space_between;
int i, j = 0, alen;
char *bp = buf;
spaces_needed = minspaces+(width-(len+1));
if (spaces_needed<=minspaces || minspaces<=0)
{
sprintf(buf, "%s\n\r", str);
return buf;
}
space_ratio = (float)spaces_needed/(float)minspaces;
space_between = space_ratio;
for (i = 0; i < minspaces; ++i)
{
str = break_arg(str, arg, sizeof(arg), width, &alen, NULL);
strcpy(bp, arg);
bp += alen;
for (; j < (int)(space_between+0.5); ++j)
*bp++ = ' ';
space_between += space_ratio;
}
str = break_arg(str, arg, sizeof(arg), width, &alen, NULL);
strcpy(bp, arg);
bp += alen;
*bp++ = '\n';
*bp++ = '\r';
*bp = '\0';
if (rlen)
*rlen = bp-buf;
return buf;
}
char last_color(char *str)
{
char *end;
for (end=str+strlen(str)-2; end > str; --end)
if (*end == '`' && end[-1]=='`')
return end[1];
return '\0';
}
char *string_format(char *str, int *numlines, int width, int height, bool unjust)
{
static char ret[MSL];
char buf[MSL];
char arg[MAX_INPUT_LENGTH];
int alen;
int blen=0;
char *pbuf=buf, *pret=ret;
int len;
int currline = 0;
int last;
char *sp;
char c;
int numwords = 0;
int jlen;
--height;
--width;
*pret='\0';
for (sp = break_arg(str, arg, sizeof(arg), width, &len, &alen); *arg;
sp = break_arg(sp, arg, sizeof(arg), width, &len, &alen))
{
blen += alen;
if (blen+1>=width || iseol(*arg))
{
*pbuf++='\n';
*pbuf++='\r';
*pbuf='\0';
c = last_color(buf);
if (unjust || iseol(*arg))
{
strcpy(pret, buf);
pret += pbuf-buf;
}
else
{
strcpy(pret, string_justify(buf, blen-alen, width, numwords, &jlen));
pret += jlen;
}
pbuf=buf;
if (++currline>height)
break;
if (c)
{
*pbuf++='`';
*pbuf++='`';
*pbuf++=c;
}
blen=alen;
if (iseol(*arg))
*arg='\0';
numwords = 0;
}
else if (pbuf>buf)
{
if (pbuf-buf>2 && pbuf[-2]=='`' && pbuf[-3]=='`')
{
if (pbuf-buf==3)
last=0;
else
last=-4;
}
else
last=-1;
if (last)
{
if (unjust && pbuf[last]=='.')
*pbuf++=' ', ++blen;
*pbuf++=' ', ++blen;
}
}
strcpy(pbuf, arg);
pbuf+=len;
++numwords;
}
if (pbuf>buf)
{
if (pbuf-buf>2 && pbuf[-2]=='`' && pbuf[-3]=='`')
{
if (pbuf-buf==3)
last=0;
else
last=-4;
}
else
last=-1;
if (last && pbuf[last]!='\n' && pbuf[last]!='\r')
{
*pbuf++='\n';
*pbuf++='\r';
++currline;
}
}
*pbuf='\0';
strcpy(pret, buf);
if (numlines)
*numlines=currline;
return ret;
}
char *map_format(char *str, int start, char map[MAP_Y][MSL], int *numlines,
int term_width, int height, bool unjust)
{
static char ret[MSL];
char buf[MSL];
char arg[MAX_INPUT_LENGTH];
int width = (start<MAP_Y ? term_width-15 : term_width-1);
int alen;
int blen=0;
char *pbuf=buf, *pret=ret;
int len;
int currline = start;
int last;
char *sp;
char c;
int numwords = 0;
int jlen;
--height;
*pret='\0';
for (sp = break_arg(str, arg, sizeof(arg), width, &len, &alen); *arg;
sp = break_arg(sp, arg, sizeof(arg), width, &len, &alen))
{
blen += alen;
if (blen+1>=width || iseol(*arg))
{
*pbuf++='\n';
*pbuf++='\r';
*pbuf='\0';
c = last_color(buf);
if (currline<MAP_Y)
pret += sprintf(pret, "%s ", map[currline]);
else if (currline==MAP_Y)
strcpy(pret, " "), pret+=14;
if (unjust || iseol(*arg))
{
strcpy(pret, buf);
pret += pbuf-buf;
}
else
{
strcpy(pret, string_justify(buf, blen-alen, width, numwords, &jlen));
pret += jlen;
}
if (currline==MAP_Y)
width=term_width-1;
pbuf=buf;
if (++currline>height)
break;
if (c)
{
*pbuf++='`';
*pbuf++='`';
*pbuf++=c;
}
blen=alen;
if (iseol(*arg))
*arg='\0';
numwords = 0;
}
else if (pbuf>buf)
{
if (pbuf-buf>2 && pbuf[-2]=='`' && pbuf[-3]=='`')
{
if (pbuf-buf==3)
last=0;
else
last=-4;
}
else
last=-1;
if (last)
{
if (unjust && pbuf[last]=='.')
*pbuf++=' ', ++blen;
// if (!iseol(pbuf[last]))
*pbuf++=' ', ++blen;
}
}
strcpy(pbuf, arg);
pbuf+=len;
++numwords;
}
if (pbuf>buf)
{
if (pbuf-buf>2 && pbuf[-2]=='`' && pbuf[-3]=='`')
{
if (pbuf-buf==3)
last=0;
else
last=-4;
}
else
last=-1;
if (last && pbuf[last]!='\n' && pbuf[last]!='\r')
{
*pbuf++='\n';
*pbuf++='\r';
if (currline<MAP_Y)
pret += sprintf(pret, "%s ", map[currline]);
else if (currline==MAP_Y || (currline==MAP_Y+1 && blen<=term_width-15))
strcpy(pret, " "), pret+=14;
++currline;
}
}
*pbuf='\0';
strcpy(pret, buf);
if (numlines)
*numlines=currline;
return ret;
}
void disp_map(char *border, char *map, CHAR_DATA *ch, ROOM_INDEX_DATA *room)
{
int cols=80;
int rows=9999;
char bufs[MAP_Y][MSL];
char disp[MSL];
char cdisp[MSL];
int y, ty=MAP_Y-1;
char *x, *ox;
strcpy(bufs[0], border);
strcpy(bufs[ty], border);
x = map;
for (y = 1; y < ty && *x; ++y)
{
while (*x=='\n' || *x=='\r')
++x;
ox = x;
while (*x!='\n' && *x!='\r' && *x!='\0')
++x;
sprintf(bufs[y], "%.*s", (x-ox), ox);
}
sprintf(cdisp, "`c%s`n", room->name);
strcpy(disp, map_format(cdisp, 0, bufs, &y, cols+colorcount(cdisp), rows, TRUE));
strcat(disp, map_format(room->description, y, bufs, &y, cols ,rows, TRUE));
if (y<MAP_Y)
{
x = disp+strlen(disp);
while (y<MAP_Y)
x += sprintf(x, "%s\n\r", bufs[y]), ++y;
}
send_to_char("\r\n", ch);
send_to_char(disp, ch);
return;
}
void MapArea
(ROOM_INDEX_DATA *room, CHAR_DATA *ch,
int x, int y, int min, int max, int line_of_sight )
{
ROOM_INDEX_DATA *prospect_room;
EXIT_DATA *pexit;
int door;
sh_int door_type = 0;
if ( map[x][y] <= 0 )
return; /* it's a door, not a room in the map */
/* marks the room as visited */
map[x][y]=room->sector_type;
for ( door = 0; door < MAX_MAP_DIR; door++ )
{ /* cycles through for each exit */
if ( ( (pexit = room->exit[door]) != NULL )
&& ( pexit->u1.to_room != NULL ) )
{ /* if exit there */
if ((x<min)||(y<min)||(x>max)||(y>max)) return;
prospect_room = pexit->u1.to_room;
if ( ( prospect_room->exit[rev_dir[door]] )
&& ( prospect_room->exit[rev_dir[door]]->u1.to_room != room ))
{ /* if not two way */
map[x][y]=SECT_BLOCKED; /* one way into area OR maze */
return;
} /* end two way */
/* selects door symbol */
door_type = 0;
if ( !IS_SET(pexit->exit_info, EX_ISDOOR) &&
!IS_SET(pexit->exit_info, EX_HIDDEN))
{
if ( ( door == 0 )
|| ( door == 2 ) )
door_type = DOOR_NS;
else
door_type = DOOR_EW;
}
else if (IS_SET(pexit->exit_info, EX_HIDDEN))
{
door_type = DOOR_HIDDEN;
}
else if ( IS_SET( pexit->exit_info, EX_LOCKED ) )
{
door_type = DOOR_LOCKED;
}
else if ( IS_SET( pexit->exit_info, EX_CLOSED ) )
{
door_type = DOOR_CLOSED;
}
else
door_type = DOOR_OPEN;
if ( ( !IS_NPC( ch ) )
&& ( !str_cmp( pexit->keyword, "" ) )
&& ( ( door_type <= DOOR_OPEN )
|| ( !IS_SET(pexit->exit_info, EX_ISDOOR ) )
|| ( ( IS_SET( pexit->exit_info, EX_CLOSED ) )
&& ( !str_cmp( pexit->keyword, "" ) ) ) ) )
{
map[x+door_marks[door][0]][y+door_marks[door][1]]=door_type;
if ( ( door_type < DOOR_CLOSED )
&& ( ( line_of_sight == LOS_INITIAL )
|| ( door == line_of_sight ) )
&& (map[x+offsets[door][0]][y+offsets[door][1]]==SECT_UNSEEN) )
{
MapArea (pexit->u1.to_room,ch,
x+offsets[door][0], y+offsets[door][1],min,max,
( line_of_sight == LOS_INITIAL ) ?
door :
line_of_sight );
}
}
}
/* end if exit there */
}
return;
}
void ShowRoom(CHAR_DATA *ch, int min, int max, int size, int center, ROOM_INDEX_DATA *room)
{
void disp_map(char *border, char *map, CHAR_DATA *ch, ROOM_INDEX_DATA *room);
int x,y, looper;
char outbuf[MSL];
char catbuf[MSL];
char borderbuf[MSL];
char colorbuf[MSL];
char displaybuf[MSL];
outbuf[0] = '\0';
sprintf( outbuf, "%s", "\n\r" );
sprintf( borderbuf, "%s", "`y+`W" );
for ( looper = 0; looper <= size+1; looper++ )
{
sprintf( catbuf, "%s", "-" );
strcat( borderbuf, catbuf );
}
strcat( borderbuf, "`y+`n" );
for (x = min; x <= max; ++x)
{ /* every row */
strcat( outbuf, "`W| " );
for (y = min; y <= max; ++y)
{ /* every column */
if ( (y==min) || (map[x][y-1]!=map[x][y]) )
{
sprintf( colorbuf, "%s%s",
( ( map[x][y]<= 0 ) ?
get_door_color( map[x][y] ) :
get_sector_color( map[x][y] ) ),
( ( m_contents[x][y].string[0] == '\0' ) ?
"" :
get_invert_color( map[x][y] ) ) );
sprintf( displaybuf, "%s",
( ( map[x][y]<= 0 ) ?
get_door_display( map[x][y] ) :
( ( m_contents[x][y].string[0] == '\0' ) ?
get_sector_display(map[x][y] ) :
m_contents[x][y].string ) ) );
sprintf( catbuf, "%s%s",
colorbuf, displaybuf );
strcat( outbuf, catbuf );
}
else
{
sprintf( catbuf, "%s",
(map[x][y]<=0) ?
get_door_display( map[x][y] ) :
get_sector_display(map[x][y]) );
strcat( outbuf, catbuf );
}
}
strcat( outbuf, " `W|`n\n\r" );
}
disp_map(borderbuf, outbuf, ch, room);
return;
}
void ShowMap( CHAR_DATA *ch, int min, int max, int size, int center )
{
int x,y, looper;
char outbuf[MSL];
char catbuf[MSL];
char borderbuf[MSL];
char colorbuf[MSL];
char displaybuf[MSL];
outbuf[0] = '\0';
sprintf( outbuf, "%s", "\n\r" );
sprintf( borderbuf, "%s", "`y+`W" );
for ( looper = 0; looper <= size+1; looper++ )
{
sprintf( catbuf, "%s", "-" );
strcat( borderbuf, catbuf );
}
strcat( borderbuf, "`y+`n" );
for (x = min; x <= max; ++x)
{ /* every row */
strcat( outbuf, "`W| " );
for (y = min; y <= max; ++y)
{ /* every column */
if ( (y==min) || (map[x][y-1]!=map[x][y]) )
{
sprintf( colorbuf, "%s%s",
( ( map[x][y]<= 0 ) ?
get_door_color( map[x][y] ) :
get_sector_color( map[x][y] ) ),
( ( m_contents[x][y].string[0] == '\0' ) ?
"" :
get_invert_color( map[x][y] ) ) );
sprintf( displaybuf, "%s",
( ( map[x][y]<= 0 ) ?
get_door_display( map[x][y] ) :
( ( m_contents[x][y].string[0] == '\0' ) ?
get_sector_display(map[x][y] ) :
m_contents[x][y].string ) ) );
sprintf( catbuf, "%s%s",
colorbuf, displaybuf );
strcat( outbuf, catbuf );
}
else
{
sprintf( catbuf, "%s",
(map[x][y]<=0) ?
get_door_display( map[x][y] ) :
get_sector_display(map[x][y]) );
strcat( outbuf, catbuf );
}
}
strcat( outbuf, " `W|`n\n\r" );
}
send_to_char( "\n\r", ch );
/* this is the top line of the map itself, currently not part of the mapstring */
send_to_char( borderbuf, ch );
send_to_char( outbuf, ch );
/* this is the bottom line of the map */
send_to_char( borderbuf, ch );
send_to_char( "\n\r", ch );
send_to_char( "Also try map legend.\n\r", ch );
return;
}
ACMD(do_mapper) {
map_room(ch, argument, IN_ROOM(ch));
}
void map_room(CHAR_DATA *ch, char *argument, ROOM_INDEX_DATA *room) {
int size, center,
x, y, min, max, looper;
char arg1[MSL];
char catbuf[MSL];
char outbuf[MSL];
bool SRoom = FALSE;
one_argument(argument, arg1);
if (is_name(arg1, "legend key help")) {
sprintf(outbuf, "`WMap Legend:`n\n\r");
for (looper = 0; looper < SECT_UNSEEN; looper++) {
sprintf(catbuf, "%s%s : `n%s\n\r",
map_info[looper].display_color,
map_info[looper].display_code,
map_info[looper].desc);
strcat(outbuf, catbuf);
}
for (looper = 0; looper < 5 ; looper++) {
sprintf(catbuf, "%s%s : `n%s\n\r",
door_info[looper].display_color,
door_info[looper].display_code,
door_info[looper].desc);
strcat(outbuf, catbuf);
}
send_to_char(outbuf, ch);
return;
}
size = (is_number(arg1)) ? atoi(arg1) : 11;
if (is_name(arg1, "SRoom")) {
size = 7;
SRoom = TRUE;
}
if (size != 7) {
size = (IS_IMMORTAL(ch) ? size : 8);
if (size % 2 == 0)
size +=1;
size = URANGE(8, size, MAX_MAP);
}
size = URANGE(3,size,MAX_MAP/2);
center = MAX_MAP/2;
min = MAX_MAP/2-size/2;
max = MAX_MAP/2+size/2;
for (x = 0; x < MAX_MAP; ++x) {
for (y = 0; y < MAX_MAP; ++y) {
map[x][y]=SECT_UNSEEN;
m_contents[x][y].string[0] = '\0';
}
}
MapArea(room, ch, center, center, min-1, max, LOS_INITIAL);
sprintf(m_contents[center][center].string, "%s", "`f*`n");
if (SRoom == TRUE)
ShowRoom(ch, min, max, size, center, room);
else
ShowMap(ch, min, max, size, center);
return;
}