#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; }