atd/area/
atd/build/
atd/clans/
atd/log/
atd/player/store/
atd/site/
atd/src/bin/
/***************************************************************************
 *  God Wars Mud originally written by KaVir aka Richard Woolcock.         *
 *  Changes done to the code done by Sage aka Walter Howard, this mud is   *
 *  for the public, however if you run this code it means you agree        *
 *  to the license.low, license.gw, and license.merc have fun. :)          *
***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>	/* OLC 1.1b */
#include <time.h>
#include "merc.h"
#include "commands.h"
#include "build.h"


char     * spec_name   args(( SPEC_FUN * spec  ));
SPEC_FUN * spec_lookup args(( const char *name ));
bool       show_help   args(( CHAR_DATA *ch, char *argument ));

/*
 * Globals
 */
extern          int                     top_reset;
extern          int                     top_area;
extern          int                     top_exit;
extern          int                     top_ed;
extern          int                     top_room;

struct item_spells spells[];
AREA_DATA		*	area_free;
EXTRA_DESCR_DATA	*	extra_descr_free;
EXIT_DATA		*	exit_free;
ROOM_INDEX_DATA		*	room_index_free;
OBJ_INDEX_DATA		*	obj_index_free;
SHOP_DATA		*	shop_free;
MOB_INDEX_DATA		*	mob_index_free;
RESET_DATA		*	reset_free;
extern HELP_AREA * had_list;

const struct olc_cmd_type hedit_table[] =
{
    /*	{	command		function	}, */

    {	"keyword",	hedit_keyword	},
    {	"text",		hedit_text	},
    {	"new",		hedit_new	},
    {	"level",	hedit_level	},
    {	"delete",	hedit_delete	},
    {	"list",		hedit_list	},
    {	"show",		hedit_show	},

    {	"commands",	show_commands	},
    {   "?",            show_help       },
    {	"",		0		}
};

const struct olc_cmd_type medit_table[] =
{
/*  {	command		function	}, */
    {   "show",         medit_show              },
    {   "create",       medit_create            },
    {   "desc",         medit_desc              },
    {   "level",        medit_level             },
    {   "long",         medit_long              },
    {   "name",         medit_name              },
    {   "shop",         medit_shop              },
    {   "short",        medit_short             },
    {   "alignment",    medit_align             },
    {   "spec",         medit_spec              },
    {   "commands",     show_commands           },

    {   "?",            show_help               },
    {   "",             0,                      }
};

const struct olc_cmd_type aedit_table[] =
{
    {   "age",          aedit_age               },
    {   "builders",     aedit_builder           },
    {   "create",       aedit_create            },
    {   "filename",     aedit_filename          },
    {   "name",         aedit_name              },
    {   "reset",        aedit_reset             },
    {   "security",     aedit_security          },
    {   "show",         aedit_show              },
    {   "vnum",         aedit_vnum              },
    {   "lvnum",        aedit_lvnum             },
    {   "uvnum",        aedit_uvnum             },
    {   "mod",          aedit_mod               },
    {   "connected",    aedit_connected         },    
    {   "commands",     show_commands           },
    {   "?",            show_help               },
    {   "",             0,                      }
};


const struct olc_cmd_type oedit_table[] =
{

    {   "addaffect",    oedit_addaffect         },
    {   "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            },
    {   "weight",       oedit_weight            },
    {   "artifact",     oedit_artifact          },

    {   "commands",     show_commands           },
    {   "?",            show_help               },
    {   "",             0,                      }
};


const struct olc_cmd_type redit_table[] =
{

    {   "create",       redit_create            },
    {   "desc",         redit_desc              },
    {   "ed",           redit_ed                },
    {   "format",       redit_format            },
    {   "name",         redit_name              },
    {   "show",         redit_show              },
    {   "copy",         redit_copy              },
    {   "north",        redit_north             },
    {   "south",        redit_south             },
    {   "east",         redit_east              },
    {   "west",         redit_west              },
    {   "up",           redit_up                },
    {   "down",         redit_down              },
    {   "walk",         redit_move              },
    {   "roomtext",     redit_roomtext          },
    {   "mreset",       redit_mreset            },
    {   "oreset",       redit_oreset            },
    {   "findreset",    redit_findreset         },

    {   "?",            show_help               },
    {   "commands",     show_commands           },
    {   "",             0,                      }
};

const struct olc_cmd_type cedit_table[] =
{
    {   "show",         cedit_show              },
    {   "savefreq",     cedit_savefreq          },
    {   "dodgemod",     cedit_dodgemod          },
    {   "parrymod",     cedit_parrymod          },
    {   "dam_pvp",      cedit_dam_pvp           },
    {   "dam_pvm",      cedit_dam_pvm           },
    {   "dam_mvp",      cedit_dam_mvp           },
    {   "dam_mvm",      cedit_dam_mvm           },
    {   "plr_mset",     cedit_plr_mset          },
    {   "forcepc",      cedit_forcepc           },
    {   "ban_clas",     cedit_ban_class         },
    {   "ban_site",     cedit_ban_site          },
    {   "cleanpfiles",  cedit_pfiles            },
    {   "newbie_purge", cedit_newbie_purge      },
    {   "regular_purge",cedit_regular_purge     },   
    {   "?",            show_help               },
    {   "commands",     show_commands           },
    {   "",             0,                      }
};

const struct olc_cmd_type cledit_table[] =
{
/*  {	command		function		}, */

    { "create",		cledit_create    },
    { "filename",       cledit_filename  },
    { "description",	cledit_desc      },
    { "display",	cledit_display   },
    { "motto",		cledit_motto     },
    { "name",		cledit_name      },
    { "leader",		cledit_leader    },
    { "recall",		cledit_recall    },
    { "obj_1",          cledit_obj1      },
    { "obj_2",          cledit_obj2      },
    { "obj_3",          cledit_obj3      },
    { "recall",         cledit_recall    },
    { "show",		cledit_show	 },
    { "story",		cledit_desc	 },

    { "?",		show_help	 },
    { "commands",	show_commands	 },

    { "",               0               }
};

const struct olc_cmd_type rename_obj_table[] =
{
/*  {   command         function                }, */

    {   "keyword",	rename_keyword		},
    {	"short",	rename_short		},
    {	"long",		rename_long		},
    {   "show",         rename_show             },

    {	"1",		rename_keyword		},
    {	"2",		rename_short		},
    { 	"3",		rename_long		},

    {   "commands",	show_commands		},

    {   "",            	0,                      }
};


/*
 * This table contains help commands and a brief description of each.
 * ------------------------------------------------------------------
 */
const struct olc_help_type help_table[] =
{
    {	"area",		area_flags,	 8, "Area attributes."		   },
    {	"room",		room_flags,	 8, "Room attributes."		   },
    {	"sector",	sector_flags,	 8, "Sector types, terrain."	   },
    {	"exit",		exit_flags,	 8, "Exit types."		   },
    {	"type",		type_flags,	 8, "Types of objects."		   },
    {	"extra",	extra_flags,	 8, "Object attributes."	   },
    {	"wear",		wear_flags,	 8, "Where to wear object."	   },
    {	"spec",		spec_table,	 8, "Available special programs."  },
    {	"sex",		sex_flags,	 8, "Sexes."			   },
    {	"act",		act_flags,	 8, "Mobile attributes."	   },
    {	"affect",	affect_flags,	 8, "Mobile affects."		   },
    {	"wear-loc",	wear_loc_flags,	 8, "Where mobile wears object."   },
    {	"spells",	skill_table,	 8, "Names of current spells." 	   },
    {	"weapon",	weapon_flags,	 8, "Type of weapon." 		   },
    {	"container",	container_flags, 8, "Container status."		   },
    {   "apply",        apply_flags,     8, "Types of Obj applys."         },
    {	"liquid",	liquid_flags,	 8, "Types of liquids."	           },
    {   "itemspells",   spells,          8, "Different item affect spells" },
    {   "log",          log_flags,      10, "Types of logs"                },
    {   "newbits",      newbit_flags,   10, "Types of NewBits"             },
    {   "plr_flags",    plr_flags,      10, "Player flags (ActBit)"        },
    {   "immunties",    imm_flags,      10, "Immunites"                    },
    {   "itemaflags",   itema_flags,    10, "ItemAffects"                  },
    {   "position",     position_flags, 10, "Position types"               },
    {   "levels",       level_flags,    10, "Levels"                       },
    {   "worldflags",   world_flags,    9,  "World Flags"                  },
    {   "cmd_show",     show_flags,     10, "CmdShow"                      },
    {   "rt_types",     rt_flags,       8,  "RoomText Types - help 'type'" },
    {   "weap_flags",   weap_flags,     10, "WeaponFlags"                  },
    {	"",		0,		0,  ""				   }
};

/*
 * Flag Tables
 */


struct item_spells spells[] =
{
    { "Infared",   1, "%s allows the wearer to see in the dark."  },
    { "Dinvis",    2, "%s allows the wearer to see invisible things."},
    { "Flying",    3, "%s grants the power of flight."  },
    { "Blind",     4, "%s radiates and aura of darkness."  },
    { "Invis",     5, "%s makes the owner invisible to the human eye." },
    { "Pdoor",     6, "%s allows the wearer to walk through solid doors."},
    { "Protect",   7, "%s protects the wearer from evil." },
    { "Sanc",      8, "%s protects the wearer in combat." },
    { "Sneak",     9, "%s allows the wearer to walk in complete silence." },
    { "Shockshld", 10,"This powerful %s surrounds its wielder with a shield of lightning." },
    { "Fireshld",  11,"This powerful %s surrounds its wielder with a shield of fire."},
    { "Acidshld",  12,"This powerful %s surrounds its wielder with a shield of acid."},
    { "Iceshld",   13,"This powerful %s surrounds its wielder with a shield of lightning."},
    { "Dbpass",    14,"%s protects you from clan DarkBlade guardians." },
    { "Chaos",     15,"This ancient %s is the wielder of chaos." },
    { "Regen",     16,"This ancient %s regenerates the wounds of the wearer."},
    { "Speed",     17,"This %s allows you to move increedibly fast."},
    { "Vorpal",    18,"This %s sucks the blood from its victims."},
    { "Peace",     19,"This ancient %s protects its wearer from player attacks." },
    { "Reflect",   20,"This ancient %s surrounds its wielder with a shield of darkness."},
    { "Resist",    21,"This ancient %s grants superior protection to its wielder."},
    { "Vision",    22,"This ancient %s grants its wielder supernatural vision."},
    { "Stalker",   23,"This ancient %s makes its wielder fleet-footed."},
    { "Vanish",    24,"This ancient %s conceals its wielder from sight."},
    { "Rager",     25,"This ancient %s invokes the power of the beast."},
    { "Totalblind",26,"This %s causes you to be blind."},
    { "criticals", 27,"This %s cause's you to find your opponents weakness." },
    { "Dhid",      60,"This ancient %s hides you from sight."},
    { NULL,        -1,NULL}
};

/*
 * Remove carriage returns from a line
 */
char *strip_cr( char *str )
{
    static char newstr[MAX_STRING_LENGTH];
    int i, j;

    if( str == NULL )
        return '\0';
    
    for ( i=j=0; str[i] != '\0'; i++ )
	if ( str[i] != '\r' || str[i] == '~')
	{
	  newstr[j++] = str[i];	
	}
    newstr[j] = '\0';
    return newstr;
}


/*
 * Removes the tildes from a line, except if it's the last character.
 */
void smush_tilde( char *str )
{
    int len;
    char last;
    char *strptr;
    
    strptr = str;
    
    len  = strlen( str );
    if ( len )
      last = strptr[len-1];
    else
      last = '\0';

    for ( ; *str != '\0'; str++ )
    {
	if ( *str == '~' )
	    *str = '-';
    }
    if ( len )
      strptr[len-1] = last;

    return;
}



HELP_AREA * had_lookup( char *arg )
{
    HELP_AREA * temp;

    for ( temp = had_list; temp; temp = temp->next )
        if ( !str_cmp( arg, temp->filename ) )
            return temp;

    return NULL;
}

CLAN_DATA *clan_vnum ( char *buf )
{
    CLAN_DATA *clan = NULL;
    int vnum;
    int x;
    if( buf[0] == '\0' || !is_number( buf ) )
    	return NULL;

    vnum = atoi( buf );
    x = -1;
    for( clan = clan_first; clan; clan = clan->next )
    {
	if( x == vnum )
		return clan;
	x++;
    }
    return NULL;
}

CLAN_DATA *clan_lookup( const char *name )
{
    CLAN_DATA *clan = NULL;
    for( clan = clan_first; clan; clan = clan->next )
	if( is_name( name, clan->name ) )
	    break;
    return clan;
}

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[0] != '\0'; 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;
}

