/* $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)
{
}