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 <ctype.h>
#include <string.h>
#include "db.h"
#include "externs.h"

void do_name(OBJ *player, char *arg, char *newname)
{
  OBJ *thing;
  char *password;
  char *no_ansi_name;

  thing = match_object(player, arg, NOTYPE);
  if(!thing)
  {
    notify(player, no_match(arg));
    return;
  }

  if(!*newname)
  {
    notify(player, name(thing));
    return;
  }
    
  if(!controls(player, thing, POW_MODIFY))
  {
    notify(player, perm_denied());
    return;
  }

  if(Typeof(thing) == TYPE_PLAYER)
  {
    if((password = strrchr(newname, ' ')))
      *password++ = '\0';
    else
      password = "";

    no_ansi_name = strip_color(newname);

/* Check for reserved player names */
    if(string_prefix(no_ansi_name, config.guest_prefix))
    {
      notify(player,
        tprintf("Only guests may have names beginning with '%s'",
        config.guest_prefix));
      return;
    }

    if(!*password && !is_root(player))
    {
      notify(player,
        "You must specify a password to change a player name.");
      notify(player, "E.g.: @name <player>=<newname> <password>");
      return;
    }

    if(*Pass(player) && strcmp(Pass(player), password) &&
      strcmp(crypt(password, "XX"), Pass(player)) && !is_root(player))
    {
      notify(player, "Incorrect password.");
      return;
    }
    if(!(ok_player_name(thing, no_ansi_name, atr_get(thing, "ALIAS"))))
    {
      notify(player, "You can't give a player that name.");
      return;
    }

    log_important(tprintf("NAME CHANGE: %s to %s",
      unparse_object(thing, thing), newname));
    notify_in(thing->location, thing,
      tprintf("%s is now known as %s.", name(thing), newname));
    thing->name = stack_string_realloc(thing->name, no_ansi_name);
    atr_add(thing, "RAINBOW", newname);
    notify(player, "Name set.");
    return;
  }

  no_ansi_name = strip_color(newname);

  if(!ok_object_name(thing, no_ansi_name))
  {
    notify(player, "That is not a reasonable name.");
    return;
  }

  if(thing->flags & PUPPET)
    notify_in(thing->location, thing, tprintf("%s is now known as %s.",
     name(thing), newname));
  thing->name = stack_string_realloc(thing->name, no_ansi_name);
  atr_add(thing, "RAINBOW", newname);
  check_spoofobj(player, thing);
  notify(player, "Name set.");
}

void do_describe(OBJ *player, char *name, char *description)
{
  OBJ *thing;
  
  thing = match_object(player, name, NOTYPE);
  if(!thing)
  {
    notify(player, no_match(name));
    return;
  }
  if(!controls(player, thing, POW_MODIFY))
  {
    notify(player, perm_denied());
    return;
  }

  atr_add(thing, "DESC", description);
  notify(player, "Description set.");
}

void do_chown(OBJ *player, char *arg1, char *arg2)
{
  OBJ *thing, *owner;
  
  if(!(thing = match_object(player, arg1, TYPE_MASK & ~TYPE_PLAYER)))
  {
    notify(player, no_match(arg1));
    return;
  }

  if(!*arg2)
    owner = def_owner(player);
  else
  {
    if(!(owner = match_object(player, arg2, TYPE_PLAYER)))
    {
      notify(player, no_match(arg2));
      return;
    }
  }

  log_sensitive(tprintf("Player %s(#%d) attempts: @chown %s=%s",
    name(player), player->dbref, arg1, arg2));
  
  if(!controls(player, owner, POW_CHOWN) ||
    !controls(player, thing, POW_CHOWN))
  {
    notify(player, perm_denied());
    return;
  }

  if(owns_stuff(owner)+1 > atoi(atr_get(owner, "QUOTA")) &&
    !power(owner, POW_NOQUOTA))
  {
    notify(player,
      tprintf("%s doesn't have enough quota!", name(owner)));
    return;
  }

  log_sensitive(tprintf("Player %s(#%d) succeeds with: @chown %s=%s",
    name(player), player->dbref, unparse_object(thing, thing),
    unparse_object(owner, owner)));
    
  thing->owner = owner;
  notify(player, "Owner changed.");
}

