/
rogue24b3/
rogue24b3/data/
/***************************************************************************
 *  File: olc.c                                                            *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 *                                                                         *
 *  This code was freely distributed with the The Isles 1.1 source code,   *
 *  and has been used here for OLC - OLC would not be what it is without   *
 *  all the previous coders who released their source code.                *
 *                                                                         *
 ***************************************************************************/

#include "merc.h"
#include "interp.h"
#include "recycle.h"
#include "tables.h"
#include "olc.h"
#include "staffcmds.h"

/*
 * Local functions.
 */
AREA_DATA *get_area_data	args( ( int vnum ) );
bool SOCIAL_CHANGED = FALSE;

/* Executed from comm.c.  Minimizes compiling when changes are made. */
bool run_olc_editor( DESCRIPTOR_DATA *d )
{
    switch ( d->editor )
    {
    case ED_GUILD:
        gedit( d->character, d->incomm );
        break;
    case ED_AREA:
	aedit( d->character, d->incomm );
	break;
    case ED_ROOM:
	redit( d->character, d->incomm );
	break;
    case ED_OBJECT:
	oedit( d->character, d->incomm );
	break;
    case ED_MOBILE:
	medit( d->character, d->incomm );
	break;
    case ED_MPCODE:
    	mpedit( d->character, d->incomm );
        break;
    case ED_HELP:
        hedit( d->character, d->incomm );
        break;
    case ED_SOCIAL:
	sedit( d->character, d->incomm );
	break;
    default:
	return FALSE;
    }
    return TRUE;
}



char *olc_ed_name( CHAR_DATA *ch )
{
    static char buf[10];
    
    buf[0] = '\0';
    switch (ch->desc->editor)
    {
    case ED_AREA:
	sprintf( buf, "AEdit" );
	break;
    case ED_ROOM:
	sprintf( buf, "REdit" );
	break;
    case ED_OBJECT:
	sprintf( buf, "OEdit" );
	break;
    case ED_MOBILE:
	sprintf( buf, "MEdit" );
	break;
    case ED_MPCODE:
    	sprintf( buf, "MPEdit" );
	break;
    case ED_HELP:
        sprintf( buf, "HEdit" );
        break;
    case ED_GUILD:
	sprintf( buf, "GEdit" );
	break;
    case ED_SOCIAL:
	sprintf( buf, "SEdit" );
	break;
    default:
	sprintf( buf, " " );
	break;
    }
    return buf;
}

char *olc_ed_desc( CHAR_DATA *ch )
{
    static char buf[256];

    buf[0] = '\0';
    switch (ch->desc->editor)
    {
	case ED_SOCIAL: {
		SOCIAL_DATA *pSocial;
		pSocial = (SOCIAL_DATA *)ch->desc->pEdit;
		sprintf(buf, "%s", pSocial->name);
		break;
	}
	case ED_HELP: {
		HELP_DATA *pHelp;
		pHelp = (HELP_DATA *)ch->desc->pEdit;
		sprintf(buf, "%s", pHelp->keyword);
		break;
	}
	case ED_GUILD: {
		CLAN_DATA *pClan;
		pClan = (CLAN_DATA *)ch->desc->pEdit;
		sprintf(buf, "%s", pClan->who_name);
		break;
	}
	case ED_AREA: {
		AREA_DATA *pArea;
		pArea = (AREA_DATA *)ch->desc->pEdit;
		sprintf(buf, "%s", pArea->name);
		break;
	}
	case ED_ROOM: {
		ROOM_INDEX_DATA *pRoom;
		pRoom = IN_ROOM(ch);
		sprintf(buf, "%s", pRoom->name);
		break;
	}
	case ED_OBJECT: {
		OBJ_INDEX_DATA *pObj;
		pObj = (OBJ_INDEX_DATA *)ch->desc->pEdit;
		sprintf(buf, "%s", pObj->short_descr);
		break;
	}
	case ED_MOBILE: {
		MOB_INDEX_DATA *pMob;
		pMob = (MOB_INDEX_DATA *)ch->desc->pEdit;
		sprintf(buf, "%s", pMob->short_descr);
		break;
	}
	case ED_MPCODE: {
		MPROG_CODE *pMprog;
		pMprog = (MPROG_CODE *)ch->desc->pEdit;
		sprintf(buf, "%s", pMprog->name);
		break;
	}
	case ED_RACE: {
		RACE_DATA *pRace = (RACE_DATA *)ch->desc->pEdit;
		sprintf(buf, "%s", pRace->name);
		break;
	}
	default:
		sprintf(buf, "ERROR");
		break;
    }
    return buf;
}

char *olc_ed_vnum( CHAR_DATA *ch )
{
    static char buf[10];
	
    buf[0] = '\0';
    switch (ch->desc->editor)
    {
    case ED_SOCIAL: {
	SOCIAL_DATA *pSocial;
	pSocial = (SOCIAL_DATA *)ch->desc->pEdit;
	sprintf(buf, "%d", social_lookup(pSocial->name));
	break;
    }
    case ED_HELP: {
	HELP_DATA *pHelp;
	pHelp = (HELP_DATA *)ch->desc->pEdit;
	sprintf(buf, "%d", pHelp->level);
	break;
    }
    case ED_GUILD: {
	CLAN_DATA *pClan;
	pClan = (CLAN_DATA *)ch->desc->pEdit;
	sprintf(buf, "%d", pClan ? pClan->vnum : 0);
	break;
    }
    case ED_AREA: {
	AREA_DATA *pArea;
	pArea = (AREA_DATA *)ch->desc->pEdit;
	sprintf(buf, "%d", pArea ? pArea->vnum : 0);
	break;
    }
    case ED_ROOM: {
	ROOM_INDEX_DATA *pRoom;
	pRoom = ch->in_room;
	sprintf(buf, "%d", pRoom ? pRoom->vnum : 0);
	break;
    }
    case ED_OBJECT: {
	OBJ_INDEX_DATA *pObj;
	pObj = (OBJ_INDEX_DATA *)ch->desc->pEdit;
	sprintf(buf, "%d", pObj ? pObj->vnum : 0);
	break;
    }
    case ED_MOBILE: {
	MOB_INDEX_DATA *pMob;
	pMob = (MOB_INDEX_DATA *)ch->desc->pEdit;
	sprintf(buf, "%d", pMob ? pMob->vnum : 0);
	break;
    }
    case ED_MPCODE: {
	MPROG_CODE *pMprog;
    	pMprog = (MPROG_CODE *)ch->desc->pEdit;
    	sprintf(buf, "%d", pMprog ? pMprog->vnum : 0);
	break;
    }
    case ED_RACE: {
	RACE_DATA *pRace = (RACE_DATA *)ch->desc->pEdit;
	sprintf(buf, "%d", race_lookup(pRace->name));
	break;
    }
    default:
	sprintf(buf, " ");
	break;
    }

    return buf;
}



/*****************************************************************************
 Name:		show_olc_cmds
 Purpose:	Format up the commands from given table.
 Called by:	show_commands(olc_act.c).
 ****************************************************************************/
void show_olc_cmds( CHAR_DATA *ch, const struct olc_cmd_type *olc_table )
{
    char buf  [ MAX_STRING_LENGTH ];
    char buf1 [ MAX_STRING_LENGTH ];
    int  cmd;
    int  col;
 
    buf1[0] = '\0';
    col = 0;
    for (cmd = 0; olc_table[cmd].name != NULL; cmd++)
    {
	sprintf( buf, "%-15.15s", olc_table[cmd].name );
	strcat( buf1, buf );
	if ( ++col % 5 == 0 )
	    strcat( buf1, "\n\r" );
    }
 
    if ( col % 5 != 0 )
	strcat( buf1, "\n\r" );

    send_to_char( buf1, ch );
    return;
}



/*****************************************************************************
 Name:		show_commands
 Purpose:	Display all olc commands.
 Called by:	olc interpreters.
 ****************************************************************************/
bool show_commands( CHAR_DATA *ch, char *argument )
{
    switch (ch->desc->editor)
    {
        case ED_GUILD:
            show_olc_cmds( ch, gedit_table );
            break;
	case ED_AREA:
	    show_olc_cmds( ch, aedit_table );
	    break;
	case ED_ROOM:
	    show_olc_cmds( ch, redit_table );
	    break;
	case ED_OBJECT:
	    show_olc_cmds( ch, oedit_table );
	    break;
	case ED_MOBILE:
	    show_olc_cmds( ch, medit_table );
	    break;
	case ED_MPCODE:
	    show_olc_cmds( ch, mpedit_table );
            break;
	case ED_HELP:
	    show_olc_cmds( ch, hedit_table );
	    break;
	case ED_SOCIAL:
	    show_olc_cmds( ch, sedit_table );
	    break;
    }

    return FALSE;
}



