/
teeny/db/
teeny/dbm/
teeny/docs/
teeny/includes/
teeny/misc/
teeny/news/
teeny/text/
/* buildcmds.c */

#include "copyright.h"
#include "config.h"

#include <stdio.h>
#ifdef STRING_H
#include <string.h>
#else
#include <strings.h>
#endif					/* STRING_H */
#include <ctype.h>

#include "teeny.h"

/*
 * Building/Creating commands 
 */

/* Buffer from cmds.c */

extern char     cmdwork[];

voidfunc 
do_create(player, argone)
  int             player;
  char           *argone;
{
  int             obj, next, count, home, here;
  char           *p;

#ifdef RESTRICT_BUILDING
  if (!isbuilder(player) && !iswiz(player))
  {
    notify_player(player, "That command is for authorized builders only.\r\n");
    return;
  }
#endif				/* RESTRICT_BUILDING */

  if (!argone || !*argone)
  {
    notify_player(player, "You need to specify a name.\r\n");
    return;
  }
  if (!ok_name(argone))
  {
    notify_player(player, "That's a silly name for an object!\r\n");
    return;
  }

  /* Go to it */

  obj = create_obj(TYP_THING);
  if (set_str_elt(obj, NAME, argone) == -1)
    goto createbomb;

  if (set_int_elt(obj, OWNER, player) == -1)
    goto createbomb;
  if (set_int_elt(obj, LOC, player) == -1)
    goto createbomb;
  if (get_int_elt(player, LOC, &here) == -1)
    goto createbomb;
  if (controls(player, here) || isabode(here))
  {
    home = here;
  } else
  {
    if (get_int_elt(player, HOME, &home) == -1)
      goto createbomb;
  }
  if (set_int_elt(obj, HOME, home) == -1)
    goto createbomb;

  if (get_int_elt(player, CONTENTS, &next) == -1)
    goto createbomb;
  if (set_int_elt(player, CONTENTS, obj) == -1)
    goto createbomb;
  if (set_int_elt(obj, NEXT, next) == -1)
    goto createbomb;

#ifdef TIMESTAMPS
  stamp(obj);
#endif				/* TIMESTAMPS */

  /* Tell the player */

  p = cmdwork;
  count = 0;
  strcpy(p, "Object ");
  p += 7;
  count += 7;
  while (*argone && count < BUFFSIZ - 33)
  {
    *p++ = *argone++;
    count++;
  }
  strcpy(p, " created with number #");
  p += 22;
  p = ty_itoa(p, obj);
  *p++ = '.';
  *p++ = '\r';
  *p++ = '\n';
  *p = '\0';
  notify_player(player, cmdwork);
  return;
createbomb:
  notify_bad(player);
  return;
}
voidfunc 
do_dig(player, arg)
  int             player;
  char           *arg;
{
  int             room, count;
  char           *p;

#ifdef RESTRICT_BUILDING
  if (!isbuilder(player) && !iswiz(player))
  {
    notify_player(player, "That command is for authorized builders only.\r\n");
    return;
  }
#endif				/* RESTRICT_BUILDING */

  if (!arg || !*arg)
  {
    notify_player(player, "You need to specify a name.\r\n");
    return;
  }
  if (!ok_name(arg))
  {
    notify_player(player, "That's a silly name for a room!\r\n");
    return;
  }
  room = create_obj(TYP_ROOM);
  if (set_int_elt(room, OWNER, player) == -1)
    goto digbomb;
  if (set_str_elt(room, NAME, arg) == -1)
    goto digbomb;

#ifdef TIMESTAMPS
  stamp(room);
#endif				/* TIMESTAMPS */

  /* Tell the player */

  p = cmdwork;
  count = 0;
  strcpy(p, "Room ");
  p += 5;
  count += 5;
  while (*arg && count < BUFFSIZ - 33)
  {
    *p++ = *arg++;
    count++;
  }
  strcpy(p, " dug with number #");
  p += 18;
  p = ty_itoa(p, room);
  *p++ = '.';
  *p++ = '\r';
  *p++ = '\n';
  *p = '\0';
  notify_player(player, cmdwork);
  return;
digbomb:
  notify_bad(player);
  return;
}
void 
do_set_string(player, argone, argtwo, code)
  int             player;
  char           *argone;
  char           *argtwo;
  int             code;
{
  int             obj, flags;
  char           *oldname;
  char           *givenpwd, ch;

  /* Find the thing to set the string ON */

  if (!argone || !*argone)
  {
    notify_player(player, "Set what on what?\r\n");
    return;
  }
  if ((obj = resolve_object_or_exit(player, argone, 0)) == -1)
  {
    notify_player(player, "I don't see that here.\r\n");
    return;
  }
  if (obj == -2)
  {
    notify_player(player, "I don't know which one you mean.\r\n");
    return;
  }
  if (!controls(player, obj))
  {
    notify_player(player, "You can't do that!\r\n");
    return;
  }
#ifdef TIMESTAMPS
  if (!isplayer(obj))
    stamp(obj);
#endif				/* TIMESTAMPS */

  if (code == GENDER && !isplayer(obj))
  {
    notify_player(player, "Only players have gender.\r\n");
    return;
  }
  if ((code == OARRIVE || code == OLEAVE) && !isplayer(obj))
  {
    notify_player(player, "Only players have teleport strings.\r\n");
    return;
  }
  if ((code == FAIL || code == SUC) && isplayer(obj))
  {
    notify_player(player, "Players don't have that string.\r\n");
    return;
  }

  /* We *might* be setting a player name. Gotta be careful */

  if (code == NAME)
  {

    /* Check out the name */

    if (get_int_elt(obj, FLAGS, &flags) == -1)
    {
      warning("do_set_string", "cannot get flags");
      goto namebomb;
    }
    if((flags & TYPE_MASK) == TYP_EXIT)
    {
      if (!ok_exit_name(argtwo))
      {
        notify_player(player, "Bad name.\r\n");
        return;
      }
    } else {
      if (!ok_name(argtwo))
      {
        notify_player(player, "Bad name.\r\n");
        return;
      }
    }
    if ((flags & TYPE_MASK) == TYP_PLAYER)
    {
      /* skip to pwd in given name */

      givenpwd = argtwo;
      while (!isspace(*givenpwd) && *givenpwd)
	givenpwd++;
      ch = *givenpwd;
      *givenpwd = '\0';

      if (!ok_player_name(argtwo))
      {
	notify_player(player, "You can't give a player that name.\r\n");
	return;
      }
      *givenpwd = ch;
      while (isspace(*givenpwd))
	givenpwd++;
      /* Ok. Hack around. */

      if (get_str_elt(obj, NAME, &oldname) == -1)
      {
	goto namebomb;
      }
      /* Skip to password in oldname */

      while (!isspace(*oldname) && *oldname)
	oldname++;
      while (isspace(*oldname))
	oldname++;

      if (strcmp(oldname, givenpwd) != 0)
      {
	notify_player(player, "Wrong password.\r\n");
	return;
      }
      /* argtwo has a valid name/pwd pair */
    }
  }
  if(code == OARRIVE)
    code = FAIL;
  if(code == OLEAVE)
    code = SUC;
    
  if (set_str_elt(obj, code, argtwo) == -1)
    goto namebomb;

  switch (code)
  {
  case NAME:
    notify_player(player, "Name set.\r\n");
    break;
  case GENDER:
    notify_player(player, "Gender set.\r\n");
    break;
  case DESC:
    notify_player(player, "Description set.\r\n");
    break;
  default:
    notify_player(player, "Message set.\r\n");
  }

  return;

namebomb:
  notify_bad(player);
  return;
}

