mud/cnf/
mud/lib/
mud/lib/etc/boards/
mud/lib/house/
mud/lib/misc/
mud/lib/plralias/ZZZ/
mud/lib/plrfiles/
mud/lib/plrfiles/ZZZ/
mud/lib/plrobjs/
mud/lib/plrobjs/ZZZ/
mud/lib/world/
mud/lib/world/gld/
mud/lib/world/mob/
mud/lib/world/obj/
mud/lib/world/shp/
mud/lib/world/trg/
mud/lib/world/wld/
mud/lib/world/zon/
mud/src/
mud/src/doc/
#include "conf.h"
#include "sysdep.h"

#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "interpreter.h"
#include "handler.h"
#include "db.h"
#include "spells.h"
#include "house.h"
#include "constants.h"
#include "dg_scripts.h"

#define MAX_MAP 72
#define MAX_MAP_DIR 10
#define SECT_MAX 30
#define CONFIG_DEFAULT_MAP_SIZE	20

extern struct room_data *world;
extern int default_map_size;
int add_to_save_list(zone_vnum zone, int type);
int can_edit_zone(struct char_data *ch, int number);

int map[MAX_MAP][MAX_MAP];
int offsets[10][2] ={ {-1, 0},{ 0, 1},{ 1, 0},{ 0, -1},{0, 0},{0, 0},{-1,-1},{-1,1},{1,1},{1,-1} };

/* 
 * WARNING: When dealing with x and y variables throughout here, ignore the concept
 * of a graph.  KEY: x = vertical, and y = horizontal changes.  -kyse
 */

/* Heavily modified - Edward */
void MapArea(room_rnum room, struct char_data *ch, int x, int y, int min, int max)
{
  room_rnum prospect_room;
  struct room_direction_data *pexit;
  int door;

  /* marks the room as visited */
  map[x][y] = world[room].sector_type;
  
  for (door = 0; door < MAX_MAP_DIR; door++) {
    if ((pexit = world[room].dir_option[door]) > 0 && /* Exit exists       */ 
        //(pexit->to_room > 0) &&                     /* Bad if vnum is 0  */
        (pexit->to_room != NOWHERE) &&                /* Vnum exists       */
	(!IS_SET(pexit->exit_info, EX_CLOSED))) {     /* Door isn't closed */

      /* Stop if coordinates are too low or high */
      if ((x < min) || (y < min) || (x > max) || (y > max))
        return;
      
      prospect_room = pexit->to_room;

      /* one way into area OR maze, if not two way */	
      if (!(world[prospect_room].dir_option[rev_dir[door]]) ||
         (world[prospect_room].dir_option[rev_dir[door]] && 
          world[prospect_room].dir_option[rev_dir[door]]->to_room != room)) { 
        map[x+offsets[door][0]][y+offsets[door][1]] = SECT_MAX + 1;
      return;
      }
      /* end two way */
      
      /* 
       * Players cant see past these sectors
       * I'd like to set it where each sector type has a certain
       * amount of rooms they can see through before it cuts off.
       * Commented out for now untill I can work a little more on
       * this task. -kyse
       */
      //if ((world[prospect_room].sector_type == SECT_CITY) ||
      //    (world[prospect_room].sector_type == SECT_HILLS) ||
      //  (world[prospect_room].sector_type == SECT_INSIDE)) { 


      if (map[x+offsets[door][0]][y+offsets[door][1]] == SECT_MAX &&
         (prospect_room != room) &&
	 !((x+offsets[door][0]) < min) && 
	 !((y+offsets[door][1]) < min) &&
	 !((x+offsets[door][0]) > max) &&
	 !((x+offsets[door][1]) > max)) {
        MapArea(pexit->to_room,ch,x + offsets[door][0], y + offsets[door][1], min, max);
      } /* end if exit there */
    } else {
      continue;
    }
  }
  return;
}