/*****************************************************************************
 *                           Interpreter Tables.                             *
 *****************************************************************************/
/* Guild edit command table */
const struct olc_cmd_type gedit_table[] =
{
    {   "commands",	show_commands   },
    {   "create",	gedit_create	},
    {   "flag",		gedit_flags	},
    {   "list",		gedit_list	},
    {   "ml",           gedit_ml        },
    {   "name",		gedit_name	},
    {   "whoname",	gedit_whoname	},
    {   "rank",		gedit_rank	},
    {	"recall",	gedit_recall	},
    {	"morgue",	gedit_morgue	},
    {   "show",		gedit_show	},
    {   "?",		show_help	},
    {   NULL,		0		}
};

const struct olc_cmd_type aedit_table[] =
{
/*  {   command		function	}, */
    {   "age",		aedit_age	},
    {   "builder",	aedit_builder	},
    {   "commands",	show_commands	},
    {   "create",	aedit_create	},
    {   "filename",	aedit_file	},
    {   "name",		aedit_name	},
    {	"reset",	aedit_reset	},
    {   "security",	aedit_security	},
    {	"show",		aedit_show	},
    {   "vnum",		aedit_vnum	},
    {   "lvnum",	aedit_lvnum	},
    {   "uvnum",	aedit_uvnum	},
    {   "theme",	aedit_theme	},
    {   "?",		show_help	},
    {   "version",	show_version	},
    {	NULL,		0,		}
};



const struct olc_cmd_type redit_table[] =
{
/*  {   command		function	}, */
    {   "commands",	show_commands	},
    {   "create",	redit_create	},
    {   "desc",		redit_desc	},
    {   "ed",		redit_ed	},
    {   "format",	redit_format	},
    {   "name",		redit_name	},
    {	"show",		redit_show	},
    {   "heal",		redit_heal	},
    {	"mana",		redit_mana	},
    {   "clan",		redit_clan	},
    {   "copy",		redit_copy	},
    {   "north",	redit_north	},
    {   "south",	redit_south	},
    {   "east",		redit_east	},
    {   "west",		redit_west	},
    {   "up",		redit_up	},
    {   "down",		redit_down	},

    /* New reset commands. */
    {	"mreset",	redit_mreset	},
    {	"oreset",	redit_oreset	},
    {	"mshow",	redit_mshow	},
    {	"oshow",	redit_oshow	},
    {   "owner",	redit_owner	},
    {	"room",		redit_room	},
    {	"sector",	redit_sector	},
    {   "image",	redit_image	},

    {   "?",		show_help	},
    {   "version",	show_version	},
    {	NULL,		0,		}
};



const struct olc_cmd_type oedit_table[] =
{
/*  {   command		function	}, */
    {   "addaffect",	oedit_addaffect	},
    {	"addapply",	oedit_addapply	},
    {   "commands",	show_commands	},
    {   "cost",		oedit_cost	},
    {   "create",	oedit_create	},
    {   "delaffect",	oedit_delaffect	},
    {   "ed",		oedit_ed	},
    {   "long",		oedit_long	},
    {   "name",		oedit_name	},
    {   "short",	oedit_short	},
    {	"show",		oedit_show	},
    {   "v0",		oedit_value0	},
    {   "v1",		oedit_value1	},
    {   "v2",		oedit_value2	},
    {   "v3",		oedit_value3	},
    {   "v4",		oedit_value4	},  /* ROM */
    {   "weight",	oedit_weight	},
    {   "extra",        oedit_extra     },  /* ROM */
    {   "wear",         oedit_wear      },  /* ROM */
    {   "type",         oedit_type      },  /* ROM */
    {   "material",     oedit_material  },  /* ROM */
    {   "level",        oedit_level     },  /* ROM */
    {   "condition",    oedit_condition },  /* ROM */
    {   "copy",		oedit_copy	},
    {	"autoweapon",	oedit_autoweapon },
    {	"autoarmor",	oedit_autoarmor	},
    {   "ndesc",	oedit_notedesc	},
    {   "?",		show_help	},
    {   "version",	show_version	},

    {	NULL,		0,		}
};



const struct olc_cmd_type medit_table[] =
{
/*  {   command		function	}, */
    {   "alignment",	medit_align	},
    {   "commands",	show_commands	},
    {   "create",	medit_create	},
    {   "desc",		medit_desc	},
    {   "level",	medit_level	},
    {   "long",		medit_long	},
    {   "name",		medit_name	},
    {   "shop",		medit_shop	},
    {   "short",	medit_short	},
    {	"show",		medit_show	},
    {   "spec",		medit_spec	},
    {   "copy",		medit_copy	},
    {   "sex",          medit_sex       },  /* ROM */
    {   "act",          medit_act       },  /* ROM */
    {   "affect",       medit_affect    },  /* ROM */
    {   "armor",        medit_ac        },  /* ROM */
    {   "form",         medit_form      },  /* ROM */
    {   "part",         medit_part      },  /* ROM */
    {   "imm",          medit_imm       },  /* ROM */
    {   "res",          medit_res       },  /* ROM */
    {   "vuln",         medit_vuln      },  /* ROM */
    {   "material",     medit_material  },  /* ROM */
    {   "off",          medit_off       },  /* ROM */
    {   "size",         medit_size      },  /* ROM */
    {   "hitdice",      medit_hitdice   },  /* ROM */
    {   "manadice",     medit_manadice  },  /* ROM */
    {   "damdice",      medit_damdice   },  /* ROM */
    {   "race",         medit_race      },  /* ROM */
    {   "position",     medit_position  },  /* ROM */
    {   "wealth",       medit_gold      },  /* ROM */
    {   "hitroll",      medit_hitroll   },  /* ROM */
    {	"damtype",	medit_damtype	},  /* ROM */
    {   "group",	medit_group	},  /* ROM */
    {   "addmprog",	medit_addmprog  },  /* ROM */
    {	"delmprog",	medit_delmprog	},  /* ROM */
    {	"autoset",	medit_autoset	},
    {	"autohard",	medit_autohard	},
    {	"autoeasy",	medit_autoeasy	},
    {   "?",		show_help	},
    {   "version",	show_version	},

    {	NULL,		0,		}
};

/* Social Editor - Mendanbar */
const struct olc_cmd_type sedit_table[] =
{
    { "commands",	show_commands	},
    { "cnoarg",		sedit_cnoarg	},
    { "onoarg",		sedit_onoarg	},
    { "cfound",		sedit_cfound	},
    { "ofound",		sedit_ofound	},
    { "vfound",		sedit_vfound	},
    { "cself",		sedit_cself	},
    { "oself",		sedit_oself	},
    { "cobj",		sedit_cobj	},
    { "oobj",		sedit_oobj	},
    { "position",	sedit_position	},
    { "create",		sedit_create	},
    { "delete",		sedit_delete	},
    { "show",		sedit_show	},
    { "?",		show_help	},
    { NULL,		0,		}
};

/* Help Editor - kermit 1/98 */
const struct olc_cmd_type hedit_table[] =
{
    { "commands",	show_commands	},
    { "desc",		hedit_desc	},
    { "keywords",	hedit_keywords	},
    { "level",		hedit_level	},
    { "create",		hedit_create	},
    { "copy",		hedit_copy	},
    { "delete",		hedit_delete	},
    { "show",		hedit_show	},
    { "?",		show_help	},
    { NULL,		0,		}
};

/*****************************************************************************
 *                          End Interpreter Tables.                          *
 *****************************************************************************/


CLAN_DATA *get_clan_data( int clan )
{
  if (clan <= MAX_CLAN && 
       (clan_table[clan].name != NULL && clan_table[clan].name[0] != '\0'))
    return &clan_table[clan];

  return &clan_table[0]; /* null clan */
}

/*****************************************************************************
 Name:		get_area_data
 Purpose:	Returns pointer to area with given vnum.
 Called by:	do_aedit(olc.c).
 ****************************************************************************/
AREA_DATA *get_area_data( int vnum )
{
    AREA_DATA *pArea;

    for (pArea = area_first; pArea; pArea = pArea->next )
    {
        if (pArea->vnum == vnum)
            return pArea;
    }

    return 0;
}



/*****************************************************************************
 Name:		edit_done
 Purpose:	Resets builder information on completion.
 Called by:	aedit, redit, oedit, medit(olc.c)
 ****************************************************************************/
bool edit_done( CHAR_DATA *ch )
{
    ch->desc->pEdit = NULL;
    ch->desc->editor = 0;
    return FALSE;
}



/*****************************************************************************
 *                              Interpreters.                                *
 *****************************************************************************/
/** Function: gedit
  * Descr   : Interprets commands sent while inside the guild editor.
  *         : Passing appropriate commands on to editor, rest to mud.
  * Returns : (N/A)
  * Syntax  : (N/A| called by do_gedit only)
  * Written : v1.0 3/98
  * Author  : Gary McNickle <gary@dharvest.com>
  */