static char chk_can_set(OBJ *player, OBJ *thing, unsigned long set,
                        unsigned long flag)
{
  if(!(set & flag))
    return(1);

  if(player == thing)
  {
    if(!Wizard(player))
      return(0);
    return(1);
  }

  if(!controls(player, thing, POW_MODIFY))
    return(0);
  return(1);
}

unsigned long match_flag(OBJ *player, OBJ *thing, char *flagstr, int *denied)
{
  unsigned long flag = 0;
  unsigned long thing_power_flags = 0;
  unsigned long player_power_flags =
    PLAYER_NO_ANN|PLAYER_NO_COM;
  unsigned long room_power_flags = 0;
  unsigned long exit_power_flags = 0;
  unsigned long common_power_flags = 0;

  switch(Typeof(thing))
  {
    case TYPE_THING:
      if(!string_compare("light", flagstr))
        flag = THING_LIGHT;

      if(!chk_can_set(player, thing, thing_power_flags, flag))
      {
        flag = 0;
        *denied = 1;
      }
      break;
    case TYPE_PLAYER:
      if(!string_compare("newbie", flagstr))
        flag = PLAYER_NEWBIE;
      else if(!string_compare("slave", flagstr))
      {
        if(!controls(player, thing, POW_SLAVE))
          *denied = 1;
        else
          flag = PLAYER_SLAVE;
      }
      else if(!string_compare("terse", flagstr))
        flag = PLAYER_TERSE;
      else if(!string_compare("ansi", flagstr))
        flag = PLAYER_ANSI;
      else if(!string_compare("mortal", flagstr))
        flag = PLAYER_MORTAL;
      else if(!string_compare("invisible", flagstr))
      {
        if(Wizard(player))
          flag = PLAYER_INVISIBLE;
      }
      else if(!string_compare("no_announce", flagstr))
        flag = PLAYER_NO_ANN;
      else if(!string_compare("no_com", flagstr))
        flag = PLAYER_NO_COM;
      else if(!string_compare("no_walls", flagstr))
        flag = PLAYER_NO_WALLS;
      else if(!string_compare("suspect", flagstr))
      {
        if(Wizard(player))
          flag = PLAYER_SUSPECT;
      }

      if(!chk_can_set(player, thing, player_power_flags, flag))
      {
        flag = 0;
        *denied = 1;
      }
      break;
    case TYPE_ROOM:
      if(!string_compare("floating", flagstr))
        flag = ROOM_FLOATING;

      if(!chk_can_set(player, thing, room_power_flags, flag))
      {
        flag = 0;
        *denied = 1;
      }
      break;
    case TYPE_EXIT:
      if(!string_compare("light", flagstr))
        flag = EXIT_LIGHT;
      else if(!string_compare("transparent", flagstr))
        flag = OPAQUE;

      if(!chk_can_set(player, thing, exit_power_flags, flag))
      {
        flag = 0;
        *denied = 1;
      }
      break;
  }

  if(flag || *denied)
    return(flag);

  if(!string_compare("quiet", flagstr))
    flag = QUIET;
  else if(!string_compare("nomod", flagstr))
    flag = NOMODIFY;
  else if(!string_compare("dark", flagstr))
    flag = DARK;
  else if(!string_compare("puppet", flagstr))
    flag = PUPPET;
  else if(!string_compare("inherit", flagstr))
    flag = INHERIT_POWERS;
  else if(!string_compare("visible", flagstr))
    flag = VISIBLE;
  else if(!string_compare("opaque", flagstr))
    flag = OPAQUE;
  else if(!string_compare("haven", flagstr))
    flag = HAVEN;

  if(!chk_can_set(player, thing, common_power_flags, flag))
  {
    flag = 0;
    *denied = 1;
  }

  return(flag);
}

