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