voidfunc 
do_lock(player, argone, argtwo)
  int             player;
  char           *argone;
  char           *argtwo;
{
  int             obj, *exp;

  if (!argone || !*argone || !argtwo || !*argtwo)
  {
    notify_player(player, "Lock what to what?\r\n");
    return;
  }
  if ((obj = resolve_object_or_exit(player, argone, 0)) == -1)
  {
    notify_player(player, "I don't see that here.\r\n");
    return;
  }
  if (obj == -2)
  {
    notify_player(player, "I don't know which one you mean.\r\n");
    return;
  }
  if (!controls(player, obj))
  {
    notify_player(player, "You can't do that!\r\n");
    return;
  }
  /* OK. We can mess with the lock on this thing. */

  exp = bool_parse(player, argtwo);
  if (exp == NULL)
    return;			/* bool_parse() already told the player off. */

  if (set_lock_elt(obj, LOCK, exp) == -1)
  {
    notify_bad(player);
    return;
  }
  notify_player(player, "Locked.\r\n");
}
voidfunc 
do_unlock(player, arg)
  int             player;
  char           *arg;
{
  int             obj;

  if (!arg || !*arg)
  {
    notify_player(player, "Unlock what?\r\n");
    return;
  }
  if ((obj = resolve_object_or_exit(player, arg, 0)) == -1)
  {
    notify_player(player, "I don't see that here.\r\n");
    return;
  }
  if (obj == -2)
  {
    notify_player(player, "I don't know which on you want to unlock.\r\n");
    return;
  }
  if (!controls(player, obj))
  {
    notify_player(player, "You can't do that!\r\n");
    return;
  }
  if (set_lock_elt(obj, LOCK, (int *) NULL) == -1)
  {
    notify_bad(player);
    return;
  }
  notify_player(player, "Unlocked.\r\n");
}

