diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/changelog tbamud-3.54/changelog
--- tbamud-3.53/changelog	2007-07-02 15:59:22.000000000 +0200
+++ tbamud-3.54/changelog	2007-11-29 03:02:23.000000000 +0100
@@ -4,10 +4,96 @@ Rumble
 The Builder Academy
 builderacademy.net 9091
  
+tbaMUD 3.54
+[Nov 12 2007] - Rumble
+  Updated users command to fix GET_INVIS_LEV bug.
+  Updated the drink command to work in rooms where the sector type should logically allow it.
+[Oct 04 2007] - Rumble
+Increased the size of a mail message from 4k to 8k.
+  Updated remove_player so that the players command would not show phantom users when someone self-deletes.
+  Updated sedit_rooms_menu to prevent a crash bug when trying to display a shop with rooms that have been removed.
+[Nov 01 2007] - Rumble
+  Updated mag_objectmagic bug where action description was not being used correctly on scrolls.
+  Increased the size of MAX_RAW_INPUT_LENGTH and PLR_DESC_LENGTH.
+[Oct 19 2007] - Rumble
+  Fixed a few more 128 bit MOB_FLAGGED bugs.
+[Oct 17 2007] - Rumble
+  Fixed loading of non-128 bit prefs in load_char. (thanks Ziz)
+[Oct 15 2007] - Rumble
+  Removed some prototypes leftover from the old history command. (thanks Rhade)
+[Oct 13 2007] - Rumble
+  Updated World, Help, News, Socials, and src for tbaMUD3.54rc.
+  Fixed bug where toggling syslog enabled brief. (thanks Rhade)
+  Added zone 11.
+[Oct 10 2007] - Rumble
+  Added OLC menu options for Copying. The Xcopy option is still available for GODs and above.
+  Player table is now created if it does not exist. (thanks Rhade)
+[Oct 08 2007] - Rumble
+  Removed top_shop_offset variable, hopefully fixing the infamous sedit bug.
+  Fixed memory leaks from not freeing new zone builders and new zone commands. (thanks Neme)
+[Oct 04 2007] - Rumble
+  Changed autoexit to display doors as Exits: n (e) w s. DISP_CLOSED_DOORS added to cedit.
+  Added rcopy, ocopy, etc. for all forms of OLC. (thanks Neme)
+[Oct 01 2007] - Rumble
+  Added trigedit variables %zonename% and %zonenumber%. (thanks Drefs)
+  Fixed memory leak in do_dig. (thanks Neme)
+  Added trigedit variables %roomflag% and object %affects%. (thanks Jamdog)
+[Sep 27 2007] - Rumble
+  Update to do_hit to prevent crash if the player is AFF_CHARM somehow without a master. (thanks Jamdog)
+  Removed alias.c. New ASCII aliases handled in players.c and saved in plrfiles.
+[Sep 25 2007] - Rumble
+  Added set/not set to extra descriptions menu in oedit so a builder can tell if they exist or not without having to enter the extra desc menu or stat the object.
+  Replaced [TRIG] flag (showvnum enabled) with [T<vnum>] to make things easier to stat.
+[Sep 24 2007] - Rumble
+  Added %is_pc% to return -1 for objects. (thanks Jamdog)
+  Fixed do_gen_comm color bleed into last apostrophe in gossip/shout/grat/etc.
+  Fixed bug where object keywords took precedence over door keywords. i.e. open door would try to open an object with keyword door. (thanks Trulight)
+[Sep 23 2007] - Rumble
+  Fixed minlev checks in do_grab, do_wield, and do_wear. (thanks Trulight)
+  Added trigedit variables(modifiable) Hunger, Thirst, and Drunk.
+[Sep 15 2007] - Rumble
+  Fixed bug in unlimited drinks showing as empty. (thanks AaronGoulet)
+[Sep 13 2007] - Rumble
+  Changed binary search functions (real_xxxx, real_zone_by_thing), except real_shop. (thanks Neme)
+  script_proto list freed when exiting without saving in oedit/medit/redit.  (thanks Neme)
+  dg_olc.c, trigedit_save(): trig name and arg duping removed. (thanks Neme)
+  genobj.c, update_all_obects(): object ID copied, no more 0 uid. (thanks Neme)
+  CLEANUP_ALL in redit after saving a room.  (thanks Neme)
+  new function in genolc.c: free_save_list(), called during shutdown.  (thanks Neme)
+  Event_free_all() now frees all events. (thanks Neme)
+  Fixed memory leak in perform_act(). (thanks Rhade)
+  Changed NUM_BOARDS from 10 to 7 (the actual num of boards). (thanks Neme)
+  Removed the Keywords option in hedit since they have to be in the body.
+[Sep 12 2007] - Rumble
+  Fixed crash bug caused by olist with no objects. (thanks Rhade)
+  Several changes made to compile clean on older versions of GCC. (thanks Neme)
+[Sep 10 2007] - Rumble
+  Fixed items with rnum = NOTHING or NOBODY being changed to rnum = 0.  (thanks Neme)
+  Fixed memory leak in dg_olc.c trigedit save. (thanks Neme)
+[Sep 04 2007] - Rumble
+  Changed CLSOLC to LVL_BUILDER.
+  removed delete_doubledollar from do_say. (thanks Rhade)
+[Sep 01 2007] - Rumble
+  Made Puff a hidden mob since she is used on room entry trigs to do dg_cast.
+  Fixed dg_affect to not add 1 to the desired affect duration.
+  Fixed dg_affect to work with 128 bits.
+[Aug 17 2007] - Rumble
+  128 bit fixes: pfile conversion, world sector conversion, and player flags. (thanks Jamdog)
+  Added stop_fighting calls in do_flee to fix stock bug. (thanks Juras)
 tbaMUD 3.53
-[Jun 28 2007]
+[Jul 01 2007] - Rumble
+  Added run_autowiz to do_cheat. (thanks Fizban)
   Updated World and files for 3.53 release.
+[Jul 30 2007] - Rumble
+  Fixed bad color counting in shop listing. (thanks Ziz)
+  Stat zone without arg displays current zone.
+[Jun 29 2007] - Rumble
+  Added new object variable wearflag.
+[Jun 28 2007] - Rumble
+  Removed char_from_furniture in do_sit. (Thanks Jamdog)
+  Replaced strcasecmp and strncasecmp with str_cmp and strn_cmp. (Thanks Khorlane)
 [Jun 26 2007] - Rumble
+  Added Jamdog's "complete" screen.h. (Thanks Jamdog)
   Updated hedit to Rhade's cleaner version. (thanks Rhade)
 [Jun 25 2007] - Rumble
   Added questpoints to load_char and set autoexit on by default. (thanks Trulight)
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/lib/misc/messages tbamud-3.54/lib/misc/messages
--- tbamud-3.53/lib/misc/messages	2007-07-02 15:59:22.000000000 +0200
+++ tbamud-3.54/lib/misc/messages	2007-11-29 03:02:23.000000000 +0100
@@ -1,10 +1,9 @@
 * Note: all lines between records which start with '*' are comments and
 * are ignored.  Comments can only be between records, not within them.
 *
-* This file is where the damage messages go for offensive spells, and
-* skills such as kick and backstab.  Also, starting with Circle 3.0, these
-* messages are used for failed spells, and weapon messages for misses and
-* death blows.
+* This file is where the damage messages go for offensive spells, skills 
+* (such as kick and backstab), failed spells, and weapon messages for 
+* misses and death blows.
 *
 * All records must start with 'M' in the first column (for 'Message').
 * The next line must contain the damage number (defined in spells.h),
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/lib/misc/socials.new tbamud-3.54/lib/misc/socials.new
--- tbamud-3.53/lib/misc/socials.new	2007-07-02 15:59:22.000000000 +0200
+++ tbamud-3.54/lib/misc/socials.new	2007-11-29 03:02:30.000000000 +0100
@@ -1096,12 +1096,12 @@ $n wishes $mself a very Merry Christmas.
 ~chuckles chu 0 5 0 0
 You chuckle politely.
 $n chuckles politely.
-You chuckle at $M.
+You chuckle at $N.
 $n chuckles at $N.
 $n chuckles at you.
 Hmm... No one like that seems to be about.
 You chuckle quietly to yourself.
-$n chuckle quietly to $mself, obviously some private joke.
+$n chuckles quietly to $mself, obviously some private joke.
 You chuckle at $S $t.
 $n chuckles at $N's $t.
 $n chuckles at your $t.
@@ -5461,7 +5461,7 @@ $n sidles up cozily to $p.
 ~sigh sigh 0 5 0 0
 You sigh.
 $n sighs loudly.
-You look at $M and sigh.
+You look at $N and sigh.
 $n sighs at $N.
 $n sighs at you.
 You sigh in a halfhearted way.
@@ -6121,7 +6121,7 @@ $n strangles $p.
 ~stretch stretch 0 5 0 0
 You stretch your tired muscles.  That feels so good.
 $n stretches $s aching muscles.
-You stretch $M.
+You stretch $N.
 $n stretches $N.
 $n stretches you.
 I hope you know this person!
@@ -7148,7 +7148,7 @@ No one with that name is present.
 You wink at yourself?? -- what are you up to?
 $n winks at $mself -- something strange is going on...
 You wink at $S $t.
-$n winks at $N's $.
+$n winks at $N's $t.
 $n winks at your $t.
 You wink at $p.
 $n winks at $p.
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/lib/text/immlist tbamud-3.54/lib/text/immlist
--- tbamud-3.53/lib/text/immlist	2007-07-02 15:58:55.000000000 +0200
+++ tbamud-3.54/lib/text/immlist	2007-11-29 03:02:10.000000000 +0100
@@ -4,4 +4,5 @@
 
                                    Immortals
                                    ~~~~~~~~~
+   Testdet         
 
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/lib/text/news tbamud-3.54/lib/text/news
--- tbamud-3.53/lib/text/news	2007-07-02 15:58:55.000000000 +0200
+++ tbamud-3.54/lib/text/news	2007-11-29 03:02:10.000000000 +0100
@@ -4,6 +4,8 @@
 
 NEW COMMANDS AND NEW MUD BEHAVIOR:
 ---------------------------------
+**  Doors are now visible in the exits menu. i.e. Exits: n (e) w s.
+
 **  Added questpoints so be sure to ask about quests.
 
 **  Added furniture for your MUDding comfort.
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/Makefile.amiga tbamud-3.54/src/Makefile.amiga
--- tbamud-3.53/src/Makefile.amiga	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/Makefile.amiga	2007-11-29 03:02:08.000000000 +0100
@@ -24,7 +24,7 @@ OBJFILES = comm.o act.comm.o act.informa
 	castle.o class.o config.o constants.o db.o fight.o graph.o handler.o \
 	house.o interpreter.o limits.o magic.o mail.o mobact.o modify.o \
 	objsave.o shop.o spec_assign.o spec_procs.o spell_parser.o \
-	spells.o utils.o weather.o alias.o players.o
+	spells.o utils.o weather.o players.o
 
 default: .accepted
 	$(MAKE) ../bin/circle
@@ -91,8 +91,6 @@ clean:
 # Dependencies for the object files (automagically generated with
 # gcc -MM)
 
-alias.o: alias.c conf.h sysdep.h structs.h utils.h interpreter.h db.h
-	$(CC) -c $(CFLAGS) alias.c
 act.comm.o: act.comm.c conf.h sysdep.h structs.h utils.h comm.h interpreter.h \
   handler.h db.h screen.h
 	$(CC) -c $(CFLAGS) act.comm.c
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/Makefile.arc tbamud-3.54/src/Makefile.arc
--- tbamud-3.53/src/Makefile.arc	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/Makefile.arc	2007-11-29 03:02:08.000000000 +0100
@@ -26,7 +26,7 @@ OBJFILES = o.comm act.o.comm act.o.infor
 	o.castle o.class o.config o.constants o.db o.fight o.graph o.handler \
 	o.house o.interpreter o.limits o.magic o.mail o.mobact o.modify \
 	o.objsave o.random o.shop o.spec_assign o.spec_procs \
-	o.spell_parser o.spells o.utils o.weather o.players o.alias
+	o.spell_parser o.spells o.utils o.weather o.players 
 
 default:	all
 
@@ -41,8 +41,6 @@ clean:
 # Dependencies for the object files (automagically generated with
 # gcc -MM)
 
-o.alias: c.alias h.conf h.sysdep h.structs h.utils h.interpreter h.db
-        $(CC) -c $(CFLAGS) c.alias -o o.alias
 act.o.comm: act.c.comm h.conf h.sysdep h.structs \
   h.utils h.comm h.interpreter h.handler \
   h.db h.screen
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/Makefile.bcc tbamud-3.54/src/Makefile.bcc
--- tbamud-3.53/src/Makefile.bcc	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/Makefile.bcc	2007-11-29 03:02:08.000000000 +0100
@@ -43,7 +43,6 @@ circle : BccW32.cfg $(Dep_circle)
   echo MakeNode
 
 Dep_circledexe = \
-   alias.obj\
    act.comm.obj\
    act.movement.obj\
    act.item.obj\
@@ -85,7 +84,6 @@ circle.exe : $(Dep_circledexe)
   $(TLINK32) @&&|
  /v $(IDE_LinkFLAGS32) $(LinkerOptsAt_circledexe) $(LinkerInheritOptsAt_circledexe) +
 C:\BC5\LIB\c0x32.obj+
-alias.obj+
 act.comm.obj+
 act.movement.obj+
 act.item.obj+
@@ -129,11 +127,6 @@ C:\BC5\LIB\cw32i.lib
 
 
 |
-alias.obj : alias.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_circledexe) $(CompInheritOptsAt_circledexe) -o$@ alias.c
-|
-
 act.comm.obj :  act.comm.c
   $(BCC32) -P- -c @&&|
  $(CompOptsAt_circledexe) $(CompInheritOptsAt_circledexe) -o$@ act.comm.c
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/Makefile.bcc55 tbamud-3.54/src/Makefile.bcc55
--- tbamud-3.53/src/Makefile.bcc55	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/Makefile.bcc55	2007-11-29 03:02:08.000000000 +0100
@@ -44,7 +44,6 @@ circle : BccW32.cfg $(Dep_circle)
   echo MakeNode
 
 Dep_circledexe = \
-   alias.obj\
    act.comm.obj\
    act.movement.obj\
    act.item.obj\
@@ -86,7 +85,6 @@ circle.exe : $(Dep_circledexe)
   $(TLINK32) @&&|
  /v $(IDE_LinkFLAGS32) $(LinkerOptsAt_circledexe) $(LinkerInheritOptsAt_circledexe) +
 C:\BORLAND\BCC55\LIB\c0x32.obj+
-alias.obj+
 act.comm.obj+
 act.movement.obj+
 act.item.obj+
@@ -128,11 +126,6 @@ C:\BORLAND\BCC55\LIB\import32.lib+
 C:\BORLAND\BCC55\LIB\cw32i.lib
 
 |
-alias.obj : alias.c
-  $(BCC32) -P- -c @&&|
- $(CompOptsAt_circledexe) $(CompInheritOptsAt_circledexe) -o$@ alias.c
-|
-
 act.comm.obj :  act.comm.c
   $(BCC32) -P- -c @&&|
  $(CompOptsAt_circledexe) $(CompInheritOptsAt_circledexe) -o$@ act.comm.c
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/Makefile.in tbamud-3.54/src/Makefile.in
--- tbamud-3.53/src/Makefile.in	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/Makefile.in	2007-11-29 03:02:08.000000000 +0100
@@ -24,7 +24,7 @@ CFLAGS = @CFLAGS@ $(MYFLAGS) $(PROFILE)
 LIBS = @LIBS@ @CRYPTLIB@ @NETLIB@
 
 OBJFILES = act.comm.o act.informative.o act.item.o act.movement.o \
-	act.offensive.o act.other.o act.social.o act.wizard.o aedit.o alias.o \
+	act.offensive.o act.other.o act.social.o act.wizard.o aedit.o \
 	ban.o boards.o bsd-snprintf.o castle.o cedit.o class.o comm.o config.o \
 	constants.o db.o dg_comm.o dg_db_scripts.o dg_event.o \
 	dg_handler.o dg_misc.o dg_mobcmd.o dg_objcmd.o dg_olc.o dg_scripts.o \
@@ -37,7 +37,7 @@ OBJFILES = act.comm.o act.informative.o 
 	weather.o zedit.o zmalloc.o 
 
 CXREF_FILES = act.comm.c act.informative.c act.item.c act.movement.c \
-	act.offensive.c act.other.c act.social.c act.wizard.c aedit.c alias.c \
+	act.offensive.c act.other.c act.social.c act.wizard.c aedit.c \
 	ban.c boards.c bsd-snprintf.c castle.c cedit.c class.c comm.c config.c \
 	constants.c db.c dg_comm.c dg_db_scripts.c dg_event.c \
 	dg_handler.c dg_misc.c dg_mobcmd.c dg_objcmd.c dg_olc.c dg_scripts.c \
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/Makefile.lcc tbamud-3.54/src/Makefile.lcc
--- tbamud-3.53/src/Makefile.lcc	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/Makefile.lcc	2007-11-29 03:02:08.000000000 +0100
@@ -52,7 +52,6 @@ OBJS=\
 	act.item.obj \
 	act.informative.obj \
 	act.comm.obj \
-	alias.obj
 
 LIBS=$(LCCDIR)\lib\wsock32.lib
 
@@ -551,14 +550,3 @@ ACT_COMM_C=\
 act.comm.obj: $(ACT_COMM_C) $(DISTDIR)\src\act.comm.c
     $(CC)  $(CFLAGS) $(DISTDIR)\src\act.comm.c
 
-# Build ALIAS.C
-ALIAS_C=\
-    $(DISTDIR)\src\sysdep.h\
-    $(DISTDIR)\src\structs.h\
-    $(DISTDIR)\src\utils.h\
-    $(DISTDIR)\src\interpreter.h\
-    $(DISTDIR)\src\db.h\
-
-alias.obj: $(ALIAS_C) $(DISTDIR)\src\alias.c
-    $(CC)  $(CFLAGS) $(DISTDIR)\src\alias.c
-
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/Makefile.msvc tbamud-3.54/src/Makefile.msvc
--- tbamud-3.53/src/Makefile.msvc	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/Makefile.msvc	2007-11-29 03:02:08.000000000 +0100
@@ -40,7 +40,7 @@ OBJFILES = comm.obj act.comm.obj act.inf
         castle.obj class.obj config.obj constants.obj db.obj fight.obj graph.obj handler.obj \
         house.obj interpreter.obj limits.obj magic.obj mail.obj mobact.obj modify.obj \
         objsave.obj shop.obj spec_assign.obj spec_procs.obj spell_parser.obj \
-        spells.obj utils.obj weather.obj random.obj alias.obj players.obj
+        spells.obj utils.obj weather.obj random.obj players.obj
 
 default: circle.exe
         $(MAKE) circle.exe
@@ -52,8 +52,6 @@ circle.exe : $(OBJFILES)
 # Dependencies for the object files (automagically generated with
 # gcc -MM)
 
-alias.obj: alias.c conf.h sysdep.h structs.h utils.h interpreter.h db.h
-	$(CC) -c $(CFLAGS) alias.c
 act.comm.obj: act.comm.c conf.h sysdep.h structs.h utils.h comm.h interpreter.h \
   handler.h db.h screen.h
 	$(CC) -c $(CFLAGS) act.comm.c
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/Makefile.os2 tbamud-3.54/src/Makefile.os2
--- tbamud-3.53/src/Makefile.os2	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/Makefile.os2	2007-11-29 03:02:08.000000000 +0100
@@ -26,7 +26,7 @@ OBJFILES = comm.o act.comm.o act.informa
         castle.o class.o config.o constants.o db.o fight.o graph.o handler.o \
         house.o interpreter.o limits.o magic.o mail.o mobact.o modify.o \
         objsave.o shop.o spec_assign.o spec_procs.o spell_parser.o \
-        spells.o utils.o weather.o random.o alias.o players.o
+        spells.o utils.o weather.o random.o players.o
 
 default: .accepted
         $(MAKE) ../bin/circle
@@ -93,8 +93,6 @@ clean:
 # Dependencies for the object files (automagically generated with
 # gcc -MM)
 
-alias.o: alias.c conf.h sysdep.h structs.h utils.h interpreter.h db.h
-	$(CC) -c $(CFLAGS) alias.c
 act.comm.o: act.comm.c conf.h sysdep.h structs.h utils.h comm.h interpreter.h \
   handler.h db.h screen.h
         $(CC) -c $(CFLAGS) act.comm.c
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/act.comm.c tbamud-3.54/src/act.comm.c
--- tbamud-3.53/src/act.comm.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/act.comm.c	2007-11-29 03:02:08.000000000 +0100
@@ -33,9 +33,6 @@ ACMD(do_page);
 ACMD(do_gen_comm);
 ACMD(do_qcomm);
 void handle_webster_file(void);
-ACMD(do_list_history);
-void new_hist_messg(struct descriptor_data *d, const char *msg);
-void free_hist_messg(struct descriptor_data *d);
 
 static long last_webster_teller = -1L;
 
@@ -47,11 +44,11 @@ ACMD(do_say)
     send_to_char(ch, "Yes, but WHAT do you want to say?\r\n");
   else {
     char buf[MAX_INPUT_LENGTH + 14], *msg;
+    struct char_data *vict;
 
     snprintf(buf, sizeof(buf), "$n@n says, '%s@n'", argument);
     msg = act(buf, FALSE, ch, 0, 0, TO_ROOM | DG_NO_TRIG);
 
-    struct char_data *vict;
     for (vict = world[IN_ROOM(ch)].people; vict; vict = vict->next_in_room)
       if (vict != ch && GET_POS(vict) > POS_SLEEPING)
         add_history(vict, msg, HIST_SAY);
@@ -59,7 +56,6 @@ ACMD(do_say)
     if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_NOREPEAT))
       send_to_char(ch, "%s", CONFIG_OK);
     else {
-      delete_doubledollar(argument);
       sprintf(buf, "You say, '%s@n'", argument);
       msg = act(buf, FALSE, ch, 0, 0, TO_CHAR | DG_NO_TRIG);
       add_history(ch, msg, HIST_SAY);
@@ -517,7 +513,8 @@ ACMD(do_gen_comm)
     send_to_char(ch, "%s", CONFIG_OK);
   else {
     if (!first_word_is_name(ch, argument)) {
-      snprintf(buf1, sizeof(buf1), "%sYou %s, '%s'%s", COLOR_LEV(ch) >= C_CMP ? color_on : "", com_msgs[subcmd][1], argument, CCNRM(ch, C_CMP));
+      snprintf(buf1, sizeof(buf1), "%sYou %s, '%s%s'%s", COLOR_LEV(ch) >= C_CMP ? color_on : "", com_msgs[subcmd][1], argument, COLOR_LEV(ch) >= C_CMP
+      ? color_on : "", CCNRM(ch, C_CMP));
     } else {
       emoting = TRUE;
       snprintf(buf1, sizeof(buf1), "%s%s: %s%s", COLOR_LEV(ch) >= C_CMP ? color_on : "", com_msgs[subcmd][1], CAP(argument), CCNRM(ch, C_CMP));
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/act.informative.c tbamud-3.54/src/act.informative.c
--- tbamud-3.53/src/act.informative.c	2007-07-02 16:01:36.000000000 +0200
+++ tbamud-3.54/src/act.informative.c	2007-11-29 03:05:30.000000000 +0100
@@ -131,17 +131,21 @@ void show_obj_to_char(struct obj_data *o
     if (*obj->description == '.' && (IS_NPC(ch) || !PRF_FLAGGED(ch, PRF_HOLYLIGHT)))
       return;
 
-    if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_SHOWVNUMS))
-      send_to_char(ch, "[%d] %s", GET_OBJ_VNUM(obj), SCRIPT(obj) ? "[TRIG] " : "");
-
+    if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_SHOWVNUMS)) {
+      send_to_char(ch, "[%d] ", GET_OBJ_VNUM(obj));
+      if (SCRIPT(obj))
+        send_to_char(ch, "[T%d] ", obj->proto_script->vnum);
+    }
     send_to_char(ch, "%s", CCGRN(ch, C_NRM));
     send_to_char(ch, "%s", obj->description);
     break;
 
   case SHOW_OBJ_SHORT:
-    if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_SHOWVNUMS))
-      send_to_char(ch, "[%d] %s", GET_OBJ_VNUM(obj), SCRIPT(obj) ? "[TRIG] " : "");
-
+    if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_SHOWVNUMS)) {
+      send_to_char(ch, "[%d] ", GET_OBJ_VNUM(obj));
+      if (SCRIPT(obj))
+        send_to_char(ch, "[T%d] ", obj->proto_script->vnum);
+    }
     send_to_char(ch, "%s", obj->short_description);
     break;
 
@@ -321,8 +325,11 @@ void list_one_char(struct char_data *i, 
     " is standing here."
   };
 