void gedit( CHAR_DATA *ch, char *argument )
{
  CLAN_DATA *pClan;
  char command[MIL];
  char arg[MIL];
  
  int cmd;
  
  EDIT_GUILD(ch, pClan);
  smash_tilde( argument );
  strcpy( arg, argument );
  argument = one_argument( argument, command );
  
  if (!STF_FLAGGED(ch, STAFF_CLANS))
  {
    send_to_char("Insuffecient security to modify guild data", ch);
    edit_done( ch );
    return;
  }

  if ( !str_cmp(command, "done") )
  {
    edit_done( ch );
    return;
  }

  if ( command[0] == '\0' )
  {
    gedit_show( ch, argument );
    return;
  }
  
  /* Search Table and Dispatch Command. */
  for ( cmd = 0; gedit_table[cmd].name != NULL; cmd++ )
  {
    if ( !str_prefix( command, gedit_table[cmd].name ) )
    {
      if ( (*gedit_table[cmd].olc_fun) ( ch, argument ) )
      {
	SET_BIT( pClan->flags, GUILD_CHANGED );
	return;
      }
      else
       return;
    }
  }

  /* Default to Standard Interpreter. */
  interpret( ch, arg );
  return;
}

/* Area Interpreter, called by do_aedit. */
void aedit( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char command[MAX_INPUT_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    int  cmd;
    int  value;

    EDIT_AREA(ch, pArea);
    smash_tilde( argument );
    strcpy( arg, argument );
    argument = one_argument( argument, command );

    if ( !IS_BUILDER( ch, pArea ) )
    {
	send_to_char( "AEdit:  Insufficient security to modify area.\n\r", ch );
	edit_done( ch );
	return;
    }

    if ( !str_cmp(command, "done") )
    {
	edit_done( ch );
	return;
    }

    if ( command[0] == '\0' )
    {
	aedit_show( ch, argument );
	return;
    }

    if ( ( value = flag_value( area_flags, command ) ) != NO_FLAG )
    {
	TOGGLE_BIT(pArea->area_flags, value);
	SET_BIT(AREA_FLAGS(pArea), AREA_CHANGED);
	send_to_char( "Flag toggled.\n\r", ch );
	return;
    }

    /* Search Table and Dispatch Command. */
    for ( cmd = 0; aedit_table[cmd].name != NULL; cmd++ )
    {
	if ( !str_prefix( command, aedit_table[cmd].name ) )
	{
	    if ( (*aedit_table[cmd].olc_fun) ( ch, argument ) )
	    {
		SET_BIT( pArea->area_flags, AREA_CHANGED );
		return;
	    }
	    else
		return;
	}
    }

    /* Default to Standard Interpreter. */
    interpret( ch, arg );
    return;
}



/* Room Interpreter, called by do_redit. */
void redit( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    ROOM_INDEX_DATA *pRoom;
    char arg[MAX_STRING_LENGTH];
    char command[MAX_INPUT_LENGTH];
    int  cmd;

    EDIT_ROOM(ch, pRoom);
    pArea = pRoom->area;

    smash_tilde( argument );
    strcpy( arg, argument );
    argument = one_argument( argument, command );

    if ( !IS_BUILDER( ch, pArea ) )
    {
        send_to_char( "REdit:  Insufficient security to modify room.\n\r", ch );
	edit_done( ch );
	return;
    }

    if ( !str_cmp(command, "done") )
    {
	edit_done( ch );
	return;
    }

    if ( command[0] == '\0' )
    {
	redit_show( ch, argument );
	return;
    }

    /* Search Table and Dispatch Command. */
    for ( cmd = 0; redit_table[cmd].name != NULL; cmd++ )
    {
	if ( !str_prefix( command, redit_table[cmd].name ) )
	{
	    if ( (*redit_table[cmd].olc_fun) ( ch, argument ) )
	    {
		SET_BIT( pArea->area_flags, AREA_CHANGED );
		return;
	    }
	    else
		return;
	}
    }

    /* Default to Standard Interpreter. */
    interpret( ch, arg );
    return;
}



/* Object Interpreter, called by do_oedit. */
void oedit( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    OBJ_INDEX_DATA *pObj;
    char arg[MAX_STRING_LENGTH];
    char command[MAX_INPUT_LENGTH];
    int  cmd;

    smash_tilde( argument );
    strcpy( arg, argument );
    argument = one_argument( argument, command );

    EDIT_OBJ(ch, pObj);
    pArea = pObj->area;

    if ( !IS_BUILDER( ch, pArea ) )
    {
	send_to_char( "OEdit: Insufficient security to modify area.\n\r", ch );
	edit_done( ch );
	return;
    }

    if ( !str_cmp(command, "done") )
    {
	edit_done( ch );
	return;
    }

    if ( command[0] == '\0' )
    {
	oedit_show( ch, argument );
	return;
    }

    /* Search Table and Dispatch Command. */
    for ( cmd = 0; oedit_table[cmd].name != NULL; cmd++ )
    {
	if ( !str_prefix( command, oedit_table[cmd].name ) )
	{
	    if ( (*oedit_table[cmd].olc_fun) ( ch, argument ) )
	    {
		SET_BIT( pArea->area_flags, AREA_CHANGED );
		return;
	    }
	    else
		return;
	}
    }

    /* Default to Standard Interpreter. */
    interpret( ch, arg );
    return;
}



/* Mobile Interpreter, called by do_medit. */
void medit( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    MOB_INDEX_DATA *pMob;
    char command[MAX_INPUT_LENGTH];
    char arg[MAX_STRING_LENGTH];
    int  cmd;

    smash_tilde( argument );
    strcpy( arg, argument );
    argument = one_argument( argument, command );

    EDIT_MOB(ch, pMob);
    pArea = pMob->area;

    if ( !IS_BUILDER( ch, pArea ) )
    {
	send_to_char( "MEdit: Insufficient security to modify area.\n\r", ch );
	edit_done( ch );
	return;
    }

    if ( !str_cmp(command, "done") )
    {
	edit_done( ch );
	return;
    }

    if ( command[0] == '\0' )
    {
        medit_show( ch, argument );
        return;
    }

    /* Search Table and Dispatch Command. */
    for ( cmd = 0; medit_table[cmd].name != NULL; cmd++ )
    {
	if ( !str_prefix( command, medit_table[cmd].name ) )
	{
	    if ( (*medit_table[cmd].olc_fun) ( ch, argument ) )
	    {
		SET_BIT( pArea->area_flags, AREA_CHANGED );
		return;
	    }
	    else
		return;
	}
    }

    /* Default to Standard Interpreter. */
    interpret( ch, arg );
    return;
}

/* Social Editor - Mendanbar */
void sedit(CHAR_DATA *ch, char *argument)
{
    int  cmd = 0;
    char arg[MAX_INPUT_LENGTH], command[MAX_INPUT_LENGTH];

    smash_tilde(argument);
    strcpy(arg, argument);
    argument = one_argument(argument, command);

    if (!STF_FLAGGED(ch, STAFF_SOCIALS)) {
	send_to_char("SEdit: Insufficient security to modify socials.\n\r", ch);
	edit_done(ch);
    }

    if (!str_cmp(command, "done")) {
	edit_done(ch);
	return;
    }

    if (command[0] == '\0') {
	sedit_show(ch, argument);
	return;
    }

    for (cmd = 0; sedit_table[cmd].name != NULL; cmd++) {
	if (!str_prefix(command, sedit_table[cmd].name)) {
		if ((*sedit_table[cmd].olc_fun) (ch, argument))
			SOCIAL_CHANGED = TRUE;
		return;
	}
    }
    interpret(ch, arg);
    return;
}

/* Help Editor - kermit 1/98 */
void hedit( CHAR_DATA *ch, char *argument)
{
    char command[MIL];
    char arg[MIL];
    int cmd;
    
    smash_tilde(argument);
    strcpy(arg, argument);
    argument = one_argument( argument, command);

    if (!STF_FLAGGED(ch, STAFF_HELP))
    {
        send_to_char("HEdit: Insufficient security to modify code\n\r",ch);
       edit_done(ch);
    }

    if ( !str_cmp(command, "done") )
    {
	edit_done( ch );
	return;
    }

    if ( command[0] == '\0' )
    {
        hedit_show( ch, argument );
	return;
    }

    for ( cmd = 0; hedit_table[cmd].name != NULL; cmd++ )
    {
	if ( !str_prefix( command, hedit_table[cmd].name ) )
	{
            (*hedit_table[cmd].olc_fun) ( ch, argument );
            return;
	}
    }

    interpret( ch, arg );
    return;    
}



const struct editor_cmd_type editor_table[] =
{
/*  {   command		function	}, */
    {   "guild",	do_gedit	},
    {   "area",		do_aedit	},
    {   "room",		do_redit	},
    {   "object",	do_oedit	},
    {   "mobile",	do_medit	},
    {	"mpcode",	do_mpedit	},
    {   "help",         do_hedit        },
    {	"social",	do_sedit	},
    {	NULL,		0,		}
};

char *path_to_area(CHAR_DATA *ch, AREA_DATA *pArea) {
    EXIT_DATA		*pexit, *pexit2;
    ROOM_INDEX_DATA	*pRoomIndex, *queueIn, *queueOut, *source;
    UInt32		iHash = 0, door, door2;
    const char *shortdir_name[] = {"n","e","s","w","u","d"};
    char buf[MAX_STRING_LENGTH], buf2[MAX_STRING_LENGTH];
    extern ROOM_INDEX_DATA *room_index_hash[MAX_KEY_HASH];

    if ((source = ch->in_room) == NULL)
	return "Not accessable.";

    if (!pArea) {
	mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: path_to_area passing invalid area");
	return "Ah this is an error.";
    }

    if (source->area == pArea)
	return "You are here.";

    for (iHash = 0; iHash < MAX_KEY_HASH; iHash++) {
	for (pRoomIndex = room_index_hash[iHash];
	pRoomIndex != NULL; pRoomIndex = pRoomIndex->next)
	{
		pRoomIndex->distance_from_source = 32765;
		pRoomIndex->shortest_from_room = NULL;
		pRoomIndex->shortest_next_room = NULL;
	}
    }
    source->distance_from_source = 0;
    queueIn = source;
    for (queueOut = source; queueOut; queueOut = queueOut->shortest_next_room)
    {
	    for (door = 0; door < MAX_DIR ; door++) {
		if ((pexit = queueOut->exit[door]) != NULL && pexit->u1.to_room != NULL) {
		    if (pexit->u1.to_room->distance_from_source > queueOut->distance_from_source + 1) {
			pexit->u1.to_room->distance_from_source = queueOut->distance_from_source + 1;
			if (pexit->u1.to_room->area == pArea) {
			    int count = 1;
			    char buf3[3];
			    sprintf(buf3,"%s",shortdir_name[door]);
			    sprintf(buf2,"%s",buf3);
			    for (pRoomIndex = queueOut; pRoomIndex->shortest_from_room; pRoomIndex = pRoomIndex->shortest_from_room) {
				for (door2 = 0; door2 < MAX_DIR ; door2++) {
				    if ((pexit2 = pRoomIndex->shortest_from_room->exit[door2]) != NULL
				    && pexit2->u1.to_room == pRoomIndex) {
					if (!str_cmp(shortdir_name[door2],buf3)) {
						count++;
					} else {
						sprintf(buf,"%s",buf2);
						if (count > 1) {
							sprintf(buf2,"%s%d%s",shortdir_name[door2],count,buf);
						} else {
							sprintf(buf2,"%s%s",shortdir_name[door2],buf);
						}
						count = 1;
						sprintf(buf3,"%s",shortdir_name[door2]);
					}
				    }
				}
			    }
			if (count > 1) {
			    sprintf(buf,"%s",buf2);
			    sprintf(buf2,"%d%s",count,buf);
			}
			sprintf(buf,"%s.", buf2);
			return str_dup(buf);
		    }
		    pexit->u1.to_room->shortest_from_room = queueOut;
		    queueIn->shortest_next_room = pexit->u1.to_room;
		    queueIn = pexit->u1.to_room;
                }
            }
        }
    }
    return "Not accessable.";
}

ACMD(do_path) {
    ROOM_INDEX_DATA	*pRoomIndex, *queueIn, *queueOut, *source,
			*destination = NULL;
    extern ROOM_INDEX_DATA *room_index_hash[MAX_KEY_HASH];
    extern ROOM_INDEX_DATA *find_location( CHAR_DATA *ch, char *arg );
    int iHash, door, door2, fArea = 0;
    AREA_DATA *pArea=NULL;
    EXIT_DATA *pexit, *pexit2;
    const char *shortdir_name[] = {"n","e","s","w","u","d"};
    char buf[MAX_STRING_LENGTH], buf2[MAX_STRING_LENGTH];

    //Use a breadth-first search to find shortest path.
    if ( argument[0] == '\0' ) {
	send_to_char( "Syntax: shortestpath <destination player, mob, or vnum>\n\r", ch );
	send_to_char( "        shortestpath area <area vnum>\n\r", ch );
	return;
    }
    //First, find source and destination rooms:
    if ( ( source = ch->in_room) == NULL ) {
	send_to_char( "You must be somewhere to go anywhere.\n\r", ch );
	return;
    }
    //Check if we're looking for area vnum
    if (!str_prefix("area ",argument ))  {
    	argument = one_argument(argument,buf); // strip "area" and discard buf
	if ( is_number( argument ) ) {
	    fArea = atoi( argument ); 
	    if ( !( pArea = get_area_data( fArea ) ) ) {
		send_to_char( "That area vnum does not exist.\n\r", ch );
		return;
	    }
	    fArea++; // since vnums start at 0 this makes it nonzero.
	}
    } else if ( ( destination = find_location( ch, argument ) ) == NULL ) {
	send_to_char( "No such destination.\n\r", ch );
	return;
    }
    if ( (fArea && source->area == pArea) || source == destination ) {
	send_to_char( "No need to walk to get there!\n\r", ch );
	return;
    }

    /* Initialize: set distance of every room to a very large number,
     * null links and queue */
    for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ ) {
	for ( pRoomIndex = room_index_hash[iHash];
	      pRoomIndex != NULL;
	      pRoomIndex = pRoomIndex->next ) {
	    pRoomIndex->distance_from_source = 32765;
	    pRoomIndex->shortest_from_room = NULL;
	    pRoomIndex->shortest_next_room = NULL;
	}
    }
    //Now set source distance to 0 and put it on the "search" queue
    source->distance_from_source = 0;
    queueIn = source;
    //Now, set distance for all adjacent rooms to search room + 1 until destination.
    //If destination not found, put each unsearched adjacent room on queue and repeat
    for ( queueOut = source; queueOut; queueOut = queueOut->shortest_next_room) {
    	//for each exit to search room:
	for ( door = 0; door < MAX_DIR ; door++ ) {
	    if ( ( pexit = queueOut->exit[door] ) != NULL
	        && pexit->u1.to_room != NULL ) {
	        //if we haven't looked here, set distance and add to search list
		if (pexit->u1.to_room->distance_from_source >
	            queueOut->distance_from_source + 1) {
		    pexit->u1.to_room->distance_from_source =
			queueOut->distance_from_source + 1;
		    //if we've found destination, we're done!
		    if ((fArea && pexit->u1.to_room->area == pArea) ||
		    	pexit->u1.to_room == destination) {
			int count = 1;
			char buf3[3];
			// print the directions in reverse order as we walk back
			sprintf(buf3,"%s",shortdir_name[door]);
			sprintf(buf2,"%s",buf3);
			for (pRoomIndex = queueOut ; pRoomIndex->shortest_from_room;
				pRoomIndex = pRoomIndex->shortest_from_room) {
			    for ( door2 = 0; door2 < MAX_DIR ; door2++ ) {
				if ( ( pexit2 = pRoomIndex->shortest_from_room->exit[door2] ) != NULL
	        			&& pexit2->u1.to_room == pRoomIndex ) {
				    if (!str_cmp(shortdir_name[door2],buf3)) {
					count++;
				    } else {
					sprintf(buf,"%s",buf2);
					if (count > 1) {
					sprintf(buf2,"%s, %d%s",shortdir_name[door2],count,buf);
					} else {
					sprintf(buf2,"%s, %s",shortdir_name[door2],buf);
					}
					count = 1;
					sprintf(buf3,"%s",shortdir_name[door2]);
				    }
				}
			    }
			}
			if (count > 1) {
			    sprintf(buf,"%s",buf2);
			    sprintf(buf2,"%d%s",count,buf);
			}
			if (fArea) {
			    sprintf(buf,"Shortest path to %s from %s is %d steps: %s.\n\r",
			    		pArea->name, source->name,
					pexit->u1.to_room->distance_from_source,buf2);
			} else {
			    sprintf(buf,"Shortest path is %d steps: %s.\n\r",
				pexit->u1.to_room->distance_from_source,buf2);
			}
			send_to_char( buf, ch );
			return;
		    }
		    //Didn't find destination, add to queue
		    pexit->u1.to_room->shortest_from_room = queueOut;
		    queueIn->shortest_next_room = pexit->u1.to_room;
		    queueIn = pexit->u1.to_room;		    
	        }
	    }
	}	
    }
    send_to_char( "No path to destination.\n\r", ch );
    return;
}

