#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "emlen.h"
/* MAXX holds the maximum size of the 'visited already' array.
Make this dynamic later, since this is using 100/200k */
#ifdef NEW_WORLD
#define MAXX 100000
#else
#define MAXX 200000
#endif
/* Is there an exit from room 'room' in direction 'dir'? */
#define CAN_GO(room,dir) (room->exit[dir] && room->exit[dir]->to_room)
bool kk = FALSE; /* Internal use */
bool mb = FALSE; /* Show all mobiles option */
bool flip = FALSE; /* Rotate 90 degrees option */
bool noibm = FALSE; /* No Extended IBM char set option */
bool dbs = FALSE; /* Double space option */
bool disp_already[MAXX]; /* Displayed this coordinate already? */
int ctr;
char outp[80][25][2]; /* Virtual Screen for character output */
char scrnn[80][25][15]; /* Virtual Screen - holds ANSI color values */
signed char colrs[80][25]; /* Virtual Screen - numeric color values */
char smlmap[MAP_WIDTH][MAP_HEIGHT][2];
char smlcolors[MAP_WIDTH][MAP_HEIGHT];
char max_col[25];
bool now = FALSE;
char cur_col = -6;
char last_col;
/* Clears the screen. */
void
clr (CHAR_DATA * ch)
{
write_to_buffer (ch->desc, "\x1B[37;0m\x1B[2J\x1B[1;1f", 0);
return;
}
/* Jump to x,y with writing the positioning code to user's output buffer */
void
gotoxy (CHAR_DATA * ch, int x, int y)
{
char tt[50];
sprintf (tt, "\x1B[%d;%df", y, x);
write_to_buffer (ch->desc, tt, 0);
return;
}
/* Jump to x,y with direct write to port - for updates that won't
trigger a new prompt */
void
gotoxy_dir (CHAR_DATA * ch, int x, int y)
{
char tt[50];
sprintf (tt, "\x1B[%d;%df", y, x);
write_to_descriptor (ch->desc->descriptor, tt, 0);
return;
}
/* Gotoxy returning a string */
char *
ggotoxy_dir (CHAR_DATA * ch, int x, int y)
{
static char tt[50];
sprintf (tt, "\x1B[%d;%df", y, x);
return tt;
}
void
do_drawrooms (CHAR_DATA * ch, char *argy)
{
DEFINE_COMMAND ("codeone", do_drawrooms, POSITION_DEAD, IMM_LEVEL, LOG_NORMAL, "This shows an overhead map of the current area around you.")
reset_data();
do_rawclear(ch);
if (!ch->desc)
return;
drawstuff(ch, argy, 22, 78);
return;
}
/* Reset all data used for mapping */
void
reset_data (void)
{
bzero (max_col, sizeof (max_col));
bzero (scrnn, sizeof (scrnn));
bzero (disp_already, sizeof (disp_already));
bzero (outp, sizeof (outp));
bzero (colrs, sizeof (colrs));
cur_col = -5;
return;
}
void
drawstuff (CHAR_DATA *ch, char* argy, int maxy, int maxx)
{
char *y = argy;
char tt[50];
int i,j,m;
if (IS_MOB(ch)) return;
if (IS_SET(ch->pcdata->act2, PLR_NOIBM))
noibm = TRUE;
else
noibm = FALSE;
flip = FALSE;
kk = FALSE;
mb = FALSE;
for (; *y != '\0'; y++)
{
if (*y == 'N' || *y == 'n')
noibm = TRUE;
if (*y == 'D' || *y == 'd')
kk = TRUE;
if (*y == 'M' || *y == 'm')
mb = TRUE;
if (*y == 'F' || *y == 'f')
flip = TRUE;
}
for (i=0; i<80; i++)
{
for (j=0; j<25; j++)
{
outp[i][j][0] = ' ';
outp[i][j][1] = '\0';
for (m=0; m < 15; m++)
scrnn[i][j][m]='\0';
colrs[i][j]='\0';
}
}
reset_data();
ch->pcdata->maxx = maxx;
ch->pcdata->maxy = maxy;
go_display (ch, ch->in_room, (maxx/2), (maxy/2), maxy, maxx);
outp[(maxx/2)][(maxy/2)][0] = 'X';
outp[(maxx/2)][(maxy/2)][1] = '\0';
draw_data (ch, maxy);
write_to_buffer(ch->desc, "\x1B[0;37m", 0);
gotoxy (ch, 1, maxy+1);
undisplay(ch, ch->in_room, 150);
gotoxy(ch, 1, ch->pcdata->pagelen);
mb = FALSE;
kk = FALSE;
noibm = FALSE;
flip = FALSE;
return;
}
void
undisplay (CHAR_DATA *ch, ROOM_DATA *rid, int distance)
{
int i;
ROOM_DATA *troom;
EXIT_DATA *pexit;
if (!rid->y) return;
rid->y = FALSE;
for (i = 0; i < 4; i++)
{
if (rid->mapexit[i] != NULL)
{
undisplay(ch, rid->exit[i]->to_room, distance--);
}
}
return;
}
void
go_display (CHAR_DATA * ch, ROOM_DATA * rid, int x, int y, int maxy, int maxx)
{
int i, newx = x, newy = y;
EXIT_DATA *pexit, *backexit;
ROOM_DATA *troom;
if (x > maxx || x < 0) /* Boundary x case stop */
return;
if (y > maxy || y < 0) /* Boundary y case stop */
return;
if (rid->y) return; /* Don't do same room twice. */
display_room (ch, rid, x, y);
for (i = 0; i < 4; i ++)
{
if ((pexit = rid->exit[i]) != NULL && (troom = pexit->to_room) !=
NULL && troom == rid->mapexit[i])
{
if ((i % 2) == 0)
if (flip)
newx += (i-1);
else
newy += (i-1);
else
if (flip)
newy += (2-i);
else
newx += (2-i);
go_display(ch, rid->mapexit[i], newx, newy, maxy, maxx);
newy = y;
newx = x;
}
}
return;
}
/*
Draw the actual data to the user's output buffer.
*/
void
draw_data (CHAR_DATA * ch, int lines)
{
int i, j;
bool ibm = !IS_SET(ch->pcdata->act2, PLR_NOIBM);
gotoxy (ch, 1, 1); /* Home cursor */
last_col = 0; /* Last column used for truncating trailing spaces */
for (i = 1; i <= lines; i++)
{
for (j = 1; j < ch->pcdata->maxx+1; j++)
{
if (outp[j][i][0] == '\0' || outp[j][i][0] == ' ') /* Null -> Space */
{
write_to_buffer (ch->desc, " ", 0);
}
else
{ /* Optimize colors so we don't send repeat color
sequences that are unnecessary */
if (colrs[j][i] == 0 || colrs[j][i] != last_col)
{
write_to_buffer (ch->desc, scrnn[j][i], 0);
}
last_col = colrs[j][i]; /* Set the last color drawn */
write_to_buffer (ch->desc, outp[j][i], 0); /* Draw the char */
}
}
if (max_col[i] < 20) send_to_char(" ", ch);
send_to_char ("\n\r", ch); /* Next line */
}
send_to_char ("\x1B[0;37m", ch); /* Back to gray */
return;
}
void
do_drawtop (CHAR_DATA * ch, char *argy)
{
char tt[50];
DEFINE_COMMAND ("drawtop", do_drawtop, POSITION_DEAD, IMM_LEVEL, LOG_NORMAL, "This command shows an updated map in the upper half of the screen.")
if (!ch->desc)
return;
/* Vt100 windowing code - set up window */
drawstuff(ch, argy, 10, 78);
write_to_buffer (ch->desc, "\x1B[0;37m", 0);
send_to_char ("\x1B[10;1f\x1B[1;37m-------------------------------------------------------------------------------\x1B[0;37m", ch);
sprintf (tt, "\x1B[%d;1f", ch->pcdata->pagelen);
send_to_char (tt, ch);
return;
}
void
display_room (CHAR_DATA * ch, ROOM_DATA * rid, int x, int y)
{
bool dir[4];
char out = ' ';
int i;
bool found = TRUE;
char outpt[20];
char color[25];
rid->y = TRUE;
for (i = 0; i < 4; i ++)
{
dir[i] = (rid->exit[i] != NULL);
}
if (flip)
{
bool temp;
for (i = 0; i < 4; i ++)
{
temp = dir[i];
dir[i] = dir[(i+1) % 4];
dir[(i+1) % 4] = temp;
}
}
if (kk && DESCRIPTED (rid) && LEVEL(ch) > IMM_LEVEL)
out = 'D';
else if (mb && (rid->more && rid->more->people != NULL))
{
out = (rid->more->pcs > 0 ? 'P' : 'M');
}
else
{
if (rid->a != '\0')
{
out = rid->a;
}
else if (noibm)
{
switch (rid->sector_type)
{
default:
found = FALSE;
break;
case SECT_HILLS:
case SECT_MOUNTAIN:
case SECT_ROCKY:
case SECT_CANYON:
{
out = '^';
break;
}
case SECT_FOREST:
case SECT_WOODS:
case SECT_BRUSH:
{
out = '*';
break;
}
case SECT_DESERT:
case SECT_WASTELAND:
{
out = ',';
break;
}
case SECT_WATER_SWIM:
case SECT_WATER_NOSWIM:
case SECT_UNDERWATER:
{
out = '#';
break;
}
case SECT_SWAMP:
case SECT_MARSH:
case SECT_HOLLOW:
case SECT_ICE:
case SECT_SNOW:
case SECT_ARCTIC:
{
out = '"';
break;
}
case SECT_FIELD:
case SECT_GRASSLANDS:
case SECT_PLAINS:
case SECT_SAVANNAH:
case SECT_STEPPE:
{
out = '.';
break;
}
case SECT_ROAD:
case SECT_TRAIL:
case SECT_PATH:
{
out = '+';
break;
}
}
}
if (!found || !noibm)
{
if (dir[DIR_EAST])
{
if (dir[DIR_WEST])
{
if (dir[DIR_NORTH])
{
if (dir[DIR_SOUTH]) /* N E W S */
{
out = (noibm ? '+' : '\305');
}
else /* N E W */
{
out = (noibm ? '+' : '\301');
}
}
else if (dir[DIR_SOUTH]) /* Not North */
{
out = (noibm ? '+' : '\302'); /* E W S */
}
else /* E W */
{
out = (noibm ? '-' : '\304');
}
}
else /* East and Not West */
{
if (dir[DIR_NORTH])
{
if(dir[DIR_SOUTH])
{
out = (noibm ? '}' : '\303'); /* E N S */
}
else
{
out = (noibm ? '\\' : '\330'); /* E N */
}
}
else if (dir[DIR_SOUTH]) /* E S */
{
out = (noibm ? '/' : '\332');
}
}
}
else if (dir[DIR_WEST]) /* West but not east */
{
if (dir[DIR_NORTH])
{
if (dir[DIR_SOUTH])
{
out = (noibm ? '{' : '\264'); /* N S W */
}
else
{
out = (noibm ? '/' : '\331'); /* W N */
}
}
else if (dir[DIR_SOUTH]) /* S W */
{
out = (noibm ? '\\' : '\277');
}
}
else if (dir[DIR_NORTH] || dir[DIR_SOUTH])
{
out = (noibm ? '|' : '\263'); /* N || S */
}
}
}
if (rid->c != '\0')
{
int iii;
for (iii = 1; iii <= 15; iii++)
{
if (rid->c == color_table[iii].number)
{
if (iii < 8)
{
cur_col = 0;
sprintf (color, "\x1B[0m%s", color_table[iii].code);
}
else
{
cur_col = 0;
sprintf (color, color_table[iii].code);
}
}
}
}
else
{
if ((rid->sector_type >= 0) && (rid->sector_type <= (SECT_MAX-1)))
{
cur_col = (rid->sector_type)+1;
sprintf(color, sectors[rid->sector_type].color);
}
else
{
cur_col = SECT_MAX;
sprintf (color, "\x1B[0;37m");
}
}
sprintf (outpt, "%s%c", color, out);
if (x > max_col[y])
max_col[y] = x;
outp[x][y][0] = out;
outp[x][y][1] = '\0';
strcpy (scrnn[x][y], color);
colrs[x][y] = cur_col;
return;
}
/* This is the recursive function that builds the map in memory and displays it.
-> came_from stores the direction last came from, so we don't need to check
that direction again.
-> rid is the current room data being examined.
-> x and y are the current screen coordinates that we are at.
-> maxx and maxy are the maximum screen coordinates we should draw to.
allows for us to make variable window sizes for mapping
-> ds is for double space. For double spacing the X direction to give
an aspect ration of 40x25, not 80x25.
*/
void
sml_ibm (CHAR_DATA * ch, ROOM_DATA * rid, int x, int y)
{
bool found = FALSE;
int i, newx = x, newy = y;
if (x > MAP_WIDTH || x < 0) /* Boundary x case stop */
return;
if (y > MAP_HEIGHT || y < 0) /* Boundary y case stop */
return;
if (rid->y) return; /* Don't do same room twice. */
rid->y = TRUE;
smlcolors[x][y] = rid->color;
if (rid->more && kk && rid->more->pcs > 0)
{
CHAR_DATA *rch;
for(rch = rid->more->people; rch != NULL; rch=rch->next_in_room)
{
if (IS_PLAYER(rch) && !DIFF_ALIGN(ch, rch))
{
found = TRUE;
smlmap[x][y][0] = 'P';
smlcolors[x][y] = 12;
break;
}
}
}
if (!found && rid->more && mb && rid->more->people != NULL)
{
CHAR_DATA *rch;
for (rch = rid->more->people; rch != NULL; rch = rch->next_in_room)
{
if (IS_MOB(rch))
{
found = TRUE;
smlmap[x][y][0] = 'M';
smlcolors[x][y] = 9;
break;
}
}
}
if (!found)
{
smlmap[x][y][0] = rid->ibm[0];
}
for (i = 0; i < 4; i ++)
{
if (rid->mapexit[i])
{
if ((i % 2) == 0)
newy += (i-1);
else
newx += (2-i);
sml_ibm(ch, rid->mapexit[i], newx, newy);
newy = y;
newx = x;
}
}
return;
}
void
sml_noibm (CHAR_DATA * ch, ROOM_DATA * rid, int x, int y)
{
int i, newx = x, newy = y;
bool found = FALSE;
if (x > MAP_WIDTH || x < 0) /* Boundary x case stop */
return;
if (y > MAP_HEIGHT || y < 0) /* Boundary y case stop */
return;
if (rid->y) return; /* Don't do same room twice. */
rid->y = TRUE;
smlcolors[x][y] = rid->color;
if (rid->more && kk && rid->more->pcs > 0)
{
CHAR_DATA *rch;
for(rch = rid->more->people; rch != NULL; rch=rch->next_in_room)
{
if(IS_PLAYER(rch) && !DIFF_ALIGN(ch,rch))
{
smlmap[x][y][0] = 'P';
smlcolors[x][y] = 12;
found = TRUE;
break;
}
}
}
if (!found && rid->more && mb && rid->more->people > 0)
{
CHAR_DATA *rch;
for (rch = rid->more->people; rch != NULL; rch =rch->next_in_room)
{
if (IS_MOB(rch))
{
found = TRUE;
smlmap[x][y][0] = 'M';
smlcolors[x][y] = 9;
break;
}
}
}
if (!found)
{
smlmap[x][y][0] = rid->noibm[0];
}
for (i = 0; i < 4; i ++)
{
if (rid->mapexit[i])
{
if ((i % 2) == 0)
newy += (i-1);
else
newx += (2-i);
sml_noibm(ch, rid->mapexit[i], newx, newy);
newy = y;
newx = x;
}
}
return;
}
void
small_map (CHAR_DATA *ch)
{
int i,j;
if (IS_MOB(ch)) return;
if (IS_SET(ch->pcdata->act2, PLR_NOIBM)) noibm = TRUE;
if (IS_SET(ch->pcdata->act2, PLR_VIEWMOBS)) mb = TRUE;
if (IS_SET(ch->pcdata->act2, PLR_VIEWPLAYERS)) kk = TRUE;
for (i=0; i < MAP_WIDTH; i++)
{
for (j=0; j < MAP_HEIGHT; j++)
{
smlmap[i][j][0] = ' ';
smlmap[i][j][1] = '\0';
smlcolors[i][j]= 0;
}
}
reset_small();
ch->pcdata->x = (MAP_WIDTH/2);
ch->pcdata->y = (MAP_HEIGHT/2);
if (noibm)
sml_noibm(ch, ch->in_room,MAP_WIDTH/2, MAP_HEIGHT/2);
else
sml_ibm(ch, ch->in_room, MAP_WIDTH/2, MAP_HEIGHT/2);
smlmap[MAP_WIDTH/2][MAP_HEIGHT/2][0] = 'X';
smlmap[MAP_WIDTH/2][MAP_HEIGHT/2][1] = '\0';
smlcolors[MAP_WIDTH/2][MAP_HEIGHT/2] = 12;
draw_small (ch);
write_to_buffer(ch->desc, "\x1B[0;37m", 0);
undisplay(ch, ch->in_room, 50);
gotoxy(ch, 1, ch->pcdata->pagelen);
mb = FALSE;
noibm = FALSE;
kk = FALSE;
return;
}
void
draw_small (CHAR_DATA * ch)
{
int i, j;
int currcolor = 0;
char buf[100];
sprintf(buf, "\x1b[%d;%dr", MAP_HEIGHT, ch->pcdata->pagelen);
send_to_char(buf, ch);
gotoxy(ch,1,1);
for (i = 1; i <= MAP_HEIGHT; i++)
{
for (j = 1; j < MAP_WIDTH; j++)
{
if (smlmap[j][i][0] == '\0')
{
write_to_buffer (ch->desc, " ", 0);
}
if (smlcolors[j][i] != 0 && smlcolors[j][i] != currcolor)
{
write_to_buffer (ch->desc, color_table[smlcolors[j][i]].code, 0);
currcolor = smlcolors[j][i];
}
write_to_buffer (ch->desc, smlmap[j][i] , 0);
}
send_to_char ("\n\r", ch); /* Next line */
}
sprintf(buf, "\x1b[%d;1f", ch->pcdata->pagelen);
send_to_char(buf, ch);
send_to_char ("\x1B[0;37m", ch); /* Back to gray */
return;
}
void
reset_small (void)
{
bzero (smlcolors, sizeof(smlcolors));
bzero (smlmap, sizeof(smlmap));
return;
}