-  if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_SHOWVNUMS) && IS_NPC(i))
-     send_to_char(ch, "[%d] %s", GET_MOB_VNUM(i), SCRIPT(i) ? "[TRIG] " : "");
+  if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_SHOWVNUMS) && IS_NPC(i)) {
+    send_to_char(ch, "[%d] ", GET_MOB_VNUM(i));
+    if (SCRIPT(i))
+      send_to_char(ch, "[T%d] ", i->proto_script->vnum);
+  }
 
   if (IS_NPC(i) && i->player.long_descr && GET_POS(i) == GET_DEFAULT_POS(i)) {
     if (AFF_FLAGGED(i, AFF_INVISIBLE))
@@ -427,9 +434,11 @@ void do_auto_exits(struct char_data *ch)
   for (door = 0; door < NUM_OF_DIRS; door++) {
     if (!EXIT(ch, door) || EXIT(ch, door)->to_room == NOWHERE)
       continue;
-    if (EXIT_FLAGGED(EXIT(ch, door), EX_CLOSED))
+    if (EXIT_FLAGGED(EXIT(ch, door), EX_CLOSED) && !CONFIG_DISP_CLOSED_DOORS)
       continue;
-
+    if (EXIT_FLAGGED(EXIT(ch, door), EX_CLOSED))
+      send_to_char(ch, "%s(%c)%s ", CCRED(ch, C_NRM), LOWER(*dirs[door]), CCCYN(ch, C_NRM));
+    else
     send_to_char(ch, "%c ", LOWER(*dirs[door]));
     slen++;
   }
@@ -451,14 +460,18 @@ ACMD(do_exits)
   for (door = 0; door < NUM_OF_DIRS; door++) {
     if (!EXIT(ch, door) || EXIT(ch, door)->to_room == NOWHERE)
       continue;
-    if (EXIT_FLAGGED(EXIT(ch, door), EX_CLOSED))
+    if (EXIT_FLAGGED(EXIT(ch, door), EX_CLOSED) && !CONFIG_DISP_CLOSED_DOORS)
       continue;
 
     len++;
 
-    if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_SHOWVNUMS)) 
-      send_to_char(ch, "%-5s - [%5d] %s\r\n", dirs[door], GET_ROOM_VNUM(EXIT(ch, door)->to_room),
-		world[EXIT(ch, door)->to_room].name);
+    if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_SHOWVNUMS) && !EXIT_FLAGGED(EXIT(ch, door), EX_CLOSED)) 
+      send_to_char(ch, "%-5s - [%5d] %s\r\n", dirs[door], GET_ROOM_VNUM(EXIT(ch, door)->to_room), world[EXIT(ch, door)->to_room].name);
+    else if (CONFIG_DISP_CLOSED_DOORS && EXIT_FLAGGED(EXIT(ch, door), EX_CLOSED)) {
+      /* But we tell them the door is closed */
+      send_to_char(ch, "%-5s - The %s is closed.\r\n", dirs[door],
+                  (EXIT(ch, door)->keyword)? fname(EXIT(ch, door)->keyword) : "opening" );
+      }
     else
       send_to_char(ch, "%-5s - %s\r\n", dirs[door], IS_DARK(EXIT(ch, door)->to_room) &&
 		!CAN_SEE_IN_DARK(ch) ? "Too dark to tell." : world[EXIT(ch, door)->to_room].name);
@@ -488,9 +501,10 @@ void look_at_room(struct char_data *ch, 
     sprintbitarray(ROOM_FLAGS(IN_ROOM(ch)), room_bits, RF_ARRAY_MAX, buf);
     send_to_char(ch, "[%5d] ", GET_ROOM_VNUM(IN_ROOM(ch)));
 
-    send_to_char(ch, "%s%s [ %s]",
-                     SCRIPT(rm) ? "[TRIG] " : "",
-                     world[IN_ROOM(ch)].name, buf);
+    if (rm->proto_script)
+      send_to_char(ch, "[T%d] ", rm->proto_script->vnum);
+      
+    send_to_char(ch, "%s [ %s]", world[IN_ROOM(ch)].name, buf);
   } else
     send_to_char(ch, "%s", world[IN_ROOM(ch)].name);
 
@@ -561,7 +575,7 @@ void look_in_obj(struct char_data *ch, c
 	list_obj_to_char(obj->contains, ch, SHOW_OBJ_SHORT, TRUE);
       }
     } else {		/* item must be a fountain or drink container */
-      if (GET_OBJ_VAL(obj, 1) <= 0)
+      if ((GET_OBJ_VAL(obj, 1) == 0) && (!GET_OBJ_VAL(obj, 0) == 1))
 	send_to_char(ch, "It is empty.\r\n");
       else {
         if (GET_OBJ_VAL(obj, 0) < 0)
@@ -1047,10 +1062,10 @@ ACMD(do_help)
   space_to_minus(argument);
 
   if ((mid = search_help(argument, GET_LEVEL(ch))) == NOWHERE) {
+    int i, found = 0;
     send_to_char(ch, "There is no help on that word.\r\n");
     mudlog(NRM, MAX(LVL_IMPL, GET_INVIS_LEV(ch)), TRUE,
       "%s tried to get help on %s", GET_NAME(ch), argument);
-    int i, found = 0;
     for (i = 0; i <= top_of_helpt; i++)  {
       if (help_table[i].min_level > GET_LEVEL(ch))
         continue;
@@ -1085,6 +1100,17 @@ ACMD(do_who)
   int showclass = 0, short_list = 0, outlaws = 0;
   int who_room = 0, showgroup = 0, showleader = 0;
 
+  struct {
+    char *disp;
+    int min_level;
+    int max_level;
+    int count; /* must always start as 0 */
+  } rank[] = {
+    { "Immortals\r\n---------\r\n", LVL_IMMORT, LVL_IMPL, 0},
+    { "Mortals\r\n-------\r\n", 1, LVL_IMMORT - 1, 0 },
+    { "\n", 0, 0, 0 }
+  };
+
   skip_spaces(&argument);
   strcpy(buf, argument);   /* strcpy: OK (sizeof: argument == buf) */
   name_search[0] = '\0';
@@ -1144,17 +1170,6 @@ ACMD(do_who)
     }
   }
 
-  struct {
-    char *disp;
-    int min_level;
-    int max_level;
-    int count; /* must always start as 0 */
-  } rank[] = {
-    { "Immortals\r\n---------\r\n", LVL_IMMORT, LVL_IMPL, 0},
-    { "Mortals\r\n-------\r\n", 1, LVL_IMMORT - 1, 0 },
-    { "\n", 0, 0, 0 }
-  };
-
   for (d = descriptor_list; d && !short_list; d = d->next) {
     if (d->original)
       tch = d->original;
@@ -1404,7 +1419,7 @@ ACMD(do_users)
 	continue;
       if (showclass && !(showclass & (1 << GET_CLASS(tch))))
 	continue;
-      if (GET_INVIS_LEV(ch) > GET_LEVEL(ch))
+      if (GET_INVIS_LEV(tch) > GET_LEVEL(ch))
 	continue;
 
       if (d->original)
@@ -1553,7 +1568,7 @@ void print_object_location(int num, stru
     send_to_char(ch, "%33s", " - ");
 
   if (obj->proto_script)
-    send_to_char(ch, "[TRIG]");
+    send_to_char(ch, "[T%d]", obj->proto_script->vnum);
 
   if (IN_ROOM(obj) != NOWHERE)
     send_to_char(ch, "[%5d] %s%s\r\n", GET_ROOM_VNUM(IN_ROOM(obj)), world[IN_ROOM(obj)].name, QNRM);
@@ -1594,9 +1609,11 @@ void perform_immort_where(struct char_da
     for (i = character_list; i; i = i->next)
       if (CAN_SEE(ch, i) && IN_ROOM(i) != NOWHERE && isname(arg, i->player.name)) {
 	found = 1;
-	send_to_char(ch, "M%3d. %-25s%s - [%5d] %-25s%s %s\r\n", ++num, GET_NAME(i), QNRM,
-		GET_ROOM_VNUM(IN_ROOM(i)), world[IN_ROOM(i)].name, QNRM,
-		(IS_NPC(i) && i->proto_script) ? "[TRIG]" : "");
+        send_to_char(ch, "M%3d. %-25s%s - [%5d] %-25s%s", ++num, GET_NAME(i), QNRM,
+               GET_ROOM_VNUM(IN_ROOM(i)), world[IN_ROOM(i)].name, QNRM);
+        if (SCRIPT(i))
+          send_to_char(ch, "[T%5d] ", i->proto_script->vnum);
+        send_to_char(ch, "%s\r\n", QNRM);
       }
     for (num = 0, k = object_list; k; k = k->next)
       if (CAN_SEE_OBJ(ch, k) && isname(arg, k->name)) {
@@ -1732,6 +1749,95 @@ ACMD(do_toggle)
   int toggle, tp, wimp_lev, result = 0, len = 0;
   const char *types[] = { "off", "brief", "normal", "on", "\n" };
 
+  const struct {
+    char *command;
+    bitvector_t toggle; /* this needs changing once hashmaps are implemented */
+    char min_level;
+    char *disable_msg;
+    char *enable_msg;
+  } tog_messages[] = {
+    {"summonable", PRF_SUMMONABLE, 0,
+    "You are now safe from summoning by other players.\r\n",
+    "You may now be summoned by other players.\r\n"},
+    {"nohassle", PRF_NOHASSLE, LVL_IMMORT,
+    "Nohassle disabled.\r\n",
+    "Nohassle enabled.\r\n"},
+    {"brief", PRF_BRIEF, 0,
+    "Brief mode off.\r\n",
+    "Brief mode on.\r\n"},
+    {"compact", PRF_COMPACT, 0,
+    "Compact mode off.\r\n",
+    "Compact mode on.\r\n"},
+    {"notell", PRF_NOTELL, 0,
+    "You can now hear tells.\r\n",
+    "You are now deaf to tells.\r\n"},
+    {"noauction", PRF_NOAUCT, 0,
+    "You can now hear auctions.\r\n",
+    "You are now deaf to auctions.\r\n"},
+    {"noshout", PRF_NOSHOUT, 0,
+    "You can now hear shouts.\r\n",
+    "You are now deaf to shouts.\r\n"},
+    {"nogossip", PRF_NOGOSS, 0,
+    "You can now hear gossip.\r\n",
+    "You are now deaf to gossip.\r\n"},
+    {"nograts", PRF_NOGRATZ, 0,
+    "You can now hear gratz.\r\n",
+    "You are now deaf to gratz.\r\n"},
+    {"nowiz", PRF_NOWIZ, LVL_IMMORT,
+    "You can now hear the Wiz-channel.\r\n",
+    "You are now deaf to the Wiz-channel.\r\n"},
+    {"quest", PRF_QUEST, 0,
+    "Okay, you are part of the Quest.\r\n",
+    "You are no longer part of the Quest.\r\n"},
+    {"showvnums", PRF_SHOWVNUMS, LVL_IMMORT,
+    "You will no longer see the vnums.\r\n",
+    "You will now see the vnums.\r\n"},
+    {"norepeat", PRF_NOREPEAT, 0,
+    "You will now have your communication repeated.\r\n",
+    "You will no longer have your communication repeated.\r\n"},
+    {"holylight", PRF_HOLYLIGHT, LVL_IMMORT,
+    "HolyLight mode off.\r\n",
+    "HolyLight mode on.\r\n"},
+    {"slownameserver", 0, LVL_IMPL,
+    "Nameserver_is_slow changed to OFF; IP addresses will now be resolved.\r\n",
+    "Nameserver_is_slow changed to ON; sitenames will no longer be resolved.\r\n"},
+    {"autoexits", PRF_AUTOEXIT, 0,
+    "Autoexits disabled.\r\n",
+    "Autoexits enabled.\r\n"},
+    {"trackthru", 0, LVL_IMPL,
+    "Players can no longer track through doors.\r\n",
+    "Players can now track through doors.\r\n"},
+    {"clsolc", PRF_CLS, LVL_BUILDER,
+    "You will no longer clear screen in OLC.\r\n",
+    "You will now clear screen in OLC.\r\n"},
+    {"buildwalk", PRF_BUILDWALK, LVL_BUILDER,
+    "Buildwalk is now Off.\r\n",
+    "Buildwalk is now On.\r\n"},
+    {"afk", PRF_AFK, 0,
+    "AFK is now Off.\r\n",
+    "AFK is now On.\r\n"},
+    {"color", 0, 0, "\n", "\n"},
+    {"syslog", 0, LVL_IMMORT, "\n", "\n"},
+    {"wimpy", 0, 0, "\n", "\n"},
+    {"pagelength", 0, 0, "\n", "\n"},
+    {"autoloot", PRF_AUTOLOOT, 0,
+    "Autoloot disabled.\r\n",
+    "Autoloot enabled.\r\n"},
+    {"autogold", PRF_AUTOGOLD, 0,
+    "Autogold disabled.\r\n",
+    "Autogold enabled.\r\n"},
+    {"autosplit", PRF_AUTOSPLIT, 0,
+    "Autosplit disabled.\r\n",
+    "Autosplit enabled.\r\n"},
+    {"autosac", PRF_AUTOSAC, 0,
+    "Autosac disabled.\r\n",
+    "Autosac enabled.\r\n"},
+    {"autoassist", PRF_AUTOASSIST, 0,
+    "Autoassist disabled.\r\n",
+    "Autoassist enabled.\r\n"},
+    {"\n", 0, -1, "\n", "\n"} /* must be last */
+  };
+
   if (IS_NPC(ch))
     return;
 
@@ -1838,95 +1944,6 @@ ACMD(do_toggle)
     return;
   }
 
-  const struct {
-    char *command;
-    bitvector_t toggle; /* this needs changing once hashmaps are implemented */
-    char min_level;
-    char *disable_msg;
-    char *enable_msg;
-  } tog_messages[] = {
-    {"summonable", PRF_SUMMONABLE, 0,
-    "You are now safe from summoning by other players.\r\n",
-    "You may now be summoned by other players.\r\n"},
-    {"nohassle", PRF_NOHASSLE, LVL_IMMORT,
-    "Nohassle disabled.\r\n",
-    "Nohassle enabled.\r\n"},
-    {"brief", PRF_BRIEF, 0,
-    "Brief mode off.\r\n",
-    "Brief mode on.\r\n"},
-    {"compact", PRF_COMPACT, 0,
-    "Compact mode off.\r\n",
-    "Compact mode on.\r\n"},
-    {"notell", PRF_NOTELL, 0,
-    "You can now hear tells.\r\n",
-    "You are now deaf to tells.\r\n"},
-    {"noauction", PRF_NOAUCT, 0,
-    "You can now hear auctions.\r\n",
-    "You are now deaf to auctions.\r\n"},
-    {"noshout", PRF_NOSHOUT, 0,
-    "You can now hear shouts.\r\n",
-    "You are now deaf to shouts.\r\n"},
-    {"nogossip", PRF_NOGOSS, 0,
-    "You can now hear gossip.\r\n",
-    "You are now deaf to gossip.\r\n"},
-    {"nograts", PRF_NOGRATZ, 0,
-    "You can now hear gratz.\r\n",
-    "You are now deaf to gratz.\r\n"},
-    {"nowiz", PRF_NOWIZ, LVL_IMMORT,
-    "You can now hear the Wiz-channel.\r\n",
-    "You are now deaf to the Wiz-channel.\r\n"},
-    {"quest", PRF_QUEST, 0,
-    "Okay, you are part of the Quest.\r\n",
-    "You are no longer part of the Quest.\r\n"},
-    {"showvnums", PRF_SHOWVNUMS, LVL_IMMORT,
-    "You will no longer see the vnums.\r\n",
-    "You will now see the vnums.\r\n"},
-    {"norepeat", PRF_NOREPEAT, 0,
-    "You will now have your communication repeated.\r\n",
-    "You will no longer have your communication repeated.\r\n"},
-    {"holylight", PRF_HOLYLIGHT, LVL_IMMORT,
-    "HolyLight mode off.\r\n",
-    "HolyLight mode on.\r\n"},
-    {"slownameserver", 0, LVL_IMPL,
-    "Nameserver_is_slow changed to OFF; IP addresses will now be resolved.\r\n",
-    "Nameserver_is_slow changed to ON; sitenames will no longer be resolved.\r\n"},
-    {"autoexits", PRF_AUTOEXIT, 0,
-    "Autoexits disabled.\r\n",
-    "Autoexits enabled.\r\n"},
-    {"trackthru", 0, LVL_IMPL,
-    "Players can no longer track through doors.\r\n",
-    "Players can now track through doors.\r\n"},
-    {"clsolc", PRF_CLS, LVL_BUILDER,
-    "You will no longer clear screen in OLC.\r\n",
-    "You will now clear screen in OLC.\r\n"},
-    {"buildwalk", PRF_BUILDWALK, LVL_BUILDER,
-    "Buildwalk is now Off.\r\n",
-    "Buildwalk is now On.\r\n"},
-    {"afk", PRF_AFK, 0,
-    "AFK is now Off.\r\n",
-    "AFK is now On.\r\n"},
-    {"color", 0, 0, "\n", "\n"},
-    {"syslog", 0, LVL_IMMORT, "\n", "\n"},
-    {"wimpy", 0, 0, "\n", "\n"},
-    {"pagelength", 0, 0, "\n", "\n"},
-    {"autoloot", PRF_AUTOLOOT, 0,
-    "Autoloot disabled.\r\n",
-    "Autoloot enabled.\r\n"},
-    {"autogold", PRF_AUTOGOLD, 0,
-    "Autogold disabled.\r\n",
-    "Autogold enabled.\r\n"},
-    {"autosplit", PRF_AUTOSPLIT, 0,
-    "Autosplit disabled.\r\n",
-    "Autosplit enabled.\r\n"},
-    {"autosac", PRF_AUTOSAC, 0,
-    "Autosac disabled.\r\n",
-    "Autosac enabled.\r\n"},
-    {"autoassist", PRF_AUTOASSIST, 0,
-    "Autoassist disabled.\r\n",
-    "Autoassist enabled.\r\n"},
-    {"\n", 0, -1, "\n", "\n"} /* must be last */
-  };
-
 	len = strlen(arg);
   for (toggle = 0; *tog_messages[toggle].command != '\n'; toggle++)
     if (!strncmp(arg, tog_messages[toggle].command, len))
@@ -1950,8 +1967,8 @@ ACMD(do_toggle)
     }
     REMOVE_BIT_AR(PRF_FLAGS(ch), PRF_COLOR_1);
     REMOVE_BIT_AR(PRF_FLAGS(ch), PRF_COLOR_2);
-    SET_BIT_AR(PRF_FLAGS(ch), (PRF_COLOR_1 * (tp & 1)));
-    SET_BIT_AR(PRF_FLAGS(ch), (PRF_COLOR_2 * (tp & 2) >> 1));
+    if (tp & 1) SET_BIT_AR(PRF_FLAGS(ch), PRF_COLOR_1);
+    if (tp & 2) SET_BIT_AR(PRF_FLAGS(ch), PRF_COLOR_2);
 
     send_to_char(ch, "Your %scolor%s is now %s.\r\n", CCRED(ch, C_SPR), CCNRM(ch, C_OFF), types[tp]);
     return;
@@ -1967,8 +1984,8 @@ ACMD(do_toggle)
     }
     REMOVE_BIT_AR(PRF_FLAGS(ch), PRF_LOG1);
     REMOVE_BIT_AR(PRF_FLAGS(ch), PRF_LOG2);
-    SET_BIT_AR(PRF_FLAGS(ch), (PRF_LOG1 * (tp & 1)));
-    SET_BIT_AR(PRF_FLAGS(ch), (PRF_LOG2 * (tp & 2) >> 1));
+    if (tp & 1) SET_BIT_AR(PRF_FLAGS(ch), PRF_LOG1);
+    if (tp & 2) SET_BIT_AR(PRF_FLAGS(ch), PRF_LOG2);
 
     send_to_char(ch, "Your syslog is now %s.\r\n", types[tp]);
     return;
@@ -2148,10 +2165,11 @@ void free_history(struct char_data *ch, 
 ACMD(do_history)
 {
   char arg[MAX_INPUT_LENGTH];
+  int type;
 
   one_argument(argument, arg);
 
-  int type = search_block(arg, history_types, FALSE);
+  type = search_block(arg, history_types, FALSE);
   if (!*arg || type < 0) {
     int i;
 
@@ -2183,12 +2201,14 @@ void add_history(struct char_data *ch, c
 {
   int i = 0;
   char time_str[MAX_STRING_LENGTH], buf[MAX_STRING_LENGTH];
+  struct txt_block *tmp;
+  time_t ct;
 
   if (IS_NPC(ch)) 
     return;
 
-  struct txt_block *tmp = GET_HISTORY(ch, type);
-  time_t ct = time(0);
+  tmp = GET_HISTORY(ch, type);
+  ct = time(0);
   strftime(time_str, sizeof(time_str), "%H:%M ", localtime(&ct));
 
   sprintf(buf, "%s%s", time_str, str);
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/act.item.c tbamud-3.54/src/act.item.c
--- tbamud-3.53/src/act.item.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/act.item.c	2007-11-29 03:02:08.000000000 +0100
@@ -825,9 +825,26 @@ ACMD(do_drink)
     return;
 
   if (!*arg) {
+    char buf[MAX_STRING_LENGTH];
+    switch (SECT(IN_ROOM(ch))) {
+      case SECT_WATER_SWIM:
+      case SECT_WATER_NOSWIM:
+      case SECT_UNDERWATER:
+        if ((GET_COND(ch, HUNGER) > 20) && (GET_COND(ch, THIRST) > 0)) {
+          send_to_char(ch, "Your stomach can't contain anymore!\r\n");
+        }
+        snprintf(buf, sizeof(buf), "$n takes a refreshing drink.");
+        act(buf, TRUE, ch, 0, 0, TO_ROOM);
+        send_to_char(ch, "You take a refreshing drink.\r\n");
+        gain_condition(ch, THIRST, 1);
+        if (GET_COND(ch, THIRST) > 20)
+          send_to_char(ch, "You don't feel thirsty any more.\r\n");
+        return;
+      default:
     send_to_char(ch, "Drink from what?\r\n");
     return;
   }
+  }
   if (!(temp = get_obj_in_list_vis(ch, arg, NULL, ch->carrying))) {
     if (!(temp = get_obj_in_list_vis(ch, arg, NULL, world[IN_ROOM(ch)].contents))) {
       send_to_char(ch, "You can't find it!\r\n");
@@ -854,8 +871,8 @@ ACMD(do_drink)
     send_to_char(ch, "Your stomach can't contain anymore!\r\n");
     return;
   }
-  if (!GET_OBJ_VAL(temp, 1)) {
-    send_to_char(ch, "It's empty.\r\n");
+  if ((GET_OBJ_VAL(temp, 1) == 0) && (!GET_OBJ_VAL(temp, 0) == 1)) {
+    send_to_char(ch, "It is empty.\r\n");
     return;
   }
 
@@ -1330,10 +1347,14 @@ ACMD(do_wear)
     for (obj = ch->carrying; obj; obj = next_obj) {
       next_obj = obj->next_content;
       if (CAN_SEE_OBJ(ch, obj) && (where = find_eq_pos(ch, obj, 0)) >= 0) {
+        if (GET_LEVEL(ch) < GET_OBJ_LEVEL(obj))
+          send_to_char(ch, "You are not experienced enough to use that.\r\n");
+        else {
 	items_worn++;
 	perform_wear(ch, obj, where);
       }
     }
+    }
     if (!items_worn)
       send_to_char(ch, "You don't seem to have anything wearable.\r\n");
   } else if (dotmode == FIND_ALLDOT) {
@@ -1357,6 +1378,8 @@ ACMD(do_wear)
   } else {
     if (!(obj = get_obj_in_list_vis(ch, arg1, NULL, ch->carrying)))
       send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg1), arg1);
+    else if (GET_LEVEL(ch) < GET_OBJ_LEVEL(obj))
+      send_to_char(ch, "You are not experienced enough to use that.\r\n");
     else {
       if ((where = find_eq_pos(ch, obj, arg2)) >= 0)
 	perform_wear(ch, obj, where);
@@ -1382,6 +1405,8 @@ ACMD(do_wield)
       send_to_char(ch, "You can't wield that.\r\n");
     else if (GET_OBJ_WEIGHT(obj) > str_app[STRENGTH_APPLY_INDEX(ch)].wield_w)
       send_to_char(ch, "It's too heavy for you to use.\r\n");
+    else if (GET_LEVEL(ch) < GET_OBJ_LEVEL(obj))
+      send_to_char(ch, "You are not experienced enough to use that.\r\n");
     else
       perform_wear(ch, obj, WEAR_WIELD);
   }
@@ -1398,6 +1423,8 @@ ACMD(do_grab)
     send_to_char(ch, "Hold what?\r\n");
   else if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying)))
     send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg), arg);
+  else if (GET_LEVEL(ch) < GET_OBJ_LEVEL(obj))
+    send_to_char(ch, "You are not experienced enough to use that.\r\n");
   else {
     if (GET_OBJ_TYPE(obj) == ITEM_LIGHT)
       perform_wear(ch, obj, WEAR_LIGHT);
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/act.movement.c tbamud-3.54/src/act.movement.c
--- tbamud-3.53/src/act.movement.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/act.movement.c	2007-11-29 03:02:08.000000000 +0100
@@ -509,6 +509,11 @@ ACMD(do_gen_door)
   if (!generic_find(type, FIND_OBJ_INV | FIND_OBJ_ROOM, ch, &victim, &obj))
     door = find_door(ch, type, dir, cmd_door[subcmd]);
 
+  if ((obj) && (GET_OBJ_TYPE(obj) != ITEM_CONTAINER)) {
+    obj = NULL;
+    door = find_door(ch, type, dir, cmd_door[subcmd]);
+  }
+
   if ((obj) || (door >= 0)) {
     keynum = DOOR_KEY(ch, obj, door);
     if (!(DOOR_IS_OPENABLE(ch, obj, door)))
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/act.offensive.c tbamud-3.54/src/act.offensive.c
--- tbamud-3.53/src/act.offensive.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/act.offensive.c	2007-11-29 03:02:08.000000000 +0100
@@ -105,7 +105,7 @@ ACMD(do_hit)
 	  check_killer(ch, vict);
 	}
       }
-      if (AFF_FLAGGED(ch, AFF_CHARM) && !IS_NPC(ch->master) && !IS_NPC(vict))
+      if (AFF_FLAGGED(ch, AFF_CHARM) && ch->master && !IS_NPC(ch->master) && vict && !IS_NPC(vict)) 
 	return;			/* you can't order a charmed pet to attack a
 				 * player */
     }
@@ -274,6 +274,10 @@ ACMD(do_flee)
 	  loss *= GET_LEVEL(was_fighting);
 	  gain_exp(ch, -loss);
 	}
+      if (FIGHTING(ch)) 
+        stop_fighting(ch); 
+      if (was_fighting && ch == FIGHTING(was_fighting))
+        stop_fighting(was_fighting); 
       } else {
 	act("$n tries to flee, but can't!", TRUE, ch, 0, 0, TO_ROOM);
       }
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/act.other.c tbamud-3.54/src/act.other.c
--- tbamud-3.53/src/act.other.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/act.other.c	2007-11-29 03:02:08.000000000 +0100
@@ -202,9 +202,8 @@ ACMD(do_steal)
   if (!AWAKE(vict))	/* Easier to steal from sleeping people. */
     percent -= 50;
 
