/* MTF v1.0 Rywfol 990910 */
#include "mtfincl.h";
mixed *map;
mapping key_data;
class map_class {
string filename;
int counter;
string inheritname;
string basename;
string short;
string long;
mapping exits;
}
class exit {
string dest;
int ypos;
int xpos;
}
/*
* Find how the rooms interconnect.
* We look in a square around the item for + & - chars.
* If we find one we've found an exit.
*/
mapping get_exits(int ypos, int xpos) {
int x, y;
class map_class data;
mapping exits = ([ ]);
if(!classp(map[ypos][xpos]))
return ([ ]);
// check the rooms either side of this one.
for(y = -1; y < 2; y++) {
if((y*2)+ypos < 0)
continue;
if((y*2)+ypos >= sizeof(map))
continue;
for(x = -1; x < 2; x++) {
if((x*2)+xpos < 0)
continue;
if((x*2)+xpos >= sizeof(map[(y*2)+ypos]))
continue;
if(!x && !y)
continue;
if(classp(map[(y*2)+ypos][(x*2)+xpos])) {
data = map[(y*2)+ypos][(x*2)+xpos];
if((map[y+ypos][x+xpos] == '*') ||
(map[y+ypos][x+xpos] == '+' && (y == 0 || x == 0)) ||
(map[y+ypos][x+xpos] == 'x' && (y != 0 && x != 0)) ||
(map[y+ypos][x+xpos] == '|' && y != 0 && x == 0) ||
(map[y+ypos][x+xpos] == '-' && y == 0 && x != 0) ||
(map[y+ypos][x+xpos] == '\\' && y == -1 && x == -1) ||
(map[y+ypos][x+xpos] == '\\' && y == 1 && x == 1) ||
(map[y+ypos][x+xpos] == '/' && y == 1 && x == -1) ||
(map[y+ypos][x+xpos] == '/' && y == -1 && x == 1)) {
exits[DIRECTIONS[y+1][x+1]] = new(class exit,
dest : upper_case(data->basename)+
" + \"" + data->filename + "\"",
ypos : y+ypos,
xpos : x+xpos);
} else if(map[y+ypos][x+xpos] != ' ') {
debug_printf("Unknown direction char: %O (%c), %d - %d, %d - %d %O %s",
map[y+ypos][x+xpos], map[y+ypos][x+xpos], x, xpos, y, ypos,
map[ypos][xpos],
data->basename);
}
}
}
}
// debug_printf("%0", exits);
return exits;
}
#ifdef 0
/*
*
*/
mixed *find_nearby(int ypos, int xpos, int distance, int direc) {
string *dirs;
int ny, nx;
class exit tmp;
if(distance > 4)
return 0;
if(!classp(map[ypos][xpos]))
return 0;
dirs = keys(map[ypos][xpos]->exits);
if(direc >= sizeof(dirs))
return 0;
tmp = map[ypos][xpos]->exits;
ny = tmp[]->ypos;
nx = tmp[]->xpos;
if(nx == xpos && ny == ypos) {
if(direc == sizeof(dirs) -1)
return 0;
else
direc++;
}
if(!find_nearby(ny, nx, ++distance);
}
#endif
/*
* This is a lot like get_exits except that it goes further along the road.
*/
string calc_long(int ypos, int xpos) {
int x, y, sameroad;
class map_class data;
string *exits = ({ });
string *junctions = ({ });
string long_str;
mixed *nearby;
if(!classp(map[ypos][xpos]))
return "";
/*
* First we'll see how many exits we have that lead to this road.
* 0 == end of the road
* 1 == nothing special
* 2 == fork
*/
sameroad = 0;
for(y = -1; y < 2; y++) {
if((y*2)+ypos < 0)
continue;
if((y*2)+ypos >= sizeof(map))
continue;
for(x = -1; x < 2; x++) {
if((x*2)+xpos < 0)
continue;
if((x*2)+xpos >= sizeof(map[(y*2)+ypos]))
continue;
if(!x && !y)
continue;
if(classp(map[(y*2)+ypos][(x*2)+xpos])) {
data = map[(y*2)+ypos][(x*2)+xpos];
// Do we have another room in this road?
if(map[y+ypos][x+xpos] == '+' &&
map[ypos][xpos]->basename ==
map[(y*2)+ypos][(x*2)+xpos]->basename) {
sameroad++;
exits += ({ DIRECTIONS[y+1][x+1] });
}
}
}
}
// check the rooms either side of this one to see if this is a junction.
for(y = -1; y < 2; y++) {
if((y*2)+ypos < 0)
continue;
if((y*2)+ypos >= sizeof(map))
continue;
for(x = -1; x < 2; x++) {
if((x*2)+xpos < 0)
continue;
if((x*2)+xpos >= sizeof(map[(y*2)+ypos]))
continue;
if(!x && !y)
continue;
if(classp(map[(y*2)+ypos][(x*2)+xpos])) {
data = map[(y*2)+ypos][(x*2)+xpos];
// Do we have a junction?
if(((map[y+ypos][x+xpos] == '*') ||
(map[y+ypos][x+xpos] == '+' && (y == 0 || x == 0)) ||
(map[y+ypos][x+xpos] == 'x' && (y != 0 && x != 0)) ||
(map[y+ypos][x+xpos] == '|' && y != 0 && x == 0) ||
(map[y+ypos][x+xpos] == '-' && y == 0 && x != 0) ||
(map[y+ypos][x+xpos] == '\\' && y == -1 && x == -1) ||
(map[y+ypos][x+xpos] == '\\' && y == 1 && x == 1) ||
(map[y+ypos][x+xpos] == '/' && y == 1 && x == -1) ||
(map[y+ypos][x+xpos] == '/' && y == -1 && x == 1)) &&
map[ypos][xpos]->basename !=
map[(y*2)+ypos][(x*2)+xpos]->basename) {
if(member_array(map[(y*2)+ypos][(x*2)+xpos]->short, junctions) == -1)
junctions += ({ map[(y*2)+ypos][(x*2)+xpos]->short });
}
}
}
}
#ifdef 0
// Not a junction so lets start looking for junctions nearby.
if(!sizeof(junctions)) {
nearby = find_nearby(ypos, xpos);
}
#endif
/*
* Build the long desc using priorities of things.
*/
long_str = "This is ";
if(sizeof(junctions)) {
long_str += map[ypos][xpos]->short + " at the junction with " +
query_multiple_short(junctions) +
".\n";
} else if(sameroad == 0) {
long_str += "the end of " + map[ypos][xpos]->short;
} else if(sameroad == 1) {
long_str += "a fork in " + map[ypos][xpos]->short +
" where it splits heading " +
query_multiple_short(exits);
} else {
long_str += map[ypos][xpos]->short;
}
// debug_printf("%O", exits);
return long_str;
}
/*
* Write the file out.
*/
int write_this_file(string fdir, int ypos, int xpos) {
class map_class room;
string str, tmp, exit;
mapping exits;
int i;
room = map[ypos][xpos];
str = "#include \"path.h\";\n\n";
str += "inherit " + room->inheritname + ";\n";
str += "\n";
str += "void setup() {\n";
str += " set_short(\"" + room->short + "\");\n";
str += " set_long(\"" + room->long + "\\n\");\n";
str += " set_light( 80 );\n";
// Build the exits into the string
exits = room->exits;
foreach(exit in keys(exits)) {
/*
* A little wizardry.
* ne,se,sw,nw are all odd numbered in the array.
* so, if we have an odd numbered exit and the exits on either side of it
* also exist then make it secret. This stops courtyards getting
* overcrowded with exits.
*/
i = member_array(exit, DIRECTIONS);
if(i % 2 == 1 &&
exits[DIRECTIONS[i-1]] &&
exits[DIRECTIONS[(i+1) % sizeof(DIRECTIONS)]])
str += sprintf(" add_exit(\"%s\", %s, \"secret\");\n",
exit, exits[exit]->dest);
else
str += sprintf(" add_exit(\"%s\", %s, \"road\");\n",
exit, exits[exit]->dest);
}
str += "}\n";
// Create the directory if necessary and a path.h to go in it.
if(file_size(fdir + "/" + room->basename) != -2) {
mkdir(fdir + "/" + room->basename);
tmp = "#include \"../path.h\"\n";
tmp += "#undef PATH\n";
tmp += "#define PATH __DIR__\n";
write_file(fdir + "/" + room->basename + "/path.h", tmp, 1);
}
// debug_printf("Str: %s", str);
return write_file( fdir + "/" + room->basename + "/" + room->filename + ".c",
str, 1 );
}
/**
* Read the map into a mixed array (be better if it was a class.
*/
mixed *read_map(string mapfile) {
int i, j;
mixed *temp_map;
string *lines;
lines = explode(read_file(mapfile), "\n");
temp_map = allocate(sizeof(lines));
for(i=0; i<sizeof(lines); i++) {
temp_map[i] = allocate(strlen(lines[i]));
for(j=0; j<strlen(lines[i]); j++) {
if(key_data[lines[i][j]]) {
// inc the room count.
// debug_printf("%c:%s", lines[i][j], key_data[lines[i][j]][2]);
key_data[lines[i][j]][0] = to_int(key_data[lines[i][j]][0]) + 1;
if(sizeof(key_data[lines[i][j]]) < 4)
debug_printf("Key data too small: %O", key_data[lines[i][j]]);
temp_map[i][j] = new(class map_class,
filename : key_data[lines[i][j]][2] +
key_data[lines[i][j]][0],
counter : key_data[lines[i][j]][0],
inheritname : key_data[lines[i][j]][1],
basename : key_data[lines[i][j]][2],
short : key_data[lines[i][j]][3]);
} else
temp_map[i][j] = lines[i][j];
}
}
return temp_map;
}
/* Read the key file into a mapping.
* The mapping is indexed by key character and contains
* ({ counter, inheritname, filename, name })
* counter is the start value for the counter (so we can start a street at some
* value if we've already got rooms for it from another map).
* inheritname is the name of the file to be inherited
* filename is the base filename for the room eg. short
* name is the name of the street eg. Short Street.
*/
mapping read_keys(string keyfile) {
mapping key_data;
string line, *lines;
key_data = ([ ]);
lines = explode(read_file(keyfile), "\n");
foreach(line in lines) {
key_data[line[0]] = explode(line[1..], "\t");
//debug_printf("%c: %s", line[0], key_data[line[0]][2]);
}
return key_data;
}
/* Do the actual mapping */
int map_to_files( string mapfile, string fdir, string keyfile ) {
int tot;
string *file_tmp;
string pstr;
int x, y;
if(!mapfile || mapfile == "")
return NO_MAP_FILE;
file_tmp = this_player()->get_files(mapfile);
if(!file_tmp || sizeof(file_tmp) != 1 || file_size(file_tmp[0]) < 1)
return NO_MAP_FILE;
else
mapfile = file_tmp[0];
if(!fdir || fdir == "")
file_tmp = ({ this_player()->query_path() });
else
file_tmp = this_player()->get_files(fdir);
if(!file_tmp || sizeof(file_tmp) != 1 || file_size(file_tmp[0]) != -2)
return NO_FILE_DIR;
else
fdir = file_tmp[0];
if(!keyfile || keyfile == "" )
keyfile = DEFAULT_KEYS;
file_tmp = this_player()->get_files(keyfile);
if(sizeof(file_tmp) != 1 || file_size(file_tmp[0]) < 1)
return NO_KEY_FILE;
else
keyfile = file_tmp[0];
key_data = read_keys(keyfile);
map = read_map(mapfile);
// debug_printf("Map read %O", map);
// go through the map line by line.
for(y = 0; y < sizeof(map); y++)
for(x = 0; x < sizeof(map[ y ]); x++)
if(classp(map[y][x])) {
map[y][x]->exits = get_exits(y, x);
}
reset_eval_cost();
for(y = 0; y < sizeof(map); y++)
for(x = 0; x < sizeof(map[ y ]); x++)
if(classp(map[y][x]))
map[y][x]->long = calc_long(y, x);
reset_eval_cost();
for(y = 0; y < sizeof(map); y++)
for(x = 0; x < sizeof(map[ y ]); x++)
if(classp(map[y][x]))
tot += write_this_file(fdir, y, x);
pstr = "/* Created at " + ctime( time() ) + " */\n";
pstr += "#define CITYROOM \"/d/am/cityroom\"\n";
pstr += "#undef CITY\n";
pstr += "#define CITY \"" + fdir + "/\"\n";
foreach(x in keys(key_data))
pstr += "#define " + upper_case(key_data[x][2]) + " CITY + \"" + key_data[x][2] +
"/\"\n";
tot += write_file( fdir+ "/path.h", pstr, 1 );
return tot;
}