I've fixed up some of the things from the ascii map on circlemud.org. Here's how to add the new one:
-Rikishi
1. Open utils.h, somewhere in the file add this:
#define MAPS(a, b, c) ((b) < (a) ? (a) : ((b) > (c) ? (c) : (b)))
2. close utils.h
3. Open act.informative.c, and: find send_to_char(ch, "%s", world[target_room].description);
under that add:
do_map(ch, " ");
4. now open Makefile. Then add the map.o, and map.c in the right spots.
5. now in interpreter.c define do_map as a command
6. open map.c, now that made a new file, now add this:
#include "conf.h"
#include "sysdep.h"
#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "interpreter.h"
#include "handler.h"
#include "db.h"
#include "spells.h"
#include "house.h"
#include "constants.h"
#include "dg_scripts.h"
#define MAX_MAP 72
#define MAX_MAP_DIR 4
#define SECT_MAX 22
extern struct room_data *world;
int add_to_save_list(zone_vnum zone, int type);
int can_edit_zone(struct char_data *ch, int number);
int map[MAX_MAP][MAX_MAP];
int offsets[4][2] ={ {-1, 0},{ 0, 1},{ 1, 0},{ 0, -1} };
/* Heavily modified - Edward */
void MapArea(room_rnum room, struct char_data *ch, int x, int y, int min, int max)
{
room_rnum prospect_room;
struct room_direction_data *pexit;
int door;
/* marks the room as visited */
map[x][y] = world[room].sector_type;
/* Otherwise we get a nasty crash */
/* if (!IS_SET(world[ch->in_room].room_flags, ROOM_WILDERNESS))
return;*/
for ( door = 0; door < MAX_MAP_DIR; door++ ) {
if ( (pexit = world[room].dir_option[door]) > 0 &&
(pexit->to_room > 0 ) &&
(!IS_SET(pexit->exit_info, EX_CLOSED)))
{
if ( (x < min) || ( y < min) || ( x > max ) || ( y >max) ) return;
prospect_room = pexit->to_room;
/* one way into area OR maze */
/* if not two way */
if ( world[prospect_room].dir_option[rev_dir[door]] &&
world[prospect_room].dir_option[rev_dir[door]]->to_room != room)
{
map[x][y] = SECT_MAX + 1;
return;
}
/* end two way */
/* players cant see past these */
if ( (world[prospect_room].sector_type == SECT_CITY)
||(world[prospect_room].sector_type == SECT_HILLS)
||(world[prospect_room].sector_type == SECT_INSIDE))
{
map[x+offsets[door][0]][y+offsets[door][1]] = world[prospect_room].sector_type;
/* ^--two way into area */
}
if ( map[x+offsets[door][0]][y+offsets[door][1]] == SECT_MAX ) {
MapArea(pexit->to_room,ch,x + offsets[door][0], y + offsets[door][1], min, max);
}
} /* end if exit there */
}
return;
}
/* mlk :: shows a map, specified by size */
void ShowMap( struct char_data* ch, int min, int max)
{
int x, y;
/* every row */
for (x = min; x < max; ++x) {
/* every column */
for (y = min; y < max; ++y) {
if ( (y==min) || (map[x][y-1]!=map[x][y]) ) {
switch(map[x][y]) {
case SECT_MAX: send_to_char(ch," "); break;
case SECT_FOREST: send_to_char(ch,"@g@"); break;
case SECT_FIELD: send_to_char(ch,"@G\""); break;
case SECT_HILLS: send_to_char(ch,"@G^"); break;
case SECT_MOUNTAIN: send_to_char(ch,"@y^"); break;
case SECT_WATER_SWIM: send_to_char(ch,"@B:"); break;
case SECT_WATER_NOSWIM:send_to_char(ch,"@b:"); break;
case SECT_INSIDE: send_to_char(ch,"@W@"); break;
case SECT_CITY: send_to_char(ch,"@W#"); break;
case (SECT_MAX+1): send_to_char(ch,"@D?"); break;
default: send_to_char(ch,"@R*"); break;
}
}
else {
switch(map[x][y]) {
case SECT_MAX: send_to_char(ch," "); break;
case SECT_FOREST: send_to_char(ch,"@"); break;
case SECT_FIELD: send_to_char(ch,"\""); break;
case SECT_HILLS: send_to_char(ch,"^"); break;
case SECT_MOUNTAIN: send_to_char(ch,"^"); break;
case SECT_WATER_SWIM:send_to_char(ch,":"); break;
case SECT_WATER_NOSWIM:send_to_char(ch,":"); break;
case SECT_INSIDE: send_to_char(ch,"@"); break;
case SECT_CITY: send_to_char(ch,"#"); break;
case (SECT_MAX+1): send_to_char(ch,"?"); break;
default: send_to_char(ch,"*");
}
}
}
send_to_char(ch,"\n\r");
}
return;
}
/* This is for simplicities sake, if the room's name if
** like An unfinished room, it will replace it with a fake
** room name here - Edward
*/
void get_room_name(struct char_data *ch, int argument)
{
char buf[500];
switch(argument) {
case SECT_MAX:
sprintf(buf,"&n &cThe Wilderness&n");break;
case SECT_FOREST:
sprintf(buf,"&n &cWithin a Forest&n");break;
case SECT_FIELD:
sprintf(buf,"&n &cOn an Open Field&n");break;
case SECT_HILLS:
sprintf(buf,"&n &cOn a Hill&n");break;
case SECT_MOUNTAIN:
sprintf(buf,"&n &cClimbing a Mountain&n");break;
case SECT_WATER_SWIM:
sprintf(buf,"&n &cIn Shallow Water&n");break;
case SECT_WATER_NOSWIM:
sprintf(buf,"&n &cAdrift In Deep Water&n");break;
case SECT_INSIDE:
sprintf(buf,"&n &cThe Wilderness&n");break;
case SECT_CITY:
sprintf(buf,"&n &cWithin a City&n");break;
case (SECT_MAX+1):
sprintf(buf,"&n &cThe Wilderness&n");break;
default:
sprintf(buf,"&n &cThe Wilderness&n");break;
}
send_to_char(ch, buf);
}
/* will put a small map with current room desc and title */
/* this is the main function to show the map, its do_map with " " */
/* Heavily modified - Edward */
void ShowRoom( struct char_data *ch, int min, int max)
{
int x, y;
char buf[500];
char desc[500];
strcpy(desc,world[ch->in_room].description);
/* mlk :: rounds edges */
map[min][min]=SECT_MAX;map[max-1][max-1]=SECT_MAX;
map[min][max-1]=SECT_MAX;map[max-1][min]=SECT_MAX;
/* every row */
for (x = min; x < max; ++x) {
/* every column */
for (y = min; y < max; ++y) {
if ( (y==min) || (map[x][y-1]!=map[x][y]) )
switch(map[x][y]) {
case SECT_MAX: send_to_char(ch," "); break;
case SECT_FOREST: send_to_char(ch,"@g@"); break;
case SECT_FIELD: send_to_char(ch,"@G\""); break;
case SECT_HILLS: send_to_char(ch,"@G^"); break;
case SECT_MOUNTAIN: send_to_char(ch,"@y^"); break;
case SECT_WATER_SWIM: send_to_char(ch,"@B:"); break;
case SECT_WATER_NOSWIM: send_to_char(ch,"@b:"); break;
case SECT_INSIDE: send_to_char(ch,"@W@"); break;
case SECT_CITY: send_to_char(ch,"@W#"); break;
case (SECT_MAX+1): send_to_char(ch,"@D?"); break;
default: send_to_char(ch,"@R*"); break;
}
else
switch(map[x][y]) {
case SECT_MAX: send_to_char(ch," "); break;
case SECT_FOREST:send_to_char(ch,"@"); break;
case SECT_FIELD: send_to_char(ch,"\""); break;
case SECT_HILLS: send_to_char(ch,"^"); break;
case SECT_MOUNTAIN: send_to_char(ch,"^"); break;
case SECT_WATER_SWIM: send_to_char(ch,":"); break;
case SECT_WATER_NOSWIM: send_to_char(ch,":"); break;
case SECT_INSIDE: send_to_char(ch,"@"); break;
case SECT_CITY: send_to_char(ch,"#"); break;
case (SECT_MAX+1): send_to_char(ch,"?"); break;
default: send_to_char(ch,"*"); break;
}
}
if (x == min) {
if (!strcmp(world[ch->in_room].name, "The Wilderness") ||
!strcmp(world[ch->in_room].name, "An unfinished room"))
get_room_name(ch, world[ch->in_room].sector_type);
else {
sprintf(buf," ");
send_to_char(ch, buf);
}
if (GET_LEVEL(ch) >= LVL_IMMORT) {
sprintf(buf," @c[@RRoom @Y%d@c]@n", world[ch->in_room].number);
send_to_char(ch, buf);
}
}
/* I removed the room descriptions from the ascii map, the map is descriptive enough
** I think - Edward. Just remove the comments if you want them back.
else {
start = str_pos;
for (desc_pos = desc_pos ; desc[desc_pos]!='\0' ; desc_pos++) {
if (desc[desc_pos]=='\n') {
line[str_pos-start]='\0';
str_pos += 3;
desc_pos += 2;
break;
}
else if (desc[desc_pos]=='\r') {
line[str_pos-start]='\0';
str_pos += 2;
break;
}
else {
line[str_pos-start]=desc[desc_pos];
str_pos += 1;
}
}
line[str_pos-start]='\0';
if (x == min + 1) send_to_char(" ", ch);
send_to_char(" &c", ch);
send_to_char(line, ch);
send_to_char("&n",ch);
}
*/
send_to_char(ch,"\n\r");
}
send_to_char(ch,"\n\r"); /* puts a line between contents/people */
return;
}
/* This is the main map function, do_map(ch, " ") is good to use */
/* do_map(ch "number") is for immortals to see the world map */
/* Edward: If you play with some of the values here you can make the normal
** map people see larger or smaller. size = URANGE(9, size, MAX_MAP), the 9
** is the map size shown by default. Also look for: ShowMap (ch, min, max+1);
** and change the size of min and max and see what you like.
*/
void do_map( struct char_data *ch, char *argument )
{
int size, center, x, y, min, max;
char arg1[10];
one_argument( argument, arg1 );
size = atoi(arg1);
size = MAPS(10,size,MAX_MAP);
center = MAX_MAP/2;
min = MAX_MAP/2 - size/2;
max = MAX_MAP/2 + size/2;
for (x = 0; x < MAX_MAP; ++x)
for (y = 0; y < MAX_MAP; ++y)
map[x][y]=SECT_MAX;
/* starts the mapping with the center room */
MapArea(ch->in_room, ch, center, center, min-1, max-1);
/* marks the center, where ch is */
map[center][center] = SECT_MAX+2; /* can be any number above SECT_MAX+1 */
/* switch default will print out the * */
if ( (GET_LEVEL(ch) < LVL_IMMORT)||(IS_NPC(ch)) ) {
/* if ( !IS_SET(world[ch->in_room].room_flags, ROOM_WILDERNESS) ) {
send_to_char(ch, "&CYou can not do that here&n.\n\r");return;}*/
if ( IS_DARK(ch->in_room) ) {
send_to_char(ch, "&bThe wilderness is pitch black at night... &n\n\r");
return;
}
else {
ShowRoom(ch,MAX_MAP/2-3,MAX_MAP/2+3);
return;
}
}
/* mortals not in city, enter or inside will always get a ShowRoom */
if (GET_LEVEL(ch) >= LVL_IMMORT) {
if (arg1[0] == '\0')
ShowRoom (ch, min, max+1);
else
ShowMap (ch, min, max+1);
return;
}
send_to_char(ch,"@CHuh?&n\n\r");
return;
}