/* $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 "os.h" #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"); } int 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 (); return 0; } void clear_players (dbref i) { } void add_player (dbref i) { }