/****************************************************************************
* [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[MAX_STRING_LENGTH];
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[MAX_STRING_LENGTH];
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[MAX_STRING_LENGTH];
char buf[MAX_STRING_LENGTH];
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[MAX_STRING_LENGTH];
char arg[MAX_INPUT_LENGTH];
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
char arg3[MAX_INPUT_LENGTH]; /* growl */
char arg4[MAX_INPUT_LENGTH]; /* 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 );
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[MAX_STRING_LENGTH];
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