daleken/
daleken/data/notes/
daleken/data/player/
daleken/data/system/poses/
daleken/doc/Homepage/images/
daleken/log/
/*___________________________________________________________________________*
   )()(			  DalekenMUD 1.12 (C) 2000			)()(
   `]['		       by Martin Thomson, Lee Brooks,			`]['
    ||		       Ken Herbert and David Jacques			 ||
    || ----------------------------------------------------------------- ||
    || Envy Diku Mud improvements copyright (C) 1994 by Michael Quan,	 ||
    || David Love, Guilherme 'Willie' Arnold, and Mitchell Tse.		 ||
    || Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael	 ||
    || Chastain, Michael Quan, and Mitchell Tse.			 ||
    || Original Diku Mud copyright (C) 1990, 1991			 ||
    || by Sebastian Hammer, Michael Seifert, Hans Henrik St{rfeldt,	 ||
    || Tom Madsen, and Katja Nyboe.					 ||
    || ----------------------------------------------------------------- ||
    || Any use of this software must follow the licenses of the		 ||
    || creators.  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.					 ||
    || ----------------------------------------------------------------- ||
    ||                            olc_misc.c                             ||
    || Miscellaneous OLC code.						 ||
 *_/<>\_________________________________________________________________/<>\_*/


#include <limits.h>		/* OLC 1.1b */
#include "mud.h"
#include "olc.h"

#if defined( unix )
#include <unistd.h>
#endif

#ifndef INT_MAX
#define INT_MAX 65536
#endif


void show_liqlist	args( ( CHAR_DATA *ch ) );


bool show_version( CHAR_DATA *ch, const char *argument )
{
    send_to_char( VERSION, ch );
    send_to_char( "\n\r", ch );
    send_to_char( AUTHOR, ch );
    send_to_char( "\n\r", ch );
    send_to_char( DATE, ch );
    send_to_char( "\n\r", ch );
    send_to_char( CREDITS, ch );
    send_to_char( "\n\r", ch );

    return FALSE;
}


/*****************************************************************************
 Name:		show_flag_cmds
 Purpose:	Displays settable flags and stats.
 Called by:	show_help( olc_act.c ).
 ****************************************************************************/
void show_flag_cmds( CHAR_DATA *ch, const struct flag_type *flag_table )
{
    char buf[MAX_STRING_LENGTH];
    char buf1[MAX_STRING_LENGTH];
    int flag;
    int col;

    buf1[0] = '\0';
    col = 0;
    for( flag = 0; *flag_table[flag].name; flag++ )
    {
	if( flag_table[flag].settable )
	{
	    sprintf( buf, "%-19.18s", flag_table[flag].name );
	    strcat( buf1, buf );
	    if( ++col % 4 == 0 )
		strcat( buf1, "\n\r" );
	}
    }

    if( col % 4 != 0 )
	strcat( buf1, "\n\r" );

    send_to_char( buf1, ch );
    return;
}


/*****************************************************************************
 Name:		show_skill_cmds
 Purpose:	Displays all skill functions.
		Does remove those damn immortal commands from the list.
		Could be improved by:
		( 1 ) Adding a check for a particular class.
		( 2 ) Adding a check for a level range.
 Called by:	show_help( olc_act.c ).
 ****************************************************************************/
void show_skill_cmds( CHAR_DATA *ch, int tar )
{
    char buf[MAX_STRING_LENGTH];
    char buf1[MAX_STRING_LENGTH * 2];
    int sn;
    int col;

    buf1[0] = '\0';
    col = 0;
    for( sn = 0; sn < MAX_SKILL; sn++ )
    {
	if( !skill_table[sn].name )
	    break;

	if( !str_cmp( skill_table[sn].name, "reserved" )
	    || skill_table[sn].spell_fun == spell_null )
	    continue;

	if( tar == -1 || skill_table[sn].target == tar )
	{
	    sprintf( buf, "%-19.18s", skill_table[sn].name );
	    strcat( buf1, buf );
	    if( ++col % 4 == 0 )
		strcat( buf1, "\n\r" );
	}
    }

    if( col % 4 != 0 )
	strcat( buf1, "\n\r" );

    send_to_char( buf1, ch );
    return;
}


/*****************************************************************************
 Name:		show_spec_cmds
 Purpose:	Displays settable special functions.
 Called by:	show_help( olc_act.c ).
 ****************************************************************************/
void show_spec_cmds( CHAR_DATA *ch )
{
    char buf[MAX_STRING_LENGTH];
    char buf1[MAX_STRING_LENGTH];
    int spec;
    int col;

    buf1[0] = '\0';
    col = 0;
    send_to_char( "Preceed special functions with 'spec_'\n\r\n\r", ch );
    for( spec = 0; *spec_table[spec].spec_fun; spec++ )
    {
	if( !str_prefix( "spec_", spec_table[spec].spec_name ) )
	    sprintf( buf, "%-25.24s", &spec_table[spec].spec_name[5] );
	else
	    sprintf( buf, "%-25.24s", spec_table[spec].spec_name );
	strcat( buf1, buf );
	if( ++col % 3 == 0 )
	    strcat( buf1, "\n\r" );
    }

    if( col % 3 != 0 )
	strcat( buf1, "\n\r" );

    send_to_char( buf1, ch );
    return;
}


