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