/* 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