TinyMAZE/
TinyMAZE/config/
TinyMAZE/doc/
TinyMAZE/run/msgs/
TinyMAZE/src/
TinyMAZE/src/db/
TinyMAZE/src/ident/
TinyMAZE/src/io/
TinyMAZE/src/prog/
TinyMAZE/src/softcode/
TinyMAZE/src/util/
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include "db.h"
#include "config.h"
#include "externs.h"

static int ok_name P((char *));

int IS(OBJ *thing, int type, unsigned long flag)
{
  if(!thing)
    return(0);
  if(Typeof(thing) != type)
    return(0);
  if(!(thing->flags & flag))
    return(0);

  return(1);
}

int is_root(OBJ *thing)
{
  if(root_obj)
    return(thing == root_obj);

  return(thing == find_object(config.root));
}

int neighbors(OBJ *obj1, OBJ *obj2)
{
  return((obj1->location == obj2->location));
}

char *tprintf(char *fmt, ...)
{
  char buff[4096];
  va_list ap;
  
  va_start(ap, fmt);
  vsnprintf(buff, sizeof(buff), fmt, ap);
  va_end(ap);

  return(stack_string_alloc(buff, 0));
}

int power(OBJ *thing, int level_check)
{
/* MORTAL flag on player makes him mortal - no arguments */
  if(IS(thing, TYPE_PLAYER, PLAYER_MORTAL))
    return(0);
  return(has_pow(thing, NULL, level_check));
}

int inf_mon(OBJ *thing)
{
  return(power(thing, POW_MONEY));
}

int could_doit(OBJ *player, OBJ *thing, char *atrname)
{
  return(eval_boolexp(player, thing, atr_get(thing, atrname)));
}

void did_it(OBJ *player, OBJ *thing, char *what, char *def, char *aprog)
{ 
  char *d;

/* Message to player */
  if(what)
  {
    if(*(d = atr_get(thing, what)))
    {
      notify(player, d);
    }
    else
      if(def)
	notify(player, def);
  }
}

int can_see(OBJ *player, OBJ *thing, int can_see_loc)
{        
  /* 1) your own body isn't listed in a 'look'
     2) unconnected (sleeping) players aren't listed in a 'look'
     3) players set INVISIBLE aren't listed in a 'look'
     4) If you don't match the LSEE attribute you can't see it */

  if(player == thing ||
    (Typeof(thing) == TYPE_PLAYER && !is_connected_raw(thing)))
  {
    return(0);
  }
  
  if(IS(thing, TYPE_PLAYER, PLAYER_INVISIBLE))
    return(0);

/* If you don't match the LSEE then you can never see it */
  if(!could_doit(player, thing, "LSEE"))
    return(0);

/* If it's dark you can't see it */
  if(Typeof(thing) != TYPE_PLAYER && !(thing->flags & PUPPET) &&
    thing->flags & DARK)
  {
    return(0);
  }

  if(can_see_loc)
    return(!is_dark(thing));

  if(IS(thing, TYPE_THING, THING_LIGHT) &&
    controls(thing, thing->location, POW_MODIFY))
  {
    return(1);
  }
  else
    return(0);
}

int can_set_atr(OBJ *who, OBJ *what, ATTR *atr)
{
  if(!can_see_atr(who, what, atr))
    return(0);
  if(atr->flags & AF_BUILTIN)
    return(0);
  if(atr->flags & AF_NOMOD)
    return(0);
  if(!controls(who, what, POW_MODIFY))
    return(0);
  if(atr->flags & AF_WIZARD && !power(who, POW_WATTR))
    return(0);
  return(1);
}

int can_see_atr(OBJ *who, OBJ *what, ATTR *atr)
{
  if(!string_compare(atr->name, "PASSWORD") && !is_root(who))
    return(0);
  if(!(atr->flags & AF_OSEE) && !controls(who, what, POW_SEEATR) &&
    !(what->flags & VISIBLE))
  {
    return(0);
  }

  if(atr->flags & AF_DARK && !Wizard(who))
    return(0);

  return(1);
}