bool show_commands( CHAR_DATA *ch, char *argument )
{
    switch (ch->desc->editor)
    {
    case ED_MOBILE: show_olc_cmds( ch, medit_table ); break;
    case ED_HELP:   show_olc_cmds( ch, hedit_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_CMD:    show_olc_cmds( ch, cmdedit_table ); break;
    case ED_SOCIAL: show_olc_cmds( ch, sedit_table ); break;
    case ED_CONTROL:show_olc_cmds( ch, cedit_table ); break;
    case ED_CLAN:   show_olc_cmds( ch, cledit_table ); break;
    case ED_RENAME: show_olc_cmds( ch, rename_obj_table ); break;
    }

    return FALSE;
}





void show_spec_cmds( CHAR_DATA *ch )
{
    char buf  [ MAX_STRING_LENGTH ];
    char buf1 [ MAX_STRING_LENGTH ];
    int  spec;
    int  col;

extern const struct spec_type spec_table []; 
    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; spec++)
    {
	sprintf( buf, "%-19.18s", &spec_table[spec].name[5] );
	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_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;
}

void show_itemspells( CHAR_DATA *ch )
{
	char buf  [ MSL ];
	char buf1 [ MSL ];
       
        int cnt;
	buf1[0] = '\0';
        for( cnt = 0; spells[cnt].name; cnt++ )
        {
            sprintf(buf, "%-15.15s",spells[cnt].name );
	    strcat( buf1, buf );
            if( cnt % 5 == 0 ) 
   		strcat( buf1, "\n\r" );
            else 
		strcat( buf1, " ");
        }
        stc( buf1, ch );
};

/*****************************************************************************
 Name:		do_qhelp
 Purpose:	Displays help for many tables used in OLC.

****************************************************************************/
void do_qhelp( CHAR_DATA *ch, char *argument )
{
    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' )
    {
	send_to_char( "Syntax: qhelp <command>\n\r",    ch );
	send_to_char( "\n\r",                       ch );
	send_to_char( "Command being one of:\n\r",  ch );
	for (cnt = 0; help_table[cnt].command[0] != '\0'; cnt++)
            if( get_trust(ch) >= help_table[cnt].trust )
		ch_printf( ch, "%-14.14s    %s\n\r",
			   capitalize( help_table[cnt].command ),
			   help_table[cnt].desc );
	return;
    }

    /*
     * Find the command, show changeable data.
     * ---------------------------------------
     */
    for (cnt = 0; *help_table[cnt].command
	        && help_table[cnt].trust <= get_trust(ch); cnt++)
    {
        if (  arg[0] == help_table[cnt].command[0]
	      && !str_prefix( arg, help_table[cnt].command ) )
	{
	    if ( help_table[cnt].structure == spec_table )
	    {
		show_spec_cmds( ch );
		return;
	    }
	    else
	    if ( help_table[cnt].structure == spells )
	    {
		show_itemspells( ch );
		return;
	    }
	    if ( help_table[cnt].structure == skill_table )
	    {

		if ( spell[0] == '\0' )
		{
		    send_to_char( "Syntax:  ? spells "
		        "[ignore/attack/defend/self/object/all]\n\r", ch);
		    return;
		}

		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;
	    }
	    else
	    {
		show_flag_cmds( ch, help_table[cnt].structure );
		return;
	    }
	}
    }

    do_qhelp( ch, "" );
    return;
}


/*****************************************************************************
 Name:		show_help
 Purpose:	Displays help for many tables used in OLC.
 Called by:	olc interpreters.

****************************************************************************/
bool show_help( CHAR_DATA *ch, char *argument )
{
    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' )
    {
	send_to_char( "Syntax:  ? [command]\n\r\n\r", ch );
	send_to_char( "[command]  [description]\n\r", ch );
	for (cnt = 0; help_table[cnt].command[0] != '\0'; cnt++)
            if( get_trust(ch) >= help_table[cnt].trust )
		ch_printf( ch, "%-10.10s -%s\n\r",
			   capitalize( help_table[cnt].command ),
			   help_table[cnt].desc );
	return FALSE;
    }

    /*
     * Find the command, show changeable data.
     * ---------------------------------------
     */
    for (cnt = 0; *help_table[cnt].command
	        && help_table[cnt].trust <= get_trust(ch); cnt++)
    {
        if (  arg[0] == help_table[cnt].command[0]
	      && !str_prefix( arg, help_table[cnt].command ) )
	{
	    if ( help_table[cnt].structure == spec_table )
	    {
		show_spec_cmds( ch );
		return FALSE;
	    }
	    else
	    if ( help_table[cnt].structure == spells )
	    {
		show_itemspells( ch );
		return FALSE;
	    }
	    if ( help_table[cnt].structure == skill_table )
	    {

		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, help_table[cnt].structure );
		return FALSE;
	    }
	}
    }

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

/* Executed from comm.c.  Minimizes compiling when changes are made. */
bool run_olc_editor( DESCRIPTOR_DATA *d )
{
    switch ( d->editor )
    {
    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_HELP:
        hedit( d->character, d->incomm );
        break;
    case ED_CMD:
        cmdedit( d->character, d->incomm );
        break;
    case ED_SOCIAL:
	sedit( d->character, d->incomm );
	break;
    case ED_CONTROL:
	cedit( d->character, d->incomm );
	break;
    case ED_CLAN:
	cledit( d->character, d->incomm );
	break;
    case ED_RENAME:
	rename_object( 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_CONTROL:
	sprintf( buf, "CEdit" );
	break;
    case ED_CLAN:
	sprintf( buf, "CLEdit" );
	break;
    default:
        sprintf( buf, " " );
        break;
    }
    return buf;
}



char *olc_ed_vnum( CHAR_DATA *ch )
{
    AREA_DATA *pArea;
    ROOM_INDEX_DATA *pRoom;
    OBJ_INDEX_DATA *pObj;
    MOB_INDEX_DATA *pMob;
    CLAN_DATA *pClan;

    static char buf[10];
        
    buf[0] = '\0';
    switch ( ch->desc->editor )
    {
    case ED_AREA:
        pArea = (AREA_DATA *)ch->desc->pEdit;
        sprintf( buf, "%d", pArea ? pArea->vnum : 0 );
        break;
    case ED_ROOM:
        pRoom = ch->in_room;
        sprintf( buf, "%d", pRoom ? pRoom->vnum : 0 );
        break;
    case ED_OBJECT:
        pObj = (OBJ_INDEX_DATA *)ch->desc->pEdit;
        sprintf( buf, "%d", pObj ? pObj->vnum : 0 );
        break;
    case ED_MOBILE:
        pMob = (MOB_INDEX_DATA *)ch->desc->pEdit;
        sprintf( buf, "%d", pMob ? pMob->vnum : 0 );
        break;
    case ED_CLAN:
	pClan = (CLAN_DATA *)ch->desc->pEdit;
	sprintf( buf, "%s", pClan ? pClan->filename : "");
	break;	
    default:
        sprintf( buf, " " );
        break;
    }

    return buf;
}


/*
 * Memory Recycling
 */
RESET_DATA *new_reset_data(void)
{
    RESET_DATA *pReset;

    if (reset_free == NULL)
    {
        pReset          =   alloc_perm(sizeof(*pReset));
        top_reset++;
    }
    else
    {
        pReset          =   reset_free;
        reset_free      =   reset_free->next;
    }

    pReset->next        =   NULL;
    pReset->command     =   'X';
    pReset->arg1        =   0;
    pReset->arg2        =   0;
    pReset->arg3        =   0;

    return pReset;
}



void free_reset_data(RESET_DATA *pReset)
{
    pReset->next            = reset_free;
    reset_free              = pReset;
    return;
}

extern HELP_AREA * had_free;

HELP_AREA * new_had args( ( void ) );
 
HELP_DATA * help_free;
 
HELP_DATA * new_help ( void )
{
	HELP_DATA * help;
 
	if ( help_free )
	{
		help		= help_free;
		help_free	= help_free->next;
	}
	else
		help		= alloc_perm( sizeof( *help ) );
 
	return help;
}
 
void free_help(HELP_DATA *help)
{
	free_string(help->keyword);
	free_string(help->text);
	help->next = help_free;
	help_free = help;
}


AREA_DATA *new_area(void)
{
    AREA_DATA *pArea;
    char buf[MAX_INPUT_LENGTH];

    if (area_free == NULL)
    {
        pArea   =   alloc_perm(sizeof(*pArea));
        top_area++;
    }
    else
    {
        pArea       =   area_free;
        area_free   =   area_free->next;
    }

    pArea->next             =   NULL;
    pArea->name             =   str_dup("New area");
    pArea->area_flags       =   AREA_ADDED | AREA_UNLINKED;
    pArea->security         =   1;
    pArea->builders         =   str_dup("None");
    pArea->lvnum            =   0;
    pArea->uvnum            =   0;
    pArea->age              =   0;
    pArea->nplayer          =   0;
    sprintf(buf, "area%d.are", pArea->vnum);
    pArea->filename         =   str_dup(buf);
    pArea->vnum             =   top_area-1;
    pArea->mod              =   0;
    pArea->bits             =   0;
    return pArea;
}



void free_area(AREA_DATA *pArea)
{
    free_string(pArea->name);
    free_string(pArea->filename);
    free_string(pArea->builders);

    pArea->next         =   area_free->next;
    area_free           =   pArea;
    return;
}



EXIT_DATA *new_exit(void)
{
    EXIT_DATA *pExit;

    if (exit_free == NULL)
    {
        pExit           =   alloc_perm(sizeof(*pExit));
        top_exit++;
    }
    else
    {
        pExit           =   exit_free;
        exit_free       =   exit_free->next;
    }

    pExit->to_room      =   NULL;
    pExit->next         =   NULL;
    pExit->vnum         =   0;
    pExit->exit_info    =   0;
    pExit->key          =   0;

    free_string( pExit->keyword );
    pExit->keyword      =   str_dup("");
    free_string( pExit->description );
    pExit->description  =   str_dup("");
    pExit->rs_flags     =   0;

    return pExit;
}



void free_exit(EXIT_DATA *pExit)
{
    free_string(pExit->keyword);
    free_string(pExit->description);

    pExit->next         =   exit_free;
    exit_free           =   pExit;
    return;
}



EXTRA_DESCR_DATA *new_extra_descr(void)
{
    EXTRA_DESCR_DATA *pExtra;

    if (extra_descr_free == NULL)
    {
        pExtra              =   alloc_perm(sizeof(*pExtra));
        top_ed++;
    }
    else
    {
        pExtra              =   extra_descr_free;
        extra_descr_free    =   extra_descr_free->next;
    }

    pExtra->keyword          =   NULL;
    pExtra->description     =   NULL;
    pExtra->next            =   NULL;

    return pExtra;
}



void free_extra_descr(EXTRA_DESCR_DATA *pExtra)
{
    free_string(pExtra->keyword);
    free_string(pExtra->description);

    pExtra->next        =   extra_descr_free;
    extra_descr_free    =   pExtra;
    return;
}



ROOM_INDEX_DATA *new_room_index(void)
{
    ROOM_INDEX_DATA *pRoom;
    int i;

    if (room_index_free == NULL)
    {
        pRoom           =   alloc_perm(sizeof(*pRoom));
        top_room++;
    }
    else
    {
        pRoom           =   room_index_free;
        room_index_free =   room_index_free->next;
    }

    pRoom->next             =   NULL;
    pRoom->people           =   NULL;
    pRoom->contents         =   NULL;
    pRoom->extra_descr      =   NULL;
    pRoom->area             =   NULL;
    for (i = 0; i < MAX_DIR; i++)
    {
        pRoom->exit[i]      =   NULL;
        pRoom->track_dir[i]     = 0;
	pRoom->track[i]     =   str_dup("");
    }
    pRoom->name             =   &str_empty[0];
    pRoom->description      =   &str_empty[0];
    pRoom->vnum             =   0;
    pRoom->room_flags       =   0;
    pRoom->light            =   0;
    pRoom->sector_type      =   0;
    pRoom->roomtext         =   NULL;
    pRoom->affected         =   NULL;
    pRoom->affected_by      =   0;
    return pRoom;
}



void free_room_index(ROOM_INDEX_DATA *pRoom)
{
    int i;
    EXTRA_DESCR_DATA *pExtra;

    free_string(pRoom->name);
    free_string(pRoom->description);

    for (i = 0; i < MAX_DIR; i++) 
    {
        if (pRoom->exit[i] != NULL)
            free_exit(pRoom->exit[i]);
	if (pRoom->track[i])
	    free_string( pRoom->track[i]);
    }

    for (pExtra = pRoom->extra_descr; pExtra != NULL; pExtra = pExtra->next) {
        free_extra_descr(pExtra);
    }

    pRoom->next     =   room_index_free;
    room_index_free =   pRoom;
    return;
}



AFFECT_DATA *new_affect(void)
{
    AFFECT_DATA *pAf;

    if (affect_free == NULL)
    {
        pAf             =   alloc_perm(sizeof(*pAf));
        top_affect++;
    }
    else
    {
        pAf             =   affect_free;
        affect_free     =   affect_free->next;
    }

    pAf->next       =   NULL;
    pAf->location   =   0;
    pAf->modifier   =   0;
    pAf->type       =   0;
    pAf->duration   =   0;
    pAf->bitvector  =   0;

    return pAf;
}



void free_affect(AFFECT_DATA* pAf)
{
    pAf->next           = affect_free;
    affect_free         = pAf;
    return;
}



SHOP_DATA *new_shop(void)
{
    SHOP_DATA *pShop;
    int buy;

    if (shop_free == NULL)
    {
        pShop           =   alloc_perm(sizeof(*pShop));
        top_shop++;
    }
    else
    {
        pShop           =   shop_free;
        shop_free       =   shop_free->next;
    }

    pShop->next         =   NULL;
    pShop->keeper       =   0;

    for (buy=0; buy<MAX_TRADE; buy++)
        pShop->buy_type[buy]    =   ITEM_NONE;

    pShop->profit_buy   =   100;
    pShop->profit_sell  =   100;
    pShop->open_hour    =   0;
    pShop->close_hour   =   23;

    return pShop;
}



void free_shop(SHOP_DATA *pShop)
{
    pShop->next = shop_free;
    shop_free   = pShop;
    return;
}



OBJ_INDEX_DATA *new_obj_index(void)
{
    OBJ_INDEX_DATA *pObj;
    int value;

    if (obj_index_free == NULL)
    {
        pObj           =   alloc_perm(sizeof(*pObj));
        top_obj_index++;
    }
    else
    {
        pObj            =   obj_index_free;
        obj_index_free  =   obj_index_free->next;
    }

    pObj->next          =   NULL;
    pObj->extra_descr   =   NULL;
    pObj->affected      =   NULL;
    pObj->area          =   NULL;
    pObj->name          =   str_dup("no name");
    pObj->short_descr   =   str_dup("(no short description)");
    pObj->description   =   str_dup("(no description)");
    pObj->vnum          =   0;
    pObj->item_type     =   ITEM_TRASH;
    pObj->extra_flags   =   0;
    pObj->wear_flags    =   0;
    pObj->count         =   0;
    pObj->weight        =   0;
    pObj->cost          =   0;
    pObj->quest         =   0;
    for (value=0; value<MAX_OVALUE; value++)
        pObj->value[value]  =   0;

    return pObj;
}



void free_obj_index(OBJ_INDEX_DATA *pObj)
{
    EXTRA_DESCR_DATA *pExtra;
    AFFECT_DATA *pAf;

    free_string(pObj->name);
    free_string(pObj->short_descr);
    free_string(pObj->description);

    for (pAf = pObj->affected; pAf != NULL; pAf = pAf->next)
    {
        free_affect(pAf);
    }

    for (pExtra = pObj->extra_descr; pExtra != NULL; pExtra = pExtra->next)
    {
        free_extra_descr(pExtra);
    }
    
    pObj->next              = obj_index_free;
    obj_index_free          = pObj;
    return;
}



MOB_INDEX_DATA *new_mob_index(void)
{
    MOB_INDEX_DATA *pMob;

    if (mob_index_free == NULL)
    {
        pMob           =   alloc_perm(sizeof(*pMob));
        top_mob_index++;
    }
    else
    {
        pMob            =   mob_index_free;
        mob_index_free  =   mob_index_free->next;
    }

    pMob->next          =   NULL;
    pMob->spec_fun      =   NULL;
    pMob->pShop         =   NULL;
    pMob->area          =   NULL;
    pMob->player_name   =   str_dup("no name");
    pMob->short_descr   =   str_dup("(no short description)");
    pMob->long_descr    =   str_dup("(no long description)");
    pMob->description   =   str_dup("");
    pMob->vnum          =   0;
    pMob->count         =   0;
    pMob->killed        =   0;
    pMob->sex           =   0;
    pMob->level         =   0;
    pMob->act           =   1;	/* NPC */
    pMob->affected_by   =   0;
    pMob->alignment     =   0;
    pMob->hitroll	=   0;
    pMob->ac	        =   0;
    pMob->hitnodice	=   0;
    pMob->hitsizedice	=   0;
    pMob->hitplus	=   0;
    pMob->damnodice	=   0;
    pMob->damsizedice	=   0;
    pMob->damplus	=   0;
    pMob->gold          =   0;

    return pMob;
}



void free_mob_index(MOB_INDEX_DATA *pMob)
{
    free_string(pMob->player_name);
    free_string(pMob->short_descr);
    free_string(pMob->long_descr);
    free_string(pMob->description);

    free_shop(pMob->pShop);

    pMob->next              = mob_index_free;
    mob_index_free          = pMob;
    return;
}



/*
 * End Memory Recycling
 */

AREA_DATA *get_area_data(int vnum)
{
    AREA_DATA *pArea;

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

    return NULL;
}


bool check_range( int lower, int upper )
{
    AREA_DATA *pArea;
    int cnt = 0;

    for ( pArea = area_first; pArea; pArea = pArea->next )
    {
	/*
	 * lower < area < upper
	 */
	if ( ( lower <= pArea->lvnum && upper >= pArea->lvnum )
	||   ( upper >= pArea->uvnum && lower <= pArea->uvnum ) )
	    cnt++;

	if ( cnt > 1 )
	    return FALSE;
    }
    return TRUE;
}

AREA_DATA *get_vnum_area(int vnum)
{
    AREA_DATA *pArea;

    for (pArea = area_first; pArea != NULL; pArea = pArea->next)
    {
        if (vnum >= pArea->lvnum
          && vnum <= pArea->uvnum)
            return pArea;
    }

    return NULL;
}

/************************************************************************
 * Editors
 ************************************************************************/
bool    edit_done (CHAR_DATA * ch)
{

    if (ch->desc->editor != ED_NONE)
        send_to_char("You exit the editor.\n\r", ch);
    ch->desc->pEdit = NULL;
    ch->desc->editor = ED_NONE;
    return FALSE;
}

void set_editor( DESCRIPTOR_DATA *d, int editor, void * param )
{
	d->editor = editor;
	d->pEdit = param;
}

/*
 * Now for the prime editor functions
 */
AEDIT(aedit_mod)
{
    AREA_DATA *pArea;

    EDIT_AREA( ch, pArea );

    if( !argument || !is_number(argument))
    {
	send_to_char("Syntax: mod [##]\n\r", ch );
	return FALSE;
    }

    pArea->mod = atoi(argument);
    send_to_char("Area mod set.\n\r",ch);
    return TRUE;
}

bool aedit_reset( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;

    EDIT_AREA(ch, pArea);

    reset_area( pArea );
    send_to_char( "Area reset.\n\r", ch );

    return FALSE;
}

AEDIT(aedit_show)
{
    AREA_DATA *pArea;
    char buf [ MAX_STRING_LENGTH ];

    EDIT_AREA( ch, pArea );

    sprintf(buf, "%d", pArea->vnum);
    do_ashow(ch, buf);
    return FALSE;
}

AEDIT(aedit_connected)
{
    AREA_DATA *pArea;
    ROOM_INDEX_DATA *pRoom; 
    char buf  [MAX_STRING_LENGTH];
    int i;
    
    EDIT_AREA(ch, pArea);

    for( i = 0; i < MAX_KEY_HASH; i++ )
    {
        for( pRoom = room_index_hash[i]; pRoom; pRoom = pRoom->next )
        {
            checkexits( pRoom, pArea, buf);
            stc( buf, ch );
        }
    }
    return FALSE;
}

AEDIT(aedit_create)
{
    AREA_DATA *pArea;
    
    pArea               =   new_area();
    area_last->next     =   pArea;


    send_to_char("Area created.\n\r", ch);
    set_editor( ch->desc, ED_AREA, pArea );
    return TRUE;
}

AEDIT(aedit_name)
{
    AREA_DATA *pArea;
    char       arg2[MAX_INPUT_LENGTH];
    
    EDIT_AREA( ch, pArea );

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

    free_string(pArea->name);
    pArea->name = str_dup(arg2);

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

AEDIT( aedit_filename )
{
    AREA_DATA *pArea;
    char file[MAX_STRING_LENGTH];
    int i, length;

    EDIT_AREA(ch, pArea);

    one_argument( argument, file );	/* Forces Lowercase */

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

    /*
     * Simple Syntax Check.
     */
    length = strlen( argument );
    if ( length > 8 )
    {
	send_to_char( "No more than eight characters allowed.\n\r", ch );
	return FALSE;
    }

    /*
     * Allow only letters and numbers.
     */
    for ( i = 0; i < length; i++ )
    {
	if ( !isalnum( file[i] ) )
	{
	    send_to_char( "Only letters and numbers are valid.\n\r", ch );
	    return FALSE;
	}
    }    

    free_string( pArea->filename );
    strcat( file, ".are" );
    pArea->filename = str_dup( file );

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

bool aedit_age( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char age[MAX_STRING_LENGTH];

    EDIT_AREA(ch, pArea);

    one_argument( argument, age );

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

    pArea->age = atoi( age );

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




bool aedit_security( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char sec[MAX_STRING_LENGTH];
    char buf[MAX_STRING_LENGTH];
    int  value;

    EDIT_AREA(ch, pArea);

    one_argument( argument, sec );

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

    value = atoi( sec );

    if ( value > ch->pcdata->security || value < 0 )
    {
	if ( ch->pcdata->security != 0 )
	{
	    sprintf( buf, "Security is 0-%d.\n\r", ch->pcdata->security );
	    send_to_char( buf, ch );
	}
	else
	    send_to_char( "Security is 0 only.\n\r", ch );
	return FALSE;
    }

    pArea->security = value;

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



bool aedit_builder( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char name[MAX_STRING_LENGTH];
    char buf[MAX_STRING_LENGTH];

    EDIT_AREA(ch, pArea);

    one_argument( argument, name );

    if ( name[0] == '\0' )
    {
	send_to_char( "Syntax:  builder [$name]  -toggles builder\n\r", ch );
	send_to_char( "Syntax:  builder All      -allows everyone\n\r", ch );
	return FALSE;
    }

    name[0] = UPPER( name[0] );

    if ( strstr( pArea->builders, name ) != '\0' )
    {
	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 );
	return TRUE;
    }
    else
    {
	buf[0] = '\0';
	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( buf, pArea->builders );
	    strcat( buf, " " );
	}
	strcat( buf, name );
	free_string( pArea->builders );
	pArea->builders = string_proper( str_dup( buf ) );

	send_to_char( "Builder added.\n\r", ch );
	return TRUE;
    }

    return FALSE;
}



bool aedit_vnum( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char lower[MAX_STRING_LENGTH];
    char upper[MAX_STRING_LENGTH];
    int  ilower;
    int  iupper;

    EDIT_AREA(ch, pArea);

    argument = one_argument( argument, lower );
    one_argument( argument, upper );

    if ( !is_number( lower ) || lower[0] == '\0'
    || !is_number( upper ) || upper[0] == '\0' )
    {
	send_to_char( "Syntax:  vnum [#lower] [#upper]\n\r", ch );
	return FALSE;
    }

    if ( ( ilower = atoi( lower ) ) > ( iupper = atoi( upper ) ) )
    {
	send_to_char( "AEdit:  Upper must be larger then lower.\n\r", ch );
	return FALSE;
    }
    
    /* OLC 1.1b */
    if ( ilower <= 0 || ilower >= INT_MAX || iupper <= 0 || iupper >= INT_MAX )
    {
	char output[MAX_STRING_LENGTH];

	sprintf( output, "AEdit: vnum must be between 0 and %d.\n\r", INT_MAX );
	send_to_char( output, ch );
	return FALSE;
    }

    if ( !check_range( ilower, iupper ) )
    {
	send_to_char( "AEdit:  Range must include only this area.\n\r", ch );
	return FALSE;
    }

    if ( get_vnum_area( ilower )
    && get_vnum_area( ilower ) != pArea )
    {
	send_to_char( "AEdit:  Lower vnum already assigned.\n\r", ch );
	return FALSE;
    }

    pArea->lvnum = ilower;
    send_to_char( "Lower vnum set.\n\r", ch );

    if ( get_vnum_area( iupper )
    && get_vnum_area( iupper ) != pArea )
    {
	send_to_char( "AEdit:  Upper vnum already assigned.\n\r", ch );
	return TRUE;	/* The lower value has been set. */
    }

    pArea->uvnum = iupper;
    send_to_char( "Upper vnum set.\n\r", ch );

    return TRUE;
}



bool aedit_lvnum( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char lower[MAX_STRING_LENGTH];
    int  ilower;
    int  iupper;

    EDIT_AREA(ch, pArea);

    one_argument( argument, lower );

    if ( !is_number( lower ) || lower[0] == '\0' )
    {
	send_to_char( "Syntax:  lvnum [#lower]\n\r", ch );
	return FALSE;
    }

    if ( ( ilower = atoi( lower ) ) > ( iupper = pArea->uvnum ) )
    {
	send_to_char( "AEdit:  Value must be less than the uvnum.\n\r", ch );
	return FALSE;
    }
    
    /* OLC 1.1b */
    if ( ilower <= 0 || ilower >= INT_MAX || iupper <= 0 || iupper >= INT_MAX )
    {
	char output[MAX_STRING_LENGTH];

	sprintf( output, "AEdit: vnum must be between 0 and %d.\n\r", INT_MAX );
	send_to_char( output, ch );
	return FALSE;
    }

    if ( !check_range( ilower, iupper ) )
    {
	send_to_char( "AEdit:  Range must include only this area.\n\r", ch );
	return FALSE;
    }

    if ( get_vnum_area( ilower )
    && get_vnum_area( ilower ) != pArea )
    {
	send_to_char( "AEdit:  Lower vnum already assigned.\n\r", ch );
	return FALSE;
    }

    pArea->lvnum = ilower;
    send_to_char( "Lower vnum set.\n\r", ch );
    return TRUE;
}



bool aedit_uvnum( CHAR_DATA *ch, char *argument )
{
    AREA_DATA *pArea;
    char upper[MAX_STRING_LENGTH];
    int  ilower;
    int  iupper;

    EDIT_AREA(ch, pArea);

    one_argument( argument, upper );

    if ( !is_number( upper ) || upper[0] == '\0' )
    {
	send_to_char( "Syntax:  uvnum [#upper]\n\r", ch );
	return FALSE;
    }

    if ( ( ilower = pArea->lvnum ) > ( iupper = atoi( upper ) ) )
    {
	send_to_char( "AEdit:  Upper must be larger then lower.\n\r", ch );
	return FALSE;
    }
    
    /* OLC 1.1b */
    if ( ilower <= 0 || ilower >= INT_MAX || iupper <= 0 || iupper >= INT_MAX )
    {
	char output[MAX_STRING_LENGTH];

	sprintf( output, "AEdit: vnum must be between 0 and %d.\n\r", INT_MAX );
	send_to_char( output, ch );
	return FALSE;
    }

    if ( !check_range( ilower, iupper ) )
    {
	send_to_char( "AEdit:  Range must include only this area.\n\r", ch );
	return FALSE;
    }

    if ( get_vnum_area( iupper )
    && get_vnum_area( iupper ) != pArea )
    {
	send_to_char( "AEdit:  Upper vnum already assigned.\n\r", ch );
	return FALSE;
    }

    pArea->uvnum = iupper;
    send_to_char( "Upper vnum set.\n\r", ch );

    return TRUE;
}


void aedit(CHAR_DATA *ch, char *argument)
{
    AREA_DATA *pArea;
    char arg[MAX_STRING_LENGTH];
    char arg1[MAX_STRING_LENGTH];
    char arg2[MAX_STRING_LENGTH];
    char buf [MAX_STRING_LENGTH];
    int  value, cmd;

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


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


    if (arg1[0] == '\0')
    {
        sprintf(buf, "%d", pArea->vnum);
        do_ashow(ch, buf);
        return;
    }


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


    if (!IS_BUILDER(ch, pArea))
    {
        edit_done(ch);
        interpret(ch, arg);
        return;
    }


    for ( cmd = 0; *aedit_table[cmd].name; cmd++ )
    {
        if ( !str_prefix( arg1, aedit_table[cmd].name ) )
        {
            if ( (*aedit_table[cmd].olc_fun) ( ch, argument ) )
                SET_BIT( pArea->area_flags, AREA_CHANGED );
            return;
        }
    }
    
    /* Take care of flags. */
    if ( ( value = flag_value( area_flags, arg ) ) != NO_FLAG )
    {
	TOGGLE_BIT(pArea->area_flags, value);
        SET_BIT( pArea->area_flags, AREA_CHANGED );
	send_to_char( "Flag toggled.\n\r", ch );
	return;
    }

    interpret(ch, arg);
    return;
}

void do_rlist( CHAR_DATA *ch, char *argument )
{
    ROOM_INDEX_DATA	*room;
    int			 vnum;
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    AREA_DATA		*tarea;
    int lrange;
    int trange;

    if ( IS_NPC(ch) || !ch->pcdata || !IS_BUILDER_HERE(ch))
    {
	stc( "{YYou don't have an assigned area.\n\r", ch );
	return;
    }

    tarea = ch->in_room->area;
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0]!='\0' && !is_number(arg1) )
       return;
    if ( arg2[0]!='\0' && !is_number(arg2) )
       return;

    if ( tarea )
    {
        if ( arg1[0] == '\0' )		/* cleaned a big scary mess */
            lrange = tarea->lvnum;	/* here.	    -Thoric */
        else
            lrange = atoi( arg1 );
        if ( arg2[0] == '\0' )
        trange = tarea->uvnum;
      else
        trange = atoi(arg2);

      if ((lrange < tarea->lvnum || trange > tarea->uvnum)
      &&   get_trust( ch ) < MAX_LEVEL-2 )
      {
	stc("{YThat is out of your vnum range.\n\r", ch);
	return;
      }
    }
   else
    {
      lrange = ( is_number( arg1 ) ? atoi( arg1 ) : 1 );
      trange = ( is_number( arg2 ) ? atoi( arg2 ) : 1 );
    }

    for ( vnum = lrange; vnum <= trange; vnum++ )
    {
	if ( (room = get_room_index( vnum )) == NULL )
	  continue;
	ch_printf( ch, "{W%5d{C) {c%s\n\r", vnum, room->name );
    }
    return;
}

void do_olist( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA	*obj;
    int			 vnum;
    AREA_DATA		*tarea;
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    int lrange;
    int trange;

    /*
     * Greater+ can list out of assigned range - Tri (mlist/rlist as well)
     */

    if ( !IS_BUILDER_HERE(ch) )
    {
        stc( "{YYou don't have an assigned area.\n\r", ch );
        return;
    }

    tarea = ch->in_room->area;
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( tarea )
    {
        if ( arg1[0] == '\0' )		/* cleaned a big scary mess */
            lrange = tarea->lvnum;	/* here.	    -Thoric */
        else
            lrange = atoi( arg1 );
        if ( arg2[0] == '\0' )
        trange = tarea->uvnum;
      else
        trange = atoi(arg2);

      if ((lrange < tarea->lvnum || trange > tarea->uvnum)
      &&   get_trust( ch ) < MAX_LEVEL-2 )
      {
	stc("{YThat is out of your vnum range.\n\r", ch);
	return;
      }
    }
   else
    {
      lrange = ( is_number( arg1 ) ? atoi( arg1 ) : 1 );
      trange = ( is_number( arg2 ) ? atoi( arg2 ) : 3 );
    }

    for ( vnum = lrange; vnum <= trange; vnum++ )
    {
	if ( (obj = get_obj_index( vnum )) == NULL )
            continue;
        ch_printf( ch, "{W%5d{C) {c%-20s {C({D%s{C)\n\r", vnum,
                   obj->name,
                   obj->short_descr );
    }
    return;
}

void do_mlist( CHAR_DATA *ch, char *argument )
{
    MOB_INDEX_DATA	*mob;
    int			 vnum;
    AREA_DATA		*tarea;
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    int lrange;
    int trange;

    if ( IS_BUILDER_HERE(ch) )
    {
        stc( "{YYou don't have an assigned area.\n\r", ch );
        return;
    }

    tarea = ch->in_room->area;
    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( tarea )
    {
        if ( arg1[0] == '\0' )		/* cleaned a big scary mess */
            lrange = tarea->lvnum;	/* here.	    -Thoric */
        else
            lrange = atoi( arg1 );
        if ( arg2[0] == '\0' )
        trange = tarea->uvnum;
      else
        trange = atoi(arg2);

      if ((lrange < tarea->lvnum || trange > tarea->uvnum)
      &&   get_trust( ch ) < MAX_LEVEL-2 )
      {
	stc("{YThat is out of your vnum range.\n\r", ch);
	return;
      }
    }
    else
    {
      lrange = ( is_number( arg1 ) ? atoi( arg1 ) : 1 );
      trange = ( is_number( arg2 ) ? atoi( arg2 ) : 1 );
    }
    
    for ( vnum = lrange; vnum <= trange; vnum++ )
    {
        if ( (mob = get_mob_index( vnum )) == NULL )
            continue;
        ch_printf( ch, "{W%5d{C) {c%-20s{C ({D%s{C)\n\r", vnum,
                   mob->player_name,
                   mob->short_descr );
    }
}


/* Entry point for editing area_data. */
void    do_aedit (CHAR_DATA * ch, char *argument)
{
	AREA_DATA *pArea;
        int     value;
        char    arg[MAX_STRING_LENGTH];

        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 ("{YThat area vnum does not exist.\n\r", ch);
                return;
            }
        }
	else if (!str_cmp (arg, "create"))
        {
            pArea               =   new_area();
            area_last->next     =   pArea;
            ch->desc->pEdit     =   (void *)pArea;

            send_to_char("{YArea created.\n\r", ch);
        }

	if (!IS_BUILDER (ch, pArea) || ch->pcdata->security < 9)
        {
            send_to_char ("{YInsufficant security to modify this area.\n\r", ch);
            return;
        }

        set_editor(ch->desc, ED_AREA, pArea);
        return;
}

