[Tutorials Copyright 2002 Jekteir]
MUCK:
Tutorials: building, actions, mpi, lsedit Building
To start off your bulding, you should think about where you are. If you are in, say, Chaos, or Recreations, at the time, you will not be able to build, as the parent is set so that you can't. However, if you are in anywhere in the OOC MUCK Area (go to the portal and then go through the [O]OC exit) or in FreeForm (Portal then [F]ree[F]orm), you can start building!
So, to start building, just use the command '@dig', with a room name. E.g.: '@dig My Bedroom'. This will create a room, named 'My Bedroom', owned by you. The MUCK will automatically set the 'parent' of the room to the OOC Environment Room, or to the parent of the room you are standing in when you build it. The MUCK will also tell you the room number of the room you have just built (Tip: To see the numbers and names of everything you own, use '@own').
Now, you can jump to your room, using 'j [room number you were told it had]'. If you are not sure what the number is, but you don't want to use @own, you can use '@find My bedroom', or '@find [room-name]'. (Tip: If the numbers do not appear next to the names when you use @find or @own, type: '@set me=!S'. This will show you the number of things you own when you see them.)
Now that you are in your room, you can start to set it up. You may want to start by setting the room so that when you log onto the MUCK, you wake up there. This is done by linking yourself to the room. Use: '@link me=here'. (Note: Once you have linked yourself there, you can use 'gohome' to send you straight to your room.)
Now, you will probably want to start describing your room (setting what you will see when you enter it, or when you type 'look' or 'look here'). To do this, use '@desc here=[description]'. (Tip: To put those ====== lines above and below the description of the room like it is in Staff-built areas, use '@hd [description]'. Use '+help @hd' for details.)
So, you have jumped to your room, given your room a description, and linked yourself there. You may well want to set up a couple of handy extras to finish off your fine job. You might for instance want to allow others to set their homes to your room as well. To allow them to link themselves there, you must use '@set here=A'. The reason you don't have to set it 'abode' (the 'A' flag) to link yourself there is because you own it. You may also want to set the room so only you can jump to it. To do this, use '@set here=!J'. [Advice: read 'help flags' to learn more about using @set.]
Now, your first room is pretty much done! The next part is creating more, and then setting up exits between them. To create another room, use the same method. Now that you have got your second room, and are standing in it, you can create exits between them.
To create an exit from one room you own to another, you use @open, followed by the exit name, followed by a semicolon ( ; ) then the letters needed to type to go through the exit, then = , then the room number that you are creating the exit to. So, if I were creating an exit from one of my rooms to My Bedroom, which was #1234, I might use: @open [M]y Bedroom;m=#1234
As long as the letter(s) in brackets in the exit name ( [M]y Bedroom ) correspond to the letter(s) after the semicolon, then the exit is easy to use. For example, using the exit just mentioned, you would only have to type 'm' to go through the exit. Note: It is a good idea to have only one letter in the brackets, because it means exits are quicker to type in, and it is also good practice to make sure the exits aren't the same as system actions (like [L]eafy Road would mean that anyone typing in 'l' for 'look' would move to the road instead).
Now, you can go through the exit, and create an exit from the other side, leading back (E.g: @open [Fr]ont Hall;fr=#9273). [Tip: You can use the program @door to create double exits in one go, but it can be hard to use, and it is recommended that you stick to the method just taught. However, you may see '+help @door' for more information.] (Note: Creating exits: Creating an exit is called linking to a room.)
How to get out of your rooms and back into the rest of the MUCK: You can use 'ooc' to send you back to the OOC area, and from there you can use 'ic' to go to the portal. However, you may well want to get permission to create an exit from your home to a room elsewhere, so that you do not have to go through this. There are two ways of doing this: 1): Go to the Residential Area from OOC; 2): Rent an apartment in an IC area.
Actions
To create an action, you use '@action [action]=[where it is used from]'. In your own rooms, you can attach an action to the room itself, e.g: '@action [name]=here'. However, when you are creating an action you can use wherever you go, you will want to link it to yourself: '@action [name]=me'.
Now your action will need to be linked to a program. An action should be linked to $nothing [If you wish to, use 'exp' for an explanation]. If it isn't, you will get a 'You can't go that way' if you try to use the action. To link the action to $nothing, use '@link [name]=$nothing'.
So, if you try using your action, so will see that although there is no error message, nothing happens! This is the fun part. First off, you will want to get an acknowledgement that something has happened when you use your action. For this, we use a 'success' message. To set this, use '@succ [action-name]=[message]'. An example would be: '@succ belch=You belch loudly, and glancing around you, apologise profusely.' So now, if you try using your action, you will get the message sent back to you.
However, at this stage, using your action will only tell you something - others will be blissfully unaware that you have 'done' anything at all. To set what they see, we use the 'osuccess' message. This is the success message that others see, and hence 'osucc'. So, for example, '@osucc grin=grins merrily'. Note how your name is omitted from before the message. This is because the action program will automatically put your name in front, so what others will see will actually be: '[your-name] grins merrily'.
MPI
[Note: This tutorial does not include information on lsedit, or lists. See the lsedit tutorial about this.] MPI rocks: It's a better programming language than MUF, although it has less power. You can be a lot more detailed with it, and in truth, anything you can do 'for real' in MUF, like make an object or room with a command, you can simulate with MPI, in your own environment. Just as the MUF-made objects on this game aren't real outside of this game, the MPI objects and rooms etc. are 'real' within any MPI environment you choose to make. Don't worry if you don't get it: this doesn't matter, I'm just rambling. Go on to learn the easiest and coolest MUCK stuff there is.
First thing: MPI commands be used in all the major aspects of the game which you can make. You can put MPI commands in descriptions, and action or exit @succs (and osuccs, drops, fails etc). They will not, however, work in 'say' messages, or action messages. If you don't know how to make actions or build and describe rooms, it would be a good idea to go see those tutorials before continuing, as MPI can only be used within rooms or actions. To try out most of the commands in this tutorial, you will be able to use the '@mpi' command, but there will be points where you will need to make and @succ an action, or even @dig and @hd a room.
To test a command here, use '@mpi [whatever]'. Try out '@mpi {name:me}'. This returns the name of the user. So, if you @succ'ed an action to, 'Hi there, {name:me}!', and then used it, it would return, 'Hi there, [user's name]!'. It won't return the name of the owner of the action. It returns the name of the user, or viewer for a description.
Similar commands to {name:me} are {ref:me}, and {loc:me}. To get help on MPI commands, you can use 'mpi category' for a list of all commands, or 'mpi [name]' for help on one specific command. This allows you to explore new commands when you wish to do something further than this course teaches.
Mathematics commands. Pretty simple. Try out {add:1,5}, or {div:20,4}, or {mult:2,3}, or {subt:10,7} to get the idea. Note the order in {div} and {subt}: it makes a difference which around they go for those. 20 divided by 4 is 5, but 4 divided by 20 is 0.2 . Also note: MPI mathematics does not work with decimal points, only with whole numbers.
The next step is a big one. It will take you some time to grasp if you're new to this, so bear with me, because it just so happens to be the best thing about MPI - the thing which allows you to do the most. Props. Props are little files with names, organised into categories, which have a 'value' given to them. These props are 'stored' on objects (rooms, players, things, actions/exits, programs [that's MUF ones]). What this means is that a prop can be accessed by referring to its name, and what object it is 'stored' on. You can also view the props on a object. Okay, time for examples.
Props contain all the special information which you set by using programs. Your description, sex, species, pinfo and all other things like that are stored on these. The props can be changed, removed, and stored by MPI. 1): You can change and view props on yourself and things you own without writing programs. They've already been done for you. To see what props currently exist on an object, use 'ex [name]=/', e.g. 'ex me=/'. Note: other information is given by using 'ex [name]'. Ex is short for examine; see 'help examine' for more. You will note when you try 'ex me=/' that a prop called 'sex' has a value which is your sex, etc. 2): To set a prop, use the '@set' command. You also use this to set flags on yourself. See help flags and help @set for information on them. All you need to know here is that you can set props by using '@set [name]=[prop name]:[value]'. So, to change your sex prop, you'd use '@set me=sex:[whatever]', e.g. '@set me=sex:Male'.
One other thing about props. They work in directories, defined by / slashes. This makes viewing and separating props easier. E.g. you could use '@set me=testprops/test1:This is test 1.' and '@set me=testprops/test2:This is the second test.', and when you use 'ex me=/' you would see, as one of the props, 'dir /testprops/:(no value)'. This means: a): 'testprops' is a directory, hence 'dir'; b): it has no value itself, only values contained inside the directory. To see the props and their values inside the directory, you need to use 'ex me=testprops/'. These layers of props can continue as deep as you like, e.g. there's a prop I use for the OOC channel command, which is, '~/channels/off/ooc', and whose value is 'yes' if you've turned off the OOC channel.
Now the MPI of props. To set a prop on an object, the object either has to be owned by the owner of the program (action, with the MPI in the @succ message of the action), or owned by the user of the program. These are the 'permissions' required to allow you to set props. We won't worry about these during the tutorial: when you go out and try MPI, you'll get a feel for what you can and cannot do. Simple action. Setting a prop, viewing it, removing it. Make an action on yourself, link it to $nothing, and then @succ it like so: '@succ [name]={null:{store:{&arg},temprop,me}}You've stored the prop.{nl}The prop's value is {prop:temprop,me}.{nl}{delprop:temprop,me}You've removed the prop.' That's it. Try it out. When using the action, use '[action_name] [intended_prop_value]', e.g. 'propaction This is a testprop!'. Continue for the explanation.
This is how your action works. Use '@succ [actionname]' to view the MPI, if you want to check up on what it looks like while I explain. First off, {&arg} is simple. That's whatever you typed in after the command name of the action when you used it. So with '[actioname] This is the prop.', 'This is the prop.' would be the {&arg}. Now, the {store} command takes the {&arg}, and 'stores' it on a prop called 'temprop', on you. The {null} bit around the store command is needed because without it, the {&arg} you were storing would be shown to you as you used the action. Feel free to try removing it etc. to see what it would look like. Experiment. {null:{store:{&arg},temprop,me}} is the same as '@set me=temprop:[whatever you typed in]'. See mpi store for more, and mpi &arg. Then the action tells the user, 'You've stored the prop'. The {nl} is simple - it means 'new line', which means that the next piece of text will be shown to you on the next line.
So, on the next line, you're told 'The prop's value is {prop:temprop,me}.' The {prop} command is pretty simple too. It goes, {prop:[propname],[object where it's stored]}. So, it calls up the value of the prop temprop, which you just stored, and shows it to you. New line. {delprop:temprop,me}. You can probably already guess what this means. It's the same as '@set me=temprop:'. It removes the prop from you. Then the action tells you, still on the new line, 'You've removed the prop.' Simple, eh? The reason you don't need {null} around the {delprop} is that it never gives a value when it's used, and the reason you don't need one around {prop} is because it's already telling you something. I'm not going to talk very much about {null} from here on, either: you'll get a feel for that too. You should get the idea, roughly, what it means now. See 'mpi null' for more, but don't get confused.
Okay, so, with {&arg} and {store} and {prop}, you can actually do quite a lot now. There's 2 other major aspects of MPI to discuss. One is the absolutely most crucial part of MPI, and the other is nearly as useful. These arer {if} and {tell}. First, {if}. Once you understand this, I'll be able to show you some great programs to work on and adapt, and learn from. {if} checks whether a statement is true or not. If it is, it does one thing. If it isn't, it does something else. It works like this: {if:{[statement to check]},[do this if true],[do this if false]}. For a very simple test, you can try '@mpi {if:{eq:1,2},1 and 2 are equal.,1 and 2 are not equal.}'. The {eq:1,2} part is the statement to be checked. It means, are 1 and 2 numerically equal? And they aren't. Since they aren't equal, the bit after the second comma, [do this if false], is shown to you, and you see '1 and 2 are not equal'. Remember, @mpi is just a way of checking out MPI strings without out writing an action to stick it in, but it won't work when you want the MPI to use {&arg}. Just remember that. Let's see what other 'checking' statements there are, and exactly how they work.
In the last example, you saw '{eq:1,2}'. This is the checking statement, and it means, 'see if these are equal'. It can compare numbers, or 'strings'. 'Strings' mean bits of text. A string is 'Hello there!', as is 'This is a string which has number 1 in it'. If you were comparing strings, you might try '{eq:{&arg},yes}'. This checks whether the 'argument' you put in, that is, what you typed after the action name, is 'yes'. Other 'checking functions' apart from {eq} are: {ne}, 'is the first thing not the same as the second?', {gt}, 'is the first thing greater than the second?', {lt}, 'is the first thing less than the second?', {ge}, 'is the first thing greater than or equal to the second?', {le}, 'is the first thing less than or equal to the second?'. If any of these are true, then the [do this if true] bit is run. Note: The things to be compared are separated by a comma, as are the [do this if true] and [do this if false] bits of the {if} function.
Now, what's actually happening? It's simple. The checking part sees if a statement, like {gt:3,1} is true. If it is true, the checking statement tells the 'if' function that it is true. The if function then 'evaluates' (runs the MPI in) the part of the if function which is after comma after the checking part, and before the next comma. This explains why commas are soo important. They sort out which part of the function is which. So, {if:{eq:{&arg},yes},You typed 'yes'.,You didn't type 'yes'.}' sorts out whether you typed 'yes' after the action name. If you did, it goes past the '{eq:{&arg},yes}', and past the comma right after that, to 'You typed 'yes'.,You didn't type 'yes'.}'. Then it separates this by the comma in the middle, so that the bit which it evaluates is 'You typed 'yes'.' And that's what it tells you, the user of the action.
To put in commas into what you want to be evaluated, you need to make it clear that they aren't part of the MPI itself, or else the program gets confused and ends in an error. Misplaced or extra commas, or ones which aren't intended to be part of the programming, are the most common MPI mistakes there are. If you wanted the last program explained to tell you 'You said 'yes', I've just checked.' if they did type yes, you'd need to make sure that the comma in the middle of that part was not part of the program itself. To do this, you put a \ slash in front of it. This means that it is not counted as part of the MPI. Incidentally, that's how I can show you all this MPI in these room descriptions - normally all this would be evaluated every time someone looked at the description, but I've put \ slashes before each { and } bracket. I don't need to put \ slashes before the commas if I do that, because they aren't inside MPI brackets. Now, the last part of the tutorial, and then examples.
The last important thing before you can do a lot of stuff is {tell}. This tells a player a message. It's used by {tell:[message],[player]}. Again, if there are any commas in the message you're sending, you'll need to put slashes before them, otherwise, they'll be mistaken for the comma separating the message and player name, and then you'll get an error, and everything won't work. Now, the 'permissions' are quite important with {tell}, because you can't just use any player name at the end, and expect the message to be told to that player. If a player isn't in the room the user of the program is in, you'll get an error message when you try to use that player's name in the program. You can use a player reference # in {tell} functions, and the permissions apply. The only difference is, if the dbref# is that of the owner of the program, and the owner isn't in the room, the owner can still be notified.
{tell} is another one of those functions where you'll usually want {null} brackets around it, otherwise it will tell the user player the message it's sending to the other player as it sends it. Note: you can also use {tell:[message],me} to tell the user messages, but you won't generally want to do that, as you can just input the message to be told in plain text, and it will be told to the user because the text is in the success/description/drop etc. message. The {otell} function is simple. It works, {otell:[message],[room # or 'here']}. This tells the message to everyone in that room except for the user of the program. The room is specified either with a room dbref#, or 'here', which means the room where the user is when using the program.
Now we'll have a room of miscellaneous MPI functions, which you will be able to use in context with all your knowledge so far, then a couple of rooms of examples, and then some extra 'advanced MPI' rooms, and that'll be that. I'll also link up some 'frequently asked questions' rooms from here, when people start complaining about how pathetic my tutorial is, and how it doesn't tell them anything :) You need to recognise that what I've given you here is the tip of an iceberg. With MPI _solely_, I've created boats (controllable ones, with docks where the boats can be called from and to, with varying times etc.); elevators; spells; surprisingly complex 'who' lists for areas, and much more. You can create your own interractive areas in 'Recreations' with this MPI, as well as anything in other countries, or in OOC homes. Major functions to be discussed later on in the advanced tutorial are delays, looping functions *shudder*, the 'for' and the 'parse' functions (very useful for advanced MPI).
MISCELLANEOUS FUNCTIONS:
{contents:[room/player/'here'/'this'/object](,[type])} See 'mpi contents'.
{time}
{and} {or} {not} These are similar things. See 'mpi [name]'.
{listprops}
{eval}
{dbeq}
{owner}
{flags}
These are all simple enough for you to figure out with 'mpi [name]'. They can be useful. Please note: 'lists', list items, the lsedit program, and all other MPI (e.g. {lrand}) to do with lists is discussed in the lsedit tutorial.
MPI Examples:
1: The blackboard. So simple, you'll cry. But worth putting here. '@create Blackboard', 'drop blackboard' (not here), '@desc blackboard=It reads: "{prop:written,this}"', '@action write=blackboard', '@link write=$nothing', '@succ write={if:{eq:{&arg},},Write what on the blackboard?,You write "{&arg}" on the blackboard.{null:{store:{&arg},written,blackboard}}}'. That's it. Work it through: the description of the blackboard shows whatever's written on it by bringing up the 'written' prop on it. The 'write' action checks if what you've put after the action name is equal to nothing (i.e. you've only done 'write', with nothing after). If it is, it asks you what you want to write. If it isn't, it stores what you've said to the 'written' prop, and if you look at the blackboard, it'll be there.
A 'hit' action. '@action hit=me', '@link hit=$nothing', '@succ hit={if:{eq:{&arg},},Hit whom?,You hit {&arg}.{null:{otell:{name:me} HITS {&arg}!,here}}}'. Nice and simple.