home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / games / tinymud2.zip / EXTRACT.C < prev    next >
C/C++ Source or Header  |  1990-09-02  |  11KB  |  451 lines

  1. #include "copyright.h"
  2.  
  3. #include <stdio.h>
  4. #include <ctype.h>
  5. #include <sys/param.h>
  6.  
  7. #include "db.h"
  8.  
  9. static int include_all = 0;    /* include everything unless specified */
  10. static int keep_players = 0;    /* keep all players */
  11. static int safe_below = 1;    /* Keep everything <= safe_below */
  12. static int safe_above = 2e9;    /* Keep everything >= safe_above */
  13. static int reachable = 0;    /* Only keep rooms reachable from #0 */
  14. static int norecycle = 0;    /* Exclude things in recycling center */
  15. static int inbuild = 0;        /* True when in main nuild_trans loop */
  16. static int recycling_center = 0;/* Room number home("Recycler") */
  17.  
  18. # define REACH_FLAG 0x40000000
  19. # define REACHABLE(X) (db[X].flags & REACH_FLAG)
  20. # define SET_REACHABLE(X) (db[X].flags |= REACH_FLAG)
  21.  
  22. static dbref included[NCARGS+1];
  23. static dbref excluded[NCARGS+1];
  24.  
  25. static dbref *trans;        /* translation vector */
  26.  
  27. #define DEFAULT_LOCATION (0)
  28. #define DEFAULT_OWNER (1)
  29.  
  30. static int isok(dbref);
  31.  
  32. /* returns 1 if object is specifically excluded */
  33. static int is_excluded(dbref x)
  34. {
  35.     int i;
  36.  
  37.     if(x == NOTHING) return 0; /* Don't exclude nothing */
  38.  
  39.     /* check that it isn't excluded */
  40.     for(i = 0; excluded[i] != NOTHING; i++) {
  41.     if(excluded[i] == x) return 1; /* always exclude specifics */
  42.         if(excluded[i] == db[x].owner) return 1;
  43.     }
  44.  
  45.     return (0);
  46. }
  47.  
  48. /* returns 1 if it is not excluded */
  49. static int not_excluded(dbref x)
  50. {
  51.     int i;
  52.  
  53.     if(x == NOTHING) return 1; /* Don't exclude nothing */
  54.  
  55.     /* check that it isn't excluded */
  56.     for(i = 0; excluded[i] != NOTHING; i++) {
  57.     if(excluded[i] == x) return 0; /* always exclude specifics */
  58.         if(excluded[i] == db[x].owner) return 0;
  59.     }
  60.  
  61.     /* if it's an exit, check that its destination is ok */
  62.     if(Typeof(x) == TYPE_EXIT && db[x].location >= 0) {
  63.     return isok(db[x].location);
  64.     } else {
  65.     return 1;
  66.     }
  67. }
  68.  
  69. /* returns 1 if it should be included in translation vector */
  70. static int isok(dbref x)
  71. {
  72.     int i;
  73.  
  74.     if(x == DEFAULT_OWNER || x == DEFAULT_LOCATION) return 1;
  75.     if(x == NOTHING) return 1;
  76.     
  77.     for(i = 0; included[i] != NOTHING; i++) {
  78.     if(included[i] == x) return 1; /* always get specific ones */
  79.     
  80.     if(reachable && Typeof(x) == TYPE_ROOM && !REACHABLE(x))
  81.     { 
  82. # ifdef DEBUG
  83.       if (inbuild)
  84.         fprintf (stderr, "Excluding %s(%dR), not reachable\n", 
  85.              db[x].name, x);
  86. # endif
  87.           return 0;
  88.     }
  89.     
  90.     if(norecycle && db[x].location == recycling_center) return 0;
  91.  
  92.     if(included[i] == db[x].owner 
  93.        || (x <= safe_below || x >= safe_above)
  94.        || keep_players && Typeof(x) == TYPE_PLAYER) {
  95.         return not_excluded(x);
  96.     }
  97.     }
  98.  
  99.     /* not in the list, can only get it if include_all is on */
  100.     /* or it's owned by DEFAULT_OWNER */
  101.     return (include_all && not_excluded(x));
  102. }
  103.  
  104. static void build_trans(void)
  105. {
  106.     dbref i;
  107.     dbref val;
  108.  
  109.     if((trans = (dbref *) malloc(sizeof(dbref) * db_top)) == 0) {
  110.     abort();
  111.     }
  112.     
  113.     inbuild++;
  114.  
  115.     val = 0;
  116.     for(i = 0; i < db_top; i++) {
  117.     if(isok(i)) {
  118.         trans[i] = val++;
  119.     } else {
  120.         trans[i] = NOTHING;
  121.     }
  122.     }
  123.     
  124.     inbuild--;
  125. }
  126.  
  127. static dbref translate(dbref x)
  128. {
  129.     if(x == NOTHING || x == HOME) {
  130.     return(x);
  131.     } else {
  132.     return(trans[x]);
  133.     }
  134. }
  135.  
  136. /* TRUE_BOOLEXP means throw this argument out */
  137. /* even on OR; it's effectively a null boolexp */
  138. /* NOTE: this doesn't free anything, it just munges it up */
  139. static struct boolexp *translate_boolexp(struct boolexp *exp)
  140. {
  141.     struct boolexp *s1;
  142.     struct boolexp *s2;
  143.  
  144.     if(exp == TRUE_BOOLEXP) {
  145.     return TRUE_BOOLEXP;
  146.     } else {
  147.     switch(exp->type) {
  148.       case BOOLEXP_NOT:
  149.         s1 = translate_boolexp(exp->sub1);
  150.         if(s1 == TRUE_BOOLEXP) {
  151.         return TRUE_BOOLEXP;
  152.         } else {
  153.         exp->sub1 = s1;
  154.         return exp;
  155.         }
  156.         /* break; */
  157.       case BOOLEXP_AND:
  158.       case BOOLEXP_OR:
  159.         s1 = translate_boolexp(exp->sub1);
  160.         s2 = translate_boolexp(exp->sub2);
  161.         if(s1 == TRUE_BOOLEXP && s2 == TRUE_BOOLEXP) {
  162.         /* nothing left */
  163.         return TRUE_BOOLEXP;
  164.         } else if(s1 == TRUE_BOOLEXP && s2 != TRUE_BOOLEXP) {
  165.         /* s2 is all that is left */
  166.         return s2;
  167.         } else if(s1 != TRUE_BOOLEXP && s2 == TRUE_BOOLEXP) {
  168.         /* s1 is all that is left */
  169.         return s1;
  170.         } else {
  171.         exp->sub1 = s1;
  172.         exp->sub2 = s2;
  173.         return exp;
  174.         }
  175.         /* break; */
  176.       case BOOLEXP_CONST:
  177.         exp->thing = translate(exp->thing);
  178.         if(exp->thing == NOTHING) {
  179.         return TRUE_BOOLEXP;
  180.         } else {
  181.         return exp;
  182.         }
  183.         /* break; */
  184.       default:
  185.         abort();        /* bad boolexp type, we lose */
  186.         return TRUE_BOOLEXP;
  187.     }
  188.     }
  189. }
  190.  
  191. static int ok(dbref x)
  192. {
  193.     if(x == NOTHING || x == HOME) {
  194.     return 1;
  195.     } else {
  196.     return trans[x] != NOTHING;
  197.     }
  198. }
  199.  
  200. static void check_bad_exits(dbref x)
  201. {
  202.     dbref e;
  203.  
  204.     if(Typeof(x) == TYPE_ROOM && !isok(x)) {
  205.     /* mark all exits as excluded */
  206.     DOLIST(e, db[x].exits) {
  207.         trans[e] = NOTHING;
  208.     }
  209.     }
  210. }
  211.  
  212. static void check_owner(dbref x)
  213. {
  214.     if(ok(x) && !ok(db[x].owner)) {
  215.     db[x].owner = DEFAULT_OWNER;
  216.     }
  217. }
  218.  
  219. static void check_location(dbref x)
  220. {
  221.     dbref loc;
  222.     dbref newloc;
  223.  
  224.     if(ok(x) && (Typeof(x) == TYPE_THING || Typeof(x) == TYPE_PLAYER)
  225.        && !ok(loc = db[x].location)) {
  226.     /* move it to home or DEFAULT_LOCATION */
  227.     if(ok(db[x].exits)) {
  228.         newloc = db[x].exits; /* home */
  229.     } else {
  230.         newloc = DEFAULT_LOCATION;
  231.     }
  232.     db[loc].contents = remove_first(db[loc].contents, x);
  233.     PUSH(x, db[newloc].contents);
  234.     db[x].location = newloc;
  235.     }
  236. }
  237.  
  238. static void check_next(dbref x)
  239. {
  240.     dbref next;
  241.  
  242.     if(ok(x)) {
  243.     while(!ok(next = db[x].next)) db[x].next = db[next].next;
  244.     }
  245. }
  246.  
  247. static void check_contents(dbref x)
  248. {
  249.     dbref c;
  250.  
  251.     if(ok(x)) {
  252.     while(!ok(c = db[x].contents)) db[x].contents = db[c].next;
  253.     }
  254. }
  255.  
  256. /* also updates home */
  257. /* MUST BE CALLED AFTER check_owner! */
  258. static void check_exits(dbref x)
  259. {
  260.     dbref e;
  261.  
  262.     if(ok(x) && !ok(e = db[x].exits)) {
  263.     switch(Typeof(x)) {
  264.       case TYPE_ROOM:
  265.         while(!ok(e = db[x].exits)) db[x].exits = db[e].next;
  266.         break;
  267.       case TYPE_PLAYER:
  268.       case TYPE_THING:
  269.         if(ok(db[db[x].owner].exits)) {
  270.         /* set it to owner's home */
  271.         db[x].exits = db[db[x].owner].exits; /* home */
  272.         } else {
  273.         /* set it to DEFAULT_LOCATION */
  274.         db[x].exits = DEFAULT_LOCATION; /* home */
  275.         }
  276.         break;
  277.     }
  278.     }
  279. }
  280.  
  281. static void do_write(void)
  282. {
  283.     dbref i;
  284.     dbref kludge;
  285.  
  286.     /* this is braindamaged */
  287.     /* we have to rebuild the translation map */
  288.     /* because part of it may have gotten nuked in check_bad_exits */
  289.     for(i = 0, kludge = 0; i < db_top; i++) {
  290.     if(trans[i] != NOTHING) trans[i] = kludge++;
  291.     }
  292.  
  293.     for(i = 0; i < db_top; i++) {
  294.     if(ok(i)) {
  295.         /* translate all object pointers */
  296.         db[i].location = translate(db[i].location);
  297.         db[i].contents = translate(db[i].contents);
  298.         db[i].exits = translate(db[i].exits);
  299.         db[i].next = translate(db[i].next);
  300.         db[i].key = translate_boolexp(db[i].key);
  301.         db[i].owner = translate(db[i].owner);
  302.  
  303.         /* write it out */
  304.         printf("#%d\n", translate(i));
  305.         db_write_object(stdout, i);
  306.     }
  307.     }
  308.     puts("***END OF DUMP***");
  309. }
  310.  
  311. int reach_lvl = 0;
  312.  
  313. make_reachable (dbref x)
  314. {   dbref e, r;
  315.     int i;
  316.     
  317.     if (Typeof(x) != TYPE_ROOM || is_excluded(x)) return;
  318.  
  319.     reach_lvl++;
  320.  
  321.     SET_REACHABLE(x);
  322.  
  323. #ifdef DEBUG
  324.     for (i=0; i<reach_lvl; i++ ) fputc (' ', stderr);
  325.     fprintf (stderr, "Set %s(%dR) reachable.\n", db[x].name, x);
  326. #endif
  327.  
  328.     DOLIST(e, db[x].exits) {
  329.     r = db[e].location;
  330.  
  331.     if (r < 0) continue;
  332.     if (is_excluded(r)) continue;
  333.         if (is_excluded(e)) continue;
  334.     if (!REACHABLE(r)) make_reachable(r);
  335.     }
  336.  
  337.     reach_lvl--;
  338. }
  339.  
  340. void main(int argc, char **argv)
  341. {
  342.     dbref i;
  343.     int top_in;
  344.     int top_ex;
  345.     char *arg0;
  346.  
  347.     top_in = 0;
  348.     top_ex = 0;
  349.  
  350.     /* Load database */
  351.     if(db_read(stdin) < 0) {
  352.     fputs("Database load failed!\n", stderr);
  353.     exit(1);
  354.     } 
  355.  
  356.     fputs("Done loading database...\n", stderr);
  357.  
  358.  
  359.     /* now parse args */
  360.     arg0 = *argv;
  361.     for (argv++, argc--; argc > 0; argv++, argc--) {
  362.     if (isdigit (**argv) || **argv == '-' && isdigit ((*argv)[1])) {
  363.         i = atol(*argv);
  364.     } else if (**argv == '+' && isdigit ((*argv)[1])) {
  365.         i = atol(*argv+1);
  366.     } else if (**argv == 'b' && isdigit ((*argv)[1])) {
  367.         safe_below = atol(*argv+1);
  368.         fprintf (stderr, "Including all objects %d and below\n",
  369.                  safe_below);
  370.     } else if (**argv == 'a' && isdigit ((*argv)[1])) {
  371.         safe_above = atol(*argv+1);
  372.         fprintf (stderr, "Including all objects %d and above\n",
  373.                  safe_above);
  374.     } else if (!strcmp(*argv, "all")) {
  375.         include_all = 1;
  376.     } else if (!strcmp(*argv, "reachable")) {
  377.         reachable = 1;
  378.     } else if (!strcmp(*argv, "players")) {
  379.         keep_players = 1;
  380.     } else if (!strcmp(*argv, "norecycle")) {
  381.         norecycle = 1;
  382.     } else if (**argv == '-' &&
  383.                (i = lookup_player (*argv+1)) != 0) {
  384.         fprintf (stderr, "Excluding player %s(%d)\n",
  385.              db[i].name, i);
  386.         i = -i;
  387.     } else if (**argv != '-' &&
  388.                    (i = lookup_player (*argv)) != NOTHING) {
  389.         fprintf (stderr, "Including player %s(%d)\n",
  390.              db[i].name, i);
  391.     } else {
  392.         fprintf(stderr, "%s: bogus argument %s\n", arg0, *argv);
  393.         continue;
  394.     }
  395.     
  396.     if(i < 0) {
  397.         excluded[top_ex++] = -i;
  398.     } else {
  399.         included[top_in++] = i;
  400.     }
  401.     }
  402.  
  403.     /* Terminate */
  404.     included[top_in++] = NOTHING;
  405.     excluded[top_ex++] = NOTHING;
  406.  
  407.     /* Check for reachability from DEFAULT_LOCATION */
  408.     if (reachable)
  409.     { make_reachable (DEFAULT_LOCATION); 
  410.       fputs ("Done marking reachability...\n", stderr); 
  411.     }
  412.     
  413.     /* Find recycler */
  414.     if (norecycle && ((i = lookup_player (RECYCLER)) != NOTHING))
  415.     { recycling_center = db[i].exits;
  416.       if (recycling_center == DEFAULT_LOCATION) norecycle = 0;
  417.       else
  418.       { fprintf (stderr, "Excluding all players in %s(%d)\n",
  419.                 db[recycling_center].name, recycling_center);
  420.       }
  421.     }
  422.  
  423.     /* Build translation table */
  424.     build_trans();
  425.     fputs("Done building translation table...\n", stderr);
  426.  
  427.     /* Scan everything */
  428.     for(i = 0; i < db_top; i++) check_bad_exits(i);
  429.     fputs("Done checking bad exits...\n", stderr);
  430.  
  431.     for(i = 0; i < db_top; i++) check_owner(i);
  432.     fputs("Done checking owners...\n", stderr);
  433.  
  434.     for(i = 0; i < db_top; i++) check_location(i);
  435.     fputs("Done checking locations...\n", stderr);
  436.  
  437.     for(i = 0; i < db_top; i++) check_next(i);
  438.     fputs("Done checking next pointers...\n", stderr);
  439.  
  440.     for(i = 0; i < db_top; i++) check_contents(i);
  441.     fputs("Done checking contents...\n", stderr);
  442.  
  443.     for(i = 0; i < db_top; i++) check_exits(i);
  444.     fputs("Done checking homes and exits...\n", stderr);
  445.  
  446.     do_write();
  447.     fputs("Done.\n", stderr);
  448.  
  449.     exit(0);
  450. }
  451.