unsigned long match_flag2(OBJ *player, OBJ *thing, char *flagstr,
                          int *denied)
{
  unsigned long flag = 0;
  unsigned long thing_power_flags = 0;
  unsigned long player_power_flags = 0;
  unsigned long room_power_flags = 0;
  unsigned long exit_power_flags = 0;
  unsigned long common_power_flags = 0;

  switch(Typeof(thing))
  {
    case TYPE_THING:
      if(!chk_can_set(player, thing, thing_power_flags, flag))
      {
        flag = 0;
        *denied = 1;
      }
      break;
    case TYPE_PLAYER:
      if(!chk_can_set(player, thing, player_power_flags, flag))
      {
        flag = 0;
        *denied = 1;
      }
      break;
    case TYPE_ROOM:
      if(!chk_can_set(player, thing, room_power_flags, flag))
      {
        flag = 0;
        *denied = 1;
      }
      break;
    case TYPE_EXIT:
      if(!chk_can_set(player, thing, exit_power_flags, flag))
      {
        flag = 0;
        *denied = 1;
      }
      break;
  }

  if(flag || *denied)
    return(flag);

  if(!chk_can_set(player, thing, common_power_flags, flag))
  {
    flag = 0;
    *denied = 1;
  }

  return(flag);
}

void do_set(OBJ *player, char *arg, char *flag)
{
  OBJ *thing;
  char *p, *q;
  unsigned long f;
  int denied;
  int flags2;
  
  thing = match_object(player, arg, NOTYPE);
  if(!thing)
  {
    notify(player, no_match(arg));
    return;
  }

  if(!controls(player, thing, POW_MODIFY))
  {
    notify(player, perm_denied());
    return;
  }

/* Check for attribute set first */
  for(p = flag;*p && (*p != ':');p++);
  if(*p)
  {
    ATTR *attr;
    
    *p++ = '\0';

    if(!(attr = find_attr(flag)))
    {
      notify(player, "Sorry that isn't a valid attribute.");
      return;
    }

    if(!can_set_atr(player, thing, attr))
    {
      notify(player, "You can't set that attribute.");
      return;
    }

    if(!string_compare(attr->name, "ALIAS") && Typeof(thing) != TYPE_PLAYER)
    {
      notify(player, "Sorry only players can have aliases.");
      return;
    }
    if(!string_compare(attr->name, "ALIAS") &&
      !ok_player_name(thing, thing->name, p))
    {
      notify(player, "You can't set alias to that.");
      return;
    }
    if(!string_compare(attr->name, "SEX"))
    {
      if(tolower(*p) != 'm' && tolower(*p) != 'f' &&
        tolower(*p) != 'n')
      {
        notify(player,
          "You may only set your sex to male, female, or neuter.");
        return;
      }    
    }
    if(!string_compare(attr->name, "COLOR"))
    {
      if(strstr(p, "N") && !strstr(p, "+"))
      {
        char buf[4096];

        sprintf(buf, "+%s", p);
        strcpy(p, buf);
      }
    }

    if(attr)
      if(attr->flags & AF_LOCK)
      {
        if((q = process_lock(player, p)))
        {
          thing->mod_time = now;
          atr_add_a(thing, attr, q);
          if(*q)
            notify(player, "Locked.");
          else
            notify(player, "Unlocked.");
        }
        return;
      }

    thing->mod_time = now;
    atr_add_a(thing, attr, p);
    if(!(player->flags & QUIET))
      notify(player, tprintf("%s - Set.", name(thing)));
    return;
  }
  
  flags2 = 0;
  denied = 0;

/* Move p past NOT_TOKEN if present */
  for(p = flag;*p && (*p == NOT_TOKEN || isspace(*p));p++);
  
  if(!*p)
  {
    notify(player, "You must specify a flag to set.");
    return;
  }
  
  f = match_flag(player, thing, p, &denied);
  if(denied)
  {
    notify(player, perm_denied());
    return;
  }
  if(!f)
  {
    f = match_flag2(player, thing, p, &denied);
    if(denied)
    {
      notify(player, perm_denied());
      return;
    }
    if(!f)
    {
      notify(player, tprintf("Unknown flag '%s'.", p));
      return;
    }
    flags2 = 1;
  }
  
/* Check for restricted flag */
  if(f == HAVEN && *flag == NOT_TOKEN)
  {
    OBJ *o;

    o = match_player(NULL, thing->name);
    if(o && !controls(player, thing, POW_SPOOF))
    {
      notify(player, "Sorry, a player holds that name.");
      return;
    }
  }
  if(Typeof(thing) == TYPE_PLAYER && f == PLAYER_SLAVE)
  {
    log_sensitive(tprintf("%s(#%d) %sslaved %s", name(player),
      player->dbref, (*flag == NOT_TOKEN)?"un":"en",
      unparse_object(thing, thing)));
  }

  if(f == INHERIT_POWERS &&
    !controls(player, thing, POW_SECURITY))
  {
    notify(player, perm_denied());
    return;
  }

  if(*flag == NOT_TOKEN)
  {
    if(flags2)
      thing->flags2 &= ~f;
    else
      thing->flags &= ~f;
    notify(player, "Flag reset.");
  }
  else
  {
    if(flags2)
      thing->flags2 |= f;
    else
      thing->flags |= f;
    notify(player, "Flag set.");
  }
}