voidfunc 
do_open(player, argone, argtwo)
  int             player;
  char           *argone;
  char           *argtwo;
{
  int             here, exit, list, dest, flags;
  int             count;
  extern int      total_objects;
  char           *p;

#ifdef RESTRICT_BUILDING
  if (!isbuilder(player) && !iswiz(player))
  {
    notify_player(player, "That command is for authorized builders only.\r\n");
    return;
  }
#endif				/* RESTRICT_BUILDING */

  if (!argone || !*argone)
  {
    notify_player(player, "You must specify a name.\r\n");
    return;
  }
  if (!ok_exit_name(argone))
  {
    notify_player(player, "That's a silly name for an exit!\r\n");
    return;
  }
  if (get_int_elt(player, LOC, &here) == -1)
    goto openbomb;
#ifndef BUILDING_OK
  if (!controls(player, here))
  {
    notify_player(player, "You can't open an exit here!\r\n");
    return;
  }
#else
  if (!controls(player, here) && !isbuilder(here))
  {
    notify_player(player, "You can't open an exit here!\r\n");
    return;
  }
#endif				/* BUILDING_OK */

  exit = create_obj(TYP_EXIT);
  if (set_str_elt(exit, NAME, argone) == -1)
    goto openbomb;
  if (set_int_elt(exit, OWNER, player) == -1)
    goto openbomb;
  if (set_int_elt(exit, LOC, here) == -1)
    goto openbomb;
  if (get_int_elt(here, EXITS, &list) == -1)
    goto openbomb;
  if (set_int_elt(exit, NEXT, list) == -1)
    goto openbomb;
  if (set_int_elt(here, EXITS, exit) == -1)
    goto openbomb;

#ifdef TIMESTAMPS
  stamp(exit);
#endif				/* TIMESTAMPS */
  /* Tell the player about this exit */

  p = cmdwork;
  count = 0;
  strcpy(p, "Exit ");
  p += 5;
  count += 5;
  while (*argone && count < BUFFSIZ - 33)
  {
    *p++ = *argone++;
    count++;
  }
  strcpy(p, " opened with number #");
  p += 21;
  p = ty_itoa(p, exit);
  *p++ = '.';
  *p++ = '\r';
  *p++ = '\n';
  *p = '\0';
  notify_player(player, cmdwork);

  if (argtwo != NULL)
  {				/* Try to link this */
    if (strcmp(argtwo, "home") == 0)
    {
      dest = -3;
    } else
    if (strcmp(argtwo, "here") == 0)
    {
      dest = here;
    } else
    {
      if (*argtwo != '#' || !isdigit(argtwo[1]))
      {
	notify_player(player, "I don't grok your destination.\r\n");
	return;
      }
      dest = atoi(argtwo + 1);
    }
    notify_player(player, "Trying to link...\r\n");

    /* Can we link there? */

    if (dest != -3 && !exists_object(dest))
    {
      notify_player(player, "Bad destination.\r\n");
      return;
    }
    if (dest != -3 && get_int_elt(dest, FLAGS, &flags) == -1)
    {
      notify_player(player, "Can't find destination.\r\n");
      return;
    }
    if (dest != -3 && (TYPE_MASK & flags) != TYP_ROOM)
    {
      notify_player(player, "That's not a room!\r\n");
      return;
    }
    if (!controls(player, dest) && !(flags & LINK_OK))
    {
      notify_player(player, "Can't link to destination.\r\n");
      return;
    }
    /* OK. We can link there. */

    if (set_int_elt(exit, DESTINATION, dest) == -1)
      goto openbomb;
    notify_player(player, "Linked.\r\n");
  }
  return;

openbomb:
  notify_bad(player);
  return;
}
voidfunc 
do_link(player, argone, argtwo)
  int             player;
  char           *argone;
  char           *argtwo;
{
  int             dest, flags, thing, here, location;
  int             code, foo, exowner;
  char           *msg;

  if (!argone || !*argone || !argtwo || !*argtwo)
  {
    notify_player(player, "Link what to where?\r\n");
    return;
  }
  if (get_int_elt(player, LOC, &here) == -1)
    goto linkbomb;

  /* Find the destination, thing to link to */

  if (strcmp(argtwo, "home") == 0)
  {
    dest = -3;			/* Abstract db ref to home */
  } else
  if (strcmp(argtwo, "here") == 0)
  {
    dest = here;
  } else
  {
    if (*argtwo != '#' || !isdigit(argtwo[1]))
    {
      notify_player(player, "I don't understand that destination.\r\n");
      return;
    }
    dest = atoi(argtwo + 1);
  }
  /* Can we link there? */

  if (dest != -3 && !exists_object(dest))
  {
    notify_player(player, "Bad destination.\r\n");
    return;
  }
  if (dest != -3 && get_int_elt(dest, FLAGS, &flags) == -1)
  {
    notify_player(player, "Can't find destination.\r\n");
    return;
  }
  if (dest != -3 && (flags & TYPE_MASK) != TYP_ROOM)
  {
    notify_player(player, "That's not a room!\r\n");
    return;
  }
  /* OK. Try to get the thing to link */

  if ((thing = resolve_object_or_exit(player, argone)) == -1)
  {
    notify_player(player, "I don't see that here.\r\n");
    return;
  }
  if (thing == -2)
  {
    notify_player(player, "I can't tell which one you want to link.\r\n");
    return;
  }
  if (get_int_elt(thing, FLAGS, &flags) == -1)
    goto linkbomb;

  if ((((flags & TYPE_MASK) == TYP_PLAYER) ||
       ((flags & TYPE_MASK) == TYP_THING)) &&
      !controls(player, dest) && !isabode(dest))
  {
    notify_player(player, "You can't link that there!\r\n");
    return;
  }
  if ((((flags & TYPE_MASK) == TYP_EXIT) ||
       ((flags & TYPE_MASK) == TYP_ROOM)) &&
      !controls(player, dest) && !islinkok(dest))
  {
    notify_player(player, "You can't link that there!\r\n");
    return;
  }
  /* What sort of thing is it? */

  switch (flags & TYPE_MASK)
  {
  case TYP_PLAYER:
  case TYP_THING:
    if (dest == -3)
    {
      notify_player(player, "Paradox in link of object.\r\n");
      return;
    }
    msg = "Home set.\r\n";
    code = HOME;
    break;
  case TYP_ROOM:
    msg = "Dropto set.\r\n";
    code = DROPTO;
    break;
  case TYP_EXIT:
    msg = "Linked.\r\n";
    code = DESTINATION;
    /* Check to see if the exit is in the room */
    if (get_int_elt(thing, LOC, &location) == -1)
      goto linkbomb;
    if (location != here)
    {
      notify_player(player, "That exit's not in this room.\r\n");
      return;
    }
    /* Check that the exit is unlinked */

    if (get_int_elt(thing, DESTINATION, &foo) == -1)
      goto linkbomb;

    if (foo != -1)
    {
      notify_player(player, "That exit is linked.\r\n");
      return;
    } else
    {
      if (get_int_elt(thing, OWNER, &exowner) == -1)
	goto linkbomb;
      if (exowner != player)
      {

#ifdef RESTRICT_BUILDING
	if (!isbuilder(player) && !iswiz(player))
	{
	  notify_player(player, "Only authorized builders may do that.\r\n");
	  return;
	}
#endif				/* RESTRICT_BUILDING */

      }
    }
    if (set_int_elt(thing, OWNER, player) == -1)
      goto linkbomb;
    notify_player(player, "Trying to link...\r\n");
    break;
  default:
    notify_player(player, "I don't understand that.\r\n");
    warning("do_link", "bad type field detected");
    return;
  }

  if (!controls(player, thing))
  {
    notify_player(player, "You don't own that!\r\n");
    return;
  }
  /* Link it up. */

  if (set_int_elt(thing, code, dest) == -1)
    goto linkbomb;
  notify_player(player, msg);
  return;

linkbomb:

  notify_bad(player);
  return;
}

