TinyMUX 2.0:  CHANGES
Last Update:  September 2000

Major changes that may affect performance and require softcode tweaks:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 --  MUX 2.0 no longer uses any version of GDBM for it's database.
 --  Broad Time/Date from 27255 BC to 30826 AD with a proleptic Gregorian
     Calender. The internal resolution of time is 100 ns.
 --  Large 64-bit Integer Math support.
 --  Moved code from C to C++.
 --  Shared sources between Unix and Win32 including native NT networking.
 --  Queuing (@wait/@notify/@kick) is completely re-written and fits more 
     seamlessly with the networking. 
 --  Added optionally included WOD_REALMS support.
 --  Replace udb_ocache with an attribute cache using CHashTable.
 --  vmul() behavior didn't match PennMUSH, MUSH 3, or MUX 2 help files.

Feature Additions:
~~~~~~~~~~~~~~~~~
 --  Greatly improve @dbclean so that it checks the internal and external 
     integrity of five data structures against themselves, removes stale 
     attributes, and renumbers the attributes that remain. And, it's very 
     much faster than the original version. Removing stale attributes by 
     itself takes 6 seconds. 
 --  Allow comtitles to -replace- your name instead of just prefix it. 
     Staff continues to see who is who. This behavior is choosen with
     @cset/spoof <channelname>.
 --  Server automatically creates a minimal database if one does not 
     already exist.  
 --  dbconvert will not allow you to load into a non-empty database or 
     unload from a non-existent one.
 --  Added a TinyMUSH-style backup script which runs dbconvert, as well as 
     creating a tarball that includes flatfile, mail.db, comsys.db, 
     mux.config, GAMENAME.conf, and all .txt files except help and wizhelp.  
 --  Added %cu for ANSI underline.
 --  columns() is fully ANSI-aware and maintains the intended color.
 --  strtrunc() is fully ANSI-aware and maintains the intended color.
 --  ucstr() and lcstr() are now fully-ANSI aware and only uppercases 
     (lowercase) the non-ANSI text.
 --  ANSI has been re-worked and there are no known color leaking issues in 
     the server. The server automatically goes to normal color mode even if 
     you don't specify it explicitly in your text. ANSI sequences are 
     optimized (sometimes totally out of existence). Truncation of ANSI 
     strings into fixed-sized buffers or fixed-width fields is handled 
     properly.
 --  Better NOBLEED support. NOBLEED support is accomplished with fewer 
     ANSI codes.
 --  Reworked the game's command line processing and filled in some 
     combinations. 
 --  Added a @list resources command to show total number of open files, 
     sockets, etc. 
 --  Added @mail/reply[/quote], and @mail/replyall[/quote]
 --  Included safer_passwords configuration option.
 --  Configuration option added to deal with guest logins at reg-only MUXen.
 --  Added channel functions: comalias(), channels(), and comtitle().
 --  Added functions: doing(), motd(), and poll().
 --  Added @idletimeout
 --  Added SIGUSR2 signal handler.
 --  IRIX builds cleanly and runs.
 --  Solaris builds and runs cleanly.
 --  Added @log command.
 --  Added iadd(), div(), imul(), and isub() functions.
 --  Use dynamic string allocation in conf.cpp to support filenames longer
     than 30 characters.
 --  OpenBSD and FreeBSD build and run clean.
 --  comtitle prefix/replace behavior is now optional on a per-channel
     basis. See @cset/spoof
 --  Added @idletimeout
 --  Added comtitle(), alias(), comalias(), channels(), poll(), doing()
     and motd() functions.
 --  Tiny_ltoa() and Tiny_i64toa() are about twice as fast.
 --  db_write is about 4 times faster.
 --  putstring is about 30% faster.
 --  Added @function/list from RHostMUSH.
 --  Added /noeval to @pemit and @npemit
 --  ucstr(), lcstr(), capstr(), reverse(), and revwords() are now
     ANSI-aware.
 --  band(), bnand(), and bor() were added months ago.
 --  Added lpos() function from MUSH 3.
 --  Added @timecheck command from MUSH 3 and changed it to use
     MUX 2's internal time format and to work on WinNT and Win9x.
 --  Added flag_access configuration option from MUSH 3.
 --  Rewrote PERMISSIONS topic in wizhelp.txt to accurately reflect the code.
 --  Have server abort() with a log entry instead of just abort()'ing.
 --  Added 'head' access permission.
 --  Added 'lag_maximum' configuration option with default of 120 seconds.
 --  Added the object list stack originally from U1 and ChaoticMUX that
     keeps certain operations (when nested) from stepping on each other's
     object searches.
 --  Use ANSI_TruncateToField on object names so that embedded ANSI
     in object names are ANSI-optimized and correctly terminated with %cn.
 --  Added a 'report' command that shows a distribution of 'last logged in'
     times for a week in 8 hour intervals. 
 --  Updated lnum() function to accept three arguments.
 --  Enhanced secs(), convsecs(), time(), and convtime() to handle both
     UTC and local timezones with room for others.
 --  Added the Mersenne Twister random number generator as an option.
 --  Added various time/accounting functions from DooferMUX.  This is
     controlled by the GAME_DOOFERMUX define and it's turned off by default.
     Some of the DooferMUX stuff may be removed at a future time.
 --  Subnets can now be expressed with the 'slash' notation. i.e, a.b.c.d/e
 --  guest_site configuration option is in, but based on input from ChaoticMUX,
     and RHostMUSH, this may be accomplished in another way or with a different
     name. And, there is currently no help for this option.
 --  Bug #401 - @dump/flatfile is now supported.
 --  Included all but two GAME_DOOFERMUX changes in the default build.