/* mlk :: shows a map, specified by size */
/* This function is currently unused by any function in the mud. */
void ShowMap(struct char_data* ch, int min, int max)
{
  int x, y;

  /* every row */
  for (x = (min-1); x < max; ++x) { 
    /* every column */
    for (y = min; y < max; ++y) { 
      
      if ((y==min) || (map[x][y-1]!=map[x][y])) {
        switch(map[x][y]) {
        case SECT_MAX:		 send_to_char(ch," ");		break;
	case SECT_FOREST:	 send_to_char(ch,"@g@");	break;
	case SECT_FIELD:	 send_to_char(ch,"@G.");	break;
	case SECT_HILLS:	 send_to_char(ch,"@G^");	break;
	case SECT_MOUNTAIN:	 send_to_char(ch,"@W^");	break;
	case SECT_WATER_SWIM:    send_to_char(ch,"@B.");	break;
	case SECT_WATER_NOSWIM:  send_to_char(ch,"@b.");	break;
	case SECT_INSIDE:	 send_to_char(ch,"@W#");	break;
	case SECT_CITY:	      	 send_to_char(ch,"@WC");	break;
	case (SECT_MAX+1):	 send_to_char(ch,"@D?");	break;
	default: 		 send_to_char(ch,"@R*");	break;
	}
      } else {
        switch(map[x][y]) {
	case SECT_MAX:		 send_to_char(ch," ");		break;
	case SECT_FOREST:	 send_to_char(ch,"@");		break;
	case SECT_FIELD:	 send_to_char(ch,".");		break;
	case SECT_HILLS:	 send_to_char(ch,"^");		break;
	case SECT_MOUNTAIN:	 send_to_char(ch,"^");		break;
	case SECT_WATER_SWIM:    send_to_char(ch,".");		break;
	case SECT_WATER_NOSWIM:  send_to_char(ch,".");		break;
	case SECT_INSIDE:	 send_to_char(ch,"#");		break;
	case SECT_CITY:		 send_to_char(ch,"C");		break;
	case (SECT_MAX+1):	 send_to_char(ch,"?");		break;
	default: 		 send_to_char(ch,"*");		break;
        } 
      }
    }
    send_to_char(ch,"\n\r"); 
  }
  return;
}


/* This is for simplicities sake, if the room's name is
** like An unfinished room, it will replace it with a fake
** room name here - Edward */

void get_room_name(struct char_data *ch, int argument)
{
  char buf[500];
  switch(argument) {
    case SECT_MAX:
      sprintf(buf,"&n   &cThe Wilderness&n");		break;
    case SECT_FOREST:
      sprintf(buf,"&n   &cWithin a Forest&n");		break;
    case SECT_FIELD:
      sprintf(buf,"&n   &cOn an Open Field&n");		break;
    case SECT_HILLS:
      sprintf(buf,"&n   &cOn a Hill&n");		break;
    case SECT_MOUNTAIN:
      sprintf(buf,"&n   &cClimbing a Mountain&n");	break;
    case SECT_WATER_SWIM:
      sprintf(buf,"&n   &cIn Shallow Water&n");		break;
    case SECT_WATER_NOSWIM:
      sprintf(buf,"&n   &cAdrift In Deep Water&n");	break;
    case SECT_INSIDE:
      sprintf(buf,"&n   &cThe Wilderness&n");		break;
    case SECT_CITY:
      sprintf(buf,"&n   &cWithin a City&n");		break;
    case (SECT_MAX+1):
      sprintf(buf,"&n   &cThe Wilderness&n");		break;
    default:
      sprintf(buf,"&n   &cThe Wilderness&n");		break;
  }
  send_to_char(ch, buf);
}

/* 
 * will put a small map with current room desc and title
 * this is the main function to show the map, its do_map with " "
 */ 