int controls(OBJ *who, OBJ *what, int cutoff_level)
{
  if(is_root(who))
    return(1);
  
  if(!what)
    return(has_pow(who, what, cutoff_level));
  
  if((cutoff_level == POW_EXAMINE || cutoff_level == POW_SEEATR) &&
    what->flags & VISIBLE)
  {
    return(1);
  }

  if(who->owner == what->owner)
    return(1);

  if(what->flags & INHERIT_POWERS)
    what = what->owner;

  if(is_root(what) || is_root(what->owner))
    return(0);

  if(has_pow(who, what, cutoff_level))
    return(1);

  return(0);
}

OBJ *def_owner(OBJ *who)
{
  OBJ *o;

  if(!*atr_get(who, "DEFOWN"))
    return(who->owner);

  o = match_object(who, atr_get(who, "DEFOWN"), TYPE_PLAYER);
  if(!o)
  {
    notify(who, "You have an invalid setting in your DEFOWN attribute.");
    return(who->owner);
  }
  if(!controls(who, o, POW_MODIFY))
  {
    notify(who,
      tprintf("You don't control %s, so you can't make things owned by %s.",
      unparse_object(who, o), unparse_object(who, o)));
    return(who->owner);
  }

  return(o->owner);
}

void giveto(OBJ *who, int amt)
{
  long old_amount;

  if(has_pow(who->owner, NULL, POW_MONEY))
    return;
  
  who = who->owner;
  old_amount = Pennies(who);
  if(old_amount+amt < 0)
  {
    if((old_amount > 0) && (amt > 0))
      atr_add(who, "PENNIES", tprintf("%u", (((unsigned)-2)/2)));
    else
      atr_add(who, "PENNIES", "0");
  }
  else
    atr_add(who, "PENNIES", tprintf("%ld", old_amount+amt));
}       

int payfor(OBJ *who, int cost)
{
  if(Guest(who) || has_pow(who->owner, NULL, POW_MONEY))
    return(1);

  if(Pennies(who->owner) >= cost)
  {
    my_atr_add(who->owner, "PENNIES", (-cost));
    return(1);
  }

  return(0);
}

static int my_index(char *s1, int c)
{
  while(*s1 && (*s1 != c))
    s1++;
  return(*s1);
}

int ok_thing_name(char *name)
{
  return(ok_name(name) && !my_index(name, ';'));
}

int ok_exit_name(char *name)
{
  return(ok_name(name));
}

int ok_room_name(char *name)
{
  return(ok_name(name) && !my_index(name, ';'));
}

static int ok_name(char *name)
{
  return(name
    && *name
    && *name != LOOKUP_TOKEN
    && *name != NUMBER_TOKEN
    && *name != NOT_TOKEN
    && !my_index(name, ARG_DELIMITER)
    && !my_index(name, AND_TOKEN)
    && !my_index(name, OR_TOKEN)
    && !my_index(name, '@')
    && string_compare(name, "me")
    && string_compare(name, "home")
    && string_compare(name, "here"));
}

int ok_object_name(OBJ *obj, char *name)
{
  switch(Typeof(obj))
  {
    case TYPE_THING:
      return(ok_thing_name(name));
    case TYPE_EXIT:
      return(ok_exit_name(name));
    case TYPE_ROOM:
      return(ok_room_name(name));
  }

  return(0);
}