Bug Fixes:
~~~~~~~~~
 --  Fixed: merge() let *bufc point one character too far.
 --  Fixed: space() SIGSEGV
 --  Fixed: lparent endless loop.
 --  Fixed: bad_command and shout log buffer overrun.
 --  Fixed: welcome screen character creation SIGSEGV
 --  Fixed: @mail could go blank if too large.
 --  Fixed: Players couldn't test dark wizards for AUDIBLE.
 --  Fixed: @mailer queuing loop if mailer was disabled.
 --  Fixed: help topic aliases were shown.
 --  Fixed: Removed DarkZone 990 character limits.
 --  Fixed: non-players can no longer use @mail.
 --  Fixed: @clone stepped on pennies.
 --  Fixed: @ps was not showing @wait 0 commands.
 --  Fixed: SIGSEGV in dbconvert with object @locked to sex:f when no other
     user-defined attributes have been defined.
 --  Fixed: subtle bug in ANSI_TruncateToField going from normal to normal
     color near the end of the buffer.
 --  Fixed: Buffer trash problem with delete() function.
 --  Fixed: Rounding bug in time_format_1 (affected WHO).
 --  Fixed: fun_ansi used ANSI_TruncateToField with the wrong field size.
 --  Fixed: idle() returned '0' for unconnected players instead of '-1'.
 --  Fixed: Protect math libraries against NaN and Inf with IEEE
     floating-point goo.
 --  Fixed: SIGSEGV bug in before() and after() if no second parameter
     was given.
 --  Fixed: HAVE_WAIT3 build issue on FreeBSD.
 --  Fixed: bsd.cpp SIGUSR1 blockage. The second SIGUSR1 would not be
     caught.
 --  Fixed: @program me SIGSEGV.
 --  Fixed: @pemit/list to a list of players sometimes used strtok a
     second time.
 --  Fixed: @dbclean and @prog bug caused by atr_add_raw/atr_get_raw idiom.
 --  Fixed: SIGSEGV in undocumented alphamin() and alphamax().
 --  Fixed: Parser wasn't enforcing minimal number of arguments.
 --  Fixed: Lit() bug and unsaved parser mode.
 --  Fixed: Potential StringCopyTrunc overflow in site names.
 --  Fixed: Potential buffer resuse in atol call in do_open in create.cpp
 --  Fixed: mid() SIGSEGV. Also made mid() ANSI-aware.
 --  Fixed: fun_create SIGSEGV. Argument count not validated.
 --  Fixed: Edge case ANSI bleeding.
 --  Fixed: die() edge case SIGSEGV.
 --  Fixed: buildnum.data missing in distribution.
 --  Fixed: INT64/scanf/printf problem on FreeBSD.
 --  Fixed: Configuration file SIGSEGV.
 --  Fixed: Race conditions in @restart, @dump, and @shutdown which can 
     cause DB corruption have been fixed.
 --  Fixed: @shutdown now waits for a forked dump to finish before exiting 
     the game.
 --  Fixed: All known comsystem buffer overflow issues have been fixed.
 --  Fixed: Setting a room transparent and linking an exit to home would 
     SIGSEGV.
 --  Fixed: Invalid master_room references would SIGSEGV.
 --  Fixed: protect against atof() SIGSEGV in certain libraries.
 --  Fixed: @program + LOGOUT + piping interactions would SIGSEGV.
 --  Fixed: NOBLEED with enough ANSI caused a buffer overrun and stack  
     corruption and a SIGSEGV.
 --  Fixed: Buffer overflow problems with ucstr() and lcstr() causing 
     SIGSEGV.
 --  Fixed: Buffer overflow problems with safe_tprintf_str that would 
     SIGSEGV.
 --  Fixed: @mvattr would still remove the source attribute if it couldn't 
     add the destination attribute.
 --  Fixed: events_daily_hour can now be hour 23 without causing daily    
     activities to execute 3-4 times about every 15 minutes. 
 --  Translate() now quotes backslashes correctly.
 --  @mail/fwd checks whether a message is already in progress.
 --  @doing color leaking.
 --  Trunc() now truly truncates a number instead of rounding.
 --  Fixed: @wait bug.
 --  Fixed: If you have @mail, and then purged it all (everything in all
     folders), you wouldn't be able to receive any further @mail until the 
     game @restarts.
 --  User-attribute name length was enforced incorrectly. 
 --  delcom showed DARK wizards leaving.
 --  Fixed a bug where parse_to was looking for an escape character on byte 
     -before- beginning of an allocated buffer.
 --  Fixed a bug where pending characters in 'session' report was negative. 
     It was caused by receiving a backspace without something to backspace 
     over.  Telnet clients usually demonstrate this bug. Other clients do 
     the editing themselves before they send. 
 --  @mail/fwd caused a SIGSEGV. get_attr_raw can return NULL. 
 --  Set flag2 and flag3 to zero for a minimal room. This is just an
     uninitialized variable that left most of the flags set to random stuff 
     on non-debug builds. 
 --  Fixed a lot of lint-type issues. 
 --  Fixed: mid() SIGSEGV. Also made mid() ANSI-aware. (from Robby Griffin)
 --  Fixed: fun_create SIGSEGV.  Variable number of arguments, pointers not 
     guaranteed valid. (from Robby Griffin)
 --  Fixed: edge case ANSI bleeding. (from Robby Griffin)
 --  die() SIGSEGV. (from Robby Griffin)
 --  Fixed: long integer problem in FreeBSD. (from Robby Griffin)
 --  Fixed: Configuration file SIGSEGV. (from Lew Newby)
 --  Changed: Config option added to deal with guest logins at reg-only 
     MUXen. (from Audumla)
 --  Use g++ explicitly instead of gcc.  This fixes a problem with builds
     under RH 5.1. (thanks MacGuyver)
 --  Documented band(), bnand(), and bor().
 --  Documented link(), subeval(), tel(), and valid() from MUX 1.6
 --  Documented allow_guest_from_registered_site configuration option.
 --  Obsoleted cache_depth, cache_trim, and cache_width in wizhelp.txt.
 --  Documented max_cache_size in wizhelp.txt.
 --  Changed default concentrator port in wizhelp.txt.
 --  Updated crash_database entry in wizhelp.txt
 --  Documented game_dir_file and game_pag_file configuration options.
 --  Obsoleted gdbm_database configuration option.
 --  do_conv now accepts "Jan 01 00:00:00 2000" as well as
     "Sat Jan 01 00:00:00 2000". Long-standing bug where the comments and the
     code describe different things.
 --  Fixed bug in trimmed_site where with a sufficiently large site_chars
     configuration limit, the server will overflow a MBUF_SIZE buffer.
 --  Fixed slow SBUF memory leak in find_power() which is called by the
     haspower() softcode function (from Robby Griffen).
 --  Found memory leak in !MEMORY_BASED + RADIX_COMPRESSION.
 --  Found typo that prevented !MEMORY_BASED + RADIX_COMPRESSION configuration
     from compiling.
 --  Fixed the way convtime() mishandled daylight savings time.
 --  TRUNC(5.0) would return 0 because the fractional part was zero and
     fun_trunc was testing the wrong number. This bug was introduced at the
     time as the IEEE floating-point Ind/+Inf/-Inf stuff was introduced.
 --  Subnet masks for restricted sites are now validated.
 --  Bits in the base IP address for restricted subnets are now removed.
 --  MEMORY_BASED attributes were allocated one byte too short (introduced in
     Beta 8).
 --  isValidSubnetMask() went through the wrong sequence of valid subnet masks
     (introduced in Beta 9).
 --  cf_log_syntax showed gibberish because of the way va_start/va_end-type
     arguments were handled (introduced in Beta 9).
 --  Setting #1 GOING is no longer permitted.
 --  @create no longer can create things with blank names. @create(%b,)
 --  MUX is more restrictive when loading comsys.db
 --  A KILLED database didn't have passwords in it (also with MEMORY_BASED).
     Introduced in Beta 10 (Build #267).
 --  objeval() security was too lax.
 --  The mail_sw and malias_sw tables were not terminated.
 --  Side-effect functions now enforce the same security that the
     corresponding commands enforce.
 --  CR, LF, and TAB are not allowed in @doing and @doing headers.
 --  Creating an exit like 'tes%crt;t' would leak ANSI color.
 --  Using a pipe with an unconnect player would duplicate output.
 --  Security flaw in @mail allowed WIZARD to use objeval to read @mail.
 --  Guests can no longer set attributes on themselves.
 --  @addcom allowed empty aliases.
 --  Strange player names are no longer allowed with
     '@wait 0=@pcreate %b=blah'.
 --  Buffer in view_atr was too small. No ill effects however.
 --  Bug with %v in the parser -- only apparent with syntactically
     incorrect use of %v.
 --  GetProcessorUsage assumed HAVE_GETRUSAGE.
 --  conn() now returns -1 for unconnected players as documented.
 --  A MEMORY_BASED build will now properly create a minimal
     database.
 --  Forward list length is now checked to avoid SIGSEGV.
 --  @toad now releases comsys and @mail resources associated with
     player.
 --  Bug in set_prefix_cmds that would effect space mods.
 --  Fixed minor bug in dbnum() used with sorting dbrefs. It's also
     smaller and faster.
 --  Fixed minor bug in GeneralTimeConversion with how to express the
     pluralization of '0'.
 --  Use time_t instead of long in test_time_t().
 --  Bug #277 - escape() is now ANSI-aware.
 --  Bug #293 - secure() is now ANSI-aware.
 --  Bug #352 - @mail 0 now gives something reasonable.
 --  Bug #422 - Fixed @toad race condition.
 --  Bug #461 - Descriptors 0 and 1 could be closed after a @restart.
 --  Bug #462 - boot_slave could close it's own socket to the DNS slave.
 --  Bug #463 - identd info never made it through on Win32.
 --  Bug #464 - Flag aliases are now put into canonical form.
 --  Bug #480 - @toad strips the zone on chown objects.
 --  Bug #483 - Bad socket descriptions are now discovered and removed.
 --  Bug #484 - @dump/text prevented normal @restart/@dump/@shutdown.
 --  Bug #485, #486, #487, #488, #489, #490, #491 - possible buffer overflows.
 --  Bug #492 - @dbclean is no longer allowed while @dump'ing.
 --  Bug #495 - @destroy strip the zone on chown objects.
 --  Long @malias no longer SIGSEGV at game start time. @malias length is
     limited to 12. @malias description visual width is limited to 40.
 --  columns on @malias reports are lined up even if descriptions include
     ANSI color.


Performance Enhancements:
~~~~~~~~~~~~~~~~~~~~~~~~
 --  The parser speed has been substantially increased: TinyExec() and 
     parse_to()
 --  Main networking loop is brief, to the point, and fast.
 --  Combined all the queues, do_second, dispatch, cache_tick, do_top, etc.
     and the way process_output and process_commands were scheduled into a 
     single unified mini-task design. Everything is now scheduled, or it 
     doesn't run.  @kick, @timewarp, @enable/disable queuing all still 
     work. The server will sleep until there is work to do or IO to 
     perform, otherwise, it will sleep for an arbitrarily long time (which 
     ight now is 5 minutes). The WinNT shovechars loop is now 12 lines long 
     (not counting blanks, braces, or comments). Alarm() has been removed 
     from the server. It caused the main networking loop to run once a 
     second regardless of whether there was anything on the queue to run or
     whether the status of any connections changes.
 --  Commands that are waiting on quota are now scheduled more fluidly.
 --  The interface for safe_copy_chr() and safe_copy_str() is now different 
     which was done to support a speed increase.
 --  Bread-and-butter dumping functions: putref, getref, putstring, and 
     getstring_noalloc have all been highly optimized for speed.
 --  Translate() and all handling of ANSI functions has been optimized in 
     terms of execution speed and also optimized in terms of using only 
     the minimal number of sequences to accomplish the color goal.
 --  ansi() is faster.
 --  Got rid of unnecessary static buffers to save memory.
 --  and(), or(), xor(), add(), mul(), max(), and min() re-written for 
     speed. They will also handle a single argument.
 --  Using ChashTable instead of the htab. The newer implementation uses 
     extendable hashing of large pages of memory. This avoid the linked 
     lists that are virtual memory hostile and keeps the server's working 
     set small. Also this structure automatically grows as necessary 
     without degrading performance.
 --  User memcpy or memmove appropriately depending on overlap assumptions. 
     Compilers deal with memcpy as an instrinsic function and so these are 
     typically the same as large structure assignments.
 --  Use stricmp, toupper, tolower as approriate instead of server's 
     variety of these same functions.
 --  Avoided a lot of unnecessary memory allocations, improved code 
     readability and performance of how help file topic names are indexed 
     when the game loads.
 --  Changed the way user attributes are stored and accessed to save a 
     duplicate copy of attribute names from memory. This saved 1.5MB of 
     memory for me.
 --  Increased the size of stream buffers for @dump and game startup.
 --  Improved performance of dbconvert when loading a DB by doing some key
     sorting.
 --  mid() was still one character too agressive.
 --  repeat() was one character too conservative.
 --  Save and restore global registers using memcpy instead of strcpy.
 --  Save and restore global registers in a few extra places in the code.
 --  Use our own tables for character typing instead of ctype.h
 --  Use MakeCanonicalAttributeName and MakeCanonicalAttributeCommand with
     their truncation, uppercasing, and validity checking done in one place
     and in one pass. And have them called from one level in the code.
     This instead of having these steps performed redundantly at
     different levels in the code.
 --  Removed cache_reset calls throughout the server as the call is a null
     operation with CHashFile.
 --  Maintain a length for the current A_LIST so we can use memcpy instead
     of strcpy for speed.
 --  Wrote DbrefToBuffer_* functions that deal with creating dbref lists
     more efficiently.
 --  Improved speed of get(), xget(), and v() by using length from the
     database layer.
 --  Improved speed of switch() by avoiding a buffer allocation.
 --  Improved speed of lt(), lte(), gt(), gte(), eq(), and neq() by 
     avoiding use of the floating point conversions when possibly.
 --  Use safe_chr instead of safe_str whereever possible for speed.
 --  Added safe_ltoa because it's faster than using
     safe_tprintf_str(buff, bufc, "%d", i);
 --  Improved speed of insert(), replace(), and ldelete() by using memcpy
     instead of strcpy.
 --  Re-wrote do_conv to avoid a buffer allocation, safe_db_copy call, etc.
 --  Re-wrote ljust() and rjust() for speed, and they do the right thing
     ANSI-wise as well.
 --  Re-wrote the random number generator to be 32-bit instead of 31-bit,
     encouraged all 32 of those bits to be 'equally' 'psuedo-random', and
     saved unused bits from one call to service later calls as a way to
     improve performance. @wait uses RandomLong to decide whether to ding
     the invoker for an extra penny.
 --  The random number generators are now given a seed which is based upon
     the full resolution of the current time (milliseconds or better).
 --  LAST() is faster.
 --  Removed duplicate code.
 --  Improved speed and consistancy of object name checking.
 --  Use assert checking macros.
 --  Improve speed of queue argument and environment passing.
 --  Removed three unused LBUF_SIZE buffers in !RADIX_COMPRESSION builds.
 --  Rewrote parse_msglist to avoid an extra buffer. The parse is no longer
     destructive.

Cosmetic Changes:
~~~~~~~~~~~~~~~~
 --  Removed the unused 'empty' column from @list hashstats.
 --  All the tools have a version number now so that you can tell that they 
     go together.
 --  README and related server docs have been reviewed and updated. 
 --  buildnum.data added into distribution.
 --  Spelling error in 'wizhelp have_macros' topic.

Miscellaneous:
~~~~~~~~~~~~~
 --  Game uses UTC time internally.
 --  Free memory properly when the game exits to allow potential memory 
     leaks to be more easily found.
 --  Replace random number generator. 
 --  Source code untars into its own directory.
 --  Miscellaneous server documentation moved to docs/
 --  Increased the size trigger for rotating logfiles on Win32.
 --  Syncronized version.cpp, _build.cpp, and _build.h between Unix and Win32.