tinymush-3.1p2/game/backups/
tinymush-3.1p2/game/bin/
tinymush-3.1p2/game/data/
tinymush-3.1p2/game/modules/
tinymush-3.1p2/game/modules/old/
tinymush-3.1p2/src/modules/comsys/
tinymush-3.1p2/src/modules/hello/
tinymush-3.1p2/src/modules/mail/
tinymush-3.1p2/src/tools/
Frequently-Asked Questions
==========================

- I found a bug! What do I do?
- How do I make a new configuration file?
- How do I back up my database?
- How do I restore a database backup?
- How do I apply a patch upgrade or bugfix?
- How do logfiles work?
- How do I use multiple guests?
- How do I create my own flags? (How do I configure marker flags?)
= How can I create "altered reality" realm states like invisibility?
- How do I tune the database cache?
- How do I use an in-memory database?
- Help! I'm having database problems.
- How do I set up a link to an external SQL database?

------------------------------------------------------------------------------

I found a bug! What do I do?

- Make sure that it really is a bug, and not a new feature or design
  decision. If it crashes the server, it's a bug. If you can't tell,
  consider it a bug.

- Try to come up with an easily-reproducible sequence of events that
  will demonstrate the bug.

- Send email to tinymush-bugs@lists.sourceforge.net with the bug report.