void show_liqlist( CHAR_DATA *ch )
{
    int liq;
    BUFFER *buf = buffer_new( MAX_INPUT_LENGTH );
    char tmp[MAX_INPUT_LENGTH];

    for( liq = 0; liq_table[liq].liq_name != NULL; liq++ )
    {
	if( liq == 0 )
	    buffer_strcat( buf, "&bName                 Color          Proof Full Thirst&n\n\r" );

	bprintf( buf, "&g%-20.20s %s&g %4d %4d %5d&n\n\r",
		 liq_table[liq].liq_name,
		 colour_strpad( tmp, liq_table[liq].liq_color, 14 ),
		 liq_table[liq].liq_affect[0], liq_table[liq].liq_affect[1],
		 liq_table[liq].liq_affect[2] );
    }

    send_to_char( buf->data, ch );
    buffer_free( buf );
    return;
}


void do_flaglookup( CHAR_DATA *ch, const char *argument )
{
    CHAR_DATA *rch;

    rch = get_char( ch );
    if( !authorized( rch, "flaglookup" ) )
	return;

    show_help( ch, argument );
}


/*****************************************************************************
 Name:		show_help
 Purpose:	Displays help for many tables used in OLC.
 Called by:	olc interpreters.
 ****************************************************************************/
bool show_help( CHAR_DATA *ch, const char *argument )
{
    BUFFER *buf;
    char arg[MAX_INPUT_LENGTH];
    char spell[MAX_INPUT_LENGTH];
    int cnt;

    argument = one_argument( argument, arg );
    one_argument( argument, spell );

    /*
     * Display syntax.
     */
    if( arg[0] == '\0' )
    {
	buf = buffer_new( MAX_STRING_LENGTH );
	buffer_strcat( buf, "Syntax:  ? [command]\n\r\n\r" );
	buffer_strcat( buf, "[command]	[description]\n\r" );
	for( cnt = 0; bit_table[cnt].command[0] != '\0'; cnt++ )
	{
	    if( !IS_SET( bit_table[cnt].flags, BIT_INVISIBLE ) )
		bprintf( buf, "%-10.10s -%s\n\r",
			 capitalize( bit_table[cnt].command ),
			 bit_table[cnt].desc );
	}
	send_to_char( buf->data, ch );
	buffer_free( buf );
	return FALSE;
    }

    /*
     * Find the command, show changeable data.
     * ---------------------------------------
     */
    for( cnt = 0; *bit_table[cnt].command; cnt++ )
    {
	if( arg[0] == bit_table[cnt].command[0]
	    && !str_prefix( arg, bit_table[cnt].command ) )
	{
	    if( !str_cmp( bit_table[cnt].command, "spec" ) )
	    {
		show_spec_cmds( ch );
		return FALSE;
	    }
	    else if( !str_cmp( bit_table[cnt].command, "liquid" ) )
	    {
		show_liqlist( ch );
		return FALSE;
	    }
	    else if( !str_cmp( bit_table[cnt].command, "spells" ) )
	    {
		if( spell[0] == '\0' )
		{
		    send_to_char(
			"Syntax:  ? spells "
			"[ignore/attack/defend/self/object/all]\n\r", ch );
		    return FALSE;
		}

		if( !str_prefix( spell, "all" ) )
		    show_skill_cmds( ch, -1 );
		else if( !str_prefix( spell, "ignore" ) )
		    show_skill_cmds( ch, TAR_IGNORE );
		else if( !str_prefix( spell, "attack" ) )
		    show_skill_cmds( ch, TAR_CHAR_OFFENSIVE );
		else if( !str_prefix( spell, "defend" ) )
		    show_skill_cmds( ch, TAR_CHAR_DEFENSIVE );
		else if( !str_prefix( spell, "self" ) )
		    show_skill_cmds( ch, TAR_CHAR_SELF );
		else if( !str_prefix( spell, "object" ) )
		    show_skill_cmds( ch, TAR_OBJ_INV );
		else
		    send_to_char(
			"Syntax:  ? spell "
			"[ignore/attack/defend/self/object/all]\n\r", ch );

		return FALSE;
	    }
	    else
	    {
		show_flag_cmds( ch, bit_table[cnt].structure );
		return FALSE;
	    }
	}
    }

    show_help( ch, "" );
    return FALSE;
}


bool sedit_create( CHAR_DATA *ch, const char *argument )
{
    SOCIAL_DATA *pSocial;
    char buf[MAX_INPUT_LENGTH];
    char *p;

    strcpy( buf, argument );
    for( p = &buf[0]; p && *p; ++p )
	*p = LOWER( *p );
    pSocial = new_social( buf );
    ch->desc->pEdit = (void *)pSocial;

    wiznetf( ch, WIZ_CREATE, get_trust( ch ), "%s has created a social %s.",
	     ch->name, pSocial->name );
    send_to_char( "SEdit:  Social created.\n\r", ch );
    if( strchr( buf, ' ' ) )
	send_to_char( "Be careful with spaces, "
		      "they might stuff you up here.\n\r", ch );
    return TRUE;
}


