/* db.h */

#include "copyright.h"

#ifndef	__DB_H
#define	__DB_H

#include "config.h"

#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/file.h>
#include <string.h>

#ifdef WANT_ANSI
#ifdef __STDC__
#include <stdlib.h>
#endif /* __STDC__ */
#endif /* WANT_ANSI */

#define	KEY_SIZE 17
#define	STORE(key,con) (dbp->put)(dbp,&(key),&(con),R_PUT)
#define	DELETE(key) (dbp->del)(dbp, &(key), O_RDWR)
#define	FETCH(key,res) (dbp->get)(dbp, &(key), &(res), O_RDWR)
#define	SYNC (dbp->sync)(dbp)
#define	CLOSE (dbp->close)(dbp)

#include "udb.h"
extern DB *dbp;

extern int depth;

typedef int dbref;		/* offset into db */
typedef int FLAG;		/* flags */

#define	TYPE_ROOM 	0x0
#define	TYPE_THING 	0x1
#define	TYPE_EXIT 	0x2
#define	TYPE_PLAYER 	0x3
#define	TYPE_LOST	0x4	/* unused for now... */
#define	TYPE_FREE	0x5	/* unused for now... */
#define	NOTYPE		0x7	/* no particular type */
#define	TYPE_MASK 	0x7	/* room for expansion */

#define	WIZARD		0x00000010	/* gets automatic control */
#define	LINK_OK		0x00000020	/* anybody can link to this room */
#define	DARK		0x00000040	/* Don't show contents or presence */
#define	STICKY		0x00000100	/* Object goes home when dropped */
#define	HAVEN		0x00000400	/* No killing here, or no pages */
#define	QUIET		0x00000800	/* Prevent 'feelgood' messages */
#define	HALT		0x00001000	/* object cannot perform actions */
#define	GOING		0x00004000	/* object is available for recycling */
#define	MONITOR		0x00008000	/* Process ^x:action listens on obj? */
/* #define	MARKED	0x00010000 */	/* flag used for db checking */
#define	PUPPET		0x00020000	/* Relays ALL messages to owner */
#define	CHOWN_OK	0x00040000	/* Object may be @chowned freely */
#define	ENTER_OK	0x00080000	/* Object may be ENTERed */
#define	VISUAL		0x00100000	/* Everyone can see properties */
#define	IMMORTAL	0x00200000	/* Object can't be killed */
#define	STARTUP		0x00400000	/* Object has a startup field */
#define	OPAQUE		0x00800000	/* Can't see inside */
#define	VERBOSE		0x01000000	/* Tells owner everything it does. */
#define	INHERIT		0x02000000	/* Gets owner's privs. (i.e. Wiz) */
#define	NOSPOOF		0x04000000	/* Report originator of all actions. */
#define	HEARTHRU	0x40000000	/* Can hear out of this object or exit */

/* object specific flags */

/* Exit flags */
#define	EXIT_SEETHRU	0x00000008	/* Show dest @desc also */
#define	EXIT_KEY	0x00000080	/* Divest of KEY objs when used */
#define	EXIT_ROBOT	0x08000000	/* Robots may not use */
#define	EXIT_SAFE	0x10000000	/* Prevents accidental @destroy */

/* Object flags */
#define	THING_KEY	0x00000008	/* cannot be picked up by puppets */
#define	THING_DEST_OK	0x00000200	/* Destroyable by others */
#define	THING_ROBOT	0x08000000	/* Robots cannot use */
#define	THING_SAFE	0x10000000	/* Prevents accidental @destroy */

/* Player flags */
#define	PLAYER_BUILD	0x00000008	/* Player can build. */
#define	PLAYER_GAGGED	0x00000080	/* Player can't speak, etc */
#define	PLAYER_CONNECT	0x00000200	/* Player is connected */
#define	PLAYER_UNFIND	0x00002000	/* Hidden from @whereis */
#define	PLAYER_ROBOT	0x08000000	/* Allowed to use robot commands */
#define	PLAYER_SLAVE	0x10000000	/* Prevents player from modifying db */
#define	PLAYER_SUSPECT	0x20000000	/* Report logins/logouts to wizards */

