ackmud/area/boards/
ackmud/area/imc/
ackmud/npcs/a/
ackmud/npcs/c/
ackmud/npcs/d/
ackmud/npcs/e/
ackmud/npcs/f/
ackmud/npcs/h/
ackmud/npcs/i/
ackmud/npcs/k/
ackmud/npcs/l/
ackmud/npcs/n/
ackmud/npcs/o/
ackmud/npcs/p/
ackmud/npcs/r/
ackmud/npcs/s/
ackmud/npcs/w/
ackmud/player/c/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  Ack 2.2 improvements copyright (C) 1994 by Stephen Dooley              *
 *                                                                         *
 *  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.                                               *
 *                                                                         *
 *       _/          _/_/_/     _/    _/     _/    ACK! MUD is modified    *
 *      _/_/        _/          _/  _/       _/    Merc2.0/2.1/2.2 code    *
 *     _/  _/      _/           _/_/         _/    (c)Stephen Zepp 1998    *
 *    _/_/_/_/      _/          _/  _/             Version #: 4.3          *
 *   _/      _/      _/_/_/     _/    _/     _/                            *
 *                                                                         *
 *                        http://ackmud.nuc.net/                           *
 *                        zenithar@ackmud.nuc.net                          *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

/* This code inspired by a snippet from :                                  */

/************************************************************************/
/* 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 <ctype.h>  /* for isalpha */
#include <string.h>
#include <stdlib.h>
#include <stdio.h> 
#include <time.h> 
#include "mapper.h"


extern char * compass_name[];

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_NULL, "@@N", " ", "@@f","Invalid" }
};

const struct map_info_type map_info[] =
{
  { SECT_BLOCKED, "@@m", "~@@N", "", "blocked" },
  { SECT_UNSEEN, "@@N@@d"," @@N", "", "unknown" },
  { SECT_HERE, "@@N@@W", "*@@N", "", "you!" },
  { SECT_CITY, "@@g@@i", " @@N", "", "city" },
  { SECT_FIELD, "@@r@@i", " @@N", "", "field" },
  { SECT_FOREST, "@@3", " @@N", "@@W", "forest" },
  { SECT_HILLS,  "@@4", " @@N", "@@W","hills" },
  { SECT_MOUNTAIN, "@@2", " @@N", "", "mountain" },
  { SECT_WATER_SWIM,"@@l@@i", " @@N", "", "shallow water" },
  { SECT_WATER_NOSWIM, "@@1", " @@N", "", "deep running water" },
  { SECT_RECALL_OK, "@@5", " @@N", "","inside" },
  { SECT_AIR, "@@a@@i", " @@N", "","air" },
  { SECT_DESERT, "@@y@@i", " @@N", "","desert" },
  { SECT_INSIDE, "@@d@@i", " @@N", "","inside" },
  { 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 += sprintf(bp, "\n\r%d:%d:%d", len, width, numwords);
  bp += sprintf(bp, "\n\r%d:%d:%f", minspaces, spaces_needed, space_ratio);*/
  *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;
//        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';
      ++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;
  }
/*  sprintf(bug_buf, "%d:%d", width, blen);
  monitor_chan(bug_buf, MONITOR_DEBUG);*/
  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;
}

char *exit_string( CHAR_DATA * ch, ROOM_INDEX_DATA *r)
{
  int e;
  static char buf[128];
  
  strcpy(buf, "[");
  for (e = 0; e < 6; e++)
    if (r->exit[e] && r->exit[e]->to_room && !str_cmp( "", r->exit[e]->keyword) )
    {
      if ( IS_SET( r->exit[e]->exit_info, EX_CLOSED ) )
      {
        if ( IS_SET( r->exit[e]->exit_info, EX_NODETECT ) )
        {
          continue;
        }
        else if (  ( IS_NPC( ch ) ?
                     50 :
                     ch->pcdata->learned[gsn_find_doors] ) > number_percent() )
        {
          sprintf(buf+strlen(buf), " (%s)", compass_name[e] );
        }
      }
      else
      {
        sprintf(buf+strlen(buf), " %s", compass_name[e]);
      }
    }
  strcat(buf, " ]");
  return buf;
}