bool sedit_show( CHAR_DATA *ch, const char *argument )
{
    SOCIAL_DATA *pSocial;
    BUFFER *buf = buffer_new( MAX_INPUT_LENGTH );

    EDIT_SOCIAL( ch, pSocial );

    bprintf( buf, "&gName          &b[&c%s&b]&n\n\r", pSocial->name );
    bprintf( buf, "&gChar_No_Arg:  &w%s&n\n\r", pSocial->char_no_arg );
    bprintf( buf, "&gOthers_No_Arg:&w%s&n\n\r", pSocial->others_no_arg );
    bprintf( buf, "&gChar_Found:   &w%s&n\n\r", pSocial->char_found );
    bprintf( buf, "&gOthers_Found: &w%s&n\n\r", pSocial->others_found );
    bprintf( buf, "&gVictim_Found: &w%s&n\n\r", pSocial->vict_found );
    bprintf( buf, "&gChar_Auto:    &w%s&n\n\r", pSocial->char_auto );
    bprintf( buf, "&gOthers_Auto:  &w%s&n\n\r", pSocial->others_auto );
    send_to_char( buf->data, ch );
    buffer_free( buf );
    return FALSE;
}


bool sedit_name( CHAR_DATA *ch, const char *argument )
{
    SOCIAL_DATA *pSocial;

    EDIT_SOCIAL( ch, pSocial );

    if( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  name <$name>\n\r", ch );
	return FALSE;
    }

    free_string( pSocial->name );
    pSocial->name = str_dup( argument );

    send_to_char( "Name set.\n\r", ch );
    return FALSE;
}


bool sedit_change( CHAR_DATA *ch, const char *argument, char **which,
		   bool hasvict )
{
    char const *legal = "nNeEmMsSgGoO%$";
    const char *p;

    if( !hasvict )
	legal = "nemsgo%$";
    for( p = strchr( argument, '$' );
	 p && *p; p = strchr( p, '$' ) )
    {
	p++;
	if( !*p || !strchr( legal, *p ) )
	{
	    send_to_char( "Illegal act string.\n\r", ch );
	    return FALSE;
	}
    }
    free_string( *which );
    *which = str_dup( argument );
    send_to_char( "Value set.\n\r", ch );
    return TRUE;
}


bool sedit_cna( CHAR_DATA *ch, const char *argument )
{
    SOCIAL_DATA *pSocial;

    EDIT_SOCIAL( ch, pSocial );

    if( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  cna <$char no arg>\n\r", ch );
	return FALSE;
    }

    return sedit_change( ch, argument, &pSocial->char_no_arg, FALSE );
}


bool sedit_ona( CHAR_DATA *ch, const char *argument )
{
    SOCIAL_DATA *pSocial;

    EDIT_SOCIAL( ch, pSocial );

    if( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  ona <$others no arg>\n\r", ch );
	return FALSE;
    }

    return sedit_change( ch, argument, &pSocial->others_no_arg, FALSE );
}


bool sedit_cf( CHAR_DATA *ch, const char *argument )
{
    SOCIAL_DATA *pSocial;

    EDIT_SOCIAL( ch, pSocial );

    if( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  cf <$char found>\n\r", ch );
	return FALSE;
    }

    return sedit_change( ch, argument, &pSocial->char_found, TRUE );
}


bool sedit_of( CHAR_DATA *ch, const char *argument )
{
    SOCIAL_DATA *pSocial;

    EDIT_SOCIAL( ch, pSocial );

    if( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  of <$others found>\n\r", ch );
	return FALSE;
    }

    return sedit_change( ch, argument, &pSocial->others_found, TRUE );
}


bool sedit_vf( CHAR_DATA *ch, const char *argument )
{
    SOCIAL_DATA *pSocial;

    EDIT_SOCIAL( ch, pSocial );

    if( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  vf <$victim found>\n\r", ch );
	return FALSE;
    }

    return sedit_change( ch, argument, &pSocial->vict_found, TRUE );
}


bool sedit_ca( CHAR_DATA *ch, const char *argument )
{
    SOCIAL_DATA *pSocial;

    EDIT_SOCIAL( ch, pSocial );

    if( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  ca <$char auto>\n\r", ch );
	return FALSE;
    }

    return sedit_change( ch, argument, &pSocial->char_auto, FALSE );
}


bool sedit_oa( CHAR_DATA *ch, const char *argument )
{
    SOCIAL_DATA *pSocial;

    EDIT_SOCIAL( ch, pSocial );

    if( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  oa <$others auto>\n\r", ch );
	return FALSE;
    }

    return sedit_change( ch, argument, &pSocial->others_auto, FALSE );
}


bool hedit_create( CHAR_DATA *ch, const char *argument )
{
    HELP_DATA *pHelp;
    AREA_DATA *pArea;
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_STRING_LENGTH];

    pArea = ch->in_room->area;
    if( !IS_BUILDER( ch, pArea ) )
    {
	send_to_char( "SEdit:  You can't edit this area.\n\r", ch );
	return FALSE;
    }

    argument = one_argument( argument, arg );
    if( argument[0] == '\0' || arg[0] == 0 || !is_number( arg ) )
    {
	send_to_char( "Syntax:  create <#level> <keyword(s)>\n\r", ch );
	return FALSE;
    }
    pHelp = new_help( );
    pHelp->area = pArea;
    pHelp->level = atoi( arg );
    pHelp->keyword = str_dup( all_capitalize( buf, argument ) );
    pHelp->text = str_dup( "" );
    ch->desc->pEdit = (void *)pHelp;
    ch->desc->interpreter = get_interpreter( "HEdit" );

    wiznetf( ch, WIZ_CREATE, get_trust( ch ), "%s has created a new help %s.",
	    ch->name, pHelp->keyword );
    send_to_char( "HEdit:  New help created.\n\r", ch );
    hedit_show( ch, "" );
    return TRUE;
}


