circle30bpl20/bin/
circle30bpl20/cnf/
circle30bpl20/lib/
circle30bpl20/lib/etc/
circle30bpl20/lib/house/
circle30bpl20/lib/misc/
circle30bpl20/lib/plralias/A-E/
circle30bpl20/lib/plralias/F-J/
circle30bpl20/lib/plralias/K-O/
circle30bpl20/lib/plralias/P-T/
circle30bpl20/lib/plralias/U-Z/
circle30bpl20/lib/plralias/ZZZ/
circle30bpl20/lib/plrobjs/
circle30bpl20/lib/plrobjs/A-E/
circle30bpl20/lib/plrobjs/F-J/
circle30bpl20/lib/plrobjs/K-O/
circle30bpl20/lib/plrobjs/P-T/
circle30bpl20/lib/plrobjs/U-Z/
circle30bpl20/lib/plrobjs/ZZZ/
circle30bpl20/lib/text/
circle30bpl20/lib/text/help/
circle30bpl20/lib/world/
circle30bpl20/lib/world/shp/
circle30bpl20/log/
circle30bpl20/src/doc/
/* ************************************************************************
*   File: olc.c                                         Part of CircleMUD *
*  Usage: online creation                                                 *
*                                                                         *
*  All rights reserved.  See license.doc for complete information.        *
*                                                                         *
*  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
*  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
************************************************************************ */

/*
 * PLEASE, FOR THE LOVE OF GOD, DON'T TRY TO USE THIS YET!!!
 *  *** DO *** NOT *** SEND ME MAIL ASKING WHY IT DOESN'T WORK -- IT'S
 *  NOT DONE!!
 */

#include "conf.h"
#include "sysdep.h"

#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "interpreter.h"
#include "handler.h"
#include "db.h"
#include "olc.h"

/* OLC command format:
 *
 * olc {"." | {<"room"|"mobile"|"object"> <number>}} <arguments>
 * olc {"set"|"show"} <attribute> <arguments>
 */

#define OLC_USAGE "Usage: olc { . | set | show | obj | mob | room} [args]\r\n"

/* local globals */
struct char_data *olc_ch;

/* local functions */
void olc_interpreter(void *targ, int mode, char *arg);
void olc_set_show(struct char_data *ch, int olc_mode, char *arg);
void olc_string(char **string, size_t maxlen, char *arg);
int can_modify(struct char_data *ch, int vnum);
ACMD(do_olc);
void olc_bitvector(int *bv, const char **names, char *arg);

const char *olc_modes[] = {
  "set",			/* set OLC characteristics */
  "show",			/* show OLC characteristics */
  ".",				/* repeat last modification command */
  "room",			/* modify a room */
  "mobile",			/* modify a mobile */
  "object",			/* modify an object */
  "\n"
};

const char *olc_commands[] = {
  "copy",
  "name",
  "description",
  "aliases",
  "\n",				/* many more to be added */
};


/* The actual do_olc command for the interpreter.  Determines the target
   entity, checks permissions, and passes control to olc_interpreter */
