/* $Header: predicates.c,v 1.1 90/04/14 14:56:49 lachesis Exp $
 * $Log:    predicates.c,v $
 * Revision 1.1  90/04/14  14:56:49  lachesis
 * Initial revision
 *
 */
#include "copyright.h"

/* Predicates for testing various conditions */

#include "os.h"

#include "db.h"
#include "interface.h"
#include "config.h"
#include "externs.h"

int can_link_to (dbref who, dbref where)
{
  return (where >= 0
    && where < db_top
    && (controls (who, where) || (db[where].flags & LINK_OK)));
}

int could_doit (dbref player, dbref thing)
{
  if (Typeof (thing) == TYPE_EXIT && db[thing].sp.exit.ndest == 0) {
    return 0;
  }
  return (eval_boolexp (player, db[thing].key));
}

int can_doit (dbref player, dbref thing, const char *default_fail_msg)
{
  dbref loc;
  char buf[BUFFER_LEN];

  if ((loc = getloc (player)) == NOTHING)
    return 0;

  if (!could_doit (player, thing)) {
    /* can't do it */
    if (db[thing].fail_message) {
      notify (player, db[thing].fail_message);
    } else if (default_fail_msg) {
      notify (player, default_fail_msg);
    }

    if (db[thing].ofail && !Dark (player)) {
#ifdef GENDER
      pronoun_substitute (buf, player, db[thing].ofail, 1);
#else
      sprintf (buf, "%s %s", db[player].name, db[thing].ofail);
#endif /* GENDER */
      notify_except (db[loc].contents, player, buf);
    }

    return 0;
  } else {
    /* can do it */
    if (db[thing].succ_message) {
      notify (player, db[thing].succ_message);
    }

    if (db[thing].osuccess && !Dark (player)) {
#ifdef GENDER
      pronoun_substitute (buf, player, db[thing].osuccess, 1);
#else
      sprintf (buf, "%s %s", db[player].name, db[thing].osuccess);
#endif /* GENDER */
      notify_except (db[loc].contents, player, buf);
    }

    return 1;
  }
}

int can_see (dbref player, dbref thing, int can_see_loc)
{
  if (player == thing || Typeof (thing) == TYPE_EXIT) {
    return 0;
  } else if (can_see_loc) {
    return (!Dark (thing) || controls (player, thing));
  } else {
    /* can't see loc */
    return (controls (player, thing));
  }
}

int controls (dbref who, dbref what)
{
  /* Wizard controls everything */
  /* owners control their stuff */
  if (what < 0 || what >= db_top)
    return 0;
#ifdef RECYCLE
  /* No one controls garbage */
  if (Typeof (what) == TYPE_GARBAGE)
    return 0;
#endif
  if (Wizard (who))
    return 1;
  switch (Typeof (what)) {
  case TYPE_ROOM:
    return (who == db[what].sp.room.owner);
     /*NOTREACHED*/ break;
  case TYPE_PLAYER:
    return (who == what);
     /*NOTREACHED*/ break;
  case TYPE_EXIT:
    return (who == db[what].sp.exit.owner);
     /*NOTREACHED*/ break;
  case TYPE_THING:
    return (who == db[what].sp.thing.owner);
     /*NOTREACHED*/ break;
  }
  return 0;
}

int can_link (dbref who, dbref what)
{
  return ((Typeof (what) == TYPE_EXIT && db[what].sp.exit.ndest == 0)
    || controls (who, what));
}

int payfor (dbref who, int cost)
{
  if (Wizard (who)) {
    return 1;
  } else if (db[who].sp.player.pennies >= cost) {
    db[who].sp.player.pennies -= cost;
    return 1;
  } else {
    return 0;
  }
}

static int word_start (const char *str, const char let)
{
  int chk;

  for (chk = 1; *str; str++) {
    if (chk && *str == let)
      return 1;
    chk = *str == ' ';
  }
  return 0;
}

int ok_name (const char *name)
{
  return (name
    && *name
    && *name != LOOKUP_TOKEN
    && *name != NUMBER_TOKEN && !index (name, ARG_DELIMITER)
    && !index (name, AND_TOKEN)
    && !index (name, OR_TOKEN)
    && !word_start (name, NOT_TOKEN)
    && string_compare (name, "me")
    && string_compare (name, "home")
    && string_compare (name, "here"));
}

int ok_player_name (const char *name)
{
  const char *scan;

  if (!ok_name (name) || strlen (name) > PLAYER_NAME_LIMIT)
    return 0;

  for (scan = name; *scan; scan++) {
    if (!(isprint (*scan) && !isspace (*scan))) {       /* was isgraph(*scan) */
      return 0;
    }
  }

  /* lookup name to avoid conflicts */
  return (lookup_player (name) == NOTHING);
}

int ok_password (const char *password)
{
  const char *scan;

  if (*password == '\0')
    return 0;

  for (scan = password; *scan; scan++) {
    if (!(isprint (*scan) && !isspace (*scan))) {
      return 0;
    }
  }

  return 1;
}