-  /* NO NO With Imp's and Shopkeepers, and if player thieving is not allowed */
-  if (GET_LEVEL(vict) >= LVL_IMMORT || pcsteal ||
-      GET_MOB_SPEC(vict) == shop_keeper)
+  /* No stealing if not allowed. If it is no stealing from Imm's or Shopkeepers. */
+  if (GET_LEVEL(vict) >= LVL_IMMORT || pcsteal || GET_MOB_SPEC(vict) == shop_keeper)
     percent = 101;		/* Failure */
 
   if (str_cmp(obj_name, "coins") && str_cmp(obj_name, "gold")) {
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/act.social.c tbamud-3.54/src/act.social.c
--- tbamud-3.53/src/act.social.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/act.social.c	2007-11-29 03:02:08.000000000 +0100
@@ -85,7 +85,7 @@ ACMD(do_action)
     if (action->char_auto)
       send_to_char(ch, "%s\r\n", action->char_auto);
     else
-      send_to_char(ch, "Erm, no.");
+      send_to_char(ch, "Erm, no.\r\n");
     act(action->others_auto, action->hide, ch, 0, 0, TO_ROOM);
     return;
   }
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/act.wizard.c tbamud-3.54/src/act.wizard.c
--- tbamud-3.53/src/act.wizard.c	2007-07-02 16:01:58.000000000 +0200
+++ tbamud-3.54/src/act.wizard.c	2007-11-29 03:05:47.000000000 +0100
@@ -1302,12 +1302,13 @@ ACMD(do_return)
 
 ACMD(do_load)
 {
-  char buf[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH];
+  char buf[MAX_INPUT_LENGTH], buf2[MAX_INPUT_LENGTH], buf3[MAX_INPUT_LENGTH];
+  int i=0, n=1;
 
-  two_arguments(argument, buf, buf2);
+  one_argument(two_arguments(argument, buf, buf2), buf3);
 
   if (!*buf || !*buf2 || !isdigit(*buf2)) {
-    send_to_char(ch, "Usage: load { obj | mob } <number>\r\n");
+    send_to_char(ch, "Usage: load < obj | mob > <vnum> <number>\r\n");
     return;
   }
   if (!is_number(buf2)) {
@@ -1315,22 +1316,29 @@ ACMD(do_load)
     return;
   }
 
+  if (atoi(buf3) > 0  && atoi(buf3) <= 100) {
+    n = atoi(buf3);
+  } else {
+    n = 1;
+  }
+
   if (is_abbrev(buf, "mob")) {
-    struct char_data *mob;
+    struct char_data *mob=NULL;
     mob_rnum r_num;
 
     if ((r_num = real_mobile(atoi(buf2))) == NOBODY) {
       send_to_char(ch, "There is no monster with that number.\r\n");
       return;
     }
+    for (i=0; i < n; i++) {
     mob = read_mobile(r_num, REAL);
     char_to_room(mob, IN_ROOM(ch));
 
-    act("$n makes a quaint, magical gesture with one hand.", TRUE, ch,
-	0, 0, TO_ROOM);
+      act("$n makes a quaint, magical gesture with one hand.", TRUE, ch, 0, 0, TO_ROOM);
     act("$n has created $N!", FALSE, ch, 0, mob, TO_ROOM);
     act("You create $N.", FALSE, ch, 0, mob, TO_CHAR);
     load_mtrigger(mob);
+    }
   } else if (is_abbrev(buf, "obj")) {
     struct obj_data *obj;
     obj_rnum r_num;
@@ -1339,6 +1347,7 @@ ACMD(do_load)
       send_to_char(ch, "There is no object with that number.\r\n");
       return;
     }
+    for (i=0; i < n; i++) {
     obj = read_object(r_num, REAL);
     if (CONFIG_LOAD_INVENTORY)
       obj_to_char(obj, ch);
@@ -1348,6 +1357,7 @@ ACMD(do_load)
     act("$n has created $p!", FALSE, ch, obj, 0, TO_ROOM);
     act("You create $p.", FALSE, ch, obj, 0, TO_CHAR);
     load_otrigger(obj);
+    }
   } else
     send_to_char(ch, "That'll have to be either 'obj' or 'mob'.\r\n");
 }
@@ -1506,8 +1516,14 @@ ACMD(do_advance)
     GET_LEVEL(victim) = newlevel;
     send_to_char(victim, "You are momentarily enveloped by darkness!\r\nYou feel somewhat diminished.\r\n");
   } else {
-    act("$n advances you.\r\n" , FALSE, ch, 0, victim, TO_VICT);
-  }
+    act("$n makes some strange gestures. A strange feeling comes upon you,\r\n"
+      "Like a giant hand, light comes down from above, grabbing your body,\r\n"
+      "that begins to pulse with colored lights from inside.\r\n\r\n" 
+      "Your head seems to be filled with demons from another plane as your\r\n"
+      "your body dissolves to the elements of time and space itself.\r\n" 
+      "Suddenly a silent explosion of light snaps you back to reality.\r\n\r\n"
+      "You feel slightly different.", FALSE, ch, 0, victim, TO_VICT); 
+}
 
   send_to_char(ch, "%s", CONFIG_OK);
 
