/* $Header: sanity.c,v 1.1 90/05/05 12:48:53 lachesis Exp $ * $Log: sanity.c,v $ * Revision 1.1 90/05/05 12:48:53 lachesis * Initial revision * */ #include "copyright.h" #include "db.h" extern dbref recyclable; void violate(dbref i, const char *s, const char *why) { printf("Object #%d violates %s rules: %s\n", i, s, why); db_write_object(stdout, i); } int recursive_location(dbref what, dbref loc) { if (loc == NOTHING) return 0; if (what == loc) return 1; if (recursive_location(what, db[loc].location)) return 1; return 0; } int recursive_list(dbref what, dbref next) { if (next == NOTHING) return 0; if (what == next) return 1; if (recursive_list(what, db[next].next)) return 1; return 0; } void check_common(dbref obj) { int i; /* check location */ if (db[obj].location >= db_top) violate(obj, "location", "out of range"); if (recursive_location(obj, db[obj].location)) violate(obj, "location", "recursive"); /* check contents */ if (recursive_list(db[obj].contents, HOME)) violate(obj, "contents", "recursive"); for (i = db[obj].contents; i < db_top && i != NOTHING; i = db[i].next) ; if (i != NOTHING) violate(obj, "contents", "garbage at end"); } void check_room(dbref obj) { dbref i; if (db[obj].sp.room.dropto >= db_top || (((db[db[obj].sp.room.dropto].flags & TYPE_MASK) != TYPE_ROOM) && db[obj].sp.room.dropto != NOTHING && db[obj].sp.room.dropto != HOME)) violate(obj, "dropto", "garbage or not a room"); if (recursive_list(db[obj].contents, HOME)) violate(obj, "contents", "recursive"); if (recursive_list(db[obj].sp.room.exits, HOME)) violate(obj, "exits", "recursive"); for (i = db[obj].sp.room.exits; i != NOTHING && i < db_top; i = db[i].next) if ((db[i].flags & TYPE_MASK) != TYPE_EXIT) violate(i, "exits", "non-exit in exit list"); if (i != NOTHING) violate(obj, "exits", "garbage at end"); if (db[obj].sp.room.owner >= db_top || ((db[db[obj].sp.room.owner].flags & TYPE_MASK) != TYPE_PLAYER)) violate(obj, "owner", "garbage or not a player"); } void check_thing(dbref obj) { dbref i; if (db[obj].sp.thing.home >= db_top || ((db[db[obj].sp.thing.home].flags & TYPE_MASK) != TYPE_ROOM)) violate(obj, "home", "garbage or not a room"); if (recursive_list(db[obj].contents, HOME)) violate(obj, "contents", "recursive"); for (i = db[obj].sp.thing.actions; i < db_top && i != NOTHING; i = db[i].next) if ((db[i].flags & TYPE_MASK) != TYPE_EXIT) violate(i, "actions", "non-action in action list"); if (i != NOTHING) violate(obj, "actions", "garbage at end"); if (db[obj].sp.thing.owner >= db_top || ((db[db[obj].sp.thing.owner].flags & TYPE_MASK) != TYPE_PLAYER)) violate(obj, "owner", "garbage or not a player"); } void check_exit(dbref obj) { int i; for (i = 0; i < db[obj].sp.exit.ndest; i++) if (db[obj].sp.exit.dest[i] >= db_top) violate(obj, "destination", "garbage"); if (db[obj].sp.exit.owner >= db_top || ((db[db[obj].sp.exit.owner].flags & TYPE_MASK) != TYPE_PLAYER)) violate(obj, "owner", "garbage or not a player"); } void check_player(dbref obj) { dbref i; if (db[obj].sp.player.home >= db_top || ((db[db[obj].sp.player.home].flags & TYPE_MASK) != TYPE_ROOM)) violate(obj, "home", "garbage or not a room"); if (recursive_list(db[obj].sp.player.actions, HOME)) violate(obj, "actions", "recursive"); for (i = db[obj].sp.player.actions; i < db_top && i != NOTHING; i = db[i].next) if ((db[i].flags & TYPE_MASK) != TYPE_EXIT) violate(obj, "actions", "non-action in action list"); if (i != NOTHING) violate(obj, "actions", "garbage at end"); } void check_garbage(void) { dbref i; if (recursive_list(recyclable, HOME)) fprintf(stderr, "Garbage free list is recursive!\n"); for (i = recyclable; i != NOTHING && i < db_top; i = db[i].next) if (Typeof(i) != TYPE_GARBAGE) violate(i, "garbage", "not TYPE_GARBAGE"); if (i != NOTHING) fprintf(stderr, "Garbage at end of garbage free list! (no puns please)\n"); } void main(int argc, char **argv) { int i; db_read(stdin); printf("dbtop = %d\n", db_top); for (i = 0; i < db_top; i++) { #ifdef DEBUG fprintf(stderr, "Checking object %d..\n", i); #endif check_common(i); switch( db[i].flags & TYPE_MASK ) { case TYPE_ROOM: check_room(i); break; case TYPE_THING: check_thing(i); break; case TYPE_EXIT: check_exit(i); break; case TYPE_PLAYER: check_player(i); break; case TYPE_GARBAGE: break; default: violate(i, "type", "bad type"); break; } } check_garbage(); } void clear_players(dbref i) { } void add_player(dbref i) { }