voidfunc 
do_unlink(player, arg)
  int             player;
  char           *arg;
{
  int             obj, flags, code;
  char           *msg;

  if (!arg || !*arg)
  {
    notify_player(player, "Unlink what?\r\n");
    return;
  }
  if ((obj = resolve_object_or_exit(player, arg)) == -1)
  {
    notify_player(player, "I can't find that.\r\n");
    return;
  }
  if (obj == -2)
  {
    notify_player(player, "I can't tell which one you want to unlink.\r\n");
    return;
  }
  if (!controls(player, obj))
  {
    notify_player(player, "You can't unlink that!\r\n");
    return;
  }
  /* Unlink it. */

  if (get_int_elt(obj, FLAGS, &flags) == -1)
    goto unlinkbomb;
  switch (flags & TYPE_MASK)
  {
  case TYP_PLAYER:
  case TYP_THING:
    notify_player(player, "Can't unset an object's home!\r\n");
    return;
  case TYP_EXIT:
    code = DESTINATION;
    msg = "Exit unlinked.\r\n";
    break;
  case TYP_ROOM:
    code = DROPTO;
    msg = "Dropto unset.\r\n";
    break;
  default:
    notify_player(player, "I don't understand that.\r\n");
    return;
  }

  if (set_int_elt(obj, code, -1) == -1)
    goto unlinkbomb;
  notify_player(player, msg);
  return;

unlinkbomb:

  notify_bad(player);
  return;
}