/* Heavily modified - Edward */
void ShowRoom(struct char_data *ch, int min, int max, int dirarg)
{
  int x, y;
  int desccount = 0;
  int cccount = 0;
  char desc[1000];
  char descline[100];
  int dispalrdy = 0;
  int maxlnlng = 80;
  int desclinelng = 0;
  int c1 = 0;
  int c2 = 0;
  int c3 = 0;
  char *spacepos;
  char *colorpos;
  char colorchar[2];
  int diropt = 0;
  int show_desc = 0;
  
  /* Copy the room description into desc */
  /* Add options for the room description for when they look to another room to get that next room's desc instead */
  
  if (dirarg == 0) {
    if (!ROOM_FLAGGED(ch->in_room, ROOM_SHOW_DESC)) {
      show_desc = 1;
      strcpy(desc, world[ch->in_room].description);
      colorchar[0] = 'n';
      /* remove all \r and \n characters in the room description string */
      for (c1 = 0; c1 <= strlen(desc); c1++) { // Loop for the whole length of the description
        if (desc[c1] == '\r' || desc[c1] == '\n') { // If we find a character in the desc we don't want
          if (desc[c1+1] == '\r' || desc[c1+1] == '\n') { // Usually these two characters are combined with each other.
            desc[c1] = ' ';
          } else {
            memmove(desc+c1, desc+c1+1, strlen(desc)-c1);
          }
          c1--;
        }
      }
    }
  } else {
    diropt = dirarg-1;
    if (ROOM_FLAGGED(EXIT(ch, diropt)->to_room, ROOM_SHOW_DESC)) {
      show_desc = 1;
      strcpy(desc, world[EXIT(ch, diropt)->to_room].description);
      colorchar[0] = 'n';
      for (c1 = 0; c1 <= strlen(desc); c1++) {
        if (desc[c1] == '\r' || desc[c1] == '\n') {
	  if (desc[c1+1] == '\r' || desc[c1+1] == '\n') {
	    desc[c1] = ' ';
	  } else {
	    memmove(desc+c1, desc+c1+1, strlen(desc)-c1);
	  }
	  c1--;
	}
      }
    }
  }



  /* mlk :: rounds edges */

  /* 
   * Is it worth rounding off the edges when the character
   * is only viewing a small amount of the map (during the
   * nighttime for instance)? Just a thought. -Kyse
   */

  //map[min][min]=SECT_MAX;map[max-1][max-1]=SECT_MAX;
  //map[min][max-1]=SECT_MAX;map[max-1][min]=SECT_MAX;
  
  /* enter top row of border for map */
  x=min;
  for (y = min; y <= (max-1); ++y) { /* loop to get the full top row */
    if (y==min) {               /* if the top row coord is the very left side, send the color code */
      send_to_char(ch,"@W(@Y*@W)");
    } else {
      if (y==(max-1)) {
        send_to_char(ch,"(@Y*@W)@n"); /* send right side of top border */
      } else {
        send_to_char(ch,"-");     /* send normal border for the rest of the row */
      }
    }
  }
  send_to_char(ch,"\n\r");      /* send the new line after the border */

  /* every row */
  for (x = min; x < max; ++x) { 
    /* every column */
    for (y = min; y < max; ++y) { 
      /* send left side of border */
      if (y==min) {
        send_to_char(ch,"@W |");
      }
      if ((y==min) || (map[x][y-1]!=map[x][y])) {
        switch(map[x][y]) {
	case SECT_MAX:		 send_to_char(ch," ");		break;
	case SECT_FOREST:	 send_to_char(ch,"@g@");	break;
	case SECT_FIELD:	 send_to_char(ch,"@G.");	break;
	case SECT_HILLS:	 send_to_char(ch,"@G^");	break;
	case SECT_MOUNTAIN:	 send_to_char(ch,"@W^");	break;
	case SECT_WATER_SWIM:	 send_to_char(ch,"@B.");	break;
	case SECT_WATER_NOSWIM:  send_to_char(ch,"@b.");	break;
	case SECT_INSIDE:	 send_to_char(ch,"@W#");	break;
	case SECT_CITY:		 send_to_char(ch,"@WC");	break;
	case (SECT_MAX+1):	 send_to_char(ch,"@D?");	break;
	default: 		 send_to_char(ch,"@R*");	break;
        } 	
      } else {
        switch(map[x][y]) {
	case SECT_MAX:		 send_to_char(ch," ");		break;
	case SECT_FOREST:	 send_to_char(ch,"@");		break;
	case SECT_FIELD:	 send_to_char(ch,".");		break;
	case SECT_HILLS:	 send_to_char(ch,"^");		break;
	case SECT_MOUNTAIN:	 send_to_char(ch,"^");		break;
	case SECT_WATER_SWIM:	 send_to_char(ch,".");		break;
	case SECT_WATER_NOSWIM:	 send_to_char(ch,".");		break;
	case SECT_INSIDE:	 send_to_char(ch,"#");		break;
	case SECT_CITY:		 send_to_char(ch,"C");		break;
	case (SECT_MAX+1):	 send_to_char(ch,"?");		break;
	default:		 send_to_char(ch,"*");		break;
 	}
      }
      /* send right side of border */
      if (y==(max-1)) {
        send_to_char(ch,"@W|@n ");
	
	/* Send Description Line Here */
        if (show_desc == 1) {
          if (dispalrdy < strlen(desc)) {
	    desclinelng = maxlnlng-(max-min+4);
	    for (desccount = dispalrdy; desccount < (dispalrdy+desclinelng); desccount++) {
	      if (desc[desccount] == '@') {
	        cccount++; // cccount is the number of color codes in the desc line.
	        desclinelng = (desclinelng+2);
	      }	    
	    }
	    strncpy(descline, desc+dispalrdy, (desclinelng)); // Copy the description line
	    descline[desclinelng] = '\0';
	    spacepos = strrchr(descline, ' ');
	    c2 = descline - spacepos;
	    if (c2 < 0){
	      c2 *= -1;
	    }
	    if (c2 > strlen(descline)) {
	      c2 = 0;
	    }
	    descline[c2] = '\0';
	    if (descline[0] == ' ') {
	      memmove(descline, descline+1, (strlen(descline)));
	      dispalrdy += 1;
	    }
	    if (colorchar[0] != 'n') {
	      send_to_char(ch, "@%s", colorchar);
	      send_to_char(ch, "%s", descline);
	    } else {
	      send_to_char(ch, "%s", descline);
	    }
	    dispalrdy += strlen(descline); // Add the count of color codes to the displayed already number for the next loop.
	  
	    colorpos = strrchr(descline, '@');
	    c3 = descline - colorpos;
	    if (c3 < 0){
	      c3 *= -1;
	    }
	    if (c3 <= strlen(descline)) {
	      if (descline[c3+1] == 'n'){
	        colorchar[0] = 'n';
	        colorchar[1] = '\0';
	      } else {
	        colorchar[0] = descline[c3+1];
	        colorchar[1] = '\0';
	      }
            }
	  }
	}
	send_to_char(ch, "\n\r");
      }
    }

 /*   if (x == min) {
  *    if (!strcmp(world[ch->in_room].name, "The Wilderness") ||
  *        !strcmp(world[ch->in_room].name, "An unfinished room")) {
  *      get_room_name(ch, world[ch->in_room].sector_type);
  *    } else {
  *      sprintf(buf," ");
  *      send_to_char(ch, buf);
  */    }

   /*
    * if (GET_LEVEL(ch) >= LVL_IMMORT) {
    *   sprintf(buf," @c[@RRoom @Y%d@c]@n", world[ch->in_room].number);
    *   send_to_char(ch, buf);
    * }
    * } */

// Description removed from ansi map, map is descriptive enough
// just remove the commends if you want them back. -Edward
/*
 * else {
 *     start = str_pos;
 *     for (desc_pos = desc_pos ; desc[desc_pos]!='\0' ; desc_pos++) { 
 *       if (desc[desc_pos]=='\n') {
 *         line[str_pos-start]='\0';
 *         str_pos += 3;
 *         desc_pos += 2;
 *        break;
 *      }
 *       else if (desc[desc_pos]=='\r') {
 *    line[str_pos-start]='\0'
 *    str_pos += 2;
 *	    break;
 *      } else {
 *	    line[str_pos-start]=desc[desc_pos];
 *	    str_pos += 1;
 *	  }
 *     }
 *     line[str_pos-start]='\0';
 *     if (x == min + 1) send_to_char("  ", ch);
 *     send_to_char("   &c", ch);
 *     send_to_char(line, ch);
 *     send_to_char("&n",ch);
 *}
 *   send_to_char(ch,"\n\r"); 
 * }
 */

    /* enter bottom row of border for map */
    x=min;
    for (y=min;y <= (max-1); ++y) {
      if (y==min) {
        send_to_char(ch,"@W(@Y*@W)");
      } else {
        if (y==(max-1)) {
          send_to_char(ch,"(@Y*@W)@n");
        } else {
          send_to_char(ch,"-");
        }
      }
    }
  send_to_char(ch,"\n\r");  /* puts a line between contents/people */
  return;
}