/* Room flags */
#define	ROOM_FLOATING	0x00000008	/* Don't blather about disconnected */
#define	ROOM_TEMPLE	0x00000080	/* Get sac value for dropped objs */
#define	ROOM_ABODE	0x00000200	/* May set home here */
#define	ROOM_JUMP_OK	0x00002000	/* May @tel here */
#define	ROOM_SAFE	0x10000000	/* Prevents accidental @destroy */

#define	GOD ((dbref) 1)

/* ---------------------- Object Permission/Attribute Macros */
/* IS(X,T,F)		- Is X of type T and have flag F set? */
/* Typeof(X)		- What object type is X */
/* God(X)		- Is X player #1 */
/* Guest(X)		- Is X the GUEST player */
/* Robot(X)		- Is X a robot player */
/* Wizard(X)		- Does X have wizard privs */
/* Immortal(X)		- Is X unkillable */
/* Alive(X)		- Is X a player or a puppet */
/* Dark(X)		- Is X dark */
/* Builder(X)		- Is X allowed to add on to the db */
/* Floating(X)		- Prevent 'disconnected room' msgs for room X */
/* Quiet(X)		- Should 'Set.' messages et al from X be disabled */
/* Gagged(X)		- Should X be prevented from yakking */
/* Player_haven(X)	- Is the owner of X no-page */
/* Haven(X)		- Is X no-kill(rooms) or no-page(players) */
/* Halted(X)		- Is X halted (not allowed to run commands)? */
/* Suspect(X)		- Is X someone the wizzes should keep an eye on */
/* Slave(X)		- Should X be prevented from db-changing commands */
/* Safe(X,P)		- Does P need the /OVERRIDE switch to @destroy X? */
/* Monnitor(X)		- Should we check for ^xxx:xxx listens on player? */
/* Unfindable(X)	- Is @whereis blocked for X */
/* Findable(X)		- Can @whereis find X */
/* No_robots(X)		- Does X disallow robot players from using */
/* Has_location(X)	- Is X something with a location (ie plyr or obj) */
/* Has_home(X)		- Is X something with a home (ie plyr or obj) */
/* Has_contents(X)	- Is X something with contents (ie plyr/obj/room) */
/* Good_obj(X)		- Is X inside the DB and have a valid type? */
/* Good_owner(X)	- Is X a good owner value? */
/* Going(X)		- Is X marked GOING? */
/* Inherits(X)		- Does X inherit the privs of its owner */
/* Examinable(P,X)	- Can P look at attribs of X */
/* Controls(P,X)	- Can P force X to do something */
/* Affects(P,X)		- (Controls in MUSH V1) Is P wiz or same owner as X */
/* Abode(X)		- Is X an ABODE room */
/* Link_exit(P,X)	- Can P link from exit X */
/* Linkable(P,X)	- Can P link to X */
/* Mark(x)		- Set marked flag on X */
/* Unmark(x)		- Clear marked flag on X */
/* Marked(x)		- Check marked flag on X */
/* See_attr(P,X.A,O)	- Can P see text attr A on X if attr has owner O */
/* Set_attr(P,X,A,F)	- Can P set/change text attr A (with flags F) on X */
/* Read_attr(P,X.A,O)	- Can P see attr A on X if attr has owner O */
/* Write_attr(P,X,A,F)	- Can P set/change attr A (with flags F) on X */

#define	IS(thing,type,flag) ((Typeof(thing)==(type)) && (Flags(thing) & (flag)))
#define	Typeof(x)	(Flags(x) & TYPE_MASK)
#define	God(x)		((x) == GOD)
#define	Guest(x)	(Owner(x) == mudconf.guest_char)
#define	Robot(x)	IS((x),TYPE_PLAYER,PLAYER_ROBOT)
#define	Wizard(x)	((Flags(x) & WIZARD) || \
			 ((Flags(Owner(x)) & WIZARD) && Inherits(x)))
