From 7e8c0a5c5fc934555e6802cd12e10677ff7f9be5 Mon Sep 17 00:00:00 2001
From: mcmlxxix <>
Date: Thu, 14 Oct 2010 20:18:38 +0000
Subject: [PATCH] added help information for all (most) commands, ghost exits
 for unlinked rooms, categorized commands for group disabling/enabling,
 verbose zone editor display (now with
 colorz!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)

---
 exec/ircbots/rpgbot/rpg_commands.js  | 1063 +++++++++++++++++---------
 exec/ircbots/rpgbot/rpg_functions.js |  205 +++--
 exec/ircbots/rpgbot/rpgbot.js        |   21 +
 3 files changed, 864 insertions(+), 425 deletions(-)

diff --git a/exec/ircbots/rpgbot/rpg_commands.js b/exec/ircbots/rpgbot/rpg_commands.js
index e0f09b6ae4..4c502e09f5 100644
--- a/exec/ircbots/rpgbot/rpg_commands.js
+++ b/exec/ircbots/rpgbot/rpg_commands.js
@@ -76,11 +76,42 @@ Bot_Commands["LOGIN"].command = function (target,onick,ouh,srv,lvl,cmd) {
 		display_room(srv,player,player.@zone,player.@room);
 		return;
 	}
+	
+
+	if(!zones[player.@zone]) {
+		player.@zone=0;
+	}
+	var zone=zones[player.@zone];
+
+	if(!zone.room.(@id == player.@room).length() > 0) {
+		player.@room = 0;
+	}
+	
+	
 	player.@active=1;
 	player.@channel=target;
 	display_room(srv,player,player.@zone,player.@room);
 }
 
