/* db.h */

#include "copyright.h"
#include "attrib.h"

#ifndef __DB_H
#define __DB_H
#include <stdio.h>

#ifndef XENIX
extern void *malloc();
extern void *realloc();
extern void free();
#endif				/* XENIX */

extern int depth;

typedef int dbref;		/* offset into db */
typedef int object_flag_type;

#define TYPE_ROOM 	0x0
#define TYPE_THING 	0x1
#define TYPE_EXIT 	0x2
#define TYPE_PLAYER 	0x3
#define NOTYPE		0x7	/* no particular type */
#define TYPE_MASK 	0x7	/* room for expansion */

#define WIZARD		0x10	/* gets automatic control */
#define LINK_OK		0x20	/* anybody can link to this room */
#define DARK		0x40	/* contents of room are not printed */
				/* exit doesn't appear as 'obvious' */
#define STICKY		0x100	/* this object goes home when dropped */
#define	HAVEN		0x400	/* this room disallows kills in it */
				/* on a player, disallow paging, */
#define QUIET		0x800	/* On an object, will not emit 'set' */
				/* messages.. on a player.. will not see ANY */
				/* set messages. */
#define HALT		0x1000  /* object cannot perform actions */

#ifdef DESTROY
#define GOING 0x4000		/* object is available for recycling */

extern dbref first_free;	/* pointer to free list */
void free_object();
extern void fix_free_list();
void do_empty();
#define FIX fix_free_list()
#else /* DESTROY */
#define FIX
#endif /* DESTROY */

#define ACCESSED 0x8000		/* object has been accessed recently */
#define MARKED   0x10000	/* flag used to trace db checking of room
				 * linkages. */
#define CHOWN_OK 0x40000	/* object can be 'stolen' and made yours */
#define ENTER_OK 0x80000	/* object basically acts like a room with
				 * only one exit (leave), on players */
				/* means that items can be given freely, AND
				 * taken from! */
#define VISUAL	0x100000	/* People other than owners can see property
				 * list of object. */
#define NOSPOOF 0x200000        /* receives notification of those issuing
				 * emits and Pemits */
#ifdef ROYALTY_FLAG
#define ROYALTY	0x400000	/* can look, ex, and @tel like a wizard */
#endif
#define OPAQUE  0x800000	/* Objects inside object will not be seen
				 * on a look. */
#define TERSE 0x2000000         /* Terse objects do not see descriptions,
				 * or succ/fail messages on rooms. */
#ifdef INHERIT_FLAG
#define INHERIT 0x1000000       /* Inherit objects can force their owners. */
                                /* Inherit players have all objects inherit. */
#endif

/* object specific flags */

/* Exit flags */
#define EXIT_KEY 0x8	        /* puppets cannot go through it.  this */
                                /* replaced EXIT_TRANSPARENT, which */
                                /* was not used... */ 
#define EXIT_TRANSPARENT 0x200	/* when you look at the exit you see it's */
				/* desitinations description */

/* Object flags */
#define THING_KEY  0x8		/* cannot be picked up by puppets */
#define THING_VERBOSE 0x80      /* object echoes commands before execution */
#define THING_DEST_OK 0x200	/* can be destroyed by others via @destroy. */
#define THING_IMMORTAL 0x2000   /* cannot be killed */
#define THING_PUPPET   0x20000	/* object relays ALL messages it recieves
				 * to its owner. */
#define THING_SAFE 0x4000000    /* objects marked SAFE cannot be destroyed */
                                /* via the @destroy command. */

/* Player flags */
#ifdef RESTRICTED_BUILDING
#define PLAYER_BUILD 0x8	/* Player can build. */
#endif				/* RESTRICTED_BUILDING */

#define PLAYER_GAGGED 0x80	/* only settable by wizard. Prevents object */
				/* from anything but move and look. */
#define PLAYER_CONNECT 0x200
#define PLAYER_DARK  0x2000	 /* Hide a player from whereis command. */
#define PLAYER_SUSPECT 0x4000000 /* Only settable by wizards. Notifies of a */
				 /* player's name changes, connects, and */
                                 /* disconnects. */

/* Room flags */
#define ROOM_TEMPLE 0x80
#define ROOM_ABODE 0x200
#define ROOM_JUMP_OK 0x2000	/* Anyone can teleport to this room */
#define ROOM_FLOATING 0x8	/* Don't keep blathering about disconnected */
#define ROOM_NO_TEL 0x4000000   /* Mortals can't teleport out of the room */

/* macro to make set string easier to use */
#define SET(a,b) set_string(&(a),b)

/* set macro for compressed strings */

