Mud20/accounts/
Mud20/accounts/c/
Mud20/accounts/f/
Mud20/accounts/k/
Mud20/accounts/s/
Mud20/accounts/t/
Mud20/area_current/
Mud20/area_current/newareas/
Mud20/bin/
Mud20/clans/
Mud20/gods/
Mud20/old-sources/
Mud20/player/
Mud20/player/a/del/
Mud20/player/b/
Mud20/player/b/bak/
Mud20/player/b/del/
Mud20/player/f/
Mud20/player/f/bak/
Mud20/player/f/del/
Mud20/player/k/
Mud20/player/k/bak/
Mud20/player/k/del/
Mud20/player/k/dmp/
Mud20/player/m/
Mud20/player/m/bak/
Mud20/player/o/
Mud20/player/o/bak/
Mud20/player/p/
Mud20/player/s/
Mud20/player/s/bak/
Mud20/player/s/del/
Mud20/player/t/
Mud20/player/t/del/
Mud20/player/v/
Mud20/public_html/
Mud20/races/
Mud20/skilltables/
__MACOSX/Mud20/accounts/
__MACOSX/Mud20/accounts/c/
__MACOSX/Mud20/accounts/f/
__MACOSX/Mud20/accounts/k/
__MACOSX/Mud20/accounts/s/
__MACOSX/Mud20/area_current/
__MACOSX/Mud20/area_current/core_areas/
__MACOSX/Mud20/area_current/helps/
__MACOSX/Mud20/area_current/newareas/
__MACOSX/Mud20/backups/
__MACOSX/Mud20/bin/
__MACOSX/Mud20/clans/
__MACOSX/Mud20/gods/
__MACOSX/Mud20/log/
__MACOSX/Mud20/old-sources/
__MACOSX/Mud20/player/
__MACOSX/Mud20/player/a/del/
__MACOSX/Mud20/player/b/
__MACOSX/Mud20/player/b/bak/
__MACOSX/Mud20/player/f/
__MACOSX/Mud20/player/f/bak/
__MACOSX/Mud20/player/f/del/
__MACOSX/Mud20/player/k/
__MACOSX/Mud20/player/k/bak/
__MACOSX/Mud20/player/k/del/
__MACOSX/Mud20/player/k/dmp/
__MACOSX/Mud20/player/m/
__MACOSX/Mud20/player/m/bak/
__MACOSX/Mud20/player/o/
__MACOSX/Mud20/player/o/bak/
__MACOSX/Mud20/player/p/
__MACOSX/Mud20/player/s/
__MACOSX/Mud20/player/s/bak/
__MACOSX/Mud20/player/t/del/
__MACOSX/Mud20/player/v/
__MACOSX/Mud20/public_html/
__MACOSX/Mud20/races/
__MACOSX/Mud20/skilltables/
/***************************************************************************
 * Mud20 1.0 by Todd H. Johnson (Kregor) a derivative of the Open Gaming   *
 * License by Wizards of the Coast. All comments referring to D20, OGL,    *
 * and SRD refer to the System Reference Document for the Open Gaming      *
 * system. Any inclusion of these derivatives must include credit to the   *
 * Mud20 system, the full and complete Open Gaming LIcense, and credit to  *
 * the respective authors. See ../doc/srd.txt for more information.        *
 *                                                                         *
 * Emud  2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem.   *
 *                                                                         *
 * MrMud 1.4 by David Bills, Dug Michael and Martin Gallwey                *
 *                                                                         *
 * Merc  2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael      *
 * Chastain, Michael Quan, and Mitchell Tse.                               *
 *                                                                         *
 * Original Diku Mud copyright (C) 1990 1991 by Sebastian Hammer,          *
 * Michael Seifert, Hans Henrik St{rfeld, Tom Madsen, and Katje Nyboe.     *
 ***************************************************************************/

/***************************************************************************
 * edit.c: Game editor functions																				   *
 ***************************************************************************/

#include "mud.h"

void		expand_mob_prog	args( ( MOB_INDEX_DATA *mob, OBJ_INDEX_DATA *obj, ROOM_INDEX_DATA *room, MPROG_DATA *prog) );
void		do_rredit			args( ( CHAR_DATA *ch, char *argument ) );
void		obj_prog_if_dest	args( ( OBJ_INDEX_DATA *obj ) );

char *  const   sdesc_flags [] =
{
	"acid",
	"air",
	"chaotic",
	"charm",
	"cold",
	"compulsion",
	"darkness",
	"death",
	"disease",
	"earth",	
	"electricity",	
	"evil",
	"fear",
	"fire",
	"force",
	"good",
	"healing",
	"illusion",
	"lawful",
	"light",
	"magic",
	"mind",
	"negative",
	"paralysis",
	"petrification",
	"poison",
	"sonic",
	"sleep",
	"water",
	"polymorph",
	"summoning",
	"*"
};

char *  const   dtype_flags [] =
{
	"piercing",
	"slashing",
	"bludgeoning",
	"magic",
	"good",	
	"evil",
	"lawful",
	"chaotic",
	"cold iron",
	"silver",
	"adamantine",
	"nonlethal",
	"acid",
	"cold",
	"electricity",
	"fire",
	"sonic",
	"divine",
	"force",
	"*"
};

int body_wear_locs [BTYPE_MAX] =
{
	/*bipedal*/ 		CAN_WEAR_HEAD|CAN_WEAR_FACE|CAN_WEAR_EARS|CAN_WEAR_NECK|CAN_WEAR_ARMS|CAN_WEAR_WRIST|CAN_WEAR_HANDS|CAN_WEAR_FINGER|CAN_WEAR_BODY|CAN_WEAR_ABOUT|CAN_WEAR_BACK|CAN_WEAR_WAIST|CAN_WEAR_LEGS|CAN_WEAR_ANKLE|CAN_WEAR_FEET,
	/*amorphous*/ 	CAN_WEAR_BODY|CAN_WEAR_ABOUT,
	/*aquatic*/ 		CAN_WEAR_HEAD|CAN_WEAR_FACE|CAN_WEAR_NECK|CAN_WEAR_BODY|CAN_WEAR_ABOUT|CAN_WEAR_BACK|CAN_WEAR_SADDLE|CAN_WEAR_WAIST,
	/*arhtropod*/ 	CAN_WEAR_HEAD|CAN_WEAR_FACE|CAN_WEAR_BODY|CAN_WEAR_ABOUT|CAN_WEAR_BACK|CAN_WEAR_SADDLE|CAN_WEAR_LEGS,
	/*arthrohyb*/ 	CAN_WEAR_HEAD|CAN_WEAR_FACE|CAN_WEAR_EARS|CAN_WEAR_NECK|CAN_WEAR_ARMS|CAN_WEAR_WRIST|CAN_WEAR_HANDS|CAN_WEAR_FINGER|CAN_WEAR_BODY|CAN_WEAR_ABOUT|CAN_WEAR_BACK|CAN_WEAR_SADDLE|CAN_WEAR_LEGS|CAN_WEAR_ANKLE|CAN_WEAR_FEET,
	/*avian*/ 			CAN_WEAR_HEAD|CAN_WEAR_FACE|CAN_WEAR_EARS|CAN_WEAR_NECK|CAN_WEAR_BODY|CAN_WEAR_ABOUT|CAN_WEAR_BACK|CAN_WEAR_WAIST|CAN_WEAR_LEGS|CAN_WEAR_ANKLE|CAN_WEAR_FEET,
	/*multiarm*/ 		CAN_WEAR_HEAD|CAN_WEAR_FACE|CAN_WEAR_EARS|CAN_WEAR_NECK|CAN_WEAR_ARMS|CAN_WEAR_WRIST|CAN_WEAR_HANDS|CAN_WEAR_FINGER|CAN_WEAR_BODY|CAN_WEAR_ABOUT|CAN_WEAR_BACK|CAN_WEAR_WAIST|CAN_WEAR_LEGS|CAN_WEAR_ANKLE|CAN_WEAR_FEET,
	/*quadruped*/ 	CAN_WEAR_HEAD|CAN_WEAR_FACE|CAN_WEAR_EARS|CAN_WEAR_NECK|CAN_WEAR_BODY|CAN_WEAR_ABOUT|CAN_WEAR_BACK||CAN_WEAR_SADDLE|CAN_WEAR_LEGS|CAN_WEAR_ANKLE|CAN_WEAR_FEET,
	/*quadhyb*/ 		CAN_WEAR_HEAD|CAN_WEAR_FACE|CAN_WEAR_EARS|CAN_WEAR_NECK|CAN_WEAR_ARMS|CAN_WEAR_WRIST|CAN_WEAR_HANDS|CAN_WEAR_FINGER|CAN_WEAR_BODY|CAN_WEAR_ABOUT|CAN_WEAR_BACK|CAN_WEAR_SADDLE|CAN_WEAR_WAIST|CAN_WEAR_LEGS|CAN_WEAR_ANKLE|CAN_WEAR_FEET,
	/*radial*/ 			CAN_WEAR_HEAD|CAN_WEAR_FACE|CAN_WEAR_NECK|CAN_WEAR_BODY|CAN_WEAR_ABOUT,
	/*serpent*/ 		CAN_WEAR_HEAD|CAN_WEAR_FACE|CAN_WEAR_EARS|CAN_WEAR_NECK|CAN_WEAR_BODY|CAN_WEAR_ABOUT,
	/*serpenthyb*/	CAN_WEAR_HEAD|CAN_WEAR_FACE|CAN_WEAR_EARS|CAN_WEAR_NECK|CAN_WEAR_ARMS|CAN_WEAR_WRIST|CAN_WEAR_HANDS|CAN_WEAR_FINGER|CAN_WEAR_BODY|CAN_WEAR_ABOUT|CAN_WEAR_BACK|CAN_WEAR_WAIST
};

char *  const   metamagic_flags [] =
{
	"empower",
	"enlarge",
	"extend",
	"maximize",
	"quicken",
	"silent",	
	"still",
	"merciful",
	"disguise",
	"enhance",
	"persist",
	"reach",
	"repeat",
	"sacred",
	"*"
};

char *  const   obj_layers [] =
{
	"none",
	"under",
	"clothes",
	"overclothes",
	"armor",
	"overarmor",
	"*"
};

char *  const   punishment_flags [] =
{
	"none",
	"death",
	"sever",
	"jail",
	"confiscate",
	"*"
};

char *  const   race_specs [] =
{
	"air",
	"angel",
	"aquatic",
	"archon",
	"chaotic",
	"cold",
	"demon",
	"devil",
	"drow",
	"dwarf",
	"earth",
	"elemental",
	"elf",
	"evil",
	"extraplanar",
	"fire",
	"giant",
	"gnoll",
	"gnome",
	"goblinoid",
	"good",
	"halfling",
	"human",
	"incorporeal",
	"lawful",
	"native",
	"orc",
	"reptilian",
	"shapechanger",
	"swarm",
	"water",
	"multi-armed",
	"multi-legged",
	"quadruped",
	"*"
};

char *  const   body_types [] =
{
	"bipedal",
	"amorphous",
	"aquatic",
	"arthropod",
	"arthropod_hybrid",
	"avian",
	"multiarmed",
	"quadruped",
	"quadruped_hybrid",
	"radial",
	"serpentine",
	"serpentine_hybrid",
	"*"
};

char *  const   mprog_flags [] =
{
	"act",
	"speech",
	"rand",	
	"fight",
	"death",
	"hitprcnt",
	"entry",
	"greet",
	"dogreet",
	"give",
	"bribe",
	"range",
	"social",
	"kill",
	"group_greet",
	"time",
	"repop",
	"delay",
	"exit",
	"trigger",
	"desc",
	"month",
	"day",
	"intercept",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"arrival",
	"buy",
	"sayto",
	"cast",
	"*"
};

char *  const   oprog_flags [] =
{
	"act",
	"speech",
	"rand",	
	"fight",
	"@",
	"@",
	"@",
	"greet",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"group_greet",
	"time",
	"repop",
	"@",
	"@",
	"trigger",
	"desc",
	"month",
	"day",
	"intercept",
	"wear",
	"remove",
	"use",
	"sac",
	"get",
	"drop",
	"damage",
	"hit",
	"@",
	"@",
	"@",
	"cast",
	"*"
};

char *  const   rprog_flags [] =
{
	"act",
	"speech",
	"rand",	
	"fight",
	"death",
	"@",
	"entry",
	"greet",
	"@",
	"@",
	"@",
	"@",
	"@",
	"kill",
	"group_greet",
	"time",
	"@",
	"@",
	"exit",
	"@",
	"desc",
	"month",
	"day",
	"intercept",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"cast",
	"*"
};

char *  const   weapon_flags [] =
{
	"anarchic",
	"axiomatic",
	"bane",	
	"disruption",
	"distance",
	"flaming",
	"flaming burst",
	"frost",
	"ghost touch",
	"holy",
	"icy burst",
	"keen",
	"ki focus",
	"merciful",
	"returning",
	"seeking",
	"shock",
	"shocking burst",
	"speed",
	"spell storing",
	"thundering",
	"throwing",
	"unholy",
	"venomous",
	"vicious",
	"vampiric",
	"vorpal",
	"wounding",
	"slaying",
	"caustic",
	"*"
};

char *  const   armor_flags [] =
{
	"arrow deflection",
	"bashing",	
	"ghost touch",
	"reflecting",
	"wild",
	"hooded",
	"*"
};

char *  const   treasure_flags [] =
{
	"spell_storing",
	"counterspell",
	"spell_recast",	
	"spell_charges",
	"absorption",
	"*"
};

char *  const   faith_ranks [] =
{
	"unproven",
	"acolyte",
	"prelate",	
	"inner circle",
	"chosen",
	"*"
};

char *  const   weapon_flag_descs [] =
{
	"Does additional damage to lawful opponents",
	"Does additional damage to chaotic opponents",
	"Does additional damage to",
	"Undead must WILL save or are destroyed",
	"Double range of mundane weapon",
	"Adds fire damage on a successful hit",
	"Burst of flame upon critical hit adds damage",
	"Adds cold damage on successful hit",
	"Can hit incorporeal creatures",
	"Does additional damage to evil opponents",
	"Does additional burst of cold upon critical hit",
	"Threat range is double that of mundane weapon", 
	"A monk can use his ki strikes with this weapon",
	"Does additional damage, but all is nonlethal",
	"Returns to the wielder when thrown",
	"Strikes unerringly at its target",
	"Adds electrical damage on successful hit",
	"Does additional surge of electricity on critical hit",
	"Adds an extra attack to the wielder",
	"Stores a spell of up to level 3 in power",
	"Does sonic damage upon critical hit.",
	"Can throw this weapon, which you otherwise couldn't",
	"Does additional damage to good opponents",
	"Poisons the opponent upon a critical hit",
	"Does additional damage to opponent, but also damages wielder",
	"Drains a level from the opponent, adds hitpoints to the wielder",
	"Beheads your target upon a critical hit",
	"Causes bleeding on a critical hit",
	"Slays upon failed FORT save ",
	"*"
};

char *  const   oprog_commands [] =
{
	"echo",			"godcommand",		"godargument",		"command",
	"argument",		"ifhasobj",		"if",			"junk",
	"questset",		"questadd",		"ifobjquest",		"ifplrquest",
	"apply",			"*"
};

char *  const   oprog_applies [] =
{
	"@",				"hp",			"move",			"mana",
	"alignment",		"*"
};

char *  const   oprog_weathers [] =
{
	"clear",			"cloudy",			"raining",		"storms",
	"*"
};

char *  const	 boolean []=
{
	"false",			"true",			"*"
};

char *  const   oprog_ifchecks [] =
{
	"mclass_barbarian",	"mclass_bard",	"mclass_cleric",	"mclass_druid",
	"mclass_fighter",	"mclass_monk",	"mclass_paladin",	"mclass_ranger",
	"mclass_rogue",	"mclass_sorcerer",	"mclass_wizard",
	"wearloc",		"time",			"weather",		"rand",
	"hitprcnt",		"manaprcnt",		"moveprcnt",		"sector",
	"alignment",		"gold",			"class",			"god",
	"area",			"level",			"position",		"race",
	"sex",			"room",			"fighting",		"*"
};

char *  const   area_flags [] =
{
	"@",
	"noteleport",
	"@",
	"norecall",
	"nocastle",
	"norip",
	"@",
	"nosummon",
	"autosave",
	"modified",
	"weather",
	"converted",
	"village",
	"town",
	"city",
	"metropolis",
	"*"
};

char * const    cont_flags []=
{
	"closeable",
	"pickproof",
	"closed",
	"locked",
	"magical_lock",
	"bashproof",
	"weak",
	"strong",
	"easy_pick",
	"hard_pick",
	"amazing_pick",
	"holding1",
	"holding2",
	"holding3",
	"holding4",
	"*"
};

char *  const   exit_flags [] =
{
	"isdoor",
	"closed",
	"locked",
	"hidden",
	"@",
	"pickproof",
	"bashproof",
	"magicproof",
	"@",
	"climb",
	"fly",
	"barred",
	"passproof",
	"magical_lock",
	"easy_pick",
	"hard_pick",
	"amazing_pick",
	"weak_door",
	"heavy_door",
	"iron_door",
	"jump",
	"@",
	"window",
	"*"
};

char *  const   reset_exit_types [] =
{
	"open",			"close",			"lock",			"*"
};

char * const    reset_rand_types [] =
{
	"@",				"ne",			"nes",			"nesw",
	"neswu",			"neswud",			"*"
};

char *  const   f_flags [] =
{
	"sleep_in",
	"sleep_on",
	"rest_in",
	"rest_on",
	"sit_in",
	"sit_on",
	"sit_at",
	"stand_in",
	"stand_on",
	"kneel_at",
	"place_on",
	"*"
};

char *  const   furn_poses [] =
{
	"sleep in",
	"sleep on",
	"rest in",
	"rest on",
	"sit in",
	"sit on",
	"sit at",
	"stand in",
	"stand on",
	"kneel at",
	"place on",
	"*"
};

char *  const   shop_flags [] =
{
	"identify",
	"temple",
	"avail1",
	"avail2",
	"avail3",
	"avail4",
	"avail5",
	"avail6",
	"avail7",
	"*"
};

char *  const   r_flags [] =
{
	"dark",
	"fog",
	"nomob",
	"indoors",
	"@",
	"noastral",
	"storeroom",
	"swarm",
	"nomagic",
	"private",
	"safe",
	"solitary",
	"petshop",
	"norecall",
	"@",
	"block",
	"nosave",
	"morgue",
	"inn",
	"nofloor",
	"noscry",
	"nocover",
	"@",
	"@",
	"light",
	"noair",
	"@",
	"@",
	"noteboard",
	"@",
	"norip",
	"maze",
	"ice",
	"dynamic",
	"@",
	"hash",
	"@",
	"*"
};

char *  const   o_flags [] =
{
	"glow",
	"resize",
	"loyal",
	"@",
	"invis",
	"magic",
	"nodrop",
	"@",
	"evil",
	"good",
	"neutral",
	"chaotic",
	"lawful",
	"unconcerned",
	"noremove",
	"inventory",
	"burning",
	"@",
	"autoengrave",
	"@",
	"ethereal",
	"@",
	"hidden",
	"masterwork",
	"noscry",
	"concealed",
	"broken",
	"buried",
	"transparent",
	"*"
};

char *  const   act_flags [] =
{
	"stayarea",
	"sentinel",
	"scavenger",
	"drunk",
	"summoned",
	"aggressive",
	"nowander",
	"wimpy",
	"pet",
	"train",
	"bank",
	"weak",
	"secretive",
	"nocorpse",
	"day",
	"night",
	"companion",
	"@",
	"ishealer",
	"@",
	"nofight",
	"@",
	"guard",
	"familiar",
	"undead",
	"subdual",
	"citizen",
	"noassist",
	"request",
	"mobinvis",
	"warhorse",
	"*"
};

char *  const   a_flags [] =
{
	"blind",
	"curse",
	"deaf",
	"detect_hidden",
	"detect_invis",
	"detect_traps",
	"dominate",
	"feather_fall",
	"flying",
	"freedom",
	"gaseous",
	"haste",
	"hide",
	"hooded",
	"spell_immunity",
	"invisible",
	"mind_blank",
	"nondetection",
	"poison",
	"sanctuary",
	"see_darkness",
	"sleep",
	"sneak",
	"sustain",
	"telepathy",
	"tongues",
	"truesight",
	"understand",
	"water_breathing",
	"water_walk",
	"ethereal",
	"*"
};

char *  const   a2_flags [] =
{
	"astral",
	"berserk",
	"bleeding",
	"calmed",
	"camping",
	"confusion",
	"dazed",
	"dazzled",
	"entangled",
	"ethereal",
	"exhausted",
	"falling",
	"fascinated",
	"fatigued",
	"fear",
	"hallucinating",
	"longterm_care",
	"fascinated",
	"paralysis",
	"petrification",
	"possessed",
	"sickened",
	"silence",
	"staggered",
	"stunned",
	"unconscious",
	"charmed",
	"drowning",
	"*"
};

char *  const   oa_flags1 [] =
{
	"blind",
	"curse",
	"deaf",
	"detect_hidden",
	"detect_invis",
	"detect_traps",
	"@",
	"feather_fall",
	"flying",
	"freedom",
	"gaseous",
	"haste",
	"hide",
	"@",
	"spell_immunity",
	"invisible",
	"mind_blank",
	"nondetection",
	"@",
	"sanctuary",
	"see_darkness",
	"sleep",
	"@",
	"sustain",
	"telepathy",
	"tongues",
	"truesight",
	"understand",
	"water_breathing",
	"water_walk",
	"@",
	"*"
};

char *  const   oa_flags2 [] =
{
	"astral",
	"berserk",
	"bleeding",
	"calmed",
	"@",
	"confusion",
	"dazed",
	"dazzled",
	"entangled",
	"ethereal",
	"@",
	"@",
	"fascinated",
	"@",
	"@",
	"hallucinating",
	"@",
	"@",
	"paralyzed",
	"petrified",
	"@",
	"@",
	"silenced",
	"staggered",
	"@",
	"@",
	"charmed",
	"@",
	"tied",
	"*"
};

char *  const   plr_flags [] =
{
	"search",
	"exp_tnl",
	"autoexits",
	"available",
	"available",
	"blank",
	"brief",
	"repeat",
	"holylight",
	"wizinvis",
	"wiztime",
	"outcast",
	"wizcloak",
	"thief",
	"killer",
	"damage",
	"split",
	"quiet",
	"pager",
	"afk",
	"hearlog",
	"buildlight",
	"*"
};

char *  const   wear_locs [] =
{
	"none",
	"float",
	"head",
	"face",
	"ears",
	"neck1",
	"neck2",
	"arms",
	"wrist1",
	"wrist2",
	"hands",
	"finger1",
	"finger2",
	"about",
	"body",
	"saddle",
	"back",
	"waist",
	"belt1",
	"belt2",
	"belt3",
	"legs",
	"ankle1",
	"ankle2",
	"feet",
	"shield",
	"wield",
	"dual-wield",
	"both",
	"hold",
	"*"
};

char *  const   attack_part_flags [] =
{
	"bite",
	"claw",
	"gore",
	"hoof",
	"kick",
	"pincer",
	"punch",
	"rake",
	"slam",
	"sting",
	"tail",
	"talon",
	"tentacle",
	"wing",
	"other",
	"touch",
	"*"
};

char *  const   o_types [] =
{
	"nothing",
	"light",
	"scroll",
	"wand",
	"staff",
	"weapon",
	"symbol",
	"spellbook",
	"treasure",
	"armor",
	"potion",
	"spellpouch",
	"furniture",
	"trash",
	"sheath",
	"container",
	"quiver",
	"drinkcon",
	"key",
	"food",
	"money",
	"component",
	"boat",
	"@",
	"@",
	"fountain",
	"pill",	
	"portal",
	"window",
	"tools",
	"ammo",
	"totem",
	"@",
	"piece",
	"paper",
	"book",
	"trap",
	"map",
	"fire",
	"cart",
	"*"
};

char *  const   w_flags [] =
{
	"take",
	"float",
	"head",
	"face",
	"ears",
	"neck",
	"arms",
	"wrist",
	"hands",
	"finger",
	"body",
	"about",
	"back",
	"waist",
	"belt",	
	"legs",
	"ankle",
	"feet",
	"shield",
	"wield",
	"both",
	"hold",
	"saddle",
	"*"
};

char *  const   race_wear_flags [] =
{
	"@",
	"@",
	"head",
	"face",
	"ears",
	"neck",
	"arms",
	"wrist",
	"hands",
	"finger",
	"body",
	"about",
	"back",
	"waist",
	"belt",	
	"legs",
	"ankle",
	"feet",
	"@",
	"@",
	"@",
	"@",
	"saddle",
	"*"
};

char *  const   a_types [] =
{
	"none",
	"str",
	"dex",
	"int",
	"wis",
	"con",
	"cha",
	"sex",
	"race",
	"level",
	"age",
	"size",
	"mana",
	"hp",
	"move",
	"save_fort",
	"save_refl",
	"save_will",
	"saves",
	"deflect",
	"dodge",
	"shield",
	"armor",
	"comp_skill",
	"comp_tohit",
	"comp_dam",
	"comp_fort",
	"comp_refl",
	"comp_will",
	"comp_saves",
	"enhance_ac",
	"tohit",
	"dam",
	"insight_ac",
	"insight_tohit",
	"insight_fort",
	"insight_refl",
	"insight_will",
	"insight_saves",
	"insight_skill",
	"luck_skill",
	"luck_tohit",
	"luck_dam",
	"luck_fort",
	"luck_refl",
	"luck_will",
	"luck_saves",
	"morale_tohit",
	"morale_dam",
	"morale_fort",
	"morale_refl",
	"morale_will",
	"morale_saves",
	"morale_skill",
	"natural_ac",
	"resist_vs_good",
	"resist_vs_evil",
	"resist_vs_law",
	"resist_vs_chaos",
	"resist_saves",
	"save_vs_spell",
	"appraise",
	"bluff",
	"climb",
	"concentration",
	"decipher",
	"diplomacy",
	"disable_device",
	"disguise",
	"escape",
	"first_aid",
	"streetwise",
	"handle_animal",
	"intimidate",
	"jump",
	"listen",
	"mount",
	"pick_lock",
	"perform",
	"search",
	"stealth",
	"sense_motive",
	"sleight_of_hand",
	"spellcraft",
	"spot",
	"survival",
	"swim",
	"tumble",
	"use_magic",
	"alchemy",
	"armorsmithing",
	"bowmaking",
	"cooking",
	"fletching",
	"jewelry",
	"leathermaking",
	"mining",
	"poisoncrafting",
	"tailoring",
	"trapmaking",
	"weaponsmithing",
	"dr_bash",
	"dr_pierce",
	"dr_slash",
	"dr_magic",
	"dr_good",
	"dr_evil",
	"dr_law",
	"dr_chaos",
	"dr_iron",
	"dr_silver",
	"dr_adamantine",
	"dr_none",
	"dr_acid",
	"dr_cold",
	"dr_electric",
	"dr_fire",
	"dr_sonic",
	"spell_res",
	"weapon_flag",
	"objval_0",
	"objval_1",
	"objval_2",
	"objval_3",
	"objval_4",
	"objval_5",
	"objval_6",
	"objval_7",
	"spell_slot_1",
	"spell_slot_2",
	"spell_slot_3",
	"spell_slot_4",
	"spell_slot_5",
	"str_damage",
	"dex_damage",
	"con_damage",
	"int_damage",
	"wis_damage",
	"cha_damage",
	"str_drain",
	"dex_drain",
	"con_drain",
	"int_drain",
	"wis_drain",
	"cha_drain",
	"save_vs_acid",
	"save_vs_air",
	"save_vs_chaotic",
	"save_vs_charm",
	"save_vs_cold",
	"save_vs_compulsion",
	"save_vs_darkness",
	"save_vs_death",
	"save_vs_disease",
	"save_vs_earth",
	"save_vs_electric",
	"save_vs_evil",
	"save_vs_fear",
	"save_vs_fire",
	"save_vs_force",
	"save_vs_good",
	"save_vs_illusion",
	"save_vs_lawful",
	"save_vs_light",
	"save_vs_magic",
	"save_vs_mind",
	"save_vs_negative",
	"save_vs_paralysis",
	"save_vs_petri",
	"save_vs_poison",
	"save_vs_polymorph",
	"save_vs_healing",
	"save_vs_sleep",
	"save_vs_sonic",
	"save_vs_water",
	"immune_acid",
	"immune_air",
	"immune_chaotic",
	"immune_charm",
	"immune_cold",
	"immune_compulsion",
	"immune_darkness",
	"immune_death",
	"immune_disease",
	"immune_earth",
	"immune_electric",
	"immune_evil",
	"immune_fear",
	"immune_fire",
	"immune_force",
	"immune_good",
	"immune_illusion",
	"immune_lawful",
	"immune_light",
	"immune_magic",
	"immune_mind",
	"immune_negative",
	"immune_paralysis",
	"immune_petri",
	"immune_poison",
	"immune_polymorph",
	"immune_healing",
	"immune_sleep",
	"immune_sonic",
	"immune_water",
	"sr_vs_chaos",
	"sr_vs_evil",
	"sr_vs_good",
	"sr_vs_law",
	"fast_healing",
	"regeneration",
	"turn_resistance",
	"darkvision",
	"lowlight_vision",
	"concealment",
	"fortification",
	"room_sector",
	"room_light",
	"material",
	"*"
};

char *  const	 p_types [] =
{
	"@",
	"@",
	"@",
	"@",
	"sleeping",
	"resting",
	"sitting",
	"kneeling",
	"crouching",
	"fighting",
	"standing",
	"*"
};

char *  const   sex_types [] =
{
	"neutral",
	"male",
	"female",
	"*"
};

char *  const   size_types [] =
{
	"none",
	"fine",
	"diminutive",
	"tiny",
	"small",
	"medium",	
	"large",
	"huge",
	"gargantuan",
	"colossal",
	"*"
};

char *  const   lang_names [] =
{
	"Abyssal",
	"Aquan",
	"Auran",
	"Celestial",
	"Common",
	"Dwarven",	
	"Elven",
	"Giant",
	"Gnoll",
	"Gnome", 
	"Goblin",
	"Halfling",
	"Ignan",
	"Infernal",
	"Orcish",
	"Sylvan",
	"Terran",
	"Undercommon",
	"Draconic",
	"Druidic",
	"Thieves Cant",
	"*"
};

char *  const   school_types [] =
{
	"universal",
	"abjuration",
	"conjuration",
	"divination",
	"enchantment",
	"evocation",
	"illusion",
	"necromancy",
	"transmutation",
	"*"
};

char *  const   oppschool_types [] =
{
	"none",
	"transmutation",
	"necromancy",
	"illusion",
	"evocation",
	"enchantment",
	"divination",
	"conjuration",
	"abjuration",
	"*"
};

char *  const   spell_flags [] =
{
	"verbal",
	"somatic",
	"noncombat",
	"focus",
	"divinefocus",
	"personal",
	"touch",
	"close_range",
	"medium_range",
	"long_range",
	"infinite",
	"instant",
	"permanency",
	"nonscalable",
	"dismissable",
	"nodice",
	"radius",
	"ranged touch",
	"area cone",
	"area blast",
	"area line",
	"enemies",
	"group",
	"noresist",
	"extraordinary",
	"supernatural",
	"nocorpse",
	"spell_like",
	"language_dependent",
	"audible",
	"visual",
	"*"
};

char *  const   save_flags [] =
{
	"no_save",
	"fort_half",
	"fort_none",
	"refl_half",
	"refl_none",
	"will_half",
	"will_none",
	"fort_quarter",
	"will_quarter",
	"reflex_quarter",
	"*"
};

char *  const   prof_flags [] =
{
	"@",
	"focus",
	"greater focus",
	"epic focus",
	"specialized",
	"greater specialized",
	"epic specialized",
	"imp. critical",
	"power critical",
	"devastating",
	"*"
};

char *  const   target_types [] =
{
	"ignore",
	"char_offensive",
	"char_defensive",
	"char_self",
	"obj_inv",
	"obj_char_off",
	"obj_char_def",
	"obj_wield",
	"obj_room",
	"undead_offensive",
	"undead_defensive",
	"*"
};

char *  const   rtype_flags [] =
{
	"@",
	"aberration",
	"animal",
	"construct",
	"dragon",
	"fey",
	"humanoid",
	"magical",
	"monstrous",
	"ooze",
	"outsider",
	"plant",
	"undead",
	"vermin",
	"*"
};

char *  const  sect_types [] =
{
	"inside",
	"city",
	"field",
	"forest",
	"hills",
	"mountain",
	"lake",
	"river",
	"ocean",
	"air",
	"desert",
	"lava",
	"ethereal",
	"astral",
	"underwater",
	"underground",
	"deep_earth",
	"road",
	"swamp",
	"beach",	
	"tundra",
	"barren",
	"*"
};

char *  const  race_sectors [] =
{
	"city",
	"field",
	"forest",
	"hills",
	"mountain",
	"lake",
	"river",
	"ocean",
	"air",
	"desert",
	"lava",
	"ethereal",
	"astral",
	"underwater",
	"underground",
	"deep_earth",
	"road",
	"swamp",
	"beach",	
	"tundra",
	"barren",
	"*"
};

char * const   weap_types [] =
{
	"weapon",
	"knife",
	"dagger",
	"light_mace",
	"sickle",	
	"club",
	"heavy_mace",
	"morningstar",
	"shortspear",
	"longspear",
	"quarterstaff",
	"spear",
	"heavy_crossbow",
	"light_crossbow",
	"dart",
	"javelin",
	"sling",
	"throwing_axe",
	"light_hammer",
	"handaxe",
	"kukri",
	"light_pick",
	"sap",
	"shortsword",
	"battleaxe",
	"flail",
	"longsword",
	"heavy_pick",
	"rapier",
	"scimitar",
	"trident",
	"warhammer",
	"falchion",
	"glaive",
	"greataxe",
	"greatclub",
	"heavy_flail",
	"greatsword",
	"guisarme",
	"halberd",
	"lance",
	"ranseur",
	"scythe",
	"longbow",
	"comp_longbow",
	"shortbow",
	"comp_shortbow",
	"kama",
	"nunchaku",
	"sai",
	"siangham",
	"bastard_sword",
	"dwarven_waraxe",
	"elven_thinblade",
	"whip",
	"double_axe",
	"spiked_chain",
	"dire_flail",
	"double_sword",
	"dwarven_urgrosh",
	"bola",
	"hand_crossbow",
	"chakram",
	"shuriken",
	"*"
};

char * const   bow_types [] =
{
	"@",
	"@",
	"@",
	"@",
	"@",	
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"crossbow_heavy",
	"crossbow_light",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"longbow",
	"longbow_comp",
	"shortbow",
	"shortbow_comp",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"@",
	"crossbow_hand",
	"@",
	"*"
};

char * const  arm_types [] =
{
	"cloth",
	"padded",
	"leather",
	"studded_leather",
	"elven_chain",
	"hide",
	"scalemail",	
	"chainmail",
	"splint_mail",
	"banded_mail",
	"full_plate",
	"buckler",
	"light_shield",
	"heavy_shield",
	"tower_shield",
	"*"
};

char * const	noun_types [] =
{
	"hit",
	"slash",
	"crush",
	"pierce",
	"*"
};

char * const  tool_types [] =
{
	"none",
	"alchemy_kit",
	"climbers_kit",
	"disguise_kit",
	"firstaid_kit",
	"jewelers_tools",
	"magnifying_glass",
	"miners_pick",
	"merchants_scale",
	"pen",
	"rope",
	"shovel",
	"smith_tools",
	"survival_tools",
	"tanning_tools",
	"thieves_tools",	
	"woodworkers_tools",
	"seal",
	"fishing_pole",
	"tailors_tools",
	"anvil",
	"furnace",
	"lathe",
	"cooking_pot",
	"tinder",
	"shackles",
	"*"
};

char *  const   material_types [] =
{
	"unknown",
	"hardwood",
	"softwood",
	"darkwood",
	"oak",
	"yew",
	"ebony",
	"ironwood",
	"cloth",
	"silk",
	"wool",
	"fur",
	"leather",
	"hide",
	"dragonhide",
	"steel",
	"tin",
	"lead",
	"bronze",
	"copper",
	"gold",
	"silver",
	"platinum",
	"cold iron",
	"mithral",
	"adamantine",
	"diamond",
	"pearl",
	"gem",
	"ruby",
	"obsidian",
	"ivory",
	"emerald",
	"sapphire",
	"marble",
	"stone",
	"energy",
	"paper",
	"plant",
	"glass",
	"bone",
	"powder",
	"oil",
	"ice",
	"flesh",
	"water",
	"*"
};

char * const	liq_types [] =
{
	"water",
	"beer",
	"wine",
	"ale",
	"darkale",
	"whisky",
	"lemonade",
	"firebreather",
	"strong_ale",
	"strong_wine",
	"milk",
	"tea",
	"coffee",
	"blood",
	"saltwater",
	"oil",
	"juice",
	"brandy",
	"icewine",
	"rum",
	"vodka",
	"champagne",
	"*"
};

char * const	portal_flags [] =
{
	"teleport_world",
	"gowith",	
	"noflee",
	"stepthrough",
	"stepinto",
	"teleport_area",
	"closeable",
	"closed",
	"locked",
	"no_enter",
	"pickproof",
	"easy_pick",
	"hard_pick",
	"amazing_pick",
	"knocked",
	"*"
};

/* names of faerun deities */
char * const   god_types [] =
{
	"Agnostic",

	/* faerunian pantheon */
	"Akadi",
	"Auril",
	"Azuth",
	"Bane",
	"Beshaba",
	"Chauntea",
	"Cyric",
	"Deneir",
	"Eldath",
	"Finder Wyvernspur",
	"Garagos",
	"Gargauth",
	"Gond",
	"Grumbar",
	"Gwaeron Windstrom",
	"Helm",
	"Hoar",
	"Ilmater",
	"Istishia",
	"Jergal",
	"Kelemvor",
	"Kossuth",
	"Lathander",
	"Leira",
	"Lliira",
	"Loviatar",
	"Lurue",
	"Malar",
	"Mask",
	"Mielikki",
	"Milil",
	"Mystra",
	"Oghma",
	"Red Knight",
	"Savras",
	"Selune",
	"Shar",
	"Sharess",
	"Shaundakul",
	"Shiallia",
	"Siamorphe",
	"Silvanus",
	"Sune",
	"Talona",
	"Talos",
	"Tempus",
	"Torm",
	"Tymora",
	"Tyr",
	"Umberlee",
	"Valkur",
	"Velsharoon",
	"Waukeen",

	/* elven pantheon */
	"Aerdrie Faenya",
	"Angarradh",
	"Corellon Larethian",
	"Erevan Ilesere",
	"Fenmarel Mestarine",
	"Hanali Celanil",
	"Labelas Enoreth",
	"Rillfane Rallathil",
	"Sehanine Moonbow",
	"Shevarash",
	"Solonor Thelandira",

	/* drow pantheon */
	"Eilistraee",
	"Kiransalee",
	"Ghaunadaur",
	"Lolth",
	"Seveltarm",
	"Vhaeraun",

	/* dwarven pantheon */
	"Abbathor",
	"Berronar Truesilver",
	"Clangeddin Silverbeard",
	"Deep Duerra",
	"Dugmaren Brightmantle",
	"Dumathoin",
	"Gorm Gulthyn",
	"Haela Brightaxe",
	"Laduguer",
	"Marthammor Duin",
	"Moradin",
	"Sharindlar",
	"Thard Harr",
	"Vergadain",

	/* gnome pantheon */
	"Baervan Wildwanderer",
	"Baravar Cloakshadow",
	"Callarduran Smoothhands",
	"Flandal Steelskin",
	"Gaerdal Ironhand",
	"Garl Glittergold",
	"Segojan Earthcaller",
	"Urdlen",

	/* halfling pantheon */
	"Arvoreen",
	"Brandobaris",
	"Cyrrollalee",
	"Sheela Peryroyl",
	"Urogalan",
	"Yondalla",

	/* orcish pantheon */
	"Bahgtru",
	"Gruumsh",
	"Ilneval",
	"Luthic",
	"Shargaas",
	"Yurtrus",

	/* other deities */
	"Bahamut",
	"Baphomet",
	"Blibdoolpoolp",
	"Hruggek",
	"Kurtulmak",
	"Maglubiyet",
	"Semuanya",
	"Sseth",
	"Tiamat",
	"Vaprak",
	"Yeenoghu",
	"*"
};

char * const	class_types [] =
{
	"monster",
	"barbarian",
	"bard",
	"cleric",
	"druid",
	"fighter",
	"monk",	
	"paladin",
	"ranger",
	"rogue",
	"sorcerer",
	"wizard",
	"arcane archer",
	"arcane trickster",
	"assassin",
	"blackguard",
	"chevalier",
	"divine champion",
	"divine trickster",
	"duelist",
	"dwarven defender",
	"eldritch knight",
	"halfling slinger",
	"loremaster",
	"mystic theurge",
	"shadow adept",
	"shadowdancer",
	"adept",
	"noble",
	"commoner",
	"expert",
	"warrior",
	"*"
};

char *  const   trap_types [] =
{
	"sleep",
	"spell",
	"fire",
	"cold",
	"acid",
	"electrical",
	"blunt",
	"pierce",
	"slash",
	"ranged",
	"mload",
	"oload",
	"roomflag",
	"poison",
	"teleport",
	"*"
};

char *  const   scroll_types [] =
{
	"none",
	"arcane",
	"divine",
	"*"
};

char *  const   trap_triggers [] =
{
	"move",
	"move_north",
	"move_east",
	"move_south",
	"move_west",
	"move_up",
	"move_down",
	"open_north",
	"open_east",
	"open_south",
	"open_west",
	"open_up",
	"open_down",
	"open_obj",
	"getput",
	"roomeffect",
	"magical",
	"*"
};


char *  const   trap_resets [] =
{
	"none",
	"manual",
	"auto",
	"*"
};


char *  const   trap_state [] =
{
	"unarmed",
	"armed",
	"*"
};

char *  const   poison_names [] =
{
	"none",
	"nitharit",
	"sassone",
	"malyss_root",
	"terinav_root",
	"black_lotus",
	"dragon_bile",
	"toadstool",
	"arsenic",
	"id_moss",
	"lich_dust",
	"ungol_dust",
	"insanity_mist",
	"black_adder_venom",
	"centipede_poison",
	"bloodroot",
	"spider_venom",
	"wyvern_poison",
	"scorpion_venom",
	"giant_wasp_poison",
	"deathblade",
	"purple_worm_venom",
	"sleep_poison",
	"*"
};


char *  const   disease_names [] =
{
	"none",
	"blinding_sickness",
	"cackle_fever",
	"demon_fever",
	"devil_chills",
	"filth_fever",
	"ghoul_fever",
	"mindfire",
	"mummy_rot",
	"red_ache",
	"shakes",
	"slimy_doom",
	"*"
};


/*
 * dynamically compute the value of an item - Kregor
 * calcs on obj_index_data for editing objects.
 */
int obj_index_cost( OBJ_INDEX_DATA *obj)
{
	AFFECT_DATA *paf;
	int cost = -1;
	int spell_lvl;
	int cnt, mod;
	
	push_call("obj_index_cost(%p)",obj);
	
	switch (obj->item_type)
	{
		case ITEM_SYMBOL:
			cost = 2500;
			cost += obj->value[3] * obj->value[3] * 100000;
			break;
		case ITEM_WEAPON:
			cost = weapon_table[obj->value[0]].cost;
			break;
		case ITEM_AMMO:
			cost = 10;
			break;
		case ITEM_ARMOR:
			cost = armor_table[obj->value[0]].cost;
			break;
		case ITEM_TOOLS:
			cost = tool_table[obj->value[0]].cost;
			break;
		case ITEM_POTION:
			spell_lvl = get_spell_circle(NULL, obj->value[1]);
			cost = 5000 * obj->value[0] * (spell_lvl == 0 ? 0.5 : spell_lvl);
			break;
		case ITEM_SCROLL:
			spell_lvl = get_spell_circle(NULL, obj->value[1]);
			cost = 2500 * obj->value[0] * (spell_lvl == 0 ? 0.5 : spell_lvl);
			break;
		case ITEM_WAND:
			spell_lvl = get_spell_circle(NULL, obj->value[3]);
			cost = 1500 * obj->value[0] * obj->value[1] * (spell_lvl == 0 ? 0.5 : spell_lvl);
			break;
		case ITEM_STAFF:
			spell_lvl = get_spell_circle(NULL, obj->value[3]);
			cost = 1500 * obj->value[0] * obj->value[1] * (spell_lvl == 0 ? 0.5 : spell_lvl);
			if (is_spell(obj->value[4]))
			{
				spell_lvl = get_spell_circle(NULL, obj->value[4]);
				cost += 1125 * obj->value[0] * obj->value[1] * (spell_lvl == 0 ? 0.5 : spell_lvl);
			}
			if (is_spell(obj->value[5]))
			{
				spell_lvl = get_spell_circle(NULL, obj->value[5]);
				cost += 750 * obj->value[0] * obj->value[1] * (spell_lvl == 0 ? 0.5 : spell_lvl);
			}
			if (is_spell(obj->value[6]))
			{
				spell_lvl = get_spell_circle(NULL, obj->value[6]);
				cost += 750 * obj->value[0] * obj->value[1] * (spell_lvl == 0 ? 0.5 : spell_lvl);
			}
			break;
	}
					
	if (obj->item_type == ITEM_ARMOR)
	{
		if (IS_SET(obj->wear_flags, CAN_WEAR_BODY))
		{
			cost *= 3;
		}
		else if (IS_SET(obj->wear_flags, CAN_WEAR_HEAD)
		|| IS_SET(obj->wear_flags, CAN_WEAR_ARMS)
		|| IS_SET(obj->wear_flags, CAN_WEAR_LEGS))
		{
			cost *= 2;
		}
		else if (IS_SET(obj->wear_flags, CAN_WEAR_FEET)
		|| IS_SET(obj->wear_flags, CAN_WEAR_HANDS))
		{
			cost /= 2;
		}
		for (cnt = 0 ; cnt < ARMORFLAG_MAX ; cnt++)
		{
			if (IS_SHIFT(obj->value[1], cnt))
			{
				cnt += armflag_cost_mod[cnt];
			}
		}
	}

	if (IS_SET(obj->extra_flags, ITEM_MASTERWORK))
	{
		switch (obj->item_type)
		{
			case ITEM_WEAPON:
				cost += 30000;
				break;
			case ITEM_AMMO:
				cost += 600;
				break;
			case ITEM_ARMOR:
				cost += 15000;
				break;
			case ITEM_TOOLS:
				cost *= (obj->value[2] * 5);
				break;
		}
	}

	if (obj->item_type == ITEM_TREASURE)
	{
		if (IS_SET(obj->value[0], TFLAG_SPELL_STORING))
		{
			cost += 10000000;
		}
		if (IS_SET(obj->value[0], TFLAG_SPELL_RECAST))
		{
			cost += 1800000;
		}
		if (IS_SET(obj->value[0], TFLAG_SPELL_CHARGES))
		{
			cost += 900000;
		}
		if (IS_SET(obj->value[0], TFLAG_ABSORPTION))
		{
			cost += 4000000;
		}
		if (IS_SET(obj->value[0], TFLAG_COUNTERSPELL))
		{
			cost += 400000;
		}
	}

	for (paf = obj->first_affect ; paf != NULL ; paf = paf->next)
	{
		if (paf->duration >= 0) // so spell affects don't add to cost
			continue;
		
		if (paf->location == APPLY_HITROLL)
		{
			if (obj->item_type == ITEM_WEAPON || obj->item_type == ITEM_AMMO)
			{
				mod = paf->modifier;
				for (cnt = 0 ; cnt < WFLAG_MAX ; cnt++)
				{
					if (IS_SHIFT(obj->value[1], cnt))
					{
						mod += wflag_cost_mod[cnt];
					}
				}
				cost += mod * mod * 100000;
				continue;
			}
		}
		if (paf->location == APPLY_ENHANCE_AC)
		{
			if (obj->item_type == ITEM_ARMOR)
			{
				mod = paf->modifier;
				for (cnt = 0 ; cnt < WFLAG_MAX ; cnt++)
				{
					if (IS_SHIFT(obj->value[1], cnt))
					{
						mod += wflag_cost_mod[cnt];
					}
				}
				cost += mod * mod * 100000;
				continue;
			}
		}
		cost += obj_affect_cost(paf);
	}
	pop_call();
	return cost;
}


char *flag_string( lg_int bitvector, char * const array[] )
{
	static char buf[MAX_STRING_LENGTH];
	int x, count;

	push_call("flag_string(%p,%p)",bitvector,array);

	buf[0] = '\0';

	for (count = x = 0 ; x < 64 ; x++)
	{
		if (!strcmp("@", array[x]))
		{
			continue;
		}
		if (!strcmp("*", array[x]))
		{
			break;
		}
		if (IS_SET(bitvector, 1LL << x))
		{
			if (count)
				strcat( buf, ", " );
			strcat( buf, array[x] );
			count++;
		}
	}

	if ((x = strlen(buf)) > 0)
	{
		buf[x] = '\0';
	}
	pop_call();
	return buf;
}

char *type_string( lg_int bitvector, char * const array[] )
{
	int x;

	push_call("type_string(%p,%p)",bitvector,array);

	for (x = 0 ; x < 256 ; x++)
	{
		if (!strcmp("@", array[x]))
		{
			continue;
		}
		if (!strcmp("*", array[x]) || bitvector == x)
		{
			pop_call();
			return(array[x]);
		}
	}
	pop_call();
	return "";
}


lg_int get_flag( char *flag, char * const array[])
{
	int x;

	push_call("get_flag(%p)",flag);

	for (x = 0 ; x < 256 ; x++)
	{
		if (!strcmp("@", array[x]))
		{
			continue;
		}
		if (!strcmp("*", array[x]))
		{
			break;
		}
		if (!strcasecmp(flag, array[x]))
		{
			pop_call();
			return x;
		}
	}
	pop_call();
	return -1;
}


bool toggle_flags(void *field, char *flag, char * const array[])
{
	char arg[MAX_INPUT_LENGTH];
	lg_int *value;
	int x;

	push_call("toggle_flags(%p,%p,%p)",field,flag,array);

	value = field;

	if (*flag == '\0')
	{
		pop_call();
		return FALSE;
	}

	for (flag = one_argument(flag, arg) ; arg[0] != '\0' ; flag = one_argument(flag, arg))
	{
		for (x = 0 ; x < 64 ; x++)
		{
			if (!strcmp("@", array[x]))
			{
				continue;
			}
			if (!strcmp("*", array[x]))
			{
				break;
			}
			if (!strcasecmp(arg, array[x]))
			{
				TOGGLE_BIT(*value, 1LL << x);
				break;
			}
		}
		if (!strcmp("*", array[x]))
		{
			pop_call();
			return FALSE;
		}
	}
	pop_call();
	return TRUE;
}

char *give_flags( char * const array[])
{
	static char buf[MAX_STRING_LENGTH * 2];
	int x, count;

	push_call("give_flags(%p)",array);

	for (buf[0] = '\0', count = x = 0 ; x < 256 ; x++)
	{
		if (!strcmp("@", array[x]))
		{
			continue;
		}
		if (!strcmp("*", array[x]))
		{
			break;
		}
		if (count)
			cat_sprintf(buf, "| ");
		cat_sprintf(buf, "%s ", array[x]);
		count++;
	}
	buf[strlen(buf)-1] = '\0';

	pop_call();
	return buf;
}


char *flag_menu( char * const array[])
{
	static char buf[MAX_STRING_LENGTH * 2];
	int x, col;

	push_call("give_flags(%p)",array);

	for (buf[0] = '\0', col = x = 0 ; x < 256 ; x++)
	{
		if (!strcmp("@", array[x]))
		{
			continue;
		}
		if (!strcmp("*", array[x]))
		{
			break;
		}
		cat_sprintf(buf, " %-19s", array[x]);
		if (col++ % 4 == 0)
			cat_sprintf(buf, "\n\r");
	}
	if (col % 4 != 0)
		cat_sprintf(buf, "\n\r");
	buf[strlen(buf)-1] = '\0';

	pop_call();
	return buf;
}


bool can_olc_modify( CHAR_DATA *ch, int vnum )
{
	AREA_DATA *area;

	push_call("can_olc_modify(%p,%p)",ch,vnum);

	if (IS_NPC(ch) || !IS_IMMORTAL(ch))
	{
		log_string("BUG OLC Security Breach.");
		dump_stack();
		pop_call();
		return FALSE;
	}

	if ((area = get_area_from_vnum(vnum)) == NULL)
	{
		pop_call();
		return FALSE;
	}

	if (ch->level >= LEVEL_IMMORTAL)
	{
		if (IS_GOD(ch))
		{
			pop_call();
			return TRUE;
		}
		else
		{
			log_printf("Illegal God");
			dump_stack();
		}
	}

	if (is_name(ch->name, area->authors))
	{
		pop_call();
		return TRUE;
	}

	if (ch->pcdata->a_range_lo == 0)
	{
		pop_call();
		return FALSE;
	}

	if (vnum >= ch->pcdata->a_range_lo && vnum <= ch->pcdata->a_range_hi)
	{
		pop_call();
		return TRUE;
	}


	pop_call();
	return FALSE;
}

bool show_build_vnum ( CHAR_DATA *ch, int vnum )
{
	push_call("show_build_vnum(%p,%p)",ch,vnum);

	if (IS_NPC(ch))
	{
		pop_call();
		return FALSE;
	}

	if (!IS_SET(ch->act, PLR_BUILDLIGHT))
	{
		pop_call();
		return FALSE;
	}

	if (!can_olc_modify(ch, vnum))
	{
		pop_call();
		return FALSE;
	}
	pop_call();
	return TRUE;
}

EXTRA_DESCR_DATA *set_ed_room(ROOM_INDEX_DATA *room, char *keywords )
{
	EXTRA_DESCR_DATA *ed;

	push_call("set_ed_room(%p,%p)",room,keywords);

	for (ed = room->first_extradesc ; ed ; ed = ed->next)
	{
		if (is_name(keywords, ed->keyword) || !strcasecmp(keywords, ed->keyword))
		{
			break;
		}
	}

	if (ed == NULL)
	{
		ALLOCMEM(ed, EXTRA_DESCR_DATA, 1);
		LINK(ed, room->first_extradesc, room->last_extradesc, next, prev);
		ed->keyword     = STRALLOC( keywords );
		ed->description = STRALLOC( "" );
		mud->top_ed++;
	}
	pop_call();
	return ed;
}

EXTRA_DESCR_DATA *set_ed_obj(OBJ_INDEX_DATA *obj, char *keywords )
{
	EXTRA_DESCR_DATA *ed;

	push_call("set_ed_obj(%p,%p)",obj,keywords);

	for (ed = obj->first_extradesc ; ed ; ed = ed->next)
	{
		if (is_name(keywords, ed->keyword) || !strcasecmp(keywords, ed->keyword))
		{
			break;
		}
	}

	if (ed == NULL)
	{
		ALLOCMEM(ed, EXTRA_DESCR_DATA, 1);
		LINK(ed, obj->first_extradesc, obj->last_extradesc, next, prev);
		ed->keyword     = STRALLOC( keywords );
		ed->description = STRALLOC( "" );
		mud->top_ed++;
	}
	pop_call();
	return ed;
}

EXTRA_DESCR_DATA *set_ed_mob(MOB_INDEX_DATA *mob, char *keywords )
{
	EXTRA_DESCR_DATA *ed;

	push_call("set_ed_mob(%p,%p)",mob,keywords);

	for (ed = mob->first_extradesc ; ed ; ed = ed->next)
	{
		if (is_name(keywords, ed->keyword) || !strcasecmp(keywords, ed->keyword))
		{
			break;
		}
	}

	if (ed == NULL)
	{
		ALLOCMEM(ed, EXTRA_DESCR_DATA, 1);
		LINK(ed, mob->first_extradesc, mob->last_extradesc, next, prev);
		ed->keyword     = STRALLOC( keywords );
		ed->description = STRALLOC( "" );
		mud->top_ed++;
	}
	pop_call();
	return ed;
}

bool del_ed_room( ROOM_INDEX_DATA *room, char *keywords )
{
	EXTRA_DESCR_DATA *ed;

	push_call("del_ed_room(%p,%p)",room,keywords);

	for (ed = room->first_extradesc ; ed ; ed = ed->next)
	{
		if (is_name(keywords, ed->keyword) || !strcasecmp(keywords, ed->keyword))
		{
			break;
		}
	}

	if (ed)
	{
		UNLINK(ed, room->first_extradesc, room->last_extradesc, next, prev);
		STRFREE(ed->keyword);
		STRFREE(ed->description);
		FREEMEM(ed);
		mud->top_ed--;
		pop_call();
		return TRUE;
	}
	pop_call();
	return FALSE;
}

bool del_ed_obj( OBJ_INDEX_DATA *obj, char *keywords )
{
	EXTRA_DESCR_DATA *ed;

	push_call("del_ed_obj(%p,%p)",obj,keywords);

	for (ed = obj->first_extradesc ; ed ; ed = ed->next)
	{
		if (is_name(keywords, ed->keyword) || !strcasecmp(keywords, ed->keyword))
		{
			break;
		}
	}

	if (ed)
	{
		UNLINK(ed, obj->first_extradesc, obj->last_extradesc, next, prev);
		STRFREE(ed->keyword);
		STRFREE(ed->description);
		FREEMEM(ed);
		mud->top_ed--;
		pop_call();
		return TRUE;
	}
	pop_call();
	return FALSE;
}


bool del_ed_mob( MOB_INDEX_DATA *mob, char *keywords )
{
	EXTRA_DESCR_DATA *ed;

	push_call("del_ed_mob(%p,%p)",mob,keywords);

	for (ed = mob->first_extradesc ; ed ; ed = ed->next)
	{
		if (is_name(keywords, ed->keyword) || !strcasecmp(keywords, ed->keyword))
		{
			break;
		}
	}

	if (ed)
	{
		UNLINK(ed, mob->first_extradesc, mob->last_extradesc, next, prev);
		STRFREE(ed->keyword);
		STRFREE(ed->description);
		FREEMEM(ed);
		mud->top_ed--;
		pop_call();
		return TRUE;
	}
	pop_call();
	return FALSE;
}

char *get_ed(CHAR_DATA *ch, EXTRA_DESCR_DATA *ed)
{
	static char buf[MAX_STRING_LENGTH];

	push_call("get_ed(%p)",ed);

	for (buf[0] = '\0' ; ed ; ed = ed->next)
	{
		cat_sprintf(buf, "%s", ed->keyword);
		if (ed->next)
		{
			cat_sprintf(buf, "%s", ansi_translate_text(ch, "{078}, {178}"));
		}
	}
	pop_call();
	return buf;
}

void set_obj_affect( OBJ_INDEX_DATA *obj, int value, int modif, int type, lg_int bitv )
{
	int count;
	AFFECT_DATA *aff;

	push_call("set_obj_affect(%p,%p,%p,%p)",obj,value,modif,type);

	for (count = 0, aff = obj->first_affect ; aff ; aff = aff->next)
	{
		if (++count == value)
		{
			break;
		}
	}
	if (aff == NULL)
	{
		ALLOCMEM(aff, AFFECT_DATA, 1);
		aff->type      =  0;
		aff->duration  = -1;
		aff->bitvector =  0;
		LINK(aff, obj->first_affect, obj->last_affect, next, prev);
		mud->top_affect++;
	}
	if (type != -1)
	{
		aff->location = type;
	}
	if (modif != -1)
	{
		aff->modifier = modif;
	}
	if (bitv != -1)
	{
		aff->bitvector = bitv;
	}

	if (aff->bitvector)
	{
		aff->bittype = AFFECT_TO_CHAR;
	}
	else
	{
		aff->bittype = AFFECT_TO_NONE;
	}

	if (type == -2)
	{
		UNLINK(aff, obj->first_affect, obj->last_affect, next, prev);
		FREEMEM(aff);
		mud->top_affect--;
	}
	pop_call();
	return;
}

void set_mob_affect( MOB_INDEX_DATA *mob, int value, int modif, int type, lg_int bitv )
{
	int count;
	AFFECT_DATA *aff;

	push_call("set_mob_affect(%p,%p,%p,%p)",mob,value,modif,type);

	for (count = 0, aff = mob->first_affect ; aff ; aff = aff->next)
	{
		if (++count == value)
		{
			break;
		}
	}
	if (aff == NULL)
	{
		ALLOCMEM(aff, AFFECT_DATA, 1);
		aff->type      =  0;
		aff->duration  = -1;
		aff->bitvector =  0;
		LINK(aff, mob->first_affect, mob->last_affect, next, prev);
		mud->top_affect++;
	}
	if (type != -1)
	{
		aff->location = type;
	}
	if (modif != -1)
	{
		aff->modifier = modif;
	}
	if (bitv != -1)
	{
		aff->bitvector = bitv;
	}

	if (aff->bitvector)
	{
		aff->bittype = AFFECT_TO_CHAR;
	}
	else
	{
		aff->bittype = AFFECT_TO_NONE;
	}

	if (type == -2)
	{
		UNLINK(aff, mob->first_affect, mob->last_affect, next, prev);
		FREEMEM(aff);
		mud->top_affect--;
	}
	pop_call();
	return;
}

void set_link( int room, int door, int dest)
{
	EXIT_DATA  *pExit;
	RESET_DATA *pReset;

	push_call("set_link(%p,%p,%p)",room,door,dest);

	if (room < 1 || dest < -1
	||  room_index[room] == NULL
	||  door < 0 || door > 5
	|| (dest != -1 && room_index[dest] == NULL))
	{
		log_printf("Bad room connect at %d door %d to %d", room, door, dest);
		pop_call();
		return;
	}

	if (room_index[room]->exit[door] == NULL && dest > 0)
	{
		create_exit(room_index[room], door);
	}

	pExit = room_index[room]->exit[door];

	if (dest > 0)
	{
		pExit->vnum	= dest;
		pExit->to_room	= dest;
	}
	else
	{
		if (pExit)
		{
			delete_exit(room_index[room], door);

			for (pReset = room_index[room]->area->first_reset ; pReset ; )
			{
				if (is_room_reset(pReset, room_index[room]) && is_door_reset(pReset, door))
				{
					delete_reset(room_index[room]->area, pReset);

					pReset = room_index[room]->area->first_reset;
				}
				else
				{
					pReset = pReset->next;
				}
			}
		}
	}
	pop_call();
	return;
}

void do_link( CHAR_DATA *ch, char *argument )
{
	ROOM_INDEX_DATA *room;
	int dest_vnum, rev_dest_vnum;
	int door_num;
	char arg1 [MAX_INPUT_LENGTH];
	char arg2 [MAX_INPUT_LENGTH];
	char arg3 [MAX_INPUT_LENGTH];

	push_call("do_link(%p,%p)",ch,argument);

	if ((room = ch->in_room) == NULL)
	{
		pop_call();
		return;
	}
	
	if (!can_olc_modify(ch, room->vnum))
	{
		ch_printf_color(ch, "This room is not in your allocated range.\n\r");
		pop_call();
		return;
	}
	
	argument = one_argument( argument, arg1 );
	argument = one_argument( argument, arg2 );
	strcpy( arg3, argument );

	if (arg1[0] == '\0' || arg2[0] == '\0')
	{
		send_to_char("Syntax: <dir> link <destination vnum> [both]\n\r", ch);
		send_to_char("Syntax: <dir> link delete [both]\n\r", ch);
		pop_call();
		return;
	}

	door_num		= direction_door(arg1);
	dest_vnum 	= atoi( arg2 );
	rev_dest_vnum	= 0;

	if (door_num < 0 || door_num > 5 )
	{
		send_to_char( "Invalid direction.\n\r",ch);
		pop_call();
		return;
	}

	if (!strcasecmp(arg2, "delete"))
	{
		rev_dest_vnum = room->exit[door_num]->to_room;

		if (arg3[0] == 'b' || arg3[0] == 'B')
		{
			delete_exit(room_index[rev_dest_vnum], rev_dir[door_num]);
		}
		delete_exit(room, door_num);
		pop_call();
		return;
	}
	else if (!is_number(arg2))
	{
		ch_printf_color(ch, "Not a valid vnum.\n\r");
		pop_call();
		return;
	}
	
	if (get_room_index(dest_vnum) == NULL && dest_vnum != -1)
	{
		if (can_olc_modify(ch, dest_vnum))
		{
			do_rcreate(ch, arg2);
		}
		else
		{
			send_to_char( "A room with that vnum does not exist.\n\r",ch);
			pop_call();
			return;
		}
	}

	if (!IS_NPC(ch) && dest_vnum != -1 && !can_olc_modify(ch, dest_vnum))
	{
		ch_printf_color(ch, "That vnum is not in your allocated range.\n\r");
		pop_call();
		return;
	}

	if (room->exit[door_num] && room->exit[door_num]->vnum > 0)
	{
		rev_dest_vnum = room->exit[door_num]->vnum;
	}

	set_link(room->vnum, door_num, dest_vnum);

	if (arg3[0] == 'b' || arg3[0] == 'B')
	{
		if (dest_vnum != -1)
		{
			set_link(dest_vnum, rev_dir[door_num], room->vnum);
		}
		else
		{
			set_link(rev_dest_vnum, rev_dir[door_num], -1);
		}
	}

	pop_call();
	return;
}

void start_editing( CHAR_DATA *ch, char *data )
{
	EDITOR_DATA *edit;
	char c, buffer[MAX_INPUT_LENGTH];
	sh_int line     = 0;
	sh_int leng     = 0;
	sh_int size     = 0;
	sh_int max_line = 150;
	sh_int max_size = 8000;

	push_call("start_editing(%p,%p)",ch,data);

	if (ch->level >= LEVEL_IMMORTAL)
	{
		max_line = 600;
		max_size = 32000;
	}

	if (ch->pcdata->editor) /* likely called by /w in the editor */
	{
		edit = ch->pcdata->editor;

		while (edit->numlines)
		{
			edit->numlines--;
			STRFREE(edit->line[edit->numlines]);
		}
	}
	else
	{
		ch->desc->connected = CON_EDITING;

		send_to_char( "Begin entering your text now (/? = help /s = save /c = clear /l = list)\n\r", ch );
		send_to_char( "-----------------------------------------------------------------------\n\r", ch );

		ALLOCMEM(edit, EDITOR_DATA, 1);
	}

	while (TRUE)
	{
		c = data[size++];

		switch (c)
		{
			case '\0':
				if (leng)
				{
					buffer[leng] = 0;
					edit->line[line++] = STRALLOC(buffer);
				}
				goto endofloop;

			case '\r':
				continue;

			case '\n':
				buffer[leng] = 0;
				edit->line[line++] = STRALLOC(buffer);
				leng = 0;
				break;

			default:
				buffer[leng++] = c;
				break;
		}

		if (line == max_line)
		{
			break;
		}

		if (size == max_size)
		{
			buffer[leng] = 0;
			edit->line[line++] = STRALLOC(buffer);
			break;
		}
	}
	endofloop:

	edit->numlines     = line;
	edit->size         = size;
	edit->on_line      = line;

	ch->pcdata->editor = edit;

	edit_buffer(ch, "/p");
	pop_call();
	return;
}

/*
	Copy the buffer, strips tailing spaces - Scandum
*/

char *copy_buffer( CHAR_DATA *ch )
{
	char buf1[MAX_INPUT_LENGTH], buf2[MAX_STRING_LENGTH];
	int x, y;

	push_call("copy_buffer(%p)",ch);

	for (x = buf2[0] = '\0' ; x < ch->pcdata->editor->numlines ; x++)
	{
		strcpy(buf1, ch->pcdata->editor->line[x]);

		for (y = strlen(buf1) - 1 ; y >= 0 ; y--)
		{
			if (buf1[y] == ' ')
			{
				buf1[y] = '\0';
			}
			else
			{
				break;
			}
		}
		cat_sprintf(buf2, "%s\n\r", buf1);
	}
	smash_tilde(buf2);

	pop_call();
	return STRALLOC(buf2);
}

void stop_editing( CHAR_DATA *ch )
{
	int x;

	push_call("stop_editing(%p)",ch);

	if (ch->pcdata->editor)
	{
		for (x = 0 ; x < ch->pcdata->editor->numlines ; x++)
		{
			STRFREE(ch->pcdata->editor->line[x]);
		}
		FREEMEM(ch->pcdata->editor);
		ch->pcdata->editor = NULL;
	}
	send_to_char("Done.\n\r", ch);

	ch->pcdata->editmode  = ch->pcdata->tempmode;
	ch->pcdata->tempmode  = MODE_NONE;

	if (ch->desc)
	{
		ch->desc->connected = CON_PLAYING;
	}
	pop_call();
	return;
}

void stop_olc_editing( CHAR_DATA *ch, AREA_DATA *area)
{
	push_call("stop_olc_editing(%p,%p)",ch,area);

	ch->pcdata->edittype = EDIT_TYPE_NONE;
	ch->pcdata->editmode = MODE_NONE;
	ch->pcdata->tempmode = MODE_NONE;
	ch->pcdata->edit_ptr = NULL;
	ch->pcdata->temp_ptr = NULL;

	if (ch->pcdata && ch->pcdata->subprompt)
	{
		STRFREE(ch->pcdata->subprompt);
		ch->pcdata->subprompt = NULL;
	}
	CHECK_AUTOSAVE(area);

	pop_call();
	return;
}

/*
	Simple but nice and handle line editor.                     Martin
*/

void edit_buffer( CHAR_DATA *ch, char *argument )
{
	DESCRIPTOR_DATA *d;
	EDITOR_DATA *edit;
	char cmd[MAX_INPUT_LENGTH];
	char buf[MAX_INPUT_LENGTH];
	char prompt[15];
	char word1[MAX_INPUT_LENGTH];
	char word2[MAX_INPUT_LENGTH];
	char word3[MAX_INPUT_LENGTH];
	char *data;
	sh_int x        = 0;
	sh_int y        = 0;
	sh_int line     = 0;
	sh_int max_line = 150;
	sh_int max_leng = 1000;
	sh_int max_size = 8000;
	bool save       = FALSE;

	push_call("edit_buffer(%p,%p)",ch,argument);

	if (ch->level >= LEVEL_IMMORTAL)
	{
		max_line = 600;
		max_size = 32000;
	}

	if ((d = ch->desc) == NULL)
	{
		send_to_char( "You have no descriptor.\n\r", ch );
		pop_call();
		return;
	}

	sprintf(prompt, "%s> ", get_color_string(ch, COLOR_PROMPT, VT102_DIM));

	edit = ch->pcdata->editor;

	if (argument[0] == '/' || argument[0] == '\\')
	{
		argument = one_argument(argument, cmd);

		switch (cmd[1])
		{
			case '?':
				ch_printf(ch,
					"Editing commands\n\r"
					"-----------------------------------\n\r"
					"/c                 clear buffer    \n\r"
					"/d [line] [amount] delete lines    \n\r"
					"/g <line>          goto line       \n\r"
					"/i [line] [amount] insert lines    \n\r"
					"/l [range]         list buffer     \n\r"
					"/r <old> <new>     global replace  \n\r"
					"/w                 global word wrap\n\r"
					"/a                 abort editing   \n\r"
					"/s                 save buffer     \n\r");

				write_to_buffer( ch->desc, prompt, 1000000 );
				break;

			case 'p':
				write_to_buffer( ch->desc, prompt, 1000000 );
				break;

			case 'c':
				for (x = 0 ; x < edit->numlines ; x++)
				{
					STRFREE(edit->line[x]);
				}
				edit->numlines = 0;
				edit->on_line  = 0;
				edit->size     = 0;
				send_to_char( "Buffer cleared.\n\r", ch );
				write_to_buffer( ch->desc, prompt, 1000000 );
				break;

			case 'w':
				if (ch->pcdata->editmode == MODE_MPROG_EDIT
				|| ch->pcdata->editmode == MODE_RPROG_EDIT
				|| ch->pcdata->editmode == MODE_OPROG_EDIT)
				{
					send_to_char("You wouldn't want to word wrap a program buffer.\n\r", ch);
					write_to_buffer( ch->desc, prompt, 1000000 );
				}
				else
				{
					for (x = 0 ; x < edit->numlines ; x++)
					{
						strcpy(buf, ansi_justify(edit->line[x], 80));
						RESTRING(edit->line[x], buf);
					}

					data = copy_buffer(ch);

					start_editing(ch, data);

					STRFREE(data);

					ch_printf(ch, "Word wrapped text between line 1 and %d\n\r", x);
					write_to_buffer( ch->desc, prompt, 1000000 );
				}
				break;

			case 'r':
				{
					char *wptr, *lwptr;
					int count, wordln, word2ln;

					argument = one_argument_nolower(argument, word1);
					argument = one_argument_nolower(argument, word2 );

					if (word1[0] == '\0' || word2[0] == '\0')
					{
						send_to_char( "You need a word to replace, and it's replacement.\n\r", ch);
						write_to_buffer( ch->desc, prompt, 1000000 );
						pop_call();
						return;
					}

					count   = 0;
					wordln  = strlen(word1);
					word2ln = strlen(word2);

					ch_printf( ch, "Replacing all occurrences of %s with %s...\n\r", word1, word2 );

					for (x = 0 ; x < edit->numlines ; x++)
					{
						lwptr = strcpy(buf, edit->line[x]);
	
						while ((wptr = strstr(lwptr, word1)) != NULL)
						{
							if (edit->size + (word2ln - wordln) >= max_size)
							{
								break;
							}
							if (strlen(buf) + (word2ln - wordln) >= max_leng)
							{
								break;
							}
							lwptr = wptr + word2ln;

							sprintf(word3, "%s%s", word2, wptr + wordln);
							strcpy(wptr, word3);

							edit->size += (word2ln - wordln);
							count      += 1;
						}
						RESTRING(edit->line[x], buf);
					}
					ch_printf( ch, "Found and replaced %d occurrence%s between line 1 and %d.\n\r", count, count == 1 ? "" : "s",  edit->numlines);
					write_to_buffer( ch->desc, prompt, 1000000 );
				}
				break;

			case 'i':
				if (edit->numlines >= max_line)
				{
					send_to_char( "Buffer is full.\n\r", ch );
					write_to_buffer( ch->desc, prompt, 1000000 );
				}
				else
				{
					int count;

					argument = one_argument_nolower(argument, word1);
					argument = one_argument_nolower(argument, word2 );

					if (word1[0] != '\0')
					{
						line = atoi(word1) - 1;
					}
					else
					{
						line = edit->on_line;
					}
					count = URANGE(1, atoi(word2), max_line - edit->numlines);

					if (line < 0 || line > edit->numlines)
					{
						send_to_char( "Out of range.\n\r", ch );
						write_to_buffer( ch->desc, prompt, 1000000 );
					}
					else
					{
						for (y = 0 ; y < count ; y++)
						{
							for (x = ++edit->numlines ; x > line ; x--)
							{
								edit->line[x] = edit->line[x-1];
							}
							edit->line[line] = STRDUPE(str_empty);
						}
						ch_printf(ch, "Line%s inserted.\n\r", count > 1 ? "s" : "");
						write_to_buffer( ch->desc, prompt, 1000000 );
					}
				}
				break;

			case 'd':
				if (edit->numlines == 0)
				{
					send_to_char( "Buffer is empty.\n\r", ch );
					write_to_buffer( ch->desc, prompt, 1000000 );
				}
				else
				{
					int count;

					argument = one_argument_nolower(argument, word1);
					argument = one_argument_nolower(argument, word2 );

					if (word1[0] != '\0')
					{
						line = atoi(word1) - 1;
					}
					else
					{
						line = URANGE(0, edit->on_line, edit->numlines - 1);
					}
					count = URANGE(1, atoi(word2), edit->numlines - line);

					if (line < 0 || line > edit->numlines)
					{
						send_to_char( "Out of range.\n\r", ch );
						write_to_buffer( ch->desc, prompt, 1000000 );
					}
					else
					{
						for (y = 0 ; y < count ; y++)
						{
							edit->size -= strlen(edit->line[line]);

							STRFREE(edit->line[line]);

							for (x = line ; x < (edit->numlines - 1) ; x++)
							{
								edit->line[x] = edit->line[x+1];
							}

							edit->numlines--;

							if (edit->on_line > edit->numlines)
							{
								edit->on_line = edit->numlines;
							}

						}
						ch_printf(ch, "Line%s deleted.\n\r", count > 1 ? "s" : "");
						write_to_buffer( ch->desc, prompt, 1000000 );
					}
				}
				break;

			case 'g':
				if (edit->numlines == 0)
				{
					send_to_char( "Buffer is empty.\n\r", ch );
					write_to_buffer( ch->desc, prompt, 1000000 );
				}
				else
				{
					if (argument[0] != '\0')
					{
						line = atoi(argument) - 1;
					}
					else
					{
						send_to_char( "Goto what line?\n\r", ch );
						write_to_buffer( ch->desc, prompt, 1000000 );
						pop_call();
						return;
					}
					if (line < 0 || line > edit->numlines)
					{
						send_to_char( "Out of range.\n\r", ch );
						write_to_buffer( ch->desc, prompt, 1000000 );
					}
					else
					{
						edit->on_line = line;
						ch_printf( ch, "(On line %d)\n\r", line+1 );
						write_to_buffer( ch->desc, prompt, 1000000 );
					}
				}
				break;

			case 'l':
				if (edit->numlines == 0)
				{
					send_to_char( "Buffer is empty.\n\r", ch );
					write_to_buffer( ch->desc, prompt, 1000000 );
				}
				else
				{
					argument = one_argument(argument, word1);
					argument = one_argument(argument, word2);

					x = atoi(word1)-1;
					y = atoi(word2);

					x = x ? URANGE(0, x, edit->numlines) : 0;
					y = y ? URANGE(0, y, edit->numlines) : edit->numlines;

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

					for ( ; x < y ; x++)
					{
						ch_printf(ch, "%c%2d> %s\n\r", x == edit->on_line ? '*' : ' ', x + 1, edit->line[x] );
					}
					write_to_buffer( ch->desc, prompt, 1000000 );
				}
				break;

			case 'v':
				if (edit->numlines == 0)
				{
					send_to_char( "Buffer is empty.\n\r", ch );
					write_to_buffer( ch->desc, prompt, 1000000 );
				}
				else
				{
					argument = one_argument(argument, word1);
					argument = one_argument(argument, word2);

					x = atoi(word1)-1;
					y = atoi(word2);

					x = x ? URANGE(0, x, edit->numlines) : 0;
					y = y ? URANGE(0, y, edit->numlines) : edit->numlines;

					ch_printf(ch, "------------------\n\r");

					for ( ; x < y ; x++)
					{
						ch_printf(ch, "%s\n\r", edit->line[x]);
					}

					ch_printf(ch, "------------------\n\r");

					write_to_buffer( ch->desc, prompt, 1000000 );
				}
				break;

			case 'a':
				send_to_char( "\n\rAborting...\n\r", ch );
				stop_editing( ch );
				break;

			case 's':
				d->connected = CON_PLAYING;

				if (ch->pcdata->last_cmd)
				{
					(*ch->pcdata->last_cmd) ( ch, "" );
				}
				break;

			default:
				ch_printf(ch, "Unknown command: /%c, /? = help\n\r", cmd[1]);
				write_to_buffer(ch->desc, prompt, 1000000);
				break;
		}
		pop_call();
		return;
	}

	if (strlen(argument) >= max_leng)
	{
		argument[max_leng] = '\0';
	}

	if (edit->size + strlen(argument) >= max_size)
	{
		send_to_char( "Max buffer size reached.\n\r", ch );
		save = TRUE;
	}
	else if (edit->numlines >= max_line)
	{
		send_to_char( "Max buffer length reached.\n\r", ch );
		save = TRUE;
	}
	else
	{
		edit->size += strlen(argument);

		edit->line[edit->on_line] = STRALLOC(argument);

		if (++edit->on_line > edit->numlines)
		{
			edit->numlines++;
		}

		if (edit->numlines >= max_line)
		{
			send_to_char("Max buffer length reached.\n\r", ch );
			save = TRUE;
		}
	}

	if (save)
	{
		d->connected = CON_PLAYING;
		if (ch->pcdata->last_cmd)
		{
			(*ch->pcdata->last_cmd) ( ch, "" );
		}
		pop_call();
		return;
	}

	ch_printf(ch, "%s\n\r", edit->line[edit->on_line-1]);

	write_to_buffer( ch->desc, prompt, 1000000 );
	pop_call();
	return;
}

/*
	The edit stuff
*/
void do_hlist( CHAR_DATA *ch, char *argument )
{
	char buf[MAX_STRING_LENGTH];
	HELP_DATA *help;
	AREA_DATA *pArea;

	push_call("do_hlist(%p,%p)",ch,argument);

	if (argument[0] == '\0')
	{
		pArea = ch->in_room->area;
	}
	else
	{
		pArea = lookup_area(argument);
	}

	if (pArea && !can_olc_modify(ch, pArea->low_r_vnum))
	{
		ch_printf_color(ch, "That area is not in your allocated range.\n\r");
		pop_call();
		return;
	}
	else if (pArea == NULL)
	{
		ch_printf_color(ch, "Syntax: hlist [areaname]\n\r");
		pop_call();
		return;
	}

	for (help = pArea->first_help, buf[0] = '\0' ; help ; help = help->next)
	{
		cat_sprintf(buf, "{178}[{078}%2d{178}] {168}%s\n\r",
			help->level,
			help->keyword);
	}
	send_to_char_color(buf, ch);
	pop_call();
	return;
}


void do_rlist( CHAR_DATA *ch, char *argument )
{
	char buf[MAX_STRING_LENGTH];
	ROOM_INDEX_DATA *pRoomIndex;
	EXIT_DATA *pExit;
	AREA_DATA *pArea;
	int vnum, dir;
	bool rDesc = FALSE;
	bool rLink = FALSE;

	push_call("do_rlist(%p,%p)",ch,argument);

	if (argument[0] == '\0' || (pArea = lookup_area(argument)) == NULL)
	{
		pArea = ch->in_room->area;
	}

	if (!can_olc_modify(ch, pArea->low_r_vnum))
	{
		ch_printf_color(ch, "That area is not in your allocated range.\n\r");
		pop_call();
		return;
	}
	else if (argument[0] != '\0')
	{
		if (!strcasecmp(argument, "nodesc"))
			rDesc = TRUE;
		else if (!strcasecmp(argument, "nolink"))
			rLink = TRUE;
		else
		{
			ch_printf_color(ch, "Syntax: rlist [area name|nodesc|nolink]\n\r");
			pop_call();
			return;
		}
	}

	memset(buf, 0, MAX_STRING_LENGTH);

	for (vnum = pArea->low_r_vnum ; vnum <= pArea->hi_r_vnum ; vnum++)
	{
		if ((pRoomIndex = get_room_index(vnum)) != NULL)
		{
			if (rDesc && is_string(pRoomIndex->description))
				continue;
			if (pRoomIndex->area == pArea)
			{
				if (!rLink)
					cat_sprintf(buf, "{178}[{078}%5u{178}] %s\n\r", pRoomIndex->vnum, pRoomIndex->name);
				else
				{
					for(pExit = NULL, dir = 0 ; dir < 6 ; dir++)
					{
						if ((pExit = pRoomIndex->exit[dir]) != NULL)
						{
							break;
						}
					}
					if (!pExit)
						cat_sprintf(buf, "{178}[{078}%5u{178}] %s\n\r", pRoomIndex->vnum, pRoomIndex->name);
				}
			}
			if (buf[MAX_STRING_LENGTH * 3 / 4] != '\0')
			{
				break;
			}
		}
	}
	if (*buf == '\0')
	{
		if (rDesc)
			send_to_char("There are no rooms without descriptions in this area.\n\r", ch);
		else if (rLink)
			send_to_char("There are no rooms without links in this area.\n\r", ch);
		else
			send_to_char("There are no rooms in this area.\n\r", ch);
		pop_call();
		return;
	}
	send_to_char_color(buf, ch);
	pop_call();
	return;
}


void do_mlist( CHAR_DATA *ch, char *argument )
{
	char buf[MAX_STRING_LENGTH],t1[81];
	MOB_INDEX_DATA *pMobIndex;
	AREA_DATA *pArea;
	int vnum;
	bool fAll;
	FILE *mobFile;

	push_call("do_mlist(%p,%p)",ch,argument);

	mobFile = NULL;

	if (argument[0] == '\0')
	{
		pArea = ch->in_room->area;
	}
	else
	{
		pArea = lookup_area(argument);
	}

	if (pArea && !can_olc_modify(ch, pArea->low_r_vnum))
	{
		ch_printf_color(ch, "That area is not in your allocated range.\n\r");
		pop_call();
		return;
	}
	else if (pArea == NULL)
	{
		if (!IS_GOD(ch))
		{
			ch_printf_color(ch, "Syntax: mlist [areaname]\n\r");
			pop_call();
			return;
		}
		else if (strcasecmp(argument, "all"))
		{
			ch_printf_color(ch, "Syntax: mlist [areaname|all]\n\r");
			pop_call();
			return;
		}
	}

	fAll = (!pArea && !strcasecmp(argument, "all"));

	if (fAll)
	{
		close_reserve();
		mobFile = my_fopen("mlist.all", "wt", FALSE);
	}

	for (buf[0] = '\0', vnum = 0 ; vnum < MAX_VNUM ; vnum++)
	{
		if ((pMobIndex = get_mob_index(vnum)) != NULL)
		{
			if (!fAll && pMobIndex->area == pArea)
			{
				cat_sprintf(buf, "{200}[{078}%5u{200}] ({078}%3d{200}) {178}%-36s {200}lvl {078}%3d\n\r",
					pMobIndex->vnum,
					pMobIndex->total_mobiles,
					str_resize(pMobIndex->short_descr, t1, -36),
					pMobIndex->level);
			}
			else if (fAll)
			{
				sprintf(buf, "[%5u] %-40s %3d\n",
					pMobIndex->vnum,
					str_resize(capitalize(pMobIndex->player_name), t1, -40),
					pMobIndex->level);
				fprintf(mobFile, "%s", buf);
			}
		}
	}
	if (fAll)
	{
		my_fclose(mobFile);
		open_reserve();
		send_to_char("Written to file: mlist.all\n\r",ch);
		pop_call();
		return;
	}
	send_to_char_color(buf, ch);
	pop_call();
	return;
}


void do_olist( CHAR_DATA *ch, char *argument )
{
	char buf        [MAX_STRING_LENGTH];
	char buf2       [MAX_STRING_LENGTH];
	char wearlocBuf [MAX_STRING_LENGTH];
	char itemtypeBuf[MAX_STRING_LENGTH];
	char t1[81], t2[81];

	FILE *objFile;
	OBJ_INDEX_DATA *pObjIndex;
	AREA_DATA *pArea, *lArea;

	int vnum, nMatch, level, lRange, hRange;
	bool fAll, fSort, fBrief;

	push_call("do_olist(%p,%p)",ch,argument);

	lArea = NULL;

	if (argument[0] == '\0')
	{
		pArea = ch->in_room->area;
	}
	else
	{
		pArea = lookup_area(argument);
	}

	if (pArea && !can_olc_modify(ch, pArea->low_r_vnum))
	{
		ch_printf_color(ch, "That area is not in your allocated range.\n\r");
		pop_call();
		return;
	}
	else if (pArea == NULL)
	{
		if (!IS_GOD(ch))
		{
			ch_printf_color(ch, "Syntax: olist [areaname]\n\r");
			pop_call();
			return;
		}
		else
		{
			if (strcasecmp(argument, "all")
			&&  strcasecmp(argument, "sort")
			&&  strcasecmp(argument, "brief"))
			{
				ch_printf_color(ch, "Syntax: olist [areaname|all|sort|brief]\n\r");
				pop_call();
				return;
			}
		}
	}

	fAll		= (!pArea && !strcasecmp(argument, "all"));
	fSort	= (!pArea && !strcasecmp(argument, "sort"));
	fBrief	= (!pArea && !strcasecmp(argument, "brief"));

	objFile = NULL;

	if (fAll || fSort || fBrief)
	{
		close_reserve();
		objFile = my_fopen("olist.all", "wt", FALSE );
	}

	nMatch = 0;

	if( !fSort )
	{
		lRange=0;
		hRange=1;
	}
	else
	{
		lRange = 0;
		hRange = 115;
	}

	for (buf2[0] = '\0', level = lRange ; level < hRange ; level++)
	{
		for (vnum = 0, nMatch = 0 ; nMatch < mud->top_obj_index ; vnum++)
		{
			if ((pObjIndex = get_obj_index(vnum)) != NULL)
			{
				nMatch++;
				if ((fSort && level == pObjIndex->level) || fAll || fBrief || pObjIndex->area == pArea)
				{
					/* Add spot for area name	- Chaos 1/17/96	*/

					if(fAll || fBrief)
					{
						if (lArea != pObjIndex->area)
						{
							if (fBrief)
							{
								lArea = pObjIndex->area;
								fprintf(objFile,"\n%s\n\n", lArea->name);
							}
							else
							{
								lArea = pObjIndex->area;
								fprintf(objFile,"\n[%5d] %s\n\n", lArea->low_r_vnum, lArea->name);
							}
						}
					}

					sprintf(t2, "%10s", str_resize(o_types[pObjIndex->item_type],t1,10));
					strcpy(itemtypeBuf,t2);

					if (fBrief || fSort)
					{
						strcpy(wearlocBuf,"");

						if (!IS_SET(pObjIndex->wear_flags, CAN_WEAR_TAKE) && pObjIndex->item_type != ITEM_LIGHT)
						{
							continue;
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_FINGER ) )
						{
							strcpy( wearlocBuf, "Finger->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_NECK ) )
						{
							strcpy( wearlocBuf, "Neck--->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_BODY ) )
						{
							strcpy( wearlocBuf, "Body--->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_HEAD ) )
						{
							strcpy( wearlocBuf, "Head--->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_LEGS ) )
						{
							strcpy( wearlocBuf, "Legs--->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_FEET ) )
						{
							strcpy( wearlocBuf, "Feet--->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_HANDS ) )
						{
							strcpy( wearlocBuf, "Hands-->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_ARMS ) )
						{
							strcpy( wearlocBuf, "Arms--->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_SHIELD ) )
						{
							strcpy( wearlocBuf, "Shield->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_ABOUT ) )
						{
							strcpy( wearlocBuf, "About-->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_WAIST ) )
						{
							strcpy( wearlocBuf, "Waist-->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_WRIST ) )
						{
							strcpy( wearlocBuf, "Wrist-->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_WIELD ) )
						{
							strcpy( wearlocBuf, "Wield-->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_HOLD ) )
						{
							strcpy( wearlocBuf, "Hold--->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_BOTH ) )
						{
							strcpy( wearlocBuf, "Both--->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_BELT ) )
						{
							strcpy( wearlocBuf, "Belt--->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_FLOAT ) )
						{
							strcpy( wearlocBuf, "Float-->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_FACE ) )
						{
							strcpy( wearlocBuf, "Face--->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_EARS ) )
						{
							strcpy( wearlocBuf, "Ears--->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_ANKLE ) )
						{
							strcpy( wearlocBuf, "Ankle-->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_BACK ) )
						{
							strcpy( wearlocBuf, "Back--->");
						}
						else if ( IS_SET( pObjIndex->wear_flags, CAN_WEAR_TAKE ) )
						{
							continue;
						}
						else
						{
							strcpy( wearlocBuf, "Unknown>");
						}
					}
					if (fBrief || fSort)
					{
						sprintf(buf,"%s %s %10s\n",
							wearlocBuf,
							capitalize( str_resize(pObjIndex->short_descr, t1, -50)),
							itemtypeBuf);
					}
					else if (fAll)
					{
						sprintf(buf,"[%5u] %s %10s\n",
							pObjIndex->vnum,
							capitalize(str_resize(pObjIndex->short_descr, t1, -50)),
							itemtypeBuf);
					}
					else
					{
						sprintf(buf,"{200}[{078}%5u{200}] {178}({078}%4d{178}) {174}%-40s {200}lvl {078}%2d\n",
							pObjIndex->vnum,
							pObjIndex->total_objects,
							str_resize(pObjIndex->short_descr, t1, -40),
							pObjIndex->level);
					}

					if (!fAll && !fSort && !fBrief)
					{
						strcat( buf, "\r" );
						cat_sprintf(buf2, buf);
					}
					else
					{
						char dummy[4];
						strcpy(dummy,"%s" ); /* to handle objects with %s in their names */
						fprintf(objFile,buf,dummy,dummy,dummy);
					}
				}
			}
		}
	}
	if (fAll || fSort || fBrief)
	{
		my_fclose(objFile);
		open_reserve();
		send_to_char("Written to file: olist.all\n\r",ch);
	}
	else
	{
		send_to_char_color(buf2, ch);
	}
	pop_call();
	return;
}


void do_slist( CHAR_DATA *ch, char *argument )
{
	char buf[MAX_STRING_LENGTH],t1[81];
	MOB_INDEX_DATA *pMobIndex;
	AREA_DATA *pArea;
	SHOP_DATA *pShop;
	bool fAll;

	push_call("do_mlist(%p,%p)",ch,argument);

	if (argument[0] == '\0')
	{
		pArea = ch->in_room->area;
	}
	else
	{
		pArea = lookup_area(argument);
	}

	if (pArea && !can_olc_modify(ch, pArea->low_r_vnum))
	{
		ch_printf_color(ch, "That area is not in your allocated range.\n\r");
		pop_call();
		return;
	}
	else if (pArea == NULL)
	{
		if (!IS_GOD(ch))
		{
			ch_printf_color(ch, "Syntax: mlist [areaname]\n\r");
			pop_call();
			return;
		}
		else if (strcasecmp(argument, "all"))
		{
			ch_printf_color(ch, "Syntax: mlist [areaname|all]\n\r");
			pop_call();
			return;
		}
	}

	fAll = (!pArea && !strcasecmp(argument, "all"));

	for (buf[0] = '\0', pShop = mud->f_shop ; pShop ; pShop = pShop->next)
	{
		if ((pMobIndex = get_mob_index(pShop->keeper)) == NULL)
			continue;

		if (!fAll && pMobIndex->area != pArea)
			continue;

		cat_sprintf(buf, "{200}[{078}%5u{200}] {178}%-20s {200}hrs: {078}%2d - %2d    {200}buy: {078}%-3d {200}sell: {078}%-3d \n\r",
			pShop->keeper, str_resize(pMobIndex->short_descr, t1, -20), pShop->open_hour, pShop->close_hour, pShop->profit_buy, pShop->profit_sell);
	}
	send_to_char_color(buf, ch);
	pop_call();
	return;
}


void do_inn_list( CHAR_DATA *ch, char *argument )
{
	char buf[MAX_STRING_LENGTH],t1[81];
	MOB_INDEX_DATA *pMobIndex;
	AREA_DATA *pArea;
	INN_DATA *pInn;
	bool fAll;
	int iRoom;

	push_call("do_mlist(%p,%p)",ch,argument);

	if (argument[0] == '\0')
	{
		pArea = ch->in_room->area;
	}
	else
	{
		pArea = lookup_area(argument);
	}

	if (pArea && !can_olc_modify(ch, pArea->low_r_vnum))
	{
		ch_printf_color(ch, "That area is not in your allocated range.\n\r");
		pop_call();
		return;
	}
	else if (pArea == NULL)
	{
		if (!IS_GOD(ch))
		{
			ch_printf_color(ch, "Syntax: edit shop list [areaname]\n\r");
			pop_call();
			return;
		}
		else if (strcasecmp(argument, "all"))
		{
			ch_printf_color(ch, "Syntax: edit shop list [areaname|all]\n\r");
			pop_call();
			return;
		}
	}

	fAll = (!pArea && !strcasecmp(argument, "all"));

	for (buf[0] = '\0', pInn = mud->f_inn ; pInn ; pInn = pInn->next)
	{
		if ((pMobIndex = get_mob_index(pInn->keeper)) == NULL)
			continue;

		if (!fAll && pMobIndex->area != pArea)
			continue;

		cat_sprintf(buf, "{200}[{078}%5u{200}] {178}%-20s",
			pInn->keeper, str_resize(pMobIndex->short_descr, t1, -20));
		for (iRoom = 0 ; iRoom < MAX_INN_ROOMS ; iRoom++)
		{
			if (pInn->room[iRoom] == -1)
				continue;
			cat_sprintf(buf, " {078}%5d-{178}%-4d", pInn->room[iRoom], pInn->rent[iRoom]);
		}
		cat_sprintf(buf, "\n\r");
	}
	send_to_char_color(buf, ch);
	pop_call();
	return;
}


void do_stable_list( CHAR_DATA *ch, char *argument )
{
	char buf[MAX_STRING_LENGTH],t1[81];
	MOB_INDEX_DATA *pMobIndex;
	AREA_DATA *pArea;
	STABLE_DATA *pStable;
	bool fAll;

	push_call("do_mlist(%p,%p)",ch,argument);

	if (argument[0] == '\0')
	{
		pArea = ch->in_room->area;
	}
	else
	{
		pArea = lookup_area(argument);
	}

	if (pArea && !can_olc_modify(ch, pArea->low_r_vnum))
	{
		ch_printf_color(ch, "That area is not in your allocated range.\n\r");
		pop_call();
		return;
	}
	else if (pArea == NULL)
	{
		if (!IS_GOD(ch))
		{
			ch_printf_color(ch, "Syntax: edit shop list [areaname]\n\r");
			pop_call();
			return;
		}
		else if (strcasecmp(argument, "all"))
		{
			ch_printf_color(ch, "Syntax: edit shop list [areaname|all]\n\r");
			pop_call();
			return;
		}
	}

	fAll = (!pArea && !strcasecmp(argument, "all"));

	for (buf[0] = '\0', pStable = mud->f_stable ; pStable ; pStable = pStable->next)
	{
		if ((pMobIndex = get_mob_index(pStable->keeper)) == NULL)
			continue;

		if (!fAll && pMobIndex->area != pArea)
			continue;

		cat_sprintf(buf, "{200}[{078}%5u{200}] {178}%-20s {200}hrs: {078}%2d - %-2d    {200}rent: {078}%-4d\n\r",
			pStable->keeper, str_resize(pMobIndex->short_descr, t1, -20), pStable->open_hour, pStable->close_hour, pStable->rent);
	}
	send_to_char_color(buf, ch);
	pop_call();
	return;
}

/*
 * Major revamp of the function to add default 
 * exit connection with a directional argument, 
 * or specify a range of vnums to create at once - Kregor
 */
void do_rcreate( CHAR_DATA *ch, char *argument )
{
	AREA_DATA *area;
	ROOM_INDEX_DATA *pRoomIndex;
	char arg[MAX_INPUT_LENGTH];
	int vnum, room_lo, room_hi;
	int door = -1;
	bool fMatch = FALSE;

	push_call("do_rcreate(%p,%p)",ch,argument);

	if (!ch->in_room)
	{
		pop_call();
		return;
	}

	argument = one_argument(argument, arg);

	/* without vnum argument, find the lowest open vnum in the area - Kregor */
	if (arg[0] == '\0' || (door = direction_door(arg)) != -1)
	{
		if (can_olc_modify(ch, ch->in_room->vnum))
			vnum = ch->in_room->area->olc_range_lo;
		else
		{
			ch_printf_color(ch, "Syntax: edit room create [vnum|direction] [to vnum|direction]\n\r");
			pop_call();
			return;
		}
		if ((area = get_area_from_vnum(vnum)) == NULL)
		{
			ch_printf_color(ch, "Cannot locate the area to make room in.\n\r");
			pop_call();
			return;
		}

		for ( ; vnum <= area->olc_range_hi ; vnum++)
		{
			if (get_room_index(vnum) == NULL && can_olc_modify(ch, vnum))
			{
				fMatch = TRUE;
				break;
			}
		}
		if (!fMatch)
		{
			ch_printf_color(ch, "Next room index not found.\n\r");
			pop_call();
			return;
		}
		room_lo = room_hi = vnum;
	}
	else
	{
		room_lo = room_hi = atoi(arg);
	}
	
	if (!can_olc_modify(ch, room_lo))
	{
		ch_printf_color(ch, "Vnum: %d is not in your allocated range.\n\r", vnum);
		pop_call();
		return;
	}
	
// 	ch_printf(ch, "Room index chosen will be %d.\n\r", room_lo);
// 	pop_call();
// 	return;
// 
	if (door == -1 && argument[0] != '\0')
	{
		if (is_number(argument))
		{
			room_hi = atoi(argument);
	
			if (!can_olc_modify(ch, room_hi))
			{
				ch_printf_color(ch, "Vnum: %d is not in your allocated range.\n\r", vnum);
				pop_call();
				return;
			}
		}
		else if ((door = direction_door(argument)) == -1)
		{
			ch_printf_color(ch, "%s is not a valid direction.\n\r", argument);
			pop_call();
			return;
		}
	}
	
	/* make sure can add an exit from the room you're in - Kregor */
	if (door != -1 && !can_olc_modify(ch, ch->in_room->vnum))
	{
		ch_printf_color(ch, "The room you are in is out of your allocated range.\n\r");
		pop_call();
		return;
	}
	
	/* make sure a directional argument is valid before making the room */
	if (door != -1)
	{
		if (ch->in_room->exit[door] != NULL)
		{
			ch_printf_color(ch, "There is already an exit in that direction.\n\r", vnum);
			pop_call();
			return;
		}
	}

	for (vnum = room_lo ; vnum <= room_hi ; vnum++ )
	{
		if (get_room_index(vnum) != NULL)
			continue;
		if (!can_olc_modify(ch, vnum))
			continue;

		if ((pRoomIndex = make_room(vnum)) != NULL)
			ch_printf_color(ch, "Room %d added and ready to be connected to %s.\n\r", vnum, pRoomIndex->area->name);
	}
	
	if (!pRoomIndex)
	{
		ch_printf_color(ch, "Your area doesn't seem to have a valid olc vnum range.\n\r");
	}

	if (door != -1)
	{
		set_link(ch->in_room->vnum, door, pRoomIndex->vnum);
		set_link(pRoomIndex->vnum, rev_dir[door], ch->in_room->vnum);
	}
	
	CHECK_AUTOSAVE(pRoomIndex->area);

	pop_call();
	return;
}


void do_rdupe( CHAR_DATA *ch, char *argument )
{
	ROOM_INDEX_DATA	*room;
	char arg[MAX_INPUT_LENGTH];
	int vnum, lo_vnum, hi_vnum;

	push_call("do_rdupe(%p,%p)",ch,argument);

	if (!ch->desc)
	{
		send_to_char( "You have no descriptor.\n\r", ch );
		pop_call();
		return;
	}

	if (!can_olc_modify(ch, ch->in_room->vnum))
	{
		send_to_char("The room you are standing in is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}
	
	argument = one_argument(argument, arg);

	if (!is_number(arg) || (argument[0] != '\0' && !is_number(argument)))
	{
		send_to_char("Syntax: edit room dupe <vnum> [range vnum].\n\r", ch);
		pop_call();
		return;
	}
	
	lo_vnum = atoi(arg);
	
	if (!can_olc_modify(ch, lo_vnum))
	{
		send_to_char("That is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	if (argument[0] != '\0')
	{
		hi_vnum = atoi(argument);

		if (!can_olc_modify(ch, hi_vnum))
		{
			send_to_char("That is not in your allocated range.\n\r", ch);
			pop_call();
			return;
		}
	}
	else
	{
		hi_vnum = lo_vnum;
	}

	for (vnum = lo_vnum ; vnum <= hi_vnum ; vnum++)
	{
		if (vnum == ch->in_room->vnum)
			continue;

		if ((room = get_room_index(vnum)) == NULL)
			if ((room = make_room(vnum)) == NULL)
		continue;
	
		RESTRING(room->name, ch->in_room->name);
		RESTRING(room->description, ch->in_room->description);
		room->sector_type = ch->in_room->sector_type;
		room->room_flags = ch->in_room->room_flags;
		if (is_string(ch->in_room->night_desc))
			RESTRING(room->night_desc, ch->in_room->night_desc);
	
		send_to_char("Room duplicated.\n\r", ch);
	}

	pop_call();
	return;
}

void do_mcreate( CHAR_DATA *ch, char *argument )
{
	MOB_INDEX_DATA *pMobIndex;
	int vnum;

	push_call("do_mcreate(%p,%p)",ch,argument);

	vnum = is_number(argument) ? atoi(argument) : -1;

	if (vnum == -1 || argument[0] == '\0' )
	{
		send_to_char("Usage: mcreate <vnum>\n\r", ch );
		pop_call();
		return;
	}

	if (vnum < 1 || vnum > MAX_VNUM)
	{
		send_to_char( "Vnum out of range.\n\r", ch );
		pop_call();
		return;
	}

	if (!can_olc_modify(ch, vnum))
	{
		send_to_char("Vnum is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	if (get_mob_index(vnum))
	{
		send_to_char( "A mobile with that number already exists.\n\r", ch );
		pop_call();
		return;
	}

	pMobIndex = make_mobile(vnum);

	if (pMobIndex)
	{
		ch_printf_color(ch, "[%d] Mobile Created.\n\r", vnum);
		CHECK_AUTOSAVE(pMobIndex->area);
	}
	else
	{
		send_to_char( "Error, failed to create a new mobile.\n\r", ch );
	}
	pop_call();
	return;
}


void do_ocreate( CHAR_DATA *ch, char *argument )
{
	OBJ_INDEX_DATA      *pObjIndex;
	int                  vnum;

	push_call("do_ocreate(%p,%p)",ch,argument);

	vnum = is_number(argument) ? atoi(argument) : -1;

	if (vnum == -1 || !argument || argument[0] == '\0')
	{
		send_to_char( "Usage:  ocreate <vnum>\n\r", ch );
		pop_call();
		return;
	}

	if (vnum < 1 || vnum > MAX_VNUM)
	{
		send_to_char( "Vnum out of range.\n\r", ch );
		pop_call();
		return;
	}

	if (!can_olc_modify(ch, vnum))
	{
		ch_printf_color(ch, "Vnum is not in your allocated range.\n\r");
		pop_call();
		return;
	}

	if (get_obj_index(vnum))
	{
		send_to_char( "An object with that number already exists.\n\r", ch );
		pop_call();
		return;
	}

	pObjIndex = make_object(vnum);

	if (pObjIndex)
	{
		ch_printf_color(ch, "[%d] Object Created.\n\r", vnum);
		CHECK_AUTOSAVE(pObjIndex->area);
	}
	else
	{
		send_to_char( "Error. Failed to create a new object.\n\r", ch );
	}
	pop_call();
	return;
}


void do_hcreate( CHAR_DATA *ch, char *argument )
{
	HELP_DATA *help;
	AREA_DATA *area;
	char arg[MAX_INPUT_LENGTH];

	push_call("do_hcreate(%p,%p)",ch,argument);

	if (argument[0] == '\0')
	{
		ch_printf_color(ch, "Syntax: edit help create <area name> <helpfile name>\n\r");
		pop_call();
		return;
	}

	argument = one_argument(argument, arg);

	if ((area = lookup_area(arg)) == NULL)
	{
		ch_printf_color(ch, "Area: %s not found.\n\r", arg);
		pop_call();
		return;
	}

	if (!can_olc_modify(ch, area->low_r_vnum))
	{
		send_to_char("That area is not in your allocated vnum range.\n\r", ch);
		pop_call();
		return;
	}

	if (argument[0] == '\0')
	{
		ch_printf_color(ch, "You must enter a helpfile name.\n\r");
		pop_call();
		return;
	}

	if ((help = get_help(ch, argument)) != NULL)
	{
		ch_printf_color(ch, "A help file with that name already exists.\n\r");
		pop_call();
		return;
	}

	help = make_helpfile(capitalize_all(argument), area);

	if (help)
	{
		ch_printf_color(ch, "[%d] Helpfile %s Created.\n\r", help->area->low_r_vnum, help->keyword);
		CHECK_AUTOSAVE(help->area);
	}
	else
	{
		send_to_char( "Error. Failed to create a new helpfile.\n\r", ch );
	}
	pop_call();
	return;
}

void do_screate( CHAR_DATA *ch, char *argument )
{
	MOB_INDEX_DATA *mob;
	CHAR_DATA *mobile;
	int vnum;

	push_call("do_screate(%p,%p)",ch,argument);

	vnum = is_number(argument) ? atoi(argument) : -1;

	if (*argument == '\0')
	{
		send_to_char("Usage: screate <mob vnum>\n\r", ch );
		pop_call();
		return;
	}

	if (vnum == -1)
	{
		if ((mobile = get_char_room(ch, argument)) == NULL)
		{
			send_to_char( "Not a valid mob.\n\r", ch );
			pop_call();
			return;
		}
		vnum = mobile->pIndexData->vnum;
	}
			
	if (vnum < 1 || vnum > MAX_VNUM)
	{
		send_to_char( "Vnum out of range.\n\r", ch );
		pop_call();
		return;
	}

	if (!can_olc_modify(ch, vnum))
	{
		send_to_char("Vnum is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	if ((mob = get_mob_index(vnum)) == NULL)
	{
		send_to_char( "A mobile with that number does not exist.\n\r", ch );
		pop_call();
		return;
	}

	create_shop(mob);

	ch_printf_color(ch, "[%d] Shop created.\n\r", mob->vnum);
	CHECK_AUTOSAVE(mob->area);
	pop_call();
	return;
}

void do_inn_create( CHAR_DATA *ch, char *argument )
{
	MOB_INDEX_DATA *mob;
	CHAR_DATA *mobile;
	int vnum;

	push_call("do_inn_create(%p,%p)",ch,argument);

	vnum = is_number(argument) ? atoi(argument) : -1;

	if (*argument == '\0')
	{
		send_to_char("Usage: edit inn create <mob vnum>\n\r", ch );
		pop_call();
		return;
	}

	if (vnum == -1)
	{
		if ((mobile = get_char_room(ch, argument)) == NULL)
		{
			send_to_char( "Not a valid mob.\n\r", ch );
			pop_call();
			return;
		}
		vnum = mobile->pIndexData->vnum;
	}
			
	if (vnum < 1 || vnum > MAX_VNUM)
	{
		send_to_char( "Vnum out of range.\n\r", ch );
		pop_call();
		return;
	}

	if (!can_olc_modify(ch, vnum))
	{
		send_to_char("Vnum is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	if ((mob = get_mob_index(vnum)) == NULL)
	{
		send_to_char( "A mobile with that number does not exist.\n\r", ch );
		pop_call();
		return;
	}

	create_inn(mob);

	ch_printf_color(ch, "[%d] Inn created.\n\r", mob->vnum);
	CHECK_AUTOSAVE(mob->area);
	pop_call();
	return;
}

void do_stable_create( CHAR_DATA *ch, char *argument )
{
	MOB_INDEX_DATA *mob;
	CHAR_DATA *mobile;
	int vnum;

	push_call("do_stable_create(%p,%p)",ch,argument);

	vnum = is_number(argument) ? atoi(argument) : -1;

	if (*argument == '\0')
	{
		send_to_char("Usage: edit stable create <mob vnum>\n\r", ch );
		pop_call();
		return;
	}

	if (vnum == -1)
	{
		if ((mobile = get_char_room(ch, argument)) == NULL)
		{
			send_to_char( "Not a valid mob.\n\r", ch );
			pop_call();
			return;
		}
		vnum = mobile->pIndexData->vnum;
	}
			
	if (vnum < 1 || vnum > MAX_VNUM)
	{
		send_to_char( "Vnum out of range.\n\r", ch );
		pop_call();
		return;
	}

	if (!can_olc_modify(ch, vnum))
	{
		send_to_char("Vnum is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	if ((mob = get_mob_index(vnum)) == NULL)
	{
		send_to_char( "A mobile with that number does not exist.\n\r", ch );
		pop_call();
		return;
	}

	create_stable(mob);

	ch_printf_color(ch, "[%d] Stable created.\n\r", mob->vnum);
	CHECK_AUTOSAVE(mob->area);
	pop_call();
	return;
}

void do_rdelete( CHAR_DATA *ch, char *argument )
{
	ROOM_INDEX_DATA *room;

	push_call("do_rdelete(%p,%p)",ch,argument);

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

	if ((room = get_room_index(atoi(argument))) == NULL)
	{
		send_to_char("No room has that vnum.\n\r", ch);
		pop_call();
		return;
	}

	if (!can_olc_modify(ch, room->vnum))
	{
		send_to_char("That room is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	if (delete_room(room))
	{
		send_to_char( "Room deleted.\n\r", ch );
	}
	else
	{
		send_to_char( "Room not deleted.\n\r", ch);
	}
	pop_call();
	return;
}


void do_odelete( CHAR_DATA *ch, char *argument )
{
	OBJ_INDEX_DATA *obj;

	push_call("do_odelete(%p,%p)",ch,argument);

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

	if ((obj = get_obj_index(atoi(argument))) == NULL)
	{
		send_to_char("No mobile loaded has that vnum.\n\r", ch);
		pop_call();
		return;
	}

	if (!can_olc_modify(ch, obj->vnum))
	{
		send_to_char("That room is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	delete_obj(obj);

	send_to_char( "Object deleted.\n\r", ch );

	pop_call();
	return;
}


void do_mdelete( CHAR_DATA *ch, char *argument )
{
	MOB_INDEX_DATA *mob;

	push_call("do_mdelete(%p,%p)",ch,argument);

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

	if ((mob = get_mob_index(atoi(argument))) == NULL)
	{
		send_to_char("No mobile loaded has that vnum.\n\r", ch);
		pop_call();
		return;
	}

	if (!can_olc_modify(ch, mob->vnum))
	{
		send_to_char("That mobile is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	delete_mob( mob );

	send_to_char( "Mob deleted.\n\r", ch );
	pop_call();
	return;
}


void do_hdelete( CHAR_DATA *ch, char *argument )
{
	HELP_DATA *help;

	push_call("do_hdelete(%p,%p)",ch,argument);

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

	if ((help = get_help(ch, argument)) == NULL)
	{
		send_to_char("No helpfile has that name.\n\r", ch);
		pop_call();
		return;
	}

	if (!can_olc_modify(ch, help->area->olc_range_lo))
	{
		send_to_char("That helpfile is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	delete_help( help );

	send_to_char( "Helpfile deleted.\n\r", ch );
	pop_call();
	return;
}

void do_sdelete( CHAR_DATA *ch, char *argument )
{
	MOB_INDEX_DATA *mob;
	CHAR_DATA *mobile;

	push_call("do_mdelete(%p,%p)",ch,argument);

	if (argument[0] == '\0' )
	{
		send_to_char( "Syntax: edit shop delete <vnum|target>\n\r", ch );
		pop_call();
		return;
	}

	if ((mob = get_mob_index(atoi(argument))) == NULL)
	{
		if ((mobile = get_char_room(ch, argument)) == NULL || (mob = mobile->pIndexData) == NULL)
		{
			send_to_char("No mobile loaded has that vnum.\n\r", ch);
			pop_call();
			return;
		}
	}

	if (!can_olc_modify(ch, mob->vnum))
	{
		send_to_char("That mobile is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	if (mob->pShop == NULL)
	{
		ch_printf_color(ch, "Mobile %d is not a shop keeper.\n\r", mob->vnum);
		pop_call();
		return;
	}

	delete_shop( mob );

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

void do_inn_delete( CHAR_DATA *ch, char *argument )
{
	MOB_INDEX_DATA *mob;
	CHAR_DATA *mobile;

	push_call("do_mdelete(%p,%p)",ch,argument);

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

	if ((mob = get_mob_index(atoi(argument))) == NULL)
	{
		if ((mobile = get_char_room(ch, argument)) == NULL || (mob = mobile->pIndexData) == NULL)
		{
			send_to_char("No mobile loaded has that vnum.\n\r", ch);
			pop_call();
			return;
		}
	}

	if (!can_olc_modify(ch, mob->vnum))
	{
		send_to_char("That mobile is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	if (mob->pInn == NULL)
	{
		ch_printf_color(ch, "Mobile %d is not a inn keeper.\n\r", mob->vnum);
		pop_call();
		return;
	}

	delete_inn( mob );

	send_to_char( "Inn deleted.\n\r", ch );
	pop_call();
	return;
}


void do_stable_delete( CHAR_DATA *ch, char *argument )
{
	MOB_INDEX_DATA *mob;
	CHAR_DATA *mobile;

	push_call("do_mdelete(%p,%p)",ch,argument);

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

	if ((mob = get_mob_index(atoi(argument))) == NULL)
	{
		if ((mobile = get_char_room(ch, argument)) == NULL || (mob = mobile->pIndexData) == NULL)
		{
			send_to_char("No mobile loaded has that vnum.\n\r", ch);
			pop_call();
			return;
		}
	}

	if (!can_olc_modify(ch, mob->vnum))
	{
		send_to_char("That mobile is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	if (mob->pStable == NULL)
	{
		ch_printf_color(ch, "Mobile %d is not a stable keeper.\n\r", mob->vnum);
		pop_call();
		return;
	}

	delete_stable( mob );

	send_to_char( "Stable deleted.\n\r", ch );
	pop_call();
	return;
}

void break_bits( FILE *fp, lg_int number, char *vector , bool linear)
{
	lg_int bit, cnt;
	bool found;

	push_call("break_bits(%p,%p,%p,%p)",fp,number,vector,linear);

	if (IS_SET(mud->flags, MUD_STRAIGHTNUMBERS))
	{
		fprintf( fp, "%lld" , number);
		pop_call();
		return;
	}

	found	= FALSE;
	bit		= 0;

	if (!linear)
	{
		while (bit <= number && bit >= 0) /* Scandum - 10-09-2002 */
		{
			if (IS_SET(number, bit))
			{
				for (cnt = mud->bitvector_ref[*vector - 'A'] ; *bitvector_table[cnt].name != '\0' ; cnt++)
				{
					if (bit == bitvector_table[cnt].value)
					{
						if (!str_prefix(vector, bitvector_table[cnt].name))
						{
							if (found)
							{
								fprintf( fp, "|" );
							}
							fprintf( fp, "%s", bitvector_table[cnt].name );
							found = TRUE;
							break;
						}
					}
				}
				if (*bitvector_table[cnt].name == '\0')
				{
					log_printf("unknown vector: %s", vector);

					if (found)
					{
						fprintf( fp, "|" );
					}

					fprintf( fp, "%lld", bit );
					found = TRUE;
				}
			}
			if (bit != 0)
			{
				bit *= 2LL;
			}
			else
			{
				bit++;
			}
		}
	}
	else	for (cnt = mud->bitvector_ref[*vector - 'A'] ; *bitvector_table[cnt].name != '\0' ; cnt++)
	{
		if (number == bitvector_table[cnt].value)
		{
			if (!str_prefix(vector, bitvector_table[cnt].name))
			{
				fprintf( fp, "%s", bitvector_table[cnt].name );
				found = TRUE;
				break;
			}
		}
	}
	if (!found)
	{
		fprintf( fp, "%lld", number );
	}
	pop_call();
	return;
}

char fixit[MAX_STRING_LENGTH];

char *fixer_oprog( char *arg)
{
	char *str,*fix;

	push_call("fixer(%p)",arg);

	if (arg == NULL)
	{
		fixit[0] = '\0';
		pop_call();
		return ( fixit );
	}

	for (str = arg, fix = fixit ; *str != '\0' ; str++)
	{
		if (*str != '\r')
		{
			*fix = *str ;
			fix++;
		}
	}
	*fix = '\0';
	pop_call();
	return( fixit );
}

char *fixer_mprog( MPROG_DATA *mprog)
{
	NPC_TOKEN *token;
	int cnt;
	char lbuf[300];

	push_call("fixer_mprog(%p)",mprog);

	fixit[0] = '\0';

	for (token = mprog->first_token ; token ; token = token->next)
	{
		for (cnt = 0 ; cnt < token->level*2 ; cnt++)
		{
			lbuf[cnt] = ' ';
		}
		lbuf[cnt] = '\0';

		switch (token->type)
		{
			case MPTOKEN_SOCIAL:
				cat_sprintf(fixit, "%s%s %s\n", lbuf, (char *) token->function, token->string);
				break;
			case MPTOKEN_COMMAND:
				cat_sprintf(fixit, "%s%s %s\n", lbuf, cmd_table[token->value].name, token->string);
				break;
			case MPTOKEN_IF:
				if (strstr(token->string, "actorhasobjnum"))
				{
					token->string[strlen(token->string) - 1] = 0;
	
					cat_sprintf(fixit, "%sif hasobjnum ($n) == %s\n", lbuf, &token->string[16]);
	
					token->string[strlen(token->string)] = ')';
				}
				else
				{
					cat_sprintf(fixit, "%sif %s\n", lbuf, token->string);
				}
				break;
			case MPTOKEN_OR:
				if (strstr(token->string, "actorhasobjnum"))
				{
					token->string[strlen(token->string) - 1] = 0;

					cat_sprintf(fixit, "%sor hasobjnum ($n) == %s\n", lbuf, &token->string[16]);

					token->string[strlen(token->string)] = ')';
				}
				else
				{
					cat_sprintf(fixit, "%sor %s\n", lbuf, token->string);
				}
				break;
			case MPTOKEN_ELSE:
				cat_sprintf(fixit, "%selse\n", lbuf);
				break;
			case MPTOKEN_ENDIF:
				cat_sprintf(fixit, "%sendif\n", lbuf);
				break;
			case MPTOKEN_BREAK:
				cat_sprintf(fixit, "%sbreak\n", lbuf);
				break;
			case MPTOKEN_SWITCH:
				cat_sprintf(fixit, "%sswitch %s\n", lbuf, token->string);
				break;
			case MPTOKEN_CASE:
				cat_sprintf(fixit, "%scase %s\n", lbuf, token->string);
				break;
			case MPTOKEN_DEFAULT:
				cat_sprintf(fixit, "%sdefault\n", lbuf);
				break;
			case MPTOKEN_ENDSWITCH:
				cat_sprintf(fixit, "%sendswitch\n", lbuf);
				break;
			case MPTOKEN_IFNOT:
				cat_sprintf(fixit, "%sifnot %s\n", lbuf, token->string);
				break;
			case MPTOKEN_ORNOT:
				cat_sprintf(fixit, "%sornot %s\n", lbuf, token->string);
				break;
			default:
				cat_sprintf(fixit, "%sUnknown %s\n", lbuf, token->string);
				break;
		}
	}
	pop_call();
	return( fixit );
}

char *fixer( char *arg)
{
	char *str,*fix;

	push_call("fixer(%p)",arg);

	if (arg == NULL)
	{
		fixit[0] = '\0';
		pop_call();
		return ( fixit );
	}

	for (str = arg, fix = fixit ; *str != '\0' ; str++)
	{
		if (*str != '\r')
		{
			*fix = *str ;
			fix++;
		}
	}
	*fix = '\0';
	pop_call();
	return( fixit );
}

void save_header( FILE *fp, AREA_DATA *area)
{
	int cnt;
	
	push_call("save_header(%p,%p)",fp,area);

	fprintf( fp, "#AREA %s~\n",			area->name);
	fprintf( fp, "#AUTHORS %s~\n",		area->authors);
	fprintf( fp, "#VERSION %d\n",			AREA_VERSION);
	fprintf( fp, "#RANGES %d %d %d %d\n",	area->low_soft_range, area->hi_soft_range, area->low_hard_range, area->hi_hard_range);
	if (area->olc_range_hi != 0)
	{
		fprintf( fp, "#OLC_RANGES %d %d\n",	area->olc_range_lo, area->olc_range_hi);
	}
	else
	{
		fprintf( fp, "#OLC_RANGES %d %d\n",	area->low_r_vnum, area->hi_r_vnum);
	}

	if (*area->resetmsg)
	{
		fprintf( fp, "#RESETMSG %s~\n\n", area->resetmsg );
	}

	if (!IS_SET(area->flags, AFLAG_CONVERTED))
	{
		SET_BIT(area->flags, AFLAG_CONVERTED);
	}
	SET_BIT(area->flags, AFLAG_NEWHELPS);
	
	if (area->flags)
	{
		fprintf( fp, "#FLAGS " );
		break_bits( fp, area->flags, "AFLAG_", FALSE);
		fprintf( fp, "\n");
	}

	if (IS_SET(area->flags, AFLAG_WEATHER))
	{
		fprintf( fp, "#WEATHER %d %d %d %d %d\n", area->weather_info->temp_winter,area->weather_info->temp_summer, area->weather_info->temp_daily, area->weather_info->wet_scale, area->weather_info->wind_scale);
	}

	fprintf( fp, "#JUSTICE\n");
	if (area->courtroom != 0)
	{
		fprintf( fp, "Courtroom %d\n",	area->courtroom);
	}
	if (area->dungeon != 0)
	{
		fprintf( fp, "Dungeon %d\n",	area->dungeon);
	}
	if (area->storeroom != 0)
	{
		fprintf( fp, "Storeroom %d\n",	area->storeroom);
	}
	if (area->judge != 0)
	{
		fprintf( fp, "Judge %d\n",	area->judge);
	}
	if (area->guard != 0)
	{
		fprintf( fp, "Guard %d\n",	area->guard);
	}
	for (cnt = 0 ; cnt < CRIME_MAX ; cnt++)
	{
		if (area->punishment[cnt] != 0)
		{
			fprintf( fp, "Crime " );
			break_bits( fp, cnt, "CRIME_", TRUE);
			fprintf( fp, " ");
			break_bits( fp, area->punishment[cnt], "PUNISHMENT_", TRUE);
			fprintf( fp, "\n");
		}
	}	
	fprintf( fp, "$\n\n");

	pop_call();
	return;
}

void save_rooms( FILE *fp, AREA_DATA *area)
{
	ROOM_INDEX_DATA *room;
	ROOM_TIMER_DATA *rtd;
	MPROG_DATA *mpg;
	int vnum, door;
	char buf[MAX_STRING_LENGTH];
	EXTRA_DESCR_DATA *ed;

	push_call("save_rooms(%p,%p)",fp,area);

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

	for (rtd = mud->f_room_timer ; rtd ; rtd = rtd->next)
	{
		if (rtd->vnum >= area->low_r_vnum && rtd->vnum <= area->hi_r_vnum)
		{
			REMOVE_BIT(room_index[rtd->vnum]->room_flags, rtd->bitvector);
			rtd->duration = 1;
			del_room_timer(rtd->vnum, rtd->type);
		}
	}

	for (vnum = area->low_r_vnum ; vnum <= area->hi_r_vnum ; vnum++)
	{
		if ((room = get_room_index(vnum)) == NULL)
		{
			continue;
		}
		if (IS_SET(room->room_flags, ROOM_RIP)) //make sure we don't accidentally save private sanctums! - Kregor
		{
			continue;
		}
		if (room->vnum >= MAX_VNUM && IS_SET(room->room_flags, ROOM_HASH))
		{
			continue;
		}
		if (room->area != area)
		{
		/*
			log_printf("Found room from area %s while saving %s.", room->area->name, area->name);
		*/
			continue;
		}
		fprintf( fp, "\n#%d\n", vnum );
		fprintf( fp, "%s~\n", fixer(room->name));
		fprintf( fp, "%s~\n", fixer(room->description));
		if (IS_SET(room->room_flags, ROOM_CLANHALL))
		{
			fprintf( fp, "%d ", room->creator_pvnum);
		}
		else
		{
			fprintf( fp, "%d ", 0);
		}
		break_bits( fp, room->room_flags, "ROOM_", FALSE);
		fprintf( fp, " ");
		break_bits( fp, room->sector_type, "SECT_", TRUE);
		fprintf( fp, " 0 0 0\n");
		for (door = 0 ; door < 6 ; door++)
		{
			if (room->exit[door] != NULL)
			{
				if (room->exit[door]->vnum <= 0)
				{
					continue;
				}

				REMOVE_BIT(room->exit[door]->exit_info, EX_BASHED|EX_KNOCKED);
				fprintf( fp, "D" );
				break_bits( fp, door, "DIR_" , TRUE);
				fprintf( fp, "\n~\n");
// 				fprintf( fp, "\n%s~\n", fixer( room->exit[door]->description ));
				if (IS_SET(room->exit[door]->exit_info, EX_ISDOOR))
				{
					fprintf( fp, "%s~\n", fixer(room->exit[door]->keyword) );
				}
				else
				{
					fprintf( fp, "~\n");
				}
				break_bits(fp, room->exit[door]->exit_info, "EX_" , FALSE);
				fprintf( fp, " %d %u %d %d %d\n", room->exit[door]->key, room->exit[door]->vnum, room->exit[door]->exit_size, room->exit[door]->climb_dc, room->exit[door]->fall_dist);
			}
		}

		for (ed = room->first_extradesc ; ed != NULL ; ed = ed->next)
		{
			fprintf( fp, "E\n" );
			fprintf( fp, "%s~\n", fixer(ed->keyword ));
			sprintf(buf, "%s", fixer(ed->description ));
			if (buf[0] == ' ')
			{
				fprintf( fp, "." );
			}
			fprintf( fp, "%s~\n", buf);
		}
		if (room->listen_desc[0] != '\0')
		{
			fprintf( fp, "L\n" );
			fprintf( fp, "%s~\n", fixer(room->listen_desc));
		}
		if (room->night_desc[0] != '\0')
		{
			fprintf( fp, "N\n" );
			fprintf( fp, "%s~\n", fixer(room->night_desc));
		}
		if (room->first_prog)
		{
			for (mpg = room->first_prog ; mpg ; mpg = mpg->next)
			{
				fprintf( fp, ">%s ",	mprog_type_to_name(mpg->type));
				fprintf( fp, "%s~\n",	mpg->arglist);
				fprintf( fp, "%s~\n",	fixer_mprog(mpg));
			}
			fprintf( fp, "|\n");
		}
		fprintf( fp, "S\n");
	}
	fprintf( fp, "\n#0\n" );
	pop_call();
	return;
}

void save_mobiles( FILE *fp, AREA_DATA *area)
{
	MOB_INDEX_DATA *pMobIndex;
	MPROG_DATA *mpg;
	EXTRA_DESCR_DATA *ed;
	AFFECT_DATA *aff;
	int vnum, cnt, sn;
	char buf[MAX_STRING_LENGTH], buf2[200], *pt;

	push_call("save_mobiles(%p,%p)",fp,area);

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

	for (vnum = area->low_m_vnum ; vnum <= area->hi_m_vnum ; vnum++)
	{
		if ((pMobIndex = get_mob_index(vnum)) == NULL)
		{
			continue;
		}
		if (pMobIndex->area != area)
		{
			log_printf("Found mob from area %s while saving %s.", pMobIndex->area->name, area->name);
			continue;
		}
		fprintf( fp, "\n#%d\n", 	vnum 				);
		strcpy( buf, pMobIndex->player_name );
		sprintf( buf2, "m%d", pMobIndex->vnum );
		if ((pt = strstr(buf, buf2)) != NULL)
		{
			*( pt -1 ) = '\0';
		}
		fprintf( fp, "%s~\n", 	fixer( buf ));
		fprintf( fp, "%s~\n", 	fixer(pMobIndex->short_descr)	);
		fprintf( fp, "%s~\n", 	fixer(pMobIndex->long_descr)	);
		fprintf( fp, "%s~\n", 	fixer(pMobIndex->description)	);
		if (pMobIndex->unique)
			fprintf( fp, "U %d ",	pMobIndex->level	);
		else
			fprintf( fp, "S %d ",	pMobIndex->level	);
		break_bits( fp, pMobIndex->class, "CLASS_", TRUE);
		fprintf( fp, " " );
		break_bits( fp, pMobIndex->race, "RACE_", TRUE);
		fprintf( fp, " ");
		break_bits( fp, pMobIndex->sex, "SEX_", TRUE);
		fprintf( fp, " ");
		break_bits( fp, pMobIndex->position, "POS_", TRUE);
		fprintf( fp, " ");
		break_bits( fp, pMobIndex->god, "GOD_", TRUE);
		fprintf( fp, "\n");
		break_bits( fp, pMobIndex->act, "ACT_", FALSE		);
		fprintf( fp, "\n");
		if (pMobIndex->unique)
		{
			break_bits( fp, pMobIndex->affected_by, "AFF_", FALSE	);
			fprintf( fp, "\n");
			fprintf( fp, "%d ",	pMobIndex->nat_armor );
			break_bits( fp, pMobIndex->armor_type, "ARMOR_TYPE_", TRUE);
			fprintf( fp, " \n" );
			fprintf( fp, "d%d+%d %dd%d+%d %d %d %d\n",
				pMobIndex->hitsizedice,pMobIndex->hitplus,
				0,0,0,
				pMobIndex->alignment,pMobIndex->ethos,pMobIndex->gold);
			fprintf( fp, "%d %d %d %d %d %d\n",
				pMobIndex->perm_str, 
				pMobIndex->perm_int, 
				pMobIndex->perm_wis,
				pMobIndex->perm_dex,
				pMobIndex->perm_con,
				pMobIndex->perm_cha);
			if (!pMobIndex->race)
			{
				break_bits( fp, pMobIndex->body_type, "BTYPE_", TRUE);
				fprintf( fp, " ");
				break_bits( fp, pMobIndex->wear_locs, "CAN_WEAR_", FALSE);
				fprintf( fp, " ");
				break_bits( fp, pMobIndex->size, "SIZE_", TRUE);
				fprintf( fp, " ");
				break_bits( fp, pMobIndex->race_type, "RTYPE_", TRUE);
				fprintf( fp, " ");
				break_bits( fp, pMobIndex->rspecs, "RSPEC_", FALSE);
				fprintf( fp, "\n");
				for (cnt = 0 ; cnt < ATTK_MAX ; cnt++)
				{
					if (pMobIndex->attacks[cnt] <= 0)
						continue;
		
					fprintf( fp, "X " );
					break_bits( fp, cnt, "ATTK_", TRUE);
					fprintf( fp, " %d\n", pMobIndex->attacks[cnt] );
				}
			}
			else
			{
				fprintf( fp, "0 0 ");
				break_bits( fp, pMobIndex->size, "SIZE_", TRUE);
				fprintf( fp, " 0 0\n");
			}
			break_bits( fp, pMobIndex->understands, "LANG_", FALSE);		
			fprintf( fp, " ");
			break_bits( fp, pMobIndex->speaks, "LANG_", FALSE);		
			fprintf( fp, " 0 0 0\n");
		}
    for (ed = pMobIndex->first_extradesc ; ed ; ed = ed->next)
		{
			fprintf( fp, "E\n" );
			fprintf( fp, "%s~\n", fixer(ed->keyword ));
			fprintf( fp, "%s~\n", fixer(ed->description ));
		}
		for (aff = pMobIndex->first_affect ; aff ; aff = aff->next)
		{
			fprintf(fp, "A %s %d %s\n", broken_bits(aff->location, "APPLY_", TRUE), aff->modifier, aff->bitvector < 0 ? broken_bits(aff->location, "AFF2_", FALSE) : broken_bits(aff->location, "AFF_", FALSE));
		}
		if (pMobIndex->reset_msg)
		{
			fprintf( fp, "M %s~\n", fixer(pMobIndex->reset_msg));
		}
		for (cnt = 0 ; cnt < MAX_CLASS ; cnt++)
		{
			if (pMobIndex->mclass[cnt] <= 0)
				continue;

			fprintf( fp, "C " );
			break_bits( fp, cnt, "CLASS_", TRUE);
			fprintf( fp, " %d\n", pMobIndex->mclass[cnt] );
		}
		for (cnt = 0 ; cnt < MAX_WEAR ; cnt++)
		{
			if (pMobIndex->load_eq[cnt] <= 0)
				continue;

			fprintf( fp, "O " );
			break_bits( fp, cnt, "WEAR_", TRUE);
			fprintf( fp, " %d\n", pMobIndex->load_eq[cnt] );
		}
		for (sn = 0 ; *skill_table[sn].name != '\0' ; sn++)
		{
			if (pMobIndex->learned[sn] > 0)
			{
				fprintf( fp, "%% %d %s~\n", pMobIndex->learned[sn], skill_table[sn].name );
			}
		}
		if (pMobIndex->first_prog)
		{
			for (mpg = pMobIndex->first_prog ; mpg ; mpg = mpg->next)
			{
				fprintf( fp, ">%s ",	mprog_type_to_name(mpg->type));
				fprintf( fp, "%s~\n",	mpg->arglist);
				fprintf( fp, "%s~\n",	fixer_mprog(mpg));
			}
			fprintf( fp, "|\n");
		}
	}
	fprintf( fp, "\n#0\n" );
	pop_call();
	return;
}

void save_helps( FILE *fp, AREA_DATA *area)
{
	HELP_DATA *help;
	HELP_MENU_DATA *menu;

	push_call("save_helps(%p,%p)",fp,area);

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

	for (help = area->first_help ; help ; help = help->next)
	{
		fprintf(fp,"%d %s~\n", help->level, fixer(help->keyword));
		if (is_string(help->title))
			fprintf(fp,"%s~\n", fixer(help->title));
		else
			fprintf(fp,"%s~\n", fixer(strlower(help->keyword)));
		fprintf(fp, "%s", fixer(help->text));

		for (menu = help->first_menu ; menu ; menu = menu->next)
		{
			fprintf(fp, "{%c}%s\n", menu->option, menu->help->keyword);
		}
		fprintf(fp, "~\n\n");
	}
	fprintf(fp, "0 $~\n");
	pop_call();
	return;
}


void save_objects( FILE *fp, AREA_DATA *area)
{
	OBJ_INDEX_DATA *pObjIndex;
	EXTRA_DESCR_DATA *ed;
	AFFECT_DATA *aff;
	MPROG_DATA *mpg;
	int vnum;
	char buf[MAX_STRING_LENGTH], buf2[200], *pt;

	push_call("save_objects(%p,%p)",fp,area);

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

	for (vnum = area->low_o_vnum ; vnum <= area->hi_o_vnum ; vnum++)
	{
		if ((pObjIndex = get_obj_index(vnum)) == NULL)
		{
			continue;
		}
		if (pObjIndex->area != area)
		{
			log_printf("Found object from area %s while saving %s.", pObjIndex->area->name, area->name);
			continue;
		}
		fprintf( fp, "\n#%d\n", vnum );
		strcpy( buf, pObjIndex->name );
		sprintf( buf2, "i%d", pObjIndex->vnum );
		if ((pt = strstr(buf, buf2)) != NULL)
		{
			*( pt -1 ) = '\0';
		}
		fprintf( fp, "%s~\n", fixer( buf ));
		fprintf( fp, "%s~\n", fixer(pObjIndex->short_descr));
		fprintf( fp, "%s~\n", fixer(pObjIndex->long_descr));
		fprintf( fp, "%s~\n", fixer(pObjIndex->description));
		break_bits( fp, pObjIndex->item_type, "ITEM_TYPE_", TRUE);
		fprintf( fp, "\n");
		break_bits( fp, pObjIndex->extra_flags, "FLAG_", FALSE);
		fprintf( fp, "\n");
		break_bits( fp, pObjIndex->wear_flags, "CAN_WEAR_", FALSE);
		fprintf( fp, "\n");
		fprintf( fp, "0 ");
		break_bits( fp, pObjIndex->material, "MATERIAL_", TRUE);
		fprintf( fp, " %d ", pObjIndex->hit_points);
		break_bits( fp, pObjIndex->size, "SIZE_", TRUE);
		fprintf( fp, "\n");
		switch (pObjIndex->item_type)
		{
			case ITEM_SYMBOL:
				fprintf(fp, "%d %d ", pObjIndex->value[0], pObjIndex->value[1]);
				break_bits(fp, pObjIndex->value[2], "GOD_", TRUE);
				fprintf(fp, " %d %d %d %d %d", pObjIndex->value[3], pObjIndex->value[4], pObjIndex->value[5], pObjIndex->value[6], pObjIndex->value[7]);
				break;
			case ITEM_SCROLL:
				fprintf( fp, "%d %d ",pObjIndex->value[0], pObjIndex->value[1]);
				break_bits( fp, pObjIndex->value[2], "SCROLL_", TRUE);
				fprintf(fp, " %d %d %d %d %d", pObjIndex->value[3], pObjIndex->value[4], pObjIndex->value[5], pObjIndex->value[6], pObjIndex->value[7]);
				break;
			case ITEM_WEAPON:
				break_bits(fp, pObjIndex->value[0], "WEAPON_TYPE_", TRUE);
				fprintf( fp, " ");
				break_bits(fp, pObjIndex->value[1], "WFLAG_", FALSE);
				fprintf( fp, " ");
				if (IS_SET(pObjIndex->value[1], WFLAG_BANE))
				{
					break_bits(fp, pObjIndex->value[2], "RTYPE_", TRUE);
					fprintf( fp, " ");
					break_bits(fp, pObjIndex->value[3], "RSPEC_", TRUE);
					fprintf( fp, " ");
				}
				else
				{
					fprintf(fp, "%d %d ", pObjIndex->value[2], pObjIndex->value[3]);
				}
				fprintf(fp, "%d %d %d %d", pObjIndex->value[4], pObjIndex->value[5], pObjIndex->value[6], pObjIndex->value[7]);
				break;
			case ITEM_ARMOR:
				break_bits(fp, pObjIndex->value[0], "ARMOR_TYPE_", TRUE);
				fprintf( fp, " ");
				break_bits(fp, pObjIndex->value[1], "ARMORFLAG_", FALSE);
				fprintf(fp, " %d %d ", pObjIndex->value[2], pObjIndex->value[3]);
				break_bits(fp, pObjIndex->value[4], "LAYER_", TRUE);
				fprintf(fp, " %d %d %d",pObjIndex->value[5],pObjIndex->value[6],pObjIndex->value[7]);
				break;
			case ITEM_SPELLPOUCH:
			case ITEM_CONTAINER:
			case ITEM_SHEATH:
			case ITEM_CART:
			case ITEM_QUIVER:
				fprintf(fp, "%d ",pObjIndex->value[0]);
				break_bits( fp, pObjIndex->value[1], "CONT_", FALSE);
				fprintf(fp, " %d %d ",pObjIndex->value[2],pObjIndex->value[3]);
				break_bits(fp, pObjIndex->value[4], "LAYER_", TRUE);
				fprintf(fp, " %d %d %d",pObjIndex->value[5],pObjIndex->value[6],pObjIndex->value[7]);
				break;
			case ITEM_DRINK_CON:
			case ITEM_FOUNTAIN:
				fprintf(fp, "%d %d ", pObjIndex->value[0], pObjIndex->value[1]);
				break_bits(fp, pObjIndex->value[2], "LIQ_", TRUE);
				fprintf(fp, " 0");
				fprintf(fp, " %d %d %d %d", pObjIndex->value[4], pObjIndex->value[5], pObjIndex->value[6], pObjIndex->value[7]);
				break;
			case ITEM_FOOD:
				fprintf(fp, "%d %d %d %d", pObjIndex->value[0], pObjIndex->value[1], pObjIndex->value[2], pObjIndex->value[3]);
				fprintf(fp, " %d %d %d %d", pObjIndex->value[4], pObjIndex->value[5], pObjIndex->value[6], pObjIndex->value[7]);
				break;
			case ITEM_COMPONENT:
				fprintf(fp, "%d %d %d %d", pObjIndex->value[0], pObjIndex->value[1], pObjIndex->value[2], pObjIndex->value[3]);
				fprintf(fp, " %d %d %d %d", pObjIndex->value[4], pObjIndex->value[5], pObjIndex->value[6], pObjIndex->value[7]);
				break;
			case ITEM_PORTAL:
				fprintf(fp, "%d %d ", pObjIndex->value[0], pObjIndex->value[1]);
				break_bits(fp, pObjIndex->value[2], "PORTAL_", FALSE);
				fprintf(fp, " %d", pObjIndex->value[3]);
				fprintf(fp, " %d %d %d %d", pObjIndex->value[4], pObjIndex->value[5], pObjIndex->value[6], pObjIndex->value[7]);
				break;
			case ITEM_FURNITURE:
				fprintf(fp, "%d %d ", pObjIndex->value[0], pObjIndex->value[1]);
				break_bits(fp, pObjIndex->value[2], "FURN_", FALSE);
				fprintf(fp, " %d", pObjIndex->value[3]);
				fprintf(fp, " %d %d %d %d", pObjIndex->value[4], pObjIndex->value[5], pObjIndex->value[6], pObjIndex->value[7]);
				break;
			case ITEM_FIRE:
			case ITEM_LIGHT:
				fprintf(fp, "%d %d %d %d", pObjIndex->value[0], pObjIndex->value[1], pObjIndex->value[2], pObjIndex->value[3]);
				fprintf(fp, " %d %d %d %d", pObjIndex->value[4], pObjIndex->value[5], pObjIndex->value[6], pObjIndex->value[7]);
				break;
			case ITEM_TREASURE:
				break_bits(fp, pObjIndex->value[0], "TFLAG_", FALSE);
				fprintf(fp, " %d %d %d ",  pObjIndex->value[1], pObjIndex->value[2], pObjIndex->value[3]);
				break_bits(fp, pObjIndex->value[4], "LAYER_", TRUE);
				fprintf(fp, " ");
				break_bits(fp, pObjIndex->value[5], "COMP_", TRUE);
				fprintf(fp, " %d %d",pObjIndex->value[6],pObjIndex->value[7]);
				break;
			case ITEM_TRAP:
				break_bits(fp, pObjIndex->value[0], "TRAP_TYPE_", TRUE);
				fprintf( fp, " ");
				break_bits(fp, pObjIndex->value[1], "TRAP_RESET_", FALSE);
				fprintf( fp, " ");
				break_bits(fp, pObjIndex->value[2], "TRAP_TRIG_", FALSE);
				fprintf(fp, " %d ", pObjIndex->value[3]);
				fprintf(fp, " %d %d %d %d",pObjIndex->value[4],pObjIndex->value[5],pObjIndex->value[6],pObjIndex->value[7]);
				break;
			default:
				fprintf(fp, "%d %d %d %d",  pObjIndex->value[0], pObjIndex->value[1], pObjIndex->value[2], pObjIndex->value[3]);
				fprintf(fp, " %d %d %d %d", pObjIndex->value[4], pObjIndex->value[5], pObjIndex->value[6], pObjIndex->value[7]);
				break;
		}
		fprintf( fp, "\n");
		fprintf( fp, "%d %d %d\n",pObjIndex->weight,pObjIndex->cost,pObjIndex->level);

		//fprint new spell loading flags - Kregor
		switch ( pObjIndex->item_type )
		{
			case ITEM_PILL:
				if (is_spell(pObjIndex->value[1]))
					fprintf(fp, "V 1 '%s'\n", skill_table[pObjIndex->value[1]].name);
				if (is_spell(pObjIndex->value[2]))
					fprintf(fp, "V 2 '%s'\n", skill_table[pObjIndex->value[2]].name);
				if (is_spell(pObjIndex->value[3]))
					fprintf(fp, "V 3 '%s'\n", skill_table[pObjIndex->value[3]].name);
				break;
			case ITEM_SCROLL:
			case ITEM_POTION:
				if (is_spell(pObjIndex->value[1]))
					fprintf(fp, "V 1 '%s'\n", skill_table[pObjIndex->value[1]].name);
				break;
			case ITEM_STAFF:
				if (is_spell(pObjIndex->value[3]))
					fprintf(fp, "V 3 '%s'\n", skill_table[pObjIndex->value[3]].name);
				if (is_spell(pObjIndex->value[4]))
					fprintf(fp, "V 4 '%s'\n", skill_table[pObjIndex->value[4]].name);
				if (is_spell(pObjIndex->value[5]))
					fprintf(fp, "V 5 '%s'\n", skill_table[pObjIndex->value[5]].name);
				if (is_spell(pObjIndex->value[6]))
					fprintf(fp, "V 6 '%s'\n", skill_table[pObjIndex->value[6]].name);
				break;
			case ITEM_WAND:
				if (is_spell(pObjIndex->value[3]))
					fprintf(fp, "V 3 '%s'\n", skill_table[pObjIndex->value[3]].name);
				break;
			case ITEM_TOTEM:
				if (is_spell(pObjIndex->value[0]))
					fprintf(fp, "V 0 '%s'\n", skill_table[pObjIndex->value[0]].name);
				if (is_spell(pObjIndex->value[1]))
					fprintf(fp, "V 1 '%s'\n", skill_table[pObjIndex->value[1]].name);
				if (is_spell(pObjIndex->value[2]))
					fprintf(fp, "V 2 '%s'\n", skill_table[pObjIndex->value[2]].name);
				if (is_spell(pObjIndex->value[3]))
					fprintf(fp, "V 3 '%s'\n", skill_table[pObjIndex->value[3]].name);
			case ITEM_TREASURE:
				if (IS_SET(pObjIndex->value[0], TFLAG_SPELL_STORING))
				{
					if (valid_skill(pObjIndex->value[1]))
						fprintf(fp, "V 1 '%s'\n", skill_table[pObjIndex->value[1]].name);
					if (valid_skill(pObjIndex->value[2]))
						fprintf(fp, "V 2 '%s'\n", skill_table[pObjIndex->value[2]].name);
					if (valid_skill(pObjIndex->value[3]))
						fprintf(fp, "V 3 '%s'\n", skill_table[pObjIndex->value[3]].name);
				}
				if (IS_SET(pObjIndex->value[0], TFLAG_COUNTERSPELL))
				{
					if (valid_skill(pObjIndex->value[1]))
						fprintf(fp, "V 1 '%s'\n", skill_table[pObjIndex->value[1]].name);
				}
				if (IS_SET(pObjIndex->value[0], TFLAG_SPELL_RECAST|TFLAG_SPELL_CHARGES))
				{
					if (is_spell(pObjIndex->value[3]))
						fprintf(fp, "V 3 '%s'\n", skill_table[pObjIndex->value[3]].name);
				}
				break;
		}

		for (ed = pObjIndex->first_extradesc ; ed ; ed = ed->next)
		{
			fprintf( fp, "E\n%s~\n%s~\n", ed->keyword, fixer(ed->description));
		}

		for (aff = pObjIndex->first_affect ; aff ; aff = aff->next)
		{
			if (aff->bitvector > 0)
			{
				fprintf(fp, "A %s ", broken_bits(aff->location, "APPLY_", TRUE));
				fprintf(fp, "%d %s\n", aff->modifier, broken_bits(aff->bitvector, "AFF_", FALSE));
			}
			else
			{
				fprintf(fp, "A %s ", broken_bits(aff->location, "APPLY_", TRUE));
				fprintf(fp, "%d %s\n", aff->modifier, broken_bits(aff->bitvector, "AFF2_", FALSE));
			}
		}

		if (pObjIndex->attack_string[0] != '\0' || pObjIndex->class_flags)
		{
			fprintf( fp, "C\n%s~\n%s\n", pObjIndex->attack_string, broken_bits(pObjIndex->class_flags, "FLAG_CLASS_", FALSE));
		}

		if (pObjIndex->id_name[0] != '\0' || pObjIndex->id_descr[0] != '\0' )
		{
			if (pObjIndex->id_name[0] == '\0' || pObjIndex->id_descr[0] == '\0' )
				log_build_printf(pObjIndex->vnum, "ID string MUST include both name and description");
			else
				fprintf( fp, "I\n%s~\n%s~\n", fixer(pObjIndex->id_name), fixer(pObjIndex->id_descr));
		}

		if (pObjIndex->first_prog)
		{
			for (mpg = pObjIndex->first_prog ; mpg ; mpg = mpg->next)
			{
				fprintf( fp, ">%s ",	mprog_type_to_name(mpg->type));
				fprintf( fp, "%s~\n",	mpg->arglist);
				fprintf( fp, "%s~\n",	fixer_mprog(mpg));
			}
			fprintf( fp, "|\n");
		}
	}
	fprintf(fp,"#0\n");
	pop_call();
	return;
}


void save_shops( FILE *fp, AREA_DATA *area)
{
	MOB_INDEX_DATA *mob;
	int vnum, i;
  char tmp[MAX_INPUT_LENGTH];

	push_call("save_shops(%p,%p)",fp,area);

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

	for (vnum = area->low_m_vnum ; vnum <= area->hi_m_vnum ; vnum++)
	{
		if ((mob = get_mob_index(vnum)) == NULL)
		{
			continue;
		}

		if (mob->area != area)
		{
			continue;
		}

		if (mob->pShop == NULL)
		{
			continue;
		}

		fprintf(fp,"\n%d ", mob->pShop->keeper);

		for (i = 0 ; i < MAX_TRADE ; i++)
		{
			break_bits(fp, mob->pShop->buy_type[i], "ITEM_TYPE_", TRUE);
			fprintf(fp, " ");
		}
		break_bits( fp, mob->pShop->shop_flags, "SHOP_", FALSE);
		fprintf(fp,"\n       %3d %3d %2d %2d", mob->pShop->profit_buy, mob->pShop->profit_sell, mob->pShop->open_hour, mob->pShop->close_hour);
    fprintf(fp," ; %s\n",str_resize(fixer(ansi_strip(ansi_translate(mob->short_descr))),tmp,-25));
	}
	fprintf(fp,"0\n");
	pop_call();
	return;
}

void save_inns( FILE *fp, AREA_DATA *area)
{
	MOB_INDEX_DATA *mob;
	int vnum;
  char tmp[MAX_INPUT_LENGTH];
	int i;

	push_call("save_inns(%p,%p)",fp,area);

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

	for (vnum = area->low_m_vnum ; vnum <= area->hi_m_vnum ; vnum++)
	{
		if ((mob = get_mob_index(vnum)) == NULL)
		{
			continue;
		}

		if (mob->area != area)
		{
			continue;
		}

		if (mob->pInn == NULL)
		{
			continue;
		}

		fprintf(fp,"\n%-8d ", mob->pInn->keeper);

		for (i = 0 ; i < MAX_INN_ROOMS ; i++)
		{
			fprintf(fp,"%-8d ", mob->pInn->room[i]);
		}
		fprintf(fp, "\n         ");
		for (i = 0 ; i < MAX_INN_ROOMS ; i++)
		{
			fprintf(fp,"%-8d ", mob->pInn->rent[i]);
		}
		fprintf(fp,"\n       -1 %2d %2d ", mob->pInn->open_hour, mob->pInn->close_hour);
		break_bits( fp, mob->pInn->shop_flags, "SHOP_", FALSE);
    fprintf(fp," ; %s\n",str_resize(fixer(ansi_strip(ansi_translate(mob->short_descr))),tmp,-25));
	}
	fprintf(fp,"0\n");
	pop_call();
	return;
}

void save_stables( FILE *fp, AREA_DATA *area)
{
	MOB_INDEX_DATA *mob;
	int vnum;
  char tmp[MAX_INPUT_LENGTH];

	push_call("save_stables(%p,%p)",fp,area);

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

	for (vnum = area->low_m_vnum ; vnum <= area->hi_m_vnum ; vnum++)
	{
		if ((mob = get_mob_index(vnum)) == NULL)
		{
			continue;
		}

		if (mob->area != area)
		{
			continue;
		}

		if (mob->pStable == NULL)
		{
			continue;
		}

		fprintf(fp,"\n%d %d ", mob->pStable->keeper, mob->pStable->room);
		break_bits( fp, mob->pStable->shop_flags, "SHOP_", FALSE);
		fprintf(fp," %3d %2d %2d", mob->pStable->rent, mob->pStable->open_hour, mob->pStable->close_hour);
    fprintf(fp," ; %s\n",str_resize(fixer(ansi_strip(ansi_translate(mob->short_descr))),tmp,-25));
	}
	fprintf(fp,"0\n");
	pop_call();
	return;
}

void save_resets( FILE *fp, AREA_DATA *area)
{
	RESET_DATA *reset;
  MOB_INDEX_DATA *mob;
  OBJ_INDEX_DATA *obj;
  ROOM_INDEX_DATA *room;
  char tmp[MAX_INPUT_LENGTH];

	push_call("save_resets(%p,%p)",fp,area);

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

	for (reset = area->first_reset ; reset ; reset = reset->next)
	{
		switch (reset->command)
		{
			case 'M':
				fprintf(fp, "%c %d %3d %d",
					reset->command,
					reset->arg1,
					100,
					reset->arg3);
        if((mob=get_mob_index(reset->arg1))!=NULL)
          fprintf(fp," ; %s",str_resize(fixer(ansi_strip(ansi_translate(mob->short_descr))),tmp,-25));
        if((room=get_room_index(reset->arg3))!=NULL)
          fprintf(fp," in %s\n",str_resize(fixer(room->name),tmp,-25));
				break;
			case 'O':
				fprintf(fp, "%c %d %3d %d",
					reset->command,
					reset->arg1,
					100,
					reset->arg3);
        if((obj=get_obj_index(reset->arg1))!=NULL)
          fprintf(fp," ; %s",str_resize(fixer(ansi_strip(ansi_translate(obj->short_descr))),tmp,-25));
        if((room=get_room_index(reset->arg3))!=NULL)
          fprintf(fp," in %s\n",str_resize(fixer(room->name),tmp,-25));
				break;
			case 'G':
				fprintf(fp, " %c %d %3d %d",
					reset->command,
					reset->arg1,
					100,
					reset->arg3);
        if((obj=get_obj_index(reset->arg1))!=NULL)
          fprintf(fp," ; carries %s\n", str_resize(fixer(ansi_strip(ansi_translate(obj->short_descr))),tmp,-25));
				break;
			case 'E':
				fprintf(fp, " %c %d %3d %s",
					reset->command,
					reset->arg1,
					100,
					broken_bits(reset->arg3, "WEAR_", TRUE));
        if((obj=get_obj_index(reset->arg1))!=NULL)
          fprintf(fp," ; equip %s\n", str_resize(fixer(ansi_strip(ansi_translate(obj->short_descr))),tmp,-25));
				break;
			case 'P':
				fprintf(fp, " %c %d %3d %d",
					reset->command,
					reset->arg1,
					100,
					reset->arg3);
        if((obj=get_obj_index(reset->arg1))!=NULL)
          fprintf(fp," ; %s",str_resize(fixer(ansi_strip(ansi_translate(obj->short_descr))),tmp,-25));
        if((obj=get_obj_index(reset->arg3))!=NULL)
          fprintf(fp," in %s\n",str_resize(fixer(ansi_strip(ansi_translate(obj->short_descr))),tmp,-25));
				break;
			case 'D':
				fprintf(fp, "%c %d %-9s ",
					reset->command,
					reset->arg1,
					broken_bits(reset->arg2, "DIR_",  TRUE));
				fprintf(fp, "%s",
					broken_bits(reset->arg3, "DOOR_", TRUE));
        if((room=get_room_index(reset->arg1))!=NULL)
          fprintf(fp," ; door in %s\n",str_resize(fixer(room->name),tmp,-25));
				break;
			case 'R':
				fprintf(fp, "%c %d %d %d",
					reset->command,
					reset->arg1,
					reset->arg2,
					reset->arg3);
        if((room=get_room_index(reset->arg1))!=NULL)
          fprintf(fp," ; randomize exits in %s\n", str_resize(fixer(room->name),tmp,-25));
				break;
			default:
				fprintf(fp, "%c %d %d %d\n",
					reset->command,
					reset->arg1,
					reset->arg2,
					reset->arg3);
				break;
		}
	}
	fprintf(fp,"S\n");
	pop_call();
	return;
}

void save_specials( FILE *fp, AREA_DATA *area)
{
	MOB_INDEX_DATA *pMobIndex;
	int vnum;

	push_call("save_specials(%p,%p)",fp,area);

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

	for (vnum = area->low_m_vnum ; vnum <= area->hi_m_vnum ; vnum++)
	{
		if ((pMobIndex = get_mob_index(vnum)) == NULL)
		{
			continue;
		}
		if (pMobIndex->area != area)
		{
			continue;
		}
		if (!pMobIndex->spec_fun)
		{
			continue;
		}
		fprintf(fp,"M %d %s\n", vnum, fixer(spec_name_lookup(pMobIndex->spec_fun)));
	}
	fprintf(fp,"S\n");
	pop_call();
	return;
}


void do_savearea( CHAR_DATA *ch, char *arg)
{
	AREA_DATA *area = NULL;
	bool forreal;
	bool numbers;

	push_call("do_savearea(%p,%p)",ch,arg);

	if (ch == NULL)
	{
		for (area = mud->f_area ; area ; area = area->next)
		{
			if (IS_SET(area->flags, AFLAG_MODIFIED))
			{
				save_area(area, TRUE);
			}
		}
		pop_call();
		return;
	}

	if (IS_NPC(ch))
	{
		log_printf("un authorized savearea");
		dump_stack();
		pop_call();
		return;
	}

	forreal =  strcasecmp(arg, "backup");
	numbers = !strcasecmp(arg, "numbers");

	if (numbers && IS_GOD(ch))
	{
		TOGGLE_BIT(mud->flags, MUD_STRAIGHTNUMBERS);

		if (IS_SET(mud->flags, MUD_STRAIGHTNUMBERS))
		{
			send_to_char("Bitvectors are now saved as numbers.\n\r", ch);
		}
		else
		{
			send_to_char("Bitvectors are now saved as words.\n\r", ch);
		}
		pop_call();
		return;
	}

	if (!strcasecmp(arg, "all"))
	{
		if (IS_GOD(ch))
		{
			for (area = mud->f_area ; area ; area = area->next)
			{
				log_god_printf("%s saving area %s.", ch->name, area->name);
				save_area( area, TRUE );
			}
			send_to_char("Finished.\n\r", ch );
		}
		else
		{
			send_to_char("Only Gods are allowed to do that.\n\r", ch);
		}
		pop_call();
		return;
	}
	else
	{
		if (arg[0] == '\0' || (area = lookup_area(arg)) == NULL)
		{
			area = ch->in_room->area;
		}

		if (!can_olc_modify(ch, area->low_r_vnum))
		{
			send_to_char("You cannot save this area.\n\r", ch);
			pop_call();
			return;
		}
	}

	save_area( area, forreal );

	if (ch != NULL)
	{
		if (!forreal)
		{
			log_god_printf("%s saving (backup format) area %s", ch->name, area->name);
			send_to_char("Area saved (backup format).\n\r", ch);
		}
		else
		{
			log_god_printf("%s saving (normal format) area %s", ch->name, area->name);
			send_to_char("Area saved (normal format).\n\r", ch);
		}
	}
	pop_call();
	return;
}

void save_area( AREA_DATA *area, bool forreal )
{
	char buf[200];
	FILE *fp;

	push_call("save_area(%p,%p)",area,forreal);

	sprintf( buf, "%s.bak", area->filename );

	close_reserve();

	fp = my_fopen(buf, "w", FALSE);

	REMOVE_BIT(area->flags, AFLAG_MODIFIED);

	save_header(	fp, area);
	if (area->first_help)
	{
		save_helps(	fp, area);
	}
	if (area->hi_m_vnum)
	{
		save_mobiles(	fp, area );
	}
	if (area->hi_o_vnum)
	{
		save_objects(	fp, area );
	}
	if (area->hi_r_vnum)
	{
		save_rooms(	fp, area );
		save_shops(	fp, area );
		save_inns(	fp, area );
		save_stables(	fp, area );
	}
	if (area->first_reset)
	{
		save_resets(	fp, area );
		save_specials(	fp, area );
	}

	fprintf( fp, "\n\n#$\n\nXXXXXXXXXX\n#Savearea\n" );

	my_fclose( fp );

	if (is_valid_save(buf, "Savearea"))
	{
		if (forreal)
		{
			remove( area->filename );
			rename(buf,area->filename);
		}
	}

	open_reserve();

	pop_call();
	return;
}

void do_goto( CHAR_DATA *ch, char *argument )
{
	CHAR_DATA *fch, *fch_next;
	CHAR_DATA *mount;
	ROOM_INDEX_DATA *in_room;
	int vnum;

	push_call("do_goto(%p,%p)",ch,argument);

	if (IS_NPC(ch))
	{
		log_printf( "[%d] Mob using goto: %s", ch->pIndexData->vnum, argument);
		pop_call();
		return;
	}

	if (argument[0] == '\0')
	{
		send_to_char( "Goto where?\n\r", ch );
		pop_call();
		return;
	}

	mount = ch->mounting;
	vnum  = atol(argument);

	if (!is_number(argument))
	{
		if ((vnum = find_location(ch, argument)) == -1)
		{
			send_to_char("You cannot find that.\n\r", ch);
			pop_call();
			return;
		}
	}
	else if (get_room_index(vnum) == NULL)
	{
		if (can_olc_modify(ch, vnum))
		{
			do_rcreate(ch, argument);
		}
		else
		{
			send_to_char( "That is out of your assigned vnum range.\n\r", ch );
			pop_call();
			return;
		}
	}
	else if ((vnum = find_location(ch, argument)) == -1)
	{
		send_to_char("You cannot find that.\n\r", ch);
		pop_call();
		return;
	}

	if (!can_olc_modify(ch, vnum))
	{
		send_to_char("That destination is not in your allocated vnum range.\n\r", ch);
		pop_call();
		return;
	}

	if ( room_is_private( room_index[vnum] ) )
	{
		if ( get_trust( ch ) < LEVEL_IMMORTAL )
		{
			send_to_char( "That room is private right now.\n\r", ch );
			pop_call();
			return;
		}
		else
		{
			send_to_char( "Overriding private flag!\n\r", ch );
		}
	}

	in_room = ch->in_room;

	if (in_combat(ch))
	{
		char_from_combat(ch);
	}

	if (!IS_SET(ch->act, PLR_WIZINVIS))
	{
		act( ch->pcdata->bamfout[0] != '\0' ? ch->pcdata->bamfout : "$n leaves in a swirling mist.", ch, NULL, NULL, TO_ROOM);
	}

	ch->regoto = ch->in_room->vnum;
	char_from_room( ch );
	char_to_room( ch, vnum, FALSE );

	if (!IS_SET(ch->act, PLR_WIZINVIS))
	{
		act( ch->pcdata->bamfin[0] != '\0' ? ch->pcdata->bamfin : "$n appears in a swirling mist.", ch, NULL, NULL, TO_ROOM);
	}

	do_look( ch, "auto" );

	ch->mounting = mount;

	if ( ch->in_room == in_room )
	{
		pop_call();
		return;
	}

	for (fch = in_room->first_person ; fch ; fch = fch_next)
	{
		fch_next = fch->next_in_room;

		if (IS_NPC(fch) && fch->master == ch)
		{
			char_from_room (fch);
			char_to_room( fch, vnum, FALSE );
		}
		else if (fch->master == ch && IS_IMMORTAL(fch))
		{
			act( "You follow $N.", fch, NULL, ch, TO_CHAR );
			do_goto( fch, argument );
		}
	}
	pop_call();
	return;
}

void do_regoto( CHAR_DATA *ch, char *argument )
{
	char buf[MAX_STRING_LENGTH];

	push_call("do_regoto(%p,%p)",ch,argument);

	if (!ch->regoto)
	{
		pop_call();
		return;
	}
	sprintf(buf, "%d", ch->regoto);
	do_goto(ch, buf);
	pop_call();
	return;
}

extern int top_area;

void write_area_list( )
{
	AREA_DATA *tarea;
	FILE *fpout;

	push_call("write_area_list()");

// 	log_printf( "writing area.lst not allowed, use shell, aborting." );
// 	dump_stack();
// 
// 	pop_call();
// 	return;
// 
	fpout = my_fopen( AREA_LIST, "w",FALSE );

	if ( !fpout )
	{
		bug( "couldn't open area.lst for writing");
		pop_call();
		return;
	}

	for (tarea = mud->f_area ; tarea ; tarea = tarea->next)
	{
		fprintf( fpout, "%s\n", tarea->filename );
	}

	fprintf( fpout, "$\n" );
	my_fclose( fpout );
	pop_call();
	return;
}

void assign_area( CHAR_DATA *ch )
{
 	char buf1[MAX_STRING_LENGTH];
	char buf2[MAX_STRING_LENGTH];
	char taf[1024];
	AREA_DATA *pArea = NULL, *temp_area;

	push_call("assign_area(%p)",ch);

	if (ch->level >= LEVEL_IMMORTAL && ch->pcdata->a_range_lo && ch->pcdata->a_range_hi)
	{
		sprintf( taf, "newareas/%s.are", ch->name);

		log_printf( "Creating area entry for %s", ch->name );

		sprintf(buf1, "%s's Area", ch->name);
		sprintf(buf2, "%s", ch->name);

		ALLOCMEM( pArea, AREA_DATA, 1 );

		pArea->first_reset				= NULL;
		pArea->last_reset				= NULL;
		pArea->name         			= STRALLOC(buf1);
		pArea->filename				= STRALLOC(taf);
		pArea->authors					= STRALLOC(buf2);
		pArea->age					= 0;
		pArea->nplayer					= 0;
		pArea->flags					= AFLAG_MODIFIED;
		pArea->resetmsg				= STRDUPE(str_empty);
		ALLOCMEM(pArea->weather_info, WEATHER_DATA, 1);
		pArea->weather_info->temp_winter	= -10;
		pArea->weather_info->temp_summer	=  20;
		pArea->weather_info->temp_daily	=  10;
		pArea->weather_info->wet_scale	=   4;
		pArea->weather_info->wind_scale	=   4;
		pArea->olc_range_lo				= ch->pcdata->a_range_lo;
		pArea->olc_range_hi				= ch->pcdata->a_range_hi;
		pArea->low_r_vnum				= ch->pcdata->a_range_lo;
		pArea->low_m_vnum				= ch->pcdata->a_range_lo;
		pArea->low_o_vnum				= ch->pcdata->a_range_lo;
		pArea->hi_r_vnum				= ch->pcdata->a_range_hi;
		pArea->hi_m_vnum				= ch->pcdata->a_range_hi;
		pArea->hi_o_vnum				= ch->pcdata->a_range_hi;

		for (temp_area = mud->f_area ; temp_area ; temp_area = temp_area->next)
		{
			if (strcmp(pArea->name, temp_area->name) < 0)
			{
				INSERT_LEFT(pArea, temp_area, mud->f_area, next, prev);
				break;
			}
		}
		if (!temp_area)
		{
			LINK(pArea, mud->f_area, mud->l_area, next, prev);
		}
		mud->top_area++;
	}
	write_area_list();
	
	pop_call();
	return;
}

void do_medit( CHAR_DATA *ch, char *argument )
{
	char strg [MAX_INPUT_LENGTH];
	char arg2 [MAX_INPUT_LENGTH];
	char arg3 [MAX_INPUT_LENGTH];
	char buf  [MAX_STRING_LENGTH];
	char buf1 [MAX_STRING_LENGTH];
	char buf2	[MAX_STRING_LENGTH];
	int  value, cnt, col, vnum;

	EXTRA_DESCR_DATA *ed;
	MOB_INDEX_DATA *mob;
	AFFECT_DATA *aff;
	CHAR_DATA *mobile;

	char *origarg = argument;

	char colw[10], colg[10], colW[10];

	push_call("do_medit(%p,%p)",ch,argument);

	CHECK_EDITMODE( ch );

	strcpy(colw, get_color_string(ch, COLOR_TEXT, VT102_DIM));
	strcpy(colg, get_color_string(ch, COLOR_ACCENT, VT102_DIM));
	strcpy(colW, get_color_string(ch, COLOR_TEXT, VT102_BOLD));

	if (!ch->desc)
	{
		send_to_char( "You have no descriptor\n\r", ch );
		pop_call();
		return;
	}

	if (ch->pcdata->edit_ptr && (mob = ch->pcdata->edit_ptr)->area == NULL)
	{
		ch_printf_color(ch, "The mob you were editing is no longer valid.\n\r");
		stop_olc_editing(ch, ch->in_room->area);
		pop_call();
		return;
	}

	switch (ch->pcdata->editmode)
	{
		case MODE_MOB_DESC:
			mob = ch->pcdata->edit_ptr;

			STRFREE(mob->description);
			mob->description = copy_buffer(ch);
			stop_editing(ch);
			do_medit(ch, "stat");
			pop_call();
			return;

		case MODE_MOB_EXTRA:
			ed  = ch->pcdata->temp_ptr;

			STRFREE( ed->description );
			ed->description = copy_buffer( ch );
			stop_editing( ch );
			do_medit(ch, "stat");
			pop_call();
			return;
	}

	smash_tilde( argument );

	if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		mob = ch->pcdata->edit_ptr;

		if (!strcasecmp(argument, "done"))
		{
			send_to_char( "Medit mode off.\n\r", ch );

			stop_olc_editing(ch, mob->area);

			pop_call();
			return;
		}

		if (!strcmp(argument, ">"))
		{
			for (vnum = mob->vnum + 1 ; vnum <= mob->area->hi_m_vnum ; vnum++)
			{
				if (get_mob_index(vnum) && can_olc_modify(ch, vnum))
				{
					stop_olc_editing(ch, mob->area);
					sprintf(buf, "%d", vnum);
					do_medit(ch, buf);
					do_medit(ch, "stat");
					pop_call();
					return;
				}
			}
			ch_printf_color(ch, "Next index not found.\n\r");
			pop_call();
			return;
		}

		if (!strcmp(argument, "<"))
		{
			for (vnum = mob->vnum - 1 ; vnum >= mob->area->low_m_vnum ; vnum--)
			{
				if (get_mob_index(vnum) && can_olc_modify(ch, vnum))
				{
					stop_olc_editing(ch, mob->area);
					sprintf(buf, "%d", vnum);
					do_medit(ch, buf);
					do_medit(ch, "stat");
					pop_call();
					return;
				}
			}
			ch_printf_color(ch, "Next index not found.\n\r");
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "stat"))
		{
			buf2[0] = '\0';
			cat_sprintf(buf2, "%s  name%s:%s %s\n\r", colg, colw, colW, mob->player_name);
			cat_sprintf(buf2, "%s short%s:%s %s\n\r", colg, colw, colW, mob->short_descr);
			cat_sprintf(buf2, "%s  long%s:%s %s\n\r", colg, colw, colW, mob->long_descr);
			cat_sprintf(buf2, "%s  desc%s:%s \n\r%s", colg, colw, colW, mob->description);
			cat_sprintf(buf2, "%s reset%s:%s %s\n\r", colg, colw, colW, mob->reset_msg);
			cat_sprintf(buf2, "%s    ed%s:%s %s\n\r", colg, colw, colW, get_ed(ch, mob->first_extradesc));
			cat_sprintf(buf2, "%s level%s:%s %-10d", colg, colw, colW, mob->level);
			cat_sprintf(buf2, "%s class%s:%s %-10s", colg, colw, colW, class_types[mob->class]);
			cat_sprintf(buf2, "%s  race%s:%s %-10s", colg, colw, colW, race_table[mob->race].race_name);
			cat_sprintf(buf2, "%s   sex%s:%s %-10s\n\r", colg, colw, colW, sex_types[mob->sex]);
			cat_sprintf(buf2, "%s   pos%s:%s %-10s", colg, colw, colW, p_types[mob->position]);
			cat_sprintf(buf2, "%s   god%s:%s %s\n\r", colg, colw, colW, god_table[mob->god].god_name);
			cat_sprintf(buf2, "%s   act%s:%s %s\n\r", colg, colw, colW, flag_string(mob->act, act_flags));
			cat_sprintf(buf2, "%sunique%s:%s %s\n\r", colg, colw, colW, mob->unique ? "yes" : "no");
			if (!mob->unique)
				cat_sprintf(buf2, "   %s %s\n\r", colw,"(Set mobile to UNIQUE for more customization.)");

			if (mob->unique)
			{
				if (IS_UNCONCERNED(mob) && IS_NEUTRAL(mob))
					sprintf(buf1, "TN");
				else
				{
					if (IS_LAWFUL(mob))
						sprintf(buf1, "L");
					if (IS_CHAOTIC(mob))
						sprintf(buf1, "C");
					if (IS_UNCONCERNED(mob))
						sprintf(buf1, "N");
					if (IS_GOOD(mob))
						strcat(buf1, "G");
					if (IS_NEUTRAL(mob))
						strcat(buf1, "N");
					if (IS_EVIL(mob))
						strcat(buf1, "E");
				}
	
				cat_sprintf(buf2, "%s armor%s:%s %s\n\r", colg, colw, colW, type_string(mob->armor_type, arm_types));
				cat_sprintf(buf2, "%s align%s:%s %-10s", colg, colw, colW, buf1);
				cat_sprintf(buf2, "%s  size%s:%s %-10s", colg, colw, colW, size_types[mob->size]);
				cat_sprintf(buf2, "%s  gold%s:%s %-10d", colg, colw, colW, mob->gold);
				cat_sprintf(buf2, "%shitdie%s:%s %-5d\n\r", colg, colw, colW, mob->hitsizedice);
				cat_sprintf(buf2, "%s  aff1%s:%s %s\n\r", colg, colw, colW, flag_string(mob->affected_by, a_flags));
				cat_sprintf(buf2, "%s  aff2%s:%s %s\n\r", colg, colw, colW, flag_string(mob->affected_by, a2_flags));
				cat_sprintf(buf2, "%sspeaks%s:%s %s\n\r", colg, colw, colW, flag_string(mob->speaks, lang_names));
				cat_sprintf(buf2, "%s langs%s:%s %s\n\r", colg, colw, colW, flag_string(mob->understands, lang_names));
				cat_sprintf(buf2, "%s   str%s:%s %-2d%s    dex%s:%s %-2d%s    con%s:%s %-2d%s    int%s:%s %-2d%s    wis%s:%s %-2d%s    cha%s:%s %-2d\n\r",
					colg, colw, colW, mob->perm_str, colg, colw, colW, mob->perm_dex, colg, colw, colW, mob->perm_con,
					colg, colw, colW, mob->perm_int, colg, colw, colW, mob->perm_wis, colg, colw, colW, mob->perm_cha);
				if (!mob->race)
				{
					cat_sprintf(buf2, "%s natac%s:%s %-2d", colg, colw, colW, mob->nat_armor);
					cat_sprintf(buf2, "%s rtype%s:%s %-15s", colg, colw, colW, type_string(mob->race_type, rtype_flags));
					cat_sprintf(buf2, "%srspecs%s:%s %s\n\r", colg, colw, colW, flag_string(mob->rspecs, race_specs));
					cat_sprintf(buf2, "%s  body%s:%s %-15s", colg, colw, colW, type_string(mob->body_type, body_types));
					cat_sprintf(buf2, "%s  wear%s:%s %s\n\r", colg, colw, colW, flag_string(mob->wear_locs, w_flags));
					cat_sprintf(buf2, "%sattack%s:%s ", colg, colw, colW);
					for (cnt = col = 0 ; cnt < ATTK_MAX ; cnt++)
					{
						if (mob->attacks[cnt])
						{
							cat_sprintf(buf2, "%s %d", attack_part_flags[cnt], mob->attacks[cnt]);
							col++;
						}
						else
							continue;
						if (col % 5 == 0)
							cat_sprintf(buf2, "\n\r        ");
						else
							cat_sprintf(buf2, "  ");
					}	
					if (col % 5 != 0)
						cat_sprintf(buf2, "\n\r");
				}
			}
			cat_sprintf(buf2, "%smclass%s:%s ", colg, colw, colW);
			for (cnt = col = 0 ; cnt < MAX_CLASS ; cnt++)
			{
				if (mob->mclass[cnt])
				{
					cat_sprintf(buf2, "%s %d", class_types[cnt], mob->mclass[cnt]);
					col++;
				}
				else
					continue;
				if (col % 5 == 0)
					cat_sprintf(buf2, "\n\r        ");
				else
					cat_sprintf(buf2, "  ");
			}
			if (col % 5 != 0)
				cat_sprintf(buf2, "\n\r");
			cat_sprintf(buf2, "%s  spec%s:%s %s\n\r", colg, colw, colW, mob->spec_fun != NULL ? spec_name_lookup(mob->spec_fun) : "none");
			cat_sprintf(buf2, "%s skill%s:%s ", colg, colw, colW);
			for (cnt = col = 0 ; *skill_table[cnt].name != '\0' ; cnt++)
			{
				if (mob->learned[cnt])
				{
					cat_sprintf(buf2, "%s %d", skill_table[cnt].name, mob->learned[cnt]);
					col++;
				}
				else
					continue;
				if (col % 5 == 0)
					cat_sprintf(buf2, "\n\r        ");
				else
					cat_sprintf(buf2, "  ");
			}
			cat_sprintf(buf2, "\n\r");
			for (value = 0, aff = mob->first_affect ; aff ; aff = aff->next)
			{
				cat_sprintf(buf2, "%saffect%s:%s %d%s %4d %s %s\n\r", colg, colw, colg, ++value, colW, aff->modifier, a_types[aff->location], aff->bitvector > 0 ? flag_string(aff->bitvector, oa_flags1) : flag_string(aff->bitvector * -1, oa_flags2));
			}
			if (value == 0)
			{
				cat_sprintf(buf2, "%saffect%s:%s %d%s %s\n\r", colg, colw, colg, ++value, colW, "no affect set");
			}
			bool Equipped = FALSE;
			for (cnt = 0 ; cnt < MAX_WEAR ; cnt++)
			{
				if (mob->load_eq[cnt] && obj_index[mob->load_eq[cnt]] != NULL)
				{
					cat_sprintf(buf2, "%s equip%s:%s %s - (%d) %s\n\r", colg, colw, colW, wear_locs[cnt], mob->load_eq[cnt], obj_index[mob->load_eq[cnt]]->name);
					Equipped = TRUE;
				}
			}	
			if (!Equipped)
				cat_sprintf(buf2, "%s equip%s:%s <wear location> <vnum>\n\r", colg, colw, colW);
			cat_sprintf(buf2, "Syntax: <field> <value>                        < %sprev next %s>\n\r", colg, colW);
			send_to_char_color(buf2, ch);
			pop_call();
			return;
		}
	}
	else
	{
		if ((mob = get_mob_index(atoi(argument))) == NULL)
		{
			if ((mobile = get_char_room(ch, argument)) == NULL || (mob = mobile->pIndexData) == NULL)
			{
				send_to_char("Syntax: edit mob <mobile vnum>\n\r", ch);
				pop_call();
				return;
			}
		}
		else if (!can_olc_modify(ch, mob->vnum))
		{
			send_to_char("That vnum is not in your allocated range.\n\r", ch);
			pop_call();
			return;
		}

		ch->pcdata->edit_ptr = mob;
		ch->pcdata->edittype = EDIT_TYPE_MOB;

		ch->pcdata->editmode = MODE_REPEATCMD;

		if (ch->pcdata)
		{
			if (ch->pcdata->subprompt)
			{
				STRFREE(ch->pcdata->subprompt);
			}
			sprintf( buf, "Editing Mobile Vnum: %d", mob->vnum );
			ch->pcdata->subprompt = STRALLOC( buf );
		}
		do_medit(ch, "stat");
		pop_call();
		return;
	}

	argument = one_argument(argument, arg2);
	strcpy(strg, argument);
	argument = one_argument(argument, arg3);

	value = is_number(arg3) ? atoi(arg3) : -1;

	if (!strcasecmp(arg2, "unique"))
	{
		if (*arg3 == '\0' || (strcasecmp(arg3, "yes") && strcasecmp(arg3, "no")))
		{
			ch_printf_color(ch, "Syntax: unique <yes or no>\n\r");
			pop_call();
			return;
		}
		mob->unique = !strcasecmp(arg3, "yes") ? TRUE : FALSE;
	}

	else if (!strcasecmp(arg2, "sex"))
	{
		if ((value = get_flag(arg3, sex_types)) == -1)
		{
			ch_printf_color(ch, "Syntax: sex <%s>\n\r", give_flags(sex_types));
			pop_call();
			return;
		}
		mob->sex = value;
	}

	else if (!strcasecmp(arg2, "size"))
	{
		if ((value = get_flag(arg3, size_types)) == -1)
		{
			ch_printf_color(ch, "Syntax: size <%s>\n\r", give_flags(size_types));
			pop_call();
			return;
		}
		mob->size = value;
	}

	else if (!strcasecmp(arg2, "race"))
	{
		if (!strcasecmp(arg3, "none"))
		{
			mob->race = RACE_NONE;
			mob->hitsizedice = 8;
		}
		else if ((value = lookup_race(arg3)) == -1)
		{
			ch_printf_color(ch, "%s is not a valid race.\n\r", arg3);
			pop_call();
			return;
		}
		else
		{
			mob->race = value;
			mob->size = race_table[value].size;
			mob->level = UMAX(1, race_table[value].hit_dice);
			if (mob->class == CLASS_MONSTER)
				mob->hitsizedice = race_type_table[race_table[value].type].hit_die;
			mob->hitplus = 0;
			mob->perm_str = 10 + race_table[value].race_mod[0];
			mob->perm_dex = 10 + race_table[value].race_mod[1];
			mob->perm_con = 10 + race_table[value].race_mod[2];
			mob->perm_int = 10 + race_table[value].race_mod[3];
			mob->perm_wis = 10 + race_table[value].race_mod[4];
			mob->perm_cha = 10 + race_table[value].race_mod[5];
			mob->alignment	= race_table[value].alignment;
			mob->ethos			= race_table[value].ethos;
		}
	}

	else if (!strcasecmp(arg2, "rtype"))
	{
		if (!strcasecmp(arg3, "none"))
		{
			mob->race_type = RTYPE_NONE;
			mob->hitsizedice = 8;
		}
		else if ((value = get_flag(arg3, rtype_flags)) == -1)
		{
			ch_printf_color(ch, "%s is not a valid race type.\n\r", arg3);
			pop_call();
			return;
		}
		else
		{
			mob->race_type = value;
			if (mob->class == CLASS_MONSTER)
				mob->hitsizedice = race_type_table[mob->race_type].hit_die;
		}
	}

	else if ( !strcasecmp( arg2, "rspecs" ) )
	{
		if (*arg3 == '\0')
		{
			ch_printf_color(ch, "Syntax: rspecs <%s>\n\r", give_flags(race_specs));
			pop_call();
			return;
		}
		if ((value = get_flag(arg3, race_specs)) == -1)
		{
			ch_printf_color(ch, "%s is not a valid race spec.\n\r", arg3);
		}
		else
		{
			TOGGLE_BIT(mob->rspecs, 1LL << value);
		}
		while (*argument != '\0')
		{
			argument = one_argument(argument, arg3);

			if ((value = get_flag(arg3, race_specs)) == -1)
			{
				ch_printf_color(ch, "%s is not a valid race spec.\n\r", arg3);
			}
			else
			{
				TOGGLE_BIT(mob->rspecs, 1LL << value);
			}
		}
	}

	else if (!strcasecmp(arg2, "body"))
	{
		if ((value = get_flag(arg3, body_types)) == -1)
		{
			ch_printf_color(ch, "%s is not a valid body type.\n\r", arg3);
			pop_call();
			return;
		}
		else
		{
			mob->body_type = value;
			mob->wear_locs = body_wear_locs[value];
		}
	}

	else if (!strcasecmp(arg2, "attack"))
	{
		if ((value = get_flag(arg3, attack_part_flags)) == -1)
		{
			sprintf(buf, "Syntax: attack <%s>", give_flags(attack_part_flags));
			ch_printf_color(ch, "%s\n\r", justify(buf, get_page_width(ch)));
			pop_call();
			return;
		}
		else if (!is_number(argument))
		{
			ch_printf_color(ch, "Syntax: attack <part> <number>\n\r");
			pop_call();
			return;
		}
		else
		{
			mob->attacks[value] = atol(argument);
		}
	}

	else if (!strcasecmp(arg2, "class"))
	{
		if (!strcasecmp(arg3, "monster"))
		{
			mob->class 		 = CLASS_MONSTER;
			mob->hitnodice = mob->level;
			if (mob->race == RACE_NONE)
				mob->hitsizedice = 8;
			else
				mob->hitsizedice = race_type_table[race_table[mob->race].type].hit_die;
			for (cnt = 0 ; cnt < MAX_CLASS ; cnt++)
			{
				mob->mclass[cnt] = 0;
			}
			mob->mclass[CLASS_MONSTER] = mob->level;
		}
		else if ((value = get_flag(arg3, class_types)) == -1)
		{
			sprintf(buf, "Syntax: class <%s>", give_flags(class_types));
			ch_printf_color(ch, "%s\n\r", justify(buf, get_page_width(ch)));
			pop_call();
			return;
		}
		else
		{
			mob->class = value;
			mob->mclass[mob->class] = mob->level;
			mob->hitnodice   = mob->level;
			mob->hitsizedice = class_table[mob->class].hp_max;
			mob->hitplus     = 0;
		}
	}

	else if (!strcasecmp(arg2, "mclass"))
	{
		if ((value = get_flag(arg3, class_types)) == -1)
		{
			sprintf(buf, "Syntax: mclass <%s>", give_flags(class_types));
			ch_printf_color(ch, "%s\n\r", justify(buf, get_page_width(ch)));
			pop_call();
			return;
		}
		else if (!is_number(argument))
		{
			ch_printf_color(ch, "Syntax: mclass <'class'> <level>\n\r");
			pop_call();
			return;
		}
		else
		{
			mob->mclass[value] = atol(argument);
			mob->hitsizedice = class_table[mob->class].hp_max;
		}
	}

	else if (!strcasecmp(arg2, "skill"))
	{
		if ((value = skill_lookup(arg3)) == -1 || !is_number(argument))
		{
			ch_printf_color(ch, "Syntax: skill <'skill name'> <rank>\n\r");
			pop_call();
			return;
		}
		else
		{
			mob->learned[value] = atol(argument);
		}
	}

	else if (!strcasecmp(arg2, "armor"))
	{
		if ((value = get_flag(arg3, arm_types)) == -1)
		{
			ch_printf_color(ch, "That is not a valid armor type.\n\r");
			pop_call();
			return;
		}
		else
		{
			mob->armor_type = value;
		}
	}

	else if (!strcasecmp(arg2, "god"))
	{
		if ((value = lookup_god(arg3)) == -1)
		{
			ch_printf_color(ch, "That is not a valid god.\n\r");
			pop_call();
			return;
		}
		else
		{
			mob->god = value;
		}
	}

	else if ( !strcasecmp( arg2, "str" ) )
	{
		if ( value < 0 || value > 45 )
		{
			ch_printf_color( ch, "Stat range is 0 to 45.\n\r");
			pop_call();
			return;
		}
		mob->perm_str = value;
	}

	else if ( !strcasecmp( arg2, "int" ) )
	{
		if ( value < 0 || value > 45 )
		{
			ch_printf_color( ch, "Stat range is 0 to 45.\n\r");
			pop_call();
			return;
		}
		mob->perm_int = value;
	}

	else if ( !strcasecmp( arg2, "wis" ) )
	{
		if ( value < 0 || value > 45 )
		{
			ch_printf_color( ch, "Stat range is 0 to 45.\n\r");
			pop_call();
			return;
		}
		mob->perm_wis = value;
	}

	else if ( !strcasecmp( arg2, "dex" ) )
	{
		if ( value < 0 || value > 45 )
		{
			ch_printf_color( ch, "Stat range is 0 to 45.\n\r");
			pop_call();
			return;
		}
		mob->perm_dex = value;
	}

	else if ( !strcasecmp( arg2, "con" ) )
	{
		if ( value < 0 || value > 45 )
		{
			ch_printf_color( ch, "Stat range is 0 to 45.\n\r");
			pop_call();
			return;
		}
		mob->perm_con = value;
	}

	else if ( !strcasecmp( arg2, "cha" ) )
	{
		if ( value < 0 || value > 45 )
		{
			ch_printf_color( ch, "Stat range is 0 to 45.\n\r");
			pop_call();
			return;
		}
		mob->perm_cha = value;
	}

	else if ( !strcasecmp( arg2, "level" ) )
	{
		if ( value < 0 || value > 99 )
		{
			ch_printf_color( ch, "Level range is 0 to 99.\n\r");
			pop_call();
			return;
		}
		mob->level = value;
		mob->hitnodice   = value;
	}

	else if ( !strcasecmp( arg2, "gold" ) )
	{
		if (value < 0 || value > 300000)
		{
			ch_printf_color(ch, "Gold range is 0 to 300000.\n\r");
			pop_call();
			return;
		}
		mob->gold = value;
	}

	else if ( !strcasecmp( arg2, "align" ) )
	{
		int align = -1;
		int ethos = -1;

		if (arg3[0] == '\0')
		{
			send_to_char( "Syntax: align <tn|lg|ng|cg|ln|cn|le|ne|ce>\n\r", ch );
			pop_call();
			return;
		}
		switch (arg3[0])
		{
			case 't':
				align = 0;
				ethos = 0;
				break;
			case 'l':
				ethos = 1000;
				if (arg3[1] == 'n')
					align = 0;
				else if (arg3[1] == 'g')
					align = 1000;
				else if (arg3[1] == 'e')
					align = -1000;
				break;
			case 'c':
				ethos = -1000;
				if (arg3[1] == 'n')
					align = 0;
				else if (arg3[1] == 'g')
					align = 1000;
				else if (arg3[1] == 'e')
					align = -1000;
				break;
			case 'n':
				ethos = 0;
				if (arg3[1] == 'n')
					align = 0;
				else if (arg3[1] == 'g')
					align = 1000;
				else if (arg3[1] == 'e')
					align = -1000;
				break;
		}
		if (ethos == -1 || align == -1)
		{
			send_to_char( "Sntax: align <tn|lg|ng|cg|ln|cn|le|ne|ce>\n\r", ch );
			pop_call();
			return;
		}
		mob->alignment = align;
		mob->ethos = ethos;
	}

	else if (!strcasecmp(arg2, "name"))
	{
		cat_sprintf(strg, " m%d", mob->vnum);
		STRFREE(mob->player_name);
		mob->player_name = STRALLOC(lower_all(strg));
	}

	else if (!strcasecmp(arg2, "short"))
	{
		STRFREE(mob->short_descr );
		mob->short_descr = STRALLOC(strg);
	}

	else if (!strcasecmp( arg2, "long"))
	{
		STRFREE( mob->long_descr );
		mob->long_descr = STRALLOC(capitalize(strg));
	}

	else if (!strcasecmp( arg2, "reset"))
	{
		STRFREE( mob->reset_msg );
		mob->reset_msg = STRALLOC(capitalize(strg));
	}

	else if (!strcasecmp(arg2, "desc"))
	{
		ch->pcdata->editmode = MODE_MOB_DESC;
		ch->pcdata->tempmode  = MODE_REPEATCMD;
		start_editing(ch, mob->description);
		pop_call();
		return;
	}

	else if (!strcasecmp(arg2, "ed"))
	{
		if (strg[0] == '\0')
		{
			ch_printf_color(ch, "Syntax: ed <keywords>\n\r");
			pop_call();
			return;
		}
		ed            = set_ed_mob(mob, strg);
		ch->pcdata->tempmode   = MODE_REPEATCMD;
		ch->pcdata->editmode  = MODE_MOB_EXTRA;
		ch->pcdata->temp_ptr = ed;

		start_editing(ch, ed->description);
		pop_call();
		return;
	}

	else if (!strcasecmp(arg2, "rmed"))
	{
		if (*arg3 == '\0')
		{
			ch_printf_color(ch, "Syntax: rmed <keyword>\n\r");
			pop_call();
			return;
		}

		if (!del_ed_mob(mob, arg3))
		{
			ch_printf_color(ch, "Keyword: %s not found.\n\r", arg3);
			pop_call();
			return;
		}
	}

	else if ( !strcasecmp( arg2, "spec" ) )
	{
		if ( !strcasecmp( arg3, "none" ) )
		{
			mob->spec_fun = 0;
		}
		else if (spec_lookup(arg3) == 0)
		{
			send_to_char( "No such spec fun.\n\r", ch );
			pop_call();
			return;
		}
		mob->spec_fun = spec_lookup(arg3);
	}

	else if ( !strcasecmp( arg2, "act" ) )
	{
		if (*arg3 == '\0')
		{
			ch_printf_color(ch, "Syntax: act <%s>\n\r", give_flags(act_flags));
			pop_call();
			return;
		}
		if ((value = get_flag(arg3, act_flags)) == -1)
		{
			ch_printf_color(ch, "%s is not a valid ACT flag.\n\r", arg3);
		}
		else
		{
			TOGGLE_BIT(mob->act, 1LL << value);
		}
		while (*argument != '\0')
		{
			argument = one_argument(argument, arg3);

			if ((value = get_flag(arg3, act_flags)) == -1)
			{
				ch_printf_color(ch, "%s is not a valid ACT flag.\n\r", arg3);
			}
			else
			{
				TOGGLE_BIT(mob->act, 1LL << value);
			}
		}
	}

	else if ( !strcasecmp( arg2, "aff1" ) )
	{
		if (*arg3 == '\0')
		{
			ch_printf_color(ch, "Syntax: affect <%s>\n\r", give_flags(a_flags));
			pop_call();
			return;
		}
		if ((value = get_flag(arg3, a_flags)) == -1)
		{
			ch_printf_color(ch, "%s is not a valid affect flag.\n\r", arg3);
		}
		else
		{
			TOGGLE_BIT(mob->affected_by, 1LL << value);
		}
		while (*argument != '\0')
		{
			argument = one_argument(argument, arg3);

			if ((value = get_flag(arg3, a_flags)) == -1)
			{
				ch_printf_color(ch, "%s is not a valid affect flag.\n\r", arg3);
			}
			else
			{
				TOGGLE_BIT(mob->affected_by, 1LL << value);
			}
		}
	}

	else if ( !strcasecmp( arg2, "aff2" ) )
	{
		if (*arg3 == '\0')
		{
			ch_printf_color(ch, "Syntax: affect <%s>\n\r", give_flags(a2_flags));
			pop_call();
			return;
		}
		if ((value = get_flag(arg3, a2_flags)) == -1)
		{
			ch_printf_color(ch, "%s is not a valid affect flag.\n\r", arg3);
		}
		else
		{
			TOGGLE_BIT(mob->affected2_by, 1LL << value * -1);
		}
		while (*argument != '\0')
		{
			argument = one_argument(argument, arg3);

			if ((value = get_flag(arg3, a2_flags)) == -1)
			{
				ch_printf_color(ch, "%s is not a valid affect flag.\n\r", arg3);
			}
			else
			{
				TOGGLE_BIT(mob->affected2_by, 1LL << value * -1);
			}
		}
	}

	else if (!strcasecmp(arg2, "affect"))
	{
		lg_int type;

		if (arg3[0] == '\0' || atoi(arg3) < 1 || atoi(arg3) > 3)
		{
			ch_printf_color(ch, "Syntax: affect <1|2|3> <del|apply|mod|aff1|aff2> <argument>\n\r");
			pop_call();
			return;
		}
		value = atoi(arg3);
		argument = one_argument(argument, arg3);

		if (arg3[0] == '\0')
		{
			ch_printf_color(ch, "Syntax: affect <%d> <apply|mod|spell1|spell2> <argument>\n\r", value);
			pop_call();
			return;
		}

		if (!strcasecmp(arg3, "del"))
		{
			set_mob_affect(mob, value, -1, -2, -1);
		}

		if (!strcasecmp(arg3, "apply"))
		{
			if ((type = get_flag(argument, a_types)) == -1)
			{
				ch_printf_color(ch, "Syntax: affect <%d> apply <%s>\n\r", value, give_flags(a_types));
				pop_call();
				return;
			}
			set_mob_affect(mob, value, -1, type, -1);
		}

		if (!strcasecmp(arg3, "aff1"))
		{
			if ((type = get_flag(argument, oa_flags1)) == -1)
			{
				ch_printf_color(ch, "Syntax: affect <%d> spell1 <%s>\n\r", value, give_flags(oa_flags1));
				pop_call();
				return;
			}
			set_mob_affect(mob, value, -1, -1, 1LL << type);
		}

		if (!strcasecmp(arg3, "aff2"))
		{
			if ((type = get_flag(argument, oa_flags2)) == -1)
			{
				ch_printf_color(ch, "Syntax: affect <%d> spell1 <%s>\n\r", value, give_flags(oa_flags2));
				pop_call();
				return;
			}
			set_mob_affect(mob, value, -1, -1, (1LL << type) * -1);
		}
		if (!strcasecmp(arg3, "mod"))
		{
			set_mob_affect(mob, value, atol(argument), -1, -1);
		}
	}

	else if ( !strcasecmp( arg2, "pos" ) )
	{
		if ((value = get_flag(arg3, p_types)) == -1)
		{
			sprintf(buf, "Syntax: pos <%s>", give_flags(p_types));
			ch_printf_color(ch, "%s\n\r", justify(buf, get_page_width(ch)));
			pop_call();
			return;
		}
		mob->position = value;
	}

	else if ( !strcasecmp( arg2, "langs" ) )
	{
		if (*arg3 == '\0')
		{
			ch_printf_color(ch, "Syntax: langs <%s>\n\r", give_flags(lang_names));
			pop_call();
			return;
		}
		if ((value = get_flag(arg3, lang_names)) == -1)
		{
			ch_printf_color(ch, "%s is not a valid language.\n\r", arg3);
		}
		else
		{
			TOGGLE_BIT(mob->understands, 1LL << value);
		}
		while (*argument != '\0')
		{
			argument = one_argument(argument, arg3);

			if ((value = get_flag(arg3, lang_names)) == -1)
			{
				ch_printf_color(ch, "%s is not a valid language.\n\r", arg3);
			}
			else
			{
				TOGGLE_BIT(mob->understands, 1LL << value);
			}
		}
	}

	else if ( !strcasecmp( arg2, "speaks" ) )
	{
		if ((value = get_flag(arg3, lang_names)) == -1)
		{
			ch_printf_color(ch, "Syntax: speaks <%s>\n\r", give_flags(lang_names));
			pop_call();
			return;
		}
		mob->speaks = 1LL << value;
	}

	else if ( !strcasecmp( arg2, "wear" ) )
	{
		if (*arg3 == '\0')
		{
			ch_printf_color(ch, "Syntax: wear <%s>\n\r", give_flags(w_flags));
			pop_call();
			return;
		}
		else if (!strcasecmp(arg3, "none"))
		{
			mob->wear_locs = 0;
		}
		else if ((value = get_flag(arg3, w_flags)) == -1)
		{
			ch_printf_color(ch, "%s is not a valid wear location.\n\r", arg3);
		}
		else
		{
			TOGGLE_BIT(mob->wear_locs, 1LL << value);
		}
		while (*argument != '\0')
		{
			argument = one_argument(argument, arg3);

			if ((value = get_flag(arg3, w_flags)) == -1)
			{
				ch_printf_color(ch, "%s is not a valid body part.\n\r", arg3);
			}
			else
			{
				TOGGLE_BIT(mob->wear_locs, 1LL << value);
			}
		}
	}

	else if (!strcasecmp(arg2, "hitdie"))
	{
		if (value == -1)
		{
			ch_printf_color(ch, "Value must be a number.\n\r");
			pop_call();
			return;
		}

		switch (value)
		{
			case 3:
			case 4:
			case 6:
			case 8:
			case 10:
			case 12:
				break;
			default:
				ch_printf_color(ch, "Hit dice must 3, 4, 6, 8, 10 or 12 sided.\n\r");
				pop_call();
				return;
		}

		mob->hitnodice   = mob->level;
		mob->hitsizedice = value;
		mob->hitplus     = 0;
	}

	else if (!strcasecmp(arg2, "equip"))
	{
		if (argument[0] == '\0' || !is_number(argument))
		{
			ch_printf_color(ch, "Syntax: equip <wear_loc> <vnum>\n\r");
			pop_call();
			return;
		}
		if ((value = get_flag(arg3, wear_locs)) == -1)
		{
			sprintf(buf, "wear_locs: <%s>", give_flags(wear_locs));
			ch_printf_color(ch, "%s\n\r", justify(buf, get_page_width(ch)));
			pop_call();
			return;
		}
		if (*argument == '\0' || !strcasecmp(argument, "none"))
		{
			mob->load_eq[value] = 0;
		}
		else
		{
			if (obj_index[atol(argument)] == NULL)
			{
				ch_printf_color(ch, "%s - not a valid object!\n\r", argument);
				pop_call();
				return;
			}
			mob->load_eq[value] = atol(argument);
		}
	}

	else if ( ch->pcdata->editmode == MODE_REPEATCMD )
	{
		ch->pcdata->editmode = MODE_RESTRICTED;
		interpret( ch, origarg );
		ch->pcdata->editmode = MODE_REPEATCMD;
		ch->pcdata->last_cmd = do_edit;
		pop_call();
		return;
	}

	do_medit( ch, "stat" );
	pop_call();
	return;
}

void do_oedit( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	char buf[MAX_STRING_LENGTH];
	char buf2[MAX_STRING_LENGTH];

	OBJ_INDEX_DATA *obj;
	EXTRA_DESCR_DATA *ed;
	AFFECT_DATA *aff;

	char *origarg = argument;

	int value, vnum, sn;

	char colw[10], colg[10], colW[10], colM[10];

	push_call("do_oedit(%p,%p)",ch,argument);

	CHECK_EDITMODE( ch );

	strcpy(colw, get_color_string(ch, COLOR_TEXT, VT102_DIM));
	strcpy(colg, get_color_string(ch, COLOR_ACCENT, VT102_DIM));
	strcpy(colW, get_color_string(ch, COLOR_TEXT, VT102_BOLD));
	strcpy(colM, ansi_translate_text(ch, "{158}"));

	if (!ch->desc)
	{
		send_to_char( "You have no descriptor\n\r", ch );
		pop_call();
		return;
	}

	if (ch->pcdata->edit_ptr && (obj = ch->pcdata->edit_ptr)->area == NULL)
	{
		ch_printf_color(ch, "The object you were editing is no longer valid.\n\r");
		stop_olc_editing(ch, ch->in_room->area);
		pop_call();
		return;
	}

	switch(ch->pcdata->editmode)
	{
		case MODE_OBJ_DESC:
			obj = ch->pcdata->edit_ptr;

			STRFREE(obj->description);
			obj->description = copy_buffer(ch);
			stop_editing(ch);
			do_oedit(ch, "stat");
			pop_call();
			return;

		case MODE_OBJ_ID_DESC:
			obj = ch->pcdata->edit_ptr;

			STRFREE(obj->id_descr);
			obj->id_descr = copy_buffer(ch);
			stop_editing(ch);
			do_oedit(ch, "stat");
			pop_call();
			return;

		case MODE_OBJ_EXTRA:
			ed  = ch->pcdata->temp_ptr;

			STRFREE( ed->description );
			ed->description = copy_buffer( ch );
			stop_editing( ch );
			do_oedit(ch, "stat");
			pop_call();
			return;
	}

	smash_tilde( argument );

	if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		obj = ch->pcdata->edit_ptr;

		if (argument[0] == '?')
		{
			/*
				Show oedit status
			*/
			ch_printf_color(ch, "Syntax: <command> <value>\n\r");
			ch_printf_color(ch, "Command being on of:\n\r");
			ch_printf_color(ch, "  type flags wear material hitpts size weight cost affect\n\r");
			ch_printf_color(ch, "  done stat idname iddesc? < >\n\r");
			switch (obj->item_type)
			{
				case ITEM_ARMOR:
					ch_printf_color(ch, "  name short long desc ed rmed armor aflags wearsize\n\r");
					break;
				case ITEM_WEAPON:
					ch_printf_color(ch, "  name short long desc ed rmed weapon wflags dammsg\n\r");
					break;
				case ITEM_SCROLL:
				case ITEM_PILL:
				case ITEM_POTION:
				case ITEM_TOTEM:
					ch_printf_color(ch, "  name short long desc ed rmed level spell\n\r");
					break;
				case ITEM_COMPONENT:
					ch_printf_color(ch, "  name short long desc ed rmed type uses\n\r");
					break;
				case ITEM_WAND:
				case ITEM_STAFF:
					ch_printf_color(ch, "  name short long desc ed rmed level spell charges\n\r");
					break;
				case ITEM_SPELLPOUCH:
				case ITEM_CONTAINER:
				case ITEM_QUIVER:
				case ITEM_CART:
				case ITEM_SHEATH:
					ch_printf_color(ch, "  name short long desc ed rmed carry cflags key max\n\r");
					break;
				case ITEM_LIGHT:
					ch_printf_color(ch, "  name short long desc ed rmed refill light charges ignite\n\r");
					break;
				case ITEM_FIRE:
					ch_printf_color(ch, "  name short long desc ed rmed hours\n\r");
					break;
				case ITEM_FOUNTAIN:
					ch_printf_color(ch, "  name short long desc ed rmed liquid\n\r");
					break;
				case ITEM_DRINK_CON:
					ch_printf_color(ch, "  name short long desc ed rmed liquid charges poison\n\r");
					break;
				case ITEM_FOOD:
					ch_printf_color(ch, "  name short long desc ed rmed fill cooked poison\n\r");
					break;
				case ITEM_MONEY:
					ch_printf_color(ch, "  name short long desc ed rmed gold silver copper\n\r");
					break;
				case ITEM_SYMBOL:
					ch_printf_color(ch, "  name short long desc ed rmed god bonus\n\r");
					break;
				case ITEM_PORTAL:
					ch_printf_color(ch, "  name short long desc ed rmed charges enter toroom\n\r");
					break;
				case ITEM_FURNITURE:
					ch_printf_color(ch, "  name short long desc ed rmed max poses regen\n\r");
					break;
				case ITEM_TOOLS:
					ch_printf_color(ch, "  name short long desc ed rmed type charges bonus\n\r");
					break;
				case ITEM_AMMO:
					ch_printf_color(ch, "  name short long desc ed rmed weapon\n\r");
					break;
				case ITEM_PAPER:
					ch_printf_color(ch, "  name short long desc ed rmed used sealed language dc\n\r");
					break;
				case ITEM_BOOK:
					ch_printf_color(ch, "  name short long desc ed rmed language dc page rmpage\n\r");
					break;
				case ITEM_TRAP:
					ch_printf_color(ch, "  name short long desc ed rmed ttype reset trigger state value\n\r");
					break;
				case ITEM_WINDOW:
					ch_printf_color(ch, "  name short long desc ed rmed viewroom castable\n\r");
					break;
				case ITEM_MAP:
					ch_printf_color(ch, "  name short long desc ed rmed lovnum hivnum\n\r");
					break;
			}
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "done"))
		{
			send_to_char( "Oedit mode off.\n\r", ch );

			stop_olc_editing(ch, obj->area);

			pop_call();
			return;
		}

		if (!strcmp(argument, ">"))
		{
			for (vnum = obj->vnum + 1 ; vnum <= obj->area->hi_o_vnum ; vnum++)
			{
				if (get_obj_index(vnum) && can_olc_modify(ch, vnum))
				{
					stop_olc_editing(ch, obj->area);
					sprintf(buf, "%d", vnum);
					do_oedit(ch, buf);
					pop_call();
					return;
				}
			}
			ch_printf_color(ch, "Next index not found.\n\r");
			pop_call();
			return;
		}

		if (!strcmp(argument, "<"))
		{
			for (vnum = obj->vnum - 1 ; vnum >= obj->area->low_o_vnum ; vnum--)
			{
				if (get_obj_index(vnum) && can_olc_modify(ch, vnum))
				{
					stop_olc_editing(ch, obj->area);
					sprintf(buf, "%d", vnum);
					do_oedit(ch, buf);
					pop_call();
					return;
				}
			}
			ch_printf_color(ch, "Next index not found.\n\r");
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "stat"))
		{
			sprintf(buf2, "%s    name%s:%s %s\n\r", colg, colw, colW, obj->name);
			cat_sprintf(buf2, "%s   short%s:%s %s\n\r", colg, colw, colW, obj->short_descr);
			cat_sprintf(buf2, "%s    long%s:%s %s\n\r", colg, colw, colW, obj->long_descr);
			cat_sprintf(buf2, "%s    desc%s:%s \n\r%s", colg, colw, colW, obj->description);
			cat_sprintf(buf2, "%s      ed%s:%s %s\n\r", colg, colw, colW, get_ed(ch, obj->first_extradesc));
			cat_sprintf(buf2, "%s  idname%s:%s %s\n\r", colg, colw, colW, !is_string(obj->id_name) ? "(None)" : obj->id_name);
			cat_sprintf(buf2, "%s  iddesc%s:%s %s\n\r", colg, colw, colW, !is_string(obj->id_descr) ? "(None)" : obj->id_descr);
			cat_sprintf(buf2, "%s    type%s:%s %s\n\r", colg, colw, colW, type_string(obj->item_type, o_types));
			cat_sprintf(buf2, "%s   flags%s:%s %s\n\r", colg, colw, colW, flag_string(obj->extra_flags, o_flags));
			cat_sprintf(buf2, "%s    wear%s:%s %s\n\r", colg, colw, colW, flag_string(obj->wear_flags, w_flags));
			cat_sprintf(buf2, "%smaterial%s:%s %-15s", colg, colw, colW, type_string(obj->material, material_types));
// 			cat_sprintf(buf2, "%s  hitpts%s:%s %d\n\r", colg, colw, colW, obj->hit_points);
			cat_sprintf(buf2, "%s    size%s:%s %-15s\n\r", colg, colw, colW, size_types[obj->size]);
			cat_sprintf(buf2, "%s    cost%s:%s %-15d", colg, colw, colW, obj->cost);
			cat_sprintf(buf2, "%s  weight%s:%s %-15d", colg, colw, colW, obj->weight);
			cat_sprintf(buf2, "%s   level%s:%s %-15d\n\r", colg, colw, colW, obj->level);
			cat_sprintf(buf2, "%s   class%s:%s %s\n\r", colg, colw, colW, flag_string(obj->class_flags, class_types));
			switch (obj->item_type)
			{
				case ITEM_ARMOR:
					cat_sprintf(buf2, "%s   armor%s:%s %s\n\r", colg, colw, colW, type_string(obj->value[0], arm_types));
					cat_sprintf(buf2, "           %s (AC plus:%s %d, %smax DEX bonus:%s %d, %sarmor check:%s %d, %sspell fail:%s %d%\n\r",
						colw, colW, armor_table[obj->value[0]].ac_bonus, colw, colW, armor_table[obj->value[0]].dex_max,
						colw, colW,armor_table[obj->value[0]].armor_check, colw, colW, armor_table[obj->value[0]].spell_fail);
					cat_sprintf(buf2, "%s  aflags%s:%s %s\n\r", colg, colw, colW, flag_string(obj->value[1], armor_flags));
					cat_sprintf(buf2, "%swearsize%s:%s %s\n\r", colg, colw, colW, size_types[obj->value[3]]);
					cat_sprintf(buf2, "%s   layer%s:%s %d\n\r", colg, colw, colW, obj->value[4]);
					break;
				case ITEM_WEAPON:
				case ITEM_AMMO:
					cat_sprintf(buf2, "%s  weapon%s:%s %s\n\r", colg, colw, colW, type_string(obj->value[0], weap_types));
					cat_sprintf(buf2, "             %s (dmg:%s %dd%d, %sthreat range:%s %d, %scrit x:%s %d, %srange:%s %d%)\n\r",
						colw, colW, weapon_table[obj->value[0]].damnodice, weapon_table[obj->value[0]].damsizedice,
						colw, colW, weapon_table[obj->value[0]].threat, colw, colW, weapon_table[obj->value[0]].critical,
						colw, colW, weapon_table[obj->value[0]].range);
					cat_sprintf(buf2, "%s  wflags%s:%s %s\n\r", colg, colw, colW, flag_string(obj->value[1], weapon_flags));
					if (IS_SET(obj->value[1], WFLAG_SPELL_STORING))
						cat_sprintf(buf2, "%s   spell%s:%s lvl %d %s\n\r", colg, colw, colW, obj->value[3], skill_table[URANGE(0, obj->value[2], MAX_REAL_SKILL)].name);
					if (IS_SET(obj->value[1], WFLAG_BANE|WFLAG_SLAYING))
					{
						cat_sprintf(buf2, "%sracetype%s:%s %s\n\r", colg, colw, colW, type_string(obj->value[2], rtype_flags));
						cat_sprintf(buf2, "%s subtype%s:%s %s\n\r", colg, colw, colW, flag_string(obj->value[3], race_specs));
					}
					if (obj->item_type == ITEM_WEAPON)
						cat_sprintf(buf2, "%s  dammsg%s:%s %s\n\r", colg, colw, colW, obj->attack_string[0] == '\0' ? "none" : obj->attack_string);
					break;
				case ITEM_SCROLL:
				case ITEM_PILL:
				case ITEM_POTION:
					cat_sprintf(buf2, "%s   spell%s:%s lvl %d %s%s,%s %s%s,%s %s\n\r", colg, colw, colW, obj->value[0],
						skill_name(obj->value[1]), colw, colW,
						skill_name(obj->value[2]), colw, colW,
						skill_name(obj->value[3]));
					if (obj->item_type == ITEM_SCROLL)
						cat_sprintf(buf2, "%s   class%s:%s %s\n\r", colg, colw, colW, type_string(obj->value[2], scroll_types));
					break;
				case ITEM_WAND:
				case ITEM_STAFF:
					cat_sprintf(buf2, "%s   spell%s:%s lvl %d %s\n\r", colg, colw, colW, obj->value[0], skill_table[URANGE(0, obj->value[3], MAX_REAL_SKILL)].name);
					cat_sprintf(buf2, "%s charges%s:%s %d%s/%s%d\n\r", colg, colw, colW,
						obj->value[1], colw, colW, obj->value[2]);
					break;
				case ITEM_TOTEM:
					cat_sprintf(buf2, "%s   spell%s:%s %s%s,%s %s%s,%s %s%s,%s %s\n\r", colg, colw, colW,
						skill_name(obj->value[0]), colw, colW,
						skill_name(obj->value[1]), colw, colW,
						skill_name(obj->value[2]), colw, colW,
						skill_name(obj->value[3]));
					break;
				case ITEM_SPELLBOOK:
					for (sn = 0 ; *skill_table[sn].name != '\0' ; sn++)
					{
						if (obj->scribed[sn])
							cat_sprintf(buf2, "%s scribed%s:%s\n\r", colg, colw, colW, skill_table[sn].name);
					}
					break;
				case ITEM_CONTAINER:
				case ITEM_SHEATH:
				case ITEM_CART:
				case ITEM_QUIVER:
					cat_sprintf(buf2, "%s   carry%s:%s %d\n\r", colg, colw, colW, obj->value[0]);
					cat_sprintf(buf2, "%sconflags%s:%s %s\n\r", colg, colw, colW, flag_string(obj->value[1], cont_flags));
					cat_sprintf(buf2, "%s     key%s:%s %d\n\r", colg, colw, colW, obj->value[2]);
					cat_sprintf(buf2, "%s     max%s;%s %d\n\r", colg, colw, colW, obj->value[3]);
					cat_sprintf(buf2, "%s   layer%s:%s %d\n\r", colg, colw, colW, obj->value[4]);
					break;
				case ITEM_COMPONENT:
					cat_sprintf(buf2, "%s    type%s:%s %s\n\r", colg, colw, colW, component_flags[obj->value[0]]);
					cat_sprintf(buf2, "%s    uses%s:%s %d\n\r", colg, colw, colW, obj->value[1]);
					break;
				case ITEM_WINDOW:
					cat_sprintf(buf2, "%sviewroom%s:%s %d (%s)\n\r", colg, colw, colW, obj->value[0], room_index[obj->value[0]] != NULL ? room_index[obj->value[0]]->name : "BUG! NULL scried room");
					cat_sprintf(buf2, "%scastable%s:%s %s\n\r", colg, colw, colW, obj->value[1] ? "true" : "false");
					break;
				case ITEM_LIGHT:
					cat_sprintf(buf2, "%s   light%s:%s %d (%d foot radius)\n\r", colg, colw, colW, obj->value[0], obj->value[0] * 20 / 50);
					cat_sprintf(buf2, "%s  refill%s:%s %s\n\r", colg, colw, colW, obj->value[1] ? "true" : "false");
					cat_sprintf(buf2, "%s charges%s:%s %d\n\r", colg, colw, colW, obj->value[2]);
					cat_sprintf(buf2, "%s  ignite%s:%s %s\n\r", colg, colw, colW, obj->value[3] ? "true" : "false");
					break;
				case ITEM_FIRE:
					cat_sprintf(buf2, "%s   hours%s:%s %d\n\r", colg, colw, colW, obj->value[2]);
					break;
				case ITEM_SYMBOL:
					cat_sprintf(buf2, "%s   god%s:%s %s\n\r", colg, colw, colW, get_god_name(obj->value[2]));
					cat_sprintf(buf2, "%s bonus%s:%s %d\n\r", colg, colw, colW, obj->value[3]);
					break;
				case ITEM_FOUNTAIN:
					cat_sprintf(buf2, "%s  liquid%s:%s %s\n\r", colg, colw, colW, type_string(obj->value[2], liq_types));
					cat_sprintf(buf2, "%s  poison%s:%s %s\n\r", colg, colw, colW, type_string(obj->value[3], poison_names));
					break;
				case ITEM_DRINK_CON:
					cat_sprintf(buf2, "%s  liquid%s:%s %s\n\r", colg, colw, colW, type_string(obj->value[2], liq_types));
					cat_sprintf(buf2, "%s charges%s:%s %d%s/%s%d\n\r", colg, colw, colW,
						obj->value[0], colw, colW, obj->value[1]);
					cat_sprintf(buf2, "%s  poison%s:%s %s\n\r", colg, colw, colW, type_string(obj->value[3], poison_names));
					break;
				case ITEM_FOOD:
					cat_sprintf(buf2, "%s    fill%s:%s %d\n\r", colg, colw, colW, obj->value[0]);
					cat_sprintf(buf2, "%s  cooked%s:%s %s\n\r", colg, colw, colW, obj->value[2] ? "yes" : "no");
					cat_sprintf(buf2, "%s  poison%s:%s %s\n\r", colg, colw, colW, type_string(obj->value[3], poison_names));
					break;
				case ITEM_PORTAL:
					cat_sprintf(buf2, "%s charges%s:%s %d\n\r", colg, colw, colW, obj->value[0]);
					cat_sprintf(buf2, "%s     key%s:%s %d\n\r", colg, colw, colW, obj->value[1]);
					cat_sprintf(buf2, "%s   enter%s:%s %s\n\r", colg, colw, colW, flag_string(obj->value[2], portal_flags));
					cat_sprintf(buf2, "%s  toroom%s:%s %d\n\r", colg, colw, colW, obj->value[3]);
					break;
				case ITEM_FURNITURE:
					cat_sprintf(buf2, "%s   users%s:%s %d\n\r", colg, colw, colW, obj->value[0]);
					cat_sprintf(buf2, "%s   poses%s:%s %s\n\r", colg, colw, colW, flag_string(obj->value[2], f_flags));
					break;
				case ITEM_TOOLS:
					cat_sprintf(buf2, "%s    tool%s:%s %s\n\r", colg, colw, colW, tool_types[obj->value[0]]);
					cat_sprintf(buf2, "%s charges%s:%s %d\n\r", colg, colw, colW, obj->value[1]);
					cat_sprintf(buf2, "%s   bonus%s:%s %d\n\r", colg, colw, colW, obj->value[2]);
					break;
				case ITEM_MONEY:
					cat_sprintf(buf2, "%s    gold%s:%s %d\n\r", colg, colw, colW, obj->value[0]);
					cat_sprintf(buf2, "%s  silver%s:%s %d\n\r", colg, colw, colW, obj->value[1]);
					cat_sprintf(buf2, "%s  copper%s:%s %d\n\r", colg, colw, colW, obj->value[2]);
					break;
				case ITEM_TREASURE:
					cat_sprintf(buf2, "%s  tflags%s:%s %s\n\r", colg, colw, colW, flag_string(obj->value[0], treasure_flags));
					cat_sprintf(buf2, "%s   layer%s:%s %d\n\r", colg, colw, colW, obj->value[4]);
					cat_sprintf(buf2, "%scomptype%s:%s %s\n\r", colg, colw, colW, type_string(obj->value[5], component_flags));
					cat_sprintf(buf2, "%  setting%s:%s %s\n\r", colg, colw, colW, type_string(obj->value[6], material_types));
					break;
				case ITEM_PIECE:
					cat_sprintf(buf2, "%s  piece1%s:%s %d (%-30s)\n\r", colg, colw, colW, obj->value[0], obj_index[obj->value[0]]->short_descr == NULL ? "Unknown" : obj_index[obj->value[0]]->short_descr);
					cat_sprintf(buf2, "%s  piece2%s:%s %d (%-30s)\n\r", colg, colw, colW, obj->value[1], obj_index[obj->value[1]]->short_descr == NULL ? "Unknown" : obj_index[obj->value[1]]->short_descr);
					cat_sprintf(buf2, "%s creates%s:%s %d (%-30s)\n\r", colg, colw, colW, obj->value[2], obj_index[obj->value[2]]->short_descr == NULL ? "Unknown" : obj_index[obj->value[2]]->short_descr);
					cat_sprintf(buf2, "%s   skill%s:%s %s\n\r", colg, colw, colW, is_string(skill_table[obj->value[3]].name) ? skill_table[obj->value[3]].name : "None");
					cat_sprintf(buf2, "%s skilldc%s:%s %d\n\r", colg, colw, colW, obj->value[4]);
					break;
				case ITEM_PAPER:
					cat_sprintf(buf2, "%s written%s:%s %s\n\r", colg, colw, colW, obj->value[1] ? "true" : "false");
					cat_sprintf(buf2, "%s  sealed%s:%s %s\n\r", colg, colw, colW, obj->value[2] ? "true" : "false");
					cat_sprintf(buf2, "%slanguage%s:%s %s\n\r", colg, colw, colW, obj->value[3] == 0 ? "None" : lang_names[UNSHIFT(obj->value[3])]);
					cat_sprintf(buf2, "%s      dc%s:%s %d\n\r", colg, colw, colW, obj->value[4]);
					break;
				case ITEM_BOOK:
					cat_sprintf(buf2, "%snumpages%s:%s %d\n\r", colg, colw, colW, obj->value[1]);
					cat_sprintf(buf2, "%slanguage%s:%s %s\n\r", colg, colw, colW, obj->value[3] == 0 ? "None" : lang_names[UNSHIFT(obj->value[3])]);
					cat_sprintf(buf2, "%s      dc%s:%s %d\n\r", colg, colw, colW, obj->value[4]);
					break;
				case ITEM_MAP:
					cat_sprintf(buf2, "%s  lovnum%s:%s %d\n\r", colg, colw, colW, obj->value[1]);
					cat_sprintf(buf2, "%s  hivnum%s:%s %d\n\r", colg, colw, colW, obj->value[2]);
					break;
				case ITEM_TRAP:
					cat_sprintf(buf2, "%s   ttype%s:%s %s\n\r", colg, colw, colW, obj->value[0] == 0 ? "None" : trap_types[obj->value[0]]);
					cat_sprintf(buf2, "%s   reset%s:%s %s\n\r", colg, colw, colW, trap_types[obj->value[1]]);
					cat_sprintf(buf2, "%s trigger%s:%s %s\n\r", colg, colw, colW, flag_string(obj->value[2], trap_triggers));
					cat_sprintf(buf2, "%s   state%s:%s %s\n\r", colg, colw, colW, trap_state[obj->value[3]]);
					if (obj->value[0] == TRAP_TYPE_POISON)
						cat_sprintf(buf2, "%s   value%s:%s %s\n\r", colg, colw, colW, poison_names[obj->value[4]]);
					else if (obj->value[0] == TRAP_TYPE_SPELL)
						cat_sprintf(buf2, "%s   value%s:%s %s\n\r", colg, colw, colW, skill_table[obj->value[4]].name);
					else
						cat_sprintf(buf2, "%s   value%s:%s %d\n\r", colg, colw, colW, obj->value[4]);
					cat_sprintf(buf2, "%s  dammsg%s:%s %s\n\r", colg, colw, colW, obj->attack_string[0] == '\0' ? "none" : obj->attack_string);
					break;
			}
			cat_sprintf(buf2, "%s  values%s: v0:%s%d%s v1:%s%d%s v2:%s%d%s v3:%s%d%s v4:%s%d%s v5:%s%d%s v6:%s%d%s v7:%s%d\n\r",
				colg, colw, colW, obj->value[0], colw, colW, obj->value[1], colw, colW, obj->value[2], colw, colW, obj->value[3],
				colw, colW, obj->value[4], colw, colW, obj->value[5], colw, colW, obj->value[6], colw, colW, obj->value[7]);
			for (value = 0, aff = obj->first_affect ; aff ; aff = aff->next)
			{
				cat_sprintf(buf2, "%s  affect%s:%s %d%s %4d %s %s\n\r", colg, colw, colM, ++value, colW, aff->modifier, a_types[aff->location], aff->bitvector > 0 ? flag_string(aff->bitvector, oa_flags1) : flag_string(aff->bitvector * -1, oa_flags2));
			}
			if (value == 0)
			{
				cat_sprintf(buf2, "%s  affect%s:%s %d%s %s\n\r", colg, colw, colM, ++value, colW, "no affect set");
			}
			cat_sprintf(buf2, "Syntax: <field> <value>                        < %sprev next %s>\n\r", colg, colW);
			send_to_char_color(buf2, ch);
			pop_call();
			return;
		}
	}
	else if ((obj = get_obj_index(atoi(argument))) == NULL)
	{
		do_ocreate(ch, argument);
		obj = get_obj_index(atoi(argument));
// 		send_to_char("Syntax: edit obj <object vnum>\n\r", ch);
// 		pop_call();
// 		return;
	}
	if (!obj || !can_olc_modify(ch, obj->vnum))
	{
		send_to_char("That vnum is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	if (ch->pcdata->editmode != MODE_REPEATCMD)
	{
		ch->pcdata->edit_ptr = obj;
		ch->pcdata->edittype = EDIT_TYPE_OBJ;

		ch->pcdata->editmode = MODE_REPEATCMD;

		if (ch->pcdata)
		{
			if (ch->pcdata->subprompt)
			{
				STRFREE(ch->pcdata->subprompt);
			}
			sprintf( buf, "Editing Object Vnum: %d", obj->vnum );
			ch->pcdata->subprompt = STRALLOC( buf );
		}
		do_oedit(ch, "stat");
		pop_call();
		return;
	}

	argument = one_argument(argument, arg);
	value = is_number(argument) ? atoi(argument) : -1;
	bool found = FALSE; //have to pass a bool to keep from passing to interp at end of function - Kregor

	if (!strcasecmp(arg, "name"))
	{
		cat_sprintf(argument, " i%d", obj->vnum);
		STRFREE(obj->name );
		obj->name = STRALLOC(lower_all(argument));
		found = TRUE;
	}

	else if (!strcasecmp(arg, "short"))
	{
		STRFREE(obj->short_descr );
		obj->short_descr = STRALLOC(argument);
		//add a default long_desc - Kregor
		strcat(argument, " {300}lies here.");
		STRFREE( obj->long_descr);
		obj->long_descr = STRALLOC(capitalize(argument));
		found = TRUE;
	}

	else if (!strcasecmp(arg, "long"))
	{
		STRFREE( obj->long_descr);
		obj->long_descr = STRALLOC(capitalize(argument));
		found = TRUE;
	}

	else if (!strcasecmp(arg, "desc"))
	{
		ch->pcdata->editmode = MODE_OBJ_DESC;
		ch->pcdata->tempmode  = MODE_REPEATCMD;
		start_editing(ch, obj->description);
		pop_call();
		return;
	}

	else if (!strcasecmp(arg, "idname"))
	{
		STRFREE(obj->id_name);
		obj->id_name = STRALLOC(argument);
		found = TRUE;
	}

	else if (!strcasecmp(arg, "iddesc"))
	{
		ch->pcdata->editmode = MODE_OBJ_ID_DESC;
		ch->pcdata->tempmode  = MODE_REPEATCMD;
		start_editing(ch, obj->id_descr);
		pop_call();
		return;
	}

	else if (!strcasecmp(arg, "ed"))
	{
		if (argument[0] == '\0')
		{
			ch_printf_color(ch, "Syntax: ed <keywords>\n\r");
			pop_call();
			return;
		}
		ed            = set_ed_obj(obj, argument);
		ch->pcdata->tempmode = MODE_REPEATCMD;
		ch->pcdata->editmode = MODE_OBJ_EXTRA;
		ch->pcdata->temp_ptr = ed;

		start_editing(ch, ed->description);
		pop_call();
		return;
	}

	else if (!strcasecmp(arg, "rmed"))
	{
		if (!argument || argument[0] == '\0')
		{
			ch_printf_color(ch, "Syntax: rmed <keyword>\n\r");
			pop_call();
			return;
		}
		else if (!del_ed_obj(obj, argument))
		{
			ch_printf_color(ch, "Keyword: %s not found.\n\r", argument);
			pop_call();
			return;
		}
		found = TRUE;
	}

	else if (!strcasecmp(arg, "type"))
	{
		if ((value = get_flag(argument, o_types)) == -1)
		{
			ch_printf_color(ch, "Syntax: type <%s>\n\r", give_flags(o_types));
			pop_call();
			return;
		}
		obj->item_type = value;
		/* Reset all object type related settings */
		obj->value[0] = obj->value[1] = obj->value[2] = obj->value[3] = obj->value[4] = obj->value[5] = 0;
		RESTRING(obj->attack_string, "");
		fix_materials(obj);
		fix_sizes(obj);
		load_obj_hit(obj);
		found = TRUE;
	}

	else if (!strcasecmp( arg, "flags" ))
	{
		if (*argument == '\0')
		{
			ch_printf_color(ch, "Syntax: flags <%s>\n\r", give_flags(o_flags));
			pop_call();
			return;
		}
		while (argument[0] != '\0')
		{
			argument = one_argument(argument, arg);

			if ((value = get_flag(arg, o_flags)) == -1)
			{
				ch_printf_color(ch, "Error: %s not a valid object flag.\n\r", arg);
			}
			else
			{
				TOGGLE_BIT(obj->extra_flags, 1LL << value);
			}
		}
		found = TRUE;
	}

	else if ( !strcasecmp( arg, "class" ) )
	{
		if (*argument == '\0')
		{
			ch_printf_color(ch, "Syntax: class <%s>\n\r", give_flags(class_types));
			pop_call();
			return;
		}
		while (argument[0] != '\0')
		{
			argument = one_argument(argument, arg);

			if ((value = get_flag(arg, class_types)) == -1)
			{
				ch_printf_color(ch, "%s is not a valid class.\n\r", arg);
			}
			else
			{
				TOGGLE_BIT(obj->class_flags, 1LL << value);
			}
		}
		found = TRUE;
	}

	else if ( !strcasecmp( arg, "wear" ) )
	{
		if (*argument == '\0')
		{
			ch_printf_color(ch, "Syntax: wear <%s>\n\r", give_flags(w_flags));
			pop_call();
			return;
		}
		while (argument[0] != '\0')
		{
			argument = one_argument(argument, arg);

			if ((value = get_flag(arg, w_flags)) == -1)
			{
				ch_printf_color(ch, "%s is not a wear location.\n\r", arg);
			}
			else
			{
				TOGGLE_BIT(obj->wear_flags, 1LL << value);
			}
		}
		found = TRUE;
	}

	else if (!strcasecmp(arg, "weight"))
	{
		obj->weight = URANGE(1, value, 30000);
	}

	else if (!strcasecmp(arg, "layer"))
	{
		switch(obj->item_type)
		{
			case ITEM_ARMOR:
			case ITEM_CONTAINER:
			case ITEM_SHEATH:
			case ITEM_QUIVER:
			case ITEM_TREASURE:
				break;
			default:
				send_to_char("This object type is not layered.", ch);
				pop_call();
				return;
		}
		if ((value = get_flag(argument, obj_layers)) == -1)
		{
			ch_printf_color(ch, "Syntax: layer <%s>\n\r", give_flags(obj_layers));
			pop_call();
			return;
		}
		obj->value[4] = value;
		found = TRUE;
	}

	else if (!strcasecmp(arg, "level"))
	{
		obj->level = URANGE(1, value, 99);
		found = TRUE;
	}

	else if (!strcasecmp(arg, "cost"))
	{
		if (*argument == '\0' || !strcasecmp(argument, "auto"))
		{
			obj->cost = obj_index_cost(obj);
		}
		else
		{
			obj->cost = value;
		}
		found = TRUE;
	}

	else if (!strcasecmp(arg, "hitpts"))
	{
		if (*argument == '\0' || !strcasecmp(argument, "auto"))
		{
			load_obj_hit(obj);
		}
		else
		{
			obj->hit_points = value;
		}
		found = TRUE;
	}

	else if (!strcasecmp(arg, "material"))
	{
		if ((value = get_flag(argument, material_types)) == -1)
		{
			ch_printf_color(ch, "Syntax: material <%s>\n\r", give_flags(material_types));
			pop_call();
			return;
		}
		else
		{
			obj->material = value;
		}
		found = TRUE;
	}

	else if (!strcasecmp(arg, "size"))
	{
		if ((value = get_flag(argument, size_types)) == -1)
		{
			ch_printf_color(ch, "Syntax: size <%s>\n\r", give_flags(size_types));
			pop_call();
			return;
		}
		obj->size = value;
		obj->weight = UMAX(0,load_obj_weight(obj));
		load_obj_hit(obj);
		found = TRUE;
	}

	else if (!strcasecmp(arg, "affect"))
	{
		lg_int type;

		argument = one_argument(argument, arg);

		if (arg[0] == '\0' || atoi(arg) < 1 || atoi(arg) > 3)
		{
			ch_printf_color(ch, "Syntax: affect <1|2|3> <del|apply|mod|aff1|aff2> <argument>\n\r");
			pop_call();
			return;
		}
		value = atoi(arg);
		argument = one_argument(argument, arg);

		if (arg[0] == '\0')
		{
			ch_printf_color(ch, "Syntax: affect <%d> <apply|mod|spell1|spell2> <argument>\n\r", value);
			pop_call();
			return;
		}

		if (!strcasecmp(arg, "del"))
		{
			set_obj_affect(obj, value, -1, -2, -1);
		}

		else if (!strcasecmp(arg, "apply"))
		{
			if ((type = get_flag(argument, a_types)) == -1)
			{
				ch_printf_color(ch, "Syntax: affect <%d> apply <%s>\n\r", value, give_flags(a_types));
				pop_call();
				return;
			}
			set_obj_affect(obj, value, -1, type, -1);
		}

		else if (!strcasecmp(arg, "aff1"))
		{
			if ((type = get_flag(argument, oa_flags1)) == -1)
			{
				ch_printf_color(ch, "Syntax: affect <%d> aff1 <%s>\n\r", value, give_flags(oa_flags1));
				pop_call();
				return;
			}
			set_obj_affect(obj, value, -1, -1, 1LL << type);
		}

		else if (!strcasecmp(arg, "aff2"))
		{
			if ((type = get_flag(argument, oa_flags2)) == -1)
			{
				ch_printf_color(ch, "Syntax: affect <%d> aff2 <%s>\n\r", value, give_flags(oa_flags2));
				pop_call();
				return;
			}
			set_obj_affect(obj, value, -1, -1, (1LL << type) * -1);
		}

		else if (!strcasecmp(arg, "mod"))
		{
			set_obj_affect(obj, value, atol(argument), -1, -1);
		}
		found = TRUE;
	}

	switch (obj->item_type)
	{
		case ITEM_TREASURE:
			if ( !strcasecmp( arg, "tflags" ) )
			{
				if ((value = get_flag(argument, treasure_flags)) == -1)
				{
					ch_printf_color(ch, "Syntax: tflags <%s>\n\r", give_flags(treasure_flags));
					pop_call();
					return;
				}
				obj->value[0] = (1LL << value);
				obj->value[1] = obj->value[2] = obj->value[3] = 0;
				obj->cost = obj_index_cost(obj);
				found = TRUE;
			}
			else if (!strcasecmp(arg, "charges"))
			{
				if (IS_SET(obj->value[0], TFLAG_SPELL_CHARGES))
				{
					int max, left;
					char char1;
	
					if (argument[0] == '\0')
					{
						ch_printf_color(ch, "Syntax: charges ?/?");
						pop_call();
						return;
					}
	
					value = sscanf(argument, "%d %c %d", &left, &char1, &max);
	
					if (char1 != '/' || value != 3)
					{
						ch_printf_color(ch, "Syntax: charges ?/?\n\r");
					}
					else
					{
						obj->value[1] = max;
						obj->value[2] = left;
					}
				}
				else if (IS_SET(obj->value[0], TFLAG_SPELL_RECAST))
				{
					if (argument[0] == '\0' || !is_number(argument))
					{
						ch_printf_color(ch, "How many uses per day?");
						pop_call();
						return;
					}
					value = atoi(argument);
					obj->value[1] = value;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "spell"))
			{
				if (argument[0] == '\0')
				{
					ch_printf_color(ch, "Syntax: spell 'spell name'\n\r");
					pop_call();
					return;
				}
				argument		= one_argument(argument, arg);
				switch (obj->value[0])
				{
					case TFLAG_SPELL_STORING:
					case TFLAG_COUNTERSPELL:
						obj->value[1]	= UMAX(0, skill_lookup(arg));
						break;
					case TFLAG_SPELL_RECAST:
					case TFLAG_SPELL_CHARGES:
						obj->value[3]	= UMAX(0, skill_lookup(arg));
						break;
					default:
						ch_printf_color(ch, "No treasure flag set for spell storing.\n\r");
						pop_call();
						return;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "comptype"))
			{
				if ((value = get_flag(argument, component_flags)) == -1)
				{
					ch_printf_color(ch, "Syntax: comptype <%s>\n\r", give_flags(component_flags));
				}
				else
				{
					obj->value[5] = value;
					obj->cost = UMAX(component_table[value].cost, obj->cost);
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "setting"))
			{
				if ((value = get_flag(argument, material_types)) == -1
				|| (material_table[value].parent != MATERIAL_TYPE_GEM))
				{
					send_to_char("That is not a valid gem type.\n\r", ch);
				}
				else
				{
					obj->value[6] = value;
				}
				found = TRUE;
			}
			break;
		case ITEM_ARMOR:
			if (!strcasecmp(arg, "armor"))
			{
				if ((value = get_flag(argument, arm_types)) == -1)
				{
					ch_printf_color(ch, "Syntax: armor <%s>\n\r", give_flags(arm_types));
				}
				else
				{
					obj->value[0] = value;
					obj->cost = obj_index_cost(obj);
					obj->weight = armor_table[obj->value[0]].weight;
					if (IS_SET(obj->wear_flags, CAN_WEAR_BODY))
					{
						obj->weight *= 3;
					}
					else if (IS_SET(obj->wear_flags, CAN_WEAR_HEAD) || IS_SET(obj->wear_flags, CAN_WEAR_ARMS) || IS_SET(obj->wear_flags, CAN_WEAR_LEGS))
					{
						obj->weight *= 2;
					}
					else if (IS_SET(obj->wear_flags, CAN_WEAR_FEET) || IS_SET(obj->wear_flags, CAN_WEAR_HANDS))
					{
						obj->weight /= 2;
					}
				}
				found = TRUE;
			}
			else if ( !strcasecmp( arg, "aflags" ) )
			{
				if ((value = get_flag(argument, armor_flags)) == -1)
				{
					ch_printf_color(ch, "Syntax: aflags <%s>\n\r", give_flags(armor_flags));
					pop_call();
					return;
				}
				TOGGLE_BIT(obj->value[1], 1LL << value);
				obj->cost = obj_index_cost(obj);
				found = TRUE;
			}
			else if ( !strcasecmp( arg, "wearsize" ) )
			{
				if ((value = get_flag(argument, size_types)) == -1)
				{
					ch_printf_color(ch, "Syntax: wearsize <%s>\n\r", give_flags(size_types));
					pop_call();
					return;
				}
				obj->value[3] = value;
				found = TRUE;
			}
			break;
		case ITEM_WEAPON:
		case ITEM_AMMO:
			if (!strcasecmp(arg, "weapon"))
			{
				if ((value = get_flag(argument, weap_types)) == -1)
				{
					ch_printf_color(ch, "Syntax: weapon <%s>\n\r", give_flags(weap_types));
					pop_call();
					return;
				}
				else
				{
					obj->value[0] = value;
					obj->cost = obj_index_cost(obj);
					obj->weight = weapon_table[obj->value[0]].weight;
					obj->size = weapon_table[obj->value[0]].size;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "racetype") && IS_SET(obj->value[1], WFLAG_BANE|WFLAG_SLAYING))
			{
				if ((value = get_flag(argument, rtype_flags)) == -1)
				{
					ch_printf_color(ch, "Syntax: racetype <%s>\n\r", give_flags(rtype_flags));
					pop_call();
					return;
				}
				obj->value[2] = value;
				obj->cost = obj_index_cost(obj);
				found = TRUE;
			}
			else if (!strcasecmp(arg, "subtype") && IS_SET(obj->value[1], WFLAG_BANE|WFLAG_SLAYING))
			{
				if ((value = get_flag(argument, race_specs)) == -1)
				{
					ch_printf_color(ch, "Syntax: subtype <%s>\n\r", give_flags(race_specs));
					pop_call();
					return;
				}
				TOGGLE_BIT(obj->value[3], 1LL << value);
				obj->cost = obj_index_cost(obj);
				found = TRUE;
			}
			else if (!strcasecmp(arg, "spell") && IS_SET(obj->value[1], WFLAG_SPELL_STORING))
			{
				if (argument[0] == '\0')
				{
					ch_printf_color(ch, "Syntax: spell <level> 'spell name'\n\r");
					pop_call();
					return;
				}
				argument		= one_argument(argument, arg);
				obj->value[2]	= URANGE(1, atoi(arg), 100);
				argument		= one_argument(argument, arg);
				obj->value[3]	= UMAX(0, skill_lookup(arg));
				found = TRUE;
			}
			else if (!strcasecmp(arg, "wflags"))
			{
				if ((value = get_flag(argument, weapon_flags)) == -1)
				{
					ch_printf_color(ch, "Syntax: wflags <%s>\n\r", give_flags(weapon_flags));
					pop_call();
					return;
				}
				TOGGLE_BIT(obj->value[1], 1LL << value);
				obj->value[2] = obj->value[3] = 0; // reset bits for weapon flag specs
				obj->cost = obj_index_cost(obj);
				found = TRUE;
			}
			else if (!strcasecmp(arg, "dammsg") && obj->item_type == ITEM_WEAPON)
			{
				RESTRING(obj->attack_string, argument);
				found = TRUE;
			}
			break;
		case ITEM_COMPONENT:
			if (!strcasecmp(arg, "comptype"))
			{
				if ((value = get_flag(argument, component_flags)) == -1)
				{
					ch_printf_color(ch, "Syntax: type <%s>\n\r", give_flags(component_flags));
					pop_call();
					return;
				}
				else
				{
					obj->value[0] = value;
					obj->cost = component_table[value].cost;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "uses"))
			{
				if (argument[0] == '\0')
				{
					ch_printf_color(ch, "Syntax: uses <no. of uses>\n\r");
					pop_call();
					return;
				}
				argument		= one_argument(argument, arg);
				obj->value[0]	= URANGE(1, atoi(arg), 100);
				found = TRUE;
			}
			break;
		case ITEM_SCROLL:
		case ITEM_PILL:
		case ITEM_POTION:
			if (!strcasecmp(arg, "spell"))
			{
				if (argument[0] == '\0')
				{
					ch_printf_color(ch, "Syntax: spell <spell level> 'spell name' 'spell name' 'spell name'\n\r");
					pop_call();
					return;
				}
				argument		= one_argument(argument, arg);
				obj->value[0]	= URANGE(1, atoi(arg), 100);
				argument		= one_argument(argument, arg);
				obj->value[1]	= UMAX(0, skill_lookup(arg));
				if (obj->item_type == ITEM_PILL)
				{
					argument		= one_argument(argument, arg);
					obj->value[2]  = UMAX(0, skill_lookup(arg));
					argument		= one_argument(argument, arg);
					obj->value[3]  = UMAX(0, skill_lookup(arg));
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "class"))
			{
				if ((value = get_flag(argument, scroll_types)) == -1)
				{
					ch_printf_color(ch, "Syntax: class <%s>\n\r", give_flags(scroll_types));
					pop_call();
					return;
				}
				else
				{
					obj->value[2] = value;
				}
				found = TRUE;
			}
			break;
			break;
		case ITEM_WAND:
		case ITEM_STAFF:
			if (!strcasecmp(arg, "spell"))
			{
				if (argument[0] == '\0')
				{
					ch_printf_color(ch, "Syntax: spell <spell level> 'spell name' 'spell name' 'spell name' 'spell name'\n\r");
					pop_call();
					return;
				}
				argument		= one_argument(argument, arg);
				obj->value[0]	= URANGE(1, atoi(arg), 100);
				argument		= one_argument(argument, arg);
				obj->value[3]	= UMAX(0, skill_lookup(arg));
				if (obj->item_type == ITEM_STAFF)
				{
					argument		= one_argument(argument, arg);
					obj->value[4]  = UMAX(0, skill_lookup(arg));
					argument		= one_argument(argument, arg);
					obj->value[5]  = UMAX(0, skill_lookup(arg));
					argument		= one_argument(argument, arg);
					obj->value[6]  = UMAX(0, skill_lookup(arg));
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "charges"))
			{
				int max, left;
				char char1;

				if (argument[0] == '\0')
				{
					ch_printf_color(ch, "Syntax: charges ?/?");
					pop_call();
					return;
				}

				value = sscanf(argument, "%d %c %d", &left, &char1, &max);

				if (char1 != '/' || value != 3)
				{
					ch_printf_color(ch, "Syntax: charges ?/?\n\r");
					pop_call();
					return;
				}
				else
				{
					obj->value[1] = max;
					obj->value[2] = left;
				}
				found = TRUE;
			}
			break;
		case ITEM_TOTEM:
			if (!strcasecmp(arg, "spell"))
			{
				if (argument[0] == '\0')
				{
					ch_printf_color(ch, "Syntax: spell [spell1] [spell2] [spell3] [spell4]\n\r");
					pop_call();
					return;
				}
				argument		= one_argument(argument, arg);
				obj->value[0]	= UMAX(0, skill_lookup(arg));
				argument		= one_argument(argument, arg);
				obj->value[1]	= UMAX(0, skill_lookup(arg));
				argument		= one_argument(argument, arg);
				obj->value[2]  = UMAX(0, skill_lookup(arg));
				argument		= one_argument(argument, arg);
				obj->value[3]  = UMAX(0, skill_lookup(arg));
				found = TRUE;
			}
			break;
		case ITEM_SPELLPOUCH:
		case ITEM_CONTAINER:
		case ITEM_QUIVER:
		case ITEM_SHEATH:
		case ITEM_CART:
			if (!strcasecmp(arg, "carry"))
			{
				obj->value[0] = URANGE(0, value, 2000);
				found = TRUE;
			}
			else if ( !strcasecmp( arg, "conflags" ) )
			{
				if ((value = get_flag(argument, cont_flags)) == -1)
				{
					ch_printf_color(ch, "Syntax: conflags <%s>\n\r", give_flags(cont_flags));
					pop_call();
					return;
				}
				TOGGLE_BIT(obj->value[1], 1LL << value);
				found = TRUE;
			}
			else if (!strcasecmp(arg, "key"))
			{
				obj->value[2] = URANGE(-1, value, MAX_VNUM-1);
				found = TRUE;
			}
			else if (!strcasecmp(arg, "max"))
			{
				obj->value[3] = URANGE(0, value, 150);
				found = TRUE;
			}
			break;
		case ITEM_LIGHT:
			if (!strcasecmp(arg, "light"))
			{
				obj->value[0] = URANGE(10, value, 200);
				found = TRUE;
			}
			else if (!strcasecmp(arg, "refill"))
			{
				if (!strcasecmp(argument, "true"))
				{
					obj->value[1] = 1;
				}
				else if (!strcasecmp(argument, "false"))
				{
					obj->value[1] = 0;
				}
				else
				{
					send_to_char("Is the light refillable? True or False?", ch);
					pop_call();
					return;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "charges"))
			{
				obj->value[2] = URANGE(-1, value, 10000);
			}
			else if (!strcasecmp(arg, "ignite"))
			{
				if (!strcasecmp(argument, "true"))
				{
					obj->value[3] = 1;
				}
				else if (!strcasecmp(argument, "false"))
				{
					obj->value[3] = 0;
				}
				else
				{
					send_to_char("Must the light be ignited? True or False?", ch);
					pop_call();
					return;
				}
				found = TRUE;
			}
			break;
		case ITEM_FIRE:
			if (!strcasecmp(arg, "hours"))
			{
				obj->value[2] = URANGE(-1, value, 10000);
				found = TRUE;
			}
			break;
		case ITEM_SYMBOL:
			if (!strcasecmp(arg, "god"))
			{
				if ((value = lookup_god(argument)) == -1)
				{
					ch_printf_color(ch, "That is not a valid god.\n\r");
					pop_call();
					return;
				}
				else
				{
					obj->value[2] = value;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "bonus"))
			{
				obj->value[3] = URANGE(0, value, 5);
				found = TRUE;
			}
			break;
		case ITEM_PIECE:
			if (!strcasecmp(arg, "piece1"))
			{
				value = atoi(argument);
				if (get_obj_index(value) && can_olc_modify(ch, value))
				{
					obj->value[0] = value;
				}
				else
				{
					ch_printf_color(ch, "%d: Object index not found.\n\r", value);
					pop_call();
					return;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "piece2"))
			{
				value = atoi(argument);
				if (get_obj_index(value) && can_olc_modify(ch, value))
				{
					obj->value[1] = value;
				}
				else
				{
					ch_printf_color(ch, "%d: Object index not found.\n\r", value);
					pop_call();
					return;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "creates"))
			{
				value = atoi(argument);
				if (get_obj_index(value) && can_olc_modify(ch, value))
				{
					obj->value[2] = value;
				}
				else
				{
					ch_printf_color(ch, "%d: Object index not found.\n\r", value);
					pop_call();
					return;
				}
				found = TRUE;
			}
			break;
		case ITEM_FOUNTAIN:
			if (!strcasecmp(arg, "liquid"))
			{
				if ((value = get_flag(argument, liq_types)) == -1)
				{
					ch_printf_color(ch, "Syntax: liquid <%s>\n\r", give_flags(liq_types));
					pop_call();
					return;
				}
				else
				{
					obj->value[2] = value;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "poison"))
			{
				if ((value = get_flag(argument, poison_names)) == -1)
				{
					ch_printf_color(ch, "Syntax: poison <%s>\n\r", give_flags(poison_names));
					pop_call();
					return;
				}
				else if (poison_table[value].type != POISON_TYPE_INGEST
				&& poison_table[value].type != POISON_TYPE_CONTACT)
				{
					send_to_char("That poison cannot be ingested.\n\r", ch);
					pop_call();
					return;
				}
				else
				{
					obj->value[3] = value;
				}
				found = TRUE;
			}
			break;
		case ITEM_DRINK_CON:
			if (!strcasecmp(arg, "liquid"))
			{
				if ((value = get_flag(argument, liq_types)) == -1)
				{
					ch_printf_color(ch, "Syntax: liquid <%s>\n\r", give_flags(liq_types));
					pop_call();
					return;
				}
				else
				{
					obj->value[2] = value;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "charges"))
			{
				int max, left;
				char char1;

				if (argument[0] == '\0')
				{
					ch_printf_color(ch, "Syntax: charges ?/?");
					pop_call();
					return;
				}

				value = sscanf(argument, "%d %c %d", &left, &char1, &max);

				if (char1 != '/' || value != 3)
				{
					ch_printf_color(ch, "Syntax: charges ?/?\n\r");
					pop_call();
					return;
				}
				else
				{
					obj->value[0] = max;
					obj->value[1] = left;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "poison"))
			{
				if ((value = get_flag(argument, poison_names)) == -1)
				{
					ch_printf_color(ch, "Syntax: poison <%s>\n\r", give_flags(poison_names));
					pop_call();
					return;
				}
				else if (poison_table[value].type != POISON_TYPE_INGEST
				&& poison_table[value].type != POISON_TYPE_CONTACT)
				{
					send_to_char("That poison cannot be ingested.\n\r", ch);
					pop_call();
					return;
				}
				else
				{
					obj->value[3] = value;
				}
				found = TRUE;
			}
			break;
		case ITEM_FOOD:
			if (!strcasecmp(arg, "fill"))
			{
				obj->value[0] = URANGE(-48, value, 48);
				found = TRUE;
			}
			else if (!strcasecmp(arg, "cooked"))
			{
				if (!strcasecmp(argument, "yes"))
				{
					obj->value[2] = 1;
				}
				else if (!strcasecmp(argument, "no"))
				{
					obj->value[2] = 0;
				}
				else
				{
					ch_printf_color(ch, "Syntax: cooked <yes|no>\n\r");
					pop_call();
					return;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "poison"))
			{
				if ((value = get_flag(argument, poison_names)) == -1)
				{
					ch_printf_color(ch, "Syntax: poison <%s>\n\r", give_flags(poison_names));
					pop_call();
					return;
				}
				else if (poison_table[value].type != POISON_TYPE_INGEST
				&& poison_table[value].type != POISON_TYPE_CONTACT)
				{
					send_to_char("That poison cannot be ingested.\n\r", ch);
					pop_call();
					return;
				}
				else
				{
					obj->value[3] = value;
				}
				found = TRUE;
			}
			break;
		case ITEM_PORTAL:
			if (!strcasecmp(arg, "charges"))
			{
				obj->value[0] = URANGE(-1, value, 10000);
				found = TRUE;
			}
			else if (!strcasecmp(arg, "key"))
			{
				obj->value[1] = URANGE(-2, value, MAX_VNUM-1);
				found = TRUE;
			}
			else if ( !strcasecmp( arg, "enter" ) )
			{
				if ((value = get_flag(argument, portal_flags)) == -1)
				{
					ch_printf_color(ch, "Syntax: enter <%s>\n\r", give_flags(portal_flags));
					pop_call();
					return;
				}
				TOGGLE_BIT(obj->value[2], 1LL << value);
				found = TRUE;
			}
			else if (!strcasecmp(arg, "toroom"))
			{
				if (!can_olc_modify(ch, value))
				{
					ch_printf_color(ch, "That vnum is not in your allocated range.\n\r");
					pop_call();
					return;
				}
				else
				{
					obj->value[3] = value;
				}
				found = TRUE;
			}
			break;
		case ITEM_FURNITURE:
			if (!strcasecmp(arg, "users"))
			{
				obj->value[0] = URANGE(0, value, 100);
				found = TRUE;
			}
			else if ( !strcasecmp( arg, "poses" ) )
			{
				if ((value = get_flag(argument, f_flags)) == -1)
				{
					ch_printf_color(ch, "Syntax: poses <%s>\n\r", give_flags(f_flags));
					pop_call();
					return;
				}
				TOGGLE_BIT(obj->value[2], 1LL << value);
				found = TRUE;
			}
			break;
		case ITEM_TOOLS:
			if (!strcasecmp(arg, "tool"))
			{
				if ((value = get_flag(argument, tool_types)) == -1)
				{
					ch_printf_color(ch, "Syntax: type <%s>\n\r", give_flags(tool_types));
					pop_call();
					return;
				}
				else
				{
					obj->value[0] = value;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "bonus"))
			{
				obj->value[2] = URANGE(0, value, 5);
				if (value > 0)
					SET_BIT(obj->extra_flags, ITEM_MASTERWORK);
				else
					REMOVE_BIT(obj->extra_flags, ITEM_MASTERWORK);
				found = TRUE;
			}
			else if (!strcasecmp(arg, "charges"))
			{
				obj->value[1] = URANGE(0, value, 1000);
				found = TRUE;
			}
			break;
		case ITEM_MONEY:
			if (!strcasecmp(arg, "gold"))
			{
				obj->value[0] = value;
				found = TRUE;
			}
			else if (!strcasecmp(arg, "silver"))
			{
				obj->value[1] = value;
				found = TRUE;
			}
			else if (!strcasecmp(arg, "copper"))
			{
				obj->value[2] = value;
				found = TRUE;
			}
			break;
		case ITEM_SPELLBOOK:
			if (!strcasecmp(arg, "scribed"))
			{
				if (*argument == '\0')
				{
					ch_printf_color(ch, "Scribe what spell?\n\r");
					pop_call();
					return;
				}				
				if ((value = skill_lookup(argument)) == -1 || !is_spell(value))
				{
					ch_printf_color(ch, "%s is not a spell.\n\r", argument);
					pop_call();
					return;
				}				
				if (obj->scribed[value])
					obj->scribed[value] = 0;
				else
					obj->scribed[value] = 1;
				found = TRUE;
			}
			break;
		case ITEM_TRAP:
			if (!strcasecmp(arg, "ttype"))
			{
				if ((value = get_flag(argument, trap_types)) == -1)
				{
					ch_printf_color(ch, "Syntax: ttype <%s>\n\r", give_flags(trap_types));
					pop_call();
					return;
				}
				else
				{
					obj->value[0] = value;
					obj->value[4] = 0;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "reset"))
			{
				if ((value = get_flag(argument, trap_resets)) == -1)
				{
					ch_printf_color(ch, "Syntax: reset <%s>\n\r", give_flags(trap_resets));
					pop_call();
					return;
				}
				else
				{
					obj->value[1] = value;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "trigger"))
			{
				if ((value = get_flag(argument, trap_triggers)) == -1)
				{
					ch_printf_color(ch, "Syntax: trigger <%s>\n\r", give_flags(trap_triggers));
					pop_call();
					return;
				}
				else
				{
					TOGGLE_BIT(obj->value[2], 1 << value);
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "state"))
			{
				if ((value = get_flag(argument, trap_state)) == -1)
				{
					ch_printf_color(ch, "Syntax: state <%s>\n\r", give_flags(trap_state));
					pop_call();
					return;
				}
				else
				{
					obj->value[3] = value;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "dammsg"))
			{
				RESTRING(obj->attack_string, argument);
				found = TRUE;
			}
			else if (!strcasecmp(arg, "value"))
			{
				switch (obj->value[0])
				{
					case TRAP_TYPE_POISON:
						if ((value = get_flag(argument, poison_names)) == -1)
						{
							ch_printf_color(ch, "Syntax: value <%s>\n\r", give_flags(poison_names));
							pop_call();
							return;
						}
						else
						{
							obj->value[4] = value;
						}
						found = TRUE;
						break;
					case TRAP_TYPE_SPELL:
						if ((value = skill_lookup(argument)) == -1)
						{
							ch_printf_color(ch, "Syntax: value - %s is not a spell!\n\r", argument);
							pop_call();
							return;
						}
						obj->value[4] = value;
						found = TRUE;
						break;
					case TRAP_TYPE_TELEPORT:
						if (strcasecmp(argument, "random") && room_index[value] == NULL)
						{
							ch_printf_color(ch, "%d: NULL room! (Use RANDOM for random room)\n\r", value);
							pop_call();
							return;
						}
						else if (!strcasecmp(argument, "random"))
						{
							obj->value[4] = -1;
						}
						else
						{
							obj->value[4] = value;
						}
						found = TRUE;
						break;
					case TRAP_TYPE_MLOAD:
						if (mob_index[value] == NULL)
						{
							ch_printf_color(ch, "%d: NULL mobile!\n\r", value);
							pop_call();
							return;
						}
						obj->value[4] = value;
						found = TRUE;
						break;
					case TRAP_TYPE_OLOAD:
						if (obj_index[value] == NULL)
						{
							ch_printf_color(ch, "%d: NULL object!\n\r", value);
							pop_call();
							return;
						}
						obj->value[4] = value;
						found = TRUE;
						break;
					default:
						obj->value[4] = value;
						found = TRUE;
						break;
				}
			}
			break;
		case ITEM_BOOK:
			if (!strcasecmp(arg, "page"))
			{
				if (argument[0] == '\0' || !is_number(argument))
				{
					ch_printf_color(ch, "Syntax: page <number>\n\r");
					pop_call();
					return;
				}
				int num = atoi(argument);
				if (num - 1 > 0)
				{
					sprintf(buf, "_p%d_", num - 1);
					if (get_extra_descr(buf, obj->first_extradesc) == NULL)
					{
						ch_printf_color(ch, "Page %d should be added first.\n\r", num - 1);
						pop_call();
						return;
					}
				}
				sprintf(buf, "_p%d_", num);
				ed = set_ed_obj(obj, buf);
				ch->pcdata->tempmode = MODE_REPEATCMD;
				ch->pcdata->editmode = MODE_OBJ_EXTRA;
				ch->pcdata->temp_ptr = ed;
				obj->value[2]++;
				start_editing(ch, ed->description);
				pop_call();
				return;
			}
			else if (!strcasecmp(arg, "rmpage"))
			{
				if (!argument || argument[0] == '\0' || !is_number(argument))
				{
					ch_printf_color(ch, "Syntax: rmpage <number>\n\r");
					pop_call();
					return;
				}
				sprintf(buf, "_p%d_", atoi(argument));
				if (!del_ed_obj(obj, buf))
				{
					ch_printf_color(ch, "rmpage: page %d not found.\n\r", atoi(argument));
					pop_call();
					return;
				}
				obj->value[2]--;
				found = TRUE;
			}
			else if (!strcasecmp(arg, "language"))
			{
				if ((value = get_flag(argument, lang_names)) == -1)
				{
					ch_printf_color(ch, "Syntax: language <%s>\n\r", give_flags(lang_names));
					pop_call();
					return;
				}
				obj->value[3] = 1LL << value;
				found = TRUE;
			}
			else if (!strcasecmp(arg, "dc"))
			{
				if (value == -1)
				{
					ch_printf_color(ch, "Syntax: dc <number>\n\r");
					pop_call();
					return;
				}
				else
				{
					obj->value[4] = value;
				}
				found = TRUE;
			}
			break;
		case ITEM_PAPER:
			if (!strcasecmp(arg, "written"))
			{
				if (!strcasecmp(argument, "true"))
				{
					obj->value[1] = 1;
				}
				else if (!strcasecmp(argument, "false"))
				{
					obj->value[1] = 0;
				}
				else
				{
					ch_printf_color(ch, "Syntax: written <true|false>\n\r");
					pop_call();
					return;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "sealed"))
			{
				if (!strcasecmp(argument, "true"))
				{
					obj->value[2] = 1;
				}
				else if (!strcasecmp(argument, "false"))
				{
					obj->value[2] = 0;
				}
				else
				{
					ch_printf_color(ch, "Syntax: sealed <true|false>\n\r");
					pop_call();
					return;
				}
				found = TRUE;
			}
			else if (!strcasecmp(arg, "language"))
			{
				if ((value = get_flag(argument, lang_names)) == -1)
				{
					ch_printf_color(ch, "Syntax: language <%s>\n\r", give_flags(lang_names));
					pop_call();
					return;
				}
				obj->value[3] = 1LL << value;
				found = TRUE;
			}
			else if (!strcasecmp(arg, "dc"))
			{
				if (value == -1)
				{
					ch_printf_color(ch, "Syntax: dc <number>\n\r");
					pop_call();
					return;
				}
				else
				{
					obj->value[4] = value;
				}
				found = TRUE;
			}
			break;
		case ITEM_MAP:
			if (!strcasecmp(arg, "lovnum"))
			{
				obj->value[1] = value;
				found = TRUE;
			}
			else if (!strcasecmp(arg, "hivnum"))
			{
				obj->value[2] = value;
				found = TRUE;
			}			
			break;
		case ITEM_WINDOW:
			if (!strcasecmp(arg, "viewroom"))
			{
				if (room_index[value] == NULL)
				{
					ch_printf_color(ch, "%d: NULL room!\n\r", value);
					pop_call();
					return;
				}				
				obj->value[0] = value;
				found = TRUE;
			}
			else if (!strcasecmp(arg, "castable"))
			{
				if (!strcasecmp(argument, "true"))
				{
					obj->value[1] = 1;
				}
				else if (!strcasecmp(argument, "false"))
				{
					obj->value[1] = 0;
				}
				else
				{
					ch_printf_color(ch, "Syntax: castable <true|false>\n\r");
					pop_call();
					return;
				}
				found = TRUE;
			}
			break;
	}

	if (!found && ch->pcdata->editmode == MODE_REPEATCMD)
	{
		ch->pcdata->editmode = MODE_RESTRICTED;
		interpret( ch, origarg );
		ch->pcdata->editmode = MODE_REPEATCMD;
		ch->pcdata->last_cmd = do_edit;
		pop_call();
		return;
	}

	do_oedit(ch, "stat");
	pop_call();
	return;
}

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

	ROOM_INDEX_DATA	*room;
	EXTRA_DESCR_DATA	*ed;
	EXIT_DATA           *exit;
	int				door, value, vnum;
	char				*origarg = argument;

	char colw[10], colg[10], colW[10], colM[10];

	push_call("do_redit(%p,%p)",ch,argument);

	CHECK_EDITMODE( ch );

	strcpy(colw, get_color_string(ch, COLOR_TEXT, VT102_DIM));
	strcpy(colg, get_color_string(ch, COLOR_ACCENT, VT102_DIM));
	strcpy(colW, get_color_string(ch, COLOR_TEXT, VT102_BOLD));
	strcpy(colM, ansi_translate_text(ch, "{158}"));

	if (!ch->desc)
	{
		send_to_char( "You have no descriptor.\n\r", ch );
		pop_call();
		return;
	}

	if (ch->pcdata->edit_ptr && (room = ch->pcdata->edit_ptr)->area == NULL)
	{
		ch_printf_color(ch, "The room you were editing is no longer valid.\n\r");
		stop_olc_editing(ch, ch->in_room->area);
		pop_call();
		return;
	}

	switch(ch->pcdata->editmode)
	{
		default:
			break;
		case MODE_ROOM_DESC:
			room = ch->pcdata->edit_ptr;

			STRFREE(room->description );
			room->description = copy_buffer(ch);
			stop_editing( ch );
			do_redit(ch, "stat");
			pop_call();
			return;
		case MODE_ROOM_LISTEN:
			room = ch->pcdata->edit_ptr;

			STRFREE(room->listen_desc );
			room->listen_desc = copy_buffer(ch);
			stop_editing( ch );
			do_redit(ch, "stat");
			pop_call();
			return;
		case MODE_ROOM_NIGHT:
			room = ch->pcdata->edit_ptr;

			STRFREE(room->night_desc );
			room->night_desc = copy_buffer(ch);
			stop_editing( ch );
			do_redit(ch, "stat");
			pop_call();
			return;
		case MODE_ROOM_EXTRA:
			ed = ch->pcdata->temp_ptr;
			STRFREE(ed->description);

			ed->description = copy_buffer(ch);
			stop_editing(ch);
			do_redit(ch, "stat");
			pop_call();
			return;
	}

	smash_tilde( argument );

	if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		room = ch->pcdata->edit_ptr;

// 		if (argument[0] == '?')
// 		{
// 			/*
// 				Show redit status
// 			*/
// 			ch_printf_color(ch, "\n\r");
// 			ch_printf_color(ch, "%sSyntax%s: %s<%scommand%s> <%svalue%s>\n\r", colw, colW, colw, colg, colw, colW, colw);
// 			ch_printf_color(ch, "%s  flag sect name desc night ed rmed listen done stat copy ? < >\n\r", colg);
// 			ch_printf_color(ch, "\n\r");
// 			ch_printf_color(ch, "%sSyntax%s: %s<%sdir%s> <%scommand%s> <%svalue%s>\n\r", colw, colW, colw, colM, colw, colg, colw, colW, colw);
// 			ch_printf_color(ch, "%s  link delete desc name flag [climbdc] [dist]\n\r", colg);
// 			pop_call();
// 			return;
// 		}
// 
		if (!strcasecmp(argument, "done"))
		{
			send_to_char("Redit mode off.\n\r", ch);

			stop_olc_editing(ch, room->area);

			pop_call();
			return;
		}

		if (!strcmp(argument, ">"))
		{
			for (vnum = room->vnum + 1 ; vnum <= room->area->hi_r_vnum ; vnum++)
			{
				if (get_room_index(vnum) && can_olc_modify(ch, vnum))
				{
					stop_olc_editing(ch, room->area);
					sprintf(buf, "%d", vnum);
					do_redit(ch, buf);
					pop_call();
					return;
				}
			}
			ch_printf_color(ch, "Next index not found.\n\r");
			pop_call();
			return;
		}

		if (!strcmp(argument, "<"))
		{
			for (vnum = room->vnum - 1 ; vnum >= room->area->low_r_vnum ; vnum--)
			{
				if (get_room_index(vnum) && can_olc_modify(ch, vnum))
				{
					stop_olc_editing(ch, room->area);
					sprintf(buf, "%d", vnum);
					do_redit(ch, buf);
					pop_call();
					return;
				}
			}
			ch_printf_color(ch, "Next index not found.\n\r");
			pop_call();
			return;
		}

		if (!is_string(argument) || !strcasecmp(argument, "stat"))
		{
			sprintf(buf, "\n\r");
			cat_sprintf(buf, "%s  name%s:%s %s\n\r", colg, colw, colW, room->name);
			cat_sprintf(buf, "%s  desc%s:%s \n\r%s", colg, colw, colW, room->description);
			cat_sprintf(buf, "%s night%s:%s \n\r%s", colg, colw, colW, room->night_desc);
			cat_sprintf(buf, "%slisten%s:%s \n\r%s", colg, colw, colW, room->listen_desc);
			cat_sprintf(buf, "%s  flag%s:%s %s\n\r", colg, colw, colW, flag_string(room->room_flags, r_flags));
			cat_sprintf(buf, "%s  sect%s:%s %s\n\r", colg, colw, colW, sect_types[room->sector_type]);
			cat_sprintf(buf, "%s    ed%s:%s %s\n\r", colg, colw, colW, get_ed(ch, room->first_extradesc));
			for (door = 0 ; door < 6 ; door++)
			{
				if ((exit = room->exit[door]) != NULL)
				{
					cat_sprintf(buf, "%s%6s%s:%s %d (%s)\n\r", colg, dir_name[door], colw, colW, exit->to_room, get_room_index(exit->to_room) == NULL ? "Error: NULL room!" : get_room_index(exit->to_room)->name);
				}
			}	
			cat_sprintf(buf, "Syntax: <field> <value>                        < %sprev next %s>\n\r", colg, colW);
			send_to_char_color(buf, ch);
			pop_call();
			return;
		}
	}
	else if (argument[0] == '\0')
	{
		if (!can_olc_modify(ch, ch->in_room->vnum))
		{
			send_to_char("This room is not in your allocated range.\n\r", ch);
			pop_call();
			return;
		}
		room = ch->in_room;
	}
	else if ((room = get_room_index(atoi(argument))) == NULL)
	{
		send_to_char("Syntax: edit room <room vnum>\n\r", ch);
		pop_call();
		return;
	}
	else if (!can_olc_modify(ch, room->vnum))
	{
		send_to_char("That vnum is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	if (ch->pcdata->editmode != MODE_REPEATCMD)
	{
		ch->pcdata->edit_ptr = room;
		ch->pcdata->edittype = EDIT_TYPE_ROOM;

		ch->pcdata->editmode = MODE_REPEATCMD;

		if (ch->pcdata)
		{
			if (ch->pcdata->subprompt)
			{
				STRFREE(ch->pcdata->subprompt);
			}
			sprintf( buf, "Editing Room Vnum: %d", room->vnum );
			ch->pcdata->subprompt = STRALLOC( buf );
		}
		do_redit(ch, "stat");
		pop_call();
		return;
	}

	argument = one_argument(argument, arg);

	value = is_number(argument) ? atoi(argument) : -1;

	if (!strcasecmp(arg, "name"))
	{
		STRFREE(room->name);
		room->name = STRALLOC(capitalize(argument));
	}

	else if (!strcasecmp(arg, "desc"))
	{
		ch->pcdata->tempmode  = MODE_REPEATCMD;
		ch->pcdata->editmode = MODE_ROOM_DESC;
		start_editing( ch, room->description );
		pop_call();
		return;
	}

	else if (!strcasecmp(arg, "listen"))
	{
		ch->pcdata->tempmode  = MODE_REPEATCMD;
		ch->pcdata->editmode = MODE_ROOM_LISTEN;
		start_editing( ch, room->listen_desc );
		pop_call();
		return;
	}

	else if (!strcasecmp(arg, "night"))
	{
		ch->pcdata->tempmode  = MODE_REPEATCMD;
		ch->pcdata->editmode = MODE_ROOM_NIGHT;
		start_editing( ch, room->night_desc );
		pop_call();
		return;
	}

	else if (!strcasecmp(arg, "ed"))
	{
		if (argument[0] == '\0')
		{
			ch_printf_color(ch, "Syntax: ed <keywords>\n\r");
			pop_call();
			return;
		}
		ed            = set_ed_room(room, argument);
		ch->pcdata->tempmode   = MODE_REPEATCMD;
		ch->pcdata->editmode  = MODE_ROOM_EXTRA;
		ch->pcdata->temp_ptr = ed;

		start_editing(ch, ed->description);
		pop_call();
		return;
	}

	else if (!strcasecmp(arg, "rmed"))
	{
		if (!argument || argument[0] == '\0')
		{
			ch_printf_color(ch, "Syntax: rmed <keyword>\n\r");
			pop_call();
			return;
		}

		if (!del_ed_room(room, argument))
		{
			ch_printf_color(ch, "Keyword: %s not found.\n\r", argument);
			pop_call();
			return;
		}
	}

	else if (!strcasecmp( arg, "flag" ))
	{
		while (argument[0] != '\0')
		{
			argument = one_argument(argument, arg);

			if ((value = get_flag(arg, r_flags)) == -1)
			{
				ch_printf_color(ch, "Error: %s not a valid room flag.\n\r", arg);
			}
			else
			{
				TOGGLE_BIT(room->room_flags, 1LL << value);
			}
		}
	}
	
	else if (!strcasecmp(arg, "sect"))
	{
		if ((value = get_flag(argument, sect_types)) == -1)
		{
			sprintf(buf, "Syntax: sect <%s>", give_flags(sect_types));
			ch_printf_color(ch, "%s\n\r", justify(buf, get_page_width(ch)));
			pop_call();
			return;
		}
		room->sector_type = value;
		pop_call();
		return;
	}
	
	else if (!strcasecmp(arg, "copy"))
	{
		ROOM_INDEX_DATA *sourceroom = NULL;

		if (!is_number(argument))
		{
			send_to_char("Not a valid vnum to copy.\n\r", ch);
			pop_call();
			return;
		}
		if ((sourceroom = get_room_index(atoi(argument))) == NULL)
		{
			ch_printf(ch, "Bad room vnum: %d.\n\r", vnum);
			pop_call();
			return;
		}
		if (!can_olc_modify(ch, atoi(argument)))
		{
			send_to_char("That vnum is not in your allocated range.\n\r", ch);
			pop_call();
			return;
		}
		RESTRING(room->name, sourceroom->name);
		RESTRING(room->description, sourceroom->description);
		room->sector_type = sourceroom->sector_type;
		room->room_flags = sourceroom->room_flags;
		if (is_string(sourceroom->night_desc))
			RESTRING(room->night_desc, sourceroom->night_desc);
		ch_printf(ch, "{178}Room %d copied to room %d.\n\r", sourceroom->vnum, room->vnum);
		pop_call();
		return;
	}

	else if (!strcasecmp(arg, "n") || !strcasecmp(arg, "north")
	||  !strcasecmp(arg, "e") || !strcasecmp(arg,  "east")
	||  !strcasecmp(arg, "s") || !strcasecmp(arg, "south")
	||  !strcasecmp(arg, "w") || !strcasecmp(arg,  "west")
	||  !strcasecmp(arg, "u") || !strcasecmp(arg,  "down")
	||  !strcasecmp(arg, "d") || !strcasecmp(arg,    "up"))
	{
		door = direction_door(arg);

		if (argument[0] == '\0')
		{
			if ((exit = room->exit[door]) != NULL)
			{
				ch_printf_color(ch, "%s%9s%s:%s %d\n\r", colM, dir_name[door], colw, colW, exit->vnum);
				ch_printf_color(ch, "%s%9s%s:%s %s\n\r", colg,  "desc", colw, colW, exit->description);
				ch_printf_color(ch, "%s%9s%s:%s %s\n\r", colg,  "name", colw, colW, exit->keyword);
				ch_printf_color(ch, "%s%9s%s:%s %s\n\r", colg,  "flag", colw, colW, flag_string(exit->exit_info, exit_flags));
				ch_printf_color(ch, "%s%9s%s:%s %d\n\r", colg,   "key", colw, colW, exit->key);
				ch_printf_color(ch, "%s%9s%s:%s %s\n\r", colg,  "size", colw, colW, size_types[exit->exit_size]);
				if (IS_SET(exit->exit_info, EX_CLIMB))
					ch_printf_color(ch, "%s%9s%s:%s %-2d %s(DC of climb check)\n\r", colg, "climbdc", colw, colW, exit->climb_dc, colw);
				if (IS_SET(exit->exit_info, EX_JUMP|EX_CLIMB))
					ch_printf_color(ch, "%s%9s%s:%s %-2d %s(dist of climb/jump)\n\r", colg,  "dist", colw, colW, exit->fall_dist, colw);
			}
			else
			{
				ch_printf_color(ch, "There is no connection %s.\n\r", dir_name[door]);
			}
			pop_call();
			return;
		}

		argument = one_argument(argument, arg);

		if (!strcasecmp(arg, "link"))
		{
			sprintf(buf, "%d %s", door, argument);
			do_link(ch, buf);
		}

		else if (!strcasecmp( arg, "villaexit" ))
		{
			sprintf(buf, "%d %s", door, argument);
			do_link(ch, buf);
			if ((exit = room->exit[door]) == NULL)
			{
				ch_printf_color(ch, "There is no exit in that direction.\n\r");
				pop_call();
				return;
			}
			exit->keyword = STRALLOC("estate gate");
			SET_BIT(exit->exit_info, EX_ISDOOR|EX_CLOSED|EX_LOCKED|EX_BASHPROOF|EX_MAGICPROOF|EX_PICKPROOF);
		}

		else if ((exit = room->exit[door]) == NULL)
		{
			ch_printf_color(ch, "There is no exit in that direction.\n\r");
			pop_call();
			return;
		}
		
		else if (!strcasecmp(arg, "delete"))
		{
			int rev_dest_vnum = exit->to_room;
	
			if (argument[0] == 'b' || argument[0] == 'B')
			{
				if (room_index[rev_dest_vnum] != NULL)
					delete_exit(room_index[rev_dest_vnum], rev_dir[door]);
			}
			delete_exit(room, door);
		}

		else if (!strcasecmp(arg, "desc"))
		{
			STRFREE(exit->description);
			exit->description = STRALLOC(capitalize(argument));
		}

		else if (!strcasecmp(arg, "name"))
		{
			STRFREE(exit->keyword);
			exit->keyword = STRALLOC(argument);
		}

		else if (!strcasecmp( arg, "flags" ))
		{
			while (argument[0] != '\0')
			{
				argument = one_argument(argument, arg);

				if ((value = get_flag(arg, exit_flags)) == -1)
				{
					ch_printf_color(ch, "Error: %s not a valid exit flag.\n\r", arg);
				}
				else
				{
					TOGGLE_BIT(exit->exit_info, 1LL << value);
				}
			}
		}

		else if (!strcasecmp(arg, "key"))
		{
			value = atoi(argument);

			if (value >= 0 && get_obj_index(value) == NULL)
			{
				ch_printf_color(ch, "vnum %d = NULL object.\n\r", value);
				pop_call();
				return;
			}
			exit->key = UMAX(-2, value);
		}		

		else if ( !strcasecmp( arg, "size" ) )
		{
			if ((value = get_flag(argument, size_types)) == -1)
			{
				ch_printf_color(ch, "Syntax: size <%s>\n\r", give_flags(size_types));
				pop_call();
				return;
			}
			exit->exit_size = value;
		}
	
		else if (!strcasecmp(arg, "climbdc"))
		{
			if (!IS_SET(exit->exit_info, EX_CLIMB))
			{
				send_to_char("There is no climb flag set for this exit.\n\r", ch);
			}
			else
			{
				exit->climb_dc = atoi(argument);
			}
		}		

		else if (!strcasecmp(arg, "dist"))
		{
			if (!IS_SET(exit->exit_info, EX_CLIMB|EX_JUMP))
			{
				send_to_char("There is no climb or jump flag set for this exit.\n\r", ch);
			}
			else
			{
				exit->fall_dist = atoi(argument);
			}
		}	
		
		else
		{
			ch_printf_color(ch, "Syntax: <dir> <link|delete|desc|name|flags|climbdc|dist> <argument>\n\r");
		}

		do_redit(ch, dir_name[door]);
		pop_call();
		return;
	}

	else if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		ch->pcdata->editmode = MODE_RESTRICTED;
		interpret( ch, origarg );
		ch->pcdata->editmode = MODE_REPEATCMD;
		ch->pcdata->last_cmd = do_edit;
		pop_call();
		return;
	}

	do_redit(ch, "stat");
	pop_call();
	return;
}

void do_hedit( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	char txt[MAX_STRING_LENGTH];
	HELP_DATA *help;
	HELP_MENU_DATA *menu;

	char *origarg = argument;

	char colg[10], colw[10], colW[10], colM[10];

	push_call("do_hedit(%p,%p)",ch,argument);

	CHECK_EDITMODE( ch );

	strcpy(colw, get_color_string(ch, COLOR_TEXT, VT102_DIM));
	strcpy(colg, get_color_string(ch, COLOR_ACCENT, VT102_DIM));
	strcpy(colW, get_color_string(ch, COLOR_TEXT, VT102_BOLD));
	strcpy(colM, ansi_translate_text(ch, "{158}"));

	if (!ch->desc)
	{
		send_to_char( "You have no descriptor.\n\r", ch );
		pop_call();
		return;
	}

	if (ch->pcdata->edit_ptr && (help = ch->pcdata->edit_ptr)->area == NULL)
	{
		ch_printf_color(ch, "The help file you were editing is no longer valid.\n\r");
		stop_olc_editing(ch, ch->in_room->area);
		pop_call();
		return;
	}

	switch( ch->pcdata->editmode )
	{
		case MODE_HELP_EDIT:
			help = ch->pcdata->edit_ptr;

			STRFREE(help->text);
			help->text = copy_buffer(ch);
			stop_editing( ch );

			pop_call();
			return;
	}

	smash_tilde(argument);

	if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		help = ch->pcdata->edit_ptr;

		if (argument[0] == '?')
		{
			/*
				Show hedit status
			*/
			ch_printf_color(ch, "Syntax: <command> <value>\n\r\n\r");
			ch_printf_color(ch, "Command being one of:\n\r");
			ch_printf_color(ch, "  name desc level menu\n\r");
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "done"))
		{
			send_to_char( "Hedit mode off.\n\r", ch );

			stop_olc_editing(ch, help->area);
			save_area(help->area, TRUE);
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "cancel"))
		{
			send_to_char( "Hedit mode canceled, use COPYOVER to restore the old help.\n\r", ch );

			stop_olc_editing(ch, help->area);
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "stat"))
		{
			sprintf(txt, "%skeywords%s:%s %s\n\r", colg, colw, colW, help->keyword);
			cat_sprintf(txt, "%s   title%s:%s %s\n\r", colg, colw, colW, is_string(help->title) ? help->title : "(NULL)");
			cat_sprintf(txt, "%s   level%s:%s %d\n\r", colg, colw, colW, help->level);
			cat_sprintf(txt, "%s    desc%s:%s (Type DESC to edit...)\n\r", colg, colw, colW);
			for (menu = help->first_menu ; menu ; menu = menu->next)
			{
				cat_sprintf(txt, "%s    menu%s:%s %c %s%s\n\r", colg, colw, colM, menu->option, colW, menu->help->keyword);
			}
			send_to_char_color(txt, ch);
			pop_call();
			return;
		}
	}
	else if ((help = get_help(ch, argument)) == NULL)
	{
		send_to_char("Syntax: edit help <help keyword>\n\r", ch);
		pop_call();
		return;
	}
	else if (!IS_GOD(ch) && !can_olc_modify(ch, help->area->olc_range_lo))
	{
		send_to_char("That help file's area is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	if (ch->pcdata->editmode != MODE_REPEATCMD)
	{
		ch->pcdata->edit_ptr = help;
		ch->pcdata->edittype = EDIT_TYPE_HELP;
		ch->pcdata->editmode = MODE_REPEATCMD;

		if (ch->pcdata)
		{
			if (ch->pcdata->subprompt)
			{
				STRFREE(ch->pcdata->subprompt);
			}
			sprintf(arg, "Editing Help: %s", is_string(help->title) ? help->title : "(No Title)");
			ch->pcdata->subprompt = STRALLOC( arg );
		}
		do_hedit(ch, "stat");
		pop_call();
		return;
	}

	argument = one_argument(argument, arg);

	if (!strcasecmp(arg, "desc"))
	{
		ch->pcdata->editmode = MODE_HELP_EDIT;
		ch->pcdata->tempmode  = MODE_REPEATCMD;
		start_editing(ch, help->text);
		pop_call();
		return;
	}

	else if (!strcasecmp(arg, "level"))
	{
		help->level = URANGE(0, atoi(argument), MAX_LEVEL);
	}

	else if (!strcasecmp(arg, "keywords"))
	{
		if (argument[0] == '\0')
		{
			ch_printf_color(ch, "Syntax: name <help keywords>\n\r");
			pop_call();
			return;
		}
		STRFREE(help->keyword);
		help->keyword = STRALLOC(capitalize_all(argument));
	}

	else if (!strcasecmp(arg, "title"))
	{
		if (argument[0] == '\0')
		{
			RESTRING(help->title, "");
			pop_call();
			return;
		}
		STRFREE(help->title);
		help->title = STRALLOC(capitalize_title(argument));
	}

	else if (!strcasecmp(arg, "menu"))
	{
		if (argument[0] == '\0')
		{
			ch_printf_color(ch, "Syntax: menu <option> [keyword]\n\r");
			pop_call();
			return;
		}
		argument = one_argument(argument, arg);

		for (menu = help->first_menu ; menu ; menu = menu->next)
		{
			if (menu->option == arg[0])
			{
				break;
			}
		}
		if (menu)
		{
			if (argument[0] == '\0')
			{
				ch_printf_color(ch, "menu %c removed.\n\r", menu->option);
				UNLINK(menu, help->first_menu, help->last_menu, next, prev);
			}
			else
			{
				if (get_help(ch, argument))
				{
					menu->help = get_help(ch, argument);
				}
				else
				{
					ch_printf_color(ch, "help file: %s not found.\n\r", argument);
				}
			}
			pop_call();
			return;
		}
		else
		{
			if (argument[0] == '\0')
			{
				ch_printf_color(ch, "Syntax: menu <option> <help file>\n\r");
			}
			else
			{
				if (get_help(ch, argument))
				{
					ALLOCMEM(menu, HELP_MENU_DATA, 1);
					menu->option = arg[0];
					menu->help   = get_help(ch, argument);
					LINK(menu, help->first_menu, help->last_menu, next, prev);
				}
				else
				{
					ch_printf_color(ch, "help file: %s not found.\n\r", argument);
				}
			}
		}
	}

	else if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		ch->pcdata->editmode = MODE_RESTRICTED;
		interpret(ch, origarg);
		ch->pcdata->editmode = MODE_REPEATCMD;
		ch->pcdata->last_cmd = do_edit;
		pop_call();
		return;
	}
	
	do_hedit(ch, "stat");
	pop_call();
	return;
}

void do_sedit( CHAR_DATA *ch, char *argument )
{
	char arg [MAX_INPUT_LENGTH];
	int  iTrade, value;

	MOB_INDEX_DATA *mob;
	SHOP_DATA		*shop;

	char *origarg = argument;

	char colw[10], colg[10], colW[10], colM[10];

	push_call("do_sedit(%p,%p)",ch,argument);

	CHECK_EDITMODE( ch );

	strcpy(colw, get_color_string(ch, COLOR_TEXT, VT102_DIM));
	strcpy(colg, get_color_string(ch, COLOR_ACCENT, VT102_DIM));
	strcpy(colW, get_color_string(ch, COLOR_TEXT, VT102_BOLD));
	strcpy(colM, ansi_translate_text(ch, "{158}"));

	if (!ch->desc)
	{
		send_to_char( "You have no descriptor\n\r", ch );
		pop_call();
		return;
	}

	smash_tilde( argument );

	if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		shop = ch->pcdata->edit_ptr;

		if (argument[0] == '?')
		{
			/*
				Show edit status
			*/
			ch_printf_color(ch, "Syntax: <command> <value>\n\r\n\r");
			ch_printf_color(ch, "Command being one of:\n\r");
			ch_printf_color(ch, "  open close buy sell item flags done ?\n\r");
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "done"))
		{
			send_to_char( "Sedit mode off.\n\r", ch );

			stop_olc_editing(ch, get_mob_index(shop->keeper)->area);
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "stat"))
		{
			ch_printf_color(ch, "%s  open%s:%s %2d\n\r", colg, colw, colW, shop->open_hour);
			ch_printf_color(ch, "%s close%s:%s %2d\n\r", colg, colw, colW, shop->close_hour);
			ch_printf_color(ch, "%s   buy%s:%s %2d\n\r", colg, colw, colW, shop->profit_buy);
			ch_printf_color(ch, "%s  sell%s:%s %2d\n\r", colg, colw, colW, shop->profit_sell);
			ch_printf_color(ch, "%s flags%s:%s %s\n\r", colg, colw, colW, flag_string(shop->shop_flags, shop_flags));

			for (iTrade = 0 ; iTrade < MAX_TRADE ; iTrade++)
			{
				ch_printf_color(ch, "%s  item%s:%s %d %s%s\n\r", colg, colw, colM, iTrade+1, colW, type_string(shop->buy_type[iTrade], o_types));
			}
			pop_call();
			return;
		}
	}
	else
	{
		if ((mob = get_mob_index(atoi(argument))) == NULL)
		{
			send_to_char("Syntax: edit shop <mobile vnum>\n\r", ch);
			pop_call();
			return;
		}
		else if (!can_olc_modify(ch, mob->vnum))
		{
			send_to_char("That vnum is not in your allocated range.\n\r", ch);
			pop_call();
			return;
		}
		else if (mob->pShop == NULL)
		{
			ch_printf_color(ch, "Mobile %d is not a shop keeper.\n\r", mob->vnum);
			pop_call();
			return;
		}

		ch->pcdata->edit_ptr = mob->pShop;
		ch->pcdata->edittype = EDIT_TYPE_SHOP;

		ch->pcdata->editmode = MODE_REPEATCMD;

		if (ch->pcdata)
		{
			if (ch->pcdata->subprompt)
			{
				STRFREE(ch->pcdata->subprompt);
			}
			sprintf( arg, "Editing Shop Vnum: %d", mob->vnum );
			ch->pcdata->subprompt = STRALLOC( arg );
		}
		do_sedit(ch, "stat");
		pop_call();
		return;
	}

	shop		= ch->pcdata->edit_ptr;
	argument	= one_argument(argument, arg);
	value = atoi(argument);

	if (!strcasecmp(arg, "open"))
	{
		if (value < 0 || value > 23)
		{
			ch_printf_color(ch, "Syntax: open <0-23>\n\r");
			pop_call();
			return;
		}
		else
		{
			shop->open_hour = value;
		}
	}

	else if (!strcasecmp(arg, "close"))
	{
		if (value < 0 || value > 23)
		{
			ch_printf_color(ch, "Syntax: close <0-23>\n\r");
			pop_call();
			return;
		}
		else
		{
			shop->close_hour = value;
		}
	}

	else if (!strcasecmp(arg, "buy"))
	{
		if (value < 100 || value > 200)
		{
			ch_printf_color(ch, "Syntax: buy <percentage> (100-200)\n\r");
			pop_call();
			return;
		}
		else
		{
			shop->profit_buy = value;
		}
	}

	else if (!strcasecmp(arg, "sell"))
	{
		if (value < 1 || value > 50)
		{
			ch_printf_color(ch, "Syntax: sell <percentage> (1-50)\n\r");
			pop_call();
			return;
		}
		else
		{
			shop->profit_sell = value;
		}
	}

	else if (!strcasecmp(arg, "trade"))
	{
		argument = one_argument(argument, arg);
		value = atoi(arg);

		if (value < 1 || value > 5)
		{
			ch_printf_color(ch, "Syntax: trade <1-5> <item type>\n\r");
			pop_call();
			return;
		}
		if (get_flag(argument, o_types) == -1)
		{
			sprintf(arg, "Syntax: trade <index> <%s>", give_flags(o_types));
			ch_printf_color(ch, "%s\n\r", justify(arg, get_page_width(ch)));
			pop_call();
			return;
		}
		shop->buy_type[value - 1] = get_flag(argument, o_types);
	}

	else if (!strcasecmp(arg, "flags"))
	{
		if (*argument == '\0')
		{
			ch_printf_color(ch, "Syntax: flags <%s>\n\r", give_flags(shop_flags));
			pop_call();
			return;
		}
		while (*argument != '\0')
		{
			argument = one_argument(argument, arg);
			
			if ((value = get_flag(arg, shop_flags)) == -1)
			{
				ch_printf_color(ch, "%s is not a valid shop flag\n\r", arg);
			}
			else
			{
				TOGGLE_BIT(shop->shop_flags, 1LL << value);
			}
		}
	}

	else if ( ch->pcdata->editmode == MODE_REPEATCMD )
	{
		ch->pcdata->editmode = MODE_RESTRICTED;
		interpret( ch, origarg );
		ch->pcdata->editmode = MODE_REPEATCMD;
		ch->pcdata->last_cmd = do_edit;
		pop_call();
		return;
	}

	do_sedit(ch, "stat");
	pop_call();
	return;
}

void do_inn_edit( CHAR_DATA *ch, char *argument )
{
	char arg [MAX_INPUT_LENGTH];
	char arg2 [MAX_INPUT_LENGTH];

	MOB_INDEX_DATA *mob;
	INN_DATA		*inn;
	int iRoom, value;

	char *origarg = argument;

	char colw[10], colg[10], colW[10], colM[10];

	push_call("do_inn_edit(%p,%p)",ch,argument);

	CHECK_EDITMODE( ch );

	strcpy(colw, get_color_string(ch, COLOR_TEXT, VT102_DIM));
	strcpy(colg, get_color_string(ch, COLOR_ACCENT, VT102_DIM));
	strcpy(colW, get_color_string(ch, COLOR_TEXT, VT102_BOLD));
	strcpy(colM, ansi_translate_text(ch, "{158}"));

	if (!ch->desc)
	{
		send_to_char( "You have no descriptor\n\r", ch );
		pop_call();
		return;
	}

	smash_tilde( argument );

	if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		inn = ch->pcdata->edit_ptr;

		if (argument[0] == '?')
		{
			/*
				Show edit status
			*/
			ch_printf_color(ch, "Syntax: <command> <value>\n\r\n\r");
			ch_printf_color(ch, "Command being one of:\n\r");
			ch_printf_color(ch, "  open close rent vnum done ?\n\r");
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "done"))
		{
			send_to_char( "Inn edit mode off.\n\r", ch );

			stop_olc_editing(ch, get_mob_index(inn->keeper)->area);
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "stat"))
		{
			ch_printf_color(ch, "%s  open%s:%s %2d\n\r", colg, colw, colW, inn->open_hour);
			ch_printf_color(ch, "%s close%s:%s %2d\n\r", colg, colw, colW, inn->close_hour);
			ch_printf_color(ch, "%s flags%s:%s %s\n\r", colg, colw, colW, flag_string(inn->shop_flags, shop_flags));
			for (iRoom = 0 ; iRoom < MAX_INN_ROOMS ; iRoom++)
			{
				ch_printf_color(ch, "%s  room%s:%s %d %s%-7d %s%d\n\r", colg, colw, colM, iRoom+1, colW, inn->room[iRoom], colw, inn->rent[iRoom]);
			}
			pop_call();
			return;
		}
	}
	else
	{
		if ((mob = get_mob_index(atoi(argument))) == NULL)
		{
			send_to_char("Syntax: edit inn <mobile vnum>\n\r", ch);
			pop_call();
			return;
		}
		else if (!can_olc_modify(ch, mob->vnum))
		{
			send_to_char("That vnum is not in your allocated range.\n\r", ch);
			pop_call();
			return;
		}
		else if (mob->pInn == NULL)
		{
			ch_printf_color(ch, "Mobile %d is not a inn keeper.\n\r", mob->vnum);
			ch_printf_color(ch, "Use edit inn create to make it one.\n\r");
			pop_call();
			return;
		}

		ch->pcdata->edit_ptr = mob->pInn;
		ch->pcdata->edittype = EDIT_TYPE_INN;

		ch->pcdata->editmode = MODE_REPEATCMD;

		if (ch->pcdata)
		{
			if (ch->pcdata->subprompt)
			{
				STRFREE(ch->pcdata->subprompt);
			}
			sprintf( arg, "Editing Inn Vnum: %d", mob->vnum );
			ch->pcdata->subprompt = STRALLOC( arg );
		}
		do_inn_edit(ch, "stat");
		pop_call();
		return;
	}

	inn		= ch->pcdata->edit_ptr;
	argument	= one_argument(argument, arg);
	value = atol(argument);

	if (!strcasecmp(arg, "open"))
	{
		if (value < 0 || value > 23)
		{
			ch_printf_color(ch, "Syntax: open <0-23>\n\r");
			pop_call();
			return;
		}
		else
		{
			inn->open_hour = URANGE(0, atoi(argument), 23);
		}
	}

	else if (!strcasecmp(arg, "close"))
	{
		if (value < 0 || value > 23)
		{
			ch_printf_color(ch, "Syntax: close <0-23>\n\r");
			pop_call();
			return;
		}
		else
		{
			inn->close_hour = URANGE(0, atoi(argument), 23);
		}
	}

	else if (!strcasecmp(arg, "room"))
	{
		argument = one_argument(argument, arg);
		value = atoi(arg);

		if (value < 1 || value > 5)
		{
			ch_printf_color(ch, "Syntax: room <1-5> <room vnum> <rent in copper>\n\r");
			pop_call();
			return;
		}
		argument = one_argument(argument, arg2);

		if (!is_number(arg2) || !is_number(argument))
		{
			ch_printf_color(ch, "Syntax: room <1-5> <room vnum> <rent in copper>\n\r");
			pop_call();
			return;
		}
		if (room_index[atoi(arg2)] == NULL)
		{
			ch_printf_color(ch, "no room exists with that vnum!\n\r");
			pop_call();
			return;
		}
		inn->room[value - 1] = atoi(arg2);
		inn->rent[value - 1] = atoi(argument);
	}

	else if (!strcasecmp(arg, "flags"))
	{
		if (*argument == '\0')
		{
			ch_printf_color(ch, "Syntax: flags <%s>\n\r", give_flags(shop_flags));
			pop_call();
			return;
		}
		while (*argument != '\0')
		{
			argument = one_argument(argument, arg);
			
			if ((value = get_flag(arg, shop_flags)) == -1)
			{
				ch_printf_color(ch, "%s is not a valid shop flag\n\r", arg);
			}
			else
			{
				TOGGLE_BIT(inn->shop_flags, 1LL << value);
			}
		}
	}

	else if ( ch->pcdata->editmode == MODE_REPEATCMD )
	{
		ch->pcdata->editmode = MODE_RESTRICTED;
		interpret( ch, origarg );
		ch->pcdata->editmode = MODE_REPEATCMD;
		ch->pcdata->last_cmd = do_edit;
		pop_call();
		return;
	}

	do_inn_edit(ch, "stat");
	pop_call();
	return;
}

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

	MOB_INDEX_DATA *mob;
	STABLE_DATA		*stable;

	char *origarg = argument;

	char colw[10], colg[10], colW[10], colM[10];

	push_call("do_stable_edit(%p,%p)",ch,argument);

	CHECK_EDITMODE( ch );

	strcpy(colw, get_color_string(ch, COLOR_TEXT, VT102_DIM));
	strcpy(colg, get_color_string(ch, COLOR_ACCENT, VT102_DIM));
	strcpy(colW, get_color_string(ch, COLOR_TEXT, VT102_BOLD));
	strcpy(colM, ansi_translate_text(ch, "{158}"));

	if (!ch->desc)
	{
		send_to_char( "You have no descriptor\n\r", ch );
		pop_call();
		return;
	}

	smash_tilde( argument );

	if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		stable = ch->pcdata->edit_ptr;

		if (argument[0] == '?')
		{
			/*
				Show edit status
			*/
			ch_printf_color(ch, "Syntax: <command> <value>\n\r\n\r");
			ch_printf_color(ch, "Command being one of:\n\r");
			ch_printf_color(ch, "  open close rent vnum done ?\n\r");
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "done"))
		{
			send_to_char( "Stable edit mode off.\n\r", ch );

			stop_olc_editing(ch, get_mob_index(stable->keeper)->area);
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "stat"))
		{
			sprintf(buf, "%sStable %s(%d - %s)\n\r", colg, colW, stable->keeper, get_mob_index(stable->keeper)->player_name);
			cat_sprintf(buf, "%s  vnum%s:%s %d %s(vnum of storage room)\n\r", colg, colw, colW, stable->room, colw);
			cat_sprintf(buf, "%s  open%s:%s %2d\n\r", colg, colw, colW, stable->open_hour);
			cat_sprintf(buf, "%s close%s:%s %2d\n\r", colg, colw, colW, stable->close_hour);
			cat_sprintf(buf, "%s  rent%s:%s %d %s(amount in copper)\n\r", colg, colw, colW, stable->rent, colw);
			cat_sprintf(buf, "%s flags%s:%s %s\n\r", colg, colw, colW, flag_string(stable->shop_flags, shop_flags));
			send_to_char_color(buf, ch);
			pop_call();
			return;
		}
	}
	else
	{
		if ((mob = get_mob_index(atoi(argument))) == NULL)
		{
			send_to_char("Syntax: edit stable <mobile vnum>\n\r", ch);
			pop_call();
			return;
		}
		else if (!can_olc_modify(ch, mob->vnum))
		{
			send_to_char("That vnum is not in your allocated range.\n\r", ch);
			pop_call();
			return;
		}
		else if (mob->pStable == NULL)
		{
			ch_printf_color(ch, "Mobile %d is not a stable keeper.\n\r", mob->vnum);
			pop_call();
			return;
		}

		ch->pcdata->edit_ptr = mob->pStable;
		ch->pcdata->edittype = EDIT_TYPE_STABLE;

		ch->pcdata->editmode = MODE_REPEATCMD;

		if (ch->pcdata)
		{
			if (ch->pcdata->subprompt)
			{
				STRFREE(ch->pcdata->subprompt);
			}
			sprintf( arg, "Editing Stable Vnum: %d", mob->vnum );
			ch->pcdata->subprompt = STRALLOC( arg );
		}
		do_stable_edit(ch, "stat");
		pop_call();
		return;
	}

	stable		= ch->pcdata->edit_ptr;
	argument	= one_argument(argument, arg);
	int value = atol(argument);

	if (!strcasecmp(arg, "open"))
	{
		if (value < 0 || value > 23)
		{
			ch_printf_color(ch, "Syntax: open <0-23>\n\r");
			pop_call();
			return;
		}
		else
		{
			stable->open_hour = value;
		}
	}

	else if (!strcasecmp(arg, "close"))
	{
		if (value < 0 || value > 23)
		{
			ch_printf_color(ch, "Syntax: close <0-23>\n\r");
			pop_call();
			return;
		}
		else
		{
			stable->close_hour = value;
		}
	}

	else if (!strcasecmp(arg, "rent"))
	{
		if (value <= 0)
		{
			ch_printf_color(ch, "Syntax: rent <amount in copper>\n\r");
			pop_call();
			return;
		}
		else
		{
			stable->rent = value;
		}
	}

	else if (!strcasecmp(arg, "vnum"))
	{
		if (value <= 0)
		{
			ch_printf_color(ch, "Syntax: vnum <vnum of storeroom>\n\r");
		}
		else if (get_room_index(value) == NULL)
		{
			ch_printf_color(ch, "no room exists with that vnum!\n\r");
		}
		else if (!can_olc_modify(ch, value))
		{
			send_to_char("That vnum is not in your allocated range.\n\r", ch);
		}
		else
		{
			stable->room = value;
		}
	}

	else if (!strcasecmp(arg, "flags"))
	{
		if (*argument == '\0')
		{
			ch_printf_color(ch, "Syntax: flags <%s>\n\r", give_flags(shop_flags));
			pop_call();
			return;
		}
		while (*argument != '\0')
		{
			argument = one_argument(argument, arg);
			
			if ((value = get_flag(arg, shop_flags)) == -1)
			{
				ch_printf_color(ch, "%s is not a valid shop flag\n\r", arg);
			}
			else
			{
				SET_BIT(stable->shop_flags, 1 << value);
			}
		}
	}

	else if ( ch->pcdata->editmode == MODE_REPEATCMD )
	{
		ch->pcdata->editmode = MODE_RESTRICTED;
		interpret( ch, origarg );
		ch->pcdata->editmode = MODE_REPEATCMD;
		ch->pcdata->last_cmd = do_edit;
		pop_call();
		return;
	}
	
	do_stable_edit(ch, "stat");
	pop_call();
	return;
}

void do_aedit( CHAR_DATA *ch, char *argument )
{
	AREA_DATA *area;
	char arg[MAX_INPUT_LENGTH];
	char buf[MAX_STRING_LENGTH];
	char *origarg = argument;
	int value;

	char colw[10], colg[10], colW[10], colM[10];

	push_call("do_aedit(%p,%p)",ch,argument);

	CHECK_EDITMODE( ch );

	strcpy(colw, get_color_string(ch, COLOR_TEXT, VT102_DIM));
	strcpy(colg, get_color_string(ch, COLOR_ACCENT, VT102_DIM));
	strcpy(colW, get_color_string(ch, COLOR_TEXT, VT102_BOLD));
	strcpy(colM, ansi_translate_text(ch, "{158}"));

	if (!ch->desc)
	{
		send_to_char( "You have no descriptor\n\r", ch );
		pop_call();
		return;
	}

	area = NULL;
	smash_tilde( argument );

	if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		area = ch->pcdata->edit_ptr;

		if (argument[0] == '?')
		{
			/*
				Show edit status
			*/
			ch_printf_color(ch, "Syntax: <command> <value>\n\r");
			ch_printf_color(ch, "Command being one of:\n\r");
			ch_printf_color(ch, "  name author popmsg flags softlo softhi hardlo hardhi done ?\n\r");
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "done"))
		{
			send_to_char( "Aedit mode off.\n\r", ch );

			stop_olc_editing(ch, area);

			pop_call();
			return;
		}

		if (!strcasecmp(argument, "stat"))
		{
			sprintf(buf, "%s   name%s:%s %s\n\r", colg, colw, colW, area->name);
			cat_sprintf(buf, "%s author%s:%s %s\n\r", colg, colw, colW, area->authors);
			cat_sprintf(buf, "%s popmsg%s:%s %s\n\r", colg, colw, colW, area->resetmsg);
			cat_sprintf(buf, "%s  flags%s:%s %s\n\r", colg, colw, colW, flag_string(area->flags, area_flags));
			if (IS_SET(area->flags, AFLAG_WEATHER))
			{
				cat_sprintf(buf, "%s   wind%s:%s %-3d    ", colg, colw, colW, area->weather_info->wind_scale);
				cat_sprintf(buf, "%s   rain%s:%s %-3d    ", colg, colw, colW, area->weather_info->wet_scale);
				cat_sprintf(buf, "%s winter%s:%s %-3d    ", colg, colw, colW, area->weather_info->temp_winter);
				cat_sprintf(buf, "%s summer%s:%s %-3d    ", colg, colw, colW, area->weather_info->temp_summer);
				cat_sprintf(buf, "%s  daily%s:%s %-3d\n\r", colg, colw, colW, area->weather_info->temp_daily);
			}
			cat_sprintf(buf, "%s softlo%s:%s %-3d    ", colg, colw, colW, area->low_soft_range);
			cat_sprintf(buf, "%s softhi%s:%s %-3d    ", colg, colw, colW, area->hi_soft_range);
			cat_sprintf(buf, "%s hardlo%s:%s %-3d    ", colg, colw, colW, area->low_hard_range);
			cat_sprintf(buf, "%s hardhi%s:%s %-3d\n\r", colg, colw, colW, area->hi_hard_range);
			if (IS_GOD(ch))
			{
				cat_sprintf(buf, "%s  olclo%s:%s %-8d     ", colg, colw, colW, area->olc_range_lo);
				cat_sprintf(buf, "%s  olchi%s:%s %-8d\n\r", colg, colw, colW, area->olc_range_hi);
			}
			cat_sprintf(buf, "%scourtrm%s:%s %d %s(%s)\n\r", colg, colw, colW, area->courtroom, colw, !area->courtroom ? "None" : room_index[area->courtroom] == NULL ? "Error: NULL room" : room_index[area->courtroom]->name);
			cat_sprintf(buf, "%sdungeon%s:%s %d %s(%s)\n\r", colg, colw, colW, area->dungeon, colw, !area->dungeon ? "None" : room_index[area->dungeon] == NULL ? "Error: NULL room" : room_index[area->dungeon]->name);
			cat_sprintf(buf, "%simpound%s:%s %d %s(%s)\n\r", colg, colw, colW, area->storeroom, colw, !area->storeroom ? "None" : room_index[area->storeroom] == NULL ? "Error: NULL room" : room_index[area->storeroom]->name);
			cat_sprintf(buf, "%s  judge%s:%s %d %s(%s)\n\r", colg, colw, colW, area->judge, colw, !area->judge ? "None" : mob_index[area->judge] == NULL ? "Error: NULL mobile" : mob_index[area->judge]->player_name);
			cat_sprintf(buf, "%s  guard%s:%s %d %s(%s)\n\r", colg, colw, colW, area->guard, colw, !area->guard ? "None" : mob_index[area->guard] == NULL ? "Error: NULL mobile" : mob_index[area->guard]->player_name);
			cat_sprintf(buf, "%s  theft%s:%s %s\n\r", colg, colw, colW, punishment_flags[area->punishment[CRIME_MUGGING]]);
			cat_sprintf(buf, "%sassault%s:%s %s\n\r", colg, colw, colW, punishment_flags[area->punishment[CRIME_ASSAULT]]);
			cat_sprintf(buf, "%s  mkill%s:%s %s\n\r", colg, colw, colW, punishment_flags[area->punishment[CRIME_LOW_MURDER]]);
			cat_sprintf(buf, "%s  pkill%s:%s %s\n\r", colg, colw, colW, punishment_flags[area->punishment[CRIME_HIGH_MURDER]]);
			send_to_char_color(buf, ch);
			pop_call();
			return;
		}
	}
	else
	{
		if (argument[0] == '\0')
		{
			area = ch->in_room->area;
		}
		else
		{
			area = lookup_area(argument);
		}

		if (area  == NULL)
		{
			ch_printf_color(ch, "Area: %s not found.\n\r", argument);
			pop_call();
			return;
		}
		else
		{
			if (!can_olc_modify(ch, area->olc_range_lo))
			{
				send_to_char("This area is not in your allocated vnum range.\n\r", ch);
				pop_call();
				return;
			}
		}
	}

	if (ch->pcdata->editmode != MODE_REPEATCMD)
	{
		ch->pcdata->edittype = EDIT_TYPE_AREA;
		ch->pcdata->edit_ptr = area;

		ch->pcdata->editmode = MODE_REPEATCMD;

		if (ch->pcdata)
		{
			if (ch->pcdata->subprompt)
			{
				STRFREE(ch->pcdata->subprompt);
			}
			sprintf( arg, "Editing Area: %s", area->name);
			ch->pcdata->subprompt = STRALLOC( arg );
		}
		do_aedit(ch, "stat");
		pop_call();
		return;
	}

	area		= ch->pcdata->edit_ptr;
	argument	= one_argument(argument, arg);
	value = is_number(argument) ? atoi(argument) : -1;


	if (!strcasecmp(arg, "name"))
	{
		RESTRING(area->name, argument);
	}
	else if (!strcasecmp(arg, "author"))
	{
		RESTRING(area->authors, argument);
	}
	else if (!strcasecmp(arg, "popmsg"))
	{
		RESTRING(area->resetmsg, argument);
	}
	else if ( !strcasecmp( arg, "flags" ) )
	{
		if (*argument == '\0')
		{
			ch_printf_color(ch, "Syntax: flag <%s>\n\r", give_flags(area_flags));
			pop_call();
			return;
		}
		while (*argument != '\0')
		{
			argument = one_argument(argument, arg);

			if ((value = get_flag(arg, area_flags)) == -1)
			{
				ch_printf_color(ch, "%s is not a valid area flag.\n\r", arg);
			}
			else
			{
				TOGGLE_BIT(area->flags, 1LL << value);
			}
		}
	}
	else if (!strcasecmp(arg, "courtrm"))
	{
		if (room_index[value] == NULL)
		{
			ch_printf_color(ch, "%d is not a valid room.\n\r", value);
			area->courtroom = 0;
		}
		else
		{
			area->courtroom = value;
		}
	}
	else if (!strcasecmp(arg, "dungeon"))
	{
		if (room_index[value] == NULL)
		{
			ch_printf_color(ch, "%d is not a valid room.\n\r", value);
			area->dungeon = 0;
		}
		else
		{
			area->dungeon = value;
		}
	}
	else if (!strcasecmp(arg, "impound"))
	{
		if (room_index[value] == NULL)
		{
			ch_printf_color(ch, "%d is not a valid room.\n\r", value);
			area->storeroom = 0;
		}
		else
		{
			area->storeroom = value;
		}
	}
	else if (!strcasecmp(arg, "judge"))
	{
		if (mob_index[value] == NULL)
		{
			ch_printf_color(ch, "%d is not a valid mobile.\n\r", value);
			area->judge = 0;
		}
		else
		{
			area->judge = value;
		}
	}
	else if (!strcasecmp(arg, "guard"))
	{
		if (mob_index[value] == NULL)
		{
			ch_printf_color(ch, "%d is not a valid mobile.\n\r", value);
			area->guard = 0;
		}
		else
		{
			area->guard = value;
		}
	}
	else if (!strcasecmp(arg, "theft"))
	{
		if ((value = get_flag(argument, punishment_flags)) == -1)
		{
			ch_printf_color(ch, "%s is not a valid punishment.\n\r", argument);
			area->punishment[CRIME_MUGGING] = 0;
		}
		else
		{
			area->punishment[CRIME_MUGGING] = value;
		}
	}
	else if (!strcasecmp(arg, "assault"))
	{
		if ((value = get_flag(argument, punishment_flags)) == -1)
		{
			ch_printf_color(ch, "%s is not a valid punishment.\n\r", argument);
			area->punishment[CRIME_ASSAULT] = 0;
		}
		else
		{
			area->punishment[CRIME_ASSAULT] = value;
		}
	}
	else if (!strcasecmp(arg, "mkill"))
	{
		if ((value = get_flag(argument, punishment_flags)) == -1)
		{
			ch_printf_color(ch, "%s is not a valid punishment.\n\r", argument);
			area->punishment[CRIME_LOW_MURDER] = 0;
		}
		else
		{
			area->punishment[CRIME_LOW_MURDER] = value;
		}
	}
	else if (!strcasecmp(arg, "pkill"))
	{
		if ((value = get_flag(argument, punishment_flags)) == -1)
		{
			ch_printf_color(ch, "%s is not a valid punishment.\n\r", argument);
			area->punishment[CRIME_HIGH_MURDER] = 0;
		}
		else
		{
			area->punishment[CRIME_HIGH_MURDER] = value;
		}
	}
	else if (!strcasecmp(arg, "softlo"))
	{
		area->low_soft_range = URANGE(1, value, 95);
	}
	else if (!strcasecmp(arg, "softhi"))
	{
		area->hi_soft_range = URANGE(1, value, 95);
	}
	else if (!strcasecmp(arg, "hardlo"))
	{
		if (IS_GOD(ch))
		{
			area->low_hard_range = URANGE(1, value, 100);
		}
		else
		{
			area->low_hard_range = URANGE(1, value, 95);
		}
	}
	else if (!strcasecmp(arg, "hardhi"))
	{
		if (IS_GOD(ch))
		{
			area->hi_hard_range = URANGE(1, value, 100);
		}
		else
		{
			area->hi_hard_range = URANGE(1, value, 95);
		}
	}
	else if (!strcasecmp(arg, "wind"))
	{
		area->weather_info->wind_scale = URANGE(0, value, 10);
	}
	else if (!strcasecmp(arg, "rain"))
	{
		area->weather_info->wet_scale = URANGE(0, value, 10);
	}
	else if (!strcasecmp(arg, "winter"))
	{
		area->weather_info->temp_winter = URANGE(-100, value, 100);
	}
	else if (!strcasecmp(arg, "summer"))
	{
		area->weather_info->temp_summer = URANGE(-100, value, 100);
	}
	else if (!strcasecmp(arg, "daily"))
	{
		area->weather_info->temp_daily = URANGE(0, value, 50);
	}
	else if (IS_GOD(ch) && !strcasecmp(arg, "olclo"))
	{
		area->olc_range_lo = URANGE(1, value, MAX_VNUM-1);
	}
	else if (IS_GOD(ch) && !strcasecmp(arg, "olchi"))
	{
		area->olc_range_hi = URANGE(0, value, MAX_VNUM-1);
	}
	else if (IS_GOD(ch) && !strcasecmp(arg, "setfilename"))
	{
		RESTRING(area->filename, argument);
	}
	else if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		ch->pcdata->editmode = MODE_RESTRICTED;
		interpret( ch, origarg );
		ch->pcdata->editmode = MODE_REPEATCMD;
		ch->pcdata->last_cmd = do_edit;
		pop_call();
		return;
	}
	
	do_aedit(ch, "stat");
	pop_call();
	return;
}


void do_opedit( CHAR_DATA *ch, char *argument )
{
	char arg [MAX_INPUT_LENGTH];
	char buf [MAX_INPUT_LENGTH];

	int  value, cnt, type;

	OBJ_INDEX_DATA *obj;
	MPROG_DATA	*prog,  *prog2;
	NPC_TOKEN		*token;

	char *origarg = argument;

	char colw[10], colg[10], colW[10], colM[10];

	push_call("do_opedit(%p,%p)",ch,argument);

	CHECK_EDITMODE( ch );

	strcpy(colw, get_color_string(ch, COLOR_TEXT, VT102_DIM));
	strcpy(colg, get_color_string(ch, COLOR_ACCENT, VT102_DIM));
	strcpy(colW, get_color_string(ch, COLOR_TEXT, VT102_BOLD));
	strcpy(colM, ansi_translate_text(ch, "{158}"));

	if (!ch->desc)
	{
		send_to_char( "You have no descriptor\n\r", ch );
		pop_call();
		return;
	}

	obj = NULL;
	smash_tilde( argument );

	switch( ch->pcdata->editmode )
	{
		case MODE_OPROG_EDIT:
			if (ch->pcdata->edit_ptr && ch->pcdata->temp_ptr)
			{
				obj  = ch->pcdata->edit_ptr;
				prog = ch->pcdata->temp_ptr;
				STRFREE(prog->comlist);
				prog->comlist = copy_buffer(ch);
				stop_editing( ch );

				if (strstr(prog->comlist, "$r") != NULL)
				{
					SET_BIT(prog->flags, MPTRIGGER_RAND_PLR);
				}
				else
				{
					REMOVE_BIT(prog->flags, MPTRIGGER_RAND_PLR);
				}

				while ((token = prog->first_token) != NULL)
				{
					UNLINK(token, prog->first_token, prog->last_token, next, prev);
					STRFREE(token->string);
					FREEMEM(token);
				}
				expand_mob_prog(NULL, obj, NULL, prog);
				do_opedit(ch, "stat");
			}
			else
			{
				log_printf("do_opedit: null edit_ptr or temp_ptr");
				ch->pcdata->tempmode = MODE_NONE;
				stop_editing(ch);
			}
			pop_call();
			return;
	}

	if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		obj = ch->pcdata->edit_ptr;

		if (argument[0] == '?')
		{
			/*
				Show opedit status
			*/
			ch_printf_color(ch, "Syntax: <command> <value>\n\r\n\r");
			ch_printf_color(ch, "Command being one of:\n\r");
			ch_printf_color(ch, "  add del set edit done stat ? < >\n\r");
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "done"))
		{
			send_to_char( "oprog edit mode off.\n\r", ch );

			stop_olc_editing(ch, obj->area);

			pop_call();
			return;
		}

		if (!strcmp(argument, ">"))
		{
			if (get_obj_index(obj->vnum + 1) && can_olc_modify(ch, obj->vnum + 1))
			{
				stop_olc_editing(ch, obj->area);
				sprintf(buf, "%d", obj->vnum + 1);
				do_opedit(ch, buf);
			}
			else
			{
				ch_printf_color(ch, "Next index not found.\n\r");
			}
			pop_call();
			return;
		}

		if (!strcmp(argument, "<"))
		{
			if (get_obj_index(obj->vnum - 1) && can_olc_modify(ch, obj->vnum - 1))
			{
				stop_olc_editing(ch, obj->area);
				sprintf(buf, "%d", obj->vnum - 1);
				do_opedit(ch, buf);
			}
			else
			{
				ch_printf_color(ch, "Prev index not found.\n\r");
			}
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "stat"))
		{
			*buf = '\0';
			for (cnt = 0, prog = obj->first_prog ; prog ; prog = prog->next)
			{
				cat_sprintf(buf, "{178}%2d{078}] {138}%s {128}%s\n\r", ++cnt, mprog_type_to_name(prog->type), prog->arglist);
			}
			if (obj->first_prog == NULL)
			{
				cat_sprintf(buf, "This object does not have any programs defined.\n\r");
			}
			cat_sprintf(buf, "Syntax: <field> <value>                        < %sprev next %s>\n\r", colg, colW);
			send_to_char_color(buf, ch);
			pop_call();
			return;
		}
	}	
	else if ((obj = get_obj_index(atoi(argument))) == NULL)
	{
		send_to_char("Syntax: edit oprog <object vnum>\n\r", ch);
		pop_call();
		return;
	}
	else if (!can_olc_modify(ch, obj->vnum))
	{
		send_to_char("That vnum is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	argument = one_argument(argument, arg);

	if (ch->pcdata->editmode != MODE_REPEATCMD)
	{
		ch->pcdata->edit_ptr = obj;
		ch->pcdata->edittype = EDIT_TYPE_OPROG;

		ch->pcdata->editmode = MODE_REPEATCMD;

		if (ch->pcdata)
		{
			if (ch->pcdata->subprompt)
			{
				STRFREE(ch->pcdata->subprompt);
			}
			sprintf( arg, "Editing Oprog Vnum: %d", obj->vnum );
			ch->pcdata->subprompt = STRALLOC( arg );
			do_opedit(ch, "stat");
		}
		pop_call();
		return;
	}

	if (!strcasecmp(arg, "del"))
	{
		if ((value = atoi(argument)) < 1)
		{
			ch_printf_color(ch, "Syntax: del <index>\n\r");
			pop_call();
			return;
		}
		else
		{
			for (cnt = 0, prog = obj->first_prog ; prog ; prog = prog->next)
			{
				if (++cnt == value)
				{
					break;
				}
			}
			if (prog)
			{
				UNLINK(prog, obj->first_prog, obj->last_prog, next, prev);

				for (obj->progtypes = 0, prog = obj->first_prog ; prog ; prog = prog->next)
				{
					SET_BIT(obj->progtypes, prog->type);
				}
			}
			else
			{
				ch_printf_color(ch, "Index %d not found.\n\r", value);
				pop_call();
				return;
			}
		}
	}

	else if (!strcasecmp(arg, "add"))
	{
		argument = one_argument(argument, arg);

		if ((value = atoi(arg)) < 1)
		{
			ch_printf_color(ch, "Syntax: add <index> <trigger> [argument]\n\r");
			pop_call();
			return;
		}

		argument = one_argument(argument, arg);

		if ((type = get_flag(arg, oprog_flags)) == -1)
		{
			ch_printf_color(ch, "add <index> <%s>\n\r", give_flags(oprog_flags));
			pop_call();
			return;
		}

		ALLOCMEM(prog, MPROG_DATA, 1);

		prog->type	= 1LL << type;
		prog->arglist	= STRALLOC(argument);
		prog->comlist  = STRALLOC("");

		for (cnt = 0, prog2 = obj->first_prog ; prog2 ; prog2 = prog2->next)
		{
			if (++cnt == value)
			{
				break;
			}
		}
		if (prog2)
		{
			INSERT_LEFT(prog, prog2, obj->first_prog, next, prev);
		}
		else
		{
			LINK(prog, obj->first_prog, obj->last_prog, next, prev);
		}
		SET_BIT(obj->progtypes, prog->type);
	}

	else if (!strcasecmp(arg, "set"))
	{
		argument = one_argument(argument, arg);

		if ((value = atoi(arg)) < 1)
		{
			ch_printf_color(ch, "Syntax: set <index> <trigger> <argument>\n\r");
			ch_printf_color(ch, "Syntax: set <index> <arglist> <argument>\n\r");
			pop_call();
			return;
		}

		for (cnt = 0, prog = obj->first_prog ; prog ; prog = prog->next)
		{
			if (++cnt == value)
			{
				break;
			}
		}

		if (prog == NULL)
		{
			ch_printf_color(ch, "Index %d not found.\n\r", value);
			pop_call();
			return;
		}

		argument = one_argument(argument, arg);

		if (!strcasecmp(arg, "trigger"))
		{
			if ((type = get_flag(argument, oprog_flags)) == -1)
			{
				ch_printf_color(ch, "set <index> trigger <%s>\n\r", give_flags(oprog_flags));
				pop_call();
				return;
			}
			else
			{
				prog->type = 1LL << type;

				for (obj->progtypes = 0, prog = obj->first_prog ; prog ; prog = prog->next)
				{
					SET_BIT(obj->progtypes, prog->type);
				}
			}
		}

		else if (!strcasecmp(arg, "arglist"))
		{
			RESTRING(prog->arglist, argument);
		}
		else
		{
			ch_printf_color(ch, "Syntax: set <index> <trigger> <argument>\n\r");
			ch_printf_color(ch, "Syntax: set <index> <arglist> <argument>\n\r");
			pop_call();
			return;
		}
	}

	else if (!strcasecmp(arg, "edit"))
	{
		if ((value = atoi(argument)) < 1)
		{
			ch_printf_color(ch, "Syntax: edit <index>\n\r");
			pop_call();
			return;
		}

		for (cnt = 0, prog = obj->first_prog ; prog ; prog = prog->next)
		{
			if (++cnt == value)
			{
				break;
			}
		}

		if (prog == NULL)
		{
			ch_printf_color(ch, "Index %d not found.\n\r", value);
			pop_call();
			return;
		}

		if (prog->comlist)
		{
			STRFREE(prog->comlist);
		}
		prog->comlist = STRALLOC(fixer_mprog(prog));

		ch->pcdata->temp_ptr = prog;

		ch->pcdata->editmode = MODE_OPROG_EDIT;
		ch->pcdata->tempmode = MODE_REPEATCMD;

		start_editing(ch, prog->comlist);
		pop_call();
		return;
	}

	else if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		ch->pcdata->editmode = MODE_RESTRICTED;
		interpret( ch, origarg );
		ch->pcdata->editmode = MODE_REPEATCMD;
		ch->pcdata->last_cmd = do_edit;
		pop_call();
		return;
	}

	do_opedit(ch, "stat");
	pop_call();
	return;
}

void do_mpedit( CHAR_DATA *ch, char *argument )
{
	char arg [MAX_INPUT_LENGTH];
	char buf [MAX_INPUT_LENGTH];

	int  value, cnt, type;

	MOB_INDEX_DATA *mob;
	MPROG_DATA	*prog,  *prog2;
	NPC_TOKEN		*token;

	char *origarg = argument;

	char colw[10], colg[10], colW[10], colM[10];

	push_call("do_mpedit(%p,%p)",ch,argument);

	CHECK_EDITMODE( ch );

	strcpy(colw, get_color_string(ch, COLOR_TEXT, VT102_DIM));
	strcpy(colg, get_color_string(ch, COLOR_ACCENT, VT102_DIM));
	strcpy(colW, get_color_string(ch, COLOR_TEXT, VT102_BOLD));
	strcpy(colM, ansi_translate_text(ch, "{158}"));

	if (!ch->desc)
	{
		send_to_char( "You have no descriptor\n\r", ch );
		pop_call();
		return;
	}

	mob = NULL;
	smash_tilde( argument );

	switch( ch->pcdata->editmode )
	{
		case MODE_MPROG_EDIT:
			if (ch->pcdata->edit_ptr && ch->pcdata->temp_ptr)
			{
				mob  = ch->pcdata->edit_ptr;
				prog = ch->pcdata->temp_ptr;
				STRFREE(prog->comlist);
				prog->comlist = copy_buffer(ch);
				stop_editing( ch );

				if (strstr(prog->comlist, "$r") != NULL)
				{
					SET_BIT(prog->flags, MPTRIGGER_RAND_PLR);
				}
				else
				{
					REMOVE_BIT(prog->flags, MPTRIGGER_RAND_PLR);
				}

				while ((token = prog->first_token) != NULL)
				{
					UNLINK(token, prog->first_token, prog->last_token, next, prev);
					STRFREE(token->string);
					FREEMEM(token);
				}
				expand_mob_prog(mob, NULL, NULL, prog);
				do_mpedit(ch, "stat");
			}
			else
			{
				log_printf("do_mpedit: null edit_ptr or temp_ptr");
				ch->pcdata->tempmode = MODE_NONE;
				stop_editing(ch);
			}
			pop_call();
			return;
	}

	if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		mob = ch->pcdata->edit_ptr;

		if (argument[0] == '?')
		{
			/*
				Show mpedit status
			*/
			ch_printf_color(ch, "Syntax: <command> <value>\n\r\n\r");
			ch_printf_color(ch, "Command being one of:\n\r");
			ch_printf_color(ch, "  add del set edit done stat ? < >\n\r");
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "done"))
		{
			send_to_char( "oprog edit mode off.\n\r", ch );

			stop_olc_editing(ch, mob->area);

			pop_call();
			return;
		}

		if (!strcmp(argument, ">"))
		{
			if (get_mob_index(mob->vnum + 1) && can_olc_modify(ch, mob->vnum + 1))
			{
				stop_olc_editing(ch, mob->area);
				sprintf(buf, "%d", mob->vnum + 1);
				do_mpedit(ch, buf);
			}
			else
			{
				ch_printf_color(ch, "Next index not found.\n\r");
			}
			pop_call();
			return;
		}

		if (!strcmp(argument, "<"))
		{
			if (get_mob_index(mob->vnum - 1) && can_olc_modify(ch, mob->vnum - 1))
			{
				stop_olc_editing(ch, mob->area);
				sprintf(buf, "%d", mob->vnum - 1);
				do_mpedit(ch, buf);
			}
			else
			{
				ch_printf_color(ch, "Prev index not found.\n\r");
			}
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "stat"))
		{
			*buf = '\0';
			for (cnt = 0, prog = mob->first_prog ; prog ; prog = prog->next)
			{
				cat_sprintf(buf, "{178}%2d{078}] {138}%s {128}%s\n\r", ++cnt, mprog_type_to_name(prog->type), prog->arglist);
			}
			if (mob->first_prog == NULL)
			{
				cat_sprintf(buf, "This mobile does not have any programs defined.\n\r");
			}
			cat_sprintf(buf, "Syntax: <field> <value>                        < %sprev next %s>\n\r", colg, colW);
			send_to_char_color(buf, ch);
			pop_call();
			return;
		}
	}	
	else if ((mob = get_mob_index(atoi(argument))) == NULL)
	{
		send_to_char("Syntax: edit mprog <mobile vnum>\n\r", ch);
		pop_call();
		return;
	}
	else if (!can_olc_modify(ch, mob->vnum))
	{
		send_to_char("That vnum is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	argument = one_argument(argument, arg);

	if (ch->pcdata->editmode != MODE_REPEATCMD)
	{
		ch->pcdata->edit_ptr = mob;
		ch->pcdata->edittype = EDIT_TYPE_MPROG;

		ch->pcdata->editmode = MODE_REPEATCMD;

		if (ch->pcdata)
		{
			if (ch->pcdata->subprompt)
			{
				STRFREE(ch->pcdata->subprompt);
			}
			sprintf( arg, "Editing Mprog Vnum: %d", mob->vnum );
			ch->pcdata->subprompt = STRALLOC( arg );
			do_mpedit(ch, "stat");
		}
		pop_call();
		return;
	}

	if (!strcasecmp(arg, "del"))
	{
		if ((value = atoi(argument)) < 1)
		{
			ch_printf_color(ch, "Syntax: del <index>\n\r");
		}
		else
		{
			for (cnt = 0, prog = mob->first_prog ; prog ; prog = prog->next)
			{
				if (++cnt == value)
				{
					break;
				}
			}
			if (prog)
			{
				UNLINK(prog, mob->first_prog, mob->last_prog, next, prev);

				for (mob->progtypes = 0, prog = mob->first_prog ; prog ; prog = prog->next)
				{
					SET_BIT(mob->progtypes, prog->type);
				}
			}
			else
			{
				ch_printf_color(ch, "Index %d not found.\n\r", value);
				pop_call();
				return;
			}
		}
	}

	else if (!strcasecmp(arg, "add"))
	{
		argument = one_argument(argument, arg);

		if ((value = atoi(arg)) < 1)
		{
			ch_printf_color(ch, "Syntax: add <index> <trigger> [argument]\n\r");
			pop_call();
			return;
		}

		argument = one_argument(argument, arg);

		if ((type = get_flag(arg, mprog_flags)) == -1)
		{
			ch_printf_color(ch, "add <index> <%s>\n\r", give_flags(mprog_flags));
			pop_call();
			return;
		}

		ALLOCMEM(prog, MPROG_DATA, 1);

		prog->type	= 1LL << type;
		prog->arglist	= STRALLOC(argument);
		prog->comlist  = STRALLOC("");

		for (cnt = 0, prog2 = mob->first_prog ; prog2 ; prog2 = prog2->next)
		{
			if (++cnt == value)
			{
				break;
			}
		}
		if (prog2)
		{
			INSERT_LEFT(prog, prog2, mob->first_prog, next, prev);
		}
		else
		{
			LINK(prog, mob->first_prog, mob->last_prog, next, prev);
		}
		SET_BIT(mob->progtypes, prog->type);
	}

	else if (!strcasecmp(arg, "set"))
	{
		argument = one_argument(argument, arg);

		if ((value = atoi(arg)) < 1)
		{
			ch_printf_color(ch, "Syntax: set <index> <trigger> <argument>\n\r");
			ch_printf_color(ch, "Syntax: set <index> <arglist> <argument>\n\r");
			pop_call();
			return;
		}

		for (cnt = 0, prog = mob->first_prog ; prog ; prog = prog->next)
		{
			if (++cnt == value)
			{
				break;
			}
		}

		if (prog == NULL)
		{
			ch_printf_color(ch, "Index %d not found.\n\r", value);
			pop_call();
			return;
		}

		argument = one_argument(argument, arg);

		if (!strcasecmp(arg, "trigger"))
		{
			if ((type = get_flag(argument, mprog_flags)) == -1)
			{
				ch_printf_color(ch, "set <index> trigger <%s>\n\r", give_flags(mprog_flags));
				pop_call();
				return;
			}
			else
			{
				prog->type = 1LL << type;

				for (mob->progtypes = 0, prog = mob->first_prog ; prog ; prog = prog->next)
				{
					SET_BIT(mob->progtypes, prog->type);
				}
			}
		}

		else if (!strcasecmp(arg, "arglist"))
		{
			RESTRING(prog->arglist, argument);
		}
		else
		{
			ch_printf_color(ch, "Syntax: set <index> <trigger> <argument>\n\r");
			ch_printf_color(ch, "Syntax: set <index> <arglist> <argument>\n\r");
			pop_call();
			return;
		}
	}

	if (!strcasecmp(arg, "edit"))
	{
		if ((value = atoi(argument)) < 1)
		{
			ch_printf_color(ch, "Syntax: edit <index>\n\r");
			pop_call();
			return;
		}

		for (cnt = 0, prog = mob->first_prog ; prog ; prog = prog->next)
		{
			if (++cnt == value)
			{
				break;
			}
		}

		if (prog == NULL)
		{
			ch_printf_color(ch, "Index %d not found.\n\r", value);
			pop_call();
			return;
		}

		if (prog->comlist)
		{
			STRFREE(prog->comlist);
		}
		prog->comlist = STRALLOC(fixer_mprog(prog));

		ch->pcdata->temp_ptr = prog;

		ch->pcdata->editmode = MODE_MPROG_EDIT;
		ch->pcdata->tempmode = MODE_REPEATCMD;

		start_editing(ch, prog->comlist);

		pop_call();
		return;
	}

	else if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		ch->pcdata->editmode = MODE_RESTRICTED;
		interpret( ch, origarg );
		ch->pcdata->editmode = MODE_REPEATCMD;
		ch->pcdata->last_cmd = do_edit;
		pop_call();
		return;
	}
	
	do_mpedit(ch, "stat");
	pop_call();
	return;
}

void do_rpedit( CHAR_DATA *ch, char *argument )
{
	char arg [MAX_INPUT_LENGTH];
	char buf [MAX_INPUT_LENGTH];

	int  value, cnt, type;

	ROOM_INDEX_DATA *room;
	MPROG_DATA	*prog,  *prog2;
	NPC_TOKEN		*token;

	char *origarg = argument;

	char colw[10], colg[10], colW[10], colM[10];

	push_call("do_rpedit(%p,%p)",ch,argument);

	CHECK_EDITMODE( ch );

	strcpy(colw, get_color_string(ch, COLOR_TEXT, VT102_DIM));
	strcpy(colg, get_color_string(ch, COLOR_ACCENT, VT102_DIM));
	strcpy(colW, get_color_string(ch, COLOR_TEXT, VT102_BOLD));
	strcpy(colM, ansi_translate_text(ch, "{158}"));

	if (!ch->desc)
	{
		send_to_char( "You have no descriptor\n\r", ch );
		pop_call();
		return;
	}

	room = NULL;
	smash_tilde( argument );

	switch( ch->pcdata->editmode )
	{
		case MODE_RPROG_EDIT:
			if (ch->pcdata->edit_ptr && ch->pcdata->temp_ptr)
			{
				room  = ch->pcdata->edit_ptr;
				prog = ch->pcdata->temp_ptr;
				STRFREE(prog->comlist);
				prog->comlist = copy_buffer(ch);
				stop_editing( ch );

				if (strstr(prog->comlist, "$r") != NULL)
				{
					SET_BIT(prog->flags, MPTRIGGER_RAND_PLR);
				}
				else
				{
					REMOVE_BIT(prog->flags, MPTRIGGER_RAND_PLR);
				}

				while ((token = prog->first_token) != NULL)
				{
					UNLINK(token, prog->first_token, prog->last_token, next, prev);
					STRFREE(token->string);
					FREEMEM(token);
				}
				expand_mob_prog(NULL, NULL, room, prog);
				do_rpedit(ch, "stat");
			}
			else
			{
				log_printf("do_rpedit: null edit_ptr or temp_ptr");
				ch->pcdata->tempmode = MODE_NONE;
				stop_editing(ch);
			}
			pop_call();
			return;
	}

	if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		room = ch->pcdata->edit_ptr;

		if (argument[0] == '?')
		{
			/*
				Show rpedit status
			*/
			ch_printf_color(ch, "Syntax: <command> <value>\n\r\n\r");
			ch_printf_color(ch, "Command being one of:\n\r");
			ch_printf_color(ch, "  add del set edit done stat ? < >\n\r");
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "done"))
		{
			send_to_char( "oprog edit mode off.\n\r", ch );

			stop_olc_editing(ch, room->area);

			pop_call();
			return;
		}

		if (!strcmp(argument, ">"))
		{
			if (get_room_index(room->vnum + 1) && can_olc_modify(ch, room->vnum + 1))
			{
				stop_olc_editing(ch, room->area);
				sprintf(buf, "%d", room->vnum + 1);
				do_rpedit(ch, buf);
			}
			else
			{
				ch_printf_color(ch, "Next index not found.\n\r");
			}
			pop_call();
			return;
		}

		if (!strcmp(argument, "<"))
		{
			if (get_room_index(room->vnum - 1) && can_olc_modify(ch, room->vnum - 1))
			{
				stop_olc_editing(ch, room->area);
				sprintf(buf, "%d", room->vnum - 1);
				do_rpedit(ch, buf);
			}
			else
			{
				ch_printf_color(ch, "Prev index not found.\n\r");
			}
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "stat"))
		{
			*buf = '\0';
			for (cnt = 0, prog = room->first_prog ; prog ; prog = prog->next)
			{
				cat_sprintf(buf, "{178}%2d{078}] {138}%s {128}%s\n\r", ++cnt, mprog_type_to_name(prog->type), prog->arglist);
			}
			if (room->first_prog == NULL)
			{
				cat_sprintf(buf, "This room does not have any programs defined.\n\r");
			}
			cat_sprintf(buf, "Syntax: <field> <value>                        < %sprev next %s>\n\r", colg, colW);
			send_to_char_color(buf, ch);
			pop_call();
			return;
		}
	}	
	else if ((room = get_room_index(atoi(argument))) == NULL)
	{
		if ((room = ch->in_room) == NULL)
		{
			send_to_char("Syntax: edit rprog <room vnum>\n\r", ch);
			pop_call();
			return;
		}
	}
	if (!can_olc_modify(ch, room->vnum))
	{
		send_to_char("That vnum is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	argument = one_argument(argument, arg);

	if (ch->pcdata->editmode != MODE_REPEATCMD)
	{
		ch->pcdata->edit_ptr = room;
		ch->pcdata->edittype = EDIT_TYPE_RPROG;

		ch_printf_color( ch, "[%d] Editing Rprog.\n\r", room->vnum);
		ch->pcdata->editmode = MODE_REPEATCMD;

		if (ch->pcdata)
		{
			if (ch->pcdata->subprompt)
			{
				STRFREE(ch->pcdata->subprompt);
			}
			sprintf( arg, "Editing Rprog Vnum: %d", room->vnum );
			ch->pcdata->subprompt = STRALLOC( arg );
		}
		pop_call();
		return;
	}

	if (!strcasecmp(arg, "del"))
	{
		if ((value = atoi(argument)) < 1)
		{
			ch_printf_color(ch, "Syntax: del <index>\n\r");
			pop_call();
			return;
		}
		else
		{
			for (cnt = 0, prog = room->first_prog ; prog ; prog = prog->next)
			{
				if (++cnt == value)
				{
					break;
				}
			}
			if (prog)
			{
				UNLINK(prog, room->first_prog, room->last_prog, next, prev);

				for (room->progtypes = 0, prog = room->first_prog ; prog ; prog = prog->next)
				{
					SET_BIT(room->progtypes, prog->type);
				}
			}
			else
			{
				ch_printf_color(ch, "Index %d not found.\n\r", value);
				pop_call();
				return;
			}
		}
	}

	else if (!strcasecmp(arg, "add"))
	{
		argument = one_argument(argument, arg);

		if ((value = atoi(arg)) < 1)
		{
			ch_printf_color(ch, "Syntax: add <index> <trigger> [argument]\n\r");
			pop_call();
			return;
		}

		argument = one_argument(argument, arg);

		if ((type = get_flag(arg, rprog_flags)) == -1)
		{
			ch_printf_color(ch, "add <index> <%s>\n\r", give_flags(rprog_flags));
			pop_call();
			return;
		}

		ALLOCMEM(prog, MPROG_DATA, 1);

		prog->type	= 1LL << type;
		prog->arglist	= STRALLOC(argument);
		prog->comlist  = STRALLOC("");

		for (cnt = 0, prog2 = room->first_prog ; prog2 ; prog2 = prog2->next)
		{
			if (++cnt == value)
			{
				break;
			}
		}
		if (prog2)
		{
			INSERT_LEFT(prog, prog2, room->first_prog, next, prev);
		}
		else
		{
			LINK(prog, room->first_prog, room->last_prog, next, prev);
		}
		SET_BIT(room->progtypes, prog->type);
	}

	else if (!strcasecmp(arg, "set"))
	{
		argument = one_argument(argument, arg);

		if ((value = atoi(arg)) < 1)
		{
			ch_printf_color(ch, "Syntax: set <index> <trigger> <argument>\n\r");
			ch_printf_color(ch, "Syntax: set <index> <arglist> <argument>\n\r");
			pop_call();
			return;
		}

		for (cnt = 0, prog = room->first_prog ; prog ; prog = prog->next)
		{
			if (++cnt == value)
			{
				break;
			}
		}

		if (prog == NULL)
		{
			ch_printf_color(ch, "Index %d not found.\n\r", value);
			pop_call();
			return;
		}

		argument = one_argument(argument, arg);

		if (!strcasecmp(arg, "trigger"))
		{
			if ((type = get_flag(argument, oprog_flags)) == -1)
			{
				ch_printf_color(ch, "set <index> trigger <%s>\n\r", give_flags(oprog_flags));
				pop_call();
				return;
			}
			else
			{
				prog->type = 1LL << type;

				for (room->progtypes = 0, prog = room->first_prog ; prog ; prog = prog->next)
				{
					SET_BIT(room->progtypes, prog->type);
				}
			}
		}

		else if (!strcasecmp(arg, "arglist"))
		{
			RESTRING(prog->arglist, argument);
		}
		else
		{
			ch_printf_color(ch, "Syntax: set <index> <trigger> <argument>\n\r");
			ch_printf_color(ch, "Syntax: set <index> <arglist> <argument>\n\r");
			pop_call();
			return;
		}
	}

	else if (!strcasecmp(arg, "edit"))
	{
		if ((value = atoi(argument)) < 1)
		{
			ch_printf_color(ch, "Syntax: edit <index>\n\r");
			pop_call();
			return;
		}

		for (cnt = 0, prog = room->first_prog ; prog ; prog = prog->next)
		{
			if (++cnt == value)
			{
				break;
			}
		}

		if (prog == NULL)
		{
			ch_printf_color(ch, "Index %d not found.\n\r", value);
			pop_call();
			return;
		}

		if (prog->comlist)
		{
			STRFREE(prog->comlist);
		}
		prog->comlist = STRALLOC(fixer_mprog(prog));

		ch->pcdata->temp_ptr = prog;

		ch->pcdata->editmode = MODE_RPROG_EDIT;
		ch->pcdata->tempmode = MODE_REPEATCMD;

		start_editing(ch, prog->comlist);

		pop_call();
		return;
	}

	else if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		ch->pcdata->editmode = MODE_RESTRICTED;
		interpret( ch, origarg );
		ch->pcdata->editmode = MODE_REPEATCMD;
		ch->pcdata->last_cmd = do_edit;
		pop_call();
		return;
	}
	
	do_rpedit(ch, "stat");
	pop_call();
	return;
}

void stop_race_editing(CHAR_DATA *ch)
{
	push_call("stop_race_editing(%p,%p)",ch);

	if (ch->pcdata->edit_race)
	{
		fwrite_race(ch->pcdata->edit_race);
	}
	ch->pcdata->edittype 	= EDIT_TYPE_NONE;
	ch->pcdata->editmode 	= MODE_NONE;
	ch->pcdata->tempmode 	= MODE_NONE;
	ch->pcdata->edit_race = 0;

	if (ch->pcdata && ch->pcdata->subprompt)
	{
		STRFREE(ch->pcdata->subprompt);
		ch->pcdata->subprompt = NULL;
	}
// 	save_races();

	pop_call();
	return;
}


void do_race_edit( CHAR_DATA *ch, char *argument )
{
	char arg2 [MAX_INPUT_LENGTH];
	char arg3 [MAX_INPUT_LENGTH];
	char buf  [MAX_STRING_LENGTH];
	char buf2	[MAX_STRING_LENGTH];
	int  sn, value, cnt, col, race;
	char *origarg = argument;
	
	char colw[10], colg[10], colW[10];

	push_call("do_race_edit(%p,%p)",ch,argument);

	CHECK_EDITMODE( ch );

	strcpy(colw, get_color_string(ch, COLOR_TEXT, VT102_DIM));
	strcpy(colg, get_color_string(ch, COLOR_ACCENT, VT102_DIM));
	strcpy(colW, get_color_string(ch, COLOR_TEXT, VT102_BOLD));

	if (!ch->desc)
	{
		send_to_char( "You have no descriptor\n\r", ch );
		pop_call();
		return;
	}

	smash_tilde( argument );

	if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		race = ch->pcdata->edit_race;

// 		if (argument[0] == '?')
// 		{
// 			/*
// 				Show race_edit status
// 			*/
// 			ch_printf_color(ch, "Syntax: <command> <value>\n\r\n\r");
// 			ch_printf_color(ch, "Command being one of:\n\r");
// 			ch_printf_color(ch, "  name size racetype subtype hitdice landspeed burrow climb fly swim\n\r");
// 			ch_printf_color(ch, "  armor deflect pcrace vision str dex con int wis cha weight\n\r");
// 			ch_printf_color(ch, "  height apply vulnerable drand speaks understands bonuslang\n\r");
// 			ch_printf_color(ch, "  attack priattack poison favclass leveladj align ethos done ? < >\n\r");
// 			pop_call();
// 			return;
// 		}
// 
		if (!strcasecmp(argument, "done"))
		{
			send_to_char( "RaceEdit mode off.\n\r", ch );

			stop_race_editing(ch);

			pop_call();
			return;
		}

		if (!strcmp(argument, ">"))
		{
			if ((race = race + 1) >= MAX_RACE)
			{
				ch_printf_color(ch, "Next index not found.\n\r");
				pop_call();
				return;
			}
			stop_race_editing(ch);
			sprintf(buf, "%s", race_table[race].race_name);
			do_race_edit(ch, buf);
			pop_call();
			return;
		}

		if (!strcmp(argument, "<"))
		{
			if ((race = race - 1) < 1)
			{
				ch_printf_color(ch, "Next index not found.\n\r");
				pop_call();
				return;
			}
			stop_race_editing(ch);
			sprintf(buf, "%s", race_table[race].race_name);
			do_race_edit(ch, buf);
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "stat"))
		{
			sprintf(buf2, "{200}  Race Name:{178} %-18s     {200}HitDice:{178} %2d{200}       ParentRace:{178} %-12s\n\r", race_table[race].race_name, race_table[race].hit_dice, race_table[race_table[race].parent_race].race_name);
			cat_sprintf(buf2, "{200}     Height:{178} %-6d  {200}Weight:{178} %-6d    {200}Size:{178} %-10s   {200}PCRace: {178}%-6s\n\r",
					race_table[race].height, race_table[race].weight, size_types[race_table[race].size], race_table[race].pcrace ? "yes" : "no");
			cat_sprintf(buf2, "{200}      Speed: {078}Land:{178} %-d{078}, Burrow:{178} %-d{078}, Climb: {178}%-d{078}, Fly: {178}%-d{078}, Swim: {178}%-d\n\r",
					race_table[race].land_speed, race_table[race].burrow_speed, race_table[race].climb_speed, race_table[race].fly_speed, race_table[race].swim_speed);
			cat_sprintf(buf2, "{200}      Armor:{178} %-2d  {200}Deflection:{178} %-2d {200}   FavClass: {178}%s\n\r",
					race_table[race].nat_armor, race_table[race].deflection, class_types[race_table[race].favored_class]);
			cat_sprintf(buf2, "{200}      Align:{178} %-5d    {200}Ethos: {178}%-5d{200} LevelAdj: {178}%-5d{200} Material: {178}%s\n\r", race_table[race].alignment, race_table[race].ethos, race_table[race].lvl_adj, material_types[race_table[race].material]);
		
			cat_sprintf(buf2, "{200}    StatAdj:{178} STR: %+2d DEX: %+2d CON: %+2d INT: %+2d WIS: %+2d CHA: %+2d\n\r",
					race_table[race].race_mod[0],
					race_table[race].race_mod[1],
					race_table[race].race_mod[2],
					race_table[race].race_mod[3],
					race_table[race].race_mod[4],
					race_table[race].race_mod[5]);
		
			cat_sprintf(buf2, "{200}Nonabilities:{178}");
			for (cnt = 0 ; cnt < 6 ; cnt++)
			{
				if (race_table[race].nonability[cnt])
					cat_sprintf(buf2, "%s", cnt == 0 ? " STR" : cnt == 1 ? " DEX" : cnt == 2 ? " CON" : cnt == 3 ? " INT" : cnt == 4 ? " WIS" : "CHA");
				else
					strcat(buf2, "");
			}
			strcat(buf2, "\n\r");
		
			cat_sprintf(buf2, "{200}   RaceType:{178} %s {200}Subtype:{178}[%s] {200}Bodytype:{178}%s\n\r",
				type_string(race_table[race].type, rtype_flags), flag_string(race_table[race].flags, race_specs), type_string(race_table[race].body_type, body_types));
		
			cat_sprintf(buf2, "{200}      Apply:{178} ");		
			for (cnt = col = 0 ; cnt < MAX_APPLY ; cnt++)
			{
				if (!race_table[race].apply[cnt])
					continue;
				if (col && col % 3 == 0)
					strcat(buf2, "             ");
				cat_sprintf(buf2, "{178}%-16s %2d   ", a_types[cnt], race_table[race].apply[cnt]);
				col++;
				if (col % 3 == 0)
					strcat(buf2, "\n\r");
			}		
			strcat(buf2, "\n\r");
		
			cat_sprintf(buf2, "{200} AffectedBy:{178} %s\n\r", flag_string(race_table[race].affected_by, a_flags));
			cat_sprintf(buf2, "{200} Vulnerable:{178} %s\n\r", flag_string(race_table[race].vulnerability, dtype_flags));	
			cat_sprintf(buf2, "{200}     Speaks:{178} %-12s", flag_string(race_table[race].speaks, lang_names));
			cat_sprintf(buf2, "{200}Understands:{178} %s\n\r", flag_string(race_table[race].understands, lang_names));	
			cat_sprintf(buf2, "{200} BonusLangs:{178} %s\n\r", flag_string(race_table[race].bonus_langs, lang_names));	
			cat_sprintf(buf2, "{200}   WearLocs:{178} %s\n\r", flag_string(race_table[race].wear_locs, race_wear_flags));
				
			cat_sprintf(buf2, "{200}    Attacks:{178} ");		
			for (cnt = col = 0 ; cnt < ATTK_MAX ; cnt++)
			{
				if (!race_table[race].attacks[cnt])
					continue;
				if (col && col % 3 == 0)
					strcat(buf2, "             ");
				cat_sprintf(buf2, "{178}%-10s %2dx%dd%-2d  ",
					attack_part_flags[cnt], race_table[race].attacks[cnt], dam_no_dice[cnt].size[race_table[race].size], dam_size_dice[cnt].size[race_table[race].size]);
				col++;
				if (col % 3 == 0)
					cat_sprintf(buf2, "\n\r");
			}		
			if (col % 3 != 0)
				cat_sprintf(buf2, "\n\r");

			cat_sprintf(buf2, "{200}     Poison:{178} %s %s\n\r", !race_table[race].poison ? "none" : attack_part_flags[race_table[race].poison_part], poison_names[race_table[race].poison]);
			cat_sprintf(buf2, "{200}    Disease:{178} %s %s\n\r", !race_table[race].disease ? "none" : attack_part_flags[race_table[race].disease_part], disease_names[race_table[race].disease]);

			cat_sprintf(buf2, "{200}Raceattacks: {078}(Effective level)\n\r");
			for (sn = col = 0 ; *skill_table[sn].name != '\0' ; sn++)
			{
				if (skill_table[sn].skilltype != FSKILL_RACEATTACK)
					continue;
				if (skill_table[sn].race_skill[race])
				{
					cat_sprintf(buf2, "  {178}%-20s%2d  ", skill_table[sn].name, skill_table[sn].race_skill[race]);
					col++;
					if (col % 3 == 0)
						cat_sprintf(buf2, "\n\r");
				}
			}
			if (col % 3 != 0)
				cat_sprintf(buf2, "\n\r");

			cat_sprintf(buf2, "{200}    Sectors:{178} %s\n\r", flag_string(race_table[race].sectors, race_sectors));
				
			cat_sprintf(buf2, "{200}     Skills: {078}(Default ranks in skill)\n\r");
			for (sn = col = 0 ; *skill_table[sn].name != '\0' ; sn++)
			{
				if (skill_table[sn].skilltype != FSKILL_SKILL
				&& skill_table[sn].skilltype != FSKILL_NONE
				&& skill_table[sn].skilltype != FSKILL_CRAFT
				&& skill_table[sn].skilltype != FSKILL_KNOWLEDGE)
					continue;
				if (skill_table[sn].race_skill[race])
				{
					cat_sprintf(buf2, "  {178}%-20s%2d  ", skill_table[sn].name, skill_table[sn].race_skill[race]);
					col++;
					if (col % 3 == 0)
						cat_sprintf(buf2, "\n\r");
				}
			}
			if (col % 3 != 0)
				cat_sprintf(buf2, "\n\r");

			cat_sprintf(buf2, "{200}  Abilities: {078}(Level gained)\n\r");
			for (sn = col = 0 ; *skill_table[sn].name != '\0' ; sn++)
			{
				if (skill_table[sn].skilltype != FSKILL_FEAT
				&& skill_table[sn].skilltype != FSKILL_ABILITY)
					continue;
				if (skill_table[sn].race_skill[race])
				{
					cat_sprintf(buf2, "  {178}%-20s%2d  ", skill_table[sn].name, skill_table[sn].race_skill[race]);
					col++;
					if (col % 3 == 0)
						cat_sprintf(buf2, "\n\r");
				}
			}
			if (col % 3 != 0)
				cat_sprintf(buf2, "\n\r");

			cat_sprintf(buf2, "{200}  SpellLike: {078}(Daily uses or AW = at-will)\n\r");
			for (sn = col = 0 ; *skill_table[sn].name != '\0' ; sn++)
			{
				if (skill_table[sn].skilltype != FSKILL_SPELL)
					continue;
				if (skill_table[sn].race_skill[race] >= 75)
				{
					cat_sprintf(buf2, "  {178}%-20sAW  ", skill_table[sn].name);
					col++;
					if (col % 3 == 0)
						cat_sprintf(buf2, "\n\r");
				}
				else if (skill_table[sn].race_skill[race])
				{
					cat_sprintf(buf2, "  {178}%-20s%2d  ", skill_table[sn].name, skill_table[sn].race_skill[race]);
					col++;
					if (col % 3 == 0)
						cat_sprintf(buf2, "\n\r");
				}
			}
			if (col % 3 != 0)
				cat_sprintf(buf2, "\n\r");

			cat_sprintf(buf2, "Syntax: <field> <value>                        < %sprev next %s>\n\r", colg, colW);
			send_to_char_color(buf2, ch);
			pop_call();
			return;
		}
	}
	else
	{
		if ((race = lookup_race(argument)) == -1)
		{
			if (!is_number(argument) || (race = atoi(argument)) < 1 || race >= MAX_RACE)
			{
				send_to_char("Syntax: edit race <race name|race number>\n\r", ch);
				pop_call();
				return;
			}
		}
		ch->pcdata->edit_race = race;
		ch->pcdata->edittype = EDIT_TYPE_RACE;

// 		ch_printf_color( ch, "[%d] Editing Race.\n\r", race);
		ch->pcdata->editmode = MODE_REPEATCMD;

		if (ch->pcdata)
		{
			if (ch->pcdata->subprompt)
			{
				STRFREE(ch->pcdata->subprompt);
			}
			sprintf( buf, "Editing Race: %d - %s", race, race_table[race].race_name );
			ch->pcdata->subprompt = STRALLOC( buf );
		}
		do_race_edit(ch, "stat");
		pop_call();
		return;
	}

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

	value = is_number(argument) ? atoi(argument) : -1;

	value = atol(arg3);

	if ( !strcasecmp( arg2, "name" ) )
	{
		if (strlen(arg3) > 24)
		{
			ch_printf_color(ch, "name must be 24 characters or less.\n\r");
			pop_call();
			return;
		}
		strcpy(race_table[race].race_name, arg3);
	}

	else if (!strcasecmp( arg2, "armor" ))
	{
		race_table[race].nat_armor = value;
	}

	else if (!strcasecmp( arg2, "pcrace" ))
	{
		if (!strcasecmp(arg3, "yes"))
			race_table[race].pcrace = 1;
		else if (!strcasecmp(arg3, "no"))
			race_table[race].pcrace = 0;
		else
		{
			ch_printf_color(ch, "pcrace: yes or no?\n\r");
			pop_call();
			return;
		}
	}

	else if (!strcasecmp( arg2, "parentrace" ))
	{
		if ((value = lookup_race(arg3)) == -1)
		{
			ch_printf_color(ch, "Not a valid race, %s", arg3);
			pop_call();
			return;
		}
		race_table[race].parent_race = value;
	}

	else if (!strcasecmp( arg2, "deflection" ))
	{
		race_table[race].deflection = value;
	}

	else if (!strcasecmp( arg2, "str" ))
	{
		race_table[race].race_mod[0] = value;
	}

	else if (!strcasecmp( arg2, "dex" ))
	{
		race_table[race].race_mod[1] = value;
	}

	else if (!strcasecmp( arg2, "con" ))
	{
		race_table[race].race_mod[2] = value;
	}

	else if (!strcasecmp( arg2, "int" ))
	{
		race_table[race].race_mod[3] = value;
	}

	else if (!strcasecmp( arg2, "wis" ))
	{
		race_table[race].race_mod[4] = value;
	}

	else if (!strcasecmp( arg2, "cha" ))
	{
		race_table[race].race_mod[5] = value;
	}

	else if (!strcasecmp( arg2, "swim" ))
	{
		race_table[race].swim_speed = value;
	}

	else if (!strcasecmp( arg2, "fly" ))
	{
		race_table[race].fly_speed = value;
	}

	else if (!strcasecmp( arg2, "climb" ))
	{
		race_table[race].climb_speed = value;
	}

	else if (!strcasecmp( arg2, "burrow" ))
	{
		race_table[race].burrow_speed = value;
	}

	else if (!strcasecmp( arg2, "land" ))
	{
		race_table[race].land_speed = value;
	}

	else if (!strcasecmp( arg2, "hitdice" ))
	{
		race_table[race].hit_dice = value;
	}

	else if (!strcasecmp( arg2, "height" ))
	{
		race_table[race].height = value;
	}

	else if (!strcasecmp( arg2, "weight" ))
	{
		race_table[race].weight = value;
	}

	else if (!strcasecmp( arg2, "leveladj" ))
	{
		race_table[race].lvl_adj = value;
	}

	else if (!strcasecmp( arg2, "align" ))
	{
		race_table[race].alignment = URANGE(-1000, value, 1000);
	}

	else if (!strcasecmp( arg2, "ethos" ))
	{
		race_table[race].ethos = URANGE(-1000, value, 1000);
	}

	else if (!strcasecmp( arg2, "material" ))
	{
		if ((value = get_flag(arg3, material_types)) == -1)
		{
			ch_printf_color(ch, "material <%s>.\n\r", give_flags(material_types));
			pop_call();
			return;
		}
		race_table[race].material = value;
	}

	else if (!strcasecmp( arg2, "vulnerable" ))
	{
		if ((value = get_flag(arg3, dtype_flags)) == -1)
		{
			ch_printf_color(ch, "vulnerable <%s>.\n\r", give_flags(dtype_flags));
			pop_call();
			return;
		}
		TOGGLE_BIT(race_table[race].vulnerability, 1LL << value);
	}

	else if (!strcasecmp( arg2, "apply" ))
	{
		if ((value = get_flag(arg3, a_types)) == -1)
		{
			ch_printf_color(ch, "Applies:\n\r%s", flag_menu(a_types));
			pop_call();
			return;
		}
		if (!is_number(argument))
		{
			ch_printf_color(ch, "apply <apply type> amount.\n\r");
			pop_call();
			return;
		}
		race_table[race].apply[value] = atol(argument);
	}

	else if (!strcasecmp( arg2, "speaks" ))
	{
		if ((value = get_flag(arg3, lang_names)) == -1)
		{
			ch_printf_color(ch, "speaks <%s>.\n\r", give_flags(lang_names));
			pop_call();
			return;
		}
		race_table[race].speaks = 1LL << value;
	}

	else if (!strcasecmp( arg2, "affectedby" ))
	{
		if ((value = get_flag(arg3, a_flags)) == -1)
		{
			ch_printf_color(ch, "affectedby:\n\r %s\n\r", flag_menu(a_flags));
			pop_call();
			return;
		}
		TOGGLE_BIT(race_table[race].affected_by, 1LL << value);
		while (argument[0] != '\0')
		{
			argument = one_argument(argument, arg3);

			if ((value = get_flag(arg3, a_flags)) == -1)
			{
				ch_printf_color(ch, "Error: %s not a valid affect flag.\n\r", arg3);
			}
			else
			{
				TOGGLE_BIT(race_table[race].affected_by, 1LL << value);
			}
		}
	}

	else if (!strcasecmp( arg2, "understands" ))
	{
		if ((value = get_flag(arg3, lang_names)) == -1)
		{
			ch_printf_color(ch, "understands:\n\r %s\n\r", flag_menu(lang_names));
			pop_call();
			return;
		}
		TOGGLE_BIT(race_table[race].understands, 1LL << value);
		while (argument[0] != '\0')
		{
			argument = one_argument(argument, arg3);

			if ((value = get_flag(arg3, lang_names)) == -1)
			{
				ch_printf_color(ch, "Error: %s not a valid language.\n\r", arg3);
			}
			else
			{
				TOGGLE_BIT(race_table[race].understands, 1LL << value);
			}
		}
	}

	else if (!strcasecmp( arg2, "bonuslangs" ))
	{
		if ((value = get_flag(arg3, lang_names)) == -1)
		{
			ch_printf_color(ch, "bonuslangs:\n\r %s\n\r", flag_menu(lang_names));
			pop_call();
			return;
		}
		TOGGLE_BIT(race_table[race].bonus_langs, 1LL << value);
		while (argument[0] != '\0')
		{
			argument = one_argument(argument, arg3);

			if ((value = get_flag(arg3, lang_names)) == -1)
			{
				ch_printf_color(ch, "Error: %s not a valid language.\n\r", arg3);
			}
			else
			{
				TOGGLE_BIT(race_table[race].bonus_langs, 1LL << value);
			}
		}
	}

	else if (!strcasecmp( arg2, "nonabilities" ))
	{
		if (arg3[0] == '\0')
		{
			ch_printf_color(ch, "nonabilities: <str|dex|con|int|wis|cha>\n\r");
			pop_call();
			return;
		}
		
		cat_sprintf(argument, " %s", arg3);

		while (arg3[0] != '\0')
		{
			argument = one_argument(argument, arg3);

			if (!strcasecmp(arg3, "str"))
			{
				if (!race_table[race].nonability[0])
					race_table[race].nonability[0] = 1;
				else
					race_table[race].nonability[0] = 0;
			}
			else if (!strcasecmp(arg3, "dex"))
			{
				if (!race_table[race].nonability[1])
					race_table[race].nonability[1] = 1;
				else
					race_table[race].nonability[1] = 0;
			}
			else if (!strcasecmp(arg3, "con"))
			{
				if (!race_table[race].nonability[2])
					race_table[race].nonability[2] = 1;
				else
					race_table[race].nonability[2] = 0;
			}
			else if (!strcasecmp(arg3, "int"))
			{
				if (!race_table[race].nonability[3])
					race_table[race].nonability[3] = 1;
				else
					race_table[race].nonability[3] = 0;
			}
			else if (!strcasecmp(arg3, "wis"))
			{
				if (!race_table[race].nonability[4])
					race_table[race].nonability[4] = 1;
				else
					race_table[race].nonability[4] = 0;
			}
			else if (!strcasecmp(arg3, "cha"))
			{
				if (!race_table[race].nonability[5])
					race_table[race].nonability[5] = 1;
				else
					race_table[race].nonability[5] = 0;
			}
		}
	}

	else if (!strcasecmp( arg2, "subtype" ))
	{
		if ((value = get_flag(arg3, race_specs)) == -1)
		{
			ch_printf_color(ch, "subtype:\n\r %s\n\r", flag_menu(race_specs));
			pop_call();
			return;
		}
		TOGGLE_BIT(race_table[race].flags, 1LL << value);
		while (argument[0] != '\0')
		{
			argument = one_argument(argument, arg3);

			if ((value = get_flag(arg3, race_specs)) == -1)
			{
				ch_printf_color(ch, "Error: %s not a valid subtype.\n\r", arg3);
			}
			else
			{
				TOGGLE_BIT(race_table[race].flags, 1LL << value);
			}
		}
	}

	else if (!strcasecmp( arg2, "size" ))
	{
		if ((value = get_flag(arg3, size_types)) == -1)
		{
			ch_printf_color(ch, "size <%s>.\n\r", give_flags(size_types));
			pop_call();
			return;
		}
		race_table[race].size = value;
	}

	else if (!strcasecmp( arg2, "racetype" ))
	{
		if ((value = get_flag(arg3, rtype_flags)) == -1)
		{
			ch_printf_color(ch, "racetype <%s>.\n\r", give_flags(rtype_flags));
			pop_call();
			return;
		}
		race_table[race].type = value;
	}

	else if (!strcasecmp( arg2, "bodytype" ))
	{
		if ((value = get_flag(arg3, body_types)) == -1)
		{
			ch_printf_color(ch, "bodytype <%s>.\n\r", give_flags(body_types));
			pop_call();
			return;
		}
		race_table[race].body_type = value;
		race_table[race].wear_locs = body_wear_locs[value];
	}

	else if (!strcasecmp( arg2, "favclass" ))
	{
		if ((value = get_flag(arg3, class_types)) == -1)
		{
			ch_printf_color(ch, "favclass <%s>.\n\r", give_flags(class_types));
			pop_call();
			return;
		}
		race_table[race].favored_class = value;
	}

	else if (!strcasecmp( arg2, "statadj" ))
	{
		int x1, x2, x3, x4, x5, x6;
		
		x1 = x2 = x3 = x4 = x5 = x6 = 0;
		
		cat_sprintf(arg3, " %s", argument);

		if (sscanf(arg3, "%d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6) != 6)
		{
			ch_printf_color(ch, "statadj <str> <dex> <con> <int> <wis> <cha>.\n\r");
		}
		else
		{
			race_table[race].race_mod[0] = x1;
			race_table[race].race_mod[1] = x2;
			race_table[race].race_mod[2] = x3;
			race_table[race].race_mod[3] = x4;
			race_table[race].race_mod[4] = x5;
			race_table[race].race_mod[5] = x6;
		}
	}

	else if (!strcasecmp( arg2, "attacks" ))
	{
		if ((value = get_flag(arg3, attack_part_flags)) == -1)
		{
			ch_printf_color(ch, "attacks <%s>.\n\r", give_flags(attack_part_flags));
			pop_call();
			return;
		}
		if (!is_number(argument))
		{
			ch_printf_color(ch, "How many %s attacks?\n\r", attack_part_flags[value]);
			pop_call();
			return;
		}
		race_table[race].attacks[value] = atoi(argument);
	}

	else if (!strcasecmp( arg2, "sectors" ))
	{
		if ((value = get_flag(arg3, race_sectors)) == -1)
		{
			ch_printf_color(ch, "sectors <%s>.\n\r", give_flags(race_sectors));
			pop_call();
			return;
		}
		TOGGLE_BIT(race_table[race].sectors, 1LL << value);
		while (argument[0] != '\0')
		{
			argument = one_argument(argument, arg3);

			if ((value = get_flag(arg3, race_sectors)) == -1)
			{
				ch_printf_color(ch, "Error: %s not a valid sector type.\n\r", arg3);
			}
			else
			{
				TOGGLE_BIT(race_table[race].sectors, 1LL << value);
			}
		}
	}

	else if (!strcasecmp( arg2, "wearlocs" ))
	{
		if (*arg3 == '\0')
		{
			ch_printf_color(ch, "Syntax: wearlocs <%s>\n\r", give_flags(race_wear_flags));
			pop_call();
			return;
		}
		else if (!strcasecmp(arg3, "none"))
		{
			race_table[race].wear_locs = 0;
		}
		else
		{
			if ((value = get_flag(arg3, race_wear_flags)) == -1)
			{
				ch_printf_color(ch, "Syntax: wearlocs <%s>\n\r", give_flags(race_wear_flags));
				pop_call();
				return;
			}
			TOGGLE_BIT(race_table[race].wear_locs, 1LL << value);
			while (argument[0] != '\0')
			{
				argument = one_argument(argument, arg3);
	
				if ((value = get_flag(arg3, race_wear_flags)) == -1)
				{
					ch_printf_color(ch, "Error: %s not a valid wear location.\n\r", arg3);
				}
				else
				{
					TOGGLE_BIT(race_table[race].wear_locs, 1LL << value);
				}
			}
		}
	}

	else if (!strcasecmp( arg2, "poison" ))
	{
		if (!strcasecmp( arg3, "none" ))
		{
			race_table[race].poison_part = 0;
			race_table[race].poison = 0;
		}
		else if ((value = get_flag(arg3, attack_part_flags)) == -1)
		{
			ch_printf_color(ch, "poison <%s> <poison name>.\n\r", give_flags(attack_part_flags));
			pop_call();
			return;
		}
		else if (get_flag(argument, poison_names) == -1)
		{
			ch_printf_color(ch, "poison <attack part> <%s>.\n\r", give_flags(poison_names));
			pop_call();
			return;
		}
		else
		{
			race_table[race].poison_part = value;
			race_table[race].poison = get_flag(argument, poison_names);
		}
	}

	else if (!strcasecmp( arg2, "disease" ))
	{
		if (!strcasecmp( arg3, "none" ))
		{
			race_table[race].disease_part = 0;
			race_table[race].disease = 0;
		}
		else if ((value = get_flag(arg3, attack_part_flags)) == -1)
		{
			ch_printf_color(ch, "disease <%s> <disease name>.\n\r", give_flags(attack_part_flags));
			pop_call();
			return;
		}
		else if (get_flag(argument, disease_names) == -1)
		{
			ch_printf_color(ch, "disease <attack part> <%s>.\n\r", give_flags(disease_names));
			pop_call();
			return;
		}
		else
		{
			race_table[race].disease_part = value;
			race_table[race].disease = get_flag(argument, disease_names);
		}
	}

	else if (!strcasecmp( arg2, "skill" ) || !strcasecmp( arg2, "skills" ))
	{
		if ((sn = skill_lookup(arg3)) < 0 || !is_string(skill_table[sn].name))
		{
			ch_printf_color (ch, "That's not a valid skill.\n\r");
			pop_call();
			return;
		}
		switch (skill_table[sn].skilltype)
		{
			default:
				ch_printf_color (ch, "That's not a skill.\n\r");
				pop_call();
				return;
			case FSKILL_NONE:
			case FSKILL_SKILL:
			case FSKILL_KNOWLEDGE:
			case FSKILL_CRAFT:
				break;
		}
		if ((value = atoi(argument)) < 0 || value > LEVEL_IMMORTAL)
		{
			ch_printf_color (ch, "Level range is from 0 to %d.\n\r", LEVEL_IMMORTAL);
			pop_call();
			return;
		}		
		skill_table[sn].race_skill[race] = value;
	}

	else if (!strcasecmp( arg2, "spell" ) || !strcasecmp( arg2, "spelllike" ))
	{
		if ((sn = skill_lookup(arg3)) < 0 || !is_string(skill_table[sn].name))
		{
			ch_printf_color (ch, "That's not a valid skill.\n\r");
			pop_call();
			return;
		}
		switch (skill_table[sn].skilltype)
		{
			default:
				ch_printf_color (ch, "That's not a skill.\n\r");
				pop_call();
				return;
			case FSKILL_SPELL:
				break;
		}
		if (!strcasecmp(argument, "aw"))
		{
			value = 75;
		}
		else if ((value = atoi(argument)) < 0 || value >= LEVEL_IMMORTAL)
		{
			ch_printf_color (ch, "Set daily uses, or 'AW' to use at-will.\n\r");
			pop_call();
			return;
		}		
		skill_table[sn].race_skill[race] = value;
	}

	else if (!strcasecmp( arg2, "ability" ) || !strcasecmp( arg2, "abilities" ))
	{
		if ((sn = skill_lookup(arg3)) < 0 || !is_string(skill_table[sn].name))
		{
			ch_printf_color (ch, "That's not a valid skill.\n\r");
			pop_call();
			return;
		}
		switch (skill_table[sn].skilltype)
		{
			default:
				ch_printf_color (ch, "That's not a feat or ability.\n\r");
				pop_call();
				return;
			case FSKILL_ABILITY:
			case FSKILL_FEAT:
				break;
		}
		if ((value = atoi(argument)) < 0)
		{
			ch_printf_color (ch, "At what level is ability gained?\n\r");
			pop_call();
			return;
		}		
		skill_table[sn].race_skill[race] = value;
	}

	else if (!strcasecmp( arg2, "raceattack" ) || !strcasecmp( arg2, "raceattacks" ))
	{
		if ((sn = skill_lookup(arg3)) < 0 || !is_string(skill_table[sn].name))
		{
			ch_printf_color (ch, "That's not a valid racial attack.\n\r");
			pop_call();
			return;
		}
		switch (skill_table[sn].skilltype)
		{
			default:
				ch_printf_color (ch, "That's not a valid racial attack.\n\r");
				pop_call();
				return;
			case FSKILL_RACEATTACK:
				break;
		}
		if ((value = atoi(argument)) < 0 || value >= LEVEL_IMMORTAL)
		{
			ch_printf_color (ch, "What level is the ability?\n\r");
			pop_call();
			return;
		}
		skill_table[sn].race_skill[race] = value;
	}

	else if ( ch->pcdata->editmode == MODE_REPEATCMD )
	{
		ch->pcdata->editmode = MODE_RESTRICTED;
		interpret( ch, origarg );
		ch->pcdata->editmode = MODE_REPEATCMD;
		ch->pcdata->last_cmd = do_edit;
		pop_call();
		return;
	}
	
	do_race_edit(ch, "stat" );

	pop_call();
	return;
}


void stop_god_editing(CHAR_DATA *ch)
{
	push_call("stop_god_editing(%p,%p)",ch);

	ch->pcdata->edittype 	= EDIT_TYPE_NONE;
	ch->pcdata->editmode 	= MODE_NONE;
	ch->pcdata->tempmode 	= MODE_NONE;
	ch->pcdata->edit_god = 0;

	if (ch->pcdata && ch->pcdata->subprompt)
	{
		STRFREE(ch->pcdata->subprompt);
		ch->pcdata->subprompt = NULL;
	}
	save_gods();

	pop_call();
	return;
}


void do_god_edit( CHAR_DATA *ch, char *argument )
{
	char arg2 [MAX_INPUT_LENGTH];
	char arg3 [MAX_INPUT_LENGTH];
	char buf  [MAX_STRING_LENGTH];
	char buf2	[MAX_STRING_LENGTH];
	int  value, cnt, god, col;
	char *origarg = argument;
	
	char colw[10], colg[10], colW[10];

	push_call("do_god_edit(%p,%p)",ch,argument);

	CHECK_EDITMODE( ch );

	strcpy(colw, get_color_string(ch, COLOR_TEXT, VT102_DIM));
	strcpy(colg, get_color_string(ch, COLOR_ACCENT, VT102_DIM));
	strcpy(colW, get_color_string(ch, COLOR_TEXT, VT102_BOLD));

	if (!ch->desc)
	{
		send_to_char( "You have no descriptor\n\r", ch );
		pop_call();
		return;
	}

	smash_tilde( argument );

	if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		god = ch->pcdata->edit_god;

// 		if (argument[0] == '?')
// 		{
// 			/*
// 				Show god_edit status
// 			*/
// 			ch_printf_color(ch, "Syntax: <command> <value>\n\r\n\r");
// 			ch_printf_color(ch, "Command being one of:\n\r");
// 			ch_printf_color(ch, "  name domains align ethos alignhi alignlo ethoshi ethoslo\n\r");
// 			ch_printf_color(ch, "  race unproven acolyte prelate innercircle chosen\n\r");
// 			ch_printf_color(ch, "  faithenemy faithally weapon logout help done ? < >\n\r");
// 			pop_call();
// 			return;
// 		}
// 
		if (!strcasecmp(argument, "done"))
		{
			send_to_char( "GodEdit mode off.\n\r", ch );

			stop_god_editing(ch);

			pop_call();
			return;
		}

		if (!strcmp(argument, ">"))
		{
			if ((god = god + 1) >= MAX_GOD)
			{
				ch_printf_color(ch, "Next index not found.\n\r");
				pop_call();
				return;
			}
			stop_god_editing(ch);
			sprintf(buf, "%s", god_table[god].god_name);
			do_god_edit(ch, buf);
			pop_call();
			return;
		}

		if (!strcmp(argument, "<"))
		{
			if ((god = god - 1) < 1)
			{
				ch_printf_color(ch, "Next index not found.\n\r");
				pop_call();
				return;
			}
			stop_god_editing(ch);
			sprintf(buf, "%s", god_table[god].god_name);
			do_god_edit(ch, buf);
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "stat"))
		{
					sprintf(buf2, "{200}       Name:{178} %-30s\n\r", god_table[god].god_name);
			cat_sprintf(buf2, "{200}      Align:{178} %-12s    ",	god_table[god].align < 0 ? "Evil" : god_table[god].align > 0 ? "Good" : "Neutral");
			cat_sprintf(buf2, "{200}      Ethos:{178} %-12s\n\r",	god_table[god].ethos < 0 ? "Chaotic" : god_table[god].ethos > 0 ? "Lawful" : "Neutral");
			cat_sprintf(buf2, "{200}     Weapon:{178} %s\n\r",		weap_types[god_table[god].favored_weapon]);
			cat_sprintf(buf2, "{200}    Domains:{178} ");

			for(cnt = col = 0 ; cnt < MAX_DOMAIN ; cnt++)
			{
				if (!god_table[god].domain[cnt])
					continue;
				if (col)
					cat_sprintf(buf2, ", ");
				cat_sprintf(buf2, domain_types[cnt]);
				col++;
			}
			strcat(buf2, "\n\r");
		
			cat_sprintf(buf2, "{200}   Defaults:{178} %s, %s\n\r", domain_types[god_table[god].domain1], domain_types[god_table[god].domain2]);
			cat_sprintf(buf2, "{200}    AlignHi:{178} %-12s    ",  god_table[god].align_hi < -333 ? "Evil" : god_table[god].align_hi > 333 ? "Good" : "Neutral");
			cat_sprintf(buf2, "{200}    AlignLo:{178} %-12s\n\r",  god_table[god].align_lo < -333 ? "Evil" : god_table[god].align_lo > 333 ? "Good" : "Neutral");
			cat_sprintf(buf2, "{200}    EthosHi:{178} %-12s    ",  god_table[god].ethos_hi < -333 ? "Chaotic" : god_table[god].ethos_hi > 333 ? "Lawful" : "Neutral");
			cat_sprintf(buf2, "{200}    EthosLo:{178} %-12s\n\r",  god_table[god].ethos_lo < -333 ? "Chaotic" : god_table[god].ethos_lo > 333 ? "Lawful" : "Neutral");
			cat_sprintf(buf2, "{200}       Race:{178} %s\n\r",		flag_string(god_table[god].race, race_specs));
			cat_sprintf(buf2, "{200}PaladinMult:{178} %s\n\r",		flag_string(god_table[god].paladin_multi, class_types));
			cat_sprintf(buf2, "{200}  MonkMulti:{178} %s\n\r",		flag_string(god_table[god].monk_multi, class_types));
			cat_sprintf(buf2, "{200}   Unproven:{178} %s\n\r",		god_table[god].ranking[0]);
			cat_sprintf(buf2, "{200}    Acolyte:{178} %s\n\r",		god_table[god].ranking[1]);
			cat_sprintf(buf2, "{200}    Prelate:{178} %s\n\r",		god_table[god].ranking[2]);
			cat_sprintf(buf2, "{200}InnerCircle:{178} %s\n\r",		god_table[god].ranking[3]);
			cat_sprintf(buf2, "{200}     Chosen:{178} %s\n\r",		god_table[god].ranking[4]);
		
			cat_sprintf(buf2, "{200} FaithEnemy:{178}");
			for (col = cnt = 0 ; cnt < MAX_GOD ; cnt++)
			{
				if (god_table[god].faith_enemy[cnt])
				{
					if (col)
						cat_sprintf(buf2, ",");
					cat_sprintf(buf2, " %s", god_table[cnt].god_name);
					col++;
				}
				else
					continue;
			}
			cat_sprintf(buf2, "\n\r");

			cat_sprintf(buf2, "{200}  FaithAlly:{178}");
			for (col = cnt = 0 ; cnt < MAX_GOD ; cnt++)
			{
				if (god_table[god].faith_ally[cnt])
				{
					if (col)
						cat_sprintf(buf2, ",");
					cat_sprintf(buf2, " %s", god_table[cnt].god_name);
					col++;
				}
				else
					continue;
			}
			cat_sprintf(buf2, "\n\r");
			cat_sprintf(buf2, "Syntax: <field> <value>                        < %sprev next %s>\n\r", colg, colW);
			send_to_char_color(buf2, ch);
			pop_call();
			return;
		}
	}
	else
	{
		if ((god = lookup_god(argument)) == -1)
		{
			if (!is_number(argument) || (god = atoi(argument)) < 1 || god >= MAX_GOD)
			{
				send_to_char("Syntax: edit god <god name|god number>\n\r", ch);
				pop_call();
				return;
			}
		}
		ch->pcdata->edit_god = god;
		ch->pcdata->edittype = EDIT_TYPE_GOD;

		ch->pcdata->editmode = MODE_REPEATCMD;

		if (ch->pcdata)
		{
			if (ch->pcdata->subprompt)
			{
				STRFREE(ch->pcdata->subprompt);
			}
			sprintf( buf, "[%d] Editing God %s.", god, god_table[god].god_name);
			ch->pcdata->subprompt = STRALLOC( buf );
		}
		do_god_edit(ch, "stat");
		pop_call();
		return;
	}

	argument = one_argument(argument, arg2);

	value = is_number(argument) ? atoi(argument) : -1;

	if ( !strcasecmp( arg2, "name" ) )
	{
		if (strlen(argument) > 30)
		{
			ch_printf_color(ch, "name must be 30 characters or less.\n\r");
			pop_call();
			return;
		}
		strcpy(god_table[god].god_name, argument);
	}

	else if ( !strcasecmp( arg2, "unproven" ) )
	{
		strcpy(god_table[god].ranking[0], argument);
	}

	else if ( !strcasecmp( arg2, "acolyte" ) )
	{
		strcpy(god_table[god].ranking[1], argument);
	}

	else if ( !strcasecmp( arg2, "prelate" ) )
	{
		strcpy(god_table[god].ranking[2], argument);
	}

	else if ( !strcasecmp( arg2, "innercircle" ) )
	{
		strcpy(god_table[god].ranking[3], argument);
	}

	else if ( !strcasecmp( arg2, "chosen" ) )
	{
		strcpy(god_table[god].ranking[4], argument);
	}

	else if (!strcasecmp( arg2, "align" ))
	{
		if (!strcasecmp( argument, "evil" ))
			value = -1000;
		else if (!strcasecmp( argument, "neutral" ))
			value = 0;
		else if (!strcasecmp( argument, "good" ))
			value = 1000;
		else if (value != 1000 && value != 0 && value != -1000)
		{
			ch_printf_color(ch, "Options are good, neutral, or evil.\n\r");
			pop_call();
			return;
		}
		god_table[god].align = value;
	}

	else if (!strcasecmp( arg2, "alignhi" ))
	{
		if (!strcasecmp( argument, "evil" ))
			value = -333;
		else if (!strcasecmp( argument, "neutral" ))
			value = 333;
		else if (!strcasecmp( argument, "good" ))
			value = 1000;
		else
		{
			ch_printf_color(ch, "Options are good, neutral, or evil.\n\r");
			pop_call();
			return;
		}
		god_table[god].align_hi = value;
	}

	else if (!strcasecmp( arg2, "alignlo" ))
	{
		if (!strcasecmp( argument, "evil" ))
			value = -1000;
		else if (!strcasecmp( argument, "neutral" ))
			value = -333;
		else if (!strcasecmp( argument, "good" ))
			value = 333;
		else
		{
			ch_printf_color(ch, "Options are good, neutral, or evil.\n\r");
			pop_call();
			return;
		}
		god_table[god].align_lo = value;
	}

	else if (!strcasecmp( arg2, "ethos" ))
	{
		if (!strcasecmp( argument, "chaotic" ))
			value = -1000;
		else if (!strcasecmp( argument, "neutral" ))
			value = 0;
		else if (!strcasecmp( argument, "lawful" ))
			value = 1000;
		else if (value != 1000 && value != 0 && value != -1000)
		{
			ch_printf_color(ch, "Options are chaotic, neutral, or lawful.\n\r");
			pop_call();
			return;
		}
		god_table[god].ethos = value;
	}

	else if (!strcasecmp( arg2, "ethoshi" ))
	{
		if (!strcasecmp( argument, "chaotic" ))
			value = -333;
		else if (!strcasecmp( argument, "neutral" ))
			value = 333;
		else if (!strcasecmp( argument, "lawful" ))
			value = 1000;
		else
		{
			ch_printf_color(ch, "Options are chaotic, neutral, or lawful.\n\r");
			pop_call();
			return;
		}
		god_table[god].ethos_hi = value;
	}

	else if (!strcasecmp( arg2, "ethoslo" ))
	{
		if (!strcasecmp( argument, "chaotic" ))
			value = -1000;
		else if (!strcasecmp( argument, "neutral" ))
			value = -333;
		else if (!strcasecmp( argument, "lawful" ))
			value = 333;
		else
		{
			ch_printf_color(ch, "Options are chaotic, neutral, or lawful.\n\r");
			pop_call();
			return;
		}
		god_table[god].ethos_lo = value;
	}

	else if (!strcasecmp( arg2, "weapon" ))
	{
		if ((value = get_flag(argument, weap_types)) == -1)
		{
			ch_printf_color(ch, "weapon <%s>.\n\r", give_flags(weap_types));
			pop_call();
			return;
		}
		god_table[god].favored_weapon = value;
	}

	else if (!strcasecmp( arg2, "race" ))
	{
		if ((value = get_flag(argument, race_specs)) == -1)
		{
			ch_printf_color(ch, "race <%s>.\n\r", give_flags(race_specs));
			pop_call();
			return;
		}
		TOGGLE_BIT(god_table[god].race, 1 << value);
	}

	else if (!strcasecmp( arg2, "paladinmulti" ))
	{
		if ((value = get_flag(argument, class_types)) == -1)
		{
			ch_printf_color(ch, "paladinmulti <%s>.\n\r", give_flags(class_types));
			pop_call();
			return;
		}
		TOGGLE_BIT(god_table[god].paladin_multi, 1 << value);
	}

	else if (!strcasecmp( arg2, "monkmulti" ))
	{
		if ((value = get_flag(argument, class_types)) == -1)
		{
			ch_printf_color(ch, "monkmulti <%s>.\n\r", give_flags(class_types));
			pop_call();
			return;
		}
		TOGGLE_BIT(god_table[god].monk_multi, 1 << value);
	}

	else if (!strcasecmp( arg2, "faithenemy" ))
	{
		if (*argument == '\0')
		{
			ch_printf_color(ch, "Which god?\n\r");
			pop_call();
			return;
		}
		while (argument[0] != '\0')
		{
			argument = one_argument(argument, arg3);

			if ((value = lookup_god(arg3)) == -1)
			{
				ch_printf_color(ch, "%s is not a god.\n\r", arg3);
			}
			else if (value == god)
			{
				ch_printf_color(ch, "You can't set the god as his own enemy.\n\r");
			}
			else
			{
				if (god_table[god].faith_enemy[value] == 1)
				{
					god_table[god].faith_enemy[value] = 0;
					god_table[value].faith_enemy[god] = 0;
				}			
				else
				{
					god_table[god].faith_enemy[value] = 1;
					god_table[value].faith_enemy[god] = 1;
				}
			}
		}
	}

	else if (!strcasecmp( arg2, "faithally" ))
	{
		if (*argument == '\0')
		{
			ch_printf_color(ch, "Which god?\n\r");
			pop_call();
			return;
		}
		while (argument[0] != '\0')
		{
			argument = one_argument(argument, arg3);

			if ((value = lookup_god(arg3)) == -1)
			{
				ch_printf_color(ch, "%s is not a god.\n\r", arg3);
			}
			else if (value == god)
			{
				ch_printf_color(ch, "You can't set the god as his own ally.\n\r");
			}
			else
			{
				if (god_table[god].faith_ally[value] == 1)
				{
					god_table[god].faith_ally[value] = 0;
					god_table[value].faith_ally[god] = 0;
				}
				else
				{
					god_table[god].faith_ally[value] = 1;
					god_table[value].faith_ally[god] = 1;
				}
			}
		}
	}

	else if (!strcasecmp( arg2, "domains" ))
	{
		if (*argument == '\0')
		{
			ch_printf_color(ch, "domains <%s>.\n\r", give_flags(domain_types));
			pop_call();
			return;
		}
		while (argument[0] != '\0')
		{
			argument = one_argument(argument, arg3);

			if ((value = get_flag(arg3, domain_types)) == -1)
			{
				ch_printf_color(ch, "%s is not a valid domain.\n\r", arg3);
			}
			else
			{
				TOGGLE_BIT(god_table[god].domain[value], 1);
			}
		}
	}

	else if (!strcasecmp( arg2, "defaults" ))
	{
		int value2;

		argument = one_argument(argument, arg2);
		
		if ((value = get_flag(arg2, domain_types)) == -1
		|| (value2 = get_flag(argument, domain_types)) == -1)
		{
			ch_printf_color(ch, "domains <%s>.\n\r", give_flags(domain_types));
			pop_call();
			return;
		}
		god_table[god].domain1 = value;
		god_table[god].domain2 = value2;
	}

	else if (!strcasecmp( arg2, "domain2" ))
	{
		if ((value = get_flag(argument, domain_types)) == -1)
		{
			ch_printf_color(ch, "domain2 <%s>.\n\r", give_flags(weap_types));
			pop_call();
			return;
		}
		god_table[god].domain2 = value;
	}

	else if ( ch->pcdata->editmode == MODE_REPEATCMD )
	{
		ch->pcdata->editmode = MODE_RESTRICTED;
		interpret( ch, origarg );
		ch->pcdata->editmode = MODE_REPEATCMD;
		ch->pcdata->last_cmd = do_edit;
		pop_call();
		return;
	}
	
	do_god_edit( ch, "stat" );

	pop_call();
	return;
}


/*
 * online class editor - Kregor
 */
void stop_class_editing(CHAR_DATA *ch)
{
	push_call("stop_class_editing(%p,%p)",ch);

	ch->pcdata->edittype 	= EDIT_TYPE_NONE;
	ch->pcdata->editmode 	= MODE_NONE;
	ch->pcdata->tempmode 	= MODE_NONE;
	ch->pcdata->edit_class = 0;

	if (ch->pcdata && ch->pcdata->subprompt)
	{
		STRFREE(ch->pcdata->subprompt);
		ch->pcdata->subprompt = NULL;
	}
	save_classes();

	pop_call();
	return;
}

/* constants for class editor - Kregor */
char *  const   mana_flags [] =
{
	"none",
	"bard",
	"wiz_priest",
	"warrior",
	"sorcerer",
	"prestige",
	"prestige_arcane",
	"prestige_divine",
	"prestige_either",
	"prestige_both",
	"prest_arc_half",
	"prest_div_half",
	"*"
};

char *  const   stat_flags [] =
{
	"none",
	"str",
	"dex",
	"int",
	"wis",
	"con",
	"cha",
	"*"
};


void do_class_edit( CHAR_DATA *ch, char *argument )
{
	char arg2 [MAX_INPUT_LENGTH];
	char arg3 [MAX_INPUT_LENGTH];
	char buf  [MAX_STRING_LENGTH];
	char buf2	[MAX_STRING_LENGTH];
	int  value, sn, class, col, lvl;
	char *origarg = argument;
	
	char colw[10], colg[10], colW[10];

	push_call("do_class_edit(%p,%p)",ch,argument);

	CHECK_EDITMODE( ch );

	strcpy(colw, get_color_string(ch, COLOR_TEXT, VT102_DIM));
	strcpy(colg, get_color_string(ch, COLOR_ACCENT, VT102_DIM));
	strcpy(colW, get_color_string(ch, COLOR_TEXT, VT102_BOLD));

	if (!ch->desc)
	{
		send_to_char( "You have no descriptor\n\r", ch );
		pop_call();
		return;
	}

	smash_tilde( argument );

	if (ch->pcdata->editmode == MODE_REPEATCMD)
	{
		class = ch->pcdata->edit_class;

		if (!strcasecmp(argument, "done"))
		{
			send_to_char( "ClassEdit mode off.\n\r", ch );

			stop_class_editing(ch);

			pop_call();
			return;
		}

		if (!strcmp(argument, ">"))
		{
			if ((class = class + 1) >= MAX_CLASS)
			{
				ch_printf_color(ch, "Next index not found.\n\r");
				pop_call();
				return;
			}
			stop_class_editing(ch);
			sprintf(buf, "%s", class_table[class].who_name_long);
			do_class_edit(ch, buf);
			pop_call();
			return;
		}

		if (!strcmp(argument, "<"))
		{
			if ((class = class - 1) < 1)
			{
				ch_printf_color(ch, "Next index not found.\n\r");
				pop_call();
				return;
			}
			stop_class_editing(ch);
			sprintf(buf, "%s", class_table[class].who_name_long);
			do_class_edit(ch, buf);
			pop_call();
			return;
		}

		if (!strcasecmp(argument, "stat"))
		{
					sprintf(buf2, "{200}       Name:{178} %-21s", 		class_table[class].who_name_long);
			cat_sprintf(buf2, "{200}    WhoName:{178} %-4s",			class_table[class].who_name);
			cat_sprintf(buf2, "{200}    PCCLass:{178} %-4s\n\r",	class_table[class].pc_class ? "yes" : "no");
			cat_sprintf(buf2, "{200}       Fort:{178} %-4s",			type_string(class_table[class].fort_save, bab_saves));
			cat_sprintf(buf2, "{200}       Refl:{178} %-4s",			type_string(class_table[class].refl_save, bab_saves));
			cat_sprintf(buf2, "{200}       Will:{178} %-4s",			type_string(class_table[class].will_save, bab_saves));
			cat_sprintf(buf2, "{200}   MaxLevel:{178} %-4d\n\r",	class_table[class].max_level);
			cat_sprintf(buf2, "{200}     HitDie:{178} %-4d",			class_table[class].hp_max);
			cat_sprintf(buf2, "{200}        BAB:{178} %-4s",			type_string(class_table[class].base_attack, bab_saves));
			cat_sprintf(buf2, "{200}   SkillPts:{178} %-4d",			class_table[class].skill_pts);
			cat_sprintf(buf2, "{200}  ManaTable:{178} %-12s\n\r", type_string(class_table[class].mana_table, mana_flags));
			cat_sprintf(buf2, "{200}  AttrPrime:{178} %-4s",			type_string(class_table[class].attr_prime, stat_flags));
			cat_sprintf(buf2, "{200}    AttrSec:{178} %-4s",			type_string(class_table[class].attr_second, stat_flags));
			cat_sprintf(buf2, "{200}   PrimeMod:{178} %-4d",			class_table[class].prime_mod);
			cat_sprintf(buf2, "{200}     SecMod:{178} %-4d\n\r",	class_table[class].sec_mod	);
			cat_sprintf(buf2, "{200}     Spells:{178} (type to list)\n\r");
			cat_sprintf(buf2, "{200} BonusFeats:{178} (type to list)\n\r");
			cat_sprintf(buf2, "{200}  FirstFeat:{178} %-4d",			class_table[class].first_bonus);
			cat_sprintf(buf2, "{200}  FeatLevel:{178} %-4d\n\r",	class_table[class].bonus_lvl	);
		
			// display skill list
			cat_sprintf(buf2, "{200}ClassSkills:\n\r {178}");
			for (col = sn = 0 ; is_string(skill_table[sn].name) ; sn++)
			{
				if (skill_table[sn].skilltype != FSKILL_SKILL
				&& skill_table[sn].skilltype != FSKILL_KNOWLEDGE
				&& skill_table[sn].skilltype != FSKILL_CRAFT)
					continue;
				if (skill_table[sn].skill_level[class] >= LEVEL_IMMORTAL)
					continue;
				if (col)
					cat_sprintf(buf2, "  ");
				cat_sprintf(buf2, "%-18s", skill_table[sn].name);
				col++;
				
				if (col == 4)
				{
					cat_sprintf(buf2, "\n\r ");
					col = 0;
				}
			}
			if (col != 0)
				cat_sprintf(buf2, "\n\r");

			// display ability list
			cat_sprintf(buf2, "{200}    Ability:\n\r {178}");
			for (col = 0, lvl = 1 ; lvl <= 20 ; lvl++)
			{
				for (sn = 0 ; is_string(skill_table[sn].name) ; sn++)
				{
					if (skill_table[sn].skilltype != FSKILL_FEAT
					&& skill_table[sn].skilltype != FSKILL_WEAPON
					&& skill_table[sn].skilltype != FSKILL_BARDSONG
					&& skill_table[sn].skilltype != FSKILL_ABILITY)
						continue;
					if (skill_table[sn].skill_level[class] != lvl)
						continue;
					if (col)
						cat_sprintf(buf2, "  ");
					cat_sprintf(buf2, "%-21s %2d", skill_table[sn].name, lvl);
					col++;
					
					if (col % 3 == 0)
					{
						cat_sprintf(buf2, "\n\r ");
						col = 0;
					}
				}
			}
			if (col % 3 != 0)
				cat_sprintf(buf2, "\n\r");

			cat_sprintf(buf2, "\n\r%sSyntax: <field> <value>                        %s< %sprev next %s>\n\r", colg, colW, colg, colW);
			send_to_char_color(buf2, ch);
			pop_call();
			return;
		}
	}
	else
	{
		if ((class = lookup_class(argument)) == -1)
		{
			send_to_char("Syntax: edit class <class name>\n\r", ch);
			pop_call();
			return;
		}
		ch->pcdata->edit_class = class;
		ch->pcdata->edittype = EDIT_TYPE_CLASS;

		ch->pcdata->editmode = MODE_REPEATCMD;

		if (ch->pcdata)
		{
			if (ch->pcdata->subprompt)
			{
				STRFREE(ch->pcdata->subprompt);
			}
			sprintf( buf, "[%d] Editing Class %s.", class, class_table[class].who_name_long);
			ch->pcdata->subprompt = STRALLOC( buf );
		}
		do_class_edit(ch, "stat");
		pop_call();
		return;
	}

	argument = one_argument(argument, arg2);

	value = is_number(argument) ? atoi(argument) : -1;

	if ( !strcasecmp( arg2, "name" ) )
	{
		if (strlen(argument) > 20)
		{
			ch_printf_color(ch, "name must be 20 characters or less.\n\r");
			pop_call();
			return;
		}
		strcpy(class_table[class].who_name_long, argument);
	}

	if ( !strcasecmp( arg2, "whoname" ) )
	{
		if (strlen(argument) > 3)
		{
			ch_printf_color(ch, "Who name must be 3 characters or less.\n\r");
			pop_call();
			return;
		}
		strcpy(class_table[class].who_name, argument);
	}

	else if ( !strcasecmp( arg2, "bonusfeats" ) )
	{
		if (*argument == '\0')
		{
			sprintf(buf2, "{200}%s Bonus Feats:\n\r{178}", class_table[class].who_name_long);

			// display feat list
			for (col = sn = 0 ; is_string(skill_table[sn].name) ; sn++)
			{
				if (skill_table[sn].skilltype != FSKILL_FEAT)
					continue;
				if (skill_table[sn].bonus_feat[class] >= 75)
					continue;
				if (col)
					cat_sprintf(buf2, "  ");
				cat_sprintf(buf2, "%2d %-21s", skill_table[sn].bonus_feat[class], skill_table[sn].name);
				col++;
				
				if (col == 3)
				{
					cat_sprintf(buf2, "\n\r ");
					col = 0;
				}
			}
			if (col != 0)
				cat_sprintf(buf2, "\n\r ");

			send_to_char_color(buf2, ch);
			pop_call();
			return;
		}
		argument = one_argument(argument, arg3);
		
		if ((sn = skill_lookup(arg3)) == -1 || skill_table[sn].skilltype != FSKILL_FEAT)
		{
			ch_printf_color(ch, "%s is not a valid feat.\n\r", arg3);
			pop_call();
			return;
		}
		if (!is_number(argument) || (value = atoi(argument)) < 1 || value > 20)
		{
			skill_table[sn].bonus_feat[class] = 75;
		}
		else
		{
			skill_table[sn].bonus_feat[class] = value;
		}
		do_class_edit(ch, "bonusfeats");
		pop_call();
		return;
	}

	else if ( !strcasecmp( arg2, "spells" ) )
	{
		if (class_table[class].mana_table == MANA_NONE
		|| class_table[class].mana_table > MANA_PRESTIGE)
		{
			ch_printf_color(ch, "This class has no mana pool.\n\r");
			pop_call();
			return;
		}
		if (*argument == '\0')
		{
			int lvl, low, hi;
			
			switch(class_table[class].mana_table)
			{
				case MANA_WIZ_PRIEST:
				case MANA_SORCERER:
					low = 0;
					hi  = 9;
					break;
				case MANA_BARD:
					low = 0;
					hi  = 6;
					break;
				case MANA_WARRIOR:
				case MANA_PRESTIGE:
					low = 1;
					hi  = 4;
					break;
				default:
					low = hi = 0;
					break;
			}
			
			sprintf(buf2, "{200}%s Spell List:\n\r{178}", class_table[class].who_name_long);

			for (lvl = low ; lvl <= hi ; lvl++)
			{
				// display spell list
				cat_sprintf(buf2, "{200}%s Circle:\n\r {178}", numbersuf(lvl));
				
				for (col = sn = 0 ; is_string(skill_table[sn].name) ; sn++)
				{
					if (skill_table[sn].skilltype != FSKILL_SPELL)
						continue;
					if (skill_table[sn].skill_level[class] != lvl)
						continue;
					if (col)
						cat_sprintf(buf2, "  ");
					cat_sprintf(buf2, "%-24s", skill_table[sn].name);
					col++;
					
					if (col == 3)
					{
						cat_sprintf(buf2, "\n\r ");
						col = 0;
					}
				}
				if (col != 0)
					cat_sprintf(buf2, "\n\r ");
			}
			send_to_char_color(buf2, ch);
			pop_call();
			return;
		}
		argument = one_argument(argument, arg3);
		
		if ((sn = skill_lookup(arg3)) == -1 || !is_spell(sn))
		{
			ch_printf_color(ch, "%s is not a valid spell.\n\r", arg3);
			pop_call();
			return;
		}
		if (!is_number(argument) || (value = atoi(argument)) < 0 || value > 9)
		{
			ch_printf_color(ch, "What circle spell is %s?\n\r", arg3);
			pop_call();
			return;
		}
		skill_table[sn].skill_level[class] = value;
		do_class_edit(ch, "spells");
		pop_call();
		return;
	}

	else if ( !strcasecmp( arg2, "classskills" ) )
	{
		if (*argument == '\0')
		{
			ch_printf_color(ch, "What skills?\n\r");
			pop_call();
			return;
		}
		while (*argument != '\0')
		{		
			argument = one_argument(argument, arg3);
		
			if ((sn = skill_lookup(arg3)) == -1)
			{
				ch_printf_color(ch, "%s is not a valid skill.\n\r", arg3);
				continue;
			}
			if (skill_table[sn].skilltype != FSKILL_SKILL
			&& skill_table[sn].skilltype != FSKILL_CRAFT
			&& skill_table[sn].skilltype != FSKILL_KNOWLEDGE)
			{
				ch_printf_color(ch, "%s is not a skill.\n\r", arg3);
				continue;
			}
			if (skill_table[sn].skill_level[class] < LEVEL_IMMORTAL)
				skill_table[sn].skill_level[class] = LEVEL_IMMORTAL;
			else
				skill_table[sn].skill_level[class] = 1;
		}
	}

	else if ( !strcasecmp( arg2, "ability" ) || !strcasecmp( arg2, "abilities" ) )
	{
		if (*argument == '\0')
		{
			ch_printf_color(ch, "ability <feat or ability> <class level>\n\r");
			pop_call();
			return;
		}
		argument = one_argument(argument, arg3);
	
		if ((sn = skill_lookup(arg3)) == -1)
		{
			ch_printf_color(ch, "%s is not a valid class ability.\n\r", arg3);
			pop_call();
			return;
		}
		if (skill_table[sn].skilltype != FSKILL_ABILITY
		&& skill_table[sn].skilltype != FSKILL_FEAT)
		{
			ch_printf_color(ch, "%s is not a feat or ability.\n\r", arg3);
			pop_call();
			return;
		}
		if (!is_number(argument))
		{
			ch_printf_color(ch, "Gain %s at what level?\n\r", arg3);
			pop_call();
			return;
		}
		if ((value = atoi(argument)) < 1 || value > LEVEL_EPIC)
		{
			if (value == 0 || value == LEVEL_IMMORTAL)
			{
				skill_table[sn].skill_level[class] = LEVEL_IMMORTAL;
			}
			else
			{
				ch_printf_color(ch, "Class level is 1-20, or 0 to remove.\n\r", arg3);
				pop_call();
				return;
			}
		}
		skill_table[sn].skill_level[class] = value;
	}

	else if (!strcasecmp( arg2, "hitdie" ))
	{
		switch (value)
		{
			case 4:
			case 6:
			case 8:
			case 10:
			case 12:
				break;
			default:
				ch_printf_color(ch, "Not a valid hit die size.\n\r");
				pop_call();
				return;
		}
		class_table[class].hp_max = value;
	}

	else if (!strcasecmp( arg2, "pcclass" ))
	{
		if (!strcasecmp(argument, "yes"))
			value = 1;
		else if (!strcasecmp(argument, "no"))
			value = 0;
		else
		{
			ch_printf_color(ch, "PCClass: <yes|no>\n\r");
			pop_call();
			return;
		}
		class_table[class].pc_class = value;
	}

	else if (!strcasecmp( arg2, "manatable" ))
	{
		if ((value = get_flag(argument, mana_flags)) == -1)
		{
			ch_printf_color(ch, "ManaTable: <%s>\n\r", give_flags(mana_flags));
			pop_call();
			return;
		}
		class_table[class].mana_table = value;
	}

	else if (!strcasecmp( arg2, "attrprime" ))
	{
		if ((value = get_flag(argument, stat_flags)) == -1)
		{
			ch_printf_color(ch, "Attrprime: <%s>\n\r", give_flags(stat_flags));
			pop_call();
			return;
		}
		class_table[class].attr_prime = value;
	}

	else if (!strcasecmp( arg2, "attrsec" ))
	{
		if ((value = get_flag(argument, stat_flags)) == -1)
		{
			ch_printf_color(ch, "Attrsec: <%s>\n\r", give_flags(stat_flags));
			pop_call();
			return;
		}
		class_table[class].attr_second = value;
	}

	else if (!strcasecmp( arg2, "primod" ))
	{
		if (value == -1)
		{
			ch_printf_color(ch, "Modifier must be a number\n\r");
			pop_call();
			return;
		}
		class_table[class].prime_mod = value;
	}

	else if (!strcasecmp( arg2, "secmod" ))
	{
		if (value == -1)
		{
			ch_printf_color(ch, "Modifier must be a number\n\r");
			pop_call();
			return;
		}
		class_table[class].sec_mod = value;
	}

	else if (!strcasecmp( arg2, "will" ))
	{
		if (!strcasecmp( argument, "poor" ))
			value = SAVE_LOW;
		else if (!strcasecmp( argument, "good" ))
			value = SAVE_MED;
		else if (!strcasecmp( argument, "best" ))
			value = SAVE_HIGH;
		else
		{
			ch_printf_color(ch, "Save progression: poor, good, best?\n\r");
			pop_call();
			return;
		}
		class_table[class].will_save = value;
	}

	else if (!strcasecmp( arg2, "refl" ))
	{
		if (!strcasecmp( argument, "poor" ))
			value = SAVE_LOW;
		else if (!strcasecmp( argument, "good" ))
			value = SAVE_MED;
		else if (!strcasecmp( argument, "best" ))
			value = SAVE_HIGH;
		else
		{
			ch_printf_color(ch, "Save progression: poor, good, best?\n\r");
			pop_call();
			return;
		}
		class_table[class].refl_save = value;
	}

	else if (!strcasecmp( arg2, "fort" ))
	{
		if (!strcasecmp( argument, "poor" ))
			value = SAVE_LOW;
		else if (!strcasecmp( argument, "good" ))
			value = SAVE_MED;
		else if (!strcasecmp( argument, "best" ))
			value = SAVE_HIGH;
		else
		{
			ch_printf_color(ch, "Save progression: poor, good, best?\n\r");
			pop_call();
			return;
		}
		class_table[class].fort_save = value;
	}

	else if (!strcasecmp( arg2, "bab" ))
	{
		if (!strcasecmp( argument, "poor" ))
			value = BAB_POOR;
		else if (!strcasecmp( argument, "good" ))
			value = BAB_GOOD;
		else if (!strcasecmp( argument, "best" ))
			value = BAB_BEST;
		else
		{
			ch_printf_color(ch, "Base attack bonus: poor, good, best?\n\r");
			pop_call();
			return;
		}
		class_table[class].base_attack = value;
	}

	else if (!strcasecmp( arg2, "skillpts" ))
	{
		switch (value)
		{
			case 2:
			case 4:
			case 6:
			case 8:
				break;
			default:
				ch_printf_color(ch, "Class gains 2, 4, 6 or 8 skill pts per level?\n\r");
				pop_call();
				return;
		}
		class_table[class].skill_pts = value;
	}

	else if (!strcasecmp( arg2, "firstfeat" ))
	{
		if (value < 0 || value > 20)
		{
			send_to_char_color("First bonus feat at what level?\n\r", ch);
			pop_call();
			return;
		}
		class_table[class].first_bonus = value;
	}

	else if (!strcasecmp( arg2, "featlevel" ))
	{
		class_table[class].bonus_lvl = value;
	}

	else if (!strcasecmp( arg2, "maxlevel" ))
	{
		class_table[class].max_level = value;
	}

	else if ( ch->pcdata->editmode == MODE_REPEATCMD )
	{
		ch->pcdata->editmode = MODE_RESTRICTED;
		interpret( ch, origarg );
		ch->pcdata->editmode = MODE_REPEATCMD;
		ch->pcdata->last_cmd = do_edit;
		pop_call();
		return;
	}
	
	do_class_edit( ch, "stat" );

	pop_call();
	return;
}


bool bad_short_desc( char *str )
{
	push_call("bad_short_desc_check(%p)",str);

	if (!str_prefix("an ", str))
	{
		pop_call();
		return (str[0] == 'A');
	}

	if (!str_prefix("a ", str))
	{
		pop_call();
		return (str[0] == 'A');
	}

	if (!str_prefix("the ", str))
	{
		pop_call();
		return (str[0] == 'T');
	}

	pop_call();
	return FALSE;
}


void do_area_assign( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	char arg3[MAX_INPUT_LENGTH];
	int  a_lo, a_hi;
	CHAR_DATA *victim;

	push_call("do_area_assign(%p,%p)",ch,argument);

	CHECK_EDITMODE(ch)

	if (!IS_GOD(ch))
	{
		ch_printf_color(ch, "Alas, Gods only =]");
		pop_call();
		return;
	}

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

	a_lo = atoi(arg2);
	a_hi = atoi(arg3);

	if (arg1[0] == '\0' || a_lo < 1 || a_hi < 1 || a_lo > a_hi)
	{
		send_to_char( "Syntax: edit area assign <player> <low vnum> <high vnum>\n\r", ch );
		pop_call();
		return;
	}

	if ((victim = get_player_world(ch, arg1)) == NULL)
	{
		send_to_char( "They don't seem to be around.\n\r", ch );
		pop_call();
		return;
	}

	if (IS_NPC(victim) || victim->level < LEVEL_IMMORTAL)
	{
		send_to_char( "They wouldn't know what to do with a vnum range.\n\r", ch);
		pop_call();
		return;
	}

	if (a_lo > a_hi)
	{
		send_to_char( "Unacceptable vnum range.\n\r", ch );
		pop_call();
		return;
	}

	if (a_lo == 0)
	{
		a_hi = 0;
	}

	victim->pcdata->a_range_lo = a_lo;
	victim->pcdata->a_range_hi = a_hi;

	ch_printf_color(ch,     "You assigned %s the vnum range %d - %d.\n\r", victim->name, a_lo, a_hi);
	ch_printf_color(victim, "%s has assigned you the vnum range %d - %d.\n\r", ch->name, a_lo, a_hi);

	if ((get_room_index(a_lo)) == NULL)
	{
		assign_area( victim );
		do_savearea( NULL, "forreal");
	}
	pop_call();
	return;
}


int objdata_caster_level( OBJ_INDEX_DATA *obj, int sn )
{
	int mlv;

	push_call("item_caster_level(%p,%p)",obj,sn);

	if (sn == -1 || !is_spell(sn))
	{
		pop_call();
		return -1;
	}

	mlv = (get_spell_circle(NULL, sn) * 2) - 1;

	if (obj->item_type == ITEM_STAFF
	|| obj->item_type == ITEM_WAND
	|| obj->item_type == ITEM_POTION
	|| obj->item_type == ITEM_PILL)
	{
		if (obj->value[0] > mlv)
			mlv = obj->value[0];
	}
	pop_call();
	return(mlv);
}


void do_area_check ( CHAR_DATA *ch, char *argument )
{
	char 			arg[MAX_STRING_LENGTH];
	bool				fix, door, mobiles, rooms, objects;
	AREA_DATA			*area;
	ROOM_INDEX_DATA	*room;
	MOB_INDEX_DATA		*mob;
	OBJ_INDEX_DATA		*obj;
	AFFECT_DATA		*aff;
	EXTRA_DESCR_DATA	*ed;
	char colc[10], colw[10], colW[10];

	int vnum, lvl_neg, lvl_pos, lvl, cnt, max_cnt, aff_cnt, lo_vnum, hi_vnum;

	push_call("do_area_check(%p,%p)",ch,argument);

	one_argument(argument, arg);

	fix = lo_vnum = hi_vnum = FALSE;
	mobiles = objects = rooms = TRUE;
	max_cnt	= get_pager_breakpt(ch) - 2;

	if (!strcasecmp(arg, "fix"))
	{
		fix 		= TRUE;
		area 	= ch->in_room->area;
	}
	else if (!strcasecmp(arg, "mobiles"))
	{
		rooms	= FALSE;
		objects	= FALSE;
		area 	= ch->in_room->area;
	}
	else if (!strcasecmp(arg, "rooms"))
	{
		mobiles	= FALSE;
		objects	= FALSE;
		area 	= ch->in_room->area;
	}
	else if (!strcasecmp(arg, "objects"))
	{
		rooms	= FALSE;
		mobiles	= FALSE;
		area 	= ch->in_room->area;
	}
	else
	{
		if (argument[0] != '\0')
		{
			area = lookup_area(argument);
		}
		else
		{
			area = ch->in_room->area;
		}
	}

	if (area == NULL)
	{
		ch_printf_color(ch, "Syntax: edit area check [name|fix|mobiles|rooms|objects]\n\r");
		pop_call();
		return;
	}

	if (!can_olc_modify(ch, area->low_r_vnum))
	{
		ch_printf_color(ch, "You can only check areas in your allocated vnum range\n\r");
		pop_call();
		return;
	}
	
	strcpy(colc, get_color_string(ch, COLOR_ACCENT, VT102_DIM));
	strcpy(colw, get_color_string(ch, COLOR_TEXT, VT102_DIM));
	strcpy(colW, get_color_string(ch, COLOR_TEXT, VT102_BOLD));

	lvl = cnt	= 0;

	if (rooms)
	{
		lo_vnum = area->low_r_vnum;
		hi_vnum = area->hi_r_vnum;
	
		for (vnum = lo_vnum ; vnum <= hi_vnum ; vnum++)
		{
			if ((room = get_room_index(vnum)) == NULL)
			{
				continue;
			}
	
			if (IS_SET(room->room_flags, ROOM_NO_RECALL) && IS_SET(area->flags, AFLAG_NORECALL) && ++cnt < max_cnt)
			{
				if (fix)
				{
					REMOVE_BIT(room->room_flags, ROOM_NO_RECALL);
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sBoth room and area have norecall flag set.\n\r", colc, colW, room->vnum, colc, colw);
				}
			}
			if (IS_SET(room->room_flags, ROOM_NO_RIP) && IS_SET(area->flags, AFLAG_NORIP) && ++cnt < max_cnt)
			{
				if (fix)
				{
					REMOVE_BIT(room->room_flags, ROOM_NO_RIP);
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sBoth room and area have norip flag set.\n\r", colc, colW, room->vnum, colc, colw);
				}
			}
			if (room->description[0] && str_suffix("\n\r", room->description) && ++cnt < max_cnt)
			{
				if (fix)
				{
					sprintf(arg, "%s\n\r", room->description);
					RESTRING(room->description, arg);
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sRoom has a bad description.\n\r", colc, colW, room->vnum, colc, colw);
				}
			}
			for (ed = room->first_extradesc ; ed ; ed = ed->next)
			{
				if (str_suffix("\n\r", ed->description) && ++cnt < max_cnt)
				{
					if (fix)
					{
						sprintf(arg, "%s\n\r", ed->description);
						RESTRING(ed->description, arg);
					}
					else
					{
						ch_printf_color(ch, "%s[%s%u%s] %sRoom has a bad extra description.\n\r", colc, colW, room->vnum, colc, colw);
					}
				}
			}
			for (door = 0 ; door < 6 ; door++)
			{
				if (room->exit[door] && room->exit[door]->description[0])
				{
					if (!str_suffix("\n\r", room->exit[door]->description) && ++cnt < max_cnt)
					{
						if (fix)
						{
							strcpy(arg, room->exit[door]->description);
							arg[strlen(arg) - 2] = '\0';
							RESTRING(room->exit[door]->description, arg);
						}
						else
						{
							ch_printf_color(ch, "%s[%s%u%s] %sRoom has a bad exit description.\n\r", colc, colW, room->vnum, colc, colw);
						}
					}
				}
			}
		}
	}
	
	if (objects)
	{
		lo_vnum = area->low_o_vnum;
		hi_vnum = area->hi_o_vnum;
	
		for (vnum = lo_vnum ; vnum <= hi_vnum ; vnum++)
		{
			if ((obj = get_obj_index(vnum)) == NULL)
			{
				continue;
			}
	
			lvl_neg = 0;
			lvl_pos = 1;
	
			if (fix == FALSE)
			{
				for (aff_cnt = 0, aff = obj->first_affect ; aff ; aff = aff->next, aff_cnt++)
				{
					switch (aff->location)
					{
						case APPLY_STR:
						case APPLY_WIS:
						case APPLY_CON:
						case APPLY_DEX:
						case APPLY_INT:
						case APPLY_CHA:
							if (aff->modifier > 6 && ++cnt < max_cnt)
							{
								if (fix)
								{
									aff->modifier = 6;
								}
								else
								{
									ch_printf_color(ch, "%s[%s%u%s] %sObject's %s apply can be no more than 6.\n\r", colc, colW, obj->vnum, colc, colw, a_types[aff->location]);
								}
							}
							break;
						case APPLY_ARMOR:
							if (aff->modifier > 8 && ++cnt < max_cnt)
							{
								if (fix)
								{
									aff->modifier = 8;
								}
								else
								{
									ch_printf_color(ch, "%s[%s%u%s] %sObject's %s apply can be no more than 8.\n\r", colc, colW, obj->vnum, colc, colw, a_types[aff->location]);
								}
							}
							break;
						case APPLY_SHIELD:
						case APPLY_ENHANCE_AC:
						case APPLY_DEFLECT:
						case APPLY_DODGE:
							if (aff->modifier > 5 && ++cnt < max_cnt)
							{
								if (fix)
								{
									aff->modifier = 5;
								}
								else
								{
									ch_printf_color(ch, "%s[%s%u%s] %sObject's %s apply can be no more than 5.\n\r", colc, colW, obj->vnum, colc, colw, a_types[aff->location]);
								}
							}
							break;
						case APPLY_SAVING_FORT:
						case APPLY_SAVING_REFL:
						case APPLY_SAVING_WILL:
						case APPLY_SAVES:
						case APPLY_DAMROLL:
						case APPLY_HITROLL:
							if (aff->modifier > 5 && ++cnt < max_cnt)
							{
								if (fix)
								{
									aff->modifier = 5;
								}
								else
								{
									ch_printf_color(ch, "%s[%s%u%s] %sObject's %s apply can be no more than 5.\n\r", colc, colW, obj->vnum, colc, colw, a_types[aff->location]);
								}
							}
							break;
						default:
							break;
					}
				}
		
				switch (obj->item_type)
				{
					case ITEM_SCROLL:
					case ITEM_POTION:
						if (obj->value[0] <= 0 || obj->value[0] < objdata_caster_level(obj, obj->value[1]))
						{
							if (fix)
							{
								obj->value[0] = objdata_caster_level(obj, obj->value[1]);
							}
							else
							{
								ch_printf_color(ch, "%s[%s%u%s] %sObject's caster level too low for %s.\n\r", colc, colW, obj->vnum, colc, colw, skill_table[obj->value[1]].name);
							}
						}
						break;
					case ITEM_PILL:
						if (obj->value[0] <= 0
						|| obj->value[0] < objdata_caster_level(obj, obj->value[1])
						|| obj->value[0] < objdata_caster_level(obj, obj->value[2])
						|| obj->value[0] < objdata_caster_level(obj, obj->value[3]))
						{
							if (fix)
							{
								obj->value[0] = objdata_caster_level(obj, obj->value[1]);
								if (objdata_caster_level(obj, obj->value[2]) > obj->value[0])
									obj->value[0] = objdata_caster_level(obj, obj->value[2]);
								if (objdata_caster_level(obj, obj->value[3]) > obj->value[0])
									obj->value[0] = objdata_caster_level(obj, obj->value[3]);
							}
							else
							{
								ch_printf_color(ch, "%s[%s%u%s] %sObject's caster level too low.\n\r", colc, colW, obj->vnum, colc, colw);
							}
						}
						break;
					case ITEM_WAND:
						if (obj->value[0] <= 0 || obj->value[0] < objdata_caster_level(obj, obj->value[3]))
						{
							if (fix)
							{
								obj->value[0] = objdata_caster_level(obj, obj->value[3]);
							}
							else
							{
								ch_printf_color(ch, "%s[%s%u%s] %sObject's caster level too low for %s.\n\r", colc, colW, obj->vnum, colc, colw, skill_table[obj->value[1]].name);
							}
						}
						break;
					case ITEM_STAFF:
						if (obj->value[0] <= 0
						|| obj->value[0] < objdata_caster_level(obj, obj->value[3])
						|| obj->value[0] < objdata_caster_level(obj, obj->value[4])
						|| obj->value[0] < objdata_caster_level(obj, obj->value[5]))
						{
							if (fix)
							{
								obj->value[0] = objdata_caster_level(obj, obj->value[3]);
								if (objdata_caster_level(obj, obj->value[2]) > obj->value[0])
									obj->value[0] = objdata_caster_level(obj, obj->value[4]);
								if (objdata_caster_level(obj, obj->value[3]) > obj->value[0])
									obj->value[0] = objdata_caster_level(obj, obj->value[5]);
							}
							else
							{
								ch_printf_color(ch, "%s[%s%u%s] %sObject's caster level too low.\n\r", colc, colW, obj->vnum, colc, colw);
							}
						}
						break;
					default:
						break;
				}
		
				if (aff_cnt > 3 && ++cnt < max_cnt)
				{
					ch_printf_color(ch, "%s[%s%u%s] %sObject has more than 3 applies.\n\r", colc, colW, obj->vnum, colc, colw);
				}
				if (aff_cnt > 0 && !IS_SET(obj->wear_flags, CAN_WEAR_TAKE) && ++cnt < max_cnt)
				{
					ch_printf_color(ch, "%s[%s%u%s] %sObject has applies but cannot be worn or held.\n\r", colc, colW, obj->vnum, colc, colw);
				}
			}
	
			if (obj->cost < 1 && ++cnt < max_cnt)
			{
				if (fix)
				{
					if ((obj->cost = obj_index_cost(obj)) == -1)
						obj->cost = 1;
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sObject should cost at least 1 copper.\n\r", colc, colW, obj->vnum, colc, colw);
				}
			}
			if (obj_index_cost(obj) > obj->cost && ++cnt < max_cnt)
			{
				if (fix)
				{
					obj->cost = obj_index_cost(obj);
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sObject should cost at least %d copper.\n\r", colc, colW, obj->vnum, colc, colw, obj_index_cost(obj));
				}
			}
			if (obj->weight != load_obj_weight(obj) && ++cnt < max_cnt)
			{
				if (fix)
				{
					obj->weight = load_obj_weight(obj);
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sObject does not have correct weight. Should be %d.%d pounds\n\r", colc, colW, obj->vnum, colc, colw, load_obj_weight(obj) / 10, load_obj_weight(obj) % 10);
				}
			}
			if (obj->material <= 0 && ++cnt < max_cnt)
			{
				if (fix)
				{
					fix_materials(obj);
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sObject does not have a material set.\n\r", colc, colW, obj->vnum, colc, colw);
				}
			}
			if (obj->wear_flags > 0 && !IS_SET(obj->wear_flags, CAN_WEAR_TAKE) && ++cnt < max_cnt)
			{
				if (fix)
				{
					SET_BIT(obj->wear_flags, CAN_WEAR_TAKE);
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sObject can be worn but doesn't have 'wear take' set.\n\r", colc, colW, obj->vnum, colc, colw);
				}
			}
			if (obj->wear_flags > 0 && obj->long_descr[0] == '\0' && ++cnt < max_cnt)
			{
				if (fix)
				{
					sprintf(arg, "%s is here.", capitalize(obj->short_descr));
					RESTRING(obj->long_descr, arg);
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sObject has wear flags but no long description set.\n\r", colc, colW, obj->vnum, colc, colw);
				}
			}
			if (bad_short_desc(obj->short_descr) && ++cnt < max_cnt)
			{
				if (fix)
				{
					strcpy(arg, obj->short_descr);
					arg[0] = tolower(arg[0]);
					RESTRING(obj->short_descr, arg);
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sObject has a bad short desc.\n\r", colc, colW, obj->vnum, colc, colw);
				}
			}
			if (obj->description[0] && str_suffix("\n\r", obj->description) && ++cnt < max_cnt)
			{
				if (fix)
				{
					sprintf(arg, "%s\n\r", obj->description);
					RESTRING(obj->description, arg);
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sObject has a bad description.\n\r", colc, colW, obj->vnum, colc, colw);
				}
			}
			for (ed = obj->first_extradesc ; ed ; ed = ed->next)
			{
				if (str_suffix("\n\r", ed->description) && ++cnt < max_cnt)
				{
					if (fix)
					{
						sprintf(arg, "%s\n\r", ed->description);
						RESTRING(ed->description, arg);
					}
					else
					{
						ch_printf_color(ch, "%s[%s%u%s] %sObject has a bad extra description.\n\r", colc, colW, obj->vnum, colc, colw);
					}
				}
			}
		}
	}

	if (mobiles)
	{
		lo_vnum = area->low_m_vnum;
		hi_vnum = area->hi_m_vnum;
	
		for (vnum = lo_vnum ; vnum <= hi_vnum ; vnum++)
		{
			if ((mob = get_mob_index(vnum)) == NULL)
			{
				continue;
			}
			if (mob->gold > mob->level * 2000 && ++cnt < max_cnt)
			{
				if (fix)
				{
					mob->gold = number_fuzzy(mob->level * 1000);
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sMobile should have equal or less than %d copper.\n\r", colc, colW, mob->vnum, colc, colw, mob->level*2000);
				}
			}
	
			if (mob->class != CLASS_MONSTER && mob->hitsizedice != class_table[mob->class].hp_max && ++cnt < max_cnt)
			{
				if (fix)
				{
					mob->hitnodice		= mob->level;
					mob->hitsizedice	= class_table[mob->class].hp_max;
					mob->hitplus			= 0;
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sMobile's hit die is incorrect for it's class. It should be d%d\n\r", colc, colW, colc, colw, mob->vnum, class_table[mob->class].hp_max);
				}
			}
			else if (mob->race > RACE_NONE && mob->class == CLASS_MONSTER && mob->hitsizedice != race_type_table[race_table[mob->race].type].hit_die && ++cnt < max_cnt)
			{
				if (fix)
				{
					mob->hitnodice		= mob->level;
					mob->hitsizedice	= race_type_table[race_table[mob->race].type].hit_die;
					mob->hitplus			= 0;
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sMobile's hit die is incorrect for its race. It should be d%d.\n\r", colc, colW, mob->vnum, colc, colw, race_type_table[mob->race].hit_die);
				}
			}
	
			if (mob->wear_locs > 0 && mob->race && ++cnt < max_cnt)
			{
				if (fix)
				{
					mob->wear_locs = 0;
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sMobile has wear locations set but also has a race set.\n\r", colc, colW, mob->vnum, colc, colw);
				}
			}
			if (IS_SET(mob->affected_by, AFF_TRUESIGHT) && IS_SET(mob->affected_by, AFF_DETECT_INVIS) && ++cnt < max_cnt)
			{
				if (fix)
				{
					REMOVE_BIT(mob->affected_by, AFF_DETECT_INVIS);
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sMobile has both truesight and detect invis affect.\n\r", colc, colW, mob->vnum, colc, colw);
				}
			}
			if (IS_SET(mob->affected_by, AFF_TRUESIGHT) && IS_SET(mob->affected_by, AFF_DETECT_HIDDEN) && ++cnt < max_cnt)
			{
				if (fix)
				{
					REMOVE_BIT(mob->affected_by, AFF_DETECT_HIDDEN);
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sMobile has both truesight and detect hidden affect.\n\r", colc, colW, mob->vnum, colc, colw);
				}
			}
			if (IS_SET(mob->act, ACT_MOBINVIS))
			{
				if (IS_SET(mob->affected_by, AFF_DETECT_INVIS) && ++cnt < max_cnt)
				{
					if (fix)
					{
						REMOVE_BIT(mob->affected_by, AFF_DETECT_INVIS);
					}
					else
					{
						ch_printf_color(ch, "%s[%s%u%s] %sMobile has both mobinvis and detect invis affect.\n\r", colc, colW, mob->vnum, colc, colw);
					}
				}
				if (IS_SET(mob->affected_by, AFF_DETECT_HIDDEN) && ++cnt < max_cnt)
				{
					if (fix)
					{
						REMOVE_BIT(mob->affected_by, AFF_DETECT_HIDDEN);
					}
					else
					{
						ch_printf_color(ch, "%s[%s%u%s] %sMobile has both mobinvis and detect hidden affect.\n\r", colc, colW, mob->vnum, colc, colw);
					}
				}
				if (IS_SET(mob->affected_by, AFF_TRUESIGHT) && ++cnt < max_cnt)
				{
					if (fix)
					{
						REMOVE_BIT(mob->affected_by, AFF_TRUESIGHT);
					}
					else
					{
						ch_printf_color(ch, "%s[%s%u%s] %sMobile has both mobinvis and truesight affect.\n\r", colc, colW, mob->vnum, colc, colw);
					}
				}
				if (IS_SET(mob->affected_by, AFF_SNEAK) && ++cnt < max_cnt)
				{
					if (fix)
					{
						REMOVE_BIT(mob->affected_by, AFF_SNEAK);
					}
					else
					{
						ch_printf_color(ch, "%s[%s%u%s] %sMobile has both mobinvis and sneak affect.\n\r", colc, colW, mob->vnum, colc, colw);
					}
				}
				if (IS_SET(mob->affected_by, AFF_INVISIBLE) && ++cnt < max_cnt)
				{
					if (fix)
					{
						REMOVE_BIT(mob->affected_by, AFF_INVISIBLE);
					}
					else
					{
						ch_printf_color(ch, "%s[%s%u%s] %sMobile has both mobinvis and invis affect.\n\r", colc, colW, mob->vnum, colc, colw);
					}
				}
			}
			if (bad_short_desc(mob->short_descr) && ++cnt < max_cnt)
			{
				if (fix)
				{
					strcpy(arg, mob->short_descr);
					arg[0] = tolower(arg[0]);
					STRFREE(mob->short_descr);
					mob->short_descr = STRALLOC(arg);
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sMobile has a bad short desc.\n\r", colc, colW, mob->vnum, colc, colw);
				}
			}
			if (mob->description[0] && str_suffix("\n\r", mob->description) && ++cnt < max_cnt)
			{
				if (fix)
				{
					sprintf(arg, "%s\n\r", mob->description);
					RESTRING(mob->description, arg);
				}
				else
				{
					ch_printf_color(ch, "%s[%s%u%s] %sMobile has a bad description.\n\r", colc, colW, mob->vnum, colc, colw);
				}
			}
		}
	}
	if (fix)
	{
		ch_printf_color(ch, "\n\r%sTotal of %d errors fixed.\n\r", colc, cnt);
	}
	else
	{
		ch_printf_color(ch, "\n\r%sTotal of %d errors found.\n\r", colc, cnt);
	}
	pop_call();
	return;
}



void do_opstat( CHAR_DATA *ch, char *argument )
{
	char buf[MAX_INPUT_LENGTH];
	char txt[MAX_STRING_LENGTH];
	char arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	MPROG_DATA *mprog;
	OBJ_INDEX_DATA *pObjIndex;
	NPC_TOKEN *token;
	int cnt;

	push_call("do_opstat(%p,%p)",ch,argument);

	one_argument( argument, arg );

	if (arg[0] == '\0')
	{
		send_to_char("Syntax: edit oprog stat <vnum|obj name>\n\r", ch );
		send_to_char("        opstat <vnum|obj name>\n\r", ch );
		pop_call();
		return;
	}

	if (is_number(arg) && get_obj_index(atoi(arg)) != NULL)
	{
		pObjIndex = get_obj_index(atoi(arg));
	}
	else if ((obj = get_obj_here(ch, arg)) == NULL)
	{
		send_to_char( "That isn't here.\n\r", ch );
		pop_call();
		return;
	}
	else
	{
		pObjIndex = obj->pIndexData;
	}

	if (!can_olc_modify(ch, pObjIndex->vnum))
	{
		send_to_char("That object is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	sprintf(txt, "{078}[{178}%5u{078}] {058}%s\n\r", pObjIndex->vnum, pObjIndex->short_descr);

	for (mprog = pObjIndex->first_prog ; mprog ; mprog = mprog->next)
	{
		cat_sprintf(txt, "{138}>%s %s~\n\r", mprog_type_to_name(mprog->type), mprog->arglist);

		for (token = mprog->first_token ; token ; token = token->next)
		{
			for (cnt = 0 ; cnt < 2*token->level ; cnt++)
			{
				buf[cnt] = ' ';
			}
			buf[cnt] = '\0';

			switch (token->type)
			{
				default:				cat_sprintf(txt, "{118}%sunknown %s\n\r",	buf, token->string);							break;
				case MPTOKEN_SOCIAL:	cat_sprintf(txt, "{178}%s%s %s\n\r",		buf,  (char *) token->function, token->string);		break;
				case MPTOKEN_COMMAND:	cat_sprintf(txt, "{178}%s%s %s\n\r",		buf, cmd_table[token->value].name, token->string);	break;
				case MPTOKEN_IF:		cat_sprintf(txt, "{128}%sif %s\n\r",		buf, token->string);							break;
				case MPTOKEN_OR:		cat_sprintf(txt, "{128}%sor %s\n\r",		buf, token->string);							break;
				case MPTOKEN_IFNOT:		cat_sprintf(txt, "{128}%sifnot %s\n\r",	buf, token->string);							break;
				case MPTOKEN_ORNOT:		cat_sprintf(txt, "{128}%sornot %s\n\r",	buf, token->string);							break;
				case MPTOKEN_ELSE:		cat_sprintf(txt, "{128}%selse\n\r",		buf);										break;
				case MPTOKEN_ENDIF:		cat_sprintf(txt, "{128}%sendif\n\r",		buf);										break;
				case MPTOKEN_BREAK:		cat_sprintf(txt, "{118}%sbreak\n\r",		buf);										break;
				case MPTOKEN_SWITCH:	cat_sprintf(txt, "{158}%sswitch %s\n\r",	buf, token->string);							break;
				case MPTOKEN_CASE:		cat_sprintf(txt, "{158}%scase %s\n\r",	buf, token->string);							break;
				case MPTOKEN_DEFAULT:	cat_sprintf(txt, "{158}%sdefault\n\r",	buf);										break;
				case MPTOKEN_ENDSWITCH:	cat_sprintf(txt, "{158}%sendswitch\n\r",	buf);										break;
			}
		}
	}
	send_to_char_color(txt, ch);
	pop_call();
	return;
}

void do_rpstat( CHAR_DATA *ch, char *argument )
{
	char buf[MAX_INPUT_LENGTH];
	char txt[MAX_STRING_LENGTH];
	char arg[MAX_INPUT_LENGTH];
	MPROG_DATA *mprog;
	ROOM_INDEX_DATA *pRoomIndex;
	NPC_TOKEN *token;
	int cnt;

	push_call("do_rpstat(%p,%p)",ch,argument);

	one_argument( argument, arg );

	if (arg[0] == '\0' && is_number(arg) && get_room_index(atoi(arg)) != NULL)
	{
		pRoomIndex = get_room_index(atoi(arg));
	}
	else
	{
		pRoomIndex = ch->in_room;
	}
	
	if (pRoomIndex == NULL)
	{
		send_to_char("Syntax: edit rprog stat [vnum]\n\r", ch );
		send_to_char("        rpstat [vnum]\n\r", ch );
		pop_call();
		return;
	}

	if (!can_olc_modify(ch, pRoomIndex->vnum))
	{
		send_to_char("That room is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	sprintf(txt, "{078}[{178}%5u{078}] {058}%s\n\r", pRoomIndex->vnum, pRoomIndex->name);

	for (mprog = pRoomIndex->first_prog ; mprog ; mprog = mprog->next)
	{
		cat_sprintf(txt, "{138}>%s %s~\n\r", mprog_type_to_name(mprog->type), mprog->arglist);

		for (token = mprog->first_token ; token ; token = token->next)
		{
			for (cnt = 0 ; cnt < 2*token->level ; cnt++)
			{
				buf[cnt] = ' ';
			}
			buf[cnt] = '\0';

			switch (token->type)
			{
				default:							cat_sprintf(txt, "{118}%sunknown %s\n\r",	buf, token->string);							break;
				case MPTOKEN_SOCIAL:	cat_sprintf(txt, "{178}%s%s %s\n\r",		buf,  (char *) token->function, token->string);		break;
				case MPTOKEN_COMMAND:	cat_sprintf(txt, "{178}%s%s %s\n\r",		buf, cmd_table[token->value].name, token->string);	break;
				case MPTOKEN_IF:			cat_sprintf(txt, "{128}%sif %s\n\r",		buf, token->string);							break;
				case MPTOKEN_OR:			cat_sprintf(txt, "{128}%sor %s\n\r",		buf, token->string);							break;
				case MPTOKEN_IFNOT:		cat_sprintf(txt, "{128}%sifnot %s\n\r",	buf, token->string);							break;
				case MPTOKEN_ORNOT:		cat_sprintf(txt, "{128}%sornot %s\n\r",	buf, token->string);							break;
				case MPTOKEN_ELSE:		cat_sprintf(txt, "{128}%selse\n\r",		buf);										break;
				case MPTOKEN_ENDIF:		cat_sprintf(txt, "{128}%sendif\n\r",		buf);										break;
				case MPTOKEN_BREAK:		cat_sprintf(txt, "{118}%sbreak\n\r",		buf);										break;
				case MPTOKEN_SWITCH:	cat_sprintf(txt, "{158}%sswitch %s\n\r",	buf, token->string);							break;
				case MPTOKEN_CASE:		cat_sprintf(txt, "{158}%scase %s\n\r",	buf, token->string);							break;
				case MPTOKEN_DEFAULT:	cat_sprintf(txt, "{158}%sdefault\n\r",	buf);										break;
				case MPTOKEN_ENDSWITCH:	cat_sprintf(txt, "{158}%sendswitch\n\r",	buf);										break;
			}
		}
	}
	send_to_char_color(txt, ch);
	pop_call();
	return;
}

void do_mpstat( CHAR_DATA *ch, char *argument )
{
	char buf[MAX_INPUT_LENGTH];
	char txt[MAX_STRING_LENGTH];
	char arg[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	MPROG_DATA *mprog;
	MOB_INDEX_DATA *mind;
	NPC_TOKEN *token;
	int cnt;

	push_call("do_mpstat(%p,%p)",ch,argument);

	one_argument( argument, arg );

	if (arg[0] == '\0')
	{
		send_to_char("Syntax: edit mprog stat <vnum|mob name>\n\r", ch );
		send_to_char("        mpstat <vnum|mob name>\n\r", ch );
		pop_call();
		return;
	}

	if (is_number(arg) && get_mob_index(atoi(arg)) != NULL)
	{
		mind = get_mob_index(atoi(arg));
	}
	else	if ((victim = get_char_world(ch, arg)) == NULL)
	{
		send_to_char( "They aren't here.\n\r", ch );
		pop_call();
		return;
	}
	else if (!IS_NPC(victim))
	{
		send_to_char( "Players have no mobile programs.\n\r", ch);
		pop_call();
		return;
	}
	else
	{
		mind = victim->pIndexData;
	}

	if (!can_olc_modify(ch, mind->vnum))
	{
		send_to_char("That mobile is not in your allocated range.\n\r", ch);
		pop_call();
		return;
	}

	sprintf(txt, "{078}[{178}%5u{078}] {058}%s\n\r", mind->vnum, mind->short_descr);

	for (mprog = mind->first_prog ; mprog ; mprog = mprog->next)
	{
		cat_sprintf(txt, "{138}>%s %s~\n\r", mprog_type_to_name(mprog->type), mprog->arglist);

		for (token = mprog->first_token ; token ; token = token->next)
		{
			for (cnt = 0 ; cnt < 2*token->level ; cnt++)
			{
				buf[cnt] = ' ';
			}
			buf[cnt] = '\0';

			switch (token->type)
			{
				default:				cat_sprintf(txt, "{118}%sunknown %s\n\r",	buf, token->string);							break;
				case MPTOKEN_SOCIAL:	cat_sprintf(txt, "{178}%s%s %s\n\r",		buf,  (char *) token->function, token->string);		break;
				case MPTOKEN_COMMAND:	cat_sprintf(txt, "{178}%s%s %s\n\r",		buf, cmd_table[token->value].name, token->string);	break;
				case MPTOKEN_IF:		cat_sprintf(txt, "{128}%sif %s\n\r",		buf, token->string);							break;
				case MPTOKEN_OR:		cat_sprintf(txt, "{128}%sor %s\n\r",		buf, token->string);							break;
				case MPTOKEN_IFNOT:		cat_sprintf(txt, "{128}%sifnot %s\n\r",	buf, token->string);							break;
				case MPTOKEN_ORNOT:		cat_sprintf(txt, "{128}%sornot %s\n\r",	buf, token->string);							break;
				case MPTOKEN_ELSE:		cat_sprintf(txt, "{128}%selse\n\r",		buf);										break;
				case MPTOKEN_ENDIF:		cat_sprintf(txt, "{128}%sendif\n\r",		buf);										break;
				case MPTOKEN_BREAK:		cat_sprintf(txt, "{118}%sbreak\n\r",		buf);										break;
				case MPTOKEN_SWITCH:	cat_sprintf(txt, "{158}%sswitch %s\n\r",	buf, token->string);							break;
				case MPTOKEN_CASE:		cat_sprintf(txt, "{158}%scase %s\n\r",	buf, token->string);							break;
				case MPTOKEN_DEFAULT:	cat_sprintf(txt, "{158}%sdefault\n\r",	buf);										break;
				case MPTOKEN_ENDSWITCH:	cat_sprintf(txt, "{158}%sendswitch\n\r",	buf);										break;

			}
		}
	}
	send_to_char_color(txt, ch);
	pop_call();
	return;
}

void do_edit( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	char arg3[MAX_INPUT_LENGTH];

	push_call("do_edit(%p,%p)",ch,argument);

	CHECK_EDITMODE( ch );

	switch (ch->pcdata->edittype)
	{
		case EDIT_TYPE_HELP:		do_hedit (ch, argument);			pop_call();	return;
		case EDIT_TYPE_ROOM:		do_redit (ch, argument);			pop_call();	return;
		case EDIT_TYPE_MOB:			do_medit (ch, argument);			pop_call();	return;
		case EDIT_TYPE_OBJ:			do_oedit (ch, argument);			pop_call();	return;
		case EDIT_TYPE_RESET:		do_rredit(ch, argument);			pop_call();	return;
		case EDIT_TYPE_SHOP:		do_sedit (ch, argument);			pop_call();	return;
		case EDIT_TYPE_INN:			do_inn_edit (ch, argument);		pop_call();	return;
		case EDIT_TYPE_STABLE: 	do_stable_edit (ch, argument);		pop_call();	return;
		case EDIT_TYPE_MPROG:		do_mpedit(ch, argument);			pop_call();	return;
		case EDIT_TYPE_OPROG:		do_opedit(ch, argument);			pop_call();	return;
		case EDIT_TYPE_RPROG:		do_rpedit(ch, argument);			pop_call();	return;
		case EDIT_TYPE_AREA:		do_aedit (ch, argument);			pop_call();	return;
		case EDIT_TYPE_RACE:		do_race_edit (ch, argument);	pop_call();	return;
		case EDIT_TYPE_GOD:			do_god_edit (ch, argument);	pop_call();	return;
		case EDIT_TYPE_CLASS:		do_class_edit (ch, argument);	pop_call();	return;
	}

	if (argument[0] == '\0')
	{
		ch_printf_color(ch, "Syntax: edit room   [create|delete|dupe] [vnum]\n\r");
		ch_printf_color(ch, "Syntax: edit mob    [create|delete|list] <vnum>\n\r");
		ch_printf_color(ch, "Syntax: edit obj    [create|delete|list] <vnum>\n\r");
		ch_printf_color(ch, "Syntax: edit shop   [create|delete|list] <vnum>\n\r");
		ch_printf_color(ch, "Syntax: edit inn    [create|delete|list] <vnum>\n\r");
		ch_printf_color(ch, "Syntax: edit stable [create|delete|list] <vnum>\n\r");
		ch_printf_color(ch, "Syntax: edit help   [create|delete|list] <name>\n\r");
		ch_printf_color(ch, "Syntax: edit area   [check|assign|list]  [name]\n\r");
		ch_printf_color(ch, "Syntax: edit reset                       [vnum]\n\r");
		ch_printf_color(ch, "Syntax: edit mprog  [stat]               <vnum>\n\r");
		ch_printf_color(ch, "Syntax: edit oprog  [stat]               <vnum>\n\r");
		ch_printf_color(ch, "Syntax: edit rprog  [stat]               <vnum>\n\r");
		ch_printf_color(ch, "Syntax: edit race                        <name>\n\r");
		ch_printf_color(ch, "Syntax: edit god                         <name>\n\r");
		ch_printf_color(ch, "Syntax: edit class                       <name>\n\r");
		pop_call();
		return;
	}

	log_god_printf("(G) Log %s: edit %s", ch->name, argument);

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

	if (!strcasecmp(arg1, "room"))
	{
		if (!strcasecmp(arg2, "create"))
		{
			do_rcreate(ch, argument);
		}
		else if (!strcasecmp(arg2, "delete"))
		{
			do_rdelete(ch, argument);
		}
		else if (!strcasecmp(arg2, "dupe"))
		{
			do_rdupe(ch, argument);
		}
		else if (!strcasecmp(arg2, "list"))
		{
			do_rlist(ch, argument);
		}
		else
		{
			do_redit(ch, arg2);
		}
		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "mob"))
	{
		if (!strcasecmp(arg2, "create"))
		{
			do_mcreate(ch, argument);
		}
		else if (!strcasecmp(arg2, "delete"))
		{
			do_mdelete(ch, argument);
		}
		else if (!strcasecmp(arg2, "list"))
		{
			do_mlist(ch, argument);
		}
		else
		{
			do_medit(ch, arg2);
		}
		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "obj"))
	{
		if (!strcasecmp(arg2, "create"))
		{
			do_ocreate(ch, argument);
		}
		else if (!strcasecmp(arg2, "delete"))
		{
			do_odelete(ch, argument);
		}
		else if (!strcasecmp(arg2, "list"))
		{
			do_olist(ch, argument);
		}
		else
		{
			do_oedit(ch, arg2);
		}
		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "help"))
	{
		if (!strcasecmp(arg2, "create"))
		{
			do_hcreate(ch, argument);
		}
		else if (!strcasecmp(arg2, "delete"))
		{
			do_hdelete(ch, argument);
		}
		else if (!strcasecmp(arg2, "list"))
		{
			do_hlist(ch, argument);
		}
		else
		{
			do_hedit(ch, arg2);
		}
		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "shop"))
	{
		if (!strcasecmp(arg2, "create"))
		{
			do_screate(ch, argument);
		}
		else if (!strcasecmp(arg2, "delete"))
		{
			do_sdelete(ch, argument);
		}
		else if (!strcasecmp(arg2, "list"))
		{
			do_slist(ch, argument);
		}
		else
		{
			do_sedit(ch, arg2);
		}
		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "stable"))
	{
		if (!strcasecmp(arg2, "create"))
		{
			do_stable_create(ch, argument);
		}
		else if (!strcasecmp(arg2, "delete"))
		{
			do_stable_delete(ch, argument);
		}
		else if (!strcasecmp(arg2, "list"))
		{
			do_stable_list(ch, argument);
		}
		else
		{
			do_stable_edit(ch, arg2);
		}
		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "inn"))
	{
		if (!strcasecmp(arg2, "create"))
		{
			do_inn_create(ch, argument);
		}
		else if (!strcasecmp(arg2, "delete"))
		{
			do_inn_delete(ch, argument);
		}
		else if (!strcasecmp(arg2, "list"))
		{
			do_inn_list(ch, argument);
		}
		else
		{
			do_inn_edit(ch, arg2);
		}
		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "mprog"))
	{
		if (!strcasecmp(arg2, "stat"))
		{
			do_mpstat(ch, argument);
		}
		else
		{
			do_mpedit(ch, arg2);
		}

		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "oprog"))
	{
		if (!strcasecmp(arg2, "stat"))
		{
			do_opstat(ch, argument);
		}
		else
		{
			do_opedit(ch, arg2);
		}

		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "rprog"))
	{
		if (!strcasecmp(arg2, "stat"))
		{
			do_rpstat(ch, argument);
		}
		else
		{
			do_rpedit(ch, arg2);
		}

		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "area"))
	{
		if (!strcasecmp(arg2, "check"))
		{
			do_area_check(ch, argument);
		}
		else if (!strcasecmp(arg2, "assign"))
		{
			do_area_assign(ch, argument);
		}
		else if (!strcasecmp(arg2, "list"))
		{
			do_alist(ch, argument);
		}
		else
		{
			do_aedit(ch, arg3);
		}

		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "reset"))
	{
		do_rredit(ch, arg2);

		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "class"))
	{
		do_class_edit(ch, arg3);

		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "race"))
	{
		do_race_edit(ch, arg3);

		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "god"))
	{
		do_god_edit(ch, arg3);

		pop_call();
		return;
	}

	do_edit(ch, "");
	pop_call();
	return;
}


/* GridMaker 1.0 by Muerte of MND */
/* fixed for rom by Rashin of TGH2: Project X */
void do_makewild(CHAR_DATA *ch, char *argument)
{
	FILE *fp;
	char arg1[10], arg2[10], arg3[10];
	int width, height, vstart, vend, vnum, n, e, s, w, line_pos;
	
	argument = one_argument(argument, arg1);
	argument = one_argument(argument, arg2);
	argument = one_argument(argument, arg3);
	
	if ( arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0')
	{
		send_to_char("Syntax: makewild <start vnum> <width> <height>\n\r", ch);
		return;
	}
	
	width = atoi(arg2);
	height = atoi(arg3);
	vstart = atoi(arg1);
	vend = vstart + (width * height) - 1;
	
	if ((fp = fopen("new.are", "w")) == NULL)
	{
		send_to_char("MAKEWILD: fopen", ch);
		return;
	}
			 
	ch_printf(ch, "#*********************************#\n");
	ch_printf(ch, "# GENERATING %3d BY %3d AREA FILE #\n",width,height);
	ch_printf(ch, "#*********************************#\n");
	
	fprintf(fp,"#AREA Wilderness~\n#AUTHORS Mud20~\n#VERSION 4\n#OLC_RANGES %d %d\n#FLAGS AFLAG_WILDERNESS\n", vstart, vend);
	fprintf(fp,"\n\n\n#MOBILES\n#0\n");
	fprintf(fp,"\n\n\n#OBJECTS\n#0\n");
	fprintf(fp,"\n\n\n#ROOMS\n");
	
	for ( vnum=vstart; vnum<=vend; vnum++)
	{ /* for every room */
		n = vnum - width;
		s = vnum + width;
		e = vnum + 1;
		w = vnum - 1;
		
		/*where it is on the line 0 to (width-1)*/
		line_pos = (vnum-vstart + 1) % (width);
		if (line_pos == 0)
			line_pos = width;
		
		/*north border*/
		if ((vnum >= vstart) && (vnum < vstart + width))
		{
			n = 0; 
		}
		/*south border*/
		if ((vnum > vend-width) && (vnum <= vend))
		{
			s = 0;
		}
		/*east border*/
		if ((vnum - vstart + 1) % (width) == 0)
		{
			e = 0; 
		}
		/*west border*/
		if ((vnum - vstart + 1) % (width) == 1)
		{
			w = 0;
		}
		
		fprintf(fp,"#%d\nNAME~\n\n~\n0 ROOM_WILDERNESS|ROOM_DYNAMIC SECT_FOREST 0 0 0\n", vnum);
		if (n > 0)
			fprintf(fp, "DDIR_NORTH\n\n~\n~\n0 0 %d 0 0 0\n", n);
		if (e > 0)
			fprintf(fp, "DDIR_EAST\n\n~\n~\n0 0 %d 0 0 0\n", e);
		if (s > 0)
			fprintf(fp, "DDIR_SOUTH\n\n~\n~\n0 0 %d 0 0 0\n", s);
		if (w > 0)
			fprintf(fp, "DDIR_WEST\n\n~\n~\n0 0 %d 0 0 0\n", w);
		
		fprintf(fp,"S\n");
	}
	
	fprintf(fp,"#0\n");
	fprintf(fp,"\n\n\n#SPECIALS\nS\n");
	fprintf(fp,"\n\n\n#RESETS\nS\n");
	fprintf(fp,"\n\n\n#SHOPS\n0\n");
	fprintf(fp,"\n\n\n#$\n");
	fclose(fp); 
	send_to_char("Area Completed\n\r", ch);
	return;      
}