Rindar's Guide For Beginning MUD Coders (EmberMUD .029 Version) First Edition by Ron Cole (Editing help provided by Laurie Zenner) Forward: I've gotten a number of requests for coding tips and help over the past few months from various Admins/Coders that know very little about programming. After my search for MUD- specific coding documents turned up a pitifully small amount, I decided to try my hand at writing one. This guide is designed to be a "quick" guide for those unskilled with programming or just getting their feet wet with MUD programming. You will need to find other books and documents in order to become a good MUD programmer, but this is a good place to start. * * * ** Table of Contents: ** Forward ** Table of Contents ** Other Materials ** Common Terms ** Goal #1: Getting at Your Code ** An Introduction to MUD Programming ** A Bit More In-Depth - Header Files ** A Bit More In-Depth: Common Variables and Structures ** A Bit More In-Depth: Common Constants ** A Bit More In-Depth: Common Flags ** Final Warnings * * * ** Other materials: Before going any further, I thought I'd take a moment to list a few of the books and documents that I have found useful in MUD programming. Below that is a list of a few documents I recommend avoiding. The winners are: C for Dummies Volume I - This is one of IDG's better books. Yes, it is pretty basic, but then most of the people I get letters from have almost NO IDEA on how to code. This book explains the basic concepts of coding as well as common commands, the different variable types, hexidecimal, and binary numbers. Buy this book if you don't have any other C instruction manual. Linux in a Nutshell / UNIX in a Nutshell - O'Reilly, the master of good UNIX publications, brings us these two books. Both books give you a detailed rundown on standard UNIX and Linux commands such ps, kill, tar, and make as well as the commands for some of the more common text editors. If you are running your MUD in Linux, you should purchase one of these books. Note: these are reference books that explain HOW to use a command, not when or why. Running Linux - If you are actually in charge of your Linux server or just want a better understanding of how it works, this is the book for you. Another O'Reilly publication, it is worth the $30.00 price tag (more with the optional CD-ROM). Jennifer Smith's FAQs for MUDs - If you haven't been MUDing for a very long time and want to know more about MUDs, you should read these documents at http://muds.okstate.edu/~jds/mudfaqs.html Of course, if you are considering coding for a MUD you should ALREADY know everything in these FAQ's.. but then, that's not always how it works out, is it? Note: these documents contain little coder specific information. Darkoth's How to Start Your Own MUD - This is another document that anyone considering coding for a MUD should not have to read because they already know the information. But once more, that's not always how it works out, is it? The address is: http://darkoth.mudservices.com/howto.html MUD Mailing Lists - I'm not going to tell you the addresses for the most common mailing lists BECAUSE a few bad apples that read this document will start flooding the lists with very basic coding questions that DO NOT belong there ("What is a parse error?" or "I'm trying to make it so that each player can change his constants. How do I do this?" spring to mind as past questions from said "bad apples"). However, with a little work their addresses are easy to find. If you need help coding something and have an error you just can not figure out, a number of the people on the list will be willing to help. Two common lists: The Smaug Mailing List and the ROM Mailing List. Those using EmberMUD should use the ROM Mailing List. The losers are: C++ Manuals: C++ is a different language than C, though C++ is based on C. There is nothing wrong with a C++ manual on the whole, but since most MUDs are written in C, you will be learning commands that you can not use. If there is nothing else decent at your book store, buy a C++ manual. Otherwise, stick with books on C. Secrets of the MUD Wizards: This book did not have enough useful information to justify its hefty price. It is also not advanced enough for most MUD coders, especially when you consider the cost. You are better off reading this document and then buying a compre- hensive C manual. The Newsgroups: If you want lots of flames, off-topic replies, and just generally pointless feedback then the rec.games.mud.* and alt.mud.* newsgroups are for you! Yes, sometimes good and interesting information does come through these NGs (especially rec.games.mud.announce, which can be extremely useful for finding new code sites), but on the whole these groups are not the place for beginning MUD coders to seek help or ask questions. * * * ** Common terms - Here is a list of a few terms you'll need to know: Boolean or bool: A data type that is made up of TRUE or FALSE. That's it. Though in some cases the TRUE and FALSE are represented by 0 and 1 (or any non- 0 number). Character: A data type that contains letters and signs. This includes such things as the letter A. Groups of characters are called Character Arrays, and include such things as DOG, cat, and Dirk1. Data Type: Data types represent the attributes of a constant, variable, or function. What does that mean? Basicly, how it behaves. For instance, you can add 1 and 2 but you can't add the words cat and dog to each-other. Let's say you want to do 20 points of damage to a character. The character's hitpoints are stored in the variable htp, while the weapon's damage is stored in the variable wdam (this is an example with fake variable names that are not in EmberMUD). htp and wdam would probably both be integers because you can add and subtract numbers, not words. Data types are one of the most important concepts in programming. Constant: In programming, this is a set value that never changes and is usually represented by a word in capitol letters. Flags: Flags in EmberMUD are global constants which represent a specific value. They determine what "magical" affects are on your character, if your weapon is a sword, where an item can be worn, etc... GDB: This stands for GNU DeBugger or Generic DeBugger (depending on who you ask). When your MUD crashes (and it WILL CRASH.. this is a fact of virtual life), if you've configured your Makefile properly it will generate a core file which can be used by GDB and that will tell you EXACTLY where the error occured. Both Linux in a Nutshell and Running Linux give detailed accounts of how to use GDB. Global Constant: A value defined in a header file which can be used in any C file. Some common global constants are MAX_DIR (this is an integer value that tells the maximum number of directions), IMM_MAGIC, MAX_PC_RACE, MAX_LEVEL, and MAX_SKILL. They can be found within the file merc.h (in EmberMUDs) and the other header files. Global Function: A function that has been declared/defined in a header file and thus can be used in multiple .c file (as long as the header file is called in those .c files). GZIP: AKA GNU-Zip. GZipping is a way of storing information in a "compressed" form much like .zip files in DOS/ Windows. Such files will take up less room but can not be used without being "decompressed" or "expanded" to their original state. Header File: Any file with an .h extension. Header files are used to define and declare certain constants and functions that can be used in multiple source (.c) files without actually copying the code line for line into each .c file. Integer or int: A data type made up of numbers such as -1, 0, 1, and so on. Numbers with decimals are NOT integers. Linux: An operating system like Windows 95 or MS-DOS. Linux is a 32 bit system which is considered a "clone" of the UNIX operating system. Most MUDs run on Linux servers because of Linux's high speed (especially when compared to a Windows NT server). Local Function: Functions declared and used only in one .c file. Most functions are local. Make: This is used to update target files when.. er.. well. Heh. If you are new to programming, you won't understand a complex definition. Basicly, you type MAKE when you want to compile your MUD and turn it into an executable file (one that runs). Make calls on statements in your Makefile to tell it exactly what to do. MU*: A reference to any of the names for Multi-User games. This includes MUSH, MUX, MUD, TINYMUD, and so on. MUD: This stands for Multi-User Dungeon, though some people have warped it to Multi-User Dimension. Any multi- player game that has some sort of playing field fits the description of a MUD, but the common assumption is that MUDs are on-line (either via the internet or a direct dial-up connection). MUDs that use a large amount of graphics in place of text are usually refered to as Graphical MUDs. Object or .o : Object files are source files (".c") that have been translated down into a language harder for humans to understand but easily understood by the computer processor. When you compile, you turn your .c files into .o files. OLC: This stands for On-Line Creation. In other words, what happens when an immortal types EDIT. In the old days, all new mob, item, and area creation happened off-line with text editors. Many MUDs still do not have OLCs. Source Code: All of those files with ".c" extensions. Since these files tend to be useless without the header files, they are usually sent together. TAR or .tar : This stands for Tape ARchive (which TAR was originally used for). TAR takes a file or group of files and places them into a single archive file, usually retaining their permissions and structure (files within files, etc..). TGZ or .tgz: A group of files/file that has first been TARed and then GZIPed. To see the files stored inside the archive, you must first ungzip the file and then untar it. Variable: Basiclly a "storage area" that can have different values put into it. All of the values must be of the same type, however (characters, integers, etc..). .Z : Files with the .Z extension have been archived using the UNIX compress command/function. Such files are becoming rarer and rarer as the superior gzip has gained dominance. * * * ** Goal #1: Getting at your code. Ultimately, the questions arises: If you can't get at your code on your own, why do you think you can do a good job of programming or admining a MUD? Ignoring that question, I'd say going to download your code from one of the code sites on the internet would be the place to start. If you don't know the address of a site (which brings up the question of how you got this document in the first place), use a search engine to find sites with such keywords as ROM, EMBERMUD, MUD, and FTP.GAME.ORG among others. Once you've found the site, download the code and place it in the proper operating system (usually Linux). Now that you've gotten your code, you will most like- ly need to extract it from its archive file. Archive files are those that have .tgz, .gz, or .tar extensions (among others). If you are using LINUX, you can probably use the commands gunzip or gzip to decompress .tgz and .gz files. .tar files are decompressed using the command tar with one or more extensions. Try typing gzip or tar with no arguments or type manual to get more help. * * * ** An introduction to MUD programming: Okay, you're all set.. you've got your C manual, your Linux book, a server with Linux installed on it, and your source code de-archived. Now what do you do? At this point you get to think about what YOU want to code. You probably already have a lot of ideas, so let's try and shorten the list a little bit: If you are new to coding, you should eliminate all of the "large project" ideas that involve massive changes and get your feet wet with expanding old code. Some ideas that come to mind are: Adding a new skill, adding a new race, or modifying a current command. You will do all of these in the course of your MUD programming, so it is a good idea to get familiar with the process now. For these ideas, you should try and duplicate what has already been done in the code by finding and following other text strings. Use the command ts (in DOS) or grep (in Linux) to search all of your source and header files for ANY occurrence of a specific keyword. For instance, if you wanted to add a new race, you could search for the word HUMAN. After writing down the file name and line number of every occurrence of the keyword, you would then open up your code with any text editor and actually look at the code around the word. This should familiarize you enough with the code that you can do 90% of the idea (cut and paste is a wonderful thing). THERE ARE certain aspects that you will miss by using this method (the constant MAX_PC_RACE being increased by 1 comes to mind), but you will learn about that when you compile and get errors. Don't worry about it - it is all part of the learning process. Just go in and fix the errors that you find (most compilers will tell you the line number of the error and the type). Once you have a fair understanding of programming and a decent feel for the code, you should try moderately diffi- cult programming tasks. Such things as creating new commands, adding new spells, and making new item types (with their accompanied item_type flags) fall into this category. Again, use some of the "find and follow" techniques from above to help you, but more and more you will be relying on your cod- ing abilities. Finally, you'll have a good understanding of program- ming and know the various functions and values of the code back and forth. Now's the time to do those projects like removing autocombat for a "real time" system, creating a new magic system, etc, etc... You're still going to have errors and bugs when you write code, but at least now you'll be able to fix them without always looking things up in your C manual. * * * ** A bit more in-depth - Header Files: The header files contain information that is used in multiple .c files. Global constants such as the maximum level a character can attain and what level an IMP is are contained in these files, as well as declarations of global functions and variables. Of all the header files, merc.h is the most important (at least in EmberMUD). Here are a few descriptions of some of the header files and what you will find in them: Merc.h: The MOST IMPORTANT HEADER FILE. Every source file includes merc.h, so the most used functions have been declared here. As well, the structures for characters, mobs, and areas are here (in other words, every value that a char- acter file contains such as hitpoints, mana, etc.. is stored within the CHAR_DATA structure. What variable types are in that structure are defined here). If you wanted to, say, make it so that characters can have their hair color stored on their character sheets, you would modify this file. Also, all of the flags in the game are defined right here. So, if you want to make it so that characters can be affected by lycanthropsy, you'd modify this file. As well, any new skill that you create must have an entry here (as well as in const.c and db.c). I can't stress how important it is to become familiar with merc.h. Interp.h: This header file stores the declarations of any command that can actually be done in the game (though you also have to add an entry to the command table in interp.c). In other words, if you want to have a character be able to do a really cool new martial arts move called NINJAKICK, you must declare the function here. Magic.h: Whenever a new spell is created, a declaration of it must be made in Magic.h. You will also need to modify magic.c and const.c when you add a new spell. * * * ** A bit more in-depth: Common Variables and Structures. Now we are getting into the nuts and bolts of programming. Here are a few descriptions of common variables and structures: char_data : You can find a listing of all the values for char_data in merc.h. Look for "char_data" or "struct char_data" (you must have the double spacing). This structure contains the essence of a player or MOB. Its short description, hit points, stats, experience, and armor value are all stored in this sort of structure. You need to be familiar with it. You will most often see this called by functions in the form of ( CHAR_DATA *ch ) in which ch contains the variable data for a specific mob or player. race_type: This structure contains the data for both PC and NPC races and can be found in merc.h. Such values as imm (immunities), parts, and aff (affect bits that a race permanently has) are a part of this structure. The specific data for each race is contained in const.c. pc_race_type: This structure contains certain additional information for each player-character race. Points (the number of creation points it takes to purchase the race) and skills (bonus skills that the race gets to start with) can be found in this structure. The structure can be found in merc.h, though each individual PC race will have its own entry in const.c. affect_data: A structure containing the data for affects (those things that you inflict characters with when you hit them with a spell, room affect, etc..). obj_data: This contains all of the information about a single object. What it is affected by, if it is enchanted, the descriptions, what level it is, etc... Note: You're probably thinking, "I understand that a structure 'stores' data inside of itself, but how do I call up that data?" Simple. Just point it out. An example: We have player ch which is CHAR_DATA. We want to find out what their level is. To find the value, we would "point" as follows: (ch->level). Of course, we'd have to plug that value into something or compare it with another value for it to be of use. * * * ** A bit more in-depth: Common Constants. Most of these con- stants are defined in merc.h. MAX_SKILL: Defined in merc.h, this is the maximum number of skills that can exist in the game at any one time. If you add a lot more skills to your game, you will need to increase this number. MAX_ALIAS: How many command aliases can a character have? This limits that number. MAX_CLASS: The maximum number of classes in the game at any 1 time. Be sure to increase this number if you decide to add a new class. MAX_PC_RACE: Sure, you can add as many new races as you want.. but the number of PC races are limited to this number. You will probably increase this number numerous times. MAX_LEVEL: The maximum level that can be attained in the game. This is set to 100 in EmberMUDs. LEVEL_HERO: The level at which a person becomes a hero and can uses hero- level commands. It is defined as (MAX_LEVEL - 9). LEVEL_IMMORTAL: The level at which one gains the use of immortal level commands. It is defined as (MAX_LEVEL - 7). PULSE_PER_SECOND: The number of pulses that occur every second. This is the basic speed control of the MUD. Want things to slow down? Decrease the number. IMPLEMENTOR: The level at which a character gains every command in the game. This value is set to MAX_LEVEL. ML: This is a re-definition of Implementor that is done for command purposes in interp.h. The level is MAX_LEVEL. IMPORTANT NOTE: Due to poor programming skills on the part of some of the various codebase programmers (EmberMUD is based on ROM, which is based on MERC, which is based on DIKU, and each of those code bases had a different set of programmers), constants are not always called when they should be and some variables which do the same thing are defined twice. BE AWARE OF THIS. * * * ** A bit more in-depth: Common Flags. Okay, you've heard of flags, but what are they really? Flags are a group of constants which have been set up to allow certain data bits to be more-easily set. Muh, you say? Open merc.h and look for the word "AFF_DETECT_MAGIC". This is an AFFECT FLAG which, when set, allows a character to see items affected by the ITEM_MAGIC flag. Flags allow spells to poison people, items to be wielded, weapons to be flaming, and dragons to fly. In short, they are important. So, what data type is a Flag? You might be surprised to find out that flags are Integers (long ones in most code bases). When you are defining your flags, there are two ways to do it: With a number incrementing up in units of 1 or a letter. A letter? How can that be possible, you ask? The reason is that the letter is not a character: it is the one (and in some cases 2) letter name of an integer value. Pretty tricky, eh? Yes, especially when you consider what the letter represents. The letters are used to define flags representing RT ASCII conversions of possibly extremely large numbers. Though A represents 1, B represents 2, and C represents 4, later letters represent much larger numbers as each value doubles itself. T, for instance, represents 524288 and ee (the largest of these flags) represents 1073741824. ee is much easier to type and remember than 1073741824, isn't it? For the complete list of letters to numbers, look in merc.h for the term "RT ASCII" and you should easily find the list. Now comes the question "Why do we have two different ways of assigning values to a flag? The reason is that the second way (using letters and doubled integers) allows for multiple flags to be "stacked" within a single value in a structure. Simply speaking, you use "letters" when you want to have more than one flag be possible in a value and "numbers" when you only want one flag at a time. So AFFECTs are done with "letters" in order to allow someone to be armored, poisoned, and blind, while ITEM_TYPEs are done with numbers in +1 increments so that a weapon can not also be a piece of armor and furniture. Here is a brief list of some common flags: AFFECT or AFF_ flags: Used in affected_by to determine permanent afflictions and powers. Common AFFECTS are: AFF_BLIND, AFF_INVISIBLE, and AFF_DETECT_EVIL. ITEM or ITEM_ flags: These flags are used to determine what an item does as well as what its value[] numbers are used for. Some common item flags are ITEM_LIGHT, ITEM_WAND, ITEM_WEAPON, and ITEM_ARMOR. Damage or DAM_ flags: These flags represent in what way damage is inflicted, which in turn determines how well armor works, if the character can resist it, etc... A few example: DAM_BASH, DAM_FIRE, and DAM_ACID. * * * ** A bit more in-depth: Common functions, calls, and checks. = : This one is pretty easy. Whenever you use the equal sign, the value on the LEFT is made equal to the value one the RIGHT. An example: dam = 100; dam is an integer which we'll be using to do some serious damage to a character's hit points (100 points, in fact). -= : This is a little bit more complex than =, but still easy to understand. This sign will subtract the value on the RIGHT side from the value on the LEFT. Example: victim->hit -= dam; Here, the CHAR_DATA structure victim holds the integer value hit. The integer value dam is being subtracted from the value hit, so hit is = hit-dam. Got it? Good, because you can do a number of other arithmatic symbols in this way. +=, *=, /=, etc... ! : This means not. It gets attached to boolean functions/ checks. Two examples: !IS_SET and != number_range(XX,YY) : Produces a random integer from XX to YY. So, number_range(1,10) would produce a number from 1 to 10. This function works well with the = sign. one_argument(XX,YY) : one_argument is a function that you will probably use often, especially if you add a lot of new commands to your MUD. one_argument takes the character string XX and shaves off the first "word" it finds, placing it into character string YY. If you have a character string being equal to one_argument, the new string will be equal to XX minus the first word. Sound kind of complicated? It is, but here is an example: I have a char called argument in which I have entered the sentence "I LOVE MUD". I wish to strip off the first word of that sentence so I plug it into the following statement: argument = one_argument( argument, arg1 ); arg1 is a char value that was previously empty, but after this arg1 will contain the word "I" and argument will contain "LOVE MUD". Pretty nifty, eh? if ( ): If is one of the most common checks used in program- ming. The if statement checks to see the values in its ( ) are true. If it is true, the if statement executes either 1) the next line of code or 2) anything within the { }'s below it. Here's a "real life" example of an if statement: if (you are male) { I refer to you as Mr }. A female would not be refered to as Mr because the "you are male" statement would be false. One of the nicest things about if statements is that you can "stack" checks within its brackets using the values || (or), && (and), == (equal to), and != (not equal to). Another "real life" example: if ( (you are male) && (you are over the age of 70) ) { I refer to you as Old Man }. So, only a male over 70 would be refered to as old man. Get the idea now? Here's a "real MUD" example of an if statement: if ( IS_SET(pexit->exit_info, EX_CLOSED) && IS_SET(pexit->exit_info, EX_HIDDEN)) { send_to_char( "Alas, you cannot go that way.\n\r", ch ); return; } The if statement checks the exit to see if it is set to EX_CLOSED. It then checks to see if the exit is set to EX_HIDDEN. If the exit is closed AND the exit is hidden, the character will receive the message "Alas, you cannot go that way." IS_NPC(XX) : IS_NPC looks at char_data XX (usually represented as "ch") and returns true if the character IS an NPC. THIS IS AN ESSENTIAL CHECK THAT IF NOT USED COULD CRASH THE GAME. How? If you attempt to manipulate data that characters have but that an NPC does not, you can cause various faults that will crash your game. IS_SET(XX,YY) : IS_SET checks to see if whatever you are calling up in XX is equal to the flag YY. For instance, let's say we have an item being called up as container. We want to see if said container has the flag CONT_CLOSED on it. In XX, we should insert the path to where the character's affect flags are stored and in YY the flag CONT_CLOSED. The statement will return TRUE if the flag is set in the specified location. The call will look like this: IS_SET(container->value[1], CONT_CLOSED) IS_AFFECTED(XX,YY) : IS_AFFECTED works in almost the same way as IS_SET. The difference is, you only need to plug in the variable that represents the character into XX and it only checks for AFFECT flags. In other words, checking ch for flying would look like this: IS_AFFECT(ch,AFF_FLYING) send_to_char( XX, YY ); : This will send character string XX (char) to player YY (CHAR_DATA). Two examples: send_to_char( "Alas, you cannot go that way.\n\r", ch ); ..and.. send_to_char( buf, ch ); str_cmp(XX,YY) : Compares character string XX to character string YY and returns FALSE if the two are the same. So, str_cmp("Hi","Hi") would return FALSE. Use an ! if you want it to return TRUE when the two are the same. strlen(XX) : Returns the length (an integer) of XX in which XX is a character string. strncmp(XX,YY,AA) : XX and YY are character strings that will be compared to one-another. The number of letters compared depends on integer AA. So strncmp( arg3, "experience", 5 ) would compare character string arg3 with the word experience.. or at least the first 5 bits of each string. Note: If the two strings compared are THE SAME, strncmp will return FALSE. So, if you want the comparison to go off when both strings match, you need to use !strncmp. * * * ** Final Warnings. Before you start coding on a MUD, let me just say this: Coding can be an extremely thankless job. Don't expect constant praise for your work unless the changes you make benefit a character in hunting/killing/solving quests. Most of the time, people will be yelling at you to fix XXXX or implement command YYYY and wondering why it isn't done yet... One other thing: Some parts of the MUD code have been done in an extremely poor manner. If you have decided to start coding because you want to learn C, my advice to you is: STOP NOW. You will pick up more bad habits than good. You've been warned. * * * * * * * * * Copyright Notices (boring stuff that doesn't have to do with MUDs): This document is copyright 1997 by Ron Cole. It may be freely distributed so long as 1) the author's name and the title of this document are not changed in any way and 2) no money is made from the distribution or sale of this document unless prior arrangements have been made with the author. Certain copyrighted titles such as _C For Dummies_ were referenced in this work. The author of this document is in no way attempting to challenge said copyrights in any way, shape, or form. ============================================================================= / ______ _______ ____ _____ ___ __ _ ______ ____ ____ _____ / \ | ____|__ __| _ \ / ____\ / _ \| \ / | ____| / __ \| _ \ / ____\ \ / | |__ | | | |_| | | | |_| | |\/| | |___ | | | | |_| | | / / | ___| | | | ___/| | __| _ | | | | ____| | | | | __/| | ___ \ \ | | | | | | | |___| | | | | | | | |____ | |__| | |\ \| |___| | / / |_| |_| |_| o \_____/|_| |_|_| |_|______|o \____/|_| \_|\_____/ \ \ / ============================================================================ ------------------------------------------------------------------------------ ftp://ftp.game.org/pub/mud FTP.GAME.ORG http://www.game.org/ftpsite/ ------------------------------------------------------------------------------ This file came from FTP.GAME.ORG, the ultimate source for MUD resources. ------------------------------------------------------------------------------