#define	Immortal(x)	((Flags(x) & IMMORTAL) || \
			 ((Flags(Owner(x)) & IMMORTAL) && Inherits(x)))
#define	Alive(x)	((Typeof(x)==TYPE_PLAYER) || \
			 ((Typeof(x)==TYPE_THING) && (Flags(x) & PUPPET)))
#define	Dark(x)		(((Flags(x) & DARK) != 0) && \
			 (Wizard(x) || !Alive(x))) 
#define	Builder(x)	((Flags(Owner(x)) & PLAYER_BUILD) || Wizard(x))
#define	Floating(x)	IS((x),TYPE_ROOM,ROOM_FLOATING)
#define	Quiet(x)	(((Flags(x) & QUIET) !=0) || \
			 ((Flags(Owner(x)) & QUIET) != 0))
#define	Gagged(x)	((Flags(Owner(x)) & PLAYER_GAGGED) != 0)
#define	Player_haven(x)	((Flags(Owner(x)) & HAVEN) != 0)
#define	Haven(x)	((Flags(x) & HAVEN) != 0)
#define	Halted(x)	((Flags(x) & HALT) != 0)
#define	Suspect(x)	((Flags(Owner(x)) & PLAYER_SUSPECT) != 0)
#define	Slave(x)	(Flags(Owner(x)) & PLAYER_SLAVE)
#define	Safe(x,p)	((Typeof(x) == TYPE_PLAYER) || \
			 (Flags(x) & THING_SAFE))
#define	Monitor(x)	(Flags(x) & MONITOR)
#define	Audible(x)	(Flags(x) & HEARTHRU)
#define	Unfindable(x)	((Typeof(x) == TYPE_PLAYER) && \
			 ((Flags(x) & PLAYER_UNFIND) != 0))
#define	Findable(x)	((Typeof(x) == TYPE_PLAYER) && \
			 ((Flags(x) & PLAYER_UNFIND) == 0))
#define	No_robots(x)	(IS((x),TYPE_EXIT,EXIT_ROBOT) || \
			 IS((x),TYPE_THING,THING_ROBOT))
#define	Has_location(x)	((Typeof(x) == TYPE_PLAYER) || \
			 (Typeof(x) == TYPE_THING))
#define	Has_home(x)	((Typeof(x) == TYPE_PLAYER) || \
			 (Typeof(x) == TYPE_THING))
#define	Has_contents(x)	((Typeof(x) == TYPE_PLAYER) || \
			 (Typeof(x) == TYPE_THING) || \
			 (Typeof(x) == TYPE_ROOM))
#define	Has_exits(x)	((Typeof(x) == TYPE_PLAYER) || \
			 (Typeof(x) == TYPE_THING) || \
			 (Typeof(x) == TYPE_ROOM))
#define	Good_obj(x)	((((x) >= 0) && ((x) < mudstate.db_top)) && \
			 (Typeof(x) <= TYPE_PLAYER))
#define	Good_owner(x)	(Good_obj(x) && (Typeof(x) == TYPE_PLAYER))
#define	Going(x)	((Flags(x) & GOING) != 0)
#define	Inherits(x)	(((Flags(x) & INHERIT) != 0) || \
			 ((Flags(Owner(x)) & INHERIT) != 0) || \
			 ((x) == Owner(x)))
#define	Examinable(p,x)	(((Flags(x) & VISUAL) != 0) || \
			 (Wizard(p)) || \
			 (Owner(p) == Owner(x)))
#define	Controls(p,x)	(Good_obj(x) && \
			 (!(God(x) && !God(p))) && \
			 (Wizard(p) || \
			  ((Owner(p) == Owner(x)) && \
			   (Inherits(p) || !Inherits(x)))))
#define	Affects(p,x)	(Good_obj(x) && \
			 (!(God(x) && !God(p))) && \
			 (Wizard(p) || \
			  (Owner(p) == Owner(x))))
#define	Abode(x)	(IS((x),TYPE_ROOM,ROOM_ABODE))
#define	Mark(x)		(mudstate.markbits->chunk[(x)>>3] |= \
			 mudconf.markdata[(x)&7])
