/
lib/banish/
lib/d/coronos/
lib/d/coronos/w/alena/
lib/d/coronos/w/angel/
lib/d/coronos/w/angel/caves/
lib/d/coronos/w/angel/caves/monst/
lib/d/coronos/w/angel/city/chambers/
lib/d/coronos/w/angel/city/monst/
lib/d/coronos/w/angel/city/obj/
lib/d/coronos/w/angel/city/streets/
lib/d/coronos/w/angel/farms/plains/
lib/d/coronos/w/angel/monst/
lib/d/tempus/
lib/d/tempus/w/angel/
lib/d/tempus/w/kingbill/
lib/d/tempus/w/mirak/
lib/d/tempus/w/mirak/monst/
lib/d/tempus/w/mirak/obj/
lib/d/tempus/w/relgar/planes/baat/
lib/d/tempus/w/sarak/
lib/d/tempus/w/serepion/mon/
lib/d/tempus/w/valrejn/
lib/doc/
lib/doc/domains/
lib/doc/efun/
lib/include/fn_specs/
lib/info/
lib/inherit/base/
lib/log/
lib/log/mailbox/
lib/log/main/
lib/news/
lib/obj/party/
lib/objects/componen/
lib/open/
lib/open/party/
lib/open/paste/
lib/open/spells/
lib/open/valrejn/
lib/players/
lib/players/alena/
lib/players/alena/obj/
lib/players/alena/open/
lib/players/alena/private/
lib/players/angel/
lib/players/angel/obj/
lib/players/ash/
lib/players/biggs/
lib/players/biggs/food/
lib/players/biggs/gobkeep/
lib/players/biggs/mnstr/
lib/players/biggs/town/caves/
lib/players/biggs/town/tower/
lib/players/biggs/wpns/
lib/players/calris/
lib/players/deathurg/
lib/players/deathurg/open/
lib/players/deathurg/private/thief/
lib/players/dogberry/
lib/players/dogberry/library/
lib/players/dogberry/open/
lib/players/epsilon/
lib/players/epsilon/private/
lib/players/farewell/
lib/players/hippo/
lib/players/hippo/open/
lib/players/hippo/tools/
lib/players/jimpa/
lib/players/josh/
lib/players/josh/room/
lib/players/josh/room/mage/dungeon/
lib/players/josh/room/mage/dungeon/obj/
lib/players/josh/wep/
lib/players/kingbill/
lib/players/metatron/
lib/players/miette/
lib/players/mirak/
lib/players/mirak/open/
lib/players/parsilan/
lib/players/relgar/
lib/players/relgar/private/
lib/players/sarak/
lib/players/sarak/bugs/
lib/players/sarak/feelings/
lib/players/sarak/magical/
lib/players/sarak/minotaur/island/
lib/players/sarak/open/
lib/players/sarak/private/
lib/players/serepion/
lib/players/serepion/open/
lib/players/serepion/private/
lib/players/spike/
lib/players/spike/open/
lib/players/spike/private/
lib/players/spike/seaworld/
lib/players/valrejn/
lib/players/valrejn/open/
lib/players/valrejn/private/
lib/players/virus/
lib/players/wrath/
lib/players/wrath/arm/
lib/players/wrath/mon/
lib/players/wrath/room/
lib/players/wrath/room/entry/
lib/players/wrath/room/zolgath/
lib/players/wrath/weap/
lib/players/zil/
lib/room/
lib/room/city/arena/
lib/room/city/creator/
lib/room/city/garden/monst/
lib/room/city/library/
lib/room/city/library/open/books/
lib/room/city/shop/
lib/room/death/
lib/room/death/open/
lib/room/island/
lib/room/keeps/
lib/room/registry/
lib/room/ships/crew/
lib/room/ships/open/
lib/room/ships/open/types/bounty/
lib/room/ships/open/types/nebula/
lib/room/ships/open/types/phoenix/
lib/secure/udp_cmd_/
lib/skills/
lib/skills/fighter/
lib/skills/psionici/
lib/skills/thief/
lib/usr/
lib/usr/creators/
lib/usr/no_banis/
lib/usr/players/
/*****
  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;
}