ACMD(do_olclist) {
    AREA_DATA *pArea;
    int count = 0;
    char buf[MAX_STRING_LENGTH];
    buf[0] = '\0';

    for (pArea = area_first; pArea; pArea = pArea->next) {
	if (IS_SET(pArea->area_flags, AREA_CHANGED)) {
		sprintf(buf+strlen(buf), "[%5d] %-24s- %s\r\n",
			pArea->vnum, pArea->name, pArea->file_name);
		count++;
	}
    }
    if (SOCIAL_CHANGED) {
	strcat(buf, " - Socials\n\r");
	count++;
    }
    if (!count)
	send_to_char("The database is up to date.\r\n", ch);
    else {
	send_to_char("The following Zones need saving:\r\n", ch);
	send_to_char(buf, ch);
    }
    return;
}

ACMD(do_olc_delete) {
    int  which;
    UInt32 iHash = 0;
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];

    argument = one_argument(argument, arg1);
    argument = one_argument(argument, arg2);

    if (arg1[0] == '\0' || arg2[0] == '\0' || (which = atoi(arg2)) <= 0) {
	send_to_char("Usage: delete mob|obj|room|trigger <vnum>\n\r", ch);
	return;
    }

    if (!str_prefix(arg1, "room")) {
	RESET_DATA *pReset;
	ROOM_INDEX_DATA *pRoom;
	ROOM_INDEX_DATA *pToRoom;
	UInt32 door = 0;

	if ((pRoom = get_room_index(which)) == NULL) {
		send_to_char("That room does not exist.\n\r", ch);
		return;
	}

	SET_BIT(ROOM_FLAGS(pRoom), ROOM_DELETED);
	SET_BIT(pRoom->area->area_flags, AREA_CHANGED);

	for (pReset = pRoom->reset_first; pReset; pReset = pReset->next) {
		free_reset_data(pReset);
	}
	pRoom->reset_first = NULL;
	pRoom->reset_last  = NULL;

	for (iHash = 0; iHash < MAX_KEY_HASH; iHash++) {
		for (pToRoom = room_index_hash[iHash];
		pToRoom != NULL;
		pToRoom = pToRoom->next)
		{
			for (door = 0; door <= MAX_DIR; door++) {
			if (pToRoom->exit[door] &&
			pToRoom->exit[door]->u1.to_room == pRoom) {
					free_exit(pToRoom->exit[door]);
					pToRoom->exit[door] = NULL;
					SET_BIT(pToRoom->area->area_flags, AREA_CHANGED);
				}
			}
		}
	}
	send_to_char("Room deleted.\n\r", ch);
	return;
    } else if (!str_prefix(arg1, "object")) {
	OBJ_INDEX_DATA *pObj;

	if ((pObj = get_obj_index(which)) == NULL) {
		send_to_char("That object does not exist.\n\r", ch);
		return;
	}

	SET_BIT(OBJ_FLAGS(pObj), ITEM_DELETED);
	SET_BIT(pObj->area->area_flags, AREA_CHANGED);
	send_to_char("Object deleted.\n\r", ch);
	return;
    } else if (!str_prefix(arg1, "mobile")) {
	MOB_INDEX_DATA *pMob;

	if ((pMob = get_mob_index(which)) == NULL) {
		send_to_char("That mobile does not exist.\n\r", ch);
		return;
	}

	SET_BIT(MOB_FLAGS(pMob), MOB_DELETED);
	SET_BIT(pMob->area->area_flags, AREA_CHANGED);

	send_to_char("Mobile deleted.\n\r", ch);
	return;
    } else if (!str_prefix(arg1, "trigger") || !str_prefix(arg1, "mprog")) {
	send_to_char("That function has not been created.\n\r", ch);
	return;
    } else {
	send_to_char("Usage: delete mob|obj|room|trigger <vnum>\n\r", ch);
    }
    return;
}