@@ -3018,6 +3034,10 @@ int perform_set(struct char_data *ch, st
     case 38: /* poofin */
       if ((vict == ch) || (GET_LEVEL(ch) == LVL_IMPL)) {
         skip_spaces(&val_arg);
+
+        if (POOFIN(vict)) 
+          free(POOFIN(vict)); 
+
         if (!*val_arg)
           POOFIN(vict) = NULL;
         else
@@ -3027,6 +3047,10 @@ int perform_set(struct char_data *ch, st
     case 39: /* poofout */
       if ((vict == ch) || (GET_LEVEL(ch) == LVL_IMPL)) {
         skip_spaces(&val_arg);
+
+        if (POOFOUT(vict)) 
+          free(POOFOUT(vict)); 
+	
         if (!*val_arg)
           POOFOUT(vict) = NULL;
         else
@@ -4120,7 +4144,7 @@ ACMD(do_file)
    }
    
    if(!*value)
-     req_lines = 15; /* Default is the last 30 lines. */
+     req_lines = 15; /* Default is the last 15 lines. */
    else
      req_lines = atoi(value);
 
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/alias.c tbamud-3.54/src/alias.c
--- tbamud-3.53/src/alias.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/alias.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,191 +0,0 @@
-/*************************************************************************
-* File: alias.c	                                          Part of tbaMUD *
-* Usage: Writing/reading player's aliases.				 *
-*									 *
-* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
-* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.		 *
-* by Jeremy Hess, Chad Thompson, and George Greer                        *
-**************************************************************************/
-
-#include "conf.h"
-#include "sysdep.h"
-#include "structs.h"
-#include "utils.h"
-#include "interpreter.h"
-#include "db.h"
-
-void write_aliases(struct char_data *ch);
-void read_aliases(struct char_data *ch);
-void delete_aliases(const char *charname);
-
-void write_aliases(struct char_data *ch)
-{
-  FILE *file;
-  char fn[MAX_STRING_LENGTH];
-  struct alias_data *temp;
-
-  get_filename(fn, sizeof(fn), ALIAS_FILE, GET_NAME(ch));
-  remove(fn);
-
-  if (GET_ALIASES(ch) == NULL)
-    return;
-
-  if ((file = fopen(fn, "w")) == NULL) {
-    log("SYSERR: Couldn't save aliases for %s in '%s': %s", GET_NAME(ch), fn, strerror(errno));
-    /* SYSERR_DESC: This error occurs when the server fails to open the relevant
-     * alias file for writing.  The text at the end of the error should give a
-     * valid reason why. */
-    return;
-  }
-
-  for (temp = GET_ALIASES(ch); temp; temp = temp->next) {
-    int aliaslen = strlen(temp->alias);
-    int repllen = strlen(temp->replacement) - 1;
-
-    fprintf(file, "%d\n%s\n"	/* Alias */
-		  "%d\n%s\n"	/* Replacement */
-		  "%d\n",	/* Type */
-		aliaslen, temp->alias,
-		repllen, temp->replacement + 1,
-		temp->type);
-  }
-
-  fclose(file);
-}
-
-void read_aliases(struct char_data *ch)
-{
-  FILE *file;
-  char xbuf[MAX_STRING_LENGTH];
-  struct alias_data *t2, *prev = NULL;
-  int length;
-
-  get_filename(xbuf, sizeof(xbuf), ALIAS_FILE, GET_NAME(ch));
-
-  if ((file = fopen(xbuf, "r")) == NULL) {
-    if (errno != ENOENT) {
-      log("SYSERR: Couldn't open alias file '%s' for %s: %s", xbuf, GET_NAME(ch), strerror(errno));
-      /* SYSERR_DESC: This error occurs when the server fails to open the 
-       * relevant alias file for reading.  The text at the end version should 
-       * give a valid reason why. */
-    }
-    return;
-  }
-
-  CREATE(GET_ALIASES(ch), struct alias_data, 1);
-  t2 = GET_ALIASES(ch);
-
-  for (;;) {
-    /* Read the aliased command. */
-    if (fscanf(file, "%d\n", &length) != 1)
-      goto read_alias_error;
-
-    fgets(xbuf, length + 1, file);
-    t2->alias = strdup(xbuf);
-
-    /* Build the replacement. */
-    if (fscanf(file, "%d\n", &length) != 1)
-       goto read_alias_error;
-
-    *xbuf = ' ';		/* Doesn't need terminated, fgets() will. */
-    fgets(xbuf + 1, length + 1, file);
-    t2->replacement = strdup(xbuf);
-
-    /* Figure out the alias type. */
-    if (fscanf(file, "%d\n", &length) != 1)
-      goto read_alias_error;
-
-    t2->type = length;
-
-    if (feof(file))
-      break;
-
-    CREATE(t2->next, struct alias_data, 1);
-    prev = t2;
-    t2 = t2->next;
-  };
-
-  fclose(file);
-  return;
-
-read_alias_error:
-  if (t2->alias)
-    free(t2->alias);
-  free(t2);
-  if (prev)
-    prev->next = NULL;
-  fclose(file);
-}
-
-void delete_aliases(const char *charname)
-{
-  char filename[PATH_MAX];
-
-  if (!get_filename(filename, sizeof(filename), ALIAS_FILE, charname))
-    return;
-
-  if (remove(filename) < 0 && errno != ENOENT)
-    log("SYSERR: deleting alias file %s: %s", filename, strerror(errno));
-    /* SYSERR_DESC: When an alias file cannot be removed, this error will occur,
-     * and the reason why will be the tail end of the error. */
-}
-
-/* until further notice, the alias->pfiles save and load functions will 
- * function along side the old seperate alias file load, for compatibility. */
-void write_aliases_ascii(FILE *file, struct char_data *ch)
-{
-  struct alias_data *temp;
-  int count = 0;
-
-  if (GET_ALIASES(ch) == NULL)
-    return;
-
-  for (temp = GET_ALIASES(ch); temp; temp = temp->next)
-    count++;
-
-  fprintf(file, "Alis: %d\n", count);
-  /* the +1 thing below is due to alias replacements having a space prepended 
-   * in memory. The reason for this escapes me. Welcor 27/12/06 */
-  for (temp = GET_ALIASES(ch); temp; temp = temp->next) {
-    fprintf(file, "%s\n"	/* Alias */
-		  "%s\n"	/* Replacement */
-		  "%d\n",	/* Type */
-		temp->alias,
-		temp->replacement+1,
-		temp->type);
-  }
-}
-
-void read_aliases_ascii(FILE *file, struct char_data *ch, int count)
-{
-  int i;
-  struct alias_data *temp;
-  char abuf[MAX_INPUT_LENGTH], rbuf[MAX_INPUT_LENGTH+1], tbuf[MAX_INPUT_LENGTH];
-
-  if (count == 0) {
-    GET_ALIASES(ch) = NULL;
-    return; /* No aliases in the list. */
-  }
-
-  for (i = 0; i < count; i++) {
-    /* Read the aliased command. */
-    get_line(file, abuf);
-
-    /* Read the replacement. */
-    get_line(file, tbuf);
-    strcpy(rbuf, " ");
-    strcat(rbuf, tbuf); /* strcat: OK */
-
-    /* read the type */
-    get_line(file, tbuf);
-
-    if (abuf && *abuf && tbuf && *tbuf && rbuf && *rbuf) {
-      CREATE(temp, struct alias_data, 1);
-      temp->alias = strdup(abuf);
-      temp->replacement = strdup(rbuf);
-      temp->type = atoi(tbuf);
-      temp->next = GET_ALIASES(ch);
-      GET_ALIASES(ch) = temp;
-    }
-  }
-}
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/boards.h tbamud-3.54/src/boards.h
--- tbamud-3.53/src/boards.h	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/boards.h	2007-11-29 03:02:08.000000000 +0100
@@ -8,7 +8,7 @@
 *  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
 **************************************************************************/
 
-#define NUM_OF_BOARDS		10	/* change if needed! */
+#define NUM_OF_BOARDS		7	/* change if needed! */
 #define MAX_BOARD_MESSAGES 	60      /* arbitrary -- change if needed */
 #define MAX_MESSAGE_LENGTH	4096	/* arbitrary -- change if needed */
 
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/cedit.c tbamud-3.54/src/cedit.c
--- tbamud-3.53/src/cedit.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/cedit.c	2007-11-29 03:02:08.000000000 +0100
@@ -102,6 +102,7 @@ void cedit_setup(struct descriptor_data 
   OLC_CONFIG(d)->play.load_into_inventory = CONFIG_LOAD_INVENTORY;
   OLC_CONFIG(d)->play.track_through_doors = CONFIG_TRACK_T_DOORS;
   OLC_CONFIG(d)->play.no_mort_to_immort   = CONFIG_NO_MORT_TO_IMMORT;
+  OLC_CONFIG(d)->play.disp_closed_doors   = CONFIG_DISP_CLOSED_DOORS;
 
   /* Crash Saves */
   OLC_CONFIG(d)->csd.free_rent            = CONFIG_FREE_RENT;
@@ -194,6 +195,7 @@ void cedit_save_internally(struct descri
   CONFIG_LOAD_INVENTORY = OLC_CONFIG(d)->play.load_into_inventory;
   CONFIG_TRACK_T_DOORS = OLC_CONFIG(d)->play.track_through_doors;
   CONFIG_NO_MORT_TO_IMMORT   = OLC_CONFIG(d)->play.no_mort_to_immort;
+  CONFIG_DISP_CLOSED_DOORS   = OLC_CONFIG(d)->play.disp_closed_doors;
 
   /* Crash Saves */
   CONFIG_FREE_RENT            = OLC_CONFIG(d)->csd.free_rent;
@@ -350,6 +352,8 @@ int save_config( IDXTYPE nowhere )
               "track_through_doors = %d\n\n", CONFIG_TRACK_T_DOORS);
   fprintf(fl, "* Should players who reach enough exp automatically level to immortal?\n"
               "no_mort_to_immort = %d\n\n", CONFIG_NO_MORT_TO_IMMORT);
+  fprintf(fl, "* Should closed doors be shown on autoexit / exit?\n"
+              "disp_closed_doors = %d\n\n", CONFIG_DISP_CLOSED_DOORS);
 
   strcpy(buf, CONFIG_OK);
   strip_cr(buf);
@@ -568,7 +572,8 @@ void cedit_disp_game_play_options(struct
         "%sM%s) Death Traps Junk Items      : %s%s\r\n"
         "%sN%s) Objects Load Into Inventory : %s%s\r\n"
         "%sO%s) Track Through Doors         : %s%s\r\n"
-        "%sP%s) Mortals Level To Immortal   : %s%s\r\n"
+        "%sP%s) Display Closed Doors        : %s%s\r\n"
+        "%sR%s) Mortals Level To Immortal   : %s%s\r\n"
         "%s1%s) OK Message Text         : %s%s"
         "%s2%s) NOPERSON Message Text   : %s%s"
         "%s3%s) NOEFFECT Message Text   : %s%s"
@@ -590,6 +595,7 @@ void cedit_disp_game_play_options(struct
         grn, nrm, cyn, CHECK_VAR(OLC_CONFIG(d)->play.dts_are_dumps),
         grn, nrm, cyn, CHECK_VAR(OLC_CONFIG(d)->play.load_into_inventory),
         grn, nrm, cyn, CHECK_VAR(OLC_CONFIG(d)->play.track_through_doors),
+        grn, nrm, cyn, CHECK_VAR(OLC_CONFIG(d)->play.disp_closed_doors),
         grn, nrm, cyn, CHECK_VAR(OLC_CONFIG(d)->play.no_mort_to_immort),
 
         grn, nrm, cyn, OLC_CONFIG(d)->play.OK,
@@ -881,6 +887,11 @@ void cedit_parse(struct descriptor_data 
 
         case 'p':
         case 'P':
+          TOGGLE_VAR(OLC_CONFIG(d)->play.disp_closed_doors);
+          break;
+
+        case 'r':
+        case 'R':
           TOGGLE_VAR(OLC_CONFIG(d)->play.no_mort_to_immort);
           break;
 
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/comm.c tbamud-3.54/src/comm.c
--- tbamud-3.53/src/comm.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/comm.c	2007-11-29 03:02:08.000000000 +0100
@@ -109,6 +109,7 @@ static bool fCopyOver;          /* Are w
 ush_int port;
 socket_t mother_desc;
 int log_this_messg;
+char *last_act_message = NULL;
 
 /* local functions */
 RETSIGTYPE reread_wizlists(int sig);
@@ -172,6 +173,7 @@ void board_clear_all(void);
 void free_social_messages(void);
 void free_invalid_list(void);
 void free_command_list(void);
+void free_save_list(void);
 void load_config(void);
 void new_hist_messg(struct descriptor_data *d, const char *msg);
 #ifdef __CXREF__
@@ -210,6 +212,10 @@ int main(int argc, char **argv)
   int pos = 1;
   const char *dir;
 
+#ifdef MEMORY_DEBUG 
+  zmalloc_init(); 
+#endif
+
 #if CIRCLE_GNU_LIBC_MEMORY_TRACK
   mtrace();	/* This must come before any use of malloc(). */
 #endif
@@ -339,7 +345,7 @@ int main(int argc, char **argv)
 
   /* Moved here to distinguish command line options and to show up
    * in the log if stderr is redirected to a file. */
-  log("Using %s for configuration.", CONFIG_CONFFILE);
+  log("Loading configuration.");
   log("%s", tbamud_version);
   log("%s", oasisolc_version);
   log("%s", DG_SCRIPT_VERSION);
@@ -373,9 +379,13 @@ int main(int argc, char **argv)
     free_social_messages();	/* act.social.c */
     free_help_table();		/* db.c */
     free_invalid_list();	/* ban.c */
+    free_save_list();		/* genolc.c */
     free_strings(&config_info, OASIS_CFG); /* oasis_delete.c */
   }
 
+  if (last_act_message) 
+    free(last_act_message);
+
   /* probably should free the entire config here.. */
   free(CONFIG_CONFFILE);
 
@@ -2402,7 +2412,7 @@ const char *ACTNULL = "<NULL>";
 #define CHECK_NULL(pointer, expression) \
   if ((pointer) == NULL) i = ACTNULL; else i = (expression);
 /* higher-level communication: the act() function */
-char *perform_act(const char *orig, struct char_data *ch, struct obj_data *obj,
+void perform_act(const char *orig, struct char_data *ch, struct obj_data *obj,
 		const void *vict_obj, const struct char_data *to)
 {
   const char *i = NULL;
@@ -2525,13 +2535,14 @@ char *perform_act(const char *orig, stru
   if ((IS_NPC(to) && dg_act_check) && (to != ch))
     act_mtrigger(to, lbuf, ch, dg_victim, obj, dg_target, dg_arg);
 
-  return strdup(lbuf);
+  if (last_act_message) 
+    free(last_act_message); 
+  last_act_message = strdup(lbuf); 
 }
 
 char *act(const char *str, int hide_invisible, struct char_data *ch,
 	 struct obj_data *obj, const void *vict_obj, int type)
 {
-  char *msg = NULL;
   const struct char_data *to;
   int to_sleeping;
 
@@ -2556,14 +2567,18 @@ char *act(const char *str, int hide_invi
     REMOVE_BIT(type, DG_NO_TRIG);
 
   if (type == TO_CHAR) {
-    if (ch && SENDOK(ch))
-      return perform_act(str, ch, obj, vict_obj, ch);
+    if (ch && SENDOK(ch)) { 
+      perform_act(str, ch, obj, vict_obj, ch); 
+      return last_act_message; 
+    }
     return NULL;
   }
 
   if (type == TO_VICT) {
-    if ((to = (const struct char_data *) vict_obj) != NULL && SENDOK(to))
-      return perform_act(str, ch, obj, vict_obj, to);
+    if ((to = (const struct char_data *) vict_obj) != NULL && SENDOK(to)) { 
+      perform_act(str, ch, obj, vict_obj, to); 
+      return last_act_message; 
+    }
     return NULL;
   }
 
@@ -2579,10 +2594,10 @@ char *act(const char *str, int hide_invi
           !ROOM_FLAGGED(IN_ROOM(i->character), ROOM_SOUNDPROOF)) {
 
         sprintf(buf, "%s%s%s", CCYEL(i->character, C_NRM), str, CCNRM(i->character, C_NRM));
-        msg = perform_act(buf, ch, obj, vict_obj, i->character);
+        perform_act(buf, ch, obj, vict_obj, i->character); 
       }
     }
-    return msg;
+    return last_act_message;
   }
   /* ASSUMPTION: at this point we know type must be TO_NOTVICT or TO_ROOM */
 
@@ -2602,9 +2617,9 @@ char *act(const char *str, int hide_invi
       continue;
     if (type != TO_ROOM && to == vict_obj)
       continue;
-    msg = perform_act(str, ch, obj, vict_obj, to);
+    perform_act(str, ch, obj, vict_obj, to); 
   }
-  return msg;
+  return last_act_message;
 }
 
 /* Prefer the file over the descriptor. */
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/comm.h tbamud-3.54/src/comm.h
--- tbamud-3.53/src/comm.h	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/comm.h	2007-11-29 03:02:08.000000000 +0100
@@ -24,7 +24,7 @@ void send_to_range(room_vnum start, room
     __attribute__ ((format (printf, 3, 4)));
 
 void close_socket(struct descriptor_data *d);
-char * perform_act(const char *orig, struct char_data *ch, struct obj_data *obj, const void *vict_obj, const struct char_data *to);
+void perform_act(const char *orig, struct char_data *ch, struct obj_data *obj, const void *vict_obj, const struct char_data *to); 
 char * act(const char *str, int hide_invisible, struct char_data *ch, struct obj_data *obj, const void *vict_obj, int type);
 
 #define TO_ROOM		1
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/config.c tbamud-3.54/src/config.c
--- tbamud-3.53/src/config.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/config.c	2007-11-29 03:02:08.000000000 +0100
@@ -298,3 +298,7 @@ int use_autowiz = YES;
 /* If yes, what is the lowest level which should be on the wizlist?  (All immort
  * levels below the level you specify will go on the immlist instead.) */
 int min_wizlist_lev = LVL_GOD;
+
+/* To mimic stack behavior set to NO. To allow mortals to see doors in exits
+ * set to YES. */
+int display_closed_doors = YES;
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/constants.c tbamud-3.54/src/constants.c
--- tbamud-3.53/src/constants.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/constants.c	2007-11-29 03:02:08.000000000 +0100
@@ -13,7 +13,7 @@
 #include "structs.h"
 #include "interpreter.h"	/* alias_data */
 
-cpp_extern const char *tbamud_version = "tbaMUD, version 3.53";
+cpp_extern const char *tbamud_version = "tbaMUD, version 3.54";
 cpp_extern const char *oasisolc_version = "OasisOLC 2.0.6";
 cpp_extern const char *ascii_pfiles_version = "ASCII Player Files 3.0.1";
 
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/db.c tbamud-3.54/src/db.c
--- tbamud-3.53/src/db.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/db.c	2007-11-29 03:02:08.000000000 +0100
@@ -169,6 +169,7 @@ extern int bitsavetodisk;
 extern struct player_index_element *player_table;
 extern int top_of_p_table;
 extern long top_idnum;
+extern int display_closed_doors;
 
 /* external ASCII Player Files vars */
 extern int auto_pwipe;
@@ -1192,6 +1193,9 @@ void parse_room(FILE *fl, int virtual_nr
     world[room_nr].room_flags[2] = 0;
     world[room_nr].room_flags[3] = 0;
 
+    /* In the old-style files, the 3rd item was the sector-type */ 
+    world[room_nr].sector_type = atoi(flags2); 
+   
     sprintf(flags, "room #%d", virtual_nr);	/* sprintf: OK (until 399-bit integers) */
 
     /* No need to scan the other three sections; they're 0 anyway. */
@@ -1214,13 +1218,16 @@ void parse_room(FILE *fl, int virtual_nr
     sprintf(flags, "object #%d", virtual_nr);	/* sprintf: OK (until 399-bit integers) */
     for(taeller=0; taeller < AF_ARRAY_MAX; taeller++) 
       check_bitvector_names(world[room_nr].room_flags[taeller], room_bits_count, flags, "room");
+
+    /* Added Sanity check */ 
+    if (t[2] > NUM_ROOM_SECTORS) t[2] = SECT_INSIDE; 
+
+    world[room_nr].sector_type = t[2];
   } else {
     log("SYSERR: Format error in roomflags/sector type of room #%d", virtual_nr);
     exit(1);
   }
 
-  world[room_nr].sector_type = t[2];
-
   world[room_nr].func = NULL;
   world[room_nr].contents = NULL;
   world[room_nr].people = NULL;
@@ -2080,7 +2087,8 @@ void get_one_line(FILE *fl, char *buf)
   buf[strlen(buf) - 1] = '\0'; /* take off the trailing \n */
 }
 
-void free_help(struct help_index_element *help) {
+void free_help(struct help_index_element *help) 
+{
   if (help->keywords)
     free(help->keywords);
   if (help->entry && !help->duplicate)
@@ -2093,7 +2101,7 @@ void free_help_table(void)
 {
   if (help_table) {
     int hp;
-    for (hp = 0; hp <= top_of_helpt; hp++) {
+    for (hp = 0; hp < top_of_helpt; hp++) {
       if (help_table[hp].keywords)
         free(help_table[hp].keywords);
       if (help_table[hp].entry && !help_table[hp].duplicate)
@@ -2756,13 +2764,13 @@ void free_char(struct char_data *ch)
       free(ch->player.long_descr);
     if (ch->player.description)
       free(ch->player.description);
-    if (ch->player_specials)
-      free(ch->player_specials); 
-
     for (i = 0; i < NUM_HIST; i++)
       if (GET_HISTORY(ch, i))
         free(GET_HISTORY(ch, i));
   
+    if (ch->player_specials) 
+      free(ch->player_specials);
+
     /* free script proto list */
     free_proto_script(ch, MOB_TRIGGER);
 
@@ -3046,21 +3054,21 @@ room_rnum real_room(room_vnum vnum)
   bot = 0;
   top = top_of_world;
 
+  if (world[bot].number > vnum || world[top].number < vnum)
+    return (NOWHERE);
+
   /* perform binary search on world-table */
-  for (;;) {
+  while (bot<= top) {
     mid = (bot + top) / 2;
 
     if ((world + mid)->number == vnum)
       return (mid);
-    if (bot > top)
-      return (NOWHERE);
-    if (top == 0)
-      return (NOWHERE);
     if ((world + mid)->number > vnum)
       top = mid - 1;
     else
       bot = mid + 1;
   }
+  return (NOWHERE);
 }
 
 /* returns the real number of the monster with given virtual number */
@@ -3071,21 +3079,22 @@ mob_rnum real_mobile(mob_vnum vnum)
   bot = 0;
   top = top_of_mobt;
 
+  /* quickly reject out-of-range vnums */ 
+  if (mob_index[bot].vnum > vnum || mob_index[top].vnum < vnum) 
+    return (NOBODY); 
+  
   /* perform binary search on mob-table */
-  for (;;) {
+  while (bot <= top) {
     mid = (bot + top) / 2;
 
     if ((mob_index + mid)->vnum == vnum)
       return (mid);
-    if (bot > top)
-      return (NOBODY);
-    if (top == 0)
-      return (NOBODY);
     if ((mob_index + mid)->vnum > vnum)
       top = mid - 1;
     else
       bot = mid + 1;
   }
+  return (NOBODY);
 }
 
 /* returns the real number of the object with given virtual number */
@@ -3096,21 +3105,22 @@ obj_rnum real_object(obj_vnum vnum)
   bot = 0;
   top = top_of_objt;
 
+  /* quickly reject out-of-range vnums */ 
+  if (obj_index[bot].vnum > vnum || obj_index[top].vnum < vnum) 
+    return (NOTHING); 
+
   /* perform binary search on obj-table */
-  for (;;) {
+  while (bot <= top) {
     mid = (bot + top) / 2;
 
     if ((obj_index + mid)->vnum == vnum)
       return (mid);
-    if (bot > top)
-      return (NOTHING);
-    if (top == 0)
-      return (NOTHING);
     if ((obj_index + mid)->vnum > vnum)
       top = mid - 1;
     else
       bot = mid + 1;
   }
+  return (NOTHING);
 }
 
 /* returns the real number of the zone with given virtual number */
@@ -3121,21 +3131,21 @@ zone_rnum real_zone(zone_vnum vnum)
   bot = 0;
   top = top_of_zone_table;
 
+  if (zone_table[bot].number > vnum || zone_table[top].number < vnum)
+    return (NOWHERE);
+  
   /* perform binary search on zone-table */
-  for (;;) {
+  while (bot <= top) {
     mid = (bot + top) / 2;
 
     if ((zone_table + mid)->number == vnum)
       return (mid);
-    if (bot > top)
-      return (NOWHERE);
-    if (top == 0)
-      return (NOWHERE);
     if ((zone_table + mid)->number > vnum)
       top = mid - 1;
     else
       bot = mid + 1;
   }
+  return (NOWHERE);
 }
 
 /* Extend later to include more checks and add checks for unknown bitvectors. */
@@ -3223,7 +3233,7 @@ int check_object_spell_number(struct obj
   int error = FALSE;
   const char *spellname;
 
-  if (GET_OBJ_VAL(obj, val) == -1)	/* i.e.: no spell */
+  if (GET_OBJ_VAL(obj, val) == -1 || GET_OBJ_VAL(obj, val) == 0) /* no spell */
     return (error);
 
   /* Check for negative spells, spells beyond the top define, and any spell 
@@ -3355,6 +3365,7 @@ void load_default_config( void )
   CONFIG_NOEFFECT		= strdup(NOEFFECT);
   CONFIG_TRACK_T_DOORS          = track_through_doors;
   CONFIG_NO_MORT_TO_IMMORT	= no_mort_to_immort;
+  CONFIG_DISP_CLOSED_DOORS      = display_closed_doors;
 
   /* Rent / crashsave options. */
   CONFIG_FREE_RENT              = free_rent;
@@ -3442,7 +3453,9 @@ void load_config( void )
         break;
 
       case 'd':
-        if (!str_cmp(tag, "dts_are_dumps"))
+        if (!str_cmp(tag, "display_closed_doors"))
+          CONFIG_DISP_CLOSED_DOORS = num;
+        else if (!str_cmp(tag, "dts_are_dumps"))
           CONFIG_DTS_ARE_DUMPS = num;
         else if (!str_cmp(tag, "donation_room_1"))
           if (num == -1)
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/db.h tbamud-3.54/src/db.h
--- tbamud-3.53/src/db.h	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/db.h	2007-11-29 03:02:08.000000000 +0100
@@ -26,7 +26,6 @@
 #define LIB_PLRTEXT	":plrtext:"
 #define LIB_PLROBJS	":plrobjs:"
 #define LIB_PLRVARS	":plrvars:"
-#define LIB_PLRALIAS	":plralias:"
 #define LIB_PLRFILES	":plrfiles:"
 #define LIB_HOUSE	":house:"
 #define SLASH		":"
@@ -39,7 +38,6 @@
 #define LIB_PLRTEXT	"plrtext/"
 #define LIB_PLROBJS	"plrobjs/"
 #define LIB_PLRVARS	"plrvars/"
-#define LIB_PLRALIAS	"plralias/"
 #define LIB_HOUSE	"house/"
 #define LIB_PLRFILES    "plrfiles/"
 #define SLASH		"/"
@@ -49,7 +47,6 @@
 
 #define SUF_OBJS	"objs"
 #define SUF_TEXT	"text"
-#define SUF_ALIAS	"alias"
 #define SUF_MEM	        "mem"
 #define SUF_PLR		"plr"
 
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/dg_event.c tbamud-3.54/src/dg_event.c
--- tbamud-3.53/src/dg_event.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/dg_event.c	2007-11-29 03:02:08.000000000 +0100
@@ -99,14 +99,6 @@ long event_time(struct event *event)
 /* frees all events in the queue */
 void event_free_all(void)
 {
-  struct event *the_event;
-
-  while ((the_event = (struct event *) queue_head(event_q))) {
-    if (the_event->event_obj)
-      free(the_event->event_obj);
-    free(the_event);
-  }
-
   queue_free(event_q);
 }
 
@@ -237,13 +229,19 @@ void queue_free(struct queue *q)
 {
   int i;
   struct q_element *qe, *next_qe;
+  struct event *event;
 
   for (i = 0; i < NUM_EVENT_QUEUES; i++)
     for (qe = q->head[i]; qe; qe = next_qe) {
       next_qe = qe->next;
+      if ((event = (struct event *) qe->data) != NULL) {
+	if (event->event_obj)
+	  free(event->event_obj);
+	free(event);
+      }
       free(qe);
     }
 
   free(q);
- }
+}
 
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/dg_misc.c tbamud-3.54/src/dg_misc.c
--- tbamud-3.53/src/dg_misc.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/dg_misc.c	2007-11-29 03:02:08.000000000 +0100
@@ -230,7 +230,7 @@ void do_dg_affect(void *go, struct scrip
 
   /* add the affect */
   af.type = SPELL_DG_AFFECT;
-  af.duration = duration;
+  af.duration = duration -1;
   af.modifier = value;
 
   if (type == APPLY_TYPE) {
@@ -238,7 +238,7 @@ void do_dg_affect(void *go, struct scrip
     af.bitvector = 0;
   } else {
     af.location = 0;
-    af.bitvector = (1<<i);
+    af.bitvector = (i);
   }
 
   affect_to_char(ch, &af);
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/dg_olc.c tbamud-3.54/src/dg_olc.c
--- tbamud-3.53/src/dg_olc.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/dg_olc.c	2007-11-29 03:02:08.000000000 +0100
@@ -96,6 +96,7 @@ ACMD(do_oasis_trigedit)
   else
     trigedit_setup_existing(d, real_num);
 
+  trigedit_disp_menu(d);
   STATE(d) = CON_TRIGEDIT;
 
   act("$n starts using OLC.", TRUE, d->character, 0, 0, TO_ROOM);
@@ -150,8 +151,6 @@ void trigedit_setup_new(struct descripto
 
   OLC_TRIG(d) = trig;
   OLC_VAL(d) = 0;  /* Has changed flag. (It hasn't so far, we just made it.) */
-
-  trigedit_disp_menu(d);
 }
 
 void trigedit_setup_existing(struct descriptor_data *d, int rtrg_num)
@@ -179,8 +178,6 @@ void trigedit_setup_existing(struct desc
 
   OLC_TRIG(d) = trig;
   OLC_VAL(d) = 0;  /* Has changed flag. (It hasn't so far, we just made it.) */
-
-  trigedit_disp_menu(d);
 }
 
 void trigedit_disp_menu(struct descriptor_data *d)
@@ -212,6 +209,7 @@ void trigedit_disp_menu(struct descripto
   "%s4)%s Numeric Arg  : %s%d\r\n"
   "%s5)%s Arguments    : %s%s\r\n"
   "%s6)%s Commands:\r\n%s%s\r\n"
+  "%sW%s) Copy Trigger\r\n"
   "%sQ)%s Quit\r\n"
   "Enter Choice :",
 
@@ -222,7 +220,7 @@ void trigedit_disp_menu(struct descripto
   grn, nrm, yel, trig->narg,			/* numeric arg            */
   grn, nrm, yel, trig->arglist?trig->arglist:"",/* strict arg             */
   grn, nrm, cyn, OLC_STORAGE(d),		/* the command list       */
-  grn, nrm);                                    /* quit colors            */
+  grn, nrm, grn, nrm);                          /* quit colors            */
 
   OLC_MODE(d) = TRIGEDIT_MAIN_MENU;
 }
@@ -311,6 +309,11 @@ void trigedit_parse(struct descriptor_da
            OLC_VAL(d) = 1;
 
            break;
+         case 'w':
+         case 'W':
+           write_to_output(d, "Copy what trigger? ");
+           OLC_MODE(d) = TRIGEDIT_COPY;
+           break;
          default:
            trigedit_disp_menu(d);
            return;
@@ -371,6 +374,13 @@ void trigedit_parse(struct descriptor_da
       trigedit_disp_types(d);
       return;
 
+    case TRIGEDIT_COPY:
+      if ((i = real_room(atoi(arg))) != NOWHERE) {
+        trigedit_setup_existing(d, i);
+      } else
+        write_to_output(d, "That trigger does not exist.\r\n");
+      break;
+
     case TRIGEDIT_COMMANDS:
       break;
 
@@ -513,11 +523,6 @@ void trigedit_save(struct descriptor_dat
           new_index[rnum]->proto = proto;
           trig_data_copy(proto, trig);
 
-          if (trig->name)
-            proto->name = strdup(trig->name);
-          if (trig->arglist)
-            proto->arglist = strdup(trig->arglist);
-
           new_index[rnum + 1] = trig_index[rnum];
 
           proto = trig_index[rnum]->proto;
@@ -543,11 +548,6 @@ void trigedit_save(struct descriptor_dat
       CREATE(proto, struct trig_data, 1);
       new_index[rnum]->proto = proto;
       trig_data_copy(proto, trig);
-
-      if (trig->name)
-        proto->name = strdup(trig->name);
-      if (trig->arglist)
-        proto->arglist = strdup(trig->arglist);
     }
 
     free(trig_index);
@@ -557,7 +557,7 @@ void trigedit_save(struct descriptor_dat
 
     /* HERE IT HAS TO GO THROUGH AND FIX ALL SCRIPTS/TRIGS OF HIGHER RNUM */
     for (live_trig = trigger_list; live_trig; live_trig = live_trig->next_in_world)
-      GET_TRIG_RNUM(live_trig) += (GET_TRIG_RNUM(live_trig) > rnum);
+      GET_TRIG_RNUM(live_trig) += (GET_TRIG_RNUM(live_trig) != NOTHING && GET_TRIG_RNUM(live_trig) > rnum);
 
     /* Update other trigs being edited. */
      for (dsc = descriptor_list; dsc; dsc = dsc->next)
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/dg_olc.h tbamud-3.54/src/dg_olc.h
--- tbamud-3.53/src/dg_olc.h	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/dg_olc.h	2007-11-29 03:02:08.000000000 +0100
@@ -22,6 +22,7 @@
 #define TRIGEDIT_COMMANDS		6
 #define TRIGEDIT_NARG			7
 #define TRIGEDIT_ARGUMENT		8
+#define TRIGEDIT_COPY                   9
 
 #define OLC_SCRIPT_EDIT		    82766  /* arbitrary > highest possible room number */
 #define SCRIPT_MAIN_MENU		0
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/dg_scripts.c tbamud-3.54/src/dg_scripts.c
--- tbamud-3.53/src/dg_scripts.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/dg_scripts.c	2007-11-29 03:02:08.000000000 +0100
@@ -810,7 +810,7 @@ void script_stat (char_data *ch, struct 
 
 void do_sstat_room(struct char_data * ch, struct room_data *rm)
 {
-  send_to_char(ch, "Script information:\r\n");
+  send_to_char(ch, "Triggers:\r\n");
   if (!SCRIPT(rm)) {
     send_to_char(ch, "  None.\r\n");
     return;
@@ -821,7 +821,7 @@ void do_sstat_room(struct char_data * ch
 
 void do_sstat_object(char_data *ch, obj_data *j)
 {
-  send_to_char(ch, "Script information:\r\n");
+  send_to_char(ch, "Triggers:\r\n");
   if (!SCRIPT(j)) {
     send_to_char(ch, "  None.\r\n");
     return;
@@ -832,7 +832,7 @@ void do_sstat_object(char_data *ch, obj_
 
 void do_sstat_character(char_data *ch, char_data *k)
 {
-  send_to_char(ch, "Script information:\r\n");
+  send_to_char(ch, "Triggers:\r\n");
   if (!SCRIPT(k)) {
     send_to_char(ch, "  None.\r\n");
     return;
@@ -2625,25 +2625,26 @@ int script_driver(void *go_adress, trig_
 /* returns the real number of the trigger with given virtual number */
 trig_rnum real_trigger(trig_vnum vnum)
 {
-  int bot = 0, mid;
-  int top = top_of_trigt-1;
+  trig_rnum bot, top, mid;
+
+  bot = 0;
+  top = top_of_trigt - 1;
+
+  if (!top_of_trigt || trig_index[bot]->vnum > vnum || trig_index[top]->vnum < vnum)
+    return (NOTHING);
 
   /* perform binary search on trigger-table */
-  for (;;) {
+  while (bot <= top) {
     mid = (bot + top) / 2;
 
-  /* Thanks to Derek Fisk for fixing this loop */
-    if (bot > top)
-      return (NOTHING);
     if (trig_index[mid]->vnum == vnum)
       return (mid);
-    if (top == 0)
-      return (NOTHING);
     if (trig_index[mid]->vnum > vnum)
       top = mid - 1;
     else
       bot = mid + 1;
   }
+  return (NOTHING);
 }
 
 ACMD(do_tstat)
@@ -2983,3 +2984,17 @@ void remove_from_lookup_table(long uid)
 
   log("remove_from_lookup. UID %ld not found.", uid);
 }
+
+bool check_flags_by_name_ar(int *array, int numflags, char *search, const char *namelist[]) 
+{ 
+  int i, item=-1; 
+
+  for (i=0; i<numflags && item < 0; i++) 
+    if (!strcmp(search, namelist[i])) item = i; 
+
+  if (item < 0) return FALSE; 
+
+  if (IS_SET_AR(array, item)) return TRUE; 
+
+  return FALSE; 
+}
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/dg_variables.c tbamud-3.54/src/dg_variables.c
--- tbamud-3.53/src/dg_variables.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/dg_variables.c	2007-11-29 03:02:08.000000000 +0100
@@ -20,11 +20,13 @@
 #include "screen.h"
 #include "constants.h"
 #include "spells.h"
+#include "oasis.h"
 
 /* External variables and functions */
 extern const char *pc_class_types[];
 extern struct time_info_data time_info;
 int find_eq_pos_script(char *arg);
+bool check_flags_by_name_ar(int *array, int numflags, char *search, const char *namelist[]);
 
 /* Utility functions */
 
@@ -604,6 +606,13 @@ void find_replacement(void *go, struct s
             }
             snprintf(str, slen, "%d", GET_DEX(c));
           }
+          else if (!str_cmp(field, "drunk")) {
+            if (subfield && *subfield) {
+              int addition = atoi(subfield);
+	     GET_COND(c, DRUNK) = MAX(-1, MIN(addition, 24));
+            }
+            snprintf(str, slen, "%d", GET_COND(c, DRUNK));
+          }
           break;
         case 'e':
           if (!str_cmp(field, "exp")) {
@@ -682,6 +691,13 @@ void find_replacement(void *go, struct s
             }
             snprintf(str, slen, "%d", GET_HIT(c));
           }
+          else if (!str_cmp(field, "hunger")) {
+            if (subfield && *subfield) {
+              int addition = atoi(subfield);
+              GET_COND(c, HUNGER) = MAX(-1, MIN(addition, 24));
+            }
+            snprintf(str, slen, "%d", GET_COND(c, HUNGER));
+          }
           break;
         case 'i':
           if (!str_cmp(field, "id"))
@@ -970,6 +986,14 @@ void find_replacement(void *go, struct s
             }
             snprintf(str, slen, "%s", IS_NPC(c) ? "" : GET_TITLE(c));
           }
+          else if (!str_cmp(field, "thirst")) {
+            if (subfield && *subfield) {
+              int addition = atoi(subfield);
+              GET_COND(c, THIRST) = MAX(-1, MIN(addition, 24));
+            }
+            snprintf(str, slen, "%d", GET_COND(c, THIRST));
+          }
+	  break;
         case 'v':
           if (!str_cmp(field, "vnum")) {
             if (subfield && *subfield) {
@@ -1040,6 +1064,16 @@ void find_replacement(void *go, struct s
 
       *str = '\x1';
       switch (LOWER(*field)) {
+        case 'a':
+          if (!str_cmp(field, "affects")) { 
+            if (subfield && *subfield) { 
+              if (check_flags_by_name_ar(GET_OBJ_AFFECT(o), NUM_AFF_FLAGS, subfield, affected_bits) == TRUE)
+                snprintf(str, slen, "1"); 
+              else 
+                snprintf(str, slen, "0"); 
+            } else
+              snprintf(str, slen, "0"); 
+          } 
         case 'c':
           if (!str_cmp(field, "cost")) {
             if (subfield && *subfield) {
@@ -1079,6 +1113,19 @@ o->contains));
             	strcpy(str, "0");
           }
           break;
+        case 'e':
+          if (!str_cmp(field, "extra")) {
+            if (subfield && *subfield) {
+              if (check_flags_by_name_ar(GET_OBJ_EXTRA(o), NUM_ITEM_FLAGS, subfield, extra_bits) > 0)
+                snprintf(str, slen, "1");
+              else
+                snprintf(str, slen, "0");
+            } else 
+              snprintf(str, slen, "0");
+          } else {
+            sprintbitarray(GET_OBJ_EXTRA(o), extra_bits, EF_ARRAY_MAX, str);
+          }
+          break;
         case 'h':
           /* thanks to Jamie Nelson (Mordecai of 4 Dimensions MUD) */
           if (!str_cmp(field, "has_in")) {
@@ -1099,6 +1146,9 @@ o->contains) ? "1" : "0"));
             else
               *str = '\0';
           }
+          else if (!str_cmp(field, "is_pc")) { 
+            strcpy(str, "-1"); 
+          } 
           break;
         case 'n':
           if (!str_cmp(field, "name"))
@@ -1276,6 +1326,20 @@ o->contains) ? "1" : "0"));
         else
           *str = '\0';
       }
+      else if (!str_cmp(field, "zonenumber")) 
+        snprintf(str, slen, "%d",  zone_table[r->zone].number); 
+      else if (!str_cmp(field, "zonename")) 
+        snprintf(str, slen, "%s",  zone_table[r->zone].name);
+      else if (!str_cmp(field, "roomflag")) { 
+        if (subfield && *subfield) { 
+          room_rnum thisroom = real_room(r->number); 
+          if (check_flags_by_name_ar(ROOM_FLAGS(thisroom), NUM_ROOM_FLAGS, subfield, room_bits) == TRUE) 
+            snprintf(str, slen, "1"); 
+          else 
+            snprintf(str, slen, "0"); 
+        } else
+          snprintf(str, slen, "0"); 
+      }
       else if (!str_cmp(field, "north")) {
         if (R_EXIT(r, NORTH)) {
           if (subfield && *subfield) {
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/fight.c tbamud-3.54/src/fight.c
--- tbamud-3.53/src/fight.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/fight.c	2007-11-29 03:02:08.000000000 +0100
@@ -1005,7 +1005,7 @@ void perform_violence(void)
     /* should master auto-assist followers?  */
     if (ch->master && PRF_FLAGGED(ch->master, PRF_AUTOASSIST) &&
         FIGHTING(ch) && !FIGHTING(ch->master) &&
-        (IN_ROOM(ch->master) == IN_ROOM(ch)))
+        (IN_ROOM(ch->master) == IN_ROOM(ch)) && !IS_NPC(ch->master))
       do_assist(ch->master, GET_NAME(ch), 0, 0);
 
     hit(ch, FIGHTING(ch), TYPE_UNDEFINED);
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/genmob.c tbamud-3.54/src/genmob.c
--- tbamud-3.53/src/genmob.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/genmob.c	2007-11-29 03:02:08.000000000 +0100
@@ -72,7 +72,7 @@ int add_mobile(struct char_data *mob, mo
 
   /* Update live mobile rnums. */
   for (live_mob = character_list; live_mob; live_mob = live_mob->next)
-    GET_MOB_RNUM(live_mob) += (GET_MOB_RNUM(live_mob) >= found);
+    GET_MOB_RNUM(live_mob) += (GET_MOB_RNUM(live_mob) != NOTHING && GET_MOB_RNUM(live_mob) >= found);
 
   /* Update zone table. */
   for (zone = 0; zone <= top_of_zone_table; zone++)
@@ -82,8 +82,8 @@ int add_mobile(struct char_data *mob, mo
 
   /* Update shop keepers. */
   if (shop_index)
-    for (shop = 0; shop <= top_shop - top_shop_offset; shop++)
-      SHOP_KEEPER(shop) += (SHOP_KEEPER(shop) >= found);
+    for (shop = 0; shop <= top_shop; shop++)
+      SHOP_KEEPER(shop) += (SHOP_KEEPER(shop) != NOTHING && SHOP_KEEPER(shop) >= found);
 
   add_to_save_list(zone_table[real_zone_by_thing(vnum)].number, SL_MOB);
   return found;
@@ -150,7 +150,7 @@ int delete_mobile(mob_rnum refpt)
 
   /* Update shop keepers. */
   if (shop_index)
-    for (counter = 0; counter <= top_shop - top_shop_offset; counter++)
+    for (counter = 0; counter <= top_shop; counter++)
       SHOP_KEEPER(counter) -= (SHOP_KEEPER(counter) >= refpt);
 
   save_mobiles(real_zone_by_thing(vnum));
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/genobj.c tbamud-3.54/src/genobj.c
--- tbamud-3.53/src/genobj.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/genobj.c	2007-11-29 03:02:08.000000000 +0100
@@ -65,6 +65,7 @@ int update_all_objects(struct obj_data *
     *obj = *refobj;
 
     /* Copy game-time dependent variables over. */
+    GET_ID(obj) = swap.id;
     IN_ROOM(obj) = swap.in_room;
     obj->carried_by = swap.carried_by;
     obj->worn_by = swap.worn_by;
@@ -96,7 +97,7 @@ obj_rnum adjust_objects(obj_rnum refpt)
 
   /* Renumber live objects. */
   for (obj = object_list; obj; obj = obj->next)
-    GET_OBJ_RNUM(obj) += (GET_OBJ_RNUM(obj) >= refpt);
+    GET_OBJ_RNUM(obj) += (GET_OBJ_RNUM(obj) != NOTHING && GET_OBJ_RNUM(obj) >= refpt);
 
   /* Renumber zone table. */
   for (zone = 0; zone <= top_of_zone_table; zone++) {
@@ -122,7 +123,7 @@ obj_rnum adjust_objects(obj_rnum refpt)
     BOARD_RNUM(i) += (BOARD_RNUM(i) >= refpt);
 
   /* Renumber shop produce. */
-  for (shop = 0; shop <= top_shop - top_shop_offset; shop++)
+  for (shop = 0; shop <= top_shop; shop++)
     for (i = 0; SHOP_PRODUCT(shop, i) != NOTHING; i++)
       SHOP_PRODUCT(shop, i) += (SHOP_PRODUCT(shop, i) >= refpt);
 
@@ -374,15 +375,16 @@ int copy_object_main(struct obj_data *to
 int delete_object(obj_rnum rnum)
 {
   obj_rnum i;
+  zone_rnum zrnum;
   struct obj_data *obj, *tmp;
-  int shop, j;
+  int shop, j, zone, cmd_no;
 
   if (rnum == NOTHING || rnum > top_of_objt)
     return NOTHING;
   
   obj = &obj_proto[rnum];
 
-  zone_rnum zrnum = real_zone_by_thing(GET_OBJ_VNUM(obj));
+  zrnum = real_zone_by_thing(GET_OBJ_VNUM(obj));
 
   /* This is something you might want to read about in the logs. */
   log("GenOLC: delete_object: Deleting object #%d (%s).", GET_OBJ_VNUM(obj), obj->short_description);
@@ -438,12 +440,11 @@ int delete_object(obj_rnum rnum)
     BOARD_RNUM(j) -= (BOARD_RNUM(j) > rnum);
 
   /* Renumber shop produce. */
-  for (shop = 0; shop <= top_shop - top_shop_offset; shop++)
+  for (shop = 0; shop <= top_shop; shop++)
     for (j = 0; SHOP_PRODUCT(shop, j) != NOTHING; j++)
       SHOP_PRODUCT(shop, j) -= (SHOP_PRODUCT(shop, j) > rnum);
 
   /* Renumber zone table. */
-  int zone, cmd_no;
   for (zone = 0; zone <= top_of_zone_table; zone++) {
     for (cmd_no = 0; ZCMD(zone, cmd_no).command != 'S'; cmd_no++) {
       switch (ZCMD(zone, cmd_no).command) {
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/genolc.c tbamud-3.54/src/genolc.c
--- tbamud-3.53/src/genolc.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/genolc.c	2007-11-29 03:02:08.000000000 +0100
@@ -27,7 +27,6 @@
 #include "interpreter.h"
 
 int save_config( IDXTYPE nowhere );        /* Exported from cedit.c */
-int top_shop_offset = 0;
 
 /* List of zones to be saved. */
 struct save_list_data *save_list;
@@ -160,7 +159,7 @@ int add_to_save_list(zone_vnum zone, int
 
   rznum = real_zone(zone);
   if (rznum == NOWHERE || rznum > top_of_zone_table) {
-    if (zone != AEDIT_PERMISSION) {
+    if (zone != AEDIT_PERMISSION || zone != HEDIT_PERMISSION) {
       log("SYSERR: add_to_save_list: Invalid zone number passed. (%d => %d, 0-%d)", zone, rznum, top_of_zone_table);
       return FALSE;
     }
@@ -189,6 +188,16 @@ int in_save_list(zone_vnum zone, int typ
   return FALSE;
 }
 
+void free_save_list(void)
+{
+  struct save_list_data *sld, *next_sld;
+
+  for (sld = save_list; sld; sld = next_sld) {
+    next_sld = sld->next;
+    free(sld);
+  }
+}
+
 /* Used from do_show(), ideally. */
 ACMD(do_show_save_list)
 {
@@ -484,8 +493,6 @@ int export_save_mobiles(zone_rnum rznum)
 int export_mobile_record(mob_vnum mvnum, struct char_data *mob, FILE *fd)
 {
 
-  char bit1[64];
-  char bit2[64];
   char ldesc[MAX_STRING_LENGTH];
   char ddesc[MAX_STRING_LENGTH];
 
@@ -517,13 +524,6 @@ int export_mobile_record(mob_vnum mvnum,
       GET_MANA(mob), GET_MOVE(mob), GET_NDD(mob), GET_SDD(mob),
       GET_DAMROLL(mob));
 
-  fprintf(fd,	"%s %s %d E\n"
-		"%d %d %d %dd%d+%d %dd%d+%d\n",
-		bit1, bit2, GET_ALIGNMENT(mob),
-		GET_LEVEL(mob), 20 - GET_HITROLL(mob), GET_AC(mob) / 10, GET_HIT(mob),
-		GET_MANA(mob), GET_MOVE(mob), GET_NDD(mob), GET_SDD(mob),
-		GET_DAMROLL(mob)
-  );
   fprintf(fd, 	"%d %d\n"
 		"%d %d %d\n",
 		GET_GOLD(mob), GET_EXP(mob),
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/genolc.h tbamud-3.54/src/genolc.h
--- tbamud-3.53/src/genolc.h	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/genolc.h	2007-11-29 03:02:08.000000000 +0100
@@ -28,7 +28,6 @@ struct save_list_data {
 };
 
 extern struct save_list_data *save_list;
-extern int top_shop_offset;
 
 /* save_list_data.type */
 #define SL_MOB	0
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/genshp.c tbamud-3.54/src/genshp.c
--- tbamud-3.53/src/genshp.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/genshp.c	2007-11-29 03:02:08.000000000 +0100
@@ -255,7 +255,7 @@ shop_rnum real_shop(shop_vnum vnum)
   int bot, top, mid;
 
   bot = 0;
-  top = top_shop - top_shop_offset;
+  top = top_shop;
 
   /* perform binary search on shop_table */
   while (bot < top) {
@@ -307,9 +307,9 @@ int add_shop(struct shop_data *nshp)
   }
 
   top_shop++;
-  RECREATE(shop_index, struct shop_data, top_shop - top_shop_offset + 1);
+  RECREATE(shop_index, struct shop_data, top_shop + 1);
 
-  for (rshop = top_shop - top_shop_offset; rshop > 0; rshop--) {
+  for (rshop = top_shop; rshop > 0; rshop--) {
     if (nshp->vnum > SHOP_NUM(rshop - 1)) {
       found = rshop;
 
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/genwld.c tbamud-3.54/src/genwld.c
--- tbamud-3.53/src/genwld.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/genwld.c	2007-11-29 03:02:08.000000000 +0100
@@ -228,7 +228,7 @@ int delete_room(room_rnum rnum)
       }
 
   /* Remove this room from all shop lists. */
-  for (i = 0;i < top_shop;i++) {
+  for (i = 0; i < top_shop; i++) {
     for (j = 0;SHOP_ROOM(i, j) != NOWHERE;j++) {
       if (SHOP_ROOM(i, j) == world[rnum].number)
         SHOP_ROOM(i, j) = 0; /* set to the void */
@@ -382,41 +382,6 @@ int copy_room(struct room_data *to, stru
   return TRUE;
 }
 
-/* Idea by Cris Jacob. */
-room_rnum duplicate_room(room_vnum dest_vnum, room_rnum orig)
-{
-  int new_rnum, znum;
-  struct room_data nroom;
-
-#if CIRCLE_UNSIGNED_INDEX
-  if (orig == NOWHERE || orig > top_of_world) {
-#else
-  if (orig < 0 || orig > top_of_world) {
-#endif
-    log("SYSERR: GenOLC: copy_room: Given bad original real room.");
-    return NOWHERE;
-  } else if ((znum = real_zone_by_thing(dest_vnum)) == NOWHERE) {
-    log("SYSERR: GenOLC: copy_room: No such destination zone.");
-    return NOWHERE;
-  }
-
-  /* add_room will make its own copies of strings. */
-  if ((new_rnum = add_room(&nroom)) == NOWHERE) {
-    log("SYSERR: GenOLC: copy_room: Problem adding room.");
-    return NOWHERE;
-  }
-
-  nroom = world[new_rnum];
-  nroom.number = dest_vnum;
-  nroom.zone = znum;
-
-  /* So the people and objects aren't in two places at once. */
-  nroom.contents = NULL;
-  nroom.people = NULL;
-
-  return new_rnum;
-}
-
 /* Copy strings over so bad things don't happen.  We do not free the existing 
  * strings here because copy_room() did a shallow copy previously and we'd be 
  * freeing the very strings we're copying.  If this function is used elsewhere,
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/genzon.c tbamud-3.54/src/genzon.c
--- tbamud-3.53/src/genzon.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/genzon.c	2007-11-29 03:02:08.000000000 +0100
@@ -27,8 +27,11 @@ zone_rnum real_zone_by_thing(room_vnum v
   bot = 0;
   top = top_of_zone_table;
 
+  if (genolc_zone_bottom(bot) > vznum || zone_table[top].top < vznum)
+    return (NOWHERE);
+  
   /* perform binary search on zone-table */
-  for (;;) {
+  while (bot <= top) {
     mid = (bot + top) / 2;
 
     /* Upper/lower bounds of the zone. */
@@ -37,13 +40,12 @@ zone_rnum real_zone_by_thing(room_vnum v
 
     if (low <= vznum && vznum <= high)
       return mid;
-    if (bot >= top)
-      return NOWHERE;
     if (low > vznum)
       top = mid - 1;
     else
       bot = mid + 1;
   }
+  return (NOWHERE);
 }
 
 zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top, const char **error)
@@ -482,7 +484,7 @@ void remove_cmd_from_list(struct reset_c
 int new_command(struct zone_data *zone, int pos)
 {
   int subcmd = 0;
-  struct reset_com *new_com;
+  struct reset_com new_com;
 
   /* Error check to ensure users hasn't given too large an index. */
   while (zone->cmd[subcmd].command != 'S')
@@ -492,9 +494,8 @@ int new_command(struct zone_data *zone, 
     return 0;
 
   /* Ok, let's add a new (blank) command. */
-  CREATE(new_com, struct reset_com, 1);
-  new_com->command = 'N';
-  add_cmd_to_list(&zone->cmd, new_com, pos);
+  new_com.command = 'N'; 
+  add_cmd_to_list(&zone->cmd, &new_com, pos); 
   return 1;
 }
 
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/hedit.c tbamud-3.54/src/hedit.c
--- tbamud-3.53/src/hedit.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/hedit.c	2007-11-29 03:02:08.000000000 +0100
@@ -112,7 +112,7 @@ void hedit_setup_new(struct descriptor_d
   CREATE(OLC_HELP(d), struct help_index_element, 1);
 
   OLC_HELP(d)->keywords		= strdup(OLC_STORAGE(d));
-  OLC_HELP(d)->entry		= strdup("This help file is unfinished.\r\n");
+  OLC_HELP(d)->entry		= strdup("KEYWORDS\r\n\r\nThis help file is unfinished.\r\n");
   OLC_HELP(d)->min_level	= 0;
   OLC_HELP(d)->duplicate	= 0;
   OLC_VAL(d) = 0;
@@ -138,10 +138,10 @@ void hedit_save_internally(struct descri
   struct help_index_element *new_help_table = NULL;
 
   if (OLC_ZNUM(d) > top_of_helpt) {
+    int i;
     CREATE(new_help_table, struct help_index_element, top_of_helpt + 2);
 
-    int i;
-    for (i = 0; i <= top_of_helpt; i++)
+    for (i = 0; i < top_of_helpt; i++)
       new_help_table[i] = help_table[i];
     new_help_table[++top_of_helpt] = *OLC_HELP(d);
     free(help_table);
@@ -157,6 +157,7 @@ void hedit_save_to_disk(struct descripto
 {
   FILE *fp;
   char buf1[MAX_STRING_LENGTH], index_name[READ_SIZE];
+  int i;
 
   snprintf(index_name, sizeof(index_name), "%s%s", HLP_PREFIX, HELP_FILE);
   if (!(fp = fopen(index_name, "w"))) {
@@ -164,8 +165,7 @@ void hedit_save_to_disk(struct descripto
     return;
   }
 
-  int i;
-  for (i = 0; i <= top_of_helpt; i++) {
+  for (i = 0; i < top_of_helpt; i++) {
     if (help_table[i].duplicate)
       continue;
     strncpy(buf1, help_table[i].entry ? help_table[i].entry : "Empty\r\n", sizeof(buf1) - 1);
@@ -192,13 +192,11 @@ void hedit_disp_menu(struct descriptor_d
 
   write_to_output(d,
       "%s-- Help file editor\r\n"
-      "%s1%s) Keywords    : %s%s\r\n"
-      "%s2%s) Entry       :\r\n%s%s"
-      "%s3%s) Min Level   : %s%d\r\n"
+      "%s1%s) Entry       :\r\n%s%s"
+      "%s2%s) Min Level   : %s%d\r\n"
       "%sQ%s) Quit\r\n"
       "Enter choice : ",
        nrm,
-       grn, nrm, yel, OLC_HELP(d)->keywords,
        grn, nrm, yel, OLC_HELP(d)->entry,
        grn, nrm, yel, OLC_HELP(d)->min_level,
        grn, nrm
@@ -247,7 +245,7 @@ void hedit_parse(struct descriptor_data 
       break;       
     case 'n': case 'N':
       OLC_ZNUM(d)++;
-      for (; OLC_ZNUM(d) <= top_of_helpt; OLC_ZNUM(d)++)
+      for (; OLC_ZNUM(d) < top_of_helpt; OLC_ZNUM(d)++)
         if (is_abbrev(OLC_STORAGE(d), help_table[OLC_ZNUM(d)].keywords))
           break;
         else
@@ -301,10 +299,6 @@ void hedit_parse(struct descriptor_data 
       }
       break;
     case '1':
-      write_to_output(d, "Enter keywords:-\r\n] ");
-      OLC_MODE(d) = HEDIT_KEYWORDS;
-      break;
-    case '2':
       OLC_MODE(d) = HEDIT_ENTRY;
       clear_screen(d);
       send_editor_help(d);
@@ -316,7 +310,7 @@ void hedit_parse(struct descriptor_data 
       string_write(d, &OLC_HELP(d)->entry, MAX_MESSAGE_LENGTH, 0, oldtext);
       OLC_VAL(d) = 1;
       break;
-    case '3':
+    case '2':
       write_to_output(d, "Enter min level : ");
       OLC_MODE(d) = HEDIT_MIN_LEVEL;
       break;
@@ -414,7 +408,7 @@ ACMD(do_hindex)
   }
 
   len = sprintf(buf, "Help index entries based on '%s':\r\n", argument);
-  for (i = 0; i <= top_of_helpt; i++)
+  for (i = 0; i < top_of_helpt; i++)
     if (is_abbrev(argument, help_table[i].keywords)
         && (GET_LEVEL(ch) >= help_table[i].min_level))
       len +=
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/house.c tbamud-3.54/src/house.c
--- tbamud-3.53/src/house.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/house.c	2007-11-29 03:02:08.000000000 +0100
@@ -244,7 +244,7 @@ void House_boot(void)
 
   if (!(fl = fopen(HCONTROL_FILE, "rb"))) {
     if (errno == ENOENT)
-      log("   House control file '%s' does not exist.", HCONTROL_FILE);
+      log("   No houses to load. File '%s' does not exist.", HCONTROL_FILE);
     else
       perror("SYSERR: " HCONTROL_FILE);
     return;
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/improved-edit.c tbamud-3.54/src/improved-edit.c
--- tbamud-3.53/src/improved-edit.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/improved-edit.c	2007-11-29 03:02:08.000000000 +0100
@@ -479,6 +479,7 @@ int format_text(char **ptr_string, int m
   int line_chars, cap_next = TRUE, cap_next_next = FALSE, color_chars = 0, i, pass_line = 0;
   char *flow, *start = NULL, temp;
   char formatted[MAX_STRING_LENGTH] = "";
+  char str[MAX_STRING_LENGTH];
 
   /* Fix memory overrun. */
   if (d->max_str > MAX_STRING_LENGTH) {
@@ -490,7 +491,6 @@ int format_text(char **ptr_string, int m
   if ((flow = *ptr_string) == NULL)
     return 0;
 
-  char str[MAX_STRING_LENGTH];
   strcpy(str, flow);
 
   for (i = 0; i < low - 1; i++) {
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/interpreter.c tbamud-3.54/src/interpreter.c
--- tbamud-3.53/src/interpreter.c	2007-07-02 16:01:19.000000000 +0200
+++ tbamud-3.54/src/interpreter.c	2007-11-29 03:05:01.000000000 +0100
@@ -49,8 +49,6 @@ int parse_class(char arg);
 int special(struct char_data *ch, int cmd, char *arg);
 int isbanned(char *hostname);
 int valid_name(char *newname);
-void read_aliases(struct char_data *ch);
-void delete_aliases(const char *charname);
 void remove_player(int pfilepos);
 
 /* local functions */
@@ -62,7 +60,6 @@ int perform_alias(struct descriptor_data
 int reserved_word(char *argument);
 int _parse_name(char *arg, char *name);
 int enter_player_game (struct descriptor_data *d);
-void write_aliases(struct char_data *ch);
 
 /* prototypes for all do_x functions. */
 ACMD(do_action);
@@ -157,6 +154,7 @@ ACMD(do_mtransform);
 ACMD(do_mzoneecho);
 ACMD(do_mrecho);
 ACMD(do_not_here);
+ACMD(do_oasis_copy);
 ACMD(do_order);
 ACMD(do_page);
 ACMD(do_peace);
@@ -175,7 +173,6 @@ ACMD(do_rescue);
 ACMD(do_rest);
 ACMD(do_restore);
 ACMD(do_return);
-ACMD(do_room_copy);
 ACMD(do_save);
 ACMD(do_saveall);
 ACMD(do_say);
@@ -279,7 +276,7 @@ cpp_extern const struct command_info cmd
   { "close"    , "cl"      , POS_SITTING , do_gen_door , 0, SCMD_CLOSE },
   { "clear"    , "cle"     , POS_DEAD    , do_gen_ps   , 0, SCMD_CLEAR },
   { "cls"      , "cls"     , POS_DEAD    , do_gen_ps   , 0, SCMD_CLEAR },
-  { "clsolc"   , "clsolc"  , POS_DEAD    , do_gen_tog  , 0, SCMD_CLS },
+  { "clsolc"   , "clsolc"  , POS_DEAD    , do_gen_tog  , LVL_BUILDER, SCMD_CLS },
   { "consider" , "con"     , POS_RESTING , do_consider , 0, 0 },
   { "commands" , "com"     , POS_DEAD    , do_commands , 0, SCMD_COMMANDS },
   { "compact"  , "comp"    , POS_DEAD    , do_gen_tog  , 0, SCMD_COMPACT },
@@ -366,6 +363,7 @@ cpp_extern const struct command_info cmd
   { "mail"     , "mail"    , POS_STANDING, do_not_here , 1, 0 },
   { "medit"    , "med"     , POS_DEAD    , do_oasis_medit, LVL_BUILDER, 0 },
   { "mlist"    , "mlist"   , POS_DEAD    , do_oasis_list , LVL_BUILDER, SCMD_OASIS_MLIST },
+  { "mcopy"    , "mcopy"   , POS_DEAD    , do_oasis_copy, LVL_GOD, CON_MEDIT },
   { "mute"     , "mute"    , POS_DEAD    , do_wizutil  , LVL_GOD, SCMD_MUTE },
 
   { "news"     , "news"    , POS_SLEEPING, do_gen_ps   , 0, SCMD_NEWS },
@@ -386,6 +384,7 @@ cpp_extern const struct command_info cmd
   { "olc"      , "olc"     , POS_DEAD    , do_show_save_list, LVL_BUILDER, 0 },
   { "olist"    , "olist"   , POS_DEAD    , do_oasis_list, LVL_BUILDER, SCMD_OASIS_OLIST },
   { "oedit"    , "oedit"   , POS_DEAD    , do_oasis_oedit, LVL_BUILDER, 0 },
+  { "ocopy"    , "ocopy"   , POS_DEAD    , do_oasis_copy, LVL_GOD, CON_OEDIT },
 
   { "put"      , "p"       , POS_RESTING , do_put      , 0, 0 },
   { "peace"    , "pe"      , POS_DEAD    , do_peace    , LVL_BUILDER, 0 },
@@ -421,11 +420,12 @@ cpp_extern const struct command_info cmd
   { "return"   , "retu"    , POS_DEAD    , do_return   , 0, 0 },
   { "redit"    , "redit"   , POS_DEAD    , do_oasis_redit, LVL_BUILDER, 0 },
   { "rlist"    , "rlist"   , POS_DEAD    , do_oasis_list, LVL_BUILDER, SCMD_OASIS_RLIST },
-  { "rclone"   , "rclone"  , POS_DEAD    , do_room_copy, LVL_BUILDER, 0 },
+  { "rcopy"    , "rcopy"   , POS_DEAD    , do_oasis_copy, LVL_GOD, CON_REDIT },
   { "roomflags", "roomflags", POS_DEAD   , do_gen_tog  , LVL_IMMORT, SCMD_SHOWVNUMS },
 
   { "say"      , "s"       , POS_RESTING , do_say      , 0, 0 },
   { "score"    , "sc"      , POS_DEAD    , do_score    , 0, 0 },
+  { "scopy"    , "scopy"   , POS_DEAD    , do_oasis_copy, LVL_GOD, CON_SEDIT },
   { "sit"      , "si"      , POS_RESTING , do_sit      , 0, 0 },
   { "'"        , "'"       , POS_RESTING , do_say      , 0, 0 },
   { "save"     , "sav"     , POS_SLEEPING, do_save     , 0, 0 },
@@ -465,6 +465,7 @@ cpp_extern const struct command_info cmd
   { "trigedit" , "trigedit", POS_DEAD    , do_oasis_trigedit, LVL_BUILDER, 0 },
   { "typo"     , "typo"    , POS_DEAD    , do_gen_write, 0, SCMD_TYPO },
   { "tlist"    , "tlist"   , POS_DEAD    , do_oasis_list, LVL_BUILDER, SCMD_OASIS_TLIST },
+  { "tcopy"    , "tcopy"   , POS_DEAD    , do_oasis_copy, LVL_GOD, CON_TRIGEDIT },
   { "tstat"    , "tstat"   , POS_DEAD    , do_tstat    , LVL_BUILDER, 0 },
 
   { "unlock"   , "unlock"  , POS_SITTING , do_gen_door , 0, SCMD_UNLOCK },
@@ -1193,8 +1194,10 @@ int perform_dupe_check(struct descriptor
 
   /* no target for switching into was found - allow login to continue */
   if (!target) {
-    GET_PREF(d->character)= rand_number(1, 128000);
-    GET_HOST(d->character)= strdup(d->host);
+    GET_PREF(d->character) = rand_number(1, 128000); 
+    if (GET_HOST(d->character)) 
+      free(GET_HOST(d->character)); 
+    GET_HOST(d->character) = strdup(d->host);
     return 0;
   }
 
@@ -1219,12 +1222,7 @@ int perform_dupe_check(struct descriptor
   case RECON:
     write_to_output(d, "Reconnecting.\r\n");
     act("$n has reconnected.", TRUE, d->character, 0, 0, TO_ROOM);
-
-    if (GET_INVIS_LEV(d->character))
-      mudlog(BRF, MAX(LVL_IMMORT, GET_INVIS_LEV(d->character)), TRUE, "%s has reconnected. (invis %d)", GET_NAME(d->character), GET_INVIS_LEV(d->character));
-    else
-      mudlog(BRF, LVL_IMMORT, TRUE, "%s has reconnected.", GET_NAME(d->character));
-
+    mudlog(NRM, MAX(0, GET_INVIS_LEV(d->character)), TRUE, "%s [%s] has reconnected.", GET_NAME(d->character), d->host);
     if (has_mail(GET_IDNUM(d->character)))
       write_to_output(d, "You have mail waiting.\r\n");
     break;
@@ -1253,14 +1250,6 @@ int enter_player_game (struct descriptor
     room_vnum load_room;
 
       reset_char(d->character);
-      /* See if there might be some aliases in the old alias file. Only do this 
-       * if there were no aliases in the pfile. */
-		if (GET_ALIASES(d->character) == NULL)
-		{
-      read_aliases(d->character);
-      /* delete the old file - player will be saved in a second. */
-      delete_aliases(GET_NAME(d->character));
-    }
 
       if (PLR_FLAGGED(d->character, PLR_INVSTART))
 	GET_INVIS_LEV(d->character) = GET_LEVEL(d->character);
@@ -1373,6 +1362,9 @@ void nanny(struct descriptor_data *d, ch
 	  CREATE(d->character, struct char_data, 1);
 	  clear_char(d->character);
 	  CREATE(d->character->player_specials, struct player_special_data, 1);
+
+          if (GET_HOST(d->character))
+	    free(GET_HOST(d->character));
 	  GET_HOST(d->character) = strdup(d->host);
 
 	  d->character->desc = d;
@@ -1726,7 +1718,6 @@ void nanny(struct descriptor_data *d, ch
           remove_player(player_i);
         }
 
-      delete_aliases(GET_NAME(d->character));
       delete_variables(GET_NAME(d->character));
       write_to_output(d, "Character '%s' deleted! Goodbye.\r\n", GET_NAME(d->character));
       mudlog(NRM, LVL_GOD, TRUE, "%s (lev %d) has self-deleted.", GET_NAME(d->character), GET_LEVEL(d->character));
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/mail.c tbamud-3.54/src/mail.c
--- tbamud-3.53/src/mail.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/mail.c	2007-11-29 03:02:08.000000000 +0100
@@ -263,7 +263,7 @@ char *read_delete(long recipient)
     to = get_name_by_id(record_to_keep->recipient);
 
  		snprintf(buf, sizeof(buf),
-             " * * * * Midgaard Mail System * * * *\r\n"
+             " * * * * tbaMUD Mail System * * * *\r\n"
              "Date: %s\r\n"
              "To  : %s\r\n"
              "From: %s\r\n"
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/mail.h tbamud-3.54/src/mail.h
--- tbamud-3.53/src/mail.h	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/mail.h	2007-11-29 03:02:08.000000000 +0100
@@ -18,7 +18,7 @@
 #define STAMP_PRICE 150
 
 /* Maximum size of mail in bytes (arbitrary)	*/
-#define MAX_MAIL_SIZE 4096
+#define MAX_MAIL_SIZE 8192
 
 /* size of mail file allocation blocks		*/
 #define BLOCK_SIZE 100
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/medit.c tbamud-3.54/src/medit.c
--- tbamud-3.53/src/medit.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/medit.c	2007-11-29 03:02:08.000000000 +0100
@@ -155,6 +155,7 @@ ACMD(do_oasis_medit)
   else
     medit_setup_existing(d, real_num);
 
+  medit_disp_menu(d);
   STATE(d) = CON_MEDIT;
 
   /* Display the OLC messages to the players in the same room as the
@@ -193,8 +194,6 @@ void medit_setup_new(struct descriptor_d
   /* Has changed flag. (It hasn't so far, we just made it.) */
   OLC_VAL(d) = FALSE;
   OLC_ITEM_TYPE(d) = MOB_TRIGGER;
-
-  medit_disp_menu(d);
 }
 
 void medit_setup_existing(struct descriptor_data *d, int rmob_num)
@@ -215,8 +214,6 @@ void medit_setup_existing(struct descrip
    */
   SCRIPT(mob) = NULL;
   OLC_MOB(d)->proto_script = NULL;
-
-  medit_disp_menu(d);
 }
 
 /* Ideally, this function should be in db.c, but I'll put it here for portability. */
@@ -281,9 +278,9 @@ void medit_save_internally(struct descri
   /* Update keepers in shops being edited and other mobs being edited. */
   for (dsc = descriptor_list; dsc; dsc = dsc->next) {
     if (STATE(dsc) == CON_SEDIT)
-      S_KEEPER(OLC_SHOP(dsc)) += (S_KEEPER(OLC_SHOP(dsc)) >= new_rnum);
+      S_KEEPER(OLC_SHOP(dsc)) += (S_KEEPER(OLC_SHOP(dsc)) != NOTHING && S_KEEPER(OLC_SHOP(dsc)) >= new_rnum);
     else if (STATE(dsc) == CON_MEDIT)
-      GET_MOB_RNUM(OLC_MOB(dsc)) += (GET_MOB_RNUM(OLC_MOB(dsc)) >= new_rnum);
+      GET_MOB_RNUM(OLC_MOB(dsc)) += (GET_MOB_RNUM(OLC_MOB(dsc)) != NOTHING && GET_MOB_RNUM(OLC_MOB(dsc)) >= new_rnum);
   }
 
   /* Update other people in zedit too. From: C.Raehl 4/27/99 */
@@ -423,6 +420,7 @@ void medit_disp_menu(struct descriptor_d
 	  "%sL%s) NPC Flags : %s%s\r\n"
 	  "%sM%s) AFF Flags : %s%s\r\n"
           "%sS%s) Script    : %s%s\r\n"
+          "%sW%s) Copy mob\r\n"
           "%sX%s) Delete mob\r\n"
 	  "%sQ%s) Quit\r\n"
 	  "Enter choice : ",
@@ -434,6 +432,7 @@ void medit_disp_menu(struct descriptor_d
 	  grn, nrm, cyn, flag2,
           grn, nrm, cyn, OLC_SCRIPT(d) ?"Set.":"Not Set.",
           grn, nrm,
+	  grn, nrm,
 	  grn, nrm
 	  );
 
@@ -448,7 +447,7 @@ void medit_parse(struct descriptor_data 
   if (OLC_MODE(d) > MEDIT_NUMERICAL_RESPONSE) {
     i = atoi(arg);
     if (!*arg || (!isdigit(arg[0]) && ((*arg == '-') && !isdigit(arg[1])))) {
-      write_to_output(d, "Field must be numerical, try again : ");
+      write_to_output(d, "Try again : ");
       return;
     }
   } else {	/* String response. */
@@ -470,9 +469,14 @@ void medit_parse(struct descriptor_data 
         write_to_output(d, "Mobile saved to disk.\r\n");
       } else
         write_to_output(d, "Mobile saved to memory.\r\n");
-      /* FALL THROUGH */
+      cleanup_olc(d, CLEANUP_ALL);
+      return;
     case 'n':
     case 'N':
+      /* If not saving, we must free the script_proto list. We do so by 
+       * assigning it to the edited mob and letting free_mobile in 
+       * cleanup_olc handle it. */
+      OLC_MOB(d)->proto_script = OLC_SCRIPT(d);
       cleanup_olc(d, CLEANUP_ALL);
       return;
     default:
@@ -601,6 +605,11 @@ void medit_parse(struct descriptor_data 
       OLC_MODE(d) = MEDIT_AFF_FLAGS;
       medit_disp_aff_flags(d);
       return;
+    case 'w':
+    case 'W':
+      write_to_output(d, "Copy what mob? ");
+      OLC_MODE(d) = MEDIT_COPY;
+      return;
     case 'x':
     case 'X':
       write_to_output(d, "Are you sure you want to delete this mobile? ");
@@ -767,6 +776,13 @@ void medit_parse(struct descriptor_data 
     GET_ALIGNMENT(OLC_MOB(d)) = LIMIT(i, -1000, 1000);
     break;
 
+  case MEDIT_COPY:
+    if ((i = real_mobile(atoi(arg))) != NOWHERE) {
+      medit_setup_existing(d, i);
+    } else
+      write_to_output(d, "That mob does not exist.\r\n");
+    break;
+  
   case MEDIT_DELETE:
     if (*arg == 'y' || *arg == 'Y') {
       if (delete_mobile(GET_MOB_RNUM(OLC_MOB(d))) != NOBODY) 
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/oasis.c tbamud-3.54/src/oasis.c
--- tbamud-3.53/src/oasis.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/oasis.c	2007-11-29 03:02:08.000000000 +0100
@@ -110,7 +110,11 @@ void cleanup_olc(struct descriptor_data 
 
   /* Check for a zone.  cleanup_type is irrelevant here, free() everything. */
   if (OLC_ZONE(d)) {
+    if (OLC_ZONE(d)->builders) 
+      free(OLC_ZONE(d)->builders); 
+    if (OLC_ZONE(d)->name) 
     free(OLC_ZONE(d)->name);
+    if (OLC_ZONE(d)->cmd)
     free(OLC_ZONE(d)->cmd);
     free(OLC_ZONE(d));
   }
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/oasis.h tbamud-3.54/src/oasis.h
--- tbamud-3.53/src/oasis.h	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/oasis.h	2007-11-29 03:02:08.000000000 +0100
@@ -195,6 +195,7 @@ extern const char *nrm, *grn, *cyn, *yel
 #define OEDIT_LEVEL                 	25
 #define OEDIT_PERM			26
 #define OEDIT_DELETE                   27
+#define OEDIT_COPY                      28
 
 /* Submodes of REDIT connectedness. */
 #define REDIT_MAIN_MENU 		1
@@ -214,6 +215,7 @@ extern const char *nrm, *grn, *cyn, *yel
 #define REDIT_EXTRADESC_KEY 		15
 #define REDIT_EXTRADESC_DESCRIPTION 	16
 #define REDIT_DELETE			17
+#define REDIT_COPY			18
 
 /* Submodes of ZEDIT connectedness. */
 #define ZEDIT_MAIN_MENU              	0
@@ -264,6 +266,7 @@ extern const char *nrm, *grn, *cyn, *yel
 #define MEDIT_LEVEL			25
 #define MEDIT_ALIGNMENT			26
 #define MEDIT_DELETE                    27
+#define MEDIT_COPY                      28
 
 /* Submodes of SEDIT connectedness. */
 #define SEDIT_MAIN_MENU              	0
@@ -279,8 +282,8 @@ extern const char *nrm, *grn, *cyn, *yel
 #define SEDIT_ROOMS_MENU		12
 #define SEDIT_NAMELIST_MENU		13
 #define SEDIT_NAMELIST			14
+#define SEDIT_COPY                      15
 
-/* Numerical responses. */
 #define SEDIT_NUMERICAL_RESPONSE	20
 #define SEDIT_OPEN1			21
 #define SEDIT_OPEN2			22
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/oasis_copy.c tbamud-3.54/src/oasis_copy.c
--- tbamud-3.53/src/oasis_copy.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/oasis_copy.c	2007-11-29 03:02:08.000000000 +0100
@@ -14,19 +14,153 @@
 #include "interpreter.h"
 #include "handler.h"
 #include "db.h"
+#include "shop.h"
+#include "genshp.h"
 #include "genolc.h"
 #include "genzon.h"
 #include "genwld.h"
 #include "oasis.h"
 #include "improved-edit.h"
 #include "constants.h"
+#include "dg_scripts.h"
 
 /* Internal Functions */
 ACMD(do_dig);
-ACMD(do_room_copy);
 room_vnum redit_find_new_vnum(zone_rnum zone);
 int buildwalk(struct char_data *ch, int dir);
 
+/* External Functions */
+void trigedit_save(struct descriptor_data *d);
+void redit_save_internally(struct descriptor_data *d);
+void oedit_save_internally(struct descriptor_data *d);
+void medit_save_internally(struct descriptor_data *d);
+void sedit_save_internally(struct descriptor_data *d);
+void trigedit_setup_existing(struct descriptor_data *d, int rnum);
+void redit_setup_existing(struct descriptor_data *d, int rnum);
+void oedit_setup_existing(struct descriptor_data *d, int rnum);
+void medit_setup_existing(struct descriptor_data *d, int rnum);
+void sedit_setup_existing(struct descriptor_data *d, int rnum);
+
+
+/***********************************************************
+* This function makes use of the high level OLC functions  *
+* to copy most types of mud objects. The type of data is   *
+* determined by the subcmd variable and the functions are  *
+* looked up in a table.                                    *
+***********************************************************/
+ACMD(do_oasis_copy)
+{
+  int i, src_vnum, src_rnum, dst_vnum, dst_rnum;
+  char buf1[MAX_INPUT_LENGTH];
+  char buf2[MAX_INPUT_LENGTH];
+  struct descriptor_data *d;
+
+  struct {
+    int con_type;
+    IDXTYPE (*binary_search)(IDXTYPE vnum);
+    void (*save_func)(struct descriptor_data *d);
+    void (*setup_existing)(struct descriptor_data *d, int rnum);
+    const char *command;
+    const char *text;
+  } oasis_copy_info[] = {
+    { CON_REDIT,  real_room,   redit_save_internally, redit_setup_existing, "rcopy", "room" },
+    { CON_OEDIT,  real_object, oedit_save_internally, oedit_setup_existing, "ocopy", "object" },
+    { CON_MEDIT,  real_mobile, medit_save_internally, medit_setup_existing, "mcopy", "mobile" },
+    { CON_SEDIT,  real_shop,   sedit_save_internally, sedit_setup_existing, "scopy", "shop" },
+    { CON_TRIGEDIT, real_trigger, trigedit_save,   trigedit_setup_existing, "tcopy", "trigger" },
+    { -1,         NULL,        NULL,                  NULL,                 "\n", "\n" }
+  };
+
+  /* Find the given connection type in the table (passed in subcmd). */
+  for (i = 0; *(oasis_copy_info[i].text) != '\n'; i++)
+    if (subcmd == oasis_copy_info[i].con_type)
+      break;
+  /* If not found, we don't support copying that type of data. */
+  if (*(oasis_copy_info[i].text) == '\n')
+    return;
+
+  /* No copying as a mob or while being forced. */
+  if (IS_NPC(ch) || !ch->desc || STATE(ch->desc) != CON_PLAYING) 
+    return;
+
+  /* We need two arguments. */
+  two_arguments(argument, buf1, buf2);
+
+  /* Both arguments are required and they must be numeric. */
+  if (!*buf2 || !is_number(buf1) || !is_number(buf2)) {
+    send_to_char(ch, "Syntax: %s <source vnum> <target vnum>\r\n", oasis_copy_info[i].command);
+    return;
+  }
+
+  /* We can't copy non-existing data. */
+  /* Note: the source data can be in any zone. It's not restricted */
+  /* to the builder's designated OLC zone. */
+  src_vnum = atoi(buf1);
+  src_rnum = (*oasis_copy_info[i].binary_search)(src_vnum);
+  if (src_rnum == NOWHERE) {
+    send_to_char(ch, "The source %s (#%d) does not exist.\r\n", oasis_copy_info[i].text, src_vnum);
+    return;
+  }
+
+  /* Don't copy if the target already exists. */
+  dst_vnum = atoi(buf2);
+  dst_rnum = (*oasis_copy_info[i].binary_search)(dst_vnum);
+  if (dst_rnum != NOWHERE) {
+    send_to_char(ch, "The target %s (#%d) already exists.\r\n", oasis_copy_info[i].text, dst_vnum);
+    return;
+  }
+
+  /* Check that whatever it is isn't already being edited. */
+  for (d = descriptor_list; d; d = d->next) {
+    if (STATE(d) == subcmd) {
+      if (d->olc && OLC_NUM(d) == dst_vnum) {
+	send_to_char(ch, "The target %s (#%d) is currently being edited by %s.\r\n",
+	oasis_copy_info[i].text, dst_vnum, GET_NAME(d->character));
+        return;
+      }
+    }
+  }
+
+  d = ch->desc;
+
+  /* Give the descriptor an OLC structure. */
+  if (d->olc) {
+    mudlog(BRF, LVL_IMMORT, TRUE, "SYSERR: do_oasis_copy: Player already had olc structure.");
+    free(d->olc);
+  }
+
+  /* Create the OLC structure. */
+  CREATE(d->olc, struct oasis_olc_data, 1);
+
+  /* Find the zone. */
+  if ((OLC_ZNUM(d) = real_zone_by_thing(dst_vnum)) == NOWHERE) {
+    send_to_char(ch, "Sorry, there is no zone for the given vnum (#%d)!\r\n", dst_vnum);
+    free(d->olc);
+    d->olc = NULL;
+    return;
+  }
+
+  /* Make sure the builder is allowed to modify the target zone. */
+  if (!can_edit_zone(ch, OLC_ZNUM(d))) {
+    send_cannot_edit(ch, zone_table[OLC_ZNUM(d)].number);
+    free(d->olc);
+    d->olc = NULL;
+    return;
+  }
+
+  /* We tell the OLC functions that we want to save to the target vnum. */
+  OLC_NUM(d) = dst_vnum;
+
+  /* Perform the copy. */
+  send_to_char(ch, "Copying %s: source: #%d, dest: #%d.\r\n", oasis_copy_info[i].text, src_vnum, dst_vnum);
+  (*oasis_copy_info[i].setup_existing)(d, src_rnum);
+  (*oasis_copy_info[i].save_func)(d);
+
+  /* Currently CLEANUP_ALL should be used for everything. */
+  cleanup_olc(d, CLEANUP_ALL);
+  send_to_char(ch, "Done.\r\n");
+}
+
 /* Commands */
 ACMD(do_dig)
 {
@@ -138,7 +272,7 @@ ACMD(do_dig)
     OLC_VAL(d) = 0;
 
     send_to_char(ch, "New room (%d) created.\r\n", rvnum);
-    cleanup_olc(d, CLEANUP_STRUCTS);
+    cleanup_olc(d, CLEANUP_ALL);
     /* Update rrnum to the correct room rnum after adding the room. */
     rrnum = real_room(rvnum);
   }
@@ -166,111 +300,6 @@ ACMD(do_dig)
   }
 }
 
-ACMD(do_room_copy)
-{
-   struct room_data *room_src, *room_dst;
-   int room_num, j, buf_num, taeller;
-   zone_rnum dst_zone;
-   struct descriptor_data *dsc;
-   char buf[MAX_INPUT_LENGTH];
-
-   one_argument(argument, buf);
-
-   if (!*buf) {
-     send_to_char(ch, "Usage: rclone <target room>\r\n");
-     return;
-   }
-
-   if (real_room((buf_num = atoi(buf))) != NOWHERE) {
-     send_to_char(ch, "That room already exist!\r\n");
-     return;
-   }
-
-   if ((dst_zone = real_zone_by_thing(buf_num)) == NOWHERE) {
-     send_to_char(ch, "Sorry, there is no zone for that number!\r\n");
-     return;
-   }
-
-   if (!can_edit_zone(ch, dst_zone) ||
-       !can_edit_zone(ch, world[IN_ROOM(ch)].zone) ) {
-     send_to_char(ch, "You may only copy rooms within your designated zone(s)!\r\n");
-     return;
-   }
-
-
-   room_src = &world[IN_ROOM(ch)];
-   CREATE(room_dst, struct room_data, 1);
-
-   room_dst->zone = dst_zone;
-
-   /* Allocate space for all strings. */
-   send_to_char(ch, "Cloning room....\r\n");
-
-   room_dst->name = str_udup(world[IN_ROOM(ch)].name);
-   room_dst->description = str_udup(world[IN_ROOM(ch)].description);
-   room_dst->description = str_udup(world[IN_ROOM(ch)].description);
-   room_dst->number = buf_num;
-   room_dst->sector_type = world[IN_ROOM(ch)].sector_type;
-   for(taeller=0; taeller < RF_ARRAY_MAX; taeller++)
-     room_dst->room_flags[taeller] = ROOM_FLAGS(IN_ROOM(ch))[taeller];
-
-  /* Extra descriptions, if necessary. */
-  send_to_char(ch, "Cloning extra descriptions....\r\n");
-  if (world[IN_ROOM(ch)].ex_description) {
-    struct extra_descr_data *tdesc, *temp, *temp2;
-    CREATE(temp, struct extra_descr_data, 1);
-
-    room_dst->ex_description = temp;
-    for (tdesc = world[IN_ROOM(ch)].ex_description; tdesc; tdesc = tdesc->next) {
-      temp->keyword = strdup(tdesc->keyword);
-      temp->description = strdup(tdesc->description);
-      if (tdesc->next) {
-	CREATE(temp2, struct extra_descr_data, 1);
-	temp->next = temp2;
-	temp = temp2;
-      } else
-	temp->next = NULL;
-    }
-  }
-   /* Now save the room in the right place. */
-  send_to_char(ch, "Saving new room...\r\n");
-
-  if ((room_num = add_room(room_dst)) == NOWHERE) {
-    send_to_char(ch, "Something went wrong...\r\n");
-    log("SYSERR: do_room_copy: Something failed! (%d)", room_num);
-    return;
-  }
-  /* Idea contributed by C.Raehl. */
-  for (dsc = descriptor_list; dsc; dsc = dsc->next) {
-    if (dsc == ch->desc)
-      continue;
-
-    if (STATE(dsc) == CON_ZEDIT) {
-      for (j = 0; OLC_ZONE(dsc)->cmd[j].command != 'S'; j++)
-        switch (OLC_ZONE(dsc)->cmd[j].command) {
-          case 'O':
-          case 'M':
-            OLC_ZONE(dsc)->cmd[j].arg3 += (OLC_ZONE(dsc)->cmd[j].arg3 >= room_num);
-            break;
-          case 'D':
-            OLC_ZONE(dsc)->cmd[j].arg2 += (OLC_ZONE(dsc)->cmd[j].arg2 >= room_num);
-            /* Fall through */
-          case 'R':
-            OLC_ZONE(dsc)->cmd[j].arg1 += (OLC_ZONE(dsc)->cmd[j].arg1 >= room_num);
-            break;
-          }
-    } else if (STATE(dsc) == CON_REDIT) {
-      for (j = 0; j < NUM_OF_DIRS; j++)
-        if (OLC_ROOM(dsc)->dir_option[j])
-          if (OLC_ROOM(dsc)->dir_option[j]->to_room >= room_num)
-            OLC_ROOM(dsc)->dir_option[j]->to_room++;
-    }
-  }
-  add_to_save_list(real_zone_by_thing(atoi(buf)), SL_WLD);
-  redit_save_to_disk(real_zone_by_thing(atoi(buf)));
-  send_to_char(ch, "Room cloned to %d.\r\nAll Done.\r\n", buf_num);
-}
-
 /* BuildWalk - OasisOLC Extension by D. Tyler Barnes. */
 /* For buildwalk. Finds the next free vnum in the zone */
 room_vnum redit_find_new_vnum(zone_rnum zone)
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/oasis_list.c tbamud-3.54/src/oasis_list.c
--- tbamud-3.53/src/oasis_list.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/oasis_list.c	2007-11-29 03:02:08.000000000 +0100
@@ -152,6 +152,9 @@ void list_rooms(struct char_data *ch, zo
   "Index VNum    Room Name                                Exits\r\n"
   "----- ------- ---------------------------------------- -----\r\n");
 
+  if (!top_of_world) 
+    return;
+  
   for (i = 0; i <= top_of_world; i++) {
 
     /** Check to see if this room is one of the ones needed to be listed.    **/
@@ -202,6 +205,9 @@ void list_mobiles(struct char_data *ch, 
   "Index VNum    Mobile Name                                   Level\r\n"
   "----- ------- --------------------------------------------- -----\r\n");
 
+  if (!top_of_mobt) 
+    return;
+  
   for (i = 0; i <= top_of_mobt; i++) {
     if (mob_index[i].vnum >= bottom && mob_index[i].vnum <= top) {
       counter++;
@@ -238,6 +244,9 @@ void list_objects(struct char_data *ch, 
   "Index VNum    Object Name                                  Object Type\r\n"
   "----- ------- -------------------------------------------- ----------------\r\n");
 
+  if (!top_of_objt) 
+    return;
+  
   for (i = 0; i <= top_of_objt; i++) {
     if (obj_index[i].vnum >= bottom && obj_index[i].vnum <= top) {
       counter++;
@@ -320,6 +329,9 @@ void list_zones(struct char_data *ch, zo
   "VNum  Zone Name                      Builder(s)\r\n"
   "----- ------------------------------ --------------------------------------\r\n");
 
+  if (!top_of_zone_table) 
+    return;
+  
   for (i = 0; i <= top_of_zone_table; i++) {
     if (zone_table[i].number >= bottom && zone_table[i].number <= top) {
       send_to_char(ch, "[%s%3d%s] %s%-*s %s%-1s%s\r\n",
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/oedit.c tbamud-3.54/src/oedit.c
--- tbamud-3.53/src/oedit.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/oedit.c	2007-11-29 03:02:08.000000000 +0100
@@ -170,6 +170,7 @@ ACMD(do_oasis_oedit)
   else
     oedit_setup_new(d);
 
+  oedit_disp_menu(d);
   STATE(d) = CON_OEDIT;
 
   /* Send the OLC message to the players in the same room as the builder. */
@@ -195,8 +196,6 @@ void oedit_setup_new(struct descriptor_d
 
   SCRIPT(OLC_OBJ(d)) = NULL;
   OLC_OBJ(d)->proto_script = OLC_SCRIPT(d) = NULL;
-
-  oedit_disp_menu(d);
 }
 
 void oedit_setup_existing(struct descriptor_data *d, int real_num)
@@ -216,8 +215,6 @@ void oedit_setup_existing(struct descrip
    * obj later, after editing. */
   SCRIPT(obj) = NULL;
   OLC_OBJ(d)->proto_script = NULL;
-
-  oedit_disp_menu(d);
 }
 
 void oedit_save_internally(struct descriptor_data *d)
@@ -328,7 +325,7 @@ void oedit_disp_extradesc_menu(struct de
 
      	  grn, nrm, yel, (extra_desc->keyword && *extra_desc->keyword) ? extra_desc->keyword : "<NONE>",
 	  grn, nrm, yel, (extra_desc->description && *extra_desc->description) ? extra_desc->description : "<NONE>",
-	  grn, nrm, !extra_desc->next ? "<Not set>\r\n" : "Set.", grn, nrm);
+	  grn, nrm, !extra_desc->next ? "Not set." : "Set.", grn, nrm);
   OLC_MODE(d) = OEDIT_EXTRADESC_MENU;
 }
 
@@ -444,7 +441,7 @@ void oedit_disp_val1_menu(struct descrip
     break;
   case ITEM_DRINKCON:
   case ITEM_FOUNTAIN:
-    write_to_output(d, "Max drink units : ");
+    write_to_output(d, "Max drink units (-1 for unlimited) : ");
     break;
   case ITEM_FOOD:
     write_to_output(d, "Hours to fill stomach : ");
@@ -488,7 +485,7 @@ void oedit_disp_val2_menu(struct descrip
     break;
   case ITEM_DRINKCON:
   case ITEM_FOUNTAIN:
-    write_to_output(d, "Initial drink units (-1 for unlimited) : ");
+    write_to_output(d, "Initial drink units : ");
     break;
   default:
     oedit_disp_menu(d);
@@ -648,7 +645,7 @@ void oedit_disp_menu(struct descriptor_d
 	  grn, nrm, yel, (obj->name && *obj->name) ? obj->name : "undefined",
 	  grn, nrm, yel, (obj->short_description && *obj->short_description) ? obj->short_description : "undefined",
 	  grn, nrm, yel, (obj->description && *obj->description) ? obj->description : "undefined",
-	  grn, nrm, yel, (obj->action_description && *obj->action_description) ? obj->action_description : "<not set>\r\n",
+	  grn, nrm, yel, (obj->action_description && *obj->action_description) ? obj->action_description : "Not Set.\r\n",
 	  grn, nrm, cyn, buf1,
 	  grn, nrm, cyn, buf2
 	  );
@@ -664,10 +661,11 @@ void oedit_disp_menu(struct descriptor_d
 	  "%sB%s) Timer       : %s%d\r\n"
 	  "%sC%s) Values      : %s%d %d %d %d\r\n"
 	  "%sD%s) Applies menu\r\n"
-	  "%sE%s) Extra descriptions menu\r\n"
+	  "%sE%s) Extra descriptions menu: %s%s%s\r\n"
           "%sM%s) Min Level   : %s%d\r\n"
           "%sP%s) Perm Affects: %s%s\r\n"
 	  "%sS%s) Script      : %s%s\r\n"
+          "%sW%s) Copy object\r\n"
           "%sX%s) Delete object\r\n"
 	  "%sQ%s) Quit\r\n"
 	  "Enter choice : ",
@@ -681,11 +679,12 @@ void oedit_disp_menu(struct descriptor_d
 	  GET_OBJ_VAL(obj, 1),
 	  GET_OBJ_VAL(obj, 2),
 	  GET_OBJ_VAL(obj, 3),
-	  grn, nrm, grn, nrm,
+	  grn, nrm, grn, nrm, cyn, GET_OBJ_EXTRA(obj) ? "Set." : "Not Set.", grn,
           grn, nrm, cyn, GET_OBJ_LEVEL(obj),
           grn, nrm, cyn, buf2,
           grn, nrm, cyn, OLC_SCRIPT(d) ? "Set." : "Not Set.",
 	  grn, nrm,
+	  grn, nrm,
           grn, nrm
   );
   OLC_MODE(d) = OEDIT_MAIN_MENU;
@@ -711,10 +710,13 @@ void oedit_parse(struct descriptor_data 
         write_to_output(d, "Object saved to disk.\r\n");
       } else
         write_to_output(d, "Object saved to memory.\r\n");
-
-      /* Fall through. */
+      cleanup_olc(d, CLEANUP_ALL);
+      return;
     case 'n':
     case 'N':
+      /* If not saving, we must free the script_proto list. */
+      OLC_OBJ(d)->proto_script = OLC_SCRIPT(d);
+      free_proto_script(OLC_OBJ(d), OBJ_TRIGGER);
       cleanup_olc(d, CLEANUP_ALL);
       return;
     case 'a': /* abort quit */
@@ -830,6 +832,11 @@ void oedit_parse(struct descriptor_data 
       OLC_SCRIPT_EDIT_MODE(d) = SCRIPT_MAIN_MENU;
       dg_script_menu(d);
       return;
+    case 'w':
+    case 'W':
+      write_to_output(d, "Copy what object? ");
+      OLC_MODE(d) = OEDIT_COPY;
+      break;
     case 'x':
     case 'X':
       write_to_output(d, "Are you sure you want to delete this object? ");
@@ -1174,6 +1181,14 @@ void oedit_parse(struct descriptor_data 
       return;
     }
     break;
+
+  case OEDIT_COPY:
+    if ((number = real_object(atoi(arg))) != NOWHERE) {
+      oedit_setup_existing(d, number);
+    } else
+      write_to_output(d, "That object does not exist.\r\n");
+    break;
+
   case OEDIT_DELETE:
     if (*arg == 'y' || *arg == 'Y') {
       if (delete_object(GET_OBJ_RNUM(OLC_OBJ(d))) != NOTHING)
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/players.c tbamud-3.54/src/players.c
--- tbamud-3.53/src/players.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/players.c	2007-11-29 03:02:08.000000000 +0100
@@ -17,6 +17,7 @@
 #include "pfdefaults.h"
 #include "dg_scripts.h"
 #include "comm.h"
+#include "interpreter.h"
 
 #define LOAD_HIT	0
 #define LOAD_MANA	1
@@ -30,12 +31,12 @@ void tag_argument(char *argument, char *
 void load_affects(FILE *fl, struct char_data *ch);
 void load_skills(FILE *fl, struct char_data *ch);
 void load_HMVS(struct char_data *ch, const char *line, int mode);
+void write_aliases_ascii(FILE *file, struct char_data *ch);
+void read_aliases_ascii(FILE *file, struct char_data *ch, int count);
 
 /* external fuctions */
 bitvector_t asciiflag_conv(char *flag);
 void save_char_vars(struct char_data *ch);
-void write_aliases_ascii(FILE *file, struct char_data *ch);
-void read_aliases_ascii(FILE *file, struct char_data *ch, int count);
 void save_char_vars_ascii(FILE *file, struct char_data *ch);
 void read_saved_vars_ascii(FILE *file, struct char_data *ch, int count);
 void strip_cr(char *buffer);
@@ -99,8 +100,8 @@ int create_entry(char *name)
   int i, pos;
 
   if (top_of_p_table == -1) {	/* no table */
-    CREATE(player_table, struct player_index_element, 1);
     pos = top_of_p_table = 0;
+    CREATE(player_table, struct player_index_element, 1);
   } else if ((pos = get_ptable_by_name(name)) == -1) {	/* new name */
     i = ++top_of_p_table + 1;
 
@@ -258,7 +259,6 @@ int load_char(const char *name, struct c
     GET_MOVE(ch) = PFDEF_MOVE;
     GET_MAX_MOVE(ch) = PFDEF_MAXMOVE;
     GET_OLC_ZONE(ch) = PFDEF_OLC;
-    GET_HOST(ch) = NULL;
     GET_PAGE_LENGTH(ch) = PFDEF_PAGELENGTH;
     GET_ALIASES(ch) = NULL;
     SITTING(ch) = NULL;
@@ -279,18 +279,23 @@ int load_char(const char *name, struct c
       case 'A':
         if (!strcmp(tag, "Ac  "))	GET_AC(ch)		= atoi(line);
 	else if (!strcmp(tag, "Act ")) {
-          sscanf(line, "%s %s %s %s", f1, f2, f3, f4);
+         if (sscanf(line, "%s %s %s %s", f1, f2, f3, f4) == 4) {
           PLR_FLAGS(ch)[0] = asciiflag_conv(f1);
           PLR_FLAGS(ch)[1] = asciiflag_conv(f2);
           PLR_FLAGS(ch)[2] = asciiflag_conv(f3);
           PLR_FLAGS(ch)[3] = asciiflag_conv(f4);
+        } else
+          PLR_FLAGS(ch)[0] = asciiflag_conv(line);
         } else if (!strcmp(tag, "Aff ")) {
-          sscanf(line, "%s %s %s %s", f1, f2, f3, f4);
+        if (sscanf(line, "%s %s %s %s", f1, f2, f3, f4) == 4) {
           AFF_FLAGS(ch)[0] = asciiflag_conv(f1);
           AFF_FLAGS(ch)[1] = asciiflag_conv(f2);
           AFF_FLAGS(ch)[2] = asciiflag_conv(f3);
           AFF_FLAGS(ch)[3] = asciiflag_conv(f4);
-        } else if (!strcmp(tag, "Affs")) 	load_affects(fl, ch);
+        } else 
+          AFF_FLAGS(ch)[0] = asciiflag_conv(line);	
+	}
+	if (!strcmp(tag, "Affs")) 	load_affects(fl, ch);
         else if (!strcmp(tag, "Alin"))	GET_ALIGNMENT(ch)	= atoi(line);
 	else if (!strcmp(tag, "Alis"))	read_aliases_ascii(fl, ch, atoi(line));
 	break;
@@ -329,7 +334,11 @@ int load_char(const char *name, struct c
       case 'H':
 	     if (!strcmp(tag, "Hit "))	load_HMVS(ch, line, LOAD_HIT);
 	else if (!strcmp(tag, "Hite"))	GET_HEIGHT(ch)		= atoi(line);
-	else if (!strcmp(tag, "Host"))	GET_HOST(ch)		= strdup(line);
+        else if (!strcmp(tag, "Host")) { 
+          if (GET_HOST(ch)) 
+            free(GET_HOST(ch)); 
+          GET_HOST(ch) = strdup(line); 
+        }
 	else if (!strcmp(tag, "Hrol"))	GET_HITROLL(ch)		= atoi(line);
 	else if (!strcmp(tag, "Hung"))	GET_COND(ch, HUNGER)	= atoi(line);
 	break;
@@ -365,12 +374,15 @@ int load_char(const char *name, struct c
 	else if (!strcmp(tag, "Plyd"))	ch->player.time.played	= atoi(line);
 	else if (!strcmp(tag, "PfIn"))	POOFIN(ch)		= strdup(line);
 	else if (!strcmp(tag, "PfOt"))	POOFOUT(ch)		= strdup(line);
-        else if (!strcmp(tag, "Pref"))
-          sscanf(line, "%s %s %s %s", f1, f2, f3, f4);
+        else if (!strcmp(tag, "Pref")) {
+          if (sscanf(line, "%s %s %s %s", f1, f2, f3, f4) == 4) {
           PRF_FLAGS(ch)[0] = asciiflag_conv(f1);
           PRF_FLAGS(ch)[1] = asciiflag_conv(f2);
           PRF_FLAGS(ch)[2] = asciiflag_conv(f3);
           PRF_FLAGS(ch)[3] = asciiflag_conv(f4);
+          } else
+	    PRF_FLAGS(ch)[0] = asciiflag_conv(f1);
+	  }
 	break;
 
       case 'Q':
@@ -399,6 +411,7 @@ int load_char(const char *name, struct c
 
       case 'V':
 	     if (!strcmp(tag, "Vars"))	read_saved_vars_ascii(fl, ch, atoi(line));
+      break;
 
       case 'W':
 	     if (!strcmp(tag, "Wate"))	GET_WEIGHT(ch)		= atoi(line);
@@ -431,7 +444,7 @@ int load_char(const char *name, struct c
 void save_char(struct char_data * ch)
 {
   FILE *fl;
-  char fname[40], buf[MAX_STRING_LENGTH];
+  char fname[40], buf[MAX_STRING_LENGTH], bits[127], bits2[127], bits3[127], bits4[127]; 
   int i, id, save_index = FALSE;
   struct affected_type *aff, tmp_aff[MAX_AFFECT];
   struct obj_data *char_eq[NUM_WEARS];
@@ -527,12 +540,24 @@ void save_char(struct char_data * ch)
   if (GET_WEIGHT(ch)	   != PFDEF_HEIGHT)	fprintf(fl, "Wate: %d\n", GET_WEIGHT(ch));
   if (GET_ALIGNMENT(ch)  != PFDEF_ALIGNMENT)	fprintf(fl, "Alin: %d\n", GET_ALIGNMENT(ch));
 
-    if(PLR_FLAGS(ch) != PFDEF_PLRFLAGS)
-      fprintf(fl, "Act : %u %u %u %u\n", PLR_FLAGS(ch)[0], PLR_FLAGS(ch)[1], PLR_FLAGS(ch)[2], PLR_FLAGS(ch)[3]);
-    if(AFF_FLAGS(ch) != PFDEF_AFFFLAGS)
-      fprintf(fl, "Aff : %u %u %u %u\n", AFF_FLAGS(ch)[0], AFF_FLAGS(ch)[1], AFF_FLAGS(ch)[2], AFF_FLAGS(ch)[3]);
-    if(PRF_FLAGS(ch) != PFDEF_PREFFLAGS)
-      fprintf(fl, "Pref: %d %d %d %d\n", PRF_FLAGS(ch)[0], PRF_FLAGS(ch)[1], PRF_FLAGS(ch)[2], PRF_FLAGS(ch)[3]);
+
+  sprintascii(bits,  PLR_FLAGS(ch)[0]); 
+  sprintascii(bits2, PLR_FLAGS(ch)[1]); 
+  sprintascii(bits3, PLR_FLAGS(ch)[2]); 
+  sprintascii(bits4, PLR_FLAGS(ch)[3]); 
+  fprintf(fl, "Act : %s %s %s %s\n", bits, bits2, bits3, bits4); 
+ 
+  sprintascii(bits,  AFF_FLAGS(ch)[0]); 
+  sprintascii(bits2, AFF_FLAGS(ch)[1]); 
+  sprintascii(bits3, AFF_FLAGS(ch)[2]); 
+  sprintascii(bits4, AFF_FLAGS(ch)[3]); 
+  fprintf(fl, "Aff : %s %s %s %s\n", bits, bits2, bits3, bits4); 
+ 
+  sprintascii(bits,  PRF_FLAGS(ch)[0]); 
+  sprintascii(bits2, PRF_FLAGS(ch)[1]); 
+  sprintascii(bits3, PRF_FLAGS(ch)[2]); 
+  sprintascii(bits4, PRF_FLAGS(ch)[3]); 
+  fprintf(fl, "Pref: %s %s %s %s\n", bits, bits2, bits3, bits4); 
 
   if (GET_SAVE(ch, 0)	   != PFDEF_SAVETHROW)	fprintf(fl, "Thr1: %d\n", GET_SAVE(ch, 0));
   if (GET_SAVE(ch, 1)	   != PFDEF_SAVETHROW)	fprintf(fl, "Thr2: %d\n", GET_SAVE(ch, 1));
@@ -682,6 +707,9 @@ void remove_player(int pfilepos)
   if (!*player_table[pfilepos].name)
     return;
 
+  /* Update top_of_p_table. */
+  top_of_p_table -= 1;
+
   /* Unlink all player-owned files */
   for (i = 0; i < MAX_FILES; i++) {
     if (get_filename(fname, sizeof(fname), i, player_table[pfilepos].name))
@@ -790,3 +818,63 @@ void load_HMVS(struct char_data *ch, con
     break;
   }
 }
+
+/* until further notice, the alias->pfiles save and load functions will
+ *  * function along side the old seperate alias file load, for compatibility. */
+void write_aliases_ascii(FILE *file, struct char_data *ch)
+{
+  struct alias_data *temp;
+    int count = 0;
+
+      if (GET_ALIASES(ch) == NULL)
+          return;
+
+	    for (temp = GET_ALIASES(ch); temp; temp = temp->next)
+	        count++;
+
+		  fprintf(file, "Alis: %d\n", count);
+		    /* the +1 thing below is due to alias replacements having a space prepended
+		     *    * in memory. The reason for this escapes me. Welcor 27/12/06 */
+		      for (temp = GET_ALIASES(ch); temp; temp = temp->next) {
+		          fprintf(file, "%s\n"        /* Alias */
+                    "%s\n"        /* Replacement */
+                      "%d\n",       /* Type */
+                      temp->alias,
+                      temp->replacement+1,
+                     temp->type);
+  }
+}
+
+void read_aliases_ascii(FILE *file, struct char_data *ch, int count)
+{
+  int i;
+    struct alias_data *temp;
+      char abuf[MAX_INPUT_LENGTH], rbuf[MAX_INPUT_LENGTH+1], tbuf[MAX_INPUT_LENGTH];
+
+        if (count == 0) {
+	    GET_ALIASES(ch) = NULL;
+	        return; /* No aliases in the list. */
+		  }
+
+		    for (i = 0; i < count; i++) {
+		        /* Read the aliased command. */
+			    get_line(file, abuf);
+
+			        /* Read the replacement. */
+				    get_line(file, tbuf);
+				        strcpy(rbuf, " ");
+					    strcat(rbuf, tbuf); /* strcat: OK */
+
+					        /* read the type */
+						    get_line(file, tbuf);
+
+						        if (abuf && *abuf && tbuf && *tbuf && rbuf && *rbuf) {
+							      CREATE(temp, struct alias_data, 1);
+							            temp->alias = strdup(abuf);
+								          temp->replacement = strdup(rbuf);
+									        temp->type = atoi(tbuf);
+										      temp->next = GET_ALIASES(ch);
+										            GET_ALIASES(ch) = temp;
+											        }
+												  }
+												  }
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/redit.c tbamud-3.54/src/redit.c
--- tbamud-3.53/src/redit.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/redit.c	2007-11-29 03:02:08.000000000 +0100
@@ -139,6 +139,7 @@ ACMD(do_oasis_redit)
   else
     redit_setup_new(d);
 
+  redit_disp_menu(d);
   STATE(d) = CON_REDIT;
   act("$n starts using OLC.", TRUE, d->character, 0, 0, TO_ROOM);
   SET_BIT_AR(PLR_FLAGS(ch), PLR_WRITING);
@@ -157,7 +158,6 @@ void redit_setup_new(struct descriptor_d
   OLC_ITEM_TYPE(d) = WLD_TRIGGER;
   OLC_ROOM(d)->proto_script = OLC_SCRIPT(d) = NULL;
 
-  redit_disp_menu(d);
   OLC_VAL(d) = 0;
 }
 
@@ -215,8 +215,6 @@ void redit_setup_existing(struct descrip
   dg_olc_script_copy(d);
   room->proto_script = NULL;
   SCRIPT(room) = NULL;
-
-  redit_disp_menu(d);
 }
 
 void redit_save_internally(struct descriptor_data *d)
@@ -224,10 +222,10 @@ void redit_save_internally(struct descri
   int j, room_num, new_room = FALSE;
   struct descriptor_data *dsc;
 
-  if (OLC_ROOM(d)->number == NOWHERE) {
+  if (OLC_ROOM(d)->number == NOWHERE)
     new_room = TRUE;
+
     OLC_ROOM(d)->number = OLC_NUM(d);
-  }
   /* FIXME: Why is this not set elsewhere? */
   OLC_ROOM(d)->zone = OLC_ZNUM(d);
 
@@ -315,7 +313,7 @@ void redit_disp_extradesc_menu(struct de
 	  grn, nrm
 	  );
 
-  write_to_output(d, !extra_desc->next ? "<NOT SET>\r\n" : "Set.\r\n");
+  write_to_output(d, !extra_desc->next ? "Not Set.\r\n" : "Set.\r\n");
   write_to_output(d, "Enter choice (0 to quit) : ");
   OLC_MODE(d) = REDIT_EXTRADESC_MENU;
 }
@@ -428,6 +426,7 @@ void redit_disp_menu(struct descriptor_d
 	  "%sA%s) Exit down   : %s%d\r\n"
 	  "%sB%s) Extra descriptions menu\r\n"
 	  "%sS%s) Script      : %s%s\r\n"
+          "%sW%s) Copy Room\r\n"
           "%sX%s) Delete Room\r\n"
 	  "%sQ%s) Quit\r\n"
 	  "Enter choice : ",
@@ -459,6 +458,7 @@ void redit_disp_menu(struct descriptor_d
 	  grn, nrm,
           grn, nrm, cyn, OLC_SCRIPT(d) ? "Set." : "Not Set.",
           grn, nrm,
+	  grn, nrm,
 	  grn, nrm
 	  );
 
@@ -483,12 +483,15 @@ void redit_parse(struct descriptor_data 
         write_to_output(d, "Room saved to disk.\r\n");
       } else
         write_to_output(d, "Room saved to memory.\r\n");
-      /* Do NOT free strings! Just the room structure. */
-      cleanup_olc(d, CLEANUP_STRUCTS);
+      /* Free everything. */
+      cleanup_olc(d, CLEANUP_ALL);
       break;
     case 'n':
     case 'N':
-      /* Free everything up, including strings, etc. */
+      /* If not saving, we must free the script_proto list. We do so by 
+       * assigning it to the edited room and letting free_room in 
+       * cleanup_olc handle it. */
+      OLC_ROOM(d)->proto_script = OLC_SCRIPT(d);
       cleanup_olc(d, CLEANUP_ALL);
       break;
     default:
@@ -563,6 +566,11 @@ void redit_parse(struct descriptor_data 
       OLC_DESC(d) = OLC_ROOM(d)->ex_description;
       redit_disp_extradesc_menu(d);
       break;
+    case 'w':
+    case 'W':
+      write_to_output(d, "Copy what room? ");
+      OLC_MODE(d) = REDIT_COPY;
+      break;
     case 'x':
     case 'X':
       /* Delete the room, prompt first. */
@@ -782,6 +790,13 @@ void redit_parse(struct descriptor_data 
     }
     break;
 
+  case REDIT_COPY:
+    if ((number = real_room(atoi(arg))) != NOWHERE) {
+      redit_setup_existing(d, number);
+    } else
+      write_to_output(d, "That room does not exist.\r\n");
+    break;
+  
   case REDIT_DELETE:
     if (*arg == 'y' || *arg == 'Y') {
       if (delete_room(real_room(OLC_ROOM(d)->number)))
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/sedit.c tbamud-3.54/src/sedit.c
--- tbamud-3.53/src/sedit.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/sedit.c	2007-11-29 03:02:08.000000000 +0100
@@ -164,6 +164,7 @@ ACMD(do_oasis_sedit)
   else
     sedit_setup_new(d);
 
+  sedit_disp_menu(d);
   STATE(d) = CON_SEDIT;
 
   act("$n starts using OLC.", TRUE, d->character, 0, 0, TO_ROOM);
@@ -206,7 +207,6 @@ void sedit_setup_new(struct descriptor_d
 
    /* Presto! A shop. */
   OLC_SHOP(d) = shop;
-  sedit_disp_menu(d);
 }
 
 void sedit_setup_existing(struct descriptor_data *d, int rshop_num)
@@ -216,7 +216,6 @@ void sedit_setup_existing(struct descrip
 
   /* don't waste time trying to free NULL strings -- Welcor */
   copy_shop(OLC_SHOP(d), shop_index + rshop_num, FALSE);
-  sedit_disp_menu(d);
 }
 
 /* Menu functions */
@@ -247,15 +246,18 @@ void sedit_products_menu(struct descript
 void sedit_compact_rooms_menu(struct descriptor_data *d)
 {
   struct shop_data *shop;
-  int i, count = 0;
+  int i;
 
   shop = OLC_SHOP(d);
   get_char_colors(d->character);
 
   clear_screen(d);
   for (i = 0; S_ROOM(shop, i) != NOWHERE; i++) {
-    write_to_output(d, "%2d - [%s%5d%s]  | %s", i, cyn, S_ROOM(shop, i), nrm,
-			!(++count % 5) ? "\r\n" : "");
+    if (real_room(S_ROOM(shop, i)) != NOWHERE) {
+      write_to_output(d, "%2d - [@c%5d@n] - @y%s@n\r\n", i, S_ROOM(shop, i), world[real_room(S_ROOM(shop, i))].name);
+    } else {
+      write_to_output(d, "%2d - [@R!Removed Room!@n]\r\n", i);
+    }
   }
   write_to_output(d, "\r\n"
 	  "%sA%s) Add a new room.\r\n"
@@ -404,6 +406,7 @@ void sedit_disp_menu(struct descriptor_d
 	  "%sR%s) Rooms Menu\r\n"
 	  "%sP%s) Products Menu\r\n"
 	  "%sT%s) Accept Types Menu\r\n"
+          "%sW%s) Copy Shop\r\n"
 	  "%sQ%s) Quit\r\n"
 	  "Enter Choice : ",
 
@@ -425,7 +428,7 @@ void sedit_disp_menu(struct descriptor_d
 	  grn, nrm, yel, S_SELL(shop),
 	  grn, nrm, cyn, buf1,
 	  grn, nrm, cyn, buf2,
-	  grn, nrm, grn, nrm, grn, nrm, grn, nrm
+	  grn, nrm, grn, nrm, grn, nrm, grn, nrm, grn, nrm
   );
 
   OLC_MODE(d) = SEDIT_MAIN_MENU;
@@ -472,6 +475,11 @@ void sedit_parse(struct descriptor_data 
   case SEDIT_MAIN_MENU:
     i = 0;
     switch (*arg) {
+    case 'w':
+    case 'W':
+      write_to_output(d, "Copy what shop? ");
+      OLC_MODE(d) = SEDIT_COPY;
+      return;
     case 'q':
     case 'Q':
       if (OLC_VAL(d)) {		/* Anything been changed? */
@@ -760,6 +768,12 @@ void sedit_parse(struct descriptor_data 
       return;
     }
     break;
+  case SEDIT_COPY:
+    if ((i = real_room(atoi(arg))) != NOWHERE) {
+      sedit_setup_existing(d, i);
+    } else
+      write_to_output(d, "That shop does not exist.\r\n");
+    break;
 
   default:
     /* We should never get here. */
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/shop.c tbamud-3.54/src/shop.c
--- tbamud-3.53/src/shop.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/shop.c	2007-11-29 03:02:08.000000000 +0100
@@ -240,7 +240,7 @@ int evaluate_expression(struct obj_data 
 	name[ptr - end] = '\0';
 	for (eindex = 0; *extra_bits[eindex] != '\n'; eindex++)
 	  if (!str_cmp(name, extra_bits[eindex])) {
-	    push(&vals, OBJ_FLAGGED(obj, 1 << eindex));
+	    push(&vals, OBJ_FLAGGED(obj, eindex));
 	    break;
 	  }
 	if (*extra_bits[eindex] == '\n')
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/spell_parser.c tbamud-3.54/src/spell_parser.c
--- tbamud-3.53/src/spell_parser.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/spell_parser.c	2007-11-29 03:02:08.000000000 +0100
@@ -386,7 +386,7 @@ void mag_objectmagic(struct char_data *c
 
     act("You recite $p which dissolves.", TRUE, ch, obj, 0, TO_CHAR);
     if (obj->action_description)
-      act(obj->action_description, FALSE, ch, obj, NULL, TO_ROOM);
+      act(obj->action_description, FALSE, ch, obj, tch, TO_ROOM);
     else
       act("$n recites $p.", FALSE, ch, obj, NULL, TO_ROOM);
 
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/spells.c tbamud-3.54/src/spells.c
--- tbamud-3.53/src/spells.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/spells.c	2007-11-29 03:02:08.000000000 +0100
@@ -299,7 +299,7 @@ ASPELL(spell_identify)
       send_to_char(ch, "Item will give you following abilities:  %s\r\n", bitbuf);
     }
 
-    sprintbitarray(GET_OBJ_EXTRA(obj), extra_bits, AF_ARRAY_MAX, bitbuf);
+    sprintbitarray(GET_OBJ_EXTRA(obj), extra_bits, EF_ARRAY_MAX, bitbuf);
     send_to_char(ch, "Item is: %s\r\n", bitbuf);
 
     send_to_char(ch, "Weight: %d, Value: %d, Rent: %d, Min. level: %d\r\n",
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/structs.h tbamud-3.54/src/structs.h
--- tbamud-3.53/src/structs.h	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/structs.h	2007-11-29 03:02:08.000000000 +0100
@@ -14,7 +14,7 @@
  * account the version and supply their own definition for the macro if used 
  * on an older version. You are supposed to compare this with the macro 
  * TBAMUD_VERSION() in utils.h. */
-#define _TBAMUD    0x030530 /* Major/Minor/Patchlevel - MMmmPP */
+#define _TBAMUD    0x030540 /* Major/Minor/Patchlevel - MMmmPP */
 
 /* If you want equipment to be automatically equipped to the same place
  * it was when players rented, set the define below to 1. */
@@ -485,14 +485,13 @@
 #define HISTORY_SIZE		5     /* Keep last 5 commands. */
 #define MAX_STRING_LENGTH	49152
 #define MAX_INPUT_LENGTH	512   /* Max length per *line* of input */
-#define MAX_RAW_INPUT_LENGTH	512   /* Max size of *raw* input */
+#define MAX_RAW_INPUT_LENGTH	1024  /* Max size of *raw* input */
 #define MAX_MESSAGES		60
 #define MAX_NAME_LENGTH		20
-/* ** MAX_PWD_LENGTH changed from 10 to 30 for ascii test - Sam ** */
 #define MAX_PWD_LENGTH		30
 #define MAX_TITLE_LENGTH	80
 #define HOST_LENGTH		40
-#define PLR_DESC_LENGTH		512
+#define PLR_DESC_LENGTH		4096
 #define MAX_SKILLS		200
 #define MAX_AFFECT		32
 #define MAX_OBJ_AFFECT		6     /* Used in obj_file_elem */
@@ -1047,6 +1046,7 @@ struct game_data {
   int load_into_inventory;/* Objects load in immortals inventory. */
   int track_through_doors;/* Track through doors while closed?    */
   int no_mort_to_immort;  /* Prevent mortals leveling to imms?    */
+  int disp_closed_doors;  /* Display closed doors in autoexit?    */
 
   char *OK;               /* When player receives 'Okay.' text.	  */
   char *NOPERSON;         /* 'No one by that name here.'	  */
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/utils.c tbamud-3.54/src/utils.c
--- tbamud-3.53/src/utils.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/utils.c	2007-11-29 03:02:08.000000000 +0100
@@ -526,10 +526,6 @@ int get_filename(char *filename, size_t 
     prefix = LIB_PLROBJS;
     suffix = SUF_OBJS;
     break;
-  case ALIAS_FILE:
-    prefix = LIB_PLRALIAS;
-    suffix = SUF_ALIAS;
-    break;
   case ETEXT_FILE:
     prefix = LIB_PLRTEXT;
     suffix = SUF_TEXT;
@@ -664,29 +660,29 @@ int room_is_dark(room_rnum room)
 int levenshtein_distance(char *s1, char *s2)
 {
   int s1_len = strlen(s1), s2_len = strlen(s2);
-  int *d = NULL;
-  int i, j, k;       
-
-  s1_len++;
-  s2_len++;
+  int **d, i, j; 
 
-  CREATE(d, int, (s1_len * s2_len));
+  CREATE(d, int *, s1_len + 1);
 
-  for (i = 0; i < s1_len; i++)
-    d[i] = i;   
-  for (j = 0; j < s2_len; j++)
-    d[j*s1_len] = j;   
+  for (i = 0; i <= s1_len; i++) {   
+    CREATE(d[i], int, s2_len + 1);
+    d[i][0] = i;
+  }
 
-  for (i = 1; i < s1_len; i++)
-    for (j = 1; j < s2_len; j++)
-      d[(j*s1_len)+i] = MIN(d[(j*s1_len) + i - 1] + 1, MIN(d[i+((j-1)*s1_len)]
-        + 1, d[((j-1)*s1_len) + i - 1] + ((s1[i - 1] == s2[j - 1]) ? 0 : 1)));
+  for (j = 0; j <= s2_len; j++)
+    d[0][j] = j; 
+  for (i = 1; i <= s1_len; i++)
+    for (j = 1; j <= s2_len; j++)
+      d[i][j] = MIN(d[i - 1][j] + 1, MIN(d[i][j - 1] + 1,
+      d[i - 1][j - 1] + ((s1[i - 1] == s2[j - 1]) ? 0 : 1)));
 
-  k = d[s1_len*s2_len-1];
+  i = d[s1_len][s2_len];
 
-  free (d);
+  for (j = 0; j <= s1_len; j++)
+    free(d[j]);
+  free(d);
 
-  return k; 
+  return i;
 }
 
 void char_from_furniture(struct char_data *ch)
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/utils.h tbamud-3.54/src/utils.h
--- tbamud-3.53/src/utils.h	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/utils.h	2007-11-29 03:02:08.000000000 +0100
@@ -108,10 +108,9 @@ void char_from_furniture(struct char_dat
 /* get_filename() */
 #define CRASH_FILE	 0
 #define ETEXT_FILE       1
-#define ALIAS_FILE	 2
-#define SCRIPT_VARS_FILE 3
-#define PLR_FILE         4
-#define MAX_FILES        5
+#define SCRIPT_VARS_FILE 2
+#define PLR_FILE         3
+#define MAX_FILES        4
 
 /* breadth-first searching */
 #define BFS_ERROR		(-1)
@@ -548,6 +547,7 @@ void char_from_furniture(struct char_dat
 #define CONFIG_OK               config_info.play.OK
 #define CONFIG_NOPERSON         config_info.play.NOPERSON
 #define CONFIG_NOEFFECT         config_info.play.NOEFFECT
+#define CONFIG_DISP_CLOSED_DOORS config_info.play.disp_closed_doors
 
 /* Crash Saves */
 #define CONFIG_FREE_RENT        config_info.csd.free_rent
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/zmalloc.c tbamud-3.54/src/zmalloc.c
--- tbamud-3.53/src/zmalloc.c	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/zmalloc.c	2007-11-29 03:02:08.000000000 +0100
@@ -2,11 +2,14 @@
 *  File: zmalloc.c                                         Part of tbaMUD *
 *  Usage: A simple memory allocation monitor.                             *
 *                                                                         *
-*  Version 2. Copyright 1996, 1998, 1999, 2000 Eric Murray.               *
+*  Version 2. Copyright 1996, 1998, 1999, 2000 Eric Murray ericm@lne.com  *
 **************************************************************************/
 
-/* local functions */
-void zfree_special (int *, char *, int);
+/*  Usage: To run tbaMUD in debug mode change the flags line in your Makefile
+ *  as below, make clean, and reboot.
+ *
+ *  Makefile: # Any special flags you want to pass to the compiler
+ *  Makefile: MYFLAGS = -Wall -DMEMORY_DEBUG */
 
 /* protect our calloc() and free() calls from recursive redefinition: */
 #define ZMALLOC_H
@@ -14,8 +17,12 @@ void zfree_special (int *, char *, int);
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 
-/* #define NO_MEMORY_PADDING */
+#define NUM_ZBUCKETS 256
+#define GET_ZBUCKET(addr) (((int)(addr) >> 3) & 0xFF)
+
+//#define NO_MEMORY_PADDING
 
 #ifndef NO_MEMORY_PADDING
 static unsigned char beginPad[4] = {
@@ -25,180 +32,206 @@ static unsigned char endPad[4] = {
   0xde, 0xad, 0xde, 0xad };
 #endif
 
-extern int errno;
-
-FILE * zfd;
+FILE *zfd = NULL;
 
 typedef struct meminfo {
   struct meminfo *next;
   int size; /* number of bytes malloced */
-  long addr;  /* address of memory returned */
+  unsigned char *addr;  /* address of memory returned */
   int frees; /* number of times that 'free' was called on this memory */
   char *file; /* file where malloc was called */
   int line; /* line in the code where malloc was called */
 } meminfo;
 
-static meminfo memlist;
-/* -1 not checked yet, 0 = no zmalloc, 1 = zmalloc */
-int zmallocstatus = -1;
+static meminfo *memlist[NUM_ZBUCKETS];
+
+/*
+ * 0 = only end summary
+ * 1 = show errors
+ * 2 = errors with dumps
+ * 3 = all of the above plus all mallocs/frees
+ */
+int zmalloclogging = 2;
 
 /* functions: */
-int getzmallocstatus(void);
-int * zmalloc(int len,char * file,int line);
-void zfree_special(int * what, char * file,int line);
-void zfree(int * what, char * file,int line);
+unsigned char *zmalloc(int len, char *file, int line);
+unsigned char *zrealloc(unsigned char *what, int len, char *file, int line);
+void zdump(meminfo *m);
+void zfree(unsigned char *what, char *file, int line);
 char *zstrdup(const char *src, char *file, int line);
-void zmalloc_check( void );
+void zmalloc_init(void);
+void zmalloc_check(void);
 void pad_check(meminfo *m);
 void zmalloc_free_list(meminfo *m);
 
-/* a chopped down version that works */
-int getzmallocstatus()
+
+void zmalloc_init(void)
 {
-  if (zmallocstatus == -1) {
-    zfd = fopen("test.log","w+");
-    zmallocstatus = 1;
-  }
-  return(zmallocstatus);
+  int i;
+
+  for (i = 0; i < NUM_ZBUCKETS; i++)
+    memlist[i] = NULL;
+
+  zfd = fopen("zmalloc.log","w+");
 }
 
-int * zmalloc(int len,char * file,int line)
+
+void zdump(meminfo *m)
 {
-  unsigned char * ret;
-  meminfo *m;
+#define MAX_ZDUMP_SIZE 32
+  const unsigned char *hextab = (unsigned char *)"0123456789ABCDEF";
+  unsigned char hexline[37], ascline[17], *hexp, *ascp, *inp;
+  int len, c = 1;
 
-  if (!zmallocstatus) {
-    /* zmalloc turned off */
-    ret = (unsigned char *)calloc(1,len);
-    return((int *)ret);
+  if (m->addr == NULL || m->size <= 0)
+    return;
+
+  hexp = hexline;
+  ascp = ascline;
+  inp = m->addr;
+  len = (m->size > MAX_ZDUMP_SIZE ? MAX_ZDUMP_SIZE : m->size);
+
+  for ( ; len > 0; len--, inp++, c++) {
+    *(hexp++) = hextab[(int) (*inp & 0xF0) >> 4];	/* high 4 bit */
+    *(hexp++) = hextab[(int) (*inp & 0x0F)];		/* low 4 bit */
+    if (c % 4 == 0) *(hexp++) = ' ';
+    *(ascp++) = isprint(*inp) ? *inp : '.';
+    if (c % 16 == 0 || len <= 1) {
+      *hexp = '\0';
+      *ascp = '\0';
+      fprintf(zfd, "     %-40.40s%s\n", hexline, ascline);
+      hexp = hexline;
+      ascp = ascline;
+    }
   }
+  fprintf(zfd, "\n");
+}
+
+
+unsigned char *zmalloc(int len, char *file, int line)
+{
+  unsigned char *ret;
+  meminfo *m;
 
 #ifndef NO_MEMORY_PADDING
-  ret = (unsigned char *)calloc(1,len + sizeof(beginPad) + sizeof(endPad));
+  ret = (unsigned char *) calloc(1, len + sizeof(beginPad) + sizeof(endPad));
 #else
-  ret = (unsigned char *)calloc(1,len);
+  ret = (unsigned char *) calloc(1, len);
 #endif
 
-  if (!ret)
+  if (!ret) {
     fprintf(zfd,"zmalloc: malloc FAILED");
-
+    return NULL;
+  }
 #ifndef NO_MEMORY_PADDING
   /* insert begin and end padding to detect buffer under/overruns: */
-  memcpy(ret,beginPad,sizeof(beginPad));
+  memcpy(ret, beginPad, sizeof(beginPad));
   ret +=  sizeof(beginPad);  /* make ret skip begin pad */
-  memcpy(ret + len,endPad,sizeof(endPad));
+  memcpy(ret + len, endPad, sizeof(endPad));
 #endif
 
-  if (getzmallocstatus() > 1)
+  if (zmalloclogging > 2)
     fprintf(zfd,"zmalloc: 0x%4.4x  %d bytes %s:%d\n",(int)ret,len,file,line);
 
-  m = (meminfo *)calloc(1,sizeof(meminfo));
+  m = (meminfo *) calloc(1, sizeof(meminfo));
   if (!m) {
     fprintf(zfd,"zmalloc: FAILED mem alloc for zmalloc struct... bailing!\n");
-    return((int*)0);
+    return NULL;
   }
-  m->next = &memlist;
-  m->addr = (long)ret;
-  m->size = (int)len;
-  m->file = (char *)strdup(file);
+  m->addr = ret;
+  m->size = len;
   m->frees = 0;
+  m->file = strdup(file);
   if (!m->file) {
     fprintf(zfd,"zmalloc: FAILED mem alloc for zmalloc struct... bailing!\n");
-    return((int*)0);
+    free(m);
+    return NULL;
   }
   m->line = line;
-  return((int *)ret);
+  m->next = memlist[GET_ZBUCKET(ret)];
+  memlist[GET_ZBUCKET(ret)] = m;
+  return (ret);
 }
 
-void zfree_special(int * what, char * file,int line)
+unsigned char *zrealloc(unsigned char *what, int len, char *file, int line)
 {
-  meminfo *m, *old;
-  unsigned char *addr;
-  int gotit = 0;
+  unsigned char *ret;
+  meminfo *m, *prev_m;
 
-  if (what == 0) {
-    fprintf(zfd,"zmalloc: Null pointer free'd: %s:%d\n", file, line);
-    return;
+  if (what) {
+    for (prev_m = NULL, m = memlist[GET_ZBUCKET(what)]; m; prev_m = m, m = m->next) {
+      if (m->addr == what) {
+#ifndef NO_MEMORY_PADDING
+	ret = (unsigned char *) realloc(what - sizeof(beginPad), len + sizeof(beginPad) + sizeof(endPad));
+#else
+	ret = (unsigned char *) realloc(what, len);
+#endif
+	if (!ret) {
+	  fprintf(zfd,"zrealloc: FAILED for 0x%4.4x %d bytes mallocd at %s:%d,\n"
+		      "          %d bytes reallocd at %s:%d.\n",
+		    (int)m->addr, m->size, m->file, m->line, len, file, line);
+	  if (zmalloclogging > 1) zdump(m);
+	  return NULL;
   }
+#ifndef NO_MEMORY_PADDING
+	/* insert begin and end padding to detect buffer under/overruns: */
+	memcpy(ret, beginPad, sizeof(beginPad));
+	ret +=  sizeof(beginPad);  /* make ret skip begin pad */
+	memcpy(ret + len, endPad, sizeof(endPad));
+#endif
+	if (zmalloclogging > 2)
+	  fprintf(zfd,"zrealloc: 0x%4.4x %d bytes mallocd at %s:%d, %d bytes reallocd at %s:%d.\n",
+		    (int)m->addr, m->size, m->file, m->line, len, file, line);
+
+	m->addr = ret;
+	m->size = len;
+	if (m->file) free(m->file);
+	m->file = strdup(file);
+	m->line = line;
 
-  if (!getzmallocstatus()) {
-    free(what);
-  } else {
-    /* look up allocated mem in list: */
-    old = m = &memlist;
-    if (m == (meminfo *)0) {
-      /* no memlist */
-      free(what);
-    } else {
-      for(; m  ; m = m->next) {
-        if (m->addr == (long)what) {
-          /* got it.  Print it if verbose: */
-          addr = (unsigned char *)m->addr;
-
-          fprintf(zfd,"zmalloc: Freed 0x%4.4x %d bytes mallocd@%s:%d\n",
-                        (int)addr,m->size,m->file,m->line);
-          fprintf(zfd," free'd from %s:%d\n",
-                        file, line);
-
-
-          /* check the padding: */
-          pad_check(m);
+        /* detach node */
+        if (prev_m)
+          prev_m->next = m->next;
+        else
+          memlist[GET_ZBUCKET(what)] = m->next;
 
-          /* note that we freed the memory */
-          m->frees++;
+        /* readd to proper bucket */
+        m->next = memlist[GET_ZBUCKET(ret)];
+        memlist[GET_ZBUCKET(ret)] = m;
 
-          /* check to see if it was freed > once */
-          if (m->frees > 1) {
-            fprintf(zfd," ERR: multiple frees! 0x%4.4x %d bytes: %s:%d\n",
-                        (int)addr, m->size, m->file, m->line);
-            fprintf(zfd," free'd from %s:%d\n",
-                        file, line);
-          }
-          gotit++;
-          if (!m)
-            break;
-        }
-      }
-      if (!gotit && m) {
-         fprintf(zfd,"zmalloc: ERR: Freed unallocated memory");
-         fprintf(zfd," @0x%4.4x %d bytes %s:%d\n",
-          (int)what,m->size,m->file,m->line);
-      }
-      else if (gotit > 1) {
-        /* this shouldn't happen, eh? */
-        fprintf(zfd," ERR: Multiply-allocd memory!\n");
+	/* could continue the loop to check for multiply-allocd memory */
+	/* but that's highly improbable so lets just return instead. */
+	return (ret);
       }
     }
   }
+
+  /* NULL or invalid pointer given */
+  fprintf(zfd,"zrealloc: invalid pointer 0x%4.4x, %d bytes to realloc at %s:%d.\n",
+	    (int)what, len, file, line);
+
+  return (zmalloc(len, file, line));
 }
-void zfree(int * what, char * file,int line)
+
+/* doesn't actually free memory */
+void zfree(unsigned char *what, char *file, int line)
 {
-  meminfo *m, *old;
-  unsigned char *addr;
+  meminfo *m;
   int gotit = 0;
 
-  if (what == 0) {
-    fprintf(zfd,"zmalloc: Null pointer free'd: %s:%d\n", file, line);
+  if (!what) {
+    fprintf(zfd,"zfree: ERR: Null pointer free'd: %s:%d.\n", file, line);
     return;
   }
 
-  if (!getzmallocstatus()) {
-    free(what);
-  } else {
     /* look up allocated mem in list: */
-    old = m = &memlist;
-    if (m == (meminfo *)0) {
-      /* no memlist */
-      free(what);
-    } else {
-      for(; m  ; m = m->next) {
-        if (m->addr == (long)what) {
+  for (m = memlist[GET_ZBUCKET(what)]; m; m = m->next) {
+    if (m->addr == what) {
           /* got it.  Print it if verbose: */
-          addr = (unsigned char *)m->addr;
-          if (getzmallocstatus() > 1)
-            fprintf(zfd,"zmalloc: Freed 0x%4.4x %d bytes mallocd@%s:%d\n",
-                        (int)addr,m->size,m->file,m->line);
-
+      if (zmalloclogging > 2) {
+	fprintf(zfd,"zfree: Freed 0x%4.4x %d bytes mallocd at %s:%d, freed at %s:%d\n",
+		    (int)m->addr, m->size, m->file, m->line, file, line);
+      }
           /* check the padding: */
           pad_check(m);
 
@@ -207,51 +240,39 @@ void zfree(int * what, char * file,int l
 
           /* check to see if it was freed > once */
           if (m->frees > 1) {
-            fprintf(zfd," ERR: multiple frees! 0x%4.4x %d bytes: %s:%d\n",
-                        (int)addr, m->size, m->file, m->line);
-            fprintf(zfd," free'd from %s:%d\n",
-                        file, line);
+        fprintf(zfd,"zfree: ERR: multiple frees! 0x%4.4x %d bytes\n"
+		    "       mallocd at %s:%d, freed at %s:%d.\n",
+                    (int)m->addr, m->size, m->file, m->line, file, line);
+	if (zmalloclogging > 1) zdump(m);
           }
           gotit++;
-          if (!m)
-            break;
-        }
       }
-      if (!gotit && m) {
-         fprintf(zfd,"zmalloc: ERR: Freed unallocated memory");
-         fprintf(zfd," @0x%4.4x %d bytes %s:%d\n",
-          (int)what,m->size,m->file,m->line);
+  } /* for.. */
+
+  if (!gotit) {
+    fprintf(zfd,"zfree: ERR: attempt to free unallocated memory 0x%4.4x at %s:%d.\n",
+		(int)what, file, line);
       }
-      else if (gotit > 1) {
+  if (gotit > 1) {
         /* this shouldn't happen, eh? */
-        fprintf(zfd," ERR: Multiply-allocd memory!\n");
-      }
-    }
+    fprintf(zfd,"zfree: ERR: Multiply-allocd memory 0x%4.4x.\n", (int)what);
   }
 }
 
-/* zstrdup */
+
 char *zstrdup(const char *src, char *file, int line)
 {
     char *result;
 #ifndef NO_MEMORY_STRDUP
-  if (!getzmallocstatus()) {
-    result = (char*)malloc(strlen(src) + 1);
-    if (result == (char*)0)
-	return (char*)0;
-    strcpy(result, src);  /* strcpy ok, size checked above */
-    return result;
-  } else {
     result = (char*)zmalloc(strlen(src) + 1, file, line);
-    if (result == (char*)0)
-	return (char*)0;
+  if (!result)
+    return NULL;
     strcpy(result, src);
     return result;
-  }
 #else
     result = (char*)malloc(strlen(src) + 1);
-    if (result == (char*)0)
-	return (char*)0;
+  if (!result)
+    return NULL;
     strcpy(result, src);  /* strcpy ok, size checked above */
     return result;
 #endif
@@ -257,27 +278,39 @@ char *zstrdup(const char *src, char *fil
 #endif
 }
 
+
 void zmalloc_check()
 {
-  meminfo *m;
+  meminfo *m, *next_m;
   char *admonishemnt;
-  int total_leak = 0;
-  int num_leaks = 0;
+  int total_leak = 0, num_leaks = 0, i;
 
-  if (getzmallocstatus() > 0) {
-    /* look up allocated mem in list: */
-    for(m = &memlist; m ; m = m->next) {
+  fprintf(zfd, "\n------------ Checking leaks ------------\n\n");
+
+  for (i = 0; i < NUM_ZBUCKETS; i++) {
+    for (m = memlist[i]; m; m = next_m) {
+      next_m = m->next;
       if (m->addr != 0 && m->frees <= 0) {
         fprintf(zfd,"zmalloc: UNfreed memory 0x%4.4x %d bytes mallocd at %s:%d\n",
-          (int)m->addr,m->size,m->file,m->line);
+		(int)m->addr, m->size, m->file, m->line);
+        if (zmalloclogging > 1) zdump(m);
 
         /* check padding on un-freed memory too: */
         pad_check(m);
 
         total_leak += m->size;
-        num_leaks ++;
+        num_leaks++;
       }
+#ifndef NO_MEMORY_PADDING
+      if (m->addr) free(m->addr - sizeof(beginPad));
+#else
+      if (m->addr) free(m->addr);
+#endif
+      if (m->file) free(m->file);
+      free(m);
     }
+  }
+
     if (total_leak) {
       if (total_leak > 10000)
         admonishemnt = "you must work for Microsoft.";
@@ -289,17 +322,20 @@ void zmalloc_check()
         admonishemnt = "the X consortium has a job for you...";
       else
         admonishemnt = "close, but not there yet.";
-      fprintf(zfd,"zmalloc: %d leaks totalling %d bytes... %s\n",num_leaks,total_leak,
-        admonishemnt);
+    fprintf(zfd,"zmalloc: %d leaks totalling %d bytes... %s\n",
+		num_leaks, total_leak, admonishemnt);
     }
     else {
       fprintf(zfd,"zmalloc: Congratulations: leak-free code!\n");
     }
+
+  if (zfd) {
+    fflush(zfd);
+    fclose(zfd);
   }
-  /* free up our own internal list */
-  zmalloc_free_list(&memlist);
 }
 
+
 void pad_check(meminfo *m)
 {
 #ifndef NO_MEMORY_PADDING
@@ -303,85 +339,62 @@ void zmalloc_check()
 void pad_check(meminfo *m)
 {
 #ifndef NO_MEMORY_PADDING
-  unsigned char *addr = (unsigned char *)m->addr;
-
-  /* check the padding: */
-  if (memcmp((int *)(addr - sizeof(beginPad)),
-      beginPad, sizeof(beginPad)) != 0)
-    fprintf(zfd," ERR: beginPad was modified!\n");
-  if (memcmp((int *)(addr + m->size),endPad,
-      sizeof(endPad)) != 0)
-    fprintf(zfd," ERR: endPad was modified!\n");
+  if (memcmp(m->addr - sizeof(beginPad), beginPad, sizeof(beginPad)) != 0) {
+    fprintf(zfd,"pad_check: ERR: beginPad was modified! (mallocd@ %s:%d)\n", m->file, m->line);
+    if (zmalloclogging > 1) zdump(m);
+  }
+  if (memcmp(m->addr + m->size, endPad, sizeof(endPad)) != 0) {
+    fprintf(zfd,"pad_check: ERR: endPad was modified! (mallocd@ %s:%d)\n", m->file, m->line);
+    if (zmalloclogging > 1) zdump(m);
+  }
 #endif
 }
 
-void zmalloc_free_list(meminfo *m)
-{
-  meminfo *old;
-  for( m = m->next ; m  ; ) {
-    old = m;
-    m = m->next;
-    free(old->file);
-    free(old);
-  }
-}
 
 #ifdef ZTEST
 #undef ZMALLOC_H
 
 #include "zmalloc.h"
 
-main()
+int main()
 {
-  unsigned char * tmp;
+  unsigned char * shit;
 
+  zmalloc_init();
 
-  printf("Testing Zmalloc.\n");
-  printf("Malloc test..");
-  printf("You should see no error here.\n");
-  tmp = (unsigned char*)malloc(200);
-  free(tmp);
-
-  printf("Free free mem test...\n");
-  printf("You should see an ERR: multiple frees here\n");
-  tmp = (unsigned char*)malloc(200);
-  free(tmp);
-  free(tmp);
-
-/*
-  fprintf(zfd,"\nFree unallocated mem test \n");
-  tmp += 4;
-  free(tmp);
-*/
-
-  printf("Unfreed mem test...\n");
-  printf("You should see an \"UNfreed mem at line %d\" (at end) because of this\n",__LINE__+1);
-  tmp = (unsigned char*)malloc(200);
-
-  printf("Buffer overrun test 1...\n");
-  printf("You should see an ERR:endPad here\n");
-  tmp = (unsigned char*)malloc(200);
-  tmp[200] = 0xfa;
-  free(tmp);
-
-  printf("Buffer overrun test 2...\n");
-  printf("You should see an ERR:endPad here\n");
-  tmp = (unsigned char*)malloc(200);
-  tmp[215] = 0xbb;
-  free(tmp);
-
-  printf("Buffer underrun test 1...\n");
-  printf("You should see an ERR:beginPad here\n");
-  tmp = (unsigned char*)malloc(200);
-  tmp[-10] = 0x0f;
-  free(tmp);
-
-  printf("Buffer underrun test 2...\n");
-  printf("You should see an ERR:beginPad here\n");
-  tmp = (unsigned char*)malloc(200);
-  tmp[-1] = 0x00;
-  free(tmp);
+/* You should see no error here. */
+  shit = (unsigned char*)malloc(200);
+  free(shit);
+
+/* Multiple frees test */
+  shit = (unsigned char*)malloc(200);
+  strcpy(shit, "This should show up in the dump but truncated to MAX_ZDUMP_SIZE chars");
+  free(shit);
+  free(shit);
+
+/* Free unallocated mem test */
+  shit += 4;
+  free(shit);
+
+/* Unfreed mem test... You should see "UNfreed mem at line 370" (at end) because of this */
+  shit = (unsigned char*)malloc(200);
+  strcpy(shit, "This is unfreed memory!");
+
+/* Buffer overrun test... You should see an ERR:endPad here */
+  shit = (unsigned char*)malloc(200);
+  shit[202] = 0xbb;
+  free(shit);
+
+/* Buffer underrun test... You should see an ERR:beginPad here */
+  shit = (unsigned char*)malloc(200);
+  shit[-3] = 0x0f;
+  free(shit);
+
+/* Free NULL pointer test... */
+  shit = NULL;
+  free(shit);
 
+  printf("Test completed. See zmalloc.log for the messages.\n");
 
   zmalloc_check();
   exit(0);
diff -BburpN --exclude=.svn --exclude=world --exclude=help tbamud-3.53/src/zmalloc.h tbamud-3.54/src/zmalloc.h
--- tbamud-3.53/src/zmalloc.h	2007-07-02 15:58:52.000000000 +0200
+++ tbamud-3.54/src/zmalloc.h	2007-11-29 03:02:08.000000000 +0100
@@ -2,20 +2,23 @@
 *  File: zmalloc.h                                         Part of tbaMUD *
 *  Usage: A simple memory allocation monitor, header.                     *
 *                                                                         *
-*  Version 1.1 Copyright 1996, 1998, 1999, 2000 Eric Murray.              *
+*  Version 1.1 Copyright 1996, 1998, 1999, 2000 Eric Murray ericm@lne.com *
 **************************************************************************/
 
 #ifndef ZMALLOC_H
 #define ZMALLOC_H
 
-int *zmalloc(int, char *, int);
-void zfree(int *, char *, int);
-int zmalloc_check();
-char *zstrdup(const char*, char*, int);
+unsigned char *zmalloc(int, char *, int);
+unsigned char *zrealloc(unsigned char *, int, char *, int);
+void zfree(unsigned char *, char *, int);
+void zmalloc_init(void);
+void zmalloc_check(void);
+char *zstrdup(const char *, char *, int);
 
 #define malloc(x)  zmalloc((x),__FILE__,__LINE__)
 #define calloc(n,x) zmalloc((n*x),__FILE__,__LINE__)
-#define free(x) zfree((int *)(x),__FILE__,__LINE__)
+#define realloc(r,x)	zrealloc((unsigned char *)(r),(x),__FILE__,__LINE__)
+#define free(x)		zfree((unsigned char *)(x),__FILE__,__LINE__)
 #undef strdup
 #define strdup(x) zstrdup((x), __FILE__, __LINE__)
 
