/* $Header: unparse.c,v 2.0 90/05/05 12:45:46 lachesis Exp $
 * $Log:    unparse.c,v $
 * Revision 2.0  90/05/05  12:45:46  lachesis
 * Incorporated ABODE and HAVEN flags (remembering to convert FireFoot's
 * usage of those flags to ours).
 * Added Examine of objects that don't belong to you, added GOD_PRIV.
 *
 * Revision 1.2  90/04/21  17:20:52  lachesis
 * Added property lists.
 *
 * Revision 1.1  90/04/14  14:56:56  lachesis
 * Initial revision
 *
 */
#include "os.h"
#include "db.h"

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

static const char *unparse_flags (dbref thing)
{
  static char buf[BUFFER_LEN];
  char *p;
  const char *type_codes = "R-EP";

  p = buf;
  if (Typeof (thing) != TYPE_THING)
    *p++ = type_codes[Typeof (thing)];
  if (db[thing].flags & ~TYPE_MASK) {
    /* print flags */
    if (db[thing].flags & WIZARD)
      *p++ = 'W';
    if (db[thing].flags & STICKY)
      *p++ = 'S';
    if (db[thing].flags & DARK)
      *p++ = 'D';
    if (db[thing].flags & LINK_OK)
      *p++ = 'L';
    if (db[thing].flags & TEMPLE)
      *p++ = 'T';
#ifdef RESTRICTED_BUILDING
    if (db[thing].flags & BUILDER)
      *p++ = 'B';
#endif /* RESTRICTED_BUILDING */
#ifdef PLAYER_CHOWN
    if (db[thing].flags & CHOWN_OK)
      *p++ = 'C';
#endif /* PLAYER_CHOWN */
    if (db[thing].flags & JUMP_OK)
      *p++ = 'J';
#ifdef HAVEN
    if (db[thing].flags & HAVEN)
      *p++ = 'H';
#endif /* HAVEN */
#ifdef ABODE
    if (db[thing].flags & ABODE)
      *p++ = 'A';
#endif /* ABODE */
  }
  *p = '\0';
  return buf;
}

const char *unparse_object (dbref player, dbref loc)
{
  static char buf[BUFFER_LEN];

  switch (loc) {
  case NOTHING:
    return "*NOTHING*";
  case HOME:
    return "*HOME*";
  default:
    if (controls (player, loc) || can_link_to (player, loc)
#ifdef PLAYER_CHOWN
      || (db[loc].flags & CHOWN_OK)
#endif /* PLAYER_CHOWN */
      ) {
      /* show everything */
      sprintf (buf, "%s(#%d%s)", db[loc].name, loc, unparse_flags (loc));
      return buf;
    } else {
      /* show only the name */
      return db[loc].name;
    }
  }
}

static char boolexp_buf[BUFFER_LEN];
static char *buftop;

static void unparse_boolexp1 (dbref player,
  struct boolexp *b, boolexp_type outer_type)
{
  if (b == TRUE_BOOLEXP) {
    (void) strcpy (buftop, "*UNLOCKED*");
    buftop += strlen (buftop);
  } else {
    switch (b->type) {
    case BOOLEXP_AND:
      if (outer_type == BOOLEXP_NOT) {
        *buftop++ = '(';
      }
      unparse_boolexp1 (player, b->sub1, b->type);
      *buftop++ = AND_TOKEN;
      unparse_boolexp1 (player, b->sub2, b->type);
      if (outer_type == BOOLEXP_NOT) {
        *buftop++ = ')';
      }
      break;
    case BOOLEXP_OR:
      if (outer_type == BOOLEXP_NOT || outer_type == BOOLEXP_AND) {
        *buftop++ = '(';
      }
      unparse_boolexp1 (player, b->sub1, b->type);
      *buftop++ = OR_TOKEN;
      unparse_boolexp1 (player, b->sub2, b->type);
      if (outer_type == BOOLEXP_NOT || outer_type == BOOLEXP_AND) {
        *buftop++ = ')';
      }
      break;
    case BOOLEXP_NOT:
      *buftop++ = '!';
      unparse_boolexp1 (player, b->sub1, b->type);
      break;
    case BOOLEXP_CONST:
      (void) strcpy (buftop, unparse_object (player, b->thing));
      buftop += strlen (buftop);
      break;
    case BOOLEXP_PROP:
      (void) strcpy (buftop, b->prop_check->type);
      (void) strcat (buftop, ":");
      (void) strcat (buftop, b->prop_check->class);
      buftop += strlen (buftop);
      break;
    default:
      abort ();                 /* bad type */
      break;
    }
  }
}

const char *unparse_boolexp (dbref player, struct boolexp *b)
{
  buftop = boolexp_buf;
  unparse_boolexp1 (player, b, BOOLEXP_CONST);  /* no outer type */
  *buftop++ = '\0';

  return boolexp_buf;
}