/* Entry point for all editors. */
ACMD(do_olc) {
    char command[MAX_INPUT_LENGTH];
    int  cmd;

    if ( IS_NPC(ch) )
    	return;

    argument = one_argument( argument, command );

    if ( command[0] == '\0' )
    {
        do_help( ch, "olc", 0);
        return;
    }
 
    /* Search Table and Dispatch Command. */
    for ( cmd = 0; editor_table[cmd].name != NULL; cmd++ )
    {
	if ( !str_prefix( command, editor_table[cmd].name ) )
	{
	    (*editor_table[cmd].do_fun) ( ch, argument, 0 );
	    return;
	}
    }

    /* Invalid command, send help. */
    do_help( ch, "olc", 0);
    return;
}

/** Function: do_gedit
  * Descr   : Places user into the guild editor. Verifying Security.
  * Returns : Message if improper security level.
  * Syntax  : gedit [guild #|create]
  * Written : v1.0 3/98
  * Author  : Gary McNickle <gary@dharvest.com>
  */
ACMD(do_gedit) {
    CLAN_DATA *pClan;
    int value;
    char arg[MAX_STRING_LENGTH];

    if ( IS_NPC(ch) )
    	return;

    pClan = &clan_table[1]; /* set default */
    argument	= one_argument(argument,arg);

    if ( is_number( arg ) )
    {
	value = atoi( arg );
        pClan = get_clan_data( value );
        if (pClan->name[0] == '\0')
	{
	    send_to_char( "That guild does not exist.\n\r", ch );
	    return;
	}
    }
    else
    if ( !str_cmp( arg, "create" ) )
    {
	gedit_create( ch, "" );
	ch->desc->editor = ED_GUILD;
	return;
    }

    if (!STF_FLAGGED(ch, STAFF_CLANS))
    {
	send_to_char("Insuffecient security to edit guilds.\n\r",ch);
	return;
    }

    ch->desc->pEdit = pClan;
    ch->desc->editor = ED_GUILD;
    return;
}

/* Entry point for editing area_data. */
ACMD(do_aedit) {
    AREA_DATA *pArea;
    int value;
    char arg[MAX_STRING_LENGTH];

    if ( IS_NPC(ch) )
    	return;

    pArea	= ch->in_room->area;
    argument	= one_argument(argument,arg);

    if ( is_number( arg ) )
    {
	value = atoi( arg );
	if ( !( pArea = get_area_data( value ) ) )
	{
	    send_to_char( "That area vnum does not exist.\n\r", ch );
	    return;
	}
    }
    else
    if (!str_cmp(arg, "reset" ) )
    {
	reset_area(pArea);
	send_to_char("Area reset.\r\n", ch);
	return;
    }
    else
    if ( !str_cmp( arg, "create" ) )
    {
	if (!STF_FLAGGED(ch, STAFF_OLCADMIN))
	{
		send_to_char( "AEdit : Insuficient security to edit area.\r\n",ch);
		return;
	}

	aedit_create( ch, "" );
	ch->desc->editor = ED_AREA;
	return;
    }

    if (!IS_BUILDER(ch,pArea))
    {
	send_to_char("Insuficient security to edit area.\r\n",ch);
	return;
    }

    ch->desc->pEdit = (void *)pArea;
    ch->desc->editor = ED_AREA;
    return;
}



/* Entry point for editing room_index_data. */
ACMD(do_redit) {
    ROOM_INDEX_DATA *pRoom;
    char arg1[MAX_STRING_LENGTH];

    if ( IS_NPC(ch) )
    	return;

    argument = one_argument( argument, arg1 );
    pRoom = ch->in_room;

    if (!str_cmp(arg1, "format" ) ) /* format without editing */
    {
	pRoom->description = format_string( pRoom->description );
	send_to_char("Room formatted.\r\n",ch);
	return;
    }
    else
    if ( !str_cmp( arg1, "reset" ) )	/* redit reset */
    {
	if ( !IS_BUILDER( ch, pRoom->area ) )
	{
		send_to_char("Insufficient security to modify zone.\r\n",ch);
        	return;
	}

	reset_room( pRoom );
	send_to_char( "Room reset.\n\r", ch );

	return;
    }
    else
    if ( !str_cmp( arg1, "create" ) )	/* redit create <vnum> */
    {
	if ( argument[0] == '\0' || atoi( argument ) == 0 )
	{
	    send_to_char( "Syntax:  edit room create [vnum]\n\r", ch );
	    return;
	}

	if ( redit_create( ch, argument ) ) /* pEdit == nuevo cuarto */
	{
	    ch->desc->editor = ED_ROOM;
	    char_from_room( ch );
	    char_to_room( ch, (ROOM_INDEX_DATA *)ch->desc->pEdit);
	    SET_BIT( ((ROOM_INDEX_DATA *)ch->desc->pEdit)->area->area_flags, AREA_CHANGED );
	}

	return;
    }
    else if ( !IS_NULLSTR(arg1) )	/* redit <vnum> */
    {
	pRoom = get_room_index(atoi(arg1));

	if ( !pRoom )
	{
		send_to_char( "REdit : cuarto inexistente.\n\r", ch );
		return;
	}

	if ( !IS_BUILDER(ch, pRoom->area) )
	{
		send_to_char( "REdit : Insuficient security to modify area\r\n",ch);
		return;
	}

	char_from_room( ch );
	char_to_room( ch, pRoom );
    }

    if ( !IS_BUILDER(ch, pRoom->area) )
    {
    	send_to_char( "REdit : Insuficient security to edit room.\r\n",ch);
    	return;
    }

    ch->desc->pEdit	= (void *) pRoom;
    ch->desc->editor	= ED_ROOM;

    return;
}



