/****************************************************************************** * TinTin++ * * Copyright (C) 2004 (See CREDITS file) * * * * This program is protected under the GNU GPL (See COPYING) * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ******************************************************************************/ /****************************************************************************** * (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t * * * * coded by Igor van den Hoven 2004 * ******************************************************************************/ #include "tintin.h" /* todo: */ void create_legend(struct session *ses, char *arg); int map_grid_x; int map_grid_y; int map_grid_z; struct session * map_search_ses; struct exit_data * map_search_exit_best; struct exit_data * map_search_exit_node; int map_search_last_room; int map_search_max_size; int map_search_tar_room; #define MAP_SEARCH_SIZE 500 /* MUD font #map legend {128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 161} #map legend {144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 161} */ unsigned char map_palet0[] = { 42, 35, 35, 43, 35,124, 43, 43, 35, 43, 45, 43, 43, 43, 43, 43, 120}; unsigned char map_palet1[] = {126,247,247,109,247,120,108,116,247,106,113,118,107,117,119,110, 88}; DO_COMMAND(do_map) { int cnt; char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE]; arg = get_arg_in_braces(arg, arg1, FALSE); if (*arg1 == 0) { tintin_printf2(ses, "Available map options"); tintin_printf2(ses, ""); tintin_printf2(ses, "#map at <location> {command> (execute command at given location)"); tintin_printf2(ses, "#map color <field> <color> (set the color for given field)"); tintin_printf2(ses, "#map create [size] (creates the initial map)"); tintin_printf2(ses, "#map destroy (destroys the map)"); tintin_printf2(ses, "#map delete <direction> (delete the room at given dir)"); tintin_printf2(ses, "#map dig <direction> [new] [vnum] (creates a new room)"); tintin_printf2(ses, "#map exit <direction> <command> (sets the exit command)"); tintin_printf2(ses, "#map exitflag <direction> <exit flag> (set the exit direction)"); tintin_printf2(ses, "#map explore <direction> (saves path to #path)"); tintin_printf2(ses, "#map info (info on map and current room)"); tintin_printf2(ses, "#map insert <direction> [room flag] (insert a new room)"); tintin_printf2(ses, "#map jump <x> <y> (go to given coordinate)"); tintin_printf2(ses, "#map find <location> [exits] (saves path to #path)"); tintin_printf2(ses, "#map flag <map flag> (set map wide flags)"); tintin_printf2(ses, "#map get <option> <variable> (get various values)"); tintin_printf2(ses, "#map goto <location> [exits] (moves you to given room)"); tintin_printf2(ses, "#map leave (leave the map, return with goto)"); tintin_printf2(ses, "#map legend <symbols> (sets the map legend)"); tintin_printf2(ses, "#map link <direction> <room name> (links 2 rooms)"); tintin_printf2(ses, "#map list <location> (shows list of matching rooms)"); tintin_printf2(ses, "#map map <radius> (shows an ascii map)"); tintin_printf2(ses, "#map name <room name> (set the room's name)"); tintin_printf2(ses, "#map read <filename> (load your map from a file)"); tintin_printf2(ses, "#map resize <size> (resize the maximum size)"); tintin_printf2(ses, "#map roomflag <room flag> (set room based flags)"); tintin_printf2(ses, "#map set <option> <value> (set various values)"); tintin_printf2(ses, "#map return (return to last room.)"); tintin_printf2(ses, "#map run <location> <delay> (run to given room)"); tintin_printf2(ses, "#map travel <direction> <delay> (run in given direction)"); tintin_printf2(ses, "#map undo (undo last move)"); tintin_printf2(ses, "#map uninsert <direction> (opposite of insert)"); tintin_printf2(ses, "#map unlink <direction> [both] (deletes an exit)"); tintin_printf2(ses, "#map write <filename> (save the map to a file)"); return ses; } else { for (cnt = 0 ; *map_table[cnt].name ; cnt++) { if (is_abbrev(arg1, map_table[cnt].name)) { if (map_table[cnt].check > 0 && ses->map == NULL) { tintin_printf2(ses, "#MAP: This session has no map data. Use #map create or #map read to create one."); return ses; } if (map_table[cnt].check > 1 && ses->map->room_list[ses->map->in_room] == NULL) { tintin_printf2(ses, "#MAP: You are not inside the map. Use #map goto to enter it."); return ses; } *arg1 = *arg2 = 0; map_table[cnt].map (ses, arg, arg1, arg2); break; } } if (*map_table[cnt].name == 0) { do_map(ses, ""); return ses; } if (ses->map && HAS_BIT(ses->map->flags, MAP_FLAG_VTMAP)) { SET_BIT(ses->flags, SES_FLAG_UPDATEVTMAP); } } return ses; } DO_MAP(map_at) { int new_room, old_room; arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_NONE); new_room = find_room(ses, arg1); if (new_room == -1) { show_message(ses, -1, "#MAP AT: Couldn't find room {%s}.", arg1); return; } old_room = ses->map->in_room; ses->map->in_room = new_room; script_driver(ses, -1, arg2); if (ses->map) { ses->map->in_room = old_room; } } DO_MAP(map_color) { arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN); if (*arg1 && is_abbrev(arg1, "ROOMS")) { RESTRING(ses->map->room_color, arg2); } else if (*arg1 && is_abbrev(arg1, "EXITS")) { RESTRING(ses->map->exit_color, arg2); } else if (*arg1 && is_abbrev(arg1, "PATHS")) { RESTRING(ses->map->path_color, arg2); } else { tintin_printf2(ses, "#SYNTAX: #MAP COLOR {EXIT|PATH|ROOM} {COLOR CODE}"); return; } show_message(ses, -1, "#MAP: %s color set to: %s", arg1, arg2); } DO_MAP(map_create) { arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN); create_map(ses, arg1); tintin_printf2(ses, "#MAP: %d room map created, use #map goto 1, to proceed", ses->map->size); } DO_MAP(map_delete) { int room; struct exit_data *exit; arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN); if (is_number(arg1)) { room = find_room(ses, arg1); if (room == -1) { tintin_printf2(ses, "#MAP: No room with that vnum found"); return; } } else { exit = find_exit(ses, ses->map->in_room, arg1); if (exit) { room = exit->vnum; } if (exit == NULL) { tintin_printf2(ses, "#MAP: No exit with that name found"); return; } room = exit->vnum; } if (room == ses->map->in_room) { tintin_printf2(ses, "#MAP: You must first leave the room you're trying to delete"); return; } delete_room(ses, room, TRUE); show_message(ses, -1, "#MAP: Room {%d} deleted", room); } DO_MAP(map_destroy) { delete_map(ses); tintin_printf2(ses, "#MAP: Map destroyed."); } DO_MAP(map_dig) { int room; char temp[BUFFER_SIZE]; struct exit_data *exit; struct listnode *node; arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN); if (*arg1 == 0) { tintin_printf2(ses, "#SYNTAX: #MAP DIG {<DIRECTION>} {NEW|<VNUM>}"); return; } for (room = 1 ; room < ses->map->size ; room++) { if (ses->map->room_list[room] == NULL) { break; } } exit = find_exit(ses, ses->map->in_room, arg1); if (exit) { show_message(ses, -1, "#MAP DIG: There is already a room in that direction."); return; } if (room == ses->map->size) { tintin_printf2(ses, "#MAP DIG: Maximum amount of rooms of %d reached.", ses->map->size); return; } if (is_number(arg2)) { room = atoi(arg2); if (room <= 0 || room >= ses->map->size) { tintin_printf2(ses, "#MAP DIG: Invalid room vnum: %d.", room); return; } if (ses->map->room_list[room] == NULL) { sprintf(temp, "{%d} {0} {} {%d} { }", room, room); create_room(ses, temp); } sprintf(temp, "{%d} {%s} {%s}", room, arg1, arg1); create_exit(ses, ses->map->in_room, temp); return; } if (strcasecmp(arg2, "new") && find_coord(ses, arg1)) { room = map_search_tar_room; show_message(ses, -1, "#MAP CREATE LINK %5d {%s}.", room, ses->map->room_list[room]->name); } else { sprintf(temp, "{%d} {0} {} {%d} { }", room, room); create_room(ses, temp); } sprintf(temp, "{%d} {%s} {%s}", room, arg1, arg1); create_exit(ses, ses->map->in_room, temp); if ((node = search_node_list(ses->list[LIST_PATHDIR], arg1)) != NULL) { if (find_exit(ses, room, node->right) == NULL) { sprintf(temp, "{%d} {%s} {%s}", ses->map->in_room, node->right, node->right); create_exit(ses, room, temp); } } } DO_MAP(map_exit) { char arg3[BUFFER_SIZE]; struct exit_data *exit; struct listnode *node; int room; arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg3, GET_ONE, SUB_VAR|SUB_FUN); exit = find_exit(ses, ses->map->in_room, arg1); if (exit == NULL) { tintin_printf2(ses, "#MAP: Exit {%s} not found.", arg1); return; } if (*arg2 == 0) { tintin_printf2(ses, " command: %s", exit->cmd); tintin_printf2(ses, "direction: %d", exit->dir); tintin_printf2(ses, " flags: %d", exit->flags); tintin_printf2(ses, " name: %s", exit->name); tintin_printf2(ses, " vnum: %d", exit->vnum); } else if (is_abbrev(arg2, "COMMAND")) { exit->cmd = restring(exit->cmd, arg3); show_message(ses, -1, "#MAP EXIT {%s} : COMMAND SET TO {%s}.", arg1, exit->cmd); } else if (is_abbrev(arg2, "DIRECTION")) { if ((node = search_node_list(ses->list[LIST_PATHDIR], arg3)) == NULL) { show_message(ses, -1, "#MAP EXIT {%s} : DIRECTION {%s} NOT FOUND.", arg1, arg3); return; } exit->dir = atoi(node->pr); show_message(ses, -1, "#MAP EXIT {%s} : DIRECTION SET TO {%s}.", arg1, arg3); } else if (is_abbrev(arg2, "FLAGS")) { exit->flags = atoi(arg3); show_message(ses, -1, "#MAP EXIT {%s} : FLAGS SET TO {%d}.", arg1, exit->flags); } else if (is_abbrev(arg2, "NAME")) { exit->name = restring(exit->name, arg3); show_message(ses, -1, "#MAP EXIT {%s} : NAME SET TO {%s}.", arg1, exit->name); } else if (is_abbrev(arg2, "VNUM")) { room = atoi(arg3); if (room <= 0 || room >= ses->map->size) { tintin_printf2(ses, "#MAP EXIT VNUM: Invalid room vnum: %d.", room); return; } if (ses->map->room_list[room] == NULL) { tintin_printf2(ses, "#MAP EXIT VNUM: Non existant room vnum: %d.", room); return; } exit->vnum = room; show_message(ses, -1, "#MAP EXIT {%s} : VNUM SET TO {%s}.", arg1, arg3); } else { tintin_printf2(ses, "Syntax: #MAP EXIT {<NAME>} {COMMAND|DIRECTION|NAME|FLAGS|VNUM} {<argument>}"); } } DO_MAP(map_exitflag) { struct exit_data *exit; char arg3[BUFFER_SIZE]; int flag; arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg3, GET_ONE, SUB_VAR|SUB_FUN); exit = find_exit(ses, ses->map->in_room, arg1); if (exit == NULL) { tintin_printf2(ses, "#MAP: Exit {%s} not found.", arg1); return; } if (*arg2) { if (is_abbrev(arg2, "hide")) { flag = EXIT_FLAG_HIDE; } else { tintin_printf2(ses, "#MAP: Invalid exit flag {%s}.", arg2); return; } } else { tintin_printf2(ses, "#MAP: Hide flag is set to %s.", HAS_BIT(exit->flags, EXIT_FLAG_HIDE) ? "on" : "off"); return; } if (is_abbrev("on", arg3)) { SET_BIT(exit->flags, flag); } else if (is_abbrev("off", arg3)) { DEL_BIT(exit->flags, flag); } else { TOG_BIT(exit->flags, flag); } if (is_abbrev(arg2, "hide")) { show_message(ses, -1, "#MAP: Hide flag set to %s.", HAS_BIT(exit->flags, EXIT_FLAG_HIDE) ? "on" : "off"); } } DO_MAP(map_explore) { arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN); explore_path(ses, FALSE, arg1, ""); } DO_MAP(map_find) { shortest_path(ses, FALSE, arg1, arg); } DO_MAP(map_flag) { int flag = 0, unflag = 0; arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN); if (*arg1) { if (is_abbrev(arg1, "static")) { flag = MAP_FLAG_STATIC; } else if (is_abbrev(arg1, "vtgraphics")) { flag = MAP_FLAG_VTGRAPHICS; unflag = MAP_FLAG_MUDFONT|MAP_FLAG_ASCIIGRAPHICS; } else if (is_abbrev(arg1, "vtmap")) { flag = MAP_FLAG_VTMAP; } else if (is_abbrev(arg1, "asciigraphics")) { flag = MAP_FLAG_ASCIIGRAPHICS; unflag = MAP_FLAG_MUDFONT|MAP_FLAG_VTGRAPHICS; } else if (is_abbrev(arg1, "asciivnums")) { flag = MAP_FLAG_ASCIIVNUMS; } else if (is_abbrev(arg1, "mudfont")) { flag = MAP_FLAG_MUDFONT; unflag = MAP_FLAG_ASCIIGRAPHICS|MAP_FLAG_VTGRAPHICS; } else if (is_abbrev(arg1, "nofollow")) { flag = MAP_FLAG_NOFOLLOW; } else { tintin_printf2(ses, "#MAP: Invalid flag {%s}.", arg1); return; } } else { tintin_printf2(ses, "#MAP: Static flag is set to %s.", HAS_BIT(ses->map->flags, MAP_FLAG_STATIC) ? "on" : "off"); tintin_printf2(ses, "#MAP: VTmap flag is set to %s.", HAS_BIT(ses->map->flags, MAP_FLAG_VTMAP) ? "on" : "off"); tintin_printf2(ses, "#MAP: VTgraphics flag is set to %s.", HAS_BIT(ses->map->flags, MAP_FLAG_VTGRAPHICS) ? "on" : "off"); tintin_printf2(ses, "#MAP: AsciiGraphics flag is set to %s.", HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIGRAPHICS) ? "on" : "off"); tintin_printf2(ses, "#MAP: AsciiVnums flag is set to %s.", HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIVNUMS) ? "on" : "off"); tintin_printf2(ses, "#MAP: NoFollow flag is set to %s.", HAS_BIT(ses->map->flags, MAP_FLAG_NOFOLLOW) ? "on" : "off"); return; } if (is_abbrev("on", arg2)) { SET_BIT(ses->map->flags, flag); } else if (is_abbrev("off", arg2)) { DEL_BIT(ses->map->flags, flag); } else { TOG_BIT(ses->map->flags, flag); } if (unflag) { DEL_BIT(ses->map->flags, unflag); } if (is_abbrev(arg1, "static")) { show_message(ses, -1, "#MAP: Static flag set to %s.", HAS_BIT(ses->map->flags, MAP_FLAG_STATIC) ? "on" : "off"); } else if (is_abbrev(arg1, "vtgraphics")) { show_message(ses, -1, "#MAP: VTgraphics flag set to %s.", HAS_BIT(ses->map->flags, MAP_FLAG_VTGRAPHICS) ? "on" : "off"); } else if (is_abbrev(arg1, "vtmap")) { show_message(ses, -1, "#MAP: VTmap flag set to %s.", HAS_BIT(ses->map->flags, MAP_FLAG_VTMAP) ? "on" : "off"); show_vtmap(ses); } else if (is_abbrev(arg1, "asciigraphics")) { show_message(ses, -1, "#MAP: AsciiGraphics flag set to %s.", HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIGRAPHICS) ? "on" : "off"); } else if (is_abbrev(arg1, "asciivnums")) { show_message(ses, -1, "#MAP: AsciiVnums flag set to %s.", HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIVNUMS) ? "on" : "off"); } else if (is_abbrev(arg1, "mudfont")) { show_message(ses, -1, "#MAP: MudFont flag set to %s.", HAS_BIT(ses->map->flags, MAP_FLAG_MUDFONT) ? "on" : "off"); } else if (is_abbrev(arg, "nofollow")) { show_message(ses, -1, "#MAP: NoFollow flag set to %s.", HAS_BIT(ses->map->flags, MAP_FLAG_NOFOLLOW) ? "on" : "off"); ses->map->nofollow = HAS_BIT(ses->map->flags, MAP_FLAG_NOFOLLOW) ? 1 : 0; } } DO_MAP(map_get) { struct room_data *room = ses->map->room_list[ses->map->in_room]; struct exit_data *exit; char buf[BUFFER_SIZE], arg3[BUFFER_SIZE]; arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg3, GET_ALL, SUB_VAR|SUB_FUN); if (*arg3) { if (atoi(arg3) > 0 && atoi(arg3) < ses->map->size) { room = ses->map->room_list[atoi(arg3)]; } else { room = NULL; } } if (room == NULL) { set_nest_node(ses->list[LIST_VARIABLE], arg2, "0"); } else if (*arg1 == 0 || *arg2 == 0) { tintin_printf2(ses, " roomvnum: %d", room->vnum); tintin_printf2(ses, " roomarea: %s", room->area); tintin_printf2(ses, " roomcolor: %s", room->color); tintin_printf2(ses, " roomdesc: %s", room->desc); tintin_printf2(ses, " roomexits: %d", get_map_exits(ses, room->vnum)); tintin_printf2(ses, " roomflags: %d", room->flags); tintin_printf2(ses, " roomname: %s", room->name); tintin_printf2(ses, " roomnote: %s", room->note); tintin_printf2(ses, "roomsymbol: %s", room->symbol); tintin_printf2(ses, "worldflags: %d", ses->map->flags); tintin_printf2(ses, " worldsize: %d", ses->map->size); } else { if (is_abbrev(arg1, "roomarea")) { set_nest_node(ses->list[LIST_VARIABLE], arg2, "%s", room->area); } else if (is_abbrev(arg1, "roomcolor")) { set_nest_node(ses->list[LIST_VARIABLE], arg2, "%s", room->color); } else if (is_abbrev(arg1, "roomdesc")) { set_nest_node(ses->list[LIST_VARIABLE], arg2, "%s", room->desc); } else if (is_abbrev(arg1, "roomflags")) { set_nest_node(ses->list[LIST_VARIABLE], arg2, "%d", room->flags); } else if (is_abbrev(arg1, "roomname")) { set_nest_node(ses->list[LIST_VARIABLE], arg2, "%s", room->name); } else if (is_abbrev(arg1, "roomnote")) { set_nest_node(ses->list[LIST_VARIABLE], arg2, "%s", room->note); } else if (is_abbrev(arg1, "roomsymbol")) { set_nest_node(ses->list[LIST_VARIABLE], arg2, "%s", room->symbol); } else if (is_abbrev(arg1, "roomvnum")) { set_nest_node(ses->list[LIST_VARIABLE], arg2, "%d", room->vnum); } else if (is_abbrev(arg1, "roomexits")) { buf[0] = 0; for (exit = room->f_exit ; exit ; exit = exit->next) { cat_sprintf(buf, "{%s}{%d}", exit->name, exit->vnum); } set_nest_node(ses->list[LIST_VARIABLE], arg2, "%s", buf); } else if (is_abbrev(arg1, "worldflags")) { set_nest_node(ses->list[LIST_VARIABLE], arg2, "%d", ses->map->flags); } else if (is_abbrev(arg1, "worldsize")) { set_nest_node(ses->list[LIST_VARIABLE], arg2, "%d", ses->map->size); } else { show_message(ses, -1, "#MAP GET: unknown option: %s.", arg1); } } } DO_MAP(map_goto) { int room; room = find_room(ses, arg); if (room != -1) { add_undo(ses, "%d %d %d", room, ses->map->in_room, 0); goto_room(ses, room); show_message(ses, -1, "#MAP: Location set to room {%s}.", ses->map->room_list[room]->name); } else { show_message(ses, -1, "#MAP: Couldn't find room {%s}.", arg); } } DO_MAP(map_info) { int room, cnt, exits; struct exit_data *exit; for (room = cnt = exits = 0 ; room < ses->map->size ; room++) { if (ses->map->room_list[room]) { cnt++; exits += get_map_exits(ses, room); } } tintin_printf2(ses, "%-20s %d/%d", "Total rooms:", cnt, ses->map->size); tintin_printf2(ses, "%-20s %d", "Total exits:", exits); tintin_printf2(ses, "%-20s %s", "Vtmap:", HAS_BIT(ses->map->flags, MAP_FLAG_VTMAP) ? "on" : "off"); tintin_printf2(ses, "%-20s %s", "Static:", HAS_BIT(ses->map->flags, MAP_FLAG_STATIC) ? "on" : "off"); if (ses->map->in_room) { tintin_printf2(ses, ""); tintin_printf2(ses, "%-20s %d", "Room vnum:", ses->map->in_room); tintin_printf2(ses, "%-20s %s", "Room name:", ses->map->room_list[ses->map->in_room]->name); tintin_printf2(ses, "%-20s %d", "Room size:", ses->map->room_list[ses->map->in_room]->size); tintin_printf2(ses, "%-20s %s", "Avoid:", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_AVOID) ? "on" : "off"); tintin_printf2(ses, "%-20s %s", "Hide:", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_HIDE) ? "on" : "off"); tintin_printf2(ses, "%-20s %s", "Leave:", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_LEAVE) ? "on" : "off"); tintin_printf2(ses, "%-20s %s", "Void:", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_VOID) ? "on" : "off"); for (exit = ses->map->room_list[ses->map->in_room]->f_exit ; exit ; exit = exit->next) { tintin_printf2(ses, "%-20s %03d %-3s (%s) to room: %-5d (%s)", "Exit:", exit->dir, exit->name, exit->cmd, exit->vnum, ses->map->room_list[exit->vnum]->name); } } } DO_MAP(map_insert) { int room, in_room, to_room; char temp[BUFFER_SIZE]; struct exit_data *exit; struct listnode *node; arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN); for (room = 1 ; room < ses->map->size ; room++) { if (ses->map->room_list[room] == NULL) { break; } } exit = find_exit(ses, ses->map->in_room, arg1); node = search_node_list(ses->list[LIST_PATHDIR], arg1); if (exit == NULL) { tintin_printf2(ses, "#MAP: There is no room in that direction."); return; } if (room == ses->map->size) { tintin_printf2(ses, "#MAP: Maximum amount of rooms of %d reached.", ses->map->size); return; } if (node == NULL) { tintin_printf2(ses, "#MAP: Given direction must be a pathdir."); return; } in_room = ses->map->in_room; to_room = exit->vnum; sprintf(temp, "{%d} {0} {} {%d} { }", room, room); create_room(ses, temp); sprintf(temp, "{%d} {%s} {%s}", to_room, node->left, node->left); create_exit(ses, room, temp); sprintf(temp, "{%d} {%s} {%s}", in_room, node->right, node->right); create_exit(ses, room, temp); exit->vnum = room; if ((exit = find_exit(ses, to_room, node->right)) != NULL) { exit->vnum = room; } if (*arg2) { char buf[BUFFER_SIZE]; strcpy(buf, arg2); ses->map->in_room = room; map_roomflag(ses, buf, arg1, arg2); ses->map->in_room = in_room; } show_message(ses, -1, "#MAP: Inserted room {%d}.", room); } DO_MAP(map_jump) { int vnum; arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN); map_grid_x = 0; map_grid_y = 0; map_grid_z = 0; map_search_ses = ses; map_search_tar_room = 0; map_grid_x += atoi(arg1); map_grid_y += atoi(arg2); for (vnum = 0 ; vnum < ses->map->size ; vnum++) { if (ses->map->room_list[vnum]) { ses->map->room_list[vnum]->size = MAP_SEARCH_SIZE; } } search_coord_bf(ses->map->in_room); if (map_search_tar_room) { add_undo(ses, "%d %d %d", map_search_tar_room, ses->map->in_room, 0); goto_room(ses, map_search_tar_room); show_message(ses, -1, "#MAP: Location set to room {%s}.", ses->map->room_list[map_search_tar_room]->name); } else { show_message(ses, -1, "#MAP: Couldn't find room at {%s} {%s}.", arg1, arg2); } } DO_MAP(map_leave) { if (ses->map->in_room == 0) { tintin_printf2(ses, "#MAP: You're not currently inside the map."); } else { ses->map->last_room = ses->map->in_room; ses->map->in_room = 0; show_message(ses, -1, "#MAP: Leaving the map. Use goto or return to return."); check_all_events(ses, 0, 1, "MAP EXIT MAP", ntos(ses->map->in_room)); } } DO_MAP(map_legend) { arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN); if (*arg1 == 0) { tintin_printf2(ses, "#MAP: Current legend: %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s", ses->map->legend[0], ses->map->legend[1], ses->map->legend[2], ses->map->legend[3], ses->map->legend[4], ses->map->legend[5], ses->map->legend[6], ses->map->legend[7], ses->map->legend[8], ses->map->legend[9], ses->map->legend[10], ses->map->legend[11], ses->map->legend[12], ses->map->legend[13], ses->map->legend[14], ses->map->legend[15], ses->map->legend[16]); } else { create_legend(ses, arg1); } } DO_MAP(map_link) { char arg3[BUFFER_SIZE]; struct listnode *node; struct exit_data *exit; int room; arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN); if ((room = find_room(ses, arg)) == -1) { tintin_printf2(ses, "#MAP: Couldn't find room {%s}.", arg2); return; } exit = find_exit(ses, ses->map->in_room, arg1); if (exit) { delete_exit(ses, ses->map->in_room, exit); } sprintf(arg3, "{%d} {%s} {%s}", room, arg1, arg1); create_exit(ses, ses->map->in_room, arg3); if ((node = search_node_list(ses->list[LIST_PATHDIR], arg1)) != NULL) { if (find_exit(ses, room, node->right) == NULL) { sprintf(arg3, "{%d} {%s} {%s}", ses->map->in_room, node->right, node->right); create_exit(ses, room, arg3); } } show_message(ses, -1, "#MAP LINK: Connected room {%s} to {%s}.", ses->map->room_list[ses->map->in_room]->name, ses->map->room_list[room]->name); } DO_MAP(map_list) { char arg3[BUFFER_SIZE], arg4[BUFFER_SIZE], arg5[BUFFER_SIZE]; int room; arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg3, GET_ALL, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg4, GET_ALL, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg5, GET_ALL, SUB_VAR|SUB_FUN); fill_map(ses); for (room = 0 ; room < ses->map->size ; room++) { if (match_room(ses, room, arg1, arg2, arg3, arg4, arg5)) { tintin_printf2(ses, "vnum: %5d distance: %5d name: %s", ses->map->room_list[room]->vnum, ses->map->room_list[room]->size, ses->map->room_list[room]->name); } } } DO_MAP(map_map) { char arg3[BUFFER_SIZE], buf[BUFFER_SIZE], out[BUFFER_SIZE]; FILE *logfile = NULL; int x, y, line; arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg3, GET_ONE, SUB_VAR|SUB_FUN); push_call("map_map(%p,%p)",ses,arg); if (sscanf(arg1, "%dx%d", &map_grid_x, &map_grid_y) == 2) { if (*arg2) { if (tolower((int) *arg3) == 'a') { logfile = fopen(arg2, "a"); } else { logfile = fopen(arg2, "w"); } } if (HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIGRAPHICS)) { map_grid_y = map_grid_y / 3; map_grid_x = map_grid_x / 6; } else if (HAS_BIT(ses->map->flags, MAP_FLAG_MUDFONT)) { map_grid_x = map_grid_x / 2; } if (map_grid_x > ses->map->max_grid_x) { ses->map->max_grid_x = map_grid_x; ses->map->grid = (struct room_data **) realloc(ses->map->grid, ses->map->max_grid_x * ses->map->max_grid_y); } if (map_grid_y > ses->map->max_grid_y) { ses->map->max_grid_y = map_grid_y; ses->map->grid = (struct room_data **) realloc(ses->map->grid, ses->map->max_grid_x * ses->map->max_grid_y); } } else if (HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIGRAPHICS)) { map_grid_y = get_scroll_size(ses) / 3; map_grid_x = ses->cols / 6; } else if (HAS_BIT(ses->map->flags, MAP_FLAG_MUDFONT)) { map_grid_y = get_scroll_size(ses); map_grid_x = ses->cols / 2; } else { map_grid_y = get_scroll_size(ses); map_grid_x = ses->cols; } create_map_grid(ses, ses->map->in_room, map_grid_x, map_grid_y); if (HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIGRAPHICS)) { for (y = map_grid_y - 1 ; y >= 0 ; y--) { for (line = 1 ; line <= 3 ; line++) { strcpy(buf, ""); for (x = 0 ; x < map_grid_x ; x++) { strcat(buf, draw_room(ses, ses->map->grid[x + map_grid_x * y], line)); } substitute(ses, buf, out, SUB_COL); if (logfile) { fprintf(logfile, "%s\n", out); } else { tintin_puts2(ses, out); } } } } else { for (y = map_grid_y ; y >= 0 ; y--) { strcpy(buf, ""); for (x = 0 ; x < map_grid_x ; x++) { strcat(buf, draw_room(ses, ses->map->grid[x + map_grid_x * y], 0)); } for (x = strlen(buf) - 1 ; x > 0 ; x--) { if (buf[x] != ' ') { break; } } buf[x+1] = 0; substitute(ses, buf, out, SUB_COL); if (logfile) { fprintf(logfile, "%s\n", out); } else { tintin_puts2(ses, out); } } } if (logfile) { fclose(logfile); } pop_call(); return; } DO_MAP(map_move) { arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN); ses->map->nofollow++; follow_map(ses, arg1); ses->map->nofollow--; } DO_MAP(map_name) { arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN); free(ses->map->room_list[ses->map->in_room]->name); ses->map->room_list[ses->map->in_room]->name = strdup(arg1); } DO_MAP(map_read) { FILE *myfile; struct exit_data *exit; char buffer[BUFFER_SIZE], *cptr; int line = 0, room = 0; arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN); if ((myfile = fopen(arg1, "r")) == NULL) { tintin_printf2(ses, "#MAP: Map file {%s} not found.", arg1); return; } gtd->quiet++; if (ses->map == NULL) { ses->map = (struct map_data *) calloc(1, sizeof(struct map_data)); } while (fgets(buffer, BUFFER_SIZE - 1, myfile)) { line++; cptr = strchr(buffer, '\r'); /* For map files editor on Windows systems. */ if (cptr) { *cptr = 0; } cptr = strchr(buffer, '\n'); if (cptr) { *cptr = 0; } switch (buffer[0]) { case 'C': switch (buffer[1]) { case ' ': create_map(ses, buffer + 2); break; case 'E': ses->map->exit_color = strdup(buffer + 3); break; case 'P': ses->map->path_color = strdup(buffer + 3); break; case 'R': ses->map->room_color = strdup(buffer + 3); break; } break; case 'E': create_exit(ses, room, buffer + 2); break; case 'F': ses->map->flags = atoi(buffer + 2); if (HAS_BIT(ses->map->flags, MAP_FLAG_NOFOLLOW)) { ses->map->nofollow = 1; } break; case 'I': ses->map->last_room = atoi(buffer + 2); break; case 'L': create_legend(ses, buffer + 2); break; case 'R': room = create_room(ses, buffer + 2); break; case '#': buffer[0] = gtd->tintin_char; ses = script_driver(ses, -1, buffer); break; case 0: case 13: break; default: gtd->quiet--; tintin_printf2(ses, "#MAP: INVALID COMMAND {%d} {%s} ON LINE %d. ABORTING READ..", buffer[0], buffer, line); fclose(myfile); delete_map(ses); return; } } gtd->quiet--; fclose(myfile); for (room = 0 ; room < ses->map->size ; room++) { if (ses->map->room_list[room] == NULL) { continue; } for (exit = ses->map->room_list[room]->f_exit ; exit ; exit = exit->next) { if (exit->vnum < 0 || exit->vnum >= ses->map->size || ses->map->room_list[exit->vnum] == NULL) { tintin_printf2(ses, "#MAP READ: Room %d - invalid exit '%s' to room %d.", room, exit->name, exit->vnum); delete_exit(ses, room, exit); if (ses->map->room_list[room]->f_exit) { exit = ses->map->room_list[room]->f_exit; } else { break; } } } } show_message(ses, -1, "#MAP READ: Map file {%s} loaded.", arg1); } DO_MAP(map_resize) { int size; arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN); size = atoi(arg1); if (size <= ses->map->size) { tintin_printf2(ses, "#MAP RESIZE: NEW SIZE (%d) MUST BE GREATER THAN CURRENT SIZE (%d).", size, ses->map->size); return; } ses->map->size = size; ses->map->room_list = (struct room_data **) realloc(ses->map->room_list, ses->map->size * sizeof(struct room_data *)); show_message(ses, -1, "#MAP RESIZE: MAP RESIZED TO %d ROOMS.", size); } DO_MAP(map_return) { if (ses->map == NULL || ses->map->room_list[ses->map->last_room] == NULL) { tintin_printf2(ses, "#MAP RETURN: No known last room."); return; } if (ses->map->in_room) { tintin_printf2(ses, "#MAP RETURN: Already in the map."); } else { goto_room(ses, ses->map->last_room); } } DO_MAP(map_roomflag) { int flag; arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN); if (*arg1) { if (is_abbrev(arg1, "avoid")) { flag = ROOM_FLAG_AVOID; } else if (is_abbrev(arg1, "hide")) { flag = ROOM_FLAG_HIDE; } else if (is_abbrev(arg1, "leave")) { flag = ROOM_FLAG_LEAVE; } else if (is_abbrev(arg1, "void")) { flag = ROOM_FLAG_VOID; } else if (is_abbrev(arg1, "static")) { flag = ROOM_FLAG_STATIC; } else if (is_abbrev(arg1, "river")) { flag = ROOM_FLAG_RIVER; } else { tintin_printf2(ses, "#MAP: Invalid room flag {%s}.", arg1); return; } } else { tintin_printf2(ses, "#MAP: Avoid flag is set to %s.", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_AVOID) ? "on" : "off"); tintin_printf2(ses, "#MAP: Hide flag is set to %s.", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_HIDE) ? "on" : "off"); tintin_printf2(ses, "#MAP: Leave flag is set to %s.", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_LEAVE) ? "on" : "off"); tintin_printf2(ses, "#MAP: Void flag is set to %s.", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_VOID) ? "on" : "off"); tintin_printf2(ses, "#MAP: Static flag is set to %s.", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_STATIC) ? "on" : "off"); return; } if (is_abbrev("on", arg2)) { SET_BIT(ses->map->room_list[ses->map->in_room]->flags, flag); } else if (is_abbrev("off", arg2)) { DEL_BIT(ses->map->room_list[ses->map->in_room]->flags, flag); } else { TOG_BIT(ses->map->room_list[ses->map->in_room]->flags, flag); } if (is_abbrev(arg1, "avoid")) { show_message(ses, -1, "#MAP: Avoid flag set to %s.", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_AVOID) ? "on" : "off"); } else if (is_abbrev(arg1, "hide")) { show_message(ses, -1, "#MAP: Hide flag set to %s.", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_HIDE) ? "on" : "off"); } else if (is_abbrev(arg1, "leave")) { show_message(ses, -1, "#MAP: Leave flag set to %s.", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_LEAVE) ? "on" : "off"); } else if (is_abbrev(arg1, "void")) { show_message(ses, -1, "#MAP: Void flag set to %s.", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_VOID) ? "on" : "off"); } else if (is_abbrev(arg1, "static")) { show_message(ses, -1, "#MAP: Static flag set to %s.", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_STATIC) ? "on" : "off"); } else if (is_abbrev(arg1, "river")) { show_message(ses, -1, "#MAP: River flag set to %s.", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_RIVER) ? "on" : "off"); } } DO_MAP(map_set) { struct room_data *room = ses->map->room_list[ses->map->in_room]; char arg3[BUFFER_SIZE]; arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg3, GET_ALL, SUB_VAR|SUB_FUN); if (*arg3) { if (atoi(arg3) > 0 && atoi(arg3) < ses->map->size) { room = ses->map->room_list[atoi(arg3)]; } else { room = NULL; } } if (room == NULL) { show_message(ses, -1, "#MAP SET: invalid room vnum: %s", arg3); } else if (*arg1 == 0) { tintin_printf2(ses, " roomarea: %s", room->area); tintin_printf2(ses, " roomcolor: %s", room->color); tintin_printf2(ses, " roomdesc: %s", room->desc); tintin_printf2(ses, " roomflags: %d", room->flags); tintin_printf2(ses, " roomname: %s", room->name); tintin_printf2(ses, " roomnote: %s", room->note); tintin_printf2(ses, "roomsymbol: %s", room->symbol); } else { if (is_abbrev(arg1, "roomarea")) { RESTRING(room->area, arg2); show_message(ses, -1, "#MAP SET: roomarea set to: %s", room->area); } else if (is_abbrev(arg1, "roomcolor")) { RESTRING(room->color, arg2); show_message(ses, -1, "#MAP SET: roomcolor set to: %s", arg2); } else if (is_abbrev(arg1, "roomdesc")) { RESTRING(room->desc, arg2); show_message(ses, -1, "#MAP SET: roomdesc set to: %s", arg2); } else if (is_abbrev(arg1, "roomflags")) { room->flags = (int) get_number(ses, arg2); show_message(ses, -1, "#MAP SET: roomflags set to: %d", room->flags); } else if (is_abbrev(arg1, "roomname")) { RESTRING(room->name, arg2); show_message(ses, -1, "#MAP SET: roomname set to: %s", room->name); } else if (is_abbrev(arg1, "roomnote")) { RESTRING(room->note, arg2); show_message(ses, -1, "#MAP SET: roomnote set to: %s", arg2); } else if (is_abbrev(arg1, "roomsymbol")) { RESTRING(room->symbol, arg2); show_message(ses, -1, "#MAP SET: roomsymbol set to: %s", room->symbol); } else { show_message(ses, -1, "#MAP SET: unknown option: %s", arg1); } } } DO_MAP(map_travel) { arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN); explore_path(ses, TRUE, arg1, arg2); } DO_MAP(map_uninsert) { int room1, room2, room3; struct exit_data *exit1, *exit2, *exit3; struct listnode *node; arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN); room1 = ses->map->in_room; exit1 = find_exit(ses, room1, arg1); node = search_node_list(ses->list[LIST_PATHDIR], arg1); if (exit1 == NULL) { tintin_printf2(ses, "#MAP UNINSERT: There is no room in that direction."); return; } if (node == NULL) { tintin_printf2(ses, "#MAP UNINSERT: Given direction must be a pathdir."); return; } room2 = exit1->vnum; exit2 = find_exit(ses, room2, node->left); if (exit2 == NULL) { tintin_printf2(ses, "#MAP UNINSERT: Unable to find backlink room."); return; } room3 = exit2->vnum; exit3 = find_exit(ses, room3, node->right); if (exit3 == NULL) { tintin_printf2(ses, "#MAP UNINSERT: Unable to find backlink exit."); return; } exit1->vnum = room3; exit3->vnum = room1; delete_room(ses, room2, TRUE); show_message(ses, -1, "#MAP UNINSERT: Uninserted room {%d}.", room2); } DO_MAP(map_undo) { struct link_data *link; int undo_flag; struct exit_data *exit; link = ses->map->undo_tail; if (link == NULL) { tintin_printf2(ses, "#MAP UNDO: No known last move."); return; } if (ses->map->in_room != atoi(link->str1)) { tintin_printf2(ses, "#MAP UNDO: Invalid last move."); return; } if (ses->map->room_list[atoi(link->str2)] == NULL) { tintin_printf2(ses, "#MAP UNDO: Invalid last move."); return; } undo_flag = atoi(link->str3); goto_room(ses, atoi(link->str2)); if (HAS_BIT(undo_flag, MAP_UNDO_CREATE)) { delete_room(ses, atoi(link->str1), TRUE); } else if (HAS_BIT(undo_flag, MAP_UNDO_LINK)) { exit = find_exit(ses, atoi(link->str1), link->str2); if (exit) { delete_exit(ses, atoi(link->str1), exit); } exit = find_exit(ses, atoi(link->str2), link->str1); if (exit) { delete_exit(ses, atoi(link->str2), exit); } } del_undo(ses, link); } DO_MAP(map_unlink) { struct exit_data *exit1; struct exit_data *exit2; struct listnode *node; arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN); node = search_node_list(ses->list[LIST_PATHDIR], arg1); exit1 = find_exit(ses, ses->map->in_room, arg1); if (exit1 == NULL) { tintin_printf2(ses, "#MAP UNLINK: No exit with that name found"); return; } if (*arg2 == 'b') { if (node) { exit2 = find_exit(ses, exit1->vnum, node->right); if (exit2) { delete_exit(ses, exit1->vnum, exit2); } } } delete_exit(ses, ses->map->in_room, exit1); show_message(ses, -1, "#MAP UNLINK: Exit deleted."); } DO_MAP(map_run) { arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN); arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN); shortest_path(ses, TRUE, arg2, arg1); } DO_MAP(map_write) { FILE *file; struct exit_data *exit; int vnum; arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN); if (*arg1 == 0 || (file = fopen(arg1, "w")) == NULL) { tintin_printf2(ses, "#ERROR: #MAP WRITE {%s} - COULDN'T OPEN FILE TO WRITE.", arg1); return; } fprintf(file, "C %d\n\n", ses->map->size); fprintf(file, "CE %s\nCR %s\nCP %s\n\n", ses->map->exit_color, ses->map->room_color, ses->map->path_color); fprintf(file, "F %d\n\n", ses->map->flags); fprintf(file, "I %d\n\n", ses->map->in_room ? ses->map->in_room : ses->map->last_room); fprintf(file, "L %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n\n", ses->map->legend[0], ses->map->legend[1], ses->map->legend[2], ses->map->legend[3], ses->map->legend[4], ses->map->legend[5], ses->map->legend[6], ses->map->legend[7], ses->map->legend[8], ses->map->legend[9], ses->map->legend[10], ses->map->legend[11], ses->map->legend[12], ses->map->legend[13], ses->map->legend[14], ses->map->legend[15], ses->map->legend[16]); for (vnum = 0 ; vnum < ses->map->size ; vnum++) { if (ses->map->room_list[vnum]) { fprintf(file, "\nR {%5d} {%d} {%s} {%s} {%s} {%s} {%s} {%s}\n", ses->map->room_list[vnum]->vnum, ses->map->room_list[vnum]->flags, ses->map->room_list[vnum]->color, ses->map->room_list[vnum]->name, ses->map->room_list[vnum]->symbol, ses->map->room_list[vnum]->desc, ses->map->room_list[vnum]->area, ses->map->room_list[vnum]->note); for (exit = ses->map->room_list[vnum]->f_exit ; exit ; exit = exit->next) { fprintf(file, "E {%5d} {%s} {%s} {%d} {%d}\n", exit->vnum, exit->name, exit->cmd, exit->dir, exit->flags); } } } fclose(file); show_message(ses, -1, "#MAP: Map file written to {%s}.", arg1); } void create_map(struct session *ses, char *arg) { int index; if (ses->map) { delete_map(ses); } ses->map = (struct map_data *) calloc(1, sizeof(struct map_data)); ses->map->size = atoi(arg) > 0 ? atoi(arg) : 15000; ses->map->room_list = (struct room_data **) calloc(ses->map->size, sizeof(struct room_data *)); ses->map->max_grid_x = 255; ses->map->max_grid_y = 101; ses->map->grid = (struct room_data **) calloc(ses->map->max_grid_x * ses->map->max_grid_y, sizeof(struct room_data *)); ses->map->flags = MAP_FLAG_ASCIIGRAPHICS; ses->map->room_color = strdup("<178>"); ses->map->exit_color = strdup("<078>"); ses->map->path_color = strdup("<138>"); create_room(ses, "{1} {0} {} {1} { }"); for (index = 0 ; index < 17 ; index++) { sprintf(ses->map->legend[index], "%c", map_palet0[index]); } } void delete_map(struct session *ses) { int index; for (index = 1 ; index < ses->map->size ; index++) { if (ses->map->room_list[index]) { delete_room(ses, index, FALSE); } } free(ses->map->room_list); while (ses->map->undo_head) { del_undo(ses, ses->map->undo_head); } free(ses->map); ses->map = NULL; } void create_legend(struct session *ses, char *arg) { int cnt; char buf[BUFFER_SIZE]; for (cnt = 0 ; cnt < 17 ; cnt++) { arg = get_arg_in_braces(arg, buf, FALSE); substitute(ses, buf, buf, SUB_ESC); if (is_number(buf)) { sprintf(ses->map->legend[cnt], "%c", atoi(buf)); } else { sprintf(ses->map->legend[cnt], "%s", buf); } } } int create_room(struct session *ses, char *arg) { char vnum[BUFFER_SIZE], flags[BUFFER_SIZE], color[BUFFER_SIZE], name[BUFFER_SIZE], symbol[BUFFER_SIZE], desc[BUFFER_SIZE], area[BUFFER_SIZE], note[BUFFER_SIZE]; struct room_data *newroom; arg = get_arg_in_braces(arg, vnum, FALSE); arg = get_arg_in_braces(arg, flags, FALSE); arg = get_arg_in_braces(arg, color, FALSE); arg = get_arg_in_braces(arg, name, FALSE); arg = get_arg_in_braces(arg, symbol, FALSE); arg = get_arg_in_braces(arg, desc, FALSE); arg = get_arg_in_braces(arg, area, FALSE); arg = get_arg_in_braces(arg, note, FALSE); /* Backward compatbility 1.96.5 */ if (*symbol == 0) { strcpy(symbol, " "); } newroom = (struct room_data *) calloc(1, sizeof(struct room_data)); newroom->color = strdup(color); newroom->name = strdup(name); newroom->symbol = strdup(symbol); newroom->desc = strdup(desc); newroom->area = strdup(area); newroom->note = strdup(note); newroom->flags = atoi(flags); newroom->vnum = atoi(vnum); ses->map->room_list[newroom->vnum] = newroom; show_message(ses, -1, "#MAP CREATE ROOM %5s {%s}.", vnum, name); return newroom->vnum; } void delete_room(struct session *ses, int room, int exits) { struct exit_data *exit, *exit_next; int cnt; while (ses->map->room_list[room]->f_exit) { delete_exit(ses, room, ses->map->room_list[room]->f_exit); } free(ses->map->room_list[room]->name); free(ses->map->room_list[room]->color); free(ses->map->room_list[room]->symbol); free(ses->map->room_list[room]->desc); free(ses->map->room_list[room]->area); free(ses->map->room_list[room]->note); free(ses->map->room_list[room]); ses->map->room_list[room] = NULL; if (exits) { for (cnt = 0 ; cnt < ses->map->size ; cnt++) { if (ses->map->room_list[cnt]) { for (exit = ses->map->room_list[cnt]->f_exit ; exit ; exit = exit_next) { exit_next = exit->next; if (exit->vnum == room) { delete_exit(ses, cnt, exit); } } } } } } void create_exit(struct session *ses, int room, char *arg) { struct exit_data *newexit; struct listnode *node; char vnum[BUFFER_SIZE], name[BUFFER_SIZE], cmd[BUFFER_SIZE], dir[BUFFER_SIZE], flags[BUFFER_SIZE]; arg = get_arg_in_braces(arg, vnum, FALSE); arg = get_arg_in_braces(arg, name, FALSE); arg = get_arg_in_braces(arg, cmd, TRUE); arg = get_arg_in_braces(arg, dir, FALSE); arg = get_arg_in_braces(arg, flags, FALSE); newexit = (struct exit_data *) calloc(1, sizeof(struct exit_data)); newexit->vnum = atoi(vnum); newexit->name = strdup(name); newexit->cmd = strdup(cmd); newexit->dir = atoi(dir); newexit->flags = atoi(flags); if (newexit->dir == 0) { if ((node = search_node_list(ses->list[LIST_PATHDIR], name)) != NULL) { newexit->dir = atoi(node->pr); } } LINK(newexit, ses->map->room_list[room]->f_exit, ses->map->room_list[room]->l_exit); show_message(ses, -1, "#MAP CREATE EXIT %5s {%s} {%s}.", vnum, name, cmd); } void delete_exit(struct session *ses, int room, struct exit_data *exit) { free(exit->name); free(exit->cmd); UNLINK(exit, ses->map->room_list[room]->f_exit, ses->map->room_list[room]->l_exit) free(exit); } int get_map_exit(struct session *ses, char *arg) { struct listnode *node; node = search_node_list(ses->list[LIST_PATHDIR], arg); if (node) { return atoi(node->pr); } else { return 0; } } int get_map_exits(struct session *ses, int room) { struct exit_data *exit; int count = 0; for (exit = ses->map->room_list[room]->f_exit ; exit ; exit = exit->next) { count++; } return count; } int follow_map(struct session *ses, char *argument) { struct exit_data *exit; int room; push_call("follow_map(%p,%p)",ses,argument); exit = find_exit(ses, ses->map->in_room, argument); if (exit) { room = ses->map->in_room; add_undo(ses, "%d %d %d", exit->vnum, room, 0); if (ses->map->nofollow == 0) { ses->map->nofollow++; script_driver(ses, -1, exit->cmd); ses->map->nofollow--; } goto_room(ses, exit->vnum); if (HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_LEAVE)) { show_message(ses, -1, "#MAP: LEAVE FLAG FOUND IN ROOM {%d}. LEAVING MAP.", ses->map->in_room); map_leave(ses, "", "", ""); } else if (HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_VOID)) { exit = find_exit(ses, exit->vnum, argument); if (exit) { ses->map->nofollow++; follow_map(ses, exit->name); ses->map->nofollow--; pop_call(); return 1; } for (exit = ses->map->room_list[ses->map->in_room]->f_exit ; exit ; exit = exit->next) { if (exit->vnum != room) { ses->map->nofollow++; follow_map(ses, exit->name); ses->map->nofollow--; pop_call(); return 1; } } } show_vtmap(ses); pop_call(); return 1; } if (!HAS_BIT(ses->map->flags, MAP_FLAG_STATIC) && !HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_STATIC)) { char temp[BUFFER_SIZE]; struct listnode *node; if ((node = search_node_list(ses->list[LIST_PATHDIR], argument)) == NULL) { pop_call(); return 0; } for (room = 1 ; room < ses->map->size ; room++) { if (ses->map->room_list[room] == NULL) { break; } } if (room == ses->map->size) { tintin_printf2(ses, "#MAP: Maximum amount of rooms of %d reached. Consider updating the C value in your map file.", ses->map->size); pop_call(); return 1; } if (find_coord(ses, argument)) { room = map_search_tar_room; show_message(ses, -1, "#MAP CREATE LINK %5d {%s}.", room, ses->map->room_list[room]->name); add_undo(ses, "%d %d %d", room, ses->map->in_room, MAP_UNDO_LINK); } else { sprintf(temp, "{%d} {0} {} {%d} { }", room, room); create_room(ses, temp); add_undo(ses, "%d %d %d", room, ses->map->in_room, MAP_UNDO_CREATE|MAP_UNDO_LINK); } sprintf(temp, "{%d} {%s} {%s}", room, node->left, node->left); create_exit(ses, ses->map->in_room, temp); if (find_exit(ses, room, node->right) == NULL) { sprintf(temp, "{%d} {%s} {%s}", ses->map->in_room, node->right, node->right); create_exit(ses, room, temp); } if (ses->map->nofollow == 0) { ses->map->nofollow++; script_driver(ses, -1, argument); ses->map->nofollow--; } goto_room(ses, room); show_vtmap(ses); pop_call(); return 1; } pop_call(); return 0; } void add_undo(struct session *ses, char *format, ...) { struct link_data *link; char buf[BUFFER_SIZE], *arg, dir[BUFFER_SIZE], rev[BUFFER_SIZE], flag[BUFFER_SIZE]; va_list args; push_call("add_undo(%s,%s)",ses->name, format); va_start(args, format); vsprintf(buf, format, args); va_end(args); arg = get_arg_in_braces(buf, dir, FALSE); arg = get_arg_in_braces(arg, rev, FALSE); arg = get_arg_in_braces(arg, flag, FALSE); link = (struct link_data *) calloc(1, sizeof(struct link_data)); link->str1 = strdup(dir); link->str2 = strdup(rev); link->str3 = strdup(flag); LINK(link, ses->map->undo_head, ses->map->undo_tail); ses->map->undo_size++; if (ses->map->undo_size > 100) { del_undo(ses, ses->map->undo_head); } pop_call(); return; } void del_undo(struct session *ses, struct link_data *link) { UNLINK(link, ses->map->undo_head, ses->map->undo_tail); free(link->str1); free(link->str2); free(link->str3); free(link); ses->map->undo_size--; } /* Draws a map on a grid, breadth first improvements by Bryan Turner */ #define MAP_BF_SIZE 800 struct grid_node { int vnum; int x; int y; int z; int size; }; void build_map_grid_bf(int vnum, int x, int y, int z) { int head, tail; struct grid_node *node, *temp, list[MAP_BF_SIZE]; struct exit_data *exit; struct room_data *room; int xx, yy, zz; head = 0; tail = 1; node = &list[head]; node->vnum = vnum; node->x = x; node->y = y; node->z = z; node->size = 0; while (head != tail) { node = &list[head]; head = (head + 1) % MAP_BF_SIZE; room = map_search_ses->map->room_list[node->vnum]; if (room->size <= node->size) { continue; } room->size = node->size; if (node->x >= 0 && node->x < map_grid_x && node->y >= 0 && node->y < map_grid_y && node->z == 0) { if (map_search_ses->map->grid[node->x + map_grid_x * node->y] == NULL) { map_search_ses->map->grid[node->x + map_grid_x * node->y] = room; } else { continue; } } for (exit = room->f_exit ; exit ; exit = exit->next) { if (head == (tail + 1) % MAP_BF_SIZE) { break; } if (exit->dir == 0) { continue; } if (HAS_BIT(exit->flags, EXIT_FLAG_HIDE)) { continue; } if (HAS_BIT(map_search_ses->map->room_list[exit->vnum]->flags, ROOM_FLAG_HIDE)) { continue; } xx = node->x + (HAS_BIT(exit->dir, MAP_EXIT_E) ? 1 : HAS_BIT(exit->dir, MAP_EXIT_W) ? -1 : 0); yy = node->y + (HAS_BIT(exit->dir, MAP_EXIT_N) ? 1 : HAS_BIT(exit->dir, MAP_EXIT_S) ? -1 : 0); zz = node->z + (HAS_BIT(exit->dir, MAP_EXIT_U) ? 1 : HAS_BIT(exit->dir, MAP_EXIT_D) ? -1 : 0); if (xx >= 0 && xx < map_grid_x && yy >= 0 && yy < map_grid_y && zz == 0) { if (map_search_ses->map->grid[xx + map_grid_x * yy] && map_search_ses->map->grid[xx + map_grid_x * yy]->size <= room->size + 1) { continue; } } temp = &list[tail]; temp->vnum = exit->vnum; temp->x = xx; temp->y = yy; temp->z = zz; temp->size = node->size + 1; tail = (tail + 1) % MAP_BF_SIZE; } } } void create_map_grid(struct session *ses, int room, int x, int y) { int vnum; for (vnum = 0 ; vnum < ses->map->size ; vnum++) { if (ses->map->room_list[vnum]) { ses->map->room_list[vnum]->size = 500; } } for (vnum = 0 ; vnum < x * y ; vnum++) { ses->map->grid[vnum] = NULL; } map_search_ses = ses; map_grid_y = y; map_grid_x = x; if (ses->map->room_list[room]) { build_map_grid_bf(room, x / 2, y / 2, 0); } } void show_vtmap(struct session *ses) { char buf[BUFFER_SIZE], out[BUFFER_SIZE]; int x, y, line; push_call("show_vtmap(%p)",ses); if (ses->map == NULL || !HAS_BIT(ses->map->flags, MAP_FLAG_VTMAP)) { pop_call(); return; } if (ses->map->room_list[ses->map->in_room] == NULL) { pop_call(); return; } if (ses != gtd->ses || HAS_BIT(gtd->ses->flags, SES_FLAG_READMUD)) { pop_call(); return; } if (HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIGRAPHICS)) { map_grid_y = (ses->top_row - 2) / 3; map_grid_x = (ses->cols - 0) / 6; } else if (HAS_BIT(ses->map->flags, MAP_FLAG_MUDFONT)) { map_grid_y = (ses->top_row - 2); map_grid_x = (ses->cols / 2); } else { map_grid_y = (ses->top_row - 2); map_grid_x = (ses->cols); } create_map_grid(ses, ses->map->in_room, map_grid_x, map_grid_y); save_pos(ses); goto_rowcol(ses, 1, 1); if (HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIGRAPHICS)) { for (y = map_grid_y - 1 ; y >= 0 ; y--) { for (line = 1 ; line <= 3 ; line++) { strcpy(buf, ""); for (x = 0 ; x < map_grid_x ; x++) { strcat(buf, draw_room(ses, ses->map->grid[x + map_grid_x * y], line)); } substitute(ses, buf, out, SUB_COL); printf("%s\033[0K\n", out); } } } else { for (y = map_grid_y - 1 ; y >= 0 ; y--) { strcpy(buf, ""); for (x = 0 ; x < map_grid_x ; x++) { strcat(buf, draw_room(ses, ses->map->grid[x + map_grid_x * y], 0)); } substitute(ses, buf, out, SUB_COL); printf("%s\n", out); } } restore_pos(ses); pop_call(); return; } char *draw_room(struct session *ses, struct room_data *room, int line) { struct exit_data *exit; static char buf[101]; int door, exits = 0, exit1 = 0, exit2 = 0; push_call("draw_room(%p,%p,%p)",ses,room,line); if (line) { if (room == NULL) { pop_call(); return " "; } sprintf(buf, "%s", ses->map->exit_color); for (exit = room->f_exit ; exit ; exit = exit->next) { door = exit->dir; switch (exit->dir) { case MAP_EXIT_N|MAP_EXIT_E: door = MAP_EXIT_NE; break; case MAP_EXIT_N|MAP_EXIT_W: door = MAP_EXIT_NW; break; case MAP_EXIT_S|MAP_EXIT_E: door = MAP_EXIT_SE; break; case MAP_EXIT_S|MAP_EXIT_W: door = MAP_EXIT_SW; break; case 0: continue; } SET_BIT(exits, door); } switch (line) { case 1: strcat(buf, HAS_BIT(exits, MAP_EXIT_NW) ? "\\ " : " "); strcat(buf, HAS_BIT(exits, MAP_EXIT_N) ? "|" : " "); strcat(buf, HAS_BIT(exits, MAP_EXIT_U) ? "+" : " "); strcat(buf, HAS_BIT(exits, MAP_EXIT_NE) ? "/ " : " "); break; case 2: if (HAS_BIT(room->flags, ROOM_FLAG_VOID) || !HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIVNUMS)) { strcat(buf, HAS_BIT(exits, MAP_EXIT_W) ? "-" : " "); } if (room->vnum == ses->map->in_room) { if (!HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIVNUMS)) { cat_sprintf(buf, "%s[<118>#%s]%s", *room->color ? room->color : ses->map->room_color, *room->color ? room->color : ses->map->room_color, ses->map->exit_color); } else { cat_sprintf(buf, "<118>%05d%s", room->vnum, ses->map->exit_color); } } else { if (HAS_BIT(room->flags, ROOM_FLAG_VOID)) { switch (exits) { case MAP_EXIT_N|MAP_EXIT_S: cat_sprintf(buf, " | "); break; case MAP_EXIT_E|MAP_EXIT_W: cat_sprintf(buf, "---"); break; case MAP_EXIT_NE|MAP_EXIT_SW: cat_sprintf(buf, " / "); break; case MAP_EXIT_NW|MAP_EXIT_SE: cat_sprintf(buf, " \\ "); break; default: cat_sprintf(buf, " * "); break; } } else { if (HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIVNUMS)) { cat_sprintf(buf, "<128>%05d%s", room->vnum, ses->map->exit_color); } else if (strip_color_strlen(room->symbol) <= 1) { cat_sprintf(buf, "%s[%s%s]%s", HAS_BIT(room->flags, ROOM_FLAG_PATH) ? ses->map->path_color : *room->color ? room->color : ses->map->room_color, room->symbol, HAS_BIT(room->flags, ROOM_FLAG_PATH) ? ses->map->path_color : *room->color ? room->color : ses->map->room_color, ses->map->exit_color); } else { cat_sprintf(buf, "%s%-3s%s", HAS_BIT(room->flags, ROOM_FLAG_PATH) ? ses->map->path_color : *room->color ? room->color : ses->map->room_color, room->symbol, ses->map->exit_color); } } } if (HAS_BIT(room->flags, ROOM_FLAG_VOID) || !HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIVNUMS)) { strcat(buf, HAS_BIT(exits, MAP_EXIT_E) ? "--" : " "); } else { strcat(buf, HAS_BIT(exits, MAP_EXIT_E) ? "-" : " "); } break; case 3: strcat(buf, HAS_BIT(exits, MAP_EXIT_SW) ? "/" : " "); strcat(buf, HAS_BIT(exits, MAP_EXIT_D) ? "-" : " "); strcat(buf, HAS_BIT(exits, MAP_EXIT_S) ? "| " : " "); strcat(buf, HAS_BIT(exits, MAP_EXIT_SE) ? "\\ " : " "); break; } pop_call(); return buf; } if (room == NULL) { if (HAS_BIT(ses->map->flags, MAP_FLAG_MUDFONT)) { pop_call(); return " "; } else { pop_call(); return " "; } } if (room->vnum == ses->map->in_room) { if (HAS_BIT(ses->map->flags, MAP_FLAG_MUDFONT)) { sprintf(buf, "<118>%c%c", 199, 207); } else if (HAS_BIT(ses->map->flags, MAP_FLAG_VTGRAPHICS)) { sprintf(buf, "<118>\033[12m%s\033[10m", ses->map->legend[16]); } else { sprintf(buf, "<118>%s", ses->map->legend[16]); } pop_call(); return buf; } for (exit = room->f_exit ; exit ; exit = exit->next) { if (HAS_BIT(ses->map->flags, MAP_FLAG_MUDFONT)) { switch (exit->dir) { case MAP_EXIT_N: SET_BIT(exit1, 1 << 0); SET_BIT(exit2, 1 << 0); SET_BIT(exits, MAP_EXIT_N); break; case MAP_EXIT_N|MAP_EXIT_W: SET_BIT(exit1, 1 << 1); SET_BIT(exits, MAP_EXIT_NW); break; case MAP_EXIT_N|MAP_EXIT_E: SET_BIT(exit2, 1 << 1); SET_BIT(exits, MAP_EXIT_NE); break; case MAP_EXIT_W: SET_BIT(exit1, 1 << 2); SET_BIT(exits, MAP_EXIT_W); break; case MAP_EXIT_E: SET_BIT(exit2, 1 << 2); SET_BIT(exits, MAP_EXIT_E); break; case MAP_EXIT_W|MAP_EXIT_S: SET_BIT(exit1, 1 << 3); SET_BIT(exits, MAP_EXIT_SW); break; case MAP_EXIT_E|MAP_EXIT_S: SET_BIT(exit2, 1 << 3); SET_BIT(exits, MAP_EXIT_SE); break; case MAP_EXIT_S: SET_BIT(exit1, 1 << 4); SET_BIT(exit2, 1 << 4); SET_BIT(exits, MAP_EXIT_S); break; } continue; } switch (exit->dir) { case MAP_EXIT_N|MAP_EXIT_E: case MAP_EXIT_N|MAP_EXIT_W: case MAP_EXIT_S|MAP_EXIT_E: case MAP_EXIT_S|MAP_EXIT_W: continue; } if (exit->dir >= MAP_EXIT_N && exit->dir <= MAP_EXIT_W) { SET_BIT(exits, exit->dir); } } if (HAS_BIT(ses->map->flags, MAP_FLAG_MUDFONT)) { int room1 = exit1 + 128; int room2 = exit2 + 160; if (HAS_BIT(room->flags, ROOM_FLAG_RIVER)) { switch (exits) { case 0: room1 = 192; room2 = 192 + 8; break; case MAP_EXIT_N: room1 = 192 + 1; room2 = 192 + 1 + 8; break; case MAP_EXIT_N|MAP_EXIT_W: room1 = 192 + 2; room2 = 192 + 1 + 8; break; case MAP_EXIT_S: room1 = 192 + 3; room2 = 192 + 3 + 8; break; case MAP_EXIT_W|MAP_EXIT_S: room1 = 192 + 5; room2 = 192 + 3 + 8; break; case MAP_EXIT_N|MAP_EXIT_W|MAP_EXIT_S: room1 = 192 + 6; room2 = 192 + 4 + 8; break; case MAP_EXIT_N|MAP_EXIT_E: room1 = 192 + 1; room2 = 192 + 2 + 8; break; case MAP_EXIT_N|MAP_EXIT_E|MAP_EXIT_W: room1 = 192 + 2; room2 = 192 + 2 + 8; break; case MAP_EXIT_E|MAP_EXIT_S: room1 = 192 + 3; room2 = 192 + 5 + 8; break; case MAP_EXIT_N|MAP_EXIT_E|MAP_EXIT_S: room1 = 192 + 4; room2 = 192 + 6 + 8; break; case MAP_EXIT_E|MAP_EXIT_S|MAP_EXIT_W: room1 = 192 + 5; room2 = 192 + 5 + 8; break; } } sprintf(buf, "%s%c%c", *room->color ? room->color : ses->map->room_color, room1, room2); } else if (HAS_BIT(ses->map->flags, MAP_FLAG_VTGRAPHICS)) { sprintf(buf, "%s\033[12m%s\033[10m", *room->color ? room->color : ses->map->room_color, ses->map->legend[exits]); } else { sprintf(buf, "%s%s", *room->color ? room->color : ses->map->room_color, ses->map->legend[exits]); } pop_call(); return buf; } int match_room(struct session *ses, int room, char *arg1, char *arg2, char *arg3, char *arg4, char *arg5) { if (ses->map->room_list[room] == NULL) { return 0; } if (*arg1) { if (!match(ses, ses->map->room_list[room]->name, arg1)) { return 0; } } if (*arg2) { char exit[BUFFER_SIZE]; int size = 0; char *arg = arg2; while (*arg) { arg = get_arg_in_braces(arg, exit, GET_ONE); size++; if (!find_exit(ses, room, exit)) { size = -1; break; } if (*arg == COMMAND_SEPARATOR) { arg++; } } if (size != get_map_exits(ses, room)) { return 0; } } if (*arg3) { if (!match(ses, ses->map->room_list[room]->desc, arg3)) { return 0; } } if (*arg4) { if (!match(ses, ses->map->room_list[room]->area, arg4)) { return 0; } } if (*arg5) { if (!match(ses, ses->map->room_list[room]->note, arg5)) { return 0; } } return 1; } int find_room(struct session *ses, char *arg) { char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE], arg3[BUFFER_SIZE], arg4[BUFFER_SIZE], arg5[BUFFER_SIZE]; int room, vnum, size; push_call("find_room(%p,%s)",ses,arg); arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN); // name arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN); // exits arg = sub_arg_in_braces(ses, arg, arg3, GET_ALL, SUB_VAR|SUB_FUN); // desc arg = sub_arg_in_braces(ses, arg, arg4, GET_ALL, SUB_VAR|SUB_FUN); // area arg = sub_arg_in_braces(ses, arg, arg5, GET_ALL, SUB_VAR|SUB_FUN); // note room = atoi(arg1); if (room > 0 && room < ses->map->size) { if (ses->map->room_list[room]) { pop_call(); return room; } if (!strcmp(arg2, "dig")) { sprintf(arg3, "{%d} {0} {} {%d} { }", room, room); create_room(ses, arg3); pop_call(); return room; } pop_call(); return -1; } fill_map(ses); vnum = -1; size = MAP_SEARCH_SIZE + 1; for (room = 0 ; room < ses->map->size ; room++) { if (!match_room(ses, room, arg1, arg2, arg3, arg4, arg5)) { continue; } if (ses->map->room_list[room]->size < size) { size = ses->map->room_list[room]->size; vnum = room; } } pop_call(); return vnum; } void goto_room(struct session *ses, int room) { int last_room = ses->map->in_room; push_call("goto_room(%p,%d)",ses,room); if (ses->map->in_room) { check_all_events(ses, 0, 2, "MAP EXIT ROOM", ntos(last_room), ntos(room)); check_all_events(ses, 1, 2, "MAP EXIT ROOM %d", last_room, ntos(last_room), ntos(room)); } ses->map->in_room = room; DEL_BIT(ses->map->room_list[room]->flags, ROOM_FLAG_PATH); if (last_room == 0) { check_all_events(ses, 0, 1, "MAP ENTER MAP", ntos(room)); } check_all_events(ses, 0, 2, "MAP ENTER ROOM", ntos(room), ntos(last_room)); check_all_events(ses, 1, 2, "MAP ENTER ROOM %d", room, ntos(room), ntos(last_room)); pop_call(); return; } struct exit_data *find_exit(struct session *ses, int room, char *arg) { struct exit_data *exit; for (exit = ses->map->room_list[room]->f_exit ; exit ; exit = exit->next) { if (!strcmp(exit->name, arg) || exit->vnum == atoi(arg)) { return exit; } } return NULL; } int revdir(int dir) { int revdir = 0; if (HAS_BIT(dir, MAP_EXIT_N)) { SET_BIT(revdir, MAP_EXIT_S); } if (HAS_BIT(dir, MAP_EXIT_E)) { SET_BIT(revdir, MAP_EXIT_W); } if (HAS_BIT(dir, MAP_EXIT_S)) { SET_BIT(revdir, MAP_EXIT_N); } if (HAS_BIT(dir, MAP_EXIT_W)) { SET_BIT(revdir, MAP_EXIT_E); } if (HAS_BIT(dir, MAP_EXIT_U)) { SET_BIT(revdir, MAP_EXIT_D); } if (HAS_BIT(dir, MAP_EXIT_D)) { SET_BIT(revdir, MAP_EXIT_U); } return revdir; } struct exit_data *find_exit_dir(struct session *ses, int room, int dir) { struct exit_data *exit; for (exit = ses->map->room_list[room]->f_exit ; exit ; exit = exit->next) { if (exit->dir == dir) { return exit; } } if (get_map_exits(ses, room) != 2) { show_message(map_search_ses, -1, "#ERROR: ROOM {%d} IS AN INVALID VOID ROOM.", room); return NULL; } if (ses->map->room_list[room]->f_exit->dir != revdir(dir)) { return ses->map->room_list[room]->f_exit; } else { return ses->map->room_list[room]->l_exit; } } /* Fast, short distance node weighted algorithms - Igor */ int follow_void(struct session *ses, int from, int room, int dir) { struct exit_data *exit; map_search_last_room = from; if (room == map_search_tar_room) { return room; } exit = find_exit_dir(ses, room, dir); if (exit) { if (HAS_BIT(ses->map->room_list[exit->vnum]->flags, ROOM_FLAG_VOID)) { return follow_void(ses, room, exit->vnum, exit->dir); } else { return exit->vnum; } } else { return room; } } void search_path(int room, int size, int dir) { struct exit_data *exit; map_search_ses->map->room_list[room]->size = size; if (size >= map_search_max_size) { return; } if (room == map_search_tar_room) { map_search_exit_best = map_search_exit_node; map_search_max_size = size; } else { if (HAS_BIT(map_search_ses->map->room_list[room]->flags, ROOM_FLAG_AVOID)) { return; } if (HAS_BIT(map_search_ses->map->room_list[room]->flags, ROOM_FLAG_VOID)) { exit = find_exit_dir(map_search_ses, room, dir); if (exit && map_search_ses->map->room_list[exit->vnum]->size > size) { search_path(exit->vnum, size, exit->dir); } } else { size++; for (exit = map_search_ses->map->room_list[room]->f_exit ; exit ; exit = exit->next) { if (map_search_ses->map->room_list[exit->vnum]->size > size) { search_path(exit->vnum, size, exit->dir); } } } } } void fill_map(struct session *ses) { int vnum, room; struct exit_data *exit; push_call("fill_map(%p)",ses); map_search_ses = ses; map_search_tar_room = -1; map_search_max_size = MAP_SEARCH_SIZE; for (vnum = 0 ; vnum < ses->map->size ; vnum++) { if (ses->map->room_list[vnum]) { ses->map->room_list[vnum]->size = map_search_max_size; } } if (ses->map->in_room == 0) { pop_call(); return; } room = ses->map->in_room; ses->map->room_list[room]->size = 0; for (exit = ses->map->room_list[room]->f_exit ; exit ; exit = exit->next) { if (ses->map->room_list[exit->vnum]) { search_path(exit->vnum, 1, exit->dir); } } pop_call(); return; } void shortest_path(struct session *ses, int run, char *delay, char *arg) { struct exit_data *exit; int room, vnum; if (HAS_BIT(ses->flags, SES_FLAG_MAPPING)) { tintin_printf2(ses, "#SHORTEST PATH: You have to stop #PATH TRACKING first."); return; } kill_list(ses->list[LIST_PATH]); room = find_room(ses, arg); if (room == -1) { tintin_printf2(ses, "#SHORTEST PATH: Couldn't find the room %s", arg); return; } if (room == ses->map->in_room) { tintin_printf2(ses, "Already there."); return; } map_search_exit_best = NULL; map_search_ses = ses; map_search_tar_room = room; map_search_max_size = MAP_SEARCH_SIZE; for (vnum = 0 ; vnum < ses->map->size ; vnum++) { if (ses->map->room_list[vnum]) { ses->map->room_list[vnum]->size = map_search_max_size; DEL_BIT(ses->map->room_list[vnum]->flags, ROOM_FLAG_PATH); } } room = ses->map->in_room; ses->map->room_list[room]->size = 0; for (exit = ses->map->room_list[room]->f_exit ; exit ; exit = exit->next) { if (ses->map->room_list[exit->vnum]) { map_search_exit_node = exit; search_path(exit->vnum, 1, exit->dir); } } if (map_search_exit_best == NULL) { tintin_printf2(ses, "#SHORTEST PATH: No path found."); return; } while (TRUE) { ses->map->room_list[room]->size = 0; for (exit = ses->map->room_list[room]->f_exit ; exit ; exit = exit->next) { if (ses->map->room_list[exit->vnum]) { map_search_exit_node = exit; search_path(exit->vnum, 1, exit->dir); } } if (map_search_exit_best == NULL) { return; } if (HAS_BIT(ses->map->flags, MAP_FLAG_NOFOLLOW)) { insert_node_list(ses->list[LIST_PATH], map_search_exit_best->cmd, "", "0"); } else { insert_node_list(ses->list[LIST_PATH], map_search_exit_best->name, "", "0"); } if (HAS_BIT(ses->map->room_list[map_search_exit_best->vnum]->flags, ROOM_FLAG_VOID)) { room = follow_void(ses, room, map_search_exit_best->vnum, map_search_exit_best->dir); } else { room = map_search_exit_best->vnum; } SET_BIT(ses->map->room_list[room]->flags, ROOM_FLAG_PATH); if (room == map_search_tar_room) { break; } } if (run) { path_run(ses, delay); } } /* Do a coordinate based search. */ int find_coord(struct session *ses, char *arg) { int vnum, coord; map_grid_x = 0; map_grid_y = 0; map_grid_z = 0; map_search_ses = ses; map_search_tar_room = 0; coord = get_map_exit(ses, arg); if (coord == 0) { return 0; } map_grid_y += (HAS_BIT(coord, MAP_EXIT_N) ? 1 : HAS_BIT(coord, MAP_EXIT_S) ? -1 : 0); map_grid_x += (HAS_BIT(coord, MAP_EXIT_E) ? 1 : HAS_BIT(coord, MAP_EXIT_W) ? -1 : 0); map_grid_z += (HAS_BIT(coord, MAP_EXIT_U) ? 1 : HAS_BIT(coord, MAP_EXIT_D) ? -1 : 0); for (vnum = 0 ; vnum < ses->map->size ; vnum++) { if (ses->map->room_list[vnum]) { ses->map->room_list[vnum]->size = MAP_SEARCH_SIZE; } } search_coord_bf(ses->map->in_room); if (ses->map->room_list[map_search_tar_room]) { if (HAS_BIT(ses->map->room_list[map_search_tar_room]->flags, ROOM_FLAG_STATIC)) { show_message(ses, -1, "#MAP: Linkable room is marked static. Creating overlapping room instead."); return 0; } } return map_search_tar_room; } void search_coord_bf(int vnum) { int head, tail; struct grid_node *node, *temp, list[MAP_BF_SIZE]; struct exit_data *exit; struct room_data *room; int xx, yy, zz; push_call("search_coord_bf(%d)",vnum); head = 0; tail = 1; node = &list[head]; node->vnum = vnum; node->x = 0; node->y = 0; node->z = 0; node->size = 0; while (head != tail) { node = &list[head]; head = (head + 1) % MAP_BF_SIZE; room = map_search_ses->map->room_list[node->vnum]; if (room->size <= node->size) { continue; } room->size = node->size; if (node->x == map_grid_x && node->y == map_grid_y && node->z == map_grid_z) { map_search_tar_room = node->vnum; pop_call(); return; } for (exit = room->f_exit ; exit ; exit = exit->next) { if (head == (tail + 1) % MAP_BF_SIZE) { break; } if (exit->dir == 0) { continue; } if (HAS_BIT(exit->flags, EXIT_FLAG_HIDE)) { continue; } if (HAS_BIT(map_search_ses->map->room_list[exit->vnum]->flags, ROOM_FLAG_HIDE)) { continue; } xx = node->x + (HAS_BIT(exit->dir, MAP_EXIT_E) ? 1 : HAS_BIT(exit->dir, MAP_EXIT_W) ? -1 : 0); yy = node->y + (HAS_BIT(exit->dir, MAP_EXIT_N) ? 1 : HAS_BIT(exit->dir, MAP_EXIT_S) ? -1 : 0); zz = node->z + (HAS_BIT(exit->dir, MAP_EXIT_U) ? 1 : HAS_BIT(exit->dir, MAP_EXIT_D) ? -1 : 0); temp = &list[tail]; temp->vnum = exit->vnum; temp->x = xx; temp->y = yy; temp->z = zz; temp->size = node->size + 1; tail = (tail + 1) % MAP_BF_SIZE; } } pop_call(); return; } void explore_path(struct session *ses, int run, char *arg1, char *arg2) { struct exit_data *exit; int room, vnum; if (HAS_BIT(ses->flags, SES_FLAG_MAPPING)) { tintin_printf2(ses, "#MAP EXPLORE: You have to stop #PATH TRACKING first."); return; } kill_list(ses->list[LIST_PATH]); room = ses->map->in_room; exit = find_exit(ses, room, arg1); if (exit == NULL) { tintin_printf2(ses, "#MAP: There's no exit named '%s'.", arg1); return; } vnum = exit->vnum; if (HAS_BIT(ses->map->flags, MAP_FLAG_NOFOLLOW)) { insert_node_list(ses->list[LIST_PATH], exit->cmd, "", "0"); } else { insert_node_list(ses->list[LIST_PATH], exit->name, "", "0"); } while (get_map_exits(ses, vnum) == 2) { if (ses->map->room_list[vnum]->f_exit->vnum != room) { exit = ses->map->room_list[vnum]->f_exit; } else { exit = ses->map->room_list[vnum]->l_exit; } if (HAS_BIT(ses->map->flags, MAP_FLAG_NOFOLLOW)) { insert_node_list(ses->list[LIST_PATH], exit->cmd, "", "0"); } else { insert_node_list(ses->list[LIST_PATH], exit->name, "", "0"); } if (HAS_BIT(ses->map->room_list[exit->vnum]->flags, ROOM_FLAG_VOID)) { vnum = follow_void(ses, room, exit->vnum, exit->dir); room = map_search_last_room; } else { room = vnum; vnum = exit->vnum; } } if (run) { path_run(ses, arg2); } }