#define	Unmark(x)	(mudstate.markbits->chunk[(x)>>3] &= \
			 ~mudconf.markdata[(x)&7])
#define	Marked(x)	(mudstate.markbits->chunk[(x)>>3] & \
			 mudconf.markdata[(x)&7])
#define	Mark_all(i)	for ((i)=0; (i)<((mudstate.db_top+7)>>3); (i)++) \
				mudstate.markbits->chunk[i]=0xff
#define	Unmark_all(i)	for ((i)=0; (i)<((mudstate.db_top+7)>>3); (i)++) \
				mudstate.markbits->chunk[i]=0x0
#define	Link_exit(p,x)	((Typeof(x) == TYPE_EXIT) && \
			 ((Location(x) == NOTHING) || Controls(p,x)))
#define	Linkable(p,x)	(Good_obj(x) && \
			 (((Flags(x) & LINK_OK) != 0) || \
			  Controls(p,x)))
#define	See_attr(p,x,a,o) \
			(!((a)->flags & (AF_INTERNAL|AF_IS_LOCK)) && \
			 (God(p) || \
			  ((Examinable(p,x) || (Owner(p) == o)) && \
			   !((a)->flags & (AF_DARK|AF_MDARK))) || \
			  (Wizard(p) && !((a)->flags & AF_DARK)) || \
			  !((a)->flags & (AF_DARK|AF_MDARK|AF_ODARK))))
#define	Set_attr(p,x,a,f) \
			(!((a)->flags & (AF_INTERNAL|AF_IS_LOCK)) && \
			 (God(p) || \
			  (!God(x) && !(f & AF_LOCK) && \
			   ((Controls(p,x) && \
			     !((a)->flags & (AF_WIZARD|AF_GOD))) || \
			    (Wizard(p) && \
			     !((a)->flags & AF_GOD))))))
#define	Read_attr(p,x,a,o) \
			(!((a)->flags & AF_INTERNAL) && \
			 (God(p) || \
			  ((Examinable(p,x) || (Owner(p) == o)) && \
			   !((a)->flags & (AF_DARK|AF_MDARK))) || \
			  (Wizard(p) && !((a)->flags & AF_DARK)) || \
			  !((a)->flags & (AF_DARK|AF_MDARK|AF_ODARK))))
#define	Write_attr(p,x,a,f) \
			(!((a)->flags & AF_INTERNAL) && \
			 (God(p) || \
			  (!God(x) && !(f & AF_LOCK) && \
			   ((Controls(p,x) && \
			     !((a)->flags & (AF_WIZARD|AF_GOD))) || \
			    (Wizard(p) && \
			     !((a)->flags & AF_GOD))))))
#define	Has_power(p,x)	(check_access((p),powers_nametab[x].flag))

/* Player classes and pseudo-classes for determining access to commands */
#define	CLASS_SLAVE	0
#define	CLASS_GUEST	1
#define	CLASS_VISITOR	2
#define	CLASS_PLAYER	4
#define	CLASS_ARCHITECT	8
#define	CLASS_MAGE	12
#define	CLASS_WIZARD	14
#define	CLASS_MAINT	15
#define	CLASS_GOD	16	/* Cannot assign players to this class */
#define	CLASS_DISABLED	17	/* Cannot assign players to this class */

typedef struct attr ATTR;
struct attr {
	const char *name;	/* This has to be first.  braindeath. */
	int	number;		/* attr number */
	int	flags;
	int	(*check) (int key, dbref player, dbref thing, int anum,
			char *atext);
};

extern ATTR *atr_num(int anum);
extern ATTR *atr_str(char *s);

extern ATTR attr[];

