/* $Header: /belch_a/users/rearl/tinymuck/src/RCS/property.c,v 1.5 90/09/16 04:42:47 rearl Exp $ */ /* * $Log: property.c,v $ * Revision 1.5 90/09/16 04:42:47 rearl * Preparation code added for disk-based MUCK. * * Revision 1.4 90/09/15 22:27:45 rearl * Fixed dangerous COMPRESS-related bug. * * Revision 1.3 90/09/10 02:19:49 rearl * Introduced string compression of properties, for the * COMPRESS compiler option. * * Revision 1.2 90/08/02 18:50:00 rearl * Fixed NULL pointer problem in get_property_class(). * * Revision 1.1 90/07/19 23:04:03 casie * Initial revision * * */ #include "copyright.h" #include "config.h" #include "params.h" #include "db.h" #include "externs.h" /* property.c A whole new lachesis mod. Adds property manipulation routines to TinyMUCK. */ /* IN ALL CASES, the argument "value" is referred to only when "class" is a NULL string. */ /* modify a property list */ void insert_prop(struct plist *start, const char *type, const char *class) { struct plist *curr, *prev; int diff; for(curr = start; curr; curr = curr -> next) { diff = string_compare(type, curr -> type); if(diff < 0) { prev -> next = new_prop(); prev = prev -> next; prev -> type = alloc_string(type); prev -> class = alloc_compressed(class); prev -> next = curr; return; } if(diff == 0) { if(curr -> class) free((void *) curr -> class); curr -> class = alloc_compressed(class); return; } prev = curr; } prev -> next = new_prop(); prev = prev -> next; prev -> type = alloc_string(type); prev -> class = alloc_compressed(class); } /* adds a new property to an object */ void add_property(dbref player, const char *type, const char *class) { struct plist *p, *new; if (!type || !*type || index(type, PROP_DELIMITER)) return; /* stick properties at the end because most frequently used ones will be put in front. */ if(*type == PROP_WIZARD) p = DBFETCH(player) -> attributes; else p = DBFETCH(player) -> properties; if(p) { if(string_compare(type, p -> type) >= 0) { insert_prop(p, type, class); return; } } if(*type == PROP_WIZARD) { DBSTORE(player, attributes, new_prop()); new = DBFETCH(player)->attributes; } else { DBSTORE(player, properties, new_prop()); new = DBFETCH(player)->properties; } new -> type = alloc_string(type); new -> class = alloc_compressed(class); new -> next = p; } void add_attr(dbref player, const char *type, const char *class) { char *attribute = (char *) calloc(strlen(type) + 2, sizeof(char)); *attribute = PROP_WIZARD; strcat(attribute, type); if(class && *class) add_property(player, attribute, class); free((void *) attribute); } void delete_prop(struct plist *start, const char *type) { struct plist *curr, *prev; int diff = 0; prev = start; for(curr = prev -> next; curr && (diff >= 0); curr = curr -> next) { diff = string_compare(type, curr -> type); if(diff == 0) { prev -> next = curr -> next; free_prop(curr); return; } prev = curr; } } /* removes property list --- if it's not there then ignore */ void remove_property(dbref player, const char *type) { struct plist *p; if(*type == PROP_WIZARD) p = DBFETCH(player) -> attributes; else p = DBFETCH(player) -> properties; if(p) { if(string_compare(type, p -> type)) { delete_prop(p, type); } else { if(*type == PROP_WIZARD) { DBSTORE(player, attributes, p -> next); } else { DBSTORE(player, properties, p -> next); } free_prop(p); } } } /* checks if object has property, returning 1 if it or any of it's contents has the property stated */ int has_property(dbref player, const char *type, const char *class) { dbref things; if (has_property_strict(player, type, class)) return 1; for (things = DBFETCH(player)->contents; things != NOTHING; things = DBFETCH(things)->next) if (has_property_strict(things, type, class)) return 1; return 0; } struct plist * find_prop(struct plist *start, const char *type) { struct plist *p; int diff = 0; for(p = start; p && (diff >= 0); p = p -> next) { diff = string_compare(type, p -> type); if(diff == 0) return p; } return (struct plist *) 0; } /* checks if object has property, returning 1 if it has the property asked for */ int has_property_strict(dbref player, const char *type, const char *class) { struct plist *p; const char *str; str = get_compress(DoNull(class)); if(*type == PROP_WIZARD) p = find_prop(DBFETCH(player)->attributes, type); else p = find_prop(DBFETCH(player)->properties, type); if(p) return (!string_compare(str, p -> class)); return 0; } /* return class of property */ char * get_property_class(dbref player, const char *type) { struct plist *p; if(*type == PROP_WIZARD) p = find_prop(DBFETCH(player)->attributes, type); else p = find_prop(DBFETCH(player)->properties, type); if(p) return((char *) get_uncompress(p -> class)); return((char *) 0); } char * get_attr(dbref player, const char *type) { char *result; char *attribute = (char *) calloc(strlen(type) + 2, sizeof(char)); *attribute = PROP_WIZARD; strcat(attribute, type); result = (char *) get_property_class(player, attribute); free((void *) attribute); return result; } /* copies properties */ struct plist * copy_prop(dbref old) { struct plist *p; struct plist *new = 0, *first = 0; for (p = DBFETCH(old)->properties; p; p = p -> next) { if (!first) first = new = new_prop(); else new -> next = new_prop(); if (new -> next) new = new -> next; new -> type = alloc_string(p -> type); new -> class = alloc_compressed(p -> class); } return first; } /* copies attributes */ struct plist * copy_attr(dbref old) { struct plist *p; struct plist *new = 0, *first = 0; for (p = DBFETCH(old)->attributes; p; p = p -> next) { if (!first) first = new = new_prop(); else new -> next = new_prop(); if (new -> next) new = new -> next; new -> type = alloc_string(p -> type); new -> class = alloc_compressed(p -> class); } return first; } /* return old gender values for pronoun substitution code */ int genderof(dbref player) { char gender[5]; sprintf(gender, "%c%s", PROP_WIZARD, "sex"); if (has_property_strict(player, gender, "male")) return GENDER_MALE; else if (has_property_strict(player, gender, "female")) return GENDER_FEMALE; else if (has_property_strict(player, gender, "neuter")) return GENDER_NEUTER; else return GENDER_UNASSIGNED; }