/
rogue24b3/
rogue24b3/data/
/************************************************************************/
/* 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;
}