bool hedit_keyword( CHAR_DATA *ch, const char *argument )
{
    HELP_DATA *pHelp;
    char buf[MAX_INPUT_LENGTH];
    char *p;

    EDIT_HELP( ch, pHelp );

    if( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  keyword <$keywords>\n\r", ch );
	return FALSE;
    }

    strcpy( buf, argument );
    for( p = &buf[0]; *p; ++p )
	*p = UPPER( *p );

    free_string( pHelp->keyword );
    pHelp->keyword = str_dup( buf );

    send_to_char( "Keyword(s) set.\n\r", ch );
    return TRUE;
}


bool hedit_trust( CHAR_DATA *ch, const char *argument )
{
    HELP_DATA *pHelp;

    EDIT_HELP( ch, pHelp );

    if( argument[0] == '\0' || !is_number( argument ) )
    {
	send_to_char( "Syntax:  trust <#level>\n\r", ch );
	return FALSE;
    }

    pHelp->level = atoi( argument );

    send_to_char( "Trust level set.\n\r", ch );
    return TRUE;

}


bool hedit_text( CHAR_DATA *ch, const char *argument )
{
    HELP_DATA *pHelp;

    EDIT_HELP( ch, pHelp );

    if( argument[0] == '\0' )
    {
	string_edit( ch, &pHelp->text );
	return TRUE;
    }

    send_to_char( "Syntax:  text    - line edit\n\r", ch );
    return FALSE;
}


bool hedit_show( CHAR_DATA *ch, const char *argument )
{
    HELP_DATA *pHelp;
    BUFFER *buf = buffer_new( MAX_STRING_LENGTH );

    EDIT_HELP( ch, pHelp );

    bprintf( buf, "&gKeyword(s): &b[&c%s&b]&n\n\r", pHelp->keyword );
    bprintf( buf, "&gArea:       &b[&c%4d&b]&m %s&n\n\r",
	     !pHelp->area ? -1 : pHelp->area->vnum,
	     !pHelp->area ? "No Area" : pHelp->area->name );
    bprintf( buf, "&gLevel:      &b[&c%4d&b]&n\n\r"
	     "&gText:\n\r&w", pHelp->level );
    if( *pHelp->text == '.' )
	buffer_strcat( buf, pHelp->text + 1 );
    else
	buffer_strcat( buf, pHelp->text );
    send_to_char( buf->data, ch );
    send_to_char( "&n", ch );
    buffer_free( buf );
    return FALSE;
}


bool hedit_harea( CHAR_DATA *ch, const char *argument )
{
    HELP_DATA *pHelp;
    AREA_DATA *pArea;

    EDIT_HELP( ch, pHelp );
    if( argument[0] == '\0' || !is_number( argument ) )
    {
	send_to_char( "Syntax:  harea <#areavnum>\n\r", ch );
	return FALSE;
    }

    pArea = get_area_data( atoi( argument ) );
    if( !pArea )
    {
	send_to_char( "No area there.\n\r", ch );
	return FALSE;
    }
    if( !IS_BUILDER( ch, pArea ) )
    {
	send_to_char( "You can build that area.\n\r", ch );
	return FALSE;
    }

    pHelp->area = pArea;
    SET_BIT( pArea->area_flags, AREA_CHANGED );

    send_to_char( "HEdit:  Help area set.\n\r", ch );
    return TRUE;
}


