/****************************************************************************
* [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