REDIT(redit_findreset)
{
    OBJ_INDEX_DATA  *pObj;
    AREA_DATA       *pArea;
    ROOM_INDEX_DATA *pRoom;
    RESET_DATA      *pReset;
    MOB_INDEX_DATA  *pMob;
    int room;
    char mobs  [ MSL ];
    char objs  [ MSL ];
    char buf   [ MSL ];
    
    EDIT_ROOM(ch, pRoom);

    pArea = pRoom->area;

    mobs[0] = '\0';
    objs[0] = '\0';

    if( argument[0] == '\0')
    {
        stc("Find mobs/objects with which keyword?\n\r", ch);
        return FALSE;
    }

    for( room = pArea->lvnum; room < pArea->uvnum; room++ )
    {
        pRoom = get_room_index( room );
        if( !pRoom )
            continue;

        if( pRoom->area != pArea )
            continue;
        
        for( pReset = pRoom->reset_first; pReset; pReset = pReset->next )
        {
            switch( pReset->command )
            {
            default:
                break;
            case 'M':
                if( !(pMob = get_mob_index( pReset->arg1 ) ) )
                    break;
                if( !is_name( argument, pMob->player_name ) )
                    break;
                sprintf( buf, "[%5d] %-13.13s in room %-23.23s [%5d]\n\r",
                         pReset->arg1, pMob->short_descr, pRoom->name,
                         pRoom->vnum );
                strcat( mobs, buf );
                break;
            case 'O':
            case 'P':
            case 'G':
            case 'E':
                if( !(pObj = get_obj_index( pReset->arg1 ) ) )
                    break;
                if( !is_name( argument, pObj->name ) )
                    break;
                sprintf( buf, "[%5d] %-13.13s in room %-23.23s [%5d]\n\r",
                         pReset->arg1, pObj->short_descr,
                         pRoom->name, pRoom->vnum );
                strcat( objs, buf );
                break;
            }
        }
    }

    stc( "----------------------------------[{CMobiles{n]----------------------------------\n\r",ch);
    stc( mobs, ch );
    stc( "----------------------------------[{CObjects{n]----------------------------------\n\r",ch);
    stc( objs, ch );
    return FALSE;
}
REDIT( redit_create )
{
    AREA_DATA *pArea;
    ROOM_INDEX_DATA *pRoom;
    char arg [ MAX_INPUT_LENGTH ];

    int value, iHash;

    argument = one_argument( argument, arg );

    value = atoi(arg);

    if (arg[0] == '\0'  || value == 0)
    {
        send_to_char("{YSyntax:  create [vnum]\n\r", ch);
        return FALSE;
    }

    pArea = get_vnum_area(value);

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

        if (!IS_BUILDER(ch, pArea))
        {
            send_to_char("{YREdit:  Vnum in an area you cannot build in.\n\r", ch);
            return FALSE;
        }

        if (get_room_index(value) != NULL)
        {
            send_to_char("{YREdit:  Room vnum already exists.\n\r", ch);
            return FALSE;
        }

        pRoom                   = new_room_index();
        pRoom->area             = pArea;
        pRoom->vnum             = value;

        if (value > top_vnum_room) top_vnum_room = value;

        iHash                   = value % MAX_KEY_HASH;
        pRoom->next             = room_index_hash[iHash];
        room_index_hash[iHash]  = pRoom;
//        ch->desc->pEdit         = (void *)pRoom;
	set_editor( ch->desc, ED_ROOM, pRoom );
        SET_BIT(pArea->area_flags, AREA_CHANGED);
        send_to_char("Room created.\n\r", ch);
        return TRUE;
}


REDIT(redit_show)
{
    ROOM_INDEX_DATA *pRoom;
    char buf [ 50 ];
    EDIT_ROOM( ch, pRoom );
    
    sprintf( buf, "%d", pRoom->vnum );
    do_rshow( ch, buf );
    return FALSE;
}
/* OLC 1.1b */
/*****************************************************************************
 Name:		change_exit
 Purpose:	Command interpreter for changing exits.
 Called by:	redit_<dir>.  This is a local function.
 ****************************************************************************/
