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 <stdio.h>
#include <sys/types.h>
#include <time.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include "db.h"
#include "config.h"
#include "externs.h"
#include "funcs.h"

struct fun wordlist[] =
{
  {"gt",            fun_gt,            2, FNUM},
  {"get",           fun_get,           2, FSTR},
  {"eq",            fun_eq,            2, FNUM},
  {"gteq",          fun_gteq,          2, FNUM},
  {"lt",            fun_lt,            2, FNUM},
  {"end",           fun_end,           1, FSTR},
  {"tan",           fun_tan,           1, FNUM},
  {"ln",            fun_ln,            1, FNUM},
  {"lteq",          fun_lteq,          2, FNUM},
  {"type",          fun_type,          1, FSTR},
  {"exp",           fun_exp,           1, FNUM},
  {"delete",        fun_delete,        3, FSTR},
  {"rest",          fun_rest,          1, FSTR},
  {"sgn",           fun_sgn,           1, FNUM},
  {"chr",           fun_chr,           1, FSTR},
  {"lattr",         fun_lattr,         1, FSTR},
  {"rank",          fun_rank,          1, FNUM},
  {"rand",          fun_rand,          1, FNUM},
  {"log",           fun_log,           1, FNUM},
  {"sqrt",          fun_sqrt,          1, FNUM},
  {"owner",         fun_owner,         1, FSTR},
  {"extract",       fun_extract,       3, FSTR},
  {"name",          fun_name,          1, FSTR},
  {"fsgn",          fun_fsgn,          1, FNUM},
  {"dtoc",          fun_dtoc,          1, FNUM},
  {"spc",           fun_spc,           1, FSTR},
  {"loc",           fun_loc,           1, FSTR},
  {"start",         fun_start,         1, FSTR},
  {"dtof",          fun_dtof,          1, FNUM},
  {"arctan",        fun_arctan,        1, FNUM},
  {"port",          fun_port,          1, FNUM},
  {"idle",          fun_idle,          1, FNUM},
  {"truth",         fun_truth,         1, FNUM},
  {"num",           fun_num,           1, FSTR},
  {"time",          fun_time,         -1, FSTR},
  {"tmfrmt",        fun_tmfrmt,       -1, FSTR},
  {"fsqrt",         fun_fsqrt,         1, FNUM},
  {"last",          fun_last,          1, FSTR},
  {"has",           fun_has,           2, FNUM},
  {"strcat",        fun_strcat,        2, FSTR},
  {"denied",        fun_denied,        0, FSTR},
  {"sin",           fun_sin,           1, FNUM},
  {"nspc",          fun_nspc,          1, FSTR},
  {"abs",           fun_abs,           1, FNUM},
  {"cos",           fun_cos,           1, FNUM},
  {"huh",           fun_huh,           0, FSTR},
  {"base",          fun_base,          3, FNUM},
  {"link",          fun_link,          1, FSTR},
  {"mid",           fun_mid,           3, FSTR},
  {"strlen",        fun_strlen,        1, FNUM},
  {"anum",          fun_anum,          1, FNUM},
  {"lwho",          fun_lwho,          0, FSTR},
  {"quota",         fun_quota,         1, FNUM},
  {"flip",          fun_flip,          1, FSTR},
  {"flags",         fun_flags,         1, FSTR},
  {"wcount",        fun_wcount,        1, FNUM},
  {"xtime",         fun_xtime,        -1, FNUM},
  {"pos",           fun_pos,           2, FNUM},
  {"lnum",          fun_lnum,          1, FSTR},
  {"fabs",          fun_fabs,          1, FNUM},
  {"first",         fun_first,         1, FSTR},
  {"rjust",         fun_rjust,         2, FSTR},
  {"wmatch",        fun_wmatch,        2, FNUM},
  {"cjust",         fun_cjust,         2, FSTR},
  {"string",        fun_string,        2, FSTR},
  {"contype",       fun_contype,       2, FNUM},
  {"randclr",       fun_randclr,       2, FSTR},
  {"strchr",        fun_strchr,        2, FNUM},
  {"comp",          fun_comp,          2, FNUM},
  {"host",          fun_host,          1, FSTR},
  {"entrances",     fun_entrances,     1, FSTR},
  {"ljust",         fun_ljust,         2, FSTR},
  {"onfor",         fun_onfor,         1, FNUM},
  {"roman",         fun_roman,         1, FSTR},
  {"money",         fun_money,         1, FNUM},
  {"room",          fun_room,          1, FSTR},
  {"fcomp",         fun_fcomp,         2, FNUM},
  {"players",       fun_players,       0, FSTR},
  {"class",         fun_class,         1, FSTR},
  {"remove",        fun_remove,        3, FSTR},
  {"arcsin",        fun_arcsin,        1, FNUM},
  {"arccos",        fun_arccos,        1, FNUM},
  {"unparse",       fun_unparse,       1, FSTR},
  {"randword",      fun_randword,      1, FSTR},
  {"linkup",        fun_linkup,        1, FSTR},
  {"hasstr",        fun_hasstr,        2, FNUM},
  {"comma",         fun_comma,         1, FSTR},
  {"scomp",         fun_scomp,         2, FNUM},
  {"playmem",       fun_playmem,       1, FNUM},
  {"quota_left",    fun_quota_left,    1, FNUM},
  {"mazename",      fun_mazename,      0, FSTR},
  {"isdigit",       fun_isdigit,       1, FNUM},
  {"objmem",        fun_objmem,        1, FNUM},
  {"controls",      fun_controls,      3, FNUM},
  {"find",          fun_find,          1, FSTR},
  {"float",         fun_float,         2, FNUM},
  {"stripcolor",    fun_stripcolor,    1, FSTR},
  {"descriptor",    fun_descriptor,    1, FNUM},
  {"haspow",        fun_haspow,        2, FNUM},
  {"sort",          fun_sort,          1, FSTR},
  {"",              NULL,              0}
};

static int istrue(char *str)
{
  return(((strcmp(str, "#-1") == 0) || (strcmp(str, "") == 0) ||
    (strcmp(str, "#-2") == 0) ||
    ((atoi(str) == 0) && isdigit(str[0])))?0:1);
}

int fun_stripcolor(char *buff, char *args[], OBJ *player)
{
  strcpy(buff, strip_color(args[0])); 
  return(0);
}

int fun_descriptor(char *buff, char *args[], OBJ *player)
{
  OBJ *who;
  DDATA *d;

  if(!(who = match_object(player, args[0], TYPE_PLAYER)))
  {
    strcpy(buff, no_match(args[0]));
    return(0);
  }

  if(!controls(player, who, POW_HOST))
  {
    strcpy(buff, perm_denied());
    return(1);
  }

  for(d = descriptor_list;d;d = d->next)
    if(d->player == who)
      break;

  if(!d)
  {
    strcpy(buff, "That player is not connected!");
    return(1);
  }

  sprintf(buff, "%d", d->descriptor);
  return(0);
}