void disp_map(char *border, char *map, CHAR_DATA *ch)
{
#ifdef ACK_43
  int cols=(IS_NPC(ch) ? 80 : ch->pcdata->term_columns);
  int rows=(IS_NPC(ch) || !IS_SET(ch->config, CONFIG_FULL_ANSI) ? 9999 : 10);
#else
  int cols=80;
  int rows=9999;
#endif
  char bufs[MAP_Y][MSL];
  char disp[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);
  }
#ifdef ACK_43
  if (!IS_NPC(ch) && IS_SET(ch->config, CONFIG_FULL_ANSI))
  {
    sprintf(disp, "%s%s%i;%ir%s%i;%iH%s%s",
    	    CRS_SAVE_ALL,
    	    CRS_CMD,
    	    ch->pcdata->term_rows-11,
    	    ch->pcdata->term_rows-1,
    	    CRS_CMD,
    	    ch->pcdata->term_rows-11,
    	    0,
    	    CRS_CMD,
    	    "J");
    send_to_char(disp, ch);
  }
#endif
  strcpy(disp, map_format(ch->in_room->name, 0, bufs, &y, cols, rows, TRUE));
  strcat(disp, map_format(exit_string(ch, ch->in_room), y, bufs, &y, cols, rows, TRUE));
  strcat(disp, map_format(ch->in_room->description, y, bufs, &y, cols, rows,
  	  !IS_SET(ch->config, CONFIG_JUSTIFY)));
  if (y<MAP_Y)
  {
    x = disp+strlen(disp);
    while (y<MAP_Y)
      x += sprintf(x, "%s\n\r", bufs[y]), ++y;
  }
  send_to_char(disp, ch);
#ifdef ACK_43
  if (!IS_NPC(ch) && IS_SET(ch->config, CONFIG_FULL_ANSI))
  {
    sprintf(disp, "%s%i;%ir%s%i;%iH",
    	    CRS_CMD,
    	    0,
    	    ch->pcdata->term_rows-12,
    	    CRS_CMD,
    	    ch->pcdata->term_rows-13,
    	    0);
    send_to_char(disp, ch);
  }
#endif
  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;
  CHAR_DATA * victim;
  int door, looper;
  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;

/* displays seen mobs nearby as numbers */

  for ( looper = 0,victim = room->first_person;
        victim;
        victim = victim->next_in_room )
    if (  ( can_see( ch, victim ) )
       && ( !is_same_group( ch, victim ) ) )
      looper++;
  if ( looper > 0 )
    sprintf( contents[x][y].string, "%i@@N", UMIN( looper, 9 ) );
  else
    contents[x][y].string[0] = '\0';

  for ( door = 0; door < MAX_MAP_DIR; door++ ) 
  { /* cycles through for each exit */
    if (  ( (pexit = room->exit[door]) != NULL )
	     && ( pexit->to_room != NULL ) )

    { /* if exit there */
      if ((x<min)||(y<min)||(x>max)||(y>max)) return;

      prospect_room = pexit->to_room;
      if (  ( prospect_room->exit[rev_dir[door]] )
         && ( prospect_room->exit[rev_dir[door]]->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) )
      {
        if (  ( door == 0 )
           || ( door == 2 ) )
          door_type = DOOR_NS;
        else
          door_type = DOOR_EW;
      }
      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 ) )
               && ( !IS_SET( pexit->exit_info, EX_NODETECT ) )
               && ( ch->pcdata->learned[gsn_find_doors] > number_percent() ) 
               && ( !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->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 )
{
  void disp_map(char *border, char *map, CHAR_DATA *ch);
  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", "-" );
    safe_strcat( MSL, borderbuf, catbuf );
  }
  safe_strcat( MSL, borderbuf, "@@y+@@N" );
  for (x = min; x <= max; ++x) 
  { /* every row */

    safe_strcat( MSL, 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] ) ),
          ( ( 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] ) :
              ( ( contents[x][y].string[0] == '\0' ) ?
                get_sector_display(map[x][y] ) :
                contents[x][y].string )  )  );
        sprintf( catbuf, "%s%s", 
                 colorbuf, displaybuf );
        safe_strcat( MSL, outbuf, catbuf  );

      }
      else 
      {
        sprintf( catbuf, "%s", 
          (map[x][y]<=0) ?
          get_door_display( map[x][y] ) :
          get_sector_display(map[x][y]) );
        safe_strcat( MSL, outbuf, catbuf  );
      }

    }
    safe_strcat( MSL, outbuf, " @@W|@@N\n\r" );
  }

  disp_map(borderbuf, outbuf, ch);

