MUSE Manual version 1.5. General Note: The MUSE Manual will always have the same version number as the version of MUSE that it relates to. This means that the version numbers of the manual have little to do with proofreading rewrites etc. Updated Manuals will have a name such as: MUSEman1.5a MUSEman1.5b etc. Where the letter appearing at the end of the file name represents the rewrite versions. Later versions will have letters closer to the end of the alphabet. This manual was written by Edward L. Wallace, 'Falryx' (falryx@dartmouth.edu) and any rights and privileges of reproduction are his in accordance with the US Copyright laws. All users have the author's permission to print, pass on and reproduce this manual in its entirety without modification, or parts of this manual may be used so long as this copyright is present and due credit given. Changes to the manual or requests to use the manual for other publications should be sent to the author. There are currently NO approved appendices to the manual, as dictated by the text in Part V of this manual. Thanks to Barry, Nils and 'Carrie Gram' for suggestions on improvements to this manual. NOTE: Later in the manual, commands will be displayed with a 'syntax' for usage. Rather than using the syntax displayed in 'help syntax' available online, I've developed my own for ease of use. Each syntax line will begin with the keyword 'SYNTAX:' for easy searching. Information contained within curly braces ({}) is optional. Information contained within bent brackets (<>) is required. At times something may appear like: SYNTAX: help < command | topic > The '|' symbol means 'or'. In other words - you should type 'help ' or 'help '. For some commands, a shortened, or abbreviated, version of the command may appear after it's name. It will be contained within parentheses '()' to indicate this. SYNTAX: look (l) When executing a command according to the listed syntax - do NOT include the <>'s or {}'s as I have here in the documentation. I've used them in an effort to explain what is required and what isn't - and the MUSE will often be unable to understand commands if you include these symbols. In general, I tried to avoid using symbols which can be significant, or commonly used in MUSE programming. Unfortunately, curly braces are SOMETIMES required in MUSE code. Symbols meaningful to MUSE code include (this is not a complete list, by the way): '/', '[', ']', '{', '}', ';' and ','. Now, down to business. ----- Change Log. MUSEman1.5c - Example sections redone: format changed, more added. - Parser section rewritten - Added Queue section MUSEman1.5b - Corrected some typographical, syntactical and general errors. - Standardized formatting for 'SYNTAX' headings. MUSEman1.5a - First MUSEman 'published' for Internet use. ----- Welcome to the wonderful world of MUSE: Multi-User Simulation Environment. If you have managed to get ahold of this manual, you probably have at least some basic experience with MUSE, and perhaps with MU*'s (MUD, MUSH, MUCK, MUSE, etc.) in general. However, this manual attempts to cover as much material from the absolute basics to the more subtle intricacies of advanced level MUSE programming. With that in mind, read ahead and enjoy. Please email me any corrections, suggestions or questions regarding the manual, I'd be happy to hear honest feedback. Table Of Contents: I. Basic MUSE knowledge A. The Environment: What's around you? B. Interacting with The Environment 1. Looking/Examining 2. Communicating 3. Taking and Dropping Things 4. Moving II. Basic Building and Programming A. Building - the basics 1. Objects 2. Rooms/Exits 3. @destroy / @undestroy 4. @link / @unlink B. More advanced building 1. Making what you build look better 2. Some tricks of the trade C. Programming on MUSE 1. $ events 2. ! events 3. Other basic programming things a. @listen / @ahear b. @switch c. @foreach d. @force D. Locks E. Flags F. Building a puppet G. The Queue H. Good Building and Programming III. Advanced Building and Programming A. Functions B. User-defined options C. Parenting D. Zones E. The Parser F. Good Building and Programming for the Advanced Student IV. Administrating a MUSE A. Powers B. Classes C. Official Commands D. Responsibilities V. Appendices A. Glossary Part I: Basic MUSE knowledge A. The Environment: What's around you? MUSE takes place in an alternate, virtual reality, where you are 'transported' via your computer into a world of text, where vision and imagination commingle to cover the jobs that normally five senses do. In MUSE you are connected to a 'server' (the MUSE) which has a database full of objects, people, places, etc. Your time in this virtual reality is among this database using your imagination and creativity as the primary tools to understand and enjoy what MUSE offers. The general MUSE environment consists of a variety of kinds of objects: characters, rooms, exits and things. Each of thesekinds of objects has a unique # in the database, called the dbref or database reference number. This number allows the MUSE to find all the information it needs about an object in its database with relative ease. [You'll see more on dbrefs later.] Characters are the virtual reality extension of you, the player.It is the characters of the MUSE who are able to manipulate the environment and interact with one another. MUSE supports a multi-player/character setting where many computer users can connect simultaneously to the server and partake of the virtual reality together Rooms are 'places' within the virtual reality, relating to actual physical locations. Rooms are very similar to the ones within your home, with four walls and a ceiling, but can also be used to represent the 'outdoors'. In this sense 'rooms' are a very broad category of objects meaning any place on the MUSE which relates to an actual 'physical' location where your character can go. Exits are objects which link rooms to one another. In your home, your exits are doors, stairways, or perhaps even windows. Similarly, in a virtual reality you can have exits which link one room to another, and this exits can represent everything from a large hole, to a door, to a catapult which launches you through the sky to land at your new location. Lastly there are 'normal' objects. These are things that range from empty soda cans, to cars, to a set of keys, or anything you can think of. Objects can generally be manipulated to make them unique, or do things, or just look nice. [There will be more on objects, rooms, and exits later.] That's the basic structure of the environment. When you log in to a MUSE you see: A Room This is a room in a large mansion. The walls are tastefully decorated with oak paneling. Along the north wall a massive bookshelf spans the length and breadth of the wall, running from the ceiling down to the plush green carpeting of the room. Scattered about, chairs and sofas offer comfortable places to sit and read, or just relax. A large door on the south wall leads out into the Dining Room, and a smaller one to the east leads into the hallway. Contents: Falryx A Chair A Book Puppy Dog(#4234I) Obvious Exits: South East This is a typical example of what you might see upon login if you were in a study of a mansion, or a similar room. What exactly you see depends on the MUSE, and where inside the MUSE you actually are. There are four main parts to this output: the name, the description, the contents and the exits. The name is what appears in the first line of the example: A Room. This is generally a little less vague than the example, such as: Falryx's Study or Cyberion City Transport Center. The name of the room gives you a quick reference about your location, and as you become familiar with the virtual 'terrain' you will become more adept at moving about, using the names as guides. Following the name is the description (often abbreviated to: 'desc') of the room. This is written in an attempt to give you a visual representation of the room, to help you picture just what the room looks like. Often, the desc will contain important information (for example: where the exits go), and it is worth reading through them. The next part of the output is the list of contents of the room.This list tells you what is in the room. In this room you see: Falryx, A Chair, A Book and Puppy Dog. The contents list will show you extra information if you own the object in the room, like with Puppy Dog. It tells you the database reference number (dbref) as well as any appropriate flags. [More on flags later]. Lastly, you see the obvious exits in the room. In this case 'South' and 'East'. This list will give you accurate information about the directions you can go to leave the room, taking you into another room in the MUSE. Now that you have a good idea of the environment, and a very basic background of the setup of MUSE, we can turn our attention to how one interacts with this environment. I.B Getting information on the MUSE I.B.1 Help files! The help files are perhaps the most important files on the MUSE for any new user. To access them you simply type "help". They will contained fairly detailed information on any commands, and many other topics that are important to the MUSE. The help files are constantly updated by the Directors of a MUSE to make sure they remain accurate and readable. If you encounter any problems using the help files, you should probably contact a director with 'page' (see below) SYNTAX: help help I.B.2 News files, finding out what's up, what's new, etc. Just as the help files are vital to understanding some MUSE commands in general, each MUSE has its very own different style and information that it needs to get out to its players. This is generally transmitted through the news to inform players of important activities, concepts or rules. To get a news listing, just type 'news' and you can go from there to find out the newson any one of a number of topics. SYNTAX: news news I.C Interacting With The Environment I.C.1 Looking/Examining - what's out there anyway, and how do I see it? Now that you are oriented in the environment, you are probably itching to experience it. Since MUSE is a text based virtual reality,the only way you can interact with it is visually. This makes the commands of looking and examining vastly important and very widely used.In the style of old adventure games the command to look at an object is (not surprisingly): look. "Look" by itself provides you with the name, description, contents and obvious exits of a room, similar to the example above. This gives you excellent information about your surroundings. The "look" command is often abbreviated to "l". In order to look at objects, people, exits, etc. you use "look [object or person or exit]". So in the example room from above, "look Falryx" would show you the description and contents of the character, Falryx. "Look A Book"would so you the book, and so on. The way MUSE works allows you to type in a couple keywords to look at an object, without having to type out its entire name. For example, "l book" would so you the description of something named "a book" or "the book" or "big bad blue book" etc. If there is more than one object in the room with the word "book" in its name then you need to be more specific, like "look blue book," etc. The general syntax of the look command, therefore is: SYNTAX: look (l) { thing | room person | exit } Here the object|room|person|exit can be identified through its name, database reference number (i.e. look #123), the keyword 'me' (i.e.. "look me" shows you your description) and the keyword 'here' ("look here" is the same as "look") "Look" tells you all sorts of interesting information, but there is also another command, "examine" which tells you even more. The syntax for the examine command is the similar to that for "look" and like "look", "examine" can be abbreviated to "ex". Before explaining the -examine command in detail, let's look at its syntax: SYNTAX: examine (ex) { / } Like "look" the things specified between the brackets ( [] ) are optional. "Examine" lets you specify a direct object to examine, much the same as "look" does, allowing for the same keywords and basic syntax: ex me, or ex here, or ex, or ex A book, or ex #123, etc. The optional / allows you to look at a specific part of an object, rather than the whole. For example: ex me/desc - will show you.only the description of yourself. [ There will be more on attributes later. ] "Examine" will show you different things depending on the object your are examining. If you examine an object that you own, like yourself, then you will be shown detailed information about yourself: a description, money, owner, any locks, any set attributes, contents, etc. If you are connected to a MUSE now, then do "ex me" and look at the output. Any object you make will also show you similar information, since you are the object's owner. If you examine an object you don't own (for example: examine shkoo) then you will be shown a much abbreviated list of information, including the owner of the object and any publicly viewable attributes (like sex, last connection time, and alias). This may seem rather limiting, but this is where the VISIBLE (v) flag comes in. [ For a detailed explanation of flags, check the glossary ] If an object has the VISIBLE (v) flag, then the owner of the object is saying that anyone can examine the object and get all the information that the owner gets: that is if shkoo was VISIBLE then you would get the same information about him when you examine him, as you do about yourself. This flag is very helpful in learning and teaching others with examples - they can see how the examples work and then examine them to see what >makes< them work. I.C.2 Communicating with other players Now that you can see them, how do you talk to other people? Part of the thrill of MUSE is meeting and interacting with people from all over the nation and the world, and MUSE has a number of ways to communicate with these folks. The "say" command lets you speak into the room you are in and to the people around you. When you use the "say" command (or the abbreviated double quotes: ") the people in the same location as you see: Your_Name says "Hello!" and you see: You say "Hello!". Since the function of this command is pretty straightforward, we'll hop right to syntax: SYNTAX: say (") Say is often abbreviated to just ". This means that 'say hello!' and ' "hello! ' are the same exact command (one is just a lot shorter to type). The "pose" command is another helpful command for communicating with other players in the same room as you. It essentially allows you to 'pose' an action for other players to see. Like "say," it has an abbreviation: ':' so, 'pose jumps up and down!' is the same as ':jumps up and down!'. With the pose command you input an action and your name in prefixed to that action and displayed to the contents of the room. SYNTAX: pose (:) - results in something like: 'Falryx jumps up and down!' There will be times when you'll want to speak with a person privately. This is done through the "whisper" and "page" commands. "Whisper" allows you to whisper a private message to someone in the same room as you are, and "page" allows you to send a message to someone anywhere in the MUSE. SYNTAX: page = whisper = When you page/whisper someone you can either choose to page or whisper to them with a message or an action. Here are some examples of what some page and whisper commands might look like: page Falryx=Hi there! You paged Falryx with: Hi there! whisper shkoo=:waves! How are you? You whisper-posed shkoo with: You sense: Your_Name waves! How are you? Next, there is the +com system which is widely used on MUSE to communicate with other players. Like "say," the +com system allows you to communicate with numerous players simultaneously and like "page" it lets you communicate with them no matter where they are on the MUSE. Essentially, the +com system is similar to a huge CB radio system. When a new character is created on a MUSE they are immediately placed on the 'public' +com channel, where most conversation on the +com system takes place. Unlike say, pose, etc. the +com system is slightly more complex with a variety of commands. These commands and their syntax are: SYNTAX: +com = = +channel (+ch) +channel (+ch) + +channel (+ch) - The first two commands allow you to speak on the +com system, and the last three allow you to manipulate the channels that you are listening too. Unlike a CB radio, +com lets you listen to any number of channels at one time, so to tell the MUSE to have you listen to another channel you would enter: +ch +Channel_Name - and poof, you'd be listening to a new channel PLUS any of your old channels. If you decide you don't like listening to a certain channel you can leave it by typing: +ch -Channel_Name. And lastly, if you get confused as to what channels you are on, +ch will list them all out for you. +com = allows you to choose which channel you send a message to, i.e.: +com public=Hello! The use of +com is pretty straightforward, and basically acts like a page command in many ways, where you type out the command, then the name, then the message or action. A nice shortcut to use with +com is the equals sign. For example: =Hello! would have you say "Hello!" on the >last< channel you joined. This is called your default channel, and is changed each time you add or delete a channel to your list. Play with the channel commands a bit and get used to seeing how they work. It may seem a little confusing at first, but you'll discover it can be pretty straightforward. Here's a quick example of some +com stuff. [public] Falryx has joined this channel. =Hello Falryx! [public] Your_Name: Hello Falryx! [public] Falryx: Hiya! shkoo pages: Please join channel shkoo. +ch +shkoo [shkoo] Your_Name has joined this channel. shkoo has been added to your channel list. [shkoo] shkoo blinks and waves. =So shkoo how are you? [ Note: See how the default channel has chanaged from public to 'shkoo' when you added the channel? ] [shkoo] Your_Name: So shkoo, how are you? [shkoo] shkoo: mostly idle. +ch You are currently on the following channels: shkoo public [public] Falryx: What's up, Your_Name? +com public=Not much, Falryx... how are you? [public] Your_Name: Not much, Falryx... how are you? +ch -public public has been deleted from your channel list. [public] Your_Name has left this channel. +ch +public [public] Your_Name has joined this channel. public has been added to your channel list. NOTE: This is basically the format to change your >default< channel back to public by making it the last channel you joined.] =:smiles... much better. [public] Your_Name smiles... much better. etc. Note the way the default channel works, and how the various +com commands work. As usual you can get fairly detailed help from the on-line help system by doing: help +com and help +channel. Next is the on-line mail facility, accessed through the +mail command. This lets you leave a message for someone to read at a later time, like email. There are three different modes for the on-line mail system: reading, writing, and checking. All three modes handily revolve around the single command: +mail. SYNTAX: +mail +mail = +mail +mail clear +mail all by itself will check the mail files and list out any mail that you have in your mailbox. Each message is assigned a number in your box, and that is used with the +mail command in order to read a specific message. To send +mail to a person, you use the same format as page, whisper, etc... command person=message: +mail = [message]. Lastly, to empty your mailbox, you simply type +mail clear. A quick +mail example is below for your aid: +mail 1) From: Falryx(#36747) Date: Wed Jun 24 11:12:34 1992 2) From: shkoo(#100) Date: Mon Jun 22 22:23:11 1992 --- done --- +mail 1 Message #1 From: Falryx(#36747) Date: Wed Jun 24 11:12:34 1992 --- Hi there! I just wanted to send a note to you saying hello! --- +mail Falryx=Thanks! Hello back at you! Your mail has been sent to Falryx. +mail clear Mailbox cleared! +mail Sorry, no mail today. And that's +mail. Lastly, we have '@emit', '@pemit' and '@remit' which can be used to communicate with other players. These are a little more obscure than the other methods, and are more often used in on-line programming. However, you can communicate with people using these, so it is appropriate to address them here. In general, emitting a message emits exactly what you tell it to. Therefore, unlike "pose" and "say," your name isn't automatically attached to anything that you emit. This allows people to program objects which can do interesting things, and allows for a great freedom in channeling one's creative energies. No @pemit, @remit or @emit may start with the name of another player or another player's puppet [puppets are talked about a bit later]. This is a safeguard programmed into MUSE which prevents people from impersonating other users. Although I'm constantly surprised at why someone would care to do this - there are dangers involved. On a MUSE, your identity is significantly defined by your name. In fact, your name could be know throughout the MUSE/MUSH world if you are notorious enough (in either a good or bad way). A unique name affords you the assurance that people know it's _you_ talking to them, and not some other random user from Timbuktu. Apparently, some people get some weird sense of joy from trying to incite other users against someone. This can be done several ways, but one of the easiest is to do something like: @emit Falryx says "You are a real jerk!" Which, without "spoof protection" built into MUSE would look like: Falryx says "You are a real jerk!" Clearly, I (Falryx) didn't say that, however. Rather than allowing these kinds of situations to come up, MUSE has something called "spoof protection." This means that no user can @emit, @pemit or @remit with another user's name as the first word. In other words, actions which start with a user's name are authentic. There are arguments for and against spoof protection. The primary purpose of maintaining your privacy and giving only you the right to use your name is consistent with the original goals of MUSE development. As such, "spoofing" is viewed with distaste and distrust. Back to the emitting. These commands all have a similar syntax. @Emit is used to send messages to the room you (or the object emitting) is in. @Pemit and @remit are variations of the same theory. @Pemit is used to send something to a specific person, or object, and @remit is used to send a message to a specific room, or container. SYNTAX: @emit @pemit = @remit = Both @pemit and @remit accept a dbref (i.e. #100) as the player, or room to send to. @Pemit generally must be done 'locally,' that is you have to have the same location as the object you are trying to @pemit to in order to be successful. This is _not_ true with objects you own. MUSE allows you to handle your own objects via dbrefs, no matter what their location. @Remit and @pemit will also accept 'me' as an argument. Again, most of these ramifications are _programming_ ones and will be address further in section II. That's it for communicating with other people and things. I.C.3 Taking and dropping things MUSE has many many objects which can be found in various places. At times, you may wish to pick up an object to use it, and later drop it, or whatever. Needless to say MUSE provides a quick and easy way for you to pick up and put down objects as well as checking to see what you currently are carrying. SYNTAX: get take You may pick up any thing which isn't @locked against you (check out the section on Locks in Part II) or an exit which is not @linked (yup, you guessed it, this is addressed in Part II as well). However, even though you may pick up several different objects, it is generally considered rude to pick things up which aren't yours unless you have been asked to. At times, people will take everything they see (and sometimes even 'get' a player) and this can be extremely aggravating to the people who own these objects. It's best to practice caution when in a MUSE - if something isn't yours, don't mess with it unless you have permission. (Note: This doesn't mean don't _use_ an object. Often, objects will exist in public places for people to use - what this does mean is don't take the object and drop it somewhere else, etc. Use your common sense and you should be fine) Dropping an object is easy (especially for any fans of Zork out there). SYNTAX: drop Tada! There isn't a whole lot more to say. You can drop anything that you are carrying into the location you are currently in. Lastly, there is a way to find out just what it is you are carrying. MUSE does not have a restriction on the number of objects you can carry so you are restricted as you might be in real life. For all you Zork players out there, this too will be familiar: SYNTAX: inventory (i) This will list all the items in your possession as well as telling you how much money you currently are carrying. For now, don't worry too much about money. It can be used to buy things, and is used for some bookkeeping within the MUSE. Essentially money has begun to become obsolete. It can probably be expected that sometime in the future the role of 'money' will be drastically changed. These three very simple commands are all you need to know when interacting with objects in your environment -- remember to treat things which aren't yours with some respect. I.C.4 Moving around in Virtual Reality You are now an expert socializer and observer, but the problem is, you can only do all that in one room! Horrors! Well this next section is about the various ways you can move about the virtual reality of the MUSE. Walking around from place to place on the MUSE is fairly simple and is done by using exits that link various rooms together. As mentioned above, these exits can represent a lot of different things, but usually are one form or another of door, like you might have in your room or house. To use an exit you simply type the exit name, and poof! you are in the place it leads to. Alternatively, if you like having verbs, you can type: go and you will use the exit. This method of moving is fairly basic and based upon Zorklike adventures where you type 'north' to go north etc. MUSE is more flexible in that it allows you to name an exit: Slimy Green Slide, instead of 'north' or 'south' etc.... (so for that exit you'd type either: Slimy Green Slide or: go Slimy Green Slide) When you look at a room, the obvious exits of the room are displayed, following the keywords: 'Obvious Exits'. You might want to refer to the first example in this manual which shows this. SYNTAX: go move goto All these accomplish the exact same thing. A quick way to move about the MUSE is to use the @teleport (@tel) command to jump from one room to another - often covering large distances and avoiding a time consuming walk. The syntax for the @teleport command is: SYNTAX: @teleport (@tel) For example: @tel #1234. This will quickly change your location to room #1234. @teleport only 'likes' database reference numbers, so you have to know the number of your destination before you can teleport there. @tel seems like the answer to all your wishes for moving about the MUSE, but there is a hitch. You can always @teleport to any room that you own, since you maintain control over that room. However, if you _don't_ own a room, it must be set JUMP_OK (J). If the room does not have the JUMP_OK flag that means you can't @teleport to the room. Rooms that are JUMP_OK will display their database reference number when you look at them, providing you with an easy way to find out the number. As mentioned above, there will be more on flags later, but for now, it is just important to note that @teleport doesn't always work - and it's not because you are doing anything incorrectly, but most likely because of the JUMP_OK flag. There are some _objects_ which you will be allowed to enter (like a car, or bus). These are typically vehicles of some sort, or perhaps a small building or structure (dragon, phone booth, elevator, etc.). Getting in and out of these objects is relatively simple: SYNTAX: enter You won't be able to enter all objects. You may always enter an object you own (unless you specifically lock it _against_ yourself). No one else may enter an object which you own unless it is set ENTER_OK (e). [Flags are described in more detail later on in this manual.] Leaving an object is simply SYNTAX: leave This command does not work in rooms, only in objects that you are in. This is in many ways, forcing yourself to be 'dropped' from the object (picture what would happen if a car I was in typed: drop Falryx -- I'd be dropped just like you can drop an object you are carrying). Leave is useful only for leaving objects which you have entered. Lastly, there is a quick way to move to a specific room called your "home". Your "home" is generally a private room where you have some of your more treasured belongings, etc. The home on a MUSE is probably very similar in function to your bedroom in your real life. To get to your home you type the command "home". SYNTAX: home When you log in to a MUSE as a new character, your home is automatically set to a specific room - generally a public area that doesn't get too much traffic, but is near anything important. Once you have made yourself a new home, or if someone offers you a place to call home, you need to use the @link command. This command will change your "home" for you. SYNTAX: @link me = The @link command is used for a lot of things, but for now we will just assume it changes your home, and wait until later to discuss @link more in depth. You may @link yourself to any room that you own, or to any other room on the MUSE that has the LINK_OK (L) flag. Like the JUMP_OK flag, the LINK_OK flag will display the room number of the room next to its name so you have an easy reference: For example: east You walk east. A Room(#2345RL) Etc. etc. If you change the room your are @linked to then that becomes your new home, and the "home" command will automatically take you to that room. Often, its a good idea to type "home" before you disconnect from the MUSE. I.D The End. That's the end of Part I. After some experimentation you should be able to look, communicate and move around the MUSE with some degree of confidence. In general most users are ready to help you out of any problems, so when in doubt: page = Help! I'm lost! And there's a good chance they'll try and help you out. MUSEs have 'classes' which allow you to spot Directors, Administrators, Officials, Guides, etc. (or classes along these lines). These people generally have an official function in the MUSE and should always be able and willing to help you. Part II: Basic Building and Programming II.A Building - the basics. In the previous section, I introduced you to the basics of MUSE: looking around, talking to people and moving around the virtual universe that a MUSE represents. One of the extreme beauties of MUSE (and other similar network environments) is the ability to create your own additions to it. You are empowered to leave your 'mark' on the MUSE, for better or worse. How you choose to do that is up to you, but one of the most common ways is to become a prolific and proficient builder. Builders create objects, rooms, gadgets, environments, whole cities, etc. Without people to Build, a MUSE is doomed to a small db, and a short life. It is the users who, via contributing, ensure the continued survival of the MUSE. In this next section, I'll teach you the commands for basic building, and point to some important tangents which you will want to explore on your own time. Sadly, I am unable to write, in this sitting, all the commands and intricacies involved in 'Good Building'. I'd be here long after I was supposed to graduate in June... II.A.1 Things Making things is simple. Making things intriguing, amusing, and eye- catching is much more difficult. The purpose of any thing-maker should be to create something which other people will find entertaining, or even educational... something people will want to learn from and perhaps emulate. To create a thing, one simply does: SYNTAX: @create i.e. @create Table, or @create A Large Table in the Corner, or @create A pretty blue bird, etc., etc. ad infinitum. This command tells the MUSE to make space for a new thing with the name you give it. In turn, the MUSE will tell you that it has reserved this space with the number '#1234'. If you recall, this number represents, for the MUSE, the place in the database where the information about this object can be found. You can always refer to the object using its 'dbref' (database reference), even if it isn't in the same room as you are. Great. So now we have this thing. What do we do with it? If we were to exercise some of our usual commands it wouldn't be that interesting. 'Look' for example would give us: 'You see nothing special.' Horrors! All that work and it's "nothing special"?! What kind of MUSE is this anyway? Well, _you_ need to make it something special. The MUSE won't take your intentions (as you might indicate with the name 'Table') and make it something special. Your job, as a builder is to take this perfectly uninteresting table and transform it into something really special. There are a couple quick ways to make your table more special, they are: @desc (remember '@desc' from above?), @adesc, @odesc, @idesc, @succ, @osucc, @asucc, @drop, @odrop, @adrop, @fail, @afail, @ofail, @efail, @lock, @elock... Wow! All these commands! They seem intimidating, but they all follow a general syntax which I'll outline for you. @*succ @*drop @*fail @*desc @*lock Notice, the * stands for 'any character'. That is, @succ, @osucc and @asucc can all be represented by @*succ. Each of the letters which take the place of the * are important and correlate to something, but first, let's look into what the stuff _after_ the *'s means. @*succ: The 'succ' stands for success. In MUSE, success means something entirely different from what it may mean to you in your real life. To the MUSE success means different things for different object types (just as it means different things to different people in real life). For example, if you pick up an object using the 'get' command you 'succeed' with that object and the information stored in the @*succ's is triggered. Here is a little table with what success means for MUSE: Rooms: You have successfully 'looked' at a room (and gotten the description). Objects: You have successfully picked the object up. Players: You have successfully picked the player up. (Note: This is in general considered very rude. Make sure you don't pick someone up without their consent. If you just pick someone up, you may have a very irate person.) Exits: You have successfully gone through an exit to another room. @*fail: 'Fail' is rather self-explanatory. Any time you do not _succeed_ the MUSE triggers the 'fail' information. Using the above example, if you tried to pick up an elephant, you would fail, and so the 'fail' messages set on the elephant would be triggered. (If this seems like a lot to absorb, hang in there, I'll have an example coming up soon). Rooms: You have failed to look around because you are unable. Objects: You have failed to take an object. Players: You have failed to take them. (see my earlier note about picking up players) Exits: You fail to go through the exit. @*drop: 'Drop' generally means what it says. The information there is triggered when you drop an object, or player. Again, here's a quick table: Rooms: This means something - but I'm honestly not quite sure what. In almost two years of MUSE-ing I've never used it. Objects: You have 'dropped' an object with the 'drop' command. Players: You have dropped a player with the 'drop' command. Exits: You have gone through an exit. (This is a bit screwy, but will be addressed more fully when I talk about building rooms). @*lock: This is a command which can restrict the people who can 'succeed' with your objects. For example, if you wanted to make a gift for someone and didn't want anyone else able to take it, you could lock it to that person, so that they could pick it up, but no one else might. Any object can be locked. The @lock command is fairly complex, so I'll address some parts in my example, and leave the rest for another section. @*desc: These sets of commands store information which is triggered when someone looks at an object. These are essentially the same whether used on rooms, people, objects or exits, so we don't need to have a handy table. I realize that is a lot of information to absorb, and now would probably be a good time for an example, but there is one more important aspect about basic building that I want to touch on before I do that. That is, what can the *'s be replaced with? Another quick table will point to the options: a: 'Action' - the information here will be triggered, like a set of commands and will be run after the appropriate action has been taken. For example, a very common one is: @adesc me=whisper MyName=You have been looked at by %n. (I'll get into %n in basic programming..) This tells you when someone looks at you, because the Actions in @adesc are triggered after someone looks at your description. 'Action' commands will be addressed more fully in the programming section. e: 'Enter' - this option is used primarily in conjunction with 'fail' and 'lock' (efail and elock). Efail is triggered when someone fails to 'enter' and object because it has been locked with the 'elock' command: which restricts who can enter it. i: 'Inside' - this is used only with 'desc' and means the description you see when you are _inside_ an object. o: 'Other' - this option sets a message which is displayed to _Other_ players in the room when you succeed, fail, drop, etc. It is automatically prepended with the player's name. A quick example of an object: @osucc box=picks up the box. - This way, when you 'take' the box other people will see: MyName picks up the box. Messages will have certain pronouns substituted to them if you choose. Though this is discussed in more detail later, you can have messages containing either %s, %o, or %p. These will transalte to he/she/it/, him/her/it and his/her/its, depending on the '@sex' attribute of the object. Spivak settings give different, non-gender biased messages, but I'm not familiar with the exact ones. A quick example might be: @ofail venus fly trap=tries to take the fly trap and jumps away when it tries to eat %o. (This will turn into: Falryx tries to take the fly trap and jumps away when it tries to eat him.) A quick way to remember which %s/o/p does what: %s Subject (He did that. She is nice.) %o Object (I waved to him. Joe gave her the ball.) %p Possessive (That is hers. I laughed at his joke.) nothing: When you just have 'succ' or 'fail' or 'drop' you are setting a message which will be sent to the player when they take, fail to take or drop an object (for example). Again, all this seems a bit intimidating, so here are a couple examples for illustration: Thanks to Barry Kort, from MicroMUSE (who sent this to me from another MUSEr), I can give you this handy table. Hopefully this table will aptly explain things where I may have failed in that endeavor. /-------------------------------------------------------------------\ | |TO SHOW MSG| TO SHOW MSG | TO TRIGGER | | | TO ENACTOR| TO OTHERS | ACTIONS | |-----------------------|-----------|-------------|-----------------| | AT FAIL TO USE (*) | @fail | @ofail (P) | @afail | | AT FAIL TO ENTER | @efail | @oefail | @aefail | | AT FAIL TO LEAVE | @lfail | @olfail (P) | @alfail | | AT FAIL DUE TO S-LOCK | @sfail | @osfail | @asfail | | AT FAIL DUE TO U-LOCK | @ufail | @oufail | @aufail | |-----------------------|-----------|-------------|-----------------| | AT USE (*) | @succ | @osucc | @asucc | \-------------------------------------------------------------------/ The name of the command is really a description of what it does (and to whom) if you know how to read it. Some other "@Command-families" work this way: *Enter, *Leave, *Desc, *Drop, and *Move. (*) The Definition of "Use" depends upon Object type: For Rooms: successful enter or look For Things and Players: successful take/get For Exits: successful entry through (P) Message will be prefixed with name of the triggering Player. Thanks again, Barry - and thanks also to the anonymous contributor. ## AWOOGA! EXAMPLE ALERT! (Ex 2.1) ## @create An Elephant An Elephant(#445) created. @describe An Elephant=This is a large grey elephant. As you watch the great beast, it sways back in forth in a lacadazical rhythm on its ponderous journey to a nearby stream. The elephant's large grey trunk snakes around passing plants grabbing on for a bite or two. Description set. @odesc elephant=looks at the big elephant. Set. @lock elephant=me (this means only you can pick up the elephant) Locked. @succ elephant=You pick up an elephant! Wow, you must be strong! Set. @osucc elephant=picks up an elephant! Watch out! Set. @odrop elephant=teeters back and forth under the weight of a large elephant and drops it with a loud *THUD* Set. @drop elephant=The elephant gets very heavy, so you decide to drop it. Set. @fail elephant=You can't pick up an elephant!! Set. @ofail elephant=tried to pick up the elephant, who doesn't even notice. Set. ## END OF EXAMPLE ## This is a typical way to create a simple object. By addressing the @lock, the Fails and the Succs we have thoroughly made the elephant so people will always get a reaction that is unique for the elephant. If you are on a MUSE now, try creating something like the elephant, and try out some of the commands. If there are people in the room with you, ask them to try taking the elephant so you can see the 'ofail' or 'osucc' message. II.A.2 ROOMS Well, now we've got a good idea how to make more objects - but you still are limited to the rooms which already exist in the MUSE. Fortunately, MUSE has, within itself, the method for adding more rooms to the database - effectively enabling the users of a MUSE to increaseits 'physical geometry'. Indeed, with a few simple commands, and the armory of commands introduced above, you can turn yourself from a crafter of objects to a construction worker, of sorts. The few commands you'll need to know are simple, and make sense: SYNTAX: @dig ={exit-to; alias; alias , exit-from; alias; alias } This command tells the MUSE to set aside place in the database for a room, which you own. If you specify an exit, the MUSE will automatically open an exit for you from the room you are currently in to the one you just dug. This offers an excellent shortcut for builders. The same is true for an entrance. Should you specify a name, an exit from the room you dug will be opened to the room you currently are in. This command effectively makes a room and the requisite exits for you. There are a few important things worth noting, however. If you don't own the room you are currently in, the MUSE will prevent you from opening an exit from that room to the room you dig. Conversely, no one can do the same in a room you own. This prevents people from building off of your rooms without your express permission. In addition, if the room you are in is not set Link_ok (see the portion on flags - still to come) and you don't own the room, then you may not open an exit from the room you built into the room you currently occupy. Every room in the MUSE has to be connected, somehow, to the other rooms. If you imagine this, it means that every single place you can go in a MUSE is connected, somehow, to every other place. If you have a room which is disconnected from the entire MUSE, the server will remind you on a regular basis (perhaps, every ten minutes). This interval is just short enough to be extremely annoying if you have unconnected rooms. The best way to get around having to deal with this problem, is to find a place you can call your own (and own), then build off of that, or receive permission to build from a public point. Different MUSEs have different policies about building. I recommend that you read the 'news' of a MUSE when you first login. This way, you are informed about the specific policies of the MUSE which you are on. If you happen to @dig a room without any way to get there, you aren't left out in the cold. In fact, MUSE has a command to open additional exits into and out of a room. The command, oddly enough, is: SYNTAX: @open = When you name an exit, you can give it aliases. For example, you might call an exit: Kitchen;k;out;kitch. This means that anytime you press 'k' or 'out' or 'kitchen' or 'kitch' you will tell the MUSE that you wish to go through that exit. It is generally a good idea to have exits with at least a few aliases. This facilitates moving around in the rooms that you create, and it makes it more enjoyable to explore when you don't have to type out long names for exits. The destination you specify has to be a 'database reference number' or 'dbref'. If you recall, a dbref is a number, prefixed by the #-sign, which is unique to every exit, object, player and room on the MUSE. This unique number allows you to address this object no matter where you may be. That is, in order to use the name of an object you must be in the same location as the object. But if you are far away from something, you can reference it by using this database reference number. It is this ability which enables you to open an exit to a room, since you cannot reference by name. Rooms and exits, just like objects, need to be personalized with the 'succ', 'drop', and 'desc' messages. For rooms, it is important to use @desc to describe the place that you are in. The 'succ' and 'drop' messages mean something for rooms, but these are a little more obscure (as pointed out in the table above). For exits, @desc, isn't as important (though describing exits is a sure sign of Good Building), while @succ, @osucc, and @odrop are very important. There is a flag, known as the 'TRANSPARENT' flag. When set upon an exit, it allows you to look through the exit to the next room. This is one way to allow people to get a feel for where exits lead, etc. This flag is especially appropriate for 'outdoor' settings where someone may be able to see for several miles. [Again, there will be a lot more on flags later.] As the tables above show, these messages inform people in the MUSE where you go, or where you come from. This makes following someone around, etc., much easier. In general, _all_ exits should have @osucc and @odrop messages set. If these aren't set, the places you build will confuse other players, defeating the purpose of the MUSE environment. ## AWOOGA! EXAMPLE ALERT! (EX 2.2) ## Let's quickly walk through building a room. For now, we'll pretend we're in a room we already own, so we can freely @open exits to new rooms. l Outside the Front Door(#1234RJ) You are standing outside the Front Door of the Not-So-Famous Office of the City Planner in MicroMoscow. The door to the office is made of a fine, solid wood, with a carved nameplate announcing the occupant of the office. The landing, upon which you stand, overlooks the main foyer of the Governmental Palace, bedecked in splendor. @dig Reception Reception created with room number 19793. @open Door;d;office;off Door;d;office;off opened. @link d=#19793 Door;d;office;off(#19794E) linked to Reception(#19793R). door Reception You see nothing special. (note: We don't have an exit leading out - so let's make one, we can @open and @link again, or we can shorten it by doing:) @open Out;o=#1234 Out;o opened. Linked to Outside the Front Door(#1234RJ). Yay! We've now built another room, and made exits. Now, we could have done this in one simple command, instead of all those commands we just typed. What? That's right! Just do: @dig Reception=Door;d;office;off,Out;o Next time, and you'll see: Door;d;office;off opened. Linked to Reception(#19793R). Out;o opened. Linked to Falryx's Study(#1234RJ). As you can see, building with the latter command is easier and faster. ## END OF EXAMPLE ## II.A.3 @destroy / @undestroy Most (if not all) MUSEs use a quota system for their users. That is, each user is restricted in the number of objects (rooms, exits, things, etc.) that she or he can build. This is done to ensure that the building which goes on in a MUSE is generally of good quality, as well as to protect the database from growing too large, too quickly. For more on quota, etc., consult the section on Good Building and Programming at the end of Part II. One way to act as a responsible user is to recycle objects of yours which have outgrown their usefulness. This is why MUSE has the @destroy command. This command tags the object you state (no, you can't @destroy a Player, or something you don't own), for recycling. After ten minutes, the object will be recycled by the MUSE, freeing up the space it took for another object. SYNTAX: @destroy Please keep in mind, that @destroying old objects which are no longer used is a _good_ idea. Keeping around various objects for memorabilia is a detriment to the entire MUSE, as it contributes to the very serious problem of database bloating. Should you accidently @destroy an object you don't want to recycle, MUSE has a quick fix: @undestroy. This will remove the tag that MUSE puts on it for recycling and effectively save the object you specify from destruction. SYNTAX: @undestroy Since these two commands are fairly straightforward and their usage is primarily that of responsible building and programming, I'll save the rest of the discussion for later Some MUSEs (most, I think) have the ability to 'protect' certain objects from being destroyed. They actual mechanism they use to do this isn't all that impotant, but the commands may be helpful. To protect an object from accidental '@destroy' commands use the command: SYNTAX: @protect To remove this protection, you need only type: SYNTAX: @unprotect If you try to @destroy an object that is protected, MUSE will tell you that you can't destroy it, because it is protected. This is a helpful way to insure some of your more important belongs don't accidentally get destroyed. II.A.4 @link / @unlink @Link means different things depending on the object you are @linking. In general, @unlink reverses the effect of the @link command, resetting whatever value you specified at an earlier time. SYNTAX: @link = SYNTAX: @unlink For players and objects, @link defines the 'home' of that objet or player. @Unlink cannot reset this value, it may only be changed by @linking to another location. By @linking yourself to a certain place, you are able to choose where it is that you go when you type the 'home' command. Similarly, objects can sometimes be sent home (if left lying around in public areas, or if left in a room which is @destroyed). @Link, therefore, links you (or an object) to a certain location and defines that location as your home. An object's home can be determined by examining it. If you recall, we set up your home in part I, you may wish to change it to a room that you own. Objects have homes automatically set upon them. That is, whenever you create an object, MUSE gives the object a home, and that home is the room you are currently in. Since this can sometimes be unwanted, @link provides a quick way of changing where your objects call 'home'. For exits, @link will change where the exit leads to. If an exit is already @linked to a room, then you must first @unlink the exit in order to relink it to another location. In this sense, @link, ties together an exit and its destination, where @unlink resets that link. There is a new command called '@relink' - which may allow you to change the @link of an exit without first @unlinking it. More information that when I have it. Also, it's possible to @link exit=home - this prevents exits from lying around unlinked (other users can pick up unlinked exits and use them for their own purposes). Lastly, for rooms, @link sets something known as the 'dropto'. If you @link a room to another location, any objects dropped in that room will be sent to that location (you may wish to read the helpfiles on the STICKY flag, as well). This is a way of keeping rooms relatively clean of debris, etc., often sending the objects to a lost or found. The @link can also be described as 'home' (i.e. @link here=home), in which case any objects dropped in the room are sent to their home. II.B More advanced building Well, we now know how to build things. But somehow, it feels like you should be able to do a little more than just set a bunch of descriptive messages. Well, there are a few ways to accomplish this: one is by making your descriptions, etc., more real, another is through 'coding' or 'programming'. The latter will be addressed in section II.C. II.B.1 Making what you build look better It's always possible to just @create A wooden table, and @describe it as "An oak table." This, however, is really not all that interesting. When you look at a table, what do you notice? The shape, color, texture, quality, etc. You'd notice if the table was rickety, or if it had chips in it, or what was on it, or even under it. Since people can't literally see these things unless you put them there, you should endeavor to make your work stand out. If someone looks at an object, or room, that you have made, they should be able to walk away from their computer screen, close their eyes, and picture exactly what it is you wanted them to. Or, at least, very close to what you have in mind. Each person develops their own style of building, and this is a good thing. However, there are a couple points you should keep in mind when building: * Remember that users have only the written word to convey a plethora of senses. The words which you attach to an object or a room will be the only things capable of giving a person a _sense_ of where they are, or what they are interacting with. If something has a distinctive smell, or feel, or sound -- make sure and tell people through @desc, @succ, etc. * Paint vivid, but not melodramatic, pictures. Using active constructions (i.e. The table stands stoically against the far corner) instead of passive ones (i.e. You see the table standing in the corner) creates an environment which tantalizes the senses, and engages the imagination. Remember that you like to read things which are interesting, so make your creations interesting. * Check your text for typos. While people can generally adeptly decipher typos, it takes away from the quality of your work if someone has to endeavor to understand it. [Note: Please report any typos in the manual - I'd hate to be hypocritical] In general, objects and rooms shouldn't just sit there -- they should jump out at the user and envelop her completely, giving her a sense of being as well as seeing. II.B.2 Some tricks of the trade Wonderful. We've managed to build some stuff, and make it look really cool. In fact, it almost seems like we are actually there in person, rather than interacting via a computer. However it's just not quite good enough for our tastes. How can you make building a little more special, still? One way is through programming. In this section, I'll briefly point out a couple areas and a few ideas. Play around with them and see what you can discover on your own. In your perusals of the helpfiles you might have discovered things like: @adesc, @asucc, @adrop, @afail, etc. These attributes store a string of commands which are triggered when an object is looked at, picked up, dropped, etc. Using this commands, it is possible to do a little basic coding to help give your rooms 'life'. Now, rooms don't have to just sit there, patiently passing away the time, offering only their description to passerby. Here, it seems, is the appropriate place to introduce @wait. SYNTAX: @wait = ={ ; ; ; ... } @Wait allows you to delay an action (or a set of actions) for a certain number of seconds. For example, if you are on a MUSE now, try: @wait 5=:waves! yay! -- Now, watch and see yourself wave five seconds after you press return. As you might guess @wait has a number of wonderful uses within MUSE and has some interesting implications for building. Here are a couple quick examples: ## AWOOGA! EXAMPLE ALERT! (EX 2.3) ## Picture a room: Deli(#4vR) You find yourself standing in the corner deli, where Market and Main streets meet. Outside, the noisy hustle and bustle of the city pass by, muted by the large glass windows enclosing this family business. Near the counter, several people stand patiently in line, awaiting their turn with the clerk. Scattered about the deli are a few tables, a few of which are occupied by the clientele. (etc. etc.) Contents: Falryx Obvious Exits: Out Now, with a good imagination, you can piece together the life of the deli - almost seeing a young teenaged-clerk (or, older: since I didn't specify, it's up to you) taking orders from people on their lunch break. Maybe one or two people are reading papers, or impatient to be served. I could include all this in the description or I could use an @adesc (or even an @aenter, which is triggered after you ENTER an object (like a room) -- or even an @asucc (if you consult the table from earlier in section II you'll see why)). @aenter here=@wait 5=@remit me=Nearby, an older man puffs meaningfully on his cigarette, his eyes devouring the newspaper before him.;@wait 15=@remit me=A young man in line glances nervously at his watch, offering some encouragement to the teenaged clerk: "Hey! I don't have all day here, you know?!" ... and so on. Now, when someone enters the room, they'll have a few more messages sent to them (notice the use of @remit), to make it seem more alive. After you learn a little more about programming, you'll probably want to change those @remits to @pemits, but that can wait a little until you are ready. ## END OF EXAMPLE ## ... and the other example ... ## AWOOGA! EXAMPLE ALERT! (EX 2.4) ## What if we had an object that we wanted to make seem more alive -- have it react to the world around it a little. One way would be via @adesc, or @afail, etc. Let's imagine the elephant we made in the earlier example. Remember how you locked it so only you could pick it up. Well, if we do: @afail elephant=@wait 7=:trumpets loudly at the attempt to pick it up! Then the elephant will respond (albeit, a bit late) to the failed attempt to take it. Similarly, @asucc, @adesc, etc. could all be used to make the elephant seem like it was more than just a static object. ## END OF EXAMPLE ## II.C Programming on MUSE One of the really nifty things about MUSE (and many MUDs) is the ability to program objects and rooms to do certain things. In this way, you can make things that you build come alive, or simulate complex actions and devices. In short, programming a MUSE allows you to create an environment which does what you want. MUSE's programming language is not like BASIC, Pascal, or C. So if you don't know any of these languages, you don't need to worry. In fact, MUSE's programming language is fairly simple to understand and once you get the hang of it, only time stands between you and highly competent programming in MUSE. I'm not a Computer Science major (nor was I ever), so I only _think_ I'm being accurate when I say that the programming language in MUSE is a script language - like Hypercard is a script language for the Macintosh. Let's get into the thick of things and cover the basics: First, let me remind you of 'attributes'. Each object has 26 attributes built in for your use. These attributes are called: VA, VB, VC, ..., VZ. You can store information, or programming code, or whatever you like, in these attributes -- they act as storage spaces for whatever you want to put there. In MUSE, when you begin to program, these attributes are easiest to learn and use (there are others you can define for yourself, but I'll hit that in section III). Attributes are easily set: (NOTE!: In general, using VA-VZ to code objects can be very messy and difficult to read. I've included it here, because these things ARE a part of MUSE. It's probably better to use @defattr [talked about in detail later] or use a new command which allows you (at least - on MicroMUSE) to give meaningful names to attributes: SYNTAX: @_ = i.e. @_monday me=@desc me=On Mondays, Falryx wears... @_tuesday me=@desc me=On Tuesdays... Once defined, you can change the values of these attributes by simply doing: SYNTAX: @ = i.e. @monday me=@desc me=On Mondays.. @tuesday me=etc. If this is a little confusing -- bear with me, it IS described in more detail later on, and VA-VZ *do* work, it just is a little difficult to decipher, and can make the learning process a little more of a pain in the neck.) SYNTAX: @va = @vb = @vc = . . . @vz = Well, you can set attributes now. There are several ways to look at the contents of an attribute. One was is via 'examine'. If you recall you can: SYNTAX: examine / i.e. ex me/va Another way to look at what is in the attribute is via the v() or get() functions. These two, very important, functions are ones that you will use almost constantly throughout your career on a MUSE so let's get you familiar with them now. In many cases, v() and get() are the exact same thing, that is, they are different ways of accomplishing the same ends. Like all functions, they must be surrounded by []'s to use them and they can't be entered into the command line directly. One way to test a function is to 'say [function],' but then people see you emitting random numbers, phrases and error messages. Some places might have a special command for testing functions, or you can always do: @pemit [name(me)]=[function()] Name() is another function (as you might have guessed from the parentheses), whose purpose seems fairly obvious. It returns the name of the object you specify. In my case, name(me) is 'Falryx'. There will be a lot more on functions in section III. This little introduction is meant to get you used to dealing with them for basic programming purposes only. Back to v() and get(). Their syntax is: SYNTAX: [v(attribute)] i.e. [v(va)] ... [v(vb] ... [v(vz)] V() allows you to retrieve the contents of an attribute on yourself. Try setting an attribute on yourself then 'say [v(attribute)]' and you'll see what happens. An interesting thing about v() is that it can be abbreviated to: %. In other words, %va and [v(va)] are the exact same thing. Which of these two options you use is generally a matter of programming style, since they are completely equivalent. Any more, with the changes occuring to MUSE, a new syntax has come into being: %/attribute/. (i.e. %/va/, or %/monday/). This format is required for user-defined attributes [yes, talked about in detail later] that make programming a little easier to understand. shkoo suggests this method as a 'preferred method'. SYNTAX: [get(object/attribute)] i.e. [get(elephant/va)] [get(me/va)] [get(#1234/va)] .. etc. Get() allows you to retrieve the contents of an attribute from the object you specify. If the object specified is 'me', then get() functions exactly as v() does. Essentially get() acts as a configurable version of v(). Like v(), you should test this on an object of yours just to get a feel for it. Also like v(), get() has an equivalent notation using %. It is: SYNTAX: [get(object/attribute)] or %/object/attribute Now we know how to set attributes and look and see what is in them. Let's move on to some more programming and see what uses all this stuff can be put to. Recently, a new syntax for get() has come into being, which is more in accord with some real life programming languages. Instead of using the get(.../...) format, you can use: get(...,...). The difference may seem miniscule, but it allows you to accomplish some things with get() previously not possible. A preferred syntax, therefore is: SYNTAX: [get(object,attribute)] i.e. [get(elephant,va)] [get(me,va)] [get(v(va),vb)] NOTE: This can't be done with '/' unless you use the s() function, described much later. Basically, this new format allows you to use variable names more easily in the get() function. This makes get()'s ease of use skyrocket, and simplifies some major coding tasks significantly. This new format is probably the 'endorsed' method - and is certainly your best bet. Generally, the contents of attributes can be triggered with the @trigger command. This command tells the MUSE to read the contents of the attribute specified and run it as if it was typed in by a player. SYNTAX: @trigger (@tr) / i.e. @tr me/va The @trigger command tells the MUSE to take the contents of an attribute and run it. Since attributes contain commands that you, yourself, could use at the command line (like @emit, say, pose, etc.), the MUSE can easily read these and execute them. For example: ## AWOOGA! EXAMPLE ALERT! (EX 2.5) ## If you like having different descriptions (perhaps to change your clothing, or maybe your character is a chameleon, or whatever) you could store them in attributes and then use @trigger to set them. @describe me=Before you stands a young physics major, looking especially harried. Falryx nods towards you as he notices your gaze and turns back towards his homework, as it appears he has a problem set due tomorrow. Well, it's not every day that I have a problem set due. What about Fridays? @va me=@describe me=Before you stands a young physics major, looking relaxed and ready for the weekend. As it is Friday, he's finished with classes for the week and has a little time to blow off steam before turning back to the scads of work he has waiting for him in his room. Hrm. What about Saturday morning? @vb me=@describe me=Yearning for his innocent childhood, Falryx is dressed in his bathrobe and sweats, seated in front of a large color TV. Though it appears he's doing little more than absorbing the colored images tossed at him, the young physics major is receiving therapeutic cartoon treatment. etc. Now, if I want to change a description all I need to do is @trigger it. l me Before you stands a young physics major, looking especially harried. Falryx nods towards you as he notices your gaze and turns back towards his homework, as it appears he has a problem set due tomorrow. @trigger me/va Triggered. Description set. l me Before you stands a young physics major, looking relaxed and ready for the weekend. As it is Friday, he's finished with classed for the week and has a little time to blow off steam before turning back to the scads of work he has waiting for him in his room. etc. ## END OF EXAMPLE ## II.C.1 $ events In MUSE you can make your own commands and put them on objects or in rooms, etc., for other people to use. Naturally, there is a special syntax needed in order for this to work, and this is where the $ event enters into the picture. $ events are specified in attributes that you program, and basically tell the MUSE that the keyword you specify can trigger the string of commands that you have placed after it. Let's take a look at the syntax: SYNTAX: @va =$ : ; ; ... i.e. @va foo=$foo:say bar! So: foo foo says "bar!" Keep in mind, that the spaces I've included _after_ the equals sign are to facilitate reading, when you program a $ event, don't put those spaces in. As you can see from the construct, you specify that you are making a new command (with the $), name the command, then tell the MUSE what to do when the command is entered (the : acts as a delimiter between the command and the actions. Because of this, no command can contain a ':' in it (to my knowledge)). Keep in mind that $ events aren't limited to just @va -- you can use vb, vc, ... vz. I'm using @va as a simple convention. When a command is triggered the MUSE automatically assigns certain values to some variables. In MUSE some of the most common variables are: %n, %#, %n, %s, %o, %p, %0, %1, %2, ..., %9. Most of these can also be addressed as [v(variable)] (i.e. [v(0)], [v(n)], [v(#)]...), just like attributes can. But, what are all of these? Here's a quick table: Variable Definition %n Name of person who activates the command (activator) %# Dbref of person who activates the command (activator) %s Subject pronoun of activator (he/she/it) %p Possessive pronoun of activator (his/her/its) %o Object pronoun of activator (him/her/it) %0 - %9 Argument specifier Most of these are self explanatory, but let's look at the pronoun variables and the argument specifiers. The pronoun variables use the contents of @sex to determine which variable to use. If you have something bizarre in that attribute that the MUSE doesn't understand (or if it's empty) then the result will be the neuter pronouns (it/its/it). If it can find 'male' or 'female' in the attribute it will use the appropriate pronouns. Commands can be created to allow arguments. If you think of the 'look' command you can give it an argument to look at a specific object. For example, 'look me' - 'look' is the command and 'me' is the argument. Using the quick example from above: @va foo=$foo:say bar! If we do: @va foo=$foo *:say bar!; say You put in the argument [v(0)] (or %0). So: foo blee! foo says "bar!" foo says "You put in the argument blee! (or blee!)." Notice how [v(0)] and %0 mean the same exact thing in this case With simple arguments, they will be the same thing, however, %0 strips out all commas and semicolons from the argument. This means that you can better protect your code and objects from outside interference. Unless you need to preserve commas and semicolons, you should probably use %0. For example: Argument [v(0)] %0 Hi There! Hi There! Hi There! Hi!;p shkoo=boo! Hi!;p shkoo=boo! Hi! p shkoo=boo! If you have code set up a certain way, the semicolon can force your objects to do things you hadn't intended. Problems like these can be avoided with judicious use of %0, and care programming. If an object of yours is behaving strangely, you might try using semicolons and new commands to see if that could be the cause. Arguments don't have to be only a single word either -- it could be a phrase, or a paragraph, or whatever was entered after 'foo'. Notice also that the MUSE starts counting at %0. If we do something like what is below, we can identify the arguments: @vb foo=$blee * for * and *:action1 ; action2 ; ... %0 ---^ ^ ^--- %2 %1 And the commands which follow can address these arguments appropriately. This allows you to construct complex actions and commands. So far, so good, but what is that '*' anyway? The asterix is called a wildcard. If you've used DOS or Unix before, you'll recognize that right away. It basically means 'anything'. So in the above case, %0 represents the asterix between 'blee' and 'for'. Similarly, when the command is triggered, %0 means 'anything that was typed in after blee and before for'. There is another wildcard and that is: '?'. Unlike *, ? can only refer to a single character. In this way, you can limit the length of what is input into your command. Here I'd like to make a small note of the @trigger command. Like $ events, @trigger can be used with arguments/variables. So let's redefine the syntax: SYNTAX: @trigger /={argument1, etc.} i.e. @tr me/va=Falrx,foo,blee,baz In this example we tell the @trigger command to send 'Falryx', 'foo', 'blee', and 'baz' to me/va as the arguments for that set of commands. Each of these arguments is numbered exactly as if they were entered in the command line for a wildcard. A quick table will show what is where: Argument Specifier Falryx %0 foo %1 blee %2 baz %3 So, @trigger can be used to pass arguments from one attribute to another (allowing some modular programming in more advanced stages). Naturally, the best way to get a feel for this is through some examples: ## AWOOGA! EXAMPLE ALERT! (EX 2.6) ## Let's recall our elephant. It'd be great to have some programming to help the elephant come to life. Perhaps a command to feed the elephant? @va Elephant=$feed elephant:pose snakes his trunk out and sniffs at %n's hand.; @wait 3=pose gathers up the food in %n's hand and stuffs it into his mouth, emitting happy elephant noises. Now, if we are in the same room as the elephant, we can do: l elephant This is a large grey elephant. As you watch the great beast, it sways back in forth in a lacadazical rhythm on its ponderous journey to a nearby stream. The elephant's large grey trunk snakes around passing plants grabbing on for a bite or two. feed elephant An Elephant snakes his trunk out and sniffs at Falryx's hand. :smiles. Falryx smiles. An Elephant gathers up the food in Falryx's hand and stuffs it into his mouth, emitting happy elephant noises. Here, we notice a couple things. First, the elephant's full name is used.(remember, we @created An Elephant). It's kind of weird to see 'an Elephant' does this, or 'an Elephant' does that when there is only the one elephant. One way to get around this is by renaming the elephant to 'the Elephant'. But he's not really _the_ elephant either. Woe is us. ## END OF EXAMPLE ## ... and another example using wildcards: ## AWOOGA! EXAMPLE ALERT! (EX 2.7) ## Well, let's add on to our elephant, a bit. Let us say that the elephant is the curious sort who likes to be shown things. So, we program a command to show things to our curious elephant. @vb elephant=$show * to elephant:@emit The elephant cocks his head to the side, curiously twitching an ear, and eyes %n and %p gift cautiously.; @wait 3=@emit The large grey elephant sniffs %0, inspecting it curiously. So now we can: show the peanut to elephant The elephant cocks his head to the side, curiously twitching an ear, and eyes Falryx and his gift cautiously. :grins, "It's safe." Falryx grins, "It's safe." The large grey elephant sniffs the peanut, inspecting it curiously. Notice how using @emits allows use to use the name we choose when referring to the elephant? Rather than having it say 'An Elephant..' and have some wierd capitalization, we can use a construction that seems more natural and is easier to read. ## END OF EXAMPLE ## ... and another using @trigger and wildcards: ## AWOOGA! EXAMPLE ALERT! (EX 2.8) ## Though this example isn't particularly filled with good programming techniques, it shows the use of @trigger with wildcards, which is really more important to us at this stage. [I'll talk with you about good building and programming techniques later.] Let us imaging that our elephant is very bright and like to be taught things. Again, we can write a command so people can teach the elephant various things (later, you could program the elephant to remember what it was taught). @vc elephant=$teach elephant to *:@tr me/vd=[v(n)];@tr me/ve=[v(n)],[v(0)] @vd elephant=@emit You see [v(0)] approach the elephant and gesture wildly, as if teaching it something. @ve elephant=@wait 20=@emit After a small wait, the elephant nods his head and nudges [v(0)] aside.;@wait 25=@emit Surprisingly, the elephant begins to [v(1)]. Notice here in this bit of code we trigger other attributes with the activator's name and the lesson. Vd has a nice message explaining that someone is teaching something to the elephant. In order not to lose the name of the activator, the @trigger sends it to Vd, which then accesses it through %0 (or v(0)). The second trigger activates Ve, giving it the name of the activator and the lesson to be taught. Like Vd, Ve picks up these triggers in numerical order, %0 (or v(0)) referring to the first thing sent ([v(n)]) and %1 referring to the second thing sent ([v(0)] - from @vc). This can be a little confusing, but remember that variables and arguments are reset with each trigger and each command. So what is v(0) for one trigger may not be v(0) for another, unless you specifically construct it to be that way. Notice how we didn't use v(n) in @vd and @ve? This is because @trigger redefines %# and %n. Instead of being the name of the person who entered the command it would change to the name of the person or thing that @triggered the attribute. So you can see that %n in @ve would mean the object, 'An Elephant'. Again, this is because the activator for @ve isn't the user, but the object which does the @trigger. It's easy to get confused by all this, and the best way to understand it is to do a little programming on your own and try things. ## END OF EXAMPLE ## II.C.2 ! events ! events are very similar to $ events. Like $ events, ! events are programmed into the attributes of an object. The difference between these two kinds of events is in how they are triggered. As you recall, $ events are commands, and you must enter a specific command in order to trigger these events and the actions they define. ! events _listen_ for a matched phrase, and when it they hear the given phrase, they trigger their events. Now, we can make objects which respond to the activity around them, almost as if they were alive themselves. SYNTAX: @va =!:{action 1 ; action 2 ; ... } i.e. @va foo=!*blee*:"foo! So: say blee. You say "blee." foo says "foo!" The pattern will be matched exactly. So if you specify a pattern like 'blee' without wildcards, it will ONLY be triggered if 'blee' appears on a single line without anything before or after it (i.e. you'd have to @emit blee). Generally this isn't what you are looking for, so you need wildcards. Just like above, the 'stuff' in the wildcards can be accessed via %0 - %9. With just a little thought, the number of uses which ! events can be put to is astounding. Here's a quick example of a very common usage: ## AWOOGA! EXAMPLE ALERT! (EX 2.9) ## Let us return to our famed elephant. For the sake of this example, let us suppose he is surprised by people entering his home. Well, a simple ! event can make this possible. @vf elephant=!* has arrived.:@emit The elephant blinks in surprise as [v(0)] enters. As you can see, our ability to listen for things, and MUSE's consistency with entrances and exits, allows us to set up objects which can listen for arrival and departure and react to them. Similarly, if we wanted our elephant to trumpet every time someone said the word 'peanut' a ! event could do this perfectly. @vg elephant=!* says "*peanut*":@emit The elephant trumpets at the mention of his favorite food! Now, if someone says the magic word near our elephant they'll be surprised at the outcome! ## END OF EXAMPLE ## As you can see, $ and ! events allow us to customize objects and rooms wonderfully. We can make unique situations that are interesting with the application of a little elbow grease and a healthy dose of imagination. One important thing to keep in mind is the fact that Exits can't have commands or 'listening events' on them. Rather, they _can_, but they will never be triggered. MUSE doesn't check exits for commands or patterns, so storing commands, etc., in them is, at best, futile. Lastly, you can put commands on yourself, which only you may trigger, however you cannot put a ! event on yourself which can be triggered. II.C.3 Other basic programming things While $ and ! events allow us a lot of freedom we are still fairly restricted. So far we only have the ability to @emit (in all the various ways), @trigger, say, pose, etc. Clearly, we need some more ways to accomplish things, and this is where some of the things mentioned in the part come in. II.C.3.a @listen / @ahear These two attributes are worth pointing out. Back in earlier versions of MUSE, ! events didn't exist. All listening had to be done through something called the @listen attribute. If the pattern in @listen was matched, then the commands in @ahear (actions - hear) would be triggered. As you might guess, this is fairly restrictive, and almost completely outdated. A quick translation of the @listen/@ahear pair is: @va =!@listen:@ahear As you can see the @listen corresponds to the pattern to match and the @ahear corresponds to the actions. ! events tend to be a little more intuitive, so generally they are used more often than the @listen/@ahear pair. @Listen can be used, however, to have objects _inside_ an object hear what it hears. So if you had a car, for example, and you wanted to be able to get in the car and still hear what was going on outside, you'd have to make the car: @listen car=* -- this means that _everything_ the car hears is passed on to its contents. NOTE: ! events are incapable of doing this without using @remit, or @pemit. Other than @listen =* there isn't a whole heck of a lot of use for this pair, but here is their syntax anyway: SYNTAX: @listen = @ahear ={ action 1 ; action 2 ; ... } II.C.3.b @switch If you've had some experience with programming languages, you've no doubt encountered conditional statements. These are statements which allow you to 'test' something and take an action according to the results of that test. We do conditional things all the time, one example might be IF phone is busy THEN hang up ELSE talk to Jane. MUSE doesn't have an IF-THEN-ELSE construct. Instead MUSE has a construct called @switch which is similar to C's switch() and Pascal's 'case'. Here's the syntax, SYNTAX: @switch =,{action1;...},,{...},{default actions} You can match a test against any number of results -- your only constraint is the size limit on the attribute itself (1000 characters. In general, however most 'clients' don't like more than 512 characters. In MUSE you shouldn't use more than 900 characters since, according to shkoo, that could cause some problems). Using our telephone example, you might have a @switch like this, @switch [v(va)] =busy,{hang up},no answer,{hang up},{talk to jane} Here we see that if we store the status of the phone in @va, we can check to see what it is. If it's busy, then Jane must be on the phone, so we should hang up. If there isn't an answer, then perhaps Jane is out. If it isn't busy and there is an answer, then Jane must have answered the phone, so we talk to Jane as a default action. ## AWOOGA! EXAMPLE ALERT! (EX 2.10) ## Now we can make another command for feeding the elephant. Let's imagine, however that our elephant really likes peanuts, is allergic to bananas and just doesn't like the way cheese tastes. Any other food is just plain old food. With a @switch we can have a command for feeding the elephant and make him respond appropriately depending on the food given: @vg elephant=$feed * to elephant:@switch [v(0)]=*peanut?,{@emit The elephant gladly eats up all of %n's peanuts!},*banana*,{@emit The elephant sniffs the food and backs away, noting he's allergic to [v(0)].},*cheese*,{@emit The elephant sniffs at the food and shakes his head, he doesn't like the way [v(0)] tastes.},{@emit The elephant eats the [v(0)] offered by %n.} ## END OF EXAMPLE ## Notice the varied responses dependent on the type of food offered? You probably also noticed the ? and the *'s which appear around the words. @Switches, like ! events, match patterns to make sure whatever it is they are testing fits. Because of this you can be as discriminating as you want. For example, I didn't want the elephant eating peanut-flavored bananas (he is, after all, allergic to bananas), so I tested for *peanut?. The * allows me put adjectives in front of the peanuts, and the ? allows me to give him one peanut, or many peanuts. Remember the ? wildcard is only one character, so if I tried to add more to it, it wouldn't match it properly. Like all the things I'm showing you, the best way to get some experience is to play around with the construct yourself. See what you can get it to do, see what it can't do. As a final note, it is possible to 'nest' @switches. Let's use the phone example: @switch [v(va)]=busy,{hang up},{@switch [v(va)]=no answer,{hang up},{@switch [v(va)]=Jane answers,{talk to jane},{ask for jane}}}} When you nest switches, be careful to keep track of your curly brackets: {}'s. Using a wrong number can result in code that acts very strange, indeed. In general, this is a bad example of nested switches, as they are all testing the same exact thing (v(va)), so one @switch should suffice: @switch [v(va)]=busy,{hang up},no answer,{hang up},jane answers,{talk to jane},{ask for jane}. However if you are testing many different things, like the contents of v(va) and then v(vb), you might need to nest @switches. II.C.3.c @foreach Sometimes you want to be able to do a certain action several times. The key to doing this is the @foreach command construct. Like @switch it can be used within attributes (as well as just on the command line) to repeat an action several times, or even to send several pieces of data through a set of commands. The syntax for the @foreach command is: SYNTAX: @foreach ={ action 1 ; action 2 ; ... } i.e. @foreach 1 2 3=say foo! You say "foo!" You say "foo!" You say "foo!" i.e. @foreach foo bar blee=say %0 You say "foo" You say "bar" You say "blee" As you can see, MUSE assigns the various elements of the list to %0. Because of this, you can manipulate a large number of objects easily, or a large list of data can be examined, or whatever you choose. If you want more than one command to be repeated, you must use {}'s to enclose the entire set of commands: i.e. @foreach 1 2 3={say foo!;say %0} There isn't much more to say about @foreach. Later on when you try to create more advanced constructs, it will take diligence to defeat the parser when using @foreach, however that remains to be discussed in a later part of this manual. Try messing around a little with @foreach to see what you can do with it. However, keep in mind that @foreach can 'spam the queue,' which is bad. A quick note: The queue is a 'line' of commands. Each command that an object is forced to do is entered into the queue. The command then waits for its turn to execute. You can imagine that putting a lot of commands on the queue slows down the entire MUSE. In this way, @foreach can be used detrimentally to the whole MUSE. I caution you, therefore, against irresponsible use of the @foreach command. Keep in mind that you can effect people elsewhere by your actions. There is a lot more on the queue in section II.G. ## AWOOGA! EXAMPLE ALERT! (EX 2.11) ## One case where you could use @foreach would be for an automated 'roll-calling' machine. If you were having a meeting, and wanted the machine to tell you everything that was in the room, and say.. how long they were idle, you could make a command and use @foreach to do that. @va me=$rollcall:@foreach lcon(here)=@pemit me=name(%0) Mind you, this will also tell you OBJECTS that are in the room, and it is REALLY bad for the queue. So this is just an example to let you know how to use @foreach. It's best to find other ways to do things if at all possible. ## END OF EXAMPLE ## II.C.3.e @force Well you have objects which can react to $ events and ! events in a variety of ways, but at some point you will want an object to be able to affect another object. @Force provides one method of doing just that. As you might imagine from the name, @force makes an object do something. SYNTAX: @force =action @force ={action 1; action 2; ... } This literally makes the object behave as if it typed in whatever you supply as the action. i.e. @force elephant=:woofs! an Elephant woofs! or @force elephant=@foreach 1 2 3=say foo! an Elephant says "foo!" an Elephant says "foo!" an Elephant says "foo!" etc. Objects can be forced to trigger ! events and $ events now, rather than having to have a command tailor made for every purpose. @Force can be 'parsed' strangely by MUSE, so it may take a couple efforts to get something to work properly. I do my best to explain the parser in Part III. As usual the can be 'me', or the name of an object, its database reference number (dbref) or even 'here'. Experiment a little with the @force command and your objects and see what you can come up with. MUSE prevents you from @forcing other players, or objects that other players own. Similarly, you are protected from other people making your objects do things you don't want them to. Lastly, your own objects CAN @force you, but only if they have the INHERIT (I) flag set on them. The section on flags is coming up soon, so you may want to read a little more about them in a little bit. ## AWOOGA! EXAMPLE ALERT! (EX 2.12) ## Let's say, for arguments sake, you wish to appear as a psychic. You could use your room to trigger irresistable feelings in you whenever someone went inside. Using the rooms @aenter, we can do the following: @aenter MyRoom=@force [owner(me)]="%N has just entered my room! Budda bing! Now, whenever someone enters your room, you suddenly say: You say "Someone has just entered my room! Budda bing!" I'm not certain there's any particular use to doing this, but the option exists for those who wish to use it. In general, @force can provide you ways to make an object do certain things from a distance - or cause an object to affect another object. ## END OF EXAMPLE ## II.D Locks There are several ways to lock things on MUSE, and dependent on the lock and the method you choose, they accomplish different things. I will describe the various natures of locks, then describe the syntax of locks towards the end of the section. Naturally, the most common type of lock is @lock. @Lock on an object or a player restricts who can pick that object (or player) up via the 'take' or 'get' commands. On exits, a @lock restricts who can use the exit. This prevents people from using exits to enter rooms which you consider private, or restricted access. Lastly, a @lock on a room prevents who can 'look' at it successfully -- that is, get the description. This latter use is a little esoteric, and I have never personally used it, but nonetheless it's good to know. SYNTAX: @lock < thing | player | exit | room>=LOCK CODE (more on LOCK CODE at the end of the section). Next, we have @ulock. Quickly translated this is the uselock. If you've used MUSH you'll be familiar with @lock/uselock instead of @ulock, however their function is identical. @Ulock restricts who may trigger $ and ! events on an object, or room. If someone is passed by the lock code, then their actions or commands can trigger ! and $ events. If not, they'll receive the 'Huh?' message (for commands) or receive no response (for ! events). SYNTAX: @ulock =LOCK CODE (Notice, @ulock currently means nothing for players or exits. Exits cannot match commands or ! events, and only players may trigger commands on themselves - other players or objects cannot do so) Moving right along brings us to @elock (enterlock). This lock restricts who may 'enter' an object. Some MUSEs have vehicles or flying animals, or what have you, and in order to take advantage of their transportation abilities you need to 'enter ' (remember this from Part I?). As you might suspect, @elock restricts just who can enter a specific object. For players, @elock restricts either who or what can give or be given to you. In order for other players to be able to 'give' you things (remember that from Part I?) you need to be set ENTER_OK. It is possible to keep players from using that as a way to just 'enter Falryx' and muck around in your inventory (using: @elock me=![pos(P,flags(v(#)))]) Rooms can be @elocked as well, restricting who may enter through ANY exit. This is the exact same as if you @locked all the exits to the room. SYNTAX: @elock =LOCK CODE Lastly, it is possible to lock attributes on a one by one basis. In this way, you can still have an object which anyone can use, but perhaps there are a few key commands that you want to restrict to yourself, or a certain set of users. These locks (attribute locks) are attached to $ events and ! events and act like local versions of @ulock (where @ulock could be considered a global lock). SYNTAX: @va =$:/LOCK CODE/action 1; action 2; ... @va =!:/LOCK CODE/action 1; action 2; ... (Again, not the exits and players are not included for the very same reasons as above for @ulock) Now that we know the different kinds of locks, just what is this 'LOCK CODE' stuff, anyway? Well, locks are generally very simple to understand, once you know the nomenclature. First, let's define the 'tokens' which MUSE uses for locks: Token Meaning | OR & AND ! NOT @ Indirect Lock With these tokens, locks are yours to enjoy. If you imagine how a lock would sound in English: OK, lock this door so either me or my mom can get through it. The @lock would be: @lock exit=me | *mom (When locking to a player, always use '*' before the player's name. Unlike before, this does NOT act as a wildcard. Instead this is MUSE's little signal to itself that it needs to look up the dbref of the player.) If I wanted to make an object which couldn't be moved from its position (like, say, a wall) I'd set the @fail and @ofail messages then I'd do: @lock wall=me&!me Translations: Lock the Wall to me AND NOT me. That means the only person or thing which can pick up the wall is something (or someone) which is BOTH you and NOT you. Now, this can be an interesting philosophical topic if you really want it to be -- but it is enough to say that as far as MUSE concerns, there isn't anything out there which can be BOTH you and NOT you (in other words, nothing can pick it up). If you wanted an object which you wanted to restrict to a certain number of users you could do: @lock foo=me|*joe|*harry|*tina ... or Translation: Lock foo to me, or joe, or harry, or tina... @lock foo=!*fred Translation: Lock foo to anyone who isn't Fred. The first one says who can pick up the object by giving a list of people who are allowed to, the second lock says who can pick up the object by giving the name of someone who ISN'T allowed to pick up the object. Lastly, the @ token inside a lock allows you to specify an object number to copy the lock from. This way, if you have several objects you want locked to the same thing, you can use: @lock foo=@#123 and if they are in the lock for object #123, then they can take foo. ## AWOOGA! EXAMPLE ALERT! ## Let us say, for argument's sake, that I have a large mansion, and I want certain people to be able to walk into various rooms of the mansion. I'd like my butler to be able to get everywhere (me to!), as well as the maid. The garderner should have access to some places, and the cooks to others. One way I could do this is by personally locking every door to the right combination. Another way would be to create a few 'generic' locks for places. So: @lock foo=me|*maid|*butler @lock blee=me|*maid|*butler|*gardener @lock ook=me|*maid|*butler|*cook Now, on the exits I want to lock, I can simply do: @lock exit=@foo for any places I want to restrict access to. I might @lock kitchen=@ook, because I don't want the gardener bringing dirty tools into the kitchen. Indirect locks can be handy ways to lock multiple objects with a single command and reference. Later on, if I want to add a friend to the locks, I simply have to add her to the locks for 'blee', 'foo' and 'ook', and not every exit in the mansion. ## END OF EXAMPLE ## Locks may seem a little tricky at first, so take them slowly if you need and play with them little by little. They are extremely helpful in keeping track of object you own and provide you with some security. In time the lock syntax will become second nature so don't worry about rushing it. II.E Flags FLAGS. I mentioned these earlier on, and was about to blissfully exclude them completely from the manual, but I recognized my error. Flags are a list of possible 'settings' that an object can have. If the object is set 'on' for a certain flag, then it has that flag. If it is set off, then it doesn't. There are several (over 30) flags on MUSE, and rather than explaining each one, I'd like to point you towards 'help flags'. The information in the helpfiles should be sufficient enough to satisfy any curiosities. Flags appear after an object's name and dbref when you look at it, or see it in the contents of a room or person. Just like you can always see the dbref of objects which you own, you always see the flags of an object which you own. Flags generally allow the object to be affected by other people in various ways, or enable your objects to behave in specific ways. How they can be affected or what they can do is dictated by the flag that you use. Here's a list of the more common flags with a brief description of what the flag does: Flag Name What's it do? C Chown_ok This flag allows people to @chown (change ownership) an object from another person. People cannot randomly @chown objects you own, so this flag can enable ANYONE to do so. (for more information on Chown, check out the helpfiles) D Dark When set on a room, the contents and exits aren't listed. When set on an object or exit, it isn't listed in a 'look'. When set on a player, @whereis cannot locate them (for more information on @whereis, consult the helpfiles). E Exit This object is an exit - this flag is NOT setable. G Going The object has been @destroyed H Haven When set on an object or room or exit, any commands or ! events or @adescs, @asuccs, etc. will not work. Haven can act like an on/off switch. When set on a player, it turns off pages (i.e. the character may not be paged). I Inherit The object inherits whatever powers you have [mentioned later] and may @force you. J Jump_ok Any person may @tel to a room set Jump_ok. L Link_ok Any person may @link an exit to a room set Link_ok. N No_Walls @announcements are filtered out. P Player The object is a player (note: this flag NOT setable) R Room The object is a room (note: this flag NOT setable) c connected This flag applies to players only and means that the player is currently connected to the MUSE d destroy_ok Any player may @destroy an object with this set. e enter_ok Any player who matches the @elock may enter this object. h hidden The player cannot be found on the WHO list. To set, do: @hide, to reset do: @unhide o opaque If set on an object or a player, when you look at that object or player you cannot see what is inside of it. When set on an exit, you can see through it to the next room. p puppet The object is set 'puppet' [more on PUPPET later] v visible Any player may examine the object, receiving complete information about that object. For a more complete list, consult the helpfiles. A few sample cases: Foo(#123Iev) Falryx(#36747PIeDNc) etc. Flags which may be set by players (there are some flags which only the MUSE can set, and some which only the administration of the MUSE may set) can be set and reset in the following manner, SYNTAX: @set =flag i.e. @set me=visible @set =!flag i.e. @set me=!dark Here, the ! signifies 'NOT'. People familiar with higher-level programming languages may recognize the construct != (or, not equal). MUSE lacks this particular construct, but uses the same convention for @locks and flags. Generally the name of the flag is enough to hint at the purpose of the flag. A completely flag list appears in the appendices with a list ofall the commands available in standard MUSE 1.5. II.F Creating a puppet What's a puppet? In MUSE a puppet is a little bit different from your typical cloth contraption which can be made to dance around, introduce John Denver or heckle other puppets (hats off, by the way, to the Muppets! Yay!).On MUSE a puppet is an object which you own and relays everything it sees or hears to you, it's owner. In MUSE, just about anything can be @set PUPPET (p) (rooms, objects, players), however objects typically act as puppets. When an object is @set PUPPET and something is seen by it you see: Puppet> Falryx waves to the puppet. This is how you can tell what your output is coming from, and which puppet (that's right, you can have several puppets!). The name which appears before the ">" is the name of the puppet which is sending information to you. Puppets are often used for a variety of purposes on various MUSE's, but they serve very well as an introduction into programming via MUSE's language. Rather than having an 'example' section or building off of our elephant, let's start afresh. First, we need to decide on a design. Since puppets can move around, I'm going to make mine a cherry-headed conure. You could either use my example, or better yet, make your own: @create Admiral Bird @describe bird=This small parrot is a member of the cherry-headed conure family. The perky green bird is about a ten inches long from head to the end of his tailfeathers with bright red coloration on his 'shoulders' (the joints of his wings). Two black eyes, like little pieces of obsidian peak out from a mask of red feathers which anoints the head of this small fellow. Although he is small, his beak seems powerful enough to make short work of even thick branches of wood. @sex bird=male @succ bird=You whistle to the Admiral and he flutters happily over to your shoulder. @osucc bird=whistles a few notes to the Admiral, who flutters happily over to %p shoulder. @ofail bird=whistles a few notes to the Admiral, who obligingly ignores %p. @fail bird=You whistle to the Admiral but he appears to ignore you. @lock bird=me @drop bird=You place your hand before the Admiral who steps up, pausing momentarily before launching into the air with a chirrup. @odrop bird=places %p hand before Admiral Bird who uses the proffered hand as a launch pad, bursting into the air with a chirrup. @adesc bird=@pemit %#=The conure cocks his head to one side to look back at you. Now that we have the bird created, making him into a puppet is easy: @set bird=puppet Tada! We now have our own puppet! You may recall, that in order to get him to do things we need to @force him. Now, it is possible to remember the dbref number of the puppet and manually @force it whenever you want, however this is tedious and inconvenient and is better done via an $ event on some object you own, or even on yourself. In order to control the Admiral, I want to have a $command written on me, so I do the following: @va me=$ado *:@force #XXXX=%0 [ where XXXX is the dbref of the puppet ] What's all this mean? Well, remember that @va is the syntax used to set one of the twenty-six main attribute of an object (VA-VZ), 'me' is you (or me), and the stuff after the equals sign is what is put inside 'VA'. Looking at the right hand side of this statement we have: $ado *:@force #XXXX=%0. Recall from the earlier section that $ events are commands which we can type in like 'look', 'examine', etc. The stuff after the $ and before the colon (:) is the command, in this case it's "ado *" which means the key phrase 'ado' followed by a space followed by anything (you might picture 'look' behaving like: $look *: ). Remember the section on *'s and argument specifiers we are careful to note that whatever is typed in after 'ado ' will be put into the %0 slot (or [v(0)]) so we can use it in the actions which appear after the colon. We can easily take this paragraph and make a diagram: argument object | | | @va me=$ado *:@force #XXXX=%0 | | \_____________/ | | | | command action attribute OK, so what does that action do? Well, we remember that @force makes objects do things, that #xxxx refers to an object by its database reference number, and that the stuff after an '=' in a @force statement is the stuff the object is forced to do. In this case, %0 refers to 'anything typed after "ado "'. Taken apart, that's: @force #XXXX=%0 | | | | object | command argument specifier Now I can make him pose, say, @emit, or whatever I want just by doing: ado :chirrups! ado look ado "hello there! ado go east etc. Yay! Now we can make our puppet do things. Try dropping it and playing around with it a little. Notice, you can make it do everything you can do! Essentially you have an extension of yourself which you can use for whatever purpose you may desire. On occasion, however, puppets can be very loud -- that is, you may not want to hear what they hear. Cutting off what a puppet hears is very easy, all you have to do is reset the PUPPET flag. So you could manually @set admiral bird=!puppet or @set #XXXX=!puppet and then @set it 'PUPPET' when you want it back on. Again, however, this means you have to memorize the database reference number for the puppet and this can be tiresome, so let's code an on/off switch: @vb me=$aon:@set #XXXX=puppet;@pemit name(me)=Admiral Bird is switched on! @vc me=$aoff:@set #XXXX=!puppet;@pemit name(me)=Admiral Bird is switched off! Now we can turn on and off our puppet just by doing: aon Flag set. Admiral Bird is switched on! aoff Flag reset. Admiral Bird is switched off! aon Flag set. Admiral Bird is switched on! etc. Now you have a puppet and now you should recognize what each part of the code involving the puppet does. If you have questions about any of this feel free to ask me (if you see me around on the MUSE you are on) or try the helpfiles and the officials of the MUSE they should be able to clear up any questions you might have. II.G The Queue As you get used to programming, and used to a MUSE that you play on, you will become familiar with this 'entity' known as the queue which sometimes gets 'hosed' or 'spammed' or 'thrashed' or what have you. Typically when people refer to the queue, they refer to its abuse. The queue is a marvelous thing. Basically, every command that you enter, or than an object does, or what have you is 'queued'. This means that it gets in line behind some other commands, and in front of yet others and waits for its turn to get executed. Basically, the queue allows the MUSE to organize and moderate the execution of commands so that the machine the MUSE is running on doesn't go completely haywire having to do about a bazillion things at once. Whenever you use the @wait command, it goes into its own little queue, where it waits until its time to be executed. At that time, it moves from the top of the 'wait' queue to the bottom of the 'Immediate' queue. (Basically, it waits in line to wait in line). Certain commands 'hit' the queue more than once. For example, if you do: @pemit Joe=Blee!, that hits the queue just once. If you do: @foreach 1 2 3 4 5=@pemit Joe=blee, that hits the queue SIX times: one for the @foreach, and one time each for the elements of the list. Another good example is the '@switch' command. If you do: @switch blee=foo,{},blee,{@switch me=you,{},me,{@pemit Joe=Blee!}} Then this will hit the queue 3 times. One each for the @switches, and one for the @pemit. Knowing how many times something will be in the queue will help you learn how to create efficient code that will run quickly, and not slow down everyone else. As you can imagine, if you did a REALLY big @foreach command, it would put a lot of stuff in the queue, and whatever anyone else put in would have to wait for all your commands to finish first. Lastly, understanding how many times something is in the queue will enable you to conquer the parser (see section III.E) with more ease. Take some time out to check out the queue and see how it works. You can see what commands _YOU_ have in the queue if you use the command @ps. SYNTAX: @ps This command will show you what commands you have waiting for execution with @waits, and what commands are in the immediate queue. Some sample @ps output might look something like this (notice: I've obtained these as a cut-down list from the @ps on MicroMUSE. I have the ability to see EVERYTHING in the queue, but since you can only see things YOU own, you would see something short like this (instead of the PAGES I have to wade through)). Immediate commands: Que(#9032I):@set me=_Thrust:[extract(v(2),2,1)] Que(#9032I):@wait sync(1)={@fore %[get(me/NotMatched)]=@tri me/%%%%0} @waited commands: Que(#9032I):5:@fore [get(me/NotMatched)]=@tri me/%%0 Cleaning Robot(#43592oIq):13::finishes cleaning the room, dries everything off, and dust wipes the whole room. And then moves onto the next room.;@tr me/va shkoo(#100PDoqc):30882:@tr #32440/va As you can see, the commands waiting for immediate attention are listed first, giving the name, dbref of the object, and the commands it wants to do. The @waited command lists the name, dbref, and the time it is going to wait (in these caes, 5 seconds, 13 seconds and 30,882 seconds) until it does the listed commands. Don't worry about all those extra %'s before things: I'll try and explain them in the parser section. II.H Good Building and Programming You now have all the tools you need to start your career of building and creating objects of interest. In fact with your own ingenuity and the helpfiles, you could even skip the rest of my manual and learn on your own how to become an excellent MUSE programmer. I'll take this time and pat my own back as evidence that this is possible -- I began to MUSE in August of 1991 without a single idea about programming. It's now December 1992 and I'm writing a manual. No... I'm not Einstein, MUSE is just something where a little time and dedication is rewarded by an increase in your own knowledge and abilities, and teaching yourself to accomplish complex tasks via MUSE coding can be very rewarding. As long as I'm up on my soap box, I want to talk to you about good programming and building. I mentioned earlier that MUSE has a 'quota' system where the number of objects that you can own is restricted. This number can be changed, so as you build more things, it's possible that the administration of a MUSE will increase your quota so you can build even more! One day you may even have infinite quota. Each object, exit, player, or room which is created takes up space in the database of the MUSE. The database is a large text file (kind of like this manual) which is formatted a special way so the MUSE program can read it ALL into memory when the program is run. Since all the database is loaded in at one time, MUSEs can be threatened by something known as 'db bloat'. This basically means that the database is growing at a rate to such an extent that the effects could be disastrous. One of the best ways to do your part to avoid damaging the MUSE and the database is to be conscious of the number of objects you own. Don't hold on to objects which don't do anything or you don't use. In other words, don't @create a 'button' to have a specific message and just carry it around. This is a waste of one of your quota, and a waste of space. Good building and programming is geared towards making the maximum effect with a minimum impact on the MUSE, this brings us to the first principle of good building: PRINCIPLE ONE: Don't create 'atmosphere' objects whose only purpose is to 'sit there looking like a useless object'. Make sure each object that you create has a specific purpose, or is interesting in and of itself - that is, make sure it is a contribution and not a parasite of the resources. For example, don't @create a Table to sit in a room if that is all it will do -- put the table in the @description of the room -- people will see it, and it will save you quota and save the MUSE space. PRINCIPLE TWO: Make your objects and rooms interesting. Spend time with your creations to make them special. There are hundreds of 'bedrooms' on any one MUSE. Why not take the time to make yours a little different? Interesting objects and rooms might have commands coded on them to give them a little life. PRINCIPLE THREE: Build Well. This means: @describe exits, make sure they have @odrop and @osuccs (and maybe @succs) set on them. Build your rooms so that if you go 'east' to get to a room, going 'west' will take you back where you started from. Basically, try and use some common sense. You have the ability to @create and build things which can be very unique and special. If people are exploring or using something that you've made and they see 'You see nothing special.' on an exit... Take the extra effort to make your work worthy of praise. You will no doubt be pleased with the results, and appreciative comments from your peers online. I'll talk a little more about Good Building and Programming at the end of Part III (the section on Advanced Programming). Try taking some time out from the manual and work on some objects and rooms. Once you feel comfortable with everything I've introduced up until this point, move on into Part III and hold on to your hat... Part III: Advanced Programming Alrighty folks, the gloves are off. I'm assuming that you've either read or are already familiar with the basic programming ideas I've put forth in part II (this implies that you also know how to get around in a MUSE, @describe yourself, etc.). I'm going to make an effort to assume a certain level of competence with the basics to avoid getting bogged down in explaining details. As a side note: if you find that a little more detail could be useful in any section of this part, let me know and I'll be happy to address any constructive criticism or comments (and maybe even add some more to the manual). This Part will cover some of the intermediate to advanced level ideas in MUSE programming. It may all seem pretty basic, and that is good. Essentially, the very simple ideas I'm about to present to you can be worked together to create objects of great complexity. III.A Functions Functions are your friends. MUSE has scads and scads of functions (and with something you'll learn about later on, you'll realize that scads and scads can be easily translated into 'a nearly infinite number'). This can be daunting at first, but don't let it be. To get a list of all the functions on a MUSE just do: help functions. Typically you might see something like: --------------------------- Standard Functions ----------------------------- sub() fsub() lor() bor() cos() arccos() exp() base() truth() lt() mul() fmul() lxor() bxor() tan() arctan() ln() mod() if() pi() tms() div() fdiv() lnot() bnot() pow() fsqrt() sqrt() simp() ifelse() tml() first() remove() strcat() extract() dist2d() subj() ljust() v() rest() pos() string() match() dist3d() objn() rjust() s() next() scomp() strlen() wmatch() string() poss() cjust() spc() delete() comp() wcount() plural() lnum() flip() rtime() art() fcomp() time() type() name() parents() zone() con() quota() xtime() class() lwho() children() inzone() exit() quota_left() stime() owner() idle() lattr() loc() lcon() entrances() objmem() flags() onfor() lattrdef() room() lexit() credits() playmem() nearby() host() flags() link() objlist() controls() zwho() linkup() change() haspow() hasflag() Note: Some of these functions may not be installed on standard versions of MUSE 1.5 ------------------------------------------------------------------------------ Some of these you might recognize from earlier on (name(), v(), get(), ...) and you should probably be moderately familiar with these. Others will be fairly obvious in what they do (add(), sub(), mul(), div(), ...). If I were to sit down now and explain what each and every function did, I'd likely have several pages of uninteresting drivel -- that is to say, even more uninteresting than this manual already is! So, instead, I'm going to talk about what functions are, how to test what they do, and how to use them -- I'll leave figuring out specific functions to yourself and the helpfiles which are provided in MUSE. Functions are routines which you call with arguments. These routines take the arguments you give and manipulate them somehow (add(), for example, adds them together) and then returns the result of that manipulation. One important implication for MUSE is the fact that functions are evaluated immediately, so they don't have to go onto the queue like @force, @foreach, or @switch. Judicious use of functions can, in fact, increase the speed ofcomplex programming by as much as 100-200 per cent. To see what a specific function does, look at the 'help' entry on it and read it carefully (note, on MUSE you must type: help add function, not help add(). The latter doesn't work). The helpfiles will tell you what the function takes as arguments as well as specifying what kind of results you'll get. Once you know this, you can test functions by using any command which goes through the parser [more on that later], i.e. say, pose, @emit, @pemit, etc. I prefer to use the '@echo' command: @echo [function()] Now I can do: @echo [name(me)] and it'll send me the results. So now we can do: @echo [add(5,1)] @echo [mul(10,2)] etc. Notice, that functions, unlike commands, cannot be entered directly into the command line - they must be sent to the parser by a command in order for them to be properly evaluated. This leaves us at the last portion of functions, how to use them. I use functions extensively in my work to create 'switchless code'. Remember our phone example of way back when? @switch v(va)=busy,{hang up},no answer,{hang up},answer,{@switch v(vb)=Jane is home,{talk to Jane; hang up},Jane isn't home,{leave a message; hang up}} Well if we were REALLY only interested in the case where Jane was at home, we could easily rewrite the @switch to: @switch land(lnot(scomp(v(va),answer)),lnot(scomp(v(vb),Jane is home)))=1,{talk to Jane; hang up},{Jane isn't home, or it's busy, or there's no answer, so just hang up} Where land(x,y) = 1 if x and y are both true 'LOGICAL AND' = 0 if either x or y is false lnot(x) = 1 if x is false 'LOGICAL NOT' = 0 if x is true scomp(x,y) = 0 if x is the same as y 'STRING COMPARISON' = 1 if x is greater than y = -1 if x is less than y Now, instead of touching the queue _twice_ the switch touches the queue only once, effectively doubling the speed of the @switch. (Nitpickers are allowed to argue this point, but it serves my purpose as an example). Your ability to master switchless code will enable you to create objects which work efficiently WITH the MUSE. There is no substitute for nice switchless programming. It is more fun and FAST to use, and users appreciate this. It is also less of a drag on the entire MUSE, and administrators appreciate this. As you can see, functions can return various different values. The math functions return the appropriate answer, where other function will return lists, or just a 0 or a 1. By knowing what a function will return you can use functions within you commands to tailor outcomes to very specific cases. Often, functions need to be surrounded by square brackets ([]) in order to be evaluated, and just to confuse you, often times these brackets aren't necessarily needed. MUSE's parser will not accept something like: [name([num(Falryx)])], because it hates having []'s inside another set of []'s. The proper way to write this would be: [name(num(Falryx))]. Functions are the key to coding complex objects which work efficiently and don't drain the resources of the MUSE too much (by avoiding throwing lots of commands on the queue). As with most things related to MUSE programming, the best way to get a feel for functions is to take the time to find out what each one does and experiment a little with it. For a sample use of some of the easier functions we have the first example of this Part. ## AWOOGA! EXAMPLE ALERT! (EX 3.1) ## @create Calculator (@desc, @succ, @osucc, @drop, @odrop, @fail, @ofail, @lock, etc. yourself). @va calc=$do * + *:@pemit %#=[v(0)] plus [v(1)] = [add(v(0),v(1))] @vb calc=$do * - *:@pemit %#=[v(0)] minus [v(1)] = [sub(v(0),v(1))] @vc calc=$do * x *:@pemit %#=[v(0)] times [v(1)] = [mul(v(0),v(1))] @vd calc=$do * / *:@pemit %#=[v(0)] divided by [v(1)] = [div(v(0),v(1))] Tadah. Here you have the basic arithmetic operations. With a little effort you could make this calculator into a Hewlitt-Packard reverse polish notation calculator with all the bells and whistles. ## END OF EXAMPLE ## I've said it before, I'll say it again. Take some time out to play around with functions a little and see what you can make them do. For your convenience here's a couple tips on troubleshooting problems with functions: * In order to see how the parser is evaluating functions you have written into commands set the object they are in to 'DARK' and 'PUPPET'. The output can help you debug what's happening. You may also set an object 'DEBUG' and 'PUPPET' for the same results. * Check the number of ('s and )'s.. make sure they are equal. * Make sure your []'s don't have other []'s inside them or have %0, %n, %#, etc. Functions don't like those. I'll discuss one particular function, [s()], in great detail in the section on the parser. Unless you are ready for some advanced toying and potential frustration, I suggest you stay away from this function for a little bit until you are comfortable with functions. III.B User-Defined Options If you are familiar with MUSH programming things like u() and '&' may be very familiar to you. However if not, it's no big deal. For a long time, the twenty-six main attributes were all that were open for MUSE programmers to utilize for their tasks, both simple and complex. Fortunately, user-defined attributes and user-defined functions have created a wonderful variety of options available to all MUSE programmers great and small. Essentially, user-defined options allow you to create new attributes and assign them certain characteristics based upon what you want them to do. Many of the characteristics are related to parenting, which will be introduced in the next section. As any user who has done a little programming on MUSE knows, keeping track of 'va', 'vb', etc. can be tedious and sometimes result in disastrous mistakes. Now, however, we can create our own attributes and name them whatever we want: 'foo', 'bar', 'feed_command' or whatever. To do this you simply need only use the following syntax. SYNTAX: @defattr / = { options } or, you can use the shortcut method I indicated earlier: SYNTAX: @_ = This automatically creates a new attribute with the 'inherit' option (which probably should be standard, unless you specifically don't want an attribute to be inherited). Also, this method sets the attribute straight away, rather than having to do the two-step method of @deffatr object/attribute=inherit, then @attribute object=text. If you don't specify any options with '@defattr' it will just add another attribute onto the object without any special characteristics. Some examples are: @defattr me/puppet_control @defattr me/change_desc etc. The options available are: dark, date, function, inherit, lock, osee, unsaved and wizard, and they function as follows: dark - An attribute set 'dark' will not be displayed when the object is examined. This is true even if the object should be set 'visible'. Dark attributes may not be @triggered nor can their contents be utilized in a 'get()' function. date - A 'date' attribute acts like the 'last' field. If a number in the style of xtime() is stored in it, then anyone examining the object will see a date and time, the exact date and time shown depending on the timezone of the person examining the object. function - A 'function' attribute acts as a user-defined function which is discussed in detail below. inherit - An attribute set 'inherit' will be inherited by any children of the object (note: This refers to parenting). In this way, new attributes can be kept on parents, or passed down to children as the owner desires. lock - An attribute with the 'lock' option set is treated as a lock for the purposes of 'examine'; all dbrefs are expanded to show names, and the value must conform to lock syntax. THERE IS CURRENTLY NO MEANING TO A USER-DEFINED LOCK ATTRIBUTE, except as a place to store values that can be copied into built-in locks. osee - An attribute set 'osee' is always accessible to other players via 'examine' or 'get()'. unsaved - An attribute which is set 'unsaved' will not be saved in the database of the MUSE and will disappear when the MUSE is rebooted. wizard - An attribute set 'wizard' cannot be change via @edit, nor can the attribute be changed on any children of this object (should the attribute also be set inherit). As a more advanced programmer, you should realize the abilities of user- defined attributes to create custom made objects which can then act as parents to other objects (again, this is discussed very soon). At the very least, you no longer have to rely on VA-VZ for your attributes and your code can make sense, since you can: get(me/CREW_LIST) instead of having to do: get(me/VA). You can also do: %/crew_list/ (like you can %/va/). Or %/object/crew_list. User-defined attributes generally behave as other attributes do (va-vz), and any deviation from normal behavior is due to their settings with the options you specify. It is possible to change the options of an attribute which you have defined at any time, all you need do is: @defattr / = new options. In order to reset an attribute to act completely normal, just do @defattr / and things will be set. For example, @defattr elephant/feed_command=wizard inherit dark function Attribute defined. @defattr elephant/feed_command=wizard Options set. @defattr elephant/feed_command Options set. At times, you may wish to remove an attribute from an object. This is easily done with @undefattr. SYNTAX: @undefattr / Keep in mind that 'dark' or 'wizard' attributes must first be reset before you can @undefattr them. These options specifically are designed to prevent tampering with the attributes. General Note: The standard attributes of an object (odrop, osucc, va-vz, akill, etc.) are all BY DEFAULT set 'inherit'. The status of these attributes cannot be changed, nor can you @undefattr any of these attributes. It is sometimes possible to @defattr _OVER_ these attributes with very undesirable results. You should stay away from using any standard terms or nomenclature in your @defattr and @undefattr commands. User-defined functions can be a special thing. By now, you should be fairly familiar with functions and how they can streamline code. User-defined functions allow you to create your own functions (using the ones already provided by MUSE) so you can tailor your output to fit your desires. A simple example is something which returns a specific word from a list, or '0' if the word isn't in the list. User-defined functions, like user-defined attributes, have a shortcut definition available. Rather than using @defattr, you can use: SYNTAX: @()_ = This replaces the two step process below: @defattr object/grab=function Attribute defined. @grab object=[extract(get(me,list),wmatch(get(me,list),v(0)),1)] Set. With: @()_grab object=[extract(get(me,list),wmatch(get(me,list),v(0)),1)] Things are done in one simple command. Now, all we need to do is: @defattr object/list Attribute defined. @list object=Foo Bar Baz Blee Set. @va object=$show *:@emit [grab(v(0))] Set. show Foo Foo show Blee Blee show Ackph 0 etc. This particular example is not particularly impressive, but it illustrates the point. Now, if you use large constructs of functions (like the extract() or land(land(land(lor(...etc.) you can place the construct into one user-defined function and just call that one function repeatedly. This is much simpler than retyping functions which can be 80+ characters long. User-defined functions must be placed on the object using them, or on a zone. There is more on zones in a little bit. As a last note, an object can have up to ninety-one (91) user-defined attributes defined upon it. This may be any combination of functions or attributes. Objects can INHERIT more than this via parenting (i.e. three parents with 91 attributes set 'inherit' means the object has 273... etc.). ## AWOOGA! EXAMPLE ALERT (EX 3.2) ## (Thanks to Camac of PernMUSH for this function, which he originally taught me on MUSH and which I have changed over to MUSE. Without his guidance I would have taken a great deal of time to discover the power of User-Defined Functions). To whet your whistle with the power of user-defined functions, here's a slightly more complex arrangement. This object takes six numbers and sorts them in order from highest to lowest: @create sorter (@desc it, etc.) @defattr sorter/swap=function @swap sorter=[s(ifelse(gt(v(0),v(1)),{[v(0)] [v(1)]},{[v(1)] [v(0)]}))] Set. /* This function takes two numbers and decides: if the first number is greater, do nothing, if the second number is greater, reverse them. */ @defattr sorter/list Attribute defined. @list Sorter=18 25 0 12 4 435 Set. @defattr sorter/grab Attribute defined. @grab sorter=[extract(v(list),v(0),1)] Set. /*This is just to make the sort code cleaner */ @va Sorter=$sort:@emit The list is: [v(LIST)].;@list me=[swap(first(v(list)), grab(2))] [swap(grab(3),grab(4))] [swap(grab(5),grab(6))];EMIT;@list me=[first(v(list))] [swap(grab(2),grab(3))] [swap(grab(4),grab(5))] [grab(6)]; EMIT;@list me=[swap(first(v(list)),grab(2))] [swap(grab(3),grab(4))] [swap(grab(5),grab(6))];EMIT;@list me=[first(v(list))] [swap(grab(2),grab(3))] [swap(grab(4),grab(5))] [grab(6)];EMIT;INSERT @edit sorter/va=INSERT,{@list me=[swap(first(v(list)),grab(2))] [swap(grab(3), grab(4))] [swap(grab(5),grab(6))];@emit [v(list)];@list me=[first(v(list))] [swap(grab(2),grab(3))] [swap(grab(4),grab(5))] [grab(6)]} @edit sorter/va=EMIT,{@emit [v(list)]} Now play with different combinations of 6 numbers and see what happens. Cool huh? ## END OF EXAMPLE ## III.C Parenting What is parenting? If I were a computer science major, I might be able to point out how parenting is a necessary part of good object-oriented programming. Of course, if I tried to do that now, I'd confuse myself as well as you. In simple terms, parenting replaces '@clone' and adds on several other nifty things. NOTE: @clone is 'bad'. Don't use it. (why they keep it in the code, is beyond this particular author, especially when I'm asked to tell you not to use it. :) ). @clone is extremely inefficient and wastes a lot of database space. Not only is it inefficient, but with the advent of user-defined attributes and functions, @clone doesn't properly copy objects any more. Since @clone is icky to begin with and is broken on top of that -- why bother ever using it? Just remember: D.U.C.K! (Don't Use Clone!, K?) Parenting is handled primarily through the following two commands: SYNTAX: @addparent = i.e. @addparent me=#16 @add elephant=#123 @add me=elephant This command can be abbreviated to '@add' and adds an object to the list of parents of another object. SYNTAX: @delparent = i.e. @delparent me=#16 @del elephant=#123 @del me=elephant This command removes an object from a parent list, and may be abbreviated to '@del'. In general, you should try to be aware of what exactly a parent does before adding one of your objects to its children. It is possible that parents may have commands written in them to force you to give the owner of the parent money, etc. This is undesirable, of course, and you should be wary of blindly @addparenting to anything offered to you. Make sure you 'examine' an object before parenting to it. An object can have any number of parents, from which it can inherit a variety of attributes (as mentioned above), functions (ditto), etc. One way to get a quick example of how parenting works is to simply do: ## AWOOGA! EXAMPLE ALERT! (EX 3.3) ## @create Parent (@desc, etc. yourself) Remember, that all built-in attributes (like VA-VZ, @osucc, @succ, @desc, etc.) are automatically inherited by an object's children. If there is something which you specifically DON'T want inherited, use @defattr to create a new attribute, and don't set the inherit option. Keep in mind, that with parenting the 'Inherit' flag means nothing - it's all internal to objects, and the flag refers to something completely different. @va parent=$foo:"bar Set. drop parent Dropped. foo parent says "bar" Now do: @create child (@desc, etc.) @addparent child=parent New Parents of Child: Parent(#xxx) foo parent says "bar" child says "bar" @set Parent=haven Flag set. foo child says "bar" etc. ## END OF EXAMPLE ## From that very simple example you can see how parenting works. For people involved in 'vendors' or creating objects for mass production and public use, parenting is a boon. If you make a new version of your object, by updating the code, or adding a command, parenting will automagically send the update to all the children. On the other hand, if you used @clone, you would have to manually find all the objects and change them -- tedious at best. Parenting also allows for cases when you want people to own their own objects and they want to benefit from your ability in programming. For example, you might create a superbly fantastic puppet controller which is all the rage. Obviously, you can't control their objects, so they must own their own controllers. Parenting allows you to make your controller the central 'code' object from which everyone else's controllers picks up the information. With parenting, you can change your parent, and the children will STILL inherit the change, even if you don't own the child. Like most things in MUSE, I lack the eloquence to discuss parenting in a theoretical manner which can 'wow' the audience. Also, there really is no substitute for taking time out to mess with things yourself - this manual is primarily meant to act as an introduction to concepts. /* Note to readers: I'm not particularly happy with how this section turned out... please consider sending me some suggestions. */ III.D Zones Before I dive into a discussion about zones, let me first state that this is another thing which is best explored on your own time. At the very least the topic can be a little confusing. But here I go... a valiant attempt to introduce you to: zones. In Real Life, zones are areas of property or some such which fall under the same rules. You can easily imagine a mall as being on property which is 'commercially zoned,' while your home stands on 'residential zoning'. MUSE can sort of act in the same way with zones -- that is to say you can create areas which have a common set of commands, or ! events. Zones can also be used to identify the location of a person (for example, you could have a 'White House Zone' and if someone's zone() returned that number, you would have a decent idea of their location). Essentially zones are a way to associate a collection of rooms with one another. After this association is done, you are capable of creating $ and ! events which are standard across the zone. One popular usage of zones is in MicroSpace on MicroMUSE. Each starship has its own zone -- this makes sense since the starship can act as a complete entity (and often does) and may have some commands (like: "computer, where is Captain Falryx?") which should be appropriate to the zone. In order to create a zone you need only @create a Zone Object. Once you've done that you have to manually link all the necessary rooms to the zone via the @zlink command: SYNTAX: @zlink = Like @link, this command has an antonym: SYNTAX: @unzlink Only rooms may be @zlinked and @unzlinked. These commands may work for players and objects, but it has no meaning (that is, @zlinking a player will tell you the person is zlinked but it won't actually DO anything). Players, exits and object pick up their zone from the room they are in. In other words: Rooms dictate what zone you are in. Lastly, rooms may be @zlinked ONLY to one zone object. Currently there is not an option available in MUSE 1.5 to have a room with more than one zone (which is too bad). The functions commonly associated with zones are: [zone(object)] - returns the zone of the object specified [inzone(zone object)] - returns a list of all the rooms in the zone specified. Commands and ! events added on to a zone work for each room in that zone. In this way you can develop a certain set of commands which work anywhere within that zone, but not necessarily anywhere else. A typical example is a space ship, or similar place, but zones can be anything you want them to be: you could have an 'outdoors zone', or an 'indoors zone', or whatever you want. Lastly, unlike parents, the flags and @locks on a zone make a difference. It is possible to make a zone so only certain people can enter it (@elock and @lock). Or by using flags (like 'enter_ok') you can restrict entrance completely from OTHER zones. Once you are inside a zone, these restrictions don't apply and only make a difference when you cross from one zone to another. For example, if I wanted to lock my house against unauthorized entry, but still wanted it Jump_Ok, I could set up a zone in my house and then do: @lock house zone=me|*shkoo @elock house zone=me|*shkoo And only shkoo and I could enter my house via @teleport or via any exits into my house. If a zone is set 'HAVEN' then the ! events and $ events will not be activated and the zone will behave just like any other object which has been havened. As a final note about zones, there exists an object called the Universal Zone Object (UZO) on just about every MUSE running version 1.4 or later. This object is the zone for the entire MUSE (which is done via a command only Player #1 can use). The UZO is typically owned by a director and acts as a place where global commands can be added on for the ease of the users. It's also possible to add user-defined functions to the UZO for the use of the entire MUSE (since every room in the MUSE is in Universal Zone). When you @zlink a room, it remains Zlinked to BOTH the UZO and the new zone (I know this contradicts my earlier statement about more than one zone for a room, but the UZO is a special case). Many MUSEs have their universal zone set 'visible' for the users to look at. If you are on MicroMUSE, check out object #20 or try out @echo [zone(#0)], as well for use on any MUSE. (A word of note, the zone of room #0, also acts as the Universal Zone for an entire MUSE). Zones, parenting and functions can all be manipulated together to create a patchwork quilt of complex code. By becoming adept in the use of all these things you are on the path to creating interesting and complex devices and places which will provide challenges for you to overcome. III.E The Parser Unfortunately for me, many people seem to be under the impression that I actually understand the MUSE parser. This is a complete falsehood. In fact, the MUSE parser and myself have constantly waged war against one another and I've managed to overcome its little quirks and tricks to arrive at acceptable outcomes. I'm often told that the parser behaves in a systematic and intelligent way, and while I don't mean to insult the people who CREATED it, I really do doubt this. I tend to view the parser as a living entity whose sole purpose is to give me a hard time. With this dubious introduction to the Parser, welcome to this section of Part III. The parser is, as I see it, a big machine which takes code and runs certain operations on it (like converting functions from [get(me/va)] to the contents of 'VA' ... i.e. evaluating functions). Sometimes you need to run things through the parser several times, sometimes you want the parser not to evaluate something, sometimes you want to kill the parser. Basically -- view the parser as a big pasta machine. You put in your lump of dough (code) and it passes it through. Depending on what kind of pasta and dough you use, a single pass may give you perfect pasta. Sometimes you may need to have it pass through the machine a few times. Sometimes the machine eats your pasta and it comes out with holes and stretchmarks, and you have to fix things. Dealing with the parser is basically done through code on your objects. When you execute a command, you typically want it evaluated immediately, and therefore no knowledge of the workings of the parser is necessary. However, when you begin to code advanced objects, their behavior can be radically changed by how they interact with the parser. Let us take, for example, the classic problem... Some well-meaning, but new, user asks what the syntax of the add() function is. You would like to help her out, so you do: say [add(3,2)] What happens? The parser grabs onto that function and evaluates it. The end result is You say "5" Not surprisingly, this doesn't impart any knowledge on how to use the add function. In effect, you have to 'fool' the parser into letting you say the _function_. You can do this by suspending the evaluation of the function. In order to do that, you simply add a few '\'s to the function: say \[add(3,2)\] Which results in You say "[add(3,2)]" Yay! It worked! But what's with these backslashes anyway? The backslashes provide a method for suspending functions and their evaluation by the parser. Depending on how many passes through the parser you want a function to survive, you can have as few as one backslash, or as many as 32! How does one know how many backslashes you need? Well there is a formula: n # = 2 - 1 Where 'n' represents the number of passes you want it to survive. In our previous example, we wanted the [add()] function to live through one pass, so it took 2 - 1 = 1 backslash. I understand all too well that this can be confusing, and not necessarily intuitive to those of us who aren't well-versed in computer sciences. The best way to learn how to tackle the parser and come out ahead is to get a lot of practice. Perhaps most of you won't be as cynical about it as I am either. Let us take, for another example, the case where you'd like a puppet to be able to say a function without it being evaluated. As we've seen before, a typical puppet command is: $pdo *:@force #12345=%0 Now, let's think this through. If we want the puppet to be able to say a function without it being evaluated, it has to 'survive' the FIRST pass, when the parser evaluates the contents of the command (inside the %0). Then it must survive the SECOND pass, when it executes the command. Falryx(#19707PDeqc):@fo #22166=%0 Then, this becomes evaluated and the puppet's command is placed on the queue: puppet(#22166pD):say \\\[get(me/va)\\\] Then, since this is a pass, any \\ turns into a \, and \[function\] turns into [function], so we get: puppet>> say \[get(me/va)\] Where the first pass has been run. This next pass (the execution) changes \[function\] to [function] and we get: puppet> You say "[get(me/va)] So, we figure that it has to survive two passes. So that takes (2 * 2 ) - 1 backslashes, or three. Try it out and see if it works. Ok, so that works, and we sort of understand what's going on. But let's have another example, shall we? (Thanks to Garet_Jax of BattleTech 3056 for this example) Let us say we have an object that we want to change based upon the day, and we want it to change multiple parts, something like: @adesc object=@switch day=today,{do nothing}, {@foreach va vb vc vd=@%0 object=blee} Well, we know that @foreach uses '%0' as its keyword. Now, if it is going to change, we need to count the passes through the queue: the @switch is one, and the @foreach is another. So, in order to preserve the '%0' we need to have (2 * 2) - 1 = 3 backslashes. So if we do: @adesc object=@switch day=today,{do nothing}, {@foreach va vb vc vd=@\\\%0 object=blee} Naturally 'day' and 'today' are hardly keywords you'll be using, but there isn't the need (in this example) to clutter the example with lengthy [extract()]s. What if, however, we wanted to do something like this: @adesc object=@switch day=today,{do nothing}, {@foreach va vb vc vd=@%0 object=[get(#4444/%0)]} Now, we have a little more complex situation. The very first %0 would still need three backslashes, for all the reasons we mentioned above. But what about the second %0? It is inside the [get()] function, and we know that []'s don't like to have other []'s or %'s in them. Well, here is a trick: * After an equals (=) sign, you don't have to have square brackets ([]). In fact, it will work JUST as well without them. Keep in mind though you can do: =[blee()] [blee()], but not =blee() [blee()] So we could solve it by simply doing: @adesc object=@switch day=today,{do nothing}, {@foreach va vb vc vd=@%0 object=get(#4444/%0)} In some ways, we feel like we are cheating the parser of normal, rational behavior, but you can't hold back when it comes to the parser. If you don't tackle it with all the tricks you know, you are dead meat. ## AWOOGA! EXAMPLE ALERT! (EX 3.4) ## As a last example, I wrote a '@duplicate' command which would simulate @clone. In general, there really isn't a need for this kind of command, although it does occasionally have it's uses. Here's the code for that command with some explanations: First, let's put the appropriate attributes on the UZO. @defattr UZO/duplicate_command @defattr UZO/duplicate_bleef @defattr UZO/duplicate_stage1 @defattr UZO/duplicate_stage2 @defattr UZO/duplicate_stage3 Now, let's code it! @duplicate_command UZO=$@duplicate *=*:@fo %#=duplicate-bleef %[num(%0)]=%1 (This is another 'trick'. Since we can't garauntee that the person put in the number of the object to be duplicated, we force them to use a command that we've hidden and make them send us the number!) @duplicate_bleef UZO=$duplicate-bleef *=*:@switch controls(%#,%0,seeatr)= 0,{@pemit %#=Permission Denied},#-1,{@pemit %#=I don't know what you are talking about},{@create [v(N)]Copy[v(0)];@pemit %#=Duplicating [name(v(0))] as [v(1)](\[num(s([v(N)]Copy[(v(0)]))\]).; @tr me/duplicate_stage1=%0,%1,\[num(s([v(N)]Copy[v(0)]))\],%#} (Ok, here we check and see if the object is visible, or if the person has the power to see the object without it being visible. If not, or if the object wasn't found, then we send them an appropriate error message and stop. Otherwise, we @create an object, which is named uniquely for this duplication (this is important, because we will work on it later, and require some way to identify it, in case someone else is duplicating something at the same time). Here, we see the use of a backslash and the s() function. The s() function forces the evaluation of a function before it might normally expect to evaluate. Essentially, this allows us to put []'s within []'s with wild abandon. Although, as a side note, it is only fair to indicate that if we suspend the evaluation of a function, we can sometimes put another function (i.e. %0 or [add()] or whatever) inside it. In order to let the s() evaluate before the [num()] does, we use a backslash to suspend evaluation for one pass. Basically, this means we are able to successfully grab the number of the object we JUST created, and not have to worry about its name anymore.) @dupicate_stage1 UZO=@pemit %3=Defining attributes...;@foreach lattrdef(v(0)) =@defattr %2/%%0;@wait 1=@tr me/duplicate_stage2=%0,%1,%2,%3 (Here we use a simple @foreach. But you no doubt noticed the %%0. Since we @triggered this attribute with some data, %0 already HAS a value, so we need to make sure the parser understands which %0 we want -- since we want the %0 from the @foreach we ask it to suspend evaluation of the %0 for a pass, allowing the value from the @foreach to override what we sent the attribute in the trigger. The @wait ensures that the @trigger gets in the queue only AFTER the @foreach is finished, so that we do one part at a time, without overlapping needlessly) @duplicate_stage2 UZO=@pemit %3=Copying attributes...;@defattr %2/ZYXXY; @ZYXXY %2=lattr(v(0));@wait 1={@edit %2/ZYXXY={[v(0)].},{};@wait 1= {@foreach get(%2,ZYXXY)=@nset %2=%2.\\\\\\\%0:\\\\\\\[get( s(%0/\\\\\\\%0))];@wait 1=@tr me/duplicate_stage3=%0,%1,%2,%3}} (Here we had the tricky part, which occupied me for quite some time. First, we have to make a fake attribute and dump the names of the copied attributes into it. But since lattr() has the format #object.attribute we need to make sure we get rid of the extra stuff (#object.) and use only the attribute names. So, we use the @wait 1 to make sure the attribute is set before we change the values with a simple @edit. Using the @wait 1, again we insure that the next step will only occur after the @edit is complete. The @foreach sets the attributes appropriately, then another @wait to make sure THAT part is complete and we move on to the final stage of duplication. The @foreach, as you can see, is FILLED with backslashes. Well, let us take a look and see why. For the first set (of seven) we need it to survive a @wait, a @foreach and an @nset. That's three passes or (2 * 2 * 2) - 1 = 7 backslashes. We also want the [get()] to survive that long, so we put 7 backslashes in front of it. [NOTE: There is a quirk with @foreach, and this would not work properly with 7 backslashes before the right bracket ']'. Since I've no clue why this is, I merely point out that it didn't appear to want to work with that in place, yet it worked perfectly as I have presented it.] Now we see the s() function again. Here, we're using it to make sure we have the proper attribute put into the get() function so things get set. Since we want it to make it through three passes and then evaluate we need to make sure it can survive _3_ passes so the s() will evaulate JUST before the get() [i.e. not TOO soon]. That means we need (2 * 2 * 2) - 1 = 7 backslashes as well. Lastly, inside the get() we see the s(%0/..) in this case, the %0 doesn't mean the same %0 as the @foreach, but the one that will identify the object number - remember what we sent as the trigger. This is because we don't have anything trying to suspend the evaluation, so it grabs the first %0 given to it - which was sent from the trigger.) @duplicate_stage3 UZO=@pemit %3=Copying parentage...;@foreach parents(v(0))= @addparent %2=%%0;@undefattr %2/ZYXXY;@wait 1={@name %2=%1;@chown %2=%3; @set %2=!haven;@tel %2=%3;@pemit %3=\[name(%0)\] duplicated.} (This is the last step, and we see the @foreach ...=%%0 again, for the same reasons that we had in stage1. The next job is to get rid of our fake attribute. Lastly, we make sure everything is finished before we rename the object, change the ownership, set it !HAVEN, give it to the person who initiated the @duplicate command, and let them know everything was duplicated.) This is only one small example on how it takes time and patience to overcome the parser in all of its glory. There are still many more examples that could be added to this section, but mostly they'd say the same thing. Count the parsing, and when all else fails, try everything. ## END OF EXAMPLE ## I'm feeling better about the parser, how about you? Things seem to be behaving somewhat rationally. The key to the parser is to sit down and consider how many passes are going to be made. When you know this, you should be able to conquer the parser without too much of a hassle. In learning how to overcome the difficulties of the parser, you will be enabling yourself to create objects which can accomplish some nifty stuff. III.F Good Programming for the Advanced Student Something like 'good programming' is pretty subjective. I have my own ideas one what makes up good programming and I'm certain there are some influential people out on the Net who would disagree with me in some cases and agree in others. In general, however, I think the couple points which I'm about to bring up warrant consideration and can be attributed to good work. * When referring to attributes in your code, capitalize them:[get(me/LIST)] or [v(CREW)] etc. This makes your code a little more readable. * Capitalize user-defined functions: [FOO(v(0),v(1)]. This will let other people who read your code know that the function is one that you created for your own usage. * Try to avoid nested @switches. Often there may not be away around a @foreach or a @switch, but the fewer times you access the queue in your code, the faster it will be, and the less impact it will make on the MUSE as awhole. Often this goal is called switchless programming. It's hard for me to adequately state how important it can be to make code which has as little impact as possible on the operation of the entire MUSE. Whenever possible, replace @switches like: @switch test=pattern1,{@pemit %#=Blee},{@pemit %#=foo} With: @pemit %#=[ifelse(test,Blee,Foo)] And, as I said, avoid nested @switches - try to merge the tests into one large one with the use of the logical functions. * Remember that you aren't the only person who will read your code. Try to make it readable to other people so they can understand it, or so weeks down the line YOU can decipher it. In my experience the goal should be efficient, easy-to-use and easy-to- understand programming. Again these are my personal opinions and you have every right to ignore my advice. III.G The End Well that's the end of my work on part III. By now, you should be familiar with the ideas of MUSE programming and building at more advanced levels and essentially capable of tackling any problem set before you. All that stands between you and 'expert' status is a little time and practice. Part IV Administration and Other Details In this part I'll talk about some of the more administrative details of MUSE. The official commands, classes, and powers. The average user should be familiar with classes and powers even though they may never have the ability to affect these. IV.A Classes MUSE was constructed to give a hierarchical structure to the administration. In this way, various users and people could hold responsibility in the government of the MUSE, unlike traditional systems which have only 'Wizbits'. Some MUSEs use the class system to imitate a rank-based society (like the military), others use it purely as a form of administration. Classes are completely configurable in a MUSE so each one may have differentcriterion and responsibilities associated with different classes. I should emphasize that in general, the purpose of any MUSE is to enjoy yourself, either through learning or role-playing, or simulation, or whatever. At times people can come to the conclusion that this is synonymous with gaining 'rank' and privileges by advancing through a class structure. It is my humble, up-on-a-soapbox opinion that this serves only to detract from the enjoyment of the game. If you want to work to provide a service to the MUSE, then advancing in classes may be one way to do this - hoping for a higher class just so you can be better than all the rest, however, is petty. OK, enough of THAT lecture. The standard class structure of MUSE is: Director, Administrator, Corporation, Official, Guide, Citizen, Visitor. The responsibilities assigned to each of these various classes is dependent upon the MUSE you are on. Some MUSEs will create new classes, others will get rid of unused ones. In general, someone who has a class greater than 'Citizen' has some sort of official responsibility on the MUSE and can be someone you can turn to for aid. If you spot a visitor in the WHO list, you should consider giving them a hand, etc. Remember, classes are a tool, not a way of life. IV.B Powers To provide a companion to classes, MUSE has a power structure which can be modified and designed as appropriate for any specific MUSE's needs. In this way, people can share responsibilities and have the means to carry out these responsibilities, and yet not have to be full-blown wizards. The variety of powers have a variety of different purposes (for example, there's a power that allows you to 'spoof' people, there's another power which gives you infinite money, etc.). All powers can be set at one of four levels: 'No' (effectively removing the power from the person who had it), 'YesLT' (Yes, lower than. This means it can be used on classes LOWER than the person so empowered), 'YesEQ' (Yes, equal. This means it can be used on classes equal to and lower than the person so empowered) and 'Yes' which means it can be used on anyone. Some powers (like 'Money', 'Noquota', etc.) don't make sense as 'YesEQ' or 'YesLT' and are typically set to 'Yes'. After all, it doesn't make sense to have infinite money for people only lower than you class - money isn't something which is dictated by class. Below is a list of all the powers available on MUSE with brief descriptions of what it is they do. Remember, like classes, powers are tools for the administration of the MUSE and should not occupy to large a part of your time. Don't worry about _getting_ powers. Being a responsible and productive user often takes care of this for you. --------------------------------- Power List ------------------------------- Ability to do a @dbtop (Dbtop) Ability to @announce for free (Announce) Ability to @boot players off the game (Boot) Ability to @broadcast a message (Broadcast) Ability to change ownership of an object (Chown) for equal and lower classes Ability to re@classify somebody (Class) for lower classes Ability to use @dbck and other database utilities (Database) Ability to see people's homes and locations (Examine) Ability to build, etc. for free (currently unused) (Free) Ability to see classes and hidden players on the WHO list (Who) Ability to see hostnames on the WHO list (Hostnames) Ability to 'join' players (Join) Ability to change your name and password (Member) Ability to modify other people's objects (Modify) for equal and lower classes Power to have INFINITE money (Money) Ability to use the @newpassword command (Newpassword) for lower classes Power to not be killed (currently unused) (Noslay) Power to have INFINITE quota (Noquota) Power to @nuke other characters (Nuke) for lower classes Power to create new characters (Pcreate) Power to see everyone's commands in the queue (Queue) (Currently unused) (Quota) Ability to see attributes on other people's things (Seeatr) for equal and lower classes Ability to alter people's powers (Setpow) for lower classes Ability to @shutdown the game (Shutdown) Ability to 'summon' other players (Summon) Ability to set the SLAVE flag. (Slave) for lower classes Ability to use the 'slay' command (Slay) Ability to do unlimited @emit etc. (Spoof) Ability to @stat other ppl (Stats) Ability to give negative amounts of Marks (Steal) Ability to use unlimited @tel (Teleport) Ability to set Last, Queue, etc. (WizAttributes) Ability to set Temple, etc. (WizFlags) Ability to do remote whisper, @pemit, etc. (Remote) Ability to do various security-related things (Security) Ability to see numbers on all objects (Backstage) Ability to get correct results from all functions (Functions) Ability to change people's quotas (Setquota) ------------------------------------------------------------------------------ IV.C Official Commands Naturally, MUSE has some specific commands which only officials of the MUSE can use. Below is a list of the helpscreens which display all these commands accompanied by my own observations and comments. join summon slay @boot @broadcast @class @newpassword @pcreate @poor @ps @shutdown @dbtop @nuke @wipeout @allquota @empower @giveto @huhto @powers @chownall @dump @dbck @pbreak @ulink @doomsday @mailhuh* @purge* @check* @ctrace* @misc* Join - This automatically teleports you to the location of the player you specify. If you have this power - USE IT WITH CAUTION. You should always ask a player before you join them, as they could be engaged in private conversation, or idle, or whatever. Needless to say it is _extremely_ rude to join without asking first. Summon - This automatically teleports the person you specify to _your_ location. Like join, you should make absolutely certain sure that someone is ready to be summoned before doing so. Having someone join you in the middle of a private conversation is annoying, having someone teleport you OUT of that conversation without your consent is twenty times worse. Slay - This kills plays - essentially sending them home. There is not particularly day-to-day use for this, other than to be annoying, which I _strongly_ advise against being. Annoying officials wind up as annoying demoted officials usually. @Boot - This kicks a player off the MUSE, immediately disconnecting them. @Booting without a valid reason is plain stupid - generally there is no reason to use this command except for special behavior cases. @Pcreate - This command creates a player with the specified name and password. No special warnings from this camper. @Dbtop - This command displays some statistics of database usage. I don't recommend doing this often as it can chew up some major CPU time on the MUSE and really slow things down. shkoo says that @dbtop memory is the worse kind and that other methods aren't as bad. @Empower - This command gives powers to another person. Be careful whom you empower with what. If you make sure that the people you empower are responsible enough to use what you give them wisely, instances of power abuse will be few and far between. @chownall - This command @chowns all of one player's objects to another. Needless to say, BE VERY CAREFUL with this one. The last thing people want is all their objects 'accidentally' chowned to someone else. @ulink - This is a God-Only command and it sets the UZO. @broadcast - This is kind of like @announce, except that it can break through a 'No_Walls' flag. Use this sparingly as people typically don't want to hear random ramblings via an official broadcast. System messages of Importance should be sent via @broadcast, not lunch suggestions. @class - This command changes a player's class. Like Empower, make sure you are sure that the people whom you are classing are capable of fulfilling their duties to the MUSE responsibly. This will save you much hardship. @newpassword - This command changes a player's password and notifies the player that it has been changed by you. Ordinarily this should be done only in _extreme_ discipline cases or at the request of the user. Be very careful with this one. @poor - This command resets the credits of all players to the specified number. Like several other official commands this can have drastic implications so try to avoid 'testing it to see if it'd work' and that kind of nonsense. @ps - This gives you a list of all the actions which are on the queue (both ones that are yours and all others which belong to other players). @shutdown - This command saves the database and terminates the game. Normally @shutdowns are used for code updates, etc. This command really shouldn't be used too often. Also, don't @shutdown without warning players. Give them 5 or 10 minutes to finish up their work, or conversations, and log off before you force them off. Normally you should use @reboot to bring up new server code, or the like, using @shutdown only in emergencies of if some other major work needs to be done. @nuke - This command destroys a character, removing him/her/it from the database. The character must not own any objects in order for this command to work. Like @newpass this should generally only be used at a player's request or in extreme discipline cases. @wipeout - This command destroys all of a player's objects, or all of a certain type (i.e. exits). Careful careful careful! Don't use this lightly! @allquota - Like @poor, this sets the quota of every player on the MUSE to the specified number. Also like @poor, this can have important ramifications, so use this command sparingly. @giveto - This command Quietly gives of credits to without generating the usual messages associated with the regular 'give' command. @huhto - his command may only be issued by a Director. It initiates or terminates the automatic logging of failed commands attempted by players in rooms owned by . The log is periodically mailed to the specified E- Mail-Address. The use of HuhLogs enables a Builder to improve the choice of exit-names and trigger verbs in the Builder's realm to better respond to commands most frequently attempted by visitors. NOTE: This command not fully functional in MUSE 1.5. @powers - This command lists the powers of the player you specify. @dump - Execution of this command causes the database to back itself up to disk (called checkpointing). Normally dumps occur at regular intervals and this command need only be used on special occasions. @dbck - This command lists all the disconnected rooms (ones that aren't linked to the database) and recalculates the 'free list'. The free list is the list of all @destroyed objects, available for re@creation. @pbreak - This gives a break down of the different player classes, showing the demographics of the MUSE - generally quite fascinating. @doomsday - The @doomsday attribute determines when an object will be destroyed. The @doomsday attribute is set by @destroy, @undestroy, @protect, and @unprotect. In general, it is a time in xtime() format, specifying the system time before which an object should not be destroyed. Objects with the GOING flag set will be destroyed during the first @dbck after the time given. If @doomsday is set to -1, the object is protected. If an object winds up with a @doomsday value but no GOING flag, it cannot be destroyed and must be @unprotected first. Only Administrators may set the doomsday attribute directly. @check - this should be used on an object if you've got database corruption. @ctrace - buggy. shows concentrator trace, if you have concentrators enabled. @misc - miscelaneous command. shkoo says: i just use this when i want to write something in c instead of in muse, and it's a one time thing @purge - like @dbck, but just makes GOING & @doomsday'd objects go away if it's time. @mailhuh - emails out the @huhto logs. buggy. * - commands with an asterix near them didn't have information in the helpfiles of MicroMUSE and information supplied on them came from shkoo. IV.D Responsibility If you've gotten to the point where you are a member of the administration of a MUSE, there are certain matters which you should be aware of. I recommend Amberyl's section on 'Being a Wizard' in her MUSH Manual, it is informative and many of the ideas contained therein are sound. As an administrator you should remember your place. Yes, it's true, you have more power than other users, and you can do all sorts of neat things (including @booting people at random, or whatever). NEVER use your position or powers to further your own ends on a MUSE. As an official you are effectively a public servant to the users of the MUSE. You are _entrusted_ with power and responsibility and you should act accordingly at all times. MUSEs MAY be games, but running a MUSE is no game: it takes dedication, maturity, and responsibility. IV.E The End This marks the end of the official MUSE Manual. Thanks for suffering though my writing style and keeping with the manual. I hope that you have found it as informative to read as I have found it to write. Remember, that at all times, I welcome constructive criticism, comments and suggestions (as well as praise) to the email address specified in the beginning of the manual. If you have progressed through time with the help of this manual from a new user to an administrator, let me know - it is always rewarding to find that I am able to help out other folks. Best of luck to you. Enjoying MU*ing. See you on the net. Falryx Part V: Appendices V.A Glossary Below are a list of words with short definitions which you may find helpful in your use of MUSE. ! event - ! events match what they hear and when a given pattern matches the one given by the ! event, actions are taken by the object on which the ! event resides. $ event - $ events are essentially new commands or verbs. $ events match what is typed in (as opposed to what is heard) and if matched properly execute commands as dictated by the object the $ event is on. Action - Used in the manual to refer to 'commands' which an object would do after an event was triggered. Attribute - Attributes are registers, attached to MUSE objects, in which you can store data or commands. There are built-in attributes, such as 'succ', 'osucc', 'fail', 'ofail', etc. These can be set on any muse object. The @defattr command can be used to define additional attributes on particular objects. Character - These are the people who are wandering about the MUSE with you. People like 'Falryx' and 'shkoo' are characters. Child - An object which has a parent (and therefore has inherited any number of attributes, commands, ! events and functions from the parent). Class - Classes are ways to separate the users of the MUSE from the officials who oversee the smooth running of the MUSE. In general someone with a class of 'Director' is a head honcho. Database Reference Number (dbref) - The number appearing after the names of objects. Each number is unique to that object and allows MUSE to properly store thousands of different objects, even with the same names. This number can almost always be used in place of the name of an object. Exit - An 'object' in MUSE which allows you to move from one room to another. Flag - Everything in the universe of MicroMUSE (Rooms, Exits, Objects, Players, etc....) are represented in the same way at the program level. A room merely has the room flags set and a player has the player flags set. In addition, flags also give objects abilities or qualities. Function - Functions are routines which can be quickly evaluated by MUSE to return values based upon their function. (i.e. the 'add()' function will add two numbers together and return the new value) Lock - A lock is an attribute that determines who may take, use, enter, or otherwise control an object. Parent - A parent is an object which has children and which has been madespecifically for the purpose of acting as a 'central reference point' for its children. Player - The person in control of a character. 'Falryx' is a Character. 'John Doe' is a Player. At times this distinction is blurred within MUSE. (for example the 'Player' flag is set on characters, not the players. :)) Power - A special permission to be able to use commands or do specific actions which might not otherwise be allowed (i.e. spoofing). Puppet - An object with the 'PUPPET (p)' flag set. Puppets transmit what they hear to their owners, acting as 'ears from afar'. Room - An object with the 'Room' flag set. Rooms can represent any number of various locations - out of doors, in a cave, your bed room etc. In MUSE, rooms are the backbone of the structure. Thing - Any object which is not a player, an exit or a room is a thing. Things include tables, zone objects, pet dragons, etc. User-Defined Attribute - An attribute which has been defined by a user to have a certain name. User-defined attributes may also have various options set upon them which modify their behavior and utility. User-Defined Function - A functions created by a user. UDFs may be used only by the object they are defined upon. If they are on a zone object and set inherit, they may be used in any room in at zone. Zone - An object which acts as a reference point for a collection of rooms, unifying them into a greater whole. Zones may have functions, ! events and commands which are common to all of the rooms in the zone. --- The rest of part V is currently unwritten and in progress. With luck it will be finished soon. Any contributions to the appendices of this manual would be appreciated. Appendices should be relevant to MUSE and can be something akin to: Changing from MOO to MUSE Changing from LPMud to MUSE A Guide to MicroMUSE A Guide to TrekMUSE etc. Official Appendices will be listed in the beginning of the manual. An official copy of the manual can be obtained from 'michael.ai.mit.edu' at all times. Manuals obtained from other sites may be out of date or contain information which has not be proofread by the author of the manual. Because of this, manuals obtained from other sites should not be considered 'Official' copies of the MUSE manual. In turn, appendices listed in the beginning of the manual have been thoroughly read by the author and approved for circulation with the manual as a possible aid to MUSE. I reserve the right to circulate Appendices as I see fit: either as a part of the manual, or as a separate entity which exists in its own file, that is, not a member of MUSEman archive.