/* $Header: property.c,v 1.2 90/05/02 20:25:27 lachesis Exp $
 * $Log:    property.c,v $
 * Revision 1.2  90/05/02  20:25:27  lachesis
 * Converted gender substitution code to read properties,
 * changed page to provide a message, too.
 *
 * Revision 1.1  90/04/21  17:21:01  lachesis
 * Initial revision
 *
 */
#include "copyright.h"

/* property.c
   A whole new lachesis mod.
   Adds property manipulation routines to TinyMUCK.   */

#include "os.h"
#include "db.h"
#include "externs.h"

/* IN ALL CASES, the argument "value" is referred to only when "class" is
   a NULL string.                                                       */

/* adds a new property to an object */
void
add_property (dbref player, const char *type, const char *class, int value)
{
  struct plist *p, *l;

  if (db[player].properties) {
    /* stick properties at the end because most frequently used ones
       will be put in front.                                      */
    for (l = db[player].properties; l; l = l->next) {
      if (!string_compare (type, l->type)) {
        if (class) {
          if (l->class)
            free ((void *) l->class);
          l->class = alloc_string (class);
        }
#ifdef NUMBER_PROPS
        else
          l->value = value;
#endif
        return;
      }
      p = l;
    }
    p->next = new_prop ();
    p = p->next;
    p->type = alloc_string (type);
    if (class)
      p->class = alloc_string (class);
#ifdef NUMBER_PROPS
    else
      p->value = value;
#endif
  } else {
    /* no current property list --- create property list */
    p = new_prop ();
    p->type = alloc_string (type);
    if (class)
      p->class = alloc_string (class);
#ifdef NUMBER_PROPS
    else
      p->value = value;
#endif
    db[player].properties = p;
  }
}

/* removes property list --- if it's not there then ignore */
void remove_property (dbref player, const char *type)
{
  struct plist *last, *curr;

  for (last = curr = db[player].properties; curr; curr = curr->next) {
    if (!string_compare (curr->type, type)) {
      if (db[player].properties == curr)
        db[player].properties = curr->next;
      else
        last->next = curr->next;
      free_prop (curr);
    }
    last = curr;
  }
}

/* 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, int value)
{
  dbref things;

  if (has_property_strict (player, type, class, value))
    return 1;

  for (things = db[player].contents; things != NOTHING;
    things = db[things].next)
    if (has_property_strict (things, type, class, value))
      return 1;

  return 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,
  int value)
{
  struct plist *p;

  for (p = db[player].properties; p; p = p->next)
    if (!string_compare (type, p->type)) {
      if (p->class && class)
        return (!string_compare (class, p->class));
#ifdef NUMBER_PROPS
      else
        return (value == p->value);
#endif
    }

  return 0;
}

/* return class of property */
const char *get_property_class (dbref player, const char *type)
{
  struct plist *p;

  for (p = db[player].properties; p; p = p->next)
    if (!string_compare (type, p->type))
      return (p->class);

  return 0;
}

#ifdef NUMBER_PROPS
/* return value of property */
int get_property_value (dbref player, const char *type)
{
  struct plist *p;

  for (p = db[player].properties; p; p = p->next)
    if (!string_compare (type, p->type))
      return p->value;

  return 0;                     /* I guess this is as good as any other.. */
}
#endif /* NUMBER_PROPS */

#ifdef GENDER
/* return old gender values for pronoun substitution code */
int genderof (dbref player)
{
  if (has_property_strict (player, "sex", "male", 0))
    return GENDER_MALE;
  else if (has_property_strict (player, "sex", "female", 0))
    return GENDER_FEMALE;
  else if (has_property_strict (player, "sex", "neuter", 0))
    return GENDER_NEUTER;
  else
    return GENDER_UNASSIGNED;
}
#endif /* GENDER */

char *get_string (const char *s)
{
  char *n;

  n = (char *) malloc (strlen (s) + 1);
  *n = '\0';
  if (!n)
    abort ();
  strcpy (n, s);
  return n;
}