home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume11
/
tinymud2
/
part08
/
extract.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-10
|
11KB
|
451 lines
#include "copyright.h"
#include <stdio.h>
#include <ctype.h>
#include <sys/param.h>
#include "db.h"
static int include_all = 0; /* include everything unless specified */
static int keep_players = 0; /* keep all players */
static int safe_below = 1; /* Keep everything <= safe_below */
static int safe_above = 2e9; /* Keep everything >= safe_above */
static int reachable = 0; /* Only keep rooms reachable from #0 */
static int norecycle = 0; /* Exclude things in recycling center */
static int inbuild = 0; /* True when in main nuild_trans loop */
static int recycling_center = 0;/* Room number home("Recycler") */
# define REACH_FLAG 0x40000000
# define REACHABLE(X) (db[X].flags & REACH_FLAG)
# define SET_REACHABLE(X) (db[X].flags |= REACH_FLAG)
static dbref included[NCARGS+1];
static dbref excluded[NCARGS+1];
static dbref *trans; /* translation vector */
#define DEFAULT_LOCATION (0)
#define DEFAULT_OWNER (1)
static int isok(dbref);
/* returns 1 if object is specifically excluded */
static int is_excluded(dbref x)
{
int i;
if(x == NOTHING) return 0; /* Don't exclude nothing */
/* check that it isn't excluded */
for(i = 0; excluded[i] != NOTHING; i++) {
if(excluded[i] == x) return 1; /* always exclude specifics */
if(excluded[i] == db[x].owner) return 1;
}
return (0);
}
/* returns 1 if it is not excluded */
static int not_excluded(dbref x)
{
int i;
if(x == NOTHING) return 1; /* Don't exclude nothing */
/* check that it isn't excluded */
for(i = 0; excluded[i] != NOTHING; i++) {
if(excluded[i] == x) return 0; /* always exclude specifics */
if(excluded[i] == db[x].owner) return 0;
}
/* if it's an exit, check that its destination is ok */
if(Typeof(x) == TYPE_EXIT && db[x].location >= 0) {
return isok(db[x].location);
} else {
return 1;
}
}
/* returns 1 if it should be included in translation vector */
static int isok(dbref x)
{
int i;
if(x == DEFAULT_OWNER || x == DEFAULT_LOCATION) return 1;
if(x == NOTHING) return 1;
for(i = 0; included[i] != NOTHING; i++) {
if(included[i] == x) return 1; /* always get specific ones */
if(reachable && Typeof(x) == TYPE_ROOM && !REACHABLE(x))
{
# ifdef DEBUG
if (inbuild)
fprintf (stderr, "Excluding %s(%dR), not reachable\n",
db[x].name, x);
# endif
return 0;
}
if(norecycle && db[x].location == recycling_center) return 0;
if(included[i] == db[x].owner
|| (x <= safe_below || x >= safe_above)
|| keep_players && Typeof(x) == TYPE_PLAYER) {
return not_excluded(x);
}
}
/* not in the list, can only get it if include_all is on */
/* or it's owned by DEFAULT_OWNER */
return (include_all && not_excluded(x));
}
static void build_trans(void)
{
dbref i;
dbref val;
if((trans = (dbref *) malloc(sizeof(dbref) * db_top)) == 0) {
abort();
}
inbuild++;
val = 0;
for(i = 0; i < db_top; i++) {
if(isok(i)) {
trans[i] = val++;
} else {
trans[i] = NOTHING;
}
}
inbuild--;
}
static dbref translate(dbref x)
{
if(x == NOTHING || x == HOME) {
return(x);
} else {
return(trans[x]);
}
}
/* TRUE_BOOLEXP means throw this argument out */
/* even on OR; it's effectively a null boolexp */
/* NOTE: this doesn't free anything, it just munges it up */
static struct boolexp *translate_boolexp(struct boolexp *exp)
{
struct boolexp *s1;
struct boolexp *s2;
if(exp == TRUE_BOOLEXP) {
return TRUE_BOOLEXP;
} else {
switch(exp->type) {
case BOOLEXP_NOT:
s1 = translate_boolexp(exp->sub1);
if(s1 == TRUE_BOOLEXP) {
return TRUE_BOOLEXP;
} else {
exp->sub1 = s1;
return exp;
}
/* break; */
case BOOLEXP_AND:
case BOOLEXP_OR:
s1 = translate_boolexp(exp->sub1);
s2 = translate_boolexp(exp->sub2);
if(s1 == TRUE_BOOLEXP && s2 == TRUE_BOOLEXP) {
/* nothing left */
return TRUE_BOOLEXP;
} else if(s1 == TRUE_BOOLEXP && s2 != TRUE_BOOLEXP) {
/* s2 is all that is left */
return s2;
} else if(s1 != TRUE_BOOLEXP && s2 == TRUE_BOOLEXP) {
/* s1 is all that is left */
return s1;
} else {
exp->sub1 = s1;
exp->sub2 = s2;
return exp;
}
/* break; */
case BOOLEXP_CONST:
exp->thing = translate(exp->thing);
if(exp->thing == NOTHING) {
return TRUE_BOOLEXP;
} else {
return exp;
}
/* break; */
default:
abort(); /* bad boolexp type, we lose */
return TRUE_BOOLEXP;
}
}
}
static int ok(dbref x)
{
if(x == NOTHING || x == HOME) {
return 1;
} else {
return trans[x] != NOTHING;
}
}
static void check_bad_exits(dbref x)
{
dbref e;
if(Typeof(x) == TYPE_ROOM && !isok(x)) {
/* mark all exits as excluded */
DOLIST(e, db[x].exits) {
trans[e] = NOTHING;
}
}
}
static void check_owner(dbref x)
{
if(ok(x) && !ok(db[x].owner)) {
db[x].owner = DEFAULT_OWNER;
}
}
static void check_location(dbref x)
{
dbref loc;
dbref newloc;
if(ok(x) && (Typeof(x) == TYPE_THING || Typeof(x) == TYPE_PLAYER)
&& !ok(loc = db[x].location)) {
/* move it to home or DEFAULT_LOCATION */
if(ok(db[x].exits)) {
newloc = db[x].exits; /* home */
} else {
newloc = DEFAULT_LOCATION;
}
db[loc].contents = remove_first(db[loc].contents, x);
PUSH(x, db[newloc].contents);
db[x].location = newloc;
}
}
static void check_next(dbref x)
{
dbref next;
if(ok(x)) {
while(!ok(next = db[x].next)) db[x].next = db[next].next;
}
}
static void check_contents(dbref x)
{
dbref c;
if(ok(x)) {
while(!ok(c = db[x].contents)) db[x].contents = db[c].next;
}
}
/* also updates home */
/* MUST BE CALLED AFTER check_owner! */
static void check_exits(dbref x)
{
dbref e;
if(ok(x) && !ok(e = db[x].exits)) {
switch(Typeof(x)) {
case TYPE_ROOM:
while(!ok(e = db[x].exits)) db[x].exits = db[e].next;
break;
case TYPE_PLAYER:
case TYPE_THING:
if(ok(db[db[x].owner].exits)) {
/* set it to owner's home */
db[x].exits = db[db[x].owner].exits; /* home */
} else {
/* set it to DEFAULT_LOCATION */
db[x].exits = DEFAULT_LOCATION; /* home */
}
break;
}
}
}
static void do_write(void)
{
dbref i;
dbref kludge;
/* this is braindamaged */
/* we have to rebuild the translation map */
/* because part of it may have gotten nuked in check_bad_exits */
for(i = 0, kludge = 0; i < db_top; i++) {
if(trans[i] != NOTHING) trans[i] = kludge++;
}
for(i = 0; i < db_top; i++) {
if(ok(i)) {
/* translate all object pointers */
db[i].location = translate(db[i].location);
db[i].contents = translate(db[i].contents);
db[i].exits = translate(db[i].exits);
db[i].next = translate(db[i].next);
db[i].key = translate_boolexp(db[i].key);
db[i].owner = translate(db[i].owner);
/* write it out */
printf("#%d\n", translate(i));
db_write_object(stdout, i);
}
}
puts("***END OF DUMP***");
}
int reach_lvl = 0;
make_reachable (dbref x)
{ dbref e, r;
int i;
if (Typeof(x) != TYPE_ROOM || is_excluded(x)) return;
reach_lvl++;
SET_REACHABLE(x);
#ifdef DEBUG
for (i=0; i<reach_lvl; i++ ) fputc (' ', stderr);
fprintf (stderr, "Set %s(%dR) reachable.\n", db[x].name, x);
#endif
DOLIST(e, db[x].exits) {
r = db[e].location;
if (r < 0) continue;
if (is_excluded(r)) continue;
if (is_excluded(e)) continue;
if (!REACHABLE(r)) make_reachable(r);
}
reach_lvl--;
}
void main(int argc, char **argv)
{
dbref i;
int top_in;
int top_ex;
char *arg0;
top_in = 0;
top_ex = 0;
/* Load database */
if(db_read(stdin) < 0) {
fputs("Database load failed!\n", stderr);
exit(1);
}
fputs("Done loading database...\n", stderr);
/* now parse args */
arg0 = *argv;
for (argv++, argc--; argc > 0; argv++, argc--) {
if (isdigit (**argv) || **argv == '-' && isdigit ((*argv)[1])) {
i = atol(*argv);
} else if (**argv == '+' && isdigit ((*argv)[1])) {
i = atol(*argv+1);
} else if (**argv == 'b' && isdigit ((*argv)[1])) {
safe_below = atol(*argv+1);
fprintf (stderr, "Including all objects %d and below\n",
safe_below);
} else if (**argv == 'a' && isdigit ((*argv)[1])) {
safe_above = atol(*argv+1);
fprintf (stderr, "Including all objects %d and above\n",
safe_above);
} else if (!strcmp(*argv, "all")) {
include_all = 1;
} else if (!strcmp(*argv, "reachable")) {
reachable = 1;
} else if (!strcmp(*argv, "players")) {
keep_players = 1;
} else if (!strcmp(*argv, "norecycle")) {
norecycle = 1;
} else if (**argv == '-' &&
(i = lookup_player (*argv+1)) != 0) {
fprintf (stderr, "Excluding player %s(%d)\n",
db[i].name, i);
i = -i;
} else if (**argv != '-' &&
(i = lookup_player (*argv)) != NOTHING) {
fprintf (stderr, "Including player %s(%d)\n",
db[i].name, i);
} else {
fprintf(stderr, "%s: bogus argument %s\n", arg0, *argv);
continue;
}
if(i < 0) {
excluded[top_ex++] = -i;
} else {
included[top_in++] = i;
}
}
/* Terminate */
included[top_in++] = NOTHING;
excluded[top_ex++] = NOTHING;
/* Check for reachability from DEFAULT_LOCATION */
if (reachable)
{ make_reachable (DEFAULT_LOCATION);
fputs ("Done marking reachability...\n", stderr);
}
/* Find recycler */
if (norecycle && ((i = lookup_player (RECYCLER)) != NOTHING))
{ recycling_center = db[i].exits;
if (recycling_center == DEFAULT_LOCATION) norecycle = 0;
else
{ fprintf (stderr, "Excluding all players in %s(%d)\n",
db[recycling_center].name, recycling_center);
}
}
/* Build translation table */
build_trans();
fputs("Done building translation table...\n", stderr);
/* Scan everything */
for(i = 0; i < db_top; i++) check_bad_exits(i);
fputs("Done checking bad exits...\n", stderr);
for(i = 0; i < db_top; i++) check_owner(i);
fputs("Done checking owners...\n", stderr);
for(i = 0; i < db_top; i++) check_location(i);
fputs("Done checking locations...\n", stderr);
for(i = 0; i < db_top; i++) check_next(i);
fputs("Done checking next pointers...\n", stderr);
for(i = 0; i < db_top; i++) check_contents(i);
fputs("Done checking contents...\n", stderr);
for(i = 0; i < db_top; i++) check_exits(i);
fputs("Done checking homes and exits...\n", stderr);
do_write();
fputs("Done.\n", stderr);
exit(0);
}