/* Attribute flags */
#define	AF_ODARK	0x0001	/* players other than owner can't see it */
#define	AF_DARK		0x0002	/* No one can see it */
#define	AF_WIZARD	0x0004	/* only wizards can change it */
#define	AF_MDARK	0x0008	/* Only wizards can see it. Dark to mortals */
#define	AF_INTERNAL	0x0010	/* Don't show even to #1 */
#define	AF_NOCMD	0x0020	/* Don't create a @ command for it */
#define	AF_LOCK		0x0040	/* Attribute is locked */
#define	AF_DELETED	0x0080	/* Attribute should be ignored */
#define	AF_NOPROG	0x0100	/* Don't process $-commands from this attr */
#define	AF_GOD		0x0200	/* Only #1 can change it */
#define	AF_IS_LOCK	0x0400	/* Attribute is a lock */

#define	ATR_INFO_CHAR	'\1'	/* Leadin char for attr control data */

#define	A_OSUCC		1	/* Others success message */
#define	A_OFAIL		2	/* Others fail message */
#define	A_FAIL		3	/* Invoker fail message */
#define	A_SUCC		4	/* Invoker success message */
#define	A_PASS		5	/* Password (only meaningful for players) */
#define	A_DESC		6	/* Description */
#define	A_SEX		7	/* Sex */
#define	A_ODROP		8	/* Others drop message */
#define	A_DROP		9	/* Invoker drop message */
#define	A_OKILL		10	/* Others kill message */
#define	A_KILL		11	/* Invoker kill message */
#define	A_ASUCC		12	/* Success action list */
#define	A_AFAIL		13	/* Failure action list */
#define	A_ADROP		14	/* Drop action list */
#define	A_AKILL		15	/* Kill action list */
#define	A_AUSE		16	/* Use action list */
#define	A_CHARGES	17	/* Number of charges remaining */
#define	A_RUNOUT	18	/* Actions done when no more charges */
#define	A_STARTUP	19	/* Actions run when game started up */
#define	A_ACLONE	20	/* Actions run when obj is cloned */
#define	A_APAY		21	/* Actions run when given COST pennies */
#define	A_OPAY		22	/* Others pay message */
#define	A_PAY		23	/* Invoker pay message */
#define	A_COST		24	/* Number of pennies needed to invoke xPAY */
#define	A_RAND		25	/* Unused */
#define	A_LISTEN	26	/* (Wildcarded) string to listen for */
#define	A_AAHEAR	27	/* Actions to do when anyone says LISTEN str */
#define	A_AMHEAR	28	/* Actions to do when I say LISTEN str */
#define	A_AHEAR		29	/* Actions to do when others say LISTEN str */
#define	A_LAST		30	/* Date/time of last login (players only) */
#define	A_QUEUE		31	/* Number of entries obj has in the queue */
#define	A_IDESC		32	/* Inside description (ENTER to get inside) */
#define	A_ENTER		33	/* Invoker enter message */
#define	A_OXENTER	34	/* Others enter message in dest */
#define	A_AENTER	35	/* Enter action list */
#define	A_ADESC		36	/* Describe action list */
#define	A_ODESC		37	/* Others describe message */
#define	A_RQUOTA	38	/* Relative object quota */
#define	A_ACONNECT	39	/* Actions run when player connects */
#define	A_ADISCONNECT	40	/* Actions run when player disconnectes */
#define	A_ALLOWANCE	41	/* Daily allowance, if diff from default */
#define	A_LOCK		42	/* Object lock */
#ifdef ATR_NAME
#define	A_NAME		43	/* Object name */
#endif
#define	A_COMMENT	44	/* Wizard-accessable comments */
#define	A_USE		45	/* Invoker use message */
#define	A_OUSE		46	/* Others use message */
#define	A_SEMAPHORE	47	/* Semaphore control info */
#define	A_TIMEOUT	48	/* Per-user disconnect timeout */
#define	A_QUOTA		49	/* Absolute quota (to speed up @quota) */
#define	A_LEAVE		50	/* Invoker leave message */
#define	A_OLEAVE	51	/* Others leave message in src */
#define	A_ALEAVE	52	/* Leave action list */
#define	A_OENTER	53	/* Others enter message in src */
#define	A_OXLEAVE	54	/* Others leave message in dest */
#define	A_MOVE		55	/* Invoker move message */
#define	A_OMOVE		56	/* Others move message */
#define	A_AMOVE		57	/* Move action list */
#define	A_ALIAS		58	/* Alias for player names */
#define	A_LENTER	59	/* ENTER lock */
#define	A_LLEAVE	60	/* LEAVE lock */
#define	A_LPAGE		61	/* PAGE lock */
#define	A_LUSE		62	/* USE lock */
#define	A_LGIVE		63	/* Give lock (who may give me away?) */
#define	A_EALIAS	64	/* Alternate names for ENTER */
#define	A_LALIAS	65	/* Alternate names for LEAVE */
#define	A_EFAIL		66	/* Invoker entry fail message */
#define	A_OEFAIL	67	/* Others entry fail message */
#define	A_AEFAIL	68	/* Entry fail action list */
#define	A_LFAIL		69	/* Invoker leave fail message */
#define	A_OLFAIL	70	/* Others leave fail message */
#define	A_ALFAIL	71	/* Leave fail action list */
#define	A_REJECT	72	/* Rejected page return message */
#define	A_AWAY		73	/* Not_connected page return message */
#define	A_IDLE		74	/* Success page return message */
#define	A_UFAIL		75	/* Invoker use fail message */
#define	A_OUFAIL	76	/* Others use fail message */
#define	A_AUFAIL	77	/* Use fail action list */
#define	A_PFAIL		78	/* Invoker page fail message */
#define	A_TPORT		79	/* Invoker teleport message */
#define	A_OTPORT	80	/* Others teleport message in src */
#define	A_OXTPORT	81	/* Others teleport message in dst */
#define	A_ATPORT	82	/* Teleport action list */
#define	A_PRIVS		83	/* Individual permissions */
#define	A_LOGINDATA	84	/* Recent login information */
#define	A_LTPORT	85	/* Teleport lock (can others @tel to me?) */
#define	A_LDROP		86	/* Drop lock (can I be dropped or @tel'ed) */
#define	A_LRECEIVE	87	/* Receive lock (who may give me things?) */
#define	A_LASTSITE	88	/* Last site logged in from, in cleartext */
#define	A_INPREFIX	89	/* Prefix on incoming messages into objects */
#define	A_PREFIX	90	/* Prefix used by exits/objects when audible */
#define	A_INFILTER	91	/* Filter to zap incoming text into objects */
#define	A_FILTER	92	/* Filter to zap text forwarded by audible. */
#define	A_LLINK		93	/* Who may link to here */
#define	A_LTELOUT	94	/* Who may teleport out from here */
#define	A_FORWARDLIST	95	/* Recipients of AUDIBLE output */
#define	A_VA		100	/* VA attribute (VB-VZ follow) */