#ifdef COMPRESS
#define SETC(a,b) SET(a,compress(b))
#else
#define SETC(a,b) SET(a,b)
#endif

/* Updates an objects age */
#define Access(x) (db[(x)].flags|=ACCESSED)
#define Typeof(x) (db[(x)].flags & TYPE_MASK)
#define Wizard(x) ((db[(x)].flags & WIZARD) != 0 || God(x))
#ifdef ROYALTY_FLAG 
#define Royalty(x) ((db[(x)].flags & ROYALTY) != 0)
#define Hasprivs(x) (Royalty(x) || Wizard(x))
#else
#define Hasprivs(x) ((db[(x)].flags & WIZARD) != 0 || God(x))
#endif
#define Suspect(x) (db[db[(x)].owner].flags & PLAYER_SUSPECT)
#define Dark(x) (((db[(x)].flags & DARK) != 0) && \
		 (Wizard(x) || \
		  ((Typeof(x)!=TYPE_PLAYER) && \
                   !(db[(x)].flags & THING_PUPPET))))
#define Alive(x) ((Typeof(x)==TYPE_PLAYER) ||      \
                  ((Typeof(x)==TYPE_THING) && (db[x].flags & THING_PUPPET)))
#define Builder(x) ((db[db[(x)].owner].flags & PLAYER_BUILD) || Wizard(x))
#define Nospoof(x) ((db[db[(x)].owner].flags & NOSPOOF))
#define Floating(x) ((db[x].flags & ROOM_FLOATING) != 0)
#define Quiet(x) ((db[x].flags & QUIET) !=0)
#define Haven(x) ((db[x].flags & HAVEN) !=0)
#define Visual(x) ((db[x].flags & VISUAL) != 0)
#ifdef INHERIT_FLAG
#define Inherit(x) ((db[(x)].flags & WIZARD) || \
		    (db[(x)].flags & INHERIT) || \
		    (db[db[(x)].owner].flags & INHERIT) || \
		    (Typeof(x) == TYPE_PLAYER))
/* Note that this is a utility to determine the objects which may or may */
/* not be controlled, rather than a strict check for the INHERIT flag */
#endif

#define IS(thing,type,flag) ((Typeof(thing)==type) && (db[thing].flags & flag))

#define Pennies(thing) (db[thing].penn)
#define s_Pennies(thing,p) (db[thing].penn=(p))

/* 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_IND 5
#define BOOLEXP_CARRY 6
#define BOOLEXP_IS 7

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

#define TRUE_BOOLEXP ((struct boolexp *) 0)

/* lock types */
#define BASICLOCK 0
#define USELOCK 1
#define ENTERLOCK 2

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

struct object {
  const char *name;
  dbref location;		/* pointer to container */
                                /* for exits, pointer to destination */
  dbref contents;		/* pointer to first item */
  dbref exits;			/* pointer to first exit for rooms */
                                /* pointer to home for things and players */
				/* pointer to room it's in for exits. */
  dbref next;			/* pointer to next in contents/exits chain */
  dbref pageto;			/* pointer to last person paged */
  
  /* the following is used for pickups for things, entry for exits */
  struct boolexp *key;		/* if not NOTHING, must have this to do op */
  struct boolexp *usekey;      /* page lock for players, use lock for things */
  struct boolexp *enterkey;     /* enter key */

  dbref owner;			/* who controls this object */
  dbref zone;			/* zone master object number */
  int penn;			/* number of pennies object contains */
  object_flag_type flags;
  object_flag_type status;
  ALIST *list;
};

struct dblist {			/* used by routines in util.c */
	dbref obj;
	struct dblist *next;
};

extern struct object *db;
extern dbref db_top;

extern const char *alloc_string();
extern dbref new_object();
extern dbref getref();
extern void putref();
extern struct boolexp *getboolexp();
extern void putboolexp();
extern int db_write_object();
extern dbref db_write();
extern dbref db_read();
/* Warning: destroys existing db contents! */
extern void free_bool();
extern struct boolexp *dup_bool();
extern struct boolexp *alloc_bool();
extern void free_boolexp();
extern void db_free();
extern dbref parse_dbref();

#define DOLIST(var, first)\
    for((var) = (first); (var) != NOTHING; (var) = db[(var)].next)

#define PUSH(thing, locative) \
    ((db[(thing)].next = (locative)), (locative) = (thing))

#define getloc(thing) (db[thing].location)
#define getzone(thing) (db[thing].zone)

#ifdef USE_MAILER
typedef int mdbref;

struct mail {
  const char *message;
  const char *time;
  dbref from;
  dbref to;
  int number;
  int read;
};
#endif

#endif				/* __DB_H */