bool hedit_hlist( CHAR_DATA *ch, const char *argument )
{
    HELP_DATA *pHelp;
    AREA_DATA *pArea;
    char buf[MAX_STRING_LENGTH];
    char buf1[MAX_STRING_LENGTH * 4];
    bool fAll = FALSE;

    EDIT_HELP( ch, pHelp );
    pArea = pHelp->area;

    if( !str_cmp( argument, "all" ) )
    {
	fAll = TRUE;
    }
    buf1[0] = '\0';
    for( pHelp = help_first; pHelp; pHelp = pHelp->next )
    {
	if( pHelp->level > get_trust( ch ) )
	    continue;
	if( !fAll && pHelp->area != pArea )
	    continue;

	sprintf( buf, ">%s\n\r", pHelp->keyword );
	strcat( buf1, buf );
    }
    send_to_char( buf1, ch );
    return FALSE;
}


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

    EDIT_ROOM( ch, pRoom );

    buffer_strcat( final,
	" &gNo.  Loads    Description       Location         Vnum    Max  Description&n\n\r"
	"&B==== ======== ============= =================== ======== ===== ===============&n\n\r" );

    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;
	int save_pos;

	bprintf( final, "&b[&r%2d&b] ", ++iReset );
	save_pos = final->len;

	switch( pReset->command )
	{
	default:
	    bprintf( final, "&RBad reset command: %c.", pReset->command );
	    break;

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

	    pMob = pMobIndex;
	    bprintf( final, "&cM&b[&r%5d&b] &g%s &win room             ",
		     pReset->arg1, colour_strpad( tmp, pMob->short_descr, 13 ) );
	    bprintf( final, "&cR&b[&r%5d&b] [&r%3d&b] &y%s&n\n\r",
		     pRoom->vnum, pReset->arg2,
		     colour_strpad( tmp, pRoom->name, 15 ) );

	    /*
	     * Check for pet shop, change 'M' to 'P'
	     */
	    {
		ROOM_INDEX_DATA *pRoomIndexPrev;

		pRoomIndexPrev = get_room_index( pRoom->vnum - 1 );
		if( pRoomIndexPrev
		    && IS_SET( pRoomIndexPrev->room_flags, ROOM_PET_SHOP ) )
		    final->data[save_pos + 2] = 'P';
	    }

	    break;

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

	    pObj = pObjIndex;

	    bprintf( final, "&cO&b[&r%5d&b] &g%s &win room             ",
		     pReset->arg1, colour_strpad( tmp, pObj->short_descr, 13 ) );
	    bprintf( final, "&cR&b[&r%5d&b]       &y%s&n\n\r",
		     pRoom->vnum, colour_strpad( tmp, pRoom->name, 15 ) );
	    break;

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

	    pObj = pObjIndex;

	    if( !( pObjToIndex = get_obj_index( pReset->arg2 ) ) )
	    {
		bprintf( final, "&RPut Object - Bad To Object %d&n\n\r",
			 pReset->arg2 );
		continue;
	    }

	    bprintf( final, "&cO&b[&r%5d&b] &g%s &winside              ",
		     pReset->arg1,
		     colour_strpad( tmp, pObj->short_descr, 13 ) );
	    bprintf( final, "&cO&b[&r%5d&b]       &g%s&n\n\r",
		     pReset->arg2,
		     colour_strpad( tmp, pObjToIndex->short_descr, 15 ) );
	    break;

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

	    pObj = pObjIndex;

	    if( !pMob )
	    {
		bprintf( final, "&RGive/Equip Object - No Previous Mobile&n\n\r" );
		break;
	    }

	    bprintf( final, "&cO&b[&r%5d&b] &g%s &w%-19.19s ",
		     pReset->arg1,
		     colour_strpad( tmp, pObj->short_descr, 13 ),
		     ( pReset->command == 'G' ) ?
		     wear_loc_strings[0].name
		     : flag_string( wear_loc_strings, &pReset->arg2 ) );
	    bprintf( final, "&c%c&b[&r%5d&b]       &g%s&n\n\r",
		     pMob->pShop ? 'S' : 'M',
		     pMob->vnum,
		     colour_strpad( tmp, pMob->short_descr, 15 ) );
	    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':
	     pRoom = get_room_index( pReset->arg1 );
	     bprintf( final,
	     "&cR&b[&r%5d&b] &g%s &wdoor of %s reset to %s&n\n\r",
	     pReset->arg1,
	     capitalize( dir_name[ pReset->arg2 ] ),
	     colour_strpad( tmp, pRoom->name, 19 ),
	     flag_string( door_resets, &pReset->arg3 ) );

	     break;
	     *
	     * End Doors Comment.
	     */
	case 'R':
	    if( pReset->arg1 != 0 )
		bprintf( final, "&cR&b[&r%5d&b] &g%d &wExits are randomized in &y%s&n\n\r",
			 pRoom->vnum, pReset->arg1, pRoom->name );
	    else
		bprintf( final, "&cR&b[&r%5d&b] Exits &g%s&w are randomized in &y%s&n\n\r",
			 pRoom->vnum,
			 flag_string( direction_flags, &pReset->arg2 ),
			 pRoom->name );
	    break;
	}
    }
    send_to_char( final->data, ch );
    buffer_free( final );

    return;
}


/*****************************************************************************
 Name:		add_reset
 Purpose:	Inserts a new reset in the given index slot.
 Called by:	do_resets( olc.c ).
 ****************************************************************************/
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;
    SET_BIT( room->area->area_flags, AREA_CHANGED );
    return;
}