/* Check for abbreviated set command */
int test_set(OBJ *player, char *command, char *arg1, char *arg2)
{
  char buff[4096];
  OBJ *thing;

  if(*command != '~' || Guest(player))
    return(0);

  thing = match_object(player, arg1, NOTYPE);
  if(!thing)
    return(0);
  if(!find_attr(command+1))
    return(0);

  sprintf(buff, "%s:%s", command+1, arg2);
  do_set(player, arg1, buff);
  return(1);
}

static char *split_arg(char *arg)
{
  char *p = arg;
  char *arg2 = NULL;

  while(*p)
  {
    switch(*p)
    {
      case '{':
        extract_char(p);
        while(*p && *p != '}')
          p++;
        if(!*p)
          return(NULL);
        extract_char(p);
        break;
      case ',':
        *p++ = '\0';
        arg2 = p;
        break;
      default:
        p++;
    }
  }

  if(!arg2)
    return(NULL);

  return(arg2);
}

void do_edit(OBJ *player, char *it, char *arg)
{
  OBJ *thing;
  ATTR *attr;
  ALIST *atr;
  char *p, *q;
  char buf[4096], buf2[4096];
  int ctr = 0;

  if(!parse_attrib(player, it, &thing, &attr))
  {
    notify(player, "No match.");
    return;
  }

  if(!(atr = find_attr_on_obj(thing, attr)))
  {
    notify(player, "No match.");
    return;
  }

  if(!controls(player, thing, POW_MODIFY))
  {
    notify(player, perm_denied());
    return;
  }

  if(!can_set_atr(player, thing, attr))
  {
    notify(player, perm_denied());
    return;
  }

  if(!string_compare(attr->name, "ALIAS"))
  {
    notify(player, "To set an alias, do @alias me=<new alias>.");
    return;
  }

  if(!*arg || !(p = split_arg(arg)))
  {
    notify(player, "Nothing to do.");
    return;
  }

  if(!strcmp(arg, p))
  {
    notify(player, "Nothing to do.");
    return;
  }
  strcpy(buf, atr_get_a(thing, attr));

  for(q = buf, ctr = 0;q;q += strlen(arg), ctr++)
  {
    if(!(q = strstr(q, arg)))
      break;
    strcpy(buf2, q+strlen(arg));
    sprintf(q, "%s%s", p, buf2);
  }

  if(!ctr)
  {
    notify(player, tprintf("No instances of '%s' were found.", arg));
    return;
  }

  notify(player, tprintf("Modified %d instances of '%s'.", ctr, arg));

  atr_add_a(thing, attr, buf);

  if(!(player->flags & QUIET))
  {
    notify(player, tprintf("%s - Set.", name(thing)));
    do_examine(player, it);
  }
}

void do_ansi(OBJ *player, char *arg)
{
  if(!*arg)
  {
    notify(player, tprintf("|+B|ANSI emulation is|+W|: |+C|%s",
      (player->flags & PLAYER_ANSI)?"ON":"OFF"));
    return;
  }

  if(!string_compare(arg, "on"))
  {
    if(player->flags & PLAYER_ANSI)
      notify(player, "You already have ANSI emulation on.");
    else
    {
      player->flags |= PLAYER_ANSI;
      notify(player, "ANSI emulation enabled.");
    }
    return;
  }

  if(!string_compare(arg, "off"))
  {
    if(!(player->flags & PLAYER_ANSI))
      notify(player, "You already have ANSI emulation off.");
    else
    {
      player->flags &= ~PLAYER_ANSI;
      notify(player, "ANSI emulation disabled.");
    }
    return;
  }

  notify(player, "Valid arguments are 'on' and 'off'.");
}