/**************************************************************************** * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// * * -----------------------------------------------------------| (0...0) * * SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by Derek Snider | ).:.( * * -----------------------------------------------------------| {o o} * * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ * * Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek, |~'~.VxvxV.~'~* * Tricops and Fireblade | * * ------------------------------------------------------------------------ * * v. 0.9: 6/19/95: Converts an ascii map to rooms. * * v. 1.0: 7/05/95: Read/write maps to .are files. Efficient storage. * * Room qualities based on map code. Can add & remove rms * * from a map. (Somewhat) intelligent exit decisions. * * v. 1.1: 7/11/95: Various display options. See comments over draw_map * * * ****************************************************************************/ #include <sys/types.h> #include <stdio.h> #include <string.h> #include <time.h> #include "mud.h" /* * Useful Externals */ extern int top_exit; void note_attach(CHAR_DATA * ch); /* * Local defines. Undef'ed at end of file. */ #define MID MAP_INDEX_DATA #define MD MAP_DATA #define RID ROOM_INDEX_DATA #define CD CHAR_DATA #define EDD EXTRA_DESCR_DATA #define OD OBJ_DATA #define OID OBJ_INDEX_DATA #define XD EXIT_DATA /* * Local function prototypes */ MID *make_new_map_index(int vnum); void map_to_rooms(CD * ch, MID * m_index); void map_stats(CD * ch, int *rooms, int *rows, int *cols); int num_rooms_avail(CD * ch); int add_new_room_to_map(CD * ch, MID * map, int row, int col, int proto_room, char code); int number_to_room_num(int array_index); int char_to_number(char code); int exit_lookup(int vnum1, int vnum2); void draw_map(CD * ch, RID * rm, int flag, int mode); char *you_are_here(int row, int col, char *map); char get_map_code(RID * room, int mode); /* * Local Variables & Structs */ char text_map[4150]; extern MID *first_map; /* should be global */ struct map_stuff { int vnum; int proto_vnum; int exits; int index; char code; }; /*************************************************************/ /* */ /* First section for read/write of map to .are files and */ /* on-line map editing, such as it is. */ /* */ /*************************************************************/ /* * Be careful not to give * this an existing map_index */ MID *make_new_map_index(int vnum) { MID *map_index; int i, j; CREATE(map_index, MID, 1); map_index->vnum = vnum; for (i = 0; i < 49; i++) { for (j = 0; j < 78; j++) { map_index->map_of_vnums[i][j] = -1; } } map_index->next = first_map; first_map = map_index; return map_index; } /* * output goes in global text_map * flag = 0, do a 'you_are_here' * flag = 1, don't * * * Modes : what characters mean : character set * -------------------------------------------------------------------- * 0: room code : 92 ascii chars, detailed elsewhere * 1: # of mobs : 0 thru 9, + * 2: # of pc's : 0 thru 9, + * 3: # of objs : 0 thru 9, + * 4: # of exits : 0 thru 6 * 5: sectortype : hex, 0 thru MAX_SECT * 6: light : 0 or 1 * 7: indoors : X or O * 8: death : X or O * 9: safe : X or O * 10: nosummon : X or O * 11: # of descr lines : 0 thru 9, + */ char *const map_opts[] = { "code", "mobs", "pcs", "objs", "exits", "sector", "light", "indoors", "death", "safe", "nosummon", "descr", "descrlines" }; char count_lines(char *txt) { int i; char *c, buf[MSL]; if (!txt) return (char) '0'; i = 1; for (c = txt; *c != '\0'; c++) if (*c == '\n') i++; if (i > 9) return (char) '+'; sprintf(buf, "%d", i); return (buf[0]); } char get_map_code(RID * room, int mode) { char buf[MSL]; CD *mob; OD *obj; int count /*, i */ ; /* Unused */ EXIT_DATA *pexit; if (!room) return (char) 'X'; count = 0; switch (mode) { case 11: return count_lines(room->description); case 10: if (xIS_SET(room->room_flags, ROOM_NO_SUMMON)) return (char) 'X'; return (char) 'O'; case 9: if (xIS_SET(room->room_flags, ROOM_SAFE)) return (char) 'X'; return (char) 'O'; case 8: if (xIS_SET(room->room_flags, ROOM_DEATH)) return (char) 'X'; return (char) 'O'; case 7: if (xIS_SET(room->room_flags, ROOM_INDOORS)) return (char) 'X'; return (char) 'O'; case 6: sprintf(buf, "%d", room->light); return (buf[0]); case 5: sprintf(buf, "%d", room->sector_type); return (buf[0]); case 4: for (pexit = room->first_exit; pexit; pexit = pexit->next) count++; sprintf(buf, "%d", count); return (buf[0]); case 3: for (obj = room->first_content; obj; obj = obj->next_content) count++; if (count > 9) return (char) '+'; sprintf(buf, "%d", count); return (buf[0]); case 2: for (mob = room->first_person; mob; mob = mob->next_in_room) { if (!IS_NPC(mob)) count++; } if (count > 9) return (char) '+'; sprintf(buf, "%d", count); return (buf[0]); case 1: for (mob = room->first_person; mob; mob = mob->next_in_room) { if (IS_NPC(mob)) count++; } if (count > 9) return (char) '+'; sprintf(buf, "%d", count); return (buf[0]); default: if (!room->map) return (char) 'X'; return ((char) room->map->entry); } return (char) '?'; } void draw_map(CD * ch, RID * rm, int flag, int mode) { MID *map_index; RID *tmp_rm; int i, x, y, nontriv; if (!rm->map) { sprintf(text_map, "(no rm->map)\n\r"); return; } if ((map_index = get_map_index(rm->map->vnum)) == NULL) { bug(" No map_index with vnum %d\n\r", rm->map->vnum); sprintf(text_map, "-ERROR-\n\r"); return; } i = 0; nontriv = 0; for (y = 0; y < 49; y++) { for (x = 0; x < 78; x++) { if (map_index->map_of_vnums[y][x] < 1) { text_map[i] = ' '; i++; continue; } /* tmp_rm = map_index -> map_of_ptrs[y][x]; */ tmp_rm = get_room_index(map_index->map_of_vnums[y][x]); if (tmp_rm == NULL) { text_map[i] = ' '; i++; continue; } if (!tmp_rm->map) { text_map[i] = ' '; i++; continue; } /* * Following's kinda convoluted... If ch has ansi, * bold the code of the room he's in. If not, indicate * room he's in by '*' */ if ((flag == 1)) { if (map_index->map_of_vnums[y][x] == ch->in_room->vnum) { if (xIS_SET(ch->act, PLR_ANSI)) { text_map[i] = (char) '\x1B'; /* Bold */ i++; text_map[i] = (char) '['; i++; text_map[i] = (char) '1'; i++; text_map[i] = (char) 'm'; i++; /*text_map[i] = (char) tmp_rm -> map -> entry; */ text_map[i] = (char) get_map_code(tmp_rm, mode); i++; text_map[i] = (char) '\x1B'; /* Normal */ i++; text_map[i] = (char) '['; i++; text_map[i] = (char) '0'; i++; text_map[i] = (char) 'm'; i++; } else { text_map[i] = (char) '*'; i++; } } else { text_map[i] = (char) get_map_code(tmp_rm, mode); /*text_map[i] = (char) tmp_rm -> map -> entry; */ i++; } } else { text_map[i] = (char) get_map_code(tmp_rm, mode); /*text_map[i] = (char) tmp_rm -> map -> entry; */ i++; } nontriv = i; } text_map[i] = '\n'; i++; } text_map[nontriv + 2] = '\n'; text_map[nontriv + 3] = '\r'; text_map[nontriv + 4] = '\0'; } MID *get_map_index(int vnum) { MID *map; for (map = first_map; map; map = map->next) { if (map->vnum == vnum) return map; } return NULL; } void init_maps() { int i; /* for (map_index = first_map; map_index; map_index = map_index -> next) { for (i = 0; i < 49; i++) { for (j = 0; j < 78; j++) { map_index -> map_of_ptrs[i][j] = get_room_index (map_index -> map_of_vnums[i][j]); } } } */ for (i = 0; i < 49 * 78; i++) text_map[i] = '\0'; return; } /****************************************************************** * These functions convert maps to rooms ******************************************************************/ void map_stats(CD * ch, int *rooms, int *rows, int *cols) { int row, col, n; int leftmost, rightmost; char *l, c; if (!ch->pnote) { bug("map_stats: ch->pnote==NULL!", 0); return; } n = 0; row = col = 0; leftmost = rightmost = 0; l = ch->pnote->text; do { c = l[0]; switch (c) { case '\n': break; case '\r': col = 0; row++; break; case ' ': col++; break; } if (char_to_number(c) > -1) { if (col < leftmost) leftmost = col; if (col > rightmost) rightmost = col; col++; n++; }; l++; } while (c != '\0'); *cols = rightmost - leftmost + 1; *rows = row; /* [sic.] */ *rooms = n; } int get_mode(char *type) { int x; for (x = 0; x < 12; x++) if (!str_cmp(type, map_opts[x])) return x; return -1; } void do_lookmap(CD * ch, char *argument) { char arg1[MSL]; char buf[MSL]; int mode; if (ch->in_room->map) { if (!argument) { mode = 0; } else { argument = one_argument(argument, arg1); mode = get_mode(arg1); } set_char_color(AT_PLAIN, ch); sprintf(buf, ".------[Map %5.5d]-----------------------------------------------------------.\n\r", ch->in_room->map->vnum); send_to_char(buf, ch); draw_map(ch, ch->in_room, 1, mode); send_to_char(text_map, ch); sprintf(buf, "`----------------------------------------------------------------------------'\n\r"); send_to_char(buf, ch); } else { send_to_char("You see no map here.\n\r", ch); } return; } void do_mapout(CD * ch, char *argument) { char buf[MSL]; char arg[MIL]; char arg1[MIL]; char arg2[MIL]; char arg3[MIL]; /* growl */ char arg4[MIL]; /* rediculous */ OD *map_obj; /* an obj made with map as an ed */ OID *map_obj_index; /* obj_index for previous */ EDD *ed; /* the ed for it to go in */ MID *map_index; /* the "vnum" of map_index to use */ MD *map, *tmp; /* for new per-room map info to goin */ RID *this_rm, *tmp_r = NULL; /* room ch is standing in */ XD *tmp_x; /* exit data */ char code; int rooms, rows, /* ints for stats & looping */ cols, row, col, mapnum, x, y, avail_rooms; if (!ch) { bug("do_mapout: null ch", 0); return; } if (IS_NPC(ch)) { send_to_char("Not in mobs.\n\r", ch); return; } if (!ch->desc) { bug("do_mapout: no descriptor", 0); return; } switch (ch->substate) { default: break; case SUB_WRITING_NOTE: if (ch->dest_buf != ch->pnote) bug("do_mapout: sub_writing_map: ch->dest_buf != ch->pnote", 0); STRFREE(ch->pnote->text); ch->pnote->text = copy_buffer(ch); stop_editing(ch); return; } set_char_color(AT_NOTE, ch); argument = one_argument(argument, arg); smash_tilde(argument); if (!str_cmp(arg, "stat")) { if (!ch->pnote) { send_to_char("You have no map in progress.\n\r", ch); return; } map_stats(ch, &rooms, &rows, &cols); sprintf(buf, "Map represents %d rooms, and has %d rows and %d columns\n\r", rooms, rows, cols); send_to_char(buf, ch); avail_rooms = num_rooms_avail(ch); sprintf(buf, "You currently have %d unused rooms.\n\r", avail_rooms); send_to_char(buf, ch); act(AT_ACTION, "$n glances at an etherial map.", ch, NULL, NULL, TO_ROOM); return; } /* * Adds an existing room to a map */ if (!str_cmp(arg, "continue")) { if (ch->prev_cmd == do_north) { send_to_char("Your last command was north.\n\r", ch); argument = one_argument(argument, arg1); if ((arg1[0] == '\0')) { code = '#'; } else { code = arg1[0]; } tmp = NULL; tmp_x = get_exit(ch->in_room, DIR_SOUTH); if (tmp_x) tmp_r = tmp_x->to_room; if (tmp_r) tmp = tmp_r->map; if (!tmp) { send_to_char("No exit to south, or no map in south room. Aborting. \n\r", ch); return; } row = (tmp->y) - 1; col = (tmp->x); if (row < 0) { send_to_char("Can't map off the top of the buffer.\n\r", ch); return; } if (row > 48) { send_to_char("Can't map off the bottom of the buffer.\n\r", ch); return; } mapnum = tmp->vnum; if ((map_index = get_map_index(mapnum)) == NULL) { sprintf(buf, "Trouble accessing map.(No such map?).\n\r"); send_to_char(buf, ch); return; } sprintf(buf, "addroom %d %d %d %c", mapnum, row, col, code); do_mapout(ch, buf); return; } if (ch->prev_cmd == do_east) { send_to_char("Your last command started was east\n\r", ch); argument = one_argument(argument, arg1); if ((arg1[0] == '\0')) { code = '#'; } else { code = arg1[0]; } tmp = NULL; tmp_x = get_exit(ch->in_room, DIR_WEST); if (tmp_x) tmp_r = tmp_x->to_room; if (tmp_r) tmp = tmp_r->map; if (!tmp) { send_to_char("No exit to west, or no map in west room. Aborting. \n\r", ch); return; } row = (tmp->y); col = (tmp->x) + 1; if (col < 0) { send_to_char("Can't map off the left of the buffer.\n\r", ch); return; } if (row > 78) { send_to_char("Can't map off the right of the buffer.\n\r", ch); return; } mapnum = tmp->vnum; if ((map_index = get_map_index(mapnum)) == NULL) { sprintf(buf, "Trouble accessing map.(No such map?).\n\r"); send_to_char(buf, ch); return; } sprintf(buf, "addroom %d %d %d %c", mapnum, row, col, code); do_mapout(ch, buf); return; } if (ch->prev_cmd == do_south) { send_to_char("Your last command was south\n\r", ch); argument = one_argument(argument, arg1); if ((arg1[0] == '\0')) { code = '#'; } else { code = arg1[0]; } tmp = NULL; tmp_x = get_exit(ch->in_room, DIR_NORTH); if (tmp_x) tmp_r = tmp_x->to_room; if (tmp_r) tmp = tmp_r->map; if (!tmp) { send_to_char("No exit to north, or no map in north room. Aborting. \n\r", ch); return; } row = (tmp->y) + 1; col = (tmp->x); if (row < 0) { send_to_char("Can't map off the top of the buffer.\n\r", ch); return; } if (row > 48) { send_to_char("Can't map off the bottom of the buffer.\n\r", ch); return; } mapnum = tmp->vnum; if ((map_index = get_map_index(mapnum)) == NULL) { sprintf(buf, "Trouble accessing map.(No such map?).\n\r"); send_to_char(buf, ch); return; } sprintf(buf, "addroom %d %d %d %c", mapnum, row, col, code); do_mapout(ch, buf); return; } if (ch->prev_cmd == do_west) { send_to_char("Your last command was west\n\r", ch); argument = one_argument(argument, arg1); if ((arg1[0] == '\0')) { code = '#'; } else { code = arg1[0]; } tmp = NULL; tmp_x = get_exit(ch->in_room, DIR_EAST); if (tmp_x) tmp_r = tmp_x->to_room; if (tmp_r) tmp = tmp_r->map; if (!tmp) { send_to_char("No exit to east, or no map in east room. Aborting. \n\r", ch); return; } row = (tmp->y); col = (tmp->x) - 1; if (col < 0) { send_to_char("Can't map off the left of the buffer.\n\r", ch); return; } if (row > 78) { send_to_char("Can't map off the right of the buffer.\n\r", ch); return; } mapnum = tmp->vnum; if ((map_index = get_map_index(mapnum)) == NULL) { sprintf(buf, "Trouble accessing map.(No such map?).\n\r"); send_to_char(buf, ch); return; } sprintf(buf, "addroom %d %d %d %c", mapnum, row, col, code); do_mapout(ch, buf); return; } sprintf(buf, "Your previous command was something I cannot backtrack..\n\r"); send_to_char(buf, ch); return; } /* * Adds an existing room to a map */ if (!str_cmp(arg, "addroom")) { argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); argument = one_argument(argument, arg3); argument = one_argument(argument, arg4); mapnum = atoi(arg1); /* i don't like this */ y = atoi(arg2); x = atoi(arg3); if ((arg1[0] == '\0') || (arg2[0] == '\0') || (arg3[0] == '\0')) { send_to_char("Syntax: \n\r", ch); send_to_char("mapout addroom <mapnum> <row> <col> [code]\n\r", ch); send_to_char(" \n\r", ch); send_to_char("where: <mapnum> is the vnum of map to use\n\r", ch); send_to_char(" <row> is row of room (start 0)\n\r", ch); send_to_char(" <col> is col of room (start 0)\n\r", ch); send_to_char(" [code] is optional room character code \n\r", ch); return; } if ((arg4[0] == '\0')) { code = '#'; } else { code = arg4[0]; } if ((map_index = get_map_index(mapnum)) == NULL) { #ifdef HURM sprintf(buf, "Trouble accessing map.(No such map?).\n\r"); send_to_char(buf, ch); return; #endif map_index = make_new_map_index(mapnum); if (map_index == NULL) { send_to_char("Could neither find nor make a map index with that number.\n\r", ch); return; } } this_rm = ch->in_room; if (this_rm->map != NULL) { sprintf(buf, "This room (vnum %d) is already in map %d.\n\r", ch->in_room->vnum, ch->in_room->map->vnum); send_to_char(buf, ch); return; } if ((x < 0) || (x > 78)) { sprintf(buf, "Bad map x coordinate. Room(vnum %d), x= %d \n\r", ch->in_room->vnum, x); send_to_char(buf, ch); return; } if ((y < 0) || (y > 48)) { sprintf(buf, "Bad map y coordinate. Room(vnum %d), y= %d \n\r", ch->in_room->vnum, y); send_to_char(buf, ch); return; } if (map_index->map_of_vnums[y][x] != -1) { sprintf(buf, "That (x,y) coordinate (%d, %d) is already taken by room %d.\n\r", x, y, map_index->map_of_vnums[y][x]); send_to_char(buf, ch); return; } /* all error checking done */ CREATE(map, MAP_DATA, 1); map->vnum = mapnum; map->x = x; map->y = y; map->entry = code; ch->in_room->map = map; map_index->map_of_vnums[y][x] = ch->in_room->vnum; send_to_char("Added.\n\r", ch); return; } /* * Removes a room from a map */ if (!str_cmp(arg, "removeroom")) { this_rm = ch->in_room; if (!this_rm->map) { sprintf(buf, "This room (vnum %d) is in no map \n\r", ch->in_room->vnum); send_to_char(buf, ch); return; } if ((map_index = get_map_index(this_rm->map->vnum)) == NULL) { sprintf(buf, "Trouble accessing map room(vnum %d), map vnum %d \n\r", ch->in_room->vnum, this_rm->map->vnum); send_to_char(buf, ch); return; } if ((this_rm->map->x < 0) || (this_rm->map->x > 78)) { sprintf(buf, "Bad map x coordinate. Room(vnum %d), x= %d \n\r", ch->in_room->vnum, this_rm->map->x); send_to_char(buf, ch); return; } if ((this_rm->map->y < 0) || (this_rm->map->y > 48)) { sprintf(buf, "Bad map y coordinate. Room(vnum %d), y= %d \n\r", ch->in_room->vnum, this_rm->map->y); send_to_char(buf, ch); return; } /* now that all that's out of the way.... */ sprintf(buf, "Removing room (vnum %d), from map %d \n\r", ch->in_room->vnum, this_rm->map->vnum); send_to_char(buf, ch); /* Thanks to Nick Gammon for pointing out x and y being uninitialized. -Thoric */ x = this_rm->map->x; y = this_rm->map->y; map_index->map_of_vnums[y][x] = -1; this_rm->map->vnum = 0; this_rm->map->x = -1; this_rm->map->y = -1; this_rm->map->entry = ' '; DISPOSE(this_rm->map); this_rm->map = NULL; /* redundant? */ send_to_char("Removed.\n\r", ch); return; } if (!str_cmp(arg, "write")) { note_attach(ch); ch->substate = SUB_WRITING_NOTE; ch->dest_buf = ch->pnote; start_editing(ch, ch->pnote->text); set_editor_desc(ch, "A map description"); return; } if (!str_cmp(arg, "clear")) { if (ch->pnote) { STRFREE(ch->pnote->text); STRFREE(ch->pnote->subject); STRFREE(ch->pnote->to_list); STRFREE(ch->pnote->date); STRFREE(ch->pnote->sender); DISPOSE(ch->pnote); } ch->pnote = NULL; send_to_char("Map cleared.\n\r", ch); return; } if (!str_cmp(arg, "show")) { if (!ch->pnote) { send_to_char("You have no map in progress.\n\r", ch); return; } /* send_to_char(buf, ch); */ send_to_char(ch->pnote->text, ch); do_mapout(ch, "stat"); return; } if (!str_cmp(arg, "redo")) { if (!ch->pnote) { send_to_char("You have no map in progress.\n\r", ch); return; } send_to_char("This option not yet supported.\n\r", ch); return; } if (!str_cmp(arg, "create")) { if (!ch->pnote) { send_to_char("You have no map in progress.\n\r", ch); return; } map_stats(ch, &rooms, &rows, &cols); avail_rooms = num_rooms_avail(ch); /* check for not enough rooms */ if (rooms > avail_rooms) { send_to_char("You don't have enough unused rooms allocated!\n\r", ch); return; } act(AT_ACTION, "$n warps the very dimensions of space!", ch, NULL, NULL, TO_ROOM); map_to_rooms(ch, NULL); /* this does the grunt work */ map_obj_index = get_obj_index(5013); if (!map_obj_index) { map_obj = create_object(map_obj_index, 0); ed = SetOExtra(map_obj, "runes map scrawls"); STRFREE(ed->description); ed->description = QUICKLINK(ch->pnote->text); obj_to_char(map_obj, ch); } else { send_to_char("Couldn't give you a map object. Need Great Eastern Desert\n\r", ch); return; } do_mapout(ch, "clear"); send_to_char("Ok.\n\r", ch); return; } send_to_char("mapout write: create a map in edit buffer.\n\r", ch); send_to_char("mapout stat: get information about a written, but not yet created map.\n\r", ch); send_to_char("mapout clear: clear a written, but not yet created map.\n\r", ch); send_to_char("mapout show: show a written, but not yet created map.\n\r", ch); send_to_char("mapout create: turn a written map into rooms in your assigned room vnum range.\n\r", ch); return; } int add_new_room_to_map(CD * ch, MID * map, int row, int col, int proto_room, char code) { int i; char buf[MSL]; RID *location, *rm; /* * Get a room to copy from */ rm = get_room_index(proto_room); if (!rm) rm = ch->in_room; /* * Get an unused room to copy to */ for (i = ch->pcdata->r_range_lo; i <= ch->pcdata->r_range_hi; i++) { if (get_room_index(i) == NULL) { location = make_room(i); if (!location) { bug("next_rooms_avail: make_room failed", 0); return -1; } /* * Clones current room (quietly) */ location->area = ch->pcdata->area; location->name = QUICKLINK(rm->name); location->description = QUICKLINK(rm->description); CREATE(location->map, MAP_DATA, 1); location->map->vnum = map->vnum; /* not working? */ location->map->x = col; location->map->y = row; location->map->entry = code; /* location -> room_flags = ROOM_PROTOTYPE && rm -> room_flags; */ location->light = rm->light; location->sector_type = rm->sector_type; return i; } } sprintf(buf, "No available room!\n\r"); send_to_char(buf, ch); return -1; } int num_rooms_avail(CD * ch) { int i, n; n = 0; for (i = ch->pcdata->r_range_lo; i <= ch->pcdata->r_range_hi; i++) if (!get_room_index(i)) n++; return n; } /* * This function takes the character string in ch->pnote and * creates rooms laid out in the appropriate configuration. */ void map_to_rooms(CD * ch, MID * m_index) { struct map_stuff map[49][78]; /* size of edit buffer */ int row, col, i, n, x, y, tvnum, proto_vnum, leftmost, rightmost; char *l, c; RID *newrm; MID *map_index = NULL, *tmp; XD *xit; /* these are for exits */ int exit_type; if (!ch->pnote) { bug("map_to_rooms: ch->pnote==NULL!", 0); return; } n = 0; row = col = 0; leftmost = rightmost = 0; /* * Check to make sure map_index exists. * If not, then make a new one. */ if (!m_index) { /* Make a new vnum */ for (i = ch->pcdata->r_range_lo; i <= ch->pcdata->r_range_hi; i++) { if ((tmp = get_map_index(i)) == NULL) { map_index = make_new_map_index(i); break; } } } else { map_index = m_index; } /* */ if (!map_index) { send_to_char("Couldn't find or make a map_index for you!\n\r", ch); bug("map_to_rooms: Couldn't find or make a map_index\n\r", 0); /* do something. return failed or somesuch */ } for (x = 0; x < 49; x++) { for (y = 0; y < 78; y++) { map[x][y].vnum = 0; map[x][y].proto_vnum = 0; map[x][y].exits = 0; map[x][y].index = 0; } } l = ch->pnote->text; do { c = l[0]; switch (c) { case '\n': break; case '\r': col = 0; row++; break; case ' ': col++; break; } if ((map[row][col].index = char_to_number(c)) > -1) { proto_vnum = number_to_room_num(map[row][col].index); map[row][col].vnum = add_new_room_to_map(ch, map_index, row, col, proto_vnum, c); map_index->map_of_vnums[row][col] = map[row][col].vnum; map[row][col].proto_vnum = proto_vnum; map[row][col].code = c; col++; n++; } else { map_index->map_of_vnums[row][col] = 0; map[row][col].vnum = 0; map[row][col].exits = 0; } l++; } while (c != '\0'); for (y = 0; y < row + 1; y++) { /* rows */ for (x = 0; x < 78; x++) { /* cols (78, i think) */ if (map[y][x].vnum == 0) continue; newrm = get_room_index(map[y][x].vnum); CREATE(newrm->map, MAP_DATA, 1); newrm->map->vnum = map_index->vnum; newrm->map->x = x; newrm->map->y = y; newrm->map->entry = map[y][x].code; /* * Check north */ if (y > 0) { if ((tvnum = map[y - 1][x].vnum) != 0) { exit_type = exit_lookup(map[y][x].proto_vnum, map[y - 1][x].proto_vnum); if (exit_type > -1) { xit = make_exit(newrm, get_room_index(tvnum), DIR_NORTH); xit->keyword = STRALLOC(""); xit->description = STRALLOC(""); xit->key = -1; xit->exit_info = exit_type; } } } /* east */ if (x < 79) { if ((tvnum = map[y][x + 1].vnum) != 0) { exit_type = exit_lookup(map[y][x].proto_vnum, map[y][x + 1].proto_vnum); if (exit_type > -1) { xit = make_exit(newrm, get_room_index(tvnum), DIR_EAST); xit->keyword = STRALLOC(""); xit->description = STRALLOC(""); xit->key = -1; xit->exit_info = exit_type; } } } /* south */ if (y < 48) { if ((tvnum = map[y + 1][x].vnum) != 0) { exit_type = exit_lookup(map[y][x].proto_vnum, map[y + 1][x].proto_vnum); if (exit_type > -1) { xit = make_exit(newrm, get_room_index(tvnum), DIR_SOUTH); xit->keyword = STRALLOC(""); xit->description = STRALLOC(""); xit->key = -1; xit->exit_info = exit_type; } } } /* west */ if (x > 0) { if ((tvnum = map[y][x - 1].vnum) != 0) { exit_type = exit_lookup(map[y][x].proto_vnum, map[y][x - 1].proto_vnum); if (exit_type > -1) { xit = make_exit(newrm, get_room_index(tvnum), DIR_WEST); xit->keyword = STRALLOC(""); xit->description = STRALLOC(""); xit->key = -1; xit->exit_info = exit_type; } } } } } } /****************************************************************** * Constants & constant-like functions follow ******************************************************************/ char *const standard_room_names[] = { "Hut", "Tent", "Hovel", "Campsite", "Shack", "Cabin", "Homested", "Keep", "Fortress", "Castle", "GuardHse", "Temple", "Store", "Graveyard", "Monastry", "Stable", "Tavern", "Basemnt", "Bedroom", "BnquetRm", "Corridor", "Attic", "Vault", "SittingRm", "Study", "Passage", "Tower", "Crypt", "WorkRoom", "Lab", "Hallway", "Turret", "StorRm", "Kitchen", "Larder", "Stairway", "Rooftop", "Closet", "Office", "Treasury", "Landing", "Balcony", "Foyer", "DrawingRm", "Den", "Ladder", "Catwalk", "Entrnce", "Arboretum", "Library", "Vent", "Shaft", "Gate", "AudiencRm", "Consrvty", "DumbWatr", "Chimney", "Porch", "ClassRoom", "CloakRm", "Lawn", "Garden", "Lake", "Forest", "Swamp", "Well", "Street", "River", "Canyon", "Beach", "Mine", "Road", "Stream", "Clearing", "SnakePit", "Tunnel", "Path", "Rapids", "Desert", "SandStrm", "Rope", "Cliff", "CaveRiv", "Jungle", "Sandbar", "RopeBrdg", "Bridge", "CaveLak", "Cave", "None", "RopeLadr", "NatlBrdg" }; int const standard_room_vnums[] = { 9500, 9501, 9502, 9503, 9504, 9505, 9506, 9507, 9508, 9509, 9510, 9511, 9512, 9513, 9514, 9515, 9516, 9517, 9518, 9519, 9520, 9521, 9522, 9523, 9524, 9525, 9526, 9527, 9528, 9529, 9530, 9531, 9532, 9533, 9534, 9535, 9536, 9537, 9538, 9539, 9540, 9541, 9542, 9543, 9544, 9545, 9546, 9547, 9548, 9549, 9550, 9551, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9581, 9582, 9583, 9584, 9585, 9586, 9587, 9588, 9589, 9590, 9591 }; /* * Picks an entry from standard_room_vnums[], checking * that it's legal */ int number_to_room_num(int array_index) { if ((array_index < 0) || (array_index > 91)) return 2; return standard_room_vnums[array_index]; } /* * Attempts to intellignetly determineif two adjecent rooms should * be linked with an exit, and if so, what kind. * * This fn _depends_ on standard_room_vnums[] to make decisions. */ int exit_lookup(int vnum1, int vnum2) { int sect1, sect2; ROOM_INDEX_DATA *rm1, *rm2; int exit_flag; rm1 = get_room_index(vnum1); rm2 = get_room_index(vnum2); if ((!rm1) || (!rm2)) { bug("bad room index in exit_lookup!\n\r", 0); return (0); } exit_flag = 0; sect1 = rm1->sector_type; sect2 = rm2->sector_type; if (rm1 == rm2) /* adjacent rooms with same std_rm_vnum */ return 0; /* assume they're simply linked */ if ((vnum1 == 9589) || (vnum2 == 9589)) return 0; /* if 'none,' no assumptions */ if ((sect1 == SECT_INSIDE) && (sect2 != SECT_INSIDE)) { switch (vnum1) { case 9500: /* hut *//* these are almost always */ case 9501: /* tent *//* single-roomed buildings */ case 9502: /* hovel *//* so let them be open on */ case 9504: /* shack *//* all sides -- user fixes */ case 9505: /* cabin */ case 9506: /* homestd */ case 9510: /* guardhse */ case 9511: /* temple */ case 9512: /* store */ case 9515: /* stable */ case 9516: /* tavern */ return 0; case 9542: /* foyer *//* these are always closed drs */ case 9547: /* entrance */ return 3; default: exit_flag = -1; } } if ((sect2 == SECT_INSIDE) && (sect1 != SECT_INSIDE)) { switch (vnum2) { case 9500: /* hut *//* these are almost always */ case 9501: /* tent *//* single-roomed buildings */ case 9502: /* hovel *//* so let them be open on */ case 9504: /* shack *//* all sides -- user fixes */ case 9505: /* cabin */ case 9506: /* homestd */ case 9510: /* guardhse */ case 9511: /* temple */ case 9512: /* store */ case 9515: /* stable */ case 9516: /* tavern */ return 0; case 9542: /* foyer *//* these are always closed drs */ case 9547: /* entrance */ return 3; default: exit_flag = -1; } } /* * Can look at these cases again * */ if ((sect1 == SECT_CITY) && (sect2 != SECT_CITY)) { switch (vnum1) { case 9511: /* temple *//* these are always open */ case 9512: /* store */ case 9516: /* tavern */ return 0; case 9552: /* gate *//* these are always closed drs */ case 9547: return 3; default: exit_flag = -1; } } if ((sect2 == SECT_CITY) && (sect1 != SECT_CITY)) { switch (vnum2) { case 9511: /* temple *//* these are always open */ case 9512: /* store */ case 9516: /* tavern */ return 0; case 9552: /* gate *//* these are always closed drs */ case 9547: return 3; default: exit_flag = -1; } } return exit_flag; } /* * Given a character 'code' in a map, returns the location * of the corresponding room vnum in the constant array * standard_room_vnums. If 'code' is illegal, it returns * -1. To lookup the corresponding room vnum, call * number_to_room_num on value returned here. */ int char_to_number(char code) { switch (code) { case 'a': return 0; case 'b': return 1; case 'c': return 2; case 'd': return 3; case 'e': return 4; case 'f': return 5; case 'g': return 6; case 'h': return 7; case 'i': return 8; case 'j': return 9; case 'k': return 10; case 'l': return 11; case 'm': return 12; case 'n': return 13; case 'o': return 14; case 'p': return 15; case 'q': return 16; case 'r': return 17; case 's': return 18; case 't': return 19; case 'u': return 20; case 'v': return 21; case 'w': return 22; case 'x': return 23; case 'y': return 24; case 'z': return 25; case 'A': return 26; case 'B': return 27; case 'C': return 28; case 'D': return 29; case 'E': return 30; case 'F': return 31; case 'G': return 32; case 'H': return 33; case 'I': return 34; case 'J': return 35; case 'K': return 36; case 'L': return 37; case 'M': return 38; case 'N': return 39; case 'O': return 40; case 'P': return 41; case 'Q': return 42; case 'R': return 43; case 'S': return 44; case 'T': return 45; case 'U': return 46; case 'V': return 47; case 'W': return 48; case 'X': return 49; case 'Y': return 50; case 'Z': return 51; case '0': return 52; case '1': return 53; case '2': return 54; case '3': return 55; case '4': return 56; case '5': return 57; case '6': return 58; case '7': return 59; case '8': return 60; case '9': return 61; case '!': return 62; case '@': return 63; case '#': return 64; case '$': return 65; case '%': return 66; case '^': return 67; case '&': return 68; case '*': return 69; case '(': return 70; case ')': return 71; case '-': return 72; case '_': return 73; case '+': return 74; case '=': return 75; case '|': return 76; /* case '\\': return 77; */ /* case '~': return 78; */ case '`': return 79; case '{': return 80; case '[': return 81; case '}': return 82; case ']': return 83; case ':': return 84; case '"': return 85; case '\'': return 86; case '<': return 87; case ',': return 88; case '>': return 89; case '.': return 90; case '?': return 91; default: return -1; } } #undef MID #undef MD #undef RID #undef CD #undef EDD #undef OD #undef OID #undef XD