/* $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 "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;
}