*** Congratulations! *** You have now become a Wizard. Being a Wizard on LPmud ----------------------- Congratulations. The fact that you are reading this probably means that you have just become a Wizard on LPmud. First of all, try to remember this at all times ----------------------------------------------- As a wizard, you have immense powers. But, with those powers comes responsibility - so always think before you do anything. For example, it is possible to move a room's exits, to crash the game, and to kill all the players. And it IS possible to do all these things accidentally, so PLEASE be careful! Remember that as far as the game is concerned you are NO LONGER a part of it. Wizards do not play the game, they are above that and participate only by adding new ideas, like plots and rooms. If you don't know what you are doing, then you probably shouldn't do it. If you know what you are doing, but not if you should do it, then you probably shouldn't do that either. The file structure is a tree ---------------------------- LPmud mimics the file system hierarchy and file handling commands of UNIX. A directory is a set of files, where those "files" can be both normal files and other directories. Everything starts with the so-called root directory, the name of which is "/" (at least from inside LPmud!). As in UNIX, a file or a directory is referred to by its file name or its path name, i.e. for example "thing.c" and "/players/buddha/thing.c". The rooms in the "basic" LPmud world are in the directory "/room", and the objects (like the weapon and monster objects) are in "/obj". Each wizard has his/her own home directory, called, for example, "/players/buddha". Some commands for handling files: --------------------------------- ls - list the files in a directory cd - change the current directory pwd - show the present working directory cat - print the contents of a file on the screen more - print the contents of a file, approx. one screenful at a time tail - print the last few lines of a file ed - edit a file using LPmud's built-in, line-oriented, editor cp - copy a file mv - move a file rm - remove a file Where do I find the documentation? ---------------------------------- The following commands will give you info on the documentation: *** This varies from mud to mud. On TMI, you can do one of several things: - clone a manpage. Type "clone /man/obj/man". The man command will be added to the player object pretty soon. - type "man <function name>" to see what it does. - cd into /man and look around. - if you don't find documentation for something, look in /doc/lpc. Some of our documentation hasn't been integrated into the man pages. It can happen that you won't find what you look for in the documentation. In that case, either ask another wizard, read the code (which actually contains some very useful comments sometimes), or find out by testing. One of the first things you should do is to read the entire contents of documentation that "help wiz" makes available. This is not as much work as it seems and it really pays off very soon, since you later will remember where to look for explanations of commands and routines. Remember also that the faculty ha as part of their duties the obligation to help other wizards with their problems. I especially want to point out that the information on the editor "ed" can be found in "help ed". "ed" is the editor you will be using for most of your work. You can get help from inside of "ed" by typing "h". You can read almost any file with the command "more", as in: "more /obj/object.c" or just "more object.c" if you have changed into "/obj" with "cd /obj". Doing a "?" while in "more" will show you some of its useful sub-fuctions, like numbered backpaging. Object-oriented programming in LPmud ------------------------------------ When you play LPmud, everything you encounter (weapons, monsters, players, rooms etc.) are OBJECTS. Each object is an INSTANCE of a CLASS of objects. One class can INHERIT part of its design from another class. An instance of an object is either created by CLONING or LOADING the object class, and each object is described in a file, written in a C-like language called LPC. These "objects" are the programs that make up the game. All program code that you write as a Wizard or encounter as part of the standard world will be part of a description of an object or a class of objects that can be loaded and cloned. Many of the objects use a feature known as "inheritance", in order to save time and resources. there are many "standard objects" that have special functions that allow you to customize them with a minimum of work. Loading, cloning and updating ----------------------------- "Loading an object" means the process of taking an object file, for example "/obj/object.c", and reading it into the game. This is done as soon as that object is called for any way. For example, if a function in the object is called from another object, or if another object tries to enter it (as when a player walks into a room), then the object is loaded. When the object is loaded, one instance of the object class is created. If there should be only one instance, as for example for (most) rooms, this is enough. If you need to create several instances of a class of objects, you clone it. Objects can be cloned using the wizard command "clone", as in "clone /obj/misc/torch", and with the LPC function clone_object(), as in this_torch = clone_object("obj/misc/torch"); Cloning an object will cause it to be loaded, if it wasn't already. When you have changed the description of an object by editing the file, and want to load the new version of the object, you can use the wizard command "update". Then load (or clone) the new version. If the object in question is a room, a "goto ROOMNAME" will load the room as well. LPC --- LPC is a dialect of C and differs from C mainly in being simplified and in that it allows for handling the objects. It has only four data types (plus arrays of those data types), fewer operators and a simplified control structure. Note that before the contents of a file is read it is run through the standard C pre-processor. This program can be used to insert other files into the file being read, and to define constants and macros. Lines starting with "#", as the lines (no blanks before the #!): #include "config.h" #define INSURANCE_LIMIT 1000 #define CLONE(var, file) var = clone_object(file); are all commands to the preprocessor. Read more about LPC in the files found with the function "help lpc". This will list the subjects and subdirectories. You can read more about the C preprocessor in any book about C, but that is hardly neccesary for the ordinary use of LPC. Functions: ---------- There exists two types of functions in LPC, called LOCAL and EXTERNAL functions. A local function is defined in LPC code in an LPC file, and is contained in an object. A local function can be called from LPC code inside the object or from LPC code in another object. Objects communicate with each other by calling functions in each other. A local function can be declared STATIC, meaning that it can only be called from LPC code within the same object. External function are "built in" in LPC, so it has no definition in LPC code. Examples of local functions are the functions set_value and query_value in "/obj/object.c". Examples of external functions are write(), time() and add_action(). Error messages -------------- If an error occurs when LPmud is trying to load one of your objects, an error message will be printed on the file "/log/lpmud.log". You can read the last 25 lines of so of this file using the command "log lpmud.log". Sometimes you have to look at that file to find what caused an error. "lpmud.log" will usually grow quickly, and the command "log lpmud.log" will prove useful. The last error is stored for every wizard. It can be obtained simply by doing 'ed'. If there was an error, it will be displayed with the offending line number, and the correct file will be edited. Also, don't forget to periodically check "/log/PLAYERNAME.rep". When a player files a bug report in one of your rooms, using "bug", "typo" or "idea", the message ends up in that file! This can also be checked with the command "rep PLAYERNAME". Building -------- Start by looking at the existing rooms. As a wizard, when you enter a room, LPmud prints the path name of the object that is the room, such as "/room/start". You can look at the definition of the room by using the command "more /room/start.c" or "cat /room/start.c". [ Buddha's comment: this may not be true in every case about seeing the path [ name when you enter the room. For most purposes it is sufficient to use the standard room routines that you get by inheriting "room/room". Also remember that the best way to learn how to make stuff is to look at what others have made before you. Try looking at the stuff in /room or the work that other wizards have done. An example of a room -------------------- This is an example of how a file describing a room can look like (This file exists and is called "/room/home.c"): [ Note: this file also probably won't work. ] inherit "room/room"; void create(){ set_light(1); short_desc = "A Wizards Home"; long_desc = " This is the Home of one of our studious Wizards.\n"; dest_dir = ({ "/room/WIZ/boardroom", "Board", "/room/void", "Void", "/room/nh/misc/post", "Post", }); realm = "GM#1"; enviro = "inside"; peercheck =({ "Board",1, "Void",1, "Post",1, "peer",0, }); items = ({ }); } When the first player enters the room after the game was started, the file is run through the C preprocessor. The code produced is much larger and contains a lot of other functions besides the "reset()" that was actually written above. Four of these local functions are of special interest, and many objects will have them locally defined: reset():This function is called automatically, with the argument 0, when the object is created (that is, loaded or cloned), and after that every three hours or so, but then with the argument 1. It is used to initialize things in an object, and to periodically reset it (like putting new monsters in the different rooms, when they have been killed by all those brutal players). [ in 3.0 the create() function is called instead. Check more recent docs. ] long(): This function should print the long description of the object, using the external function write. If this function is defined the "long_desc" can just as well be set to be = 0 since it won't be referenced. [ on some systems this may be query_long(). ] init(): When a living object (a player or a monster) sees this object (if he, she or it enters the object, or arrives in the same room as the object, or the object is moved into the player or monster, or the object is moved into the same room as the player or object), the living object calls the function init in this object, with the living object as current player. If you redefine functions that are automatically defined by the inherited objects, you will sometimes want to call that function in the inherited code. You do that with the operator "::". If you define the function "init()" in your room but still would like to call the "init()" in "/room/room" you do that with the command "::init();". Typically this IS something that you want to do but remember to put the call to the inherited function first. The example above was a special room called a "workroom". As a wizard you have a command called "home" that will bring you to your workroom if you have one. To get the workroom described above do like this: > cd > ed workroom.c : r /room/workroom.c : w workroom.c : q And then just "home". You can change this room later to fit your own tastes. There will be some messages from ed while you do this, but ignore them and just write as it says above. Some more local functions that are defined in many objects ---------------------------------------------------------- heart_beat(): For objects that have a heart beat, the local function heart_beat will be called (automatically) every two seconds. The heart beat is started by calling the external function "set_heart_beat()", with a non-zero argument from the object. This can be used to simulate that time is going between events in the room, but usually the external function "call_out()" is better to use for that purpose. exit(): The opposite of init. Called when someone leaves the room. Be very careful when using this function. If there is an error in it, the occupants of the room can't quit, die, leave the room or perform anything that involves them or anything moving out of the room. And if this should happend to you despite this warning (which it most problably will, *sigh*) DON'T call for help. Anyone who enters the room will only get stuck as well. The only thing you can do is hope for a reboot of the game within the near future :) . drop(): If an object has a local function called "drop", and it returns a non-zero value, the object cannot be dropped. If such a non-droppable object is held by a player that quits, it is destructed automatically. get(): For a player or monster to be able to pick up an object, that object must have a local function called "get", that returns a non-zero value. query_value(), query_weight(), query_level(), query_npc(), etc: Lots of different functions returning values of local variables in the objects. set_value(), set_weight(), set_level(), set_npc(), etc: Lots of different functions for setting local variables in the objects. To find all the available functions you should read the following files and try to understand them, since they are the most inherited and cloned objects in the game. /obj/player.c - For player functions. /basic/living/* - For common monster and player functions. /obj/weapon.c - For weapon functions. /obj/armor.c - For armor functions. /room/room.c - For standard room functions. Player commands --------------- A living object (a player or a monster) can perform commands. Every command has to be defined in an object, although some commands are defined by the player object itself, like "quit" and "look". All other commands, like "south", "north" and "buy" (in the shop) has to be defined in an object. If you look at the example of a room above, you can see how the external function add_action is used to add one commands. This is usually done in the local function "init". The "current player" -------------------- The external function "this_player()" will return the current player. This is the player OR monster that performed the command that Alluviamud is now executing or caused the function "init()" in an object to be run. The external function "write()" will send the text it is given as argument to the current player. The function "say()" will send the text to all living objects that are in the same room as the current player (or that are inside the current player!), but NOT to the current player itself. When changing your rooms etc ---------------------------- ALWAYS, ALWAYS, ALWAYS test all changes that you make to your code, at least by doing update and clone or load on the object that you changed. Do this even after a trivial change, like correcting the spelling of a word in a message. It is very easy to accidentaly put a period or a semicolon somewhere in your code, and even if the your code is correct there can be bugs in the Alluviamud game itself that can cause it not to work. Some non-technical hints on how to be a good and/or popular wizard ------------------------------------------------------------------ In this section I will relate parts of the help RULES file. I believe that some of the things discussed in the rules and guidelines can be of general interest to how a wizard should behave and what things he (or she or it) should build and not build. So here are some of the rules and guidelines: Do not harm a player directly! This means, among other things, that you should never attack or kill a player. Also take care not to zap or teleport away (or heal) a monster a player is currently fighting (stat the NPC first). Avoid teleporting a player without asking first. Do not help a player directly! This means, for example, that you must not help by killing or attacking monsters, healing players or giving away items (an occasional beer might be excused). Also take care not to leave valuable items lying around, e. g. don't zap a monster and leave its weapon-containing corpse to rot on the street. Remember that the business of players is their business only! A typical case is when one player kills another and the killed one starts yelling for blood. Let them sort it out on their own. You may NOT interfere and if you get really mad about it, tell or mail an Archwizard or administrator. NOTE: player killing player is not allowed, so report all cases of it. They are allowed to beat each other sensless however (knockouts). Do not make deadly traps! A player must never die because he didn't know what happens in the next room. If some room is very dangerous, make some hint, unless they are in an area where such things should be expected, such as a Supervillians 'secret base'. Don't make too good things! And don't make the monsters too easy to kill. A monster with much treasure and/or many experience points should be big, dangerous and very hard to kill. Remember that the purpose of the game is for it to be fun and enjoyable both for players and for wizards - not to have all players converge on your sections just to get that 30d10 sword. Don't make healing too easily available! It's an important part of the game that players have to wait for their hit points to regenerate. Also, bars are one of the main sources of player interaction and role playing. Remember that even if you only heal a few points per player command (like "drink from fountain"), many players use macros and abbreviations and can still heal almost instantly. Make the players drunk, the healing very limited, the cost very high, or the place very hard to get to! Portable healing in the way of potions and food upsets the balance of the game. If you create such an object make sure they are rare and very expensive. In the super genre you shouldn't worry about this much, players will have powers letting them heal fast anyway... but in others genre's it is a major concern... Don't build lots and lots of extra bars and shops! The bar, as mentioned above, and also the shop, are natural meeting points and important sources of player interaction. Therefore you should try not to build your own bar or shop if you don't really need it (for example in a quest or for a guild). Prices of equipment. Should be based on 'real world' values of the area/genre the game is set in. remember value is in pennies, wieght in grams, and bulk is arbitrary, where a person can hold about 10 units of it. New powers for players. Are very easy to write but it is very hard to judge what effect they will have on the game in advance. A discussion about powers and how it should be limited is currently on the way. Some very loose rules exist and the best option is to ask an Archwizard FIRST and implement the spell AFTERWARDS, if ever. If you happily make something and put a lot of time into it only to be told in no-negotiation- possible-terms to remove it, you will only get mad and frustrated. Use your good judgement and in doubtful cases do something else or ask the other wizards what they think first. I hope you have found this to be of some use to you. I realize that it is in need of being updated, and extended... If you have additions, please let me (the editor. not the author.) know and I'll add them. Just send additional documentation to adam@dogstar.colorado.edu and it will no doubt get distributed to someone if it's any good. Happy mudding!