ACMD(do_olc)
{
  void *olc_targ = NULL;
  char mode_arg[MAX_INPUT_LENGTH];
  room_rnum rnum;
  room_vnum vnum = NOWHERE;
  int olc_mode;

  /* WARNING!  **DO NOT** under any circumstances remove the code below!!!!  */
  if (strcmp(GET_NAME(ch), "Ras")) {
    send_to_char("OLC is not yet complete.  Sorry.\r\n", ch);
    return;
  }
  /* WARNING!  **DO NOT** under any circumstances remove the code above!!!!  */

  /* first, figure out the first (mode) argument */
  half_chop(argument, mode_arg, argument);
  if ((olc_mode = search_block(mode_arg, olc_modes, FALSE)) < 0) {
    sprintf(buf, "Invalid mode '%s'.\r\n", mode_arg);
    send_to_char(buf, ch);
    send_to_char(OLC_USAGE, ch);
    return;
  }
  switch (olc_mode) {
  case OLC_SET:
  case OLC_SHOW:
    olc_set_show(ch, olc_mode, argument);
    return;
  case OLC_REPEAT:
    if (!(olc_mode = GET_LAST_OLC_MODE(ch)) ||
	((olc_targ = GET_LAST_OLC_TARG(ch)) == NULL)) {
      send_to_char("No last OLC operation!\r\n", ch);
      return;
    }
    break;
  case OLC_ROOM:
    if (isdigit(*argument)) {
      /* room specified.  take the numeric argument off */
      argument = one_argument(argument, arg);
      if (!is_number(arg)) {
	sprintf(buf, "Invalid room vnum '%s'.\r\n", arg);
	send_to_char(buf, ch);
	return;
      }
      vnum = atoi(arg);
      if ((rnum = real_room(vnum)) == NOWHERE) {
	send_to_char("No such room!\r\n", ch);
	return;
      }
    } else {
      rnum = IN_ROOM(ch);
      vnum = GET_ROOM_VNUM(IN_ROOM(ch));
      sprintf(buf, "(Using current room %d)\r\n", vnum);
      send_to_char(buf, ch);
    }

/*   if (!ROOM_FLAGGED(rnum, ROOM_OLC))
	 send_to_char("That room is not modifyable.\r\n", ch);
     else
*/
    olc_targ = (void *) &(world[rnum]);
    break;
  case OLC_MOB:
    argument = one_argument(argument, arg);
    if (!is_number(arg)) {
      sprintf(buf, "Invalid mob vnum '%s'.\r\n", arg);
      send_to_char(buf, ch);
      return;
    }
    vnum = atoi(arg);
    if ((rnum = real_mobile(vnum)) == NOBODY)
      send_to_char("No such mobile vnum.\r\n", ch);
    else
      olc_targ = (void *) &(mob_proto[rnum]);
    break;
  case OLC_OBJ:
    argument = one_argument(argument, arg);
    if (!is_number(arg)) {
      sprintf(buf, "Invalid obj vnum '%s'\r\n", arg);
      send_to_char(buf, ch);
      return;
    }
    vnum = atoi(arg);
    if ((rnum = real_object(vnum)) == NOTHING) {
      sprintf(buf, "No object with vnum %d.\r\n", vnum);
      send_to_char(buf, ch);
    } else
      olc_targ = (void *) &(obj_proto[rnum]);
    break;
  default:
    send_to_char("Usage: olc {.|set|show|obj|mob|room} [args]\r\n", ch);
    return;
  }

  if (olc_targ == NULL)
    return;

  if (!can_modify(ch, vnum)) {
    send_to_char("You can't modify that.\r\n", ch);
    return;
  }
  GET_LAST_OLC_MODE(ch) = olc_mode;
  GET_LAST_OLC_TARG(ch) = olc_targ;

  olc_ch = ch;
  olc_interpreter(olc_targ, olc_mode, argument);
  /* freshen? */
}


