/* $Header: /u/cvsroot/muse/src/db/inherit.c,v 1.6 1993/03/21 00:49:57 nils Exp $ */ #include <stdio.h> #include "externs.h" #include "config.h" #include "db.h" void put_atrdefs (f, defs) FILE *f; ATRDEF *defs; { extern void putstring P((FILE *, char *)); for (;defs;defs=defs->next) { fputc('/',f); putref(f, defs->a.flags); putref(f, defs->a.obj); putstring(f, defs->a.name); } fputs("\\\n",f); } ATRDEF *get_atrdefs (f,olddefs) FILE *f; ATRDEF *olddefs; { extern char *getstring_noalloc P((FILE *)); char k; ATRDEF *ourdefs=NULL, *endptr=NULL; for (;;) { k = fgetc(f); switch (k) { case '\\': if (fgetc(f)!='\n') log_error ("No atrdef newline."); return ourdefs; break; case '/': if (!endptr) if (olddefs) { endptr = ourdefs = olddefs; olddefs = olddefs->next; } else endptr = ourdefs = malloc( sizeof(ATRDEF)); else if (olddefs) { endptr->next = olddefs; olddefs = olddefs->next; endptr = endptr->next; } else { endptr->next = malloc( sizeof(ATRDEF)); endptr = endptr->next; } endptr->a.flags = getref(f); endptr->a.obj = getref(f); endptr->next = NULL; endptr->a.name = NULL; SET (endptr->a.name, getstring_noalloc(f)); break; default: log_error ("Illegal character in get_atrdefs"); return 0; } } } void remove_attribute (obj, atr) dbref obj; ATTR *atr; { int i; atr_add (obj, atr, ""); for (i=0; db[obj].children && db[obj].children[i] != NOTHING; i++) remove_attribute (db[obj].children[i], atr); } void do_undefattr (player, arg1) dbref player; char *arg1; { dbref obj; ATTR *atr; ATRDEF *d, *prev=NULL; if(!parse_attrib(player, arg1, &obj, &atr, POW_MODIFY)) { notify(player, "No match."); return; } for (d= db[obj].atrdefs; d; prev=d, d=d->next) if (&(d->a) == atr) { if (prev) prev->next = d->next; else db[obj].atrdefs = d->next; remove_attribute (obj, atr); if (0==--d->a.refcount) { /* this should always happen, but... */ free(d->a.name); free(d); } notify(player, "Deleted."); return; } notify(player, "No match."); } void do_defattr (player, arg1, arg2) dbref player; char *arg1,*arg2; { ATTR *atr; char *flag_parse; int atr_flags = 0; dbref thing; char *attribute; int i; if (!(attribute=strchr(arg1,'/'))) { notify(player,"no match"); return; } *(attribute++) = '\0'; thing = match_controlled(player, arg1, POW_MODIFY); if (thing == NOTHING) return; if (!ok_attribute_name (attribute)) { notify(player,"Illegal attribute name."); return; } while ((flag_parse = parse_up(&arg2,' '))) { if (flag_parse == NULL); /* empty if, so we can do else: */ #define IFIS(foo,baz) else if(!string_compare(flag_parse,foo)) atr_flags|=baz IFIS("wizard",AF_WIZARD); IFIS("osee",AF_OSEE); IFIS("dark",AF_DARK); IFIS("inherit",AF_INHERIT); IFIS("unsaved",AF_UNIMP); IFIS("date",AF_DATE); IFIS("lock",AF_LOCK); IFIS("function",AF_FUNC); #undef IFIS else notify(player,tprintf("Unknown attribute option: %s",flag_parse)); } atr = atr_str (thing, thing, attribute); if (atr && atr->obj == thing) { atr->flags = atr_flags; notify(player, "Options set."); return; } { ATRDEF *k; for (k=db[thing].atrdefs,i=0; k; k=k->next, i++); if (i>90 && !power(player,POW_SECURITY)) { notify(player,"Sorry, you can't have that many attribute defs on an object."); return; } if (atr) { notify(player, "Sorry, attribute shadows a builtin attribute or one on a parent."); return; } k=malloc( sizeof(ATRDEF)); k->a.name = NULL; SET (k->a.name, attribute); k->a.flags = atr_flags; k->a.obj = thing; k->a.refcount = 1; k->next = db[thing].atrdefs; db[thing].atrdefs = k; } notify(player,"Attribute defined."); } static int is_a_internal (thing, parent, dep) dbref thing; dbref parent; int dep; { int j; if (thing == parent) return 1; if (dep < 0) return 1; if (!db[thing].parents) return 0; for (j=0; db[thing].parents[j]!=NOTHING; j++) if (is_a_internal (db[thing].parents[j], parent, dep-1)) return 1; return 0; } int is_a (thing, parent) dbref thing; dbref parent; { if (thing == NOTHING) return 1; return is_a_internal (thing, parent, 20); /* 20 is the max depth */ } #if 0 static void reparent P((dbref, dbref, dbref *)), unparent P((dbref)); #endif void do_delparent (player, arg1, arg2) dbref player; char *arg1,*arg2; { dbref thing; dbref parent; int i; int can_doit = 0; thing = match_controlled(player, arg1 , POW_MODIFY); if (thing == NOTHING) return; mark_hearing(thing); parent = match_thing (player, arg2); if (parent == NOTHING) return; if (!(db[parent].flags&BEARING) && !controls(player,parent,POW_MODIFY)) { notify (player,tprintf("Sorry, you can't unparent from that.")); can_doit = 1; } for (i=0; db[thing].parents && db[thing].parents[i]!=NOTHING; i++) if (db[thing].parents[i] == parent) can_doit |= 2; if (!(can_doit&2)) notify (player, "Sorry, it doesn't have that as its parent."); if (can_doit != 2) return; REMOVE_FIRST_L (db[thing].parents, parent); REMOVE_FIRST_L (db[parent].children, thing); notify(player, tprintf("%s is no longer a parent of %s.", unparse_object_a (player, parent), unparse_object_a (player, thing))); check_hearing(); } void do_addparent (player, arg1, arg2) dbref player; char *arg1,*arg2; { dbref thing; dbref parent; int i; int can_doit = 0; thing = match_controlled(player, arg1 , POW_MODIFY); if (thing == NOTHING) return; mark_hearing(thing); parent = match_thing (player, arg2); if (parent == NOTHING) return; if (is_a(parent, thing)) { notify (player,tprintf("but %s is a descendant of %s!", unparse_object_a (player, parent), unparse_object_a (player, thing))); can_doit |= 4; } if (!(db[parent].flags&BEARING) && !controls(player,parent,POW_MODIFY)) { notify (player,tprintf("Sorry, you can't parent to that.")); can_doit |= 1; } for (i=0; db[thing].parents && db[thing].parents[i]!=NOTHING; i++) if (db[thing].parents[i] == parent) can_doit |= 2; if (can_doit&2) notify (player, "Sorry, it already has that as its parent."); if (can_doit != 0) return; PUSH_L (db[thing].parents, parent); PUSH_L (db[parent].children, thing); notify(player, tprintf("%s is now a parent of %s.", unparse_object_a (player, parent), unparse_object_a (player, thing))); check_hearing(); } #if 0 static void reparent (player, thing, parents) dbref player; dbref thing; dbref *parents; /* as in return from match_things; length * at beginning. */ { int k,j; extern NALLOC *db_strings; int numparents; /* number weactually need to allocate */ int did_hear; did_hear = Hearer(thing); unparent(thing); numparents = parents[0]+1; /* 1 for the NOTHING at the end */ for (k=0; k<=parents[0]; k++) if (parents[k] == NOTHING) numparents--; db[thing].parents = malloc( sizeof(dbref)*(numparents)); for (k=1, j=0; k<=parents[0]; k++, j++) if (parents[k] == NOTHING) j--; else db[thing].parents[j] = parents[k]; db[thing].parents[j] = NOTHING; for (j=0; db[thing].parents[j]!=NOTHING; j++) PUSH_L(db[db[thing].parents[j]].children, thing); if (Hearer(thing) && !did_hear) { dbref *tmp; /* terrible kludge. */ tmp = db[thing].parents; db[thing].parents = NULL; make_hearing (thing); db[thing].parents = tmp; } if (did_hear && !Hearer(thing)) notify_in [db[player].location, NOTHING, tprintf("%s loses its ears and becomes deaf.",db[thing].name)); } static void unparent (thing) dbref thing; { int i; extern NALLOC *db_strings; if (!db[thing].parents) return; for (i=0; db[thing].parents[i] != NOTHING; i++) REMOVE_FIRST_L(db[db[thing].parents[i]].children, thing); malloc(db[thing].parents); db[thing].parents = NULL; } #endif