/* db.c */
/* $Id: db.c,v 1.33 1993/10/18 02:29:09 nils Exp $ */
#include "credits.h"
#include <stdio.h>
#include <ctype.h>
#include "nalloc.h"
#include "db.h"
#include "config.h"
#include "externs.h"
#include "interface.h"
#include "hash.h"
long getlong();
struct object *db = 0;
dbref db_top = 0;
NALLOC *db_strings=NULL;
#ifdef TEST_MALLOC
int malloc_count = 0;
#endif /* TEST_MALLOC */
dbref db_size = DB_INITIAL_SIZE;
extern char ccom[];
struct builtinattr {
ATTR definition;
int number;
};
/* if you're going to add things to this, please contact me and
get a range of numbers to use so you don't interfere with
attributes used by future versions of muse.
-nils@pc2.pc.maricopa.edu */
struct builtinattr attr[]={
#if 0
{{"Osucc", INH ,NOTHING,1}, 1},
{{"Ofail", INH ,NOTHING,1}, 2},
{{"Fail", INH ,NOTHING,1}, 3},
{{"Succ", INH ,NOTHING,1}, 4},
{{"Xyxxy", AF_WIZARD|AF_DARK ,NOTHING,1}, 5},
{{"Desc", INH ,NOTHING,1}, 6},
{{"Sex", INH|AF_OSEE ,NOTHING,1}, 7},
{{"Odrop", INH ,NOTHING,1}, 8},
{{"Drop", INH ,NOTHING,1}, 9},
{{"Okill", INH ,NOTHING,1}, 10},
{{"Kill", INH ,NOTHING,1}, 11},
{{"Asucc", INH ,NOTHING,1}, 12},
{{"Afail", INH ,NOTHING,1}, 13},
{{"Adrop", INH ,NOTHING,1}, 14},
{{"Akill", INH ,NOTHING,1}, 15},
{{"Does" , INH ,NOTHING,1}, 16},
{{"Charges",INH ,NOTHING,1}, 17},
{{"Runout", INH ,NOTHING,1}, 18},
{{"Startup",INH|AF_WIZARD ,NOTHING,1}, 19},
{{"Aclone", INH ,NOTHING,1}, 20},
{{"Apay", INH ,NOTHING,1}, 21},
{{"Opay", INH ,NOTHING,1}, 22},
{{"Pay", INH ,NOTHING,1}, 23},
{{"Cost", INH ,NOTHING,1}, 24},
{{"Listen", INH ,NOTHING,1}, 26},
{{"Aahear", INH ,NOTHING,1}, 27},
{{"Amhear", INH ,NOTHING,1}, 28},
{{"Ahear", INH ,NOTHING,1}, 29},
{{"Last", AF_WIZARD | AF_DATE | AF_OSEE ,NOTHING,1}, 30},
{{"Queue", AF_WIZARD |AF_UNIMP ,NOTHING,1}, 31},
{{"Idesc", INH ,NOTHING,1}, 32},
{{"Enter", INH ,NOTHING,1}, 33},
{{"Oenter", INH ,NOTHING,1}, 34},
{{"Aenter", INH ,NOTHING,1}, 35},
{{"Adesc", INH ,NOTHING,1}, 36},
{{"Odesc", INH ,NOTHING,1}, 37},
{{"Rquota", AF_DARK | AF_NOMOD | AF_WIZARD,NOTHING,1}, 38},
{{"Idle", AF_DARK | AF_WIZARD ,NOTHING,1}, 39},
{{"Away", AF_DARK | AF_WIZARD ,NOTHING,1}, 40},
{{"Mailk", AF_DARK|AF_NOMOD|AF_WIZARD|AF_UNIMP,NOTHING,1}, 41},
{{"Alias", AF_OSEE ,NOTHING,1}, 42},
{{"Efail", INH ,NOTHING,1}, 43},
{{"Oefail", INH ,NOTHING,1}, 44},
{{"Aefail", INH ,NOTHING,1}, 45},
{{"It", AF_UNIMP ,NOTHING,1}, 46},
{{"Leave", INH ,NOTHING,1}, 47},
{{"Oleave", INH ,NOTHING,1}, 48},
{{"Aleave", INH ,NOTHING,1}, 49},
{{"Channel", AF_WIZARD ,NOTHING,1}, 50},
{{"Quota", AF_DARK|AF_NOMOD|AF_UNIMP|AF_WIZARD,NOTHING,1}, 51},
{{"Pennies", AF_WIZARD | AF_DARK | AF_NOMOD,NOTHING,1}, 52},
{{"Huhto", AF_WIZARD ,NOTHING,1}, 53},
{{"Haven", AF_WIZARD | AF_DARK ,NOTHING,1}, 54},
{{"Alogin", INH ,NOTHING,1}, 55},
{{"Alogout",INH ,NOTHING,1}, 56},
{{"TZ", INH ,NOTHING,1}, 57},
{{"Doomsday", AF_WIZARD ,NOTHING,1}, 58},
#ifdef EMAIL_CREATE
{{"Email", AF_WIZARD ,NOTHING,1}, 59},
#endif
#ifdef USE_SPACE /* Attributes added by Michael Majere */
{{"Aship", AF_SPACE | INH ,NOTHING,1}, 60},
{{"Sector", AF_SPACE ,NOTHING,1}, 61},
{{"Mass", AF_SPACE ,NOTHING,1}, 62},
{{"Radius", AF_SPACE ,NOTHING,1}, 63},
{{"Thrust", AF_SPACE ,NOTHING,1}, 64},
{{"Rating", AF_SPACE ,NOTHING,1}, 65},
{{"Efficiency", AF_SPACE ,NOTHING,1}, 66},
{{"Fuel", AF_SPACE ,NOTHING,1}, 67},
{{"Acceleration", AF_SPACE ,NOTHING,1}, 68},
{{"Vismult", AF_SPACE ,NOTHING,1}, 69},
{{"Pwrgen", AF_SPACE ,NOTHING,1}, 70},
{{"Pwrfuel", AF_SPACE ,NOTHING,1}, 71},
{{"SprStr", AF_SPACE ,NOTHING,1}, 72},
{{"Hull", AF_SPACE ,NOTHING,1}, 73},
{{"Recover", AF_SPACE | AF_DARK | AF_NOMOD ,NOTHING,1}, 74},
{{"Type", AF_SPACE | AF_OSEE ,NOTHING,1}, 75},
{{"Energy", AF_SPACE | AF_UNIMP ,NOTHING,1}, 76},
{{"LinposX", AF_SPACE | AF_UNIMP ,NOTHING,1}, 80},
{{"LinposY", AF_SPACE | AF_UNIMP ,NOTHING,1}, 81},
{{"LinposZ", AF_SPACE | AF_UNIMP ,NOTHING,1}, 82},
{{"LinvelX", AF_SPACE | AF_UNIMP ,NOTHING,1}, 83},
{{"LinvelY", AF_SPACE | AF_UNIMP ,NOTHING,1}, 84},
{{"LinvelZ", AF_SPACE | AF_UNIMP ,NOTHING,1}, 85},
{{"LinaccX", AF_SPACE | AF_UNIMP ,NOTHING,1}, 86},
{{"LinaccY", AF_SPACE | AF_UNIMP ,NOTHING,1}, 87},
{{"LinaccZ", AF_SPACE | AF_UNIMP ,NOTHING,1}, 88},
{{"AngposX", AF_SPACE ,NOTHING,1}, 89},
{{"AngposY", AF_SPACE ,NOTHING,1}, 90},
{{"AngposZ", AF_SPACE ,NOTHING,1}, 91},
{{"AngvelX", AF_SPACE ,NOTHING,1}, 92},
{{"AngvelY", AF_SPACE ,NOTHING,1}, 93},
{{"AngvelZ", AF_SPACE ,NOTHING,1}, 94},
{{"AngaccX", AF_SPACE | AF_UNIMP ,NOTHING,1}, 95},
{{"AngaccY", AF_SPACE | AF_UNIMP ,NOTHING,1}, 96},
{{"AngaccZ", AF_SPACE | AF_UNIMP ,NOTHING,1}, 97},
#endif
{{"Talent", INH| AF_OSEE ,NOTHING,1}, 98},
{{"Race", INH|AF_WIZARD | AF_OSEE ,NOTHING,1}, 99},
{{"Va", INH ,NOTHING,1}, 100+0},
{{"Vb", INH ,NOTHING,1}, 100+1},
{{"Vc", INH ,NOTHING,1}, 100+2},
{{"Vd", INH ,NOTHING,1}, 100+3},
{{"Ve", INH ,NOTHING,1}, 100+4},
{{"Vf", INH ,NOTHING,1}, 100+5},
{{"Vg", INH ,NOTHING,1}, 100+6},
{{"Vh", INH ,NOTHING,1}, 100+7},
{{"Vi", INH ,NOTHING,1}, 100+8},
{{"Vj", INH ,NOTHING,1}, 100+9},
{{"Vk", INH ,NOTHING,1}, 100+10},
{{"Vl", INH ,NOTHING,1}, 100+11},
{{"Vm", INH ,NOTHING,1}, 100+12},
{{"Vn", INH ,NOTHING,1}, 100+13},
{{"Vo", INH ,NOTHING,1}, 100+14},
{{"Vp", INH ,NOTHING,1}, 100+15},
{{"Vq", INH ,NOTHING,1}, 100+16},
{{"Vr", INH ,NOTHING,1}, 100+17},
{{"Vs", INH ,NOTHING,1}, 100+18},
{{"Vt", INH ,NOTHING,1}, 100+19},
{{"Vu", INH ,NOTHING,1}, 100+20},
{{"Vv", INH ,NOTHING,1}, 100+21},
{{"Vw", INH ,NOTHING,1}, 100+22},
{{"Vx", INH ,NOTHING,1}, 100+23},
{{"Vy", INH ,NOTHING,1}, 100+24},
{{"Vz", INH ,NOTHING,1}, 100+25},
{{"Move", INH ,NOTHING,1}, 126},
{{"Omove", INH ,NOTHING,1}, 127},
{{"Amove", INH ,NOTHING,1}, 128},
{{"Lock", AF_LOCK ,NOTHING,1}, 129},
{{"Elock", AF_LOCK ,NOTHING,1}, 130},
{{"Ulock", AF_LOCK ,NOTHING,1}, 131},
{{"Ufail", INH ,NOTHING,1}, 132},
{{"Oufail", INH ,NOTHING,1}, 133},
{{"Aufail", INH ,NOTHING,1}, 134},
{{"Oconnect", INH ,NOTHING,1}, 135},
{{"Aconnect", INH ,NOTHING,1}, 136},
{{"Odisconnect", INH ,NOTHING,1}, 137},
{{"Adisconnect", INH ,NOTHING,1}, 138},
{{"Columns", INH ,NOTHING,1}, 139},
{{"who_flags", INH ,NOTHING,1}, 140},
{{"who_names", INH ,NOTHING,1}, 141},
{{"Apage", INH ,NOTHING,1}, 142},
{{"Apemit", INH ,NOTHING,1}, 143},
{{"Awhisper", INH ,NOTHING,1}, 144},
#ifdef USE_SPACE /* Registers added by Michael Majere */
{{"S0", AF_SPACE ,NOTHING,1}, 145+0},
{{"S1", AF_SPACE ,NOTHING,1}, 145+1},
{{"S2", AF_SPACE ,NOTHING,1}, 145+2},
{{"S3", AF_SPACE ,NOTHING,1}, 145+3},
{{"S4", AF_SPACE ,NOTHING,1}, 145+4},
{{"S5", AF_SPACE ,NOTHING,1}, 145+5},
{{"S6", AF_SPACE ,NOTHING,1}, 145+6},
{{"S7", AF_SPACE ,NOTHING,1}, 145+7},
{{"S8", AF_SPACE ,NOTHING,1}, 145+8},
{{"S9", AF_SPACE ,NOTHING,1}, 145+9},
#endif
{{"Use", INH ,NOTHING,1}, 155},
{{"OUse", INH ,NOTHING,1}, 156},
{{"AUse", INH ,NOTHING,1}, 157},
{{"LHide", AF_LOCK ,NOTHING,1}, 158},
{{"LPage", AF_LOCK ,NOTHING,1}, 159},
{{"Llock", AF_LOCK ,NOTHING,1}, 161},
{{"Lfail", INH ,NOTHING,1}, 162},
{{"Olfail", INH ,NOTHING,1}, 163},
{{"Alfail", INH ,NOTHING,1}, 164},
{{"Slock", AF_LOCK ,NOTHING,1}, 165},
{{"Sfail", INH ,NOTHING,1}, 166},
{{"Osfail", INH ,NOTHING,1}, 167},
{{"Asfail", INH ,NOTHING,1}, 168},
{{"Doing", INH|AF_OSEE ,NOTHING,1}, 169},
{{"Users", INH|AF_WIZARD ,NOTHING,1}, 170},
{{"Defown", INH ,NOTHING,1}, 171},
{{"Warnings",INH ,NOTHING,1}, 172},
{{"WInhibit",INH ,NOTHING,1}, 173},
{{"ANews", INH ,NOTHING,1}, 174},
#endif
#define DOATTR(var, name, flags, num) \
{{name, flags, NOTHING, 1}, num},
#include "attrib.h"
#undef DOATTR
{{0, 0 ,0,0} , 0}
};
#define NUM_BUILTIN_ATTRS ((sizeof(attr)/sizeof(struct builtinattr))-1)
#define MAX_ATTRNUM 256 /* less than this, but this will do. */
ATTR *builtin_atr(num)
int num;
{
static int initted=0;
static ATTR *numtable[MAX_ATTRNUM];
if (!initted) {
/* we need to init. */
int i;
initted = 1;
for (i=0; i<MAX_ATTRNUM; i++) {
int a=0;
while((a<NUM_BUILTIN_ATTRS)&&(attr[a].number!=i))
a++;
if(a<NUM_BUILTIN_ATTRS)
numtable[i] = &(attr[a].definition);
else
numtable[i] = NULL;
}
}
if (num>=0 && num<MAX_ATTRNUM)
return numtable[num];
else
return NULL;
}
static char *attr_disp (atr)
void *atr;
{
return tprintf("#%d, flags #%d",((struct builtinattr *)atr)->number, ((struct builtinattr *)atr)->definition.flags);
}
ATTR *builtin_atr_str (str)
char *str;
{
static struct hashtab *attrhash=NULL;
if (!attrhash)
attrhash = make_hashtab(207, attr, sizeof(struct builtinattr), "attr", attr_disp);
return &((struct builtinattr *)lookup_hash (attrhash, hash_name(str), str))->definition;
/* for (a=0; a<NUM_BUILTIN_ATTRS; a++)
if (!string_compare (str, attr[a].definition.name))
return &(attr[a].definition);
return NULL;*/
}
ATTR *atr_defined_on_str (obj, str)
dbref obj;
char *str;
{
ATRDEF *k;
if (obj < 0 || obj >= db_top)
return NULL; /* sanity check */
for (k=db[obj].atrdefs; k; k=k->next)
if (!string_compare (k->a.name, str))
return &(k->a);
return NULL;
}
ATTR *atr_find_def_str (obj, str)
dbref obj;
dbref str;
{
ATTR *k;
int i;
if ((k=atr_defined_on_str (obj, str)))
return k;
for (i=0; db[obj].parents && db[obj].parents[i]!=NOTHING; i++)
if ((k=atr_find_def_str (db[obj].parents[i], str)))
return k;
return NULL;
}
ATTR *atr_str(player, obj, s)
dbref player;
dbref obj;
char *s;
{
ATTR *a;
char *t;
if ((t=strchr(s,'.'))) { /* definately a user defined attribute. */
dbref onobj;
static char mybuf[1000];
if (t == s) /* first thing too! make it global. */
return builtin_atr_str(s+1);
strcpy(mybuf, s);
mybuf[t-s] = '\0';
init_match (player, mybuf, NOTYPE);
match_everything ();
onobj = match_result();
if (onobj == AMBIGUOUS) onobj = NOTHING;
if (onobj != NOTHING) {
a = atr_defined_on_str (onobj, t+1);
/* if (is_a (player, a->obj))
return a; */
if (a) return a;
}
}
if (player != NOTHING) {
a = atr_find_def_str (player, s);
if (a && is_a(obj, a->obj))
return a;
}
a= builtin_atr_str (s);
if (a) return a;
a = atr_find_def_str (obj, s);
return a; /* if everything else fails, use the one on the
obj. */
}
/* routines to handle object attribute lists */
/* single attribute cache */
static dbref atr_obj= -1;
static ATTR *atr_atr= NULL;
static char *atr_p;
/* clear an attribute in the list */
void atr_clr(thing,atr)
dbref thing;
ATTR *atr;
{
ALIST *ptr=db[thing].list;
atr_obj = -1;
while(ptr) {
if (AL_TYPE(ptr)==atr) {
if (AL_TYPE(ptr)) unref_atr(AL_TYPE(ptr));
AL_DISPOSE(ptr);
return;
}
ptr=AL_NEXT(ptr);
}
}
ALIST *AL_MAKE();
/* add attribute of type atr to list */
void atr_add(thing,atr,s)
dbref thing;
ATTR *atr;
char *s;
{
ALIST *ptr;
char *d;
if (atr == 0) return;
if (!s)
s="";
if (atr == NULL) return;
for(ptr=db[thing].list; ptr && (AL_TYPE(ptr)!=atr); ptr=AL_NEXT(ptr))
;
if (!*s) {
if (ptr) {
unref_atr(AL_TYPE(ptr));
AL_DISPOSE(ptr);
} else
return;
}
s=(char *)compress(s);
if (!ptr || (strlen(s)>strlen(d=(char *)AL_STR(ptr)))) {
/* allocate room for the attribute */
if (ptr) {
AL_DISPOSE(ptr);
db[thing].list=AL_MAKE(atr,db[thing].list,s);
} else {
ref_atr(AL_TYPE((db[thing].list=AL_MAKE(atr,db[thing].list,s))));
}
} else
strcpy(d,s);
atr_obj= -1;
}
/* used internally by defines */
#ifdef SMALL
ALIST *AL_GETPTR(alist)
ALIST *alist;
{
int a;
ALIST *res;
unsigned char *s,*d;
for((a=0),(s=Astr(alist)),d=(unsigned char *)&res; a<sizeof(ALIST *); a++)
*d++= *s++;
if (res)
a= *((char *)res);
return(res);
}
#endif
static char *atr_get_internal (thing, atr)
dbref thing;
ATTR *atr;
{
int i;
ALIST *ptr;
char *k;
for(ptr=db[thing].list; ptr; ptr=AL_NEXT(ptr))
if (ptr && (AL_TYPE(ptr)==atr))
return((char *)uncompress(AL_STR(ptr)));
for (i=0; db[thing].parents && db[thing].parents[i] != NOTHING; i++)
if ((k = atr_get_internal (db[thing].parents[i], atr)))
if (*k)
return k;
return "";
}
char *atr_get(thing,atr)
dbref thing;
ATTR *atr;
{
ALIST *ptr;
if (thing < 0 || thing >= db_top || !atr)
return ""; /* sanity check */
if ((thing==atr_obj) && (atr==atr_atr))
return(atr_p);
atr_obj=thing;
atr_atr=atr;
for(ptr=db[thing].list; ptr; ptr=AL_NEXT(ptr))
if (ptr && AL_TYPE(ptr)==atr)
return(atr_p=(char *)uncompress(AL_STR(ptr)));
if (atr->flags & AF_INHERIT)
return (atr_p = atr_get_internal (thing, atr));
else
return(atr_p="");
}
void atr_free(thing)
dbref thing;
{
ALIST *ptr,*next;
if (thing < 0 || thing >= db_top)
return; /* sanity check */
for(ptr=db[thing].list;ptr;ptr=next) {
next=AL_NEXT(ptr);
free(ptr);
}
db[thing].list=NULL;
atr_obj= -1;
}
ALIST *AL_MAKE(type,next,string)
ATTR *type;
ALIST *next;
char *string;
{
#ifdef SMALL
ALIST *ptr;
int a;
/* allocate maximum possibly needed */
if (type>127) {
log_error("Type out of range");
report();
}
ptr= (ALIST *)
malloc(sizeof(ALIST)+sizeof(ALIST *)+strlen(string)+1);
ptr->al_type=type;
if (((a=((char *)ptr)-((char *)next))<256) && (a>0)) {
ptr->al_type|=128;
*Astr(ptr)=a;
/* give back a lousy 3 bytes? With 100K objects each with
multiple attributes that amounts to a $&!^load of memory! */
nza_giveback(db_strings,sizeof(ALIST *)-1);
strcpy(Astr(ptr)+1,string);
}
else {
unsigned char *s,*d;
for((a=0),(s=(unsigned char *)&next),d=Astr(ptr);a<sizeof(ALIST *);a++)
*d++= *s++;
strcpy(Astr(ptr)+sizeof(ALIST *),string);
}
return(ptr);
#else
ALIST *ptr;
ptr=(ALIST *) malloc(sizeof(ALIST)+strlen(string)+1);
AL_TYPE(ptr) = type;
ptr->next=next;
strcpy(AL_STR(ptr),string);
return(ptr);
#endif
}
/* garbage collect an attribute list */
void atr_collect(thing)
dbref thing;
{
ALIST *ptr,*next;
if (thing < 0 || thing >= db_top)
return; /* sanity check */
ptr=db[thing].list;
db[thing].list=NULL;
while(ptr) {
if (AL_TYPE(ptr))
db[thing].list=AL_MAKE(AL_TYPE(ptr),db[thing].list,AL_STR(ptr));
next=AL_NEXT(ptr);
free(ptr);
ptr=next;
}
atr_obj= -1;
}
void atr_cpy_noninh(dest,source)
dbref dest;
dbref source;
{
ALIST *ptr;
ptr=db[source].list;
db[dest].list=NULL;
while(ptr) {
if (AL_TYPE(ptr) && !(AL_TYPE(ptr)->flags&AF_INHERIT)) {
db[dest].list=AL_MAKE(AL_TYPE(ptr),db[dest].list,AL_STR(ptr));
ref_atr(AL_TYPE(ptr));
}
ptr=AL_NEXT(ptr);
}
}
int db_init=0;
static void db_grow(newtop)
dbref newtop;
{
struct object *newdb;
if(newtop > db_top) {
db_top = newtop;
if(!db) {
/* make the initial one */
db_size = (db_init) ? db_init : DB_INITIAL_SIZE;
if((db = 5+(struct object *)
bigalloc((db_size+5) * sizeof(struct object))) == 0) {
abort();
}
memchr (db-5, 0, sizeof(struct object)*(db_size+5));
}
/* maybe grow it */
if(db_top > db_size) {
/* make sure it's big enough */
while(db_top > db_size) db_size *= 2;
if((newdb = 5+(struct object *)
bigalloc((5+db_size) * sizeof(struct object))) == 0) {
abort();
}
memcpy(newdb,db,db_top*sizeof(struct object));
memchr(newdb+db_top, 0, sizeof(struct object)*(db_size - db_top));
bigfree(db-5);
db = newdb;
}
}
}
dbref new_object()
{
dbref newobj;
struct object *o;
#ifdef DESTROY
/* if stuff in free list use it */
if ((newobj=free_get())==NOTHING)
/* allocate more space */
#endif /* DESTROY */
{
newobj = db_top;
db_grow(db_top + 1);
#ifdef DO_AGE
db[newobj].num1=db[newobj].num2=newobj;
#endif DO_AGE
}
/* clear it out */
o = db+newobj;
o->name = 0;
o->list = 0;
o->location = NOTHING;
o->contents = NOTHING;
o->exits = NOTHING;
o->parents = NULL;
o->children = NULL;
o->link = NOTHING;
o->next = NOTHING;
o->owner = NOTHING;
/* o->penn = 0;*/
/* flags you must initialize yourself */
o->mod_time = 0;
o->create_time = time(NULL);
o->zone = NOTHING;
return newobj;
}
#define DB_MSGLEN 1040
void putref(f,ref)
FILE *f;
dbref ref;
{
fprintf(f, "%d\n", ref);
}
void put_long(f,ref)
FILE *f;
long ref;
{
fprintf(f, "%ld\n", ref);
}
void putstring(f,s)
FILE *f;
char *s;
{
if (s) fputs(s, f);
fputc('\n', f);
}
/* static char *atr_format P((ATTR *));
static char *atr_format (k)
ATTR *k;
{
static char opbuf[100];
ATRDEF *def;
int j;
if (k->obj == NOTHING) {
sprintf(opbuf,"%d",*(((int *)k)-1)); * get the atr number. kludgy. *
return opbuf;
}
for (j=0,def=db[k->obj].atrdefs; def; def=def->next, j++)
if (&(def->a) == k) {
sprintf(opbuf,"%d.%d",k->obj, j);
return opbuf;
}
sprintf(opbuf,"%d.%d",k->obj,0);
return opbuf;
}
static ATTR *atr_unformat (o, str)
dbref o;
char *str;
{
dbref obj;
int num;
int i;
ATRDEF *atr;
if (!strchr(str,'.'))
return builtin_atr(atoi(str));
*strchr(str,'.') = '\0';
obj = atoi(str);
num = atoi(str+strlen(str)+1);
if (obj>=o) {
db_grow (obj+1);
if (!db[obj].atrdefs) {
db[obj].atrdefs=malloc(sizeof(ATRDEF));
db[obj].atrdefs->a.name=NULL;
db[obj].atrdefs->next=NULL;
}
for (atr = db[obj].atrdefs, i=0; atr->next && i<num; atr=atr->next, i++)
;
while (i < num) {
atr->next = malloc( sizeof(ATRDEF));
atr->next->a.name = NULL;
atr->next->next = NULL;
atr = atr->next;
i++;
}
} else
for (atr=db[obj].atrdefs, i=0; i<num; atr=atr->next, i++)
;
return &(atr->a);
} */
int db_write_object(f,i)
FILE *f;
dbref i;
{
struct object *o;
ALIST *list;
o = db + i;
putstring(f, o->name);
putref(f, o->location);
putref(f, o->zone);
putref(f, o->contents);
putref(f, o->exits);
putref(f, o->link);
putref(f, o->next);
putref(f, o->owner);
/* putref(f, Pennies(i));*/
putref(f, o->flags);
putref(f, o->mod_time);
putref(f, o->create_time);
if(Typeof(i)==TYPE_PLAYER)
put_powers(f,i);
/* write the attribute list */
for(list=o->list;list;list=AL_NEXT(list)) {
if (AL_TYPE(list)) {
ATTR *x;
x=AL_TYPE(list);
if(x && !(x->flags&AF_UNIMP)) {
if (x->obj == NOTHING) { /* builtin attribute. */
fputc ('>',f);
putref (f, ((struct builtinattr *)x)->number); /* kludgy. fix this. xxxx */
putref (f, NOTHING);
} else {
ATRDEF *m;
int j;
fputc ('>', f);
for (m=db[AL_TYPE(list)->obj].atrdefs, j=0;
m; m=m->next, j++)
if ((&(m->a)) == AL_TYPE(list)) {
putref (f, j);
break;
}
if (!m) {
putref (f, 0);
putref (f, NOTHING);
} else
putref(f,AL_TYPE(list)->obj);
}
putstring (f, uncompress(AL_STR (list)));
}
}
}
fprintf(f,"<\n");
putlist(f,o->parents);
putlist(f, o->children);
put_atrdefs(f, o->atrdefs);
return 0;
}
dbref db_write(f)
FILE *f;
{
dbref i;
fprintf(f,"@%d\n",DB_VERSION);
fprintf(f,"~%d\n",db_top);
for(i = 0; i < db_top; i++) {
fprintf(f, "&%d\n", i);
db_write_object(f, i);
}
fputs("***END OF DUMP***\n", f);
write_mail(f);
fflush(f);
return(db_top);
}
dbref parse_dbref(s)
char *s;
{
char *p;
long x;
x = atol(s);
if(x > 0)
return x;
else if(x == 0)
/* check for 0 */
for(p = s; *p; p++) {
if(*p == '0') return 0;
if(!isspace(*p)) break;
}
/* else x < 0 or s != 0 */
return NOTHING;
}
dbref getref(f)
FILE *f;
{
static char buf[DB_MSGLEN];
fgets(buf, sizeof(buf), f);
return(atoi(buf));
}
long getlong(f)
FILE *f;
{
static char buf[DB_MSGLEN];
fgets(buf, sizeof(buf), f);
return(atol(buf));
}
char *getstring_noalloc(f)
FILE *f;
{
static char buf[DB_MSGLEN];
char *p;
fgets(buf, sizeof(buf), f);
for(p = buf; *p; p++)
if(*p == '\n') {
*p = '\0';
break;
}
return buf;
}
/*#define getstring(x) alloc_string(getstring_noalloc(x))*/
#define getstring(x,p) {p=NULL;SET(p,getstring_noalloc(x));}
#define getstring_compress(x,p) getstring(x,p)
/* just return the string, for now, we need to convert attrs later */
void getboolexp(i, f)
dbref i;
FILE *f;
{
char buffer[DB_MSGLEN];
char *p = buffer;
int c;
while ((c = getc(f)) != '\n') {
if (c == ':') { /* snarf up the attribute */
*p++ = c;
while ((c = getc(f)) != '\n') *p++ = c;
} else *p++ = c;
}
*p = '\0';
atr_add(i, A_LOCK, buffer);
}
char *b;
void get_num(s, i)
char **s;
int *i;
{
*i = 0;
while (**s && isdigit(**s)) {
*i = (*i * 10) + **s - '0';
(*s)++;
}
return;
}
#define RIGHT_DELIMITER(x) ((x == AND_TOKEN) || (x == OR_TOKEN) || \
(x == ':') || (x == '.') || (x == ')') || \
(x == '=') || (!x))
void grab_dbref(p)
char *p;
{
int num, n;
dbref thing;
ATRDEF *atr;
ATTR *attr;
get_num(&b, &num);
switch (*b) {
case '.':
b++;
sprintf(p, "#%d", num);
p += strlen(p);
*p++ = '.';
thing = (dbref) num;
get_num(&b, &num);
for (atr=db[thing].atrdefs, n=0; n<num; atr=atr->next, n++);
strcpy(p, atr->a.name);
p += strlen(p);
*p++ = *b++;
while (!RIGHT_DELIMITER(*b)) *p++ = *b++;
*p = '\0';
break;
case ':':
b++;
attr = builtin_atr(num);
strcpy(p, attr->name);
p += strlen(p);
*p++ = ':';
while (!RIGHT_DELIMITER(*b)) *p++ = *b++;
*p = '\0';
break;
default:
sprintf(p, "#%d", num);
break;
}
return;
}
int convert_sub(p, outer)
char *p;
int outer;
{
int inner;
if (!*b) {
*p = '\0';
return 0;
}
switch (*b) {
case '(':
b++;
inner = convert_sub(p,outer);
if (*b == ')') b++;
else {
p += strlen(p);
goto part2;
}
return inner;
case NOT_TOKEN:
*p++ = *b++;
if ((inner = convert_sub(p+1,outer)) > 0) {
*p = '(';
p += strlen(p);
*p++ = ')';
*p = '\0';
} else {
p++;
while(*p) *(p-1) = *p++;
*--p = '\0';
}
return inner;
default:
/* a dbref of some sort */
grab_dbref(p);
p += strlen(p);
}
part2:
switch (*b) {
case AND_TOKEN:
*p++ = *b++;
if ((inner = convert_sub(p+1, 1)) == 2) {
*p = '(';
p += strlen(p);
*p++ = ')';
*p = '\0';
} else {
p++;
while(*p) *(p-1) = *p++;
*--p = '\0';
}
return 1;
case OR_TOKEN:
*p++ = *b++;
inner = convert_sub(p, 2);
p += strlen(p);
return 2;
default:
return 0;
}
}
int is_zone(i)
dbref i;
{
dbref j;
for (j = 0; j < db_top; j++)
if (db[j].zone == i) return 1;
return 0;
}
void convert_boolexp()
{
dbref i;
char buffer[BUFFER_LEN], *p;
for (i = 0; i < db_top; i++) {
p = buffer;
b = atr_get(i, A_LOCK);
convert_sub(p, 0);
if ((db[i].flags & ENTER_OK) && (!is_zone(i))) {
atr_add(i, A_ELOCK, buffer);
sprintf(buffer,"#%d",db[i].owner);
atr_add(i, A_LOCK, buffer);
} else atr_add(i, A_LOCK, buffer);
}
return;
}
void db_free()
{
dbref i;
struct object *o;
if(db) {
for(i = 0; i < db_top; i++) {
o = &db[i];
SET(o->name,NULL);
atr_free(i);
/* Everything starts off very old */
}
bigfree(db-5);
db = 0;
db_init=db_top = 0;
}
/* if (db_strings)
nza_close(db_strings);
db_strings=nza_open(sizeof(char *));*/
}
/* read attribute list */
int get_list(f, obj, vers)
FILE *f;
dbref obj;
int vers;
{
ATRDEF *atr;
int atrnum;
dbref atrobj;
dbref old_db_top;
char *s;
int c;
int i;
while(1)
switch(c=fgetc(f)) {
case '>': /* read # then string */
atrnum = getref(f);
if (vers <= 7) {
if (builtin_atr(atrnum) && !(builtin_atr(atrnum)->flags&AF_UNIMP))
atr_add (obj, builtin_atr(atrnum), s=getstring_noalloc(f));
else getstring_noalloc(f);
} else {
atrobj = getref(f);
if (atrobj == NOTHING) {
if (builtin_atr(atrnum) && !(builtin_atr(atrnum)->flags&AF_UNIMP))
atr_add (obj, builtin_atr(atrnum), s=getstring_noalloc(f));
else getstring_noalloc(f);
} else
if (atrobj >= obj) { /* ergh, haven't read it in yet. */
old_db_top = db_top;
db_grow (atrobj+1);
db_top = old_db_top;
if (!db[atrobj].atrdefs) {
db[atrobj].atrdefs=malloc( sizeof(ATRDEF));
db[atrobj].atrdefs->a.name = NULL;
db[atrobj].atrdefs->next = NULL;
}
for (atr = db[atrobj].atrdefs, i=0;
atr->next && i<atrnum;
atr=atr->next, i++)
; /* check to see if it's already there. */
while (i < atrnum) {
atr->next = malloc( sizeof(ATRDEF));
atr->next->a.name = NULL;
atr->next->next = NULL;
atr = atr->next;
i++;
}
atr_add (obj, &(atr->a), s=getstring_noalloc (f));
} else {
for (atr=db[atrobj].atrdefs, i=0;
i<atrnum; atr=atr->next, i++);
atr_add (obj, &(atr->a), s=getstring_noalloc (f));
}
}
break;
case '<': /* end of list */
if ('\n'!=fgetc(f)) {
log_error(tprintf("no line feed on object %d",obj));
return(0);
}
return(1);
default:
log_error(tprintf("Bad character %c on object %d",c,obj));
return(0);
}
}
object_flag_type upgrade_flags(version, player, flags)
int version;
dbref player;
object_flag_type flags;
{
long type;
int iskey, member, chown_ok, link_ok, iswizard;
/* only modify version 1 */
if ( version > 1 )
return flags;
/* record info from old bits */
iskey = (flags & 0x8); /* if was THING_KEY */
link_ok = (flags & 0x20); /* if was LINK_OK */
chown_ok = (flags & 0x40000); /* if was CHOWN_OK */
member = (flags & 0x2000); /* if player was a member */
iswizard = (flags & 0x10); /* old wizard bit flag */
type = flags & 0x3; /* yank out old object type */
/* clear out old bits */
flags &= ~TYPE_MASK; /* set up for 4-bit encoding */
flags &= ~THING_KEY; /* clear out thing key bit */
flags &= ~INHERIT_POWERS; /* clear out new spec pwrs bit */
flags &= ~CHOWN_OK;
flags &= ~LINK_OK;
/* put these bits in their new positions */
flags |= (iskey) ? THING_KEY : 0;
flags |= (link_ok) ? LINK_OK : 0;
flags |= (chown_ok) ? CHOWN_OK : 0;
#define TYPE_GUEST 0x8
#define TYPE_TRIALPL 0x9
#define TYPE_MEMBER 0xA
#define TYPE_ADMIN 0xE
#define TYPE_DIRECTOR 0xF
/* encode type under 4-bit scheme */
/* nonplayers */
if ( type != 3 ) {
flags |= type;
if ( iswizard )
flags |= INHERIT_POWERS;
}
/* god */
else if ( player == 1 )
flags |= TYPE_DIRECTOR;
/* wizards */
else if ( iswizard )
flags |= TYPE_ADMIN;
/* members */
else if ( member )
flags |= TYPE_MEMBER;
/* guests */
else if ( (flags & PLAYER_MORTAL) ) {
flags &= ~PLAYER_MORTAL;
flags |= TYPE_GUEST;
}
/* trial players */
else
flags |= TYPE_TRIALPL;
#undef TYPE_DIRECTOR
#undef TYPE_GUEST
#undef TYPE_TRIALPL
#undef TYPE_MEMBER
#undef TYPE_ADMIN
return flags;
}
void scramble_to_link()
{
dbref i,j;
for(i=0;i<db_top;i++) {
if(Typeof(i) == TYPE_ROOM || Typeof(i)== TYPE_EXIT) {
db[i].link = db[i].location;
db[i].location = i;
} else if(Typeof(i)==TYPE_THING || Typeof(i)>=TYPE_PLAYER) {
db[i].link = db[i].exits;
db[i].exits = -1;
}
}
for (i=0;i<db_top;i++) {
if(Typeof(i)==TYPE_ROOM)
for(j=db[i].exits;j!= NOTHING;j=db[j].next)
db[j].location = i;
}
}
void db_check() /* put quotas in! */
{
dbref i;
for(i=0;i<db_top;i++)
if(Typeof(i)==TYPE_PLAYER) {
dbref j;
int cnt=(-1);
for(j=0;j<db_top;j++)
if(db[j].owner == i)
cnt++;
atr_add(i,A_QUOTA,tprintf("%d",atoi(atr_get(i,A_RQUOTA))+cnt));
}
}
static int db_read_object P((dbref, FILE *));
void count_atrdef_refcounts P((void))
{
int i;
ATRDEF *k;
ALIST *l;
for (i=0; i<db_top; i++)
for (k=db[i].atrdefs; k; k=k->next) {
k->a.refcount = 1;
}
for (i=0; i<db_top; i++)
for (l=db[i].list; l; l=AL_NEXT(l)) {
if (AL_TYPE(l))
ref_atr(AL_TYPE(l));
}
}
static FILE *db_read_file=NULL;
void db_set_read(f)
FILE *f;
{
db_read_file = f;
}
int loading_db = 0;
void run_startups()
{
dbref i;
for (i=0; i<db_top; i++) {
if (*atr_get(i,A_STARTUP))
parse_que (i, atr_get(i,A_STARTUP), i);
if (IS(i,TYPE_PLAYER,PLAYER_CONNECT))
announce_disconnect(i);
}
}
void load_more_db()
{
static dbref i = NOTHING;
int j;
if (loading_db) return;
if (i == NOTHING) {
clear_players();
db_free();
i = 0;
}
for (j=0; j<123 && i >=0; j++,i++) {
if (i%1000 == 0) {
struct descriptor_data *d;
char buf[1024];
sprintf(buf,"Please wait: Database loading still in progress. Now loading object #%d of %d.\n",i,db_init*2/3);
for (d=descriptor_list; d; d=d->next) {
queue_string(d,buf);
}
}
i = db_read_object (i,db_read_file);
}
if (i == -2) {
loading_db = 1;
read_mail(db_read_file);
count_atrdef_refcounts();
run_startups();
return;
}
if (i == -1) {
log_error("Couldn't load database; shutting down the muse.");
exit_nicely(136);
}
}
dbref db_read(f)
FILE *f;
{
dbref i;
clear_players();
db_free();
for(i = 0;i>=0; i++)
i = db_read_object (i,f);
read_mail(f);
if (i == -2) {
count_atrdef_refcounts();
return db_top; /* it worked! */
}
return -1;
}
int dozonetemp;
static int db_read_object (i,f)
dbref i;
FILE *f;
{
int c;
struct object *o;
char *end;
static int db_version = 1; /* old db's default to v1 */
c = getc(f);
switch(c) {
/* read version number */
case '@':
db_version = getref(f);
if ( db_version != DB_VERSION )
log_important(tprintf("Converting DB from v%d to v%d",
db_version, DB_VERSION));
break;
/* make sure database is at least this big *1.5 */
case '~':
db_init=(getref(f)*3)/2;
break;
/* TinyMUSH old object storage definition */
case '#':
/* another entry, yawn */
if(i != getref(f))
return -2; /* we blew it */
/* make space */
db_grow(i+1);
/* read it in */
o = db+i;
o->list=NULL;
getstring(f,o->name);
s_Desc(i,getstring_noalloc(f));
o->location = getref(f);
o->zone = NOTHING;
o->contents = getref(f);
o->exits = getref(f);
o->link = NOTHING; /* atleast until we scramble_to_link */
o->next = getref(f);
o->mod_time = o->create_time = 0;
getboolexp(i, f);
s_Fail(i,getstring_noalloc(f));
s_Succ(i,getstring_noalloc(f));
s_Ofail(i,getstring_noalloc(f));
s_Osucc(i,getstring_noalloc(f));
o->owner = getref(f);
o->flags = getref(f); /* temp storage for pennies */
s_Pennies(i,o->flags);
o->flags = upgrade_flags(db_version, i, getref(f));
#ifdef DO_AGE
o->num1=o->num2=i;
#endif
s_Pass(i,getstring_noalloc(f));
o->atrdefs = 0;
o->parents = NULL;
o->children = NULL;
o->atrdefs = NULL;
/* check to see if it's a player */
if(Typeof(i) == TYPE_PLAYER)
add_player(i);
break;
/* TinyMUSH new version object storage definition */
case '!': /* non-zone oriented database */
case '&': /* zone oriented database */
/* make space */
i=getref(f);
db_grow(i+1);
/* read it in */
o = db+i;
getstring(f,o->name);
o->location = getref(f);
if ( c == '!' )
o->zone = NOTHING;
else if ( db_version >= 3 )
o->zone = getref(f);
o->contents = getref(f);
o->exits = getref(f);
if(db_version < 5)
o->link = NOTHING;
else
o->link = getref(f);
o->next = getref(f);
o->list = NULL;
if (db_version <= 8) getboolexp(i, f);
o->owner = getref(f);
if(db_version<=3) {
int k;
k=getref(f);
s_Pennies(i,k);
}
o->flags = upgrade_flags(db_version, i, getref(f));
if (db_version >= 10) {
o->mod_time = getref(f);
o->create_time = getref(f);
} else
o->mod_time = o->create_time = 0;
if (db_version <= 10) {
if (i == 0 && o->zone == NOTHING)
/* ack. */
log_error("no #0 zone");
else if (Typeof(i) == TYPE_ROOM && o->zone == NOTHING)
o->zone = db[0].zone;
else if (Typeof(i) != TYPE_ROOM)
o->zone = NOTHING;
}
if(db_version >= 6)
if (Typeof(i) == TYPE_PLAYER) {
get_powers(i,getstring_noalloc(f));
} else {
if(db_version == 6)
get_powers(i,getstring_noalloc(f));
o->pows=NULL;
}
else {
o->pows=NULL; /* we'll fiddle with it later. */
}
#ifdef DO_AGE
o->num1=o->num2=i;
#endif
/* read attribute list for item */
if (!get_list (f, i, db_version)) {
log_error(tprintf("bad attribute list object %d",i));
return -2;
}
if (db_version >7) {
o->parents = getlist (f);
o->children = getlist (f);
o->atrdefs = get_atrdefs (f, o->atrdefs);
} else {
o->parents = NULL;
o->children = NULL;
o->atrdefs = NULL;
}
/* check to see if it's a player */
if(Typeof(i) == TYPE_PLAYER ||
(db_version<6 && Typeof(i)>TYPE_PLAYER)) { /* ack! */
add_player(i);
}
break;
case '*':
end = getstring_noalloc(f);
if(strcmp(end, "**END OF DUMP***")) {
/* free((void *) end);*/
log_error(tprintf("no end of dump %d",i));
return -2;
} else {
extern void zero_free_list P((void));
/* free((void *) end);*/
log_important("done loading database.");
zero_free_list();
db_check();
if(db_version <6) {
dbref i;
atr_add(GOD,A_QUEUE,"-999999"); /* hope we don't have enough players to overflow that. */
for(i=0;i<db_top;i++) {
if((db[i].flags&TYPE_MASK) >= TYPE_PLAYER) {
parse_que(GOD,tprintf("@class #%d=%s",i,
class_to_name(old_to_new_class(db[i].flags&TYPE_MASK))),
GOD);
db[i].flags&=~TYPE_MASK;
db[i].flags|=TYPE_PLAYER;
db[i].pows=malloc(2*sizeof(ptype));;
db[i].pows[1]=0; /* don't care about the [0]... */
}
}
}
if (db_version <= 4) scramble_to_link();
if (db_version <= 8) convert_boolexp();
if (db_version <= 10 && db_version >= 3) {
int j;
/* make the zone heirarchy. */
for (j=0; j<db_top; j++)
if (db[j].zone != NOTHING && db[db[j].zone].zone == NOTHING)
db[db[j].zone].zone = db[0].zone;
if (db[0].zone != NOTHING)
db[db[0].zone].zone = NOTHING;
}
return -3;
}
default:
log_error(tprintf("failed object %d",i));
return -2;
}
return i;
}
dbref *getlist(f)
FILE *f;
{
dbref *op;
int len;
len = getref(f);
if (len == 0) return NULL;
op = malloc( sizeof(dbref)*(len+1));
op[len] = NOTHING;
for (len--;len>=0; len--)
op[len] = getref(f);
return op;
}
void putlist(f, list)
FILE *f;
dbref *list;
{
int k;
if ((!list) || (list[0] == NOTHING)) {
putref (f, 0);
return;
}
for (k=0; list[k]!=NOTHING; k++);
putref (f, k);
for (k--; k>=0; k--)
putref (f,list[k]);
}
char *unparse_attr (atr, dep)
ATTR *atr;
int dep;
{
static char buf[1000];
buf[dep]=0;
if (dep)
for (dep--; dep>=0; dep--)
buf[dep] = '+';
if (atr->obj == NOTHING)
strcat (buf, atr->name);
else
sprintf(buf+strlen(buf),"#%d.%s",atr->obj, atr->name);
return buf;
}
#define DOATTR(var, name, flags, num) ATTR *var;
#define DECLARE_ATTR
#include "attrib.h"
#undef DECLARE_ATTR
#undef DOATTR
void init_attributes()
{
#define DOATTR(var, name, flags, num) var = builtin_atr(num);
#include "attrib.h"
#undef DOATTR
}
#if 0
ATTR *A_QUEUE;
ATTR *A_LISTEN;
ATTR *A_AHEAR;
ATTR *A_AMHEAR;
ATTR *A_AAHEAR;
ATTR *A_STARTUP;
ATTR *A_HUHTO;
ATTR *A_IT;
ATTR *A_LEAVE;
ATTR *A_OLEAVE;
ATTR *A_ALEAVE;
ATTR *A_ENTER;
ATTR *A_OENTER;
ATTR *A_AENTER;
ATTR *A_SUCC;
ATTR *A_OSUCC;
ATTR *A_ASUCC;
ATTR *A_DROP;
ATTR *A_ODROP;
ATTR *A_ADROP;
ATTR *A_FAIL;
ATTR *A_OFAIL;
ATTR *A_AFAIL;
ATTR *A_PENNIES;
ATTR *A_EFAIL;
ATTR *A_OEFAIL;
ATTR *A_AEFAIL;
ATTR *A_ALIAS;
ATTR *A_CHARGES;
ATTR *A_RUNOUT;
ATTR *A_RQUOTA;
ATTR *A_SEX;
ATTR *A_TZ;
ATTR *A_LAST;
ATTR *A_CHANNEL;
ATTR *A_DOOMSDAY;
ATTR *A_QUOTA;
ATTR *A_PASS;
ATTR *A_ACLONE;
ATTR *A_DESC;
ATTR *A_ODESC;
ATTR *A_ADESC;
ATTR *A_IDESC;
ATTR *A_KILL;
ATTR *A_OKILL;
ATTR *A_AKILL;
ATTR *A_COST;
ATTR *A_PAY;
ATTR *A_OPAY;
ATTR *A_APAY;
ATTR *A_HAVEN;
ATTR *A_IDLE;
ATTR *A_AWAY;
ATTR *A_USE;
ATTR *A_OUSE;
ATTR *A_AUSE;
ATTR *A_MAILK;
#ifdef USE_SPACE /* Registers added by Michael Majere */
ATTR *A_ASHIP;
ATTR *A_SECTOR;
ATTR *A_MASS;
ATTR *A_RADIUS;
ATTR *A_THRUST;
ATTR *A_RATING;
ATTR *A_EFFICIENCY;
ATTR *A_FUEL;
ATTR *A_ACCELERATION;
ATTR *A_VISMULT;
ATTR *A_PWRGEN;
ATTR *A_PWRFUEL;
ATTR *A_SPRSTR;
ATTR *A_HULL;
ATTR *A_RECOVER;
ATTR *A_TYPE;
ATTR *A_ENERGY;
ATTR *A_LINPOSX;
ATTR *A_LINPOSY;
ATTR *A_LINPOSZ;
ATTR *A_LINVELX;
ATTR *A_LINVELY;
ATTR *A_LINVELZ;
ATTR *A_LINACCX;
ATTR *A_LINACCY;
ATTR *A_LINACCZ;
ATTR *A_ANGPOSX;
ATTR *A_ANGPOSY;
ATTR *A_ANGPOSZ;
ATTR *A_ANGVELX;
ATTR *A_ANGVELY;
ATTR *A_ANGVELZ;
ATTR *A_ANGACCX;
ATTR *A_ANGACCY;
ATTR *A_ANGACCZ;
ATTR *A_S0;
ATTR *A_S1;
ATTR *A_S2;
ATTR *A_S3;
ATTR *A_S4;
ATTR *A_S5;
ATTR *A_S6;
ATTR *A_S7;
ATTR *A_S8;
ATTR *A_S9;
#endif
ATTR *A_TALENT;
ATTR *A_DOING;
ATTR *A_RACE;
ATTR *A_MOVE;
ATTR *A_OMOVE;
ATTR *A_AMOVE;
#ifdef EMAIL_CREATE
ATTR *A_EMAIL;
#endif
ATTR *A_LOCK;
ATTR *A_ELOCK;
ATTR *A_ULOCK;
ATTR *A_LLOCK;
ATTR *A_UFAIL;
ATTR *A_OUFAIL;
ATTR *A_AUFAIL;
ATTR *A_OCONN;
ATTR *A_ACONN;
ATTR *A_ODISC;
ATTR *A_ADISC;
ATTR *A_COLUMNS;
ATTR *A_WHOFLAGS;
ATTR *A_WHONAMES;
ATTR *A_APAGE;
ATTR *A_APEMIT;
ATTR *A_AWHISPER;
#ifdef USE_DOING
ATTR *A_DOING;
#endif
ATTR *A_LFAIL;
ATTR *A_OLFAIL;
ATTR *A_ALFAIL;
ATTR *A_SLOCK;
ATTR *A_SFAIL;
ATTR *A_OSFAIL;
ATTR *A_ASFAIL;
ATTR *A_USERS;
ATTR *A_DEFOWN;
ATTR *A_LHIDE;
ATTR *A_LPAGE;
ATTR *A_WARNINGS;
ATTR *A_WINHIBIT;
ATTR *A_ANEWS;
void init_attributes()
{
A_OSUCC = builtin_atr(1);
A_OFAIL = builtin_atr(2);
A_FAIL = builtin_atr(3);
A_SUCC = builtin_atr(4);
A_PASS = builtin_atr(5);
A_DESC = builtin_atr(6);
A_SEX = builtin_atr(7);
A_ODROP = builtin_atr(8);
A_DROP = builtin_atr(9);
A_OKILL = builtin_atr(10);
A_KILL = builtin_atr(11);
A_ASUCC = builtin_atr(12);
A_AFAIL = builtin_atr(13);
A_ADROP = builtin_atr(14);
A_AKILL = builtin_atr(15);
A_USE = builtin_atr(155);
A_OUSE = builtin_atr(156);
A_AUSE = builtin_atr(157);
A_CHARGES = builtin_atr(17);
A_RUNOUT = builtin_atr(18);
A_STARTUP = builtin_atr(19);
A_ACLONE = builtin_atr(20);
A_APAY = builtin_atr(21);
A_OPAY = builtin_atr(22);
A_PAY = builtin_atr(23);
A_COST = builtin_atr(24);
A_LISTEN = builtin_atr(26);
A_AAHEAR = builtin_atr(27);
A_AMHEAR = builtin_atr(28);
A_AHEAR = builtin_atr(29);
A_LAST = builtin_atr(30);
A_QUEUE = builtin_atr(31);
A_IDESC = builtin_atr(32);
A_ENTER = builtin_atr(33);
A_OENTER = builtin_atr(34);
A_AENTER = builtin_atr(35);
A_ADESC = builtin_atr(36);
A_ODESC = builtin_atr(37);
A_RQUOTA = builtin_atr(38);
A_IDLE = builtin_atr(39);
A_AWAY = builtin_atr(40);
A_MAILK = builtin_atr(41);
A_ALIAS = builtin_atr(42);
A_EFAIL = builtin_atr(43);
A_OEFAIL = builtin_atr(44);
A_AEFAIL = builtin_atr(45);
A_IT = builtin_atr(46);
A_LEAVE = builtin_atr(47);
A_OLEAVE = builtin_atr(48);
A_ALEAVE = builtin_atr(49);
A_CHANNEL = builtin_atr(50);
A_QUOTA = builtin_atr(51);
A_PENNIES = builtin_atr(52);
A_HUHTO = builtin_atr(53);
A_HAVEN = builtin_atr(54);
A_TZ = builtin_atr(57);
A_DOOMSDAY = builtin_atr(58);
A_MOVE = builtin_atr(126);
A_OMOVE = builtin_atr(127);
A_AMOVE = builtin_atr(128);
#ifdef EMAIL_CREATE
A_EMAIL = builtin_atr(59);
#endif
A_LOCK = builtin_atr(129);
A_ELOCK = builtin_atr(130);
A_ULOCK = builtin_atr(131);
A_UFAIL = builtin_atr(132);
A_OUFAIL = builtin_atr(133);
A_AUFAIL = builtin_atr(134);
A_OCONN = builtin_atr(135);
A_ACONN = builtin_atr(136);
A_ODISC = builtin_atr(137);
A_ADISC = builtin_atr(138);
A_COLUMNS = builtin_atr(139);
A_WHOFLAGS = builtin_atr(140);
A_WHONAMES = builtin_atr(141);
A_APAGE = builtin_atr(142);
A_APEMIT = builtin_atr(143);
A_AWHISPER = builtin_atr(144);
A_LLOCK = builtin_atr(161);
A_LFAIL = builtin_atr(162);
A_OLFAIL= builtin_atr(163);
A_ALFAIL= builtin_atr(164);
A_SLOCK = builtin_atr(165);
A_SFAIL = builtin_atr(166);
A_OSFAIL= builtin_atr(167);
A_ASFAIL= builtin_atr(168);
A_USERS = builtin_atr(170);
A_DEFOWN = builtin_atr(171);
#ifdef USE_SPACE /* Registers added by Michael Majere */
A_ASHIP = builtin_atr(60);
A_SECTOR = builtin_atr(61);
A_MASS = builtin_atr(62);
A_RADIUS = builtin_atr(63);
A_THRUST = builtin_atr(64);
A_RATING = builtin_atr(65);
A_EFFICIENCY = builtin_atr(66);
A_FUEL = builtin_atr(67);
A_ACCELERATION = builtin_atr(68);
A_VISMULT = builtin_atr(69);
A_PWRGEN = builtin_atr(70);
A_PWRFUEL = builtin_atr(71);
A_SPRSTR = builtin_atr(72);
A_HULL = builtin_atr(73);
A_RECOVER = builtin_atr(74);
A_TYPE = builtin_atr(75);
A_ENERGY = builtin_atr(76);
A_LINPOSX = builtin_atr(80);
A_LINPOSY = builtin_atr(81);
A_LINPOSZ = builtin_atr(82);
A_LINVELX = builtin_atr(83);
A_LINVELY = builtin_atr(84);
A_LINVELZ = builtin_atr(85);
A_LINACCX = builtin_atr(86);
A_LINACCY = builtin_atr(87);
A_LINACCZ = builtin_atr(88);
A_ANGPOSX = builtin_atr(89);
A_ANGPOSY = builtin_atr(90);
A_ANGPOSZ = builtin_atr(91);
A_ANGVELX = builtin_atr(92);
A_ANGVELY = builtin_atr(93);
A_ANGVELZ = builtin_atr(94);
A_ANGACCX = builtin_atr(95);
A_ANGACCY = builtin_atr(96);
A_ANGACCZ = builtin_atr(97);
#endif
A_TALENT = builtin_atr(98);
A_RACE = builtin_atr(99);
A_LHIDE = builtin_atr(158);
A_LPAGE = builtin_atr(159);
#ifdef USE_SPACE /* Registers added by Michael Majere */
A_S0 = builtin_atr(145);
A_S1 = builtin_atr(146);
A_S2 = builtin_atr(147);
A_S3 = builtin_atr(148);
A_S4 = builtin_atr(149);
A_S5 = builtin_atr(150);
A_S6 = builtin_atr(151);
A_S7 = builtin_atr(152);
A_S8 = builtin_atr(153);
A_S9 = builtin_atr(154);
#endif
A_DOING = builtin_atr(169);
A_WARNINGS = builtin_atr(172);
A_WINHIBIT = builtin_atr(173);
A_ANEWS = builtin_atr(174);
}
#endif