/* Entry point for editing obj_index_data. */
ACMD(do_oedit) {
    OBJ_INDEX_DATA *pObj;
    AREA_DATA *pArea;
    char arg1[MAX_STRING_LENGTH];
    int value;

    if ( IS_NPC(ch) )
	return;

    argument = one_argument( argument, arg1 );

    if ( is_number( arg1 ) )
    {
	value = atoi( arg1 );
	if ( !( pObj = get_obj_index( value ) ) )
	{
	    send_to_char( "OEdit:  That vnum does not exist.\n\r", ch );
	    return;
	}

	if ( !IS_BUILDER( ch, pObj->area ) )
	{
		send_to_char( "Insuficient security to modify object.\r\n",ch);
	        return;
	}

	ch->desc->pEdit = (void *)pObj;
	ch->desc->editor = ED_OBJECT;
	return;
    }
    else
    {
	if ( !str_cmp( arg1, "create" ) )
	{
	    value = atoi( argument );
	    if ( argument[0] == '\0' || value == 0 )
	    {
		send_to_char( "Syntax:  edit object create [vnum]\n\r", ch );
		return;
	    }

	    pArea = get_vnum_area( value );

	    if ( !pArea )
	    {
		send_to_char( "OEdit:  That vnum is not assigned an area.\n\r", ch );
		return;
	    }

	    if ( !IS_BUILDER( ch, pArea ) )
	    {
		send_to_char( "Insuficient security to modify object.\r\n",ch);
	        return;
	    }

	    if ( oedit_create( ch, argument ) )
	    {
		SET_BIT( pArea->area_flags, AREA_CHANGED );
		ch->desc->editor = ED_OBJECT;
	    }
	    return;
	}
    }

    send_to_char( "OEdit:  There is no default object to edit.\n\r", ch );
    return;
}



/* Entry point for editing mob_index_data. */
ACMD(do_medit) {
    MOB_INDEX_DATA *pMob;
    AREA_DATA *pArea;
    int value;
    char arg1[MAX_STRING_LENGTH];

    argument = one_argument( argument, arg1 );

    if ( IS_NPC(ch) )
    	return;

    if ( is_number( arg1 ) )
    {
	value = atoi( arg1 );
	if ( !( pMob = get_mob_index( value ) ))
	{
	    send_to_char( "MEdit:  That vnum does not exist.\n\r", ch );
	    return;
	}

	if ( !IS_BUILDER( ch, pMob->area ) )
	{
		send_to_char( "Insuficient security to modify mob.\r\n",ch);
	        return;
	}

	ch->desc->pEdit = (void *)pMob;
	ch->desc->editor = ED_MOBILE;
	return;
    }
    else
    {
	if ( !str_cmp( arg1, "create" ) )
	{
	    value = atoi( argument );
	    if ( arg1[0] == '\0' || value == 0 )
	    {
		send_to_char( "Syntax:  edit mobile create [vnum]\n\r", ch );
		return;
	    }

	    pArea = get_vnum_area( value );

	    if ( !pArea )
	    {
		send_to_char( "OEdit:  That vnum is not assigned an area.\n\r", ch );
		return;
	    }

	    if ( !IS_BUILDER( ch, pArea ) )
	    {
		send_to_char( "Insuficient security to modify mob.\r\n",ch);
	        return;
	    }

	    if ( medit_create( ch, argument ) )
	    {
		SET_BIT( pArea->area_flags, AREA_CHANGED );
		ch->desc->editor = ED_MOBILE;
	    }
	    return;
	}
    }

    send_to_char( "MEdit:  There is no default mobile to edit.\n\r", ch );
    return;
}

/* Social Editor - Mendanbar */
ACMD(do_sedit) {
    SOCIAL_DATA *pSocial;
    char arg1[MAX_INPUT_LENGTH];

    argument = one_argument(argument, arg1);

    if (IS_NPC(ch))
	return;

    if (!STF_FLAGGED(ch, STAFF_SOCIALS)) {
	send_to_char("Insuficient security to edit socials.\n\r", ch);
	return;
    }

    if (!str_cmp(arg1, "show")) {
	if (argument[0] == '\0') {
		send_to_char("Syntax: sedit show [social]\n\r", ch);
		return;
	}
	sedit_show(ch, argument);
	return;
    }
    if (!str_cmp(arg1, "create")) {
	if (argument[0] == '\0') {
		send_to_char("Syntax: sedit create [social]\n\r", ch);
		return;
	}
	if (sedit_create(ch, argument)) {
		SOCIAL_CHANGED = TRUE;
		ch->desc->editor = ED_SOCIAL;
	}
	return;
    }
    if (!str_cmp(arg1, "delete")) {
	if (argument[0] == '\0') {
		send_to_char("Syntax: sedit delete [social]\n\r", ch);
		return;
	}
	if (sedit_delete(ch, argument))
		SOCIAL_CHANGED = TRUE;
	return;
    }

    if ((pSocial = get_social_data(arg1)) != NULL) {
	ch->desc->pEdit	 = (void *)pSocial;
	ch->desc->editor = ED_SOCIAL;
	return;
    }
    if (pSocial == NULL && arg1[0] != '\0') {
	send_to_char("That social does not exist.\n\r", ch);
	return;
    }

    send_to_char("SEdit: There is no default social to edit.\n\r", ch);
    return;
}

/* Help Editor - kermit 1/98 */
ACMD(do_hedit) {
    HELP_DATA *pHelp;
    char arg1[MIL];
    char argall[MAX_INPUT_LENGTH],argone[MAX_INPUT_LENGTH];
    bool found = FALSE;

    strcpy(arg1,argument);
    
    if(argument != '\0')
    {
        /* Taken from do_help */
        argall[0] = '\0';
        while (argument[0] != '\0' )
        {
            argument = one_argument(argument,argone);
            if (argall[0] != '\0')
                strcat(argall," ");
            strcat(argall,argone);
        }

        for ( pHelp = help_first; pHelp != NULL; pHelp = pHelp->next )
        {
            if ( is_name( argall, pHelp->keyword ) )
            {
                ch->desc->pEdit=(void *)pHelp;
                ch->desc->editor= ED_HELP;
                found = TRUE;
                return;
            }
        }
    }

    if(!found)
    {
        argument = one_argument(arg1, arg1);
        
        if(!str_cmp(arg1,"create"))
        {
            if (argument[0] == '\0')
            {
                send_to_char("Syntax: hedit create [topic]\n\r",ch);
                return;
            }
            if (hedit_create(ch, argument) )
                ch->desc->editor = ED_HELP;
            return;
        }
    }

    send_to_char( "HEdit:  There is no default help to edit.\n\r", ch );
    return;
}


