<!-- MHonArc v2.4.4 --> <!--X-Subject: [MUD-Dev] MUD Design doc (long) --> <!--X-From-R13: Fuvahf Pneaneq <guvahf_oneaneqNovtsbbg.pbz> --> <!--X-Date: Fri, 11 Dec 1998 01:29:08 -0800 --> <!--X-Message-Id: 3670E890.5465DAA#bigfoot,com --> <!--X-Content-Type: text/plain --> <!--X-Head-End--> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> <html> <head> <title>MUD-Dev message, [MUD-Dev] MUD Design doc (long)</title> <!-- meta name="robots" content="noindex,nofollow" --> <link rev="made" href="mailto:thinus_barnard#bigfoot,com"> </head> <body background="/backgrounds/paperback.gif" bgcolor="#ffffff" text="#000000" link="#0000FF" alink="#FF0000" vlink="#006000"> <font size="+4" color="#804040"> <strong><em>MUD-Dev<br>mailing list archive</em></strong> </font> <br> [ <a href="../">Other Periods</a> | <a href="../../">Other mailing lists</a> | <a href="/search.php3">Search</a> ] <br clear=all><hr> <!--X-Body-Begin--> <!--X-User-Header--> <!--X-User-Header-End--> <!--X-TopPNI--> Date: [ <a href="msg00948.html">Previous</a> | <a href="msg00950.html">Next</a> ] Thread: [ <a href="msg00951.html">Previous</a> | <a href="msg00936.html">Next</a> ] Index: [ <A HREF="author.html#00949">Author</A> | <A HREF="#00949">Date</A> | <A HREF="thread.html#00949">Thread</A> ] <!--X-TopPNI-End--> <!--X-MsgBody--> <!--X-Subject-Header-Begin--> <H1>[MUD-Dev] MUD Design doc (long)</H1> <HR> <!--X-Subject-Header-End--> <!--X-Head-of-Message--> <UL> <LI><em>To</em>: MUD-Dev <<A HREF="mailto:mud-dev#kanga,nu">mud-dev#kanga,nu</A>></LI> <LI><em>Subject</em>: [MUD-Dev] MUD Design doc (long)</LI> <LI><em>From</em>: Thinus Barnard <<A HREF="mailto:thinus_barnard#bigfoot,com">thinus_barnard#bigfoot,com</A>></LI> <LI><em>Date</em>: Fri, 11 Dec 1998 11:40:32 +0200</LI> <LI><em>Reply-To</em>: <A HREF="mailto:mud-dev#kanga,nu">mud-dev#kanga,nu</A></LI> </UL> <!--X-Head-of-Message-End--> <!--X-Head-Body-Sep-Begin--> <HR> <!--X-Head-Body-Sep-End--> <!--X-Body-of-Message--> <PRE> Hi, Here is a design doc I am writing for my MUD. If anyone has such documents I would love to see it. Maybe some of these docs can be published on the MUD-Dev web site..? I find design documents very instructive and much more understandable than source code. I hope this doc helps someone. Cheers Thinus ----------------------------------------- GATES OF MYTH AND MYSTERY - Design details 1. GENERAL OBJECTIVES - What I want to do. 1.1 FOREWORD - Meaningless chatter. I am writing this document mainly for myself but hope that it might prove useful and give some insight into the design and logic of MUDs in general. I will try to explain all the issues I had to deal with in a clear and easy to understand way. This document will probably never be finished as improvements and new features will be added all the time. 1.2 OVERVIEW - Whatever. I have never liked the idea of coders and builders and administrators that cannot play in a mud so I set out to create a world that would be fun to play, create and maintain. I also dislike level/experience based systems. This will be an attempt to create a pure skill based system. 1.3 ADMINISTRATORS - Targets of hatred and groveling. The administrators will be presented as gods. Gods will have a certain amount of religion points. They can use these points to affect the world in several ways. The only way a god can regain religion points is when characters sacrifice objects to the god or from donations from other gods. If a god spends points to help a character who encountered a bug the god can demand sacrifices from the coders/builders responsible for the bug. Players will be able to use a pray command to pray to a specific god or to all gods. Gods have no physical presence, if a god wants to have a physical presence he will have to possess a creature. There will be several types of possession to represent the amount of freedom the possessed creature still has. Possession will not be limited to gods. There will probably be a NPC god too. This god will have certain rules for answering prayers. It will be very expensive to get a prayer answered from this god. This god is needed for when no other gods are connected. 1.4 CODERS - The people that do all the cool stuff. All players in the world can be coders. Coding can only be done in a dream chamber. Every god will have at least one dream chamber. A player can then write the code and create the object to test it. When the player is satisfied with the object he can pray to have his dream come true. The god can then demand a suitable sacrifice before creating the object (creation will cost religion points). All objects will be measured in terms of religion points. If a player has a piece of nifty code or a cool idea to expand the game the player could be rewarded with any objects the god finds fitting. 1.5 BUILDING - I want to create a vorpal banana of god slaying. Building can also be done in a dream chamber. If a player has enough money to sacrifice he can create a whole area with NPCs and other objects. 1.6 CHARACTERS - The living. All players and NPCs are characters. All commands available to players will also be available to NPCs except for OOC commands like "who", "quit", etc. 1.7 NPCs - The living dead. NPCs will be controlled by an AI system. Each NPC will have a loyalty character and a loyalty rating. If offered enough money and if its loyalty rating is low enough the NPC might change loyalties. NPCs can be loyal to themselves. NPCs can be hired to perform simple tasks like guarding, attacking, training, following, etc. If the loyalty rating is high enough the NPC will perform the task for free. 1.8 PLAYERS - The living living. Players are free to do what they choose. The main objectives will probably be to build your own domain, to become a specialist in certain skills or to become a god (there will be ways). 1.9 THE LINK-DEAD PLAYER - The living living dead. All characters in the mud are going to exist all the time. If you log off or go link dead your character will be moved to the half-life vaults. These vaults will be well hidden. When the character re-connects the character will be moved to the last location. There will be ways to enter the vault. When a character is in the half-life state the character can not be killed. Some magic spells might still have an effect. The character can be searched for items though. So if someone finds the entrance to the vault he can rob the half-life bodies. A player will be able to change his half-life location. If a player has enough money and some good guards and locks they can create their own half-life vault. 1.10 DEATH - Oops, did I just step on your village? When a character dies the character will automatically drop all items carried. The character will be moved to the halls of the dead. A prayer will bring the character back to life and move it to a temple. The god will demand sacrifices though. The gods will keep tabs on sacrifices owed and when a character is deep in debt the gods can ask the character to perform certain tasks, like newbie duty. If a newbie keeps dying the gods can be merciful and give the newbie some instructions and assistance. 1.11 SHOPS - Adventurer heads for sale at dragon keep. A shop will only have limited supplies. The shopkeepers should encourage characters to sell their items to them so that they will have a running supply of stock. If you kill the shopkeeper you can take all the items being sold in the shop. A shop will usually have a trader with good trading skills and a guard or two with good fighting skills. Remember that the guards can be bribed. 1.12 CLOSING - Blah, blah. I would like to keep the mud as open as possible, give the players as much freedom as possible (and the NPCs too). Most muds are controlled by impossibilities, things like unkillable NPCs, unbreakable doors, unusable items or skills/spells, unpickable locks, etc. In this world no one and nothing is safe. Even the gods are vulnerable (yes, the gods can be slain, there will be ways, oh yes, there will be ways). The mud will strive not to introduce any impossibilities into the game. Some people will argue that limiting the player to a fixed set of commands is already introducing impossibilities. This has some merit as a player wont be able to break branches off a tree and make his own bow, etc. So what exactly is my objective? As I see it the game defines certain rules. These rules are implemented by a command set. The commands in the command set should be as flexible as possible. If I type in 'kill table' the reply should not be 'You cannot kill table'. An acceptable reply is 'Table is not alive and cannot be killed' or 'You whack the table a few times and are pretty sure the table has moved on to greener pastures'. I think where the problems originate is that coders just look at a player's stats and then prevents the player from doing certain things. To me this is a big no-no. If you want to prevent a player from doing something you will have to place a guard or a decent lock, and a lock can be picked and a guard can be killed. So the code will never include a statement where certain players are allowed to do something and other players are prevented from doing it. What this means is that all player affecting must be done through existing game mechanics. If you want to prevent someone going through a door get a high level mage to embed a few powerful lightning spells on the door and to supply you with a way to bypass the spell. Ok, that's the idea. Let's design. 2. DESIGN - Groovy baby. 2.1 INTRODUCTION - Hi, I'm your mugger, my name is Rob U. Blind. I will handle the design by first describing a few systems. These systems will handle all aspects of the game. 2.2 THE WORLD SYSTEM - I'm a systematic girl in a systematic world. I hesitate to use the word 'world' because it immediately brings up a picture of a rotating earth in my mind. I should rather call it universe but for ease of use I will keep it world. The world contains everything in the MUD. Let us look at how we can represent earth in a mud. First we have earth (assume that the mud is limited to earth, no space travel). Earth contains everything. We can sub divide earth into continents and oceans. For all intents and purposes they are the same things except that one has land and the other water. We can sub divide the continents again into lands. The lands into several locations. Each of these locations will be a room in normal mud terms. In these locations we will find certain objects (humans, animals, trees, houses, tables, etc.) Some of these objects, a bag for instance, can contain even more objects. This forms a nice tree structure with earth the root and at the top. It is even possible to plug space traveling into this. We just make earth not the root anymore but a node in the universe tree. My world structure will work like this. All objects will have 3 pointers. One pointer will point to the parent, one to the next sibling and one to the first child. The root object will have null pointers for the parent and for the next sibling. If you want more information see any text on tree structures. 2.2.1 POINTERS VS INDEX - Does the index disappoint? The problem with pointers are that they change if you shutdown the mud and run it again. If you save the 3 pointers with the objects they will not be valid when you load the library after a shutdown. To bypass this we give each object a number instead. The tree will be linked by numbers. The number the object is given will always stay the same. When an object is completely removed from the game we have to make the number available for use again. It would be a pity if the mud ran for a few years and suddenly crashed when we create object number 4,294,967,296. If you have this many objects in the mud then you will have to change the numbers to 64 bit and run a little conversion thingy on all the objects. 2.2.2 CONTAINERS - Stuff it. Everything in the world is contained within something else. Can we use this for moving stuff around? Partially. If we have a bag and we have a cat inside it, the cat will have the bag as a parent. If we want to let the cat out of the bag we simply add the cat as a child of the bag's parent. Does that sentence make any sense? Let me clear it up a little. We have object A - a room, B - a bag, C - a cat. B has A as a parent and C has B as a parent. To move C out of B we add C as a child of A. Now C and B will be siblings and they are both children of A, and the cat is out of the bag. This seems to work quite cool. We have to do some bookkeeping on the tree to indicate the change but other than that the procedure is easy. The problem is room exits. Rooms hardly ever has an exit that leads to its parent. First step in solving this is to implement a default movement method. Here is how it works: In every object we have a get_move method that takes the direction as a parameter and returns the number of the new parent. The default get_move method will return the number of the parent. For rooms we override the get_move method. The new get_move method will compare the direction parameter with the directions known to it and return the number if it finds a match otherwise it will return its own number. To add an exit to a room we will have another method that takes the direction and destination room number as parameters and adds the exit to the room object's exit list. This just might work. The only problem is to identify objects in such a way that the coders don't have to use numbers to link rooms together. We also have to take the dream chamber concept into consideration. An identifier field should do the trick, we just have to check for uniqueness of the field and then the builder can give his room a unique name to access it by. 2.3 THE SKILL SYSTEM - Strangle dragon failed? Why? The mud will not implement levels, exp, stats like strength and dexterity or classes. There can be only skills. Skills will also be a tree. An overall skill rating will be the root of the tree. On the first level of the tree will be the normal stats we are used to like strength, agility, constitution, mental ability (for spells), etc. Underneath for instance strength we will have a skill combat. Underneath combat we can have unarmed, swords, axes, etc. Underneath unarmed we can have punching, kicking and wrestling. Every character will have a skill tree of his own to keep track of the different values obtained in the different skills. Note that the character does not need a complete skill tree. The character just needs the branches in which the character has a skill value. If you use a skill the value of the parent should have an influence. Yes, yes, but what about shooting a bow, doesn't it use strength and agility? Ok, put a link in the bow shooting skill to strength. Compare the structure I described here with the structure of the world system. Well slap me silly, it seems to be exactly the same type of structure. A normal tree except that some nodes must be linked to completely different parts of the tree. Hmmmmmm. Maybe we should make a nice generic structure and fit all the other systems into it too. 2.4 THE COMMAND HANDLER - Command 'klli draghn' not recognized. If we look at the way commands are handled we have to start at the keyboard. The player types a command and the command is received by the networking module of the mud. The networking module now passes the command together with the player that issued the command to the command handler. The command handler now has to try and find the command somewhere. Where to start? First the command handler has to check if the player has that command defined on the player object. Then the command handler has to check if the command is defined on any object the player is carrying. Then the command handler has to check if the location the player is in defines the command and then finally the command handler has to check the standard command set for the command. If no such command is found the command handler informs the player, otherwise the method associated with the command is called to perform the required action. It is very important to decide on the scope allowed to commands. All commands in the standard command set can be executed anytime, anywhere. This has to be taken into consideration when designing the command set. Custom commands embedded in objects presents a few problems. Here are a few examples of the route of a command illustrating the problem areas: P1 - player 1 P2 - player 2 O1 - object 1 O2 - object 2 O11 - object 11 O22 - object 22 L1 - location 1 L2 - location 2 P1 is carrying O1 and P2 is carrying O2. P1 and P2 are in L1. L1 is in L2 (just say L1 is a cage and L2 a normal room). O1 contains O11 and O2 contains O22. L2 is contained in the world object. Ex 1 P1 issues a command that is only defined in the default command set. P1 tries to handle the command and fails P1 calls O1 to handle the command (in the inventory of P1) O1 fails to handle the command (O1 should NOT call O11) P1 calls L1 to handle the command L1 fails to handle the command and calls P2 to handle it (P2 is also inside L1) P2 fails to handle the command (P2 should NOT call O2) P1 calls the default command handler Example 1 does not make provision for 1 feature I would like to add to my world. Consider my world tree, let's say that on the first level of the tree we have several continents. I assign builders to each of these continents. One of the continents develops a command they want to implement but this command is only relevant in their continent. To implement it using the command handling illustrated in ex 1 will be messy. If I could change the command handling so that the command is passed to every parent until the command is handled or the root object is reached it should be easy to implement area specific commands. Another example: Ex 2 P1 issues a command that is defined in L2 P1 tries to handle the command and fails P1 calls O1 to handle the command (in the inventory of P1) O1 fails to handle the command (O1 should NOT call O11) P1 now PASSES the command to L1 L1 tries to handle the command and fails L1 calls P2 to handle the command (P2 in L1) P2 fails to handle the command (P2 should NOT call O2) L1 PASSES the command to L2 L2 handles the command and returns success. If L2 failed to handle the command it would have been passed to the parent of L2 which is the world object. The default command set will be defined in the world object. Note how easy it will be to put another node between L2 and the world object. The command will be passed from L2 to the new node and then on to the root. Also note that if we join the world with a space traveling world the command handling will not stop at the root, it will be passed on to the universe root. The more I think about the possibilities the more I drool. But first we have another wrinkle that needs to be ironed out. Imagine L2 has a bell. If we are in L2 and we type 'ring bell' then the bell rings (and you have to buy a round for everyone). If we are in L1 and we type 'ring bell' the command will eventually be passed to L2 and the bell will ring. Oops. I'm locked inside a cage but I can still ring the bell on the table. We just have to add a flag that indicates if it is a global or a local command. Global commands are available to the sub-tree of which the object containing the command is the root. To see the commands in action here are methods required: handle_command(command, command_src) no return value handle_global(command, command_src) return true or false handle_local(command, command_src) return true or false handle_static(command, command_src) return true or false handle_command This is the default command handler. Whenever a command is generated this method will be called in the object that generated the command. When an object fails to handle a command it will call the handle_command method of its parent. The first thing handle_command does is call handle_global. If handle_global fails then handle_command checks if this object is the same one as command_src. If it is then it will call the handle_static of its first child. If it is not it will check if command_src is one of its children. If it is it will call handle_static of its first child. If the command has not been handled call the handle_command of the parent. handle_global Will just check the commands with a global flag defined on this object, call the method associated with the command if found and return true, otherwise return false. handle_local Same as handle_global but checks commands with local flag. handle_static This will call the handle_global, if it fails it will call handle_local. If handle_local fails it will check if it has a sibling. If it has a sibling it will call handle_static of the sibling. If the command has not been handled return false otherwise true. 2.5 TIMING - I want it all! I want it all! And I want it now! We need a queue to store all the commands the system has to process together with a time of when to process it. We need this so that 3 pages of combat doesn't scroll past at blinding speed with the last line reading 'Welcome to Green Pasture. Home for the livingly challenged.' Whenever a command is generated that must happen at a certain time a timer object should be created. The timer object must have a trigger function, a requested time and maybe a parameter or two for the trigger function. The timer object is then added to the queue. The queue will not really be a standard queue but a queue sorted on requested time. The world will keep comparing the current time with the requested time of the first object in the queue. If the current time is equal to or later than the requested time the timer object is triggered and removed from the queue. Simple, isn't it? Will probably hit the snags come implementation. TO DO - Lazy slob. World specific details. Stuff like day/night, weather, visibility, etc. PK, RP and PG (as if enough hasn't been said already). Specific design details about structures, classes and some OOP stuff. The THEME!!! I have a theme in progress, some basic ideas but no real mind crunching done on the subject. Basically a theme to give IC explanations for OOC commands. In other words rational explanations for commands like who, finger, etc. Rational in a fantasy sense. ACRONYMICALLY CHALLENGED LIST - Why is abbreviation such a long word? IC - In character OOC - Out of character PK - Player killer/killing PG - Power gamer/gaming RP - Role playing NPC - Non-player character FINALLY - This is the end, my only friend the end - The Doors If there is anything you don't agree with or want more info about, mail me (email address at end of doc). If you want to chat about your ideas and designs, mail me. If you want to criticize or totally rip this document apart and expose the gruesome flaws and pathetic reasoning, mail me. If a butterfly flapped its wings and caused a ripple in the pond of reality that slightly altered the direction a mouse was running and forced your cat to jump at it which resulted in your cat landing in the mud and now you have to bath it and you contemplate suicide as an alternative, mail me (not recommended after criticizing me). Thinus Barnard <A HREF="mailto:thinus_barnard#bigfoot,com">mailto:thinus_barnard#bigfoot,com</A> </PRE> <!--X-Body-of-Message-End--> <!--X-MsgBody-End--> <!--X-Follow-Ups--> <HR> <!--X-Follow-Ups-End--> <!--X-References--> <!--X-References-End--> <!--X-BotPNI--> <UL> <LI>Prev by Date: <STRONG><A HREF="msg00948.html">[MUD-Dev] Re: DIS: Client-Server vs Peer-to-Peer</A></STRONG> </LI> <LI>Next by Date: <STRONG><A HREF="msg00950.html">[MUD-Dev] Re: DIS: Client-Server vs Peer-to-Peer</A></STRONG> </LI> <LI>Prev by thread: <STRONG><A HREF="msg00951.html">[MUD-Dev] A short introduction of a (quite) long-time lurker</A></STRONG> </LI> <LI>Next by thread: <STRONG><A HREF="msg00936.html">[MUD-Dev] ADMIN: (IMPORTNANT) Server down time and possible service interruption</A></STRONG> </LI> <LI>Index(es): <UL> <LI><A HREF="index.html#00949"><STRONG>Date</STRONG></A></LI> <LI><A HREF="thread.html#00949"><STRONG>Thread</STRONG></A></LI> </UL> </LI> </UL> <!--X-BotPNI-End--> <!--X-User-Footer--> <!--X-User-Footer-End--> <ul><li>Thread context: <BLOCKQUOTE><UL> <LI><STRONG>[MUD-Dev] Re: MUD Design doc (long)</STRONG>, <EM>(continued)</EM> <ul compact> <LI><strong><A NAME="01007" HREF="msg01007.html">[MUD-Dev] Re: MUD Design doc (long)</A></strong>, Benjamin D. Wiechel <a href="mailto:strycher#toast,net">strycher#toast,net</a>, Fri 18 Dec 1998, 23:38 GMT <UL> <LI><strong><A NAME="01031" HREF="msg01031.html">[MUD-Dev] Re: MUD Design doc (long)</A></strong>, J C Lawrence <a href="mailto:claw#under,engr.sgi.com">claw#under,engr.sgi.com</a>, Mon 21 Dec 1998, 23:34 GMT </LI> </UL> </LI> <LI><strong><A NAME="01048" HREF="msg01048.html">[MUD-Dev] Re: MUD Design doc (long)</A></strong>, Nathan F Yospe <a href="mailto:yospe#hawaii,edu">yospe#hawaii,edu</a>, Wed 23 Dec 1998, 20:11 GMT </LI> </ul> </LI> <LI><strong><A NAME="00951" HREF="msg00951.html">[MUD-Dev] A short introduction of a (quite) long-time lurker</A></strong>, Per Vognsen <a href="mailto:vognsen#post10,tele.dk">vognsen#post10,tele.dk</a>, Fri 11 Dec 1998, 16:39 GMT <LI><strong><A NAME="00949" HREF="msg00949.html">[MUD-Dev] MUD Design doc (long)</A></strong>, Thinus Barnard <a href="mailto:thinus_barnard#bigfoot,com">thinus_barnard#bigfoot,com</a>, Fri 11 Dec 1998, 09:29 GMT <LI><strong><A NAME="00936" HREF="msg00936.html">[MUD-Dev] ADMIN: (IMPORTNANT) Server down time and possible service interruption</A></strong>, J C Lawrence <a href="mailto:claw#under,engr.sgi.com">claw#under,engr.sgi.com</a>, Tue 08 Dec 1998, 01:56 GMT <LI><strong><A NAME="00935" HREF="msg00935.html">[MUD-Dev] Error tolerant UDP data streams</A></strong>, J C Lawrence <a href="mailto:claw#under,engr.sgi.com">claw#under,engr.sgi.com</a>, Tue 08 Dec 1998, 01:40 GMT <UL> <LI><strong><A NAME="00938" HREF="msg00938.html">[MUD-Dev] Re: [DevMUD] Error tolerant UDP data streams</A></strong>, Darren Henderson <a href="mailto:darren#jasper,somtel.com">darren#jasper,somtel.com</a>, Tue 08 Dec 1998, 02:37 GMT </LI> <LI><strong><A NAME="00941" HREF="msg00941.html">[MUD-Dev] Re: Error tolerant UDP data streams</A></strong>, James Wilson <a href="mailto:jwilson#rochester,rr.com">jwilson#rochester,rr.com</a>, Tue 08 Dec 1998, 12:31 GMT </LI> </UL> </LI> </UL></BLOCKQUOTE> </ul> <hr> <center> [ <a href="../">Other Periods</a> | <a href="../../">Other mailing lists</a> | <a href="/search.php3">Search</a> ] </center> <hr> </body> </html>