bool change_exit( CHAR_DATA *ch, char *argument, int door )
{
    ROOM_INDEX_DATA *pRoom;
    char command[MAX_INPUT_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    char total_arg[MAX_STRING_LENGTH];
    int  rev;
    int  value = 0;

    EDIT_ROOM(ch, pRoom);

    /* Often used data. */
    rev = rev_dir[door];
    
    if ( argument[0] == '\0' )
    {
	do_help( ch, "EXIT" );
	return FALSE;
    }

    /*
     * Now parse the arguments.
     */
    strcpy( total_arg, argument );
    argument = one_argument( argument, command );
    one_argument( argument, arg );

    if ( !str_cmp( command, "delete" ) )
    {	
	if ( !pRoom->exit[door] )
	{
	    send_to_char( "REdit:  Exit does not exist.\n\r", ch );
	    return FALSE;
	}

	/*
	 * Remove To Room Exit.
	 */
	if (  pRoom->exit[door]->to_room &&
	      pRoom->exit[door]->to_room->exit[rev] )
	{
	    free_exit( pRoom->exit[door]->to_room->exit[rev] );
	    pRoom->exit[door]->to_room->exit[rev] = NULL;
	}

	/*
	 * Remove this exit.
	 */
	free_exit( pRoom->exit[door] );
	pRoom->exit[door] = NULL;

	send_to_char( "Exit unlinked.\n\r", ch );
	return TRUE;
    }

    /*
     * Create a two-way exit.
     */
    if ( !str_cmp( command, "link" ) )
    {
	EXIT_DATA	*pExit;
	ROOM_INDEX_DATA	*pLinkRoom;

	if ( arg[0] == '\0' || !is_number( arg ) )
	{
	    send_to_char( "Syntax:  [direction] link [vnum]\n\r", ch );
	    return FALSE;
	}

	if ( !( pLinkRoom = get_room_index( atoi(arg) ) ) )
	{
	    send_to_char( "REdit:  Non-existant room.\n\r", ch );
	    return FALSE;
	}

	if ( !IS_BUILDER( ch, pLinkRoom->area ) )
	{
	    send_to_char( "REdit:  Cannot link to that area.\n\r", ch );
	    return FALSE;
	}

	if ( pLinkRoom->exit[rev] )
	{
	    send_to_char( "REdit:  Remote side's exit exists.\n\r", ch );
	    return FALSE;
	}

	if ( !pRoom->exit[door] )		/* No exit.		*/
	    pRoom->exit[door] = new_exit();

	pRoom->exit[door]->to_room = pLinkRoom;	/* Assign data.		*/
	pRoom->exit[door]->vnum = value;

	pExit			= new_exit();	/* No remote exit.	*/

	pExit->to_room		= ch->in_room;	/* Assign data.		*/
	pExit->vnum		= ch->in_room->vnum;

	pLinkRoom->exit[rev]	= pExit;	/* Link exit to room.	*/
	
	send_to_char( "Two-way link established.\n\r", ch );
	return TRUE;
    }

    /*
     * Create room and make two-way exit.
     */
    if ( !str_cmp( command, "dig" ) )
    {
	char buf[MAX_INPUT_LENGTH];
	
	if ( arg[0] == '\0' || !is_number( arg ) )
	{
	    send_to_char( "Syntax: [direction] dig <vnum>\n\r", ch );
	    return FALSE;
	}
	
	redit_create( ch, arg );		/* Create the room.	*/
	sprintf( buf, "link %s", arg );
	change_exit( ch, buf, door);		/* Create the exits.	*/
	return TRUE;
    }

    /*
     * Create one-way exit.
     */
    if ( !str_cmp( command, "room" ) )
    {
	ROOM_INDEX_DATA *pLinkRoom;

	if ( arg[0] == '\0' || !is_number( arg ) )
	{
	    send_to_char( "Syntax:  [direction] room [vnum]\n\r", ch );
	    return FALSE;
	}

	if ( !( pLinkRoom = get_room_index( atoi( arg ) ) ) )
	{
	    send_to_char( "REdit:  Non-existant room.\n\r", ch );
	    return FALSE;
	}

	if ( !pRoom->exit[door] )
	    pRoom->exit[door] = new_exit();

	pRoom->exit[door]->to_room = pLinkRoom;
	pRoom->exit[door]->vnum = value;
	send_to_char( "One-way link established.\n\r", ch );
	return TRUE;
    }

    if ( !str_cmp( command, "remove" ) )
    {
	if ( arg[0] == '\0' )
	{
	    send_to_char( "Syntax:  [direction] remove [key/name/desc]\n\r", ch );
	    return FALSE;
	}

	if ( !pRoom->exit[door] )
	{
	    send_to_char( "REdit:  Exit does not exist.\n\r", ch );
	    return FALSE;
	}

	if ( !str_cmp( argument, "key" ) )
	{
	    pRoom->exit[door]->key = 0;
            send_to_char( "Exit key removed.\n\r", ch );                        
            return TRUE;
	}

	if ( !str_cmp( argument, "name" ) )
	{
	    free_string( pRoom->exit[door]->keyword );
	    pRoom->exit[door]->keyword = &str_empty[0];
            send_to_char( "Exit name removed.\n\r", ch );                        
            return TRUE;
	}

	if ( argument[0] == 'd' && !str_prefix( argument, "description" ) )
	{
	    free_string( pRoom->exit[door]->description );
	    pRoom->exit[door]->description = &str_empty[0];
            send_to_char( "Exit description removed.\n\r", ch );                        
            return TRUE;
	}

	send_to_char( "Syntax:  [direction] remove [key/name/desc]\n\r", ch );
	return FALSE;
    }

    if ( !str_cmp( command, "key" ) )
    {
	OBJ_INDEX_DATA *pObjIndex;

	if ( arg[0] == '\0' || !is_number( arg ) )
	{
	    send_to_char( "Syntax:  [direction] key [vnum]\n\r", ch );
	    return FALSE;
	}

	if ( !( pObjIndex = get_obj_index( atoi( arg ) ) ) )
	{
	    send_to_char( "REdit:  Item does not exist.\n\r", ch );
	    return FALSE;
	}

	if ( pObjIndex->item_type != ITEM_KEY )
	{
	    send_to_char( "REdit:  Item is not a key.\n\r", ch );
	    return FALSE;
	}

	if ( !pRoom->exit[door] )
	    pRoom->exit[door] = new_exit();

	pRoom->exit[door]->key = pObjIndex->vnum;

	send_to_char( "Exit key set.\n\r", ch );
	return TRUE;
    }

    
    if ( !str_cmp( command, "name" ) )
    {
	if ( arg[0] == '\0' )
	{
	    send_to_char( "Syntax:  [direction] name [string]\n\r", ch );
	    return FALSE;
	}

	if ( !pRoom->exit[door] )
	    pRoom->exit[door] = new_exit();

	free_string( pRoom->exit[door]->keyword );
	pRoom->exit[door]->keyword = str_dup( argument );

	send_to_char( "Exit name set.\n\r", ch );
	return TRUE;
    }

    if ( command[0] == 'd' && !str_prefix( command, "description" ) )
    {
	if ( arg[0] == '\0' )
	{
	    if ( !pRoom->exit[door] )
	        pRoom->exit[door] = new_exit();

	    string_append( ch, &pRoom->exit[door]->description );
	    return TRUE;
	}

	send_to_char( "Syntax:  [direction] desc\n\r", ch );
	return FALSE;
    }

    /*
     * Set the exit flags, needs full argument.
     * ----------------------------------------
     */
    if ( ( value = flag_value( exit_flags, total_arg ) ) != NO_FLAG )
    {
	ROOM_INDEX_DATA *pToRoom;

	/*
	 * Create an exit if none exists.
	 */
	if ( !pRoom->exit[door] )
	    pRoom->exit[door] = new_exit();

	/*
	 * Set door bits for this room.
	 */
	TOGGLE_BIT(pRoom->exit[door]->rs_flags, value);
	pRoom->exit[door]->exit_info = pRoom->exit[door]->rs_flags;

	/*
	 * Set door bits of wconnected room.
	 * Skip one-way exits and non-existant rooms.
	 */
	if ( ( pToRoom = pRoom->exit[door]->to_room ) && pToRoom->exit[rev] )
	{
	    TOGGLE_BIT(pToRoom->exit[rev]->rs_flags, value);
	    pToRoom->exit[rev]->exit_info =  pToRoom->exit[rev]->rs_flags;
	}

	send_to_char( "Exit flag toggled.\n\r", ch );
	return TRUE;
    }

    return FALSE;
}



REDIT( redit_north )
{
    if ( change_exit( ch, argument, DIR_NORTH ) )
	return TRUE;

    return FALSE;
}



REDIT( redit_south )
{
    if ( change_exit( ch, argument, DIR_SOUTH ) )
	return TRUE;

    return FALSE;
}



REDIT( redit_east )
{
    if ( change_exit( ch, argument, DIR_EAST ) )
	return TRUE;

    return FALSE;
}



REDIT( redit_west )
{
    if ( change_exit( ch, argument, DIR_WEST ) )
	return TRUE;

    return FALSE;
}



REDIT( redit_up)
{
    if ( change_exit( ch, argument, DIR_UP ) )
	return TRUE;

    return FALSE;
}



REDIT( redit_down )
{
    if ( change_exit( ch, argument, DIR_DOWN ) )
	return TRUE;

    return FALSE;
}


/* OLC 1.1b */
REDIT( redit_move )
{
    interpret( ch, argument );
    return FALSE;
}

REDIT( redit_roomtext )
{
    ROOM_INDEX_DATA *pRoom;
    ROOMTEXT_DATA   *rt;
    char command[MAX_INPUT_LENGTH];
    char keyword[MAX_INPUT_LENGTH];
    int r;

    EDIT_ROOM(ch, pRoom);

    argument = one_argument( argument, command );
    one_argument( argument, keyword );

    if ( command[0] == '\0' || keyword[0] == '\0' )
    {
	send_to_char( "Syntax:  roomtext add  [$keyword]\n\r", ch );
	send_to_char( "         roomtext show [$keyword]\n\r", ch );
	send_to_char( "Keyword is the ## of the one you wish to edit.\n\r",ch );
	return FALSE;
    }
        
    for( r=1,rt = pRoom->roomtext;rt; rt = rt->next,r++ )
    {
	if( is_number(keyword) && r == atoi(keyword) )
		break;
	else if ( is_name( rt->input, keyword ) )
		break;
    }
    if( !rt )
    {
	send_to_char( "That room_text does not exhist.\n\r", ch );
	return FALSE;
    }

    if( !str_cmp( command, "show" ) )
    {
	ch_printf( ch, "{cType:     {C%s  ",   flag_string( rt_flags, rt->type ) );
	ch_printf( ch, "{cPower:    {n%d  ",   rt->power );
        ch_printf( ch, "{cMob:      {n%d\n\r", rt->mob   );
        ch_printf( ch, "{cInput:    {n%s\n\r", rt->input );
        ch_printf( ch, "{cName:     {n%s\n\r", rt->name );
        ch_printf( ch, "{cOutput:   {n%s\n\r", rt->output );
        ch_printf( ch, "{cChOutput: {n%s\n\r", rt->choutput );
	return FALSE;
    }
    
    return FALSE;
}

REDIT( redit_ed )
{
    ROOM_INDEX_DATA *pRoom;
    EXTRA_DESCR_DATA *ed;
    char command[MAX_INPUT_LENGTH];
    char keyword[MAX_INPUT_LENGTH];

    EDIT_ROOM(ch, pRoom);

    argument = one_argument( argument, command );
    one_argument( argument, keyword );


    if ( command[0] == '\0' || keyword[0] == '\0' )
    {
	send_to_char( "Syntax:  ed add [keyword]\n\r", ch );
	send_to_char( "         ed edit [keyword]\n\r", ch );
	send_to_char( "         ed delete [keyword]\n\r", ch );
	send_to_char( "         ed format [keyword]\n\r", ch );
	return FALSE;
    }

     
    if ( !str_cmp( command, "add" ) )
    {
	if ( keyword[0] == '\0' )
	{
	    send_to_char( "Syntax:  ed add [keyword]\n\r", ch );
	    return FALSE;
	}

	ed			=   new_extra_descr();
	ed->keyword		=   str_dup( keyword );
	ed->description		=   str_dup( "" );
	ed->next		=   pRoom->extra_descr;
	pRoom->extra_descr	=   ed;

	string_append( ch, &ed->description );

	return TRUE;
    }


    if ( !str_cmp( command, "edit" ) )
    {
	if ( keyword[0] == '\0' )
	{
	    send_to_char( "Syntax:  ed edit [keyword]\n\r", ch );
	    return FALSE;
	}

	for ( ed = pRoom->extra_descr; ed; ed = ed->next )
	{
	    if ( is_name( keyword, ed->keyword ) )
		break;
	}

	if ( !ed )
	{
	    send_to_char( "REdit:  Extra description keyword not found.\n\r", ch );
	    return FALSE;
	}

	string_append( ch, &ed->description );

	return TRUE;
    }


    if ( !str_cmp( command, "delete" ) )
    {
	EXTRA_DESCR_DATA *ped = NULL;

	if ( keyword[0] == '\0' )
	{
	    send_to_char( "Syntax:  ed delete [keyword]\n\r", ch );
	    return FALSE;
	}

	for ( ed = pRoom->extra_descr; ed; ed = ed->next )
	{
	    if ( is_name( keyword, ed->keyword ) )
		break;
	    ped = ed;
	}

	if ( !ed )
	{
	    send_to_char( "REdit:  Extra description keyword not found.\n\r", ch );
	    return FALSE;
	}

	if ( !ped )
	    pRoom->extra_descr = ed->next;
	else
	    ped->next = ed->next;

	free_extra_descr( ed );

	send_to_char( "Extra description deleted.\n\r", ch );
	return TRUE;
    }


    if ( !str_cmp( command, "format" ) )
    {
	if ( keyword[0] == '\0' )
	{
	    send_to_char( "Syntax:  ed format [keyword]\n\r", ch );
	    return FALSE;
	}

	for ( ed = pRoom->extra_descr; ed; ed = ed->next )
	{
	    if ( is_name( keyword, ed->keyword ) )
		break;
	}

	if ( !ed )
	{
	    send_to_char( "REdit:  Extra description keyword not found.\n\r", ch );
	    return FALSE;
	}

	/* OLC 1.1b */
	if ( strlen(ed->description) >= (MAX_STRING_LENGTH - 4) )
	{
	    send_to_char( "String too long to be formatted.\n\r", ch );
	    return FALSE;
	}

	ed->description = format_string( ed->description );

	send_to_char( "Extra description formatted.\n\r", ch );
	return TRUE;
    }

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

REDIT( redit_name )
{
    ROOM_INDEX_DATA *pRoom;

    EDIT_ROOM(ch, pRoom);

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

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

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



REDIT( redit_desc )
{
    ROOM_INDEX_DATA *pRoom;

    EDIT_ROOM(ch, pRoom);

    if ( argument[0] == '\0' )
    {
	string_append( ch, &pRoom->description );
	return TRUE;
    }

    send_to_char( "Syntax:  desc\n\r", ch );
    return FALSE;
}




REDIT( redit_format )
{
    ROOM_INDEX_DATA *pRoom;

    EDIT_ROOM(ch, pRoom);

    /* OLC 1.1b */
    if ( strlen(pRoom->description) >= (MAX_STRING_LENGTH - 4) )
    {
	send_to_char( "String too long to be formatted.\n\r", ch );
	return FALSE;
    }

    pRoom->description = format_string( pRoom->description );

    send_to_char( "String formatted.\n\r", ch );
    return TRUE;
}



REDIT( redit_mreset )
{
    ROOM_INDEX_DATA	*pRoom;
    MOB_INDEX_DATA	*pMobIndex;
    CHAR_DATA		*newmob;
    char		arg [ MAX_INPUT_LENGTH ];

    RESET_DATA		*pReset;
    char		output [ MAX_STRING_LENGTH ];

    EDIT_ROOM(ch, pRoom);

    argument = one_argument( argument, arg );

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

    if ( !( pMobIndex = get_mob_index( atoi( arg ) ) ) )
    {
	send_to_char( "REdit: No mobile has that vnum.\n\r", ch );
	return FALSE;
    }

    if ( pMobIndex->area != pRoom->area )
    {
	send_to_char( "REdit: No such mobile in this area.\n\r", ch );
	return FALSE;
    }

    /*
     * Create the mobile reset.
     */
    pReset = new_reset_data();
    pReset->command	= 'M';
    pReset->arg1	= pMobIndex->vnum;
    pReset->arg2	= is_number( argument ) ? atoi( argument ) : MAX_MOB;
    pReset->arg3	= pRoom->vnum;
    add_reset( pRoom, pReset, 0/* Last slot*/ );

    /*
     * Create the mobile.
     */
    newmob = create_mobile( pMobIndex );
    char_to_room( newmob, pRoom );

    sprintf( output, "%s (%d) has been loaded and added to resets.\n\r"
	"There will be a maximum of %d loaded to this room.\n\r",
	capitalize( pMobIndex->short_descr ),
	pMobIndex->vnum,
	pReset->arg2 );
    send_to_char( output, ch );
    act( "$n has created $N!", ch, NULL, newmob, TO_ROOM );
    return TRUE;
}

/*
 * redit_copy function thanks to Zanthras of Mystical Realities MUD.
 */
REDIT( redit_copy )
{
    ROOM_INDEX_DATA	*pRoom;
    ROOM_INDEX_DATA	*pRoom2; /* Room to copy */
    int vnum;

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

    if ( !is_number(argument) )
    {
      send_to_char("REdit: You must enter a number (vnum).\n\r",ch);
      return FALSE;
    }
    else /* argument is a number */
    {
      vnum = atoi(argument);
      if( !( pRoom2 = get_room_index(vnum) ) )
      {
	send_to_char("REdit: That room does not exist.\n\r",ch);
	return FALSE;
      }
    }

    EDIT_ROOM(ch, pRoom);

    free_string( pRoom->description );
    pRoom->description = str_dup( pRoom2->description );
    
    free_string( pRoom->name );
    pRoom->name = str_dup( pRoom2->name );

    /* sector flags */
    pRoom->sector_type = pRoom2->sector_type;

    /* room flags */
    pRoom->room_flags = pRoom2->room_flags;

    pRoom->extra_descr = pRoom2->extra_descr;

    send_to_char( "Room info copied.", ch );
    return TRUE;
}

struct wear_type
{
    int	wear_loc;
    int	wear_bit;
};



const struct wear_type wear_table[] =
{
    {	WEAR_NONE,	ITEM_TAKE		},
    {	WEAR_LIGHT,	ITEM_LIGHT		},
    {	WEAR_FINGER_L,	ITEM_WEAR_FINGER	},
    {	WEAR_FINGER_R,	ITEM_WEAR_FINGER	},
    {	WEAR_NECK_1,	ITEM_WEAR_NECK		},
    {	WEAR_NECK_2,	ITEM_WEAR_NECK		},
    {	WEAR_BODY,	ITEM_WEAR_BODY		},
    {	WEAR_HEAD,	ITEM_WEAR_HEAD		},
    {	WEAR_LEGS,	ITEM_WEAR_LEGS		},
    {	WEAR_FEET,	ITEM_WEAR_FEET		},
    {	WEAR_HANDS,	ITEM_WEAR_HANDS		},
    {	WEAR_ARMS,	ITEM_WEAR_ARMS		},
    {	WEAR_SHIELD,	ITEM_WEAR_SHIELD	},
    {	WEAR_ABOUT,	ITEM_WEAR_ABOUT		},
    {	WEAR_WAIST,	ITEM_WEAR_WAIST		},
    {	WEAR_WRIST_L,	ITEM_WEAR_WRIST		},
    {	WEAR_WRIST_R,	ITEM_WEAR_WRIST		},
    {	WEAR_WIELD,	ITEM_WIELD		},
    {	WEAR_HOLD,	ITEM_HOLD		},
    {   WEAR_FACE,      ITEM_WEAR_FACE          },
    {   WEAR_EAR_L,     ITEM_WEAR_EAR           },
    {   WEAR_EAR_R,     ITEM_WEAR_EAR           },
    {   WEAR_NOSE,      ITEM_WEAR_NOSE          },
    {   WEAR_ANKLE_L,   ITEM_WEAR_ANKLE         },
    {   WEAR_ANKLE_R,   ITEM_WEAR_ANKLE         },
    {	NO_FLAG,	NO_FLAG			}
};



/*****************************************************************************
 Name:		wear_loc
 Purpose:	Returns the location of the bit that matches the count.
 		1 = first match, 2 = second match etc.
 Called by:	oedit_reset(olc_act.c).
 ****************************************************************************/
int wear_loc(int bits, int count)
{
    int flag;
 
    for (flag = 0; wear_table[flag].wear_bit != NO_FLAG; flag++)
    {
        if ( IS_SET(bits, wear_table[flag].wear_bit) && --count < 1)
            return wear_table[flag].wear_loc;
    }
 
    return NO_FLAG;
}



/*****************************************************************************
 Name:		wear_bit
 Purpose:	Converts a wear_loc into a bit.
 Called by:	redit_oreset(olc_act.c).
 ****************************************************************************/
int wear_bit(int loc)
{
    int flag;
 
    for (flag = 0; wear_table[flag].wear_loc != NO_FLAG; flag++)
    {
        if ( loc == wear_table[flag].wear_loc )
            return wear_table[flag].wear_bit;
    }
 
    return 0;
}



REDIT( redit_oreset )
{
    ROOM_INDEX_DATA	*pRoom;
    OBJ_INDEX_DATA	*pObjIndex;
    OBJ_DATA		*newobj;
    OBJ_DATA		*to_obj;
    CHAR_DATA		*to_mob;
    char		arg1 [ MAX_INPUT_LENGTH ];
    char		arg2 [ MAX_INPUT_LENGTH ];
    int			olevel = 0;

    RESET_DATA		*pReset;
    char		output [ MAX_STRING_LENGTH ];

    EDIT_ROOM(ch, pRoom);

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

    if ( arg1[0] == '\0' || !is_number( arg1 ) )
    {
	send_to_char ( "Syntax:  oreset <vnum> <args>\n\r", ch );
	send_to_char ( "        -no_args               = into room\n\r", ch );
	send_to_char ( "        -<obj_name>            = into obj\n\r", ch );
	send_to_char ( "        -<mob_name> <wear_loc> = into mob\n\r", ch );
	return FALSE;
    }

    if ( !( pObjIndex = get_obj_index( atoi( arg1 ) ) ) )
    {
	send_to_char( "REdit: No object has that vnum.\n\r", ch );
	return FALSE;
    }

    if ( pObjIndex->area != pRoom->area )
    {
	send_to_char( "REdit: No such object in this area.\n\r", ch );
	return FALSE;
    }

    /*
     * Load into room.
     */
    if ( arg2[0] == '\0' )
    {
	pReset		= new_reset_data();
	pReset->command	= 'O';
	pReset->arg1	= pObjIndex->vnum;
	pReset->arg2	= 0;
	pReset->arg3	= pRoom->vnum;
	add_reset( pRoom, pReset, 0/* Last slot*/ );

	newobj = create_object( pObjIndex, number_fuzzy( olevel ) );
	obj_to_room( newobj, pRoom );

	sprintf( output, "%s (%d) has been loaded and added to resets.\n\r",
	    capitalize( pObjIndex->short_descr ),
	    pObjIndex->vnum );
	send_to_char( output, ch );
    }
    else
    /*
     * Load into object's inventory.
     */
    if ( argument[0] == '\0'
    && ( ( to_obj = get_obj_list( ch, arg2, pRoom->contents ) ) != NULL ) )
    {
	pReset		= new_reset_data();
	pReset->command	= 'P';
	pReset->arg1	= pObjIndex->vnum;
	pReset->arg2	= pObjIndex->vnum;
	pReset->arg3	= to_obj->pIndexData->vnum;
	add_reset( pRoom, pReset, 0/* Last slot*/ );

	newobj = create_object( pObjIndex, number_fuzzy( olevel ) );
	newobj->cost = 0;
	obj_to_obj( newobj, to_obj );

	sprintf( output, "%s (%d) has been loaded into "
	    "%s (%d) and added to resets.\n\r",
	    capitalize( newobj->short_descr ),
	    newobj->pIndexData->vnum,
	    to_obj->short_descr,
	    to_obj->pIndexData->vnum );
	send_to_char( output, ch );
    }
    else
    /*
     * Load into mobile's inventory.
     */
    if ( ( to_mob = get_char_room( ch, arg2 ) ) != NULL )
    {
	int	wear_loc;

	/*
	 * Make sure the location on mobile is valid.
	 */
	if ( (wear_loc = flag_value( wear_loc_flags, argument )) == NO_FLAG )
	{
	    send_to_char( "REdit: Invalid wear_loc.  '? wear-loc'\n\r", ch );
	    return FALSE;
	}

	/*
	 * Disallow loading a sword(WEAR_WIELD) into WEAR_HEAD.
	 */
	if ( !IS_SET( pObjIndex->wear_flags, wear_bit(wear_loc) ) )
	{
	    sprintf( output,
	        "%s (%d) has wear flags: %d '%s'\n\r"
		"   You choose: %d '%s'\n\r",
	        capitalize( pObjIndex->short_descr ),
	        pObjIndex->vnum,
		pObjIndex->wear_flags,
		flag_string( wear_flags, pObjIndex->wear_flags ),
		wear_bit(wear_loc), 
		flag_string( wear_flags, wear_bit(wear_loc)));
	    send_to_char( output, ch );
	    return FALSE;
	}

	/*
	 * Can't load into same position.
	 */
	if ( get_eq_char( to_mob, wear_loc )  && wear_loc != WEAR_NONE )
	{
	    send_to_char( "REdit:  Object already equipped.\n\r", ch );
	    return FALSE;
	}

	pReset		= new_reset_data();
	pReset->arg1	= pObjIndex->vnum;
	pReset->arg2	= wear_loc;
	if ( pReset->arg2 == WEAR_NONE )
	    pReset->command = 'G';
	else
	    pReset->command = 'E';
	pReset->arg3	= wear_loc;

	add_reset( pRoom, pReset, 0/* Last slot*/ );

	olevel  = URANGE( 0, to_mob->level - 2, LEVEL_HERO );
        newobj = create_object( pObjIndex, number_fuzzy( olevel ) );

	if ( to_mob->pIndexData->pShop )	/* Shop-keeper? */
	{
	    switch ( pObjIndex->item_type )
	    {
	    default:		olevel = 0;				break;
	    case ITEM_PILL:	olevel = number_range(  0, 10 );	break;
	    case ITEM_POTION:	olevel = number_range(  0, 10 );	break;
	    case ITEM_SCROLL:	olevel = number_range(  5, 15 );	break;
	    case ITEM_WAND:	olevel = number_range( 10, 20 );	break;
	    case ITEM_STAFF:	olevel = number_range( 15, 25 );	break;
	    case ITEM_ARMOR:	olevel = number_range(  5, 15 );	break;
	    case ITEM_WEAPON:	if ( pReset->command == 'G' )
	    			    olevel = number_range( 5, 15 );
				else
				    olevel = number_fuzzy( olevel );
		break;
	    }

	    newobj = create_object( pObjIndex, olevel );
	    if ( pReset->arg2 == WEAR_NONE )
		SET_BIT( newobj->extra_flags, ITEM_INVENTORY );
	}
	else
	    newobj = create_object( pObjIndex, number_fuzzy( olevel ) );

	obj_to_char( newobj, to_mob );
	if ( pReset->command == 'E' )
	    equip_char( to_mob, newobj, pReset->arg3 );

	sprintf( output, "%s (%d) has been loaded "
	    "%s of %s (%d) and added to resets.\n\r",
	    capitalize( pObjIndex->short_descr ),
	    pObjIndex->vnum,
	    flag_string( wear_loc_strings, pReset->arg3 ),
	    to_mob->short_descr,
	    to_mob->pIndexData->vnum );
	send_to_char( output, ch );
    }
    else	/* Display Syntax */
    {
	send_to_char( "REdit:  That mobile isn't here.\n\r", ch );
	return FALSE;
    }

    act( "$n has created $p!", ch, newobj, NULL, TO_ROOM );
    return TRUE;
}

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

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

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

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

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

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

    /* Search Table and Dispatch Command. */
    for ( cmd = 0; *redit_table[cmd].name; 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;
        }
    }

    /* Take care of flags. */
    if ( ( value = flag_value( room_flags, arg ) ) != NO_FLAG )
    {
        TOGGLE_BIT(pRoom->room_flags, value);

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Room flag toggled.\n\r", ch );
        return;
    }

    if ( ( value = flag_value( sector_flags, arg ) ) != NO_FLAG )
    {
        pRoom->sector_type  = value;

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Sector type set.\n\r", ch );
        return;
    }

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

/* Entry point for editing room_index_data. */
void    do_redit (CHAR_DATA * ch, char *argument)
{
    ROOM_INDEX_DATA *pRoom;
    char    arg1[MIL];

    argument = one_argument (argument, arg1);

    pRoom = ch->in_room;

    if (!str_cmp (arg1, "reset"))
    {
        if (!IS_BUILDER (ch, pRoom->area))
        {
            send_to_char ("{yInsufficant security to modify room.\n\r", ch);
            return;
        }

        reset_room (pRoom);
        send_to_char ("Room reset.\n\r", ch);
        return;
    }
    else if (!str_cmp (arg1, "create"))
    {
        if (argument[0] == '\0' || atoi (argument) == 0)
        {
            send_to_char ("{ySyntax : redit room create [vnum]\n\r", ch);
            return;
        }

        if (redit_create (ch, argument))
        {
            char_from_room (ch);
            char_to_room (ch, ch->desc->pEdit);
            SET_BIT (pRoom->area->area_flags, AREA_CHANGED);
            pRoom = ch->in_room;
        }
    }
    else if ( arg1[0] != '\0' )
    {
        pRoom = get_room_index (atoi (arg1));

        if ( pRoom == NULL )
        {
            send_to_char( "{yRoom inexsistant.\n\r", ch );
            return;
        }
    }

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

    if ( pRoom == NULL )
        bugf( "do_redit : NULL pRoom, ch %s!", ch->name );

    if (ch->in_room != pRoom)
    {
        char_from_room(ch);
        char_to_room(ch, pRoom);
    }

    set_editor(ch->desc, ED_ROOM, pRoom);
    return;
}

bool oedit_create( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;
    AREA_DATA *pArea;
    int  value;
    int  iHash;

    value = atoi( argument );
    if ( argument[0] == '\0' || value == 0 )
    {
	send_to_char( "Syntax:  oedit create [vnum]\n\r", ch );
	return FALSE;
    }

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

    if ( !IS_BUILDER( ch, pArea ) )
    {
	send_to_char( "OEdit:  Vnum in an area you cannot build in.\n\r", ch );
	return FALSE;
    }

    if ( get_obj_index( value ) )
    {
	send_to_char( "OEdit:  Object vnum already exists.\n\r", ch );
	return FALSE;
    }
        
    pObj			= new_obj_index();
    pObj->vnum			= value;
    pObj->area			= pArea;
    pObj->extra_flags		= 0;
        
    if ( value > top_vnum_obj )
	top_vnum_obj = value;

    iHash			= value % MAX_KEY_HASH;
    pObj->next			= obj_index_hash[iHash];
    obj_index_hash[iHash]	= pObj;

    set_editor(ch->desc, ED_OBJECT, pObj);

    send_to_char( "Object Created.\n\r", ch );
    return TRUE;
}

char * spell_name( int x )
{
    int cnt;
    if( x < 1 || x > MAX_SKILL )
        return "None";
    for( cnt = 0; spells[cnt].name; cnt++ )
    	if( spells[cnt].num == x )
		return spells[cnt].name;
    return "None";
};

int get_spell_item( char *argument )
{
    int sn;
    if( argument[0] == '\0' )
	return -1;
    if( is_number( argument ) )
    {
	sn = atoi( argument );
	if( sn > MAX_SKILL )
		return -1;
	else
		return sn;
    }
    else
    {
	int cnt;
	for( cnt = 0; spells[cnt].name;cnt++ )
		if( !str_cmp(argument,spells[cnt].name) )
			return spells[cnt].num;
    }
    return -1;
}

void show_obj_values(CHAR_DATA *ch, OBJ_INDEX_DATA *obj)
{
    char buf[MAX_STRING_LENGTH];

    switch(obj->item_type)
    {
        default:
	    sprintf(buf, "This object has no values.\n\r");
	    send_to_char(buf, ch);
            break;
            
        case ITEM_LIGHT:
            if (obj->value[2] == -1)
                sprintf(buf, "Hours of light(v2): Infinite(-1)\n\r");
            else
                sprintf(buf, "Hours of light(v2): %d\n\r", obj->value[2]);
            send_to_char(buf, ch);
            break;

        case ITEM_WAND:
        case ITEM_STAFF:
            sprintf(buf, "(v3) %s\n\rLevel (v0): %d\n\rCharges (v2)/(v1): %d / %d\n\r",
                obj->value[3] != -1 ?
                      capitalize(skill_table[obj->value[3]].name)
                    : "!NO SPELL!",
                obj->value[0], obj->value[2], obj->value[1]);
            send_to_char(buf, ch);
            break;

        case ITEM_SCROLL:
        case ITEM_POTION:
        case ITEM_PILL:
            sprintf(buf, "(v1) %s\n\r(v2) %s\n\r(v3) %s\n\rLevel (v0): %d\n\r",
                obj->value[1] != -1 ?
                      capitalize(skill_table[obj->value[1]].name)
                    : "!NO SPELL!",
                obj->value[2] != -1 ? skill_table[obj->value[2]].name
                                    : "!NO SPELL!",
                obj->value[3] != -1 ? skill_table[obj->value[3]].name
                                    : "!NO SPELL!",
                obj->value[0]);
            send_to_char(buf, ch);
            break;

	case ITEM_ARMOR:
	    sprintf(buf, "Spell(v4):   %s\n\r",
		         spell_name( obj->value[4] ) );
	    send_to_char( buf, ch );
	    break;
        case ITEM_WEAPON:
            sprintf(buf, "Type(v3):    %s\n\r"
			 "Min dam(v1): %d\n\r"
			 "Max dam(v2): %d\n\r"
			 "Spell(v4):   %s\n\r"
                         "FSpell(v0):  %s\n\r",
		flag_string( weapon_flags, obj->value[3] ),
                obj->value[1], obj->value[2],
		spell_name(obj->value[4]),
		(obj->value[0] >=1 && obj->value[0] <= MAX_SKILL) ?
			skill_table[obj->value[0]].name : "None" );
            send_to_char(buf, ch);
            break;

        case ITEM_CONTAINER:
            sprintf(buf, "Weight (v0): %d \n\rFlags (v1): %s\nrKey (v2): %s (%d)\n\r",
                obj->value[0], 
		flag_string( container_flags, obj->value[1] ),
		get_obj_index(obj->value[2])
                    ? get_obj_index(obj->value[2])->short_descr
                    : "none",
                obj->value[2]);
            send_to_char(buf, ch);
            break;

	case ITEM_FOUNTAIN:
	case ITEM_DRINK_CON:
	    sprintf(buf, "Contains (v1)/(v0): %d/%d\n\rLiquid (v2): %s\n\rPoisoned? (v3): %s\n\r",
	        obj->value[1], obj->value[0],
	        flag_string( liquid_flags, obj->value[2] ),
	        obj->value[3] != 0 ? "Yes" : "No");
            send_to_char(buf, ch);
            break;

	case ITEM_FOOD:
	    sprintf(buf, "Hours of food (v0): %d\n\rPoisoned? (v3): %s\n\r",
	        obj->value[0], obj->value[3] != 0 ? "Yes" : "No");
            send_to_char(buf, ch);
            break;

        case ITEM_GRENADE:
            sprintf(buf, "G.Timer (v0) %d\n\rG.Damage (v2): %d\n\r",
            obj->value[0], obj->value[2]);
            send_to_char(buf, ch);
            break;

	case ITEM_MONEY:
            sprintf(buf, "Amount of Gold (v0): %d\n\r", obj->value[0]);
            send_to_char(buf, ch);
            break;
	case ITEM_PORTAL:
	case ITEM_WGATE:
	    sprintf( buf,"To Room   (v0): %d\n\r"
			 "From Room (v3): %d\n\r",
			obj->value[0],obj->value[3]  );
	    stc( buf, ch );
	    break;
    }

    return;
}


bool set_obj_values(CHAR_DATA *ch, OBJ_INDEX_DATA *pObj, int value_num,char *argument)
{
    switch(pObj->item_type)
    {
        default:
            break;
            
        case ITEM_LIGHT:
	    switch (value_num)
	    {
	        default:
		    do_help(ch, "b_ref item_light");
	            break;
	        case 2:
	            send_to_char("HOURS OF LIGHT SET.\n\r\n\r", ch);
	            pObj->value[2] = atoi(argument);
	            break;
	    }
            break;

        case ITEM_WAND:
        case ITEM_STAFF:
	    switch (value_num)
	    {
	        default:
		    do_help(ch, "b_ref item_staff_wand");
	            break;
	        case 0:
	            send_to_char("SPELL LEVEL SET.\n\r\n\r", ch);
	            pObj->value[0] = atoi(argument);
	            break;
	        case 1:
	            send_to_char("TOTAL NUMBER OF CHARGES SET.\n\r\n\r", ch);
	            pObj->value[1] = atoi(argument);
	            break;
	        case 2:
	            send_to_char("CURRENT NUMBER OF CHARGES SET.\n\r\n\r", ch);
	            pObj->value[2] = atoi(argument);
	            break;
	        case 3:
	            send_to_char("SPELL TYPE SET.\n\r", ch);
	            pObj->value[3] = skill_lookup(argument);
	            break;
	    }
            break;

        case ITEM_SCROLL:
        case ITEM_POTION:
        case ITEM_PILL:
	    switch (value_num)
	    {
	        default:
		    do_help(ch, "b_ref item_scroll_potion_pill");
	            break;
	        case 0:
	            send_to_char("SPELL LEVEL SET.\n\r\n\r", ch);
	            pObj->value[0] = atoi(argument);
	            break;
	        case 1:
	            send_to_char("SPELL TYPE 1 SET.\n\r\n\r", ch);
	            pObj->value[1] = skill_lookup(argument);
	            break;
	        case 2:
	            send_to_char("SPELL TYPE 2 SET.\n\r\n\r", ch);
	            pObj->value[2] = skill_lookup(argument);
	            break;
	        case 3:
	            send_to_char("SPELL TYPE 3 SET.\n\r\n\r", ch);
	            pObj->value[3] = skill_lookup(argument);
	            break;
	    }
            break;

        case ITEM_WEAPON:
	    switch (value_num)
	    {
	        default:
		    do_help(ch, "b_ref item_weapon");
	            break;
	        case 0:
		    pObj->value[0] = skill_lookup(argument);
		    send_to_char("WEAPON SPELL SET.\n\r\n\r", ch);
		    break;
	        case 1:
	            send_to_char("MINIMUM DAMAGE SET.\n\r\n\r", ch);
	            pObj->value[1] = atoi(argument);
	            break;
	        case 2:
	            send_to_char("MAXIMUM DAMAGE SET.\n\r\n\r", ch);
	            pObj->value[2] = atoi(argument);
	            break;
	        case 3:
	            send_to_char("WEAPON TYPE SET.\n\r\n\r", ch);
	            pObj->value[3] = flag_value( weapon_flags, argument );	
		    break;
		case 4:
		    send_to_char("SPELL SET.\n\r\n\r", ch );
		    pObj->value[4] = get_spell_item( argument );
		    break;
	    }
            break;

        case ITEM_ARMOR:
	    switch (value_num)
	    {
	        default:
		    do_help(ch, "b_ref item_armor");
	            break;
		case 4:
		    send_to_char("SPELL SET.\n\r\n\r", ch );
		    pObj->value[4] = get_spell_item( argument );
		    break;
	    }
            break;

        case ITEM_CONTAINER:
	    switch (value_num)
	    {
	        default:
		    do_help(ch, "b_ref item_container");
	            break;
	        case 0:
	            send_to_char("WEIGHT CAPACITY SET.\n\r\n\r", ch);
	            pObj->value[0] = atoi(argument);
	            break;
	        case 1:
	            send_to_char("CONTAINER TYPE SET.\n\r\n\r", ch);
	            pObj->value[1] = flag_value(container_flags,argument);
	            break;
	        case 2:
                    if (atoi(argument) != 0)
                    {
		    if (!get_obj_index(atoi(argument)))
		    {
		        send_to_char("THERE IS NO SUCH KEY.\n\r\n\r", ch);
		        break;
		    }
		    if (get_obj_index(atoi(argument))->item_type != ITEM_KEY)
		    {
		        send_to_char("THAT ITEM IS NOT A KEY.\n\r\n\r", ch);
		        break;
		    }
		    }
	            send_to_char("CONTAINER KEY SET.\n\r\n\r", ch);
	            pObj->value[2] = atoi(argument);
	            break;
	    }
            break;

	case ITEM_FOUNTAIN:
	case ITEM_DRINK_CON:
	    switch (value_num)
	    {
	        default:
		    do_help(ch, "b_ref item_drink_con");
		    do_help(ch, "liquids");
	            break;
	        case 0:
	            send_to_char("MAXIMUM AMOUT OF LIQUID HOURS SET.\n\r\n\r", ch);
	            pObj->value[0] = atoi(argument);
	            break;
	        case 1:
	            send_to_char("CURRENT AMOUNT OF LIQUID HOURS SET.\n\r\n\r", ch);
	            pObj->value[1] = atoi(argument);
	            break;
	        case 2:
	            send_to_char("LIQUID TYPE SET.\n\r\n\r", ch);
	            pObj->value[2] = flag_value( liquid_flags, argument );
	            break;
	        case 3:
	            send_to_char("POISON VALUE TOGGLED.\n\r\n\r", ch);
	            pObj->value[3] = (pObj->value[3] == 0) ? 1 : 0;
	            break;
	    }
            break;

	case ITEM_FOOD:
	    switch (value_num)
	    {
	        default:
		    do_help(ch, "b_ref item_food");
	            break;
	        case 0:
	            send_to_char("HOURS OF FOOD SET.\n\r\n\r", ch);
	            pObj->value[0] = atoi(argument);
	            break;
	        case 3:
	            send_to_char("POISON VALUE TOGGLED.\n\r\n\r", ch);
	            pObj->value[3] = (pObj->value[3] == 0) ? 1 : 0;
	            break;
	    }
            break;

        case ITEM_GRENADE:
            switch ( value_num )
            {
                default:
                    do_help( ch, "ITEM_GRENADE" );
                    break;
              case 0:
                  send_to_char( "TIMER SET.\n\r\n\r", ch);
                  pObj->value[0] = atoi( argument );
                  break;
                case 2:
                    send_to_char( "DAMAGE SET.\n\r\n\r", ch );
                    pObj->value[2] = atoi( argument );
                    break;
            }
            break;

	case ITEM_MONEY:
	    switch (value_num)
	    {
	        default:
		    do_help(ch, "b_ref item_money");
	            break;
	        case 0:
	            send_to_char("GOLD AMOUNT SET.\n\r\n\r", ch);
	            pObj->value[0] = atoi(argument);
	            break;
	    }
            break;
	case ITEM_PORTAL:
	case ITEM_WGATE:
	    switch( value_num )
	    {
		default:
		    do_help( ch, "b_ref ITEM_PORTAL" );
		    break;
		case 0:
                    send_to_char( "TO ROOM SET.\n\r\n\r", ch );
                    pObj->value[0] = atoi( argument );
		    break;
		case 3:
                    send_to_char( "FROM ROOM SET.\n\r\n\r", ch );
                    pObj->value[3] = atoi( argument );
		    break;
	    }
	break;
    }

    show_obj_values(ch, pObj);

    return TRUE;
}

/*
 * Need to issue warning if flag isn't valid.
 */
bool oedit_addaffect( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;
    AFFECT_DATA *pAf;
    char loc[MAX_STRING_LENGTH];
    char mod[MAX_STRING_LENGTH];

    EDIT_OBJ(ch, pObj);

    argument = one_argument( argument, loc );
    argument = one_argument( argument, mod );

    if ( loc[0] == '\0' || mod[0] == '\0' || !is_number( mod ) )
    {
	send_to_char( "Syntax:  addaffect [location] [##mod] [minus]\n\r", ch );
	return FALSE;
    }

    pAf             =   new_affect();
    pAf->location   =   flag_value( apply_flags, loc );
    pAf->modifier   =   atoi( mod );
    pAf->type       =   -1;
    pAf->duration   =   -1;
    pAf->bitvector  =   0;
    if( argument[0] != '\0' && !str_cmp( argument, "minus" ) )
	pAf->modifier *= -1;
    pAf->next       =   pObj->affected;
    pObj->affected  =   pAf;

    send_to_char( "Affect added.\n\r", ch);
    return TRUE;
}



/*
 * My thanks to Hans Hvidsten Birkeland and Noam Krendel(Walker)
 * for really teaching me how to manipulate pointers.
 */
bool oedit_delaffect( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;
    AFFECT_DATA *pAf;
    AFFECT_DATA *pAf_next;
    char affect[MAX_STRING_LENGTH];
    int  value;
    int  cnt = 0;

    EDIT_OBJ(ch, pObj);

    one_argument( argument, affect );

    if ( !is_number( affect ) || affect[0] == '\0' )
    {
	send_to_char( "Syntax:  delaffect [#xaffect]\n\r", ch );
	return FALSE;
    }

    value = atoi( affect );

    if ( value < 0 )
    {
	send_to_char( "Only non-negative affect-numbers allowed.\n\r", ch );
	return FALSE;
    }

    if ( !( pAf = pObj->affected ) )
    {
	send_to_char( "OEdit:  Non-existant affect.\n\r", ch );
	return FALSE;
    }

    if( value == 0 )	/* First case: Remove first affect */
    {
	pAf = pObj->affected;
	pObj->affected = pAf->next;
	free_affect( pAf );
    }
    else		/* Affect to remove is not the first */
    {
	while ( ( pAf_next = pAf->next ) && ( ++cnt < value ) )
	     pAf = pAf_next;

	if( pAf_next )		/* See if it's the next affect */
	{
	    pAf->next = pAf_next->next;
	    free_affect( pAf_next );
	}
	else                                 /* Doesn't exist */
	{
	     send_to_char( "No such affect.\n\r", ch );
	     return FALSE;
	}
    }

    send_to_char( "Affect removed.\n\r", ch);
    return TRUE;
}



bool oedit_name( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;

    EDIT_OBJ(ch, pObj);

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

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

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

OEDIT( oedit_artifact )
{
    OBJ_INDEX_DATA *pObj;

    EDIT_OBJ(ch, pObj);

    if ( get_trust(ch) < 10 )
    {
	send_to_char( "You do not have enough trust to make this object an artifact.\n\r", ch );
	return FALSE;
    }
    
    SET_BIT(pObj->quest, QUEST_ARTIFACT);
    return TRUE;
}

/*bool oedit_action( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;

    EDIT_OBJ(ch, pObj);

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  action [string]\n\r", ch );
	return FALSE;
    }

    free_string( pObj->action );
    pObj->action = str_dup( argument );
    pObj->action[0] = LOWER( pObj->action[0] );

    send_to_char( "Action description set.\n\r", ch);
    return TRUE;
    }*/

bool oedit_short( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;

    EDIT_OBJ(ch, pObj);

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  short [string]\n\r", ch );
	return FALSE;
    }

    free_string( pObj->short_descr );
    pObj->short_descr = str_dup( argument );

    send_to_char( "Short description set.\n\r", ch);
    return TRUE;
}

	

bool oedit_long( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;

    EDIT_OBJ(ch, pObj);

    if ( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  long [string]\n\r", ch );
        send_to_char( "         long none\n\r",     ch);
        return FALSE;
    }
        
    if( !str_cmp( argument, "none" ) )
    {
        free_string( pObj->description );
        pObj->description = str_dup( "" );
        send_to_char( "Long description is now none.\n\r",ch);
        return TRUE;
    }

    free_string( pObj->description );
    pObj->description = str_dup( argument );
    pObj->description[0] = UPPER( pObj->description[0] );

    send_to_char( "Long description set.\n\r", ch);
    return TRUE;
}



bool set_value( CHAR_DATA *ch, OBJ_INDEX_DATA *pObj, char *argument, int value )
{
    if ( argument[0] == '\0' )
    {
	set_obj_values( ch, pObj, -1, '\0' );
	return FALSE;
    }

    if ( set_obj_values( ch, pObj, value, argument ) )
	return TRUE;

    return FALSE;
}



/*****************************************************************************
 Name:		oedit_values
 Purpose:	Finds the object and sets its value.
 Called by:	The four valueX functions below.
 ****************************************************************************/
bool oedit_values( CHAR_DATA *ch, char *argument, int value )
{
    OBJ_INDEX_DATA *pObj;

    EDIT_OBJ(ch, pObj);

    if ( set_value( ch, pObj, argument, value ) )
        return TRUE;

    return FALSE;
}

bool oedit_value0( CHAR_DATA *ch, char *argument )
{
    if ( oedit_values( ch, argument, 0 ) )
        return TRUE;

    return FALSE;
}



bool oedit_value1( CHAR_DATA *ch, char *argument )
{
    if ( oedit_values( ch, argument, 1 ) )
        return TRUE;

    return FALSE;
}



bool oedit_value2( CHAR_DATA *ch, char *argument )
{
    if ( oedit_values( ch, argument, 2 ) )
        return TRUE;

    return FALSE;
}



bool oedit_value3( CHAR_DATA *ch, char *argument )
{
    if ( oedit_values( ch, argument, 3 ) )
        return TRUE;

    return FALSE;
}

bool oedit_value4( CHAR_DATA *ch, char *argument )
{
    if ( oedit_values( ch, argument, 4 ) )
        return TRUE;

    return FALSE;
}

bool oedit_weight( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;

    EDIT_OBJ(ch, pObj);

    if ( argument[0] == '\0' || !is_number( argument ) )
    {
	send_to_char( "Syntax:  weight [number]\n\r", ch );
	return FALSE;
    }

    pObj->weight = atoi( argument );

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



bool oedit_cost( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;

    EDIT_OBJ(ch, pObj);

    if ( argument[0] == '\0' || !is_number( argument ) )
    {
	send_to_char( "Syntax:  cost [number]\n\r", ch );
	return FALSE;
    }

    pObj->cost = atoi( argument );

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

bool oedit_ed( CHAR_DATA *ch, char *argument )
{
    OBJ_INDEX_DATA *pObj;
    EXTRA_DESCR_DATA *ed;
    char command[MAX_INPUT_LENGTH];
    char keyword[MAX_INPUT_LENGTH];

    EDIT_OBJ(ch, pObj);

    argument = one_argument( argument, command );
    one_argument( argument, keyword );

    if ( command[0] == '\0' )
    {
	send_to_char( "Syntax:  ed add [keyword]\n\r", ch );
	send_to_char( "         ed delete [keyword]\n\r", ch );
	send_to_char( "         ed edit [keyword]\n\r", ch );
	send_to_char( "         ed format [keyword]\n\r", ch );
	return FALSE;
    }

    if ( !str_cmp( command, "add" ) )
    {
	if ( keyword[0] == '\0' )
	{
	    send_to_char( "Syntax:  ed add [keyword]\n\r", ch );
	    return FALSE;
	}

	ed                  =   new_extra_descr();
	ed->keyword         =   str_dup( keyword );
	ed->next            =   pObj->extra_descr;
	pObj->extra_descr   =   ed;

	string_append( ch, &ed->description );

	return TRUE;
    }

    if ( !str_cmp( command, "edit" ) )
    {
	if ( keyword[0] == '\0' )
	{
	    send_to_char( "Syntax:  ed edit [keyword]\n\r", ch );
	    return FALSE;
	}

	for ( ed = pObj->extra_descr; ed; ed = ed->next )
	{
	    if ( is_name( keyword, ed->keyword ) )
		break;
	}

	if ( !ed )
	{
	    send_to_char( "OEdit:  Extra description keyword not found.\n\r", ch );
	    return FALSE;
	}

	string_append( ch, &ed->description );

	return TRUE;
    }

    if ( !str_cmp( command, "delete" ) )
    {
	EXTRA_DESCR_DATA *ped = NULL;

	if ( keyword[0] == '\0' )
	{
	    send_to_char( "Syntax:  ed delete [keyword]\n\r", ch );
	    return FALSE;
	}

	for ( ed = pObj->extra_descr; ed; ed = ed->next )
	{
	    if ( is_name( keyword, ed->keyword ) )
		break;
	    ped = ed;
	}

	if ( !ed )
	{
	    send_to_char( "OEdit:  Extra description keyword not found.\n\r", ch );
	    return FALSE;
	}

	if ( !ped )
	    pObj->extra_descr = ed->next;
	else
	    ped->next = ed->next;

	free_extra_descr( ed );

	send_to_char( "Extra description deleted.\n\r", ch );
	return TRUE;
    }


    if ( !str_cmp( command, "format" ) )
    {
	EXTRA_DESCR_DATA *ped = NULL;

	if ( keyword[0] == '\0' )
	{
	    send_to_char( "Syntax:  ed format [keyword]\n\r", ch );
	    return FALSE;
	}

	for ( ed = pObj->extra_descr; ed; ed = ed->next )
	{
	    if ( is_name( keyword, ed->keyword ) )
		break;
	    ped = ed;
	}

	if ( !ed )
	{
                send_to_char( "OEdit:  Extra description keyword not found.\n\r", ch );
                return FALSE;
	}

	/* OLC 1.1b */
	if ( strlen(ed->description) >= (MAX_STRING_LENGTH - 4) )
	{
	    send_to_char( "String too long to be formatted.\n\r", ch );
	    return FALSE;
	}

	ed->description = format_string( ed->description );

	send_to_char( "Extra description formatted.\n\r", ch );
	return TRUE;
    }

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

OEDIT( oedit_show )
{
    char buf [ MAX_INPUT_LENGTH ];
    OBJ_INDEX_DATA *pObj;
    EDIT_OBJ( ch, pObj );

    sprintf( buf, "%d", pObj->vnum );
    do_oshow( ch, buf );
    return FALSE;
}
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;
    int  value;

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

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

    if (command[0] == '\0')
    {
        sprintf(arg, "%d", pObj->vnum);
        do_oshow(ch, arg);
        return;
    }


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

    if ( !IS_BUILDER( ch, pArea ) )
    {
        interpret( ch, arg );
        edit_done(ch);
        return;
    }

    for ( cmd = 0; *oedit_table[cmd].name; 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;
        }
    }


    /* Take care of flags. */
    if ( ( value = flag_value( type_flags, arg ) ) != NO_FLAG )
    {
        pObj->item_type = value;

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Type set.\n\r", ch);

        /*
         * Clear the values.
         */
        pObj->value[0] = 0;
        pObj->value[1] = 0;
        pObj->value[2] = 0;
        pObj->value[3] = 0;

        return;
    }
    /*
     * Satanic piece's can only be made with oset
     * or on the gypsy - Dreimas
     */
    if ( str_prefix( arg, "satanic" )
      && ( value = flag_value( extra_flags, arg ) ) != NO_FLAG )
    {
        TOGGLE_BIT(pObj->extra_flags, value);

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Extra flag toggled.\n\r", ch);
        return;
    }

    if ( ( value = flag_value( wear_flags, arg ) ) != NO_FLAG )
    {
        TOGGLE_BIT(pObj->wear_flags, value);

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Wear flag toggled.\n\r", ch);
        return;
    }

    interpret(ch, arg);
    return;
}



/* Entry point for editing obj_index_data. */
void    do_oedit (CHAR_DATA * ch, char *argument)
{
    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 ("{yOEdit:  That vnum does not exist.\n\r", ch);
            return;
        }

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

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

            pArea = get_vnum_area (value);

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

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

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

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

bool medit_create( CHAR_DATA *ch, char *argument )
{
    int value;
    AREA_DATA *pArea;
    MOB_INDEX_DATA *pMob;
    int iHash;
    
    value = atoi(argument);

    if (argument[0] == '\0' || value == 0)
    {
        send_to_char("{ySyntax:  medit create [vnum]\n\r", ch);
        return FALSE;
    }

    pArea = get_vnum_area(value);

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

    if (!IS_BUILDER(ch, pArea))
    {
        send_to_char("{yMEdit:  Vnum in an area you cannot build in.\n\r", ch);
        return FALSE;
    }

    if (get_mob_index(value) != NULL)
    {
        send_to_char("{yMEdit:  Mobile vnum already exists.\n\r", ch);
        return FALSE;
    }

    pMob                    = new_mob_index();
    pMob->vnum              = value;
    pMob->area              = pArea;

    if (value > top_vnum_mob) top_vnum_mob = value;

    pMob->act               = ACT_IS_NPC;
    iHash                   = value % MAX_KEY_HASH;
    pMob->next              = mob_index_hash[iHash];
    mob_index_hash[iHash]   = pMob;

    set_editor( ch->desc, ED_MOBILE, pMob );
    send_to_char("Mobile Created.\n\r", ch);
    return TRUE;
}

MEDIT(medit_show)
{
    MOB_INDEX_DATA *pMob;
    char            buf [ MAX_STRING_LENGTH ];
    
    EDIT_MOB( ch, pMob );
    
    sprintf(buf, "%d", pMob->vnum);
    do_mshow(ch, buf);
    return FALSE;
}

MEDIT(medit_shop)
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    MOB_INDEX_DATA *pMob;
    char buf [MAX_STRING_LENGTH];
    int value;

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

    EDIT_MOB(ch,pMob);
    if (arg1[0] == '\0')
    {
        send_to_char("{YSyntax:  shop hours [##opening] [##closing]\n\r", ch);
        send_to_char("{Y         shop profit [##buying%] [##selling%]\n\r", ch);
        send_to_char("{Y         shop type [##1-5] [item type]\n\r", ch);
        send_to_char("{Y         shop delete\n\r", ch);
        return FALSE;
    }


    if (!str_cmp(arg1, "hours"))
    {
        argument = one_argument(argument, arg1);
        strcpy(arg2, argument);

        if (arg1[0] == '\0' || !is_number(arg1)
            || arg2[0] == '\0' || !is_number(arg2))
        {
            send_to_char("{YSyntax:  shop hours [#opening] [#closing]\n\r", ch);
            return FALSE;
        }

        if (pMob->pShop == NULL)
        {
            pMob->pShop         = new_shop();
            pMob->pShop->keeper = pMob->vnum;
            shop_last->next     = pMob->pShop;
        }

        pMob->pShop->open_hour = atoi(arg1);
        pMob->pShop->close_hour = atoi(arg2);

        send_to_char("Shop hours set.\n\r", ch);
        return TRUE;
    }


    if (!str_cmp(arg1, "profit"))
    {
        argument = one_argument(argument, arg1);
        strcpy(arg2, argument);

        if (arg1[0] == '\0' || !is_number(arg1)
            || arg2[0] == '\0' || !is_number(arg2))
        {
            send_to_char("{YSyntax:  shop profit [#buying%] [#selling%]\n\r", ch);
            return FALSE;
        }

        if (pMob->pShop == NULL)
        {
            pMob->pShop         = new_shop();
            pMob->pShop->keeper = pMob->vnum;
            shop_last->next     = pMob->pShop;
        }

        pMob->pShop->profit_buy     = atoi(arg1);
        pMob->pShop->profit_sell    = atoi(arg2);

        send_to_char("Shop profit set.\n\r", ch);
        return TRUE;
    }


    if (!str_cmp(arg1, "type"))
    {
        argument = one_argument(argument, arg1);
        strcpy(arg2, argument);

        if (arg1[0] == '\0' || !is_number(arg1)
            || arg2[0] == '\0')
        {
            send_to_char("{YSyntax:  shop type [#] [item type]\n\r", ch);
            return FALSE;
        }

        if (atoi(arg1) > MAX_TRADE)
        {
            sprintf(buf, "%d", MAX_TRADE);
            send_to_char("{YREdit:  Shop keepers may only sell ", ch);
            send_to_char(buf, ch);
            send_to_char(" items max.\n\r", ch);
            return FALSE;
        }

	if ( ( value = flag_value( type_flags, argument ) ) == NO_FLAG )
	{
            send_to_char("{YREdit:  That type of item is not known.\n\r", ch);
            return FALSE;
        }

        if (pMob->pShop == NULL)
        {
            pMob->pShop         = new_shop();
            pMob->pShop->keeper = pMob->vnum;
            shop_last->next     = pMob->pShop;
        }

        pMob->pShop->buy_type[atoi(arg1)] = value;

        send_to_char("Shop type set.\n\r", ch);
        return TRUE;
    }


    if (!str_cmp(arg1, "delete"))
    {
        if (pMob->pShop == NULL)
        {
            send_to_char("{YREdit:  Cannot delete a shop that is non-existant.\n\r", ch);
            return FALSE;
        }

        free_shop(pMob->pShop);
        pMob->pShop = NULL;

        send_to_char("Shop deleted.\n\r", ch);
        return TRUE;
    }

    send_to_char("{YSyntax:  shop hours [##opening] [##closing]\n\r", ch);
    send_to_char("{Y         shop profit [##buying%] [##selling%]\n\r", ch);
    send_to_char("{Y         shop type [##] [item type]\n\r", ch);
    send_to_char("{Y         shop delete\n\r", ch);
    return FALSE;
}

MEDIT( medit_name )
{
    MOB_INDEX_DATA *pMob;
    
    EDIT_MOB(ch,pMob);

    if (argument[0] == '\0')
    {
        send_to_char("{YSyntax:  name [string]\n\r", ch);
        return FALSE;
    }

    free_string(pMob->player_name);
    pMob->player_name = str_dup(argument);

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

MEDIT( medit_short )
{
    MOB_INDEX_DATA *pMob;
    
    EDIT_MOB(ch,pMob);

    if (argument[0] == '\0')
    {
        send_to_char("{YSyntax:  short [string]\n\r", ch);
        return FALSE;
    }

    free_string(pMob->short_descr);
    pMob->short_descr = str_dup(argument);

    send_to_char("Short description set.\n\r", ch);
    return TRUE;
}

MEDIT( medit_long )
{
    MOB_INDEX_DATA *pMob;
    
    EDIT_MOB(ch,pMob);
    
    if (argument[0] == '\0')
    {
        send_to_char("{YSyntax:  long [string]\n\r", ch);
        return FALSE;
    }

    free_string(pMob->long_descr);
    strcat( argument, "\n\r" );
    pMob->long_descr = str_dup(argument);
    pMob->long_descr[0] = UPPER( pMob->long_descr[0]  );

    send_to_char("Long description set.\n\r", ch);
    return TRUE;
}

MEDIT( medit_desc )
{
    MOB_INDEX_DATA *pMob;
    
    EDIT_MOB(ch,pMob);

    if (argument[0] == '\0')
    {
        string_append(ch, &pMob->description);
        return TRUE;
    }

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

MEDIT(medit_level)
{
    char arg2[MAX_STRING_LENGTH];
    MOB_INDEX_DATA *pMob;
    
    argument = one_argument(argument, arg2);
    EDIT_MOB(ch,pMob);

    if (arg2[0] == '\0' || !is_number(arg2))
    {
        send_to_char("Syntax:  level [number]\n\r", ch);
        return FALSE;
    }

    pMob->level = atoi(arg2);

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

MEDIT( medit_align )
{
    char arg2[MAX_STRING_LENGTH];
    MOB_INDEX_DATA *pMob;
    
    argument = one_argument(argument, arg2);
    EDIT_MOB(ch,pMob);

    if (arg2[0] == '\0' || !is_number(arg2))
    {
        send_to_char("Syntax:  alignment [number]\n\r", ch);
        return FALSE;
    }

    pMob->alignment = atoi(arg2);

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

MEDIT( medit_spec )
{
    char arg[MAX_STRING_LENGTH];
    MOB_INDEX_DATA *pMob;
    
    argument = one_argument(argument, arg);
    EDIT_MOB(ch,pMob);

    if (!str_cmp(arg, "none"))
    {
        pMob->spec_fun = NULL;

        send_to_char("Spec removed.\n\r", ch);
        return TRUE;
    }

    if (spec_lookup(arg) != NULL)
    {
        pMob->spec_fun = spec_lookup(arg);


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

    send_to_char("{yInvalid Special.  Use ? special to see a list of them.\n\r", ch );
    return FALSE;
}


void medit(CHAR_DATA *ch, char *argument)
{
    AREA_DATA *pArea;
    MOB_INDEX_DATA *pMob;
    char arg[MAX_STRING_LENGTH];
    char arg1[MAX_STRING_LENGTH];
    char arg2[MAX_STRING_LENGTH];
    char buf[MAX_STRING_LENGTH];
    int  value ,cmd;

    strcpy(arg, argument);
    smash_tilde(argument);
    argument = one_argument(argument, arg1);
    strcpy(arg2, argument);

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


    if (arg1[0] == '\0')
    {
        sprintf(buf, "%d", pMob->vnum);
        do_mshow(ch, buf);
        return;
    }


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


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

    
    /* Take care of flags. */
    if ( ( value = flag_value( sex_flags, arg ) ) != NO_FLAG )
    {
        pMob->sex = value;

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Sex set.\n\r", ch);
        return;
    }


    if ( ( value = flag_value( act_flags, arg ) ) != NO_FLAG )
    {
        TOGGLE_BIT(pMob->act, value);

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Act flag toggled.\n\r", ch);
        return;
    }


    if ( ( value = flag_value( affect_flags, arg ) ) != NO_FLAG )
    {
        TOGGLE_BIT(pMob->affected_by, value);

        SET_BIT( pArea->area_flags, AREA_CHANGED );
        send_to_char( "Affect flag toggled.\n\r", ch);
        return;
    }

    interpret(ch, arg);
    return;
}

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

    argument = one_argument (argument, arg1);

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

        if (!IS_BUILDER (ch, pMob->area))
        {
            send_to_char ("{YInsufficant security to edit mobs.\n\r", ch);
            return;
        }

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

            pArea = get_vnum_area (value);

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

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

            if ( medit_create( ch, argument ) )
                SET_BIT (pArea->area_flags, AREA_CHANGED);
            return;
        }
    }

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

void do_ashow(CHAR_DATA *ch, char *argument)
{
    AREA_DATA *pArea;
    char arg1 [MAX_INPUT_LENGTH];
    char buf  [MAX_STRING_LENGTH];
    int pdeaths = 0, pkills = 0, mdeaths = 0, mkills = 0; 

    if( !str_cmp( "summary", argument ) )
    {
	for ( pArea = area_first; pArea; pArea = pArea->next )
	{
	    pdeaths += pArea->pdeaths;
	    mdeaths += pArea->mdeaths;
	    pkills  += pArea->pkills;
	    mkills  += pArea->mkills;
	}
        ch_printf( ch, "{WTotal pdeaths:      {x%d\n\r", pdeaths );
        ch_printf( ch, "{WTotal pkills:       {x%d\n\r", pkills );
        ch_printf( ch, "{WTotal mdeaths:      {x%d\n\r", mdeaths );
        ch_printf( ch, "{WTotal mkills:       {x%d\n\r", mkills );
   	return;
    }

    smash_tilde(argument);
    strcpy(arg1, argument);

    if (is_number(arg1))
        pArea = get_area_data(atoi(arg1));
    else
        pArea = ch->in_room->area;
        
    if (!pArea)
      pArea = ch->in_room->area;

    sprintf(buf, "{cName: {n%s\n\r", pArea->name);
    send_to_char(buf, ch);

    sprintf(buf, "{cFile: {n%s\n\r", pArea->filename);
    send_to_char(buf, ch);

    sprintf(buf, "{cAge: {n%d\n\r{cPlayers: {n%d\n\r", 
	pArea->age, pArea->nplayer);
    send_to_char(buf, ch);
    sprintf(buf, "{cMod: {n%d\n\r", pArea->mod );
    stc( buf, ch );

    sprintf(buf, "{cSecurity: {n%d\n\r{cBuilders {n%s\n\r", 
	pArea->security, pArea->builders);
    send_to_char(buf, ch);

    ch_printf( ch, "{cMdeaths: {n%d   {cMkills: {n%d  {cPdeaths: {n%d  {cPkills: {n%d\n\r",
			pArea->mdeaths,
			pArea->mkills,
			pArea->pdeaths,
			pArea->pkills );

    sprintf(buf, "{cVnums: {n%d{c-{n%d\n\r", pArea->lvnum, pArea->uvnum);
    send_to_char(buf, ch);

    sprintf(buf, "{cFlags: {n%s\n\r", 
		flag_string( area_flags, pArea->area_flags ));
    send_to_char(buf, ch);

    return;
}

void rtext_show( CHAR_DATA *ch, ROOMTEXT_DATA * rt )
{
    ch_printf( ch, "{cType:     {C%s  ",   flag_string( rt_flags, rt->type ) );
    ch_printf( ch, "{cPower:    {n%d  ",   rt->power );
    ch_printf( ch, "{cMob:      {n%d\n\r", rt->mob   );
    ch_printf( ch, "{cInput:    {n%s\n\r", rt->input );
    ch_printf( ch, "{cName:     {n%s\n\r", rt->name );
    ch_printf( ch, "{cOutput:   {n%s\n\r", rt->output );
    ch_printf( ch, "{cChOutput: {n%s\n\r", rt->choutput );

};

void do_rshow(CHAR_DATA *ch, char *argument)
{
    OBJ_DATA        *obj;
    CHAR_DATA       *rch;
    ROOM_INDEX_DATA *location;
    char             buf  [ MAX_STRING_LENGTH ];
    char             arg  [ MAX_INPUT_LENGTH  ];
    int              door;

    rch = get_char(ch);

    one_argument(argument, arg);
    location = (arg[0] == '\0') ? ch->in_room : find_location(ch, arg);
    if (!location)
    {
	send_to_char("No such location.\n\r", ch);
	return;
    }

    if (ch->in_room != location && room_is_private(location))
    {
	send_to_char("That room is private right now.\n\r", ch);
	return;
    }


    ch_printf(ch, "{cName: {n%s\n\r{cArea: {n%3d %s {cFile {n%s\n\r",
	    location->name,
  	    location->area ? location->area->vnum : 0,
	    location->area ? location->area->name : "None????",
	    location->area ? location->area->filename : "None????" );
    ch_printf(ch,
	    "{cVnum: {n%d\n\r{cSector: {n(%d) %s\n\r{cLight: {n%d\n\r",
	    location->vnum,
	    location->sector_type,
	    flag_string( sector_flags, location->sector_type),
	    location->light);

    ch_printf(ch,
	    "{cRoom flags: {n%s\n\r{cDescription:\n\r{n%s",
	    flag_string(room_flags, location->room_flags),
	    location->description);

    if (location->extra_descr)
    {
	EXTRA_DESCR_DATA *ed;

	stc( "{cExtra description keywords: {n'", ch);
	for (ed = location->extra_descr; ed; ed = ed->next)
	{
	    stc( ed->keyword, ch );
	    if (ed->next)
		stc( " ", ch );
	}
	stc("'\n\r", ch);
    }

    if (location->roomtext )
    {
        ROOMTEXT_DATA * rt;

        stc( "{cRoom Text triggers:{n\n\r", ch );
        for( door=1,rt = location->roomtext; rt; rt = rt->next,door++ )
     	{
	    ch_printf( ch, "{C%d{n: %s", door, rt->input);
	    if( rt->next )
		stc("  ", ch );
	}
	stc( "\n\r", ch );
    }
    
    stc("{cCharacters:{n", ch);
    for (rch = location->people; rch; rch = rch->next_in_room)
    {
	stc(" ",ch);
	one_argument(rch->name, buf);
	stc(buf,ch);
    }

    stc("\n\r{cObjects:{n ",ch);
    for (obj = location->contents; obj; obj = obj->next_content)
    {
	stc(" ",ch);
	one_argument(STR(obj, name), buf);
	stc(buf,ch);
    }
    stc("\n\r",ch);

    send_to_char( "{cTracking: {n",ch);
    for ( door = 0; door < 4; door ++ )
	ch_printf( ch, "%d)%s ", door,
				location->track[door][0] == '\0' ? " " :
				location->track[door] );
    send_to_char("\n\r", ch );
	
    for (door = 0; door < MAX_DIR; door++)
    {
	EXIT_DATA *pexit;
	int cnt = 0;

	if ((pexit = location->exit[door]))
	{
	   if( door == 0 )
		stc( "{c------------------- {nEXITS {c-------------------\n\r", ch );

	   ch_printf(ch,
"{W%2d) {n%2s to %-5d  {cKey: {n%d  {cKeywords: '{n%s{c'  Flags: (%d) '%s'\n\r"
"     {cExdesc: {n%s\n\r",
		    ++cnt,
		    dir_name[door],
		    pexit->to_room ? pexit->to_room->vnum : 0,
		    pexit->key,
		    pexit->keyword,
		    pexit->exit_info,
		    flag_string( exit_flags, pexit->exit_info),
	            pexit->description[0] != '\0'
		        ? pexit->description : "(none)\n\r" );
	}
    }

    if ( location->affected )
    {
       ROOM_AFFECT_DATA * raf;
       for ( raf = location->affected; raf; raf = raf->next )
       {
          ch_printf( ch,"{cRoom_Affect: {w'%s', {ccaster {w%s{c, duration {w%d\n\r",
             room_aff_table[raf->type].name, 
	     raf->caster ? raf->caster->name : "none",
	     raf->duration );
       }
    }
 
    stc( "\n\r", ch );
    return;
}



void do_mshow(CHAR_DATA *ch, char *argument)
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    MOB_INDEX_DATA *victim;

    one_argument(argument, arg);

    if (arg[0] == '\0')
    {
    send_to_char("MShow whom?\n\r", ch);
        return;
    }

    if ((victim = get_mob_index(atoi(arg))) == NULL)
    {
    send_to_char("Invalid mob index VNUM.\n\r", ch);
        return;
    }

    sprintf(buf, "Name: '%s'\n\rArea %d: '%s'\n\r",
    victim->player_name,
    victim->area == NULL ? -1        : victim->area->vnum,
    victim->area == NULL ? "No Area" : victim->area->name);
    send_to_char(buf, ch);

    sprintf(buf, "Act: %s\n\r", flag_string( act_flags, victim->act));
    send_to_char(buf, ch);

    sprintf(buf, "Vnum: %d\n\rSex:  %s\n\r",
    victim->vnum,
    victim->sex == SEX_MALE    ? "male"   :
    victim->sex == SEX_FEMALE  ? "female" : "neutral");
    send_to_char(buf, ch);

    sprintf(buf,
    "Level: %d\n\rAlign: %d\n\r",
    victim->level,       victim->alignment);
    send_to_char(buf, ch);

    sprintf(buf, "Affected by: %s\n\r",
                  flag_string(affect_flags, victim->affected_by ));
    send_to_char(buf, ch);

    sprintf(buf, "Short description: %s\n\rLong description:\n\r%s",
    victim->short_descr,
    victim->long_descr);
    send_to_char(buf, ch);

    sprintf(buf, "Description:\n\r%s", victim->description);

    if (victim->spec_fun != NULL)
    {
        sprintf(buf, "Spec fun: %s\n\r",  spec_name(victim->spec_fun));
        send_to_char(buf, ch);
    }

    if (victim->pShop != NULL)
    {
        SHOP_DATA *pShop;
        int iTrade;

        pShop = victim->pShop;

        sprintf(buf, "Shop data (for %d):\n\r    Will buy at %d%%, and sell at %d%%.\n\r",
                      pShop->keeper, pShop->profit_buy, pShop->profit_sell);
        send_to_char(buf, ch);
        sprintf(buf, "    Opens at %d, closes at %d.\n\r",
                      pShop->open_hour, pShop->close_hour);
        send_to_char(buf, ch);

        for (iTrade = 0; iTrade < MAX_TRADE; iTrade++)
        {
            if (pShop->buy_type[iTrade] != ITEM_NONE)
            {
                sprintf(buf, "    Buys %ss (#%d)\n\r",
                         flag_string( type_flags, pShop->buy_type[iTrade]), 
			iTrade);
                send_to_char(buf, ch);
            }
        }
    }

    return;
}




void do_oshow(CHAR_DATA *ch, char *argument)
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    AFFECT_DATA *paf;
    OBJ_INDEX_DATA *obj;
    int cnt;

    one_argument(argument, arg);

    if (arg[0] == '\0')
    {
    send_to_char("OShow what?\n\r", ch);
        return;
    }

    if ((obj = get_obj_index(atoi(arg))) == NULL)
    {
    send_to_char("Invalid VNUM reference.\n\r", ch);
        return;
    }

    sprintf(buf, "Name: '%s'\n\rArea %d: '%s'\n\r",
    obj->name,
    obj->area == NULL ? -1        : obj->area->vnum,
    obj->area == NULL ? "No Area" : obj->area->name);
    send_to_char(buf, ch);


    sprintf(buf, "Vnum: %d\n\rType: %s\n\r",
    obj->vnum,
    flag_string(type_flags, obj->item_type));
    send_to_char(buf, ch);

    sprintf(buf, "Short description: %s\n\rLong description: %s\n\r",
        obj->short_descr, obj->description);
    send_to_char(buf, ch);

    sprintf(buf, "Wear flags: %s\n\r",
            flag_string( wear_flags, obj->wear_flags ));
    send_to_char(buf,ch);
    sprintf(buf, "Extra flags: %s\n\r",
	    flag_string( extra_flags, obj->extra_flags ));
    send_to_char(buf, ch);

    sprintf(buf, "Quest flags: %s\n\r",
	    flag_string(quest_flags, obj->quest ) );
    send_to_char( buf, ch );

    sprintf(buf, "Weight: %d\n\rCost: %d\n\r",
    obj->weight, obj->cost);
    send_to_char(buf, ch);

    show_obj_values(ch, obj);

    if (obj->extra_descr != NULL)
    {
        EXTRA_DESCR_DATA *ed;

    send_to_char("Extra description keywords: ", ch);

        for (ed = obj->extra_descr; ed != NULL; ed = ed->next)
        {
        send_to_char("'", ch);
            send_to_char(ed->keyword, ch);
        send_to_char("'", ch);
        }

    send_to_char("\n\r", ch);
    }

    for (cnt=0,paf = obj->affected; paf != NULL; paf = paf->next, cnt++)
    {
       sprintf(buf, "%d) Affects %s by %d.\n\r",
		cnt,
		affect_loc_name(paf->location),
                paf->modifier);
       send_to_char(buf, ch);
    }

    return;
}



void display_resets(CHAR_DATA *ch, ROOM_INDEX_DATA *pRoomIndex)
{
    char    buf[MAX_STRING_LENGTH];
    char    final[MAX_STRING_LENGTH];
    int     iReset = 0;
    RESET_DATA *pReset;
    MOB_INDEX_DATA *pMob = NULL;
    OBJ_INDEX_DATA *pObj;
    MOB_INDEX_DATA *pMobIndex;
    OBJ_INDEX_DATA *pObjIndex;
    OBJ_INDEX_DATA *pObjToIndex;

    final[0] = '\0';

    stc(
        " {wNo.  Loads    Description       Location         Vnum   Ar Rm Description"
        "\n\r"
        "{B==== ======== ============= =================== ======== ===== ==========="
        "\n\r", ch);

    for (pReset = pRoomIndex->reset_first; pReset; pReset = pReset->next)
    {

        final[0] = '\0';
        sprintf (final, "{B[{w%2d{B] ", ++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, "{bLoad Mobile - Bad Mob {w%d\n\r",pReset->arg1 );
                strcat( final, buf );
                continue;
            }

            pMob = pMobIndex;
            sprintf( buf, "{bM{B[{w%5d{b] {w%-13.13s {Bin room             {bR{B[{w%5d{B] [{w%3d{B] {w%-15.15s\n\r",
                       pReset->arg1, pMob->short_descr, pReset->arg3,
                       pReset->arg2, 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, "{bLoad Object - Bad Object {w%d\n\r",
                    pReset->arg1 );
                strcat( final, buf );
                continue;
            }

            pObj       = pObjIndex;


            sprintf( buf, "{bO{B[{w%5d{B] {w%-13.13s {Bin room"
                          "             {bR{B[{w%5d{B] {w%-15.15s\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, "{bPut Object - Bad Object {w%d\n\r",
                    pReset->arg1 );
                strcat( final, buf );
                continue;
            }

            pObj       = pObjIndex;

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

            sprintf( buf,
                "{bO{B[{w%5d{B] {w%-13.13s {Binside              {bO{B[{w%5d{B]       {w%-15.15s\n\r",
                pReset->arg1,
                pObj->short_descr,
                pReset->arg3,
                pObjToIndex->short_descr );
            strcat( final, buf );

            break;

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

            pObj       = pObjIndex;

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

            if ( pMob->pShop )
            {
            sprintf( buf,
                "{bO{B[{w%5d{B] {w%-13.13s {Bin the inventory of {bS{B[{w%5d{B]       %-15.15s\n\r",
                pReset->arg1,
                pObj->short_descr,                           
                pMob->vnum,
                pMob->short_descr  );
            }
            else
            sprintf( buf,
                "{bO{B[{w%5d{B] {w%-13.13s {B%-19.19s {bM{B[{w%5d{B]       {w%-15.15s\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, "{bR{B[{b%5d{B] {w%s {Bdoor of &w%-19.19s {Breset to {b%s\n\r",
                pReset->arg1,
                capitalize( dir_name[ pReset->arg2 ] ),
                pRoomIndex->name,
                flag_string( exit_flags, pReset->arg3 ) );
            strcat( final, buf );

            break;

        case 'R':
            if ( !( pRoomIndex = get_room_index( pReset->arg1 ) ) )
            {
                sprintf( buf, "{bRandomize Exits - Bad Room {w%d\n\r",
                    pReset->arg1 );
                strcat( final, buf );
                continue;
            }

            sprintf( buf, "{bR{B[{w%5d{B] {bExits are randomized in {w%s\n\r",
                pReset->arg1, pRoomIndex->name );
            strcat( final, buf );

            break;
        }
        send_to_char( final, ch );
    }


    return;
}



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;
}



int get_max_dir(CHAR_DATA *ch, int arg)
{
    char buf[MAX_INPUT_LENGTH];

    if (arg < 0 || arg >= MAX_DIR)
    {
	sprintf(buf, "Doors range from 0 to %d.\n\r", MAX_DIR-1);
	send_to_char(buf, ch);
	return -1;
    }
    else
	return arg;
}

 


void do_resets(CHAR_DATA *ch, 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;

    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);

    if (arg1[0] == '\0') {
        if (ch->in_room->reset_first != NULL) {
			display_resets(ch,ch->in_room);
		}
        else
        send_to_char("No resets in this area.\n\r", ch);
    }

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

        else
        if( !str_cmp( arg2, "maze") && is_number( arg3 ) )
        {
            int doors = 0;
            int door = 0;

            for( door = 0; door < MAX_DIR; door++ )
            {
                if( ch->in_room->exit[door] )
                    doors++;
            }
            door = atoi( arg3 );

            if( door == 4 )
            {
                if( doors != 4 )
                {
                    send_to_char("You must have 4 exits in the room.\n\r",ch);
                    return;
                }
            }
            else if( door == 6 )
            {
                if( doors != 6 )
                {
                    send_to_char( "You must have 6 exits in the room.\n\r",ch);
                    return;
                }
            }
            else
            {
                send_to_char("You must use either 4 or 6 for thedoors.\n\r",ch);
                return;
            }
                                  
            pReset = new_reset_data();
            pReset->command = 'R';
            pReset->arg1    = ch->in_room->vnum;
            pReset->arg2    = doors;
            pReset->arg3    = 0;

            add_reset( ch->in_room, pReset, atoi( arg1 ) );
            ch_printf(ch,"%d doors will now be shoufled in this room.\n\r",doors);
        }
        else
        {
        send_to_char( "Syntax: RESET\n\r",ch );
        send_to_char( "        RESET <number> MAZE <doors> \n\r", ch );
        send_to_char( "        RESET <number> DELETE\n\r", ch );
        }
    }


    return;
}

void save_helps( FILE *fp, HELP_AREA *ha )
{
	HELP_DATA *help = ha->first;

	fprintf( fp, "#HELPS\n" );

	for ( ; help; help = help->next_area )
	{
		fprintf( fp, "%d %s~\n", help->level, help->keyword );
		fprintf( fp, "%s~\n\n", strip_cr( help->text ) );
	}

	fprintf( fp, "-1 $~\n\n" );

	ha->changed = FALSE;

	return;
}

void save_other_helps( CHAR_DATA *ch )
{
	extern HELP_AREA * had_list;
	HELP_AREA *ha;
	FILE *fp;
	char buf[MIL];

	for ( ha = had_list; ha; ha = ha->next )
		if ( ha->changed == TRUE
		&&   ha->area == NULL )
		{
			sprintf( buf, "%s", ha->filename );

			fp = fopen( buf, "w" );

			if ( !fp )
			{
				perror( ha->filename );
				return;
			}

			save_helps( fp, ha );

			if ( ch )
				ch_printf( ch, "%s\n\r", ha->filename);

			fprintf( fp, "#$\n" );
			fclose( fp );
		}

	return;
}

void fold_area( AREA_DATA *tarea, char *filename )
{
    ROOM_INDEX_DATA	*pRoomIndex;
    MOB_INDEX_DATA	*pMobIndex;
    OBJ_INDEX_DATA	*pObjIndex;
    EXTRA_DESCR_DATA    *pEd;
    RESET_DATA          *pReset;
    EXIT_DATA           *pExit;
    AFFECT_DATA         *pAf;
    ROOMTEXT_DATA       *pRt;
    FILE		*fp;
    int			 iHash;
    int                  door,x =0;
    int                  vnum;

    if ( ( fp = fopen( filename, "w" ) ) == NULL )
    {
	bug( "fold_area: fopen", 0 );
	perror( filename );
	return;
    }

    if( IS_SET(tarea->area_flags, AREA_ADDED ) )
	REMOVE_BIT( tarea->area_flags, AREA_ADDED );

    fprintf(fp, "#ADAREA\n");
    fprintf(fp, "N %s~\n",        strip_cr(tarea->name));
    fprintf(fp, "B %s~\n",        strip_cr(tarea->builders));
    fprintf(fp, "V %d %d\n",      tarea->lvnum, tarea->uvnum);
    fprintf(fp, "S %d\n",         tarea->security);
    fprintf(fp, "F %d\n",         tarea->area_flags);
    fprintf(fp, "M %d\n",         tarea->mod );
    fprintf(fp, "End\n\n\n");
  
    if ( tarea->helps && tarea->helps->first )
	save_helps( fp, tarea->helps );

    fprintf(fp, "#ADMOBS\n");
    for(iHash = 0; iHash < MAX_KEY_HASH; iHash++)
    {
        for(    pMobIndex = mob_index_hash[iHash]; 
		pMobIndex;
		pMobIndex = pMobIndex->next )
        {
            if (pMobIndex == NULL || pMobIndex->area != tarea)
            	continue;

        fprintf(fp, "#%d\n",		pMobIndex->vnum);
        fprintf(fp, "N %s~\n",		strip_cr(pMobIndex->player_name));
        fprintf(fp, "S %s~\n",		strip_cr(pMobIndex->short_descr));
        fprintf(fp, "L %s~\n",		strip_cr(pMobIndex->long_descr));
        fprintf(fp, "D %s~\n",		strip_cr(pMobIndex->description));
        fprintf(fp, "A %d\n",		pMobIndex->act);
        fprintf(fp, "Af %d\n",		pMobIndex->affected_by);
        fprintf(fp, "Al %d\n",	pMobIndex->alignment);
        fprintf(fp, "Lv %d\n",		pMobIndex->level);
        fprintf(fp, "G %d\n",		pMobIndex->gold);
        fprintf(fp, "Sx %d\n",          pMobIndex->sex);
        if( pMobIndex->spec_fun )
            fprintf(fp, "Sp %s\n",      spec_name(pMobIndex->spec_fun) );
        
        if ( pMobIndex->pShop != NULL )
        {
	    int iTrade;
            fprintf( fp, "Shop\n" );

            fprintf( fp, " P %d %d\n", pMobIndex->pShop->profit_buy,
                     pMobIndex->pShop->profit_sell );
            fprintf( fp, " H %d %d\n", pMobIndex->pShop->open_hour,
                     pMobIndex->pShop->close_hour  );
            for( iTrade = 0; iTrade < MAX_TRADE; iTrade++ )
            {
                if( pMobIndex->pShop->buy_type[iTrade] > 0 )
                    fprintf( fp, "T %d %d\n", iTrade,
                             pMobIndex->pShop->buy_type[iTrade] );
            }
            fprintf( fp, "EndShop\n" );
        }
        fprintf(fp, "End\n");
	}
    }
    fprintf(fp, "#0\n\n\n\n");

    fprintf( fp, "#ADOBJ\n" );

    for(iHash = 0; iHash < MAX_KEY_HASH; iHash++)
    {
        for(    pObjIndex = obj_index_hash[iHash]; 
		pObjIndex;
		pObjIndex = pObjIndex->next )
        {
            if (pObjIndex == NULL || pObjIndex->area != tarea)
            	continue;

        fprintf(fp, "#%d\n",    pObjIndex->vnum);
        fprintf(fp, "N %s~\n",    strip_cr(pObjIndex->name));
        fprintf(fp, "S %s~\n",    strip_cr(pObjIndex->short_descr));
        fprintf(fp, "D %s~\n",    strip_cr(pObjIndex->description));
        fprintf(fp, "T %d\n",      pObjIndex->item_type);
        fprintf(fp, "E %d\n",      pObjIndex->extra_flags);
        fprintf(fp, "W %d\n",     pObjIndex->wear_flags);
        if( pObjIndex->quest != 0 )
 	    fprintf(fp, "Qf %d\n",     pObjIndex->quest );
        
        for( x = 0; x < MAX_OVALUE; x++ )
        {
            fprintf( fp, "V %d ",x);
            switch (pObjIndex->item_type)
            {
            default:
                fprintf(fp, "%d\n",  pObjIndex->value[x] );
                break;
            case ITEM_PILL: case ITEM_POTION: case ITEM_SCROLL:
                if( x > 0 )
                    fprintf(fp, "%d\n", sn_lookup(pObjIndex->value[x]));
                else
                    fprintf(fp, "%d\n", pObjIndex->value[x] );
                break;
            case ITEM_STAFF: case ITEM_WAND:
                fprintf(fp, "%d\n", (x > 2) ? sn_lookup(pObjIndex->value[x]) :
                        pObjIndex->value[x] );
                break;
            }
        }
        fprintf(fp, "Wg %d\n", pObjIndex->weight);
        fprintf(fp, "C %d\n", pObjIndex->cost);

        for(pAf = pObjIndex->affected; pAf ; pAf = pAf->next)
        {
            fprintf(fp, "A\n%d %d\n",  pAf->location, pAf->modifier);
        }

        for(pEd = pObjIndex->extra_descr; pEd ; pEd = pEd->next)
        {
            fprintf(fp, "ED\n%s~\n%s~\n", pEd->keyword,
                    strip_cr(pEd->description));
        }

        if (pObjIndex->spectype > 0)
        {
            fprintf(fp, "Q\n%s~\n%s~\n%s~\n%s~\n%s~\n%s~\n%d %d\n",
                    strip_cr(pObjIndex->chpoweron),
                    strip_cr(pObjIndex->chpoweroff),
                    strip_cr(pObjIndex->chpoweruse),
                    strip_cr(pObjIndex->victpoweron),
                    strip_cr(pObjIndex->victpoweroff),
                    strip_cr(pObjIndex->victpoweruse),
                    pObjIndex->spectype,     pObjIndex->specpower);
        }
        fprintf(fp, "End\n");
	}
    }
    fprintf( fp, "#0\n\n\n\n" );


    /* save rooms   */
    fprintf( fp, "#ADROOMS\n" );
    for ( vnum = tarea->lvnum; vnum <= tarea->uvnum; vnum++ )
    {
        if ( (pRoomIndex = get_room_index( vnum )) == NULL )
            continue;

	if( pRoomIndex->area != tarea )
		continue;

        fprintf(fp, "#%d\n",		pRoomIndex->vnum);
        fprintf(fp, "N %s~\n",		strip_cr(pRoomIndex->name));
        fprintf(fp, "D %s~\n",		strip_cr(pRoomIndex->description));
        fprintf(fp, "F %d\n",		pRoomIndex->room_flags);
        fprintf(fp, "S %d\n",		pRoomIndex->sector_type);

        for (pEd = pRoomIndex->extra_descr; pEd;  pEd = pEd->next)
            fprintf(fp, "ED\n%s~\n%s~\n", pEd->keyword, strip_cr(pEd->description));

        for( pReset = pRoomIndex->reset_first; pReset; pReset = pReset->next )
            fprintf( fp, "R %c %d %d %d\n", pReset->command,
                     pReset->arg1,
                     pReset->arg2,
                     pReset->arg3 );

        for(door = 0; door < MAX_DIR; door++)
        {
            if ( (pExit = pRoomIndex->exit[door] ) != NULL
                 && pExit->to_room
		 && pExit->to_room->vnum > 0 )
            {
                fprintf( fp, "Dr %d %d %d %d\n", door,
                         pExit->rs_flags,
                         pExit->key,
                         pExit->to_room->vnum );

                fprintf( fp, "%s~\n", strip_cr( pExit->description ) );
                if ( pExit->keyword != NULL )
                    fprintf( fp, "%s~\n", strip_cr( pExit->keyword ) );
                else
                    fprintf( fp, "~\n" );
            }
        }

        for (pRt = pRoomIndex->roomtext; pRt; pRt = pRt->next)
        {
            fprintf(fp, "T\n%s~\n%s~\n%s~\n%s~\n%d %d %d\n",
                    pRt->input, pRt->output, pRt->choutput, pRt->name,
                    pRt->type, pRt->power, pRt->mob);
        }
        fprintf(fp, "End\n");
    }
    fprintf( fp, "#0\n\n\n" );

    fprintf( fp, "#$\n" );
    fclose( fp );
    return;
}


/*****************************************************************************
 Name:		save_area_list
 Purpose:	Saves the listing of files to be loaded at startup.
 Called by:	do_asave(olc_save.c).
 ****************************************************************************/
void save_area_list( bool build )
{
    FILE *fp;
    AREA_DATA *pArea;
    extern HELP_AREA * had_list;
    HELP_AREA * ha;
    char buf[MAX_STRING_LENGTH];

    sprintf( buf, "%s", build ? BUILD_DIR BUILD_LIST : AREA_LIST );
//    sprintf( buf, "%s", BUILD_DIR BUILD_LIST );
    if ( ( fp = fopen( buf, "w" ) ) == NULL )
    {
	bug( "Save_area_list: fopen", 0 );
	perror( buf );
    }
    else
    {
        if( !build )
        {
            for ( ha = had_list; ha; ha = ha->next )
		if ( ha->area == NULL )
			fprintf( fp, "%s\n", ha->filename );

            for( pArea = area_first; pArea; pArea = pArea->next )
            {
                fprintf( fp, "%s\n", pArea->filename );
            }
        }
        else
        {
#ifdef BUILD_AREAS
            for( pArea = build_first; pArea; pArea = pArea->next )
                fprintf( fp, "%s\n", pArea->filename );
#endif
        }
	fprintf( fp, "$\n" );
	fclose( fp );
    }

    return;
}

void do_asave(CHAR_DATA *ch, char *argument)
{
    char arg1 [MAX_INPUT_LENGTH];
    AREA_DATA *pArea;
    FILE *fp;
    int value;

    fp = NULL;

    if (ch == NULL)       /* Do an autosave */
    {
//        save_area_list(  FALSE );
        for(pArea = area_first; pArea != NULL; pArea = pArea->next)
        {
	    if( !IS_SET(pArea->area_flags, AREA_CHANGED ) )
		continue;
            REMOVE_BIT(pArea->area_flags, AREA_CHANGED);
            fold_area( pArea , pArea->filename );
        }
	save_other_helps(NULL);
        return;
    }

    smash_tilde(argument);
    strcpy(arg1, argument);

    if (arg1[0] == '\0')
    {
    send_to_char("Syntax:\n\r", ch);
    send_to_char("  asave list     - saves the area.lst file\n\r",    ch);
    send_to_char("  asave zone     - saves the zone you're in\n\r",   ch);
    send_to_char("  asave changed  - saves all changed zones\n\r",    ch);
    send_to_char("  asave world    - saves the world! (db dump)\n\r", ch);
    send_to_char("  asave helps    - saves the helps\n\r", ch );
    send_to_char("\n\r", ch);
        return;
    }

    /*
     * Snarf the value (which need not be numeric).
     */
    value = atoi(arg1);

    if ((pArea = get_area_data(value)) == '\0' && is_number(arg1))
    {
        send_to_char("That area does not exist.\n\r", ch);
        return;
    }

    if (is_number(arg1))
    {
        save_area_list( FALSE );
        fold_area(pArea, pArea->filename);
        return;
    }

    if (!str_cmp("world", arg1) || !str_cmp("all", arg1))
    {
        save_area_list( FALSE );
        for(pArea = area_first; pArea != '\0'; pArea = pArea->next)
        {
            fold_area( pArea,pArea->filename );
            REMOVE_BIT(pArea->area_flags, AREA_CHANGED);
        }
	save_other_helps(ch);
        send_to_char("You saved the world.\n\r", ch);
	send_to_all_char("Database saved.\n\r");
        return;
    }

    if (!str_cmp("changed", arg1))
    {
        char buf[MAX_INPUT_LENGTH];

        save_area_list( FALSE );

        send_to_char("Saved zones:\n\r", ch);
        sprintf(buf, "None.\n\r");

        for(pArea = area_first; pArea != '\0'; pArea = pArea->next)
        {
            if (IS_SET(pArea->area_flags, AREA_CHANGED))
            {
                REMOVE_BIT(pArea->area_flags, AREA_CHANGED);
                fold_area(pArea,pArea->filename);
                sprintf(buf, "%24s - '%s'\n\r", pArea->name, pArea->filename);
                send_to_char(buf, ch);
	    }
        }
	save_other_helps(ch);

        if (!str_cmp(buf, "None.\n\r"))
             send_to_char(buf, ch);
        return;
    }

    if (!str_cmp(arg1, "list"))
    {
      save_area_list( FALSE );
      return;
    }

    if (!str_cmp(arg1, "zone") || !str_cmp( arg1, "area") )
    {
      do_savearea( ch, "" );
      return;
    }

    if( !str_cmp( arg1, "helps" ) )
    {
	save_other_helps(ch);
	send_to_char("Done.\n\r",ch);
	return;
    }

    do_asave(ch, "");
    return;
}

void do_savearea( CHAR_DATA *ch, char *argument )
{
    AREA_DATA	*tarea;
    char	 filename[256];

    if( !IS_BUILDER_HERE(ch) )
    {
	send_to_char( "You don't have an assigned area to save.\n\r", ch );
	return;
    }

    tarea = ch->in_room->area;

    if ( !tarea )
    {
	send_to_char( "No area to save.\n\r", ch );
	return;
    }

    sprintf( filename, "%s", tarea->filename );
    send_to_char( "Saving area...\n\r", ch );
    sprintf( log_buf, "Saving %s by %s...", filename, ch->name );
    logfl( LOG_OLC, log_buf);
    REMOVE_BIT(tarea->area_flags, AREA_CHANGED);
    fold_area( tarea, filename );
    send_to_char( "Done.\n\r", ch );
}

/*****************************************************************************
 Name:		do_alist
 Purpose:	Normal command to list areas and display area information.
 Called by:	interpreter(interp.c)

****************************************************************************/
void    do_arealist (CHAR_DATA * ch, char *argument)
{
	char    result[MAX_STRING_LENGTH];	/* May need tweaking. */
	char    buf[MAX_STRING_LENGTH];	/* May need tweaking. */
	AREA_DATA *pArea;

	sprintf (result, "{c[{C%3s{c] [{C%-27s{c] ({C%-5s-%5s{c) [{C%-13.13s{c] {W%3s {c[{C%-10s{c]\n\r",
	   "Num", "Area Name", "lvnum", "uvnum", "Filename", "Sec", "Builders");

	for (pArea = area_first; pArea; pArea = pArea->next)
	{
		sprintf (buf, "{c[{C%3d{c] [{C%-27.27s{c] ({C%-5d-%5d{c) [{C%-13.13s{c] {W%3d {c[{C%-10.10s{c]\n\r",
		   pArea->vnum,
		   pArea->name,
		   pArea->lvnum,
		   pArea->uvnum,
		   pArea->filename,
		   pArea->security,
		   pArea->builders);
		stc (buf, ch);
	}

	return;
}


HELP_DATA * help_lookup( char *keyword )
{
	HELP_DATA *pHelp;
	char temp[MIL], argall[MIL];

	argall[0] = '\0';

	while (keyword[0] != '\0' )
	{
		keyword = one_argument(keyword, temp);
		if (argall[0] != '\0')
			strcat(argall," ");
		strcat(argall, temp);
	}
	for ( pHelp = help_first; pHelp != NULL; pHelp = pHelp->next )
		if ( is_name( argall, pHelp->keyword ) )
			return pHelp;

	return NULL;
}

HELP_AREA * get_help_area( HELP_DATA *help )
{
	HELP_AREA * temp;
	HELP_DATA * thelp;

	for ( temp = had_list; temp; temp = temp->next )
		for ( thelp = temp->first; thelp; thelp = thelp->next_area )
			if ( thelp == help )
				return temp;

	return NULL;
}

bool hedit_show ( CHAR_DATA *ch, char *argument )
{
	HELP_DATA * help;
	char buf[MSL*2];

	EDIT_HELP(ch, help);

	sprintf( buf, "{CKeyword : {n%s\n\r"
		      "{CLevel   : {n%d\n\r"
		      "{CText    :\n\r"
		      "{n%s\n\r",
		      help->keyword,
		      help->level,
		      help->text );
	send_to_char( buf, ch );

	return FALSE;
}

bool hedit_level ( CHAR_DATA *ch, char *argument )
{
	HELP_DATA *help;
	int lev;

	EDIT_HELP(ch, help);

	if ( !argument || !is_number(argument) )
	{
		send_to_char( "Syntax : level [-1..MAX_LEVEL]\n\r", ch );
		return FALSE;
	}

	lev = atoi(argument);

	if ( lev < -1 || lev > MAX_LEVEL )
	{
		ch_printf( ch, "HEdit : Level from -1 to %d only.\n\r", MAX_LEVEL );
		return FALSE;
	}

	help->level = lev;
	send_to_char( "Ok.\n\r", ch );
	return TRUE;
}

bool hedit_keyword ( CHAR_DATA *ch, char *argument )
{
	HELP_DATA *help;

	EDIT_HELP(ch, help);

	if ( !(argument) )
	{
		send_to_char( "Syntax : keyword [keywords]\n\r", ch );
		return FALSE;
	}

	free_string(help->keyword);
	help->keyword = str_dup(argument);

	send_to_char( "Ok.\n\r", ch );
	return TRUE;
}

bool hedit_new ( CHAR_DATA *ch, char *argument )
{
	char arg[MIL], fullarg[MIL];
	HELP_AREA *had;
	HELP_DATA *help;
	extern HELP_DATA *help_last;

	if ( !(argument) )
	{
		send_to_char( "Syntax : new [help]\n\r", ch );
		send_to_char( "         new [area] [help]\n\r", ch );
		return FALSE;
	}

	strcpy( fullarg, argument );
	argument = one_argument( argument, arg );

	if ( !(had = had_lookup(arg)) )
	{
		had = ch->in_room->area->helps;
		argument = fullarg;
	}

	if ( help_lookup(argument) )
	{
		send_to_char( "HEdit : Help already exhists.\n\r", ch );
		return FALSE;
	}

	if (!had) 
	{
		had		= new_had();
		had->filename	= str_dup(ch->in_room->area->filename);
		had->area	= ch->in_room->area;
		had->first	= NULL;
		had->last	= NULL;
		had->changed	= TRUE;
		had->next	= had_list;
		had_list	= had;
		ch->in_room->area->helps = had;
		SET_BIT(ch->in_room->area->area_flags, AREA_CHANGED);
	}

	help		= new_help();
	help->level	= 0;
	help->keyword	= str_dup(argument);
	help->text	= str_dup( "" );

	if (help_last)
		help_last->next	= help;

	if (help_first == NULL)
		help_first = help;

	help_last	= help;
	help->next	= NULL;

	if ( !had->first )
		had->first	= help;
	if ( !had->last )
		had->last	= help;

	had->last->next_area	= help;
	had->last		= help;
	help->next_area		= NULL;

	set_editor( ch->desc, ED_HELP, help );

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

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

	EDIT_HELP(ch, help);

	if ( !(argument) )
	{
		send_to_char( "Syntax : text\n\r", ch );
		return FALSE;
	}

	string_append( ch, &help->text );

	return TRUE;
}

bool hedit_delete ( CHAR_DATA *ch, char *argument )
{
    HELP_DATA * pHelp, * temp;
    HELP_AREA * had;
    DESCRIPTOR_DATA *d;
    bool found = FALSE;

    EDIT_HELP(ch, pHelp);

    for ( d = descriptor_list; d; d = d->next )
        if ( d->editor == ED_HELP && pHelp == (HELP_DATA *) d->pEdit )
            edit_done(d->character);

    if (help_first == pHelp)
        help_first = help_first->next;
    else
    {
        for ( temp = help_first; temp; temp = temp->next )
            if ( temp->next == pHelp )
                break;

        if ( !temp )
        {
            bugf( "hedit_delete : help %s not on help_first", pHelp->keyword );
            return FALSE;
        }

        temp->next = pHelp->next;
    }

    for ( had = had_list; had; had = had->next )
        if ( pHelp == had->first )
        {
            found = TRUE;
            had->first = had->first->next_area;
        }
        else
        {
            for ( temp = had->first; temp; temp = temp->next_area )
                if ( temp->next_area == pHelp )
					break;

			if ( temp )
			{
				temp->next_area = pHelp->next_area;
				found = TRUE;
				break;
			}
		}

	if ( !found )
	{
		bugf( "hedit_delete : help %s not on had_list", pHelp->keyword );
		return FALSE;
	}

	free_help(pHelp);

	send_to_char( "Ok.\n\r", ch );
	return TRUE;
}

bool hedit_list ( CHAR_DATA *ch, char *argument )
{
	char buf[MIL];
	int cnt = 0;
	HELP_DATA *pHelp;

	EDIT_HELP(ch, pHelp);

	if ( !str_cmp( argument, "all" ) )
	{
		for ( pHelp = help_first; pHelp; pHelp = pHelp->next )
		{
			sprintf( buf, "%3d. %-14.14s%s", cnt, pHelp->keyword,
				cnt % 4 == 3 ? "\n\r" : " " );
			stc( buf , ch);
			cnt++;
		}

		if ( cnt % 4 )
			stc( "\n\r",ch );

		return FALSE;
	}

	if ( !str_cmp( argument, "area" ) )
	{
		if ( ch->in_room->area->helps == NULL )
		{
			send_to_char( "No hay helps en esta area.\n\r", ch );
			return FALSE;
		}


		for ( pHelp = ch->in_room->area->helps->first; pHelp; pHelp = pHelp->next_area )
		{
			sprintf( buf, "%3d. %-14.14s%s", cnt, pHelp->keyword,
				cnt % 4 == 3 ? "\n\r" : " " );
			stc( buf, ch );
			cnt++;
		}

		if ( cnt % 4 )
			stc( "\n\r", ch );

		return FALSE;
	}

	if ( !(argument) )
	{
		send_to_char( "Syntax : list all\n\r", ch );
		send_to_char( "         list area\n\r", ch );
		return FALSE;
	}

	return FALSE;
}


void hedit( CHAR_DATA *ch, char *argument)
{
    HELP_DATA * pHelp;
    HELP_AREA *had;
    char arg[MAX_INPUT_LENGTH];
    char command[MAX_INPUT_LENGTH];
    int cmd;

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

    EDIT_HELP(ch, pHelp);

    had = get_help_area(pHelp);

    if (had == NULL)
    {
    	bugf( "hedit : Help you are editing (%s) is NULL", pHelp->keyword );
    	edit_done(ch);
    	return;
    }

    if (ch->pcdata->security < 9)
    {
        send_to_char("HEdit: Insuficient security to edit helps.\n\r",ch);
	edit_done(ch);
	return;
    }

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

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

    for (cmd = 0; *hedit_table[cmd].name; cmd++)
    {
	if (!str_cmp(command, hedit_table[cmd].name) )
	{
		if ((*hedit_table[cmd].olc_fun) (ch, argument))
			had->changed = TRUE;
		return;
	}
    }

    interpret(ch, arg);
    return;
}


void do_hedit(CHAR_DATA *ch, char *argument)
{
    HELP_DATA * pHelp;
    char arg[MIL];
    char arg2[MIL];

    if ( IS_NPC(ch) )
        return;

    strcpy( arg, argument );
    argument = one_argument( argument, arg2 );

    if( arg2[0] != '\0' && !str_cmp( arg2, "create" ) )
    {
        if( hedit_new( ch, argument ) )
			return;
	}

	if ( (pHelp = help_lookup( arg )) == NULL )
	{
		send_to_char( "HEdit : Help non-exhistant\n\r", ch );
		return;
	}

	set_editor( ch->desc, ED_HELP, pHelp );

	return;
}

CEDIT(cedit_show)
{
    ch_printf(ch, "\n\r{WMud_name: {R%s\n\r",
	      "Acension to Darkness" );
    ch_printf(ch, "{WPlayers:\n\r"
              "  {nMax: {W%d  {nTime of Max: {W%s\n\r",
              sysdata.maxplayers, sysdata.time_of_max );
    ch_printf(ch, "  {nAll Time max: {W%d\n\r",
              sysdata.alltimemax );
    ch_printf(ch, "{WChannels:\n\r"
              "  {nLog: {W%d\n\r",
              sysdata.log_level );
    ch_printf(ch, "{WBuilding:\n\r"
                  "  {nDefault Security: {W%d  {nPlayer msetting: {W%d\n\r",
              0, sysdata.level_mset_player );
    ch_printf(ch, "{WBan Data:\n\r"
                  "  {nBan Site Level: {W%d   {nBan Class Level: {W%d\n\r",
		sysdata.ban_site_level, sysdata.ban_class_level );
    ch_printf(ch, "{WCombat:\n\r"
              "  {nPlr vs. Plr: {W%d  {nPlr vs. Mob: {W%d\n\r",
              sysdata.dam_plr_vs_plr,sysdata.dam_plr_vs_mob );
    ch_printf(ch, "  {nMob vs. Plr: {W%d  {nMob vs. Mob: {W%d\n\r",
              sysdata.dam_mob_vs_plr,sysdata.dam_mob_vs_mob );
    ch_printf(ch, "{WDefenses:\n\r"
                  "  {nDodge_mod: {W%d    {nParry_mod: {W%d\n\r",
              sysdata.dodge_mod, sysdata.parry_mod );
    ch_printf(ch, "{WClass:\n\r"
              "  {nDrows: {W%3.3d  {nMonks: {W%3.3d  {nMages: {W%3.3d  {nNinjas:  {W%3.3d\n\r"
              "  {nPriests: {W%3.3d {nAngels: {W%3.3d  {nDemons: {W%3.3d  {nVampires: {W%3.3d\n\r"
              "  {nWerewolfs: {W%3.3d\n\r",
              sysdata.drows, sysdata.monks, sysdata.mages, sysdata.ninjas,
	      sysdata.priests, sysdata.angels, sysdata.demons,
	      sysdata.vampires, sysdata.werewolfs );
    ch_printf(ch, "{WPfile autocleanup status: %s\n\r"
                   "  {nDays before purging newbies: {W%d\n\r",
	    sysdata.CLEANPFILES ? "{COn" : "{cOff",
	    sysdata.newbie_purge );
    ch_printf(ch, "  {nDays before purging regular players: {W%d\n\r",
	    sysdata.regular_purge );

    ch_printf(ch, "{WOther:\n\r"
              "  {nForce on players:             {W%-2d\n\r",
              sysdata.level_forcepc);
    ch_printf(ch, "  {nPrivate room override:         {W%-2d\n\r",
              sysdata.level_override_private);
    ch_printf(ch, "  {nGet object without take flag: {W%-7d\n\r",
              sysdata.level_getobjnotake);
    ch_printf(ch, "  {nAutosave frequency (minutes):  {W%d\n\r",
		sysdata.save_frequency );
    ch_printf(ch, "  {nHostname resolving: {W%s\n\r", 
		sysdata.NO_NAME_RESOLVING ? "OFF" : "ON" );
    ch_printf(ch, "  {nWorld flags: {W%s\n\r", 
		flag_string( world_flags, sysdata.world ) );
    return FALSE;
}

bool cedit_change( CHAR_DATA *ch, char *argument, char *type, sh_int * num ) 
{
    if ( argument[0] == '\0' || !is_number( argument ) )
    {
	ch_printf(ch, "Syntax:  %s [number]\n\r", type);
	return FALSE;
    }
    
    *num = atoi(argument);
    stc("Ok.\n\r",ch);
    return TRUE;
};


CEDIT( cedit_savefreq )    
{
    return cedit_change( ch, argument, "save frequency", 
		&sysdata.save_frequency );
}

CEDIT( cedit_dodgemod )
{
    return cedit_change( ch, argument, "dodge mod",
		&sysdata.dodge_mod );
}

CEDIT( cedit_parrymod )
{
    return cedit_change( ch, argument, "parry mod",
		&sysdata.parry_mod );
}

CEDIT( cedit_dam_pvp )
{
    return cedit_change( ch, argument, "plr vs plr damage",
		&sysdata.dam_plr_vs_plr );
}

CEDIT( cedit_dam_pvm )
{
    return cedit_change( ch, argument, "plr vs mob damage",
		&sysdata.dam_plr_vs_mob );
}

CEDIT( cedit_dam_mvp )
{
    return cedit_change( ch, argument, "mob vs plr damage",
		&sysdata.dam_mob_vs_plr );
}

CEDIT( cedit_dam_mvm )
{
    return cedit_change( ch, argument, "mob vs mob damage",
		&sysdata.dam_mob_vs_mob );
}

CEDIT( cedit_plr_mset )
{
    return cedit_change( ch, argument, "mset pc",
		&sysdata.level_mset_player );
}

CEDIT( cedit_forcepc )
{
    return cedit_change( ch, argument, "force player",
		&sysdata.level_forcepc );
}

CEDIT( cedit_ban_site )
{
    return cedit_change( ch, argument, "ban site",
		&sysdata.ban_site_level );
}

CEDIT( cedit_newbie_purge )
{
    return cedit_change( ch, argument, "newbie_purge",
		&sysdata.newbie_purge );
}

CEDIT( cedit_regular_purge )
{
    return cedit_change( ch, argument, "regular_purge",
		&sysdata.regular_purge );
}
	
CEDIT( cedit_ban_class )
{
    return cedit_change( ch, argument, "ban class",
		&sysdata.ban_class_level );
}

CEDIT( cedit_pfiles )
{
      sysdata.CLEANPFILES = !sysdata.CLEANPFILES;

      if ( sysdata.CLEANPFILES )
  	   send_to_char( "Pfile autocleanup enabled.\n\r", ch );
      else
	   send_to_char( "Pfile autocleanup disabled.\n\r", ch );
      return TRUE;
}
    
void cedit( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    char command[MAX_INPUT_LENGTH];
    int cmd;
    int value;

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


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

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

    for (cmd = 0; *cedit_table[cmd].name; cmd++)
    {
	if (!str_cmp(command, cedit_table[cmd].name) )
	{
		if ((*cedit_table[cmd].olc_fun) (ch, argument))
		{
		     save_sysdata(sysdata);
		     send_to_char( "\n\r{YControl panel saved.{n\n\r", ch );
		}	
		return;
	}
    }

    if ( ( value = flag_value( world_flags, arg ) ) != NO_FLAG )
    {
        TOGGLE_BIT(sysdata.world, value);
	save_sysdata(sysdata);
	send_to_char( "{YWorld flag changed.{n\n\r", ch );
	send_to_char( "\n\r{YControl panel saved.{n\n\r", ch );
        return;
    }

    interpret(ch, arg);
    return;
}

void do_cedit(CHAR_DATA *ch, char *argument)
{
    if ( IS_NPC(ch) )
        return;

    set_editor( ch->desc, ED_CONTROL, NULL );
    do_cshow(ch,"");
    return;
}


void do_cshow( CHAR_DATA *ch, char *argument )
{
    cedit_show(ch,"");
    return;
}


CLEDIT( cledit_create )
{
    CLAN_DATA *pClan;

    if( argument[0] == '\0' )
    {
        stc("Syntax: create <filename>\n\r", ch );
        return FALSE;
    }
    
    pClan = new_clan_data( );

    free_string( pClan->filename );
    pClan->filename = str_dup( argument );
    set_editor( ch->desc, ED_CLAN, pClan );
    logf( NULL, "%s has just created a new clan!", ch->name );
    stc( "Clan created.\n\r", ch );
    return TRUE;
}

CLEDIT( cledit_filename )
{
    CLAN_DATA *pClan;

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

    free_string( pClan->filename );
    pClan->filename = str_dup( argument );

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

CLEDIT( cledit_name )
{
    CLAN_DATA *pClan;

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

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

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


CLEDIT( cledit_display )
{
    CLAN_DATA *pClan;

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

    free_string( pClan->who_name );
    pClan->who_name = str_dup( argument );

    send_to_char( "Display name set.\n\r", ch );
    return TRUE;
}

CLEDIT( cledit_show )
{
    CLAN_DATA *pClan;

    EDIT_CLAN( ch, pClan );
    
    show_clan( ch, pClan );
    return FALSE;
}


CLEDIT( cledit_motto )
{
    CLAN_DATA *pClan;

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

    free_string( pClan->motto );
    pClan->motto = str_dup( argument );
    pClan->motto[0] = UPPER( pClan->motto[0] );

    send_to_char( "Clan motto set.\n\r", ch );
    return TRUE;
}

CLEDIT( cledit_desc )
{
    CLAN_DATA *pClan;

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

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

CLEDIT( cledit_recall )
{
    CLAN_DATA *pClan;
    char room[MAX_STRING_LENGTH];
    int value;
	
    EDIT_CLAN( ch, pClan );

    one_argument( argument, room );

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

    value = atoi( room );

    if( !get_room_index( value ) )
    {
	send_to_char( "CEdit:  Room vnum does not exist.\n\r", ch );
	return FALSE;
    }
    pClan->recall = value;

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

CLEDIT( cledit_leader )
{
    CLAN_DATA *pClan;
    CHAR_DATA *victim, *oldleader = NULL;
    OBJ_DATA  *ring;
        
    EDIT_CLAN( ch, pClan );
    if( argument[0] == '\0' )
    {
	send_to_char( "Syntax:   leader <$name>\n\r", ch );
	return FALSE;
    }

    if( !( victim = get_char_world( ch, argument ) ) || IS_NPC( victim ) )
    {
	send_to_char( "You can't find them.\n\r", ch );
	return FALSE;
    }
    
    if( pClan->overlord && pClan->overlord[0]
	&& ( !( oldleader = get_char_world( ch, pClan->overlord ) )
	     || IS_NPC( oldleader ) ) )
    {
	send_to_char( "You must have the old leader logged on (use pload).\n\r", ch );
	return FALSE;
    }

    /*
     * Demote the old leader, no message.
     */
    if( oldleader )
    {
	oldleader->pcdata->clan_rank = RANK_CHIEFTAIN;
	free_string( pClan->chieftain );
	pClan->chieftain = str_dup( oldleader->name );
    }

    /*
     * change new leader's clan and make him appropriate rank.
     */
    if( victim->pcdata->clan )
        remove_from_clan( victim );
    free_string( pClan->overlord );

    victim->pcdata->clan      = pClan;
    victim->pcdata->clan_rank = RANK_CLANSMAN;
    pClan->members++;

    ring = create_object( get_obj_index( pClan->clanobj1 ), victim->level);

    if ( ring )
        obj_to_char( ring, victim );
    send_to_char( "Leader set.\n\r", ch );
    return TRUE;
}

bool cledit_obj( CHAR_DATA *ch, char *argument, char * obj_num,
                 int * clan_obj )
{
    int vnum;
    
    if( argument[0] == '\0' || !is_number(argument))
    {
        ch_printf( ch, "Syntax: %s <##ovnum>\n\r",
                   obj_num );
        return FALSE;
    }

    vnum = atoi( argument );

    if( vnum < 1 )
    {
        ch_printf( ch, "Syntax: %s <##ovnum>\n\r",
                   obj_num );
        return FALSE;
    }
        
    if( !get_obj_index( vnum ) )
    {
        ch_printf( ch, "Vnum: %d - No such object.\n\r",
                   vnum );
        return FALSE;
    }

    *clan_obj = vnum;
    stc( "Done.\n\r", ch );
    return TRUE;
}

CLEDIT( cledit_obj1 )
{
    CLAN_DATA *pClan;

    EDIT_CLAN( ch, pClan );

    return cledit_obj( ch, argument, "obj_1", &pClan->clanobj1 );
}

CLEDIT( cledit_obj2 )
{
    CLAN_DATA *pClan;

    EDIT_CLAN( ch, pClan );

    return cledit_obj( ch, argument, "obj_2", &pClan->clanobj2 );
}

CLEDIT( cledit_obj3 )
{
    CLAN_DATA *pClan;

    EDIT_CLAN( ch, pClan );

    return cledit_obj( ch, argument, "obj_3", &pClan->clanobj3 );
}
        
void cledit( CHAR_DATA *ch, char *argument )
{
    CLAN_DATA *pClan;
    char command[MAX_INPUT_LENGTH];
    char arg[MAX_STRING_LENGTH];
    int cmd;

    EDIT_CLAN( ch, pClan );

    strcpy( arg, argument );
    argument = one_argument( arg, command );
	    
    if( command[0] == '\0' )
    {
	cledit_show( ch, argument );
	return;
    }

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

    /* Search Table and Dispatch Command. */
    for( cmd = 0; *cledit_table[cmd].name; cmd++ )
    {
	if( !str_prefix( command, cledit_table[cmd].name ) )
	{
	    (*cledit_table[cmd].olc_fun) ( ch, argument );
                save_clan( pClan );
            return;
	}
    }    

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

void do_cledit( CHAR_DATA *ch, char *argument )
{
    CLAN_DATA *pClan;
    char buf[MAX_INPUT_LENGTH];

    argument = one_argument( argument, buf );
    if( !str_cmp( buf, "create" ) )
    {
        if( cledit_create( ch, argument ) )
            save_clan_list();
        return;
    }

    if( !( pClan = clan_lookup( buf )) )
    {
	int cln;
	send_to_char( "CEdit: There is no clan to edit.\n\r", ch );

	ch_printf( ch, "## ][ Clan Name\n\r", ch );
	ch_printf( ch, "---------------------------------------\n\r" );
	for( cln = 0, pClan = clan_first; pClan; pClan = pClan->next, cln++ )
	   ch_printf( ch, "%2.2d    %s\n\r",
		cln, pClan->name );		
		
	return;
    }
    
    set_editor( ch->desc, ED_CLAN, pClan );
    cledit_show( ch, "" );
    return;
}


bool rename_show(CHAR_DATA *ch, char *argument)
{
  OBJ_DATA  *pObj;

  RENAME_OBJ( ch, pObj );

  send_to_char("{YREMAKE AN ITEM: {cType {Rdone{x when finished.{x\n\r", ch );
  send_to_char("{nType '{Cshow{n' to see the item so far.{x\n\r\n\r", ch );
  ch_printf(ch,"1) Keyword(s):        Syntax: 1 <new keyword>\n\r" );
  ch_printf(ch,"   %s\n\r", pObj->name );
  ch_printf(ch,"2) Short:             Syntax: 2 <Looks in inv or equiped.>\n\r" );
  ch_printf(ch,"   %s{x\n\r", pObj->short_descr );
  ch_printf(ch,"3) Long:              Syntax: 3 <Looks when on the ground or looked at.>\n\r");
  ch_printf(ch,"   %s{x\n\r", pObj->description );
  
  return FALSE;
}

bool rename_keyword( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *pObj;

    RENAME_OBJ(ch, pObj);

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

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

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

bool rename_short( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *pObj;

    RENAME_OBJ(ch, pObj);

    if ( argument[0] == '\0' )
    {
	send_to_char("Syntax:  short [string]\n\r", ch );
	return FALSE;
    }

    free_string( pObj->short_descr );
    pObj->short_descr = str_dup( argument );

    send_to_char( "Short description set.\n\r", ch);
    return TRUE;
}

bool rename_long( CHAR_DATA *ch, char *argument )
{
    OBJ_DATA *pObj;

    RENAME_OBJ(ch, pObj);

    if ( argument[0] == '\0' )
    {
	send_to_char("Syntax:  long [$string]\n\r", ch );
	return FALSE;
    }
        
    free_string( pObj->description );
    pObj->description = str_dup( argument );
    pObj->description[0] = UPPER( pObj->description[0] );

    send_to_char( "Long description set.\n\r", ch);
    return TRUE;
}

void rename_object(CHAR_DATA *ch, char *argument)
{
  char command[MAX_INPUT_LENGTH];
  char arg[MAX_STRING_LENGTH];
  int cmd;

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

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


  if(!str_cmp(command, "done"))
  {
    edit_done( ch );
    if( !IS_IMMORTAL(ch) )
	PC(ch,stats[DEMON_CURRENT]) -= 2000;
    save_char_obj( ch );
    return;
  }

  /* Call editor function */
  for(cmd = 0;*rename_obj_table[cmd].name;cmd++)
  {
    if(!str_prefix(command, rename_obj_table[cmd].name))
    {
      (*rename_obj_table[cmd].olc_fun) (ch, argument);
      return;
    }
  }

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

/*
 *  This is called from different commands like vamp vtwist
 */
void do_rename_obj( CHAR_DATA *ch, char *argument, char *cmd )
{
    OBJ_DATA *pObj;
    char command[MAX_INPUT_LENGTH];

    argument = one_argument( argument, command );

    if( IS_NPC(ch) )
	return;

    if ( command[0] == '\0' )
    {
    	ch_printf( ch, "Syntax: %s <obj name>.\n\r", cmd );
        return;
    }

    if (!IS_IMMORTAL(ch) && PC(ch,stats[DEMON_CURRENT]) < 2000)
    {
        ch_printf(ch,"You need 2000 cps to %s an object.\n\r", cmd );
        return;
    }
    
    if ( !( pObj = get_obj_carry( ch, command ) ) )
    {
	send_to_char("You don't have that obj.\n\r", ch );
	return;
    }

    if ( !IS_IMMORTAL(ch) && IS_SET(pObj->quest, QUEST_RELIC))
    {
         send_to_char("Not on a relic.\n\r",ch);
         return;
    }
    
    if ( !IS_IMMORTAL(ch) && IS_SET(pObj->quest, QUEST_ARTIFACT))
    {
        send_to_char("Not on an Artifact.\n\r",ch);
        return;
    }

    ch->desc->pEdit = (void *)pObj;
    ch->desc->editor = ED_RENAME;
    rename_show( ch, "" );
    send_to_char( "Type 'commands' to get help.\n\r",ch);
    return;
}