- If the bug crashes the server, we really, really, want to hear about
  it. We'd like as much information as possible.

  We've included a script which automatically analyzes core files and
  emails results to us. Go to your game directory, and type './ReportCrash'
  You should eventually see a 'Done.' -- that means the analysis was
  successful. If you get an error message and early end to the script,
  you'll need to deal with it manually.

  The following sequence of commands will generate a stack trace and
  variable dumps from the core file. Cut-and-paste the output and
  email it along with your bug report. You can obtain this by doing
  the following from the game directory:

  gdb bin/netmush core
	where
	info frame
	info args
	info locals
	up
	info args
	info locals
	up	(Repeat until you're at the top procedure level.)
	quit

  If you don't have gdb, use dbx, as follows:

  dbx bin/netmush core
	where
	dump
	up
	dump
	up	(Repeat until you're at the top procedure level.)
	quit

------------------------------------------------------------------------------

How do I make a new configuration file?

TinyMUSH 3 gets the information it needs to operate the game (aside from
the database itself) from a configuration file that is read in at startup.
The configuration file contains various parameters, such as where to find
the database, what port to listen for connects, and many other things.

Follow these instructions to make a configuration file for your MUSH from
the supplied template configuration file:

In your game directory, copy the file netmush.conf to <your-mud-name>.conf
and edit it as follows:

    - Replace netmush.<whatever> in the 'xxx_database' lines with
      <your-mud-name>.<whatever>.

    - Set the port number on the 'port' line to the correct port.

    - Set the mud name on the 'mud_name' line to the name of your mud.

    - Make any other configuration changes you want to make at this time.
      Here are some of the common ones to change:
         o money_name_singular <text>  The name of one coin (penny)
         o money_name_plural <text>    The name of several coins (pennies)
         o fork_dump no           Do this if you have little swap space.
         o paycheck <amount>      Players get this much money each day
                                  they connect.
         o paystart <amount>      Players start out with this much money.
         o payfind <chance>       Each time a player moves, he has a
                                  1 in <chance> chance of finding a penny.
         o player_starting_room <roomno>  The room that new players are
                                  created in.

There are many more configuration directives available. Information
on individual directives can be obtained with the WIZHELP <directive>
command within the MUSH.

------------------------------------------------------------------------------

How do I back up my database?

Shut down your game. Go into the game directory, and type './Backup'
This will create a 'flatfile', and compress it with GNU zip; if there's
no GNU zip on your system, you should edit the Backup script so it uses
Unix compress instead.

If you want to back up your database while the game is running, use
@dump/flatfile; this is a strong candidate for a @daily on your God
character.

If for some reason, you can't run a backup from within the game
(you've forgotten your passwords to the wizard characters, or
something similarly problematic), and you can't or don't want to shut
the game down, you can safely back up the database with Backup while
the game is running, but you are not guaranteed 100% consistency
within the flatfile. You can minimize consistency errors by doing a
@dump, waiting a minute until the database is done saving, and then
do the Backup; even if there are slight out-of-sync errors (due to
changed attributes not yet being written to disk) they will
not prevent the backup from being restorable. If the game is
running, @dump/flatfile is strongly preferable, since the resulting
flatfile will contain the most current, in-sync data.

Do NOT simply naively copy around netmush.db, netmush.gdbm, etc., as
they are not portable between platforms. Use the Backup script to
create flatfiles.

Note that this does NOT back up your comsys database or mail database,
or other relevant MUSH files. You can simply copy comsys.db and
mail.db to a safe place, to back them up. Alternatively, you can
run the Archive script to back up all the important files.

------------------------------------------------------------------------------

How do I restore a database backup?

Shut down the game (if it's currently running). Then, go into the game
directory and type './Restore name-of-flatfile', where name-of-flatfile
is the name of your backup file.

Note that this only restores your database; it does not restore the
comsys or mail databases. To restore the latter, simply copy your
saved copies of comsys.db and mail.db back to the game directory.

------------------------------------------------------------------------------

How do I apply a patch upgrade or bugfix?

The easiest way to patch the server, if you have perl installed on
your system,  is to type './Update' -- this will automatically download
patches, apply them, and clean up. You will then be given instructions
as to what to do to build the new version of the server, which you should
follow unless some other instructions were specifically given with the
changes (check BETA, CHANGES, and INSTALL, for instance).

To patch the server manually:

- Download the patch from the archive, via FTP or the Web. Save the file
  in your code directory, which is probably called something like
  'tinymush-3.0' -- it's the same directory that contains this FAQ file.

- Type:  gzcat name_of_patchfile.gz | patch -p1
  name_of_patchfile will probably be something like 'patch-30p1-30p2'
  (with a .gz extension).
  If you do not have gzcat, type 'gunzip name_of_patchfile.gz' and then
  'patch -p1 < name_of_patchfile'
  If you do not have the 'patch' program on your system, you cannot
  apply patches. Get your system administrator to install it.

- If you have previously compiled TinyMUSH in this directory, you need
  to make sure that a clean build of the patched version is done, so type:
      cd src
      make clean
      cd ..

- Type:  ./Build

If there are problems with the patch, make sure that nothing strange
has happened -- for example, there are no carriage-return/newlines ('^M')
characters at the end of lines.

Also, if you're applying multiple patches, make sure to do them in 
chronological sequence -- oldest to newest patch.

------------------------------------------------------------------------------

How do logfiles work?

When you start your game from the command line, the startup information
is logged to GAMENAME.log, where GAMENAME is what you specified it to
be in your mush.config file.

Subsequently, log information is written to whatever you set your
game_log configuration parameter to be in your GAMENAME.conf file
(whatever GAMENAME is); if you didn't specify that parameter,
'netmush.log' will be used. In general, you will probably want to set
it to GAMENAME.log, so startup information and regular log information
are all written to the same file.

You can separate log information of different types into multiple
files, using the divert_log configuration parameter. See the wizhelp
for details.

When you @restart, or do a @logrotate, the existing logfiles are closed
and renamed to LOGNAME.TIMESTAMP, where LOGNAME is the name of the log,
and TIMESTAMP is the "epoch time" (equivalent to the number of seconds
returned by the secs() MUSH function). You can delete those logfiles
to reclaim disk space, if you'd like. The current logfile will always
have the "standard" name as specified by the game_log and/or divert_log
parameters, though.

When you start the game using the Startmush script, any existing
GAMENAME.log files, or log files named by the game_log and divert_log
conf parameters, will be renamed to LOGNAME.old (whatever the name
of the log happens to be). Any previous logs by those names (with
a .TIMESTAMP extension) will be deleted.

When the MUSH is running, you can use, from the game directory,
'./Logclean' to remove logs with a .TIMESTAMP extension, and
'./Logclean -o' to remove logs with a .TIMESTAMP or .old
extension.

When the MUSH is not running, './Logclean -a' can be used to
get rid of all logfiles -- GAMENAME.log, anything named by the
game_log and divert_log conf parameters, and their old versions
with .TIMESTAMP and .old extensions.

------------------------------------------------------------------------------

How do I use multiple guests?

Using multiple guests is easy, and after you set it up, you'll never have to
worry about it again. Here are the steps needed to implement multiple
guests:

1. @pcreate a prototype guest character. Name it whatever you want (although
   you should use a descriptive name like 'Guest'), and use any password you
   want (it doesn't really matter, as the prototype guest can never connect).
   Set guest_char_num to the database number of the prototype guest character.
   Note that this is just the bare number of the object, not a dbref, i.e.,
   'guest_char_num 5' not 'guest_char_num #5'.

2. You may want to set the following things on the prototype guest
   character, which are inherited by every guest character: the amount of
   money, the zone, the parent, the basic lock, the enter lock, and all
   attributes. (NOTE: Guests always start off in the room specified by the
   guest_starting_room, or player_starting_room if that is not specified.)

3. Set 'number_guests' to the maximum number of guests you wish to support.
   This number can be as small or as large as you wish.

4. Optionally, set 'guest_nuker' to a wizard's database number, if you wish
   to have a wizard other than #1 to nuke the guests.

5. Set 'guest_basename' to the name you want guests to use when they
   connect. This defaults to 'Guest'. For instance, if you want guests
   to type 'connect Visitor' instead of 'connect Guest' to connect,
   you should do 'guest_basename Visitor'.

6. Optionally, set 'guest_password' to the password you want guests to
   have. This defaults to 'guest'. This can be used to reconnect to the
   same Guest character. Otherwise, players will never see it (any
   password is acceptable for connecting to a new guest).

7. Now, you should decide how you want guests to be named. You can name
   guests using a numbering scheme, i.e., 'Guest1', 'Guest2', 'Guest3'
   or if you want to specify the list of possible guest names, i.e.,
   'Werewolf', 'Vampire', 'Skeleton', or if you want guest names to be
   generated as combinations of words, i.e., 'RedAlien', 'RedVisitor'
   'BlueAlien', 'BlueVisitor', 'GreenAlien', 'GreenVisitor' (combinations
   of 'Red', 'Blue', and 'Green', with 'Alien' and 'Visitor).

   The guest_basename conf parameter is used for the guest numbering
   scheme, so if you decide to just number your guests, they'll get
   names of '<guest_basename><number>'. If you don't use the numbering
   scheme, guests will receive @aliases of '<guest_basename><number>',
   so they're still easy to find.

   If you want to specify a list of guest names, set 'guest_prefixes'
   to the list of names you want to use. Since the guest names are
   separated by spaces, they can only be single-word names, i.e.,
   'guest_prefixes Werewolf Vampire Skeleton'.

   If you want guest names to be generated as combinations of words,
   set 'guest_prefixes' to the list of the first parts of the name,
   and 'guest_suffixes' to the list of the second parts of the name,
   i.e. 'guest_prefixes Red Blue Green', 'guest_suffixes Alien Visitor'.

   If there are more guests that try to connect (up to the number of
   'number_guests') than there are available name combinations, extra
   guests will be named '<guest_basename><number>'.

   The 'guest_basename' parameter cannot be changed except in the conf
   file. The 'guest_prefixes' and 'guest_suffixes' parameters can be
   changed via @admin while the game is running, though. If you would
   like to randomize the order in which guest names are picked, you
   can do the following, using your God character:

      &GUEST_CRON me = @admin guest_prefixes=shuffle(config(guest_prefixes));
                       @admin guest_suffixes=shuffle(config(guest_suffixes))

      @cron me/GUEST_CRON = 0 * * * *

   This will randomize the lists once an hour; if you'd like to do it 
   more frequently, change the @cron to something more frequent.


The file specified by the config parameter 'guest_file' is shown to every
guest when they connect. You may wish to use the 'access' config parameter
to bar guests from using certain commands, using the 'no_guest' permission.
All guests have the 'Guest' power, which is a marker you may use to test
whether a player is a guest or not. Guests copy the flags, attributes,
parent, and zone of the guest prototype (the guest_char_num object).

------------------------------------------------------------------------------

How do I create my own flags? (How do I configure marker flags?)

You can define your own flags through the use of "marker flags".
Flag names and permissions are defined in your conf file.

There are ten marker flags, numbered 0 through 9; 0 through 9 are the
single characters representing the flag when the flags of an object
are displayed with the dbref when you control/can link to an object,
by the flags() function, etc. In order to distinguish these flags from
dbref numbers, if they are the only flags set on an object, there will
be an underscore ('_') between the dbref and the flags.

An underscore is automatically prepended to the names of marker flags
in order to prevent a name conflict with any added flags in future
versions of TinyMUSH. You can get around this by defining an alias
for the flag without the underscore, but be forewarned that the
flag name might end up conflicting with a built-in flag in the future.

For example, the following conf directive:

flag_name	0	CHIEF

creates a flag named "_CHIEF", with the symbol 0. This means that, for
instance, that an object with this flag and the PUPPET flag (symbol 'p')
might appear on an examine to be:  Balloon(#25p0)  To set the flag,
you would use '@set <object> = _CHIEF'; to unset the flag, you would
use '@set <object> = !_CHIEF'.

By default, these flags can only be set by God. In order to change the
access restriction, use the flag_access directive. For instance:

flag_access	_CHIEF	any
flag_access	_CHIEF	wizard

make the _CHIEF flag settable by anyone, and only settable by wizards,
respectively.

To alias the flag, use the flag_alias directive:

flag_alias	CHIEF	_CHIEF

which makes it possible to do '@set <object> = CHIEF'; the caveats listed
above about future conflicts with built-ins should be kept in mind, though.

------------------------------------------------------------------------------

How do I create "altered reality" realm states like invisibility?

There are three special locks -- the HeardLock, KnownLock, and MovedLock --
that are only activated by the PRESENCE flag.

When an object which is set PRESENCE tries to speak via a speech command
such as "say", "pose", or "@emit", only those objects which pass the
speaker's HeardLock are able to hear the message.

When an object does a "look" at a room or otherwise tries to see a target,
if the target is set PRESENCE, the object must pass the target's KnownLock.
This is also true for messages generated via attributes like @odesc.

When an object which is set PRESENCE moves or tries to move, its movement 
is only seen by those objects which pass the object's MovedLock.

When an object set PRESENCE wants to hear another thing speak, that thing
must pass the object's HearsLock.

When an object set PRESENCE wants to see another thing, that thing must
pass the object's KnowsLock.

When an object set PRESENCE wants to notice another thing's movement,
that thing must pass the object's MovesLock.

Motion and the ability to see an object already in the room are treated
differently, since it's possible that you might want to have something
noticed when it's moving, but not when it's still. (For instance, your
game might have Ninjas that are invisible when they're just in a room,
but are noticed when they move.)

Basic invisibility is a very easy state to implement. Invisible
objects are not seen by anyone, whether or not they're static or
moving, but they can be heard. They can see and hear other things just
fine, though. Thus, to make an object invisible, set it PRESENCE, and
@lock/known <object> = #0, and @lock/motion <object> = #0.

A more difficult state is something like the World of Darkness's 
vampiric Obfuscation. Let's say that vampires have three levels of
obfuscation ability, stored on their OBF_ABIL attribute; vampires
who have an obfuscation ability higher than a target's can see that
target even if they are obfuscated.

That can be done as follows:

  > @create Obsfucator
  Obfuscator created as object #11.

  > &OCHECK Obfuscator = [gt(get(%#/OBF_ABIL),get(%@/OBF_ABIL))]
  > @lock Obfuscator = OCHECK/1

Now, to allow Vlad to Obfuscate, merely do:

  > @set *Vlad = PRESENCE
  > @lock/known *Vlad = @#11
  > @lock/motion *Vlad = @#11
  > &OBF_ABIL *Vlad = 1

(Clearly more complex implementations are possible and are likely to be
desirable; this is just an example.)

Alternatively, take something like the state of a ghost. Let's say that
ghosts can see each other and hear each other, but no one else can.
They can see the normal world just fine -- but they don't hear everything
that's said, they have a random chance of not hearing normal speech. 
A way to do this might be putting the following in your conf file:

  flag_name    0    GHOST

and then @set all your ghostly players _GHOST.

Then, handle the locks:

  > @create Ghost Ears
  Ghost Ears created as object #22.

  > &GCHECK Ghost Ears = or(hasflag(%#,_Ghost),rand(2))
  > @lock Ghost Ears = GCHECK/1

  > @create Ghost Haze
  Ghost Haze created as object #33.

  > &HCHECK Ghost Haze = hasflag(%#,_Ghost)
  > @lock Ghost Haze = HCHECK/1

  > @set *Caspar = PRESENCE
  > @set *Caspar = _GHOST
  > @lock/hears *Caspar = @#22
  > @lock/heard *Caspar = @#33
  > @lock/known *Caspar = @#33
  > @lock/motion *Caspar = @#33

Fundamentally, you can combine these six locks to end up with any combination
of what can hear, be heard, see, be seen, notice, and be noticed.


------------------------------------------------------------------------------

How do I tune the database cache?

Cache tuning is something of a black art. The basic tradeoff is this:
If you make your cache larger, it will consume more memory, but you
will (hopefully) need fewer disk accesses to get needed data, which
will therefore be faster. However, if you consume too much memory, the
operating system will begin to page random bits of your MUSH on and
off of disk -- you are better off staying small enough to not have
that happen, and do your own getting data on and off disk.

TinyMUSH 3.1 allows you to limit the total amount of cache memory the server
consumes. This defaults to 1,000,000 bytes, or just under 1 MB of RAM. The
size of the cache can be changed with the cache_size parameter in your conf
file. We recommend that you don't set this value any lower, except on
private or very small games. Otherwise, take a look at the size of your
netmush.gdbm file via ls -l netmush.gdbm -- the file's size in bytes should
be next to its last-modified date. (If your GDBM file is not called
netmush.gdbm, use whatever filename it's called.) You should never set your
cache size larger than the size of this file.

The optimal cache size is dependent on a number of different factors; these
include the size of your master room objects, the number of players you have
logged on at a time, and how much they move around. Generally any object
which is 'used' by a player is cached; this includes rooms and exits, as
well as objects in their inventory. Thus your cache size really shouldn't
depend on the total size of your database, but on the size of the active
playerbase, often-used softcode, and the areas your players typically move
around in. Take a look at your @list cache sometime to determine what kind
of objects are being cached.

Let your game run for a few hours with normal player activity. Check '@list
db_stats' and look at the Cache Size reported, and the Hit Ratio for Reads.
You want the latter to be in the 90-97% range. If your actual reported cache
size is much lower than your configured cache_size and your hit ratio is
still in that range, then you should be able to safely lower cache_size in
the future. If your hit ratio is low, try increasing the cache size (though
eventually there will be a trade-off in paging behavior if the process
becomes too large).

You can also tune the cache width; this is the number of 'buckets' that
cache entries are spread out over. For the vast majority of games the
default if okay. If you want to tune this, take a look at the number of
attributes being cached in '@list cache', divide this number by 50, and use
that as your cache width.

------------------------------------------------------------------------------

How do I use the in-memory database?

Follow the 'Basic Installition' steps in the INSTALL file, with one
exception: specify '--disable-disk-based' as an argument to configure (step
5). Please note that unlike previous versions, TinyMUSH 3.1 uses GDBM for
its memory-based database instead of a flatfile. You can still create a
flatfile using the Backup script the same way you would for a disk-based
game.

------------------------------------------------------------------------------

Help! I'm having database problems.

Almost everyone who runs a MUSH experiences a database disaster at
least once in their life. There can be many reasons for this; common
ones include an NFS server dying, running out of disk space,
overflowing your disk quota, a nasty game crash, and a nasty system
crash.

Typically, in this scenario, the server process either dumps core during
an attempt to load the database, or simply hangs; sometimes, it may come
back up and large chunks of your data may be missing.

Sometimes, simply by flatfiling and reloading the flatfile (doing a
Backup and a Restore), integrity issues that cause the database to
fail to load can be dealt with. Be aware that you might experience some
minor data loss in the process, though.

However, your best bet in this scenario is to restore your database
from backup. This means it's very important to keep backups; we strongly
recommend that you back up once a week at minimum, if not nightly.

If you don't have a recent backup you can restore from, you can try a
database reconstruction. This is likely to be most effective if you
have corruption resulting from a host machine crash or disk problem;
you might not be able to get back all of your data, but it'll at least
be something. If you haven't moved any files around, you can just go
into the game directory and type './Reconstruct'. If it completes
successfully, you can try to start it up with './Startmush' (though
doing a './Backup' first would be a good idea). If it doesn't complete
successfully, you'll need to revert to a backup.

------------------------------------------------------------------------------

How do I set up a link to an external SQL database?

There is built-in support in TinyMUSH 3 for connecting to an external
mSQL or MySQL database. If you want to do this, you'll need to compile
in the appropriate file (see ./configure --help for how to do this).

You can also look at db_sql.h, db_msql.c, and db_mysql.c for examples
of how to write your own method of connecting to another type of
external SQL database. If you do this, please let us know, and provide
us with a copy of the code, so it can be included with the next
TinyMUSH release.

The rest of this answer uses mSQL as a specific example; MySQL and other
database systems have similar requirements.

You'll need to have an mSQL 2.x database set up. mSQL can be obtained
from http://www.hughes.com.au/ together with the appropriate documentation.
We do not support the mSQL package itself; if you need help with mSQL
installation, configuration, and maintenance, please refer to the
mSQL pages for assistance.

If the mSQL database is on the same machine as your MUSH, the sql_host
parameter in your netmush.conf file (or equivalent) should be set to
"localhost", so the local Unix domain socket is used; if the database
is not on the same machine as your MUSH, the sql_host parameter should
be whatever the remote server's hostname is.

You then need to create a database in mSQL for the MUSH to use (or
you can, of course, use an existing database). You can do this with:

msqladmin create MUSH_DB

... which creates a database called MUSH_DB. You can then add the
parameter 'sql_database MUSH_DB' to your netmush.conf file.

Make sure that you set up your mSQL installation's msql.acl file
correctly and with the appropriate level of security. See mSQL's
own documentation for assistance with this.

The database link should come up automatically when the game is
first started. You should see logfile messages that look something
like this, after the 'Load complete.' note in the log:

990831.115339 TinyMUSH SQL/CONN : Connected to SQL server.
990831.115339 TinyMUSH SQL/CONN : SQL database selected.

You should then be able to use the SQL() function from within the MUSH
to make queries against this database. Note that users of this function
need to have the use_sql power.

Note for MySQL users: you may need to specify a username/password to
connect to the database; use the sql_username and sql_password config
parameters. These parameters have no effect for mSQL.

------------------------------------------------------------------------------
    If you have suggestions for more FAQs, please email us and let us know.
------------------------------------------------------------------------------