----------------------------------------------------------------------------- Copyright (C) 1988, 1989, 1995, 2004 - Michael Lawrie. All rights reserved. No part of this document may be used without permission. ----------------------------------------------------------------------------- The MUDDL Language by Michael Lawrie Summary. This report gives a summary of the database language MUDDL (Multi User Dungeon Definition Language) which is used for creating text based multi user adventure games. It introduces a debugger which is used to examine databases written in this language. The report consists of an introduction to multi user adventure game systems and a history of MUDDL; an overview of the language's concepts and an informal definition the language itself. A description of the debugger, along with examples of its use on a real database are given at the end of the report. The appendices of the report give details of setting up the debugger to run on a VAX-VMS system, and a list of MUDDL's internal commands and functions. Acknowledgements. I would like to thank the following people who have all helped in the creation of this project. Magee Thomas. Who made me stick at the project, kept me company in a freezing graphics lab and proof read the many incarnations of the report. Richard Bartle. For help and advice on the MUDDL language and much invaluable background material on multi user games and MUD in general. Willi Riha. Who offered to supervise the project and let me do my own thing. Neill Clift. For patience. Alan Humphries. For generally cheering me up about the report. Contents. Chapter 1. Introduction. 1.1. Computer based adventure games. 1.2. Computer based multi user adventure games. 1.3. A brief history of MUD and MUDDL. 1.4. Aims of the project. Chapter 2. An introduction to MUDDL. 2.1. Introduction. 2.2. Basic concepts of MUDDL. 2.2.1. Rooms. 2.2.2. Players. 2.2.3. Objects. 2.2.4. Mobiles. 2.2.5. Demons. 2.2.6. Player attributes. 2.2.7. The Wizard. 2.2.8. Commands and pronouns. 2.2.9. Game chaining. 2.3. Overall structure of a MUDDL database. 2.3.1. GET files and building. 2.3.2. Comments. 2.3.3. Seperators. 2.3.4. Headings. Chapter 3. Definition of MUDDL. 3.1. Introduction. 3.2. Definition of syntax and terms used in this chapter. 3.2.1. The *NAME section. 3.2.2. The *PERSONA section. 3.2.3. The *COMBAT section. 3.2.4. The *LEVELS section. 3.2.5. The *HOURS section. 3.2.6. The *ROOMS section. 3.2.7. The *MAPS section. 3.2.8. The *VOCABULARY section. 3.2.8.1. Class. 3.2.8.2. Syn. 3.2.8.3. Object. 3.2.8.4. The single argument subsections. 3.2.8.5. Motion. 3.2.8.6. Noise. 3.2.8.7. Action. 3.2.9. The *DEMONS section. 3.2.10. The *OBJECTS section. 3.2.11. The *TRAVEL section. 3.2.12. The *TEXT section. Chapter 4. The MUDDL debugger. 4.1. Introduction. 4.2. Starting the debugger. 4.3. Building the database. 4.4. Loading the database. 4.4. Debugger commands. 4.5. Moving around. 4.6. Looking at verbs. 4.7. Looking at demons. Chapter 5. Conclusions. Appendix 1. The VMS environment. Appendix 2. MUDDL functions and commands. Chapter 1. Introduction. 1.1. Computer based adventure games. The first well known computer based adventure game was called "Colossal Cave", and was written in Fortran in the late 1960's on a Dec-10. Colossal was an extension of the fantasy role playing type game which allowed a single player to explore an underground world without physically moving from his or her terminal. To play the game, the player would type in one or two word commands. The computer would then act on them and display the results. Using directional commands, he or she could "move about" in the caves and manipulate objects they found there using the GET or DROP commands. Following Colossal there have been many single-user adventure games, though few with as much fame or success. All of them use the same kind of commands, but some of the modern ones allow much more sophisticated input and give more intelligent output (sometimes in pictorial form). 1.2. Computer based multi user adventure games. A multi user adventure game, at first glance, looks similar to a traditional adventure game. There is one main difference, however: the player is not alone. If the player cannot solve a problem or puzzle at some point, they can ask other players in the game for help. This is not the only different feature though, having other players on the game means that interaction between them is an essential part of play. A good multi user adventure (We will refer to this as an MUA from now on) will exploit the multi user aspect to its fullest potential. It is possible to have problems that need co-operation between players to solve (the classic problem of this type is in opening a portcullis which is too heavy for a single player to open). In a game of this nature, players can talk to the others, discuss problems, help one another or, if the character they are playing is feeling particularly antisocial, kill the others and steal all the treasures they have accumulated. One thing that writers of MUAs have to take into account is whether the game is suited to having more than one user. At Essex University, a multi-user version of Colossal Cave was written and ran for a week or so. After a few minutes of testing the game with more than one user playing, it became apparent that although the game was a perfect copy of the classic adventure, it was not playable with more than one user. Colossal was never designed to be played in a multi user environment. There is only one of each object, and a player needs to have some or all of them in order to solve the game. If a player entered the game and the lamp (which is needed to see below ground) wasn't in the start room, there was no point in the player carrying on with the game. In a single user game, the closest an author can hope to come to matching the level of interaction found in an MUA is by giving the computer a persona which can attempt to react to the human player's actions with some degree of artificial intelligence. With today's AI techniques, however, a programmer of a single user system cannot come close to the interaction levels found in even the simplest multi user adventures. 1.3. A brief history of MUD and MUDDL. The database language MUDDL was first developed in 1979 by Roy Trubshaw, then an undergraduate at Essex University. He was writing an adventure game called MUD (The Multi User Dungeon) but unlike other adventure games of the time, he wanted his system to have more than one player. As well as having many players, Trubshaw wanted MUD to have a modifiable database; this would allow changes to the game to be made without recompiling the whole MUD program. If the database was altered to add another room, then all that was required to make the change effect the game, was for the database to be interpreted by the MUD program. Trubshaw called the database language MUDDL (standing for "Multi User Dungeon Definition Language") and based it very losely on the database system used to write "Colossal Cave". MUDDL started as a fairly simple game definition plan with a lot of parts to the game that should have been in the database still written into the main MUD program. In 1980, when Trubshaw left Essex University, MUD was taken over by Richard Bartle who continued to develop the system and added various features. MUDDL is still used today in developing the Essex games, but Bartle has gone on to develop a follow up to MUDDL that is much more powerful in many ways. In theory MUDDL could be used to write single user systems, but it would be a waste of its true power. 1.4. Aims of the project. This project comprises of a test and debugging system for a MUDDL database. At present the MUDDL databases are edited on the DEC-10 at Essex using TECO (the DEC-10 system editor) and compiled with DBASE (a program that converts MUDDL databases to a form understood by the MUD program). Testing of the program can take place only by playing the game and seeing what happens. In practice a game will be very big (the database used to test the project is over seven thousand lines long) and mistakes are easily missed. Also there is no way to examine, in context, any of the original MUDDL code so debugging becomes a major operation. This project has been developed to analyse a MUDDL database and develop a system which allows a database to be built, loaded and examined in detail, putting all of the major sections in context. The project has also been written with extendability firmly in mind. In the future, it should be fairly easy to extend the debugger into a full multi user MUA system. Chapter 2, An introduction to MUDDL. 2.1. Introduction. This chapter will describe the language MUDDL and give a general overview of its uses, limitations, and some of its concepts. There is no reference to the MUDDL language in existence. In the past writers of databases have relied on the MUD source, and trial and error. This section is just an introduction to MUDDL; a more comprehensive, but still informal definition of the language is given in chapter 3. 2.2. Basic concepts of MUDDL. A MUDDL database is a file that defines a whole game world (often known as a "land"). Before we can look at the language, we must examine some of the main concepts behind it and define some of the terms that will be used in the rest of this report. 2.2.1. Rooms. The land is made up of a number of rooms, which are the basic building blocks of the game and contain all the other entities the land has in it. A room has a description and a number of attributes; for example, if it has a natural light source or if it is a small room. A room need not be a room as it is usually thought of; for example a description of a part of a forest is still a room. 2.2.2. Players. The players are human controlled entities that can move from room to room and manipulate things that they find. The term "persona" is used to describe the player's computer form. 2.2.3. Objects. An object is a thing that is present in a room that is not a player. Some of these can be taken and dropped by players but a lot are fixed. Everything in the game that is not a room or a player is an object. An object can also be a container, in which case the object itself can contain objects. Each object has a "class" which groups together sets of similar objects, so an object named "stick" and an object named "tree" both have the class "wood". Operations can now be defined to act on anything of class "wood" and they would hold for both trees and sticks. An object has a number of other attributes and can be in a number of states (or "properties"). For each different property an object will have a different description and the game can check which property the object has. For example, a stick could have three states each with their own description: 0 - A stick lies on the ground before you. 1 - A burning stick lies on the ground before you. 2 - A charred stick lies on the ground before you. 2.2.4. Mobiles. This is a special form of object that moves from room to room under the control of the computer. Normally the mobiles represent "monsters" that will possibly attack players if they meet them. This does not always have to be the case though: a more peaceful example of a mobile would be a tumbleweed which blows from room to room. Mobiles can also have instincts associated with them. This means that they can react to situations they encounter. A good example of an instinctive mobile is the cat in the MUD database that will kill any rat it encounters on its travels. 2.2.5. Demons. A demon cannot be seen in the land, but it is an important concept in MUDDL. It is a process which, once initalised, waits in the background until it is ready and then does something. The process of starting a demon running is known as "firing" the demon. Their use in MUDDL is threefold. Firstly, a MUDDL instruction can only perform one task before it completes. However, there is an option for an instruction to "fire" a demon as the instruction terminates. If this demon has no delay incorporated and the demon itself triggers off more demons, then a sequence of instructions can be simulated. The second use of a demon is to force another player to do something. Normally, all MUDDL instructions act on the person who executed them, but MUDDL has a mechanism for sending a demon to another player in order to make them execute a sequence of commands. The final use of a demon is really an extension of the first, which is called an "animation". Unlike the first use of demons, an animation incorporates delays. The demon forces a number of actions on the player over a given time span. A good example of an animation sequence is found in the MIST database where the program simulates an old man in a pub talking to the unsuspecting player. It does not let them escape till the conversation has ended or the desparately harrassed player has quit. 2.2.6. Player attributes. A player has associated with them a number of attributes. The main ones are sex, strength, dexterity, stamina, maximum stamina, score and class. These attributes define a number of things such as how many objects they can carry, how much chance they will have in combat and how much chance they have of casting spells successfully. 2.2.7. The Wizard. When a player has reached a certain score, they become wizards (or witches). This opens up a whole new set of commands for them; where they were once restricted to moving from room to room by following the correct paths, they can now move to any room they choose with a single command. Wizards do not have to worry about death or combat because the game ignores the fact they have died. Many of the commands defined in a MUDDL database are separated into wizard commands and non wizard commands. A non-wizard player is usually known as a mortal. 2.2.8. Commands and pronouns. A command typed into a MUDDL game can be a fairly complicated one, but it basically breaks down to one or more commands of the form: verb noun noun The verb is compulsary, the two nouns are optional. Commands can be strung together with "." or "-" and the pronouns "me", "it", "him", "her", "them" and "there" (the latter only if the player is a wizard) can be used to represent the relevent players, objects or rooms. The pronoun table is updated every time something new is seen or heard. An example of a command, together with the way it breaks down is as follows: Command: where melissa-goto there-sget flower-give it to her This breaks down into the four commands: where melissa goto there sget flower give it her The first command returns the room that Melissa is in. As a result this updates the user's pronoun table, and the word "there" in the second command is replaced by the roomname last recorded. The GOTO instruction will now move the player typing the command to the same room as Melissa, and when they enter the room, their pronoun table is updated with anything seen there. The SGET instruction is now executed, and, the pronoun table's view of "it" is updated to "flower". Finally, the GIVE command replaces its two pronouns from the table. However, if there was another female in the same room as Melissa, and she was seen after Melissa, her name will be substituted for "her" from the pronoun table and the flower will be given to the wrong person! 2.2.9. Game chaining. MUDDL has a mechanism for moving a player to a specified room in a totally separate game. In moving from one game to another, the player cannot take their objects with them, as this would require different MUDDL programs to share data and may produce ambiguities. On a fast machine the transition from one game to another takes place unnoticed by the player and it provides a very versatile system where a player can move, or be moved, between a selection of games with different databases without seeming to leave the game which the player started. 2.3. Overall structure of a MUDDL database. 2.3.1. GET files and building. A database consists of a single large file, but this is built up from a smaller file and a number of standard library files (known as GET files after the DEC-10 implementation). The actual database for the land being written can include the GET files by using the "@" symbol followed by the name of the file. Bartle wrote a number of standard GET files that should be used with all databases to define a skeletal land. The debugger accesses these files so that a complete MUDDL database can be verified. Unlike the Essex implementation, the debugger allows GET files to include GET files themselves, making them more versatile but meaning that a separate building must be performed. During this building stage, all blank lines are removed, and all lines preceeded by a "%" sign are displayed on the screen. These lines are build time comments and as they are for the aid of the database writer, they are not included in the full database. Normally they are just used to indicate which stage the build process has reached. 2.3.2. Comments. Comments can be included in three ways. If there is a single semicolon at the start of a line, it is interpreted as a database comment, and is totally ignored by the database interpreter. A comment can be included at the end of a line by putting a tab followed by a semicolon, followed by the text of the comment. If there are two semicolons together at the beginning of a line it is still ignored, but it is displayed on the screen at load time (this is again for the writer's use). 2.3.3. Separators. The TAB character is the basic separator in a MUDDL database which separates individual parts of a line without ambiguity. If spaces are used instead of TAB characters, although they may look the same on the screen, the database loader will be unable to correctly interpret the database and will give errors about missing arguments. A newline character will always separate one line from another. 2.3.4. Headings. In a full MUDDL database, there are twelve section headings and a large number of item headings. A section heading signifies a distinct new section of the database and is preceded by an asterisk; these are discussed in detail in chapter 4. An item heading signifies that a new part of a section is being started. Chapter 3. A definition of MUDDL. 3.1. Introduction. This chapter will examine each section of a MUDDL database in turn and define the syntax of the MUDDL language. In many ways, especially in presuming default values, this implementation is an extension of the Essex University version. The reason for this is that the debugger needs to be able to load an incomplete database whereas the Essex system can only deal with fully formed ones. To make writing a database to run on the Essex system possible, these differences are pointed out in the text. 3.2. Definition of syntax and terms used in this chapter. The rest of this chapter will look at each section of MUDDL in turn and give the syntax of the various parts. Where a person is referred to in this chapter, the term "she" will be used. The database requires a TAB to be used to seperate arguments but this text uses a number of spaces as opposed to a tab character to attempt to overcome the ambiguities in printing tabs. This chapter uses the following terms and syntax symbols. roomname This is a text string, beginning with a letter and up to 132 characters in length. It can contain numbers and most punctuation symbols except "$". The Essex system will only allow room names to be seven characters in length, and they may only contain letters and numbers. The debugger will give no warnings if the Essex convention is not adhered to. Roomnames are not case-sensitive so "start" is the same as "START". Although the program does not force the writer to do so, it is a very good idea to keep roomnames to just letters and numbers. roomlist This is a list of tab seperated roomnames. At any point, a set of roomnames can be enclosed in "[]" or "<>" parentheses. If the list is enclosed in square brackets, then a random roomname from the list will be inserted at LOAD time; if angle brackets are used, then a random roomname will be chosen from the list every time the list is consulted. string A string is a list of characters, of the same type as a roomname but it can begin with a number and contain any punctuation symbol. number A number can be positive or negative, in most cases the sign is important. { } Items enclosed in braces are optional [ ] Items enclosed in square brackets mean that the item is an argument, which is explained in the definition. | Items seperated by the "|" sign, specify that either the first item OR the second item may be inserted. ... This signifies that a list will continue in the same way, and contain as many further items as are required. Unless otherwise stated, if a definition has two entries of the same type then this signifies that the section can contain as many of these entries as are required. The end of the section will be marked by a new section header. 3.2.1. The *NAME section. *NAME [game-name] The *NAME section defines the name of the database, and of the game. The argument game-name is a string. 3.2.2. The *PERSONA section. *PERSONA [persona-name] The *PERSONA section tells the system which persona file the system will use. Persona-name is a string and is normally the same as the game-name. It will differ when, for example, two databases share the same persona file. 3.2.3. The *COMBAT section. *COMBAT [count] [message] [message] ... [count] [message] [message] ... (etc etc...) The *COMBAT section consists of 24 subsections. Each section is headed by a number (count) which says how many messages, of type string, are in the list that follows. The use of this section is to define the words used in the combat sequences. In some MUA's, combat sequences are fairly boring, they consist of messages such as: Mattygrove hits you. You hit Mattygrove. You miss Mattygrove. MUDDL has a powerful combat system that can handle such things as the player retaliating to a blow and hitting the opponent. These sections contain the terms used during such combat sequences. If a random choice from the list of messages in subsection 4 is signified by [4] then the messages in the lists fit into the combat system (with Mattygrove as an example opponent) as follows: - Mattygrove attacks: You [16] that Mattygrove is [1] at you [2]... Eg: You perceive that Mattygrove is staring at you ominously... - Mattygrove is hit: You [3] Mattygrove with a [4] [5]! Eg: You take aim at Mattygrove with a weighty blow! - Mattygrove misses: You [22] [6] a [7] [5] [9] Mattygrove. Eg: You comfortably duck a hasty thump from Mattygrove. - The player misses Mattygrove: Your [7] [5] is [10] Mattygrove. Eg: Your poor backhand is blocked by Mattygrove. - Mattygrove hits: The [12] of a [5] [9] Mattygrove sends you [21]; or You are [11] by the [12] of a [5] [9] Mattygrove! Eg: The savageness of a blow from Mattygrove sends you sideways; or You are jarred by the force of a forehand by Mattygrove! - The player is dead, Mattygrove wins the fight: You can [13] your [14] [15]... Eg: You can sense your last seconds slipping away... - The player is ok and attacks Mattygrove again: [17] you [18], and [19] into the [8]. Eg: Yet you bear up, and advance into the slaughter. - Mattygrove has hit but the player hits back: Your [20] [5] sends Mattygrove [21]! Eg: Your follow-up thrust sends Mattygrove sprawling! - The player misses Mattygrove again: Your [7] [20] [5] at Mattygrove is [22] [23]. Eg: Your puny follow-through clout at Mattygrove is comfortably ducked. - Mattygrove is dead: Your last [5] [24] Mattygrove! Eg: Your last slash murdered Mattygrove! 3.2.4. The *LEVELS section. *LEVELS Male [level 1] [level 2] ... [level 10] Female [level 1] [level 2] ... [level 10] This is a list of strings that make up the level titles for both male and female players. When a player has a certain number of points, she has a title connected with them. For example, a player on 1,000 points may be known as "Mattygrove the hero". When a player has no points, she is on level 1, which is usually known as "novice". At 400 points, she will go up a level and every time her score doubles from then on she will go up another level. When a player reaches level-10 (normally this level name is known as "wizard" or "witch"), the score has no further effect on the level title, even if it decreases. 3.2.5. The *HOURS section. *HOURS Sun | 0 [open] [close] Sun | 0 [open] [close] ... ... ... Mon | 1 [open] [close] Mon | 1 [open] [close] ... ... Fri | 5 [open] [close] Sat | 6 [open] [close] This section defines the opening times of the game. The values for open and close are integers between 0 and 24 which say the hours at which the game is open. In this version, but not the Essex version, a day can be specified by a three character name. Any day can be defined more than once, so, if the game to be open on Wednesday from Midnight till 9am, 1pm till 2pm and then 5pm till Midnight, it should be specified as follows: WED 0 9 WED 13 14 WED 17 24 3.2.6. The *ROOMS section. *ROOMS [number] [roomname] [attributes] [short-description] [long-description] ... [roomname] [attributes] [short-description] [long-description] ... This section defines the rooms that make up the land. The argument to the actual section header is the number of rooms to be defined in the section. The debugger ignores it (although it does give an error message if the number is exceeded). Each new room is started with a roomname; these should all be unique. Following the room name, there is a list of attributes which can be selected from one or more of the following: Light The room contains a natural light source. Water There is water here. Oil There is oil here. Death If a mortal player comes in this room then she will die. Sanctuary If an object is dropped here, the player will have added to her score the amount of points the object was worth. Hideaway If a player is in here, she cannot be seen from outside by mortals. Hide If an object is in here, it cannot be seen by mortal players. Small Only one player or mobile can be in this room at a time. Chain The CHAIN attribute takes two arguments, [game-name] and [room] which follow on from the word CHAIN seperated by tabs. This attribute allows one game to run another game and put the player in the specified room. Dmove The DMOVE has a single argument [roomname] which again, follows the word DMOVE and a tab. It means that if any objects are dropped in here, either by accident (eg: by a player dying) or on purpose then the object is moved to the room specified in the roomname argument. The SANCTUARY attribute usually has a DMOVE attribute pointing to an inaccessable room as well. If this were not the case, players could drop objects, score points, pick them up and repeat the operation until they reached wizard level. Nolook This means that the room cannot be looked into from an adjacent room. Silent If a witch is in a silent room, then she receives no status messages. The short room description can be one of two forms: a string, in which case this is taken literally as the short description of the room; or it can be a percent sign followed by a roomname. If this latter form is used, then the short description of the room is taken as being the same as the short description of the room specified. Using the "%roomname" form, complex areas, like forests, can be built up. Also, if the short room description that is referenced is changed, then that description will change for all the other rooms which reference it. The long room description consists of zero or more tab indented lines which give the main description of the room. A room has two descriptions for a few reasons. The short description is meant to give the player a basic idea of where they are in the land, the long one narrows it down, usually to a unique room. Normally, both descriptions of the room are given when a player enters it, however, if a player is playing in BRIEF mode then only the short description of a room will be seen. the LOOK command always displays both descriptions. Commands like "where", which allow players to find out where in the land something is, will only return the short room description. 3.2.7. The *MAPS section. *MAPS number [roomname] [string] [string] ... [roomname] [string] [string] ... This section is not implemented in the debugger, as so few databases actually use it. The strings following the roomname can be used to create a pictorial representation of the room and its exits. 3.2.8. The *VOCABULARY section. *VOCABULARY CLASS [classname] ... SYN [synonym] [real-word] ... ... OBJECT [object] [classname] [weight] [value] ... ... ... ... CONJ [string] FPREP [string] BPREP [string] QUANT [string] PRON [string] MPRON [string] FPRON [string] PPRON [string] PLACE [string] SELF [string] INST [string] UNIVERSAL [string] NOCLASS [string] PERSN [string] STHING [string] ATHING [string] MOTION [motion] ... NOISE [string] ... ACTION [action definition] ... ... This section defines the vocabulary of the game, every word and action the game can interpret is in this section. Each of these headings can (and usually do) appear more than once in the section. It will help to look at the subsections in turn and to give an example of each. 3.2.8.1. Class. This is a list of strings that make up the class names of the objects in the database. For example: class wood weapon food 3.2.8.2. Syn. This defines synonyms which can be used in place of words that are already defined in the database. The debugger will not check whether the words you are creating synonyms for already exist in the database. For example: syn gun shotgun take get carry get wisky whiskey 3.2.8.3. Object. All the objects in the game are defined here. There are four parts to each definition: the object's name, its class which must have been defined under the class heading, a number representing its weight in grammes, and a number representing its value. For example: object stick wood 200 0 crown gold 10000 300 goat animal 100000 20 3.2.8.4. The single argument subsections. These define words that MUDDL itself uses. The debugger will provide default values for all of them if they are missed, but the Essex system does not. The headings, default values, and meanings are as follows: Conj "and" This is word used for stringing commands together, for example: GO NORTH "and" GET AXE. Fprep "with" This is the fight preposition, for example: KILL FRED "with" AXE. Bprep "at" This is used for example in LOOK "at" FRED. Quant "all" This is the quantifier; it is used to manipulate a quantity of objects in for example, GET "all" Pron "it" This is the object pronoun; in a command, this word will be replaced by the name of the last object seen. Mpron "him" This is male pronoun; it is replaced by last male seen or heard. Fpron "her" This is the female pronoun; it is replaced by last female referenced. Ppron "them" This is the person pronoun; it is replaced by the last male or female referenced. Place "there" For wizards, this is replaced by the last room referenced. Self "me" This is always replaced by the player's persona name. Inst "whichever" This is used in the demon definitions to pass an argument on to the next demon called. Universal "shout" This is the command that will be used to transmit a message to everyone in the land. Noclass "none" This is the word used in action definitions to signify something that is not an object or a person. Persn "person" This is used in action definitions to signify another player. Sthing "something" This is used in action definitions to signify an object of any class. Athing "anything" This is used in verb definitions to signify a person or an object of any class. 3.2.8.5. Motion. This section contains a list of strings of valid directions that the game should understand. The directions can be either normal strings or, strings with a "$" sign at the beginning. A "$" means that this is a special direction, which can only be taken if a demon of that name is called. For example: motion north south east $special northwest 3.2.8.7. Noise. This section exists so the writer can declare words to be added to the database's dictionary but not to be used in the game. The normal use of this section is to stop players coming into the game as certain reserved words. For example: noise someone a the 3.2.8.7. Action. In this section, every verb that the game understands is defined. The format is not easy to define, so a lot of examples from the MIST database are included. The way MUDDL executes commands is to search the verb definitions for any verbs that match the command typed in at the player's keyboard. If one is found, MUDDL checks if it is allowed to execute it. If it can run the command then the interpreter will search no further and the command will be carried out. If the command cannot be executed for some reason, it will go onto the next relevant action definition. If it fails on all definitions, or if a definition is not found, then it will give an error. It is a good practice for database writers to give all verbs a default definition with no conditions associated with it; this can be used to give a more useful error message. The format of an action can be loosely described as: verb {.command} arg1 arg2 function farg1 {farg2} m1 {m2} {m3} {dmn} If the verb is preceeded by a dollar, it is a demon action as opposed to a play action, meaning that it cannot be typed in directly as a command. The .command part is optional, if it is present, it calls an internal MUDDL function of that name. Normally, arg1 and arg2 are the nouns that go with a verb. Arg1 can be an object class, or one of the words defined in the single argument section of vocabulary. Arg2 will be described later. M1, m2 and m3 are messages that will get sent to various groups of players. It is always the case that m1 will be sent to the player who entered the command and m3 will go to the whole land but m2 could go to different places depending on the function. The simplest type of action is one with no arguments that simply prints a message to the user. An example of this is the verb "MUD" which prints the message "No! This is MIST I tell you, MIST!" The definition for this action is: mud none none null null 1193 0 The "1193" is a reference to the message defined later on in the database in the *TEXT section. In order to signify a message in the *TEXT section from now on, any message numbers that refer to it will be written after the action definition, preceded by a "#". This is not MUDDL but is a convenient way to avoid too much explanation. Using this method, the above definition would be written: mud none none null null 1193 0 #1193 No! This is MIST I tell you, MIST! Another simple type of action is one which displays a message, but that executes a MUDDL command as well. A good example is "sleep" which rests the player for a few seconds by calling the intenal MUDDL command ".sleep". This is written as: sleep .sleep none none null null 40 0 #40 ZZZzzz... More complex actions can be written which allow an argument to a command. Take an example of picking up a piece of burning coal which is of class "hot". get hot none null null 100 0 #100 You reach down to pick up the glowing coal, but as your hands get close you have second thoughts. If it is decided that wizards should be able to pick up hot coals, then a function could be used to to check if the player is a wizard. This leads to an example of an action that uses something other than a null function. The full definition of the "get" command when used with coal in this way now becomes: get hot none unlesswiz null 100 0 get .get hot none null null 101 0 #100 You reach down to pick up the glowing coal, but as your hands get close you have second thoughts. #101 You take the red hot coal without so much as noticing that it is a little warm If arg1 is left as "none" (The string defined with NOCLASS) but arg2 is a class, then this means that the verb is executed if the player has an object of that class or if there is one in the same room. A good example is the verb "swim": swim none river null null 200 0 swim none bath null null 201 0 swim none none null null 202 0 #200 You take one look at the fast flowing river and decide that swimming in there would not be a good idea. #201 Its a little bath you fool, you can't swim in it! #202 There is nothing here that you could possibly swim in. Full three part commands can be built up by using both arg1 and arg2, the statement to handle "hit door with stick" could be: hit access wood null null 450 0 #450 You bash the stick against the heavy wooden door, fun isn't it. Functions can be inserted for a number of reasons. The one previously shown was used as a conditional, but more complex ones exist. An example is in touching a stone which increases the player's score by 250 and destroys the stone. (note, the expdestroy function has two arguments instead of the usual one): touch stone none expdestroy null 250 800 0 #800 The stone vibrates and vanishes. As it does, you feel somehow different. All of the commands so far have only used a single message argument, the following MIST command uses two messages (m1 and m3), a function called .flush and a MUDDL command. charge .flush none none ifwiz null 100 101 101 100 Certainly oh master, and I hope they pay too! 101 -+ Charging has just started for this account +- The ".flush" command flushes the player's command buffer and the pronoun table. It is included to stop wizards typing CHARGE and then pressing return a number of times (which repeats the last command given to the game). Finally, the "dmn" argument allows a demon to be called. It is differentiated from the normal messages by being negative. If a command has a demon call in it then the demon is called after the command has been executed. Demons are defined in the *DEMONS section. A full list of MUDDL internal commands and functions can be found in appendix-2. 3.2.9. The *DEMONS section. *DEMONS number [demon-number] [demon-name] [arg1] [arg2] [delay] [attributes] [demon-number] [demon-name] [arg1] [arg2] [delay] [attributes] This section defines all the demons in the game. The demon-number is the number by which the demon is called, and the demon-name is the name of a demon action as defined in the action section of vocabulary. It must always be preceeded by a "$". The arguments arg1 and arg2 are nearly always "none" (or the word which is declared as "Noclass" in the Vocabulary section) with the exceptions being a couple of MUDDL system demons in the standard GET files. The delay argument is the number of seconds that this demon should sleep before the demon action is called; if it is specified as "-1" then the action takes place immediately. If a random delay time is required then the lower limit and the upper limit should be seperated by a minus sign (eg: 50-300 would specify a random delay between 50 and 300 seconds). Following the delay, there can be a list of zero or more tab seperated attribute keywords, these are: global The demon acts on everyone at once, not just the person who fired it. enabled The game automatically starts this demon running when it is started. always This demon never goes away. After it has gone off it remains enabled but dormant. One use of this is to check that someone has done something; if a demon with the "enabled" attribute is fired, the game can later check that this has happened using the ifenabled function. The number after the *DEMONS token defines the maximum number of demons, this is important in the Essex system, but is ignored in the debugger. 3.2.10. The *OBJECTS section. *OBJECTS [objname] {speed} {inst} {atp} [roomlist] stp mxp scp {stam} [attrs] [number] [string] ... [number] [string] ... ... [objname] {speed} {inst} {atp} [roomlist] stp mxp scp {stam} [attrs] [number] [string] ... [number] [string] ... ... This section defines fully every object and mobile in the game. The arguments to the definitions are as follows. Objname The name of the object to be defined, this must be an object previously defined in the Obj section of vocabulary. The obj section's definition of an object is very basic; it only defines class, weight and value. This section allows individual instances of an object be further sub-defined. Speed If speed is defined, then the object is presumed to be a mobile. The numeric argument is the time (in seconds) before the mobile will try to leave the room it is in. A value of "0" means that the mobile will never stay still, and a value of -1 means that it will never move. Inst This is a demon (and thus a negative number) that is executed every time the mobile enters a room. It defines the mobile's instincts. (see 2.2.4). Atp This is the mobile's attack probability; a number between 0 and 100 that defines how much chance the mobile has of attacking any players it meets on its travels. An attack probability of 0 means that the mobile will never attack whereas one of 100 means the mobile will always attack. Roomlist This is a list of rooms the object is to be put into. If the name of another object (it must be a container) appears instead of a roomname, then the current object will be put inside the object appearing in the list. Stp This is the start property of the object. It is a numeric value defining which of its properties it will have at the start of the game. For an explanation of an object's property values, see 2.2.3. Mxp This is the maximum property that the object can have, the minimum is always 0. If this number is negative then the object will take on a random property value from zero up to the unsigned value of the number every time it is looked at. Scp This is the score property of the object. An object is only worth points to a player when it has a certain property, this number says what this property is. Stam In mobiles, this is its maximum stamina it has if it gets into a fight. Attrs This is a list of zero or more tab seperated attribute keywords that definine the attributes of an object. These are as follows: Bright The object provides a source of light when it is at property 0. Noget This stops mortals picking this object up. The NOGET attribute would be given to objects like trees or doors. Noit This object does not update the pronoun table when it is looked at, and thus cannot be refered to as "it" - This attribute also means that the object will not be affected by quantifiers, for example: "get all". Contains This should be followed by a tab seperated number, it defines the object as being a container and thus able to carry other objects. The number is the weight in grammes that it can carry. Disguised If the object is a container and has the DISGUISED attribute then mortal players will not be told that the object is a container. Opened Normally, a player can only remove objects from a container if the container is in property 0, this attribute makes it so that objects can be removed from the container at any time. Transparent The contents of a container can only be seen by mortals when the container is in property 0. Giving a container the TRANSPARENT attribute makes the contents of a container visible whatever property it has. Mortal players will be told that a non transparent container contains "something" when it has any other property. Nosummon If a player is carrying an object with this attribute, then she cannot be summoned elsewhere by another player. Fixed This defines an object as being an important part of the game and thus impossible to take, even for wizards. This is given to objects that form part of a room description, like a marker on a beach saying if the tide is in or out. Following the initial definition, there is a list of property descriptions headed by the property number. The description of each individual property can take as many lines as are needed. If a "%" sign followed by an object name is used as a property description, then the description of the object named after the "%" sign is used in the property value being defined. If the description is simply a "?" then the object description is taken from a file called objname.DBA. The file is consulted each time a description is printed so the description can be changed as the game is running. To make things clearer, there follow some examples. beacon beach4 1 1 2 noget bright 0 You see before you a large beacon, burning brightly with magical flames. 1 A large pile of branches and twigs form an unlit beacon here. A beacon is in the fourth beach location (beach4), it can have two property values (0 and 1) because Mxp is defined as 1. The beacon starts off in property 1 (Stp is defined as 1). The "bright" attribute is defined, so if it is in property 0, then it gives off light. The score property of the object is defined as 2, which is above the maximum number of properties that the object is allowed to have, thus ensuring that the object can never be worth any points. Finally, the "noget" attribute means that the object cannot be taken away by mortal players. tide cause1 cause2 cause3 pool1 pool2 pool3 1 1 2 noget fixed 0 The tide is out. 1 The tide is in. This is a tide marker, placed on every beach location It has two states, in and out - it cannot be taken by mortals or wizards. door court1 armour 2 2 3 noget 0 There is an open door here. 1 There is a closed door here. 2 There is a locked door here. door pantry kitch 1 2 3 noget 0 %door 1 %door 2 %door This declares two typical doors. The first, the connecting door from the courtyard to the armoury, starts off locked; whereas the second, the connecting door from the kitchen to the pantry, is merely closed. This section of code declares two objects, but the players will actually see four doors, one in each of the rooms mentioned. We define a connecting door as being in two rooms rather than one because when we set the door in one room to a new property value, the other door in the other location will also be set to that property. teleport start 0 0 1 noget bright 0 A teleport beam pulsates before you. This declares a glowing teleport connecting room start to either room good1 or room bad1. In the object section (but not in other sections), it does not matter which form of bracketing you use in room lists. This is because all of the items are placed in the land when the game is loaded and so this kind of roomlist is only ever referenced once. grave grave1 grave2 grave3 grave4 0 -3 4 noget bright 0 Inscribed on a modestly asture tombstone here is the name "Richard" 1 There is a large monument here, bearing the inscription "Roy, the grand-daddy of multi user games." 2 Before you, shining with a mystical light stands a massive golden monument encrusted with diamonds. The legend reads "Lorry, modest to the end." 3 ? This defines a glowing gravestone that takes on a random property from 0 to 3 each time it is looked at. If it is looked at when has the property 3, then the file "grave.dba" is consulted for the description. 3.2.11. The *TRAVEL section. *TRAVEL [motion-word] [roomname] [condition] {roomto} [directions] ... ... ... [roomname] [condition] {roomto} [directions] ... ... ... This section defines the connections between the rooms in the land. It defines which room a player will arrive in if they travel in a certain direction and what, if anything, there is to stop the player moving. In the Essex version there must be a travel definition defined for each of the rooms defined in the *ROOMS section. The motion-word argument is the player's command used to move in a direction. In an English language database, this will nearly always be the word "go". As this word does not actually have to be typed to introduce a direction, its use is largely obsolete and so the debugger ignores it. The roomname is the name of the room that the current travel definition refers to. The condition defines whether movement is allowed or not. If the condition has a tilda in front of it then the logic of the condition is reversed. The following is a list of conditions allowed: n | none No condition, it is a simple movement command. e | empty The condition is true if the room is empty and if the player is carrying nothing. [object|class] The condition is true if the object or an object of the right class is in property 0 and is present in the room or carried by the player. [number] If the number is positive, the message of that number is printed, otherwise a demon is fired. The roomto argument can be a list of roomnames, and is the room the player will be moved to if the condition is sucessful. If a random destination is required, then a roomlist enclosed in either square or angle brackets can be used. If the argument supplied is a "0" then the message "You cannot go that way" will be displayed. The list of directions is one or more of the directions defined in the motion section of vocabulary, and can be synonyms. If random directions are required, then the whole list or a sublist can be surrounded in square or angle brackets depending when the random direction is to be worked out. When the travel tables are processed by the game, each line is taken in order. If a condition fails then the next entry is looked at, otherwise the relevant action is taken and processing stops. If all conditions fail, the message "You cannot go that way" will be printed. There follows two examples of travel entries from the MIST database. They show how powerful this system can be when used properly. mazea8 trog 0 s se sw ali 0 s se sw undead 0 s se sw talisman mazea9 se s sw n mazeb9 se s sw -200 n e w nw ne 1109 u d in jump 1145 o pit #1109 You blunder into the darkness... #1145 Naaaaah! That would be too easy! In the room "mazea8" players cannot go south, south-east or south-west if there are objects of the type trog (the class for most of MIST's monsters), the type ali (moles) or the type undead (zombies) present. If an object of type talisman is being carried, or there is one in the room, and there are none of the above mobiles in the room then going south, south-east or south-west will take the player to the room "mazea9" otherwise, it will move them to room "mazeb9" with the next line. If the player goes north, east, west, north-west or north-east, then demon 200 will be started (This checks what objects the player is carrying and moves her to various other rooms). If the player goes up, down, in or jumps, the message 1109 is printed but no actual movement takes place. If the player goes out, or gives the direction command "pit", then message 1145 is printed. mazea9 undead 0 o n mazea7 [o e] ~talisman mazea4 o e door o e 1145 o e w n s e ne nw se sw u d in pit In room "mazea9", the player cannot go out in the direction "out" if there is a zombie in the room. The loader will insert a random one of "o" or "e" in the next condition. It will be assumed that the loader chose "e". The line now becomes: n mazea7 e If the player goes east, they will be placed in room "mazea7". The next condition checks that the player is NOT carrying a talisman, if this is so then they are moved to mazea4. Now, if there is a door in property 0 (opened), going out or east will take the player to either the crypt, the barn or the pantry. As east has been trapped previously (moving the player to mazea7) only the out command will be valid here. The decision about which room the player will be placed in is taken at the time the command is executed; if square brackets had been used instead of angle ones, the decision would have been made when the game was loaded. Finally, any other direction that can be typed will produce message 1145. 3.2.12. The *TEXT section. *TEXT number [number] [string] ... [number] [string] ... This section defines every text message used in the game. The value following the *TEXT section header is the maximum number of messages you expect to define. It is needed in the Essex version but ignored by the debugger. The message body can consist of any number of tab indented strings; a new message is started when a new number is found as the header. If the text of the message is simply a "?" then the program will look in the file "number.DBA" for the message text; this file is read every time the message is referenced, so if it is updated while a game is running, the change will take place immediately. For example: The two text messages 40 and 41 could be defined as follows. 40 ZZZzzz... 41 One does not cook cats, one eats them raw - I thought EVERYONE knew that! Chapter 4. The MUDDL debugger. 4.1. Introduction. This chapter will give a basic overview of the system and its use. It will discuss running the program, building and loading databases, debugger commands and give examples of the debugger in use. It does not discuss installing the system or its environment, details of these can be found in appendix-1. 4.2. Starting the debugger. The format of the command is: MUDDL { [database] } { -HELP } { -NOWINDOW } { -NOCOMMENT } The arguments are as follows: database The name of the database to load. -HELP Print a brief help text for the system. -NOWINDOW Do not use windows. This argument must be used if a DEC terminal is not being used. -NOCOMMENT Do not display comments during the loading stage. If a database name is specified on the command line, the program will start up and automatically try to load that database. If the -NOWINDOW option has not been specified then the screen will split up into four windows. The first window, labelled "STATUS", is for any game or operating system status messages. The second, labelled "OUTPUT", is for any general game output. "DEBUG" is where any error messages are displayed, or where extra information is printed. The bottom window "INPUT" will contain the prompt "--*>" when it is waiting for input. It will allow the user to type up to 76 characters; if this limit is exceeded then it will automatically terminate the line and send it for processing. 4.3. Building the database. The debugger will only deal with a single large database file. In order to create this, the game text file and the GET files must be merged together. This process is called binding. The database file is called database.TXT and should be in the directory MUD_DATA:[SOURCE], the GET files should all be in the directory MUD_DATA:[GET]. When the build is finished, its output will go to MUD_DATA:[DATABASE]. For further details of the directories used, see appendix-1. To build the database, the command "/BUILD database" (where database is the name of the source file) is entered from within the debugger. The screen will clear and a number of diagnostic messages will be printed. If the build is sucessful, it will give a success message to the user, otherwise it will print an error message. In both cases, it will return to the debugger after a key is pressed. 4.4. Loading the database. Before the database can be examined or debugged, it must be loaded into the debugger. This can be done in two ways: if the MUDDL program is called with the database name as an argument, then it is automatically loaded; otherwise the command "/LOAD database" should be entered. The load process takes quite a long time, so it gives messages on the output window saying which section it is currently loading; in the *VOCABULARY and *LEVELS sections, it will also display the subsection names. Unless the -NOCOMMENT flag has been specified, database comments that begin with ";;" will also be displayed. Any errors found in the loading stage are database syntax errors. These will be displayed in the debug window with enough information for the source of the error to be traced. Not many errors will be serious enough to abort the loading process, the ones which are being major format errors such as unknown section names. If a lot of error messages are being produced on the debug window and are scrolling too fast to be seen, then the command "/LOG" should be typed and the load restarted. This will cause all debug output to be sent to the file MUDDL.DBG, which can be printed later for a hard-copy of the errors. Once the load stage is complete the status window will display the current database name and the number of rooms in the land. 4.4. Debugger commands. The debugger understands two types of commands, internal commands and game commands. The internal commands are the actual debugger commands, which are always preceeded by a "/". Game commands are the verbs contained in the database itself, and will not work unless a database has been loaded. The following is a list of internal commands and their functions: /HELP Displays a list of internal commands and brief descriptions of their functions. /BUILD [name] Builds a database called "name". If the argument is missed then it is prompted for. /LOAD [name] Loads a database called "name", again, if the database name is missed then it will be prompted for. /LOG Logs all the output on the DEBUG window to the file MUDDL.DBG. /DETAIL Displays detailed analysis messages for every command in the debug window. /QUIT Terminates the debugger. /SPAWN {com} Spawns a VMS command from the debugger, if no command is specified, then it will spawn to VMS. /AUTO Enables/disables the facility to put the user into the PHONE or MAIL system if they are being phoned or mailed whilst in the debugger. The following commands, although internal commands, will produce results only if a database is loaded: /LOOK {room} Looks at the current room or if an argument is given, at that room. This will give the name, attributes, short and full description of the room looked at. The argument is normally the name of a room, but if it is numeric and starts with a "$" sign, then it will look at the room by its internal room number. /EXITS {room} Displays the travel table for the current room, or if an argument is given, at that room. The room can be numeric as long as it starts with a "$" sign. /GOTO [room] Sets the current room to the specified room. The room can again be numeric if it starts with a "$" /MSG [n] Displays the text message "n" unless the number is negative in which case it displays the definition of the demon call. /BRIEF If /BRIEF is typed, then only the short description of a room is displayed when /GOTO is used. /LOC Lists all the rooms in the database along with their short descriptions. /LEVELS Displays the level tables. /HOURS Prints a table of the opening hours of the game. /COMBAT {arg} If this command is used alone, it will give help on the combat system. The arguments are as follows: * Prints the whole of the combat table. n Prints section "n" (n is a number from 1 to 24) of the combat table. . Simulates a combat sequence. keyword Prints a relevant fight message for the keyword specified, keywords are: START, IHIT, THEYMISS, IMISS, THEYHIT, IMDEAD, IMOK, IHITBACK, IMISSAGAIN, VICTORY. (See 3.2.3) /VOCAB {arg} If this command is used alone, it will give help on the vocabulary system, the arguments are as follows. * Displays every word the system knows. . Displays every verb the system knows. - Displays every synonym the system knows. [l] [l] is a single letter from "A" to "Z" and includes "$". It displays a list of every word the system knows beginning with that letter. .[l] As above, but it is limited to just verbs. -[l] As with [l], but it is limited to just synonyms. /EXAM [obj] Allows an object in the current room to be examined. If a database is loaded and a command is typed that is not preceeded by a "/" or a ";" then it is interpreted as a game command. The existence of the verb is checked in the synonym tables and any substitutions that may be needed are performed. The verb tables are then searched for the verb and if anything relevant is found, the action definition is displayed on the output window. An exception to this is the UNIVERSAL command (normally "shout") as defined in the vocabulary section: this verb is executed straight away. Commands beginning with a ";" are simply echoed to the debug window. This allows a debugging log to be commented. 4.5. Moving around. The /LOOK, /EXITS and the /GOTO commands can be used to test the rooms and the travel tables. After a database has been loaded, the debugger will always start off with the current room defined as the room with the attribute "startrm". If one of these is not found, the room called "START" is defined as the current room. From this room, /GOTO can be used to travel to another room, /LOOK to examine the room in detail and /EXITS to examine the travel tables. The /MSG command can be used in conjunction with /EXITS to examine messages or demons present in the travel tables. The use of these commands is best illustrated by means of examples. After the database has been loaded loaded the first room is examined. --*>/look Room: CHAT [2]. (Startrm) (Light) A room with a view. You are in a nice, warm cozy room full of seats and comfy chairs. There is a single exit to your north, but the view through the portal is marred by a wall of mist. --*>/exits n n o Moving north or out from this room would lead to either start, sfor2 or fyard1. The choice is made randomly after the command is entered. The room sfor2, which forms part of the southern forest, is now examined. --*>/goto sfor2 Room: SFOR2 [268]. (Light) Southern forest. You are pushing your way through the trees of the southern forest. The only ways seem to be north, back to the road, or east. --*>/exits n road3 n o n sfor1 e 1700 s w ne nw se sw in --*>/msg 1700 The forest is too dense in that direction. There are three exits from this room, two of them (north and out) lead to road3 whilst the other (east) leads to sfor1. The other directions produce message 1700. The two rooms leading from this one are now examined, the first, by actually going to it, the second by using an argument to /LOOK and /EXITS. --*>/goto sfor1 Room: SFOR1 [267]. (Light) Forest's edge. You are standing in the fringes of the southern forest. To your east your way is blocked by the castle moat, but the trees to the west are thin enough to pass through. --*>/exits n sfor2 w o 1700 n s e ne nw se sw in --*>/look road3 Room: ROAD3 [206]. (Light) Forest road. You are walking along the road through the forest. To both the north and south, the trees crowd closely to the roadside, making it very difficult to see into the depths of the forest. --*>/exits road3 n nfor2 n n sfor2 s n road2 e o n road4 w 1700 ne nw se sw in 4.6. Looking at verbs. If a verb is typed directly into the debugger, every relevant action definition is displayed on the output window. Individual action definitions can now be examined. The following example illustrates using the debugger to examine the verb "kiss". The /MSG command is used to examine the messages produced by the actions. --*>kiss KISS is a known verb. kiss froggy none destroycreate prince 1778 0 kiss princey none expdestroy null 1779 0 kiss pplayer none null null 1886 0 kiss wetfish none null null 1891 0 kiss person none emotion null 50 328 There are five actions defined for the verb kiss. The first, "kiss froggy" destroys the object of class "froggy" and creates a prince. It then displays message 1778. --*>/msg 1778 The frog looks in amazement as you bend down to kiss it, it tries to hop away but, you catch it and do the evil deed. With a flash, the frog that was always quite happy being a frog transforms into well... Something. The next action, "kiss princey", destroys the prince and gives the player who executed the command the amount of points the prince was worth. It then prints message 1779. --*>/msg 1779 The Prince's eyes light up as you approach him and he grabs you in his arms and gives you a big sloppy kiss; at that, he flies off into the distance shouting "Wheee, Chase me!" The third action "kiss pplayer" (pplayer is the class for all of MIST's "human" mobiles) prints message 1886. --*>/msg 1886 Yeuch! Why on earth would you want to do that! Kissing a live fish is handled with the fourth action "kiss fishy", this prints message 1891. --*>/msg 1891 Hmmm.. seems fishy to me guv. Finally, kissing other players is taken into account, this calls the function "emotion" with an argument of 50 and prints message 328. --*>/msg 328 You give them a great big sloppy kiss. 4.7. Looking at demons. If a verb fires a demon, then the demon can be traced using the /MSG command. There follows an example of tracing a game demon that alters the land's weather cycle to winter. It is a complicated demon that would take a great deal of time to examine with just a game listing. First, the verb to change the season is examined, this is the "winter" command. --*>winter WINTER is a known verb. winter none none ifwiz null 958 0 -33 This checks that the user is a wizard, and if so, prints message 958 on the screen and calls demon 33. --*>/msg 958 OK, it's winter... --*>/msg -33 $winter none none -1 global Demon 33 calls a verb "$winter" with no time delay, it is a global demon so it affects everyone. The "$winter" verb is now examined. --*>$winter $WINTER is a known verb. $winter none none ifdisenable null 28 0 -34 $winter none none ifdisenable null 29 0 -34 $winter none none ifdisenable null 30 0 -34 $winter none none ifdisenable null 31 0 -34 $winter none none ifdisenable null 32 0 -34 The "$winter" verb checks to see any of five other demons are enabled. If they are then they are disenabled (turned off) and demon 34 is fired. The five demons that it checks for are 28, 29, 30, 31 and 32 - These can be checked: --*>/msg -28 $brewing none none 15-30 global --*>/msg -29 $pouring none none 300-600 global --*>/msg -30 $calm none none 600-1500 enabled global --*>/msg -31 $brewing1 none none -1 global --*>/msg -32 $pouring1 none none -1 global These demons are all connected with the weather cycle, so the end result of these actions is to turn off whichever one of the five demons is currently controlling it, and then to fire demon 34. This should now be examined. --*>/msg -34 $snow none none -1 global Demon 34 calles the action "$snow", this is checked by entering the verb into the debugger. --*>$snow $SNOW is a known verb. $snow none none set rain 2 0 -35 "$snow" sets the object rain to property 2 (using the SET function) and then fires off demon 35. --*>/msg -35 $snow1 none none -1 global --*>$snow1 $SNOW1 is a known verb. $snow1 none none sendeffect rain 959 0 -36 Demon 35 calls "$snow1" with no time delay, "$snow1" then sends message 959 to every location containing the object "rain" using the sendeffect function. It also fires demon 36 when the command terminates. --*>/msg 959 It has started to snow. --*>/msg -36 $snow2 none none 300-1200 global --*>$snow2 $SNOW2 is a known verb. $snow2 none none set rain 0 0 -37 Demon 36 sleeps for a random time between 300 and 1200 seconds, it then calls the action "$snow2", this sets the object rain to property 0 and fires demon 37. --*>/msg -37 $snow3 none none -1 global --*>$snow3 $SNOW3 is a known verb. $snow3 none none sendeffect rain 960 0 -38 Demon 37 calls the action "$snow3" with no delay, "$snow3" sends message 960 to each room and then fires demon 38. --*>/msg 960 The skies clear, and it stops snowing. --*>/msg -38 $snow4 none none 300-1200 global --*>$snow4 $SNOW4 is a known verb. $snow4 none none sendeffect rain 955 0 -39 Demon 38 again sleeps for a random time between 300 and 1200 seconds. When it wakes, it calls the action "$snow4". This sends message 955 to every room containing the object "rain" and then fires demon 39. --*>/msg 955 Clouds are beginning to gather in the sky. --*>/msg -39 $snow none none 15-30 global Demon 39 sleeps for a random time between 15 and 30 seconds, it then calls the action "$snow" thus creating an infinite loop simulating a wintery weather cycle. Chapter 5. Conclusions. Throughout development and testing of the system, the MIST database was used for test data. MIST is a real game that is used every night at Essex University by players from all over the country; it is currently maintained by myself, and two other students from Essex. It is a long and laborious job to try and cross reference all the database parts to find errors, but using the debugger this task has been made much easier. Many faults in the MIST database have been discovered and traced, some of which have been there since it was first written in 1985. The informal definition of MUDDL has also proved to be very useful: previously writers of MUDDL databases have only had the original MUD database to give a basic overview of MUDDL syntax. Many of MIST's objects were incorrectly defined and some of the demons looked like GOTO's in badly written BASIC programs. The debugger was written using modular techniques, as a result it is fairly simple to extend to a full multi user game system. The structure definition module already contains all of the data structure definitions needed for the players, even though the debugger does not require them. Writing the debugging system has proved both intersting and practical. As a result of all the testing, both the MIST database, and my own understanding of MUDDL have improved. Appendix 1. Setting up the VMS environment for the MUDDL debugger. In order to set up the VMS environment in which the debugger operates, the following tasks must be carried out. The directory for the MUD databases should be created. This is normally called "MUD_DATA". Below that, the three directories "GET", "SOURCE" and "DATABASE" should be created. The routed logical name MUD_DATA should be set up to point to the MUD data source directory. This is so that the debugger can refer to this area with MUD_DATA:[]. The pathname to MUD_DATA (in this case USER6A:[CSZMJL.LORRY.PROJECT.MUD_DATA.]) has to be altered to point to the root directory which has been created. Once this alteration has been made to the DCL command procedure below, it will set up the logical names required. The program MUDDL.EXE should be placed in a directory and defined as a foreign command. The command procedure below looks for MUDDL in "BETA:[LORRY.BIN]" $ ! $ ! Program SETUP.COM $ ! Version 1.0 $ ! $ copy sys$input sys$output/nolog Logical name setup for the database generator. The logical name "MUD_DATA:" points to the database directory root, this contains the following: MUD_DATA | +------------------+--------------------+ / | \ GET SOURCE DATABASE GET: Contains the GET files for the database. SOURCE: Contains the database source. DATABASE: Contains the assembled database. Note: The building process isn't very friendly to people with low quotas (it is very inefficient in this sense). $ ! The following command sets up a concealed logical name MUD_DATA that points $ ! to USER6A:[CSZMJL.LORRY.PROJECT.MUD_DATA] $ ass/trans=concealed user6a:[cszmjl.lorry.project.mud_data.] mud_data $ ! This defines the program BETA:[LORRY.BIN]MUDDL.EXE as a foreign command. $ muddl :== $beta:[lorry.bin]muddl $ exit Appendix 2. MUDDL functions and internal commands. This appendix contains a list of MUDDL functions and internal commands. These are only listed for completeness, to provide a reference rather than a tutorial for the MUDDL language. 2.1. MUDDL functions. The only reference to the actions that these functions perform is found in the source to the MUD program. inc dec null move trans set resetdest toggle fix float destroy create forrot backrot expinc expset holdfirst holdlast flipat retal ifzero testsex ifobjcount ifprop ifpropinc ifpropdec ifrprop ifrlevel ifr noifr ifberserk unlessberserk ifwiz ifill unlessill ifdeaf ifblind ifparalysed ifdumb unlesswiz unlessrlevel flush unlessprop incdestroy destroytrans floatdestroy decdestroy destroydec decifzero swap unlessin unlessobjis ifobjis unlessinsis ifinsis unlessobjplayer ifobjplayer ifsmall unlesssmall testsmall transwhere ifin exp stamina staminadestroy loseexp losestamina injure writein enable suspend delaymove disenable unlessdisenable ifdisenable ifenabled unlessenabled unlessgot ifgot ifdead unlessdestroyed ifdestroyed ifsnooping unlesssnooping iffighting unlessfighting ifpropdestroy unlesspropdestroy unlessdead ifweighs unlessweighs ifhave unlesshave ifobjcontains unlessobjcontains iflevel unlesslevel ifplaying unlessplaying ifself destroydestroy ifinc unlessinc expdestroy expmove incmove destroyinc transhere iflight ifsex ifinvis ifasleep ifrstas unlessrstas emotion zonk dead send sendeffect sendmess sendlevel hurt sendemon ssendemon incdec decinc incsend ifhere ifheretrans unlesshere setsex togglesex destroytogglesex destroycreate destroyset setdestroy setfloat 2.2. MUDDL internal commands. The only references to the actions that these commands perform is found in the source to the MUD program (specifically in the file MUD5.BCL). The MUD and MIST help files will also give an indication to what the commands do. .tell .say .get .drop .kill .quit .score .look .log .inven .debug .make .summon .fod .eat .go .sget .sgo .back .bug .who .autowho .quickwho .reset .rooms .berserk .weigh .value .ctrap .follow .lose .begone .demo .laugh .provoke .purge .save .assist .refuse .set .password .snoop .p .unveil .unsnoop .direct .where .brief .ignore .verbose .flee .diagnose .blind .deafen .dumb .paralyse .cure .exorcise .freeze .unfreeze .mobile .humble .proof .shelve .unshelve .invis .vis .peace .war .haste .stamina .sleep .flush .wake .change .enchant .police .resurrect .keep .unkeep .attach .detach .insert .remove .pronouns .hours .newhours .spectacular .empty .bye .time .crash .map .exits .converse