int ok_player_name(OBJ *player, char *name, char *alias)
{
  char *scan;
  OBJ *obj;
  
  if(!ok_name(name) || my_index(name, ';') ||
    strlen(name) > config.player_name_limit)
  {
    return(0);
  }
  
  if(!string_compare(name, "i") ||
    !string_compare(name, "me") ||
    !string_compare(name, "my") ||
    !string_compare(name, "you") ||
    !string_compare(name, "your") ||
    !string_compare(name, "he") ||
    !string_compare(name, "she") ||
    !string_compare(name, "it") ||
    !string_compare(name, "his") ||
    !string_compare(name, "her") ||
    !string_compare(name, "hers") ||
    !string_compare(name, "its") ||
    !string_compare(name, "we") ||
    !string_compare(name, "us") ||
    !string_compare(name, "our") ||
    !string_compare(name, "they") ||
    !string_compare(name, "them") ||
    !string_compare(name, "their") ||
    !string_compare(name, "a") ||
    !string_compare(name, "an") ||
    !string_compare(name, "the") ||
    !string_compare(name, "one") ||
    !string_compare(name, "to") ||
    !string_compare(name, "if") ||
    !string_compare(name, "and") ||
    !string_compare(name, "or") ||
    !string_compare(name, "but") ||
    !string_compare(name, "at") ||
    !string_compare(name, "of") ||
    !string_compare(name, "for") ||
    !string_compare(name, "foo") ||
    !string_compare(name, "so") ||
    !string_compare(name, "this") ||
    !string_compare(name, "that") ||
    !string_compare(name, ">") ||
    !string_compare(name, ".") ||
    !string_compare(name, "-") ||
    !string_compare(name, ">>") ||
    !string_compare(name, "..") ||
    !string_compare(name, "--") ||
    !string_compare(name, "->") ||
    !string_compare(name, ":)") ||
    !string_compare(name, "delete") ||
    !string_compare(name, "purge") ||
    !string_compare(name, "check") ||
    !string_compare(name, "new") ||
    strchr(name, '%') ||
    strchr(name, ' ') ||
    !string_compare(name, "clear")) /* +mail clear. */
  return(0);
  
  for(scan = name;*scan;scan++)
    if(!isprint(*scan) || *scan == '~')
      return(0);

  obj = match_player(NULL, name);
  if(obj && obj != player)
    return(0);
  if(!string_compare(name, alias))
    return(0);

  if(player)
  {
    obj = match_player(NULL, alias);
    if(obj && obj != player)
      return(0);
    if(strlen(alias) > config.player_alias_limit)
      return(0);
  }

  if(*alias && (!ok_name(alias) || strchr(alias, ' ')))
    return(0);
  if(strlen(name) > config.player_name_limit)
    return(0);

  return(1);
}

int ok_password(char *password)
{
  char *scan;
  
  if(!*password)
    return(0);

  for(scan = password;*scan;scan++)
    if(!(isprint(*scan)))
      return(0);
  
  return(1);
}

char *main_exit_name(OBJ *exit)
{
  char buf[4096];
  char *s;

  strcpy(buf, exit->name);
  if((s = strchr(buf, ';')))
    *s = '\0';

  return(stack_string_alloc(buf, 0));
}

int is_dark(OBJ *thing)
{
  switch(Typeof(thing))
  {
    case TYPE_ROOM:
      if(thing->flags & DARK)
        return(1);
      break;
    case TYPE_PLAYER:
      if(thing->flags & PLAYER_INVISIBLE)
        return(1);
      break;
    case TYPE_THING:
      if(thing->flags & PUPPET)
        return(0);
      if(thing->flags & DARK)
        return(1);
      break;
    case TYPE_EXIT:
      if(thing->flags & DARK)
        return(1);
      break;
  }

  return(0);
}

DDATA *is_connected_raw(OBJ *who)
{
  DDATA *d;

  for(d = descriptor_list;d;d = d->next)
    if(check_state(d, STATE_CONNECTED) && d->player == who)
      break;

  return(d);
}

DDATA *is_connected(OBJ *player, OBJ *who)
{
  DDATA *d;

  if(*atr_get(who, "LHIDE") && !controls(player, who, POW_WHO))
    if(!could_doit(player, who, "LHIDE"))
      return(NULL);

  for(d = descriptor_list;d;d = d->next)
    if(check_state(d, STATE_CONNECTED) && d->player == who)
      break;

  return(d);
}

int is_coding(OBJ *player)
{
  DDATA *d;

  if(!(d = is_connected_raw(player)))
    return(0);

  return(d->mode == MODE_SOFTCODE);
}

DDATA *is_idle(OBJ *thing)
{
  DDATA *d;

  for(d = descriptor_list;d;d = d->next)
    if(d->player == thing)
      break;
  if(!d)
    return(NULL);
  if(!check_state(d, STATE_CONNECTED))
    return(NULL);

  if(d->last_time < now-300)   /* 5 minutes */
    return(d);

  return(NULL);
}

int my_is_vowel(char letter)
{
  switch(toupper(letter))
  {
    case 'A':
    case 'E':
    case 'I':
    case 'O':
    case 'U':
      return(1);
    default:
      return(0);
  }
}