void do_resets( CHAR_DATA *ch, const char *argument )
{
    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];
    RESET_DATA *pReset = NULL;
    CHAR_DATA *rch;

    rch = get_char( ch );

    if( !authorized( rch, "resets" ) )
	return;

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

    /*
     * Display resets in current room.
     * -------------------------------
     */
    if( arg1[0] == '\0' )
    {
	if( ch->in_room->reset_first )
	{
	    send_to_char(
		"&gResets: &cM&g = mobile, &cR&g = room, &cO&g = object, "
		"&cP&g = pet, &cS&g = shopkeeper&n\n\r", ch );
	    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( pRoom->area->area_flags, 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 ) )
		|| ( !str_prefix( "rand", arg2 ) ) )
	    {
		/*
		 * Check for Mobile reset.
		 * -----------------------
		 */
		if( !str_cmp( arg2, "mob" ) )
		{
		    pReset = new_reset_data( );
		    pReset->command = 'M';
		    pReset->arg1 = atoi( arg3 );
		    pReset->arg2 = is_number( arg4 ) ? atoi( arg4 ) : 1;	/* Max # */
		}
		else
		    /*
		     * Check for Object reset.
		     * -----------------------
		     */
		    if( !str_cmp( arg2, "obj" ) )
		    {
			pReset = new_reset_data( );
			if( is_number( arg3 ) )
			    pReset->arg1 = atoi( arg3 );
			else
			{
			    do_resets( ch, "1 ?" );
			    free_reset_data( pReset );
			    return;
			}
			/*
			 * Inside another object.
			 * ----------------------
			 */
			if( !str_prefix( arg4, "inside" ) )
			{
			    pReset->command = 'P';
			    pReset->arg2 = is_number( arg5 ) ? atoi( arg5 ) : 1;
			}
			else
			    /*
			     * Inside the room.
			     * ----------------
			     */
			    if( !str_cmp( arg4, "room" ) )
			    {
				pReset->command = 'O';
				pReset->arg1 = atoi( arg3 );
				pReset->arg2 = 0;
			    }
			    else
				/*
				 * Into a Mobile's inventory.
				 * --------------------------
				 */
			    {
				if( flag_value( NULL, wear_loc_flags, arg4 ) == NO_FLAG )
				{
				    send_to_char( "Resets: '? wear-loc'\n\r", ch );
				    free_reset_data( pReset );
				    return;
				}
				pReset->arg2 = flag_value( NULL, wear_loc_flags, arg4 );
				if( pReset->arg2 == WEAR_NONE )
				    pReset->command = 'G';
				else
				    pReset->command = 'E';
			    }
		    }
		    else if( !str_prefix( "rand", arg2 ) )
		    {
			pReset = new_reset_data( );
			pReset->command = 'R';
			pReset->arg1 = ( arg3[0] != '\0' && is_number( arg3 ) )
			    ? atoi( arg3 ) : 6;
			if( pReset->arg1 == 0 )
			{
			    sprintf( arg3, "%s %s %s", arg4, arg5, argument );
			    if( arg4[0] == '\0'
				|| flag_value( NULL, direction_flags, arg3 ) == NO_FLAG )
			    {
				send_to_char( "Usage reset <num> rand 0 <directions>\n\r", ch );
				free_reset_data( pReset );
				return;
			    }
			    pReset->arg2 = flag_value( NULL, direction_flags, arg3 );
			}
		    }

		add_reset( ch->in_room, pReset, atoi( arg1 ) );
		send_to_char( "Reset added.\n\r", ch );
	    }
	    else
	    {
		send_to_char(
		    "Syntax: RESET <number> OBJ <vnum> <wear_loc>\n\r"
		    "        RESET <number> OBJ <vnum> in <vnum>\n\r"
		    "        RESET <number> OBJ <vnum> room\n\r"
		    "        RESET <number> MOB <vnum> [<max #>]\n\r"
		    "        RESET <number> RANDOMIZE <num>\n\r"
		    "        RESET <number> DELETE\n\r", ch );
	    }
    }

    return;
}


/*****************************************************************************
 Name:		do_alist
 Purpose:	Normal command to list areas and display area information.
 Called by:	interpreter( interp.c )
 ****************************************************************************/
void do_alist( CHAR_DATA *ch, const char *argument )
{
    BUFFER *result = buffer_new( MAX_STRING_LENGTH * 2 );
    AREA_DATA *pArea;
    CHAR_DATA *rch;
    char tmp[MAX_INPUT_LENGTH];

    rch = get_char( ch );

    if( !authorized( rch, "alist" ) )
	return;

    bprintf( result, "&b[&r%3s&b] [&m%-27s&b] &b(&c%-5s&b-&c%5s&b)"
	     " [&c%-10s&b] &r%3s&b[&g%-11s&b]&n\n\r",
	    "Num", "Area Name", "lvnum", "uvnum", "Filename", "Sec", "Builders" );

    for( pArea = area_first; pArea; pArea = pArea->next )
    {
	bprintf( result, "&b[&r%3d&b]&m %s &b(&c%-5d&b-&c%5d&b)",
		pArea->vnum,
		colour_strpad( tmp, pArea->name, 29 ),
		pArea->lvnum,
		pArea->uvnum );
	bprintf( result, "&c %s &b[&r%d&b]",
		colour_strpad( tmp, pArea->filename, 12 ),
		pArea->security );
	bprintf( result, "[&g%s&b]&n\n\r",
		colour_strpad( tmp, pArea->builders, 11 ) );
    }

    send_to_char( result->data, ch );
    buffer_free( result );
    return;
}


/*
  ===========================================================================
  This snippet was written by Erwin S. Andreasen, erwin@pip.dknet.dk. You may
  use this code freely, as long as you retain my name in all of the files. You
  also have to mail me telling that you are using it. I am giving this,
  hopefully useful, piece of source code to you for free, and all I require
  from you is some feedback.

  Please mail me if you find any bugs or have any new ideas or just comments.

  All my snippets are publically available at:

  http://pip.dknet.dk/~pip1773/

  If you do not have WWW access, try ftp'ing to pip.dknet.dk and examine
  the /pub/pip1773 directory.
  ===========================================================================
*/

typedef enum { exit_from, exit_to, exit_both } exit_status;

/* depending on status print > or < or <> between the 2 rooms */
void room_pair( ROOM_INDEX_DATA* left, ROOM_INDEX_DATA* right, exit_status ex,
		BUFFER *buf )
{
    const char *sExit;
    char tmp[MAX_INPUT_LENGTH];

    switch( ex )
    {
    default:
	sExit = "??"; break; /* invalid usage */
    case exit_from:
	sExit = "< "; break;
    case exit_to:
	sExit = " >"; break;
    case exit_both:
	sExit = "<>"; break;
    }

    bprintf( buf, "&g%5d %s &c%s", left->vnum, colour_strpad( tmp, left->name, 24 ),
	     sExit );
    bprintf( buf, "&g %5d %s", right->vnum, colour_strpad( tmp, right->name, 24 ) );
    bprintf( buf, "(%s)\n\r", colour_strpad( tmp, right->area->name, 12 ) );
}