/* OLC interpreter command; called by do_olc */
void olc_interpreter(void *targ, int mode, char *arg)
{
  int error = 0, command;
  char command_string[MAX_INPUT_LENGTH];
  struct char_data *olc_mob = NULL;
  struct room_data *olc_room = NULL;
  struct obj_data *olc_obj = NULL;

  half_chop(arg, command_string, arg);
  if ((command = search_block(command_string, olc_commands, FALSE)) < 0) {
    sprintf(buf, "Invalid OLC command '%s'.\r\n", command_string);
    send_to_char(buf, olc_ch);
    return;
  }
  switch (mode) {
  case OLC_ROOM:
    olc_room = (struct room_data *) targ;
    break;
  case OLC_MOB:
    olc_mob = (struct char_data *) targ;
    break;
  case OLC_OBJ:
    olc_obj = (struct obj_data *) targ;
    break;
  default:
    log("SYSERR: Invalid OLC mode %d passed to interp.", mode);
    return;
  }


  switch (command) {
  case OLC_COPY:
    switch (mode) {
    case OLC_ROOM:
      break;
    case OLC_MOB:
      break;
    case OLC_OBJ:
      break;
    default:
      error = 1;
      break;
    }
    break;
  case OLC_NAME:
    switch (mode) {
    case OLC_ROOM:
      olc_string(&(olc_room->name), MAX_ROOM_NAME, arg);
      break;
    case OLC_MOB:
      olc_string(&olc_mob->player.short_descr, MAX_MOB_NAME, arg);
      break;
    case OLC_OBJ:
      olc_string(&olc_obj->short_description, MAX_OBJ_NAME, arg);
      break;
    default:
      error = 1;
      break;
    }
    break;

  case OLC_DESC:
    switch (mode) {
    case OLC_ROOM:
      olc_string(&olc_room->description, MAX_ROOM_DESC, arg);
      break;
    case OLC_MOB:
      olc_string(&olc_mob->player.long_descr, MAX_MOB_DESC, arg);
      break;
    case OLC_OBJ:
      olc_string(&olc_obj->description, MAX_OBJ_DESC, arg);
      break;
    default:
      error = 1;
      break;
    }
    break;

  case OLC_ALIASES:
    switch (mode) {
    case OLC_ROOM:
      break;
    case OLC_MOB:
      break;
    case OLC_OBJ:
      break;
    default:
      error = 1;
      break;
    }

  }
}


/* can_modify: determine if a particular char can modify a vnum */
int can_modify(struct char_data *ch, int vnum)
{
  return (1);
}


/* generic fn for modifying a string */
void olc_string(char **string, size_t maxlen, char *arg)
{
  skip_spaces(&arg);

  if (!*arg) {
    sprintf(buf, "Enter new string (max of %u characters); "
	    "use '@' on a new line when done.\r\n", maxlen);
    send_to_char(buf, olc_ch);
    **string = '\0';
    string_write(olc_ch->desc, string, maxlen, 0, NULL);
  } else {
    if (strlen(arg) > maxlen) {
      sprintf(buf, "String too long (cannot be more than %u chars).\r\n",
	      maxlen);
      send_to_char(buf, olc_ch);
    } else {
      if (*string != NULL)
	free(*string);
      *string = str_dup(arg);
      send_to_char(OK, olc_ch);
    }
  }
}


/* generic fn for modifying a bitvector */
void olc_bitvector(int *bv, const char **names, char *arg)
{
  int newbv, flagnum, remove = 0;
  char *this_name;

  skip_spaces(&arg);

  if (!*arg) {
    send_to_char("Flag list or flag modifiers required.\r\n", olc_ch);
    return;
  }
  /* determine if this is 'absolute' or 'relative' mode */
  if (*arg == '+' || *arg == '-')
    newbv = *bv;
  else
    newbv = 0;

  while (*arg) {
    arg = one_argument(arg, buf);	/* get next argument */

    /* change to upper-case */
    for (this_name = buf; *this_name; this_name++)
      CAP(this_name);

    /* determine if this is an add or a subtract */
    if (*buf == '+' || *buf == '-') {
      this_name = buf + 1;
      if (*buf == '-')
	remove = TRUE;
      else
	remove = FALSE;
    } else {
      this_name = buf;
      remove = FALSE;
    }

    /* figure out which one we're dealing with */
    if ((flagnum = search_block(this_name, names, TRUE)) < 0) {
      sprintf(buf2, "Unknown flag: %s\r\n", this_name);
      send_to_char(buf2, olc_ch);
    } else {
      if (remove)
	REMOVE_BIT(newbv, (1 << flagnum));
      else
	SET_BIT(newbv, (1 << flagnum));
    }
  }

  *bv = newbv;
  sprintbit(newbv, names, buf);
  sprintf(buf2, "Flags now set to: %s\r\n", buf);
  send_to_char(buf2, olc_ch);
}

void olc_set_show(struct char_data *ch, int olc_mode, char *arg)
{
}