EmlenMud2003LOC/
EmlenMud2003LOC/world/
#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;
}