/************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * 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. * * * * Much time and thought has gone into this software and you are * * benefiting. We hope that you share your changes too. What goes * * around, comes around. * *************************************************************************** * ROM 2.4 is copyright 1993-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * *************************************************************************** * 1stMud ROM Derivative (c) 2001-2004 by Markanth * * http://www.firstmud.com/ <markanth@firstmud.com> * * By using this code you have agreed to follow the term of * * the 1stMud license in ../doc/1stMud/LICENSE * ***************************************************************************/ #include "merc.h" char map_chars[5] = "|-|-"; char map_chars_closed[5] = "I=I="; char lcolor = 'x'; int depth = 0; #define MAXDEPTH 4 #define MAPX 10 #define MAPY 8 #define BOUNDARY(x, y) (((x) < 0) || ((y) < 0) || \ ((x) > (MAPX * 2)) || ((y) > (MAPY * 2))) \ struct map_type { char symbol; int depth; RoomIndex *pRoom; }; typedef struct map_type MAP_DATA; MAP_DATA map[(MAPX * 2) + 1][(MAPY * 2) + 1]; void get_exit_dir(int dir, int *x, int *y, int xorig, int yorig) { switch (dir) { case 0: *x = xorig; *y = yorig - 1; break; case 1: *x = xorig + 1; *y = yorig; break; case 2: *x = xorig; *y = yorig + 1; break; case 3: *x = xorig - 1; *y = yorig; break; default: *x = -1; *y = -1; break; } } void clear_coord(int x, int y) { map[x][y].symbol = ' '; map[x][y].depth = 0; map[x][y].pRoom = NULL; } struct sector_color_type { sector_t bit; const char *display_color; char display_symbol; }; const struct sector_color_type sector_color_table[SECT_MAX] = { { SECT_INSIDE, "{w", 'o'}, {SECT_CITY, "{W", 'o'}, {SECT_FIELD, "{G", '*'}, {SECT_FOREST, "{g", '*'}, {SECT_HILLS, "{y", '!'}, {SECT_MOUNTAIN, "{w", '@'}, {SECT_WATER_SWIM, "{B", '='}, {SECT_WATER_NOSWIM, "{b", '='}, {SECT_ICE, "{C", 'O'}, {SECT_AIR, "{C", '~'}, {SECT_DESERT, "{y", '+'}, {SECT_ROAD, "{m", ':'}, {SECT_PATH, "{M", ':'}, {SECT_SWAMP, "{G", '&'}, {SECT_CAVE, "{w", '#'}, {SECT_NONE, "{w", '?'} }; const char *get_sector_color(sector_t sector) { int looper; for (looper = 0; looper < SECT_MAX; looper++) if (sector_color_table[looper].bit == sector) return (sector_color_table[looper].display_color); return ""; } char get_sector_symbol(sector_t sector) { int looper; for (looper = 0; looper < SECT_MAX; looper++) if (sector_color_table[looper].bit == sector) return (sector_color_table[looper].display_symbol); return '?'; } void map_exits(CharData * ch, RoomIndex * pRoom, int x, int y) { int door; int exitx = 0, exity = 0; int roomx = 0, roomy = 0; ExitData *pExit; if (!can_see_room(ch, pRoom)) return; map[x][y].symbol = get_sector_symbol(pRoom->sector_type); map[x][y].depth = depth; map[x][y].pRoom = pRoom; if (depth >= MAXDEPTH) return; for (door = DIR_NORTH; door <= DIR_DOWN; door++) { if ((pExit = pRoom->exit[door]) == NULL) continue; if (IsSet(pExit->exit_info, EX_CLOSED)) continue; if (pExit->u1.to_room == NULL) continue; if (!can_see_room(ch, pExit->u1.to_room)) continue; get_exit_dir(door, &exitx, &exity, x, y); get_exit_dir(door, &roomx, &roomy, exitx, exity); if (BOUNDARY(exitx, exity) || BOUNDARY(roomx, roomy)) continue; if (depth == MAXDEPTH) continue; map[exitx][exity].depth = depth; if (IsSet(pExit->exit_info, EX_CLOSED)) map[exitx][exity].symbol = map_chars_closed[door]; else map[exitx][exity].symbol = map_chars[door]; map[exitx][exity].pRoom = pExit->u1.to_room; if ((depth < MAXDEPTH) && ((map[roomx][roomy].pRoom == pExit->u1.to_room) || (map[roomx][roomy].pRoom == NULL))) { depth++; map_exits(ch, pExit->u1.to_room, roomx, roomy); depth--; } } } char *erase_new_lines(const char *desc) { unsigned int l, m, sz; static char buf[MSL * 7]; char temp[MSL * 7]; if (NullStr(desc)) return ""; l = 0; m = 0; buf[0] = NUL; temp[0] = NUL; sz = strlen(desc); for (m = 0; m <= sz; m++) { if (desc[m] == '\n' || desc[m] == '\r') temp[m] = '\x20'; else temp[m] = desc[m]; } temp[m] = NUL; for (m = 0; temp[m] != NUL; m++) { if (temp[m] == '\x20' && temp[m + 1] == '\x20') { buf[l++] = ' '; do { m++; } while (temp[m] == '\x20'); } buf[l++] = temp[m]; } buf[l] = NUL; return buf; } size_t get_line_len(const char *desc, size_t max_len) { size_t m, l, sz; char buf[MSL]; if (NullStr(desc) || (sz = strlen(desc)) <= max_len) return 0; buf[0] = '\0'; l = 0; for (m = 0; m <= sz; m++) { if (desc[m] == COLORCODE) { int k = ansi_skip(&desc[m]); m += k; if (k == 1) lcolor = desc[m]; } else if (desc[m] == CUSTOMSTART) { do { m++; } while (desc[m] != CUSTOMEND); } else if (desc[m] == MXP_BEGc) { do { m++; } while (desc[m] != MXP_ENDc); } if (++l > max_len) break; } for (l = m; l > 0; l--) if (desc[l] == ' ') break; return l + 1; } void show_map(CharData * ch, const char *text, bool fSmall) { char buf[MSL * 2]; size_t x, y, m, n, pos; const char *p; bool alldesc = false; double rcnt = (double) (areacount(ch, ch->in_room->area)); double rooms = (double) (arearooms(ch->in_room->area)); int maxlen = get_scr_cols(ch); int maplen = maxlen - 15; if (fSmall) { m = 4; n = 5; } else { m = 0; n = 0; } pos = 0; p = text; buf[0] = '\0'; if (fSmall) { if (IsNPC(ch) || IsSet(ch->in_room->room_flags, ROOM_NOEXPLORE)) sprintf(buf, CTAG(_AUTOMAP) "+------------+{%c ", lcolor); else sprintf(buf, CTAG(_AUTOMAP) "+-----[{x%3.0f%%" CTAG(_AUTOMAP) "]+{%c ", Percent(rcnt, rooms), lcolor); if (!alldesc) { pos = get_line_len(p, maplen); if (pos > 0) { strncat(buf, p, pos); p += pos; } else { strcat(buf, p); alldesc = true; } } strcat(buf, NEWLINE); } for (y = m; y <= (MAPY * 2) - m; y++) { if (fSmall) strcat(buf, CTAG(_AUTOMAP) "|"); else strcat(buf, "{D"); for (x = n; x <= (MAPX * 2) - n; x++) { if (map[x][y].pRoom) { if (map[x][y].symbol == get_sector_symbol(map[x][y].pRoom->sector_type) && !IsNPC(ch) && StrIsSet(ch->pcdata->explored, map[x][y].pRoom->vnum)) { if (map[x][y].pRoom->exit[DIR_UP] && map[x][y].pRoom->exit[DIR_DOWN]) map[x][y].symbol = 'B'; else if (!map[x][y].pRoom->exit[DIR_UP] && map[x][y].pRoom->exit[DIR_DOWN]) map[x][y].symbol = 'D'; else if (map[x][y].pRoom->exit[DIR_UP] && !map[x][y].pRoom->exit[DIR_DOWN]) map[x][y].symbol = 'U'; } if (!fSmall) sprintf(buf + strlen(buf), " %s%c{D", get_sector_color(map[x][y].pRoom->sector_type), map[x][y].symbol); else sprintf(buf + strlen(buf), "%s%c", get_sector_color(map[x][y].pRoom->sector_type), map[x][y].symbol); } else { if (!fSmall) strcat(buf, " {D."); else strcat(buf, " "); } } if (!fSmall) { switch (y) { case 0: strcat(buf, " {xX You are here"); break; case 2: strcat(buf, " {xo Normal Rooms"); break; case 3: strcat(buf, " {xU Room with exit up"); break; case 4: strcat(buf, " {xD Room with exit down"); break; case 5: strcat(buf, " {xB Room with exits up & down"); break; case 6: strcat(buf, " {x|- Exits"); break; case 7: strcat(buf, " {x>I< Closed Doors"); break; case 8: strcat(buf, " {x* Field/Forest"); break; case 9: strcat(buf, " {x! Hills"); break; case 10: strcat(buf, " {x@ Mountain"); break; case 11: strcat(buf, " {x= Water"); break; case 12: strcat(buf, " {x~ Air"); break; case 13: strcat(buf, " {x+ Desert"); break; case 14: strcat(buf, " {x: Road/Path"); break; case 15: strcat(buf, " {x& Swamp"); break; case 16: strcat(buf, " {x# Cave"); break; case 17: strcat(buf, " {x? Unknown"); break; default: strcat(buf, " {x"); break; } strcat(buf, NEWLINE); } else { sprintf(buf + strlen(buf), CTAG(_AUTOMAP) "| {%c", lcolor); if (!alldesc) { pos = get_line_len(p, maplen); if (pos > 0) { strncat(buf, p, pos); p += pos; } else { strcat(buf, p); alldesc = true; } } strcat(buf, NEWLINE); } } if (!fSmall) chprintlnf(ch, "%s" NEWLINE "%s{x%s", draw_line(ch, NULL, 0), buf, draw_line(ch, NULL, 0)); else { sprintf(buf + strlen(buf), CTAG(_AUTOMAP) "+-----------+{%c ", lcolor); if (!alldesc) { pos = get_line_len(p, maplen); if (pos > 0) { strncat(buf, p, pos); p += pos; } else { strcat(buf, p); alldesc = true; } } if (!alldesc) { do { pos = get_line_len(p, maxlen); if (pos > 0) { strncat(buf, p, pos); p += pos; } else { strcat(buf, p); alldesc = true; } } while (!alldesc); } strcat(buf, "{x"); chprint(ch, buf); } } void draw_map(CharData * ch, const char *desc) { int x, y; const char *buf; bool fSmall; lcolor = 'x'; if (NullStr(desc)) { buf = desc; fSmall = false; } else { buf = erase_new_lines(desc); fSmall = true; } for (y = 0; y <= MAPY * 2; y++) { for (x = 0; x <= MAPX * 2; x++) { clear_coord(x, y); } } x = MAPX; y = MAPY; depth = (fSmall) ? 2 : 0; map_exits(ch, ch->in_room, x, y); map[x][y].symbol = 'X'; show_map(ch, buf, fSmall); } Do_Fun(do_automap) { if (IsNPC(ch)) return; set_on_off(ch, &ch->act, PLR_AUTOMAP, "You now see an automap in room descriptions.", "You no longer see automap room descriptions."); } Do_Fun(do_map) { if (IsNPC(ch)) return; if (!ch->in_room) return; if (!check_blind(ch)) return; draw_map(ch, NULL); return; }