/*
 * the next two routines provide @edit service. yay. the code be based on
 * code found deep within TinyMUSH, with me own argument parser. 
 */
#ifdef EDIT
static int 
parse_attrib(player, s, thing, atr)
  int             player;
  char           *s;
  int            *thing;
  int            *atr;
{
  char            buff[1024];

  strcpy(buff, s);
  /* get name up to / */
  for (s = buff; *s && (*s != '/'); s++);
  if (!*s)
    return (0);
  *s++ = 0;
  if ((*thing = resolve_anything(player, buff, iswiz(player))) == -1)
    return (0);
  if (*thing == -2)
    return (-2);
  if (!exists_object(*thing) || !controls(player, *thing))
    return (0);
  /* rest is attrib name */

  if (stringprefix(s, "description"))
  {
    *atr = DESC;
  } else
  if (stringprefix(s, "success"))
  {
    *atr = SUC;
  } else
  if (stringprefix(s, "osuccess"))
  {
    *atr = OSUC;
  } else
  if (stringprefix(s, "fail"))
  {
    *atr = FAIL;
  } else
  if (stringprefix(s, "ofail"))
  {
    *atr = OFAIL;
#ifdef DROP_FIELDS
  } else
  if (stringprefix(s, "drop"))
  {
    *atr = DROP;
  } else
  if (stringprefix(s, "odrop"))
  {
    *atr = ODROP;
#endif				/* DROP_FIELDS */
  } else
  if (stringprefix(s, "gender") || stringprefix(s, "sex"))
  {
    *atr = GENDER;
  } else
  if (stringprefix(s, "name"))
  {
    *atr = NAME;
  } else
    *atr = 0;

  if (*atr == 0)
    return (0);
  if (((*atr == GENDER) && !isplayer(*thing)) ||
      ((*atr == NAME) && isplayer(*thing)))
    return (-1);

  return (1);
}