/* This is the main map function, do_map(ch, " ") is good to use */
/* do_map(ch "number") is for immortals to see the world map     */

/* Edward: If you play with some of the values here you can make the normal
** map people see larger or smaller. size = URANGE(9, size, MAX_MAP), the 9
** is the map size shown by default. Also look for: ShowMap (ch, min, max+1);
** and change the size of min and max and see what you like.
*/
void do_map(struct char_data *ch, char *argument)
{
  //struct room_direction_data *pexit;
  int size, center, x, y, min, max;
  char arg1[10], dirarg[10];
  one_argument(argument, arg1);
  size = atoi(arg1);
  size = MAPS(CONFIG_DEFAULT_MAP_SIZE, 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_MAX;

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

  /* marks the center, where ch is */
  // map[center][center] = SECT_MAX+2;  
  /* can be any number above SECT_MAX+1 	*/
  /* switch default will print out the *	*/


  /* Fix this up to perform more specific to flags */
  if ((GET_LEVEL(ch) < LVL_IMMORT)||(IS_NPC(ch))) {
    /* Directional look needs to map area respectively */

    MapArea(ch->in_room, ch, center, center, min-1, max-1);
    map[center][center] = SECT_MAX+2;
    if ( IS_DARK(ch->in_room) ) {
      send_to_char(ch, "@bThe wilderness is pitch black at night... @n\n\r");
      return;
    } else {
      /* Add daylight/nighttime variables for size here */
      ShowRoom(ch,MAX_MAP/2-3,MAX_MAP/2+4, 0);
      return;
    }
  }
  /* mortals not in city, enter or inside will always get a ShowRoom */

  if (GET_LEVEL(ch) >= LVL_IMMORT) {
    if (arg1[0] == '\0') {
      MapArea(ch->in_room, ch, center, center, min-1, max+1);
      map[center][center] = SECT_MAX+2;
      ShowRoom (ch, min, max+1, 0); 
    } else {
      sprintf (dirarg, "%s", arg1);
      // 0=north, 1=east, 2=south, 3=west
      if (strcmp(dirarg, "0") == 0) {
        //do mapstuff for looking north.
	MapArea(ch->in_room, ch, center+1, center, min-1, max+1);
	map[center+1][center] = SECT_MAX+2;
	ShowRoom (ch, min, max+1, 1);
      }
      if (strcmp(dirarg, "1") == 0) {
        //do mapstuff for looking east.
	MapArea(ch->in_room, ch, center, center-1, min-1, max+1);
	map[center][center-1] = SECT_MAX+2;
	ShowRoom (ch, min, max+1, 2);
      }
      if (strcmp(dirarg, "2") == 0) {
        //do mapstuff for looking south.
	MapArea(ch->in_room, ch, center-1, center, min-1, max+1);
	map[center-1][center] = SECT_MAX+2;
	ShowRoom (ch, min, max+1, 3);
      }
      if (strcmp(dirarg, "3") == 0) {
        //do mapstuff for looking west.
	MapArea(ch->in_room, ch, center, center+1, min-1, max+1);
	map[center][center+1] = SECT_MAX+2;
	ShowRoom (ch, min, max+1, 4);
      }
      // add more arguments for other directions here
    }
    return;
  }
   send_to_char(ch,"@CHuh?&n\n\r");
   return;
}