int fun_haspow(char *buff, char *args[], OBJ *player)
{
  OBJ *who;
  int pownum;

  if(!(who = match_object(player, args[0], TYPE_PLAYER)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  if(!controls(player, who, POW_EXAMINE))
  {
    strcpy(buff, perm_denied());
    return(1);
  }

  if((pownum = name_to_pow(args[1])) == -1)
  {
    strcpy(buff, "No such power!");
    return(1);
  }

  if(!power(who, pownum))
    strcpy(buff, "0");
  else
    strcpy(buff, "1");
  return(0);
}

int fun_sort(char *buff, char *args[], OBJ *player)
{
  int *list = NULL;
  int temp;
  int i, j, num_items = 0;
  char *p, *q, *r;

  *buff = '\0';

  for(p = args[0], q = p;*q;p = q)
  {
    while(isspace(*p))
      p++;
    for(q = p;*q && !isspace(*q);q++);
    if(*q)
      *q++ = '\0';

    for(r = p;*r;r++)
    {
      if(!isdigit(*r))
      {
        strcpy(buff, "Illegal character in sort string.");
        return(1);
      }
    }

    if(!num_items)
      list = (int *)stack_alloc(sizeof(int), 0, 0);
    else
      list = (int *)stack_realloc_tmp(list, sizeof(int)*(num_items+1));
    list[num_items++] = atoi(p);
  }

  if(num_items < 2)
  {
    strcpy(buff, args[0]);
    return(0);
  }

  for(i = 0;i < num_items-1;++i)
    for(j = i+1;j < num_items;++j)
      if(list[i] > list[j])
      {
        temp = list[i];
        list[i] = list[j];
        list[j] = temp;
      }

  for(i = 0;i < num_items;++i)
  {
    if(!strlen(buff))
      sprintf(buff, "%d", list[i]);
    else
      sprintf(buff+strlen(buff), " %d", list[i]);
  }

  return(0);
}

int fun_rand(char *buff, char *args[], OBJ *player)
{
  int mod = atoi(args[0]);

  if(mod < 1)
    mod = 1;

  sprintf(buff, "%d", my_rand()%mod);
  return(0);
}

int fun_get(char *buff, char *args[], OBJ *player)
{
  OBJ *thing;
  ATTR *attrib;

  if(!parse_attrib(player, args[0], &thing, &attrib))
  {
    strcpy(buff, "NO MATCH");
    return(1);
  }

  if(!can_see_atr(player, thing, attrib))
  {
    strcpy(buff, perm_denied());
    return(1);
  }

  strcpy(buff, atr_get_a(thing, attrib));
  return(0);
}

int fun_time(char *buff, char *args[], OBJ *player, int nargs)
{
  time_t cl;
  
/* Use supplied x-value if one is given */
/* Otherwise get the current x-value of time */
  if(nargs == 2)
    cl = atol(args[1]);
  else
    cl = now;
  
  if(nargs == 0)
    strcpy(buff, mktm(cl, "D", player));
  else
    strcpy(buff, mktm(cl, args[0], player));

  return(0);
}

int fun_xtime(char *buff, char *args[], OBJ *player, int nargs)
{
  time_t cl;
  
  if(nargs == 0)
    cl = now;
  else
  {
    cl = mkxtime(args[0], player, (nargs > 1)?args[1]:"");
    if(cl == -1L)
    {
      strcpy(buff, "#-1");
      return(1);
    }
  }
  sprintf(buff, "%ld", cl);
  return(0);
}

int fun_objmem(char *buff, char *args[], OBJ *player)
{
  OBJ *thing;

  if(!(thing = match_object(player, args[0], NOTYPE)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  if(!controls(player, thing, POW_DB))
  {
    strcpy(buff, perm_denied());
    return(1);
  }

  sprintf(buff, "%d", mem_usage(thing));
  return(0);
}

int fun_playmem(char *buff, char *args[], OBJ *player)
{
  int tot = 0;
  OBJ *thing;
  OBJ *o;
  
  if(!(thing = match_object(player, args[0], TYPE_PLAYER)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  if(!controls(player, thing, POW_DB))
  {
    strcpy(buff, perm_denied());
    return(1);
  }

  for(o = player_list;o;o = o->next)
    if(o->owner == thing)
      tot += mem_usage(o);
  for(o = thing_list;o;o = o->next)
    if(o->owner == thing)
      tot += mem_usage(o);
  for(o = room_list;o;o = o->next)
    if(o->owner == thing)
      tot += mem_usage(o);
  for(o = exit_list;o;o = o->next)
    if(o->owner == thing)
      tot += mem_usage(o);

  sprintf(buff, "%d", tot);
  return(0);
}

int fun_mid(char *buff, char *args[], OBJ *player)
{
  int l = atoi(args[1]), len = atoi(args[2]);
  char *str;

  if(l < 0 || len < 0 || (len+l) > 1000)
  {
    strcpy(buff, "OUT OF RANGE");
    return(1);
  }
  str = strip_color(args[0]);

  if(l < strlen(str))
    strcpy(buff, str+l);
  else
    *buff = '\0';

  buff[len] = '\0';
  return(0);
}

int fun_truth(char *buff, char *args[], OBJ *player)
{
  sprintf(buff, "%d", (istrue(args[0])?1:0));
  return(0);
}

int fun_denied(char *buff, char *args[], OBJ *player)
{
  extern int num_perm_denied;
  extern char *perm_messages[];

  sprintf(buff, "|+R|%s|n|", perm_messages[my_rand()%num_perm_denied]);
  return(0);
}

int fun_huh(char *buff, char *args[], OBJ *player)
{
  extern int num_bad_cmd_msgs;
  extern char *bad_cmd_msgs[];

  sprintf(buff, "|+B|%s|n|", bad_cmd_msgs[my_rand()%num_bad_cmd_msgs]);
  return(0);
}

int fun_base(char *buff, char *args[], OBJ *player)
{
  int i, digit, decimal, neg, oldbase, newbase;
  char tmpbuf[1000];
  
  oldbase = atoi(args[1]);
  newbase = atoi(args[2]);
  
  if((oldbase < 2) || (oldbase > 36) || (newbase < 2) || (newbase > 36))
  {
    strcpy(buff, "BASES MUST BE BETWEEN 2 AND 36");
    return(1);
  }
  
  neg = 0;
  if(args[0][0] == '-')
  {
    neg = 1;
    args[0][0] = '0';
  }
  
  decimal = 0;
  for(i = 0;args[0][i] != 0;i++)
  {
    decimal *= oldbase;
    
    if(('0' <= args[0][i]) && (args[0][i] <= '9'))
      digit = args[0][i]-'0';
    else if(('a' <= args[0][i]) && (args[0][i] <= 'z'))
      digit = args[0][i]+10-'a';
    else if(('A' <= args[0][i]) && (args[0][i] <= 'Z'))
      digit = args[0][i]+10-'A';
    else
    {
      strcpy(buff, "ILLEGAL DIGIT");
      return(1);
    }
    
    if(digit >= oldbase)
    {
      strcpy(buff, "DIGIT OUT OF RANGE");
      return(1);
    }
    decimal += digit;
  }
  
  strcpy(buff, "");
  strcpy(tmpbuf, "");
  
  i = 0;
  while(decimal > 0)
  {
    strcpy(tmpbuf, buff);
    digit = (decimal%newbase);
    
    if(digit < 10)
      sprintf(buff, "%d%s", digit, tmpbuf);
    else
      sprintf(buff, "%c%s", digit+'a'-10, tmpbuf);
    
    decimal /= newbase;
    i++;
  }
  if(neg)
  {
    strcpy(tmpbuf, buff);
    sprintf(buff, "-%s", tmpbuf);
  }
  return(0);
}

int fun_roman(char *buff, char *args[], OBJ *player)
{
  char *p;
  int num;
  int i;
  struct
  {
    char chr;
    int num;
  } roman[8];

  roman[0].chr = 'N';
  roman[0].num = 5000;
  roman[1].chr = 'M';
  roman[1].num = 1000;
  roman[2].chr = 'D';
  roman[2].num = 500;
  roman[3].chr = 'C';
  roman[3].num = 100;
  roman[4].chr = 'L';
  roman[4].num = 50;
  roman[5].chr = 'X';
  roman[5].num = 10;
  roman[6].chr = 'V';
  roman[6].num = 5;
  roman[7].chr = 'I';
  roman[7].num = 1;

  for(p = args[0];*p && isdigit(*p);++p);

  if(*p)
  {
    strcpy(buff, "ARG must be a number!");
    return(1);
  }

  num = atoi(args[0]);

  if(!num)
  {
    strcpy(buff, "0");
    return(0);
  }

  if(num >= 10000)
  {
    strcpy(buff, "");
    return(0);
  }

  p = buff;

  while(num)
  {
    for(i = 0;i < 8;++i)
      if(num >= roman[i].num)
        break;

    if(num >= (roman[i].num)*4)
    {
      num -= (roman[i].num)*4;
      *p++ = roman[i].chr;
      *p++ = roman[i+1].chr;
    }
    else
    {
      num -= roman[i].num;
      *p++ = roman[i].chr;
    }
  }
  *p = '\0';
  return(0);
}

int fun_sgn(char *buff, char *args[], OBJ *player)
{
  sprintf(buff, "%d", atoi(args[0]) > 0?1:atoi(args[0]) < 0?-1:0);
  return(0);
}

int fun_sqrt(char *buff, char *args[], OBJ *player)
{
  extern double sqrt P((double));
  int k = atoi(args[0]);

  if(k < 0)
    k = (-k);

  sprintf(buff, "%d", (int)sqrt((double)k));
  return(0);
}

int fun_abs(char *buff, char *args[], OBJ *player)
{
  extern int abs P((int));
  
  sprintf(buff, "%d", abs(atoi(args[0])));
  return(0);
}

/* Read first word from a string */
int fun_first(char *buff, char *args[], OBJ *player)
{
  char *s = args[0];
  char *b;

/* Get rid of leading space */
  while(*s && isspace(*s))
    s++;
  b = s;
  while(*s && !isspace(*s))
    s++;
  *s++ = '\0';

  strcpy(buff, b);
  return(0);
}

int fun_last(char *buff, char *args[], OBJ *player)
{
  char *p;

  if(!strchr(args[0], ' '))
  {
    strcpy(buff, args[0]);
    return(0);
  }

  p = &args[0][strlen(args[0])-1];

  while(*(--p) != ' ');

  strcpy(buff, p+1);
  return(0);
}

int fun_rest(char *buff, char *args[], OBJ *player)
{
  char *s = args[0];

/* Skip leading space */
  while(*s && isspace(*s))
    s++;
/* Skip firsts word */
  while(*s && !isspace(*s))
    s++;
/* Skip leading space */
  while(*s && isspace(*s))
    s++;

  strcpy(buff, s);
  return(0);
}

int fun_flags(char *buff, char *args[], OBJ *player)
{
  OBJ *thing;
  
  if(!(thing = match_object(player, args[0], NOTYPE)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  strcpy(buff, unparse_flags(thing));
  return(0);
}

int fun_money(char *buff, char *args[], OBJ *player)
{
  OBJ *who;
  
  if(!(who = match_object(player, args[0], TYPE_PLAYER)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }
  
  if(!controls(player, who, POW_FUNCTIONS))
  {
    strcpy(buff, perm_denied());
    return(1);
  }
  
  sprintf(buff, "%ld", Pennies(who));
  return(0);
}

int fun_quota_left(char *buff, char *args[], OBJ *player)
{
  OBJ *who;
  
  if(!(who = match_object(player, args[0], TYPE_PLAYER)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }
  
  if(!controls(player, who, POW_FUNCTIONS))
  {
    strcpy(buff, perm_denied());
    return(1);
  }
  
  sprintf(buff, "%d", atoi(atr_get(who, "QUOTA"))-owns_stuff(who));
  return(0);
}

int fun_mazename(char *buff, char *args[], OBJ *player)
{
  strcpy(buff, config.maze_name);
  return(0);
}

int fun_quota(char *buff, char *args[], OBJ *player)
{
  OBJ *who;
  
  if(!(who = match_object(player, args[0], TYPE_PLAYER)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  if(!controls(player, who, POW_FUNCTIONS))
  {
    strcpy(buff, perm_denied());
    return(1);
  }
  
  strcpy(buff, atr_get(who, "QUOTA"));
  return(0);
}

int fun_strlen(char *buff, char *args[], OBJ *player)
{
  sprintf(buff, "%d", strlen(args[0])-str_colorlen(args[0]));
  return(0);
}

int fun_comp(char *buff, char *args[], OBJ *player)
{
  int x;
  
  x = (atoi(args[0])-atoi(args[1]));
  if(x > 0)
    strcpy(buff, "1");
  else if(x < 0)
    strcpy(buff, "-1");
  else
    strcpy(buff, "0");
  return(0);
}

int fun_scomp(char *buff, char *args[], OBJ *player)
{
  int x;
  
  x = strcmp(args[0], args[1]);
  if(x > 0)
    strcpy(buff, "1");
  else if(x < 0)
    strcpy(buff, "-1");
  else
    strcpy(buff, "0");
  return(0);
}

int fun_num(char *buff, char *args[], OBJ *player)
{
  OBJ *who;

  if(!(who = match_object(player, args[0], NOTYPE)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  sprintf(buff, "#%d", who->dbref);
  return(0);
}

int fun_loc(char *buff, char *args[], OBJ *player)
{
  OBJ *it;

  if(!(it = match_object(player, args[0], NOTYPE)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  if(IS(it, TYPE_PLAYER, DARK) && !controls(player, it, POW_FUNCTIONS))
  {
    strcpy(buff, perm_denied());
    return(1);
  }

  sprintf(buff, "#%d", it->location->dbref);
  return(0);
}

int fun_room(char *buff, char *args[], OBJ *player)
{
  OBJ *who;
  OBJ *oldloc;

  if(!(who = match_object(player, args[0], NOTYPE)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }
  if(IS(who, TYPE_PLAYER, DARK) && !controls(player, who, POW_FUNCTIONS))
  {
    strcpy(buff, perm_denied());
    return(1);
  }

  for(oldloc = getloc(who);getloc(oldloc) != oldloc;oldloc = getloc(who));

  strcpy(buff, tprintf("#%d", oldloc->dbref));
  return(0);
}

int fun_link(char *buff, char *args[], OBJ *player)
{
  OBJ *it;

  if(!(it = match_object(player, args[0], NOTYPE)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  if(it->owner != player && !controls(player, it, POW_FUNCTIONS))
  {
    strcpy(buff, perm_denied());
    return(1);
  }

  sprintf(buff, "#%d", it->link->dbref);
  return(0);
}

int fun_linkup(char *buff, char *args[], OBJ *player)
{
  OBJ *it, *o;
  int len = 0;

  if(!(it = match_object(player, args[0], TYPE_ROOM)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  if(it->owner != player && !controls(player, it, POW_FUNCTIONS))
  {
    strcpy(buff, perm_denied());
    return(1);
  }

  *buff = '\0';

  for(o = player_list;o;o = o->next)
  {
    if(o->link == it)
    {
      if(len)
        sprintf(buff+strlen(buff), " #%d", o->dbref);
      else
      {
        sprintf(buff, "#%d", o->dbref);
        len = 1;
      }
    }
  }
  for(o = thing_list;o;o = o->next)
  {
    if(o->link == it)
    {
      if(len)
        sprintf(buff+strlen(buff), " #%d", o->dbref);
      else
      {
        sprintf(buff, "#%d", o->dbref);
        len = 1;
      }
    }
  }
  for(o = exit_list;o;o = o->next)
  {
    if(o->link == it)
    {
      if(len)
        sprintf(buff+strlen(buff), " #%d", o->dbref);
      else
      {
        sprintf(buff, "#%d", o->dbref);
        len = 1;
      }
    }
  }

  return(0);
}

int fun_class(char *buff, char *args[], OBJ *player)
{
  OBJ *it;

  if(!(it = match_object(player, args[0], TYPE_PLAYER)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  strcpy(buff, class_to_name(get_class(it)));
  return(0);
}

int fun_rank(char *buff, char *args[], OBJ *player)
{
  OBJ *it;

  if(!(it = match_object(player, args[0], TYPE_PLAYER)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  sprintf(buff, "%d", get_class(it));
  return(0);
}

int fun_has(char *buff, char *args[], OBJ *player)
{
  OBJ *user, *obj;
  OBJ *o;
  
  if(!(user = match_object(player, args[0], TYPE_MASK & ~TYPE_EXIT)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }
  if(!(obj = match_object(player, args[1], TYPE_MASK & ~TYPE_ROOM)))
  {
    strcpy(buff, no_match(args[1]));
    return(1);
  }

  strcpy(buff, "0");

  for(o = user->contents;o;o = o->next_con)
    if(o == obj)
    {
      strcpy(buff, "1");
      return(0);
    }
  for(o = user->exits;o;o = o->next_exit)
    if(o == obj)
    {
      strcpy(buff, "1");
      return(0);
    }

  return(0);
}

int fun_owner(char *buff, char *args[], OBJ *player)
{
  OBJ *it;

  if(!(it = match_object(player, args[0], NOTYPE)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  sprintf(buff, "#%d", it->owner->dbref);
  return(0);
}

int fun_name(char *buff, char *args[], OBJ *player)
{
  OBJ *it;

  if(!(it = match_object(player, args[0], NOTYPE)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  strcpy(buff, name(it));
  return(0);
}

int fun_unparse(char *buff, char *args[], OBJ *player)
{
  OBJ *it;

  if(!(it = match_object(player, args[0], NOTYPE)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  strcpy(buff, unparse_object(it, it));
  return(0);
}

int fun_pos(char *buff, char *args[], OBJ *player)
{
  int i = 1;
  char *t, *u, *s = args[1];
  
  while(*s)
  {
    for(u = s, t = args[0];*t && *t == *u;++t, ++u);  /* Whole loop */
    if(!*t)
    {
      sprintf(buff, "%d", i);
      return(0);
    }
    
    ++i;
    ++s;
  }
  
  strcpy(buff, "0");
  return(0);
}

int fun_delete(char *buff, char *args[], OBJ *player)
{
  char *s = buff, *t = args[0];
  int i, l = atoi(args[1]), len = atoi(args[2]);
  int a0len = strlen(args[0]);
  
  if((l < 0) || (len < 0) || (len+l >= 1000))
  {
    strcpy(buff, "OUT OF RANGE");
    return(1);
  }
  for(i = 0;i < l && *s;i++)
    *s++ = *t++;
  if(len+l >= a0len)
  {
    *s = '\0';
    return(0);
  }
  t += len;
  while((*s++ = *t++));
  return(0);
}

int fun_remove(char *buff, char *args[], OBJ *player)
{
  char *s = buff, *t = args[0];
  int w = atoi(args[1]), num = atoi(args[2]), i;
  
  if(w < 1)
  {
    strcpy(buff, "OUT OF RANGE");
    return(1);
  }
  for(i = 1;i < w && *t;i++)
  {
    while(*t && *t != ' ')
      *s++ = *t++;
    while(*t && *t == ' ')
      *s++ = *t++;
  }
  for(i = 0;i < num && *t;i++)
  {
    while(*t && *t != ' ')
      t++;
    while(*t && *t == ' ')
      t++;
  }
  if(!*t)
  {
    if(s != buff)
      s--;
    *s = '\0';
    return(0);
  }
  while((*s++ = *t++));
  return(0);
}

int fun_extract(char *buff, char *args[], OBJ *player)
{
  int start = atoi(args[1]), len = atoi(args[2]);
  char *s = args[0], *r;

  if((start < 1) || (len < 1))
  {
    *buff = 0;
    return(0);
  }
  start--;
  while(start && *s)
  {
    while(*s && (*s == ' '))
      s++;
    while(*s && (*s != ' '))
      s++;
    start--;
  }
  while(*s && (*s == ' '))
    s++;
  r = s;
  while(len && *s)
  {
    while(*s && (*s == ' '))
      s++;
    while(*s && (*s != ' '))
      s++;
    len--;
  }
  *s = 0;
  strcpy(buff, r);
  return(0);
}

int fun_wmatch(char *buff, char *args[], OBJ *player)
{
  char *string = args[0], *word = args[1], *s, *t;
  int count = 0, done = 0;
  
  for(s = string;*s && !done;s++)
  {
    count++;
    while(isspace(*s) && *s)
      s++;
    t = s;
    while(!isspace(*t) && *t)
      t++;
    done = (!*t)?1:0;
    *t = '\0';
    if(!string_compare(s, word))
    {
      sprintf(buff, "%d", count);
      return(0);
    }
    s = t;
  }
  sprintf(buff, "0");
  return(0);
}

int fun_strcat(char *buff, char *args[], OBJ *player)
{
  strcpy(buff, tprintf("%s%s", args[0], args[1]));
  return(0);
}

int fun_controls(char *buff, char *args[], OBJ *player)
{
  OBJ *who, *object;
  int power;

  if(!(who = match_object(player, args[0], NOTYPE)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }
  if(!(object = match_object(player, args[1], NOTYPE)))
  {
    strcpy(buff, no_match(args[1]));
    return(1);
  }

  if((power = name_to_pow(args[2])) < 0)
  {
    strcpy(buff, "No such power!");
    return(1);
  }

  sprintf(buff, "%d", controls(who, object, power));
  return(0);
}

int fun_entrances(char *buff, char *args[], OBJ *player)
{
  OBJ *it, *o;
  int control_here;

  if(!(it = match_object(player, args[0], TYPE_ROOM)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  *buff = '\0';

/* This is just so we don't have to call controls() every time
   through the loop */
  control_here = controls(player, it, POW_FUNCTIONS);
  if(!control_here)
    control_here = controls(player, it, POW_EXAMINE);

  for(o = exit_list;o;o = o->next)
    if(o->link == it)
      if(control_here || controls(player, o, POW_FUNCTIONS) ||
        controls(player, o, POW_EXAMINE))
      {
        if(*buff)
          strcpy(buff+strlen(buff), tprintf(" #%d", o->dbref));
        else
          sprintf(buff, "#%d", o->dbref);
      }

  return(0);
}

int fun_fsgn(char *buff, char *args[], OBJ *player)
{
  if(atof(args[0]) < 0)
    sprintf(buff, "-1");
  else if(atof(args[0]) > 0)
    sprintf(buff, "1");
  else
    strcpy(buff, "0");
  return(0);
}

int fun_fsqrt(char *buff, char *args[], OBJ *player)
{
  if(atoi(args[0]) < 0)
    sprintf(buff, "%f", (float)0);
  else
    sprintf(buff, "%f", sqrt(atof(args[0])));
  return(0);
}

int fun_fabs(char *buff, char *args[], OBJ *player)
{
  if(atof(args[0]) < 0)
    sprintf(buff, "%f", -atof(args[0]));
  else
    strcpy(buff, args[0]);
  return(0);
}

int fun_fcomp(char *buff, char *args[], OBJ *player)
{
  char buf[90];
  char *k = buf;

  sprintf(buf, "%f", atof(args[0])-atof(args[1]));
  fun_fsgn(buff, &k, player);
  return(0);
}

int fun_exp(char *buff, char *args[], OBJ *player)
{
  if(atof(args[0]) > 99 || atof(args[0]) < -99)
  {
    sprintf(buff, "Error - operand must be from -99 to 99.");
    return(1);
  }

  sprintf(buff, "%f", exp(atof(args[0])));
  return(0);
}

int fun_log(char *buff, char *args[], OBJ *player)
{
  if(atof(args[0]) < 0)
    sprintf(buff, "%f", (float)0);
  else
    sprintf(buff, "%f", log10(atof(args[0])));
  return(0);
}

int fun_ln(char *buff, char *args[], OBJ *player)
{
  sprintf(buff, "%f", log(atof(args[0])));
  return(0);
}

int fun_arctan(char *buff, char *args[], OBJ *player)
{
  if(atof(args[0]) > 1 || atof(args[0]) < -1)
  {
    sprintf(buff, "Error - operand must be from -1 to 1.");
    return(1);
  }

  sprintf(buff, "%f", atan(atof(args[0])));
  return(0);
}

int fun_arccos(char *buff, char *args[], OBJ *player)
{
  if(atof(args[0]) > 1 || atof(args[0]) < -1)
  {
    sprintf(buff, "Error - operand must be from -1 to 1.");
    return(1);
  }

  sprintf(buff, "%f", acos(atof(args[0])));
  return(0);
}

int fun_arcsin(char *buff, char *args[], OBJ *player)
{
  if(atof(args[0]) > 1 || atof(args[0]) < -1)
  {
    sprintf(buff, "Error - operand must be from -1 to 1.");
    return(1);
  }

  sprintf(buff, "%f", asin(atof(args[0])));
  return(0);
}

int fun_tan(char *buff, char *args[], OBJ *player)
{
  if(atof(args[0]) > 1 || atof(args[0]) < -1)
  {
    sprintf(buff, "Error - operand must be from -1 to 1.");
    return(1);
  }

  sprintf(buff, "%f", tan(atof(args[0])));
  return(0);
}

int fun_cos(char *buff, char *args[], OBJ *player)
{
  if(atof(args[0]) > 1 || atof(args[0]) < -1)
  {
    sprintf(buff, "Error - operand must be from -1 to 1.");
    return(1);
  }

  sprintf(buff, "%f", cos(atof(args[0])));
  return(0);
}

int fun_sin(char *buff, char *args[], OBJ *player)
{
  if(atof(args[0]) > 1 || atof(args[0]) < -1)
  {
    sprintf(buff, "Error - operand must be from -1 to 1.");
    return(1);
  }

  sprintf(buff, "%f", sin(atof(args[0])));
  return(0);
}

int fun_eq(char *buff, char *args[], OBJ *player)
{
  sprintf(buff, "%d", (atof(args[0]) == atof(args[1])));
  return(0);
}

int fun_gt(char *buff, char *args[], OBJ *player)
{
  sprintf(buff, "%d", (atof(args[0]) > atof(args[1])));
  return(0);
}

int fun_lt(char *buff, char *args[], OBJ *player)
{
  sprintf(buff, "%d", (atof(args[0]) < atof(args[1])));
  return(0);
}

int fun_gteq(char *buff, char *args[], OBJ *player)
{
  sprintf(buff, "%d", (atof(args[0]) >= atof(args[1])));
  return(0);
}

int fun_lteq(char *buff, char *args[], OBJ *player)
{
  sprintf(buff, "%d", (atof(args[0]) <= atof(args[1])));
  return(0);
}

int fun_randclr(char *buff, char *args[], OBJ *player)
{
  char *p = args[1];
  char colors[500][5];
  char buf[1024];
  int ctr = 0;
  char *b;
  int i;

  if(strlen(args[0]) > 100)
  {
    strcpy(buff, "arg1 out of range!");
    return(1);
  }

  while(ctr < 500)
  {
    b = buf;

    while(*p && *p != ' ')
      *b++ = *p++;
    *b = '\0';

    if(strlen(buf) > 4)
    {
      strcpy(buff, "Invalid color in arg2!");
      return(1);
    }
    strcpy(colors[ctr++], buf);
    if(!*p)
      break;
    p++;
  }

  if(ctr == 500)
  {
    strcpy(buff, "Limit of 500 colors in arg2!");
    return(1);
  }

  for(i = 0;i < ctr;++i)
    if(!my_is_color(colors[i]))
    {
      sprintf(buff, "Invalid color '%s' in arg2!", colors[i]);
      return(1);
    }

  p = args[0];
  b = buff;
  *b = '\0';

  while(*p)
  {
    while(*p == ' ')
      *b++ = *p++;

    *b++ = '|';
    *b = '\0';
    strcat(b, colors[my_rand()%ctr]);
    b = &buff[strlen(buff)];
    *b++ = '|';
    *b++ = *p++;
  }
  *b = '\0';
  return(0);
}

int fun_find(char *buff, char *args[], OBJ *player)
{
  int ctr = 0;
  OBJ *thing;

  *buff = '\0';

  for(thing = player_list;thing;thing = thing->next)
  {
    if(controls(player, thing, POW_EXAMINE) &&
      string_match(thing->name, args[0]))
    {
      if(ctr++ > 99)
      {
        strcpy(buff, "TOO MANY MATCHES");
        return(1);
      }
      if(*buff)
        sprintf(buff, "%d", thing->dbref);
      else
        sprintf(buff+strlen(buff), " #%d", thing->dbref);
    }
  }

  for(thing = thing_list;thing;thing = thing->next)
  {
    if(controls(player, thing, POW_EXAMINE) &&
      string_match(thing->name, args[0]))
    {
      if(ctr++ > 99)
      {
        strcpy(buff, "TOO MANY MATCHES");
        return(1);
      }
      if(*buff)
        sprintf(buff, "%d", thing->dbref);
      else
        sprintf(buff+strlen(buff), " #%d", thing->dbref);
    }
  }

  for(thing = room_list;thing;thing = thing->next)
  {
    if(controls(player, thing, POW_EXAMINE) &&
      string_match(thing->name, args[0]))
    {
      if(ctr++ > 99)
      {
        strcpy(buff, "TOO MANY MATCHES");
        return(1);
      }
      if(*buff)
        sprintf(buff, "%d", thing->dbref);
      else
        sprintf(buff+strlen(buff), " #%d", thing->dbref);
    }
  }

  return(0);
}

int fun_float(char *buff, char *args[], OBJ *player)
{
  int format;
  char *p;
  char no_zeros = 0;

  for(p = args[0];*p && (isdigit(*p) || *p == '.');p++);

  if(*p)
  {
    strcpy(buff, args[0]);
    return(0);
  }

  p = args[1];

  if(*p == '-')
  {
    no_zeros = 1;
    p++;
  }

  while(*p && isdigit(*p))
    p++;

  if(*p)
  {
    strcpy(buff, "INVALID FORMAT: arg2");
    return(1);
  }

  format = atoi(args[1]+((*(args[1]) == '-')?1:0));

  if(format > 99)
  {
    strcpy(buff, "arg2 OUT OF RANGE");
    return(1);
  }

  if(!(p = strchr(args[0], '.')))
  {
    if(no_zeros || !format)
    {
      strcpy(buff, args[0]);
      return(0);
    }

    sprintf(buff, "%s.", args[0]);
    p = buff+strlen(buff);
    while(format--)
      *p++ = '0';
    *p = '\0';

    return(0);
  }

  p++;

/* There shouldn't be 2 '.' in a number */
  if(strchr(p, '.'))
  {
    strcpy(buff, args[0]);
    return(0);
  }

  while(*p && format--)
    p++;

  if(!*p)
  {
    strcpy(buff, args[0]);

    if(no_zeros)
    {
      p = buff+strlen(buff)-1;
      if(*p == '.')
        *p = '\0';
      return(0);
    }

    p = buff+strlen(buff);
    while(format--)
      *p++ = '0';
    *p = '\0';

    return(0);
  }

  *(p+1) = '\0';

  if(atoi(p) < 5)
  {
    *p-- = '\0';

    if(no_zeros)
      while(*p == '0')
        *p-- = '\0';

    if(*p == '.')
      *p = '\0';

    strcpy(buff, args[0]);
    return(0);
  }

/* We have to round the number */
  *p-- = '\0';

  while(p >= args[0])
  {
    if(*p == '.')
    {
      p--;
      continue;
    }

    if(*p == '9')
    {
      *p-- = '0';
      continue;
    }

    *p = (*p)+1;
    break;

  }

  if(p < args[0])
  {
    if(no_zeros)
    {
      p = args[0]+strlen(args[0])-1;
      while(*p == '0')
        *p-- = '\0';
    }

    p = args[0]+strlen(args[0])-1;
    if(*p == '.')
      *p = '\0';

    sprintf(buff, "1%s", args[0]);
    return(0);
  }

  if(no_zeros)
  {
    p = args[0]+strlen(args[0])-1;
    while(*p == '0')
      *p-- = '\0';
  }

  p = args[0]+strlen(args[0])-1;
  if(*p == '.')
    *p = '\0';

  strcpy(buff, args[0]);
  return(0);
}

int fun_nspc(char *buff, char *args[], OBJ *player)
{
  char *p;
  char *b = buff;

  if(!*args[0])
  {
    strcpy(buff, "");
    return(0);
  }

  p = &args[0][strlen(args[0])-1];
  while(p != args[0] && *p == ' ')
    p--;

  if(p == args[0])
  {
    strcpy(buff, "");
    return(0);
  }

  *(p+1) = '\0';

  p = args[0];

  while(*p && *p == ' ')
    p++;

  while(*p)
    *b++ = *p++;
  *b = '\0';
  return(0);
}

int fun_wcount(char *buff, char *args[], OBJ *player)
{
  char *p = args[0];
  int num = 0;
  
  while(*p)
  {
    while(*p && isspace(*p))
      p++;
    if(*p)
      num++;
    while(*p && !isspace(*p))
      p++;
  }
  sprintf(buff, "%d", num);
  return(0);
}

int fun_lwho(char *buff, char *args[], OBJ *player)
{
  char buf[1024];
  DDATA *d;
  
  *buf = '\0';

  for(d = descriptor_list;d;d = d->next)
  {
    if(check_state(d, STATE_CONNECTED))
    {
      if((controls(player, d->player, POW_WHO)) ||
        could_doit(player, d->player, "LHIDE"))
      {
        if(*buf)
          sprintf(buf+strlen(buf), " #%d", d->player->dbref);
        else
          sprintf(buf, "#%d", d->player->dbref);
      }
    }
  }

  strcpy(buff, buf);
  return(0);
}

int fun_spc(char *buff, char *args[], OBJ *player)
{
  char tbuf1[1024];
  int i;
  int s = atoi(args[0]);
  
  if(s <= 0)
  {
    strcpy(buff, "");
    return(0);
  }
  
  if(s > 950)
    s = 950;
  
  for(i = 0;i < s;i++)
    tbuf1[i] = ' ';
  tbuf1[i] = '\0';
  strcpy(buff, tbuf1);
  return(0);
}

static void do_flip(char *s, char *r)
{
  char *p;
  
  p = strlen(s)+r;
  for(*p-- = '\0';*s;p--, s++)
    *p = *s;
}

int fun_flip(char *buff, char *args[], OBJ *player)
{
  do_flip(args[0], buff);
  return(0);
}

int fun_lnum(char *buff, char *args[], OBJ *player)
{
  int x, i;

  x = atoi(args[0]);

  if((x > 250) || (x < 0))
  {
    strcpy(buff, "#-1 Number Out Of Range");
    return(1);
  }
  else
  {
    strcpy(buff, "0");
    for(i = 1;i < x;i++)
      sprintf(buff, "%s %d", buff, i);
  }
  return(0);
}

int fun_string(char *buf, char *args[], OBJ *player)
{
  int num, i;
  char *letter;
  *buf = '\0';

  num = atoi(args[1]);
  letter = args[0];

  if(((num*strlen(letter)) <= 0) || ((num*strlen(letter)) > 950))
  {
    strcpy(buf, "#-1 Out Of Range");
    return(1);
  }
  
  *buf = '\0';
  for(i = 0;i < num;i++)
    strcat(buf, letter);
  return(0);
}

int fun_cjust(char *buff, char *args[], OBJ *player)
{
  strcpy(buff, my_center(args[0], atoi(args[1])));
  return(0);
}

int fun_ljust(char *buff, char *args[], OBJ *player)
{
  strcpy(buff, my_ljust(args[0], atoi(args[1])));
  return(0);
}

int fun_rjust(char *buff, char *args[], OBJ *player)
{
  int number = atoi(args[1]);
  char *text;
  int leader;
  char tbuf1[1000];
  char buf[1000];
  int i;
  
  if(number <= 0 || number > 950)
  {
    sprintf(buff, "#-1 Number out of range.");
    return(1);
  }

  text = args[0];
  leader = number-strlen(text);

  if(leader <= 0)
  {
    strcpy(buff, text);
    buff[number] = 0;
    return(0);
  }

  if(leader > 950)
    leader = 950 - 1;

  for(i = 0;i < leader;i++)
    tbuf1[i] = ' ';
  tbuf1[i] = '\0';
  sprintf(buf, "%s%s", tbuf1, text);
  strcpy(buff, buf);
  return(0);
}

int fun_lattr(char *buff, char *args[], OBJ *player)
{
  OBJ *it;
  int len = 0;
  ALIST *a;
  char temp[1024];

  if(!(it = match_object(player, args[0], NOTYPE)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  *buff = '\0';

  if(!it->attrlist)
    return(0);

  for(a = it->attrlist;a;a = a->next)
  {
    if(can_see_atr(player, it, a->attr))
    {
      sprintf(temp, (*buff)?" %s":"%s", unparse_attr(a));
      if((len+strlen(temp)) > 950)
      {
        strcat(buff, "#-1");
        return(1);
      }
      strcpy(buff+len, temp);
      len += strlen(temp);
    }
  }
  return(0);
}

int fun_type(char *buff, char *args[], OBJ *player)
{
  OBJ *it;

  if(!(it = match_object(player, args[0], NOTYPE)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  strcpy(buff, type_to_name(Typeof(it)));
  return(0);
}

int fun_idle(char *buff, char *args[], OBJ *player)
{
  char buf[1024];
  DDATA *d;
  OBJ *who;

  if(!(who = match_object(player, args[0], TYPE_PLAYER)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  strcpy(buf, "#-1");

  for(d = descriptor_list;d;d = d->next)
  {
    if(check_state(d, STATE_CONNECTED))
    {
      if((controls(player, d->player, POW_WHO)) ||
        could_doit(player, d->player, "LHIDE"))
      {
        if(d->player == who)
        {
          sprintf(buf, "%ld", (now-d->last_time));
          break;
        }
      }
    }
  }

  strcpy(buff, buf);
  return(0);
}

int fun_onfor(char *buff, char *args[], OBJ *player)
{
  char buf[1024];
  DDATA *d;
  OBJ *who;
  
  if(!(who = match_object(player, args[0], TYPE_PLAYER)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  strcpy(buf, "#-1");

  for(d = descriptor_list;d;d = d->next)
  {
    if(check_state(d, STATE_CONNECTED))
    {
      if((controls(player, d->player, POW_WHO)) ||
        could_doit(player, d->player, "LHIDE"))
      {
        if(d->player == who)
        {
          sprintf(buf, "%ld", (now-d->connected_at));
          break;
        }
      }
    }
  }
  strcpy(buff, buf);
  return(0);
}

int fun_port(char *buff, char *args[], OBJ *player)
{
  char buf[1024];
  DDATA *d;
  OBJ *who;

  if(!(who = match_object(player, args[0], TYPE_PLAYER)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  strcpy(buf, "#-1");

  for(d = descriptor_list;d;d = d->next)
  {
    if(check_state(d, STATE_CONNECTED))
    {
      if((controls(player, d->player, POW_WHO)) ||
        could_doit(player, d->player, "LHIDE"))
      {
        if(d->player == who)
        {
          sprintf(buf, "%d", ntohs(d->address.sin_port));
          break;
        }
      }
    }
  }
  strcpy(buff, buf);
  return(0);
}

int fun_host(char *buff, char *args[], OBJ *player)
{
  char buf[1024];
  DDATA *d;
  OBJ *who;

  if(!(who = match_object(player, args[0], TYPE_PLAYER)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  strcpy(buf, "#-1");

  for(d = descriptor_list;d;d = d->next)
  {
    if(check_state(d, STATE_CONNECTED))
    {
      if((controls(player, d->player, POW_WHO)) ||
        could_doit(player, d->player, "LHIDE"))
      {
        if(d->player == who && controls(player, who, POW_HOST))
        {
          sprintf(buf, "%s@%s", d->user, d->addr);
          break;
	}
      }
    }
  }
  strcpy(buff, buf);
  return(0);
}

int fun_tmfrmt(char *buff, char *args[], OBJ *player, int nargs)
{
  long num = atol(args[0]);
  int num_fields = 6;

  if(nargs < 1 || nargs > 2)
  {
    strcpy(buff, "Number of arguments must be 1 or 2");
    return(1);
  }

  if(num < 0)
  {
    strcpy(buff, "Argument must be positive!");
    return(1);
  }

  if(nargs == 2)
  {
    num_fields = atoi(args[1]);
    if(num_fields < 1 || num_fields > 6)
    {
      strcpy(buff, "Number of fields must be between 1 and 6");
      return(1);
    }
  }

  strcpy(buff, time_format(num, num_fields));
  return(0);
}

int fun_comma(char *buff, char *args[], OBJ *player)
{
  int i;

  if(!isdigit(args[0][0]) && args[0][0] != '-'&& args[0][0] != '.')
  {
    strcpy(buff, "Expecting a number.");
    return(1);
  }

  for(i = 1;i < strlen(args[0]);++i)
    if(!isdigit(args[0][i]) && args[0][i] != '.')
    {
      strcpy(buff, "Expecting a number.");
      return(1);
    }
  strcpy(buff, comma(args[0]));
  return(0);
}

int fun_players(char *buff, char *args[], OBJ *player)
{
  OBJ *o;
  char buf[20];

  *buff = '\0';

  for(o = player_list;o;o = o->next)
  {
    sprintf(buf, "#%d", o->dbref);

    if(strlen(buff)+strlen(buf) > 899)
      break;

    if(*buff)
      sprintf(buff+strlen(buff), " %s", buf);
    else
      strcpy(buff, buf);
  }

  return(0);
}

int fun_start(char *buff, char *args[], OBJ *player)
{
  sprintf(buff, "%c", *args[0]);
  return(0);
}

int fun_end(char *buff, char *args[], OBJ *player)
{
  char *p;

  p = &args[0][strlen(args[0])-1];

  sprintf(buff, "%c", *p);
  return(0);
}

int fun_strchr(char *buff, char *args[], OBJ *player)
{
  if(strlen(args[1]) > 1)
  {
    strcpy(buff, "arg2 must be a single character");
    return(1);
  }

  if(strchr(args[0], *args[1]))
    strcpy(buff, "1");
  else
    strcpy(buff, "0");

  return(0);
}

int fun_hasstr(char *buff, char *args[], OBJ *player)
{
  if(strstr(args[0], args[1]))
    strcpy(buff, "1");
  else
    strcpy(buff, "0");

  return(0);
}

int fun_anum(char *buff, char *args[], OBJ *player)
{
  if(strlen(args[0]) > 1)
  {
    strcpy(buff, "Expecting a single character.");
    return(1);
  }
  sprintf(buff, "%d", *args[0]);

  return(0);
}

int fun_dtoc(char *buff, char *args[], OBJ *player)
{
  char *p = args[0];
  int deg;

  if(*p == '-')
    p++;

  while(*p)
  {
    if(!isdigit(*p) && *p != '.')
    {
      strcpy(buff, "Expecting a number");
      return(1);
    }
    p++;
  }      

  deg = atof(args[0]);
  sprintf(buff, "%.2f", (deg-32)*5./9.);

  return(0);
}

int fun_dtof(char *buff, char *args[], OBJ *player)
{
  char *p = args[0];
  int deg;

  if(*p == '-')
    p++;

  while(*p)
  {
    if(!isdigit(*p) && *p != '.')
    {
      strcpy(buff, "Expecting a number");
      return(1);
    }
    p++;
  }      

  deg = atof(args[0]);
  sprintf(buff, "%.2f", (9.*deg/5.)+32);

  return(0);
}

int fun_randword(char *buff, char *args[], OBJ *player)
{
  int num_words = 0;
  char *p = args[0];
  int which_one;
  char buf[100];
  char *b;

  while(*p)         /* Count how many words there are */
  {
    if(*p++ == ' ')
      num_words++;
  }
  num_words++;

  if(num_words <= 0)
  {
    strcpy(buff, "");
    return(0);
  }

  which_one = (my_rand()%num_words)+1;

  p = args[0];

  while(which_one--)        /* Fill buf with the right one */
  {
    b = buf;
    while(*p && *p != ' ')
      *b++ = *p++;
    *b = '\0';
    if(!*p)       /* Shouldn't really need this...but just in case */
      break;
    p++;
  }

  strcpy(buff, buf);
  return(0);
}

int fun_chr(char *buff, char *args[], OBJ *player)
{
  if(!power(player, POW_FUNCTIONS))
  {
    strcpy(buff, perm_denied());
    return(1);
  }

  sprintf(buff, "%c", atoi(args[0]));
  return(0);
}

int fun_isdigit(char *buff, char *args[], OBJ *player)
{
  sprintf(buff, "%d", (isdigit(args[0][0]))?1:0);
  return(0);
}

int fun_contype(char *buff, char *args[], OBJ *player)
{
  OBJ *loc, *thing;
  int type;

  if(!(loc = match_object(player, args[0], TYPE_MASK & ~TYPE_EXIT)))
  {
    strcpy(buff, no_match(args[0]));
    return(1);
  }

  if(string_prefix("Player", args[1]))
    type = TYPE_PLAYER;
  else if(string_prefix("Thing", args[1]))
    type = TYPE_THING;
  else if(string_prefix("Room", args[1]))
    type = TYPE_ROOM;
  else if(string_prefix("Exit", args[1]))
    type = TYPE_EXIT;
  else
  {
    strcpy(buff, "Unknown type!");
    return(1);
  }

  for(thing = loc->contents;thing;thing = thing->next_con)
  {
    if(Typeof(thing) == type)
    {
      if(type == TYPE_PLAYER && !is_connected_raw(thing))
        continue;
      strcpy(buff, "1");
      return(0);
    }
  }

  strcpy(buff, "0");
  return(0);
}

void info_funcs(OBJ *player)
{
  int i;

  notify(player, tprintf("builtin functions:"));
  notify(player, tprintf("%10s %s","function", "nargs"));
  for(i = 0;*(wordlist[i].name);i++)
    if(wordlist[i].name && wordlist[i].name[0])
    {
      if(wordlist[i].nargs == -1)
        notify(player, tprintf("%10s any", wordlist[i].name));
      else
        notify(player, tprintf("%10s %d", wordlist[i].name, wordlist[i].nargs));
    }
}

/* Function to split up a list given a seperator */
/* NOTE: str will get hacked up */
char *parse_up(char **args, int delimit)
{
  char **str = args;
  int deep = 0;
  char *s = *str, *os = *str;

  if(!*s)
    return(NULL);

  while(*s && (*s != delimit))
    if(*s++ == '{')
    {
      deep = 1;

      while(deep && *s)
        switch(*s++)
        {
          case '{':
            deep++;
            break;
          case '}':
            deep--;
            break;
        }
    }

  if(*s)
    *s++ = '\0';
  *str = s;

  return(os);
}

struct fun *lookup_func(char *str)
{
  FUN *ptr = NULL;
  int i;

  for(i = 0;*(wordlist[i].name);++i)
    if(!string_compare(wordlist[i].name, str))
    {
      ptr = &wordlist[i];
      break;
    }

  return(ptr);
}