diff -crN nakedmudv1.4/.depend nakedmudv1.5/.depend
*** nakedmudv1.4/.depend	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/.depend	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,182 ****
- gameloop.o: gameloop.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h socket.h world.h character.h object.h utils.h text_editor.h \
-   save.h handler.h inform.h log.h races.h action.h event.h auxiliary.h \
-   storage.h time/mudtime.h scripts/script.h olc/olc.h alias/alias.h \
-   char_vars/char_vars.h socials/socials.h fight/fight.h
- mud.o: mud.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h utils.h text_editor.h storage.h
- utils.o: utils.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h character.h object.h world.h zone.h room.h exit.h socket.h \
-   utils.h text_editor.h save.h handler.h inform.h dialog.h event.h \
-   action.h help.h fight/stats.h fight/fight.h scripts/script.h
- interpret.o: interpret.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h utils.h text_editor.h character.h socket.h room.h \
-   movement.h commands.h action.h scripts/script.h alias/alias.h
- handler.o: handler.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h handler.h room.h exit.h extra_descs.h character.h object.h \
-   utils.h text_editor.h body.h items.h inform.h scripts/script.h
- inform.o: inform.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h character.h object.h world.h room.h exit.h extra_descs.h \
-   utils.h text_editor.h body.h races.h items.h handler.h socket.h \
-   inform.h log.h time/mudtime.h
- movement.o: movement.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h character.h world.h room.h exit.h movement.h handler.h \
-   inform.h builder.h utils.h text_editor.h items.h object.h \
-   scripts/script.h
- action.o: action.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h utils.h text_editor.h character.h action.h
- mccp.o: mccp.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h socket.h utils.h text_editor.h
- save.o: save.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h character.h world.h utils.h text_editor.h handler.h body.h \
-   object.h room.h storage.h
- socket.o: socket.c wrapsock.h mud.h property_table.h list.h hashmap.h \
-   hashtable.h character.h utils.h text_editor.h socket.h olc/olc.h
- io.o: io.c mud.h wrapsock.h property_table.h list.h hashmap.h hashtable.h \
-   utils.h text_editor.h
- strings.o: strings.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h utils.h text_editor.h
- event.o: event.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h utils.h text_editor.h character.h event.h
- cmd_comm.o: cmd_comm.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h utils.h text_editor.h handler.h inform.h character.h \
-   world.h dialog.h scripts/script.h
- cmd_manip.o: cmd_manip.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h utils.h text_editor.h handler.h inform.h \
-   character.h items.h exit.h world.h room.h extra_descs.h object.h
- cmd_misc.o: cmd_misc.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h character.h socket.h utils.h text_editor.h save.h event.h \
-   handler.h
- text_editor.o: text_editor.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h socket.h text_editor.h utils.h scripts/script.h \
-   olc/olc.h
- builder.o: builder.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h world.h zone.h room.h exit.h movement.h builder.h \
-   character.h object.h handler.h inform.h utils.h text_editor.h races.h \
-   items.h dialog.h scripts/script.h scripts/script_set.h
- admin.o: admin.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h world.h inform.h character.h handler.h utils.h \
-   text_editor.h log.h socket.h save.h event.h action.h storage.h
- help.o: help.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h character.h help.h
- items.o: items.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h object.h items.h
- races.o: races.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h races.h body.h utils.h text_editor.h
- log.o: log.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h utils.h text_editor.h character.h storage.h log.h
- auxiliary.o: auxiliary.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h utils.h text_editor.h storage.h auxiliary.h
- world.o: world.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h zone.h room.h character.h object.h dialog.h utils.h \
-   text_editor.h storage.h world.h scripts/script.h
- character.o: character.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h utils.h text_editor.h body.h races.h handler.h \
-   auxiliary.h storage.h room.h character.h
- room.o: room.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h exit.h extra_descs.h utils.h text_editor.h handler.h \
-   character.h auxiliary.h storage.h room_reset.h room.h scripts/script.h
- exit.o: exit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h utils.h text_editor.h storage.h exit.h
- extra_descs.o: extra_descs.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h utils.h text_editor.h storage.h extra_descs.h
- object.o: object.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h extra_descs.h utils.h text_editor.h items.h body.h \
-   handler.h storage.h auxiliary.h object.h
- body.o: body.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h body.h utils.h text_editor.h
- zone.o: zone.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h storage.h object.h character.h room.h zone.h utils.h \
-   text_editor.h dialog.h scripts/script.h
- dialog.o: dialog.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h utils.h text_editor.h dialog.h storage.h
- room_reset.o: room_reset.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h utils.h text_editor.h storage.h room.h world.h \
-   character.h body.h object.h exit.h handler.h items.h room_reset.h
- list.o: list.c list.h
- property_table.o: property_table.c mud.h wrapsock.h property_table.h \
-   list.h hashmap.h hashtable.h utils.h text_editor.h
- hashtable.o: hashtable.c list.h hashtable.h
- hashmap.o: hashmap.c list.h hashmap.h
- storage.o: storage.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h utils.h text_editor.h storage.h
- time.o: time/time.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h utils.h text_editor.h inform.h character.h room.h event.h \
-   storage.h auxiliary.h time/mudtime.h
- alias.o: alias/alias.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h utils.h text_editor.h auxiliary.h storage.h character.h \
-   alias/alias.h
- char_vars.o: char_vars/char_vars.c mud.h wrapsock.h property_table.h \
-   list.h hashmap.h hashtable.h utils.h text_editor.h character.h \
-   storage.h auxiliary.h char_vars/char_vars.h
- socials.o: socials/socials.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h utils.h text_editor.h storage.h handler.h \
-   inform.h character.h socials/socials.h
- dedit.o: olc/dedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h socket.h utils.h text_editor.h dialog.h olc/olc.h
- edesc_edit.o: olc/edesc_edit.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h socket.h utils.h text_editor.h extra_descs.h \
-   olc/olc.h
- exedit.o: olc/exedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h exit.h socket.h utils.h text_editor.h olc/olc.h
- medit.o: olc/medit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h world.h character.h socket.h utils.h text_editor.h races.h \
-   dialog.h olc/olc.h scripts/script_set.h scripts/script.h
- oedit.o: olc/oedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h world.h object.h extra_descs.h socket.h utils.h \
-   text_editor.h body.h items.h olc/olc.h scripts/script_set.h \
-   scripts/script.h
- redit.o: olc/redit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h world.h room.h exit.h room_reset.h extra_descs.h socket.h \
-   utils.h text_editor.h olc/olc.h scripts/script_set.h scripts/script.h \
-   time/mudtime.h
- zedit.o: olc/zedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h world.h zone.h socket.h utils.h text_editor.h olc/olc.h
- ssedit.o: olc/ssedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h socket.h world.h utils.h text_editor.h olc/olc.h \
-   scripts/script.h scripts/script_set.h
- scedit.o: olc/scedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h socket.h utils.h text_editor.h olc/olc.h scripts/script.h
- resedit.o: olc/resedit.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h socket.h utils.h text_editor.h world.h object.h \
-   character.h room_reset.h olc/olc.h
- socedit.o: olc/socedit.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h socket.h utils.h text_editor.h character.h \
-   socials/socials.h olc/olc.h
- olc.o: olc/olc.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h socket.h object.h character.h world.h zone.h room.h \
-   room_reset.h exit.h extra_descs.h dialog.h olc/olc.h scripts/script.h \
-   scripts/script_set.h socials/socials.h
- script_set.o: scripts/script_set.c mud.h wrapsock.h property_table.h \
-   list.h hashmap.h hashtable.h utils.h text_editor.h world.h \
-   scripts/script_set.h scripts/script.h
- script.o: scripts/script.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h utils.h text_editor.h socket.h character.h room.h \
-   object.h storage.h auxiliary.h scripts/script.h scripts/script_set.h \
-   scripts/pychar.h scripts/pyroom.h scripts/pyobj.h scripts/pymud.h
- pychar.o: scripts/pychar.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h world.h room.h character.h object.h items.h \
-   races.h handler.h utils.h text_editor.h scripts/script.h \
-   scripts/pychar.h scripts/pyroom.h scripts/pyobj.h char_vars/char_vars.h
- pyobj.o: scripts/pyobj.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h world.h room.h character.h object.h races.h \
-   handler.h utils.h text_editor.h scripts/script.h scripts/pychar.h \
-   scripts/pyroom.h scripts/pyobj.h
- pymud.o: scripts/pymud.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h scripts/script.h scripts/pyroom.h \
-   scripts/pychar.h scripts/pyobj.h
- pyroom.o: scripts/pyroom.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h world.h room.h exit.h character.h races.h \
-   handler.h utils.h text_editor.h scripts/script.h scripts/pyroom.h \
-   scripts/pychar.h scripts/pyobj.h
- stats.o: fight/stats.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h utils.h text_editor.h character.h storage.h auxiliary.h \
-   handler.h event.h fight/stats.h fight/fight.h
- fight.o: fight/fight.c mud.h wrapsock.h property_table.h list.h hashmap.h \
-   hashtable.h utils.h text_editor.h world.h handler.h character.h \
-   inform.h event.h action.h body.h fight/fight.h fight/stats.h
- cmd_fight.o: fight/cmd_fight.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h utils.h text_editor.h handler.h inform.h \
-   character.h body.h object.h fight/stats.h fight/fight.h
- mob_fight.o: fight/mob_fight.c mud.h wrapsock.h property_table.h list.h \
-   hashmap.h hashtable.h utils.h text_editor.h fight/fight.h fight/stats.h
--- 0 ----
diff -crN nakedmudv1.4/doc/scripts.txt nakedmudv1.5/doc/scripts.txt
*** nakedmudv1.4/doc/scripts.txt	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/doc/scripts.txt	2010-11-01 15:54:17.000000000 -0500
***************
*** 60,66 ****
  example: ch.setvar('blackjack_winnings', 100)
  Allows you to store information on a character, regarding stuff that happened
  during the script. These variables save over reboots and crashes. The only
! restriction is that the variables must be numeric values, or strings.
  
  RETRIEVING SCRIPT DATA
  ch.getvar('varname')
--- 60,66 ----
  example: ch.setvar('blackjack_winnings', 100)
  Allows you to store information on a character, regarding stuff that happened
  during the script. These variables save over reboots and crashes. The only
! restriction is that the variables must be integer values.
  
  RETRIEVING SCRIPT DATA
  ch.getvar('varname')
Binary files nakedmudv1.4/.DS_Store and nakedmudv1.5/.DS_Store differ
diff -crN nakedmudv1.4/.gdb_history nakedmudv1.5/.gdb_history
*** nakedmudv1.4/.gdb_history	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/.gdb_history	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,256 ****
- down
- up
- up
- up
- print room->auxiliary_data
- down
- print line
- print data
- info local
- bt
- quit
- run
- quit
- run
- bt
- print line
- quit
- run
- print line
- quit
- run
- bt
- quit
- run
- bt
- down
- up
- up
- up
- up
- print world
- bt
- quit
- run
- quit
- run
- bt
- quit
- run
- quit
- run
- quit
- run
- quit
- run
- bt
- quit
- run
- bt
- qiut
- quit
- quit
- run
- bt
- quit
- run
- quit
- run
- bt
- quit
- run
- bt
- print buflen
- up
- up
- up
- up
- up
- print buflen
- print buf
- print i
- quit
- run
- quit
- run
- bt
- bt
- quit
- run
- bt
- quit
- run
- bt
- bt
- print dsock->player
- print dsock->page
- print dsock->page_string
- q
- run
- print dsock->page_string
- print dsock->player
- print dsock
- bt
- quit
- run
- quit
- run
- bt
- quit
- run
- bt
- print dsock
- print dsock->control
- print rFd
- print dsock->outbuf
- print dsock->inbuf
- print dsock->state
- print dsock->indent
- quit
- run
- clear
- bt
- quit
- run
- bt
- quit
- run
- quit
- run
- quit
- run
- quit
- run
- bt
- quit
- run
- quit
- run
- bt
- quit
- run
- quit
- run 3000
- quit
- run 4000
- bt
- bt
- up
- print i
- down
- print i
- print num
- up
- up
- up
- bt
- print i
- print param
- print one_arg
- print arg
- print one_arg
- quit
- run 3000
- quit
- run 4000
- bt
- quit
- run 4000
- quit
- run 3000
- bt
- quit
- run 4000
- bt
- quit
- run 4000
- quit
- run
- quit
- run
- quit
- run
- quit
- bt
- info local
- bt
- ls -l
- bt
- down
- up
- up
- bt
- quit
- bt
- quit
- run
- bt
- up
- print event
- print event->owner
- print event->data
- print event->arg
- print event->delay
- print events
- print events->size
- print events->head->elem
- print events->head->removed
- print events->head->next->removed
- print events->head->next->next->removed
- print events->head->next->next->next->removed
- print events->head->next->next->next->next->removed
- print events->head->next->next->next->next->next->removed
- print events->head->next->next->next->next->next->next->removed
- print events->head->next->next->next->next->next->next->next->removed
- print events->head->next->next->next->next->next->next->next->next->removed
- quit
- run
- quit
- run
- bt
- quit
- run
- print event
- print event->owner
- print sizeof(*event->owner)
- bt
- print ev_i->L->size
- print ev_i->curr
- print ev_i->L->head
- print ev_i->L->head->next
- print ev_i->L->head->next->removed
- print ev_i->L->head->removed
- bt
- print event
- print event->delay
- print time
- info local
- info global
- help info
- info all-registers
- man info
- help info
- info thread
- info stack
- info scope
- info
- quit
- run
- print 0x30bfa0
- print 0x30bfa0
- quit
- run
- print event
- quit
- run
- quit
- run
- print node
- print node->next
- quit
- run
- quit
- run
- quit
- run
- quit
--- 0 ----
diff -crN nakedmudv1.4/help/ANSI nakedmudv1.5/help/ANSI
*** nakedmudv1.4/help/ANSI	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/help/ANSI	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,14 ****
- NakedMud(tm) supports ANSI colors, and you can access them by using the
- '{{' character, followed by the colorkey from the table below.
- 
- Yellow    {yy {YY{n
- Blue      {bb {BB{n
- Green     {gg {GG{n
- Red       {rr {RR{n
- Cyan      {cc {CC{n
- Purple    {pp {PP{n
- Dark      {dd {DD{n
- White     {ww {WW{n
- 
- The 'n' key is the default NakedMud(tm) color, and the mudcolor will
- always revert to this color at the end of a string.
--- 0 ----
diff -crN nakedmudv1.4/help/CREDITS nakedmudv1.5/help/CREDITS
*** nakedmudv1.4/help/CREDITS	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/help/CREDITS	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,3 ****
- Thanks go out to Brian Graversen for creating SocketMud(tm), which NakedMud(tm)
- was built on top of. I know nothing (yet) about TCP/IP, and SocketMud(tm) made 
- my life that much easier.
--- 0 ----
diff -crN nakedmudv1.4/help/DELAY nakedmudv1.5/help/DELAY
*** nakedmudv1.4/help/DELAY	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/help/DELAY	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,6 ****
- usage: delay [seconds] [command]
- 
- example:
-   delay 2 say hello, world!
- 
- Allows the user to prepare a command to be executed in the future.
--- 0 ----
Binary files nakedmudv1.4/help/.DS_Store and nakedmudv1.5/help/.DS_Store differ
diff -crN nakedmudv1.4/help/JOBO nakedmudv1.5/help/JOBO
*** nakedmudv1.4/help/JOBO	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/help/JOBO	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,9 ****
- Jobo aka Brian Graversen is the author of SocketMud(tm), which is a
- bareboned mud codebase. The codebase was made mainly for fun and to
- learn from the experience itself.
- 
- Feel free to use the codebase for whatever purposes you have in mind,
- and should you ever make a real mud from it, send me a mail and tell
- me about it at jobo@daimi.au.dk
- 
- Brian Graversen
--- 0 ----
diff -crN nakedmudv1.4/help/LOOK nakedmudv1.5/help/LOOK
*** nakedmudv1.4/help/LOOK	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/help/LOOK	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,19 ****
- Look allows you to glean extra information about your environment, as well as
- people and items in it. Look can be used to peer into containers, glance at
- your room, examine the finer details of an item, among other things.
- 
- Usage: 
-   > look [at the <target>] [in the <container>] [on the <thing or person>]
- 
- Examples: 
-   > look
-   > look bob
-   > look at bob
-   > look at the bob
-   > look at the mole on bob
-   > look in sheath
-   > look hilt on sword in sheath
-   > look at the hilt on the sword in the sheath
- 
- Looking at an object that is a container will also peer inside and list its
- contents (provided the container is opened).
--- 0 ----
diff -crN nakedmudv1.4/help/MCCP nakedmudv1.5/help/MCCP
*** nakedmudv1.4/help/MCCP	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/help/MCCP	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,13 ****
- The Mud Client Compression Protocol has the purpose of reducing the
- bandwidth usage of the mudserver, by using an MCCP-complient mudclient,
- the data send to you will be compressed by 80-85%, and thus not only
- reducing the amount of data processed by the server, but also greatly
- reduce the amount of data you need to download (i.e. less lag for you).
- 
- This MUD supports both version 1 and 2 of the compression protocol,
- and any client supporting either of those version can be used to
- enable compression. Most clients enables compression automaticly,
- but some require that you type 'compress'. The same command can also
- be used to disable compression.
- 
- MCCP was created by Oliver Jowett
--- 0 ----
diff -crN nakedmudv1.4/help/OLC nakedmudv1.5/help/OLC
*** nakedmudv1.4/help/OLC	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/help/OLC	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,18 ****
- On-Line Creation (OLC) is a set of utilities designed to allow builders to
- design their zones while on the MUD. OLC includes utilities for editing zones,
- rooms, objects, mobiles, scripts, and dialogues. The following commands are
- available to the online builder
- 
-       edits                command                 listing command
-       rooms		   redit		   rlist <zone vnum>
-       objects		   oedit		   olist <zone vnum>
-       mobiles		   medit		   mlist <zone vnum>
-       scripts		   scedit		   sclist <zone vnum>
-       dialogs		   dedit		   dlist <zone vnum>
-       zones		   zedit		   zlist
- 
- To create a new zone, a special command must be used. It's format is:
-   zedit new [zone num] [min vnum] [max vnum]
- 
- All other OLC commands can set up new things (rooms, objects, mobiles, etc..)
- simply by using the corresponding edit command on a vnum that has not been used.
--- 0 ----
diff -crN nakedmudv1.4/lib/misc/help nakedmudv1.5/lib/misc/help
*** nakedmudv1.4/lib/misc/help	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/lib/misc/help	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,203 ----
+ helpfiles:=
+   keywords : write
+   editor   : Alister
+   timestamp: Jan 29 18:28:26
+   info     :~
+     usage: write
+     
+     With write, you can enter a text editor and compose messages. Write is useful
+     for writing helpfiles, sending mail to friends (coming soon), and posting
+     messages on bulletin boards (also coming soon).
+   -
+   keywords : socials, soclink, socunlink
+   editor   : Alister
+   timestamp: Jan 29 18:53:22
+   info     :~
+     There are 9 fields assocciated with social editing; two are for messages when
+     the social has no target. Two are for messages when the target is the character
+     performing the social. Three are for situations when a target other than the
+     character is provided for the social. The remaining two are the minimum and
+     maximum positions the socials can be used from. If a social is not to have a
+     target, the "target" fields can be left blank. Likewise, if the social is never
+     to have the character as a target, the assocciated fields can be left blank.
+     When trying to reference character information, the following symbols can be
+     used:
+     
+       $n character name
+       $N target name
+       $e character he/she
+       $E target he/she
+       $m character him/her
+       $M target him/her
+       $s character his/hers
+       $S target his/hers
+     
+     To see examples of how to write socials, check some of the pre-existing ones.
+     To generate a list of all socials, type "socials".
+     
+     If you would like more than one command to trigger the same social, you can
+     link a new command to a pre-existing social. Likewise, if you would like to
+     disable a social command, that is possible too.
+     
+     Commands:
+       soclink [new command] [old command]
+       socunlink [command]
+       socedit [social]
+       socials
+   -
+   keywords : MCCP
+   editor   : Alister
+   timestamp: Jan 29 18:14:22
+   info     :~
+     The Mud Client Compression Protocol has the purpose of reducing the bandwidth 
+     usage of the mudserver, by using an MCCP-complient mudclient, the data send to 
+     you will be compressed by 80-85%, and thus not only reducing the amount of data
+     processed by the server, but also greatly reduce the amount of data you need to
+     download (i.e. less lag for you).
+     
+     This MUD supports both version 1 and 2 of the compression protocol, and any 
+     client supporting either of those version can be used to enable compression. 
+     Most clients enables compression automaticly, but some require that you type 
+     'compress'. The same command can also be used to disable compression.
+     
+     MCCP was created by Oliver Jowett
+   -
+   keywords : look
+   editor   : Alister
+   timestamp: Jan 29 18:15:22
+   info     :~
+     Look allows you to glean extra information about your environment, as well as
+     people and items in it. Look can be used to peer into containers, glance at
+     your room, examine the finer details of an item, among other things.
+     
+     Usage: 
+       > look [at the <target>] [in the <container>] [on the <thing or person>]
+     
+     Examples: 
+       > look
+       > look bob
+       > look at bob
+       > look at the bob
+       > look at the mole on bob
+       > look in sheath
+       > look hilt on sword in sheath
+       > look at the hilt on the sword in the sheath
+     
+     Looking at an object that is a container will also peer inside and list its
+     contents (provided the container is opened).
+   -
+   keywords : Jobo
+   editor   : Alister
+   timestamp: Jan 29 18:13:11
+   info     :~
+     Jobo aka Brian Graversen is the author of SocketMud(tm), which is a bareboned 
+     mud codebase. The codebase was made mainly for fun and to learn from the 
+     experience itself.
+     
+     Feel free to use the codebase for whatever purposes you have in mind, and should
+     you ever make a real mud from it, send me a mail and tell me about it at 
+     jobo@daimi.au.dk
+     
+     Brian Graversen
+   -
+   keywords : help, hlink, hunlink, hupdate
+   editor   : Alister
+   timestamp: Jan 29 18:32:52
+   info     :~
+     There are various tools available for creating and editing helpfiles. You can
+     update the contents of any helpfile with the hupdate command. The contents of
+     your notepad (see: write) will be transferred to the helpfile. You can also
+     link a new word to an already existing helpfile with the hlink command.
+     Unlinking is also possible with the hunlink command.
+     
+     Commands:
+       hupdate [helpfile]
+       hlink [new topic] [old topic]
+       hunlink [topic]
+       help
+     
+     See also: WRITE
+   -
+   keywords : dig, fill
+   editor   : Alister
+   timestamp: Jan 29 18:35:30
+   info     :~
+     Dig allows you to link together two rooms. Fill allows you to close a down a
+     link between two rooms.
+     
+     Commands:
+       dig [direction] [room vnum]
+       fill [direction]
+   -
+   keywords : delay
+   editor   : Alister
+   timestamp: Jan 29 18:25:21
+   info     :~
+     usage: delay [seconds] [command]
+     
+     example:
+       delay 2 say hello, world!
+     
+     Allows the user to prepare a command to be executed in the future.
+   -
+   keywords : OLC, redit, oedit, medit, scedit, dedit, zedit, socedit
+   editor   : Alister
+   timestamp: Jan 29 18:12:02
+   info     :~
+     On-Line Creation (OLC) is a set of utilities designed to allow builders to
+     design their zones while on the MUD. OLC includes utilities for editing zones,
+     rooms, objects, mobiles, scripts, and dialogues. The following commands are
+     available to the online builder:
+     
+           edits                command                 listing command
+           rooms                redit                   rlist <zone vnum>
+           objects              oedit                   olist <zone vnum>
+           mobiles              medit                   mlist <zone vnum>
+           scripts              scedit                  sclist <zone vnum>
+           dialogs              dedit                   dlist <zone vnum>
+           socials              socedit                 socials
+           zones                zedit                   zlist
+     
+     To create a new zone, a special command must be used. It's format is:
+       zedit new [zone num] [min vnum] [max vnum]
+     
+     All other OLC commands can set up new things (rooms, objects, mobiles, etc..)
+     simply by using the corresponding edit command on a vnum that has not been used.
+   -
+   keywords : credits
+   editor   : Alister
+   timestamp: Jan 29 18:16:04
+   info     :~
+     Thanks go out to Brian Graversen for creating SocketMud(tm), which NakedMud(tm)
+     was built on top of. I know nothing (yet) about TCP/IP, and SocketMud(tm) made 
+     my life that much easier.
+   -
+   keywords : buildwalk
+   editor   : Alister
+   timestamp: Jan 29 18:36:38
+   info     :~
+     usage: buildwalk
+     
+     With buildwalk on, you can walk around in directions that do not exist to spawn
+     new exits. Buildwalk can be toggled on and off by simply typing buildwalk.
+   -
+   keywords : ANSI
+   editor   : Alister
+   timestamp: Jan 29 18:06:47
+   info     :~
+     NakedMud supports ANSI colors, and you can access them by using the '{{'
+     character, followed by the colorkey from the table below.
+     
+     Yellow    {yy {YY{n
+     Blue      {bb {BB{n
+     Green     {gg {GG{n
+     Red       {rr {RR{n
+     Cyan      {cc {CC{n
+     Purple    {pp {PP{n
+     Dark      {dd {DD{n
+     White     {ww {WW{n
+     
+     The 'n' key is the default NakedMud color, and the mudcolor will always
+     revert to this color at the end of a string.
+   -
+ -
diff -crN nakedmudv1.4/lib/misc/time nakedmudv1.5/lib/misc/time
*** nakedmudv1.4/lib/misc/time	2010-11-01 15:54:17.000000000 -0500
--- nakedmudv1.5/lib/misc/time	2010-11-01 15:54:17.000000000 -0500
***************
*** 1,6 ****
! hour        : 20
  day_of_week : 2
! day_of_month: 2
! month       : 1
  year        : 0
  -
--- 1,6 ----
! hour        : 18
  day_of_week : 2
! day_of_month: 11
! month       : 2
  year        : 0
  -
diff -crN nakedmudv1.4/lib/world/0/rooms~ nakedmudv1.5/lib/world/0/rooms~
*** nakedmudv1.4/lib/world/0/rooms~	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/lib/world/0/rooms~	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,25 ----
+ list:=
+   desc     :~
+     You are surrounded by nothingness.

+   auxiliary:-
+     time_aux_data  :-
+       night_desc: 
+       -
+     script_aux_data:-
+       scripts:=
+       -
+     -
+   terrain  : 0
+   vnum     : 0
+   name     : Floating in Limbo
+   exits    :=
+   edescs   :-
+     list:=
+       desc    :~
+            Well, there's not too much of it, that's for sure.  Or maybe that's all 

+         there is.  It's quite mind blowing, really.

+       keywords: nothingness
+       -
+     -
+   -
+ -
diff -crN nakedmudv1.4/lib/world/0/zone nakedmudv1.5/lib/world/0/zone
*** nakedmudv1.4/lib/world/0/zone	2010-11-01 15:54:17.000000000 -0500
--- nakedmudv1.5/lib/world/0/zone	2010-11-01 15:54:17.000000000 -0500
***************
*** 5,8 ****
--- 5,16 ----
  name       : The null zone
  desc       :~
       This zone has no purpose and should be taken out when the MUD is first 

+ auxiliary  :-
+   zone_map_data :-
+     zone_display_map: 0
+     -
+   autopilot_data:-
+     autopilot_on: 0
+     -
+   -
  -
diff -crN nakedmudv1.4/lib/world/1/dialogs nakedmudv1.5/lib/world/1/dialogs
*** nakedmudv1.4/lib/world/1/dialogs	2010-11-01 15:54:17.000000000 -0500
--- nakedmudv1.5/lib/world/1/dialogs	2010-11-01 15:54:17.000000000 -0500
***************
*** 3,110 ****
    name     : Mysty's Dialog
    greet    : Welcome to the Stuck Swine! I hope it's to your liking here. If you need a hand, or perhaps a drink, just ask me for help
    responses:=
!     keywords: Julesz
!     message : He's here most nights, working the bar. A wonderful man, and ohhh so dreamy eyes.
!     -
!     keywords: Freeport
!     message : Freeport is a large trading city to the east of Asmyr. The only way there is though the mountains to the east. The trek is about two weeks, but if you are looking to see the world, Freeport is a good place to start. They have the world's largest marketplace, and they are right on the ocean. If you go down to the docks, the view is absolutely beautiful - especially at night, around sunset.
      -
!     keywords: cards, blackjack
!     message : Symon loves to play blackjack, although I must say he is not very good at it. Ask him about it if you are looking to play a game. If you're looking for a challenge, however, you might want to look elsewhere.
      -
!     keywords: tables
!     message : If you take a seat at one of the tables, myself or one of the other waitresses will be around in a moment to take your order.
      -
!     keywords: parks
!     message : Asmyr has some of the most beautiful parks I've ever seen. In the spring, the wild flowers attract many people. The parks are great places to go if you're looking to strike up a conversation with somebody.
      -
!     keywords: merchants
!     message : Asmyr sees many merchants passing through. Just outside the east gate of the city, there's a passage through the mountains that leads down to Freeport, which has the world's largest marketplace. Since going through the pass is the only way to get to Freeport, many merchants spend a couple days here to rest up before they make the trek through the pass.
      -
!     keywords: Mysty says hi
!     message : Mysty - that's me. If you run into Julesz, let him know I say hi. I'm sure that will get him talking. Maybe he'll have some useful information for you, being new around here and all.
      -
!     keywords: bar
!     message : The bar is on the south side of the tavern. Chances are, Julesz will be working there. He's a great guy - and cute too! If you see him, let him know that Mysty says hi.
      -
!     keywords: Garod
!     message : He's a surly fellow. Keeps to himself mostly. You can usually find him in the southwest corner of the tavern, by the bar. I wouldn't go looking if I were you, though. He doesn't like company.
      -
!     keywords: Symon
!     message : He's a professional entertainer, and performs here during the night. If he's not up on stage, you can usually find him loitering around the tavern - just look for the crowd of women. He's a good guy to talk to if you're looking for some laughs, or if you've got some money to burn. He's got a great hand for the dice. The cards don't seem to like him, though.
      -
!     keywords: usual crowd
!     message : There's If you're looking to meet any of them, Symon, Oren, and Betta are good folk. Just do yourself a favor and stay away from Garod. He's got quite a temper, and doesn't take well to newcomers.
      -
      keywords: ask
      message : If you'd like to know what someone thinks about a topic, you can always try asking them about it. Taverns and other social gatherings are good places to get information.
      -
!     keywords: greet
!     message : Most of the people around here are quite friendly. Just go up to them and greet them. It's sure to get them talking. Just a small piece of advice - if you haven't been here for awhile, stay away from that Garod fellow. he usually lingers around the southwest corner of the tavern. He's not too fond of people... new people especially.
      -
!     keywords: cold, bitter cold
!     message : We're quite elevated, and the mountains aren't too far off to the east, so it can get a bit cold at times. The winter chill is really setting in early this year, too. Why don't you have a seat at one of the tables, and I'll serve you up a nice cup of mead to keep you warm?
      -
!     keywords: Asmyr
!     message : Even though everyone complains about the bitter cold, it is a wonderful city. In the spring, the parks are so beautiful. And, with all of the merchants always passing through, it is a wonderful place to be if you have a bit of spare money
      -
!     keywords: Stuck Swine
!     message : That would be where you are - home of the finest ales and entertainment this side of Asmyr! If you are looking for food or drink please, have a seat at one of the tables and I will be right with you. Or, if you'd prefer, the bar is at the south end of the tavern.
      -
!     keywords: help
!     message : You look like you're new to the Stuck Swine. The usual crowd is fairly outgoing. More likely than not, they'll all strike up a conversation with you if you greet them. If you're looking for a drink, have a seat at a table or head to the bar. Whatever you'd like, just ask!
      -
!     keywords: dice, bones
!     message : Bones is one of Symon's favorite games. I've seen him play - he's quite good at it. If you have some spare money to burn, ask him about bones. I'm sure he'd be willing to play you a game or two. Just don't blame me when you lose your money to him!
      -
!     keywords: menu, steamed crab, pudding ale, steak, veal, breaded porkchops, porkchops, shepard's pie, pie, salmon
!     message : crab merchants from Freeport recently passed through, and we stocked up. I would suggest our current special of steamed crab. It comes with a side of potatos - mashed or baked - greens, and a bun. We also have a wonderful pudding ale on tap, if you are interested. Our regular menu consists of steak, veal, breaded porkchops, shepard's pie, and salmon. If you would like to order anything, simply say so.
      -
!     keywords: order steamed crab
!     message : A wonderful choice, I must say. I will let the kitchen know right away.
      -
!     keywords: order ale, order pudding ale
!     message : Absolutely delicious. I will let the bar know you'd like one.
      -
!     keywords: order steak, order veal, order breaded porkchops, order porkchops, order shepard's pie, order pie, order salmon
!     message : very well. I will get it out to you as soon as possible.
      -
    -
    vnum     : 101
    name     : Julesz's Dialog
    greet    : looking for a drink? If so, you've come to the right place.
    responses:=
!     keywords: order ale, order pudding ale, order lager, order stout
!     message : Good choice! It will be right up.
      -
!     keywords: ale, ales
!     message : we have two ales on tap. Our pudding ale has a pleasant fruity, spicy flavor to it. Or, if you'd like, there is our normal ale.
      -
!     keywords: lager
!     message : It is a nice, light lager with a smooth, crisp taste. I'd suggest it if you are looking for something a bit more refreshing.
      -
      keywords: stout
      message : It is a particularily dark stout, with hints of caramel and roasted almonds. It is one of my favourites, I must say.
      -
!     keywords: on tap
!     message : we have a lager, a stout, and various ales on tap. If you'd like to hear about any specific one, just ask. Or, if you'd like to order one, say so.
      -
!     keywords: Mysty
!     message : Aye, she's our main server tonight. Cute lass, and she's got a good head on her shoulders too. If you're wanting to know anything about this place, she's a good one to talk to.
      -
!     keywords: drink
!     message : have a seat at the bar, and I'll be right with you. Or go find a table in the tavern, and Mysty will serve you.
      -
    -
    vnum     : 102
    name     : Garod's Dialog
    greet    : Hrmph, whaddiu want?
    responses:=
-     keywords: Garod
-     message : That's me. Whaddiu want to know? Hmm? I can tell I don't like you already. Why don't you get lost.
-     -
      keywords: get lost
      message : Go pester someone else. I'm busy with my ale right now.
      -
    -
  -
--- 3,110 ----
    name     : Mysty's Dialog
    greet    : Welcome to the Stuck Swine! I hope it's to your liking here. If you need a hand, or perhaps a drink, just ask me for help
    responses:=
!     keywords: order steak, order veal, order breaded porkchops, order porkchops, order shepard's pie, order pie, order salmon
!     message : very well. I will get it out to you as soon as possible.
      -
!     keywords: order ale, order pudding ale
!     message : Absolutely delicious. I will let the bar know you'd like one.
      -
!     keywords: order steamed crab
!     message : A wonderful choice, I must say. I will let the kitchen know right away.
      -
!     keywords: menu, steamed crab, pudding ale, steak, veal, breaded porkchops, porkchops, shepard's pie, pie, salmon
!     message : crab merchants from Freeport recently passed through, and we stocked up. I would suggest our current special of steamed crab. It comes with a side of potatos - mashed or baked - greens, and a bun. We also have a wonderful pudding ale on tap, if you are interested. Our regular menu consists of steak, veal, breaded porkchops, shepard's pie, and salmon. If you would like to order anything, simply say so.
      -
!     keywords: dice, bones
!     message : Bones is one of Symon's favorite games. I've seen him play - he's quite good at it. If you have some spare money to burn, ask him about bones. I'm sure he'd be willing to play you a game or two. Just don't blame me when you lose your money to him!
      -
!     keywords: help
!     message : You look like you're new to the Stuck Swine. The usual crowd is fairly outgoing. More likely than not, they'll all strike up a conversation with you if you greet them. If you're looking for a drink, have a seat at a table or head to the bar. Whatever you'd like, just ask!
      -
!     keywords: Stuck Swine
!     message : That would be where you are - home of the finest ales and entertainment this side of Asmyr! If you are looking for food or drink please, have a seat at one of the tables and I will be right with you. Or, if you'd prefer, the bar is at the south end of the tavern.
      -
!     keywords: Asmyr
!     message : Even though everyone complains about the bitter cold, it is a wonderful city. In the spring, the parks are so beautiful. And, with all of the merchants always passing through, it is a wonderful place to be if you have a bit of spare money
      -
!     keywords: cold, bitter cold
!     message : We're quite elevated, and the mountains aren't too far off to the east, so it can get a bit cold at times. The winter chill is really setting in early this year, too. Why don't you have a seat at one of the tables, and I'll serve you up a nice cup of mead to keep you warm?
      -
!     keywords: greet
!     message : Most of the people around here are quite friendly. Just go up to them and greet them. It's sure to get them talking. Just a small piece of advice - if you haven't been here for awhile, stay away from that Garod fellow. he usually lingers around the southwest corner of the tavern. He's not too fond of people... new people especially.
      -
      keywords: ask
      message : If you'd like to know what someone thinks about a topic, you can always try asking them about it. Taverns and other social gatherings are good places to get information.
      -
!     keywords: usual crowd
!     message : There's If you're looking to meet any of them, Symon, Oren, and Betta are good folk. Just do yourself a favor and stay away from Garod. He's got quite a temper, and doesn't take well to newcomers.
      -
!     keywords: Symon
!     message : He's a professional entertainer, and performs here during the night. If he's not up on stage, you can usually find him loitering around the tavern - just look for the crowd of women. He's a good guy to talk to if you're looking for some laughs, or if you've got some money to burn. He's got a great hand for the dice. The cards don't seem to like him, though.
      -
!     keywords: Garod
!     message : He's a surly fellow. Keeps to himself mostly. You can usually find him in the southwest corner of the tavern, by the bar. I wouldn't go looking if I were you, though. He doesn't like company.
      -
!     keywords: bar
!     message : The bar is on the south side of the tavern. Chances are, Julesz will be working there. He's a great guy - and cute too! If you see him, let him know that Mysty says hi.
      -
!     keywords: Mysty says hi
!     message : Mysty - that's me. If you run into Julesz, let him know I say hi. I'm sure that will get him talking. Maybe he'll have some useful information for you, being new around here and all.
      -
!     keywords: merchants
!     message : Asmyr sees many merchants passing through. Just outside the east gate of the city, there's a passage through the mountains that leads down to Freeport, which has the world's largest marketplace. Since going through the pass is the only way to get to Freeport, many merchants spend a couple days here to rest up before they make the trek through the pass.
      -
!     keywords: parks
!     message : Asmyr has some of the most beautiful parks I've ever seen. In the spring, the wild flowers attract many people. The parks are great places to go if you're looking to strike up a conversation with somebody.
      -
!     keywords: tables
!     message : If you take a seat at one of the tables, myself or one of the other waitresses will be around in a moment to take your order.
      -
!     keywords: cards, blackjack
!     message : Symon loves to play blackjack, although I must say he is not very good at it. Ask him about it if you are looking to play a game. If you're looking for a challenge, however, you might want to look elsewhere.
      -
!     keywords: Freeport
!     message : Freeport is a large trading city to the east of Asmyr. The only way there is though the mountains to the east. The trek is about two weeks, but if you are looking to see the world, Freeport is a good place to start. They have the world's largest marketplace, and they are right on the ocean. If you go down to the docks, the view is absolutely beautiful - especially at night, around sunset.
!     -
!     keywords: Julesz
!     message : He's here most nights, working the bar. A wonderful man, and ohhh so dreamy eyes.
      -
    -
    vnum     : 101
    name     : Julesz's Dialog
    greet    : looking for a drink? If so, you've come to the right place.
    responses:=
!     keywords: drink
!     message : have a seat at the bar, and I'll be right with you. Or go find a table in the tavern, and Mysty will serve you.
      -
!     keywords: Mysty
!     message : Aye, she's our main server tonight. Cute lass, and she's got a good head on her shoulders too. If you're wanting to know anything about this place, she's a good one to talk to.
      -
!     keywords: on tap
!     message : we have a lager, a stout, and various ales on tap. If you'd like to hear about any specific one, just ask. Or, if you'd like to order one, say so.
      -
      keywords: stout
      message : It is a particularily dark stout, with hints of caramel and roasted almonds. It is one of my favourites, I must say.
      -
!     keywords: lager
!     message : It is a nice, light lager with a smooth, crisp taste. I'd suggest it if you are looking for something a bit more refreshing.
      -
!     keywords: ale, ales
!     message : we have two ales on tap. Our pudding ale has a pleasant fruity, spicy flavor to it. Or, if you'd like, there is our normal ale.
      -
!     keywords: order ale, order pudding ale, order lager, order stout
!     message : Good choice! It will be right up.
      -
    -
    vnum     : 102
    name     : Garod's Dialog
    greet    : Hrmph, whaddiu want?
    responses:=
      keywords: get lost
      message : Go pester someone else. I'm busy with my ale right now.
      -
+     keywords: Garod
+     message : That's me. Whaddiu want to know? Hmm? I can tell I don't like you already. Why don't you get lost.
+     -
    -
  -
diff -crN nakedmudv1.4/lib/world/1/mobs nakedmudv1.5/lib/world/1/mobs
*** nakedmudv1.4/lib/world/1/mobs	2010-11-01 15:54:17.000000000 -0500
--- nakedmudv1.5/lib/world/1/mobs	2010-11-01 15:54:17.000000000 -0500
***************
*** 11,48 ****
      control.  There is always a bounce to her step, and fire in her eyes.  She 
      seems like she's quite the feisty one.
    level     : 2
!   sex       : 0
!   race      : 0
    dialog    : 100
    auxiliary :-
      stat_data        :-
        health          : 5
        curr_health     : 5
-       endurance       : 5
-       curr_endurance  : 0
        power           : 5
        curr_power      : 0
!       balance         : 5
!       curr_balance    : 0
        courage         : 5
        curr_courage    : 0
-       speed           : 5
-       curr_speed      : 0
        control         : 5
        curr_control    : 0
!       awareness       : 5
!       curr_awareness  : 0
        personality     : 5
        curr_personality: 0
-       luck            : 5
-       curr_luck       : 0
        -
      script_aux_data  :-
        scripts:=
-         vnum: 140
-         -
          vnum: 150
          -
        -
      -
    -
--- 11,42 ----
      control.  There is always a bounce to her step, and fire in her eyes.  She 
      seems like she's quite the feisty one.
    level     : 2
!   sex       : 1
!   race      : human
    dialog    : 100
    auxiliary :-
      stat_data        :-
        health          : 5
        curr_health     : 5
        power           : 5
        curr_power      : 0
!       awareness       : 5
!       curr_awareness  : 0
        courage         : 5
        curr_courage    : 0
        control         : 5
        curr_control    : 0
!       speed           : 5
!       curr_speed      : 0
        personality     : 5
        curr_personality: 0
        -
      script_aux_data  :-
        scripts:=
          vnum: 150
          -
+         vnum: 140
+         -
        -
      -
    -
***************
*** 57,93 ****
      ladies walking by the bar.
    level     : 2
    sex       : 0
!   race      : 0
    dialog    : 101
    auxiliary :-
      stat_data        :-
        health          : 5
        curr_health     : 5
-       endurance       : 5
-       curr_endurance  : 0
        power           : 5
        curr_power      : 0
!       balance         : 5
!       curr_balance    : 0
        courage         : 5
        curr_courage    : 0
-       speed           : 5
-       curr_speed      : 0
        control         : 5
        curr_control    : 0
!       awareness       : 5
!       curr_awareness  : 0
        personality     : 5
        curr_personality: 0
-       luck            : 5
-       curr_luck       : 0
        -
      script_aux_data  :-
        scripts:=
-         vnum: 151
-         -
          vnum: 141
          -
        -
      -
    -
--- 51,81 ----
      ladies walking by the bar.
    level     : 2
    sex       : 0
!   race      : human
    dialog    : 101
    auxiliary :-
      stat_data        :-
        health          : 5
        curr_health     : 5
        power           : 5
        curr_power      : 0
!       awareness       : 5
!       curr_awareness  : 0
        courage         : 5
        curr_courage    : 0
        control         : 5
        curr_control    : 0
!       speed           : 5
!       curr_speed      : 0
        personality     : 5
        curr_personality: 0
        -
      script_aux_data  :-
        scripts:=
          vnum: 141
          -
+         vnum: 151
+         -
        -
      -
    -
***************
*** 102,131 ****
      has a large, bulbous nose and squinty, black eyes.
    level     : 1
    sex       : 0
!   race      : 0
    dialog    : 102
    auxiliary :-
      stat_data        :-
        health          : 5
        curr_health     : 5
-       endurance       : 5
-       curr_endurance  : 0
        power           : 5
        curr_power      : 0
!       balance         : 5
!       curr_balance    : 0
        courage         : 5
        curr_courage    : 0
-       speed           : 5
-       curr_speed      : 0
        control         : 5
        curr_control    : 0
!       awareness       : 5
!       curr_awareness  : 0
        personality     : 5
        curr_personality: 0
-       luck            : 5
-       curr_luck       : 0
        -
      -
    -
--- 90,113 ----
      has a large, bulbous nose and squinty, black eyes.
    level     : 1
    sex       : 0
!   race      : human
    dialog    : 102
    auxiliary :-
      stat_data        :-
        health          : 5
        curr_health     : 5
        power           : 5
        curr_power      : 0
!       awareness       : 5
!       curr_awareness  : 0
        courage         : 5
        curr_courage    : 0
        control         : 5
        curr_control    : 0
!       speed           : 5
!       curr_speed      : 0
        personality     : 5
        curr_personality: 0
        -
      -
    -
***************
*** 143,172 ****
    multiname : a group of %d bar flies
    level     : 2
    sex       : 0
!   race      : 0
    dialog    : -1
    auxiliary :-
      stat_data        :-
        health          : 5
        curr_health     : 5
-       endurance       : 5
-       curr_endurance  : 0
        power           : 5
        curr_power      : 0
!       balance         : 5
!       curr_balance    : 0
        courage         : 5
        curr_courage    : 0
-       speed           : 5
-       curr_speed      : 0
        control         : 5
        curr_control    : 0
!       awareness       : 5
!       curr_awareness  : 0
        personality     : 5
        curr_personality: 0
-       luck            : 5
-       curr_luck       : 0
        -
      -
    -
--- 125,148 ----
    multiname : a group of %d bar flies
    level     : 2
    sex       : 0
!   race      : human
    dialog    : -1
    auxiliary :-
      stat_data        :-
        health          : 5
        curr_health     : 5
        power           : 5
        curr_power      : 0
!       awareness       : 5
!       curr_awareness  : 0
        courage         : 5
        curr_courage    : 0
        control         : 5
        curr_control    : 0
!       speed           : 5
!       curr_speed      : 0
        personality     : 5
        curr_personality: 0
        -
      -
    -
diff -crN nakedmudv1.4/lib/world/1/mobs~ nakedmudv1.5/lib/world/1/mobs~
*** nakedmudv1.4/lib/world/1/mobs~	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/lib/world/1/mobs~	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,149 ----
+ list:=
+   vnum      : 100
+   name      : Mysty
+   keywords  : mysty, blonde, waitress
+   rdesc     : A small, buxom blonde is here, serving the tavern patrons.
+   desc      :~
+        She's a rather petite woman - just over five feet.  She has long, curly 
+     blonde hair that hangs down past her shoulders.  Her low-cut, white cotton 
+     shirt reveals her cleavage - and quite a bit of cleavage at that!  She darts 
+     from table to table, always carrying a tray of drinks with amazing balance and 
+     control.  There is always a bounce to her step, and fire in her eyes.  She 
+     seems like she's quite the feisty one.
+   level     : 2
+   sex       : 1
+   race      : 0
+   dialog    : 100
+   auxiliary :-
+     stat_data        :-
+       health          : 5
+       curr_health     : 5
+       power           : 5
+       curr_power      : 0
+       awareness       : 5
+       curr_awareness  : 0
+       courage         : 5
+       curr_courage    : 0
+       control         : 5
+       curr_control    : 0
+       speed           : 5
+       curr_speed      : 0
+       personality     : 5
+       curr_personality: 0
+       -
+     script_aux_data  :-
+       scripts:=
+         vnum: 150
+         -
+         vnum: 140
+         -
+       -
+     -
+   -
+   vnum      : 101
+   name      : Julesz
+   keywords  : Julesz, bartender, man
+   rdesc     : A handsome, darkhaired man is here, standing behind the bar.
+   desc      :~
+        He is about average height, with short black hair and piercing grey eyes.
+     He has an air about him that screams mischief.  He looks quite preoccupied 
+     pouring drinks, but you notice he never gets too busy to not glance at the 
+     ladies walking by the bar.
+   level     : 2
+   sex       : 0
+   race      : 0
+   dialog    : 101
+   auxiliary :-
+     stat_data        :-
+       health          : 5
+       curr_health     : 5
+       power           : 5
+       curr_power      : 0
+       awareness       : 5
+       curr_awareness  : 0
+       courage         : 5
+       curr_courage    : 0
+       control         : 5
+       curr_control    : 0
+       speed           : 5
+       curr_speed      : 0
+       personality     : 5
+       curr_personality: 0
+       -
+     script_aux_data  :-
+       scripts:=
+         vnum: 141
+         -
+         vnum: 151
+         -
+       -
+     -
+   -
+   vnum      : 102
+   name      : a gruff looking man
+   keywords  : garod, gruff, man
+   rdesc     : A gruff looking man is here, keeping to himself.
+   desc      :~
+        If surly had a poster child, he would be it.  His face is pocked, and he 
+     has a sour look on his face.  His eyebrows are thick and bushy, and he has 
+     a scraggly beard that looks like it has been growing for a few weeks.  He 
+     has a large, bulbous nose and squinty, black eyes.
+   level     : 1
+   sex       : 0
+   race      : 0
+   dialog    : 102
+   auxiliary :-
+     stat_data        :-
+       health          : 5
+       curr_health     : 5
+       power           : 5
+       curr_power      : 0
+       awareness       : 5
+       curr_awareness  : 0
+       courage         : 5
+       curr_courage    : 0
+       control         : 5
+       curr_control    : 0
+       speed           : 5
+       curr_speed      : 0
+       personality     : 5
+       curr_personality: 0
+       -
+     -
+   -
+   vnum      : 130
+   name      : a barfly
+   keywords  : barfly
+   rdesc     : A barfly is here, mulling about.
+   desc      :~
+        He is middle aged, and looks like he has led a pretty tough life.  His 
+     hands look strong and calloused.  He might be a miner, or perhaps some kind 
+     of tradesman.  His face is slightly pocked, and his eyebrows are big and 
+     bushy.  He looks a bit too preoccupied with his mug of ale to pay you much 
+     attention.
+   multirdesc: A group of %d barflies are here, mulling about.
+   multiname : a group of %d bar flies
+   level     : 2
+   sex       : 0
+   race      : 0
+   dialog    : -1
+   auxiliary :-
+     stat_data        :-
+       health          : 5
+       curr_health     : 5
+       power           : 5
+       curr_power      : 0
+       awareness       : 5
+       curr_awareness  : 0
+       courage         : 5
+       curr_courage    : 0
+       control         : 5
+       curr_control    : 0
+       speed           : 5
+       curr_speed      : 0
+       personality     : 5
+       curr_personality: 0
+       -
+     -
+   -
+ -
diff -crN nakedmudv1.4/lib/world/1/objs~ nakedmudv1.5/lib/world/1/objs~
*** nakedmudv1.4/lib/world/1/objs~	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/lib/world/1/objs~	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,134 ----
+ list:=
+   value 2   : 0
+   bits      : 
+   rdesc     : A revealing, white cotton shirt is lying here.
+   value 0   : 0
+   subtype   : 0
+   desc      :~
+        It is a white cotton shirt, with a rather low cot v-line that would reveal 

+     qutie a bit.  It is small, and looks lke it was made for a rather petite 

+     woman.

+   value 3   : 0
+   type      : 2
+   auxiliary :-
+     script_aux_data:-
+       scripts:=
+       -
+     -
+   value 1   : 0
+   multirdesc: A pile of %d white cotton shirts has formed, here.
+   name      : a white cotton shirt
+   vnum      : 100
+   contents  :=
+   edescs    :-
+     list:=
+     -
+   multiname : %d white cotton shirts
+   keywords  : shirt
+   -
+   value 2   : 0
+   bits      : 
+   rdesc     : A pair of long, dangly earrings are lying here.
+   value 0   : 0
+   subtype   : 4
+   desc      :~
+      They are made of long, dangly strips of green-grey metal, and shimmer 

+     whenever they are turned in the light.

+   value 3   : 0
+   type      : 2
+   auxiliary :-
+     script_aux_data:-
+       scripts:=
+       -
+     -
+   value 1   : 0
+   multirdesc: %d pairs of long, dangly earrings are lying here.
+   name      : a pair of long, dangly earrings
+   vnum      : 101
+   contents  :=
+   edescs    :-
+     list:=
+     -
+   multiname : %d sets of long dangly earrings
+   keywords  : earrings
+   -
+   value 2   : 0
+   bits      : a
+   rdesc     : A circular wooden table is here.
+   value 0   : 5
+   subtype   : 0
+   desc      :~
+        It is made of wood, and is circular.  It stands about four feet off 

+     the ground, and has a few chairs seated around it.  It looks like it 

+     could seat about four or five people at it.

+   value 3   : 0
+   type      : 4
+   auxiliary :-
+     script_aux_data:-
+       scripts:=
+       -
+     -
+   value 1   : 0
+   multirdesc: There are %d empty wooden tables clustered about the tavern.
+   name      : a wooden table
+   vnum      : 120
+   contents  :=
+   edescs    :-
+     list:=
+     -
+   multiname : %d wooden tables
+   keywords  : table
+   -
+   value 2   : 0
+   bits      : a
+   rdesc     : A long bar counter is here, lined with seats.
+   value 0   : 12
+   subtype   : 0
+   desc      :~
+        It is about twenty feet long, and it is lined with stools.  It is made 

+     out of a polished, dark wood.

+   value 3   : 0
+   type      : 4
+   auxiliary :-
+     script_aux_data:-
+       scripts:=
+       -
+     -
+   value 1   : 0
+   multirdesc: 
+   name      : the bar
+   vnum      : 130
+   contents  :=
+   edescs    :-
+     list:=
+     -
+   multiname : 
+   keywords  : bar
+   -
+   value 2   : 0
+   bits      : 
+   rdesc     : a pint glass has been left here.
+   value 0   : 0
+   subtype   : 0
+   desc      :~
+        It looks like a typical pint glass.  Its base is a bit smaller than its 

+     top, and it has a little bulge about four fifths of the way up the glass.

+   value 3   : 0
+   type      : 0
+   auxiliary :-
+     script_aux_data:-
+       scripts:=
+       -
+     -
+   value 1   : 0
+   multirdesc: %d pint glasses are scattered about.
+   name      : a pint glass
+   vnum      : 141
+   contents  :=
+   edescs    :-
+     list:=
+     -
+   multiname : %d pint glasses
+   keywords  : pintglass, glass
+   -
+ -
diff -crN nakedmudv1.4/lib/world/1/rooms nakedmudv1.5/lib/world/1/rooms
*** nakedmudv1.4/lib/world/1/rooms	2010-11-01 15:54:17.000000000 -0500
--- nakedmudv1.5/lib/world/1/rooms	2010-11-01 15:54:17.000000000 -0500
***************
*** 14,29 ****
    terrain  : 0
    edescs   :-
      list:=
-       keywords: stage
-       desc    :~
-            There is stage not too far to the north.  Currently, it appears to 
-         be empty.
-       -
        keywords: fireplace
        desc    :~
             The fireplace looks to be blazing quite brightly.  There are a few groups 
          of people at tables scattered around it.
        -
      -
    exits    :=
      desc      :~
--- 14,29 ----
    terrain  : 0
    edescs   :-
      list:=
        keywords: fireplace
        desc    :~
             The fireplace looks to be blazing quite brightly.  There are a few groups 
          of people at tables scattered around it.
        -
+       keywords: stage
+       desc    :~
+            There is stage not too far to the north.  Currently, it appears to 
+         be empty.
+       -
      -
    exits    :=
      desc      :~
***************
*** 69,74 ****
--- 69,81 ----
      direction : southwest
      -
    reset    :=
+     type    : 0
+     times   : 4
+     chance  : 100
+     max     : 0
+     room_max: 4
+     arg     : 120
+     -
      type    : 1
      times   : 1
      chance  : 100
***************
*** 81,103 ****
        chance  : 100
        max     : 0
        room_max: 0
!       arg     : 100
        -
        type    : 0
        times   : 1
        chance  : 100
        max     : 0
        room_max: 0
!       arg     : 101
        -
      -
-     type    : 0
-     times   : 4
-     chance  : 100
-     max     : 0
-     room_max: 4
-     arg     : 120
-     -
    -
    name     : At the Bar
    desc     :~
--- 88,103 ----
        chance  : 100
        max     : 0
        room_max: 0
!       arg     : 101
        -
        type    : 0
        times   : 1
        chance  : 100
        max     : 0
        room_max: 0
!       arg     : 100
        -
      -
    -
    name     : At the Bar
    desc     :~
***************
*** 113,128 ****
    terrain  : 0
    edescs   :-
      list:=
-       keywords: stage
-       desc    :~
-            You can see an entertainment stage on the far north end of the bar.
-           It appears to be empty, currently.
-       -
        keywords: fireplace
        desc    :~
             There is a fireplace burning to the northwest.  Many people seem to 
          be scattered around it, chatting.
        -
      -
    exits    :=
      desc      :~
--- 113,128 ----
    terrain  : 0
    edescs   :-
      list:=
        keywords: fireplace
        desc    :~
             There is a fireplace burning to the northwest.  Many people seem to 
          be scattered around it, chatting.
        -
+       keywords: stage
+       desc    :~
+            You can see an entertainment stage on the far north end of the bar.
+           It appears to be empty, currently.
+       -
      -
    exits    :=
      desc      :~
***************
*** 158,178 ****
      direction : northwest
      -
    reset    :=
-     type    : 1
-     times   : 1
-     chance  : 100
-     max     : 1
-     room_max: 0
-     arg     : 101
-     in      :=
-       type    : 0
-       times   : 5
-       chance  : 100
-       max     : 0
-       room_max: 0
-       arg     : 141
-       -
-     -
      type    : 0
      times   : 1
      chance  : 100
--- 158,163 ----
***************
*** 188,193 ****
--- 173,193 ----
        arg     : 130
        -
      -
+     type    : 1
+     times   : 1
+     chance  : 100
+     max     : 1
+     room_max: 0
+     arg     : 101
+     in      :=
+       type    : 0
+       times   : 5
+       chance  : 100
+       max     : 0
+       room_max: 0
+       arg     : 141
+       -
+     -
    -
    name     : By the Stage
    desc     :~
***************
*** 308,314 ****
        -
      -
    -
!   name     : A New Buildwalk Room
    desc     :~
         There is a large fireplace here, burning away merrily.  Many people are 
      here, scattered around it at various tables.  The warmth of the fire is 
--- 308,314 ----
        -
      -
    -
!   name     : By the Fireplace
    desc     :~
         There is a large fireplace here, burning away merrily.  Many people are 
      here, scattered around it at various tables.  The warmth of the fire is 
***************
*** 322,336 ****
    terrain  : 0
    edescs   :-
      list:=
!       keywords: fire, fireplace
!       desc    :~
!            It blazes bright and warm.  The heat it gives off is rather soothing, 
!         and you can't help but feel relaxed around it.
!       -
!       keywords: bar
        desc    :~
!            You see the bar off to the southeast.  It looks like it is filling 
!         up rather quickly.
        -
        keywords: corner
        desc    :~
--- 322,331 ----
    terrain  : 0
    edescs   :-
      list:=
!       keywords: stage
        desc    :~
!            There is a small entertainment stage to the northeast.  It looks empty at 
!         the moment.
        -
        keywords: corner
        desc    :~
***************
*** 338,347 ****
          sitting over there, but most are alone and do not look like they want to 
          be disturbed.
        -
!       keywords: stage
        desc    :~
!            There is a small entertainment stage to the northeast.  It looks empty at 
!         the moment.
        -
      -
    exits    :=
--- 333,347 ----
          sitting over there, but most are alone and do not look like they want to 
          be disturbed.
        -
!       keywords: bar
        desc    :~
!            You see the bar off to the southeast.  It looks like it is filling 
!         up rather quickly.
!       -
!       keywords: fire, fireplace
!       desc    :~
!            It blazes bright and warm.  The heat it gives off is rather soothing, 
!         and you can't help but feel relaxed around it.
        -
      -
    exits    :=
diff -crN nakedmudv1.4/lib/world/1/rooms~ nakedmudv1.5/lib/world/1/rooms~
*** nakedmudv1.4/lib/world/1/rooms~	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/lib/world/1/rooms~	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,211 ----
+ list:=
+   desc     :~
+        This looks like quite the popular place; many tables are scattered around 

+     the tavern.  Groups of people huddle around them.  Some chat amongst 

+     themselves, some are playing card and dice games, and others are simply 

+     watching the entertainment stage to the north.  The bar is to the south.

+     People are lined up all along it, but you can spot a few open seats.  There 

+     are also a couple empty tables scattered throughout the tavern.  To the north, 

+     you see a small entertainment stage which seems to be attracting quite the 

+     crowd.

+   auxiliary:-
+     time_aux_data  :-
+       night_desc: 
+       -
+     script_aux_data:-
+       scripts:=
+         vnum: 100
+         -
+       -
+     -
+   terrain  : 0
+   vnum     : 100
+   name     : Within a Tavern
+   exits    :=
+     pick_level: 0
+     key       : -1
+     desc      :~
+          The entertainment stage is directly to your north.  Quite a few people have 

+       gathered around it, and it looks like there is a performance going on.

+     closable  : 0
+     enter     : 
+     direction : north
+     hide_level: 0
+     to        : 102
+     leave     : 
+     name      : 
+     keywords  : 
+     -
+     pick_level: 0
+     key       : -1
+     desc      :~
+        You see a rather crowded bar to the south.  There are still a couple of 

+       stools left, but it looks to be filling up fast.

+     closable  : 0
+     enter     : 
+     direction : south
+     hide_level: 0
+     to        : 101
+     leave     : $n makes $s way to the bar.
+     name      : going to the bar
+     keywords  : 
+     -
+     pick_level: 0
+     key       : -1
+     desc      :~
+          The light does not really get to that corner of the tavern.  A few people 

+       sit around tables, but most of them appear to be alone and not wanting any 

+       company.

+     closable  : 0
+     enter     : 
+     direction : southwest
+     hide_level: 0
+     to        : 103
+     leave     : 
+     name      : 
+     keywords  : 
+     -
+   edescs   :-
+     list:=
+     -
+   -
+   desc     :~
+        The bar is fairly busy, but you notice a couple of stools left unoccupied.

+     Servers come past now and then, picking up trays of drinks for their 

+     customers.  Most of the customers at the bar seem to be older on in the years, 

+     paying more attention to their drinks than to the crowd.  The bartenders all 

+     seem to be busy with preparing drinks for the customers.  A crowd seems to be 

+     gathering to the north, by the entertainment stage.  It looks like there is 

+     some sort of performance going on.

+   auxiliary:-
+     time_aux_data  :-
+       night_desc: 
+       -
+     script_aux_data:-
+       scripts:=
+         vnum: 101
+         -
+       -
+     -
+   terrain  : 0
+   vnum     : 101
+   name     : At the Bar
+   exits    :=
+     pick_level: 0
+     key       : -1
+     desc      :~
+          There are various tables scattered about, occupied by groups of people.  At 

+       the northern end of the tavern, you see a small entertainment stage which 

+       seems to have gathered quite the crowd.

+     closable  : 0
+     enter     : 
+     direction : north
+     hide_level: 0
+     to        : 100
+     leave     : 
+     name      : 
+     keywords  : 
+     -
+     pick_level: 0
+     key       : -1
+     desc      :~
+          The light does not really get to that corner of the tavern.  A few people 

+       sit around tables, but most of them appear to be alone and not wanting any 

+       company.

+     closable  : 0
+     enter     : 
+     direction : west
+     hide_level: 0
+     to        : 103
+     leave     : 
+     name      : 
+     keywords  : 
+     -
+   edescs   :-
+     list:=
+     -
+   -
+   desc     :~
+     This room was created by Alister.

+   auxiliary:-
+     time_aux_data  :-
+       night_desc: 
+       -
+     script_aux_data:-
+       scripts:=
+       -
+     -
+   terrain  : 0
+   vnum     : 102
+   name     : By the Stage
+   exits    :=
+     pick_level: 0
+     key       : -1
+     desc      :~
+        Tables are scattered about.  Most of them have groups of people sitting at 

+       them.  At the south end of the tavern, you see the bar.

+     closable  : 0
+     enter     : 
+     direction : south
+     hide_level: 0
+     to        : 100
+     leave     : 
+     name      : 
+     keywords  : 
+     -
+   edescs   :-
+     list:=
+     -
+   -
+   desc     :~
+        The light is much more dim in here than it is in the rest of the tavern.

+     There are also quite a few less people sitting in this area of the tavern.

+     Most that are seem to be keeping to themselves, and don't appear to want 

+     much to do with strangers.

+   auxiliary:-
+     time_aux_data  :-
+       night_desc: 
+       -
+     script_aux_data:-
+       scripts:=
+       -
+     -
+   terrain  : 0
+   vnum     : 103
+   name     : A Poorly Lit Corner
+   exits    :=
+     pick_level: 0
+     key       : -1
+     desc      :~
+          To the east, you see the bar.  It looks like it is starting to fill up 

+       quick, but you spot a couple open stools.  The bartenders look like they are 

+       quite busy with all the customers.

+     closable  : 0
+     enter     : 
+     direction : east
+     hide_level: 0
+     to        : 101
+     leave     : $n makes $s way towards the bar.
+     name      : 
+     keywords  : 
+     -
+     pick_level: 0
+     key       : -1
+     desc      :~
+          There are various tables scattered about, occupied by groups of people.  At 

+       the northern end of the tavern, you see a small entertainment stage which 

+       seems to have gathered quite the crowd.

+     closable  : 0
+     enter     : 
+     direction : northeast
+     hide_level: 0
+     to        : 100
+     leave     : 
+     name      : 
+     keywords  : 
+     -
+   edescs   :-
+     list:=
+     -
+   -
+ -
diff -crN nakedmudv1.4/lib/world/1/zone nakedmudv1.5/lib/world/1/zone
*** nakedmudv1.4/lib/world/1/zone	2010-11-01 15:54:17.000000000 -0500
--- nakedmudv1.5/lib/world/1/zone	2010-11-01 15:54:17.000000000 -0500
***************
*** 1,10 ****
  vnum       : 1
  min        : 100
  max        : 199
! pulse_timer: -1
  name       : The "Proof of Concept" zone
  desc       :~
       The ambition of this zone is to act as a repository for "proofs of 
    concept".  Hopefully, there will be enough examples in this zone to act as a 
  editors    : Alister
  -
--- 1,18 ----
  vnum       : 1
  min        : 100
  max        : 199
! pulse_timer: 1
  name       : The "Proof of Concept" zone
  desc       :~
       The ambition of this zone is to act as a repository for "proofs of 
    concept".  Hopefully, there will be enough examples in this zone to act as a 
  editors    : Alister
+ auxiliary  :-
+   zone_map_data :-
+     zone_display_map: 0
+     -
+   autopilot_data:-
+     autopilot_on: 0
+     -
+   -
  -
diff -crN nakedmudv1.4/lib/world/1/zone~ nakedmudv1.5/lib/world/1/zone~
*** nakedmudv1.4/lib/world/1/zone~	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/lib/world/1/zone~	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,10 ----
+ pulse_timer: -1
+ editors    : Alister
+ max        : 199
+ desc       :~
+      The ambition of this zone is to act as a repository for "proofs of 

+   concept".  Hopefully, there will be enough examples in this zone to act as a 

+ name       : The "Proof of Concept" zone
+ vnum       : 1
+ min        : 100
+ -
diff -crN nakedmudv1.4/lib/world/world nakedmudv1.5/lib/world/world
*** nakedmudv1.4/lib/world/world	2010-11-01 15:54:17.000000000 -0500
--- nakedmudv1.5/lib/world/world	2010-11-01 15:54:17.000000000 -0500
***************
*** 1,6 ****
  zones:=
-   vnum: 1
-   -
    vnum: 0
    -
  -
--- 1,6 ----
  zones:=
    vnum: 0
    -
+   vnum: 1
+   -
  -
diff -crN nakedmudv1.4/src/admin.c nakedmudv1.5/src/admin.c
*** nakedmudv1.4/src/admin.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/admin.c	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,171 ****
- //*****************************************************************************
- //
- // admin.c
- //
- // commands and procedures available only to admins.
- //
- //*****************************************************************************
- 
- #include "mud.h"
- #include "world.h"
- #include "inform.h"
- #include "character.h"
- #include "handler.h"
- #include "utils.h"
- #include "log.h"
- #include "socket.h"
- #include "save.h"
- #include "event.h"
- #include "action.h"
- #include "storage.h"
- 
- 
- //
- // BOOM! Shut down the MUD
- //
- COMMAND(cmd_shutdown) {
-   shut_down = TRUE;
- }
- 
- 
- //
- // Go to a specific room, object, or character in the game. Rooms are referenced
- // by vnum. Everything else is referenced by name.
- //   usage: goto [thing]
- //
- //   examples:
- //     goto 100             go to room number 100
- //     goto jim             go to an object/person named jim
- //
- COMMAND(cmd_goto) {
-   if(!arg || !*arg)
-     send_to_char(ch, "Where would you like to go to?\r\n");
-   // we're trying to go to a specific room number
-   else if(isdigit(*arg)) {
-     ROOM_DATA *room = worldGetRoom(gameworld, atoi(arg));
- 
-     if(!room)
-       send_to_char(ch, "No such room exists.\r\n");
-     else if(room == charGetRoom(ch))
-       send_to_char(ch, "You're already here, boss.\r\n");
-     else {
-       message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
- 	      "$n disappears in a puff of smoke.");
-       char_from_room(ch);
-       char_to_room(ch, room);
-       look_at_room(ch, room);
-       message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
- 	      "$n arrives in a puff of smoke.");
-     }
-   }
- 
-   // find the character we're trying to go to
-   else {
-     int tgt_type = FOUND_NONE;
-     void *tgt    = NULL;
- 
-     tgt = generic_find(ch, arg, 
- 		       FIND_TYPE_CHAR,
- 		       FIND_SCOPE_WORLD | FIND_SCOPE_VISIBLE,
- 		       FALSE, &tgt_type);
- 
-     if(ch == tgt)
-       send_to_char(ch, "You're already here, boss.\r\n");
-     else if(tgt && tgt_type == FOUND_CHAR) {
-       message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
- 	      "$n disappears in a puff of smoke.");
-       char_from_room(ch);
-       char_to_room(ch, charGetRoom(tgt));
-       look_at_room(ch, charGetRoom(ch));
-       message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
- 	      "$n arrives in a puff of smoke.");
-     }
-     else
-       send_to_char(ch, "Who were you trying to go to?\r\n");
-   }
- }
- 
- 
- //
- // Perform a copyover
- //
- COMMAND(cmd_copyover) { 
-   FILE *fp;
-   SOCKET_DATA *dsock;
-   char buf[100];
-   char control_buf[20];
-   char port_buf[20];
-   LIST_ITERATOR *sock_i = newListIterator(socket_list);
-   
-   if ((fp = fopen(COPYOVER_FILE, "w")) == NULL)
-   {
-     text_to_char(ch, "Copyover file not writeable, aborted.\n\r");
-     return;
-   }
- 
-   sprintf(buf, "\n\r <*>            The world starts spinning             <*>\n\r");
- 
-   /* For each playing descriptor, save its state */
-   //  for (dsock = dsock_list; dsock ; dsock = dsock_next)
-   ITERATE_LIST(dsock, sock_i) {
-     compressEnd(dsock, dsock->compressing, FALSE);
-     if (dsock->state != STATE_PLAYING) {
-       text_to_socket(dsock, "\r\nSorry, we are rebooting. Come back in a few minutes.\r\n");
-       close_socket(dsock, FALSE);
-     }
-     else {
-       fprintf(fp, "%d %s %s\n",
- 	      dsock->control, charGetName(dsock->player), dsock->hostname);
-       /* save the player */
-       save_player(dsock->player);
-       text_to_socket(dsock, buf);
-     }
-   }
-   deleteListIterator(sock_i);
-   
-   fprintf (fp, "-1\n");
-   fclose (fp);
- 
- 
-   /* close any pending sockets */
-   recycle_sockets();
-   
-   /* exec - descriptors are inherited */
-   sprintf(control_buf, "%d", control);
-   sprintf(port_buf, "%d", mudport);
-   execl(EXE_FILE, "NakedMud", "-copyover", control_buf, port_buf, NULL);
- 
-   /* Failed - sucessful exec will not return */
-   text_to_char(ch, "Copyover FAILED!\n\r");
- }
- 
- 
- //
- // show a list of all the PCs who are linkdead
- //
- COMMAND(cmd_linkdead) {
-   CHAR_DATA *xMob;
-   char buf[MAX_BUFFER];
-   bool found = FALSE;
-   LIST_ITERATOR *mob_i = newListIterator(mobile_list);
- 
-   ITERATE_LIST(xMob, mob_i) {
-     if (!(charIsNPC(xMob) || charGetSocket(xMob))) {
-       sprintf(buf, "%s is linkdead.\n\r", charGetName(xMob));
-       text_to_char(ch, buf);
-       found = TRUE;
-     }
-   }
-   deleteListIterator(mob_i);
- 
-   if (!found)
-     text_to_char(ch, "Noone is currently linkdead.\n\r");
- }
- 
- 
- //
- // List all of the non-player commands the character has access to
- //
- COMMAND(cmd_wizhelp) {
-   show_commands(ch, LEVEL_BUILDER, charGetLevel(ch));
- }
--- 0 ----
diff -crN nakedmudv1.4/src/admin.h nakedmudv1.5/src/admin.h
*** nakedmudv1.4/src/admin.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/admin.h	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,8 ****
- //*****************************************************************************
- //
- // admin.h
- //
- // special admin-only functions
- //
- //*****************************************************************************
- 
--- 0 ----
diff -crN nakedmudv1.4/src/alias/alias.c nakedmudv1.5/src/alias/alias.c
*** nakedmudv1.4/src/alias/alias.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/alias/alias.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 88,98 ****
    const char       *name = NULL;
    const char        *cmd = NULL;
  
!   store_list(set, "aliases", list, NULL);
    ITERATE_HASH(name, cmd, hash_i) {
      STORAGE_SET *alias_set = new_storage_set();
!     store_string(alias_set, "key", name, NULL);
!     store_string(alias_set, "val", hashIteratorCurrentVal(hash_i), NULL);
      storage_list_put(list, alias_set);
    }
    deleteHashIterator(hash_i);
--- 88,98 ----
    const char       *name = NULL;
    const char        *cmd = NULL;
  
!   store_list(set, "aliases", list);
    ITERATE_HASH(name, cmd, hash_i) {
      STORAGE_SET *alias_set = new_storage_set();
!     store_string(alias_set, "key", name);
!     store_string(alias_set, "val", hashIteratorCurrentVal(hash_i));
      storage_list_put(list, alias_set);
    }
    deleteHashIterator(hash_i);
diff -crN nakedmudv1.4/src/auxiliary.c nakedmudv1.5/src/auxiliary.c
*** nakedmudv1.4/src/auxiliary.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/auxiliary.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 148,154 ****
      entry = hashIteratorCurrentVal(hash_i);
      hashIteratorNext(hash_i);
      funcs = auxiliariesGetFuncs(name);
!     store_set(set, name, funcs->store(entry), NULL);
    }
    deleteHashIterator(hash_i);
    return set;
--- 148,154 ----
      entry = hashIteratorCurrentVal(hash_i);
      hashIteratorNext(hash_i);
      funcs = auxiliariesGetFuncs(name);
!     store_set(set, name, funcs->store(entry));
    }
    deleteHashIterator(hash_i);
    return set;
diff -crN nakedmudv1.4/src/auxiliary.h nakedmudv1.5/src/auxiliary.h
*** nakedmudv1.4/src/auxiliary.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/auxiliary.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 17,22 ****
--- 17,23 ----
  #define AUXILIARY_TYPE_CHAR      (1 << 0)
  #define AUXILIARY_TYPE_ROOM      (1 << 1)
  #define AUXILIARY_TYPE_OBJ       (1 << 2)
+ #define AUXILIARY_TYPE_ZONE      (1 << 3)
  
  
  //
diff -crN nakedmudv1.4/src/body.c nakedmudv1.5/src/body.c
*** nakedmudv1.4/src/body.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/body.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 57,67 ****
    "held"
  };
  
- const char *bodytype_list[NUM_BODYTYPES] = {
-   "humanoid",
-   "dragon",
- };
- 
  const char *bodysize_list[NUM_BODYSIZES] = {
    "diminuitive",
    "tiny",
--- 57,62 ----
***************
*** 108,173 ****
    return p_new;
  }
  
- /**
-  * Create a new body with dragon pieces and proportions
-  */
- BODY_DATA *newDragonBody() {
-   BODY_DATA *body = newBody();
-   body->size = BODYSIZE_COLLOSAL;
-   bodyAddPosition(body, "left hind claw",          BODYPOS_CLAW,          1);
-   bodyAddPosition(body, "right hind claw",         BODYPOS_CLAW,          1);
-   bodyAddPosition(body, "left front claw",         BODYPOS_CLAW,          1);
-   bodyAddPosition(body, "right front claw",        BODYPOS_CLAW,          1);
-   bodyAddPosition(body, "right hind leg",          BODYPOS_LEG,           8);
-   bodyAddPosition(body, "left hind leg",           BODYPOS_LEG,           8);
-   bodyAddPosition(body, "right front leg",         BODYPOS_LEG,           8);
-   bodyAddPosition(body, "left front leg",          BODYPOS_LEG,           8);
-   bodyAddPosition(body, "left wing",               BODYPOS_WING,         10);
-   bodyAddPosition(body, "right wing",              BODYPOS_WING,         10);
-   bodyAddPosition(body, "torso",                   BODYPOS_TORSO,        30);
-   bodyAddPosition(body, "neck",                    BODYPOS_NECK,          3);
-   bodyAddPosition(body, "face",                    BODYPOS_FACE,          3);
-   bodyAddPosition(body, "head",                    BODYPOS_HEAD,          2);
-   bodyAddPosition(body, "tail",                    BODYPOS_TAIL,          6);
-   bodyAddPosition(body, "floating about head",     BODYPOS_FLOAT,         0);
-   //                                                                  ------
-   //                                                                    100
-   return body;
- }
- 
- /**
-  * Create a new body with humanoid pieces and proportions
-  */
- BODY_DATA *newHumanoidBody() {
-   BODY_DATA *body = newBody();
-   body->size = BODYSIZE_MEDIUM;
-   bodyAddPosition(body, "right grip",              BODYPOS_HELD,          0);
-   bodyAddPosition(body, "left grip",               BODYPOS_HELD,          0);
-   bodyAddPosition(body, "right foot",              BODYPOS_RIGHT_FOOT,    2);
-   bodyAddPosition(body, "left foot",               BODYPOS_LEFT_FOOT,     2);
-   bodyAddPosition(body, "right leg",               BODYPOS_LEG,           9);
-   bodyAddPosition(body, "left leg",                BODYPOS_LEG,           9);
-   bodyAddPosition(body, "waist",                   BODYPOS_WAIST,         1);
-   bodyAddPosition(body, "right finger",            BODYPOS_FINGER,        1);
-   bodyAddPosition(body, "left finger",             BODYPOS_FINGER,        1);
-   bodyAddPosition(body, "right hand",              BODYPOS_RIGHT_HAND,    2);
-   bodyAddPosition(body, "left hand",               BODYPOS_LEFT_HAND,     2);
-   bodyAddPosition(body, "right wrist",             BODYPOS_WRIST,         1);
-   bodyAddPosition(body, "left wrist",              BODYPOS_WRIST,         1);
-   bodyAddPosition(body, "right arm",               BODYPOS_ARM,           7);
-   bodyAddPosition(body, "left arm",                BODYPOS_ARM,           7);
-   bodyAddPosition(body, "about body",              BODYPOS_ABOUT,         0);
-   bodyAddPosition(body, "torso",                   BODYPOS_TORSO,        50);
-   bodyAddPosition(body, "neck",                    BODYPOS_NECK,          1);
-   bodyAddPosition(body, "right ear",               BODYPOS_EAR,           0);
-   bodyAddPosition(body, "left ear",                BODYPOS_EAR,           0);
-   bodyAddPosition(body, "face",                    BODYPOS_FACE,          2);
-   bodyAddPosition(body, "head",                    BODYPOS_HEAD,          2);
-   bodyAddPosition(body, "floating about head",     BODYPOS_FLOAT,         0);
-   //                                                                  ------
-   //                                                                    100
-   return body;
- }
  
  
  //*****************************************************************************
--- 103,108 ----
***************
*** 196,213 ****
    return strdup(types);
  }
  
- const char *bodytypeGetName(int bodytype) {
-   return bodytype_list[bodytype];
- }
- 
- int bodytypeGetNum(const char *bodytype) {
-   int i;
-   for(i = 0; i < NUM_BODYTYPES; i++)
-     if(!strcasecmp(bodytype, bodytype_list[i]))
-       return i;
-   return BODYTYPE_NONE;
- }
- 
  const char *bodysizeGetName(int size) {
    return bodysize_list[size];
  }
--- 131,136 ----
***************
*** 232,246 ****
    return BODYPOS_NONE;
  }
  
- BODY_DATA *bodyCreate(int bodytype) {
-   switch(bodytype) {
-   case BODYTYPE_HUMANOID:  return newHumanoidBody();
-   case BODYTYPE_DRAGON:    return newDragonBody();
-   default:                 return NULL;
-   }
- }
- 
- 
  BODY_DATA *newBody() {
    struct body_data*B = malloc(sizeof(BODY_DATA));
    B->parts = newList();
--- 155,160 ----
***************
*** 268,273 ****
--- 182,191 ----
    return B->size;
  }
  
+ void bodySetSize(BODY_DATA *B, int size) {
+   B->size = size;
+ }
+ 
  //
  // Find a bodypart on the body with the given name
  //
diff -crN nakedmudv1.4/src/body.h nakedmudv1.5/src/body.h
*** nakedmudv1.4/src/body.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/body.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 38,49 ****
  
  #define NUM_BODYPOS              21
  
- #define BODYTYPE_NONE            -1
- #define BODYTYPE_HUMANOID         0
- #define BODYTYPE_DRAGON           1
- 
- #define NUM_BODYTYPES             2
- 
  #define BODYSIZE_NONE            -1
  #define BODYSIZE_DIMINUITIVE      0
  #define BODYSIZE_TINY             1
--- 38,43 ----
***************
*** 62,79 ****
  
  
  /**
-  * return the name of the bodytype number
-  */
- const char *bodytypeGetName(int bodytype);
- 
- 
- /**
-  * return the number of the bodytype
-  */
- int bodytypeGetNum(const char *bodytype);
- 
- 
- /**
   * return the name of the body position type 
   */
  const char *bodyposGetName(int bodypos);
--- 56,61 ----
***************
*** 98,109 ****
  
  
  /**
-  * Create a specific bodytype
-  */
- BODY_DATA *bodyCreate(int bodytype);
- 
- 
- /**
   * Create a new body
   */
  BODY_DATA *newBody();
--- 80,85 ----
***************
*** 127,132 ****
--- 103,112 ----
   */
  int bodyGetSize(const BODY_DATA *B);
  
+ /**
+  * change the body's size
+  */
+ void bodySetSize(BODY_DATA *B, int size);
  
  /**
   * Add a new position to the body. <type> is one of the basic
diff -crN nakedmudv1.4/src/builder.c nakedmudv1.5/src/builder.c
*** nakedmudv1.4/src/builder.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/builder.c	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,446 ****
- //*****************************************************************************
- //
- // builder.c
- //
- // various utilities (non-OLC) for builders, such as digging/filling exits, 
- // listing zone scripts/rooms/etc, and utilities for loading/purging mobs and
- // objects.
- //
- //*****************************************************************************
- 
- #include "mud.h"
- #include "world.h"
- #include "zone.h"
- #include "room.h"
- #include "exit.h"
- #include "movement.h"
- #include "builder.h"
- #include "character.h"
- #include "object.h"
- #include "handler.h"
- #include "inform.h"
- #include "utils.h"
- #include "races.h"
- #include "items.h"
- #include "dialog.h"
- 
- // optional modules
- #ifdef MODULE_SCRIPTS
- #include "scripts/script.h"
- #include "scripts/script_set.h"
- #endif
- 
- 
- //
- // Try to dig a special exit in a specific direction. Unlike cmd_dig,
- // specdig does not link the room we're digging to, back to us, since
- // we can't really figure out what the opposite direction is
- //
- void try_specdig(CHAR_DATA *ch, const char *dir, room_vnum to) {
-   if(roomGetExitSpecial(charGetRoom(ch), dir))
-     send_to_char(ch, "You must fill in the %s exit before you dig a new exit.\r\n", dir);
-   else if(!worldGetRoom(gameworld, to))
-     send_to_char(ch, "The destination, %d, does not exist.\r\n", to);
-   else {
-     roomDigExitSpecial(charGetRoom(ch), dir, to);
-     send_to_char(ch, "%s now leads to %s.\r\n", 
- 		 dir, roomGetName(worldGetRoom(gameworld, to)));
-   }
- }
- 
- 
- //
- // Try to fill in a special exit in a specific direction. Unlike cmd_dig,
- // specdig does not fill in the exit on the other side, since we can't
- // really figure out what the opposite direction is.
- //
- void try_specfill(CHAR_DATA *ch, const char *dir) {
-   if(!roomGetExitSpecial(charGetRoom(ch), dir))
-     send_to_char(ch, "There doesn't seem to be an exit in that direction.\r\n");
-   else {
-     // delete the exit
-     roomSetExitSpecial(charGetRoom(ch), dir, NULL);
-     send_to_char(ch, "You fill in %s.\r\n", dir);
-   }
- }
- 
- 
- 
- COMMAND(cmd_dig) {
-   char buf[MAX_INPUT_LEN];
-   int dir;
-   int to;
- 
-   // make sure we have input
-   if(!arg || !*arg) {
-     send_to_char(ch, "dig [direction] [room]\r\n");
-     return;
-   }
- 
-   sscanf(arg, "%s %d", buf, &to);
-   dir = dirGetNum(buf);
- 
-   if(dir == DIR_NONE)
-     dir = dirGetAbbrevNum(buf);
- 
- 
-   if(!canEditZone(worldZoneBounding(gameworld,
- 				    roomGetVnum(charGetRoom(ch))), ch))
-     send_to_char(ch, "You are not authorized to edit this zone.\r\n");
-   else if(dir == DIR_NONE)
-     try_specdig(ch, buf, to);
-   else if(roomGetExit(charGetRoom(ch), dir))
-     send_to_char(ch, "You must fill in the exit %s first, before you dig a new exit.\r\n", dirGetName(dir));
-   else if(!worldGetRoom(gameworld, to))
-     send_to_char(ch, "The destination, %d, does not exist.\r\n", to);
-   else {
-     ROOM_DATA *to_room = worldGetRoom(gameworld, to);
-     roomDigExit(charGetRoom(ch), dir, to);
- 
-     // link back to us if possible ... make sure we can edit the zone, too
-     if(!roomGetExit(worldGetRoom(gameworld, to), dirGetOpposite(dir)) &&
-        canEditZone(worldZoneBounding(gameworld, roomGetVnum(to_room)), ch))
-       roomDigExit(to_room,
- 		  dirGetOpposite(dir), 
- 		  roomGetVnum(charGetRoom(ch)));
- 
-     send_to_char(ch, "You dig %s to %s.\r\n", 
- 		 dirGetName(dir), roomGetName(worldGetRoom(gameworld, to)));
- 
-     // save the changes... this will get costly as our world gets bigger.
-     // But that should be alright once we make zone saving a bit smarter
-     worldSave(gameworld, WORLD_PATH);
-   }
- }
- 
- 
- COMMAND(cmd_fill) {
-   char buf[MAX_INPUT_LEN];
-   int dir;
- 
-   if(!arg || !*arg) {
-     send_to_char(ch, "fill [direction]\r\n");
-     return;
-   }
- 
-   sscanf(arg, "%s", buf);
-   dir = dirGetNum(buf);
- 
-   if(dir == DIR_NONE)
-     dir = dirGetAbbrevNum(buf);
- 
-   if(!canEditZone(worldZoneBounding(gameworld,roomGetVnum(charGetRoom(ch))),ch))
-     send_to_char(ch, "You are not authorized to edit this zone.\r\n");
-   else if(dir == DIR_NONE)
-     try_specfill(ch, buf);
-   else if(!roomGetExit(charGetRoom(ch), dir))
-     send_to_char(ch, "There doesn't seem to be an exit in that direction.\r\n");
-   else {
-     ROOM_DATA *exit_to   = NULL;
-     EXIT_DATA *exit_back = NULL;
- 
-     exit_to = worldGetRoom(gameworld,
- 			   exitGetTo(roomGetExit(charGetRoom(ch), dir)));
-     exit_back = roomGetExit(exit_to,
- 			    dirGetOpposite(dir));
- 
-     // see if the room we're filling leads back to us... if so, fill it in
-     if(exit_back &&
-        exitGetTo(exit_back) == roomGetVnum(charGetRoom(ch)))
-       roomSetExit(exit_to, dirGetOpposite(dir), NULL);
- 
-     // delete the exit
-     roomSetExit(charGetRoom(ch), dir, NULL);
-     send_to_char(ch, "You fill in the exit to the %s.\r\n", dirGetName(dir));
- 
-     // save the changes... this will get costly as our world gets bigger.
-     // But that should be alright once we make zone saving a bit smarter
-     worldSave(gameworld, WORLD_PATH);
-   }
- }
- 
- 
- bool try_buildwalk(CHAR_DATA *ch, int dir) {
-   ZONE_DATA *zone = worldZoneBounding(gameworld, roomGetVnum(charGetRoom(ch)));
-   
-   if(!canEditZone(zone, ch))
-     send_to_char(ch, "You are not authorized to edit this zone.\r\n");
-   else if(roomGetExit(charGetRoom(ch), dir))
-     send_to_char(ch, "You try to buildwalk %s, but a room already exists in that direction!\r\n", dirGetName(dir));
-   else if(!zone) {
-     send_to_char(ch, "The room you are in is not attached to a zone!\r\n");
-     log_string("ERROR: %s tried to buildwalk %s, but room %d was not in a zone!", charGetName(ch), dirGetName(dir), roomGetVnum(charGetRoom(ch)));
-   }
-   else {
-     room_vnum vnum = getFreeRoomVnum(zone);
-     if(vnum == NOWHERE)
-       send_to_char(ch, 
- 		   "Zone #%d has no free rooms left. "
- 		   "Buildwalk could not be performed.\r\n", zoneGetVnum(zone));
-     else {
-       char desc[MAX_BUFFER];
-       ROOM_DATA *new_room = newRoom();
-       roomSetVnum(new_room, vnum);
- 
-       roomSetName(new_room, "A New Buildwalk Room");
-       sprintf(desc, "This room was created by %s.\r\n", charGetName(ch));
-       roomSetDesc(new_room, desc);
- 
-       zoneAddRoom(zone, new_room);
-       roomDigExit(charGetRoom(ch), dir, vnum);
-       roomDigExit(new_room, dirGetOpposite(dir), 
- 		  roomGetVnum(charGetRoom(ch)));
-       try_move(ch, dir, NULL);
-       return TRUE;
- 
-       // save the changes... this will get costly as our world gets bigger.
-       // But that should be alright once we make zone saving a bit smarter
-       worldSave(gameworld, WORLD_PATH);
-     }
-   }
-   return FALSE;
- }
- 
- 
- COMMAND(cmd_load) {
-   if(!arg || !*arg)
-     send_to_char(ch, "What did you want to load?\r\n");
-   else {
-     char type[MAX_BUFFER];
-     int vnum;
- 
-     sscanf(arg, "%s %d", type, &vnum);
- 
-     if(strlen(type) < 1)
-       send_to_char(ch, "What did you want to load?\r\n");
- 
-     else if(!strncasecmp("mobile", type, strlen(type))) {
-       CHAR_DATA *mob = worldGetMob(gameworld, vnum);
-       if(mob == NULL)
- 	send_to_char(ch, "No mobile exists with that vnum.\r\n");
-       // make a copy and place it in the world
-       else {
- 	mob = charCopy(mob);
- 	send_to_char(ch, "You create %s.\r\n", charGetName(mob));
- 	char_to_game(mob);
- 	char_to_room(mob, charGetRoom(ch));
- 
- #ifdef MODULE_SCRIPTS
- 	// check for initialization scripts
- 	try_scripts(SCRIPT_TYPE_INIT,
- 		    mob, SCRIPTOR_CHAR,
- 		    NULL, NULL, charGetRoom(mob), NULL, NULL, NULL, 0);
- #endif
-       }
-     }
- 
-     else if(!strncasecmp("object", type, strlen(type))) {
-       OBJ_DATA *obj = worldGetObj(gameworld, vnum);
-       if(obj == NULL)
- 	send_to_char(ch, "No object exists with that vnum.\r\n");
-       else {
- 	obj = objCopy(obj);
- 	send_to_char(ch, "You create %s.\r\n", objGetName(obj));
- 	obj_to_game(obj);
- 	obj_to_char(obj, ch);
- 
- #ifdef MODULE_SCRIPTS
- 	// check for initialization scripts
- 	try_scripts(SCRIPT_TYPE_INIT,
- 		    obj, SCRIPTOR_OBJ,
- 		    ch, NULL, charGetRoom(ch), NULL, NULL, NULL, 0);
- #endif
-       }
-     }
-   }
- }
- 
- 
- COMMAND(cmd_purge) {
- 
-   // purge everything
-   if(!arg || !*arg) {
-     LIST_ITERATOR *list_i = newListIterator(roomGetContents(charGetRoom(ch)));
-     OBJ_DATA *obj;
-     CHAR_DATA *vict;
- 
-     send_to_char(ch, "You purge the room.\r\n");
-     message(ch, NULL, NULL, NULL, FALSE, TO_NOTCHAR,
- 	    "$n raises $s arms, and white flames engulf the entire room.");
- 
-     // purge all the objects. 
-     ITERATE_LIST(obj, list_i)
-       extract_obj(obj);
-     deleteListIterator(list_i);
- 
-     // and now all of the non-characters
-     list_i = newListIterator(roomGetCharacters(charGetRoom(ch)));
-     ITERATE_LIST(vict, list_i) {
-       if(vict == ch || !charIsNPC(vict)) 
- 	continue;
-       char_from_room(vict);
-       extract_mobile(vict);
-     }
-     deleteListIterator(list_i);
-   }
- 
-   // purge one specific thing
-   else {
- 
-     int found_type = FOUND_NONE;
-     void *found;
-     
-     found = generic_find(ch, arg,
- 			 FIND_TYPE_CHAR | FIND_TYPE_OBJ,
- 			 FIND_SCOPE_ROOM | FIND_SCOPE_VISIBLE,
- 			 FALSE, &found_type);
- 
-     // purge  characters
-     if(found_type == FOUND_CHAR) {
-       if(charGetLevel(ch) <= charGetLevel(found))
- 	send_to_char(ch, "Erm, you better not try that on %s.\r\n", 
- 		     HIMHER(found));
-       else {
- 	send_to_char(ch, "You purge %s.\r\n", charGetName(found));
- 	message(ch, found, NULL, NULL, FALSE, TO_NOTVICT | TO_NOTCHAR,
- 		"$n raises $s arms, and white flames engulf $N.");
- 	extract_mobile(found);
-       }
-     }
- 
-     // purge objects
-     else if(found_type == FOUND_OBJ) {
-       send_to_char(ch, "You purge %s.\r\n", objGetName(found));
-       message(ch, NULL, found, NULL, FALSE, TO_NOTCHAR,
- 	      "$n raises $s arms, and white flames engulf $o.");
-       obj_from_room(found);
-       extract_obj(found);
-     }
-     else
-       send_to_char(ch, "What did you want to purge?\r\n");
-   }
- }
- 
- 
- COMMAND(cmd_zreset) {
-   ZONE_DATA *zone = NULL;
- 
-   if(!arg || !*arg)
-     zone = worldZoneBounding(gameworld, roomGetVnum(charGetRoom(ch)));
-   else
-     zone = worldGetZone(gameworld, atoi(arg));
- 
-   if(zone == NULL)
-     send_to_char(ch, "Which zone did you want to reset?\r\n");
-   else if(!canEditZone(zone, ch))
-     send_to_char(ch, "You are not authorized to edit that zone.\r\n");
-   else {
-     send_to_char(ch, "Zone %d has been reset.\r\n", zoneGetVnum(zone));
-     zoneForceReset(zone);
-   }
- }
- 
- 
- //*****************************************************************************
- //
- // Functions for listing different types of data (zones, mobs, objs, etc...)
- //
- //*****************************************************************************
- 
- //
- // Generic xxxlist for builders. If the thing to list doesn't have any types
- // (e.g. dialogs) then typer and type_namer can both be NULL
- //
- void do_list(CHAR_DATA *ch, 
- 	     void *getter, void *namer, 
- 	     void *typer,  void *type_namer, 
- 	     const char *datatype, char *arg) {
-   int (* type_func)(void *)              = typer;
-   const char *(* type_naming_func)(int)  = type_namer;
-   const char *(* naming_func)(void *)    = namer;
-   void *(* get_func)(void *, int)        = getter;
-   ZONE_DATA *zone                        = NULL;
-   
-   if(!arg || !*arg)
-     zone = worldZoneBounding(gameworld, roomGetVnum(charGetRoom(ch)));
-   else
-     zone = worldGetZone(gameworld, atoi(arg));
- 
-   if(zone == NULL)
-     send_to_char(ch, "Which zone did you want to list %s for?\r\n", datatype);
-   else {
-     int vnum;
-     send_to_char(ch,
- " {wVnum  Name                                                                %s\r\n"
- "{b-------------------------------------------------------------------------------{n\r\n",
- 		 ((type_func == NULL || type_naming_func == NULL) ? "" : "Type")
- 		 );
-     for(vnum = zoneGetMinBound(zone); vnum <= zoneGetMaxBound(zone); vnum++) {
-       void *data = get_func(zone, vnum);
-       if(data != NULL)
- 	send_to_char(ch, "{y[{c%4d{y] {c%-50s{w%22s{n\r\n", 
- 		     vnum, naming_func(data), 
- 		     ((type_func == NULL || type_naming_func == NULL) ? "" :
- 		      type_naming_func(type_func(data))));
-     }
-   }
- }
- 
- 
- #ifdef MODULE_SCRIPTS
- COMMAND(cmd_sclist) {
-   do_list(ch, zoneGetScript, scriptGetName, scriptGetType, scriptTypeName,
- 	  "scripts", arg);
- }
- #endif
- 
- COMMAND(cmd_rlist) {
-   do_list(ch, zoneGetRoom, roomGetName, roomGetTerrain, terrainGetName,
- 	  "rooms", arg);
- }
- 
- 
- COMMAND(cmd_mlist) {
-   do_list(ch, zoneGetMob, charGetName, charGetRace, raceGetName,
- 	  "mobs", arg);
- }
- 
- COMMAND(cmd_olist) {
-   do_list(ch, zoneGetObj, objGetName, objGetType, itemGetType,
- 	  "objects", arg);
- }
- 
- COMMAND(cmd_dlist) {
-   do_list(ch, zoneGetDialog, dialogGetName, NULL, NULL, "dialogs", arg);
- }
- 
- int zone_comparator(ZONE_DATA *zone1, ZONE_DATA *zone2) {
-   if(zoneGetVnum(zone1) == zoneGetVnum(zone2))
-     return 0;
-   else if(zoneGetVnum(zone1) < zoneGetVnum(zone2))
-     return -1;
-   else
-     return 1;
- }
- 
- COMMAND(cmd_zlist) {
-   LIST *zones = worldGetZones(gameworld);
-   // first, order all the zones
-   listSortWith(zones, zone_comparator);
-   // now, iterate across them all and show them
-   LIST_ITERATOR *zone_i = newListIterator(zones);
-   ZONE_DATA *zone = NULL;
- 
-   send_to_char(ch,
- " {wVnum  Name                                          Editors  Timer   Min   Max\r\n"
- "{b-------------------------------------------------------------------------------\r\n{n"
- 	       );
- 
-   ITERATE_LIST(zone, zone_i)
-     send_to_char(ch, 
- 		 "{y[{c%4d{y] {c%-30s %22s  {w%5d %5d %5d\r\n",
- 		 zoneGetVnum(zone), zoneGetName(zone), zoneGetEditors(zone),
- 		 zoneGetPulseTimer(zone), zoneGetMinBound(zone), 
- 		 zoneGetMaxBound(zone));
-   deleteListIterator(zone_i);
- }
--- 0 ----
diff -crN nakedmudv1.4/src/builder.h nakedmudv1.5/src/builder.h
*** nakedmudv1.4/src/builder.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/builder.h	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,38 ****
- #ifndef __BUILDER_H
- #define __BUILDER_H
- //*****************************************************************************
- //
- // builder.h
- //
- // various utilities (non-OLC) for builders, such as digging/filling exits, and
- // such.
- //
- //*****************************************************************************
- 
- 
- 
- //
- // creates an exit in a direction to a specific room
- // usage: dig [dir] [room]
- //
- COMMAND(cmd_dig);
- 
- //
- // fills in an exit in a specific direction
- // usage: fill [dir]
- //
- COMMAND(cmd_fill);
- 
- //
- // Load a copy of a specific mob/object
- // usage: load [mob | obj] [vnum]
- //
- COMMAND(cmd_load);
- 
- //
- // Try creating a new room in the specified direction, drawn from the
- // zone we're currently in
- //
- bool try_buildwalk(CHAR_DATA *ch, int dir);
- 
- #endif // __BUILDER_H
--- 0 ----
diff -crN nakedmudv1.4/src/character.c nakedmudv1.5/src/character.c
*** nakedmudv1.4/src/character.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/character.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 93,104 ****
    char                 * password;
    bitvector_t            prfs;  
    room_vnum              loadroom;
  
    // shared data for PCs and NPCs
    int                    uid;
  
    BODY_DATA            * body;
!   int                    race;
  
    SOCKET_DATA          * socket;
    ROOM_DATA            * room;
--- 93,106 ----
    char                 * password;
    bitvector_t            prfs;  
    room_vnum              loadroom;
+   int                    imm_invis;
  
    // shared data for PCs and NPCs
    int                    uid;
  
    BODY_DATA            * body;
!   char                 * race;
!   //  int                    race;
  
    SOCKET_DATA          * socket;
    ROOM_DATA            * room;
***************
*** 128,138 ****
  
    ch->password      = strdup("");
    ch->prfs          = 0;
  
    ch->loadroom      = NOWHERE;
    ch->uid           = NOBODY;
  
!   ch->race          = RACE_HUMAN;
    ch->body          = raceCreateBody(ch->race);
    ch->room          = NULL;
    ch->furniture     = NULL;
--- 130,141 ----
  
    ch->password      = strdup("");
    ch->prfs          = 0;
+   ch->imm_invis     = 0;
  
    ch->loadroom      = NOWHERE;
    ch->uid           = NOBODY;
  
!   ch->race          = strdup(raceDefault());//RACE_HUMAN;
    ch->body          = raceCreateBody(ch->race);
    ch->room          = NULL;
    ch->furniture     = NULL;
***************
*** 281,287 ****
    return ch->body;
  }
  
! int          charGetRace  ( CHAR_DATA *ch) {
    return ch->race;
  }
  
--- 284,290 ----
    return ch->body;
  }
  
! const char  *charGetRace  ( CHAR_DATA *ch) {
    return ch->race;
  }
  
***************
*** 301,306 ****
--- 304,313 ----
    return ch->furniture;
  }
  
+ int charGetImmInvis(CHAR_DATA *ch) {
+   return ch->imm_invis;
+ }
+ 
  void         charSetSocket    ( CHAR_DATA *ch, SOCKET_DATA *socket) {
    ch->socket = socket;
  };
***************
*** 344,351 ****
    ch->body = body;
  }
  
! void         charSetRace  (CHAR_DATA *ch, int race) {
!   ch->race = race;
  }
  
  void         charSetUID(CHAR_DATA *ch, int uid) {
--- 351,359 ----
    ch->body = body;
  }
  
! void         charSetRace  (CHAR_DATA *ch, const char *race) {
!   if(ch->race) free(ch->race);
!   ch->race = strdup(race);
  }
  
  void         charSetUID(CHAR_DATA *ch, int uid) {
***************
*** 364,369 ****
--- 372,380 ----
    ch->furniture = furniture;
  }
  
+ void charSetImmInvis(CHAR_DATA *ch, int level) {
+   ch->imm_invis = level;
+ }
  
  
  //*****************************************************************************
***************
*** 401,420 ****
  CHAR_DATA *charRead(STORAGE_SET *set) {
    CHAR_DATA *mob = newMobile();
  
!   charSetVnum(mob,          read_int   (set, "vnum"));
    charSetName(mob,         read_string(set, "name"));
!   charSetKeywords(mob,      read_string(set, "keywords"));
    charSetRdesc(mob,        read_string(set, "rdesc"));
    charSetDesc(mob,         read_string(set, "desc"));
    charSetMultiRdesc(mob,   read_string(set, "multirdesc"));
    charSetMultiName(mob,    read_string(set, "multiname"));
    charSetLevel(mob,        read_int   (set, "level"));
    charSetSex(mob,          read_int   (set, "sex"));
!   charSetRace(mob,         read_int   (set, "race"));
    charSetPassword(mob,     read_string(set, "password"));
  
    // read in PC data
    if(*charGetPassword(mob)) {
      charSetUID(mob,        read_int   (set, "uid"));
      charSetLoadroom(mob,   read_int   (set, "loadroom"));
      charSetPos(mob,        read_int   (set, "position"));
--- 412,432 ----
  CHAR_DATA *charRead(STORAGE_SET *set) {
    CHAR_DATA *mob = newMobile();
  
!   charSetVnum(mob,         read_int   (set, "vnum"));
    charSetName(mob,         read_string(set, "name"));
!   charSetKeywords(mob,     read_string(set, "keywords"));
    charSetRdesc(mob,        read_string(set, "rdesc"));
    charSetDesc(mob,         read_string(set, "desc"));
    charSetMultiRdesc(mob,   read_string(set, "multirdesc"));
    charSetMultiName(mob,    read_string(set, "multiname"));
    charSetLevel(mob,        read_int   (set, "level"));
    charSetSex(mob,          read_int   (set, "sex"));
!   charSetRace(mob,         read_string(set, "race"));
    charSetPassword(mob,     read_string(set, "password"));
  
    // read in PC data
    if(*charGetPassword(mob)) {
+     charSetImmInvis(mob,   read_int   (set, "imm_invis"));
      charSetUID(mob,        read_int   (set, "uid"));
      charSetLoadroom(mob,   read_int   (set, "loadroom"));
      charSetPos(mob,        read_int   (set, "position"));
***************
*** 428,433 ****
--- 440,451 ----
    mob->auxiliary_data = auxiliaryDataRead(read_set(set, "auxiliary"), 
  					  AUXILIARY_TYPE_CHAR);
  
+   // make sure our race is OK
+   if(!isRace(mob->race)) {
+     free(mob->race);
+     mob->race = strdup(raceDefault());
+   }
+ 
    // reset our body to the default for our race
    charResetBody(mob);
  
***************
*** 437,466 ****
  
  STORAGE_SET *charStore(CHAR_DATA *mob) {
    STORAGE_SET *set = new_storage_set();
!   store_int   (set, "vnum",       mob->vnum,                 NULL);
!   store_string(set, "name",       mob->name,                 NULL);
!   store_string(set, "keywords",   mob->keywords,             NULL);
!   store_string(set, "rdesc",      mob->rdesc,                NULL);
!   store_string(set, "desc",       mob->desc,                 NULL);
!   store_string(set, "multirdesc", mob->multi_rdesc,          NULL);
!   store_string(set, "multiname",  mob->multi_name,           NULL);
!   store_int   (set, "level",      mob->level,                NULL);
!   store_int   (set, "sex",        mob->sex,                  NULL);
!   store_int   (set, "race",       mob->race,                 NULL);
  
    // PC-only data
    if(!charIsNPC(mob)) {
!     store_int   (set, "position",   mob->position,                 NULL);
!     store_string(set, "prfs",       write_bits(mob->prfs),         NULL);
!     store_string(set, "password",   mob->password,                 NULL);
!     store_int   (set, "uid",        mob->uid,                      NULL);
!     store_int   (set, "loadroom",   roomGetVnum(charGetRoom(mob)), NULL);
    }
    // NPC-only data
    else
!     store_int   (set, "dialog",     mob->dialog,               NULL);
  
!   store_set(set,"auxiliary", auxiliaryDataStore(mob->auxiliary_data), NULL);
    return set;
  }
  
--- 455,485 ----
  
  STORAGE_SET *charStore(CHAR_DATA *mob) {
    STORAGE_SET *set = new_storage_set();
!   store_int   (set, "vnum",       mob->vnum);
!   store_string(set, "name",       mob->name);
!   store_string(set, "keywords",   mob->keywords);
!   store_string(set, "rdesc",      mob->rdesc);
!   store_string(set, "desc",       mob->desc);
!   store_string(set, "multirdesc", mob->multi_rdesc);
!   store_string(set, "multiname",  mob->multi_name);
!   store_int   (set, "level",      mob->level);
!   store_int   (set, "sex",        mob->sex);
!   store_string(set, "race",       mob->race);
  
    // PC-only data
    if(!charIsNPC(mob)) {
!     store_int   (set, "imm_invis",  mob->imm_invis);
!     store_int   (set, "position",   mob->position);
!     store_string(set, "prfs",       write_bits(mob->prfs));
!     store_string(set, "password",   mob->password);
!     store_int   (set, "uid",        mob->uid);
!     store_int   (set, "loadroom",   roomGetVnum(charGetRoom(mob)));
    }
    // NPC-only data
    else
!     store_int   (set, "dialog",     mob->dialog);
  
!   store_set(set,"auxiliary", auxiliaryDataStore(mob->auxiliary_data));
    return set;
  }
  
***************
*** 480,485 ****
--- 499,505 ----
    charSetPos        (to, charGetPos(from));
    charSetRace       (to, charGetRace(from));
    charSetBody       (to, bodyCopy(charGetBody(from)));
+   charSetImmInvis   (to, charGetImmInvis(from));
  
    auxiliaryDataCopyTo(from->auxiliary_data, to->auxiliary_data);
  }
diff -crN nakedmudv1.4/src/character.h nakedmudv1.5/src/character.h
*** nakedmudv1.4/src/character.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/character.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 36,41 ****
--- 36,42 ----
  void         charResetBody    (CHAR_DATA *ch);
  
  
+ 
  //*****************************************************************************
  //
  // utility functions
***************
*** 70,81 ****
  char       **charGetDescPtr   ( CHAR_DATA *ch);
  LIST        *charGetInventory ( CHAR_DATA *ch);
  BODY_DATA   *charGetBody      ( CHAR_DATA *ch);
! int          charGetRace      ( CHAR_DATA *ch);
  int          charGetUID       ( CHAR_DATA *ch);
  room_vnum    charGetLoadroom  ( CHAR_DATA *ch);
  OBJ_DATA    *charGetFurniture ( CHAR_DATA *ch);
  int          charGetPos       ( CHAR_DATA *ch);
  void        *charGetAuxiliaryData(const CHAR_DATA *ch, const char *name);
  
  void         charSetSocket    ( CHAR_DATA *ch, SOCKET_DATA *socket);
  void         charSetRoom      ( CHAR_DATA *ch, ROOM_DATA *room);
--- 71,83 ----
  char       **charGetDescPtr   ( CHAR_DATA *ch);
  LIST        *charGetInventory ( CHAR_DATA *ch);
  BODY_DATA   *charGetBody      ( CHAR_DATA *ch);
! const char  *charGetRace      ( CHAR_DATA *ch);
  int          charGetUID       ( CHAR_DATA *ch);
  room_vnum    charGetLoadroom  ( CHAR_DATA *ch);
  OBJ_DATA    *charGetFurniture ( CHAR_DATA *ch);
  int          charGetPos       ( CHAR_DATA *ch);
  void        *charGetAuxiliaryData(const CHAR_DATA *ch, const char *name);
+ int          charGetImmInvis  ( CHAR_DATA *ch);
  
  void         charSetSocket    ( CHAR_DATA *ch, SOCKET_DATA *socket);
  void         charSetRoom      ( CHAR_DATA *ch, ROOM_DATA *room);
***************
*** 88,98 ****
  void         charSetMultiRdesc( CHAR_DATA *ch, const char *multi_rdesc);
  void         charSetMultiName ( CHAR_DATA *ch, const char *multi_name);
  void         charSetBody      ( CHAR_DATA *ch, BODY_DATA *body);
! void         charSetRace      ( CHAR_DATA *ch, int race);
  void         charSetUID       ( CHAR_DATA *ch, int uid);
  void         charSetLoadroom  ( CHAR_DATA *ch, room_vnum loadroom);
  void         charSetFurniture ( CHAR_DATA *ch, OBJ_DATA *furniture);
  void         charSetPos       ( CHAR_DATA *ch, int pos);
  
  
  //*****************************************************************************
--- 90,102 ----
  void         charSetMultiRdesc( CHAR_DATA *ch, const char *multi_rdesc);
  void         charSetMultiName ( CHAR_DATA *ch, const char *multi_name);
  void         charSetBody      ( CHAR_DATA *ch, BODY_DATA *body);
! void         charSetRace      ( CHAR_DATA *ch, const char *race);
  void         charSetUID       ( CHAR_DATA *ch, int uid);
  void         charSetLoadroom  ( CHAR_DATA *ch, room_vnum loadroom);
  void         charSetFurniture ( CHAR_DATA *ch, OBJ_DATA *furniture);
  void         charSetPos       ( CHAR_DATA *ch, int pos);
+ void         charSetImmInvis  ( CHAR_DATA *ch, int level);
+ 
  
  
  //*****************************************************************************
***************
*** 120,128 ****
--- 124,135 ----
  void         charRemoveBit    ( CHAR_DATA *ch, int field, int bit);
  bool         charIsBitSet     ( CHAR_DATA *ch, int field, int bit);
  
+ // hmmm... we should really replace bitvectors with something a bit
+ // more amenable to extention by modules. Perhaps use char_vars?
  #define BITFIELD_PRFS             0
  
  #define PRF_BUILDWALK             0    // (1 << 0)
+ #define PRF_MAPWALK               1    // (1 << 1)
  
  
  
***************
*** 132,140 ****
  //
  //*****************************************************************************
  #define SEX_NONE                (-1)
! #define SEX_NEUTRAL               0
! #define SEX_MALE                  1
! #define SEX_FEMALE                2
  #define NUM_SEXES                 3
  
  const char *sexGetName(int sex);
--- 139,147 ----
  //
  //*****************************************************************************
  #define SEX_NONE                (-1)
! #define SEX_MALE                  0
! #define SEX_FEMALE                1
! #define SEX_NEUTRAL               2
  #define NUM_SEXES                 3
  
  const char *sexGetName(int sex);
diff -crN nakedmudv1.4/src/char_vars/char_vars.c nakedmudv1.5/src/char_vars/char_vars.c
*** nakedmudv1.4/src/char_vars/char_vars.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/char_vars/char_vars.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 179,191 ****
    const char        *key = NULL;
    CHAR_VAR          *val = NULL;
  
!   store_list(set, "variables", list, NULL);
    // iterate across all the entries and add them
    ITERATE_HASH(key, val, hash_i) {
      STORAGE_SET *var_set = new_storage_set();
!     store_string(var_set, "key",  key,                       NULL);
!     store_string(var_set, "val",  val->str_val,              NULL);
!     store_string(var_set, "type", char_var_types[val->type], NULL);
      storage_list_put(list, var_set);
    }
    deleteHashIterator(hash_i);
--- 179,191 ----
    const char        *key = NULL;
    CHAR_VAR          *val = NULL;
  
!   store_list(set, "variables", list);
    // iterate across all the entries and add them
    ITERATE_HASH(key, val, hash_i) {
      STORAGE_SET *var_set = new_storage_set();
!     store_string(var_set, "key",  key);
!     store_string(var_set, "val",  val->str_val);
!     store_string(var_set, "type", char_var_types[val->type]);
      storage_list_put(list, var_set);
    }
    deleteHashIterator(hash_i);
diff -crN nakedmudv1.4/src/cmd_admin.c nakedmudv1.5/src/cmd_admin.c
*** nakedmudv1.4/src/cmd_admin.c	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/src/cmd_admin.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,252 ----
+ //*****************************************************************************
+ //
+ // cmd_admin.c
+ //
+ // commands and procedures available only to admins.
+ //
+ //*****************************************************************************
+ 
+ #include "mud.h"
+ #include "world.h"
+ #include "inform.h"
+ #include "character.h"
+ #include "handler.h"
+ #include "utils.h"
+ #include "log.h"
+ #include "socket.h"
+ #include "save.h"
+ #include "event.h"
+ #include "action.h"
+ #include "storage.h"
+ 
+ 
+ //
+ // BOOM! Shut down the MUD
+ //
+ COMMAND(cmd_shutdown) {
+   shut_down = TRUE;
+ }
+ 
+ 
+ //
+ // Go to a specific room, object, or character in the game. Rooms are referenced
+ // by vnum. Everything else is referenced by name.
+ //   usage: goto [thing]
+ //
+ //   examples:
+ //     goto 100             go to room number 100
+ //     goto jim             go to an object/person named jim
+ //
+ COMMAND(cmd_goto) {
+   if(!arg || !*arg)
+     send_to_char(ch, "Where would you like to go to?\r\n");
+   // we're trying to go to a specific room number
+   else if(isdigit(*arg)) {
+     ROOM_DATA *room = worldGetRoom(gameworld, atoi(arg));
+ 
+     if(!room)
+       send_to_char(ch, "No such room exists.\r\n");
+     else if(room == charGetRoom(ch))
+       send_to_char(ch, "You're already here, boss.\r\n");
+     else {
+       message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
+ 	      "$n disappears in a puff of smoke.");
+       char_from_room(ch);
+       char_to_room(ch, room);
+       look_at_room(ch, room);
+       message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
+ 	      "$n arrives in a puff of smoke.");
+     }
+   }
+ 
+   // find the character we're trying to go to
+   else {
+     void *tgt = generic_find(ch, arg, 
+ 			     FIND_TYPE_CHAR,
+ 			     FIND_SCOPE_WORLD | FIND_SCOPE_VISIBLE,
+ 			     FALSE, NULL);
+ 
+     if(ch == tgt)
+       send_to_char(ch, "You're already here, boss.\r\n");
+     else if(tgt != NULL) {
+       message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
+ 	      "$n disappears in a puff of smoke.");
+       char_from_room(ch);
+       char_to_room(ch, charGetRoom(tgt));
+       look_at_room(ch, charGetRoom(ch));
+       message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
+ 	      "$n arrives in a puff of smoke.");
+     }
+     else
+       send_to_char(ch, "Who were you trying to go to?\r\n");
+   }
+ }
+ 
+ 
+ //
+ // The opposite of goto. Instead of moving to a specified location, it
+ // takes the target to the user.
+ //   usage: transfer [player]
+ //
+ COMMAND(cmd_transfer) {
+   if(!arg || !*arg)
+     send_to_char(ch, "Who would you like to transfer?\r\n");
+   else {
+     void *tgt = generic_find(ch, arg, 
+ 			     FIND_TYPE_CHAR,
+ 			     FIND_SCOPE_WORLD | FIND_SCOPE_VISIBLE,
+ 			     FALSE, NULL);
+ 
+     if(ch == tgt)
+       send_to_char(ch, "You're already here, boss.\r\n");
+     else if(charGetRoom(ch) == charGetRoom(tgt))
+       send_to_char(ch, "They're already here.\r\n");
+     else if(tgt != NULL) {
+       message(ch, tgt, NULL, NULL, TRUE, TO_VICT,
+ 	      "$n has transferred you!");
+       message(tgt, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
+ 	      "$n disappears in a puff of smoke.");
+       char_from_room(tgt);
+       char_to_room(tgt, charGetRoom(ch));
+       look_at_room(tgt, charGetRoom(tgt));
+       message(tgt, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
+ 	      "$n arrives in a puff of smoke.");
+     }
+     else
+       send_to_char(ch, "Who were you trying to transfer?\r\n");
+   }
+ }
+ 
+ 
+ //
+ // Perform a copyover
+ //
+ COMMAND(cmd_copyover) { 
+   FILE *fp;
+   SOCKET_DATA *dsock;
+   char buf[100];
+   char control_buf[20];
+   char port_buf[20];
+   LIST_ITERATOR *sock_i = newListIterator(socket_list);
+   
+   if ((fp = fopen(COPYOVER_FILE, "w")) == NULL)
+   {
+     text_to_char(ch, "Copyover file not writeable, aborted.\n\r");
+     return;
+   }
+ 
+   sprintf(buf, "\n\r <*>            The world starts spinning             <*>\n\r");
+ 
+   /* For each playing descriptor, save its state */
+   //  for (dsock = dsock_list; dsock ; dsock = dsock_next)
+   ITERATE_LIST(dsock, sock_i) {
+     compressEnd(dsock, dsock->compressing, FALSE);
+     if (dsock->state != STATE_PLAYING) {
+       text_to_socket(dsock, "\r\nSorry, we are rebooting. Come back in a few minutes.\r\n");
+       close_socket(dsock, FALSE);
+     }
+     else {
+       fprintf(fp, "%d %s %s\n",
+ 	      dsock->control, charGetName(dsock->player), dsock->hostname);
+       /* save the player */
+       save_player(dsock->player);
+       text_to_socket(dsock, buf);
+     }
+   }
+   deleteListIterator(sock_i);
+   
+   fprintf (fp, "-1\n");
+   fclose (fp);
+ 
+ 
+   /* close any pending sockets */
+   recycle_sockets();
+   
+   /* exec - descriptors are inherited */
+   sprintf(control_buf, "%d", control);
+   sprintf(port_buf, "%d", mudport);
+   execl(EXE_FILE, "NakedMud", "-copyover", control_buf, port_buf, NULL);
+ 
+   /* Failed - sucessful exec will not return */
+   text_to_char(ch, "Copyover FAILED!\n\r");
+ }
+ 
+ 
+ //
+ // show a list of all the PCs who are linkdead
+ //
+ COMMAND(cmd_linkdead) {
+   CHAR_DATA *xMob;
+   char buf[MAX_BUFFER];
+   bool found = FALSE;
+   LIST_ITERATOR *mob_i = newListIterator(mobile_list);
+ 
+   ITERATE_LIST(xMob, mob_i) {
+     if (!(charIsNPC(xMob) || charGetSocket(xMob))) {
+       sprintf(buf, "%s is linkdead.\n\r", charGetName(xMob));
+       text_to_char(ch, buf);
+       found = TRUE;
+     }
+   }
+   deleteListIterator(mob_i);
+ 
+   if (!found)
+     text_to_char(ch, "Noone is currently linkdead.\n\r");
+ }
+ 
+ 
+ //
+ // List all of the non-player commands the character has access to
+ //
+ COMMAND(cmd_wizhelp) {
+   show_commands(ch, LEVEL_BUILDER, charGetLevel(ch));
+ }
+ 
+ 
+ //
+ // Turn on/off immortal invisibility
+ //
+ COMMAND(cmd_invis) {
+   int level = charGetLevel(ch); // default to our level
+   if(arg && *arg && isdigit(*arg))
+     level = atoi(arg);
+ 
+   // make sure we're not trying to go invisible at a level higher than us
+   if(level > charGetLevel(ch)) {
+     send_to_char(ch, "You cannot go invisibile to a level higher than yours.\r\n");
+     return;
+   }
+ 
+   // see if we're trying to go visible
+   if(level == 0 && charGetImmInvis(ch) > 0) {
+     send_to_char(ch, "Invisibility turned off.\r\n");
+     charSetImmInvis(ch, 0);
+     message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
+ 	    "$n slowly fades into existence.");    
+   }
+   // or invisible
+   else if(level > 0) {
+     message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
+ 	    "$n slowly fades out of existence.");
+     charSetImmInvis(ch, level);
+     send_to_char(ch, "You are now invisible to anyone below level %d.\r\n",
+ 		 level);
+   }
+   // we tried to go visible, but we already are visible
+   else
+     send_to_char(ch, "But you're already visible!\r\n");
+ }
+ 
+ 
+ //
+ // turn off immortal invisibility
+ //
+ COMMAND(cmd_visible) {
+   if(charGetImmInvis(ch) == 0)
+     send_to_char(ch, "But you're already visible!\r\n");
+   else {
+     charSetImmInvis(ch, 0);
+     message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
+ 	    "$n slowly fades into existence.");
+   }
+ }
diff -crN nakedmudv1.4/src/cmd_builder.c nakedmudv1.5/src/cmd_builder.c
*** nakedmudv1.4/src/cmd_builder.c	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/src/cmd_builder.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,423 ----
+ //*****************************************************************************
+ //
+ // cmd_builder.c
+ //
+ // various utilities (non-OLC) for builders, such as digging/filling exits, 
+ // listing zone scripts/rooms/etc, and utilities for loading/purging mobs and
+ // objects.
+ //
+ //*****************************************************************************
+ 
+ #include "mud.h"
+ #include "world.h"
+ #include "zone.h"
+ #include "room.h"
+ #include "exit.h"
+ #include "movement.h"
+ #include "character.h"
+ #include "object.h"
+ #include "handler.h"
+ #include "inform.h"
+ #include "utils.h"
+ #include "races.h"
+ #include "items.h"
+ #include "dialog.h"
+ 
+ // optional modules
+ #ifdef MODULE_SCRIPTS
+ #include "scripts/script.h"
+ #include "scripts/script_set.h"
+ #endif
+ 
+ 
+ //
+ // Try to dig a special exit in a specific direction. Unlike cmd_dig,
+ // specdig does not link the room we're digging to, back to us, since
+ // we can't really figure out what the opposite direction is
+ //
+ void try_specdig(CHAR_DATA *ch, const char *dir, room_vnum to) {
+   if(roomGetExitSpecial(charGetRoom(ch), dir))
+     send_to_char(ch, "You must fill in the %s exit before you dig a new exit.\r\n", dir);
+   else if(!worldGetRoom(gameworld, to))
+     send_to_char(ch, "The destination, %d, does not exist.\r\n", to);
+   else {
+     roomDigExitSpecial(charGetRoom(ch), dir, to);
+     send_to_char(ch, "%s now leads to %s.\r\n", 
+ 		 dir, roomGetName(worldGetRoom(gameworld, to)));
+   }
+ }
+ 
+ 
+ //
+ // Try to fill in a special exit in a specific direction. Unlike cmd_dig,
+ // specdig does not fill in the exit on the other side, since we can't
+ // really figure out what the opposite direction is.
+ //
+ void try_specfill(CHAR_DATA *ch, const char *dir) {
+   if(!roomGetExitSpecial(charGetRoom(ch), dir))
+     send_to_char(ch, "There doesn't seem to be an exit in that direction.\r\n");
+   else {
+     // delete the exit
+     roomSetExitSpecial(charGetRoom(ch), dir, NULL);
+     send_to_char(ch, "You fill in %s.\r\n", dir);
+   }
+ }
+ 
+ 
+ //
+ // creates an exit in a direction to a specific room
+ // usage: dig [dir] [room]
+ //
+ COMMAND(cmd_dig) {
+   char buf[MAX_INPUT_LEN];
+   int dir;
+   int to;
+ 
+   // make sure we have input
+   if(!arg || !*arg) {
+     send_to_char(ch, "dig [direction] [room]\r\n");
+     return;
+   }
+ 
+   sscanf(arg, "%s %d", buf, &to);
+   dir = dirGetNum(buf);
+ 
+   if(dir == DIR_NONE)
+     dir = dirGetAbbrevNum(buf);
+ 
+ 
+   if(!canEditZone(worldZoneBounding(gameworld,
+ 				    roomGetVnum(charGetRoom(ch))), ch))
+     send_to_char(ch, "You are not authorized to edit this zone.\r\n");
+   else if(dir == DIR_NONE)
+     try_specdig(ch, buf, to);
+   else if(roomGetExit(charGetRoom(ch), dir))
+     send_to_char(ch, "You must fill in the exit %s first, before you dig a new exit.\r\n", dirGetName(dir));
+   else if(!worldGetRoom(gameworld, to))
+     send_to_char(ch, "The destination, %d, does not exist.\r\n", to);
+   else {
+     ROOM_DATA *to_room = worldGetRoom(gameworld, to);
+     roomDigExit(charGetRoom(ch), dir, to);
+ 
+     // link back to us if possible ... make sure we can edit the zone, too
+     if(!roomGetExit(worldGetRoom(gameworld, to), dirGetOpposite(dir)) &&
+        canEditZone(worldZoneBounding(gameworld, roomGetVnum(to_room)), ch))
+       roomDigExit(to_room,
+ 		  dirGetOpposite(dir), 
+ 		  roomGetVnum(charGetRoom(ch)));
+ 
+     send_to_char(ch, "You dig %s to %s.\r\n", 
+ 		 dirGetName(dir), roomGetName(worldGetRoom(gameworld, to)));
+ 
+     // save the changes... this will get costly as our world gets bigger.
+     // But that should be alright once we make zone saving a bit smarter
+     worldSave(gameworld, WORLD_PATH);
+   }
+ }
+ 
+ 
+ //
+ // fills in an exit in a specific direction
+ // usage: fill [dir]
+ //
+ COMMAND(cmd_fill) {
+   char buf[MAX_INPUT_LEN];
+   int dir;
+ 
+   if(!arg || !*arg) {
+     send_to_char(ch, "fill [direction]\r\n");
+     return;
+   }
+ 
+   sscanf(arg, "%s", buf);
+   dir = dirGetNum(buf);
+ 
+   if(dir == DIR_NONE)
+     dir = dirGetAbbrevNum(buf);
+ 
+   if(!canEditZone(worldZoneBounding(gameworld,roomGetVnum(charGetRoom(ch))),ch))
+     send_to_char(ch, "You are not authorized to edit this zone.\r\n");
+   else if(dir == DIR_NONE)
+     try_specfill(ch, buf);
+   else if(!roomGetExit(charGetRoom(ch), dir))
+     send_to_char(ch, "There doesn't seem to be an exit in that direction.\r\n");
+   else {
+     ROOM_DATA *exit_to   = NULL;
+     EXIT_DATA *exit_back = NULL;
+ 
+     exit_to = worldGetRoom(gameworld,
+ 			   exitGetTo(roomGetExit(charGetRoom(ch), dir)));
+     exit_back = roomGetExit(exit_to,
+ 			    dirGetOpposite(dir));
+ 
+     // see if the room we're filling leads back to us... if so, fill it in
+     if(exit_back &&
+        exitGetTo(exit_back) == roomGetVnum(charGetRoom(ch)))
+       roomSetExit(exit_to, dirGetOpposite(dir), NULL);
+ 
+     // delete the exit
+     roomSetExit(charGetRoom(ch), dir, NULL);
+     send_to_char(ch, "You fill in the exit to the %s.\r\n", dirGetName(dir));
+ 
+     // save the changes... this will get costly as our world gets bigger.
+     // But that should be alright once we make zone saving a bit smarter
+     worldSave(gameworld, WORLD_PATH);
+   }
+ }
+ 
+ 
+ //
+ // Load a copy of a specific mob/object
+ // usage: load [mob | obj] [vnum]
+ //
+ COMMAND(cmd_load) {
+   if(!arg || !*arg)
+     send_to_char(ch, "What did you want to load?\r\n");
+   else {
+     char type[MAX_BUFFER];
+     int vnum;
+ 
+     sscanf(arg, "%s %d", type, &vnum);
+ 
+     if(strlen(type) < 1)
+       send_to_char(ch, "What did you want to load?\r\n");
+ 
+     else if(!strncasecmp("mobile", type, strlen(type))) {
+       CHAR_DATA *mob = worldGetMob(gameworld, vnum);
+       if(mob == NULL)
+ 	send_to_char(ch, "No mobile exists with that vnum.\r\n");
+       // make a copy and place it in the world
+       else {
+ 	mob = charCopy(mob);
+ 	send_to_char(ch, "You create %s.\r\n", charGetName(mob));
+ 	char_to_game(mob);
+ 	char_to_room(mob, charGetRoom(ch));
+ 
+ #ifdef MODULE_SCRIPTS
+ 	// check for initialization scripts
+ 	try_scripts(SCRIPT_TYPE_INIT,
+ 		    mob, SCRIPTOR_CHAR,
+ 		    NULL, NULL, charGetRoom(mob), NULL, NULL, 0);
+ #endif
+       }
+     }
+ 
+     else if(!strncasecmp("object", type, strlen(type))) {
+       OBJ_DATA *obj = worldGetObj(gameworld, vnum);
+       if(obj == NULL)
+ 	send_to_char(ch, "No object exists with that vnum.\r\n");
+       else {
+ 	obj = objCopy(obj);
+ 	send_to_char(ch, "You create %s.\r\n", objGetName(obj));
+ 	obj_to_game(obj);
+ 	obj_to_char(obj, ch);
+ 
+ #ifdef MODULE_SCRIPTS
+ 	// check for initialization scripts
+ 	try_scripts(SCRIPT_TYPE_INIT,
+ 		    obj, SCRIPTOR_OBJ,
+ 		    ch, NULL, charGetRoom(ch), NULL, NULL, 0);
+ #endif
+       }
+     }
+   }
+ }
+ 
+ 
+ //
+ // remove an object or player from the game. If no argument is supplied, all
+ // objects and non-player characters are removed from the current room.
+ //   usage: purge <target>
+ //
+ COMMAND(cmd_purge) {
+ 
+   // purge everything
+   if(!arg || !*arg) {
+     LIST_ITERATOR *list_i = newListIterator(roomGetContents(charGetRoom(ch)));
+     OBJ_DATA *obj;
+     CHAR_DATA *vict;
+ 
+     send_to_char(ch, "You purge the room.\r\n");
+     message(ch, NULL, NULL, NULL, FALSE, TO_NOTCHAR,
+ 	    "$n raises $s arms, and white flames engulf the entire room.");
+ 
+     // purge all the objects. 
+     ITERATE_LIST(obj, list_i)
+       extract_obj(obj);
+     deleteListIterator(list_i);
+ 
+     // and now all of the non-characters
+     list_i = newListIterator(roomGetCharacters(charGetRoom(ch)));
+     ITERATE_LIST(vict, list_i) {
+       if(vict == ch || !charIsNPC(vict)) 
+ 	continue;
+       char_from_room(vict);
+       extract_mobile(vict);
+     }
+     deleteListIterator(list_i);
+   }
+ 
+   // purge one specific thing
+   else {
+ 
+     int found_type = FOUND_NONE;
+     void *found;
+     
+     found = generic_find(ch, arg,
+ 			 FIND_TYPE_CHAR | FIND_TYPE_OBJ,
+ 			 FIND_SCOPE_ROOM | FIND_SCOPE_VISIBLE,
+ 			 FALSE, &found_type);
+ 
+     // purge  characters
+     if(found_type == FOUND_CHAR) {
+       if(charGetLevel(ch) <= charGetLevel(found))
+ 	send_to_char(ch, "Erm, you better not try that on %s.\r\n", 
+ 		     HIMHER(found));
+       else {
+ 	send_to_char(ch, "You purge %s.\r\n", charGetName(found));
+ 	message(ch, found, NULL, NULL, FALSE, TO_NOTVICT | TO_NOTCHAR,
+ 		"$n raises $s arms, and white flames engulf $N.");
+ 	extract_mobile(found);
+       }
+     }
+ 
+     // purge objects
+     else if(found_type == FOUND_OBJ) {
+       send_to_char(ch, "You purge %s.\r\n", objGetName(found));
+       message(ch, NULL, found, NULL, FALSE, TO_NOTCHAR,
+ 	      "$n raises $s arms, and white flames engulf $o.");
+       obj_from_room(found);
+       extract_obj(found);
+     }
+     else
+       send_to_char(ch, "What did you want to purge?\r\n");
+   }
+ }
+ 
+ 
+ //
+ // trigger all of a specified zone's reset scripts and such. If no vnum is
+ // supplied, the zone the user is currently in is reset.
+ //   usage: zreset <zone vnum>
+ //
+ COMMAND(cmd_zreset) {
+   ZONE_DATA *zone = NULL;
+ 
+   if(!arg || !*arg)
+     zone = worldZoneBounding(gameworld, roomGetVnum(charGetRoom(ch)));
+   else
+     zone = worldGetZone(gameworld, atoi(arg));
+ 
+   if(zone == NULL)
+     send_to_char(ch, "Which zone did you want to reset?\r\n");
+   else if(!canEditZone(zone, ch))
+     send_to_char(ch, "You are not authorized to edit that zone.\r\n");
+   else {
+     send_to_char(ch, "Zone %d has been reset.\r\n", zoneGetVnum(zone));
+     zoneForceReset(zone);
+   }
+ }
+ 
+ 
+ //*****************************************************************************
+ //
+ // Functions for listing different types of data (zones, mobs, objs, etc...)
+ //
+ //*****************************************************************************
+ 
+ //
+ // Generic xxxlist for builders. If the thing to list doesn't have any types
+ // (e.g. dialogs) then typer and type_namer can both be NULL
+ //
+ void do_list(CHAR_DATA *ch, 
+ 	     void *getter, void *namer, 
+ 	     void *typer,  void *type_namer, 
+ 	     const char *datatype, char *arg) {
+   int (* type_func)(void *)              = typer;
+   const char *(* type_naming_func)(int)  = type_namer;
+   const char *(* naming_func)(void *)    = namer;
+   void *(* get_func)(void *, int)        = getter;
+   ZONE_DATA *zone                        = NULL;
+   
+   if(!arg || !*arg)
+     zone = worldZoneBounding(gameworld, roomGetVnum(charGetRoom(ch)));
+   else
+     zone = worldGetZone(gameworld, atoi(arg));
+ 
+   if(zone == NULL)
+     send_to_char(ch, "Which zone did you want to list %s for?\r\n", datatype);
+   else {
+     int vnum;
+     send_to_char(ch,
+ " {wVnum  Name                                                                %s\r\n"
+ "{b-------------------------------------------------------------------------------{n\r\n",
+ 		 ((type_func == NULL || type_naming_func == NULL) ? "" : "Type")
+ 		 );
+     for(vnum = zoneGetMinBound(zone); vnum <= zoneGetMaxBound(zone); vnum++) {
+       void *data = get_func(zone, vnum);
+       if(data != NULL)
+ 	send_to_char(ch, "{y[{c%4d{y] {c%-50s{w%22s{n\r\n", 
+ 		     vnum, naming_func(data), 
+ 		     ((type_func == NULL || type_naming_func == NULL) ? "" :
+ 		      type_naming_func(type_func(data))));
+     }
+   }
+ }
+ 
+ 
+ #ifdef MODULE_SCRIPTS
+ COMMAND(cmd_sclist) {
+   do_list(ch, zoneGetScript, scriptGetName, scriptGetType, scriptTypeName,
+ 	  "scripts", arg);
+ }
+ #endif
+ 
+ COMMAND(cmd_rlist) {
+   do_list(ch, zoneGetRoom, roomGetName, roomGetTerrain, terrainGetName,
+ 	  "rooms", arg);
+ }
+ 
+ COMMAND(cmd_mlist) {
+   //  do_list(ch, zoneGetMob, charGetName, charGetRace, raceGetName,
+   //	  "mobs", arg);
+ }
+ 
+ COMMAND(cmd_olist) {
+   do_list(ch, zoneGetObj, objGetName, objGetType, itemGetType,
+ 	  "objects", arg);
+ }
+ 
+ COMMAND(cmd_dlist) {
+   do_list(ch, zoneGetDialog, dialogGetName, NULL, NULL, "dialogs", arg);
+ }
+ 
+ int zone_comparator(ZONE_DATA *zone1, ZONE_DATA *zone2) {
+   if(zoneGetVnum(zone1) == zoneGetVnum(zone2))
+     return 0;
+   else if(zoneGetVnum(zone1) < zoneGetVnum(zone2))
+     return -1;
+   else
+     return 1;
+ }
+ 
+ COMMAND(cmd_zlist) {
+   LIST *zones = worldGetZones(gameworld);
+   // first, order all the zones
+   listSortWith(zones, zone_comparator);
+   // now, iterate across them all and show them
+   LIST_ITERATOR *zone_i = newListIterator(zones);
+   ZONE_DATA *zone = NULL;
+ 
+   send_to_char(ch,
+ " {wVnum  Name                                          Editors  Timer   Min   Max\r\n"
+ "{b-------------------------------------------------------------------------------\r\n{n"
+ 	       );
+ 
+   ITERATE_LIST(zone, zone_i)
+     send_to_char(ch, 
+ 		 "{y[{c%4d{y] {c%-30s %22s  {w%5d %5d %5d\r\n",
+ 		 zoneGetVnum(zone), zoneGetName(zone), zoneGetEditors(zone),
+ 		 zoneGetPulseTimer(zone), zoneGetMinBound(zone), 
+ 		 zoneGetMaxBound(zone));
+   deleteListIterator(zone_i);
+ }
diff -crN nakedmudv1.4/src/cmd_manip.c nakedmudv1.5/src/cmd_manip.c
*** nakedmudv1.4/src/cmd_manip.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/cmd_manip.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 36,42 ****
  //
  COMMAND(cmd_lock) {
    if(!arg || !*arg) {
!     send_to_char(ch, "What were you wanting to unlock?\r\n");
      return;
    }
  
--- 36,42 ----
  //
  COMMAND(cmd_lock) {
    if(!arg || !*arg) {
!     send_to_char(ch, "What were you wanting to lock?\r\n");
      return;
    }
  
diff -crN nakedmudv1.4/src/cmd_misc.c nakedmudv1.5/src/cmd_misc.c
*** nakedmudv1.4/src/cmd_misc.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/cmd_misc.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 11,25 ****
  #include "utils.h"
  #include "save.h"
  #include "event.h"
  #include "handler.h"
  
  
  //
  // Various preference bits that can be turned on and off
  //
  COMMAND(cmd_tog_prf) {
    switch(subcmd) {
!   case SUBCMD_BUILDWALK:
      charToggleBit(ch, BITFIELD_PRFS, PRF_BUILDWALK);
      send_to_char(ch, "Buildwalk %s.\r\n", 
  		 (charIsBitSet(ch, BITFIELD_PRFS, PRF_BUILDWALK) ? "on":"off"));
--- 11,49 ----
  #include "utils.h"
  #include "save.h"
  #include "event.h"
+ #include "action.h"
  #include "handler.h"
  
  
  //
+ // stop performing the character's current action
+ //
+ COMMAND(cmd_stop) {
+ #ifdef MODULE_FACULTY
+   if(!is_acting(ch, FACULTY_ALL))
+     send_to_char(ch, "But you're not currently performing an action!\r\n");
+   else
+     interrupt_action(ch, FACULTY_ALL);
+ #else
+   if(!is_acting(ch, 1))
+     send_to_char(ch, "But you're not currently performing an action!\r\n");
+   else
+     interrupt_action(ch, 1);
+ #endif
+ }
+ 
+ 
+ //
  // Various preference bits that can be turned on and off
  //
  COMMAND(cmd_tog_prf) {
    switch(subcmd) {
!   case PRF_MAPWALK:
!     charToggleBit(ch, BITFIELD_PRFS, PRF_MAPWALK);
!     send_to_char(ch, "Mapwalk %s.\r\n",
! 		 (charIsBitSet(ch, BITFIELD_PRFS, PRF_MAPWALK) ? "on":"off"));
!     break;
!   case PRF_BUILDWALK:
      charToggleBit(ch, BITFIELD_PRFS, PRF_BUILDWALK);
      send_to_char(ch, "Buildwalk %s.\r\n", 
  		 (charIsBitSet(ch, BITFIELD_PRFS, PRF_BUILDWALK) ? "on":"off"));
***************
*** 140,142 ****
--- 164,177 ----
    send_to_char(ch, "You delay '%s' for %d seconds.\r\n", arg, atoi(time));
    start_event(ch, atoi(time) SECONDS, event_delayed_cmd, NULL, NULL, arg);
  }
+ 
+ 
+ //
+ // An entrypoint into the character's notepad
+ //
+ COMMAND(cmd_write) {
+   if(!charGetSocket(ch))
+     send_to_char(ch, "You cannot use notepad if you have no socket.\r\n");
+   else
+     start_notepad(charGetSocket(ch), "", MAX_BUFFER, EDITOR_MODE_NORMAL);
+ }
diff -crN nakedmudv1.4/src/commands.h nakedmudv1.5/src/commands.h
*** nakedmudv1.4/src/commands.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/commands.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 10,19 ****
--- 10,22 ----
  
  /* admin.c */
  COMMAND(cmd_goto);
+ COMMAND(cmd_transfer);
  COMMAND(cmd_copyover);
  COMMAND(cmd_shutdown);
  COMMAND(cmd_linkdead);
  COMMAND(cmd_wizhelp);
+ COMMAND(cmd_invis);
+ COMMAND(cmd_visible);
  
  
  /* builder.c */
***************
*** 63,68 ****
--- 66,73 ----
  COMMAND(cmd_tog_prf);
  COMMAND(cmd_more);
  COMMAND(cmd_back);
+ COMMAND(cmd_stop);
+ COMMAND(cmd_write);
  
  
  /* inform.c */
***************
*** 70,76 ****
  COMMAND(cmd_look);
  COMMAND(cmd_inventory);
  COMMAND(cmd_equipment);
- COMMAND(cmd_help);
  
  
  /* olc.c */
--- 75,80 ----
diff -crN nakedmudv1.4/src/.depend nakedmudv1.5/src/.depend
*** nakedmudv1.4/src/.depend	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/.depend	2010-11-01 15:54:17.000000000 -0500
***************
*** 1,171 ****
  gameloop.o: gameloop.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h socket.h world.h character.h object.h utils.h text_editor.h \
!   save.h handler.h inform.h log.h races.h action.h event.h auxiliary.h \
!   storage.h time/mudtime.h scripts/script.h olc/olc.h alias/alias.h \
!   char_vars/char_vars.h socials/socials.h
  mud.o: mud.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h utils.h text_editor.h storage.h
  utils.o: utils.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h character.h object.h world.h zone.h room.h exit.h socket.h \
!   utils.h text_editor.h save.h handler.h inform.h dialog.h event.h \
!   action.h help.h scripts/script.h
  interpret.o: interpret.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h utils.h text_editor.h character.h socket.h room.h \
!   movement.h commands.h action.h scripts/script.h alias/alias.h
  handler.o: handler.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h handler.h room.h exit.h extra_descs.h character.h object.h \
!   utils.h text_editor.h body.h items.h inform.h scripts/script.h
  inform.o: inform.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h character.h object.h world.h room.h exit.h extra_descs.h \
!   utils.h text_editor.h body.h races.h items.h handler.h socket.h \
!   inform.h log.h time/mudtime.h
  movement.o: movement.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h character.h world.h room.h exit.h movement.h handler.h \
!   inform.h builder.h utils.h text_editor.h items.h object.h \
    scripts/script.h
  action.o: action.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h utils.h text_editor.h character.h action.h
  mccp.o: mccp.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h socket.h utils.h text_editor.h
  save.o: save.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h character.h world.h utils.h text_editor.h handler.h body.h \
!   object.h room.h storage.h
  socket.o: socket.c wrapsock.h mud.h property_table.h list.h hashmap.h \
!   hashtable.h character.h utils.h text_editor.h socket.h olc/olc.h
  io.o: io.c mud.h wrapsock.h property_table.h list.h hashmap.h hashtable.h \
!   utils.h text_editor.h
  strings.o: strings.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h utils.h text_editor.h
  event.o: event.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h utils.h text_editor.h character.h event.h
  cmd_comm.o: cmd_comm.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h utils.h text_editor.h handler.h inform.h character.h \
    world.h dialog.h scripts/script.h
  cmd_manip.o: cmd_manip.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h utils.h text_editor.h handler.h inform.h \
    character.h items.h exit.h world.h room.h extra_descs.h object.h
  cmd_misc.o: cmd_misc.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h character.h socket.h utils.h text_editor.h save.h event.h \
!   handler.h
! text_editor.o: text_editor.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h socket.h text_editor.h utils.h scripts/script.h \
!   olc/olc.h
! builder.o: builder.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h world.h zone.h room.h exit.h movement.h builder.h \
    character.h object.h handler.h inform.h utils.h text_editor.h races.h \
    items.h dialog.h scripts/script.h scripts/script_set.h
! admin.o: admin.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h world.h inform.h character.h handler.h utils.h \
!   text_editor.h log.h socket.h save.h event.h action.h storage.h
! help.o: help.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h character.h help.h
! items.o: items.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h object.h items.h
  races.o: races.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h races.h body.h utils.h text_editor.h
  log.o: log.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h utils.h text_editor.h character.h storage.h log.h
  auxiliary.o: auxiliary.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h utils.h text_editor.h storage.h auxiliary.h
  world.o: world.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h zone.h room.h character.h object.h dialog.h utils.h \
    text_editor.h storage.h world.h scripts/script.h
  character.o: character.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h utils.h text_editor.h body.h races.h handler.h \
!   auxiliary.h storage.h room.h character.h
  room.o: room.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h exit.h extra_descs.h utils.h text_editor.h handler.h \
    character.h auxiliary.h storage.h room_reset.h room.h scripts/script.h
  exit.o: exit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h utils.h text_editor.h storage.h exit.h
  extra_descs.o: extra_descs.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h utils.h text_editor.h storage.h extra_descs.h
  object.o: object.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h extra_descs.h utils.h text_editor.h items.h body.h \
    handler.h storage.h auxiliary.h object.h
  body.o: body.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h body.h utils.h text_editor.h
  zone.o: zone.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h storage.h object.h character.h room.h zone.h utils.h \
!   text_editor.h dialog.h scripts/script.h
  dialog.o: dialog.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h utils.h text_editor.h dialog.h storage.h
  room_reset.o: room_reset.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h utils.h text_editor.h storage.h room.h world.h \
!   character.h body.h object.h exit.h handler.h items.h room_reset.h
  list.o: list.c list.h
  property_table.o: property_table.c mud.h wrapsock.h property_table.h \
!   list.h hashmap.h hashtable.h utils.h text_editor.h
  hashtable.o: hashtable.c list.h hashtable.h
  hashmap.o: hashmap.c list.h hashmap.h
  storage.o: storage.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h utils.h text_editor.h storage.h
  time.o: time/time.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h utils.h text_editor.h inform.h character.h room.h event.h \
!   storage.h auxiliary.h time/mudtime.h
  alias.o: alias/alias.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h utils.h text_editor.h auxiliary.h storage.h character.h \
!   alias/alias.h
  char_vars.o: char_vars/char_vars.c mud.h wrapsock.h property_table.h \
!   list.h hashmap.h hashtable.h utils.h text_editor.h character.h \
    storage.h auxiliary.h char_vars/char_vars.h
  socials.o: socials/socials.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h utils.h text_editor.h storage.h handler.h \
    inform.h character.h socials/socials.h
  dedit.o: olc/dedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h socket.h utils.h text_editor.h dialog.h olc/olc.h
  edesc_edit.o: olc/edesc_edit.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h socket.h utils.h text_editor.h extra_descs.h \
!   olc/olc.h
  exedit.o: olc/exedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h exit.h socket.h utils.h text_editor.h olc/olc.h
  medit.o: olc/medit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h world.h character.h socket.h utils.h text_editor.h races.h \
!   dialog.h olc/olc.h scripts/script_set.h scripts/script.h
  oedit.o: olc/oedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h world.h object.h extra_descs.h socket.h utils.h \
    text_editor.h body.h items.h olc/olc.h scripts/script_set.h \
    scripts/script.h
  redit.o: olc/redit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h world.h room.h exit.h room_reset.h extra_descs.h socket.h \
!   utils.h text_editor.h olc/olc.h scripts/script_set.h scripts/script.h \
!   time/mudtime.h
  zedit.o: olc/zedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h world.h zone.h socket.h utils.h text_editor.h olc/olc.h
  ssedit.o: olc/ssedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h socket.h world.h utils.h text_editor.h olc/olc.h \
    scripts/script.h scripts/script_set.h
  scedit.o: olc/scedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h socket.h utils.h text_editor.h olc/olc.h scripts/script.h
  resedit.o: olc/resedit.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h socket.h utils.h text_editor.h world.h object.h \
!   character.h room_reset.h olc/olc.h
  socedit.o: olc/socedit.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h socket.h utils.h text_editor.h character.h \
    socials/socials.h olc/olc.h
  olc.o: olc/olc.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h socket.h object.h character.h world.h zone.h room.h \
    room_reset.h exit.h extra_descs.h dialog.h olc/olc.h scripts/script.h \
    scripts/script_set.h socials/socials.h
  script_set.o: scripts/script_set.c mud.h wrapsock.h property_table.h \
!   list.h hashmap.h hashtable.h utils.h text_editor.h world.h \
    scripts/script_set.h scripts/script.h
  script.o: scripts/script.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h utils.h text_editor.h socket.h character.h room.h \
!   object.h storage.h auxiliary.h scripts/script.h scripts/script_set.h \
!   scripts/pychar.h scripts/pyroom.h scripts/pyobj.h scripts/pymud.h
  pychar.o: scripts/pychar.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h world.h room.h character.h object.h items.h \
    races.h handler.h utils.h text_editor.h scripts/script.h \
    scripts/pychar.h scripts/pyroom.h scripts/pyobj.h char_vars/char_vars.h
  pyobj.o: scripts/pyobj.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h world.h room.h character.h object.h races.h \
    handler.h utils.h text_editor.h scripts/script.h scripts/pychar.h \
    scripts/pyroom.h scripts/pyobj.h
  pymud.o: scripts/pymud.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h scripts/script.h scripts/pyroom.h \
    scripts/pychar.h scripts/pyobj.h
  pyroom.o: scripts/pyroom.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h world.h room.h exit.h character.h races.h \
    handler.h utils.h text_editor.h scripts/script.h scripts/pyroom.h \
    scripts/pychar.h scripts/pyobj.h
--- 1,179 ----
  gameloop.o: gameloop.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h socket.h world.h character.h object.h utils.h \
!   text_editor.h save.h handler.h inform.h log.h action.h event.h \
!   auxiliary.h storage.h races.h body.h time/mudtime.h scripts/script.h \
!   olc/olc.h alias/alias.h char_vars/char_vars.h socials/socials.h \
!   help/help.h
  mud.o: mud.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h utils.h text_editor.h storage.h
  utils.o: utils.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h character.h object.h world.h zone.h room.h exit.h \
!   socket.h utils.h text_editor.h save.h handler.h inform.h dialog.h \
!   event.h action.h scripts/script.h
  interpret.o: interpret.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h utils.h text_editor.h character.h socket.h \
!   room.h movement.h commands.h action.h scripts/script.h alias/alias.h
  handler.o: handler.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h handler.h room.h exit.h extra_descs.h character.h \
!   object.h utils.h text_editor.h body.h items.h inform.h scripts/script.h
  inform.o: inform.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h character.h object.h world.h room.h exit.h \
!   extra_descs.h utils.h text_editor.h body.h races.h items.h handler.h \
!   socket.h inform.h log.h time/mudtime.h
  movement.o: movement.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h character.h world.h zone.h room.h exit.h movement.h \
!   handler.h inform.h utils.h text_editor.h items.h object.h \
    scripts/script.h
  action.o: action.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h utils.h text_editor.h character.h action.h
  mccp.o: mccp.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h socket.h utils.h text_editor.h
  save.o: save.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h character.h world.h utils.h text_editor.h handler.h \
!   body.h object.h room.h storage.h
  socket.o: socket.c wrapsock.h mud.h property_table.h list.h hashmap.h \
!   hashtable.h set.h character.h utils.h text_editor.h socket.h olc/olc.h
  io.o: io.c mud.h wrapsock.h property_table.h list.h hashmap.h hashtable.h \
!   set.h utils.h text_editor.h
  strings.o: strings.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h utils.h text_editor.h
  event.o: event.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h utils.h text_editor.h character.h event.h
  cmd_comm.o: cmd_comm.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h utils.h text_editor.h handler.h inform.h character.h \
    world.h dialog.h scripts/script.h
  cmd_manip.o: cmd_manip.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h utils.h text_editor.h handler.h inform.h \
    character.h items.h exit.h world.h room.h extra_descs.h object.h
  cmd_misc.o: cmd_misc.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h character.h socket.h utils.h text_editor.h save.h \
!   event.h action.h handler.h
! cmd_admin.o: cmd_admin.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h world.h inform.h character.h handler.h \
!   utils.h text_editor.h log.h socket.h save.h event.h action.h storage.h
! cmd_builder.o: cmd_builder.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h world.h zone.h room.h exit.h movement.h \
    character.h object.h handler.h inform.h utils.h text_editor.h races.h \
    items.h dialog.h scripts/script.h scripts/script_set.h
! text_editor.o: text_editor.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h socket.h text_editor.h utils.h \
!   scripts/script.h olc/olc.h
  races.o: races.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h body.h utils.h text_editor.h races.h
! items.o: items.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h object.h items.h
  log.o: log.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h utils.h text_editor.h character.h storage.h log.h
  auxiliary.o: auxiliary.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h utils.h text_editor.h storage.h auxiliary.h
  world.o: world.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h zone.h room.h character.h object.h dialog.h utils.h \
    text_editor.h storage.h world.h scripts/script.h
  character.o: character.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h utils.h text_editor.h body.h races.h \
!   handler.h auxiliary.h storage.h room.h character.h
  room.o: room.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h exit.h extra_descs.h utils.h text_editor.h handler.h \
    character.h auxiliary.h storage.h room_reset.h room.h scripts/script.h
  exit.o: exit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h utils.h text_editor.h storage.h exit.h
  extra_descs.o: extra_descs.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h utils.h text_editor.h storage.h \
!   extra_descs.h
  object.o: object.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h extra_descs.h utils.h text_editor.h items.h body.h \
    handler.h storage.h auxiliary.h object.h
  body.o: body.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h body.h utils.h text_editor.h
  zone.o: zone.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h storage.h object.h character.h room.h utils.h \
!   text_editor.h auxiliary.h dialog.h zone.h scripts/script.h
  dialog.o: dialog.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h utils.h text_editor.h dialog.h storage.h
  room_reset.o: room_reset.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h utils.h text_editor.h storage.h room.h \
!   world.h character.h body.h object.h exit.h handler.h items.h \
!   room_reset.h
  list.o: list.c list.h
  property_table.o: property_table.c mud.h wrapsock.h property_table.h \
!   list.h hashmap.h hashtable.h set.h utils.h text_editor.h
  hashtable.o: hashtable.c list.h hashtable.h
  hashmap.o: hashmap.c list.h hashmap.h
  storage.o: storage.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h utils.h text_editor.h storage.h
! set.o: set.c list.h set.h
  time.o: time/time.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h utils.h text_editor.h inform.h character.h room.h \
!   event.h storage.h auxiliary.h time/mudtime.h
  alias.o: alias/alias.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h utils.h text_editor.h auxiliary.h storage.h \
!   character.h alias/alias.h
  char_vars.o: char_vars/char_vars.c mud.h wrapsock.h property_table.h \
!   list.h hashmap.h hashtable.h set.h utils.h text_editor.h character.h \
    storage.h auxiliary.h char_vars/char_vars.h
  socials.o: socials/socials.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h utils.h text_editor.h storage.h handler.h \
    inform.h character.h socials/socials.h
  dedit.o: olc/dedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h socket.h utils.h text_editor.h dialog.h olc/olc.h
  edesc_edit.o: olc/edesc_edit.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h socket.h utils.h text_editor.h \
!   extra_descs.h olc/olc.h
  exedit.o: olc/exedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h exit.h socket.h utils.h text_editor.h olc/olc.h
  medit.o: olc/medit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h world.h character.h socket.h utils.h text_editor.h \
!   races.h dialog.h olc/olc.h scripts/script_set.h scripts/script.h
  oedit.o: olc/oedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h world.h object.h extra_descs.h socket.h utils.h \
    text_editor.h body.h items.h olc/olc.h scripts/script_set.h \
    scripts/script.h
  redit.o: olc/redit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h world.h room.h exit.h room_reset.h extra_descs.h \
!   socket.h utils.h text_editor.h olc/olc.h scripts/script_set.h \
!   scripts/script.h time/mudtime.h
  zedit.o: olc/zedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h world.h zone.h socket.h utils.h text_editor.h \
!   olc/olc.h
  ssedit.o: olc/ssedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h socket.h world.h utils.h text_editor.h olc/olc.h \
    scripts/script.h scripts/script_set.h
  scedit.o: olc/scedit.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h socket.h utils.h text_editor.h olc/olc.h \
!   scripts/script.h
  resedit.o: olc/resedit.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h socket.h utils.h text_editor.h world.h \
!   object.h character.h room_reset.h olc/olc.h
  socedit.o: olc/socedit.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h socket.h utils.h text_editor.h character.h \
    socials/socials.h olc/olc.h
  olc.o: olc/olc.c mud.h wrapsock.h property_table.h list.h hashmap.h \
!   hashtable.h set.h socket.h object.h character.h world.h zone.h room.h \
    room_reset.h exit.h extra_descs.h dialog.h olc/olc.h scripts/script.h \
    scripts/script_set.h socials/socials.h
  script_set.o: scripts/script_set.c mud.h wrapsock.h property_table.h \
!   list.h hashmap.h hashtable.h set.h utils.h text_editor.h world.h \
    scripts/script_set.h scripts/script.h
  script.o: scripts/script.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h utils.h text_editor.h socket.h character.h \
!   room.h object.h storage.h auxiliary.h scripts/script.h \
!   scripts/script_set.h scripts/pychar.h scripts/pyroom.h scripts/pyobj.h \
!   scripts/pymud.h
  pychar.o: scripts/pychar.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h world.h room.h character.h object.h items.h \
    races.h handler.h utils.h text_editor.h scripts/script.h \
    scripts/pychar.h scripts/pyroom.h scripts/pyobj.h char_vars/char_vars.h
  pyobj.o: scripts/pyobj.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h world.h room.h character.h object.h races.h \
    handler.h utils.h text_editor.h scripts/script.h scripts/pychar.h \
    scripts/pyroom.h scripts/pyobj.h
  pymud.o: scripts/pymud.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h scripts/script.h scripts/pyroom.h \
    scripts/pychar.h scripts/pyobj.h
  pyroom.o: scripts/pyroom.c mud.h wrapsock.h property_table.h list.h \
!   hashmap.h hashtable.h set.h world.h room.h exit.h character.h races.h \
    handler.h utils.h text_editor.h scripts/script.h scripts/pyroom.h \
    scripts/pychar.h scripts/pyobj.h
+ help.o: help/help.c mud.h wrapsock.h property_table.h list.h hashmap.h \
+   hashtable.h set.h utils.h text_editor.h storage.h character.h socket.h \
+   help/help.h
diff -crN nakedmudv1.4/src/dialog.c nakedmudv1.5/src/dialog.c
*** nakedmudv1.4/src/dialog.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/dialog.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 55,62 ****
  
  STORAGE_SET *responseStore(RESPONSE_DATA *data) {
    STORAGE_SET *set = new_storage_set();
!   store_string(set, "keywords", data->keywords, NULL);
!   store_string(set, "message",  data->message,  NULL);
    return set;
  }
  
--- 55,62 ----
  
  STORAGE_SET *responseStore(RESPONSE_DATA *data) {
    STORAGE_SET *set = new_storage_set();
!   store_string(set, "keywords", data->keywords);
!   store_string(set, "message",  data->message);
    return set;
  }
  
***************
*** 128,138 ****
  
  STORAGE_SET *dialogStore(DIALOG_DATA *dialog) {
    STORAGE_SET *set = new_storage_set();
!   store_int   (set, "vnum",     dialog->vnum, NULL);
!   store_string(set, "name",     dialog->name, NULL);
!   store_string(set, "greet",    dialog->greet, NULL);
!   store_list(set, "responses", gen_store_list(dialog->responses, responseStore),
! 	     NULL);
    return set;
  }
  
--- 128,137 ----
  
  STORAGE_SET *dialogStore(DIALOG_DATA *dialog) {
    STORAGE_SET *set = new_storage_set();
!   store_int   (set, "vnum",     dialog->vnum);
!   store_string(set, "name",     dialog->name);
!   store_string(set, "greet",    dialog->greet);
!   store_list(set, "responses", gen_store_list(dialog->responses,responseStore));
    return set;
  }
  
diff -crN nakedmudv1.4/src/event.c nakedmudv1.5/src/event.c
*** nakedmudv1.4/src/event.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/event.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 24,35 ****
  LIST    *events = NULL;
  
  struct event_data {
!   void *owner; // who is the lucky person who owns this event?
    void (*  on_complete)(void *owner, void *data, char *arg);
    bool (*  check_involvement)(void *thing, void *data);
!   int   delay; // how much longer until the event is complete?
!   void *data;  // data for the event
!   char *arg;   // an argument supplied to an event
  };
  
  
--- 24,37 ----
  LIST    *events = NULL;
  
  struct event_data {
!   void *owner;   // who is the lucky person who owns this event?
    void (*  on_complete)(void *owner, void *data, char *arg);
    bool (*  check_involvement)(void *thing, void *data);
!   int   delay;   // how much longer until the event is complete?
!   int   tot_time;// what is the total delay before the event fires?
!   void *data;    // data for the event
!   char *arg;     // an argument supplied to an event
!   bool  requeue; // is the event requeue'd after it goes off?
  };
  
  
***************
*** 75,88 ****
  		     int delay, 	
  		     void (*  on_complete)(void *owner, void *data, char *arg),
  		     bool (* check_involvement)(void *thing, void *data),
! 		     void *data, char *arg) {
    EVENT_DATA *event        = malloc(sizeof(EVENT_DATA));
    event->owner             = owner;
    event->on_complete       = on_complete;
    event->check_involvement = check_involvement;
    event->delay             = delay;
    event->data              = data;
    event->arg               = strdup(arg ? arg :"");
    return event;
  }
  
--- 77,92 ----
  		     int delay, 	
  		     void (*  on_complete)(void *owner, void *data, char *arg),
  		     bool (* check_involvement)(void *thing, void *data),
! 		     void *data, const char *arg, bool requeue) {
    EVENT_DATA *event        = malloc(sizeof(EVENT_DATA));
    event->owner             = owner;
    event->on_complete       = on_complete;
    event->check_involvement = check_involvement;
    event->delay             = delay;
+   event->tot_time          = delay;
    event->data              = data;
    event->arg               = strdup(arg ? arg :"");
+   event->requeue           = requeue;
    return event;
  }
  
***************
*** 137,154 ****
  		 void *on_complete,
  		 void *check_involvement,
  		 void *data,
! 		 char *arg) {
    listPut(events, newEvent(owner, delay, on_complete, check_involvement,
! 			   data, arg));
  }
  
  void pulse_events(int time) {
    LIST_ITERATOR *ev_i = newListIterator(events);
    EVENT_DATA   *event = NULL;
  
!   // we can't use ITERATE_LIST here, because there are times
!   // where we will remove our current element  from the list, 
!   // making it kinda hard to go onto the next one afterwards ;)
    ITERATE_LIST(event, ev_i) {
      // decrement the delay
      event->delay -= time;
--- 141,166 ----
  		 void *on_complete,
  		 void *check_involvement,
  		 void *data,
! 		 const char *arg) {
    listPut(events, newEvent(owner, delay, on_complete, check_involvement,
! 			   data, arg, FALSE));
! }
! 
! void start_update(void *owner, 
! 		  int   delay,
! 		  void *on_complete,
! 		  void *check_involvement,
! 		  void *data,
! 		  const char *arg) {
!   listPut(events, newEvent(owner, delay, on_complete, check_involvement,
! 			   data, arg, TRUE));
  }
  
  void pulse_events(int time) {
    LIST_ITERATOR *ev_i = newListIterator(events);
    EVENT_DATA   *event = NULL;
  
!   // go over all of the events
    ITERATE_LIST(event, ev_i) {
      // decrement the delay
      event->delay -= time;
***************
*** 156,162 ****
      if(event->delay <= 0) {
        listRemove(events, event);
        run_event(event);
!       deleteEvent(event);
      }
    }
    deleteListIterator(ev_i);
--- 168,182 ----
      if(event->delay <= 0) {
        listRemove(events, event);
        run_event(event);
!       // if we need to requeue, reset the timer 
!       // and put us back in the list
!       if(event->requeue) {
! 	event->delay = event->tot_time;
! 	listPut(events, event);
!       }
!       // otherwise, just delete the event
!       else
! 	deleteEvent(event);
      }
    }
    deleteListIterator(ev_i);
diff -crN nakedmudv1.4/src/event.h nakedmudv1.5/src/event.h
*** nakedmudv1.4/src/event.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/event.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 57,62 ****
   		 void *on_complete,
  		 void *check_involvement,
  		 void *data,
! 		 char *arg);
  
  #endif // __EVENT_H
--- 57,75 ----
   		 void *on_complete,
  		 void *check_involvement,
  		 void *data,
! 		 const char *arg);
! 
! 
! //
! // same deal as start_event, but will automatically re-queue the event
! // after it has fired. Useful for events that are currently running (e.g.
! // mudtime updating, ticks, zone reset timers).
! //
! void start_update(void *owner,
! 		  int   delay,
! 		  void *on_complete,
! 		  void *check_involvement,
! 		  void *data,
! 		  const char *arg);
  
  #endif // __EVENT_H
diff -crN nakedmudv1.4/src/exit.c nakedmudv1.5/src/exit.c
*** nakedmudv1.4/src/exit.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/exit.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 103,118 ****
  
  STORAGE_SET *exitStore(EXIT_DATA *exit) {
    STORAGE_SET *set = new_storage_set();
!   store_string(set, "name",       exit->name,       NULL);
!   store_string(set, "keywords",   exit->keywords,   NULL);
!   store_string(set, "desc",       exit->description,NULL);
!   store_string(set, "enter",      exit->spec_enter, NULL);
!   store_string(set, "leave",      exit->spec_leave, NULL);
!   store_int   (set, "to",         exit->to,         NULL);
!   store_int   (set, "key",        exit->key,        NULL);
!   store_int   (set, "hide_level", exit->hide_lev,   NULL);
!   store_int   (set, "pick_level", exit->pick_lev,   NULL);
!   store_int   (set, "closable",   exit->closable,   NULL);
    return set;
  }
  
--- 103,118 ----
  
  STORAGE_SET *exitStore(EXIT_DATA *exit) {
    STORAGE_SET *set = new_storage_set();
!   store_string(set, "name",       exit->name);
!   store_string(set, "keywords",   exit->keywords);
!   store_string(set, "desc",       exit->description);
!   store_string(set, "enter",      exit->spec_enter);
!   store_string(set, "leave",      exit->spec_leave);
!   store_int   (set, "to",         exit->to);
!   store_int   (set, "key",        exit->key);
!   store_int   (set, "hide_level", exit->hide_lev);
!   store_int   (set, "pick_level", exit->pick_lev);
!   store_int   (set, "closable",   exit->closable);
    return set;
  }
  
diff -crN nakedmudv1.4/src/extra_descs.c nakedmudv1.5/src/extra_descs.c
*** nakedmudv1.4/src/extra_descs.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/extra_descs.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 43,50 ****
  
  STORAGE_SET *edescStore(EDESC_DATA *data) {
    STORAGE_SET *set = new_storage_set();
!   store_string(set, "keywords", data->keywords, NULL);
!   store_string(set, "desc",     data->desc,     NULL);
    return set;
  }
  
--- 43,50 ----
  
  STORAGE_SET *edescStore(EDESC_DATA *data) {
    STORAGE_SET *set = new_storage_set();
!   store_string(set, "keywords", data->keywords);
!   store_string(set, "desc",     data->desc);
    return set;
  }
  
***************
*** 64,70 ****
  
  STORAGE_SET *edescSetStore(EDESC_SET *edescs) {
    STORAGE_SET *set             = new_storage_set();
!   store_list(set, "list", gen_store_list(edescs->edescs, edescStore), NULL);
    return set;
  }
  
--- 64,70 ----
  
  STORAGE_SET *edescSetStore(EDESC_SET *edescs) {
    STORAGE_SET *set             = new_storage_set();
!   store_list(set, "list", gen_store_list(edescs->edescs, edescStore));
    return set;
  }
  
diff -crN nakedmudv1.4/src/gameloop.c nakedmudv1.5/src/gameloop.c
*** nakedmudv1.4/src/gameloop.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/gameloop.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 17,27 ****
  #include "inform.h"
  #include "text_editor.h"
  #include "log.h"
- #include "races.h"
  #include "action.h"
  #include "event.h"
  #include "auxiliary.h"
  #include "storage.h"
  
  
  // optional modules
--- 17,28 ----
  #include "inform.h"
  #include "text_editor.h"
  #include "log.h"
  #include "action.h"
  #include "event.h"
  #include "auxiliary.h"
  #include "storage.h"
+ #include "races.h"
+ #include "body.h"
  
  
  // optional modules
***************
*** 48,54 ****
  #endif
  
  
- 
  /* mccp support */
  const unsigned char do_echo         [] = { IAC, WONT, TELOPT_ECHO,      '\0' };
  const unsigned char dont_echo       [] = { IAC, WILL, TELOPT_ECHO,      '\0' };
--- 49,54 ----
***************
*** 146,151 ****
--- 146,155 ----
    log_string("Preparing auxiliary data for usage.");
    init_auxiliaries();
  
+   /* prepare races and bodies for use */
+   log_string("Initializing races and default bodies.");
+   init_races();
+ 
    /* initialize our command table */
    log_string("Initializing command table.");
    init_commands();
***************
*** 179,185 ****
    init_time();
  #endif
  
-   /* initialize faculties */
  #ifdef MODULE_CHAR_VARS
    log_string("Initializing character variables.");
    init_char_vars();
--- 183,188 ----
***************
*** 237,249 ****
  }
  
  
- int num_updates = 0;
  //
  // let all of our actions and events know that time has gone by.
  // Also, give a chance of doing some resetting in the game.
  //
  void update_handler()
  {
    // increment the number of updates we've done
    num_updates++;
  
--- 240,252 ----
  }
  
  
  //
  // let all of our actions and events know that time has gone by.
  // Also, give a chance of doing some resetting in the game.
  //
  void update_handler()
  {
+   static int num_updates = 0;
    // increment the number of updates we've done
    num_updates++;
  
***************
*** 255,261 ****
    // we don't want to be on the same schedule as
    // everything else, that updates every PULSES_PER_SECOND. 
    // We want to be on a schedule that updates every minute or so.
!   if(num_updates % PULSES_PER_SECOND * 60 == 0)
      worldPulse(gameworld);
  }
  
--- 258,264 ----
    // we don't want to be on the same schedule as
    // everything else, that updates every PULSES_PER_SECOND. 
    // We want to be on a schedule that updates every minute or so.
!   if((num_updates % (1 MINUTE)) == 0)
      worldPulse(gameworld);
  }
  
***************
*** 343,349 ****
  	case STATE_VERIFY_PASSWORD:
  	case STATE_ASK_PASSWORD:
  	case STATE_ASK_SEX:
! 	case STATE_ASK_RACE:
  	  handle_new_connections(dsock, dsock->next_command);
  	  break;
  	case STATE_PLAYING:
--- 346,352 ----
  	case STATE_VERIFY_PASSWORD:
  	case STATE_ASK_PASSWORD:
  	case STATE_ASK_SEX:
!    	case STATE_ASK_RACE:
  	  handle_new_connections(dsock, dsock->next_command);
  	  break;
  	case STATE_PLAYING:
***************
*** 547,561 ****
  }
  
  void list_races(SOCKET_DATA *sock) {
-   int i;
    send_to_socket(sock, "Available races are:\r\n");
!   for(i = 0; i < NUM_RACES; i++) {
!     if(!raceIsForPC(i))
!       continue;
!     send_to_socket(sock, "%s%s", 
! 		   (i == 0 ? "" : ", "),
! 		   raceGetName(i));
!   }
    send_to_socket(sock, "\r\n\r\nPlease enter your choice: ");
  }
  
--- 550,557 ----
  }
  
  void list_races(SOCKET_DATA *sock) {
    send_to_socket(sock, "Available races are:\r\n");
!   send_to_socket(sock, "%s", raceGetList(TRUE));
    send_to_socket(sock, "\r\n\r\nPlease enter your choice: ");
  }
  
***************
*** 563,576 ****
  // Ask for the character's race. Called each time a character is created
  //
  void state_ask_race(SOCKET_DATA *dsock, char *arg) {
!   int racenum = raceGetNum(arg);
! 
!   if(racenum == RACE_NONE || racenum >= NUM_RACES || !raceIsForPC(racenum)) {
      send_to_socket(dsock, "Invalid race! Please try again: ");
      return;
!   }
    else {
!     charSetRace(dsock->player, racenum);
      charResetBody(dsock->player);
    }
  
--- 559,570 ----
  // Ask for the character's race. Called each time a character is created
  //
  void state_ask_race(SOCKET_DATA *dsock, char *arg) {
!   if(!arg || !*arg || !raceIsForPC(arg)) {
      send_to_socket(dsock, "Invalid race! Please try again: ");
      return;
!   }    
    else {
!     charSetRace(dsock->player, arg);
      charResetBody(dsock->player);
    }
  
***************
*** 595,604 ****
    char_to_room(dsock->player, worldGetRoom(gameworld, START_ROOM));
    look_at_room(dsock->player, charGetRoom(dsock->player));
  
  #ifdef MODULE_SCRIPTS
    // check enterance scripts
!   try_enterance_script(dsock->player, charGetRoom(dsock->player),
! 		       NULL, NULL);
  #endif
  }
  
--- 589,600 ----
    char_to_room(dsock->player, worldGetRoom(gameworld, START_ROOM));
    look_at_room(dsock->player, charGetRoom(dsock->player));
  
+   /* and save him */
+   save_player(dsock->player);
+ 
  #ifdef MODULE_SCRIPTS
    // check enterance scripts
!   try_enterance_script(dsock->player, charGetRoom(dsock->player), NULL);
  #endif
  }
  
***************
*** 687,694 ****
  
  #ifdef MODULE_SCRIPTS
  	// check enterance scripts
! 	try_enterance_script(p_new, charGetRoom(p_new),
! 			     NULL, NULL);
  #endif
        }
        else {
--- 683,689 ----
  
  #ifdef MODULE_SCRIPTS
  	// check enterance scripts
! 	try_enterance_script(p_new, charGetRoom(p_new), NULL);
  #endif
        }
        else {
diff -crN nakedmudv1.4/src/.gdb_history nakedmudv1.5/src/.gdb_history
*** nakedmudv1.4/src/.gdb_history	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/.gdb_history	2010-11-01 15:54:17.000000000 -0500
***************
*** 1,47 ****
- down
- up
- up
- up
- print room->auxiliary_data
- down
- print line
- print data
- info local
- bt
- quit
- run
- quit
- run
- bt
- print line
- quit
- run
- print line
- quit
- run
- bt
- quit
- run
- bt
- down
- up
- up
- up
- up
- print world
- bt
- quit
- run
- quit
- run
- bt
- quit
- run
- quit
- run
- quit
- run
- quit
  run
  bt
  quit
--- 1,3 ----
***************
*** 254,256 ****
--- 210,256 ----
  quit
  run
  quit
+ run
+ bt
+ quit
+ run
+ quit
+ run
+ bt
+ quit
+ run
+ bt
+ quit
+ run 4000
+ bt
+ quit
+ run
+ bt
+ up
+ up
+ print data
+ print data->curr_path
+ print listSize(data->curr_path)
+ quit
+ run
+ quit
+ run
+ bt
+ quit
+ run
+ print i
+ print j
+ print map->rooms[i]
+ print map->rooms[j]
+ print map->rooms
+ quit
+ run
+ quit
+ run 4000
+ bt
+ quit
+ run
+ quit
+ run
+ bt
+ quit
diff -crN nakedmudv1.4/src/handler.c nakedmudv1.5/src/handler.c
*** nakedmudv1.4/src/handler.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/handler.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 234,245 ****
    // object give
    try_scripts(SCRIPT_TYPE_GIVE,
  	      obj, SCRIPTOR_OBJ,
! 	      ch, obj, charGetRoom(ch), NULL, NULL, NULL, 0);
    
    // char receive
    try_scripts(SCRIPT_TYPE_GIVE,
  	      recv, SCRIPTOR_CHAR,
! 	      ch, obj, charGetRoom(ch), NULL, NULL, NULL, 0);
  #endif
  }
  
--- 234,245 ----
    // object give
    try_scripts(SCRIPT_TYPE_GIVE,
  	      obj, SCRIPTOR_OBJ,
! 	      ch, obj, charGetRoom(ch), NULL, NULL, 0);
    
    // char receive
    try_scripts(SCRIPT_TYPE_GIVE,
  	      recv, SCRIPTOR_CHAR,
! 	      ch, obj, charGetRoom(ch), NULL, NULL, 0);
  #endif
  }
  
***************
*** 253,262 ****
    // check for triggers
    try_scripts(SCRIPT_TYPE_DROP,
  	      charGetRoom(ch), SCRIPTOR_ROOM,
! 	      ch, obj, charGetRoom(ch), NULL, NULL, NULL, 0);
    try_scripts(SCRIPT_TYPE_DROP,
  	      obj, SCRIPTOR_OBJ,
! 	      ch, obj, charGetRoom(ch), NULL, NULL, NULL, 0);
  #endif
  }
  
--- 253,262 ----
    // check for triggers
    try_scripts(SCRIPT_TYPE_DROP,
  	      charGetRoom(ch), SCRIPTOR_ROOM,
! 	      ch, obj, charGetRoom(ch), NULL, NULL, 0);
    try_scripts(SCRIPT_TYPE_DROP,
  	      obj, SCRIPTOR_OBJ,
! 	      ch, obj, charGetRoom(ch), NULL, NULL, 0);
  #endif
  }
  
***************
*** 828,834 ****
  
      // now special exits
      int num_exits = 0;
!     char **ex_names = roomGetExitNames(charGetRoom(looker), &num_exits);
      for(ex_i = 0; ex_i < num_exits; ex_i++) {
        exit = roomGetExitSpecial(charGetRoom(looker), ex_names[ex_i]);
        if(!exit)
--- 828,834 ----
  
      // now special exits
      int num_exits = 0;
!     const char **ex_names = roomGetExitNames(charGetRoom(looker), &num_exits);
      for(ex_i = 0; ex_i < num_exits; ex_i++) {
        exit = roomGetExitSpecial(charGetRoom(looker), ex_names[ex_i]);
        if(!exit)
***************
*** 854,861 ****
        exit = NULL;
  
      // clean up our mess
-     for(ex_i = 0; ex_i < num_exits; ex_i++)
-       free(ex_names[ex_i]);
      free(ex_names);
  
      // we got one
--- 854,859 ----
diff -crN nakedmudv1.4/src/help/help.c nakedmudv1.5/src/help/help.c
*** nakedmudv1.4/src/help/help.c	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/src/help/help.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,539 ----
+ //*****************************************************************************
+ //
+ // help.c
+ //
+ // This helpfile system has been set up to be amenable to allowing players to
+ // edit helpfiles without having to worry about malicious users. 
+ //
+ //*****************************************************************************
+ 
+ #include "../mud.h"
+ #include "../utils.h"
+ #include "../storage.h"
+ #include "../character.h"
+ #include "../socket.h"
+ 
+ #include "help.h"
+ 
+ 
+ 
+ //*****************************************************************************
+ //
+ // local variables, data structures, and functions
+ //
+ //*****************************************************************************
+ 
+ // the file we keep all of our help in
+ #define HELP_FILE          "../lib/misc/help"
+ 
+ // how many buckets are in our help table
+ #define HELP_TABLE_BUCKETS             27 // 26 for letters, 1 for non-alphas
+ 
+ // the table we store all of our helpfiles in
+ LIST *help_table[HELP_TABLE_BUCKETS];
+ 
+ typedef struct help_data {
+   char *keywords;   // words that bring up this helpfile
+   char *info;       // the information in the helpfile
+   char *editor;     // who edited the helpfile?
+   char *timestamp;  // when was it last edited?
+   LIST *backups;    // a chronologically sorted list of backup helps
+ } HELP_DATA;
+ 
+ 
+ HELP_DATA *newHelp(const char *editor, const char *timestamp,
+ 		   const char *keywords, const char *info) {
+   HELP_DATA *data = malloc(sizeof(HELP_DATA));
+   data->keywords  = strdup(keywords  ? keywords  : "");
+   data->editor    = strdup(editor    ? editor    : "");
+   data->info      = strdup(info      ? info      : "");
+   data->timestamp = strdup(timestamp ? timestamp : "");
+   data->backups   = newList();
+   return data;
+ }
+ 
+ void deleteHelp(HELP_DATA *data) {
+   deleteListWith(data->backups, deleteHelp);
+   if(data->keywords)  free(data->keywords);
+   if(data->editor)    free(data->editor);
+   if(data->timestamp) free(data->timestamp);
+   if(data->info)      free(data->info);
+   free(data);
+ }
+ 
+ HELP_DATA *helpRead(STORAGE_SET *set) {
+   HELP_DATA *data = newHelp(read_string(set, "editor"),
+ 			    read_string(set, "timestamp"),
+ 			    read_string(set, "keywords"),
+ 			    read_string(set, "info"));
+   deleteList(data->backups);
+   data->backups = gen_read_list(read_list(set, "backups"), helpRead);
+   return data;
+ }
+ 
+ STORAGE_SET *helpStore(HELP_DATA *help) {
+   STORAGE_SET *set = new_storage_set();
+   store_string(set, "keywords",  help->keywords);
+   store_string(set, "editor",    help->editor);
+   store_string(set, "timestamp", help->timestamp);
+   store_string(set, "info",      help->info);
+   store_list  (set, "backups",   gen_store_list(help->backups, helpStore));
+   return set;
+ }
+ 
+ 
+ //
+ // HELP_DATA holds all of the information about a helpfile, but HELP_ENTRY
+ // is a key/value pair used for storing helpfiles in the help table.
+ //
+ typedef struct help_entry {
+   char   *keyword;
+   HELP_DATA *help;
+ } HELP_ENTRY;
+ 
+ HELP_ENTRY *newHelpEntry(const char *keyword, HELP_DATA *data) {
+   HELP_ENTRY *entry = malloc(sizeof(HELP_ENTRY));
+   entry->keyword = strdup(keyword ? keyword : NULL);
+   entry->help    = data;
+   return entry;
+ }
+ 
+ void deleteHelpEntry(HELP_ENTRY *entry) {
+   if(entry->keyword) free(entry->keyword);
+   free(entry);
+ }
+ 
+ int hentrycmp(HELP_ENTRY *entry1, HELP_ENTRY *entry2) {
+   return strcasecmp(entry1->keyword, entry2->keyword);
+ }
+ 
+ int is_help_entry(const char *help, HELP_ENTRY *entry) {
+   return strcasecmp(help, entry->keyword);
+ }
+ 
+ int is_help_abbrev(const char *help, HELP_ENTRY *entry) {
+   return strncasecmp(help, entry->keyword, strlen(help));
+ }
+ 
+ 
+ //
+ // return the bucket that the specified helpfile belongs to
+ //
+ int helpbucket(const char *help) {
+   if(isalpha(*help))
+     return (tolower(*help) - 'a');
+   else
+     return HELP_TABLE_BUCKETS-1;
+ }
+ 
+ 
+ //
+ // save all of the helpfiles
+ //
+ void save_help() {
+   STORAGE_SET      *set = new_storage_set();
+   LIST       *help_list = newList();
+ 
+   // iterate across the table and save all the unique helpfiles
+   int i;
+   for(i = 0; i < HELP_TABLE_BUCKETS; i++) {
+     LIST_ITERATOR *row_i = newListIterator(help_table[i]);
+     HELP_ENTRY    *entry = NULL;
+     ITERATE_LIST(entry, row_i)
+       listPut(help_list, entry->help);
+     deleteListIterator(row_i);
+   }
+ 
+   store_list(set, "helpfiles", gen_store_list(help_list, helpStore));
+   deleteList(help_list);
+ 
+   // write the set
+   storage_write(set, HELP_FILE);
+   
+   // close the set
+   storage_close(set);
+ }
+ 
+ 
+ //
+ // add a helpfile to the help table. Assocciate all of its keywords with it
+ //
+ void add_help(HELP_DATA *help) {
+   int num_keywords = 0;
+   char  **keywords = parse_keywords(help->keywords, &num_keywords);
+   int i;
+   for(i = 0; i < num_keywords; i++) {
+     LIST *row = help_table[helpbucket(keywords[i])];
+     HELP_ENTRY *new_entry = newHelpEntry(keywords[i], help);
+     HELP_ENTRY *old_entry = NULL;
+     // make sure we're not already in the help table
+     if((old_entry = listRemoveWith(row, new_entry, hentrycmp)) != NULL)
+       deleteHelpEntry(old_entry);
+     listPutWith(row, new_entry, hentrycmp);
+     free(keywords[i]);
+   }
+   free(keywords);
+ }
+ 
+ 
+ //
+ // Returns the datastructure for the helpfile
+ //
+ HELP_DATA *get_help_data(const char *keyword, bool abbrev_ok) {
+   HELP_ENTRY *entry = listGetWith(help_table[helpbucket(keyword)], keyword, 
+ 				  (abbrev_ok ? is_help_abbrev : is_help_entry));
+   return (entry ? entry->help : NULL);
+ }
+ 
+ 
+ //
+ // remove a helpfile from the help table
+ //
+ HELP_DATA *remove_help(const char *keyword) {
+   HELP_ENTRY *entry = listRemoveWith(help_table[helpbucket(keyword)], keyword, 
+ 				     is_help_entry);
+   HELP_DATA *help = (entry ? entry->help : NULL);
+   if(entry) deleteHelpEntry(entry);
+   return help;
+ }
+ 
+ 
+ //
+ // return a list of matches for the specified help keyword. If we find an
+ // exact match, only that match will be contained within the list.
+ // List must be deleted after use.
+ //
+ LIST *help_matches(const char *keyword) {
+   int bucket  = helpbucket(keyword);
+   int key_len = strlen(keyword);
+   LIST_ITERATOR *buck_i = newListIterator(help_table[bucket]);
+   HELP_ENTRY     *entry = NULL;
+   LIST         *matches = newList();
+ 
+   ITERATE_LIST(entry, buck_i) {
+     // exact match
+     if(!strcasecmp(keyword, entry->keyword)) {
+       while(listSize(matches) > 0) listPop(matches);
+       listPut(matches, entry);
+       break;
+     }
+     else if(!strncasecmp(keyword, entry->keyword, key_len))
+       listQueue(matches, entry);
+   }
+   deleteListIterator(buck_i);
+   return matches;
+ }
+ 
+ 
+ //
+ // Show the contents of a helpfile to the character. If no argument is
+ // supplied, list all of the helpfiles. If we try to get info on a help
+ // that does not exist, list near-matches.
+ //
+ // usage:
+ //   help <topic>
+ //
+ COMMAND(cmd_help) {
+   static char buf[MAX_BUFFER];
+   
+   // no argument. Show a list of all our help topics
+   if(!arg || !*arg) {
+     int count, i, buf_i = 0;
+     buf_i = snprintf(buf, MAX_BUFFER, 
+ 		     "Help is available on the following topics:\r\n");
+     for(i = 0, count = 0; i < HELP_TABLE_BUCKETS; i++) {
+       LIST_ITERATOR *buck_i = newListIterator(help_table[i]);
+       HELP_ENTRY     *entry = NULL;
+       ITERATE_LIST(entry, buck_i) {
+ 	buf_i += snprintf(buf+buf_i, MAX_BUFFER-buf_i, "%-20s", entry->keyword);
+ 	count++;
+ 	// only 4 entries per row
+ 	if((count % 4) == 0) 
+ 	  buf_i += snprintf(buf+buf_i, MAX_BUFFER-buf_i, "\r\n");
+       }
+       deleteListIterator(buck_i);
+     }
+ 
+     // make sure we add a newline to the end
+     if((count % 4) != 0)
+       buf_i += snprintf(buf+buf_i, MAX_BUFFER-buf_i, "\r\n");
+ 
+     // send this to the character
+     if(charGetSocket(ch))
+       page_string(charGetSocket(ch), buf);
+   }
+ 
+ 
+   // pull out the helpfile
+   else {
+     // because we replace underscores with spaces in hlink,
+     // we should do the same thing here for consistancy's sake
+     char *ptr;
+     for(ptr = arg; *ptr; ptr++)
+       if(*ptr == '_') *ptr = ' ';
+ 
+     LIST *matches = help_matches(arg);
+     HELP_ENTRY *entry = NULL;
+     // no matches found
+     if(listSize(matches) == 0)
+       send_to_char(ch, "No help exists on that topic.\r\n");
+     // one match found
+     else if(listSize(matches) == 1) {
+       if(charGetSocket(ch)) {
+ 	entry = listPop(matches);
+ 	// the character has a socket... let's page the helpfile to him
+ 	if(charGetSocket(ch)) {
+ 	  char header[128]; // +2 for \r\n, +1 for \0
+ 	  center_string(header, entry->keyword, 80, 128, TRUE);
+ 	  sprintf(buf, "%s{wBy: %-36s%40s\r\n\r\n{n%s",
+ 		  header, entry->help->editor, entry->help->timestamp,
+ 		  entry->help->info);
+ 	  page_string(charGetSocket(ch), buf);
+ 	}
+       }
+     }
+ 
+     // more than one match found. Tell person to narrow search
+     else {
+       send_to_char(ch, "More than one entry matched your query: \r\n");
+       LIST_ITERATOR *match_i = newListIterator(matches);
+       ITERATE_LIST(entry, match_i)
+ 	send_to_char(ch, "{c%s ", entry->keyword);
+       deleteListIterator(match_i);
+       send_to_char(ch, "\r\n");
+     }
+     
+     // delete the list of matches we found
+     deleteList(matches);
+   }
+ }
+ 
+ 
+ //
+ // same as cmd_write, but loads the contents of the helpfile into the buffer
+ //
+ COMMAND(cmd_hedit) {
+   if(!arg || !*arg) {
+     send_to_char(ch, "Which helpfile are you trying to edit?\r\n");
+     return;
+   }
+   if(!charGetSocket(ch)) {
+     send_to_char(ch, "You must have a socket attached to use hedit.\r\n");
+     return;
+   }
+ 
+   // because we replace underscores with spaces in hlink,
+   // we should do the same thing here for consistancy's sake
+   char *ptr;
+   for(ptr = arg; *ptr; ptr++)
+     if(*ptr == '_') *ptr = ' ';
+ 
+   HELP_DATA *data = get_help_data(arg, FALSE);
+   start_notepad(charGetSocket(ch), (data ? data->info : ""), 
+ 		MAX_BUFFER, EDITOR_MODE_NORMAL);
+ }
+ 
+ 
+ //
+ // Edit the contents of a helpfile
+ //
+ COMMAND(cmd_hupdate) {
+   if(!arg || !*arg) {
+     send_to_char(ch, "Which helpfile were you trying to update?\r\n");
+     return;
+   }
+   if(!charGetSocket(ch) || !charGetSocket(ch)->notepad || 
+      !*charGetSocket(ch)->notepad) {
+     send_to_char(ch, "You have nothing in your notepad! Try writing something.\r\n");
+     return;
+   }
+ 
+   // because we replace underscores with spaces in hlink,
+   // we should do the same thing here for consistancy's sake
+   char *ptr;
+   for(ptr = arg; *ptr; ptr++)
+     if(*ptr == '_') *ptr = ' ';
+ 
+   update_help(charGetName(ch), arg, charGetSocket(ch)->notepad);
+ }
+ 
+ 
+ //
+ // Link a keyword to an already-existing helpfile. underscores must be
+ // used instead of spaces.
+ //   usage:
+ //     hlink [new_topic] [old_topic]
+ //
+ COMMAND(cmd_hlink) {
+   char new_help[SMALL_BUFFER];
+ 
+   if(!arg || !*arg) {
+     send_to_char(ch, "Link which helpfile to which?\r\n");
+     return;
+   }
+ 
+   arg = one_arg(arg, new_help);
+ 
+   if(!*new_help || !*arg) {
+     send_to_char(ch, "You must provide a new keyword and an old keyword "
+ 		 "to link it to.\r\n");
+     return;
+   }
+ 
+   // kill all of the underscores, and put spaces in instead
+   char *ptr;
+   for(ptr = new_help; *ptr; ptr++)
+     if(*ptr == '_') *ptr = ' ';
+   for(ptr = arg; *ptr; ptr++)
+     if(*ptr == '_') *ptr = ' ';
+ 
+   // find the help we're trying to link to
+   HELP_DATA *help = get_help_data(arg, FALSE);
+ 
+   if(help == NULL) {
+     send_to_char(ch, "No help exists for %s.\r\n", arg);
+     return;
+   }
+ 
+ 
+   // perform the link
+   link_help(new_help, arg);
+   send_to_char(ch, "%s linked to %s.\r\n", new_help, arg);
+ }
+ 
+ 
+ //
+ // Unlink a keyword from its assocciated helpfile. 
+ //   usage:
+ //     hunlink [topic]
+ //
+ COMMAND(cmd_hunlink) {
+   if(!arg || !*arg) {
+     send_to_char(ch, "Unlink which helpfile?\r\n");
+     return;
+   }
+ 
+   // because we replace underscores with spaces in hlink,
+   // we should do the same thing here for consistancy's sake
+   char *ptr;
+   for(ptr = arg; *ptr; ptr++)
+     if(*ptr == '_') *ptr = ' ';
+ 
+   // find the social we're trying to link to
+   HELP_DATA *help = get_help_data(arg, FALSE);
+ 
+   if(help == NULL) {
+     send_to_char(ch, "No help exists for %s.\r\n", arg);
+     return;
+   }
+ 
+   // perform the unlinking
+   unlink_help(arg);
+   send_to_char(ch, "The %s helpfile was unlinked.\r\n", arg);
+ }
+ 
+ 
+ 
+ //*****************************************************************************
+ //
+ // implementation of help.h
+ //
+ //*****************************************************************************
+ void init_help() {
+   // init all of our buckets
+   int i;
+   for(i = 0; i < HELP_TABLE_BUCKETS; i++)
+     help_table[i] = newList();
+ 
+   // add all of our commands
+   add_cmd("help", NULL, cmd_help, 0, POS_UNCONCIOUS, POS_FLYING,
+ 	  LEVEL_PLAYER, FALSE, FALSE);
+   add_cmd("hlink", NULL, cmd_hlink, 0, POS_UNCONCIOUS, POS_FLYING,
+ 	  LEVEL_ADMIN, FALSE, FALSE);
+   add_cmd("hunlink", NULL, cmd_hunlink, 0, POS_UNCONCIOUS, POS_FLYING,
+ 	  LEVEL_ADMIN, FALSE, FALSE);
+   add_cmd("hupdate", NULL, cmd_hupdate, 0, POS_SITTING, POS_FLYING,
+ 	  LEVEL_BUILDER, FALSE, TRUE);
+   add_cmd("hedit", NULL, cmd_hedit, 0, POS_SITTING, POS_FLYING,
+ 	  LEVEL_BUILDER, FALSE, TRUE);
+ 
+   // read in all of our helps
+   STORAGE_SET       *set = storage_read(HELP_FILE);
+   STORAGE_SET_LIST *list = read_list(set, "helpfiles");
+   STORAGE_SET     *entry = NULL;
+ 
+   // parse all of the helpfiles
+   while( (entry = storage_list_next(list)) != NULL)
+     add_help(helpRead(entry));
+ 
+   storage_close(set);
+ }
+ 
+ const char *get_help(const char *keyword) {
+   HELP_DATA *data = get_help_data(keyword, FALSE);
+   return(data ? data->info : NULL);
+ }
+ 
+ 
+ void update_help(const char *editor, const char *keyword, const char *info) {
+   HELP_DATA *data = get_help_data(keyword, FALSE);
+ 
+   if(data != NULL) {
+     HELP_DATA *help_old = newHelp(data->editor, data->timestamp, data->keywords,
+ 				  data->info);
+     if(data->editor)    free(data->editor);
+     if(data->timestamp) free(data->timestamp);
+     if(data->info)      free(data->info);
+     
+     data->editor      = strdup(editor ? editor : "");
+     data->info        = strdup(info   ? info   : "");
+     data->timestamp   = strdup(get_time());
+ 
+     listPut(data->backups, help_old);
+   }
+   else
+     add_help(newHelp(editor, get_time(), keyword, info));
+ 
+   save_help();
+ }
+ 
+ 
+ void unlink_help(const char *keyword) {
+   // remove the helpfile
+   HELP_DATA *data = remove_help(keyword);
+ 
+   // unlink the helpfile
+   if(data != NULL) {
+     remove_keyword(data->keywords, keyword);
+ 
+     // if no links are left, delete the helpfile
+     if(!*data->keywords)
+       deleteHelp(data);
+     
+     // save our changes
+     save_help();
+   }
+ }
+ 
+ 
+ void link_help(const char *keyword, const char *old_word) {
+   // check for the old keyword
+   HELP_DATA *data = get_help_data(old_word, FALSE);
+ 
+   // link the new keyword to the old one
+   if(data != NULL) {
+     // first, remove the current new_keyword help, if it exists
+     unlink_help(keyword);
+ 
+     // add the new keyword to the help
+     add_keyword(&(data->keywords), keyword);
+ 
+     // add the new command to the help table
+     LIST *row = help_table[helpbucket(keyword)];
+     HELP_ENTRY *new_entry = newHelpEntry(keyword, data);
+     listPutWith(row, new_entry, hentrycmp);
+ 
+     // save our changes
+     save_help();
+   }
+ }
diff -crN nakedmudv1.4/src/help/help.h nakedmudv1.5/src/help/help.h
*** nakedmudv1.4/src/help/help.h	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/src/help/help.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,51 ----
+ #ifndef __HELP_H
+ #define __HELP_H
+ //*****************************************************************************
+ //
+ // help.h
+ //
+ // This helpfile system has been set up to be amenable to allowing players to
+ // edit helpfiles without having to worry about malicious users. 
+ //
+ //*****************************************************************************
+ 
+ //
+ // This must be put at the top of mud.h so the rest of the MUD knows that
+ // we've got the help module installed
+ // #define MODULE_HELP
+ //
+ 
+ 
+ //
+ // prepare helpfiles for use
+ //
+ void init_help();
+ 
+ 
+ //
+ // Make changes to the content of the helpfile. The old info is backed up.
+ // To protect against malicious changes. update_help can be used to create
+ // new helpfiles as well.
+ //
+ void update_help(const char *editor, const char *keyword, const char *info);
+ 
+ 
+ //
+ // Get the content of the helpfile. Return NULL if none exists.
+ //
+ const char *get_help(const char *keyword);
+ 
+ 
+ //
+ // unlink a keyword from the help info. If no more links are left to the
+ // helpfile, the helpfile is deleted.
+ //
+ void unlink_help(const char *keyword);
+ 
+ 
+ //
+ // link a new keyword to a helpfile
+ //
+ void link_help(const char *keyword, const char *old_word);
+ 
+ #endif // __HELP_H
diff -crN nakedmudv1.4/src/help/module.mk nakedmudv1.5/src/help/module.mk
*** nakedmudv1.4/src/help/module.mk	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/src/help/module.mk	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,2 ----
+ # the source files we need to compile
+ SRC += help/help.c
diff -crN nakedmudv1.4/src/help.c nakedmudv1.5/src/help.c
*** nakedmudv1.4/src/help.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/help.c	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,201 ****
- /*
-  * This file contains the dynamic help system.
-  * If you wish to update a help file, simply edit
-  * the entry in ../help/ and the mud will load the
-  * new version next time someone tries to access
-  * that help file.
-  */
- #include <sys/types.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <stdio.h>
- #include <time.h>
- #include <dirent.h> 
- 
- /* include main header file */
- #include "mud.h"
- #include "character.h"
- #include "help.h"
- 
- HELP_DATA   *   help_list = NULL; /* the linked list of help files     */
- char        *   greeting;         /* the welcome greeting              */
- char        *   motd;             /* the MOTD help file                */
- 
- /*
-  * Check_help()
-  *
-  * This function first sees if there is a valid
-  * help file in the help_list, should there be
-  * no helpfile in the help_list, it will check
-  * the ../help/ directory for a suitable helpfile
-  * entry. Even if it finds the helpfile in the
-  * help_list, it will still check the ../help/
-  * directory, and should the file be newer than
-  * the currently loaded helpfile, it will reload
-  * the helpfile.
-  */
- bool check_help(CHAR_DATA *dMob, char *helpfile)
- {
-   HELP_DATA *pHelp;
-   char buf[MAX_HELP_ENTRY + 80];
-   char *entry, *hFile;
-   bool found = FALSE;
- 
-   hFile = capitalize(helpfile);
- 
-   for (pHelp = help_list; pHelp; pHelp = pHelp->next)
-   {
-     if (is_prefix(helpfile, pHelp->keyword))
-     {
-       found = TRUE;
-       break;
-     }
-   }
- 
-   /* If there is an updated version we load it */
-   if (found)
-   {
-     if (last_modified(hFile) > pHelp->load_time)
-     {
-       free(pHelp->text);
-       pHelp->text = strdup(read_help_entry(hFile));
-     }
-   }
-   else /* is there a version at all ?? */
-   {
-     if ((entry = read_help_entry(hFile)) == NULL)
-       return FALSE;
-     else
-     {
-       if ((pHelp = malloc(sizeof(*pHelp))) == NULL)
-       { 
-         bug("Check_help: Cannot allocate memory.");
-         abort();
-       }
-       pHelp->keyword    =  strdup(hFile);
-       pHelp->text       =  strdup(entry);
-       pHelp->load_time  =  time(NULL);
-       add_help(pHelp);
-     }
-   }
- 
-   sprintf(buf, "=== %s ===\n\r%s", pHelp->keyword, pHelp->text);
-   //  text_to_char(dMob, buf);
-   page_string(charGetSocket(dMob), buf);
-   return TRUE;
- }
- 
- /*
-  * Loads all the helpfiles found in ../help/
-  */
- void load_helps()
- {
-   HELP_DATA *new_help;
-   char buf[MAX_BUFFER];
-   char *s;
-   DIR *directory;
-   struct dirent *entry;
- 
-   log_string("Load_helps: getting all help files.");
- 
-   directory = opendir("../help/");
-   for (entry = readdir(directory); entry; entry = readdir(directory))
-   {
-     if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
-       continue;
- 
-     sprintf(buf, "../help/%s", entry->d_name);
-     s = read_help_entry(buf);
- 
-     if (s == NULL)
-     {
-       bug("load_helps: Helpfile %s does not exist.", buf);
-       continue;
-     }
- 
-     if ((new_help = malloc(sizeof(*new_help))) == NULL)
-     {
-       bug("Load_helps: Cannot allocate memory.");
-       abort();
-     }
- 
-     new_help->keyword    =  strdup(entry->d_name);
-     new_help->text       =  strdup(s);
-     new_help->load_time  =  time(NULL);
-     add_help(new_help);
-   }
-   closedir(directory);
- }
- 
- void add_help(HELP_DATA *help)
- {
-   HELP_DATA *pHelp = NULL;
-   HELP_DATA *prev = NULL;
-   bool done = FALSE;
-   int i;
- 
-   if (help_list == NULL)
-   {
-     help_list = help;
-     help->next = NULL;
-   }
-   else
-   {
-     for (pHelp = help_list; pHelp; pHelp = pHelp->next)
-     {
-       if (toupper(help->keyword[0]) > toupper(pHelp->keyword[0]))
-       {
-         prev = pHelp;
-         continue;
-       }
-       else if (toupper(help->keyword[0]) == toupper(pHelp->keyword[0]))
-       {
-         for (i = 0; help->keyword[i] != '\0' && pHelp->keyword[i] != '\0'; i++)
-         {
-           if (toupper(help->keyword[i]) > toupper(pHelp->keyword[i]))
-           {
-             prev = pHelp;
-             break;
-           }
- 
-           if (help->keyword[i+1] == '\0')
-           {
-             done = TRUE;
-             break;
-           }
- 
-           /* Helpfile should previous to this helpfile entry */
-           if (toupper(help->keyword[i]) == toupper(pHelp->keyword[i]))
-           {
-             prev = pHelp;
-             break;
-           }
- 
-           /* less than or at the end of the word */
-           if (toupper(help->keyword[i]) < toupper(pHelp->keyword[i]))
-           {
-             done = TRUE;
-             break;
-           }
-         }
- 
-         if (!done)
-           continue;
-       }
- 
-       break;
-     }
- 
-     if (prev == NULL)
-     {
-       help->next = help_list;
-       help_list = help;
-     }
-     else
-     {
-       help->next = prev->next;
-       prev->next = help;
-     }
-   }
- }
--- 0 ----
diff -crN nakedmudv1.4/src/help.h nakedmudv1.5/src/help.h
*** nakedmudv1.4/src/help.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/help.h	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,25 ****
- #ifndef __HELP_H
- #define __HELP_H
- //*****************************************************************************
- //
- // help.h
- //
- // has all of the functions needed for interacting with the helpfile system.
- //
- //*****************************************************************************
- 
- void        load_helps        ();
- void        reload_helps      ();
- HELP_DATA  *get_help          (const char *keyword);
- void        add_help          (HELP_DATA *help);
- 
- 
- HELP_DATA  *newHelpEntry      (const char *keywords, const char *desc);
- void        helpEntryCopyTo   (HELP_DATA *from, HELP_DATA *to);
- HELP_DATA  *helpEntryCopy     (HELP_DATA *help);
- void        show_help         (CHAR_DATA *ch, HELP_DATA *help);
- char      **helpEntryDescPtr  (HELP_DATA *help);
- 
- void        setHelpEntryDesc  (HELP_DATA *help);
- 
- #endif // __HELP_H
--- 0 ----
diff -crN nakedmudv1.4/src/help_new.c nakedmudv1.5/src/help_new.c
*** nakedmudv1.4/src/help_new.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/help_new.c	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,40 ****
- #include <sys/types.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <stdio.h>
- #include <time.h>
- #include <dirent.h> 
- 
- #include "mud.h"
- #include "character.h"
- #include "hashtable.h"
- 
- HASHTABLE   *   helptable = NULL;
- char        *   greeting  = NULL;   /* the welcome greeting              */
- char        *   motd      = NULL;   /* the MOTD help file                */
- 
- void load_helps() {
-   helptable = newHashtable(2500);
- }
- 
- void reload_helps() {
- 
- }
- 
- HELP_DATA *get_help(const char *keyword) {
-   return hashGet(helptable, keyword);
- }
- 
- void add_help(HELP_DATA *help) {
- 
- }
- 
- HELP_DATA *new_help(const char *keywords, 
- 		    const char *desc) {
-   return NULL;
- }
- 
- void show_help(CHAR_DATA *ch, HELP_DATA *help) {
- 
- }
--- 0 ----
diff -crN nakedmudv1.4/src/inform.c nakedmudv1.5/src/inform.c
*** nakedmudv1.4/src/inform.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/inform.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 24,36 ****
  #include "inform.h"
  #include "log.h"
  
- 
  // optional module headers
  #ifdef MODULE_TIME
  #include "time/mudtime.h"
  #endif
  
  
  //
  // Show a character who is all sitting at one piece of furniture
  //
--- 24,41 ----
  #include "inform.h"
  #include "log.h"
  
  // optional module headers
  #ifdef MODULE_TIME
  #include "time/mudtime.h"
  #endif
  
  
+ //*****************************************************************************
+ //
+ // local functions
+ //
+ //*****************************************************************************
+ 
  //
  // Show a character who is all sitting at one piece of furniture
  //
***************
*** 92,97 ****
--- 97,133 ----
  }
  
  
+ //
+ // uhhh... "contents" isn't really the right word, since we list both
+ // objects AND characters. Alas, my lexicon is not as verbose as it
+ // could be.
+ //
+ void list_room_contents(CHAR_DATA *ch, ROOM_DATA *room) {
+   LIST *list = NULL;
+ 
+   list = get_nofurniture_chars(ch, roomGetCharacters(room), FALSE, FALSE);
+   show_list(ch, list, charGetRdesc, charGetMultiRdesc, charGetVnum);
+   deleteList(list);
+ 
+   // show all of the objects that have people using them
+   list = get_used_items(ch, roomGetContents(room), FALSE);
+   list_used_furniture(ch, list);
+   deleteList(list);
+ 
+   // show all of the objects that don't have people using them that we can see
+   list = get_unused_items(ch, roomGetContents(room), FALSE);
+   show_list(ch, list, objGetRdesc, objGetMultiRdesc, objGetVnum);
+   deleteList(list);
+ }
+ 
+ 
+ 
+ //*****************************************************************************
+ //
+ // implementaiton of inform.h
+ // look_at_xxx and show_xxx functions.
+ //
+ //*****************************************************************************
  void look_at_obj(CHAR_DATA *ch, OBJ_DATA *obj) {
    char *new_desc = tagEdescs(objGetEdescs(obj),
  			     objGetDesc(obj),
***************
*** 113,119 ****
        // make sure we can still see things
        if(listSize(vis_contents) > 0) {
  	send_to_char(ch, "It contains:\r\n");
! 	show_list(ch, vis_contents, objGetName, objGetMultiName);
        }
        deleteList(vis_contents);
      }
--- 149,155 ----
        // make sure we can still see things
        if(listSize(vis_contents) > 0) {
  	send_to_char(ch, "It contains:\r\n");
! 	show_list(ch, vis_contents, objGetName, objGetMultiName, objGetVnum);
        }
        deleteList(vis_contents);
      }
***************
*** 151,158 ****
  
  
  void look_at_exit(CHAR_DATA *ch, EXIT_DATA *exit) {
!   send_to_char(ch, "%s", (*exitGetDesc(exit) ? exitGetDesc(exit) :
! 			  NOTHING_SPECIAL"\r\n"));
    // we have a door ... gotta print it's status
    if(exitIsClosable(exit)) {
      if(!*exitGetName(exit))
--- 187,194 ----
  
  
  void look_at_exit(CHAR_DATA *ch, EXIT_DATA *exit) {
!   send_to_char(ch, "{g%s", (*exitGetDesc(exit) ? exitGetDesc(exit) :
! 			    NOTHING_SPECIAL"\r\n"));
    // we have a door ... gotta print it's status
    if(exitIsClosable(exit)) {
      if(!*exitGetName(exit))
***************
*** 162,167 ****
--- 198,210 ----
  		   exitGetName(exit), (exitIsClosed(exit) ? "closed":"open"));
      }
    }
+ 
+   // the door is not closed, list off the people we can see as well
+   if(!exitIsClosed(exit)) {
+     ROOM_DATA *room = worldGetRoom(gameworld, exitGetTo(exit));
+     if(room != NULL)
+       list_room_contents(ch, room);
+   }
  }
  
  
***************
*** 178,188 ****
      if(!can_see_exit(ch, exit))
        continue;
      else if((to = worldGetRoom(gameworld, exitGetTo(exit))) == NULL) {
!        log_string("ERROR: room %d heads %s to room %d, which does not exist.",
  		 roomGetVnum(room), dirGetName(i), exitGetTo(exit));
!        continue;
      }
! 
      if(charGetLevel(ch) > LEVEL_PLAYER)
        sprintf(buf, "[%d] ", roomGetVnum(to));
      else
--- 221,231 ----
      if(!can_see_exit(ch, exit))
        continue;
      else if((to = worldGetRoom(gameworld, exitGetTo(exit))) == NULL) {
!       log_string("ERROR: room %d heads %s to room %d, which does not exist.",
  		 roomGetVnum(room), dirGetName(i), exitGetTo(exit));
!       continue;
      }
!     
      if(charGetLevel(ch) > LEVEL_PLAYER)
        sprintf(buf, "[%d] ", roomGetVnum(to));
      else
***************
*** 201,207 ****
  
    // list special exits
    int num_spec_exits = 0;
!   char **names = roomGetExitNames(room, &num_spec_exits);
    for(i = 0; i < num_spec_exits; i++) {
      if((exit = roomGetExitSpecial(room, names[i])) == NULL)
        continue;
--- 244,250 ----
  
    // list special exits
    int num_spec_exits = 0;
!   const char **names = roomGetExitNames(room, &num_spec_exits);
    for(i = 0; i < num_spec_exits; i++) {
      if((exit = roomGetExitSpecial(room, names[i])) == NULL)
        continue;
***************
*** 228,236 ****
  		  roomGetName(to)));
    }
  
    // clean up our mess
-   for(i = 0; i < num_spec_exits; i++)
-     free(names[i]);
    free(names);
  }
  
--- 271,278 ----
  		  roomGetName(to)));
    }
  
+ 
    // clean up our mess
    free(names);
  }
  
***************
*** 259,267 ****
    show_body(ch, charGetBody(vict));
  }
  
- void look_at_room(CHAR_DATA *ch, ROOM_DATA *room) {
-   LIST *list = NULL;
  
    if(charGetLevel(ch) > LEVEL_PLAYER)
      send_to_char(ch, "{c[%d] ", roomGetVnum(room));
  
--- 301,308 ----
    show_body(ch, charGetBody(vict));
  }
  
  
+ void look_at_room(CHAR_DATA *ch, ROOM_DATA *room) {
    if(charGetLevel(ch) > LEVEL_PLAYER)
      send_to_char(ch, "{c[%d] ", roomGetVnum(room));
  
***************
*** 272,301 ****
    if((is_evening() || is_night()) && *roomGetNightDesc(room))
      desc = roomGetNightDesc(room);
  #endif
- 
    char *colorize_desc = tagEdescs(roomGetEdescs(room), desc, "{c", "{g");
    send_to_char(ch, "{g%s", colorize_desc);
!   if(colorize_desc) free(colorize_desc);
! 
    list_room_exits(ch, room);
!   list = get_nofurniture_chars(ch, roomGetCharacters(room), FALSE, FALSE);
!   show_list(ch, list, charGetRdesc, charGetMultiRdesc);
!   deleteList(list);
! 
!   // show all of the objects that have people using them
!   list = get_used_items(ch, roomGetContents(room), FALSE);
!   list_used_furniture(ch, list);
!   deleteList(list);
! 
!   // show all of the objects that don't have people using them that we can see
!   list = get_unused_items(ch, roomGetContents(room), FALSE);
!   show_list(ch, list, objGetRdesc, objGetMultiRdesc);
!   deleteList(list);
  
    send_to_char(ch, "{n");
  };
  
  
  void send_outdoors(const char *format, ...) {
    if(format && *format) {
      // form the message
--- 313,336 ----
    if((is_evening() || is_night()) && *roomGetNightDesc(room))
      desc = roomGetNightDesc(room);
  #endif
    char *colorize_desc = tagEdescs(roomGetEdescs(room), desc, "{c", "{g");
    send_to_char(ch, "{g%s", colorize_desc);
!   free(colorize_desc);
!     
    list_room_exits(ch, room);
!   list_room_contents(ch, room);
  
    send_to_char(ch, "{n");
  };
  
  
+ 
+ //*****************************************************************************
+ //
+ // implementaiton of inform.h
+ // send_to_xxx functions
+ //
+ //*****************************************************************************
  void send_outdoors(const char *format, ...) {
    if(format && *format) {
      // form the message
***************
*** 309,315 ****
      LIST_ITERATOR *list_i = newListIterator(mobile_list);
      CHAR_DATA *ch = NULL;
      ITERATE_LIST(ch, list_i)
!       if(roomGetTerrain(charGetRoom(ch)) != TERRAIN_INDOORS)
  	text_to_char(ch, buf);
      deleteListIterator(list_i);
    }
--- 344,351 ----
      LIST_ITERATOR *list_i = newListIterator(mobile_list);
      CHAR_DATA *ch = NULL;
      ITERATE_LIST(ch, list_i)
!       if(roomGetTerrain(charGetRoom(ch)) != TERRAIN_INDOORS &&
! 	 roomGetTerrain(charGetRoom(ch)) != TERRAIN_CAVERN)
  	text_to_char(ch, buf);
      deleteListIterator(list_i);
    }
***************
*** 404,413 ****
  
  
  
- 
  //*****************************************************************************
  //
! // commands included in inform.c
  //
  //*****************************************************************************
  
--- 440,449 ----
  
  
  
  //*****************************************************************************
  //
! // implementation of inform.h
! // game commands
  //
  //*****************************************************************************
  
***************
*** 503,509 ****
  	send_to_char(ch, "You peer inside of %s:\r\n", objGetName(found));
  	LIST *vis_objs = find_all_objs(ch, objGetContents(found), "",
  				       NOTHING, TRUE);
! 	show_list(ch, vis_objs, objGetName, objGetMultiName);
  	deleteList(vis_objs);
        }
      }
--- 539,545 ----
  	send_to_char(ch, "You peer inside of %s:\r\n", objGetName(found));
  	LIST *vis_objs = find_all_objs(ch, objGetContents(found), "",
  				       NOTHING, TRUE);
! 	show_list(ch, vis_objs, objGetName, objGetMultiName, objGetVnum);
  	deleteList(vis_objs);
        }
      }
***************
*** 540,546 ****
    else {
      send_to_char(ch, "You are carrying:\r\n");
      LIST *vis_objs = find_all_objs(ch, charGetInventory(ch), "", NOTHING, TRUE);
!     show_list(ch, vis_objs, objGetName, objGetMultiName);
      deleteList(vis_objs);
    }
  }
--- 576,582 ----
    else {
      send_to_char(ch, "You are carrying:\r\n");
      LIST *vis_objs = find_all_objs(ch, charGetInventory(ch), "", NOTHING, TRUE);
!     show_list(ch, vis_objs, objGetName, objGetMultiName, objGetVnum);
      deleteList(vis_objs);
    }
  }
***************
*** 592,628 ****
  }
  
  
- //
- // show the character the contents of a specific helpfile, or all the helpfiles
- // available if no argument is supplied.
- //
- COMMAND(cmd_help)
- {
-   if (arg[0] == '\0')
-   {
-     HELP_DATA *pHelp;
-     BUFFER *buf = buffer_new(MAX_BUFFER);
-     int col = 0;
- 
-     bprintf(buf, "      - - - - - ----====//// HELP FILES  \\\\\\\\====---- - - - - -\n\n\r");
-     for (pHelp = help_list; pHelp; pHelp = pHelp->next)
-     {
-       bprintf(buf, " %-19.18s", pHelp->keyword);
-       if (!(++col % 4)) bprintf(buf, "\n\r");
-     }
-     if (col % 4) bprintf(buf, "\n\r");
-     bprintf(buf, "\n\r Syntax: help <topic>\n\r");
-     text_to_char(ch, buf->data);
-     buffer_free(buf);
-     return;
-   }
-   if (!check_help(ch, arg))
-   {
-     text_to_char(ch, "Sorry, no such helpfile.\n\r");
-     return;
-   }
- }
- 
  
  //*****************************************************************************
  //
--- 628,633 ----
diff -crN nakedmudv1.4/src/interpret.c nakedmudv1.5/src/interpret.c
*** nakedmudv1.4/src/interpret.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/interpret.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 91,99 ****
    // B
    add_cmd("back",       NULL, cmd_back,     0, POS_UNCONCIOUS, POS_FLYING,
  	  LEVEL_PLAYER, TRUE, FALSE);
!   add_cmd("buildwalk",  NULL, cmd_tog_prf,  SUBCMD_BUILDWALK, 
  	  POS_UNCONCIOUS, POS_FLYING, LEVEL_BUILDER, FALSE, FALSE);
  
    // C
    add_cmd("chat",       NULL, cmd_chat,     0, POS_UNCONCIOUS, POS_FLYING,
  	  LEVEL_PLAYER, TRUE, FALSE);
--- 91,100 ----
    // B
    add_cmd("back",       NULL, cmd_back,     0, POS_UNCONCIOUS, POS_FLYING,
  	  LEVEL_PLAYER, TRUE, FALSE);
!   add_cmd("buildwalk",  NULL, cmd_tog_prf,  PRF_BUILDWALK, 
  	  POS_UNCONCIOUS, POS_FLYING, LEVEL_BUILDER, FALSE, FALSE);
  
+ 
    // C
    add_cmd("chat",       NULL, cmd_chat,     0, POS_UNCONCIOUS, POS_FLYING,
  	  LEVEL_PLAYER, TRUE, FALSE);
***************
*** 149,160 ****
  	  LEVEL_BUILDER, FALSE, TRUE );
  
    // H
!   add_cmd("help",       NULL, cmd_help,     0, POS_UNCONCIOUS, POS_FLYING,
! 	  LEVEL_PLAYER, TRUE, FALSE);
  
    // I
    add_cmd("inventory",  NULL, cmd_inventory,0, POS_SITTING,  POS_FLYING,
  	  LEVEL_PLAYER, TRUE, FALSE);
  
    // L
    add_cmd("look",       "l",  cmd_look,     0, POS_SITTING,  POS_FLYING,
--- 150,163 ----
  	  LEVEL_BUILDER, FALSE, TRUE );
  
    // H
!   //  add_cmd("help",       NULL, cmd_help,     0, POS_UNCONCIOUS, POS_FLYING,
!   //	  LEVEL_PLAYER, TRUE, FALSE);
  
    // I
    add_cmd("inventory",  NULL, cmd_inventory,0, POS_SITTING,  POS_FLYING,
  	  LEVEL_PLAYER, TRUE, FALSE);
+   add_cmd("invis",      NULL, cmd_invis,    0, POS_UNCONCIOUS, POS_FLYING,
+ 	  LEVEL_BUILDER, FALSE, FALSE);
  
    // L
    add_cmd("look",       "l",  cmd_look,     0, POS_SITTING,  POS_FLYING,
***************
*** 169,174 ****
--- 172,179 ----
  	  LEVEL_ADMIN, FALSE, FALSE);
  
    // M
+   add_cmd("mapwalk",    NULL, cmd_tog_prf,  PRF_MAPWALK,
+ 	  POS_UNCONCIOUS, POS_FLYING, LEVEL_PLAYER, FALSE, FALSE);
    add_cmd("mlist",      NULL, cmd_mlist,    0, POS_UNCONCIOUS, POS_FLYING,
  	  LEVEL_BUILDER, FALSE, FALSE);
    add_cmd("more",       NULL, cmd_more,     0, POS_UNCONCIOUS, POS_FLYING,
***************
*** 211,216 ****
--- 216,223 ----
  	  LEVEL_PLAYER, TRUE, FALSE);
    add_cmd("stand",      NULL, cmd_stand,    0, POS_SITTING,  POS_STANDING,
  	  LEVEL_PLAYER, TRUE, TRUE );
+   add_cmd("stop",       NULL, cmd_stop,     0, POS_SITTING, POS_FLYING,
+ 	  LEVEL_PLAYER, TRUE, FALSE);
  #ifdef MODULE_SCRIPTS
    // really, we -should- put this in the scripts module, but there are some
    // very nice functions in builder.c that cmd_sclist uses to print scripts,
***************
*** 224,234 ****
--- 231,247 ----
  	  LEVEL_PLAYER, TRUE, TRUE );
    add_cmd("tell",       NULL, cmd_tell,     0, POS_SLEEPING, POS_FLYING,
  	  LEVEL_PLAYER, TRUE, FALSE);
+   add_cmd("transfer",   NULL, cmd_transfer, 0, POS_STANDING, POS_FLYING,
+ 	  LEVEL_BUILDER, FALSE, TRUE);
  
    // U
    add_cmd("unlock",       NULL,  cmd_unlock,    0, POS_STANDING,  POS_FLYING,
  	  LEVEL_PLAYER, TRUE, TRUE);
  
+   // V
+   add_cmd("visible",      NULL, cmd_visible,    0, POS_UNCONCIOUS, POS_FLYING,
+ 	  LEVEL_BUILDER, FALSE, FALSE);
+ 
    // W
    add_cmd("wake",       NULL, cmd_wake,     0, POS_SLEEPING,  POS_SLEEPING,
  	  LEVEL_PLAYER, TRUE, TRUE );
***************
*** 240,245 ****
--- 253,260 ----
  	  LEVEL_BUILDER, FALSE, FALSE);
    add_cmd("worn",       NULL, cmd_equipment,0, POS_SITTING,  POS_FLYING,
  	  LEVEL_PLAYER, TRUE, FALSE);
+   add_cmd("write",      NULL, cmd_write,    0, POS_SITTING, POS_FLYING,
+ 	  LEVEL_PLAYER, TRUE, TRUE);
  
    // Z
    add_cmd("zlist",      NULL, cmd_zlist,    0, POS_SITTING,  POS_FLYING,
diff -crN nakedmudv1.4/src/io.c nakedmudv1.5/src/io.c
*** nakedmudv1.4/src/io.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/io.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 81,102 ****
    communicate(NULL, buf, COMM_LOG);
  }
  
- /*
-  * This function will return the time of
-  * the last modification made to helpfile.
-  */
- time_t last_modified(char *helpfile)
- {
-   char fHelp[256];
-   struct stat sBuf;
-   time_t mTime = 0;
- 
-   sprintf(fHelp, "../help/%s", helpfile);
-   if (stat(fHelp, &sBuf) >= 0)
-     mTime = sBuf.st_mtime;
- 
-   return mTime;
- }
  
  char *read_file(const char *file) {
    FILE *fl;
--- 81,86 ----
***************
*** 116,159 ****
  }
  
  
- char *read_help_entry(const char *helpfile)
- {
-   FILE *fp;
-   static char entry[MAX_BUFFER];
-   char fHelp[256];
-   int c, ptr = 0;
- 
-   /* location of the help file */
-   sprintf(fHelp, "../help/%s", helpfile);
- 
-   /* if there is no help file, return NULL */
-   if ((fp = fopen(fHelp, "r")) == NULL)
-     return NULL;
- 
-   /* just to have something to work with */
-   c = getc(fp);
- 
-   /* read the file in the buffer */
-   while (c != EOF)
-   {
-     if (c == '\n')
-       entry[ptr++] = '\r';
-     entry[ptr] = c;
-     if (++ptr > MAX_BUFFER - 2)
-     {
-       bug("Read_help_entry: String to long.");
-       abort();
-     }
-     c = getc(fp);
-   }
-   entry[ptr] = '\0';
- 
-   fclose(fp);
- 
-   /* return a pointer to the static buffer */
-   return entry;
- }
- 
  /*
   * Reads one line from a file, and returns a
   * pointer to a _static array_ holding the line.
--- 100,105 ----
diff -crN nakedmudv1.4/src/list.c nakedmudv1.5/src/list.c
*** nakedmudv1.4/src/list.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/list.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 283,288 ****
--- 283,296 ----
    return (node ? node->elem : NULL);
  }
  
+ void *listHead(struct list *L) {
+   return L->head;
+ }
+ 
+ void *listTail(struct list *L) {
+   return L->tail;
+ }
+ 
  int isListEmpty(struct list *L) {
    return (L->size == 0);
  }
diff -crN nakedmudv1.4/src/list.h nakedmudv1.5/src/list.h
*** nakedmudv1.4/src/list.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/list.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 95,100 ****
--- 95,112 ----
  
  
  //
+ // Return the head of the list
+ //
+ void *listHead(struct list *L);
+ 
+ 
+ //
+ // Return the tail of the list
+ //
+ void *listTail(struct list *L);
+ 
+ 
+ //
  // Put the element in the list in an ascending order, based on
  // what the comparator, func, tells us is the order.
  //
diff -crN nakedmudv1.4/src/log.c nakedmudv1.5/src/log.c
*** nakedmudv1.4/src/log.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/log.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 70,80 ****
    const char *log   = NULL;
    const char *words = NULL;
  
!   store_list(set, "logs", log_list, NULL);
    ITERATE_HASH(log, words, hash_i) {
      STORAGE_SET *one_log = new_storage_set();
!     store_string(one_log, "log",      log,   NULL);
!     store_string(one_log, "keywords", words, NULL);
      storage_list_put(log_list, one_log);
    }
    deleteHashIterator(hash_i);
--- 70,80 ----
    const char *log   = NULL;
    const char *words = NULL;
  
!   store_list(set, "logs", log_list);
    ITERATE_HASH(log, words, hash_i) {
      STORAGE_SET *one_log = new_storage_set();
!     store_string(one_log, "log",      log);
!     store_string(one_log, "keywords", words);
      storage_list_put(log_list, one_log);
    }
    deleteHashIterator(hash_i);
diff -crN nakedmudv1.4/src/magic.c nakedmudv1.5/src/magic.c
*** nakedmudv1.4/src/magic.c	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/src/magic.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,632 ----
+ //*****************************************************************************
+ //
+ // magic.c
+ //
+ // A little magic system that has similarities to Richard Bartle's Spellbinder
+ // (http://www.mud.co.uk/richard/spellbnd.htm). Players chain gestures 
+ // together to make magical effects happen. The system is a little bit 
+ // different, in that players have to draw on power from different sources 
+ // (fire, water, earth, air) before they can cast spells. They can combine
+ // powers from different sources to make more elaborate powers (e.g. fire +
+ // earth = magma). Other differences exist; for instance, this magic system
+ // is realtime, whereas Bartle's is turn-based. Characters have to "spend"
+ // and "tap" magic power, whereas in Bartle's game, magic did not have a source
+ // one had to draw into, or magic power one had to spend.
+ //
+ //*****************************************************************************
+ 
+ #include "mud.h"
+ #include "utils.h"
+ #include "event.h"
+ #include "action.h"
+ #include "magic.h"
+ #include "character.h"   // send_to_char()
+ #include "inform.h"      // message()
+ 
+ 
+ 
+ //*****************************************************************************
+ //
+ // local data, structures, and functions
+ //
+ //*****************************************************************************
+ 
+ // how often do we check for mana increases and manaburn?
+ #define MAG_EVENT_DELAY      (5 SECONDS)
+ #define MAG_ACTION_DELAY      (1 SECOND)
+ #define MANABURN_MIN                  5
+ 
+ 
+ //
+ // Where all of our characters and their actions are stored
+ //
+ HASHMAP *mag_map = NULL;
+ 
+ 
+ 
+ //
+ // All of the info we need for keeping track of the magic
+ // status of a character.
+ //
+ typedef struct mag_data {
+   char *lh_actions;  // the movements we've made with our left hand
+   char *rh_actions;  // and with our right hand
+ 
+   char lh_action;    // what action are we taking this time around?
+   char rh_action;    // and in our right hand?
+ 
+   char lh_tapping;   // what magic is our left hand tapping?
+   char rh_tapping;   // what magic is our right hand tapping?
+ 
+   int mana_fire;     // how much mana have we accumulated for various elements?
+   int mana_water;    
+   int mana_earth;
+   int mana_air;
+ 
+   int barrier_fire;  // how protected are we from fire damage?
+   int barrier_water;
+   int barrier_earth;
+   int barrier_air;
+ 
+ } MAG_DATA;
+ 
+ 
+ //
+ // create a new magic entry
+ //
+ MAG_DATA *newMagic(void) {
+   MAG_DATA *magic = malloc(sizeof(MAG_DATA));
+   bzero(magic, sizeof(MAG_DATA));
+   magic->lh_actions = strdup("");
+   magic->rh_actions = strdup("");
+   magic->lh_action  = MAG_ACTION_NONE;
+   magic->rh_action  = MAG_ACTION_NONE;
+   magic->lh_tapping = MAG_ACTION_NONE;
+   magic->rh_tapping = MAG_ACTION_NONE;
+   return magic;
+ }
+ 
+ 
+ //
+ // Delete a magic entry
+ //
+ void deleteMagic(MAG_DATA *magic) {
+   if(magic->lh_actions) free(magic->lh_actions);
+   if(magic->rh_actions) free(magic->rh_actions);
+   free(magic);
+ }
+ 
+ typedef struct mag_action {
+   char      action;
+   int        delay;
+   char    *ch_mssg;
+   char *other_mssg;
+ } MAG_ACTION;
+ 
+ 
+ MAG_ACTION mag_actions[] = {
+   { MAG_ACTION_PUSH,   1 SECOND,
+     "You thrust your %s palm out in front of you",
+     "$n thrusts $s %s palm outwards" },
+   { MAG_ACTION_ARC,    1 SECOND,
+     "You raise your %s hand up in a large arc",
+     "$n arcs $s %s high above $s head" },
+   { MAG_ACTION_LOWER,  1 SECOND,
+     "You lower your %s hand",
+     "$n lowers $s hand" },
+   { MAG_ACTION_WIGGLE, 1 SECOND,
+     "You wiggle the fingers on your %s hand",
+     "$n begins wiggling the fingers on $s %s hand" },
+   { MAG_ACTION_SNAP,   1 SECOND,
+     "You snap the thumb and forefinger on your %s hand",
+     "$n snaps the thumb and forefinger on $s %s hand" },
+   { MAG_ACTION_PALM,   1 SECOND,
+     "You slowly begin rising your %s hand, palm upwards",
+     "$n slowly begins rising $s %s palm upwards" },
+   { MAG_ACTION_FINGER, 1 SECOND,
+     "You thrust the finger on your %s hand outwards",
+     "$n thrusts the finger on $s %s hand outwards" },
+ 
+ 
+   { MAG_ACTION_NONE, 0 SECONDS, "", "" } // sentinel
+ };
+ 
+ 
+ typedef struct mag_effect {
+   int   effect;          // what effect does it do?
+   int   cost;            // what's the cost in mana?
+   char *hand_movement;   // what is the hand movement?
+ } MAG_EFFECT;
+ 
+ 
+ MAG_EFFECT mag_effects_fire[] = {
+   { MAG_EFFECT_FIREBOLT,    2,           "sf" }, // snap, finger (point)
+   { MAG_EFFECT_NONE,        0,           NULL }  // sentinel
+ };
+ 
+ MAG_EFFECT mag_effects_water[] = {
+   { MAG_EFFECT_ACIDBOLT,    2,           "sf" }, // snap, finger (point)
+   { MAG_EFFECT_NONE,        0,           NULL }  // sentinel
+ };
+ 
+ MAG_EFFECT mag_effects_earth[] = {
+   { MAG_EFFECT_STONESPEAR,  2,           "sf" }, // snap, finger (point)
+   { MAG_EFFECT_NONE,        0,           NULL }  // sentinel
+ };
+ 
+ MAG_EFFECT mag_effects_air[] = {
+   { MAG_EFFECT_SHOCK,       2,           "sf" }, // snap, finger (point)
+   { MAG_EFFECT_NONE,        0,           NULL }  // sentinel
+ };
+ 
+ 
+ 
+ //
+ // get the magic table associated with the mana that has been tapped
+ //
+ MAG_EFFECT *get_mag_table(MAG_DATA *magic) {
+   if(magic->mana_fire > 0 && 
+      magic->mana_water == 0 && magic->mana_earth == 0 && magic->mana_air == 0)
+     return mag_effects_fire;
+   if(magic->mana_water > 0 && 
+      magic->mana_fire == 0 && magic->mana_earth == 0 && magic->mana_air == 0)
+     return mag_effects_water;
+   if(magic->mana_earth > 0 && 
+      magic->mana_water == 0 && magic->mana_fire == 0 && magic->mana_air == 0)
+     return mag_effects_earth;
+   if(magic->mana_air > 0 && 
+      magic->mana_water == 0 && magic->mana_earth == 0 && magic->mana_fire == 0)
+     return mag_effects_air;
+ 
+   return NULL;
+ }
+ 
+ 
+ //
+ // look in the table to see if we've completed any of the actions it has
+ //
+ int check_for_mag_effect(const MAG_EFFECT *mag_effects, 
+ 			 const char *actions) {
+   int i;
+   int act_len = strlen(actions);
+ 
+   // go through our list of effects, and search
+   for(i = 0; mag_effects[i].effect != MAG_EFFECT_NONE; i++) {
+     int move_len = strlen(mag_effects[i].hand_movement);
+ 
+     // make sure we've performed enough actions
+     if(act_len < move_len)
+       continue;
+ 
+     // go in reverse for both of them
+     int j;
+     char *movement = mag_effects[i].hand_movement;
+     for(j = move_len-1; j >= 0; j--)
+       if(movement[j] != actions[act_len-move_len+j])
+ 	break;
+ 
+     // if we got right to the end, we found a match
+     if(j == -1)
+       break;
+   }
+ 
+   return i;
+ }
+ 
+ const char *mag_hand_name(char hand) {
+   return (hand == MAG_HAND_LEFT ? "left" :
+ 	  (hand == MAG_HAND_RIGHT ? "right" : "BUG"));
+ }
+ 
+ const char *mag_tap_name(char tap_type) {
+   return (tap_type == MAG_ACTION_TAP_FIRE ? "fire" :
+ 	  (tap_type == MAG_ACTION_TAP_WATER ? "water" :
+ 	   (tap_type == MAG_ACTION_TAP_EARTH ? "earth" :
+ 	    (tap_type == MAG_ACTION_TAP_AIR ? "air" : "BUG"))));
+ }
+ 
+ const char *mag_tap_color(char tap_type) {
+   return (tap_type == MAG_ACTION_TAP_FIRE ? "red" :
+ 	  (tap_type == MAG_ACTION_TAP_WATER ? "blue" :
+ 	   (tap_type == MAG_ACTION_TAP_EARTH ? "brown" :
+ 	    (tap_type == MAG_ACTION_TAP_AIR ? "white" : "BUG"))));
+ }
+ 
+ 
+ void do_mag_effect(CHAR_DATA *ch, CHAR_DATA *vict, int effect) {
+   switch(effect) {
+   case MAG_EFFECT_FIREBOLT:
+   case MAG_EFFECT_ACIDBOLT:
+   case MAG_EFFECT_STONESPEAR:
+   case MAG_EFFECT_SHOCK:
+     send_to_char(ch, "You cast a basic spell at %s!\r\n", 
+ 		 (vict ? charGetName(vict) : "nobody"));
+     break;
+ 
+     // nothing
+   default: 
+     break;
+   }
+ }
+ 
+ 
+ //
+ // Inform the character (and room) that the character has lost his
+ // connection to a mana source
+ //
+ void magic_stop_message(CHAR_DATA *ch, char tap_type) {
+   send_to_char(ch, "Your connection with the plane of %s is cut short.\r\n",
+ 	       mag_tap_name(tap_type));
+   message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR, 
+ 	  "The %s aura around $n's body wanes.", mag_tap_color(tap_type));
+ }
+ 
+ 
+ //
+ // Inform the character (and room) that the character has begun tapping mana
+ //
+ void tap_start_message(CHAR_DATA *ch, char hand, char tap_type) {
+   send_to_char(ch, 
+ 	       "You begin tapping into the plane of %s with your %s hand.\r\n",
+ 	       mag_tap_name(tap_type), mag_hand_name(hand));
+   message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
+ 	  "$n upraises $s %s palm, and it becomes shrouded in a %s aura.",
+ 	  mag_hand_name(hand), mag_tap_color(tap_type));
+ }
+ 
+ 
+ //
+ // Inform the character (and room) that the character has begun tapping mana
+ //
+ void tap_stop_message(CHAR_DATA *ch, char hand, char tap_type) {
+   send_to_char(ch, 
+ 	       "You stop tapping into the plane of %s with your %s hand.\r\n",
+ 	       mag_tap_name(tap_type), mag_hand_name(hand));
+   message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
+ 	  "$n lowers $s %s palm, and the %s aura around it dims slightly.",
+ 	  mag_hand_name(hand), mag_tap_color(tap_type));
+ }
+ 
+ 
+ //
+ // return true if the action is mana-tapping-oriented
+ //
+ bool mag_action_is_tap(char action) {
+   return (action == MAG_ACTION_TAP_FIRE  || action == MAG_ACTION_TAP_AIR   ||
+ 	  action == MAG_ACTION_TAP_WATER || action == MAG_ACTION_TAP_EARTH);
+ }
+ 
+ 
+ //
+ // Set a character to start tapping in one hand
+ //
+ void start_tapping(CHAR_DATA *ch, MAG_DATA *magic, char hand, char action) {
+   if(hand == MAG_HAND_LEFT) {
+     magic->lh_tapping = action;
+     tap_start_message(ch, hand, action);
+   }
+   else if(hand == MAG_HAND_RIGHT) {
+     magic->rh_tapping = action;
+     tap_start_message(ch, hand, action);
+   }
+ }
+ 
+ 
+ //
+ // Stop a character tapping in one hand
+ //
+ void stop_tapping(CHAR_DATA *ch, MAG_DATA *magic, char hand) {
+   if(hand == MAG_HAND_LEFT) {
+     tap_stop_message(ch, hand, magic->lh_tapping);
+     magic->lh_tapping = MAG_ACTION_NONE;
+   }
+   else if(hand == MAG_HAND_RIGHT) {
+     tap_stop_message(ch, hand, magic->rh_tapping);
+     magic->rh_tapping = MAG_ACTION_NONE;
+   }
+ }
+ 
+ 
+ //
+ // Show the message that accompanies a hand gesture
+ //
+ void show_mag_action_message(CHAR_DATA *ch, char hand, char action) {
+   int i;
+   for(i = 0; mag_actions[i].action != MAG_ACTION_NONE; i++) {
+     if(action == mag_actions[i].action) {
+       message(ch, NULL, NULL, NULL, TRUE, TO_CHAR,
+ 	      mag_actions[i].ch_mssg, mag_hand_name(hand));
+       message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
+ 	      mag_actions[i].other_mssg, mag_hand_name(hand));
+       break;
+     }
+   }
+ }
+ 
+ 
+ 
+ //*****************************************************************************
+ //
+ // implementation of magic.h
+ //
+ //*****************************************************************************
+ 
+ void init_magic() {
+   // use standard hashing function and comparator
+   mag_map = newHashmap(NULL, NULL, 50);
+ }
+ 
+ 
+ //
+ // Check if the magic is involved in an event. Basically, straight comparison
+ //
+ int check_mag_event_involvement(void *thing, MAG_DATA *magic) {
+   return (thing == magic);
+ }
+ 
+ 
+ //
+ // Handle the completion of a magic action, and let everyone know
+ //
+ void handle_mag_action(CHAR_DATA *ch, MAG_DATA *magic, 
+ 		       bitvector_t where, char *arg) {
+   // do something about seeing if we're tapping mana
+   if(mag_action_is_tap(magic->lh_action)) {
+     start_tapping(ch, magic, MAG_HAND_LEFT, magic->lh_action);
+     // now, free our history ... nothing starts with a tap
+     free(magic->lh_actions); magic->lh_actions = strdup("");
+   }
+   if(mag_action_is_tap(magic->rh_action)) {
+     start_tapping(ch, magic, MAG_HAND_RIGHT, magic->rh_action);
+     // now, free our history ... nothing starts with a tap
+     free(magic->rh_actions); magic->rh_actions = strdup("");
+   }
+ 
+   if(magic->lh_action != MAG_ACTION_NONE)
+     show_mag_action_message(ch, MAG_HAND_LEFT,  magic->lh_action);
+   if(magic->rh_action != MAG_ACTION_NONE)
+     show_mag_action_message(ch, MAG_HAND_RIGHT, magic->rh_action);
+ 
+   // based on the mana we've accumulated, figure out what table to use
+   MAG_EFFECT *table = get_mag_table(magic);
+ 
+   // now, see if we've created any magical effects
+   if(table && magic->lh_action != MAG_ACTION_NONE) {
+     int entry = check_for_mag_effect(table, magic->lh_actions);
+     do_mag_effect(ch, NULL, table[entry].effect);
+   }
+   if(table && magic->rh_action != MAG_ACTION_NONE) {
+     int entry = check_for_mag_effect(table, magic->rh_actions);
+     do_mag_effect(ch, NULL, table[entry].effect);
+   }
+ 
+   magic->lh_action = MAG_ACTION_NONE;
+   magic->rh_action = MAG_ACTION_NONE;
+ }
+ 
+ 
+ //
+ // Stop the action prematurely
+ //
+ void interrupt_mag_action(CHAR_DATA *ch, MAG_DATA *magic, 
+ 			  bitvector_t where, char *arg) {
+   if(magic->lh_action != MAG_ACTION_NONE) {
+     send_to_char(ch, "You stop performing your left hand action.\r\n");
+     magic->lh_action = MAG_ACTION_NONE;
+   }
+ 
+   if(magic->rh_action != MAG_ACTION_NONE) {
+     send_to_char(ch, "You stop performing your right hand action.\r\n");
+     magic->rh_action = MAG_ACTION_NONE;
+   }
+ }
+ 
+ 
+ //
+ // Update the magic status (increasing mana, giving manaburn, etc...) and
+ // throw it back into the event handler
+ //
+ void handle_mag_event(CHAR_DATA *ch, MAG_DATA *magic, const char *arg) {
+   // up our mana by 2 and decrease our mana reserves by 1
+   // essentially, this results in +1 mana when we are actively tapping
+   // a manasource (+3 if we are tapping with both hands) and -1 if we
+   // are not tapping.
+   magic->mana_fire  += 2*((magic->lh_tapping == MAG_ACTION_TAP_FIRE) + 
+ 			  (magic->rh_tapping == MAG_ACTION_TAP_FIRE));
+   magic->mana_water += 2*((magic->lh_tapping == MAG_ACTION_TAP_WATER) +
+ 			  (magic->rh_tapping == MAG_ACTION_TAP_WATER));
+   magic->mana_earth += 2*((magic->lh_tapping == MAG_ACTION_TAP_EARTH) +
+ 			  (magic->rh_tapping == MAG_ACTION_TAP_EARTH));
+   magic->mana_air   += 2*((magic->lh_tapping == MAG_ACTION_TAP_AIR) +
+ 			  (magic->rh_tapping == MAG_ACTION_TAP_AIR));
+ 
+   if(magic->mana_fire > 0) {
+     magic->mana_fire--;
+     if(magic->mana_fire == 0)
+       magic_stop_message(ch, MAG_ACTION_TAP_FIRE);
+   }
+ 
+   if(magic->mana_water > 0) {
+     magic->mana_water--;
+     if(magic->mana_water == 0)
+       magic_stop_message(ch, MAG_ACTION_TAP_WATER);
+   }
+ 
+   if(magic->mana_earth > 0) {
+     magic->mana_earth--;
+     if(magic->mana_water == 0)
+       magic_stop_message(ch, MAG_ACTION_TAP_EARTH);
+   }
+ 
+   if(magic->mana_air > 0) {
+     magic->mana_air--;
+     if(magic->mana_air == 0)
+       magic_stop_message(ch, MAG_ACTION_TAP_AIR);
+   }
+ 
+ 
+   // send increase messages
+   if(magic->lh_tapping == MAG_ACTION_TAP_FIRE || magic->rh_tapping == MAG_ACTION_TAP_FIRE)
+     send_to_char(ch, "You tap into a little bit of fire mana.\r\n");
+   if(magic->lh_tapping == MAG_ACTION_TAP_WATER || magic->rh_tapping == MAG_ACTION_TAP_WATER)
+     send_to_char(ch, "You tap into a little bit of water mana.\r\n");
+   if(magic->lh_tapping == MAG_ACTION_TAP_EARTH || magic->rh_tapping == MAG_ACTION_TAP_EARTH)
+     send_to_char(ch, "You tap into a little bit of earth mana.\r\n");
+   if(magic->lh_tapping == MAG_ACTION_TAP_AIR || magic->rh_tapping == MAG_ACTION_TAP_AIR)
+     send_to_char(ch, "You tap into a little bit of air mana.\r\n");
+ 
+ 
+   // check for manaburn -> when people accumulate too much mana
+   //***********
+   // FINISH ME
+   //***********
+ 
+ 
+   // now, put it back in the event queue
+   start_event(ch, MAG_EVENT_DELAY, 
+ 	      handle_mag_event, check_mag_event_involvement, 
+ 	      magic, NULL);
+ }
+ 
+ 
+ void interrupt_magic(CHAR_DATA *ch) {
+   // see if the character has a magic entry.
+   MAG_DATA *magic = mapGet(mag_map, ch);
+ 
+   // if he does, interrupt all actions involving this magic entry
+   if(magic) { 
+     interrupt_events_involving(magic);
+ 
+     // and let the character know
+     if(magic->mana_fire > 0)
+       magic_stop_message(ch, MAG_ACTION_TAP_FIRE);
+     if(magic->mana_water > 0)
+       magic_stop_message(ch, MAG_ACTION_TAP_WATER);
+     if(magic->mana_earth > 0)
+       magic_stop_message(ch, MAG_ACTION_TAP_EARTH);
+     if(magic->mana_air > 0)
+       magic_stop_message(ch, MAG_ACTION_TAP_AIR);
+ 
+     // and finally, delete the magic entry
+     deleteMagic(magic);
+   }
+ }
+ 
+ 
+ void do_magic_action(CHAR_DATA *ch, CHAR_DATA *vict, const char *action) {
+   char lh_action = MAG_ACTION_NONE;
+   char rh_action = MAG_ACTION_NONE;
+   bool lh_acting = FALSE; // have we made a lh/rh action this turn?
+   bool rh_acting = FALSE;
+ 
+   // first, look up our magic information
+   MAG_DATA *magic = mapGet(mag_map, ch);
+ 
+   // if one doesn't exist, create it and add it to our magic map
+   // also toss it into the event queue
+   if(magic == NULL) {
+     magic = newMagic();
+     mapPut(mag_map, ch, magic);
+     start_event(ch, MAG_EVENT_DELAY, 
+ 		handle_mag_event, check_mag_event_involvement, 
+ 		magic, NULL);
+   }
+ 
+   // parse our action and add it to the magic data
+   while(*action) {
+     bool one_action_lh = FALSE;
+     bool one_action_rh = FALSE;
+     char act           = '\0';
+ 
+     // first, parse the hand(s)
+     if(*action == MAG_HAND_LEFT || *action == MAG_HAND_BOTH)
+       one_action_lh = TRUE;
+     if(*action == MAG_HAND_RIGHT || *action == MAG_HAND_BOTH)
+       one_action_rh = TRUE;
+ 
+     // check if the character has tried two actions with one hand
+     if((one_action_lh && lh_acting) || (one_action_rh && rh_acting)) {
+       send_to_char(ch,"You can only perform one action with a hand at a time!\r\n");
+       return;
+     }
+ 
+     // we didn't parse a hand ... oops!
+     if(!one_action_lh && !one_action_rh) {
+       send_to_char(ch, "Your hands get all tied, and you fail to us your magic!\r\n");
+       return;
+     }
+     
+     action++;
+     // now parse the action
+     switch(*action) {
+     case MAG_ACTION_TAP:       act = MAG_ACTION_TAP;       break;
+     case MAG_ACTION_DISMISS:   act = MAG_ACTION_NONE;      break;
+     case MAG_ACTION_PUSH:      act = MAG_ACTION_PUSH;      break;
+     case MAG_ACTION_ARC:       act = MAG_ACTION_ARC;       break;
+     case MAG_ACTION_LOWER:     act = MAG_ACTION_LOWER;     break;
+     case MAG_ACTION_WIGGLE:    act = MAG_ACTION_WIGGLE;    break;
+     case MAG_ACTION_SNAP:      act = MAG_ACTION_SNAP;      break;
+     case MAG_ACTION_PALM:      act = MAG_ACTION_PALM;      break;
+     case MAG_ACTION_FINGER:    act = MAG_ACTION_FINGER;    break;
+     case MAG_ACTION_TAP_NONE:  act = MAG_ACTION_NONE;      break;
+     case MAG_ACTION_TAP_FIRE:  act = MAG_ACTION_TAP_FIRE;  break;
+     case MAG_ACTION_TAP_WATER: act = MAG_ACTION_TAP_WATER; break;
+     case MAG_ACTION_TAP_EARTH: act = MAG_ACTION_TAP_EARTH; break;
+     case MAG_ACTION_TAP_AIR:   act = MAG_ACTION_TAP_AIR;   break;
+     default:
+       send_to_char(ch, "You try to make a gesture, but it had no magical significance.\r\n");
+       return;
+     }
+     action++;
+ 
+     // if we're trying to tap something, figure out what action it is
+     if(act == MAG_ACTION_TAP) {
+       switch(*action) {
+       case MAG_TAP_NONE:  act = MAG_ACTION_NONE;      break;
+       case MAG_TAP_FIRE:  act = MAG_ACTION_TAP_FIRE;  break;
+       case MAG_TAP_WATER: act = MAG_ACTION_TAP_WATER; break;
+       case MAG_TAP_EARTH: act = MAG_ACTION_TAP_EARTH; break;
+       case MAG_TAP_AIR:   act = MAG_ACTION_TAP_AIR;   break;
+       default:
+ 	send_to_char(ch, "You try to tap into a magic source, but fail!\r\n");
+ 	break;
+       }
+       action++;
+     }
+ 
+     // now that we've got the action, pop it into the hand it belongs in
+     // and note what hand we used to perform the action
+     if(one_action_lh) {
+       char *ptr = magic->lh_actions;
+       magic->lh_actions = malloc(sizeof(char) * (strlen(ptr) + 1));
+       sprintf(magic->lh_actions, "%s%c", ptr, act);
+       free(ptr);
+       lh_acting = TRUE;
+       lh_action = act;
+     }
+     if(one_action_rh) {
+       char *ptr = magic->rh_actions;
+       magic->rh_actions = malloc(sizeof(char) * (strlen(ptr) + 1));
+       sprintf(magic->rh_actions, "%s%c", ptr, act);
+       free(ptr);
+       rh_acting = TRUE;
+       rh_action = act;
+     }
+   }
+ 
+   // if we're using a hand that we were tapping with, stop the tapping
+   if(lh_acting && magic->lh_tapping != MAG_ACTION_NONE)
+     stop_tapping(ch, magic, MAG_HAND_LEFT);
+   if(rh_acting && magic->rh_tapping != MAG_ACTION_NONE)
+     stop_tapping(ch, magic, MAG_HAND_RIGHT);
+ 
+   magic->lh_action = lh_action;
+   magic->rh_action = rh_action;
+ 
+   // set up an action in the action queue
+   if(lh_action != MAG_ACTION_NONE || rh_action != MAG_ACTION_NONE) {
+     send_to_char(ch, "Ok.\r\n");
+     start_action(ch, MAG_ACTION_DELAY, 1/*ACTION_MENTAL*/, handle_mag_action, 
+ 		 interrupt_mag_action, magic, NULL);
+   }
+ }
diff -crN nakedmudv1.4/src/magic.c.bk nakedmudv1.5/src/magic.c.bk
*** nakedmudv1.4/src/magic.c.bk	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/src/magic.c.bk	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,572 ----
+ //*****************************************************************************
+ //
+ // magic.c
+ //
+ // A little magic system that has similarities to Richard Bartle's Spellbinder
+ // (http://www.mud.co.uk/richard/spellbnd.htm). Players chain gestures 
+ // together to make magical effects happen. The system is a little bit 
+ // different, in that players have to draw on power from different sources 
+ // (fire, water, earth, air) before they can cast spells. They can combine
+ // powers from different sources to make more elaborate powers (e.g. fire +
+ // earth = magma). Other differences exist; for instance, this magic system
+ // is realtime, whereas Bartle's is turn-based. Characters have to "spend"
+ // and "tap" magic power, whereas in Bartle's game, magic did not have a source
+ // one had to draw into, or magic power one had to spend.
+ //
+ //*****************************************************************************
+ 
+ #include "mud.h"
+ #include "utils.h"
+ #include "event.h"
+ #include "magic.h"
+ #include "character.h"   // send_to_char()
+ #include "handler.h"     // generic_find()
+ #include "inform.h"      // message()
+ 
+ 
+ 
+ //*****************************************************************************
+ //
+ // local data, structures, and functions
+ //
+ //*****************************************************************************
+ 
+ // how often do we check for mana increases and manaburn?
+ #define MAG_EVENT_DELAY      (5 SECONDS)
+ #define MANABURN_MIN                 5
+ 
+ 
+ //
+ // Where all of our characters and their actions are stored
+ //
+ HASHMAP *mag_map = NULL;
+ 
+ 
+ 
+ //
+ // All of the info we need for keeping track of the magic
+ // status of a character.
+ //
+ typedef struct mag_data {
+   char *lh_actions;  // the movements we've made with our left hand
+   char *rh_actions;  // and with our right hand
+ 
+   char lh_tapping;   // what magic is our left hand tapping?
+   char rh_tapping;   // what magic is our right hand tapping?
+ 
+   int mana_fire;     // how much mana have we accumulated for various elements?
+   int mana_water;    
+   int mana_earth;
+   int mana_air;
+ 
+   int barrier_fire;  // how protected are we from fire damage?
+   int barrier_water;
+   int barrier_earth;
+   int barrier_air;
+ 
+ } MAG_DATA;
+ 
+ 
+ //
+ // create a new magic entry
+ //
+ MAG_DATA *newMagic(void) {
+   MAG_DATA *magic = malloc(sizeof(MAG_DATA));
+   bzero(magic, sizeof(MAG_DATA));
+   magic->lh_actions = strdup("");
+   magic->rh_actions = strdup("");
+   magic->lh_tapping = MAG_ACTION_NONE;
+   magic->rh_tapping = MAG_ACTION_NONE;
+   return magic;
+ }
+ 
+ 
+ //
+ // Delete a magic entry
+ //
+ void deleteMagic(MAG_DATA *magic) {
+   if(magic->lh_actions) free(magic->lh_actions);
+   if(magic->rh_actions) free(magic->rh_actions);
+   free(magic);
+ }
+ 
+ 
+ typedef struct mag_effect {
+   int   effect;          // what effect does it do?
+   int   cost;            // what's the cost in mana?
+   char *hand_movement;   // what is the hand movement?
+ } MAG_EFFECT;
+ 
+ 
+ MAG_EFFECT mag_effects_fire[] = {
+   { MAG_EFFECT_FIREBOLT,    2,           "sf" }, // snap, finger (point)
+   { MAG_EFFECT_NONE,        0,           NULL }  // sentinel
+ };
+ 
+ MAG_EFFECT mag_effects_water[] = {
+   { MAG_EFFECT_ACIDBOLT,    2,           "sf" }, // snap, finger (point)
+   { MAG_EFFECT_NONE,        0,           NULL }  // sentinel
+ };
+ 
+ MAG_EFFECT mag_effects_earth[] = {
+   { MAG_EFFECT_STONESPEAR,  2,           "sf" }, // snap, finger (point)
+   { MAG_EFFECT_NONE,        0,           NULL }  // sentinel
+ };
+ 
+ MAG_EFFECT mag_effects_air[] = {
+   { MAG_EFFECT_SHOCK,       2,           "sf" }, // snap, finger (point)
+   { MAG_EFFECT_NONE,        0,           NULL }  // sentinel
+ };
+ 
+ 
+ 
+ //
+ // get the magic table associated with the mana that has been tapped
+ //
+ MAG_EFFECT *get_mag_table(MAG_DATA *magic) {
+   if(magic->mana_fire > 0 && 
+      magic->mana_water == 0 && magic->mana_earth == 0 && magic->mana_air == 0)
+     return mag_effects_fire;
+   if(magic->mana_water > 0 && 
+      magic->mana_fire == 0 && magic->mana_earth == 0 && magic->mana_air == 0)
+     return mag_effects_water;
+   if(magic->mana_earth > 0 && 
+      magic->mana_water == 0 && magic->mana_fire == 0 && magic->mana_air == 0)
+     return mag_effects_earth;
+   if(magic->mana_air > 0 && 
+      magic->mana_water == 0 && magic->mana_earth == 0 && magic->mana_fire == 0)
+     return mag_effects_air;
+ 
+   return NULL;
+ }
+ 
+ 
+ //
+ // look in the table to see if we've completed any of the actions it has
+ //
+ int check_for_mag_effect(const MAG_EFFECT *mag_effects, 
+ 			 const char *actions) {
+   int i;
+   int act_len = strlen(actions);
+ 
+   // go through our list of effects, and search
+   for(i = 0; mag_effects[i].effect != MAG_EFFECT_NONE; i++) {
+     int move_len = strlen(mag_effects[i].hand_movement);
+ 
+     // make sure we've performed enough actions
+     if(act_len < move_len)
+       continue;
+ 
+     // go in reverse for both of them
+     int j;
+     char *movement = mag_effects[i].hand_movement;
+     for(j = move_len-1; j >= 0; j--)
+       if(movement[j] != actions[act_len-move_len+j])
+ 	break;
+ 
+     // if we got right to the end, we found a match
+     if(j == -1)
+       break;
+   }
+ 
+   return i;
+ }
+ 
+ const char *mag_hand_name(char hand) {
+   return (hand == MAG_HAND_LEFT ? "left" :
+ 	  (hand == MAG_HAND_RIGHT ? "right" : "BUG"));
+ }
+ 
+ const char *mag_tap_name(char tap_type) {
+   return (tap_type == MAG_ACTION_TAP_FIRE ? "fire" :
+ 	  (tap_type == MAG_ACTION_TAP_WATER ? "water" :
+ 	   (tap_type == MAG_ACTION_TAP_EARTH ? "earth" :
+ 	    (tap_type == MAG_ACTION_TAP_AIR ? "air" : "BUG"))));
+ }
+ 
+ const char *mag_tap_color(char tap_type) {
+   return (tap_type == MAG_ACTION_TAP_FIRE ? "red" :
+ 	  (tap_type == MAG_ACTION_TAP_WATER ? "blue" :
+ 	   (tap_type == MAG_ACTION_TAP_EARTH ? "brown" :
+ 	    (tap_type == MAG_ACTION_TAP_AIR ? "white" : "BUG"))));
+ }
+ 
+ 
+ 
+ //*****************************************************************************
+ //
+ // implementation of magic.h
+ //
+ //*****************************************************************************
+ 
+ void init_magic() {
+   // use standard hashing function and comparator
+   mag_map = newHashmap(NULL, NULL, 50);
+ }
+ 
+ 
+ //
+ // Check if the magic is involved in an event. Basically, straight comparison
+ //
+ int check_mag_event_involvement(void *thing, MAG_DATA *magic) {
+   return (thing == magic);
+ }
+ 
+ 
+ //
+ // Inform the character (and room) that the character has lost his
+ // connection to a mana source
+ //
+ void magic_stop_message(CHAR_DATA *ch, char tap_type) {
+   send_to_char(ch, "Your connection with the plane of %s is cut short.\r\n",
+ 	       mag_tap_name(tap_type));
+   message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR, 
+ 	  "The %s aura around $n's body wanes.", mag_tap_color(tap_type));
+ }
+ 
+ 
+ //
+ // Inform the character (and room) that the character has begun tapping mana
+ //
+ void tap_start_message(CHAR_DATA *ch, char hand, char tap_type) {
+   send_to_char(ch, 
+ 	       "You begin tapping into the plane of %s with your %s hand.\r\n",
+ 	       mag_tap_name(tap_type), mag_hand_name(hand));
+   message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
+ 	  "$n upraises $s %s palm, and it becomes shrouded in a %s aura.",
+ 	  mag_hand_name(hand), mag_tap_color(tap_type));
+ }
+ 
+ 
+ //
+ // Inform the character (and room) that the character has begun tapping mana
+ //
+ void tap_stop_message(CHAR_DATA *ch, char hand, char tap_type) {
+   send_to_char(ch, 
+ 	       "You stop tapping into the plane of %s with your %s hand.\r\n",
+ 	       mag_tap_name(tap_type), mag_hand_name(hand));
+   message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
+ 	  "$n lowers $s %s palm, and the %s aura around it dims slightly.",
+ 	  mag_hand_name(hand), mag_tap_color(tap_type));
+ }
+ 
+ 
+ //
+ // Update the magic status (increasing mana, giving manaburn, etc...) and
+ // throw it back into the event handler
+ //
+ void handle_mag_event(CHAR_DATA *ch, MAG_DATA *magic, const char *arg) {
+   // up our mana by 2 and decrease our mana reserves by 1
+   // essentially, this results in +1 mana when we are actively tapping
+   // a manasource (+3 if we are tapping with both hands) and -1 if we
+   // are not tapping.
+   magic->mana_fire  += 2*((magic->lh_tapping == MAG_ACTION_TAP_FIRE) + 
+ 			  (magic->rh_tapping == MAG_ACTION_TAP_FIRE));
+   magic->mana_water += 2*((magic->lh_tapping == MAG_ACTION_TAP_WATER) +
+ 			  (magic->rh_tapping == MAG_ACTION_TAP_WATER));
+   magic->mana_earth += 2*((magic->lh_tapping == MAG_ACTION_TAP_EARTH) +
+ 			  (magic->rh_tapping == MAG_ACTION_TAP_EARTH));
+   magic->mana_air   += 2*((magic->lh_tapping == MAG_ACTION_TAP_AIR) +
+ 			  (magic->rh_tapping == MAG_ACTION_TAP_AIR));
+ 
+   if(magic->mana_fire > 0) {
+     magic->mana_fire--;
+     if(magic->mana_fire == 0)
+       magic_stop_message(ch, MAG_ACTION_TAP_FIRE);
+   }
+ 
+   if(magic->mana_water > 0) {
+     magic->mana_water--;
+     if(magic->mana_water == 0)
+       magic_stop_message(ch, MAG_ACTION_TAP_WATER);
+   }
+ 
+   if(magic->mana_earth > 0) {
+     magic->mana_earth--;
+     if(magic->mana_water == 0)
+       magic_stop_message(ch, MAG_ACTION_TAP_EARTH);
+   }
+ 
+   if(magic->mana_air > 0) {
+     magic->mana_air--;
+     if(magic->mana_air == 0)
+       magic_stop_message(ch, MAG_ACTION_TAP_AIR);
+   }
+ 
+ 
+   // send increase messages
+   if(magic->lh_tapping == MAG_ACTION_TAP_FIRE || magic->rh_tapping == MAG_ACTION_TAP_FIRE)
+     send_to_char(ch, "You tap into a little bit of fire mana.\r\n");
+   if(magic->lh_tapping == MAG_ACTION_TAP_WATER || magic->rh_tapping == MAG_ACTION_TAP_WATER)
+     send_to_char(ch, "You tap into a little bit of water mana.\r\n");
+   if(magic->lh_tapping == MAG_ACTION_TAP_EARTH || magic->rh_tapping == MAG_ACTION_TAP_EARTH)
+     send_to_char(ch, "You tap into a little bit of earth mana.\r\n");
+   if(magic->lh_tapping == MAG_ACTION_TAP_AIR || magic->rh_tapping == MAG_ACTION_TAP_AIR)
+     send_to_char(ch, "You tap into a little bit of air mana.\r\n");
+ 
+ 
+   // check for manaburn -> when people accumulate too much mana
+   //***********
+   // FINISH ME
+   //***********
+ 
+ 
+   // now, put it back in the event queue
+   start_event(ch, MAG_EVENT_DELAY, 
+ 	      handle_mag_event, check_mag_event_involvement, 
+ 	      magic, NULL);
+ }
+ 
+ 
+ void interrupt_magic(CHAR_DATA *ch) {
+   // see if the character has a magic entry.
+   MAG_DATA *magic = mapGet(mag_map, ch);
+ 
+   // if he does, interrupt all actions involving this magic entry
+   if(magic) { 
+     interrupt_events_involving(magic);
+ 
+     // and let the character know
+     if(magic->mana_fire > 0)
+       magic_stop_message(ch, MAG_ACTION_TAP_FIRE);
+     if(magic->mana_water > 0)
+       magic_stop_message(ch, MAG_ACTION_TAP_WATER);
+     if(magic->mana_earth > 0)
+       magic_stop_message(ch, MAG_ACTION_TAP_EARTH);
+     if(magic->mana_air > 0)
+       magic_stop_message(ch, MAG_ACTION_TAP_AIR);
+ 
+     // and finally, delete the magic entry
+     deleteMagic(magic);
+   }
+ }
+ 
+ 
+ //
+ // return true if the action is mana-tapping-oriented
+ //
+ bool mag_action_is_tap(char action) {
+   return (action == MAG_ACTION_TAP_FIRE  || action == MAG_ACTION_TAP_AIR   ||
+ 	  action == MAG_ACTION_TAP_WATER || action == MAG_ACTION_TAP_EARTH);
+ }
+ 
+ 
+ //
+ // Set a character to start tapping in one hand
+ //
+ void start_tapping(CHAR_DATA *ch, MAG_DATA *magic, char hand, char action) {
+   if(hand == MAG_HAND_LEFT) {
+     magic->lh_tapping = action;
+     tap_start_message(ch, hand, action);
+   }
+   else if(hand == MAG_HAND_RIGHT) {
+     magic->rh_tapping = action;
+     tap_start_message(ch, hand, action);
+   }
+ }
+ 
+ 
+ //
+ // Stop a character tapping in one hand
+ //
+ void stop_tapping(CHAR_DATA *ch, MAG_DATA *magic, char hand) {
+   if(hand == MAG_HAND_LEFT) {
+     tap_stop_message(ch, hand, magic->lh_tapping);
+     magic->lh_tapping = MAG_ACTION_NONE;
+   }
+   else if(hand == MAG_HAND_RIGHT) {
+     tap_stop_message(ch, hand, magic->rh_tapping);
+     magic->rh_tapping = MAG_ACTION_NONE;
+   }
+ }
+ 
+ 
+ //
+ // Show the message that accompanies a hand gesture
+ //
+ void show_mag_action_message(CHAR_DATA *ch, char hand, char action) {
+   if(mag_action_is_tap(action))
+     tap_start_message(ch, hand, action);
+   else {
+ 
+   }
+ }
+ 
+ 
+ void do_mag_effect(CHAR_DATA *ch, CHAR_DATA *vict, int effect) {
+   switch(effect) {
+   case MAG_EFFECT_FIREBOLT:
+   case MAG_EFFECT_ACIDBOLT:
+   case MAG_EFFECT_STONESPEAR:
+   case MAG_EFFECT_SHOCK:
+     send_to_char(ch, "You cast a basic spell at %s!\r\n", 
+ 		 (vict ? charGetName(vict) : "nobody"));
+     break;
+ 
+     // nothing
+   default: 
+     break;
+   }
+ }
+ 
+ 
+ void do_magic_action(CHAR_DATA *ch, CHAR_DATA *vict, const char *action) {
+   char lh_action = MAG_ACTION_NONE;
+   char rh_action = MAG_ACTION_NONE;
+   bool lh_acting = FALSE; // have we made a lh/rh action this turn?
+   bool rh_acting = FALSE;
+ 
+   // first, look up our magic information
+   MAG_DATA *magic = mapGet(mag_map, ch);
+ 
+   // if one doesn't exist, create it and add it to our magic map
+   // also toss it into the event queue
+   if(magic == NULL) {
+     magic = newMagic();
+     mapPut(mag_map, ch, magic);
+     start_event(ch, MAG_EVENT_DELAY, 
+ 		handle_mag_event, check_mag_event_involvement, 
+ 		magic, NULL);
+   }
+ 
+   // parse our action and add it to the magic data
+   while(*action) {
+     bool one_action_lh = FALSE;
+     bool one_action_rh = FALSE;
+     char act           = '\0';
+ 
+     // first, parse the hand(s)
+     if(*action == MAG_HAND_LEFT || *action == MAG_HAND_BOTH)
+       one_action_lh = TRUE;
+     if(*action == MAG_HAND_RIGHT || *action == MAG_HAND_BOTH)
+       one_action_rh = TRUE;
+ 
+     // check if the character has tried two actions with one hand
+     if((one_action_lh && lh_acting) || (one_action_rh && rh_acting)) {
+       send_to_char(ch,"You can only perform one action with a hand at a time!\r\n");
+       return;
+     }
+ 
+     // we didn't parse a hand ... oops!
+     if(!one_action_lh && !one_action_rh) {
+       send_to_char(ch, "Your hands get all tied, and you fail to us your magic!\r\n");
+       return;
+     }
+     
+     action++;
+     // now parse the action
+     switch(*action) {
+     case MAG_ACTION_TAP:       act = MAG_ACTION_TAP;       break;
+     case MAG_ACTION_DISMISS:   act = MAG_ACTION_NONE;      break;
+     case MAG_ACTION_PUSH:      act = MAG_ACTION_PUSH;      break;
+     case MAG_ACTION_ARC:       act = MAG_ACTION_ARC;       break;
+     case MAG_ACTION_LOWER:     act = MAG_ACTION_LOWER;     break;
+     case MAG_ACTION_WIGGLE:    act = MAG_ACTION_WIGGLE;    break;
+     case MAG_ACTION_SNAP:      act = MAG_ACTION_SNAP;      break;
+     case MAG_ACTION_PALM:      act = MAG_ACTION_PALM;      break;
+     case MAG_ACTION_FINGER:    act = MAG_ACTION_FINGER;    break;
+     case MAG_ACTION_TAP_NONE:  act = MAG_ACTION_NONE;      break;
+     case MAG_ACTION_TAP_FIRE:  act = MAG_ACTION_TAP_FIRE;  break;
+     case MAG_ACTION_TAP_WATER: act = MAG_ACTION_TAP_WATER; break;
+     case MAG_ACTION_TAP_EARTH: act = MAG_ACTION_TAP_EARTH; break;
+     case MAG_ACTION_TAP_AIR:   act = MAG_ACTION_TAP_AIR;   break;
+     default:
+       send_to_char(ch, "You try to make a gesture, but it had no magical significance.\r\n");
+       return;
+     }
+     action++;
+ 
+     // if we're trying to tap something, figure out what action it is
+     if(act == MAG_ACTION_TAP) {
+       switch(*action) {
+       case MAG_TAP_NONE:  act = MAG_ACTION_NONE;      break;
+       case MAG_TAP_FIRE:  act = MAG_ACTION_TAP_FIRE;  break;
+       case MAG_TAP_WATER: act = MAG_ACTION_TAP_WATER; break;
+       case MAG_TAP_EARTH: act = MAG_ACTION_TAP_EARTH; break;
+       case MAG_TAP_AIR:   act = MAG_ACTION_TAP_AIR;   break;
+       default:
+ 	send_to_char(ch, "You try to tap into a magic source, but fail!\r\n");
+ 	break;
+       }
+       action++;
+     }
+ 
+     // now that we've got the action, pop it into the hand it belongs in
+     // and note what hand we used to perform the action
+     if(one_action_lh) {
+       char *ptr = magic->lh_actions;
+       magic->lh_actions = malloc(sizeof(char) * (strlen(ptr) + 1));
+       sprintf(magic->lh_actions, "%s%c", ptr, act);
+       free(ptr);
+       lh_acting = TRUE;
+       lh_action = act;
+     }
+     if(one_action_rh) {
+       char *ptr = magic->rh_actions;
+       magic->rh_actions = malloc(sizeof(char) * (strlen(ptr) + 1));
+       sprintf(magic->rh_actions, "%s%c", ptr, act);
+       free(ptr);
+       rh_acting = TRUE;
+       rh_action = act;
+     }
+   }
+ 
+ 
+   // if we're using a hand that we were tapping with, stop the tapping
+   if(lh_acting && magic->lh_tapping != MAG_ACTION_NONE)
+     stop_tapping(ch, magic, MAG_HAND_LEFT);
+   if(rh_acting && magic->rh_tapping != MAG_ACTION_NONE)
+     stop_tapping(ch, magic, MAG_HAND_RIGHT);
+ 
+ 
+   // do something about seeing if we're tapping mana
+   if(lh_acting && mag_action_is_tap(lh_action)) {
+     start_tapping(ch, magic, MAG_HAND_LEFT, lh_action);
+     lh_acting = FALSE;
+     // now, free our history ... nothing starts with a tap
+     free(magic->lh_actions); magic->lh_actions = strdup("");
+   }
+   if(rh_acting && mag_action_is_tap(rh_action)) {
+     start_tapping(ch, magic, MAG_HAND_RIGHT, rh_action);
+     rh_acting = FALSE;
+     // now, free our history ... nothing starts with a tap
+     free(magic->rh_actions); magic->rh_actions = strdup("");
+   }
+ 
+   // based on the mana we've accumulated, figure out what table to use
+   MAG_EFFECT *table = get_mag_table(magic);
+ 
+   // now, see if we've created any magical effects
+   if(table && lh_acting) {
+     int entry = check_for_mag_effect(table, magic->lh_actions);
+     do_mag_effect(ch, vict, table[entry].effect);
+   }
+   if(table && rh_acting) {
+     int entry = check_for_mag_effect(table, magic->rh_actions);
+     do_mag_effect(ch, vict, table[entry].effect);
+   }
+ }
+ 
+ 
+ COMMAND(cmd_cast) {
+   char action[SMALL_BUFFER];
+ 
+   trim(arg);
+   // make sure it's not white space
+   if(!arg || !*arg) {
+     send_to_char(ch, "What were you trying to do?\r\n");
+     return;
+   }
+ 
+   // separate the action from the target
+   arg = one_arg(arg, action);
+ 
+   // look for a target if we need to
+   int found_type = FOUND_NONE;
+   CHAR_DATA *vict = NULL;
+   if(*arg)
+       vict = generic_find(ch, arg, FIND_TYPE_CHAR, 
+ 			  FIND_SCOPE_ROOM | FIND_SCOPE_VISIBLE,
+ 			  FALSE, &found_type);
+   do_magic_action(ch, vict, action);
+ }
diff -crN nakedmudv1.4/src/magic.h nakedmudv1.5/src/magic.h
*** nakedmudv1.4/src/magic.h	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/src/magic.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,102 ----
+ #ifndef __MAGIC_H
+ #define __MAGIC_H
+ //*****************************************************************************
+ //
+ // magic.h
+ //
+ // A little magic system that has similarities to Richard Bartle's Spellbinder
+ // (http://www.mud.co.uk/richard/spellbnd.htm). Players chain gestures 
+ // together to make magical effects happen. The system is a little bit 
+ // different, in that players have to draw on power from different sources 
+ // (fire, water, earth, air) before they can cast spells. They can combine
+ // powers from different sources to make more elaborate powers (e.g. fire +
+ // earth = magma). Other differences exist; for instance, this magic system
+ // is realtime, whereas Bartle's is turn-based. Characters have to "spend"
+ // and "tap" magic power, whereas in Bartle's game, magic did not have a source
+ // one had to draw into, or magic power one had to spend.
+ //
+ //*****************************************************************************
+ 
+ #define MAG_ACTION_NONE       '\0' // used to signify that no action is taken
+ 
+ #define MAG_HAND_LEFT         'l'  // perform action with left hand
+ #define MAG_HAND_RIGHT        'r'  // perform action with right hand
+ #define MAG_HAND_BOTH         'b'  // perform action with both hands
+ #define MAG_HAND_CLAP         'c'  // special marker - clap hands together
+ 
+ #define MAG_ACTION_TAP        't'  // tap into a specified energy source
+ #define MAG_ACTION_TAP_NONE   'N'  // tap nothing (dismiss)
+ #define MAG_ACTION_TAP_FIRE   'F'  // tap fire
+ #define MAG_ACTION_TAP_WATER  'W'  // tap water
+ #define MAG_ACTION_TAP_EARTH  'E'  // tap earth
+ #define MAG_ACTION_TAP_AIR    'A'  // tap air
+ 
+ #define MAG_ACTION_DISMISS    'd'  // dismiss the magic being tapped in hand
+ #define MAG_ACTION_PUSH       'p'  // push hand outward
+ #define MAG_ACTION_ARC        'a'  // raise hand upwards
+ #define MAG_ACTION_LOWER      'l'  // lower hand downwards
+ #define MAG_ACTION_WIGGLE     'w'  // wiggle fingers
+ #define MAG_ACTION_SNAP       's'  // snap fingers
+ #define MAG_ACTION_PALM       'u'  // upraised palm
+ #define MAG_ACTION_FINGER     'f'  // pointed finger
+ 
+ #define MAG_TAP_NONE          'n'
+ #define MAG_TAP_FIRE          'f'  
+ #define MAG_TAP_WATER         'w'
+ #define MAG_TAP_EARTH         'e'  
+ #define MAG_TAP_AIR           'a'
+ 
+ 
+ //      EFFECT                                 HAND MOVEMENT      WHEN TAPPING
+ #define MAG_EFFECT_NONE               (-1)
+ #define MAG_EFFECT_FIREBOLT             0   // s-f                fire
+ #define MAG_EFFECT_ACIDBOLT             1   // s-f                water
+ #define MAG_EFFECT_STONESPEAR           2   // s-f                earth
+ #define MAG_EFFECT_SHOCK                3   // s-f                air
+ 
+ 
+ //
+ // initialize the magic system
+ //
+ void init_magic();
+ 
+ 
+ //
+ // Interrupt the character's magic info
+ //
+ void interrupt_magic(CHAR_DATA *ch);
+ 
+ 
+ //
+ // perform an action. If an effect results, then return which effect it is.
+ // Actions have a syntax to them which must be followed. It goes:
+ //   hand, action, element (if the action is to tap).
+ //
+ // More than one action can be performed at a time, if they were done on
+ // separate hands.
+ //
+ // Here are some example, valid actions:
+ //   lw                           wiggle left fingers
+ //   rtf                          tap into fire with the right hand
+ //   ba                           arc both hands upwards
+ //   lara                         arc both hands upwards
+ //   ltwru                        tap water with left hand, raise right palm up
+ //   ltwrd                        tap water w/ left hand, dismiss magic in right
+ //   ltwrtn                       same as above
+ //
+ //int do_magic_action(CHAR_DATA *ch, const char *action);
+ 
+ 
+ 
+ //
+ // Make the character perform the specified action on the victim
+ //
+ //void do_mag_effect(CHAR_DATA *ch, CHAR_DATA *vict, int effect);
+ 
+ 
+ //
+ // The entrypoint into the magic system
+ //
+ COMMAND(cmd_cast);
+ 
+ #endif // __MAGIC_H
diff -crN nakedmudv1.4/src/main.mk nakedmudv1.5/src/main.mk
*** nakedmudv1.4/src/main.mk	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/main.mk	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,13 ****
- SRC    += gameloop.c mud.c utils.c interpret.c handler.c inform.c movement.c \
- 	  action.c mccp.c save.c socket.c io.c strings.c event.c \
- 	  \
- 	  cmd_comm.c cmd_manip.c cmd_misc.c \
- 	  \
- 	  text_editor.c builder.c admin.c \
- 	  \
- 	  items.c races.c log.c help.c auxiliary.c \
- 	  \
- 	  world.c character.c room.c exit.c extra_descs.c object.c body.c \
- 	  zone.c dialog.c room_reset.c \
- 	  \
- 	  list.c property_table.c hashtable.c hashmap.c storage.c
--- 0 ----
diff -crN nakedmudv1.4/src/Makefile nakedmudv1.5/src/Makefile
*** nakedmudv1.4/src/Makefile	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/Makefile	2010-11-01 15:54:17.000000000 -0500
***************
*** 14,20 ****
  CC = gcc
  
  # the modules we have installed
! MODULES := time alias char_vars socials olc scripts
  
  # flags to use during compilation
  C_FLAGS := -Wall -g -ggdb -O2
--- 14,20 ----
  CC = gcc
  
  # the modules we have installed
! MODULES := time alias char_vars socials olc scripts help
  
  # flags to use during compilation
  C_FLAGS := -Wall -g -ggdb -O2
***************
*** 26,41 ****
  SRC     := gameloop.c mud.c utils.c interpret.c handler.c inform.c movement.c \
  	   action.c mccp.c save.c socket.c io.c strings.c event.c \
  	   \
! 	   cmd_comm.c cmd_manip.c cmd_misc.c \
  	   \
! 	   text_editor.c builder.c admin.c help.c \
  	   \
! 	   items.c races.c log.c auxiliary.c \
  	   \
  	   world.c character.c room.c exit.c extra_descs.c object.c body.c \
  	   zone.c dialog.c room_reset.c \
  	   \
! 	   list.c property_table.c hashtable.c hashmap.c storage.c
  
  
  # include the description for each module. These will add to SRC
--- 26,41 ----
  SRC     := gameloop.c mud.c utils.c interpret.c handler.c inform.c movement.c \
  	   action.c mccp.c save.c socket.c io.c strings.c event.c \
  	   \
! 	   cmd_comm.c cmd_manip.c cmd_misc.c cmd_admin.c cmd_builder.c \
  	   \
! 	   text_editor.c races.c \
  	   \
! 	   items.c log.c auxiliary.c \
  	   \
  	   world.c character.c room.c exit.c extra_descs.c object.c body.c \
  	   zone.c dialog.c room_reset.c \
  	   \
! 	   list.c property_table.c hashtable.c hashmap.c storage.c set.c
  
  
  # include the description for each module. These will add to SRC
diff -crN nakedmudv1.4/src/module.mk nakedmudv1.5/src/module.mk
*** nakedmudv1.4/src/module.mk	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/src/module.mk	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1 ----
+ SRC += races/races.c
diff -crN nakedmudv1.4/src/movement.c nakedmudv1.5/src/movement.c
*** nakedmudv1.4/src/movement.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/movement.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 9,20 ****
  #include "mud.h"
  #include "character.h"
  #include "world.h"
  #include "room.h"
  #include "exit.h"
  #include "movement.h"
  #include "handler.h"
  #include "inform.h"
- #include "builder.h"
  #include "utils.h"
  #include "items.h"
  #include "object.h"
--- 9,20 ----
  #include "mud.h"
  #include "character.h"
  #include "world.h"
+ #include "zone.h"
  #include "room.h"
  #include "exit.h"
  #include "movement.h"
  #include "handler.h"
  #include "inform.h"
  #include "utils.h"
  #include "items.h"
  #include "object.h"
***************
*** 36,42 ****
  		 exitGetName(exit));
    else {
      if(*exitGetSpecLeave(exit))
!       message(ch, NULL, NULL, NULL, FALSE, TO_ROOM | TO_NOTCHAR,
  	      exitGetSpecLeave(exit));
      else if(dir != DIR_NONE)
        send_around_char(ch, TRUE, "%s leaves %s.\r\n",
--- 36,42 ----
  		 exitGetName(exit));
    else {
      if(*exitGetSpecLeave(exit))
!       message(ch, NULL, NULL, NULL, TRUE, TO_ROOM | TO_NOTCHAR,
  	      exitGetSpecLeave(exit));
      else if(dir != DIR_NONE)
        send_around_char(ch, TRUE, "%s leaves %s.\r\n",
***************
*** 63,68 ****
--- 63,110 ----
  }
  
  
+ bool try_buildwalk(CHAR_DATA *ch, int dir) {
+   ZONE_DATA *zone = worldZoneBounding(gameworld, roomGetVnum(charGetRoom(ch)));
+   
+   if(!canEditZone(zone, ch))
+     send_to_char(ch, "You are not authorized to edit this zone.\r\n");
+   else if(roomGetExit(charGetRoom(ch), dir))
+     send_to_char(ch, "You try to buildwalk %s, but a room already exists in that direction!\r\n", dirGetName(dir));
+   else if(!zone) {
+     send_to_char(ch, "The room you are in is not attached to a zone!\r\n");
+     log_string("ERROR: %s tried to buildwalk %s, but room %d was not in a zone!", charGetName(ch), dirGetName(dir), roomGetVnum(charGetRoom(ch)));
+   }
+   else {
+     room_vnum vnum = getFreeRoomVnum(zone);
+     if(vnum == NOWHERE)
+       send_to_char(ch, 
+ 		   "Zone #%d has no free rooms left. "
+ 		   "Buildwalk could not be performed.\r\n", zoneGetVnum(zone));
+     else {
+       char desc[MAX_BUFFER];
+       ROOM_DATA *new_room = newRoom();
+       roomSetVnum(new_room, vnum);
+ 
+       roomSetName(new_room, "A New Buildwalk Room");
+       sprintf(desc, "This room was created by %s.\r\n", charGetName(ch));
+       roomSetDesc(new_room, desc);
+ 
+       zoneAddRoom(zone, new_room);
+       roomDigExit(charGetRoom(ch), dir, vnum);
+       roomDigExit(new_room, dirGetOpposite(dir), 
+ 		  roomGetVnum(charGetRoom(ch)));
+       try_move(ch, dir, NULL);
+       return TRUE;
+ 
+       // save the changes... this will get costly as our world gets bigger.
+       // But that should be alright once we make zone saving a bit smarter
+       worldSave(gameworld, WORLD_PATH);
+     }
+   }
+   return FALSE;
+ }
+ 
+ 
  bool try_move(CHAR_DATA *ch, int dir, const char *specdir) {
    EXIT_DATA *exit = NULL;
    if(dir != DIR_NONE)      
***************
*** 84,92 ****
      ROOM_DATA *old_room = charGetRoom(ch);
      bool success = try_exit(ch, exit, dir);
      if(success) {
!       try_exit_script(ch, old_room, exit, 
  		      (dir != DIR_NONE ? dirGetName(dir) : specdir));
!       try_enterance_script(ch, charGetRoom(ch), exit, 
  			   (dir != DIR_NONE ? dirGetName(dir) : specdir));
      }
      return success;
--- 126,134 ----
      ROOM_DATA *old_room = charGetRoom(ch);
      bool success = try_exit(ch, exit, dir);
      if(success) {
!       try_exit_script(ch, old_room, 
  		      (dir != DIR_NONE ? dirGetName(dir) : specdir));
!       try_enterance_script(ch, charGetRoom(ch),
  			   (dir != DIR_NONE ? dirGetName(dir) : specdir));
      }
      return success;
diff -crN nakedmudv1.4/src/movement.h nakedmudv1.5/src/movement.h
*** nakedmudv1.4/src/movement.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/movement.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 28,32 ****
--- 28,37 ----
  //
  bool try_exit(CHAR_DATA *ch, EXIT_DATA *exit, int dir);
  
+ //
+ // Try creating a new room in the specified direction, drawn from the
+ // zone we're currently in.
+ //
+ bool try_buildwalk(CHAR_DATA *ch, int dir);
  
  #endif // __MOVEMENT_H
diff -crN nakedmudv1.4/src/mud.c nakedmudv1.5/src/mud.c
*** nakedmudv1.4/src/mud.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/mud.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 24,30 ****
  
  void save_mud_settings() {
    STORAGE_SET *set = storage_read(MUD_DATA);
!   store_int(set, "puid", top_char_uid, NULL);
    storage_write(set, MUD_DATA);
    storage_close(set);
  }
--- 24,30 ----
  
  void save_mud_settings() {
    STORAGE_SET *set = storage_read(MUD_DATA);
!   store_int(set, "puid", top_char_uid);
    storage_write(set, MUD_DATA);
    storage_close(set);
  }
diff -crN nakedmudv1.4/src/mud.h nakedmudv1.5/src/mud.h
*** nakedmudv1.4/src/mud.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/mud.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 27,42 ****
  #define MODULE_ALIAS
  #define MODULE_CHAR_VARS
  #define MODULE_SOCIALS
! 
! 
! //
! // Two modules that I am working on... together, they work similar to KaVir's
! // Gladiator Pits. Expect to see them for download in the near future.
! //   - Geoff Hollis, Dec26/04
! //
! //#define MODULE_FACULTY
! //#define MODULE_COMBAT
! //
  
  
  
--- 27,33 ----
  #define MODULE_ALIAS
  #define MODULE_CHAR_VARS
  #define MODULE_SOCIALS
! #define MODULE_HELP
  
  
  
***************
*** 49,55 ****
  //*****************************************************************************
  typedef struct socket_data                SOCKET_DATA;
  typedef struct char_data                  CHAR_DATA;  
- typedef struct help_data                  HELP_DATA;
  typedef struct lookup_data                LOOKUP_DATA;
  typedef struct list                       LIST;
  typedef struct list_iterator              LIST_ITERATOR;
--- 40,45 ----
***************
*** 57,62 ****
--- 47,54 ----
  typedef struct hashtable_iterator         HASH_ITERATOR;
  typedef struct hashmap                    HASHMAP;
  typedef struct map_iterator               MAP_ITERATOR;
+ typedef struct set_data                   SET;
+ typedef struct set_iterator               SET_ITERATOR;
  typedef struct datatable                  DATATABLE;
  typedef struct storage_set                STORAGE_SET;
  typedef struct storage_set_list           STORAGE_SET_LIST;
***************
*** 108,113 ****
--- 100,106 ----
  #include "list.h"
  #include "hashmap.h"
  #include "hashtable.h"
+ #include "set.h"
  
  
  
***************
*** 136,142 ****
  #define MAX_INPUT_LEN       512                   /* max length of a string someone can input */
  #define SMALL_BUFFER       1024
  #define MAX_BUFFER         8192                   /* seems like a decent amount         */
- #define MAX_HELP_ENTRY     (MAX_BUFFER)
  #define MAX_SCRIPT         16384                  /* max length of a script */
  #define MAX_OUTPUT         8192                   /* well shoot me if it isn't enough   */
  #define FILE_TERMINATOR    "EOF"                  /* end of file marker                 */
--- 129,134 ----
***************
*** 183,192 ****
  #define COMM_LOG              10  /* admins only                     */
  
  
- /* cmd_tog_prf */
- #define SUBCMD_BUILDWALK       0
- 
- 
  #define NOWHERE        (-1)
  #define NOTHING        (-1)
  #define NOBODY         (-1)
--- 175,180 ----
***************
*** 211,224 ****
   ******************************/
  
  /* the actual structures */
- struct help_data
- {
-   HELP_DATA     * next;
-   time_t          load_time;
-   char          * keyword;
-   char          * text;
- };
- 
  struct lookup_data
  {
    SOCKET_DATA       * dsock;   /* the socket we wish to do a hostlookup on */
--- 199,204 ----
***************
*** 264,275 ****
  extern  LIST           *mobile_list;
  extern  PROPERTY_TABLE *mob_table;      /* same contents as mobile_list, but
  					   arranged by uid (unique ID)        */
- extern  HELP_DATA   *   help_list;      /* the linked list of help files      */
  extern  const struct    typCmd tabCmd[];/* the command table                  */
  extern  bool            shut_down;      /* used for shutdown                  */
  extern  int             mudport;        /* What port are we running on?       */
  extern  char        *   greeting;       /* the welcome greeting               */
! extern  char        *   motd;           /* the MOTD help file                 */
  extern  int             control;        /* boot control socket thingy         */
  extern  time_t          current_time;   /* let's cut down on calls to time()  */
  
--- 244,254 ----
  extern  LIST           *mobile_list;
  extern  PROPERTY_TABLE *mob_table;      /* same contents as mobile_list, but
  					   arranged by uid (unique ID)        */
  extern  const struct    typCmd tabCmd[];/* the command table                  */
  extern  bool            shut_down;      /* used for shutdown                  */
  extern  int             mudport;        /* What port are we running on?       */
  extern  char        *   greeting;       /* the welcome greeting               */
! extern  char        *   motd;           /* the MOTD message                   */
  extern  int             control;        /* boot control socket thingy         */
  extern  time_t          current_time;   /* let's cut down on calls to time()  */
  
***************
*** 322,330 ****
  /* io.c */
  void    log_string            ( const char *txt, ... ) __attribute__ ((format (printf, 1, 2)));
  void    bug                   ( const char *txt, ... ) __attribute__ ((format (printf, 1, 2)));
- time_t  last_modified         ( char *helpfile );
  char   *read_file             ( const char *file );
- char   *read_help_entry       ( const char *helpfile);
  char   *fread_line            ( FILE *fp );                 /* pointer        */
  char   *fread_string          ( FILE *fp );                 /* allocated data */
  char   *fread_word            ( FILE *fp );                 /* pointer        */
--- 301,307 ----
***************
*** 361,368 ****
  void  page_continue         ( SOCKET_DATA *dsock);
  void  page_back             ( SOCKET_DATA *dsock);
  
- /* help.c */
- bool check_help(CHAR_DATA *dMob, char *helpfile);
  
  /*******************************
   * End of prototype declartion *
--- 338,343 ----
diff -crN nakedmudv1.4/src/object.c nakedmudv1.5/src/object.c
*** nakedmudv1.4/src/object.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/object.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 148,173 ****
  
  STORAGE_SET *objStore(OBJ_DATA *obj) {
    STORAGE_SET *set = new_storage_set();
!   store_int   (set, "vnum",      obj->vnum,                 NULL);
!   store_int   (set, "type",      obj->type,                 NULL);
!   store_int   (set, "subtype",   obj->subtype,              NULL);
!   store_int   (set, "value 0",   objGetVal(obj, 0),         NULL);
!   store_int   (set, "value 1",   objGetVal(obj, 1),         NULL);
!   store_int   (set, "value 2",   objGetVal(obj, 2),         NULL);
!   store_int   (set, "value 3",   objGetVal(obj, 3),         NULL);
!   store_int   (set, "value 4",   objGetVal(obj, 4),         NULL);
!   store_double(set, "weight",    obj->weight,               NULL);
!   store_double(set, "capacity",  obj->capacity,             NULL);
!   store_string(set, "name",      obj->name,                 NULL);
!   store_string(set, "keywords",  obj->keywords,             NULL);
!   store_string(set, "rdesc",     obj->rdesc,                NULL);
!   store_string(set, "desc",      obj->desc,                 NULL);
!   store_string(set, "multiname", obj->multi_name,           NULL);
!   store_string(set, "multirdesc",obj->multi_rdesc,          NULL);
!   store_string(set, "bits",      write_bits(obj->bits),     NULL);
!   store_set   (set, "edescs",    edescSetStore(obj->edescs),NULL);
!   store_set   (set, "auxiliary", auxiliaryDataStore(obj->auxiliary_data), NULL);
!   store_list  (set, "contents",  gen_store_list(obj->contents, objStore), NULL);
    return set;
  }
  
--- 148,173 ----
  
  STORAGE_SET *objStore(OBJ_DATA *obj) {
    STORAGE_SET *set = new_storage_set();
!   store_int   (set, "vnum",      obj->vnum);
!   store_int   (set, "type",      obj->type);
!   store_int   (set, "subtype",   obj->subtype);
!   store_int   (set, "value 0",   objGetVal(obj, 0));
!   store_int   (set, "value 1",   objGetVal(obj, 1));
!   store_int   (set, "value 2",   objGetVal(obj, 2));
!   store_int   (set, "value 3",   objGetVal(obj, 3));
!   store_int   (set, "value 4",   objGetVal(obj, 4));
!   store_double(set, "weight",    obj->weight);
!   store_double(set, "capacity",  obj->capacity);
!   store_string(set, "name",      obj->name);
!   store_string(set, "keywords",  obj->keywords);
!   store_string(set, "rdesc",     obj->rdesc);
!   store_string(set, "desc",      obj->desc);
!   store_string(set, "multiname", obj->multi_name);
!   store_string(set, "multirdesc",obj->multi_rdesc);
!   store_string(set, "bits",      write_bits(obj->bits));
!   store_set   (set, "edescs",    edescSetStore(obj->edescs));
!   store_set   (set, "auxiliary", auxiliaryDataStore(obj->auxiliary_data));
!   store_list  (set, "contents",  gen_store_list(obj->contents, objStore));
    return set;
  }
  
diff -crN nakedmudv1.4/src/olc/medit.c nakedmudv1.5/src/olc/medit.c
*** nakedmudv1.4/src/olc/medit.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/olc/medit.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 43,50 ****
  #ifdef MODULE_SCRIPTS
  		 "{gS) Script menu\r\n"
  #endif
! 		 "{gR) Change race  {y[{c%8s{y]\r\n"
! 		 "{gD) Dialog       {y[{c%8d{y]  {w%s\r\n",
  		 charGetVnum(mob),
  		 charGetName(mob),
  		 charGetMultiName(mob),
--- 43,51 ----
  #ifdef MODULE_SCRIPTS
  		 "{gS) Script menu\r\n"
  #endif
! 		 "{gR) Change race   {y[{c%8s{y]\r\n"
! 		 "{gG) Change Gender {y[{c%8s{y]\r\n"
! 		 "{gD) Dialog        {y[{c%8d{y]  {w%s\r\n",
  		 charGetVnum(mob),
  		 charGetName(mob),
  		 charGetMultiName(mob),
***************
*** 52,58 ****
  		 charGetRdesc(mob),
  		 charGetMultiRdesc(mob),
  		 charGetDesc(mob),
! 		 raceGetName(charGetRace(mob)),
  		 charGetDialog(mob),
  		 (worldGetDialog(gameworld, charGetDialog(mob)) ?
  		  dialogGetName(worldGetDialog(gameworld, 
--- 53,60 ----
  		 charGetRdesc(mob),
  		 charGetMultiRdesc(mob),
  		 charGetDesc(mob),
! 		 charGetRace(mob),
! 		 sexGetName(charGetSex(mob)),
  		 charGetDialog(mob),
  		 (worldGetDialog(gameworld, charGetDialog(mob)) ?
  		  dialogGetName(worldGetDialog(gameworld, 
***************
*** 65,86 ****
  		 );
  }
  
! void medit_race_menu(SOCKET_DATA *sock, OLC_DATA *olc) {
    int i;
!   for(i = 0; i < NUM_RACES; i++)
!     send_to_socket(sock, "%2d) %-20s%s", 
! 		   i, raceGetName(i), (i % 3 == 2 ?"\r\n":""));
!   if(i % 3 != 0)
!     send_to_socket(sock, "\r\n");
!   send_to_socket(sock,
! 		 "\r\nPlease select a race: ");
  }
  
  void medit_main_loop(SOCKET_DATA *sock, OLC_DATA *olc, char *arg) {
    int next_substate = MEDIT_MAIN;
  
!   switch(*arg) {
!   case 'q':
    case 'Q':
      send_to_socket(sock, "Save changes (Y/N) : ");
      next_substate = MEDIT_CONFIRM_SAVE;
--- 67,87 ----
  		 );
  }
  
! void medit_sex_menu(SOCKET_DATA *sock, OLC_DATA *olc) {
    int i;
!   for(i = 0; i < NUM_SEXES; i++)
!     send_to_socket(sock, "%2d) %s\r\n", i, sexGetName(i));
! }
! 
! void medit_race_menu(SOCKET_DATA *sock, OLC_DATA *olc) {
!   send_to_socket(sock, "%s\r\n\r\n", raceGetList(FALSE));
!   send_to_socket(sock, "Please select a race: ");
  }
  
  void medit_main_loop(SOCKET_DATA *sock, OLC_DATA *olc, char *arg) {
    int next_substate = MEDIT_MAIN;
  
!   switch(toupper(*arg)) {
    case 'Q':
      send_to_socket(sock, "Save changes (Y/N) : ");
      next_substate = MEDIT_CONFIRM_SAVE;
***************
*** 119,138 ****
      next_substate = MEDIT_MAIN;
      break;
  
-   case 'r':
    case 'R':
      medit_race_menu(sock, olc);
      next_substate = MEDIT_RACE;
      break;
  
!   case 'd':
    case 'D':
      send_to_socket(sock, "Enter new dialog vnum (-1 for none) : ");
      next_substate = MEDIT_DIALOG;
      break;
  
  #ifdef MODULE_SCRIPTS
-   case 's':
    case 'S':
      olcSetNext(olc, newOLC(OLC_SSEDIT, SSEDIT_MAIN,
  			   copyScriptSet(charGetScripts((CHAR_DATA *)olcGetData(olc))), charGetName((CHAR_DATA *)olcGetData(olc))));
--- 120,141 ----
      next_substate = MEDIT_MAIN;
      break;
  
    case 'R':
      medit_race_menu(sock, olc);
      next_substate = MEDIT_RACE;
      break;
  
!   case 'G':
!     medit_sex_menu(sock, olc);
!     next_substate = MEDIT_SEX;
!     break;
! 
    case 'D':
      send_to_socket(sock, "Enter new dialog vnum (-1 for none) : ");
      next_substate = MEDIT_DIALOG;
      break;
  
  #ifdef MODULE_SCRIPTS
    case 'S':
      olcSetNext(olc, newOLC(OLC_SSEDIT, SSEDIT_MAIN,
  			   copyScriptSet(charGetScripts((CHAR_DATA *)olcGetData(olc))), charGetName((CHAR_DATA *)olcGetData(olc))));
***************
*** 208,227 ****
      break;
  
    case MEDIT_RACE: {
!     int race = RACE_NONE;
!     if(isdigit(*arg)) race = atoi(arg);
!     else              race = raceGetNum(arg);
!     if(race == RACE_NONE) {
        send_to_socket(sock, "Invalid race! Try again: ");
        next_substate = MEDIT_RACE;
      }
      else {
!       charSetRace(mob, race);
        charResetBody(mob);
      }
      break;
    }
  
    case MEDIT_DIALOG: {
      int vnum = (*arg ? atoi(arg) : NOTHING);
      DIALOG_DATA *dialog = worldGetDialog(gameworld, vnum);
--- 211,240 ----
      break;
  
    case MEDIT_RACE: {
!     if(!isRace(arg)) {
        send_to_socket(sock, "Invalid race! Try again: ");
        next_substate = MEDIT_RACE;
      }
      else {
!       charSetRace(mob, arg);
        charResetBody(mob);
      }
      break;
    }
  
+   case MEDIT_SEX: {
+     int sex = SEX_NONE;
+     if(isdigit(*arg)) sex = atoi(arg);
+     else              sex = sexGetNum(arg);
+     if(sex == SEX_NONE) {
+       send_to_socket(sock, "Invalid gender! Try again: ");
+       next_substate = MEDIT_SEX;
+     }
+     else
+       charSetSex(mob, sex);
+     break;
+   }
+ 
    case MEDIT_DIALOG: {
      int vnum = (*arg ? atoi(arg) : NOTHING);
      DIALOG_DATA *dialog = worldGetDialog(gameworld, vnum);
diff -crN nakedmudv1.4/src/olc/olc.c nakedmudv1.5/src/olc/olc.c
*** nakedmudv1.4/src/olc/olc.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/olc/olc.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 67,72 ****
--- 67,73 ----
  #endif
  
  
+ 
  struct olc_data {
    bool complete;
    bool save;
***************
*** 100,106 ****
  #endif
  #ifdef MODULE_SOCIALS
    add_cmd("socedit",    NULL, cmd_socedit,  0, POS_SITTING, POS_FLYING,
! 	  LEVEL_PLAYER,  FALSE, TRUE );
  #endif
  }
  
--- 101,107 ----
  #endif
  #ifdef MODULE_SOCIALS
    add_cmd("socedit",    NULL, cmd_socedit,  0, POS_SITTING, POS_FLYING,
! 	  LEVEL_BUILDER,  FALSE, TRUE );
  #endif
  }
  
***************
*** 322,327 ****
--- 323,329 ----
    }
  #endif
  
+ 
    case OLC_RESEDIT:
    case OLC_RESPEDIT:
    case OLC_SSEDIT:
***************
*** 796,802 ****
  
  
  COMMAND(cmd_wedit) {
! 
  }
  
  
--- 798,804 ----
  
  
  COMMAND(cmd_wedit) {
!   send_to_char(ch, "Wedit has not been completed yet.\r\n");
  }
  
  
diff -crN nakedmudv1.4/src/olc/redit.c nakedmudv1.5/src/olc/redit.c
*** nakedmudv1.4/src/olc/redit.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/olc/redit.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 96,102 ****
  
    // now special exits
    int num_spec_exits = 0;
!   char **room_names = roomGetExitNames(room, &num_spec_exits);
    for(i = 0; i < num_spec_exits; i++) {
      EXIT_DATA *exit = roomGetExitSpecial(room, room_names[i]);
      send_to_socket(sock, "   {g%-10s : {y[{c%6d{y]%s",
--- 96,102 ----
  
    // now special exits
    int num_spec_exits = 0;
!   const char **room_names = roomGetExitNames(room, &num_spec_exits);
    for(i = 0; i < num_spec_exits; i++) {
      EXIT_DATA *exit = roomGetExitSpecial(room, room_names[i]);
      send_to_socket(sock, "   {g%-10s : {y[{c%6d{y]%s",
***************
*** 110,117 ****
      send_to_socket(sock, "\r\n");
  
    // clean up our mess
-   for(i = 0; i < num_spec_exits; i++)
-     free(room_names[i]);
    free(room_names);
  }
  
--- 110,115 ----
diff -crN nakedmudv1.4/src/olc/zedit.c nakedmudv1.5/src/olc/zedit.c
*** nakedmudv1.4/src/olc/zedit.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/olc/zedit.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 42,49 ****
  void zedit_main_loop(SOCKET_DATA *sock, OLC_DATA *olc, char *arg) {
    int next_substate = ZEDIT_MAIN;
  
!   switch(*arg) {
!   case 'q':
    case 'Q':
      send_to_socket(sock, "Save changes (Y/N) : ");
      next_substate = ZEDIT_CONFIRM_SAVE;
--- 42,48 ----
  void zedit_main_loop(SOCKET_DATA *sock, OLC_DATA *olc, char *arg) {
    int next_substate = ZEDIT_MAIN;
  
!   switch(toupper(*arg)) {
    case 'Q':
      send_to_socket(sock, "Save changes (Y/N) : ");
      next_substate = ZEDIT_CONFIRM_SAVE;
diff -crN nakedmudv1.4/src/property_table.c nakedmudv1.5/src/property_table.c
*** nakedmudv1.4/src/property_table.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/property_table.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 44,49 ****
--- 44,50 ----
  // Find the bucket the key belongs to
  //
  int find_bucket(int key, int num_buckets) {
+   if(key < 0) key *= -1;
    // simple for now: just take the modulo
    return key % num_buckets;
  };
diff -crN nakedmudv1.4/src/py.out nakedmudv1.5/src/py.out
*** nakedmudv1.4/src/py.out	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/py.out	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,178 ****
- /sys/block/fd0/dev
- /sys/block/md0/dev
- /sys/block/hdc/dev
- /sys/block/hda/hda3/dev
- /sys/block/hda/hda2/dev
- /sys/block/hda/hda1/dev
- /sys/block/hda/dev
- /sys/block/ram15/dev
- /sys/block/ram14/dev
- /sys/block/ram13/dev
- /sys/block/ram12/dev
- /sys/block/ram11/dev
- /sys/block/ram10/dev
- /sys/block/ram9/dev
- /sys/block/ram8/dev
- /sys/block/ram7/dev
- /sys/block/ram6/dev
- /sys/block/ram5/dev
- /sys/block/ram4/dev
- /sys/block/ram3/dev
- /sys/block/ram2/dev
- /sys/block/ram1/dev
- /sys/block/ram0/dev
- /sys/class/sound/adsp/dev
- /sys/class/sound/audio/dev
- /sys/class/sound/dsp/dev
- /sys/class/sound/mixer/dev
- /sys/class/sound/pcmC0D0c/dev
- /sys/class/sound/pcmC0D0p/dev
- /sys/class/sound/pcmC0D1c/dev
- /sys/class/sound/timer/dev
- /sys/class/sound/controlC0/dev
- /sys/class/printer/lp0/dev
- /sys/class/drm/r128/dev
- /sys/class/netlink/tap15/dev
- /sys/class/netlink/tap14/dev
- /sys/class/netlink/tap13/dev
- /sys/class/netlink/tap12/dev
- /sys/class/netlink/tap11/dev
- /sys/class/netlink/tap10/dev
- /sys/class/netlink/tap9/dev
- /sys/class/netlink/tap8/dev
- /sys/class/netlink/tap7/dev
- /sys/class/netlink/tap6/dev
- /sys/class/netlink/tap5/dev
- /sys/class/netlink/tap4/dev
- /sys/class/netlink/tap3/dev
- /sys/class/netlink/tap2/dev
- /sys/class/netlink/tap1/dev
- /sys/class/netlink/tap0/dev
- /sys/class/netlink/dnrtmsg/dev
- /sys/class/netlink/ip6_fw/dev
- /sys/class/netlink/route6/dev
- /sys/class/netlink/arpd/dev
- /sys/class/netlink/xfrm/dev
- /sys/class/netlink/nflog/dev
- /sys/class/netlink/tcpdiag/dev
- /sys/class/netlink/fwmonitor/dev
- /sys/class/netlink/usersock/dev
- /sys/class/netlink/skip/dev
- /sys/class/netlink/route/dev
- /sys/class/vc/vcsa7/dev
- /sys/class/vc/vcs7/dev
- /sys/class/vc/vcsa6/dev
- /sys/class/vc/vcs6/dev
- /sys/class/vc/vcsa5/dev
- /sys/class/vc/vcs5/dev
- /sys/class/vc/vcsa4/dev
- /sys/class/vc/vcs4/dev
- /sys/class/vc/vcsa3/dev
- /sys/class/vc/vcs3/dev
- /sys/class/vc/vcsa2/dev
- /sys/class/vc/vcs2/dev
- /sys/class/vc/vcsa1/dev
- /sys/class/vc/vcs1/dev
- /sys/class/vc/vcsa/dev
- /sys/class/vc/vcs/dev
- /sys/class/mem/kmsg/dev
- /sys/class/mem/urandom/dev
- /sys/class/mem/random/dev
- /sys/class/mem/full/dev
- /sys/class/mem/zero/dev
- /sys/class/mem/port/dev
- /sys/class/mem/null/dev
- /sys/class/mem/kmem/dev
- /sys/class/mem/mem/dev
- /sys/class/input/event1/dev
- /sys/class/input/event0/dev
- /sys/class/input/mouse0/dev
- /sys/class/input/mice/dev
- /sys/class/misc/device-mapper/dev
- /sys/class/misc/agpgart/dev
- /sys/class/misc/rtc/dev
- /sys/class/tty/ttyS7/dev
- /sys/class/tty/ttyS6/dev
- /sys/class/tty/ttyS5/dev
- /sys/class/tty/ttyS4/dev
- /sys/class/tty/ttyS3/dev
- /sys/class/tty/ttyS2/dev
- /sys/class/tty/ttyS1/dev
- /sys/class/tty/ttyS0/dev
- /sys/class/tty/tty63/dev
- /sys/class/tty/tty62/dev
- /sys/class/tty/tty61/dev
- /sys/class/tty/tty60/dev
- /sys/class/tty/tty59/dev
- /sys/class/tty/tty58/dev
- /sys/class/tty/tty57/dev
- /sys/class/tty/tty56/dev
- /sys/class/tty/tty55/dev
- /sys/class/tty/tty54/dev
- /sys/class/tty/tty53/dev
- /sys/class/tty/tty52/dev
- /sys/class/tty/tty51/dev
- /sys/class/tty/tty50/dev
- /sys/class/tty/tty49/dev
- /sys/class/tty/tty48/dev
- /sys/class/tty/tty47/dev
- /sys/class/tty/tty46/dev
- /sys/class/tty/tty45/dev
- /sys/class/tty/tty44/dev
- /sys/class/tty/tty43/dev
- /sys/class/tty/tty42/dev
- /sys/class/tty/tty41/dev
- /sys/class/tty/tty40/dev
- /sys/class/tty/tty39/dev
- /sys/class/tty/tty38/dev
- /sys/class/tty/tty37/dev
- /sys/class/tty/tty36/dev
- /sys/class/tty/tty35/dev
- /sys/class/tty/tty34/dev
- /sys/class/tty/tty33/dev
- /sys/class/tty/tty32/dev
- /sys/class/tty/tty31/dev
- /sys/class/tty/tty30/dev
- /sys/class/tty/tty29/dev
- /sys/class/tty/tty28/dev
- /sys/class/tty/tty27/dev
- /sys/class/tty/tty26/dev
- /sys/class/tty/tty25/dev
- /sys/class/tty/tty24/dev
- /sys/class/tty/tty23/dev
- /sys/class/tty/tty22/dev
- /sys/class/tty/tty21/dev
- /sys/class/tty/tty20/dev
- /sys/class/tty/tty19/dev
- /sys/class/tty/tty18/dev
- /sys/class/tty/tty17/dev
- /sys/class/tty/tty16/dev
- /sys/class/tty/tty15/dev
- /sys/class/tty/tty14/dev
- /sys/class/tty/tty13/dev
- /sys/class/tty/tty12/dev
- /sys/class/tty/tty11/dev
- /sys/class/tty/tty10/dev
- /sys/class/tty/tty9/dev
- /sys/class/tty/tty8/dev
- /sys/class/tty/tty7/dev
- /sys/class/tty/tty6/dev
- /sys/class/tty/tty5/dev
- /sys/class/tty/tty4/dev
- /sys/class/tty/tty3/dev
- /sys/class/tty/tty2/dev
- /sys/class/tty/tty1/dev
- /sys/class/tty/tty0/dev
- /sys/class/tty/ptmx/dev
- /sys/class/tty/console/dev
- /sys/class/tty/tty/dev
- /dev
- /initrd/dev
- /proc/sys/dev
- /proc/net/dev
- /lib/modules/2.6.5-1.358/build/include/config/dev
- /lib/modules/2.6.5-1.358/build/include/config/video/dev
- /lib/modules/2.6.5-1.358/build/include/config/chr/dev
- /lib/modules/2.6.5-1.358/build/include/config/blk/dev
- /usr/X11R6/lib/X11/xkb/symbols/dev
- /usr/X11R6/lib/X11/xkb/symbols/pc/dev
--- 0 ----
diff -crN nakedmudv1.4/src/races.c nakedmudv1.5/src/races.c
*** nakedmudv1.4/src/races.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/races.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 2,57 ****
  //
  // races.c
  //
! // contains all of the information assocciated with different races.
  //
  //*****************************************************************************
  
  #include "mud.h"
- #include "races.h"
  #include "body.h"
  #include "utils.h"
  
! struct race_data {
!   char *name;
!   char *abbrev;
!   int  bodytype;
!   bool pc_race;
! };
  
- const struct race_data race_info[NUM_RACES] = {
-   { "human", "hum",  BODYTYPE_HUMANOID, TRUE  },
-   { "elf",   "elf",  BODYTYPE_HUMANOID, TRUE  },
-   { "dragon","drg",  BODYTYPE_DRAGON,  FALSE  }
- };
  
- bool raceIsForPC(int race) {
-   return race_info[race].pc_race;
- }
  
! BODY_DATA *raceCreateBody(int race) {
!   return bodyCreate(race_info[race].bodytype);
! }
  
! const char *raceGetName(int race) {
!   return race_info[race].name;
  }
  
- const char *raceGetAbbrev(int race) {
-   return race_info[race].abbrev;
- }
  
- int raceGetNum(const char *race) {
-   int i;
-   for(i = 0; i < NUM_RACES; i++)
-     if(!strcasecmp(race_info[i].name, race))
-       return i;
-   return RACE_NONE;
- }
  
! int raceGetAbbrevNum(const char *race) {
!   int i;
!   for(i = 0; i < NUM_RACES; i++)
!     if(!strcasecmp(race_info[i].abbrev, race))
!       return i;
!   return RACE_NONE;
  }
--- 2,157 ----
  //
  // races.c
  //
! // contains all of the information assocciated with different races. If you are
! // wanting to add new races to the MUD, it is suggested you do so through the
! // add_race() function, and make a new module for your MUD's races.
  //
  //*****************************************************************************
  
  #include "mud.h"
  #include "body.h"
  #include "utils.h"
  
! #include "races.h"
  
  
  
! //*****************************************************************************
! //
! // local datastructures, functions, and defines
! //
! //*****************************************************************************
  
! // how big is hour hashtable for holding race data?
! #define RACE_TABLE_SIZE    10
! HASHTABLE *race_table = NULL;
! 
! 
! typedef struct race_data {
!   char      *name;
!   char      *abbrev;
!   BODY_DATA *body;
!   bool       pc_ok;
! } RACE_DATA;
! 
! 
! RACE_DATA *newRace(const char *name, const char *abbrev, BODY_DATA *body,
! 		   bool pc_ok) {
!   RACE_DATA *data = malloc(sizeof(RACE_DATA));
!   data->name   = strdup(name ? name : "");
!   data->abbrev = strdup(abbrev ? abbrev : "");
!   data->body   = body;
!   data->pc_ok  = pc_ok;
!   return data;
  }
  
  
  
! //*****************************************************************************
! //
! // implementation of race.h
! //
! //*****************************************************************************
! void init_races() {
!   // create the table for holding race data
!   race_table = newHashtable(RACE_TABLE_SIZE);
! 
!   // make the default human body
!   BODY_DATA *body = newBody();
!   bodySetSize(body, BODYSIZE_MEDIUM);
!   bodyAddPosition(body, "right grip",              BODYPOS_HELD,          0);
!   bodyAddPosition(body, "left grip",               BODYPOS_HELD,          0);
!   bodyAddPosition(body, "right foot",              BODYPOS_RIGHT_FOOT,    2);
!   bodyAddPosition(body, "left foot",               BODYPOS_LEFT_FOOT,     2);
!   bodyAddPosition(body, "right leg",               BODYPOS_LEG,           9);
!   bodyAddPosition(body, "left leg",                BODYPOS_LEG,           9);
!   bodyAddPosition(body, "waist",                   BODYPOS_WAIST,         1);
!   bodyAddPosition(body, "right finger",            BODYPOS_FINGER,        1);
!   bodyAddPosition(body, "left finger",             BODYPOS_FINGER,        1);
!   bodyAddPosition(body, "right hand",              BODYPOS_RIGHT_HAND,    2);
!   bodyAddPosition(body, "left hand",               BODYPOS_LEFT_HAND,     2);
!   bodyAddPosition(body, "right wrist",             BODYPOS_WRIST,         1);
!   bodyAddPosition(body, "left wrist",              BODYPOS_WRIST,         1);
!   bodyAddPosition(body, "right arm",               BODYPOS_ARM,           7);
!   bodyAddPosition(body, "left arm",                BODYPOS_ARM,           7);
!   bodyAddPosition(body, "about body",              BODYPOS_ABOUT,         0);
!   bodyAddPosition(body, "torso",                   BODYPOS_TORSO,        50);
!   bodyAddPosition(body, "neck",                    BODYPOS_NECK,          1);
!   bodyAddPosition(body, "right ear",               BODYPOS_EAR,           0);
!   bodyAddPosition(body, "left ear",                BODYPOS_EAR,           0);
!   bodyAddPosition(body, "face",                    BODYPOS_FACE,          2);
!   bodyAddPosition(body, "head",                    BODYPOS_HEAD,          2);
!   bodyAddPosition(body, "floating about head",     BODYPOS_FLOAT,         0);
!   //                                                                  ------
!   //                                                                    100
! 
!   // add the basic races
!   add_race("human", "hum", body, TRUE);
!   //********************************************************************
!   // If you are wanting to add new, non-stock races it is suggested
!   // you do so through a module and import them with add_race instead
!   // of putting them directly into this folder. This will make your life
!   // much easier whenever new versions of NakedMud are released and you
!   // want to upgrade!
!   //********************************************************************
! }
! 
! 
! void add_race(const char *name, const char *abbrev, BODY_DATA *body, int pc_ok){
!   hashPut(race_table, name, newRace(name, abbrev, body, pc_ok));
! }
! 
! int raceCount() {
!   return hashSize(race_table);
! }
! 
! bool isRace(const char *name) {
!   return (hashGet(race_table, name) != NULL);
! }
! 
! BODY_DATA *raceCreateBody(const char *name) {
!   RACE_DATA *data = hashGet(race_table, name);
!   return (data ? bodyCopy(data->body) : NULL);
! }
! 
! bool raceIsForPC(const char *name) {
!   RACE_DATA *data = hashGet(race_table, name);
!   return (data ? data->pc_ok : FALSE);
! }
! 
! const char *raceGetAbbrev(const char *name) {
!   RACE_DATA *data = hashGet(race_table, name);
!   return (data ? data->abbrev : NULL);
! }
! 
! const char *raceDefault() {
!   return "human";
! }
! 
! const char *raceGetList(bool pc_only) {
!   static char buf[MAX_BUFFER];
!   LIST       *name_list = newList();
!   HASH_ITERATOR *race_i = newHashIterator(race_table);
!   const char      *name = NULL;
!   RACE_DATA       *data = NULL;
! 
!   // collect all of our names
!   ITERATE_HASH(name, data, race_i) {
!     if(pc_only && data->pc_ok == FALSE) continue;
!     listPutWith(name_list, strdup(name), strcmp);
!   }
!   deleteHashIterator(race_i);
! 
!   // print all the names to our buffer
!   char *new_name = NULL; // gotta use a new name ptr.. can't free const
!   int i = 0;
!   while( (new_name = listPop(name_list)) != NULL) {
!     i += snprintf(buf+i, MAX_BUFFER-i, "%s%s",
! 		  new_name, (listSize(name_list) > 0 ? ", " : ""));
!     free(new_name);
!   }
! 
!   // delete our list of names and return the buffer
!   deleteListWith(name_list, free);
!   return buf;
  }
diff -crN nakedmudv1.4/src/races.h nakedmudv1.5/src/races.h
*** nakedmudv1.4/src/races.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/races.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 1,29 ****
! #ifndef __RACES_H
! #define __RACES_H
  //*****************************************************************************
  //
  // races.h
  //
! // contains all of the information assocciated with different races.
  //
  //*****************************************************************************
  
  
! #define RACE_NONE           (-1)
! #define RACE_HUMAN            0
! #define RACE_ELF              1
! #define RACE_DRAGON           2
! #define NUM_RACES             3
! 
! //
! // Create a copy of the bodytype assocciated with the race.
! //
! BODY_DATA *raceCreateBody(int race);
! 
! bool raceIsForPC(int race);
! const char *raceGetName(int race);
! const char *raceGetAbbrev(int race);
! int raceGetNum(const char *race);
! int raceGetAbbrevNum(const char *race);
! 
! #endif // __RACES_H
--- 1,23 ----
! #ifndef RACES_H
! #define RACES_H
  //*****************************************************************************
  //
  // races.h
  //
! // contains all of the information assocciated with different races. If you are
! // wanting to add new races to the MUD, it is suggested you do so through the
! // add_race() function, and make a new module for your MUD's races.
  //
  //*****************************************************************************
  
+ void init_races();
+ void add_race(const char *name, const char *abbrev, BODY_DATA *body, int pc_ok);
+ int raceCount();
+ bool isRace(const char *name);
+ BODY_DATA *raceCreateBody(const char *name);
+ bool raceIsForPC(const char *name);
+ const char *raceGetAbbrev(const char *name);
+ const char *raceGetList(bool pc_only);
+ const char *raceDefault(void);
  
! #endif // RACES_H
diff -crN nakedmudv1.4/src/room.c nakedmudv1.5/src/room.c
*** nakedmudv1.4/src/room.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/room.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 126,164 ****
  
  STORAGE_SET *roomStore(ROOM_DATA *room) {
    STORAGE_SET *set = new_storage_set();
!   store_string(set, "name",    room->name,                  NULL);
!   store_string(set, "desc",    room->desc,                  NULL);
!   store_int   (set, "vnum",    room->vnum,                  NULL);
!   store_int   (set, "terrain", room->terrain,               NULL);
!   store_set   (set, "edescs",  edescSetStore(room->edescs), NULL);
  
    STORAGE_SET_LIST *exits = new_storage_list();
!   store_list(set, "exits", exits, NULL);
  
    // save all of the normal directions
    int i;
    for(i = 0; i < NUM_DIRS; i++) {
      if(room->exits[i]) {
        STORAGE_SET *exit = exitStore(room->exits[i]);
!       store_string(exit, "direction", dirGetName(i), NULL);
        storage_list_put(exits, exit);
      }
    }
  
    // and now the special directions
    int num_special_exits = 0;
!   char **special_exits = roomGetExitNames(room, &num_special_exits);
    for(i = 0; i < num_special_exits; i++) {
      STORAGE_SET *exit = exitStore(roomGetExitSpecial(room, special_exits[i]));
!     store_string(exit, "direction", special_exits[i], NULL);
      storage_list_put(exits, exit);
    }
    if(special_exits) free(special_exits);
  
!   // and store our reset data
!   store_list(set, "reset",     gen_store_list(room->reset, resetStore), NULL);
! 
!   store_set(set, "auxiliary",  auxiliaryDataStore(room->auxiliary_data), NULL);
    return set;
  }
  
--- 126,162 ----
  
  STORAGE_SET *roomStore(ROOM_DATA *room) {
    STORAGE_SET *set = new_storage_set();
!   store_string(set, "name",    room->name);
!   store_string(set, "desc",    room->desc);
!   store_int   (set, "vnum",    room->vnum);
!   store_int   (set, "terrain", room->terrain);
!   store_set   (set, "edescs",  edescSetStore(room->edescs));
  
    STORAGE_SET_LIST *exits = new_storage_list();
!   store_list(set, "exits", exits);
  
    // save all of the normal directions
    int i;
    for(i = 0; i < NUM_DIRS; i++) {
      if(room->exits[i]) {
        STORAGE_SET *exit = exitStore(room->exits[i]);
!       store_string(exit, "direction", dirGetName(i));
        storage_list_put(exits, exit);
      }
    }
  
    // and now the special directions
    int num_special_exits = 0;
!   const char **special_exits = roomGetExitNames(room, &num_special_exits);
    for(i = 0; i < num_special_exits; i++) {
      STORAGE_SET *exit = exitStore(roomGetExitSpecial(room, special_exits[i]));
!     store_string(exit, "direction", special_exits[i]);
      storage_list_put(exits, exit);
    }
    if(special_exits) free(special_exits);
  
!   store_list(set, "reset",     gen_store_list(room->reset, resetStore));
!   store_set(set, "auxiliary",  auxiliaryDataStore(room->auxiliary_data));
    return set;
  }
  
***************
*** 203,209 ****
  
  void roomCopyTo(ROOM_DATA *from, ROOM_DATA *to) {
    int i, num_spec_exits;
!   char **spec_exits;
  
    // we just want to copy data ABOUT the room, and not stuff
    // contained in the particular instance (e.g. players, contents)
--- 201,207 ----
  
  void roomCopyTo(ROOM_DATA *from, ROOM_DATA *to) {
    int i, num_spec_exits;
!   const char **spec_exits;
  
    // we just want to copy data ABOUT the room, and not stuff
    // contained in the particular instance (e.g. players, contents)
***************
*** 224,233 ****
  
    // free the special exits of the <to> room
    spec_exits = roomGetExitNames(to, &num_spec_exits);
!   for(i = 0; i < num_spec_exits; i++) {
      roomSetExitSpecial(to, spec_exits[i], NULL);
-     free(spec_exits[i]);
-   }
    free(spec_exits);
    deleteHashtable(to->special_exits);
    to->special_exits = newHashtable(SPECIAL_EXIT_BUCKETS);
--- 222,229 ----
  
    // free the special exits of the <to> room
    spec_exits = roomGetExitNames(to, &num_spec_exits);
!   for(i = 0; i < num_spec_exits; i++)
      roomSetExitSpecial(to, spec_exits[i], NULL);
    free(spec_exits);
    deleteHashtable(to->special_exits);
    to->special_exits = newHashtable(SPECIAL_EXIT_BUCKETS);
***************
*** 235,245 ****
  
    // set the special exits of the <to> room
    spec_exits = roomGetExitNames(from, &num_spec_exits);
!   for(i = 0; i < num_spec_exits; i++) {
      roomSetExitSpecial(to, spec_exits[i], 
  		       exitCopy(roomGetExitSpecial(from, spec_exits[i])));
-     free(spec_exits[i]);
-   }
    free(spec_exits);
  
    
--- 231,239 ----
  
    // set the special exits of the <to> room
    spec_exits = roomGetExitNames(from, &num_spec_exits);
!   for(i = 0; i < num_spec_exits; i++)
      roomSetExitSpecial(to, spec_exits[i], 
  		       exitCopy(roomGetExitSpecial(from, spec_exits[i])));
    free(spec_exits);
  
    
***************
*** 284,290 ****
  #ifdef MODULE_SCRIPTS
    try_scripts(SCRIPT_TYPE_INIT,
  	      room, SCRIPTOR_ROOM,
! 	      NULL, NULL, room, NULL, NULL, NULL, 0);
  #endif
  }
  
--- 278,284 ----
  #ifdef MODULE_SCRIPTS
    try_scripts(SCRIPT_TYPE_INIT,
  	      room, SCRIPTOR_ROOM,
! 	      NULL, NULL, room, NULL, NULL, 0);
  #endif
  }
  
***************
*** 365,381 ****
    return hashGet(room->special_exits, dir);
  };
  
! char      **roomGetExitNames   (const ROOM_DATA *room, int *num) {
    int i;
  
    *num = hashSize(room->special_exits);
!   char **names = malloc(sizeof(char *) * *num);
    HASH_ITERATOR *hash_i = newHashIterator(room->special_exits);
  
    for(i = 0; i < *num; i++, hashIteratorNext(hash_i))
!     names[i] = strdup(hashIteratorCurrentKey(hash_i));
! 
    deleteHashIterator(hash_i);
    return names;
  };
  
--- 359,375 ----
    return hashGet(room->special_exits, dir);
  };
  
! const char      **roomGetExitNames   (const ROOM_DATA *room, int *num) {
    int i;
  
    *num = hashSize(room->special_exits);
!   const char **names = malloc(sizeof(char *) * *num);
    HASH_ITERATOR *hash_i = newHashIterator(room->special_exits);
  
    for(i = 0; i < *num; i++, hashIteratorNext(hash_i))
!     names[i] = hashIteratorCurrentKey(hash_i);
    deleteHashIterator(hash_i);
+ 
    return names;
  };
  
***************
*** 503,687 ****
  //*****************************************************************************
  struct terrain_data {
    char   *name;
-   char   *default_rname;
-   char   *default_rdesc;
-   char   *map_symbol;
-   double  move_difficulty;
-   double  visibility;
  };
  
  const struct terrain_data terrain_types[NUM_TERRAINS] = {
!   { "Inside",             
!     "Inside", 
!     "You are not outside. This desc should never be seen.\r\n",
!     "{w.",      1.0,    1.0 },
! 
!   { "City",               
!     "In the City", 
!     "You are in a city. This desc should never be seen.\r\n",
!     "{g.",      1.0,    0.6 },
! 
!   { "Road", 
!     "On a Road", 
!     "The road beneath your feet is quite well made, and looks like it is "
!     "taken care of on a regular basis. The foundation is a thick mortar, and "
!     "there are virtually no cracks in it. You see the occasionally band of "
!     "travellers pass you by, or a merchant riding a wagon hitched up to a "
!     "horse heading in the opposite direction as you.\r\n",
!     "{w.",      1.0,    1.0 },  
! 
!   { "Bridge",             
!     "On a Bridge", 
!     "The bridge appears to be quite sturdy; its foundation is a solid stone, "
!     "and it looks like it was crafted by master builders. To either side of "
!     "the bridge, you see a road continuing on for quite some ways.\r\n",
!     "{g#",      1.0,    1.0 },
! 
!   { "Shallow Water",       
!     "In Shallow Water", 
!     "The water is refreshingly cool on your skin, and it is shallow enough "
!     "that you are able to wade in it without relative ease. Occasionally, you "
!     "will see a glint of color under the water, which is probably a fish "
!     "swimming by you.\r\n",
!     "{B~",      0.5,    1.0 },
! 
!   { "Deep Water",    
!     "In Deep Waters", 
!     "The water here is much too deep to wade into. Ripples undulate around "
!     "you on the water's surface, spreading out in a beautiful rippling "
!     "pattern. Occasionally, you see a bird dive down into the water and "
!     "snatch up a fish.\r\n",
!     "{bw",      0.2,    1.0 },
! 
!   { "Ocean",
!     "On The Ocean",
!     "Water, water everywhere! On all sides, you are surrounded by an endless "
!     "view of water. At least the water is calm; occasionally, small waves "
!     "rock you back and forth, but other than that there is very little "
!     "disturbance of the water. Occasionally, you see a group of sea birds "
!     "flying overhead, or a blurry figure swimming slightly below the surface "
!     "of the water.\r\n",
!     "{bo",      0.1,    0.8 },
! 
!   { "Underwater",         
!     "Underwater", 
!     "Your vision is somewhat obscured by the water around you, but you manage "
!     "to make out shapes of various water creatures around you; hoards of "
!     "fish, sponges, and seaweed. Many more exotic creatures swim about as "
!     "well, but you are hard pressed to name any of them.\r\n",
!     "{bu",      0.1,    0.5 },
! 
!   { "Field",              
!     "In a Field", 
!     "You are in a field. Occasionally, you hear birds chirping, and "
!     "you see the occasional one fly overhead. The wilderness is quite "
!     "peaceful.\r\n",
!     "{g\"",    1.0,     1.0 },
! 
!   { "Plains",             
!     "On The Plains", 
!     "You are on the open plains. Occasionally, You see the occasional hawk "
!     "fly overhead, and you spot many small rodents as you walk. The plains "
!     "are quite flat, and you can literally see for miles.\r\n",
!     "#Yp",    1.0,      1.0 },
! 
!   { "Meadow",
!     "In A Meadow",
!     "The meadow is a sea of tall, dried yellowish grass. There is a slight "
!     "breeze, and the grass is bent in the direction the wind is blowing. You "
!     "see the occasional grasshopper leap past you as you make your way "
!     "through the meadow. Birds circle in the air above - they look like tiny "
!     "specks from where you are.\r\n",
!     "#Ym",    1.0,      1.0 },
! 
!   { "Forest",             
!     "In a Wooded Forest",
!     "Trees surround you on all sides. Poplar, fur, birch - all kinds. "
!     "The trees are not so thick that you have a hard time seeing, but "
!     "your vision is definitely impeded slightly by the trees.\r\n",
!     "{Gf",    0.8,      0.7 },
! 
!   { "Deep Forest",        
!     "In a Deep Forest", 
!     "Trees surround you on all sides. Poplar, fur, birch - all kinds. "
!     "The trees get quite thick here, and it becomes rather hard to see "
!     "anything that is not in your immediate vicinity.\r\n",
!     "{gD",    0.5,      0.4 },
! 
!   { "Hills",              
!     "On Rolling Hills", 
!     "Small hills cover the ground here, in wavy patterns. The ground is "
!     "fairly nondescript - dirt and grass. Occasionally, you spot a hole "
!     "in the ground. You would guess it to be the home of some small rodent. "
!     "\r\n",
!     "{yh",    0.7,      0.8 },
! 
!   { "High Hills",
!     "Amidst High Hills",
!     "The hills here are steep and plentiful. They are scattered across the "
!     "terrain like waves in the ocean. The ground here is rather hard, and "
!     "very rough. You spot the occasional patch of grass, but for the most "
!     "part, the ground is simply dirt. You spot holes in the ground every now "
!     "and then. Occasionally, a small rodent pokes its head in one, and then "
!     "scurries back into its shelter.\r\n",
!     "{yH",   0.4,        0.5 },
! 
!   { "Mountains",         
!     "In the Mountains", 
!     "The mountain is quite rocky, and here and there you see patches of snow "
!     "on the ground. Are visible here and there, but you notice they start to "
!     "thin out as the mountain rises up.\r\n",
!     "{w^",   0.1,        0.1 },
! 
!   { "Swamp",              
!     "In a Swamp", 
!     "The odor of the swamp is reminiscent of mold and rotting materials. "
!     "The ground is quite moist, and occasionally large bubbles float up to "
!     "the surface of it and pop, letting out rather noxious fumes. The air "
!     "is also quite damp, and very warm. Occasionally, you will hear the cry "
!     "of a bird off in the distance, or what sounds like twigs snapping.\r\n",
!     "#rs",   0.3,        0.5 },
! 
!   { "Deep Swamp",
!     "Deep in the Swamp",
!     "The air here is humid, and a very musky smell lingers about. The ground "
!     "here is quite moist - dirty, murky water rises up to your ankles. Your "
!     "surroundings are ominously quiet, except for the occasional shrill cry "
!     "of a bird off in the distance. Rotten pieces of wood float in the water "
!     "beneath your feet. Some drift as if they are a live. But, of course, "
!     "driftwood doesn't live. Or maybe that's not driftwood.\r\n",
!     "#rS",   0.1,        0.3 },
! 
!   { "Sand",               
!     "On Sand", 
!     "The sand is a bright golden yellow, and have a very fine grain. You "
!     "see the occasional rock sticking out of the sand at an odd angle, and "
!     "a small crab here or there, scurrying along.\r\n",
!     "{y\"",  0.8,        1.0 },
! 
!   { "Desert",
!     "In A Desert",
!     "Sand streches out around you for miles in every direction. The air is "
!     "unbearably hot, and very dry. Your lips are getting more and more "
!     "chapped with every passing moment. The sun beams down on you with its "
!     "relentless gaze, burning your skin and making you slightly lightheaded. "
!     "It is a wonder even the most hearty of animals can live out here.\r\n",
!     "{yD",   0.7,        1.0 },
! 
!   { "Ice",
!     "On Ice",
!     "Ice needs a description.\r\n",
!     "{CI",   0.5,        0.7 },
! 
!   { "Glacier",
!     "Amidst Glaciers",
!     "Glaciers need a description.\r\n",
!     "{cG",   0.3,        0.3 },
! 
!   { "Cavern",
!     "Within a Cavern",
!     "Caverns need a description.\r\n",
!     " ",   1.0,        0.7 }
  };
  
  
--- 497,529 ----
  //*****************************************************************************
  struct terrain_data {
    char   *name;
  };
  
  const struct terrain_data terrain_types[NUM_TERRAINS] = {
!   { "Inside"        },
!   { "City"          },
!   { "Road"          },
!   { "Alley"         },
!   { "Bridge"        },
!   { "Shallow Water" },
!   { "Deep Water"    },
!   { "Ocean"         },
!   { "Underwater"    },
!   { "Field"         },
!   { "Plains"        },
!   { "Meadow"        },
!   { "Forest"        },
!   { "Deep Forest"   },
!   { "Hills"         },
!   { "High Hills"    },
!   { "Mountains"     },
!   { "Swamp"         },
!   { "Deep Swamp"    },
!   { "Sand"          },
!   { "Desert"        }, 
!   { "Ice"           },
!   { "Glacier"       },
!   { "Cavern"        },
  };
  
  
***************
*** 689,714 ****
    return terrain_types[terrain].name;
  }
  
- const char *terrainGetDefaultRname(int terrain) {
-   return terrain_types[terrain].default_rname;
- }
- 
- const char *terrainGetDefaultRdesc(int terrain) {
-   return terrain_types[terrain].default_rdesc;
- }
- 
- const char *terrainGetMapSymbol(int terrain) {
-   return terrain_types[terrain].map_symbol;
- }
- 
- double      terrainGetVisibility(int terrain) {
-   return terrain_types[terrain].visibility;
- }
- 
- double      terrainGetMoveDifficulty(int terrain) {
-   return terrain_types[terrain].move_difficulty;
- }
- 
  int terrainGetNum(const char *terrain) {
    int i;
    for(i = 0; i < NUM_TERRAINS; i++)
--- 531,536 ----
***************
*** 716,719 ****
        return i;
    return TERRAIN_NONE;
  }
- 
--- 538,540 ----
diff -crN nakedmudv1.4/src/room.h nakedmudv1.5/src/room.h
*** nakedmudv1.4/src/room.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/room.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 32,58 ****
  #define TERRAIN_INDOORS         0	
  #define TERRAIN_CITY            1	
  #define TERRAIN_ROAD            2
! #define TERRAIN_BRIDGE          3 
! #define TERRAIN_SHALLOW_WATER   4	
! #define TERRAIN_DEEP_WATER      5	
! #define TERRAIN_OCEAN           6
! #define TERRAIN_UNDERWATER	7	
! #define TERRAIN_FIELD           8	
! #define TERRAIN_PLAINS          9 
! #define TERRAIN_MEADOW         10
! #define TERRAIN_FOREST         11
! #define TERRAIN_DEEP_FOREST    12 
! #define TERRAIN_HILLS          13
! #define TERRAIN_HIGH_HILLS     14
! #define TERRAIN_MOUNTAIN       15
! #define TERRAIN_SWAMP          16 
! #define TERRAIN_DEEP_SWAMP     17
! #define TERRAIN_SAND           18 
! #define TERRAIN_DESERT         19
! #define TERRAIN_ICE            20
! #define TERRAIN_GLACIER        21
! #define TERRAIN_CAVERN         22
! #define NUM_TERRAINS           23
  
  
  //
--- 32,59 ----
  #define TERRAIN_INDOORS         0	
  #define TERRAIN_CITY            1	
  #define TERRAIN_ROAD            2
! #define TERRAIN_ALLEY           3
! #define TERRAIN_BRIDGE          4 
! #define TERRAIN_SHALLOW_WATER   5	
! #define TERRAIN_DEEP_WATER      6	
! #define TERRAIN_OCEAN           7
! #define TERRAIN_UNDERWATER	8	
! #define TERRAIN_FIELD           9	
! #define TERRAIN_PLAINS         10 
! #define TERRAIN_MEADOW         11
! #define TERRAIN_FOREST         12
! #define TERRAIN_DEEP_FOREST    13 
! #define TERRAIN_HILLS          14
! #define TERRAIN_HIGH_HILLS     15
! #define TERRAIN_MOUNTAIN       16
! #define TERRAIN_SWAMP          17 
! #define TERRAIN_DEEP_SWAMP     18
! #define TERRAIN_SAND           19 
! #define TERRAIN_DESERT         20
! #define TERRAIN_ICE            21
! #define TERRAIN_GLACIER        22
! #define TERRAIN_CAVERN         23
! #define NUM_TERRAINS           24
  
  
  //
***************
*** 122,128 ****
  
  EXIT_DATA  *roomGetExit         (const ROOM_DATA *room, int dir);
  EXIT_DATA  *roomGetExitSpecial  (const ROOM_DATA *room, const char *dir);
! char      **roomGetExitNames    (const ROOM_DATA *room, int *num);
  EDESC_SET  *roomGetEdescs       (const ROOM_DATA *room);
  const char *roomGetEdesc        (const ROOM_DATA *room, const char *keyword);
  void       *roomGetAuxiliaryData(const ROOM_DATA *room, const char *name);
--- 123,129 ----
  
  EXIT_DATA  *roomGetExit         (const ROOM_DATA *room, int dir);
  EXIT_DATA  *roomGetExitSpecial  (const ROOM_DATA *room, const char *dir);
! const char **roomGetExitNames   (const ROOM_DATA *room, int *num);
  EDESC_SET  *roomGetEdescs       (const ROOM_DATA *room);
  const char *roomGetEdesc        (const ROOM_DATA *room, const char *keyword);
  void       *roomGetAuxiliaryData(const ROOM_DATA *room, const char *name);
***************
*** 165,177 ****
  //
  //*****************************************************************************
  const char *terrainGetName(int terrain);
! const char *terrainGetDefaultRname(int terrain);
! const char *terrainGetDefaultRdesc(int terrain);
! const char *terrainGetMapSymbol(int terrain);
! double      terrainGetVisibility(int terrain); // [0, 1]
! double      terrainGetExhaustion(int terrain); // [0, 1]
! 
! int terrainGetNum(const char *terrain);
  
  
  #endif // __ROOM_H
--- 166,172 ----
  //
  //*****************************************************************************
  const char *terrainGetName(int terrain);
! int  terrainGetNum(const char *terrain);
  
  
  #endif // __ROOM_H
diff -crN nakedmudv1.4/src/room_reset.c nakedmudv1.5/src/room_reset.c
*** nakedmudv1.4/src/room_reset.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/room_reset.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 27,33 ****
    int        type; // what kind of reset are we?
    int       times; // how many times should it be executed?
    int      chance; // what is our chance of success?
!   int         max; // what is the max number of us that ca nbe in the game?
    int    room_max; // what is the max number of us that can be in the room?
    char       *arg; // what is our reset arg (e.g. mob vnum, direction name)
    LIST        *in; // what resets do we put into ourself?
--- 27,33 ----
    int        type; // what kind of reset are we?
    int       times; // how many times should it be executed?
    int      chance; // what is our chance of success?
!   int         max; // what is the max number of us that can be in the game?
    int    room_max; // what is the max number of us that can be in the room?
    char       *arg; // what is our reset arg (e.g. mob vnum, direction name)
    LIST        *in; // what resets do we put into ourself?
***************
*** 108,122 ****
  
  STORAGE_SET   *resetStore       (RESET_DATA *reset) {
    STORAGE_SET *set = new_storage_set();
!   store_int   (set, "type",     reset->type,     NULL);
!   store_int   (set, "times",    reset->times,    NULL);
!   store_int   (set, "chance",   reset->chance,   NULL);
!   store_int   (set, "max",      reset->max,      NULL);
!   store_int   (set, "room_max", reset->room_max, NULL);
!   store_string(set, "arg",      reset->arg,      NULL);
!   store_list  (set, "in",       gen_store_list(reset->in,   resetStore), NULL);
!   store_list  (set, "on",       gen_store_list(reset->on,   resetStore), NULL);
!   store_list  (set, "then",     gen_store_list(reset->then, resetStore), NULL);
    return set;
  }
  
--- 108,122 ----
  
  STORAGE_SET   *resetStore       (RESET_DATA *reset) {
    STORAGE_SET *set = new_storage_set();
!   store_int   (set, "type",     reset->type);
!   store_int   (set, "times",    reset->times);
!   store_int   (set, "chance",   reset->chance);
!   store_int   (set, "max",      reset->max);
!   store_int   (set, "room_max", reset->room_max);
!   store_string(set, "arg",      reset->arg);
!   store_list  (set, "in",       gen_store_list(reset->in,   resetStore));
!   store_list  (set, "on",       gen_store_list(reset->on,   resetStore));
!   store_list  (set, "then",     gen_store_list(reset->then, resetStore));
    return set;
  }
  
***************
*** 568,581 ****
  bool resetRun(RESET_DATA *reset, void *initiator, int initiator_type) {
    //
    // possible problem: how do we know what to return if we're
!   // running it multiple times? 
    //
    bool ret_val = FALSE;
  
    // go through for however many times we need to
    int i;
    for(i = 0; i < resetGetTimes(reset); i++) {
!     // check our chance
      if(rand_number(1, 100) > resetGetChance(reset))
        continue;
      switch(resetGetType(reset)) {
--- 568,581 ----
  bool resetRun(RESET_DATA *reset, void *initiator, int initiator_type) {
    //
    // possible problem: how do we know what to return if we're
!   // running the reset data multiple times? 
    //
    bool ret_val = FALSE;
  
    // go through for however many times we need to
    int i;
    for(i = 0; i < resetGetTimes(reset); i++) {
!     // If we don't make our reset chance, continue onto the next check
      if(rand_number(1, 100) > resetGetChance(reset))
        continue;
      switch(resetGetType(reset)) {
diff -crN nakedmudv1.4/src/save.c nakedmudv1.5/src/save.c
*** nakedmudv1.4/src/save.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/save.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 79,86 ****
  void save_objfile(CHAR_DATA *ch) {
    STORAGE_SET *set = new_storage_set();
    // write all of the inventory
!   store_list(set, "inventory", gen_store_list(charGetInventory(ch), objStore),
! 	     NULL);
    
    // for equipped items, it's not so easy - we also have to record
    // whereabouts on the body the equipment was worn on
--- 79,85 ----
  void save_objfile(CHAR_DATA *ch) {
    STORAGE_SET *set = new_storage_set();
    // write all of the inventory
!   store_list(set, "inventory", gen_store_list(charGetInventory(ch), objStore));
    
    // for equipped items, it's not so easy - we also have to record
    // whereabouts on the body the equipment was worn on
***************
*** 89,100 ****
    OBJ_DATA *obj = NULL;
    while((obj = listPop(eq_list)) != NULL) {
      STORAGE_SET *eq_set = objStore(obj);
!     store_string(set, "equipped", bodyEquippedWhere(charGetBody(ch), obj),NULL);
      storage_list_put(list, eq_set);
    }
    deleteList(eq_list);
  
!   store_list(set, "equipment", list, NULL);
    storage_write(set, get_char_filename(charGetName(ch), FILETYPE_OFILE));
    storage_close(set);
  }
--- 88,99 ----
    OBJ_DATA *obj = NULL;
    while((obj = listPop(eq_list)) != NULL) {
      STORAGE_SET *eq_set = objStore(obj);
!     store_string(set, "equipped", bodyEquippedWhere(charGetBody(ch), obj));
      storage_list_put(list, eq_set);
    }
    deleteList(eq_list);
  
!   store_list(set, "equipment", list);
    storage_write(set, get_char_filename(charGetName(ch), FILETYPE_OFILE));
    storage_close(set);
  }
***************
*** 168,176 ****
   */
  void save_profile(CHAR_DATA *ch) {
    STORAGE_SET *set = new_storage_set();
!   store_string(set, "name",     charGetName(ch),     NULL);
!   store_string(set, "password", charGetPassword(ch), NULL);
!   store_int   (set, "uid",      charGetUID(ch),      NULL);
    storage_write(set, get_char_filename(charGetName(ch), FILETYPE_PROFILE));
    storage_close(set);
  }
--- 167,175 ----
   */
  void save_profile(CHAR_DATA *ch) {
    STORAGE_SET *set = new_storage_set();
!   store_string(set, "name",     charGetName(ch));
!   store_string(set, "password", charGetPassword(ch));
!   store_int   (set, "uid",      charGetUID(ch));
    storage_write(set, get_char_filename(charGetName(ch), FILETYPE_PROFILE));
    storage_close(set);
  }
diff -crN nakedmudv1.4/src/scripts/pychar.c nakedmudv1.5/src/scripts/pychar.c
*** nakedmudv1.4/src/scripts/pychar.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/scripts/pychar.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 261,267 ****
  static PyObject *
  PyChar_getrace(PyChar *self, void *closure) {
    CHAR_DATA *ch = propertyTableGet(mob_table, self->uid);
!   if(ch != NULL) return Py_BuildValue("s", raceGetName(charGetRace(ch)));
    else           return NULL;
  }
  
--- 261,267 ----
  static PyObject *
  PyChar_getrace(PyChar *self, void *closure) {
    CHAR_DATA *ch = propertyTableGet(mob_table, self->uid);
!   if(ch != NULL) return Py_BuildValue("s", charGetRace(ch));
    else           return NULL;
  }
  
***************
*** 434,441 ****
      return -1;
    }
  
!   int race = raceGetNum(PyString_AsString(value));
!   if(race == RACE_NONE) {
      char buf[SMALL_BUFFER];
      sprintf(buf, "%s is an invalid race type", PyString_AsString(value));
      PyErr_Format(PyExc_TypeError, buf);
--- 434,441 ----
      return -1;
    }
  
!   const char *race = PyString_AsString(value);
!   if(!isRace(race)) {
      char buf[SMALL_BUFFER];
      sprintf(buf, "%s is an invalid race type", PyString_AsString(value));
      PyErr_Format(PyExc_TypeError, buf);
***************
*** 814,820 ****
    // check for initialization scripts
    try_scripts(SCRIPT_TYPE_INIT,
  	      mob, SCRIPTOR_CHAR,
! 	      mob, NULL, room, NULL, NULL, NULL, 0);
  
    // create a python object for the new char, and return it
    PyChar *py_mob = (PyChar *)newPyChar(mob);
--- 814,820 ----
    // check for initialization scripts
    try_scripts(SCRIPT_TYPE_INIT,
  	      mob, SCRIPTOR_CHAR,
! 	      mob, NULL, room, NULL, NULL, 0);
  
    // create a python object for the new char, and return it
    PyChar *py_mob = (PyChar *)newPyChar(mob);
diff -crN nakedmudv1.4/src/scripts/pyobj.c nakedmudv1.5/src/scripts/pyobj.c
*** nakedmudv1.4/src/scripts/pyobj.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/scripts/pyobj.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 399,405 ****
    // check for initialization scripts
    try_scripts(SCRIPT_TYPE_INIT,
  	      obj, SCRIPTOR_OBJ,
! 	      ch, cont, room, NULL, NULL, NULL, 0);
  
    // create a python object for the new obj, and return it
    PyObj *py_obj = (PyObj *)newPyObj(obj);
--- 399,405 ----
    // check for initialization scripts
    try_scripts(SCRIPT_TYPE_INIT,
  	      obj, SCRIPTOR_OBJ,
! 	      ch, cont, room, NULL, NULL, 0);
  
    // create a python object for the new obj, and return it
    PyObj *py_obj = (PyObj *)newPyObj(obj);
diff -crN nakedmudv1.4/src/scripts/script.c nakedmudv1.5/src/scripts/script.c
*** nakedmudv1.4/src/scripts/script.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/scripts/script.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 82,91 ****
    STORAGE_SET_LIST *list = new_storage_list();
    LIST          *scripts = scriptSetList(data->scripts, SCRIPT_TYPE_ANY);
    SCRIPT_DATA    *script = NULL;
!   store_list(set, "scripts", list, NULL);
    while((script = listPop(scripts)) != NULL) {
      STORAGE_SET *scriptset = new_storage_set();
!     store_int(scriptset, "vnum", scriptGetVnum(script), NULL);
      storage_list_put(list, scriptset);
    }
    deleteList(scripts);
--- 82,91 ----
    STORAGE_SET_LIST *list = new_storage_list();
    LIST          *scripts = scriptSetList(data->scripts, SCRIPT_TYPE_ANY);
    SCRIPT_DATA    *script = NULL;
!   store_list(set, "scripts", list);
    while((script = listPop(scripts)) != NULL) {
      STORAGE_SET *scriptset = new_storage_set();
!     store_int(scriptset, "vnum", scriptGetVnum(script));
      storage_list_put(list, scriptset);
    }
    deleteList(scripts);
***************
*** 197,208 ****
  
  STORAGE_SET *scriptStore(SCRIPT_DATA *script) {
    STORAGE_SET *set = new_storage_set();
!   store_int   (set, "vnum", script->vnum, NULL);
!   store_int   (set, "type", script->type, NULL);
!   store_int   (set, "narg", script->num_arg, NULL);
!   store_string(set, "name", script->name, NULL);
!   store_string(set, "args", script->args, NULL);
!   store_string(set, "code", script->code, NULL);
    return set;
  }
  
--- 197,208 ----
  
  STORAGE_SET *scriptStore(SCRIPT_DATA *script) {
    STORAGE_SET *set = new_storage_set();
!   store_int   (set, "vnum", script->vnum);
!   store_int   (set, "type", script->type);
!   store_int   (set, "narg", script->num_arg);
!   store_string(set, "name", script->name);
!   store_string(set, "args", script->args);
!   store_string(set, "code", script->code);
    return set;
  }
  
***************
*** 343,349 ****
  
  
  void run_script(const char *script, void *me, int me_type,
! 		CHAR_DATA *ch, OBJ_DATA *obj, ROOM_DATA *room, EXIT_DATA *exit, 
  		const char *cmd, const char *arg, int narg) {
    static char buf[MAX_SCRIPT];
    *buf = '\0';
--- 343,349 ----
  
  
  void run_script(const char *script, void *me, int me_type,
! 		CHAR_DATA *ch, OBJ_DATA *obj, ROOM_DATA *room, 
  		const char *cmd, const char *arg, int narg) {
    static char buf[MAX_SCRIPT];
    *buf = '\0';
***************
*** 354,360 ****
    i += snprintf(buf+i, MAX_SCRIPT - i - 1, "from char import *\n");
    i += snprintf(buf+i, MAX_SCRIPT - i - 1, "from room import *\n");
    i += snprintf(buf+i, MAX_SCRIPT - i - 1, "from obj import *\n");
-   //    i += snprintf(buf+i, MAX_SCRIPT - i - 1, "from exit import *\n");
  
    // print the different variables
    i += snprintf(buf+i, MAX_SCRIPT - i - 1, "cmd = '%s'\n", (cmd ? cmd : ""));
--- 354,359 ----
***************
*** 368,375 ****
      i += snprintf(buf+i, MAX_SCRIPT - i - 1, "me = Obj(%d)\n", objGetUID(me));
    else if(me_type == SCRIPTOR_ROOM)
      i += snprintf(buf+i, MAX_SCRIPT - i - 1, "me = Room(%d)\n",roomGetVnum(me));
-   else if(me_type == SCRIPTOR_EXIT)
-     ;
  
    // print all of the other things involved
    if(ch)
--- 367,372 ----
***************
*** 562,568 ****
      if(is_keyword(scriptGetArgs(script), speech, FALSE)) {
        run_script(scriptGetCode(script),
  		 listener, SCRIPTOR_CHAR,
! 		 ch, NULL, charGetRoom(listener), NULL, NULL, speech, 0);
      }
    }
    deleteList(speech_scripts);
--- 559,565 ----
      if(is_keyword(scriptGetArgs(script), speech, FALSE)) {
        run_script(scriptGetCode(script),
  		 listener, SCRIPTOR_CHAR,
! 		 ch, NULL, charGetRoom(listener), NULL, speech, 0);
      }
    }
    deleteList(speech_scripts);
***************
*** 580,591 ****
  }
  
  
! void try_enterance_script(CHAR_DATA *ch, ROOM_DATA *room, 
! 			  EXIT_DATA *exit, const char *dirname) {
    // check the room
    try_scripts(SCRIPT_TYPE_ENTER,
  	      room, SCRIPTOR_ROOM,
! 	      ch, NULL, room, exit, dirname, NULL, 0);
  
    // check everyone in the room
    LIST_ITERATOR *char_i = newListIterator(roomGetCharacters(room));
--- 577,587 ----
  }
  
  
! void try_enterance_script(CHAR_DATA *ch, ROOM_DATA *room, const char *dirname) {
    // check the room
    try_scripts(SCRIPT_TYPE_ENTER,
  	      room, SCRIPTOR_ROOM,
! 	      ch, NULL, room, dirname, NULL, 0);
  
    // check everyone in the room
    LIST_ITERATOR *char_i = newListIterator(roomGetCharacters(room));
***************
*** 595,612 ****
        continue;
      try_scripts(SCRIPT_TYPE_ENTER,
  		greeter, SCRIPTOR_CHAR,
! 		ch, NULL, room, exit, dirname, NULL, 0);
    }
    deleteListIterator(char_i);
  }
  
  
! void try_exit_script(CHAR_DATA *ch, ROOM_DATA *room, 
! 		     EXIT_DATA *exit, const char *dirname) {
    // check the room
    try_scripts(SCRIPT_TYPE_EXIT,
  	      room, SCRIPTOR_ROOM,
! 	      ch, NULL, room, exit, dirname, NULL, 0);
  
    // check everyone in the room
    LIST_ITERATOR *char_i = newListIterator(roomGetCharacters(room));
--- 591,607 ----
        continue;
      try_scripts(SCRIPT_TYPE_ENTER,
  		greeter, SCRIPTOR_CHAR,
! 		ch, NULL, room, dirname, NULL, 0);
    }
    deleteListIterator(char_i);
  }
  
  
! void try_exit_script(CHAR_DATA *ch, ROOM_DATA *room, const char *dirname) {
    // check the room
    try_scripts(SCRIPT_TYPE_EXIT,
  	      room, SCRIPTOR_ROOM,
! 	      ch, NULL, room, dirname, NULL, 0);
  
    // check everyone in the room
    LIST_ITERATOR *char_i = newListIterator(roomGetCharacters(room));
***************
*** 617,623 ****
        continue;
      try_scripts(SCRIPT_TYPE_EXIT,
  		watcher, SCRIPTOR_CHAR,
! 		ch, NULL, room, exit, dirname, NULL, 0);
    }
    deleteListIterator(char_i);
  }
--- 612,618 ----
        continue;
      try_scripts(SCRIPT_TYPE_EXIT,
  		watcher, SCRIPTOR_CHAR,
! 		ch, NULL, room, dirname, NULL, 0);
    }
    deleteListIterator(char_i);
  }
***************
*** 630,636 ****
    // to halt the normal command from going through
    if(try_scripts(SCRIPT_TYPE_COMMAND,
  		 charGetRoom(ch), SCRIPTOR_ROOM,
! 		 ch, NULL, charGetRoom(ch), NULL, cmd, arg, 0))
      retval = 1;
  
    // check everyone in the room
--- 625,631 ----
    // to halt the normal command from going through
    if(try_scripts(SCRIPT_TYPE_COMMAND,
  		 charGetRoom(ch), SCRIPTOR_ROOM,
! 		 ch, NULL, charGetRoom(ch), cmd, arg, 0))
      retval = 1;
  
    // check everyone in the room
***************
*** 642,648 ****
        continue;
      if(try_scripts(SCRIPT_TYPE_COMMAND,
  		   scriptor, SCRIPTOR_CHAR,
! 		   ch, NULL, charGetRoom(ch), NULL, cmd, arg, 0))
        retval = 1;
    }
    deleteListIterator(char_i);
--- 637,643 ----
        continue;
      if(try_scripts(SCRIPT_TYPE_COMMAND,
  		   scriptor, SCRIPTOR_CHAR,
! 		   ch, NULL, charGetRoom(ch), cmd, arg, 0))
        retval = 1;
    }
    deleteListIterator(char_i);
***************
*** 652,658 ****
  
  int try_scripts(int script_type,
  		void *me, int me_type,
! 		CHAR_DATA *ch, OBJ_DATA *obj, ROOM_DATA *room, EXIT_DATA *exit,
  		const char *cmd, const char *arg, int narg) {
    int retval = 0;
    LIST *scripts = NULL;
--- 647,653 ----
  
  int try_scripts(int script_type,
  		void *me, int me_type,
! 		CHAR_DATA *ch, OBJ_DATA *obj, ROOM_DATA *room,
  		const char *cmd, const char *arg, int narg) {
    int retval = 0;
    LIST *scripts = NULL;
***************
*** 700,707 ****
        break;
      }
  
!     run_script(scriptGetCode(script), me, me_type,
! 	       ch, obj, room, exit, cmd, arg, narg);    
    }
    deleteList(scripts);
    return retval;
--- 695,702 ----
        break;
      }
  
!     run_script(scriptGetCode(script), me, me_type, ch, obj, room, cmd, 
! 	       arg, narg);    
    }
    deleteList(scripts);
    return retval;
diff -crN nakedmudv1.4/src/scripts/script.h nakedmudv1.5/src/scripts/script.h
*** nakedmudv1.4/src/scripts/script.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/scripts/script.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 199,205 ****
  #define SCRIPTOR_CHAR           0
  #define SCRIPTOR_ROOM           1
  #define SCRIPTOR_OBJ            2
- #define SCRIPTOR_EXIT           3
  
  //
  // initialize the scripting system
--- 199,204 ----
***************
*** 216,222 ****
  // start up a script
  //
  void run_script(const char *script, void *me, int me_type,
! 		CHAR_DATA *ch, OBJ_DATA *obj, ROOM_DATA *room, EXIT_DATA *exit, 
  		const char *cmd, const char *arg, int narg);
  
  //
--- 215,221 ----
  // start up a script
  //
  void run_script(const char *script, void *me, int me_type,
! 		CHAR_DATA *ch, OBJ_DATA *obj, ROOM_DATA *room,
  		const char *cmd, const char *arg, int narg);
  
  //
***************
*** 242,255 ****
  //
  // Try enterance scripts in the given room (the room itself, and mobs)
  //
! void try_enterance_script(CHAR_DATA *ch, ROOM_DATA *room, 
! 			  EXIT_DATA *exit, const char *dirname);
  
  //
  // Try exit scripts in the given room (the room itself, and mobs)
  //
! void try_exit_script(CHAR_DATA *ch, ROOM_DATA *room, 
! 		     EXIT_DATA *exit, const char *dirname);
  
  //
  // Searches for command scripts in the room. If the actual command should
--- 241,252 ----
  //
  // Try enterance scripts in the given room (the room itself, and mobs)
  //
! void try_enterance_script(CHAR_DATA *ch, ROOM_DATA *room, const char *dirname);
  
  //
  // Try exit scripts in the given room (the room itself, and mobs)
  //
! void try_exit_script(CHAR_DATA *ch, ROOM_DATA *room, const char *dirname);
  
  //
  // Searches for command scripts in the room. If the actual command should
***************
*** 267,273 ****
  //
  int try_scripts(int script_type,
  		void *me, int me_type,
! 		CHAR_DATA *ch, OBJ_DATA *obj, ROOM_DATA *room, EXIT_DATA *exit,
  		const char *cmd, const char *arg, int narg);
  
  #endif //__SCRIPT_H
--- 264,270 ----
  //
  int try_scripts(int script_type,
  		void *me, int me_type,
! 		CHAR_DATA *ch, OBJ_DATA *obj, ROOM_DATA *room,
  		const char *cmd, const char *arg, int narg);
  
  #endif //__SCRIPT_H
diff -crN nakedmudv1.4/src/set.c nakedmudv1.5/src/set.c
*** nakedmudv1.4/src/set.c	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/src/set.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,195 ----
+ //*****************************************************************************
+ //
+ // set.h
+ //
+ // a non-ordered container that has constant lookup time.
+ //
+ //*****************************************************************************
+ 
+ #include <stdlib.h>
+ #include "list.h"
+ #include "set.h"
+ 
+ struct set_data {
+   int       num_buckets;
+   struct list **buckets;
+ };
+ 
+ struct set_iterator {
+   int                curr_bucket; // the bucket number we're currently on
+   struct set_data           *set; // the set we're iterating over
+   struct list_iterator *bucket_i; // the iterator for our current bucket
+ };
+ 
+ 
+ //*****************************************************************************
+ //
+ // local functions
+ //
+ //*****************************************************************************
+ 
+ 
+ //
+ // Find the bucket the set element belongs to
+ //
+ int set_elem_bucket(void *elem, int num_buckets) {
+   // simple for now: just take the modulo
+   return ((int)elem) % num_buckets;
+ };
+ 
+ 
+ //*****************************************************************************
+ //
+ // implementation of set.h
+ //
+ //*****************************************************************************
+ struct set_data *newSet(int num_buckets) {
+   int i;
+ 
+   struct set_data *set = malloc(sizeof(struct set_data));
+   set->buckets = malloc(sizeof(struct list *) * num_buckets);
+ 
+   // all NULL until they actually get a content
+   for(i = 0; i < num_buckets; i++)
+     set->buckets[i] = NULL;
+   set->num_buckets = num_buckets;
+ 
+   return set;
+ };
+ 
+ 
+ void deleteSet(struct set_data *set) {
+   int i;
+ 
+   for(i = 0; i < set->num_buckets; i++)
+     if(set->buckets[i] != NULL)
+       deleteList(set->buckets[i]);
+ 
+   free(set->buckets);
+   free(set);
+ };
+ 
+ 
+ void setPut(struct set_data *set, void *elem) {
+   // find out what bucket we belong to
+   int hash_bucket = set_elem_bucket(elem, set->num_buckets);
+ 
+   // add us to the bucket
+   if(set->buckets[hash_bucket] == NULL)
+     set->buckets[hash_bucket] = newList();
+   // listPut ensures only one copy is in the list
+   listPut(set->buckets[hash_bucket], elem);
+ };
+ 
+ 
+ void setRemove(struct set_data *set, void *elem) {
+   // find out what bucket we belong to
+   int hash_bucket = set_elem_bucket(elem, set->num_buckets);
+ 
+   // see if the bucket exists
+   if(set->buckets[hash_bucket] != NULL)
+     listRemove(set->buckets[hash_bucket], elem);
+ };
+ 
+ 
+ int setIn(struct set_data *set, void *elem) {
+   // find out what bucket we belong to
+   int hash_bucket = set_elem_bucket(elem, set->num_buckets);
+ 
+   if(set->buckets[hash_bucket] != NULL)
+     return listIn(set->buckets[hash_bucket], elem);
+   else
+     return 0;
+ };
+ 
+ 
+ //*****************************************************************************
+ //
+ // set iterator
+ //
+ // we may sometimes want to iterate across all of the elements in a set.
+ // this lets us do so.
+ //
+ //*****************************************************************************
+ struct set_iterator *newSetIterator(struct set_data *S) {
+   struct set_iterator *I = malloc(sizeof(struct set_iterator));
+ 
+   I->set = S;
+   I->curr_bucket = 0;
+   I->bucket_i = NULL;
+   setIteratorReset(I);
+ 
+   return I;
+ }
+ 
+ 
+ void deleteSetIterator(struct set_iterator *I) {
+   if(I->bucket_i) deleteListIterator(I->bucket_i);
+   free(I);
+ }
+ 
+ 
+ void setIteratorReset(struct set_iterator *I) {
+   int i;
+ 
+   if(I->bucket_i) 
+     deleteListIterator(I->bucket_i);
+   I->bucket_i = NULL;
+   I->curr_bucket = 0;
+ 
+   for(i = 0; i < I->set->num_buckets; i++) {
+     if(I->set->buckets[i] == NULL)
+       continue;
+     if(isListEmpty(I->set->buckets[i]))
+       continue;
+     else {
+       I->curr_bucket = i;
+       I->bucket_i = newListIterator(I->set->buckets[i]);
+       break;
+     }
+   }
+ }
+ 
+ 
+ void *setIteratorNext(struct set_iterator *I) {
+   // we have no iterator ... we have no elements left to iterate over!
+   if(I->bucket_i == NULL)
+     return NULL;
+   else {
+     void *elem = listIteratorNext(I->bucket_i);
+     // we're okay ... we have an element
+     if(elem != NULL)
+       return elem;
+     // otherwise, we need to move onto a new bucket
+     else {
+       deleteListIterator(I->bucket_i);
+       I->bucket_i = NULL;
+ 
+       I->curr_bucket++;
+       // find the next non-empty list
+       for(; I->curr_bucket < I->set->num_buckets; I->curr_bucket++) {
+ 	if(I->set->buckets[I->curr_bucket] == NULL)
+ 	  continue;
+ 	if(isListEmpty(I->set->buckets[I->curr_bucket]))
+ 	  continue;
+ 	I->bucket_i = newListIterator(I->set->buckets[I->curr_bucket]);
+ 	break;
+       }
+ 
+       // we've ran out of buckets!
+       if(I->curr_bucket == I->set->num_buckets)
+ 	return NULL;
+       else
+ 	return listIteratorCurrent(I->bucket_i);
+     }
+   }
+ }
+ 
+ 
+ void *setIteratorCurrent(struct set_iterator *I) {
+   // we have no elements!
+   if(I->bucket_i == NULL)
+     return NULL;
+   else
+     return listIteratorCurrent(I->bucket_i);
+ }
diff -crN nakedmudv1.4/src/set.h nakedmudv1.5/src/set.h
*** nakedmudv1.4/src/set.h	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/src/set.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,34 ----
+ #ifndef SET_H
+ #define SET_H
+ //*****************************************************************************
+ //
+ // set.h
+ //
+ // a non-ordered container that has constant lookup time.
+ //
+ //*****************************************************************************
+ 
+ struct set_data  *newSet(int buckets);
+ void           deleteSet(struct set_data *set);
+ void              setPut(struct set_data *set, void *elem);
+ void           setRemove(struct set_data *set, void *elem);
+ int                setIn(struct set_data *set, void *elem);
+ 
+ 
+ 
+ //*****************************************************************************
+ //
+ // set iterator
+ //
+ // we may sometimes want to iterate across all of the elements in a set.
+ // this lets us do so.
+ //
+ //*****************************************************************************
+ 
+ struct set_iterator *newSetIterator(struct set_data *S);
+ void              deleteSetIterator(struct set_iterator *I);
+ void               setIteratorReset(struct set_iterator *I);
+ void               *setIteratorNext(struct set_iterator *I);
+ void            *setIteratorCurrent(struct set_iterator *I);
+ 
+ #endif // SET_H
diff -crN nakedmudv1.4/src/shop.c nakedmudv1.5/src/shop.c
*** nakedmudv1.4/src/shop.c	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/src/shop.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,14 ----
+ //*****************************************************************************
+ //
+ // shop.c
+ //
+ // Shops allow mobs or containers to act as stores for selling and buying
+ // other objects.
+ //
+ //*****************************************************************************
+ 
+ struct shop_data {
+ 
+ };
+ 
+ 
diff -crN nakedmudv1.4/src/shop.h nakedmudv1.5/src/shop.h
*** nakedmudv1.4/src/shop.h	1969-12-31 18:00:00.000000000 -0600
--- nakedmudv1.5/src/shop.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 0 ****
--- 1,23 ----
+ #ifndef __SHOP_H
+ #define __SHOP_H
+ 
+ //*****************************************************************************
+ //
+ // shop.h
+ //
+ // Shops allow mobs or containers to act as stores for selling and buying
+ // other objects.
+ //
+ //*****************************************************************************
+ 
+ 
+ 
+ SHOP_DATA *newShop   (shop_vnum vnum);
+ void       deleteShop(SHOP_DATA *shop);
+ 
+ void       shopCopyTo(SHOP_DATA *from, SHOP_DATA *to);
+ SHOP_DATA *shopCopy  (SHOP_DATA *shop);
+ 
+ 
+ 
+ #endif // __SHOP_H
diff -crN nakedmudv1.4/src/socials/socials.c nakedmudv1.5/src/socials/socials.c
*** nakedmudv1.4/src/socials/socials.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/socials/socials.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 52,58 ****
      listPut(soc_list, data);
    deleteHashIterator(hash_i);
  
!   store_list(set, "socials", gen_store_list(soc_list, socialStore), NULL);
    deleteList(soc_list);
  
    // write the set
--- 52,58 ----
      listPut(soc_list, data);
    deleteHashIterator(hash_i);
  
!   store_list(set, "socials", gen_store_list(soc_list, socialStore));
    deleteList(soc_list);
  
    // write the set
***************
*** 123,138 ****
  
  STORAGE_SET *socialStore(SOCIAL_DATA *data) {
    STORAGE_SET *set = new_storage_set();
!   store_string(set, "cmds",          data->cmds,                NULL);
!   store_string(set, "to_char_notgt", data->to_char_notgt,       NULL);
!   store_string(set, "to_room_notgt", data->to_room_notgt,       NULL);
!   store_string(set, "to_char_self",  data->to_char_self,        NULL);
!   store_string(set, "to_room_self",  data->to_room_self,        NULL);
!   store_string(set, "to_char_tgt",   data->to_char_tgt,         NULL);
!   store_string(set, "to_vict_tgt",   data->to_vict_tgt,         NULL);
!   store_string(set, "to_room_tgt",   data->to_room_tgt,         NULL);
!   store_string(set, "min_pos",       posGetName(data->min_pos), NULL);
!   store_string(set, "max_pos",       posGetName(data->max_pos), NULL);
    return set;
  }
  
--- 123,138 ----
  
  STORAGE_SET *socialStore(SOCIAL_DATA *data) {
    STORAGE_SET *set = new_storage_set();
!   store_string(set, "cmds",          data->cmds);
!   store_string(set, "to_char_notgt", data->to_char_notgt);
!   store_string(set, "to_room_notgt", data->to_room_notgt);
!   store_string(set, "to_char_self",  data->to_char_self);
!   store_string(set, "to_room_self",  data->to_room_self);
!   store_string(set, "to_char_tgt",   data->to_char_tgt);
!   store_string(set, "to_vict_tgt",   data->to_vict_tgt);
!   store_string(set, "to_room_tgt",   data->to_room_tgt);
!   store_string(set, "min_pos",       posGetName(data->min_pos));
!   store_string(set, "max_pos",       posGetName(data->max_pos));
    return set;
  }
  
diff -crN nakedmudv1.4/src/socket.c nakedmudv1.5/src/socket.c
*** nakedmudv1.4/src/socket.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/socket.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 687,692 ****
--- 687,693 ----
  {
    if(sock_new->page_string) free(sock_new->page_string);
    if(sock_new->text_editor) buffer_free(sock_new->text_editor);
+   if(sock_new->notepad)     free(sock_new->notepad);
  
    bzero(sock_new, sizeof(*sock_new));
    sock_new->control        =  sock;
***************
*** 697,702 ****
--- 698,704 ----
  
    sock_new->text_editor    = NULL;
    sock_new->text_pointer   = NULL;
+   sock_new->notepad        = NULL;
    sock_new->in_text_edit   = FALSE;
    sock_new->max_text_len   = 0;
  
diff -crN nakedmudv1.4/src/socket.h nakedmudv1.5/src/socket.h
*** nakedmudv1.4/src/socket.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/socket.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 34,39 ****
--- 34,40 ----
    bool            in_text_edit;  // are we doing text editing?
    BUFFER        * text_editor;   // where we do our actual work
    char         ** text_pointer;  // where the work will go to
+   char          * notepad;       // a buffer for writing messages of any type
    int             max_text_len;  // the max length we are allowed
    int             editor_mode;   // what mode are we running the editor under?
    int             indent;        // how far do we indent (script editing)
diff -crN nakedmudv1.4/src/storage.c nakedmudv1.5/src/storage.c
*** nakedmudv1.4/src/storage.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/storage.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 26,32 ****
  #define LIST_MARKER           '='
  #define STRING_MARKER         '~'
  #define TYPELESS_MARKER       ' '
- #define COMMENT_MARKER        '#'
  
  
  struct storage_set {
--- 26,31 ----
***************
*** 57,63 ****
  bool list_is_empty(STORAGE_SET_LIST *list);
  bool set_is_empty (STORAGE_SET *set);
  
- void write_storage_comment(FILE *fl, const char *comment, int indent);
  void write_storage_set(STORAGE_SET *set, FILE *fl, int indent);
  void write_storage_list(STORAGE_SET_LIST *list, FILE *fl, int indent);
  void write_storage_data(STORAGE_DATA *data, FILE *fl, int key_width,int indent);
--- 56,61 ----
***************
*** 147,161 ****
  
  
  //
- // write a comment to file
- //
- void write_storage_comment(FILE *fl, const char *comment, int indent) {
-   print_indent(fl, indent);
-   fprintf(fl, "%c %s\n", COMMENT_MARKER, comment);
- }
- 
- 
- //
  // Print a key and the key delimeter to file
  //
  void print_key(FILE *fl, const char *key, int key_width, int indent) {
--- 145,150 ----
***************
*** 365,381 ****
  
  
  //
- // Parse out the comments that are next. If none exist, return NULL
- //
- char *parse_comments(FILE *fl, int indent) {
-   //***********
-   // FINISH ME
-   //***********
-   return NULL;
- }
- 
- 
- //
  // return the type of the data we're dealing with. It is assumed
  // this will be called IMMEDIATELY after parse_key is called
  //
--- 354,359 ----
***************
*** 468,474 ****
      switch(type) {
      case TYPELESS_MARKER: {
        char *line = parse_line(fl);
!       store_string(set, key, line, NULL);
        free(line);
        break;
      }
--- 446,452 ----
      switch(type) {
      case TYPELESS_MARKER: {
        char *line = parse_line(fl);
!       store_string(set, key, line);
        free(line);
        break;
      }
***************
*** 476,494 ****
      case STRING_MARKER: {
        fgetc(fl); // kill the newline
        char *string = parse_string(fl, indent+2);
!       store_string(set, key, string, NULL);
        free(string);
        break;
      }
  
      case SET_MARKER:
        fgetc(fl); // kill the newline
!       store_set(set, key, parse_storage_set(fl, indent+2), NULL);
        break;
  
      case LIST_MARKER:
        fgetc(fl); // kill the newline
!       store_list(set, key, parse_storage_list(fl, indent+2), NULL);
        break;
      }
      free(key);
--- 454,472 ----
      case STRING_MARKER: {
        fgetc(fl); // kill the newline
        char *string = parse_string(fl, indent+2);
!       store_string(set, key, string);
        free(string);
        break;
      }
  
      case SET_MARKER:
        fgetc(fl); // kill the newline
!       store_set(set, key, parse_storage_set(fl, indent+2));
        break;
  
      case LIST_MARKER:
        fgetc(fl); // kill the newline
!       store_list(set, key, parse_storage_list(fl, indent+2));
        break;
      }
      free(key);
***************
*** 576,608 ****
  }
  
  
! void   store_set(STORAGE_SET *set, const char *key, STORAGE_SET *val,
! 		 const char *comment) {
    storage_put(set, new_data_set(val, key));
  }
  
! void   store_list(STORAGE_SET *set, const char *key, STORAGE_SET_LIST *val,
! 		  const char *comment) {
    storage_put(set, new_data_list(val, key));
  }
  
! void store_string(STORAGE_SET *set, const char *key, const char *val,
! 		  const char *comment) {
    storage_put(set, new_data_string(val, key));
  }
  
! void store_double(STORAGE_SET *set, const char *key, double val, 
! 		  const char *comment) {
    storage_put(set, new_data_double(val, key));
  }
  
! void store_int(STORAGE_SET *set, const char *key, int val, 
! 	       const char *comment) {
    storage_put(set, new_data_int(val, key));
  }
  
! void store_long(STORAGE_SET *set, const char *key, long val, 
! 	       const char *comment) {
    storage_put(set, new_data_long(val, key));
  }
  
--- 554,580 ----
  }
  
  
! void   store_set(STORAGE_SET *set, const char *key, STORAGE_SET *val) {
    storage_put(set, new_data_set(val, key));
  }
  
! void   store_list(STORAGE_SET *set, const char *key, STORAGE_SET_LIST *val) {
    storage_put(set, new_data_list(val, key));
  }
  
! void store_string(STORAGE_SET *set, const char *key, const char *val) {
    storage_put(set, new_data_string(val, key));
  }
  
! void store_double(STORAGE_SET *set, const char *key, double val) {
    storage_put(set, new_data_double(val, key));
  }
  
! void store_int(STORAGE_SET *set, const char *key, int val) {
    storage_put(set, new_data_int(val, key));
  }
  
! void store_long(STORAGE_SET *set, const char *key, long val) {
    storage_put(set, new_data_long(val, key));
  }
  
***************
*** 611,617 ****
    if(data) 
      return data->set_val;
    else {
!     store_set(set, key, new_storage_set(), NULL);
      return read_set(set, key);
    }
  }
--- 583,589 ----
    if(data) 
      return data->set_val;
    else {
!     store_set(set, key, new_storage_set());
      return read_set(set, key);
    }
  }
***************
*** 621,627 ****
    if(data) 
      return data->list_val;
    else {
!     store_list(set, key, new_storage_list(), NULL);
      return read_list(set, key);
    }
  }
--- 593,599 ----
    if(data) 
      return data->list_val;
    else {
!     store_list(set, key, new_storage_list());
      return read_list(set, key);
    }
  }
diff -crN nakedmudv1.4/src/storage.h nakedmudv1.5/src/storage.h
*** nakedmudv1.4/src/storage.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/storage.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 59,76 ****
  //
  // store various datatypes to the storage data
  //
! void    store_set(STORAGE_SET *set, const char *key, STORAGE_SET *val,
! 		  const char *comment);
! void   store_list(STORAGE_SET *set, const char *key, STORAGE_SET_LIST *val,
! 		  const char *comment);
! void store_string(STORAGE_SET *set, const char *key, const char *val,
! 		  const char *comment);
! void store_double(STORAGE_SET *set, const char *key, double val,
! 		  const char *comment);
! void    store_int(STORAGE_SET *set, const char *key, int val,
! 		  const char *comment);
! void   store_long(STORAGE_SET *set, const char *key, long val,
! 		  const char *comment);
  
  
  //
--- 59,70 ----
  //
  // store various datatypes to the storage data
  //
! void    store_set(STORAGE_SET *set, const char *key, STORAGE_SET *val);
! void   store_list(STORAGE_SET *set, const char *key, STORAGE_SET_LIST *val);
! void store_string(STORAGE_SET *set, const char *key, const char *val);
! void store_double(STORAGE_SET *set, const char *key, double val);
! void    store_int(STORAGE_SET *set, const char *key, int val);
! void   store_long(STORAGE_SET *set, const char *key, long val);
  
  
  //
diff -crN nakedmudv1.4/src/text_editor.c nakedmudv1.5/src/text_editor.c
*** nakedmudv1.4/src/text_editor.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/text_editor.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 274,282 ****
        break;
  
      case 'l':
!     case 'L':
        text_editor_display(sock, sock->editor_mode, TRUE);
        break;
  
      case 'f':
      case 'F':
--- 274,291 ----
        break;
  
      case 'l':
!     case 'L': {
        text_editor_display(sock, sock->editor_mode, TRUE);
+       if(sock->editor_mode == EDITOR_MODE_NORMAL) {
+ 	int linecount = 0;
+ 	if(buffer_string(sock->text_editor))
+ 	  linecount = count_letters(buffer_string(sock->text_editor), '\n', 
+ 				    strlen(buffer_string(sock->text_editor)));
+ 	send_to_socket(sock, "%d line%s displayed.\r\n", linecount,
+ 		       (linecount == 1 ? "" : "s"));
+       }
        break;
+     }
  
      case 'f':
      case 'F':
***************
*** 393,398 ****
--- 402,413 ----
    }
  }
  
+ void start_notepad(SOCKET_DATA *sock, const char *txt, int max_len, 
+ 		   int mode) {
+   if(sock->notepad) free(sock->notepad);
+   sock->notepad = strdup(txt ? txt : "");
+   start_text_editor(sock, &sock->notepad, max_len, mode);
+ }
  
  void start_text_editor( SOCKET_DATA *sock, char **text, int max_len, int mode) {
    // we're already in edit mode ... don't mess around
diff -crN nakedmudv1.4/src/text_editor.h nakedmudv1.5/src/text_editor.h
*** nakedmudv1.4/src/text_editor.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/text_editor.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 16,20 ****
--- 16,22 ----
  
  void start_text_editor(SOCKET_DATA *sock, char **text, int max_len, int mode);
  void text_editor_loop (SOCKET_DATA *sock, char *arg);
+ void start_notepad    (SOCKET_DATA *sock, const char *txt, int max_len, 
+ 		       int mode);
  
  #endif //__TEXT_EDITOR_H
diff -crN nakedmudv1.4/src/time/mudtime.h nakedmudv1.5/src/time/mudtime.h
*** nakedmudv1.4/src/time/mudtime.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/time/mudtime.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 4,10 ****
  //
  // mudtime.h
  //
! // A small module for handling time of day in the MUD.
  //
  //*****************************************************************************
  
--- 4,11 ----
  //
  // mudtime.h
  //
! // We can't use time.c, because it is a standard C header. A small module for
! // handling time of day in the MUD.
  //
  //*****************************************************************************
  
diff -crN nakedmudv1.4/src/time/time.c nakedmudv1.5/src/time/time.c
*** nakedmudv1.4/src/time/time.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/time/time.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 102,108 ****
  
  STORAGE_SET *timeAuxDataStore(TIME_AUX_DATA *data) {
    STORAGE_SET *set = new_storage_set();
!   store_string(set, "night_desc", data->night_desc, NULL);
    return set;
  }
  
--- 102,108 ----
  
  STORAGE_SET *timeAuxDataStore(TIME_AUX_DATA *data) {
    STORAGE_SET *set = new_storage_set();
!   store_string(set, "night_desc", data->night_desc);
    return set;
  }
  
***************
*** 174,192 ****
  
    // save our time data to file
    STORAGE_SET *set = new_storage_set();
!   store_int(set, "hour",         curr_hour,         NULL);
!   store_int(set, "day_of_week",  curr_day_of_week,  NULL);
!   store_int(set, "day_of_month", curr_day_of_month, NULL);
!   store_int(set, "month",        curr_month,        NULL);
!   store_int(set, "year",         curr_year,         NULL);
    storage_write(set, TIME_FILE);
    storage_close(set);
- 
-   // throw ourself back into the event queue
-   start_event(NULL,
- 	      TIME_UPDATE_DELAY,
- 	      handle_time_update,
- 	      NULL, NULL, NULL);
  }
  
  
--- 174,186 ----
  
    // save our time data to file
    STORAGE_SET *set = new_storage_set();
!   store_int(set, "hour",         curr_hour);
!   store_int(set, "day_of_week",  curr_day_of_week);
!   store_int(set, "day_of_month", curr_day_of_month);
!   store_int(set, "month",        curr_month);
!   store_int(set, "year",         curr_year);
    storage_write(set, TIME_FILE);
    storage_close(set);
  }
  
  
***************
*** 216,225 ****
  				       timeAuxDataStore, timeAuxDataRead));
  
    // start our time updater
!   start_event(NULL,
! 	      TIME_UPDATE_DELAY,
! 	      handle_time_update,
! 	      NULL, NULL, NULL);
  }
  
  
--- 210,216 ----
  				       timeAuxDataStore, timeAuxDataRead));
  
    // start our time updater
!   start_update(NULL, TIME_UPDATE_DELAY, handle_time_update, NULL, NULL, NULL);
  }
  
  
diff -crN nakedmudv1.4/src/update.c nakedmudv1.5/src/update.c
*** nakedmudv1.4/src/update.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/update.c	1969-12-31 18:00:00.000000000 -0600
***************
*** 1,14 ****
- /*
-  * This file contains all the update functions.
-  */
- #include <sys/types.h>
- #include <stdio.h>
- 
- /* include main header file */
- #include "mud.h"
- #include "world.h"
- #include "action.h"
- #include "event.h"
- 
- 
- 
--- 0 ----
diff -crN nakedmudv1.4/src/utils.c nakedmudv1.5/src/utils.c
*** nakedmudv1.4/src/utils.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/utils.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 25,31 ****
  #include "dialog.h"
  #include "event.h"
  #include "action.h"
- #include "help.h"
  
  
  // optional modules
--- 25,30 ----
***************
*** 91,101 ****
  #endif
    interrupt_events_involving(ch);
  
- #ifdef MODULE_FIGHT
-   stop_all_targetting(ch);
-   stop_fight(ch);
- #endif
- 
    // unequip everything the character is wearing
    // and send it to inventory
    unequip_all(ch);
--- 90,95 ----
***************
*** 157,166 ****
  
  
  /*
!  * Loading of help files, areas, etc, at boot time.
   */
  void load_muddata(bool fCopyOver) {  
-   load_helps();
    gameworld = worldLoad(WORLD_PATH);
    if(gameworld == NULL) {
      log_string("ERROR: Could not boot game world.");
--- 151,159 ----
  
  
  /*
!  * load the world and its inhabitants, as well as other misc game data
   */
  void load_muddata(bool fCopyOver) {  
    gameworld = worldLoad(WORLD_PATH);
    if(gameworld == NULL) {
      log_string("ERROR: Could not boot game world.");
***************
*** 330,335 ****
--- 323,330 ----
      return TRUE;
    if(poscmp(charGetPos(ch), POS_SLEEPING) <= 0)
      return FALSE;
+   if(charGetImmInvis(target) > charGetLevel(ch))
+     return FALSE;
  
    return TRUE;
  }
***************
*** 857,862 ****
--- 852,892 ----
  
  
  //
+ // print the string on the buffer, centered for a line of length linelen.
+ // if border is TRUE, put a border to either side of the string.
+ //
+ void center_string(char *buf, const char *string, int linelen, int buflen, 
+ 		   bool border) {
+   static char fmt[32];
+   int str_len = strlen(string);
+   int spaces  = (linelen - str_len)/2;
+ 
+   if(border) {
+     int i, buf_i = 0;
+     sprintf(fmt, "{g%%-%ds[{c", spaces-2);
+     buf_i  = snprintf(buf, buflen, fmt, " ");
+     // replace all of the spaces with -
+     for(i = 0; buf[i] != '\0'; i++) if(buf[i] == ' ') buf[i] = '-';
+ 
+     buf_i += snprintf(buf+buf_i, buflen-buf_i, " %s ", string);
+     sprintf(fmt, "{g]%%-%ds\r\n", 
+ 	    spaces-2 + (((linelen-str_len) % 2) == 1 ? 1 : 0));
+ 
+     i = buf_i;
+     buf_i += snprintf(buf+buf_i, buflen-buf_i, fmt, " ");
+     // replace all of the spaces with -
+     for(; buf[i] != '\0'; i++) if(buf[i] == ' ') buf[i] = '-';
+   }
+   else {
+     int buf_i = 0;
+     sprintf(fmt, "%%-%ds", spaces);
+     buf_i  = snprintf(buf, buflen, fmt, " ");
+     buf_i += snprintf(buf+buf_i, buflen-buf_i, "%s\r\n", string);
+   }
+ }
+ 
+ 
+ //
  // fill up the buffer with characters until
  // a newline is reached, or we hit our critical
  // length. Return how many characters were read
***************
*** 1163,1172 ****
  }
  
  
! void show_list(CHAR_DATA *ch, LIST *list, 
! 	       void *descriptor, void *multi_descriptor) {
    const char             *(* desc_func)(void *) = descriptor;
    const char            *(* multi_desc)(void *) = multi_descriptor;
  
    int i;
    int size = listSize(list);
--- 1193,1203 ----
  }
  
  
! void show_list(CHAR_DATA *ch, LIST *list, void *descriptor, 
! 	       void *multi_descriptor, void *vnum_getter) {
    const char             *(* desc_func)(void *) = descriptor;
    const char            *(* multi_desc)(void *) = multi_descriptor;
+   int                    (*  vnum_func)(void *) = vnum_getter;
  
    int i;
    int size = listSize(list);
***************
*** 1205,1218 ****
      // we've run into the end of the list
      if(things[i] == NULL)
        break;
-     if(counts[i] == 1)
-       send_to_char(ch, "%s\r\n", desc_func(things[i]));
-     else if(multi_desc == NULL || !*multi_desc(things[i]))
-       send_to_char(ch, "(%d) %s\r\n", counts[i], desc_func(things[i]));
      else {
!       char fmt[SMALL_BUFFER];
!       sprintf(fmt, "%s\r\n", multi_desc(things[i]));
!       send_to_char(ch, fmt, counts[i]);
      }
    }
  }
--- 1236,1258 ----
      // we've run into the end of the list
      if(things[i] == NULL)
        break;
      else {
!       char vnum_buf[20];
!       if(charGetLevel(ch) < LEVEL_BUILDER || vnum_func == NULL)
! 	*vnum_buf = '\0';
!       else
! 	sprintf(vnum_buf, "[%d] ", vnum_func(things[i]));
! 
!       if(counts[i] == 1)
! 	send_to_char(ch, "%s%s\r\n", vnum_buf, desc_func(things[i]));
!       else if(multi_desc == NULL || !*multi_desc(things[i]))
! 	send_to_char(ch, "%s(%d) %s\r\n", vnum_buf, 
! 		     counts[i], desc_func(things[i]));
!       else {
! 	char fmt[SMALL_BUFFER];
! 	sprintf(fmt, "%s%s\r\n", vnum_buf, multi_desc(things[i]));
! 	send_to_char(ch, fmt, counts[i]);
!       }
      }
    }
  }
***************
*** 1263,1270 ****
  
  const char *custom_prompt(CHAR_DATA *ch) {
    static char prompt[MAX_BUFFER];
!   *prompt = '\0';
!   strcat(prompt, "\r\nprompt> ");
!     
    return prompt;
  }
--- 1303,1308 ----
  
  const char *custom_prompt(CHAR_DATA *ch) {
    static char prompt[MAX_BUFFER];
!   sprintf(prompt, "\r\nprompt> ");
    return prompt;
  }
diff -crN nakedmudv1.4/src/utils.h nakedmudv1.5/src/utils.h
*** nakedmudv1.4/src/utils.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/utils.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 101,107 ****
  void format_string        (char **ptr_string, int max_width, 
  		          unsigned int maxlen, bool indent);
  int  count_letters        (const char *string, const char ch, const int strlen);
! int   fgetline            (FILE *file, char *p, int maxlen);
  
  
  
--- 101,109 ----
  void format_string        (char **ptr_string, int max_width, 
  		          unsigned int maxlen, bool indent);
  int  count_letters        (const char *string, const char ch, const int strlen);
! int  fgetline             (FILE *file, char *p, int maxlen);
! void center_string        (char *buf, const char *string, int linelen, 
! 			   int buflen, bool border);
  
  
  
***************
*** 138,143 ****
--- 140,153 ----
        mapIteratorNext(it), \
        key = mapIteratorCurrentKey(it), val = mapIteratorCurrentVal(it))
  
+ // iterate across all the elements in a set
+ #define ITERATE_SET(elem, it) \
+   for(elem = setIteratorCurrent(it); \
+       elem != NULL; \
+       setIteratorNext(it), elem = setIteratorCurrent(it))
+ 
+ 
+ 
  
  //
  // count how many objects are in the list, that meet our critereon.
***************
*** 199,206 ****
  // multi-descriptor is a pointer to the function that gets a copy of the
  // thing's description if there is more than 1 copy of it in the list.
  //
! void show_list(CHAR_DATA *ch, LIST *list, 
! 	       void *descriptor, void *multi_descriptor);
  
  
  //
--- 209,220 ----
  // multi-descriptor is a pointer to the function that gets a copy of the
  // thing's description if there is more than 1 copy of it in the list.
  //
! // vnum_getter is a pointer to a function that returns the thing's vnum for
! // displaying to players of builder level and above. vnum_getter can be NULL 
! // to display no vnums.
! //
! void show_list(CHAR_DATA *ch, LIST *list, void *descriptor, 
! 	       void *multi_descriptor, void *vnum_getter);
  
  
  //
diff -crN nakedmudv1.4/src/world.c nakedmudv1.5/src/world.c
*** nakedmudv1.4/src/world.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/world.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 185,191 ****
    char buf[MAX_BUFFER];
    STORAGE_SET       *set = new_storage_set();
    STORAGE_SET_LIST *list = new_storage_list();
!   store_list(set, "zones", list, NULL);
  
    LIST_ITERATOR *zone_i = newListIterator(world->zones);
    ZONE_DATA       *zone = NULL;
--- 185,191 ----
    char buf[MAX_BUFFER];
    STORAGE_SET       *set = new_storage_set();
    STORAGE_SET_LIST *list = new_storage_list();
!   store_list(set, "zones", list);
  
    LIST_ITERATOR *zone_i = newListIterator(world->zones);
    ZONE_DATA       *zone = NULL;
***************
*** 198,204 ****
  
      if(zoneSave(zone, buf)) {
        STORAGE_SET *zone_set = new_storage_set();
!       store_int(zone_set, "vnum", zoneGetVnum(zone), NULL);
        storage_list_put(list, zone_set);
      }
    }
--- 198,204 ----
  
      if(zoneSave(zone, buf)) {
        STORAGE_SET *zone_set = new_storage_set();
!       store_int(zone_set, "vnum", zoneGetVnum(zone));
        storage_list_put(list, zone_set);
      }
    }
diff -crN nakedmudv1.4/src/zone.c nakedmudv1.5/src/zone.c
*** nakedmudv1.4/src/zone.c	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/zone.c	2010-11-01 15:54:17.000000000 -0500
***************
*** 13,21 ****
  #include "object.h"
  #include "character.h"
  #include "room.h"
- #include "zone.h"
  #include "utils.h"
  #include "dialog.h"
  
  #ifdef MODULE_SCRIPTS
  #include "scripts/script.h"
--- 13,22 ----
  #include "object.h"
  #include "character.h"
  #include "room.h"
  #include "utils.h"
+ #include "auxiliary.h"
  #include "dialog.h"
+ #include "zone.h"
  
  #ifdef MODULE_SCRIPTS
  #include "scripts/script.h"
***************
*** 40,47 ****
--- 41,51 ----
  
    int pulse_timer;  // the timer duration
    int pulse;        // how far down have we gone?
+ 
+   HASHTABLE            * auxiliary_data; // additional data installed on us
  };
  
+ 
  ZONE_DATA *newZone(zone_vnum vnum, room_vnum min, room_vnum max) {
    ZONE_DATA *zone = malloc(sizeof(ZONE_DATA));
    zone->name    = strdup("");
***************
*** 64,69 ****
--- 68,75 ----
    zone->mob_protos = newPropertyTable(charGetVnum,    1 + (max-min)/5);
    zone->obj_protos = newPropertyTable(objGetVnum,    1 + (max-min)/5);
  
+   zone->auxiliary_data = newAuxiliaryData(AUXILIARY_TYPE_ZONE);
+ 
    return zone;
  }
  
***************
*** 82,87 ****
--- 88,94 ----
    to->max  = from->max;
    to->pulse_timer = from->pulse_timer;
    to->pulse = from->pulse;
+   auxiliaryDataCopyTo(from->auxiliary_data, to->auxiliary_data);
  }
  
  void deleteZone(ZONE_DATA *zone){ 
***************
*** 95,100 ****
--- 102,109 ----
    deletePropertyTable(zone->mob_protos);
    deletePropertyTable(zone->obj_protos);
  
+   deleteAuxiliaryData(zone->auxiliary_data);
+ 
    //*******************************************************************
    // The only time we're deleting a zone is when we're editing the copy
    // in OLC. So, We don't want to delete any of the zone's content when
***************
*** 158,163 ****
--- 167,177 ----
    zoneSetName(zone,   read_string(set, "name"));
    zoneSetDescription(zone,   read_string(set, "desc"));
    zoneSetEditors(zone,read_string(set, "editors"));
+ 
+   deleteAuxiliaryData(zone->auxiliary_data);
+   zone->auxiliary_data = auxiliaryDataRead(read_set(set, "auxiliary"), 
+ 					   AUXILIARY_TYPE_ZONE);
+ 
    storage_close(set);
  
    // now, load all of the content data
***************
*** 204,210 ****
    STORAGE_SET       *set = new_storage_set();
    STORAGE_SET_LIST *list = new_storage_list();
    void             *data = NULL;
!   store_list(set, "list", list, NULL);
  
    int i = zoneGetMinBound(zone);
    for(; i <= zoneGetMaxBound(zone); i++) {
--- 218,224 ----
    STORAGE_SET       *set = new_storage_set();
    STORAGE_SET_LIST *list = new_storage_list();
    void             *data = NULL;
!   store_list(set, "list", list);
  
    int i = zoneGetMinBound(zone);
    for(; i <= zoneGetMaxBound(zone); i++) {
***************
*** 225,237 ****
    // first, for our zone data
    sprintf(fname, "%s/zone", dirpath);
    STORAGE_SET *set = new_storage_set();
!   store_int   (set, "vnum",        zone->vnum,        NULL);
!   store_int   (set, "min",         zone->min,         NULL);
!   store_int   (set, "max",         zone->max,         NULL);
!   store_int   (set, "pulse_timer", zone->pulse_timer, NULL);
!   store_string(set, "name",        zone->name,        NULL);
!   store_string(set, "desc",        zone->desc,        NULL);
!   store_string(set, "editors",     zone->editors,     NULL);
    storage_write(set, fname);
    storage_close(set);
  
--- 239,252 ----
    // first, for our zone data
    sprintf(fname, "%s/zone", dirpath);
    STORAGE_SET *set = new_storage_set();
!   store_int   (set, "vnum",        zone->vnum);
!   store_int   (set, "min",         zone->min);
!   store_int   (set, "max",         zone->max);
!   store_int   (set, "pulse_timer", zone->pulse_timer);
!   store_string(set, "name",        zone->name);
!   store_string(set, "desc",        zone->desc);
!   store_string(set, "editors",     zone->editors);
!   store_set   (set, "auxiliary",   auxiliaryDataStore(zone->auxiliary_data));
    storage_write(set, fname);
    storage_close(set);
  
***************
*** 371,376 ****
--- 386,395 ----
    return zone->max;
  }
  
+ void *zoneGetAuxiliaryData(const ZONE_DATA *zone, char *name) {
+   return hashGet(zone->auxiliary_data, name);
+ }
+ 
  room_vnum getFreeRoomVnum(ZONE_DATA *zone) {
    zone_vnum i;
    for(i = zone->min; i <= zone->max; i++)
***************
*** 457,462 ****
--- 476,484 ----
  }
  
  void zoneSetPulseTimer(ZONE_DATA *zone, int timer) { 
+   // if we normally do not reset, change that
+   if(zone->pulse_timer < 0)
+     zone->pulse = timer;
    zone->pulse_timer = timer;
  }
  
diff -crN nakedmudv1.4/src/zone.h nakedmudv1.5/src/zone.h
*** nakedmudv1.4/src/zone.h	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/src/zone.h	2010-11-01 15:54:17.000000000 -0500
***************
*** 99,105 ****
  OBJ_DATA   *zoneGetObj(ZONE_DATA *zone, obj_vnum obj);
  SCRIPT_DATA *zoneGetScript(ZONE_DATA *zone, script_vnum script);
  DIALOG_DATA *zoneGetDialog(ZONE_DATA *zone, dialog_vnum script);
! 
  
  void zoneSetVnum(ZONE_DATA *zone, zone_vnum vnum);
  void zoneSetMinBound(ZONE_DATA *zone, room_vnum min);
--- 99,105 ----
  OBJ_DATA   *zoneGetObj(ZONE_DATA *zone, obj_vnum obj);
  SCRIPT_DATA *zoneGetScript(ZONE_DATA *zone, script_vnum script);
  DIALOG_DATA *zoneGetDialog(ZONE_DATA *zone, dialog_vnum script);
! void        *zoneGetAuxiliaryData(const ZONE_DATA *zone, char *name);
  
  void zoneSetVnum(ZONE_DATA *zone, zone_vnum vnum);
  void zoneSetMinBound(ZONE_DATA *zone, room_vnum min);
diff -crN nakedmudv1.4/TODO nakedmudv1.5/TODO
*** nakedmudv1.4/TODO	2010-11-01 15:54:18.000000000 -0500
--- nakedmudv1.5/TODO	2010-11-01 15:54:17.000000000 -0500
***************
*** 1,18 ****
  GEOFF'S TO DO LIST
  +-- KNOWN BUGS
  
  
  +-- NOT COMPLETE
!   * remove the EXIT_DATA parameter from the script functions
!   * write helpfiles, create a better helpfile system, and do hedit
    * condense normal and special exits in rooms
    * soft-code chat channels
    * random dungeon generator
-   * spellchecking in the text editor
    * mounts and vehicles
    * being able to stream music would be cool...
    * clean up and document resedit in the olc module
-   * tracking and path following
    * shops (for mobiles and players)
    * customized prompts
    * DOCUMENT DOCUMENT DOCUMENT!! Most of the major headers need full
--- 1,20 ----
  GEOFF'S TO DO LIST
  +-- KNOWN BUGS
+   * moving via tracking will not trigger enter/exit scripts
  
  
  +-- NOT COMPLETE
!   * spellchecking in the text editor
!   * Redo OLC so that if a module uses OLC, it can add the relevant functions
!     from its own module.
!   * Devise something to replace bitvectors that is a bit more amenable to
!     keeping things modular.
    * condense normal and special exits in rooms
    * soft-code chat channels
    * random dungeon generator
    * mounts and vehicles
    * being able to stream music would be cool...
    * clean up and document resedit in the olc module
    * shops (for mobiles and players)
    * customized prompts
    * DOCUMENT DOCUMENT DOCUMENT!! Most of the major headers need full
***************
*** 27,41 ****
  
  
  +-- NEEDS EXTRA WORK
    * debug dialogs. Also have a new addition, STORY for temporally extended
      responses
  
  
  +-- NEEDS DEBUGGING
-   * containers
-   * room reset
-   * Make sure extract obj/char is catching everything, and is running well
-   * Delayed action and event handlers
-   * Generic find algorithm
-   * Bodytypes, especially when setting a character's bodytype anew
    * text editor
--- 29,41 ----
  
  
  +-- NEEDS EXTRA WORK
+   * write helpfiles, create a better helpfile system, and do hedit
+   * tracking and path following -> daily routines, and patrols
+   * displaying mob/obj/room/exit vnums for immortals -> do we want to also
+     display this stuff for furniture?
    * debug dialogs. Also have a new addition, STORY for temporally extended
      responses
  
  
  +-- NEEDS DEBUGGING
    * text editor