#define	A_VLIST		252
#define	A_LIST		253
#define	A_STRUCT	254
#define	A_TEMP		255

#define	A_USER_START	256	/* Start of user-named attributes */
#define	ATR_BUF_CHUNK	100	/* Min size to allocate for attribute buffer */
#define	ATR_BUF_INCR	6	/* Max size of one attribute */

/* Attribute handler keys */
#define	AH_READ		0	/* Read the attribute from the hash db */
#define	AH_WRITE	1	/* Write the attribute to the hash db */
#define	AH_RWMASK	1	/* Mask for read/write bit */
#define	AH_RAW		2	/* Don't encode/decode tag info */
#define	AH_NOCHECK	4	/* Don't check permissions */
#define	AH_NOSPECIAL	8	/* Ignore special processing */

/* Boolean expressions, for locks */
typedef char boolexp_type;
#define	BOOLEXP_AND	0
#define	BOOLEXP_OR	1
#define	BOOLEXP_NOT	2
#define	BOOLEXP_CONST	3
#define	BOOLEXP_ATR	4
#define	BOOLEXP_INDIR	5
#define	BOOLEXP_CARRY	6
#define	BOOLEXP_IS	7
#define	BOOLEXP_OWNER	8

struct boolexp {
  boolexp_type type;
  struct boolexp *sub1;
  struct boolexp *sub2;
  dbref thing;			/* thing refers to an object */
};