/*
 * for every exit in 'room' which leads to or from pArea but NOT both, print it
 */
void checkexits( ROOM_INDEX_DATA *room, AREA_DATA *pArea, BUFFER *buf )
{
    int i;
    EXIT_DATA *exit;
    ROOM_INDEX_DATA *to_room;

    for( i = 0; i < 6; i++ )
    {
	exit = room->exit[i];
	if( !exit )
	    continue;
	else
	    to_room = exit->to_room;

	if( to_room )  /* there is something on the other side */
	{
	    if( ( room->area == pArea ) && ( to_room->area != pArea ) )
	    {
		/*
		 * an exit from our area to another area
		 * check first if it is a two-way exit
		 */
		if( to_room->exit[rev_dir[i]] &&
		     to_room->exit[rev_dir[i]]->to_room == room )
		    room_pair( room, to_room, exit_both, buf );
		else
		    room_pair( room, to_room, exit_to, buf );
	    }
	    else if( ( room->area != pArea )
		     && ( exit->to_room->area == pArea ) )
	    {
		/*
		 * an exit from another area to our area
		 * note that the twoway exits are taken care of above
		 */
		if( !( to_room->exit[rev_dir[i]]
		    && to_room->exit[rev_dir[i]]->to_room == room ) )
		    room_pair( to_room, room, exit_from, buf );
	    }
	}
    }
    return;
}


void do_exlist( CHAR_DATA *ch, const char *argument )
{
    CHAR_DATA *rch = get_char( ch );
    AREA_DATA *pArea;
    ROOM_INDEX_DATA *room;
    int i;
    BUFFER *buf = buffer_new( MAX_STRING_LENGTH );

    if( !authorized( rch, "exlist" ) )
	return;

    if( !str_cmp( argument, "area" ) )
    {
	pArea = get_editing_area( ch );
    }
    else if( is_number( argument ) )
    {
	pArea = get_area_data( atoi( argument ) );
    }
    else
	pArea = ch->in_room->area; /* this is the area we want info on */

    if( !IS_BUILDER( ch, pArea ) )
    {
	send_to_char( "You are not a builder for this area.\n\r", ch );
	return;
    }

    /*
     * Run through every room on the entire MUD
     */
    for( i = 0; i < MAX_KEY_HASH; i++ )
	for( room = room_index_hash[i]; room != NULL; room = room->next )
	    checkexits( room, pArea, buf );

    buffer_strcat( buf, "&n" );
    send_to_char( buf->data, ch );
    buffer_free( buf );
}


void do_poseset( CHAR_DATA *ch, const char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    int i;
    POSE_DATA *pose;
    CHAR_DATA *rch = get_char( ch );

    if( !authorized( rch, "poseset" ) )
	return;
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
    if( !str_prefix( arg1, "show" ) )
    {
	BUFFER * buf;
	int start, num, end;
	if( !str_prefix( arg2, "table" ) )
	{
	    buf = buffer_new( MAX_INPUT_LENGTH );
	    buffer_strcat( buf, "Pose statistics for all classes.\n\r" );
	    buffer_strcat( buf, "[Class         ] [#]  [Class         ] [#]\n\r" );
	    buffer_strcat( buf, "====================  ====================\n\r" );
	    for( i = 0; i < MAX_CLASS; ++i )
	    {
		bprintf( buf, "%-15s %4d", class_table[i].name,
			 pose_table[i].size );
		if( i % 2 )
		    buffer_strcat( buf, "\n\r" );
		else
		    buffer_strcat( buf, "  " );
	    }
	    if( i % 2 )
		buffer_strcat( buf, "\n\r" );
	    buffer_strcat( buf, "====================  ====================\n\r" );
	    send_to_char( buf->data, ch );
	    buffer_free( buf );
	    return;
	}
	for( i = 0; i < MAX_CLASS; ++i )
	    if( !str_cmp( arg2, class_table[i].who_name )
		|| !str_prefix( arg2, class_table[i].name ) )
		break;
	if( i >= MAX_CLASS )
	{
	    send_to_char( "That class doesn't exist.\n\r", ch );
	    return;
	}
	argument = one_argument( argument, arg1 );
	if( !is_number( arg1 ) )
	{
	    send_to_char( "Please specify the number of a pose to show.\n\r",
			  ch );
	    return;
	}
	start = atoi( arg1 );
	num = start;
	for( pose = pose_table[i].first; pose; pose = pose->next )
	    if( --num <= 0 )
		break;
	if( !pose )
	{
	    send_to_char( "That pose wasn't found.\n\r", ch );
	    return;
	}
	if( is_number( argument ) )
	    end = atoi( argument );
	else
	    end = start;
	if( end < start || end - start > 50 )
	{
	    send_to_char( "Usage: poseset show <class> <start#> <end#>\n\r",
			  ch );
	    return;
	}
	buf = buffer_new( MAX_INPUT_LENGTH );
	for( num = 0; pose && num <= end - start; num++ )
	{
	    bprintf( buf, "Pose number %d for the %s class:\n\r",
			start + num, class_table[i].name );
	    bprintf( buf, "  TO_CHAR: %s\n\r", pose->to_char );
	    bprintf( buf, "  TO_ROOM: %s\n\r", pose->to_room );
	    pose = pose->next;
	}
	send_to_char( buf->data, ch );
	buffer_free( buf );
	return;
    }
    if( !str_prefix( arg1, "edit" ) )
    {
	int which;
	for( i = 0; i < MAX_CLASS; ++i )
	    if( !str_cmp( arg2, class_table[i].who_name )
		|| !str_prefix( arg2, class_table[i].name ) )
		break;
	if( i >= MAX_CLASS )
	{
	    send_to_char( "That class doesn't exist.\n\r", ch );
	    return;
	}
	if( !is_number( argument ) )
	{
	    send_to_char( "Please specify the number of a pose to show.\n\r",
			  ch );
	    return;
	}
	which = atoi( argument );
	for( pose = pose_table[i].first; pose; pose = pose->next )
	    if( --which <= 0 )
		break;
	if( !pose )
	{
	    send_to_char( "That pose wasn't found.\n\r", ch );
	    return;
	}
	ch->desc->pEdit = pose;
	ch->desc->interpreter = get_interpreter( "PoseEdit" );
	poseedit_show( ch, "" );
	return;
    }
    if( !str_prefix( arg1, "create" ) )
    {
	if( poseedit_create( ch, arg2 ) )
	    ch->desc->interpreter = get_interpreter( "PoseEdit" );
	return;
    }
    do_help( ch, "poseset" );
    return;
}