void display_resets( CHAR_DATA *ch )
{
    ROOM_INDEX_DATA	*pRoom;
    RESET_DATA		*pReset;
    MOB_INDEX_DATA	*pMob = NULL;
    char 		buf   [ MAX_STRING_LENGTH ];
    char 		final [ MAX_STRING_LENGTH ];
    int 		iReset = 0;

    EDIT_ROOM(ch, pRoom);
    final[0]  = '\0';
    
    send_to_char ( 
  " No.  Loads    Description       Location         Vnum   Mx Mn Description"
  "\n\r"
  "==== ======== ============= =================== ======== ===== ==========="
  "\n\r", ch );

    for ( pReset = pRoom->reset_first; pReset; pReset = pReset->next )
    {
	OBJ_INDEX_DATA  *pObj;
	MOB_INDEX_DATA  *pMobIndex;
	OBJ_INDEX_DATA  *pObjIndex;
	OBJ_INDEX_DATA  *pObjToIndex;
	ROOM_INDEX_DATA *pRoomIndex;

	final[0] = '\0';
	sprintf( final, "[%2d] ", ++iReset );

	switch ( pReset->command )
	{
	default:
	    sprintf( buf, "Bad reset command: %c.", pReset->command );
	    strcat( final, buf );
	    break;

	case 'M':
	    if ( !( pMobIndex = get_mob_index( pReset->arg1 ) ) )
	    {
                sprintf( buf, "Load Mobile - Bad Mob %d\n\r", pReset->arg1 );
                strcat( final, buf );
                continue;
	    }

	    if ( !( pRoomIndex = get_room_index( pReset->arg3 ) ) )
	    {
                sprintf( buf, "Load Mobile - Bad Room %d\n\r", pReset->arg3 );
                strcat( final, buf );
                continue;
	    }

            pMob = pMobIndex;
            sprintf( buf, "M[%5d] %-13.13s in room             R[%5d] %2d-%2d %-15.15s`n\n\r",
                       pReset->arg1, pMob->short_descr, pReset->arg3,
                       pReset->arg2, pReset->arg4, pRoomIndex->name );
            strcat( final, buf );

	    /*
	     * Check for pet shop.
	     * -------------------
	     */
	    {
		ROOM_INDEX_DATA *pRoomIndexPrev;

		pRoomIndexPrev = get_room_index( pRoomIndex->vnum - 1 );
		if ( pRoomIndexPrev
		    && IS_SET( pRoomIndexPrev->room_flags, ROOM_PET_SHOP ) )
                    final[5] = 'P';
	    }

	    break;

	case 'O':
	    if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
	    {
                sprintf( buf, "Load Object - Bad Object %d\n\r",
		    pReset->arg1 );
                strcat( final, buf );
                continue;
	    }

            pObj       = pObjIndex;

	    if ( !( pRoomIndex = get_room_index( pReset->arg3 ) ) )
	    {
                sprintf( buf, "Load Object - Bad Room %d\n\r", pReset->arg3 );
                strcat( final, buf );
                continue;
	    }

            sprintf( buf, "O[%5d] %-13.13s in room             "
                          "R[%5d]       %-15.15s`n\n\r",
                          pReset->arg1, pObj->short_descr,
                          pReset->arg3, pRoomIndex->name );
            strcat( final, buf );

	    break;

	case 'P':
	    if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
	    {
                sprintf( buf, "Put Object - Bad Object %d\n\r",
                    pReset->arg1 );
                strcat( final, buf );
                continue;
	    }

            pObj       = pObjIndex;

	    if ( !( pObjToIndex = get_obj_index( pReset->arg3 ) ) )
	    {
                sprintf( buf, "Put Object - Bad To Object %d\n\r",
                    pReset->arg3 );
                strcat( final, buf );
                continue;
	    }

	    sprintf( buf,
		"O[%5d] %-13.13s inside              O[%5d] %2d-%2d %-15.15s`n\n\r",
		pReset->arg1,
		pObj->short_descr,
		pReset->arg3,
		pReset->arg2,
		pReset->arg4,
		pObjToIndex->short_descr );
            strcat( final, buf );

	    break;

	case 'G':
	case 'E':
	    if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
	    {
                sprintf( buf, "Give/Equip Object - Bad Object %d\n\r",
                    pReset->arg1 );
                strcat( final, buf );
                continue;
	    }

            pObj       = pObjIndex;

	    if ( !pMob )
	    {
                sprintf( buf, "Give/Equip Object - No Previous Mobile\n\r" );
                strcat( final, buf );
                break;
	    }

	    if ( pMob->pShop )
	    {
	    sprintf( buf,
		"O[%5d] %-13.13s in the inventory of S[%5d]       %-15.15s`n\n\r",
		pReset->arg1,
		pObj->short_descr,                           
		pMob->vnum,
		pMob->short_descr  );
	    }
	    else
	    sprintf( buf,
		"O[%5d] %-13.13s %-19.19s M[%5d]       %-15.15s`n\n\r",
		pReset->arg1,
		pObj->short_descr,
		(pReset->command == 'G') ?
		    flag_string( wear_loc_strings, WEAR_NONE )
		  : flag_string( wear_loc_strings, pReset->arg3 ),
		  pMob->vnum,
		  pMob->short_descr );
	    strcat( final, buf );

	    break;

	/*
	 * Doors are set in rs_flags don't need to be displayed.
	 * If you want to display them then uncomment the new_reset
	 * line in the case 'D' in load_resets in db.c and here.
	 */
	case 'D':
	    pRoomIndex = get_room_index( pReset->arg1 );
	    sprintf( buf, "R[%5d] %s door of %-19.19s reset to %s`n\n\r",
		pReset->arg1,
		capitalize( dir_name[ pReset->arg2 ] ),
		pRoomIndex->name,
		flag_string( door_resets, pReset->arg3 ) );
	    strcat( final, buf );

	    break;
	/*
	 * End Doors Comment.
	 */
	case 'R':
	    if ( !( pRoomIndex = get_room_index( pReset->arg1 ) ) )
	    {
		sprintf( buf, "Randomize Exits - Bad Room %d\n\r",
		    pReset->arg1 );
		strcat( final, buf );
		continue;
	    }

	    sprintf( buf, "R[%5d] Exits are randomized in %s`n\n\r",
		pReset->arg1, pRoomIndex->name );
	    strcat( final, buf );

	    break;
	}
	send_to_char( final, ch );
    }

    return;
}



/*****************************************************************************
 Name:		add_reset
 Purpose:	Inserts a new reset in the given index slot.
 ****************************************************************************/
void add_reset( ROOM_INDEX_DATA *room, RESET_DATA *pReset, int index )
{
    RESET_DATA *reset;
    int iReset = 0;

    if ( !room->reset_first )
    {
	room->reset_first	= pReset;
	room->reset_last	= pReset;
	pReset->next		= NULL;
	return;
    }

    index--;

    if ( index == 0 )	/* First slot (1) selected. */
    {
	pReset->next = room->reset_first;
	room->reset_first = pReset;
	return;
    }

    /*
     * If negative slot( <= 0 selected) then this will find the last.
     */
    for ( reset = room->reset_first; reset->next; reset = reset->next )
    {
	if ( ++iReset == index )
	    break;
    }

    pReset->next	= reset->next;
    reset->next		= pReset;
    if ( !pReset->next )
	room->reset_last = pReset;
    return;
}