voidfunc 
do_edit(player, it, args)
  int             player;
  char           *it;
  char           *args;
{
  int             thing;
  int             atr, d, len;
  char           *r, *s, *val;
  char            dest[1024], arg1[BUFFSIZ], arg2[BUFFSIZ];

  if(!it || !*it)
  {
    notify_player(player, "Edit what?\r\n");
    return;
  }
  d = parse_attrib(player, it, &thing, &atr);
  if (d == 0)
  {
    notify_player(player, "No match.\r\n");
    return;
  } else
  if (d == -2)
  {
    notify_player(player, "I can't tell which one you want to edit.\r\n");
    return;
  } else
  if (d != 1)
  {
    notify_player(player,
		  "Permission denied.  You can't change that attribute on that object.\r\n");
    return;
  }
  /* parse arguments */
  if (!args || !*args)
  {
    notify_player(player, "Nothing to do.\r\n");
    return;
  }

  d = 0;
  /* make arg1 */
  /* eat this pointer game, xibo  ;-) */
  /* Thanks, it was delicious. */
  while(d < (BUFFSIZ - 32) && args[0] != 0){
    if(args[0] != ',' && args[0] != '\\'){
      arg1[d] = *args++;
      d++;
    } else {
      if(args[0] == '\\' && args[1] != ','){
        arg1[d] = *args++;
      d++;
      } else {
        if(args[0] == '\\' && args[1] == ','){
        arg1[d] = args[1];
        args += 2;
        d++;
      } else {
        arg1[d] = 0;
        d++; args++;
        break;
      }
      }
    }
  }
  arg1[d] = 0;
  /* make arg2 */
  d = 0;
  while(d < (BUFFSIZ - 32) && args[d] != 0){
    arg2[d] = args[d];
    d++;
  }
  arg2[d] = 0;

  if (arg1[0] == 0)
  {
    notify_player(player, "Nothing to do.\r\n");
    return;
  }

  val = arg1;
  r = (arg2[0]) ? arg2 : (char *) "";

  /* replace all occurances of val with r */
  if (get_str_elt(thing, atr, &s) == -1)
  {
    warning("do_edit", "bad object ref");
    notify_bad(player);
    return;
  }
  if (!s || !*s)
  {
    notify_player(player, "Nothing to do.\r\n");
    return;
  }

  len = strlen(val);
  for (d = 0; (d < 1000) && *s;)
    if (strncmp(val, s, len) == 0)
    {
      if ((d + strlen(r)) < 1000)
      {
	strcpy(dest + d, r);
	d += strlen(r);
	s += len;
      } else
	dest[d++] = *s++;
    } else
      dest[d++] = *s++;
  dest[d++] = 0;

  dest[BUFFSIZ - 1] = '\0';
  if (set_str_elt(thing, atr, dest) == -1)
  {
    warning("do_edit", "failed to store revised string");
    notify_bad(player);
    return;
  }
  switch (atr)
  {
  case DESC:
    notify_player(player, "Description set.\r\n");
    break;
  case GENDER:
    notify_player(player, "Gender set.\r\n");
    break;
  case NAME:
    notify_player(player, "Name set.\r\n");
    break;
  default:
    notify_player(player, "Message set.\r\n");
  }
#ifdef TIMESTAMPS
  if (!isplayer(thing))
  {
    stamp(thing);
  }
#endif				/* TIMESTAMPS */
}

#endif				/* EDIT */