/* NOTE: with your imp, probably put the three together into one string? */

  return;
}




/* mlk :: shows a map, specified by size */


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", "-" );
    safe_strcat( MSL, borderbuf, catbuf );
  }
  safe_strcat( MSL, borderbuf, "@@y+@@N" );
  for (x = min; x <= max; ++x) 
  { /* every row */

    safe_strcat( MSL, 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] ) ),
          ( ( 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] ) :
              ( ( contents[x][y].string[0] == '\0' ) ?
                get_sector_display(map[x][y] ) :
                contents[x][y].string )  )  );
        sprintf( catbuf, "%s%s", 
                 colorbuf, displaybuf );
        safe_strcat( MSL, outbuf, catbuf  );

      }
      else 
      {
        sprintf( catbuf, "%s", 
          (map[x][y]<=0) ?
          get_door_display( map[x][y] ) :
          get_sector_display(map[x][y]) );
        safe_strcat( MSL, outbuf, catbuf  );
      }

    }
    safe_strcat( MSL, 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 );
  /* this is the contents of the map */
  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;
}










void do_mapper( CHAR_DATA *ch, char *argument )
{
  int size,center,x,y,min,max,looper;
  char arg1[MSL];
  char catbuf[MSL];
  char outbuf[MSL];
 one_argument( argument, arg1 );
 if ( is_name( arg1, "legend key help" ) )
 {
   sprintf( outbuf, "@@WMap Legend:@@N\n\r" );
   for ( looper = 0; looper < SECT_TOP-1;looper++ )
   {
      sprintf( catbuf, "%s%s : @@N%s\n\r" , 
                map_info[looper].display_color,
                map_info[looper].display_code, 
                map_info[looper].desc );
      safe_strcat( MSL, 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 );
      safe_strcat( MSL, outbuf, catbuf );
   }
   send_to_char( outbuf, ch );
   return;
 }
 size = ( is_number(  arg1 ) ) ? 
         atoi (arg1) :
         11;

  if ( size != 7 )
  {
     size = IS_IMMORTAL( ch ) ? size :
       get_curr_int( ch )/2 + 
       ( ( !IS_NPC( ch ) ) ? ch->pcdata->learned[gsn_scout]/25 : 0 );
    if ( size % 2  == 0 )
      size +=1;
    size = URANGE( 9, size, MAX_MAP );
  }
 size=URANGE(3,size,MAX_MAP);

 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;
      contents[x][y].string[0] = '\0';
   }

/* starts the mapping with the center room */
  MapArea(ch->in_room, ch, center, center, min-1, max, LOS_INITIAL); 

/* marks the center, where ch is */
  sprintf( contents[center][center].string, "%s", "@@f*@@N" ); 
  if ( size == 7 )
    ShowRoom( ch, min, max, size, center ); 
  else
    ShowMap( ch, min, max, size, center );
  return;

}