ACMD(do_resets) {
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    char arg3[MAX_INPUT_LENGTH];
    char arg4[MAX_INPUT_LENGTH];
    char arg5[MAX_INPUT_LENGTH];
    char arg6[MAX_INPUT_LENGTH];
    char arg7[MAX_INPUT_LENGTH];
    RESET_DATA *pReset = NULL;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
    argument = one_argument( argument, arg3 );
    argument = one_argument( argument, arg4 );
    argument = one_argument( argument, arg5 );
    argument = one_argument( argument, arg6 );
    argument = one_argument( argument, arg7 );

    if (!IS_BUILDER(ch, ch->in_room->area)) {
	send_to_char("Resets: Invalid security for editing this area.\n\r", ch);
	return;
    }

    /*
     * Display resets in current room.
     * -------------------------------
     */
    if ( arg1[0] == '\0' )
    {
	if ( ch->in_room->reset_first )
	    display_resets( ch );
	else
	    send_to_char( "No resets in this room.\n\r", ch );
    }


    /*
     * Take index number and search for commands.
     * ------------------------------------------
     */
    if ( is_number( arg1 ) )
    {
	ROOM_INDEX_DATA *pRoom = ch->in_room;

	/*
	 * Delete a reset.
	 * ---------------
	 */
	if ( !str_cmp( arg2, "delete" ) )
	{
	    int insert_loc = atoi( arg1 );

	    if ( !ch->in_room->reset_first )
	    {
		send_to_char( "No resets in this area.\n\r", ch );
		return;
	    }

	    if ( insert_loc-1 <= 0 )
	    {
		pReset = pRoom->reset_first;
		pRoom->reset_first = pRoom->reset_first->next;
		if ( !pRoom->reset_first )
		    pRoom->reset_last = NULL;
	    }
	    else
	    {
		int iReset = 0;
		RESET_DATA *prev = NULL;

		for ( pReset = pRoom->reset_first;
		  pReset;
		  pReset = pReset->next )
		{
		    if ( ++iReset == insert_loc )
			break;
		    prev = pReset;
		}

		if ( !pReset )
		{
		    send_to_char( "Reset not found.\n\r", ch );
		    return;
		}

		if ( prev )
		    prev->next = prev->next->next;
		else
		    pRoom->reset_first = pRoom->reset_first->next;

		for ( pRoom->reset_last = pRoom->reset_first;
		  pRoom->reset_last->next;
		  pRoom->reset_last = pRoom->reset_last->next );
	    }

	    free_reset_data( pReset );
	    SET_BIT(AREA_FLAGS(pRoom->area), AREA_CHANGED);
	    send_to_char( "Reset deleted.\n\r", ch );
	}
	else
	/*
	 * Add a reset.
	 * ------------
	 */
	if ( (!str_cmp( arg2, "mob" ) && is_number( arg3 ))
	  || (!str_cmp( arg2, "obj" ) && is_number( arg3 )) )
	{
	    /*
	     * Check for Mobile reset.
	     * -----------------------
	     */
	    if (!str_cmp(arg2, "mob"))
	    {
		if (get_mob_index(is_number(arg3) ? atoi(arg3) : 1) == NULL) {
		    send_to_char("That mob does not exist.\n\r", ch);
		    return;
		}
		pReset = new_reset_data();
		pReset->command = 'M';
		pReset->arg1    = atoi( arg3 );
		pReset->arg2    = is_number( arg4 ) ? atoi( arg4 ) : 1; /* Max # */
		pReset->arg3    = ch->in_room->vnum;
		pReset->arg4	= is_number( arg5 ) ? atoi( arg5 ) : 1; /* Min # */
	    }
	    else
	    /*
	     * Check for Object reset.
	     * -----------------------
	     */
	    if ( !str_cmp( arg2, "obj" ) )
	    {
		pReset = new_reset_data();
		pReset->arg1    = atoi( arg3 );
		/*
		 * Inside another object.
		 * ----------------------
		 */
		if ( !str_prefix( arg4, "inside" ) )
		{
		    OBJ_INDEX_DATA *temp;

		    temp = get_obj_index(is_number(arg5) ? atoi(arg5) : 1);
		if (!temp)
		{
	          send_to_char( "Couldn't find Object 2.\n\r",ch);
	          return;
	        }
		if ( ( temp->item_type != ITEM_CONTAINER ) &&
		     ( temp->item_type != ITEM_CORPSE_NPC ) )
		{
		       send_to_char("Object 2 is not a container.\n\r", ch);
		       return;
		}
		    pReset->command = 'P';
		    pReset->arg2    = is_number( arg6 ) ? atoi( arg6 ) : 1;
		    pReset->arg3    = is_number( arg5 ) ? atoi( arg5 ) : 1;
		    pReset->arg4    = is_number( arg7 ) ? atoi( arg7 ) : 1;
		}
		else
		/*
		 * Inside the room.
		 * ----------------
		 */
		if ( !str_cmp( arg4, "room" ) )
		{
		    if (get_obj_index(atoi(arg3)) == NULL)
		      {
			 send_to_char("Vnum does not exist.\n\r", ch);
		         return;
		      }
		    pReset->command  = 'O';
		    pReset->arg2     = 0;
		    pReset->arg3     = ch->in_room->vnum;
		    pReset->arg4     = 0;
		}
		else
		/*
		 * Into a Mobile's inventory.
		 * --------------------------
		 */
		{
		    if ( flag_value( wear_loc_flags, arg4 ) == NO_FLAG )
		    {
			send_to_char( "Resets: '? wear-loc'\n\r", ch );
			return;
		    }
		    if (get_obj_index(atoi(arg3)) == NULL)
		      {
			 send_to_char("Vnum does not exist.\n\r", ch);
		         return;
		      }
		    pReset->arg1 = atoi(arg3);
		    pReset->arg3 = flag_value( wear_loc_flags, arg4 );
		    if ( pReset->arg3 == WEAR_NONE )
			pReset->command = 'G';
		    else
			pReset->command = 'E';
		}
	    }
	    add_reset( ch->in_room, pReset, atoi( arg1 ) );
	    SET_BIT( ch->in_room->area->area_flags, AREA_CHANGED );
	    send_to_char( "Reset added.\n\r", ch );
	}
	else
	if (!str_cmp( arg2, "random") && is_number(arg3))
	{
		if (atoi(arg3) < 1 || atoi(arg3) > 6)
			{
				send_to_char("Invalid argument.\n\r", ch);
				return;
			}
		pReset = new_reset_data ();
		pReset->command = 'R';
		pReset->arg1 = ch->in_room->vnum;
		pReset->arg2 = atoi(arg3);
		add_reset( ch->in_room, pReset, atoi( arg1 ) );
		SET_BIT( ch->in_room->area->area_flags, AREA_CHANGED );
		send_to_char( "Random exits reset added.\n\r", ch);
	}
	else
	{
	send_to_char( "Syntax: RESET <number> OBJ <vnum> <wear_loc>\n\r", ch );
	send_to_char( "        RESET <number> OBJ <vnum> inside <vnum> [limit] [count]\n\r", ch );
	send_to_char( "        RESET <number> OBJ <vnum> room\n\r", ch );
	send_to_char( "        RESET <number> MOB <vnum> [max #x area] [max #x room]\n\r", ch );
	send_to_char( "        RESET <number> DELETE\n\r", ch );
	send_to_char( "        RESET <number> RANDOM [#x exits]\n\r", ch);
	}
    }

    return;
}

ACMD(do_zallow) {
    AREA_DATA *pArea;
    char name[MAX_STRING_LENGTH];
    char zone[MAX_STRING_LENGTH];
    char buf1[MAX_STRING_LENGTH];

    argument = one_argument(argument, name);
    argument = one_argument(argument, zone);

    if (!*name || !*zone || !is_number(zone)) {
	ch->Send("Usage: %s <player> <zone>\n\r",
		subcmd == SCMD_ZALLOW ? "zallow" : "zdeny");
	return;
    }

    name[0] = UPPER(name[0]);
    buf1[0] = '\0';

    if ((pArea = get_area_data(atoi(zone))) == NULL) {
	send_to_char("That zone doesn't seem to exist.\n\r", ch);
	return;
    }

    if (subcmd == SCMD_ZALLOW) {
	if (strstr(pArea->builders, name) != '\0') {
	    send_to_char("That person already has access to that zone.\n\r", ch);
	    return;
	}
	if (strstr(pArea->builders, "None") != '\0') {
	    pArea->builders = string_replace(pArea->builders, "None", "\0");
	    pArea->builders = string_unpad(pArea->builders);
	}
	if (pArea->builders[0] != '\0') {
	    strcat(buf1, pArea->builders);
	    strcat(buf1, " ");
	}
	strcat(buf1, name);
	free_string(pArea->builders);
	pArea->builders = string_proper(str_dup(buf1));
	send_to_char("Builder added.\n\r", ch);
    } else if (subcmd == SCMD_ZDENY) {
	if (strstr(pArea->builders, name) == '\0') {
	    send_to_char("That person doesn't have access to that zone.\n\r", ch);
	    return;
	}
	pArea->builders = string_replace(pArea->builders, name, "\0");
	pArea->builders = string_unpad(pArea->builders);
	if (pArea->builders[0] == '\0') {
	    free_string(pArea->builders);
	    pArea->builders = str_dup("None");
	}
	send_to_char("Builder removed.\n\r", ch);
    } else {
	mudlogf(BRF, LVL_STAFF, TRUE, "SYSERR: Invalid subcmd passed to do_zallow (SCMD %d)", subcmd);
	return;
    }
    SET_BIT(AREA_FLAGS(pArea), AREA_CHANGED);
    send_to_char("Zone file edited.\n\r", ch);
    mudlogf(BRF, LVL_STAFF, TRUE, "OLC: %s %s %s%s zone #%d builder access.",
	RealName(ch), subcmd == SCMD_ZALLOW ? "gives" : "removes",
	name, subcmd == SCMD_ZALLOW ? "" : "'s", pArea->vnum);
    return;
}

ACMD(do_areas) {
    char	buf[MAX_STRING_LENGTH];
    BUFFER	*buffer = new_buf();
    AREA_DATA	*pArea;

    sprintf(buf, "[%-23.23s] [%-23.23s] [%-23.23s]\n\r"
	"------------------------- ------------------------- -------------------------\n\r",
	"Area Name", "Area Theme", "Shortest Path");
    add_buf(buffer, buf);

    for (pArea = area_first; pArea; pArea = pArea->next) {
	if (AREA_FLAGGED(pArea, AREA_UNLINKED))
		continue;

	sprintf(buf, "[%-23.23s] [%-23.23s] [%-23.23s]\n\r",
		pArea->name, pArea->theme, path_to_area(ch, pArea));
	add_buf(buffer, buf);
    }
    page_to_char(buf_string(buffer), ch);
    free_buf(buffer);
    return;
}

ACMD(do_alist) {
    char 	buf[MAX_STRING_LENGTH];
    BUFFER 	*result = new_buf();
    AREA_DATA *pArea;

    sprintf(buf, "[%3s] [%-28s] (%-5s-%5s) [%-10s] %3s [%-10s]\n\r"
	"----- ------------------------------ ------------- ------------ --- ------------\n\r",
	"Num", "Area Name", "lvnum", "uvnum", "Filename", "Sec", "Builder");
    add_buf(result, buf);

    for ( pArea = area_first; pArea; pArea = pArea->next )
    {
	sprintf(buf, "[%3d] [%s%-26.26s ] (%-5d-%5d) %-12.12s [%d] [%-10.10s]\n\r",
		pArea->vnum,
		AREA_FLAGGED(pArea, AREA_UNLINKED) ? "`y*`n" : " ",
		pArea->name,
		pArea->min_vnum, pArea->max_vnum,
		pArea->file_name, pArea->security,
		pArea->builders);
	add_buf(result, buf);
    }

    page_to_char(buf_string(result), ch);
    free_buf(result);
    return;
}