How to be an UnterMUD Wizard: ----------------------------- First off, things you will need: a) about a meg of disk space, bare minimum. if you plan to build anything complex, plan to have a few megs of storage for backup copies of objects and databases. b) a C compiler. UnterMUD is written in K&R C. c) some knowledge of how C works, since the MUD is capable of being tailored to your environment, and because of environmental differences, it may require it. UnterMUD is designed to require a minimum amount of resources to run, but running a MUD is never something to be undertaken lightly. There are useful facilities for storing and archiving objects in Unter and those should be understood before you try to run a MUD. It is far easier to recover a trashed database from backup, than by hand. Building the server: -------------------- (See also the 'howtostart' file.) Edit the file "config.h", which contains all the various software switches that UnterMUD can be compiled with. Comments around each option describe its relevance. In most cases you should be able to fairly easily understand what is going on. If not, you'll have to figure it out, since it's really pretty basic stuff. Some options and system environments may require modifications to the Makefiles in the umud directory, or the DB directory. Type "make" and it should build a program called "mud". If it does not compile, save a transcript of the error, in case you can't figure it, and mail it to someone who maintains UnterMUD. Make a sincere try at figuring it out, or you'll be likely to get told to get a clue. There is a macro in the Makefile called FLAGS that gets passed in with the compiler flags in the main directory and the subdirectory. this can be used to pass compiler flags without having to edit Makefiles. on any decent UNIX, you should be able to type: make "FLAGS=-O" and it'll do that compile thang. This is useful if you need to recompile the MUD with profiling or debugging information. Building your initial database: ------------------------------- Initially, there is no database provided with the MUD, since there is no way of knowing what kind of database system you will be running with. You need to build a database from scratch. This is done using the utilities in umud/DB, namely loaddb and dumpdb, and the minimal_db.oif file, which contains a very very small raw database. The first step is to make a decision as to what directory the MUD will run out of. This is set with the #set working directory someplace safe (looks for NEWS and HELP here) _mudconfig chdir "/some/directory/or/other" option in the configfile. Inside that directory, can be two subdirectories, named "HELP" and "NEWS", if you wish to have helpfiles or news postings stored. The HELP directory is searched for files by the "help" command, and the "NEWS" command stores news articles in NEWS. Other files that are looked for in news are NEWS/welcome.txt, which is automatically sent to a player when they connect to the MUD, if it exists, and NEWS/connect.txt, which is automatically sent to a player when they first connect (before they log in), if the file exists. In the top-level directory of the distribution is a directory called "HELP" which contains help files. Moving that directory to the database directory will give a reasonable starting set of help files. Or you can just leave it where it is, and make the NEWS directory there. Either way, be sure you set the working directory correctly with the _mudconfig chdir command. Once the directory is set up, create your initial database from scratch, using one of the following techniques, depending on the database layer you wish to use. Hashed directory databases: --------------------------- First off, you must make the hash directories - ensuring that you have as many as are defined as the hash size you plan to use. IE: if the hash size is 15, you need to have 15 separate directories (all in the same parent directory) named: 0, 1, 2, 3 and so forth, up to 14. Remember that you must *ALWAYS* use the same hash size, or the database will become corrupt. (unless you copy it out and back in again). Knowing the directory in which the hash directories reside, load the database, using loaddb: loaddb -v -h -i minimal_db.oif -f /hash/directory/path and you should see the objects being copied in. If you used other then the default hash size, provide a parameter with the -b flag, indicating the value, EG: loaddb -v -h -b 23 -i minimal_db.oif -f /hash/directory/path To make a backup of the entire database, use dumpdb to copy the objects back out in OIF format: dumpdb -h -f /hash/directory/path | compress -v > backup.oif.Z Dbm/ndbm chunk databases: ------------------------- Dbm/ndbm chunk databases are stored in a packed file of logical blocks, with a throw-away in-memory bitmap for managing storage allocation. This approach results in only 3 files for the MUD database, rather than the many produced by hashed directories. Access and update times are considerably faster, but it is harder to edit the database manually, or archive individual objects. Knowing where you want to store the database files, use loaddb to load the initial database: loaddb -v -d -f /database/file/base/name -i minimal_db.oif and three files will be created: filename.db, filename.dir, and filename.pag. The filename.db contains chunks of the objects, stored in ascii, with garbage between them (the file is a binary file, do NOT EVER try to edit it with vi!) The filename.dir and filename.pag files are a dbm database of object name/size/offset values. Do not ever try to modify any of these files manually. Dbm/ndbm based databases use a logical block structure which defaults automatically to a "reasonable" value. You can modify this or select another block size, and if you do so, make sure you ALWAYS use the same block size. The use of different blocksizes is discouraged, but for some large databases with a lot of disk space to waste, using a larger block size will result in performance improvements, at a cost in space. If you do not understand these issues, do not change the block size. To make a backup of the dbm chunk database, use dumpdb to copy objects back out into OIF format: dumpdb -d -f /database/file/name | compress -v > backup.oif.Z Gdbm chunk databases: --------------------- If you have gdbm on your machine, you can use a gdbm database, which takes advantage of gdbm's ability to store large records, and stores the entire object in the database. Load the database with loaddb: loaddb -v -g -f /database/file/base/name -i minimal_db.oif The gdbm and dbm databases are not interchangable. A word about loaddb/dumpdb: --------------------------- There are additional options to loaddb and dumpdb to specify expressions to match objects against, input, output, and so forth, which are left to the wizard to discover. Roughly, the options are as follows: flag: meaning: ----- -------- [one of these MUST be defined] -d (flag) Database is a dbm chunk database. -g (flag) Database is a gdbm chunk database. -h (flag) Database is a hashed directory database. -x Extract to standard output (loaddb only). This permits loaddb to be used as a filter. -c expression Apply given expression as a selection criterion for all objects in the database or input. -l List objects only, do not extract them in OIF. This is useful when testing selection criteria. -v Verbosity. -b # Block/hash size. (If relevant to db-layer) -i filename Input filename. -o filename Output filename. -f filename Database filename. -C [i|o] Compression on input or output, if compression is compiled into your MUD. IE, to decompress a database, use: loaddb -i olddb.compressed.oif -x -C i -o newdb.uncompressed.oif to compress a database, use: loaddb -i olddb.uncompressed.oif -x -C o -o newdb.compressed.oif Boolean expressions for the selection criteria are similar in syntax to locks, with the exception of the following constructs: attribute = value - Look for named attribute with the exact value given (EG: _own = 23@HELL) type.attribute = value - Look for named atttribute of the provided type, with the exact value given (EG: cmd.fail = @do BONK) attribute = [regexp] - As above, but do a regular expression pattern match on the attribute. (EG: desc = [.*fuzzy.*]) Compressed Databases: --------------------- If your database is having problems with size, you may need to consider compressing the database, which can save in the area of 25% of the size of the chunk file. This will entail some additional administrative burden, since your MUD server will ONLY read and write compressed OIF databases, and you will need to rely on external code (like loaddb) to handle compression and decompression of backups. Compressed databases will also take up less space for backups, if that is an issue. Be aware of the fact that compressed databases will be a lot more of a chore to manipulate and edit. See DB/comp.c for a simple compress/uncompress routine. Booting the server: ------------------- There are two critical files used to initialize the server. The first is the "config" file, which performs configuration that is needed BEFORE the MUD is initialized. Typically, this is going to consist of fairly simple stuff like setting the database name or hash/blocksize, or changing directories, etc. The second file is the "startup" file, which contains startup commands that are run after the databases have been initialized and the MUD is ready to run. At the point where the startup file is being run, any arbitrary UnterMUD commands can be executed, including setting attributes, etc. These commands execute as the object named "wizard". With the distribution kit there are samples of the two startup files "config" and "startup" in the DB directory. You may wish to copy them and tailor them to your site. There are a variety of options available at boot time that you may wish to have set. Most of these will have to do with the directory the MUD should run in, etc. Some of these options will depend on the type of database routines you are running the MUD with, since different database layers accept different options. The server recognizes the two startup files with the "-c" and "-s" options. The "-c" option defines the configuration file name, and the "-s" defines the startup. Note that the configuration file is not strictly necessary, if you start your server in the database directory, with the default database names and all default values. Logging into the server: ------------------------ In the minimal_db.oif there is one player object in the db and one room. To connect to the game you must telnet/tinytalk/whatever to the player port, then type "c wizard" - which will log you in to the wizard object. At this point, you can start creating players with the "build player" command, and away you go. Maintenance Events: ------------------- Some events need to be run every so often, such as syncing dirty objects from the cache, or updating RWHO information. This is done by entering commands in the cron table, to run as the wizard. The sample startup file has some examples of this admittedly roundabout (but very extensible!) way of doing things. For example: _cronconfig defevent 300 "@_cachconfig sync" wizard _cronconfig defevent 400 "@_mudconfig rwhoupdate" wizard The first entry set a cron trigger to do a "@_cacheconfig sync" as the wizard every 5 minutes. The second will cause an RWHO update about every 400 seconds. UnterMUD's cron service is DELIBERATELY not tailored to provide extreme accuracy in submitting cron jobs, since the more you demand in precision, the more time you waste examining the cron table. There are "backup" modes defined in the database layers, for online backups. The format of the backup command is: _mudconfig backup "/backup/file/path" where the backup file pathname is the OIF output from the backup, with a sequence number appended to the file name. The backup sequence number is stored in the system object, for uniqueness. There's an optional modulus parameter that can be passed, and the sequence number is calculated modulo the given number. Therefore: _mudconfig backup "/backup/file/path" 5 means that the MUD will cycle through its backups, producing files named backup.0 backup.1... backup.4, to prevent effectively limitless disk usage. The backup operation has some subtle distinctions from dumpdb and loaddb, namely that the output is copied in raw mode - no error checking on the format of objects is attempted. Backup of a damaged database will not attempt any form of recovery. This is actually useful, since at the very least an attempt to copy each object out will be made. The intent of the backup command is to place it where it is called by cron: # bi-hourly backups _cronconfig defevent 7200 "@_mudconfig backup backupfile 5" wizard To preserve database integrity, backups are performed in one shot, by syncing the cache and writing the backup file. If your database is large, the backup will take some fraction more time to perform than would copying the database file. Performing frequent backups is probably pointless, since the database is pretty crash resistant to begin with. Talking RWHO: ------------- UnterMUD is designed to pass datagrams to an RWHO server, that in turns keeps an idea of who is logged in in the various MUDs out there. In order to pass RWHO datagrams to the server, you must first arrange with the keeper of the nearest (or most reliable) RWHO server to get a password and MUD entry, so that your RWHO packets will be accepted. This should not be a Big Deal to arrange. Since the RWHO packets sent from your MUD to the server are UDP packets written asynchronously, running RWHO doesn't cost a jot, performance-wise. To configure RWHO, you need a few lines in your server's startup file: _mudconfig rwhoserver server.host.name serverpassword _cronconfig defevent 301 "@_mudconfig rwhoupdate" wizard Where the first line defines your RWHO server's IP name, and the password you want to use when communicating with it. This command MUST be issued after your MUD's name is set, since the RWHO server expects the MUD name to be passed to it. The second line runs out of cron, and propagates the RWHO information every so often. Note that this is only a "group" propagation, and does NOT need to be run very often - it only needs to be run a little more often than the time period that the RWHO server bases information expiration on. You'll be given that by the owner of the RWHO server in question. Setting up InterMUD links: -------------------------- First off, you have to realize the implications of what you are doing. When you set up an link to another MUD, that means that people with player objects on that MUD can wander into yours and have a look about. If you don't like that idea, don't do it. It also means that your players can wander into the other MUD as well, and from there onto other MUDs, so you have to be courteous. If you think you've got players who are clueless newbies, make sure that they realize that they're being unleashed on the UnterVerse as a whole, and that in other MUDs they may get fried quickly if they annoy someone. The first step is to locate a MUD that will let you link to it. This might take a while, because the other MUD's owner might be polite enough to check with the people (s)he shares links with before allowing a new MUD into their group. Once you've reached an accord, you should exchange a pair of passwords, and the player and server port #s, as well as MUD-names, host names and addresses of the MUDs. Then make an entry in your startup script to define the remote MUD locally: #config defmud mudname IP-addr IP-host locpass rempass srvport playport [timo] _mudconfig defmud SomeMUD 6.66.66.6 host.site.dom mypass theirpass 6566 6565 8 They need to make a similar entry for you as well, for their MUD to recognize yours as legitimate. "mypass" is the password I will send to the remote MUD to prove it's me, and "theirpass" is the password they will send me to prove it's them. These are actually passed encrypted, so don't bother dumping them. The "SomeMUD" is the NAME of the MUD, and MUST match exactly what the other MUD calls itself (since the name is used as the seed for the encryption). The IP octets and host addresses should be pretty straight forward. The "srvport" value (6566 in the example) is the IP port # their server accepts server-to-server connections on, and the "playport" value (6565 in the example) is the port number they accept players on. The last value is an optional transaction timeout value, and can be set to something high if you have a terrible network connection. Be careful with the timeout (seconds) because that value is *also* how long your MUD server will hang, while trying to talk to the remote MUD. After you have the mud entries defined, the next step is to make exits. Courtesy implies you should ask the wizard of the remote MUD if there is a particular place he thinks you should make an exit to, rather than just slamming an exit down and having people wander through it. As the wizard on your MUD, you can create exits to remote MUDs without having to check to see if the remote room is link-ok, but don't abuse it. To make an exit, though, is easy: build exit exitname 426@SomeMUD Where you know 426 is a room on SomeMUD. Then when people try to walk through it, presto, off they go. If an ordinary player builds an exit to the remote MUD, your server will contact the remote and request permission first. This is the more civilized way of doing things. There is an option in the code known as the "known mud" option. What this means is that you must define every mud that you wish to allow a connection to your mud as a "known mud". This is not quite the same thing as just making a link to that mud -- if you use this option you have to define a mud both as a "known mud" and also exchange passwords if you want the link to work. The "known mud" option is simply a way of regulating who walks onto your mud. If you do not have a mud defined as a known mud, no one from that mud can walk onto yours, regardless of if they have a direct link or they walked over via another mud. The syntax for this is: _mudconfig defknownmud mudname where 'mudname' is the exact name the other mud uses to identify itself. If you decide to use this option, be sure to "defknownmud" every mud you have a "defmud" entry for. Remember - your link to a remote MUD is a privilege and a courtesy. Do not abuse it. UnterMUD literally makes MUDs a community, with all the privileges, pleasures, and responsibilities that result. System Macros: -------------- There are some system macros that come with the UnterMUD distribution. You don't have to use them, of course, but here are explanations for them anyway. _mudconfig defmac male 'pronouns $1 he him his' _mudconfig defmac female 'pronouns $1 she her her' _mudconfig defmac neuter 'pronouns $1 it it its' _mudconfig defmac many 'pronouns $1 they them their' _mudconfig defmac pronouns 'set $1 subv $2;set $1 objv $3;set $1 posv $4' These all set a player's pronouns. $1 is the player to set (should be "me" for non-wizards), $2 is the subjective pronoun (he, her, it), $3 is the objective pronoun (him, her, it), and $4 is the possessive pronoun (his, her, its). You can set these individually by using the set command, but using the system macro is faster. _mudconfig defmac sex '$2 $1' This does the same thing as the above macros, only slightly different. The syntax is "set me male" (or female or neuter or many). _mudconfig defmac BONK =@do "BONKs $1" The old familiar. The = sign is used here so everything after it will be passed as one string to the @do command, so the double quotes will come out correctly. _mudconfig defmac BOOT '_force $1 @QUIT' Wizard only. Forces the named player to quit the game. _mudconfig defmac TOAD '_force $1 @QUIT;@unset $1 pass;@unset $1 _pl;\ @set $1 name "a slimy toad named $1"' Wizard only. Forces the named player to quit, unsets their password and player flag so they can no longer log in, and changes their name to "a slimy toad named $1", where $1 is their old name. To untoad, the wizard will have to rename the toad back correctly, add the player flag with "@set player _pl", and give it a new password with "@_newpassword player password" (where 'player' is the name of the untoaded player). _mudconfig defmac pcreate '@build player $1 $2;@set $1 home 0;\ @which $1;@teleport $1 home' Wizard only. This creates a player with the given name and password, sets their home to #0 (limbo in most cases), tells the wizard what the new player's object id is, and teleports the new player home, to limbo.