#define	TRUE_BOOLEXP ((struct boolexp *) 0)

#define	Astr(alist) ((unsigned char *)(&((alist)[1])))

/* Database format information */

#define	F_UNKNOWN	0	/* Unknown database format */
#define	F_MUSH		1	/* MUSH format (many variants) */
#define	F_MUSE		2	/* MUSE format */
#define	F_MUD		3	/* Old TinyMUD format */
#define	F_MUCK		4	/* TinyMUCK format */

#define	V_MASK		0x00ff	/* Database version */
#define	V_ZONE		0x0100	/* db has a ZONE/DOMAIN field */
#define	V_LINK		0x0200	/* db has the LINK field (exits from objs) */
#define	V_GDBM		0x0400	/* attributes are in a gdbm db, not here */
#define	V_ATRNAME	0x0800	/* NAME is an attribute, not in the header */
#define	V_ATRKEY	0x1000	/* KEY is an attribute, not in the header */
#define	V_PERNKEY	0x1000	/* Extra locks in object header */
#define	V_PARENT	0x2000	/* db has the PARENT field (inherit attrs) */
#define	V_COMM		0x4000	/* Comm status in header */

/* special dbref's */
#define	NOTHING		(-1)	/* null dbref */
#define	AMBIGUOUS	(-2)	/* multiple possibilities, for matchers */
#define	HOME		(-3)	/* virtual room, represents mover's home */

typedef struct object OBJ;
struct object {
#ifndef ATR_NAME
	char	*name;		/* PLAYER, THING, ROOM: Name of the object */
				/* EXIT: Set of commands to use the exit */
#endif
	dbref	location;	/* PLAYER, THING: where it is */
				/* ROOM: dropto: */
				/* EXIT: where it goes to */
	dbref	contents;	/* PLAYER, THING, ROOM: head of contentslist */
				/* EXIT: unused */
	dbref	exits;		/* PLAYER, THING, ROOM: head of exitslist */
				/* EXIT: where it is */
	dbref	next;		/* PLAYER, THING: next in contentslist */
				/* EXIT: next in exitslist */
				/* ROOM: unused */
	dbref	link;		/* PLAYER, THING: home location */
				/* ROOM, EXIT: unused */
	dbref	parent;		/* ALL: defaults for attrs, exits, $cmds, */
	dbref	owner;		/* PLAYER: domain number */
				/* THING, ROOM, EXIT: owning player number */
	int	penn;		/* PLAYER: wealth */
				/* THING: sacrifice value */
				/* ROOM, EXIT: ignored */
	FLAG	flags;		/* ALL: Flags set on the object */
};

extern dbref getref();
extern void putref();
extern struct boolexp *dup_bool();
extern void free_boolexp();
extern dbref parse_dbref();
extern int mkattr(char *buff);
extern void al_add (dbref thing, int attrnum);
extern void al_delete (dbref thing, int attrnum);
extern void al_destroy (dbref thing);
extern void al_store (void);
extern void db_grow(dbref newtop);
extern void db_free(void);
extern void db_make_minimal(void);
extern dbref db_read(FILE * f, int *db_format, int *db_version, int *db_flags);
extern dbref db_write(FILE * f, int format, int version);

#define	DOLIST(thing,list) \
	for ((thing)=(list); \
	     ((thing)!=NOTHING) && (Next(thing)!=(thing)); \
	     (thing)=Next(thing))
#define	SAFE_DOLIST(thing,next,list) \
	for ((thing)=(list),(next)=((thing)==NOTHING ? NOTHING: Next(thing)); \
	     (thing)!=NOTHING && (Next(thing)!=(thing)); \
	     (thing)=(next), (next)=Next(next))
#define	DO_WHOLE_DB(thing) \
	for ((thing)=0; (thing)<mudstate.db_top; (thing)++)

#define	Dropper(thing) \
	(Hearer(thing) && (Flags(Owner(thing)) & PLAYER_CONNECT))

#endif				/* __DB_H */