/*****
Tool to make maps of domains, created by
Hippo@Star Rift / Hippo@Heaven7
(dido.fa.indiana.edu 6666 / salvation.com 7777)
Maps symbols:
x : room
S : room where you started mapping
-|/\X : general exits
E : other kind of exit
other : special room (see SYMBOL_ROOM)
******/
#include <mudlib.h>
#include "/include/fn/linewrap.h"
inherit "/inherit/treasure.c";
#define VER "1.2.1"
#define LOGFILE "done_map.log"
#define HERE file_name(environment(this_object()))
#define EX HERE->query_exits()
#define MA member_array
#define EXIT ({"north","northeast","east","southeast","south","southwest","west","northwest"})
#define SYMBOL ({ "|","/","-","\\","|","/","-","\\","E" })
#define PX ({ 0, 2, 2, 2, 0, -2, -2, -2, 0 })
#define PY ({ -2, -2, 0, 2, 2, 2, 0, -2, 0 })
#define SOMEROOM ({"shop","pub","post","guild","hall","street"})
#define SYMBOL_ROOM ({"s", "p", "P", "g", "h" ,"r" })
mixed *files,*xy;
string map;
int tot,maxx,maxy;
void reset(status arg) {
if(arg) return;
set_name("tracker (Version "+VER+")");
set_id("tracker");
set_short("Tracker (Version "+VER+")");
set_long("\n"+
" .------------------. \n"+
" /' T R A C K E R /| \n"+
" /' a tool to help /' | \n"+
" /' you making maps /' /' \n"+
" |~~~~~~~~~~~~~~~~~~~| /' \n"+
" |___________________|/' \n"+
" `|:. `|. |' :|' \n"+
" `:|:.`|.| :|' \n"+
" `:|`||:|' \n"+
" ``X' \n"+
" ====T==== \n"+
" || ||# || \n"+
" _## ##~ ##_ \n"+
" ~~ \n"+
" <'help tracker' for more info> \n");
}
drop() { return 0; }
get() { return 0; }
void init() {
::init();
add_action("start_map","track");
add_action("bugs","bugs");
add_action("show_files","files");
add_action("show_map","showmap");
add_action("ver","ver");
add_action("help","help");
}
status ver(string str) {
if(str=="tracker") {
write ("\nVersion\tEditor\tDate\tDescription\n"+
"~~~~~~~\t~~~~~~\t~~~~ \t~~~~~~~~~~~\n"+
"1.0.0\tHippo\t06-02-95\tCreation of the tool\n"+
"1.1.0\tHippo\t06-14-95\tMajor debugging finished\n"+
"1.1.1\tHippo\t06-20-95\tAdded useful error messages\n"+
"1.2.1\tHippo\t08-22-95\tAdded symbols for specific rooms\n"+
"");
return 1;
}
return 0;
}
status help(string str) {
if(str=="tracker") {
write("\n"+
"**************************************************************************\n"+
" Tool to make maps of domains (Version "+VER+")\n"+
" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"+
" maps symbols\n"+
" x : room\n"+
" S : the room where the tracker started (change later manually to x)\n"+
" E : room with an irregular exit\n"+
" -|/\\X : doorways\n"+
" other : symbols for specific rooms, explained at the map itselfn"+
"\n"+
" possible commands\n"+
" track : start map-making of the realm where Tracker is now\n"+
" files : shows the filenames and the exit-codes for debugging\n"+
" showmap : shows the map Tracker just created \n"+
" (also written in /players/"+this_player()->query_real_name()+"/"+LOGFILE+")\n"+
" help tracker : this info\n"+
" bugs tracker : what to do in case of new ideas, bugs or problems?\n"+
" ver tracker : information on the creation and updating of Tracker\n"+
"**************************************************************************\n");
return 1;
}
return 0;
}
status bugs(string str) {
if(str=="tracker") {
writelw("If you discover a problem of any kind while using the tracker, "+
"please mail the one who created this version (<ver tracker>) "+
"about it. Include a description in that mail of what "+
"exactly happened (or didn't happen) and where (realm and room) it "+
"occured. If you have a clue to the "+
"problem that caused the error, or if you debugged the Tracker "+
"yourself already, include that information, too! I'll try to fix it, "+
"or reply, telling what went wrong, as soon as possible.\n"+
"Finally, if you have any kind of "+
"comment on this tool, I'd like to hear it from you. Also "+
"suggestions to upgrade the Tracker, or extending its "+
"possibilities are very welcome and will be considered. "+
"\n\nHippo\n");
return 1;
}
return 0;
}
/****************************************************
* For debugging purposes: show_files() and show_map *
****************************************************/
status convert_xy2map() {
int x,y;
for(y=0;y<=maxy;y++) {
for(x=0;x<=maxx;x++) {
map=map+(((string)xy[x][y]==0 || (string)xy[x][y]=="")
? " " : (string)xy[x][y]);
}
map+="\n";
}
map+="\n";
if(maxx>75) {
map=lw("WARNING: "+
"The map might seem a bit messed up, because it exceeds 75 chars "+
"horizontally. The easiest way to solve this problem is to split "+
"it into 2 parts manually.\n");
}
return 1;
}
status show_files() {
int i;
string s;
write("\n n . e . s . w . E\n");
for(i=0;i<=tot;i+=2) {
s=files[i]+" ";
write(extract(s,0,50)+files[i+1]+"\n");
}
return 1;
}
status show_map() {
if(map==0 || map=="") convert_xy2map();
if(map==0 || map=="")
writelw("You didn't create a map, as far as I know. "+
"Type 'help tracker' for more information.");
else write(map+"\n");
return 1;
}
/*****************************************************
* make sure the trackers destruct themselves finally *
*****************************************************/
void destmap(int tel) {
if(tel==0) {
writelw("You can find yourself a new Tracker in "+
file_name(this_object())+"!!\n");
write("Tracker has been destructed.\n");
destruct(this_object());
}
else {
writelw("Tracker will destruct in "+(string)(tel*40)+
" seconds if you don't command Tracker to track a new map.\n");
tel--;
call_out("destmap",40,tel);
}
}
/***********************************************************
* The realm is bugged => bring tracker back to the wizard. *
***********************************************************/
string bugged_room(int this) {
int bugged,i,j;
string *tmp;
i=1; bugged=0;
while(bugged<=tot-this) {
tmp=explode((string)files[this-i]," ");
for(j=0;j<sizeof(tmp);j++) if(tmp[j]=="1") bugged+=2;
i+=2;
}
return files[this-i+1];
}
status bugged_realm(int this) {
writelw("The tracker tells you: It seems to me that "+files[this]+
((file_size(files[this]+".c") > 1) ? " is bugged." : " doesn't exist.")+
" Obviously, an exit from room "+bugged_room(this)+
" refers to that place. Therefore, I can't finish the map now."+
" If you still want to make the map, and the bug cannot be"+
" fixed at this moment, change the concerning exit in"+
" that room into an exitname other than one of "+
implode(EXIT," ")+" and track the realm again.\n");
move_object(this_object(),environment(this_player()));
call_out("destmap",0,5); // make sure the tracker destructs!
return 1;
}
/*************************************************
* Check all rooms for exits (doors are included) *
**************************************************/
status too_long_message() { //this error can't be fixed in a proper way!
writelw("This realm seems quite large. It's possible that "+
"the tracker will quit with the error message "+
"<too long evaluation>. There are three possible methods to "+
"handle this.\n"+
"1. Ask your admin to increase the number "+
"of loops that are allowed to pass by a program.\n"+
"2. Try to decrease the size of the realm by changing a "+
"crucial exit somewhere, create the maps of both parts "+
"seperately and manually make one map of them.\n"+
"3. Change this file in a way that it creates a temporary "+
"file on the disk and add a <continue> command. I'll probably "+
"do this myself when I have more time.\n");
return 1;
}
string convert2fil(string str) {
string s;
if(sscanf(str,"%s.c",s)==1) str=s;
if(extract(str,0,0)=="/") str=extract(str,1);
return str;
}
int is_exit(string str) {
if(MA(str,EX)!=-1) {
if(MA(convert2fil(EX[MA(str,EX)-1]),files)==-1) {
tot+=2;
files[tot]=convert2fil(EX[MA(str,EX)-1]);
return 1;
}
else { return ((convert2fil(EX[MA(str,EX)-1])==HERE) ? 0 : 2); }
}
return 0;
}
status extra_ex() {
int j;
for(j=1;j<sizeof(EX);j+=2) if(MA(EX[j],EXIT)==-1) return 1;
return 0;
}
status make_file_string() {
int i,this;
status mess;
tot=0; this=0; mess=0;
files[this]=HERE;
while(tot>=this && files[this]!="") {
this++;
for(i=0;i<sizeof(EXIT);i++) files[this]+=(string)is_exit(EXIT[i])+" ";
files[this]+=(string)extra_ex()+" ";
this++;
call_out("bugged_realm",2,this);
/* if files[this] is bugged, program will quit at next line */
if(files[this]!="") move_object(this_object(),files[this]);
remove_call_out("bugged_realm"); // if files[this] was not bugged
if(tot>10 && !mess) { too_long_message(); mess=1; }
}
writelw("There are "+tot+" rooms in this realm. "+
"The actual map is being produced now.\n");
return 1;
}
/********************************************
* The files are checked, now make the map: *
********************************************/
status move_x(int ii) {
int j,k;
maxx=maxx-PX[ii];
for(j=0;j<=maxy;j++) {
for(k=maxx;k>=-PX[ii];k--) xy[k][j] = xy[k+PX[ii]][j];
for(k=0;k<-PX[ii];k++) xy[k][j]=0;
}
return 1;
}
status move_y(int ii) {
int j,k;
maxy=maxy-PY[ii];
for(j=0;j<=maxx;j++) {
for(k=maxy;k>=-PY[ii];k--) xy[j][k] = xy[j][k+PY[ii]];
for(k=0;k<-PY[ii];k++) xy[j][k]=0;
}
return 1;
}
status make_actual_map() {
int i,j,k,l,m,n,t,x,y;
mixed *vx,*vy, *done;
string *tmp,s,s1,s2;
done=allocate(sizeof(SYMBOL_ROOM));done=({});
tmp=allocate(sizeof(SYMBOL));
vx=allocate(tot); vy=allocate(tot);
x=0; y=0; t=0; n=0; maxx=0; maxy=0; xy[0][0]="S";
while(files[t*2] && files[t*2]!="") {
tmp=explode((string)files[t*2+1]," ");
for(i=0;i<9;i++) {
if(tmp[i]!="0") {
if(tmp[i]=="1") {
if(i!=8) n++;
if(x+PX[i]<0) {
x-=PX[i];
move_x(i);
for(m=n;m>t;m--) vx[m]=vx[m]-PX[i];
}
if(y+PY[i]<0) {
y-=PY[i];
move_y(i);
for(m=n;m>t;m--) vy[m]=vy[m]-PY[i];
}
if(i==8) { xy[x+PX[i]][y+PY[i]] = "E"; }
else {
j=0;
s=files[t*2]->short();
while(j<sizeof(SOMEROOM) &&
sscanf(s,"%s"+capitalize(SOMEROOM[j])+"%s",s1,s2)==0 &&
sscanf(s,"%s"+SOMEROOM[j]+"%s",s1,s2)==0) j++;
if(j<sizeof(SOMEROOM)) {
xy[x+PX[i]][y+PY[i]] = SYMBOL_ROOM[j];
if(MA(SYMBOL_ROOM[j],done)==-1) {
done+=({SYMBOL_ROOM[j],});
map+=SYMBOL_ROOM[j]+": "+capitalize(SOMEROOM[j])+"\n";
}
}
else { xy[x+PX[i]][y+PY[i]]="x"; }
vx[n]=x+PX[i]; vy[n]=y+PY[i];
}
if(x+PX[i]>maxx) maxx=x+PX[i];
if(y+PY[i]>maxy) maxy=y+PY[i];
k=x+(int)PX[i]/2; l=y+(int)PY[i]/2;
if(xy[k][l]==SYMBOL[1] || xy[k][l]==SYMBOL[3]) xy[k][l]="X";
else xy[k][l] = SYMBOL[i];
}
else { xy[x+(int)PX[i]/2][y+(int)PY[i]/2] = SYMBOL[i]; }
}
}
t++; x=vx[t]; y=vy[t];
}
return 1;
}
status start_map() {
string creator;
int i;
files=allocate(300); for(i=0;i<sizeof(files);i++) files[i]="";
creator=call_other(this_player(),"query_real_name");
if(call_other(this_player(),"query_security_level")<20)
{ write("You're not allowed to use this tool!.\n");
destruct(this_object());
return 1;
}
while(remove_call_out("destmap") > -1) remove_call_out("destmap");
map="";
make_file_string();
xy=allocate(tot); // 'tot' was calculated in 'make_file_string()'
for(i=0;i<sizeof(xy);i++) xy[i]=allocate(80);
move_object(this_object(),environment(find_living(creator)));
make_actual_map();
convert_xy2map();
map=map+"\n ** Map created by "+capitalize(creator)+" on "+ctime()+" **\n";
write_file("/players/"+creator+"/"+LOGFILE,map);
write("Tracker tells you: Done with map-making.\n"+
"Final MAP (logged to the file /players/"+creator+"/"+LOGFILE+"): \n"+map+"\n");
call_out("destmap",0,5);
return 1;
}