+Bot_Commands["EDIT"] = new Bot_Command(80,false,false);
+Bot_Commands["EDIT"].command = function (target,onick,ouh,srv,lvl,cmd) {
+	var player=players.player.(@name == onick);
+	if(player.@active != 1) {
+		srv.o(target,"You are not logged in.");
+		return;	
+	}
+	if(player.@editing != 1) {
+		player.@editing = 1;
+		var zone=zones[player.@zone];
+		var room=zone.room.(@id == player.@room);
+		display_room_editor(srv,player,zone,room)
+	} else {
+		player.@editing = 0;
+		srv.o(target,"Editor OFF");
+	}
+	return;
+}
+
 Bot_Commands["LOGOUT"] = new Bot_Command(0,false,false);
 Bot_Commands["LOGOUT"].command = function (target,onick,ouh,srv,lvl,cmd) {
 	var player=players.player.(@name == onick);
@@ -96,18 +127,146 @@ Bot_Commands["LOGOUT"].command = function (target,onick,ouh,srv,lvl,cmd) {
 	srv.o(target,"You have been logged out.");
 }
 
-/*	Game commands */
-var RPG_Commands=[];
+Bot_Commands["SAVE"] = new Bot_Command(80,false,false);
+Bot_Commands["SAVE"].command = function (target,onick,ouh,srv,lvl,cmd) {
+	var player=players.player.(@name == onick);
+	if(player.@active != 1) {
+		srv.o(target,"You are not logged in.");
+		return;	
+	}
+	if(player.@editing != 1) {
+		srv.o(target,"You must be editing to save.");
+		return;
+	}
+	
+	var zone=zones[player.@zone];
+	mkdir(z_dir + zone.@name.toLowerCase());
+	var z_file=new File(z_dir+zone.@name.toLowerCase()+"/map.xml");
+	if(!z_file.open("w+")) return;
+	z_file.write(zone);
+	srv.o(target,"Zone saved");
+	return;
+}
+
+Bot_Commands["HELP"] = new Bot_Command(0,false,false);
+Bot_Commands["HELP"].command = function (target,onick,ouh,srv,lvl,cmd) {
+	cmd.shift();
+	var topic=cmd.shift();
+	if(!topic) {
+		var cmd_str="";
+		for(var ec in Editor_Commands) {
+			cmd_str+=", " + ec.toLowerCase();
+		}
+		srv.o(target,"editor commands: " + cmd_str.substr(2),"NOTICE");
+		cmd_str="";
+		for(var bc in Battle_Commands) {
+			cmd_str+=", " + bc.toLowerCase();
+		}
+		srv.o(target,"battle commands: " + cmd_str.substr(2),"NOTICE");
+		cmd_str="";
+		for(var ic in Item_Commands) {
+			cmd_str+=", " + ic.toLowerCase();
+		}
+		srv.o(target,"item commands: " + cmd_str.substr(2),"NOTICE");
+		cmd_str="";
+		for(var rc in RPG_Commands) {
+			cmd_str+=", " + rc.toLowerCase();
+		}
+		srv.o(target,"rpg commands: " + cmd_str.substr(2),"NOTICE");
+		srv.o(target,"for detailed command info, type 'rpg help <command>'","NOTICE");
+		srv.o(target,"for help creating a characer, type 'rpg help create'","NOTICE");
+		srv.o(target,"for help with the editor, type 'rpg help editor'","NOTICE");
+		return;
+	}
+	
+	if(Help_Topics[topic.toUpperCase()]) {
+		for each(var l in Help_Topics[topic.toUpperCase()])
+			srv.o(target,l,"NOTICE");
+		return;
+	}
+	
+	srv.o(target,"topic not found","NOTICE");
+	return;
+}
 
-RPG_Commands["NEW"] = function (srv,target,zone,room,cmd,player) {
+Bot_Commands["RESTORE"] = new Bot_Command(80,false,false);
+Bot_Commands["RESTORE"].command = function (target,onick,ouh,srv,lvl,cmd) {
+	var player=players.player.(@name == onick);
+	if(player.@active != 1) {
+		srv.o(target,"You are not logged in.");
+		return;	
+	}
 	if(player.@editing != 1) {
-		srv.o(target,"Editor is OFF. Type 'Editor ON' to enable editing.");
+		srv.o(target,"You must be editing to restore.");
+		return;
+	}
+	var zone=zones[player.@zone];
+	var zone_dir=z_dir+zone.@name.toLowerCase();
+	zone=load_zone(zone_dir);
+	if(!zone) {
+		srv.o(target,"Error loading zone");
 		return;
 	}
+	zones[zone.@id]=zone;
+	srv.o(target,"Reverted current zone to saved data");
+	return;
+}
+
+/* BATTLE COMMANDS */
+var Battle_Commands=[];
+
+Battle_Commands["FLEE"] = function (srv,target,zone,room,cmd,player) {
+	
+
+	var chance=random(100);
+	if(chance<25) {
+		srv.o(target,"You couldn't escape!");
+		return false;
+	}
+	var directions=room.exit;
+	var random_exit=directions[random(directions.length())];
+	
+	if(random_exit.door) {
+		var door=zone.door.(@id == random_exit.door);
+		if(door.open==false) {
+			srv.o(target,"You couldn't escape!");
+			return false;
+		}
+	}
+	
+	delete (player_attacks[player.@name]);
+	
+	srv.o(target,"You flee from battle!");
+	if(zones[random_exit.@zone]) player.@zone=<zone>{random_exit.@zone}</zone>;
+	player.@room=<room>{random_exit.@target}</room>;
+	display_room(srv,player,player.@zone,player.@room);
+	return;
+}
 
+Battle_Commands["KILL"] = function (srv,target,zone,room,cmd,player) {
 	cmd.shift();
-	var editor_cmd=cmd.shift();
+	var obj=cmd.shift();
+	if(!obj) {
+		srv.o(target,"Kill whom?");
+		return false;
+	}
 	
+	var mob_index=find_mob(room,obj);
+	if(!mob_index) {
+		srv.o(target,"They're not here!");
+		return false;
+	}
+	var mob=room.mob[mob_index];
+	add_player_attack(player,mob);
+	add_mob_attack(mob,player);
+}
+
+/* EDITOR COMMANDS */
+var Editor_Commands=[];
+
+Editor_Commands["NEW"] = function (srv,target,zone,room,cmd,player) {
+	cmd.shift();
+	var editor_cmd=cmd.shift();
 	switch(editor_cmd.toUpperCase()) {
 	case "ZONE":
 		var zone_level=cmd.shift();
@@ -125,10 +284,10 @@ RPG_Commands["NEW"] = function (srv,target,zone,room,cmd,player) {
 					<description>{settings.description}</description>
 				</room>
 			</zone>;
-		srv.o(target,"Zone '" + zone_title + "' created.");
+		srv.o(target,green + "Zone '" + zone_title + "' created.");
 		player.@room=0;
 		player.@zone=zone_id;
-		display_room(srv,player,zone_id,0);
+		display_room_editor(srv,player,zones[zone_id],zones[zone_id].room[0]);
 		break;
 	case "ITEM":
 		srv.o(target,"TODO: Allow dynamic item creation");
@@ -142,59 +301,7 @@ RPG_Commands["NEW"] = function (srv,target,zone,room,cmd,player) {
 	}
 }
 
-RPG_Commands["EDITOR"] = function (srv,target,zone,room,cmd,player) {
-	cmd.shift();
-	var editor_cmd=cmd.shift();
-	
-	switch(editor_cmd.toUpperCase()) {
-	case "ON":
-		if(player.@editing != 1) {
-			player.@editing = 1;
-			srv.o(target,"Zone editor ON");
-		}
-		return;
-	case "OFF":
-		if(player.@editing == 1) {
-			player.@editing = 0;
-			srv.o(target,"Zone editor OFF");
-		}
-		return;
-	}
-	
-	if(player.@editing != 1) {
-		srv.o(target,"Editor is OFF. Type 'Editor ON' to enable editing.");
-		return;
-	}
-
-	switch(editor_cmd.toUpperCase()) {
-	case "SAVE":
-		mkdir(z_dir + zone.@name.toLowerCase());
-		var z_file=new File(z_dir+zone.@name.toLowerCase()+"/map.xml");
-		if(!z_file.open("w+")) return;
-		z_file.write(zone);
-		srv.o(target,"Zone saved");
-		break;
-	case "RESTORE":
-		var zone_dir=z_dir+zone.@name.toLowerCase();
-		var zone=load_zone(zone_dir);
-		if(!zone) {
-			srv.o(target,"Error loading zone");
-			break;
-		}
-		zones[zone.@id]=zone;
-		srv.o(target,"Reverted current zone to saved data");
-		break;
-	}
-	
-	return;
-}
-
-RPG_Commands["SET"] = function (srv,target,zone,room,cmd,player) {
-	if(player.@editing == 0) {
-		srv.o(target,"You aren't currently editing.");
-		return;
-	}
-	
+Editor_Commands["SET"] = function (srv,target,zone,room,cmd,player) {
 	cmd.shift();
 	var set=cmd.shift();
 	if(!set) {
@@ -207,11 +314,11 @@ RPG_Commands["SET"] = function (srv,target,zone,room,cmd,player) {
 		switch(cmd.shift().toUpperCase()) {
 		case "TITLE":
 			settings.title=cmd.join(" ");
-			srv.o(target,"New room title set to: " + settings.title);
+			srv.o(target,green + "New room title set to: " + settings.title);
 			break;
 		case "DESCRIPTION":
 			settings.description=cmd.join(" ");
-			srv.o(target,"New room description set to: " + settings.description);
+			srv.o(target,green + "New room description set to: " + settings.description);
 			break;
 		default:
 			srv.o(target,"usage: set new <property> <value>");
@@ -222,11 +329,11 @@ RPG_Commands["SET"] = function (srv,target,zone,room,cmd,player) {
 		switch(cmd.shift().toUpperCase()) {
 		case "TITLE":
 			room.title=cmd.join(" ");
-			srv.o(target,"Current room title set to: " + room.title);
+			srv.o(target,green + "Current room title set to: " + room.title);
 			break;
 		case "DESCRIPTION":
 			room.description=cmd.join(" ");
-			srv.o(target,"Current room description set to: " + room.description);
+			srv.o(target,green + "Current room description set to: " + room.description);
 			break;
 		default:
 			srv.o(target,"usage: set current <property> <value>");
@@ -236,10 +343,10 @@ RPG_Commands["SET"] = function (srv,target,zone,room,cmd,player) {
 	case "AUTOLINK":
 		if(settings.autolink) {
 			settings.autolink=false;
-			srv.o(target,"Auto-link disabled.");
+			srv.o(target,red + "Auto-link disabled.");
 		} else {
 			settings.autolink=true;
-			srv.o(target,"Auto-link enabled.");
+			srv.o(target,green + "Auto-link enabled.");
 		}
 		break;
 	case "LINK":
@@ -252,17 +359,8 @@ RPG_Commands["SET"] = function (srv,target,zone,room,cmd,player) {
 		case "up":
 		case "down":
 			var room_id=cmd.shift();
-
 			if(!room_id) {
-				target_id=room.exit.(@name == dir).@target;
-				target_room=zone.room.(@id == target_id);
-
-				/* clear link if no target specified */
-				room.exit.(@name == dir).(@target="");
-				srv.o(target,"Room exit deleted");
-
-				/* clear corresponding link in original target room */
-				if(settings.autolink) target_room.exit.(@name == reverse_dir(dir)).(@target="");
+				srv.o(target,"TODO: auto-link adjacent room if no id is specified");
 			} else {
 				var target_room=zone.room.(@id == room_id);
 				var exit=room.exit.(@name == dir);
@@ -270,12 +368,12 @@ RPG_Commands["SET"] = function (srv,target,zone,room,cmd,player) {
 				/* set exit target for current room */
 				if(exit.@target.toString()=="") {
 					room.exit += <exit name={dir} target={room_id}/>;
-					srv.o(target,"Room exit added");
+					srv.o(target,green + "Room exit added");
 
 				/* change exit target for current room */
 				} else {
 					exit.@target=room_id;
-					srv.o(target,"Room target changed");
+					srv.o(target,green + "Room target changed");
 				}
 				
 				/* change corresponding exit for target room */
@@ -288,97 +386,56 @@ RPG_Commands["SET"] = function (srv,target,zone,room,cmd,player) {
 		}
 		break;
 	deftault:
-		srv.o(target,"Set what?");
+		srv.o(target,"Type 'rpg help set' for help.");
 		break;
 	}
 }
 
-RPG_Commands["FLEE"] = function (srv,target,zone,room,cmd,player) {
-	var chance=random(100);
-	if(chance<25) {
-		srv.o(target,"You couldn't escape!");
-		return false;
-	}
-	var directions=room.exit;
-	var random_exit=directions[random(directions.length())];
-	
-	if(random_exit.door) {
-		var door=zone.door.(@id == random_exit.door);
-		if(door.open==false) {
-			srv.o(target,"You couldn't escape!");
-			return false;
-		}
-	}
-	
-	delete (player_attacks[player.@name]);
-	
-	srv.o(target,"You flee from battle!");
-	if(zones[random_exit.@zone]) player.@zone=<zone>{random_exit.@zone}</zone>;
-	player.@room=<room>{random_exit.@target}</room>;
-	display_room(srv,player,player.@zone,player.@room);
-	return;
-}
-
-RPG_Commands["KILL"] = function (srv,target,zone,room,cmd,player) {
+Editor_Commands["UNSET"] = function (srv,target,zone,room,cmd,player) {
 	cmd.shift();
-	var obj=cmd.shift();
-	if(!obj) {
-		srv.o(target,"Kill whom?");
-		return false;
-	}
-	
-	var mob_index=find_mob(room,obj);
-	if(!mob_index) {
-		srv.o(target,"They're not here!");
-		return false;
+	var set=cmd.shift();
+	if(!set) {
+		srv.o(target,"Unset what?");
+		return;
 	}
-	var mob=room.mob[mob_index];
-	add_player_attack(player,mob);
-	add_mob_attack(mob,player);
-}
 
-RPG_Commands["SCORE"] = function (srv,target,zone,room,cmd,player) {
-	srv.o(target,
-		"player: " + player.@name + 
-		" level: " + player.level + 
-		" race: " + player.player_race +
-		" class: " + player.player_class);
-	srv.o(target,
-		"str: " + player.strength +
-		" wis: " + player.wisdom +
-		" int: " + player.intelligence +
-		" dex: " + player.dexterity +
-		" con: " + player.constitution);
-	srv.o(target,
-		"experience: " + player.experience +
-		" movement: " + player.movement + 
-		" hitpoints: " + player.hitpoints +
-		" mana: " + player.mana + 
-		" gold: " + player.gold);
-}
+	switch(set.toUpperCase()) {
+	case "LINK":
+		var dir=cmd.shift().toLowerCase()
+		switch(dir) {
+		case "north":
+		case "south":
+		case "east":
+		case "west":
+		case "up":
+		case "down":
+			target_id=room.exit.(@name == dir).@target;
+			target_room=zone.room.(@id == target_id);
 
-RPG_Commands["STATUS"] = function (srv,target,zone,room,cmd,player) {
-	srv.o(target,"<HP:" + player.hitpoints + " MA:" + player.mana + " MV:" + player.movement + ">");
+			/* clear link if no target specified */
+			room.exit.(@name == dir).(@target=undefined);
+			srv.o(target,red + "Room exit deleted");
+
+			/* clear corresponding link in original target room */
+			if(settings.autolink) target_room.exit.(@name == reverse_dir(dir)).(@target=undefined);
+			break;
+		default:
+			srv.o(target,"usage: unset <direction>");
+			break;
+		}
+		break;
+	deftault:
+		srv.o(target,"Type 'rpg help unset' for help.");
+		break;
+	}
 }
 
-RPG_Commands["MOVE"] = function (srv,target,zone,room,cmd,player) {
+
+Editor_Commands["MOVE"] = function (srv,target,zone,room,cmd,player) {
 	var exit=room.exit.(@name == cmd[1].toLowerCase());
 	if(exit.@target.toString()=="") {
-		if(player.@editing == 1) {
-			create_new_room(srv,target,zone,room,player,cmd[1].toLowerCase());
-			return true;
-		} else {
-			srv.o(target,"You cannot go that way.");
-			return false;
-		}
-	}
-	
-	if(exit.door) {
-		var door=zone.door.(@id == exit.door);
-		if(door.open == false && player.@editing != 1) {
-			srv.o(target,"The " + door.@name + " is closed.");
-			return false;
-		}
+		create_new_room(srv,target,zone,room,player,cmd[1].toLowerCase());
+		return true;
 	}
 	
 	if(zones[exit.@zone]) player.@zone=<zone>{exit.@zone}</zone>;
@@ -386,165 +443,131 @@ RPG_Commands["MOVE"] = function (srv,target,zone,room,cmd,player) {
 
 	zone=zones[player.@zone];
 	room=zone.room.(@id == player.@room);
+	
+	display_room_editor(srv,player,zone,room);
+}
 
-	srv.o(target,"You " + player.travel + " " + exit.@name + " to " + room.title + ". " + get_exit_string(zone,room,player));
+Editor_Commands["MOBS"] = function (srv,target,zone,room,cmd,player) {
+	display_mobs_editor(srv,target,zone,room);
 }
 
-RPG_Commands["UNLOCK"] = function (srv,target,zone,room,cmd,player) {
+Editor_Commands["ITEMS"] = function (srv,target,zone,room,cmd,player) {
+	display_items_editor(srv,target,zone,room);
+}
+
+Editor_Commands["EXITS"] = function (srv,target,zone,room,cmd,player) {
+	display_exits_editor(srv,target,zone,room);
+}
+
+Editor_Commands["TITLE"] = function (srv,target,zone,room,cmd,player) {
+	srv.o(target,"[title] " + room.title);
+}
+
+Editor_Commands["DESC"] = function (srv,target,zone,room,cmd,player) {
+	srv.o(target,"[desc] " + strip_ctrl(room.description));
+}
+
+Editor_Commands["GOTO"] = function (srv,target,zone,room,cmd,player) {
 	cmd.shift();
-	var name=cmd.shift();
-	if(!name) {
-		srv.o(target,"Unlock what?");
+	var dest=cmd.shift();
+	if(!dest) {
+		srv.o(target,"Where do you want to go?");
 		return false;
 	}
+	var room=cmd.shift();
+	if(room) {
+		player.@zone=<zone>{dest}</zone>;
+		zone=zones[player.@zone];
+	} else {
+		room=dest;
+	}
+	player.@room=<room>{room}</room>;
+	var room=zone.room.(@id == player.@room);
+	srv.o(target,"You teleport to " + room.title);
+	display_room_editor(srv,player,zone,room);
+	return;
+}
+
+Editor_Commands["LOOK"] = function (srv,target,zone,room,cmd,player) {
+	cmd.shift();
+	var obj=cmd.shift();
 	
-	/*	first check doors in the room */
-	var door=find_door(zone,room,name);
-	if(door) {
-		if(door.locked == false) {
-			srv.o(target,"It is already unlocked.");
-			return false;
-		}
-		
-		var key=player.inventory.item.(@id == door.key);
-		if(!key.length() > 0) {
-			srv.o(target,"You don't have the key.");
-			return false;
-		}
-		
-		srv.o(target,"You unlock the " + door.@name + ".");
-		door.locked=false;
-		return true;
-		
-	} else {
-		srv.o(target,"There is no door there.");
-		return false;
-	}
-	
-	/* then check containers */
-}
-
-RPG_Commands["EQUIPMENT"] = function (srv,target,zone,room,cmd,player) {
-	var list=[];
-	var eq=player.equipment..item;
-	for each(var i in eq) {
-		list.push("<" + i.parent().@id + "> " + i.title);
-	}
-	var str=list.length?list.join(", "):"nothing";
-	srv.o(target,"eq: " + str);
-}
-
-RPG_Commands["INVENTORY"] = function (srv,target,zone,room,cmd,player) {
-	var list=[];
-	for each(var i in player.inventory.item) {
-		list.push(i.title);
-	}
-	var str=list.length?list.join(", "):"nothing";
-	srv.o(target,"inventory: " + str);
-}
+	/*	if no target specified, look at room */
+	if(!obj) {
+		display_room_editor(srv,player,zone,room);
+		srv.o(player.@channel,red + "[title]" + black + " " + room.title);
+		srv.o(player.@channel,red + "[desc]" + black + " " + strip_ctrl(room.description));
 
-RPG_Commands["LOCK"] = function (srv,target,zone,room,cmd,player) {
-	cmd.shift();
-	var name=cmd.shift();
-	if(!name) {
-		srv.o(target,"Lock what?");
-		return false;
+		display_mobs_editor(srv,player.@channel,zone,room);
+		display_items_editor(srv,player.@channel,zone,room);
+		display_exits_editor(srv,player.@channel,zone,room);
+		return;
 	}
 	
-	/*	first check doors in the room */
-	var door=find_door(zone,room,name);
-	if(door) {
-		if(door.locked == true) {
-			srv.o(target,"It is already locked.");
-			return false;
-		}
-		
-		if(door.open == true) {
-			srv.o(target,"You should close it first.");
+	/*	if the second word is "in", attempt to look inside a container */
+	if(obj.toLowerCase()=="in") {
+		var cont=cmd.shift();
+		if(!cont) {
+			srv.o(target,"Look in what?");
 			return false;
 		}
 		
-		var key=player.inventory.item.(@id == door.key);
-		if(!key.length() > 0) {
-			srv.o(target,"You don't have the key.");
-			return false;
-		}
+		var container=false;
+		var container_index=find_object(player.inventory,cont);
+		if(container_index) container=player.inventory.item[container_index];
 		
-		srv.o(target,"You lock the " + door.@name + ".");
-		door.locked=true;
-		return true;
+		/*	attampt to match specified container with room items */
+		else container_index=find_object(room,cont); 
+		if(!container && container_index) container=room.item[container_index];
 		
-	} else {
-		srv.o(target,"There is no door there.");
-		return false;
-	}
-	
-	/* then check containers */
-}
-
-RPG_Commands["OPEN"] = function (srv,target,zone,room,cmd,player) {
-	cmd.shift();
-	var name=cmd.shift();
-	if(!name) {
-		srv.o(target,"Open what?");
+		/*	if player has this container, check items in container for specified object */
+		if(container) {
+			if(container.type!="container") {
+				srv.o(target,"That isn't a container!");
+				return false;
+			}
+			var list=[];
+			for each(var i in container.item) {
+				list.push(i.title);
+			}
+			var str=list.length?list.join(", "):"nothing";
+			srv.o(target,"contents (" + container.title + "):" + str);
+			return true;
+		}
+		srv.o(target,"You can't find it!");
 		return false;
 	}
 	
-	/*	first check doors in the room */
-	var door=find_door(zone,room,name);
-	if(door) {
-		if(door.open == true) {
-			srv.o(target,"It is already open.");
-			return false;
-		}
-		if(door.locked == true) {
-			srv.o(target,"It is locked.");
-			return false;
+	/*	handle looking at items, mobs, doors */
+	var mob_index=find_mob(room,obj);
+	if(mob_index) {
+		var mob=room.mob[mob_index];
+		if(mob.description.length() > 0) srv.o(target,mob.description);
+		var list=[];
+		var eq=mob.equipment..item;
+		for each(var i in eq) {
+			list.push("<" + i.parent().@id + "> " + i.title);
 		}
-		
-		srv.o(target,"You open the " + door.@name + ".");
-		door.open=true;
+		var str=list.length?list.join(", "):"nothing";
+		srv.o(target,"eq: " + str);
 		return true;
-	} else {
-		srv.o(target,"There is no door there.");
-		return false;
-	}
-
-	/*	then check containers in the room */
-	
-	/*	then check containers in inventory */
-}
-
-RPG_Commands["CLOSE"] = function (srv,target,zone,room,cmd,player) {
-	cmd.shift();
-	var name=cmd.shift();
-	if(!name) {
-		srv.o(target,"Close what?");
-		return false;
 	}
 	
-	/*	first check doors in the room */
-	var door=find_door(zone,room,name);
-	if(door) {
-		if(door.open == false) {
-			srv.o(target,"It is already closed.");
-			return false;
-		}
-		
-		srv.o(target,"You close the " + door.@name + ".");
-		door.open=false;
+	var item_index=find_object(room,obj);
+	if(item_index) {
+		var item=room.item[item_index];
+		srv.o(target,item.description);
 		return true;
-	} else {
-		srv.o(target,"There is no door there.");
-		return false;
 	}
-
-	/*	then check containers in the room */
 	
-	/*	then check containers in inventory */
+	srv.o(target,"You don't see that here.");
+	return false;
 }
 
-RPG_Commands["DROP"] = function (srv,target,zone,room,cmd,player) {
+/* ITEM COMMANDS */
+var Item_Commands=[];
+
+Item_Commands["DROP"] = function (srv,target,zone,room,cmd,player) {
 	cmd.shift();
 	var obj=cmd.shift();
 	if(!obj) {
@@ -575,7 +598,7 @@ RPG_Commands["DROP"] = function (srv,target,zone,room,cmd,player) {
 	return false;
 }
 
-RPG_Commands["GET"] = function (srv,target,zone,room,cmd,player) {
+Item_Commands["GET"] = function (srv,target,zone,room,cmd,player) {
 	cmd.shift();
 	var obj=cmd.shift();
 	if(!obj) {
@@ -647,7 +670,7 @@ RPG_Commands["GET"] = function (srv,target,zone,room,cmd,player) {
 	return false;
 }
 
-RPG_Commands["PUT"] = function (srv,target,zone,room,cmd,player) {
+Item_Commands["PUT"] = function (srv,target,zone,room,cmd,player) {
 	cmd.shift();
 	var obj=cmd.shift();
 	if(!obj) {
@@ -703,98 +726,142 @@ RPG_Commands["PUT"] = function (srv,target,zone,room,cmd,player) {
 	return false;
 }
 
-RPG_Commands["LOOK"] = function (srv,target,zone,room,cmd,player) {
+Item_Commands["UNLOCK"] = function (srv,target,zone,room,cmd,player) {
 	cmd.shift();
-	var obj=cmd.shift();
-	
-	/*	if no target specified, look at room */
-	if(!obj) {
-		display_room(srv,player,player.@zone,player.@room);
-		return;
+	var name=cmd.shift();
+	if(!name) {
+		srv.o(target,"Unlock what?");
+		return false;
 	}
 	
-	/*	if the second word is "in", attempt to look inside a container */
-	if(obj.toLowerCase()=="in") {
-		var cont=cmd.shift();
-		if(!cont) {
-			srv.o(target,"Look in what?");
+	/*	first check doors in the room */
+	var door=find_door(zone,room,name);
+	if(door) {
+		if(door.locked == false) {
+			srv.o(target,"It is already unlocked.");
 			return false;
 		}
 		
-		var container=false;
-		var container_index=find_object(player.inventory,cont);
-		if(container_index) container=player.inventory.item[container_index];
+		var key=player.inventory.item.(@id == door.key);
+		if(!key.length() > 0) {
+			srv.o(target,"You don't have the key.");
+			return false;
+		}
 		
-		/*	attampt to match specified container with room items */
-		else container_index=find_object(room,cont); 
-		if(!container && container_index) container=room.item[container_index];
+		srv.o(target,"You unlock the " + door.@name + ".");
+		door.locked=false;
+		return true;
 		
-		/*	if player has this container, check items in container for specified object */
-		if(container) {
-			if(container.type!="container") {
-				srv.o(target,"That isn't a container!");
-				return false;
-			}
-			var list=[];
-			for each(var i in container.item) {
-				list.push(i.title);
-			}
-			var str=list.length?list.join(", "):"nothing";
-			srv.o(target,"contents (" + container.title + "):" + str);
-			return true;
-		}
-		srv.o(target,"You can't find it!");
+	} else {
+		srv.o(target,"There is no door there.");
 		return false;
 	}
 	
-	/*	handle looking at items, mobs, doors */
-	var mob_index=find_mob(room,obj);
-	if(mob_index) {
-		var mob=room.mob[mob_index];
-		if(mob.description.length() > 0) srv.o(target,mob.description);
-		var list=[];
-		var eq=mob.equipment..item;
-		for each(var i in eq) {
-			list.push("<" + i.parent().@id + "> " + i.title);
+	/* then check containers */
+}
+
+Item_Commands["LOCK"] = function (srv,target,zone,room,cmd,player) {
+	cmd.shift();
+	var name=cmd.shift();
+	if(!name) {
+		srv.o(target,"Lock what?");
+		return false;
+	}
+	
+	/*	first check doors in the room */
+	var door=find_door(zone,room,name);
+	if(door) {
+		if(door.locked == true) {
+			srv.o(target,"It is already locked.");
+			return false;
 		}
-		var str=list.length?list.join(", "):"nothing";
-		srv.o(target,"eq: " + str);
+		
+		if(door.open == true) {
+			srv.o(target,"You should close it first.");
+			return false;
+		}
+		
+		var key=player.inventory.item.(@id == door.key);
+		if(!key.length() > 0) {
+			srv.o(target,"You don't have the key.");
+			return false;
+		}
+		
+		srv.o(target,"You lock the " + door.@name + ".");
+		door.locked=true;
 		return true;
+		
+	} else {
+		srv.o(target,"There is no door there.");
+		return false;
 	}
 	
-	var item_index=find_object(room,obj);
-	if(item_index) {
-		var item=room.item[item_index];
-		srv.o(target,item.description);
+	/* then check containers */
+}
+
+Item_Commands["OPEN"] = function (srv,target,zone,room,cmd,player) {
+	cmd.shift();
+	var name=cmd.shift();
+	if(!name) {
+		srv.o(target,"Open what?");
+		return false;
+	}
+	
+	/*	first check doors in the room */
+	var door=find_door(zone,room,name);
+	if(door) {
+		if(door.open == true) {
+			srv.o(target,"It is already open.");
+			return false;
+		}
+		if(door.locked == true) {
+			srv.o(target,"It is locked.");
+			return false;
+		}
+		
+		srv.o(target,"You open the " + door.@name + ".");
+		door.open=true;
 		return true;
+	} else {
+		srv.o(target,"There is no door there.");
+		return false;
 	}
+
+	/*	then check containers in the room */
 	
-	srv.o(target,"You don't see that here.");
-	return false;
+	/*	then check containers in inventory */
 }
 
-RPG_Commands["GOTO"] = function (srv,target,zone,room,cmd,player) {
+Item_Commands["CLOSE"] = function (srv,target,zone,room,cmd,player) {
 	cmd.shift();
-	var dest=cmd.shift();
-	if(!dest) {
-		srv.o(target,"Where do you want to go?");
+	var name=cmd.shift();
+	if(!name) {
+		srv.o(target,"Close what?");
 		return false;
 	}
-	var room=cmd.shift();
-	if(room) {
-		player.@zone=<zone>{dest}</zone>;
-		zone=zones[player.@zone];
+	
+	/*	first check doors in the room */
+	var door=find_door(zone,room,name);
+	if(door) {
+		if(door.open == false) {
+			srv.o(target,"It is already closed.");
+			return false;
+		}
+		
+		srv.o(target,"You close the " + door.@name + ".");
+		door.open=false;
+		return true;
 	} else {
-		room=dest;
+		srv.o(target,"There is no door there.");
+		return false;
 	}
-	player.@room=<room>{room}</room>;
-	var room=zone.room.(@id == player.@room);
-	srv.o(target,"You teleport to " + room.title);
-	display_room(srv,player,player.@zone,player.@room);
-	return;
+
+	/*	then check containers in the room */
+	
+	/*	then check containers in inventory */
 }
 
-RPG_Commands["REMOVE"] = function (srv,target,zone,room,cmd,player) {
+Item_Commands["REMOVE"] = function (srv,target,zone,room,cmd,player) {
 	cmd.shift();
 	var keyword=cmd.join(" ");
 	if(!keyword) {
@@ -823,7 +890,7 @@ RPG_Commands["REMOVE"] = function (srv,target,zone,room,cmd,player) {
 	}
 }
 
-RPG_Commands["WEAR"] = function (srv,target,zone,room,cmd,player) {
+Item_Commands["WEAR"] = function (srv,target,zone,room,cmd,player) {
 	cmd.shift();
 	var keyword=cmd.join(" ");
 	if(!keyword) {
@@ -855,5 +922,283 @@ RPG_Commands["WEAR"] = function (srv,target,zone,room,cmd,player) {
 		return true;
 	}
 }
-RPG_Commands["EQUIP"] = RPG_Commands["WEAR"];
-RPG_Commands["WIELD"] = RPG_Commands["WEAR"];
\ No newline at end of file
+Item_Commands["EQUIP"] = Item_Commands["WEAR"];
+Item_Commands["WIELD"] = Item_Commands["WEAR"];
+
+/* GAMEPLAY COMMANDS */
+var RPG_Commands=[];
+
+RPG_Commands["SCORE"] = function (srv,target,zone,room,cmd,player) {
+	srv.o(target,
+		"player: " + player.@name + 
+		" level: " + player.level + 
+		" race: " + player.player_race +
+		" class: " + player.player_class);
+	srv.o(target,
+		"str: " + player.strength +
+		" wis: " + player.wisdom +
+		" int: " + player.intelligence +
+		" dex: " + player.dexterity +
+		" con: " + player.constitution);
+	srv.o(target,
+		"experience: " + player.experience +
+		" movement: " + player.movement + 
+		" hitpoints: " + player.hitpoints +
+		" mana: " + player.mana + 
+		" gold: " + player.gold);
+}
+
+RPG_Commands["STATUS"] = function (srv,target,zone,room,cmd,player) {
+	srv.o(target,"<HP:" + player.hitpoints + " MA:" + player.mana + " MV:" + player.movement + ">");
+}
+
+RPG_Commands["MOVE"] = function (srv,target,zone,room,cmd,player) {
+	var exit=room.exit.(@name == cmd[1].toLowerCase());
+	if(exit.@target.toString()=="") {
+		srv.o(target,"You cannot go that way.");
+		return false;
+	}
+	
+	if(exit.door) {
+		var door=zone.door.(@id == exit.door);
+		if(door.open == false) {
+			srv.o(target,"The " + door.@name + " is closed.");
+			return false;
+		}
+	}
+	
+	if(zones[exit.@zone]) player.@zone=<zone>{exit.@zone}</zone>;
+	player.@room=<room>{exit.@target}</room>;
+
+	zone=zones[player.@zone];
+	room=zone.room.(@id == player.@room);
+
+	srv.o(target,"You " + player.travel + " " + exit.@name + " to " + room.title + ". " + get_exit_string(zone,room,player));
+}
+
+RPG_Commands["EQUIPMENT"] = function (srv,target,zone,room,cmd,player) {
+	var list=[];
+	var eq=player.equipment..item;
+	for each(var i in eq) {
+		list.push("<" + i.parent().@id + "> " + i.title);
+	}
+	var str=list.length?list.join(", "):"nothing";
+	srv.o(target,"eq: " + str);
+}
+
+RPG_Commands["INVENTORY"] = function (srv,target,zone,room,cmd,player) {
+	var list=[];
+	for each(var i in player.inventory.item) {
+		list.push(i.title);
+	}
+	var str=list.length?list.join(", "):"nothing";
+	srv.o(target,"inventory: " + str);
+}
+
+RPG_Commands["LOOK"] = function (srv,target,zone,room,cmd,player) {
+	cmd.shift();
+	var obj=cmd.shift();
+	
+	/*	if no target specified, look at room */
+	if(!obj) {
+		display_room(srv,player,player.@zone,player.@room);
+		return;
+	}
+	
+	/*	if the second word is "in", attempt to look inside a container */
+	if(obj.toLowerCase()=="in") {
+		var cont=cmd.shift();
+		if(!cont) {
+			srv.o(target,"Look in what?");
+			return false;
+		}
+		
+		var container=false;
+		var container_index=find_object(player.inventory,cont);
+		if(container_index) container=player.inventory.item[container_index];
+		
+		/*	attampt to match specified container with room items */
+		else container_index=find_object(room,cont); 
+		if(!container && container_index) container=room.item[container_index];
+		
+		/*	if player has this container, check items in container for specified object */
+		if(container) {
+			if(container.type!="container") {
+				srv.o(target,"That isn't a container!");
+				return false;
+			}
+			var list=[];
+			for each(var i in container.item) {
+				list.push(i.title);
+			}
+			var str=list.length?list.join(", "):"nothing";
+			srv.o(target,"contents (" + container.title + "):" + str);
+			return true;
+		}
+		srv.o(target,"You can't find it!");
+		return false;
+	}
+	
+	/*	handle looking at items, mobs, doors */
+	var mob_index=find_mob(room,obj);
+	if(mob_index) {
+		var mob=room.mob[mob_index];
+		if(mob.description.length() > 0) srv.o(target,mob.description);
+		var list=[];
+		var eq=mob.equipment..item;
+		for each(var i in eq) {
+			list.push("<" + i.parent().@id + "> " + i.title);
+		}
+		var str=list.length?list.join(", "):"nothing";
+		srv.o(target,"eq: " + str);
+		return true;
+	}
+	
+	var item_index=find_object(room,obj);
+	if(item_index) {
+		var item=room.item[item_index];
+		srv.o(target,item.description);
+		return true;
+	}
+	
+	srv.o(target,"You don't see that here.");
+	return false;
+}
+
+/* HELP TOPICS */
+var Help_Topics={
+SET:[
+	"change a setting:",
+	"set [new/current] [title/description] <text>",
+	"set link [north,south,east,west,up,down] <room id number>",
+	"set autolink on/off",
+	"note: autolink will automatically add adjacent",
+	" room exit links for you, if any. they can still",
+	" be set/unset manually",
+	"see topic: 'unset'"
+],
+
+UNSET:[
+	"clear an exit link setting:",
+	"unset link [north,south,east,west,up,down]",
+	"see topic: 'set'"
+],
+
+NEW:[
+	"create a new zone or object:",
+	"new zone <level> <title>",
+	"new item <not yet implemented>",
+	"new mob <not yet implemented>",
+	"new door <not yet implemented>"
+],
+
+GOTO:[
+	"move to a different room:",
+	"goto <zone id number> <room id number>"
+],
+
+REMOVE:[
+	"remove a piece of equipment:",
+	"remove <item keyword>"
+],
+
+WEAR:[
+	"wear a piece of equipment:",
+	"wear <item keyword>"
+],
+WIELD:this.WEAR,
+EQUIP:this.WEAR,
+
+GET:[
+	"retrieve an item:",
+	"get <item keyword>",
+	"get <item keyword> <container>",
+	"get all",
+	"get all <container>",
+	"note: a corpse is a container"
+],
+
+PUT:[
+	"place an item in a container:",
+	"put <item keyword> <container>",
+	"put all <container>"
+],
+
+DROP:[
+	"drop an inventory item in the room:",
+	"drop <item keyword>"
+],
+
+OPEN:[
+	"open a container or door:",
+	"open <container keyword>",
+	"open <door keyword>",
+	"see topics: 'close', 'lock', 'unlock'"
+],
+
+CLOSE:[
+	"close a container or door:",
+	"close <container keyword>",
+	"close <door keyword>",
+	"see topics: 'open', 'lock', 'unlock'"
+],
+
+LOCK:[
+	"lock a container or door:",
+	"lock <container keyword>",
+	"lock <door keyword>",
+	"you must have the key in your inventory",
+	"see topics: 'open', 'close', 'unlock'"
+],
+
+UNLOCK:[
+	"unlock a container or door:",
+	"unlock <container keyword>",
+	"unlock <door keyword>",
+	"you must have the key in your inventory",
+	"see topics: 'open', 'close', 'lock'"
+],
+
+KILL:[
+	"attack a mob/person:",
+	"kill <target keyword>"
+],
+ATTACK:this.KILL,
+HIT:this.KILL,
+FIGHT:this.KILL,
+
+FLEE:[
+	"run away from battle:",
+	"see topic: 'kill'" 
+],
+
+EDITOR:[
+	"The default world is very small. To get comfortable you may want to start by creating a new zone, and seeing how everything works.",
+	"You must first create a character and login before you can edit. Once you have logged in, type 'rpg edit' to toggle the editor on/off.",
+	"To create a new zone, turn the editor on and type 'new zone <level> <my new zone name>'.",
+	"By default, all exits will link automatically if the editor finds a room that is adjacent to you upon creating a new room. You can either turn this feature off, or modify those links later if you choose.",
+	"see topics: 'set','unset','new','goto'"
+],
+
+CREATE:[
+	"To start playing, you must first create a character.",
+	"To see a list of character races and classes, type 'rpg classes' and 'rpg races'.",
+	"When you have settled on a combination, type 'rpg create <race> <class>.",
+	"Once your character is created type 'rpg login' to start playing!"
+]
+
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exec/ircbots/rpgbot/rpg_functions.js b/exec/ircbots/rpgbot/rpg_functions.js
index 5189ed673b..df67844f9b 100644
--- a/exec/ircbots/rpgbot/rpg_functions.js
+++ b/exec/ircbots/rpgbot/rpg_functions.js
@@ -11,39 +11,29 @@ function Server_command(srv,cmdline,onick,ouh) {
 			}
 			break;
 		case "JOIN":
-			if (cmd[1][0] == ":")
-				cmd[1] = cmd[1].slice(1);
-			var target=cmd[1];
-			//srv.o(target,"Welcome to RPG test!","NOTICE");
-			//srv.o(target,"For a list of classes, type " + get_cmd_prefix() + "RPG CLASSES","NOTICE");
-			//srv.o(target,"For a list of races, type " + get_cmd_prefix() + "RPG RACES","NOTICE");
-			//srv.o(target,"To create a new character, type " + get_cmd_prefix() + "RPG CREATE <race> <class>","NOTICE");
-			//srv.o(target,"Type RPG LOGIN to start playing!","NOTICE");
+			/* if the user has no RPG player, greet them */
+			if(!player.length() > 0) {
+				if (cmd[1][0] == ":")
+					cmd[1] = cmd[1].slice(1);
+				var target=cmd[1];
+
+				srv.o(target,"Welcome to RPG test, " + onick + "!","NOTICE");
+				srv.o(target,"Type 'help rpg' to get started.","NOTICE");
+			}
 			break;
 		case "PRIVMSG":
+			/* if the user has no RPG player or is not logged in, don't process RPG commands */
+			if(player.@active != 1) break;
+
 			var target=cmd[1];
-			if ((cmd[1][0] == "#") || (cmd[1][0] == "&")) {
-				/* respond only to private message commands */
-				if(player.@active == 1 && player.@channel == target) {
-					cmd.shift();
-					cmd.shift();
-					/*	handle commands such as north, south, east, west.... */
-					try {
-						handle_command(srv,cmd,player,player.@channel);
-					} catch(e) {
-						srv.o(target,e);
-					}
-				}
-			} else if (cmd[1].toUpperCase() == srv.curnick.toUpperCase()) {
-				if(player.@active ==1 ) {
-					cmd.shift();
-					cmd.shift();
-					/*	handle commands such as north, south, east, west.... */
-					try {
-						handle_command(srv,cmd,player,onick);
-					} catch(e) {
-						srv.o(target,e);
-					}
+			if(player.@channel == target) {
+				cmd.shift();
+				cmd.shift();
+				/*	handle commands such as north, south, east, west.... */
+				try {
+					handle_command(srv,cmd,player,player.@channel);
+				} catch(e) {
+					srv.o(target,e);
 				}
 			}
 			break;
@@ -99,16 +89,38 @@ function handle_command(srv,cmd,player,target) {
 			break;
 	}
 	
+	if(player.@editing == 1) {
+		if(Editor_Commands[cmd[0]]) {
+			Editor_Commands[cmd[0]](srv,target,zone,room,cmd,player);
+		} else if(RPG_Commands[cmd[0]] ||
+			Battle_Commands[cmd[0]] ||
+			Item_Commands[cmd[0]]) {
+			srv.o(target,"You can't do that while editing.");
+		}
+		return;
+	}
 	if(RPG_Commands[cmd[0]]) {
 		RPG_Commands[cmd[0]](srv,target,zone,room,cmd,player);
 		return;
+	} 
+	if(Battle_Commands[cmd[0]]) {
+		Battle_Commands[cmd[0]](srv,target,zone,room,cmd,player);
+		return;
+	}
+	if(Item_Commands[cmd[0]]) {
+		Item_Commands[cmd[0]](srv,target,zone,room,cmd,player);
+		return;
+	}
+	if(Editor_Commands[cmd[0]]) {
+		srv.o(target,"Type 'rpg edit' to enable editing.");
+		return;
 	}
 	
 	for(var m in room.mob) {
 		var mob=room.mob[m];
 		for(var t in mob.trigger) {
 			if(cmd.join().match(mob.trigger[t].@id.toUpperCase())) {
-				srv.o(target,mob.name + " says, '" + mob.trigger[t].response + "'");
+				srv.o(target,mob.@name + " says, '" + mob.trigger[t].response + "'");
 			}
 		}
 	}
@@ -120,38 +132,31 @@ function display_room(srv,player,z,r) {
 	var zone=zones[z];
 	var room=zone.room.(@id == r);
 	
-	if(player.@editing == 1) {
-		srv.o(player.@channel,"Editing '" + zone.@name + "' [Z: " + z + " R: " + r + "]");
-	}
-	show_room_title(srv,player.@channel,zone,room,player);
-	show_room_description(srv,player.@channel,zone,room,player);
-	show_room_exits(srv,player.@channel,zone,room,player);
-	show_room_items(srv,player.@channel,zone,room,player);
-	show_room_mobs(srv,player.@channel,zone,room,player);
+	show_room_title(srv,player.@channel,zone,room);
+	show_room_description(srv,player.@channel,zone,room);
+	show_room_exits(srv,player.@channel,zone,room);
+	show_room_items(srv,player.@channel,zone,room);
+	show_room_mobs(srv,player.@channel,zone,room);
 	show_room_players(srv,player,zone,room);
 }
 
-function show_room_description(srv,target,zone,room,player) {
-	if(player.@editing == 1) srv.o(target,"[DESC] " + strip_ctrl(room.description));
-	else srv.o(target,strip_ctrl(room.description));
+function show_room_description(srv,target,zone,room) {
+	srv.o(target,strip_ctrl(room.description));
 }
 
-function show_room_title(srv,target,zone,room,player) {
-	if(player.@editing == 1) srv.o(target,"[TITLE] " + room.title);
-	else srv.o(target,room.title);
+function show_room_title(srv,target,zone,room) {
+	srv.o(target,room.title);
 }
 
-function show_room_items(srv,target,zone,room,player) {
+function show_room_items(srv,target,zone,room) {
 	for each(var i in room.item) {
-		if(player.@editing == 1) srv.o(target,"[ITEM: " + i.@id + "] " + i.appearance);
-		else srv.o(target,i.appearance);
+		srv.o(target,i.appearance);
 	}
 }
 
-function show_room_mobs(srv,target,zone,room,player) {
+function show_room_mobs(srv,target,zone,room) {
 	for each(var m in room.mob) {
-		if(player.@editing == 1) srv.o(target,"[MOB: " + m.@id + "] " + m.appearance);
-		else srv.o(target,m.appearance);
+		if(room.mob[m].@status != 0) srv.o(target,m.appearance);
 	}
 }
 
@@ -165,11 +170,11 @@ function show_room_players(srv,player,zone,room) {
 	}
 }
 
-function show_room_exits(srv,target,zone,room,player) {
-	srv.o(target,get_exit_string(zone,room,player));
+function show_room_exits(srv,target,zone,room) {
+	srv.o(target,get_exit_string(zone,room));
 }
 
-function get_exit_string(zone,room,player) {
+function get_exit_string(zone,room) {
 	var exit_str="";
 	var exits=room.exit.(@target != "");
 	for(var e in exits) {
@@ -179,8 +184,7 @@ function get_exit_string(zone,room,player) {
 			if(door.locked==true) prefix="@";
 			else if(door.open==false) prefix="#";
 		}
-		exit_str+=", "+prefix+exits[e].@name.substr(0,1);
-		if(player.@editing == 1) exit_str+="[ID:"+exits[e].@target+"]";
+		exit_str+=", "+prefix+exits[e].@name;
 	}
 	return ("exits: " + exit_str.substr(2));
 }
@@ -255,6 +259,7 @@ function find_object(container,keyword) {
 function find_mob(room,keyword) {
 	for(var m in room.mob) {
 		var mob=room.mob[m];
+		if(mob.@status == 0)  continue;
 		if(mob.keywords.match(keyword.toLowerCase())) {
 			return m;
 		}
@@ -353,7 +358,7 @@ function kill(srv,object) {
 	var zone=zones[object.@zone];
 	var room=zone.room.(@id == object.@room);
 	create_corpse(room,object);
-	delete object;
+	object.@status=0;
 }
 
 function create_corpse(room,object) {
@@ -390,11 +395,11 @@ function load_zone(dir) {
 		for(var r in zone.room) {
 			var room=zone.room[r];
 			for(var m in room.mob) {
-				var mob=mobs.mob.(@id == room.mob[m].@id).copy();
-				mob.@id=mob_count++;
-				mob.@room=room.@id;
-				mob.@zone=zone.@id;
-				room.mob[m].appendChild(mob.children());
+				room.mob[m]=mobs.mob.(@id == room.mob[m].@id).copy();
+				room.mob[m].@id=mob_count++;
+				room.mob[m].@room=room.@id;
+				room.mob[m].@zone=zone.@id;
+				room.mob[m].@status=1;
 			}
 		}
 		for (var i in zone..item) {
@@ -459,7 +464,75 @@ function load_races() {
 	r_file.close();
 }
 
-/* game edit functions */
+/* game editor display functions */
+
+function display_room_editor(srv,player,zone,room) {
+	srv.o(player.@channel,"Editing '" + blue + zone.@name + black + 
+		"' [Z:" + blue + " " + zone.@id + black + 
+		" R:" + blue + " " + room.@id + black + "]");
+}
+
+function display_exits_editor(srv,target,zone,room) {
+	var exits=["north","south","east","west","up","down"];
+	for each(var e in exits) {
+		var exit=room.exit.(@name == e);
+		if(exit.@target != undefined) {
+			var exit_str=red + "[" + e +"]";
+			if(zones[exit.@zone]) exit_str+= black + " z:" + blue + " " + exit.@zone;
+			exit_str+= black + " r:" + blue + " " + exit.@target;
+			if(exit.door != undefined) {
+				var door=zone.door.(@id == exit.door);
+				exit_str+= black + " door:" + blue + " " + door.@id;
+				exit_str+= black + " lock:" + blue + " " + door.locked;
+				exit_str+= black + " open:" + blue + " " + door.open;
+			}
+			srv.o(target,exit_str);
+		} else {
+			var start=new Coords(0,0,0);
+			var finish=get_exit_coords(start,e);
+			
+			result=find_link(zone,room,start,finish,undefined);
+			
+			if(result >= 0) {
+				var target_room=zone.room.(@id == result);
+				var exit=target_room.exit.(@name == reverse_dir(e));
+
+				var exit_str=red + "[" + e +"]";
+				exit_str+= black + " r:" + blue + " " + target_room.@id;
+				
+				if(exit.door != undefined) {
+					var door=zone.door.(@id == exit.door);
+					exit_str+= black + " door:" + blue + " " + door.@id;
+					exit_str+= black + " lock:" + blue + " " + door.locked;
+					exit_str+= black + " open:" + blue + " " + door.open;
+				}
+				exit_str+= red + " (unlinked)";
+				srv.o(target,exit_str);
+			}
+		}
+	}
+}
+
+function display_mobs_editor(srv,target,zone,room) {
+	for each(var m in room.mob) {
+		srv.o(target,
+			red + "[mob]" +  
+			black + " id:" + blue + " " + m.@id +
+			black + " name:" + blue + " " + m.@name);
+	}
+}
+
+function display_items_editor(srv,target,zone,room) {
+	for each(var i in room.item) {
+		srv.o(target,
+			red + "[item]" +  
+			black + " id:" + blue + " " + i.@id +
+			black + " name:" + blue + " " + i.title);
+	}
+}
+
+/* game editor functions */
+
 function find_link(zone,room,start_coords,finish_coords,checked) {
 	
 
@@ -598,8 +671,8 @@ function create_new_room(srv,target,zone,room,player,dir) {
 	
 	/* move player to new room */
 	player.@room=new_id;
-	srv.o(target,"room " + new_id + " created");
-	display_room(srv,player,zone.@id,new_id);
+	srv.o(target,"Room " + new_id + " created");
+	display_room_editor(srv,player,zone,new_room);
 }
 
 function get_dir_coords(exclude) {
@@ -611,7 +684,7 @@ function get_dir_coords(exclude) {
 		up:new Coords(0,0,1),
 		down:new Coords(0,0,-1),
 	}
-	delete dirs[exclude];
+	if(exclude) delete dirs[exclude];
 	return dirs;
 }
 
diff --git a/exec/ircbots/rpgbot/rpgbot.js b/exec/ircbots/rpgbot/rpgbot.js
index d2086793d4..24f2213456 100644
--- a/exec/ircbots/rpgbot/rpgbot.js
+++ b/exec/ircbots/rpgbot/rpgbot.js
@@ -1,3 +1,19 @@
+/* 
+	$Id$
+	Synchronet IRC bot module for ircbot.js
+	
+	Role-playing game bot (MUD) with in-game zone editor
+	using XML data files. 
+	
+	TODO: 
+		add in-game item creation/editing
+		add in-game mob creation/editing
+		add time-based events and zone-cycles
+		...more when I think of it
+		
+	by Matt Johnson : MCMLXXIX (2010)
+*/
+
 var p_dir=this.dir+"players/";
 var z_dir=this.dir+"zones/";
 var c_file=new File(this.dir+"classes.xml");
@@ -14,6 +30,11 @@ var player_attacks=[];
 var mob_attacks=[];
 var global_items=load_items(gi_file);
 
+var black=String.fromCharCode(3)+"1";
+var blue=String.fromCharCode(3)+"2";
+var green=String.fromCharCode(3)+"3";
+var red=String.fromCharCode(3)+"5";
+
 var activity_timeout=300;	// seconds
 var tick_time=4;	// seconds
 var max_armor=200;
-- 
GitLab