bool poseedit_create( CHAR_DATA *ch, const char *argument )
{
    int i;
    POSE_DATA *pose;

    if( argument[0] == '\0' )
    {
	send_to_char( "Usage: create <class-name>\n\r", ch );
	return FALSE;
    }
    for( i = 0; i < MAX_CLASS; ++i )
	if( !str_cmp( argument, class_table[i].who_name )
	    || !str_prefix( argument, class_table[i].name ) )
	    break;
    if( i >= MAX_CLASS )
    {
	send_to_char( "Usage: create <class-name>\n\r", ch );
	return FALSE;
    }
    pose = new_pose_data( );
    pose->next = pose_table[i].first;
    pose_table[i].first = pose;
    pose_table[i].size++;
    ch->desc->pEdit = pose;
    ch->desc->interpreter = get_interpreter( "PoseEdit" );
    return TRUE;
}


bool poseedit_show( CHAR_DATA *ch, const char *argument )
{
    POSE_DATA *pPose;

    EDIT_POSE( ch, pPose );

    charprintf( ch, "TO_CHAR: %s\n\r", pPose->to_char );
    charprintf( ch, "TO_ROOM: %s\n\r", pPose->to_room );
    return FALSE;
}


bool poseedit_tochar( CHAR_DATA *ch, const char *argument )
{
    POSE_DATA *pPose;

    EDIT_POSE( ch, pPose );

    if( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  tochar <$message>\n\r", ch );
	return FALSE;
    }
    return sedit_change( ch, argument, &pPose->to_char, FALSE );
}


bool poseedit_toroom( CHAR_DATA *ch, const char *argument )
{
    POSE_DATA *pPose;

    EDIT_POSE( ch, pPose );

    if( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  toroom <$message>\n\r", ch );
	return FALSE;
    }
    return sedit_change( ch, argument, &pPose->to_room, FALSE );
}


bool pledit_show( CHAR_DATA *ch, const char *argument )
{
    PLANE_DATA *pPlane;

    EDIT_PLANE( ch, pPlane );

    charprintf( ch, "&gPlane:       &b[&c%s&b]&n\n\r", pPlane->name );
    charprintf( ch, "&gMinimum Lvl: &b[&c%d&b]&n\n\r", pPlane->min_level );

    return FALSE;
}


bool pledit_create( CHAR_DATA *ch, const char *argument )
{
    PLANE_DATA *pPlane;

    if( argument[0] == '\0' )
    {
	send_to_char( "Syntax: create <plane name>\n\r", ch );
	return FALSE;
    }

    pPlane = new_plane( );
    pPlane->name = str_dup( argument );

    ch->desc->pEdit = pPlane;
    ch->desc->interpreter = get_interpreter( "PlEdit" );

    send_to_char( "PlEdit: Plane created.\n\r", ch );
    return TRUE;
}


bool pledit_minimum( CHAR_DATA *ch, const char *argument )
{
    PLANE_DATA *pPlane;

    EDIT_PLANE( ch, pPlane );

    if( argument[0] == '\0' || !is_number( argument ) )
    {
	send_to_char( "Syntax: minimum <#min>\n\r", ch );
	return FALSE;
    }

    pPlane->min_level = atoi( argument );
    send_to_char( "PlEdit: Plane minimum level set.\n\r", ch );
    return FALSE;
}


bool pledit_name( CHAR_DATA *ch, const char *argument )
{
    PLANE_DATA *pPlane;

    EDIT_PLANE( ch, pPlane );
    if( argument[0] == '\0' )
    {
	send_to_char( "Syntax: name <$plane name>\n\r", ch );
	return FALSE;
    }

    free_string( pPlane->name );
    pPlane->name = str_dup( argument );
    send_to_char( "PlEdit: Plane name set.\n\r", ch );
    return FALSE;
}