Written by Foxen, October 12, 1993
MPI the language, and this document are CopyLeft 1993, by Fuzzball Software and Graphic Arts.
MPI is My Personal Insanity. That's my unofficial name for it. I must have been crazy for having written 3500 lines of C code to implement it. The official name for it, is Message Parsing Interpreter. That sounds a lot more ostentatious, and looks better on a resume'. =)
MPI is a script language that lets you embed commands within plain text, to do things like substitute in the text value of a property. It's used in messages like @descs, @succs, @fails, @drops, @osuccs, @ofails, @odrops, and your 'sex' property. Those of you who use the $desc, $wf-desc,or @6800 programs are likely familiar with this sort of idea. MPI works like those programs, only much faster, and with many more possibilities.
So, what's in it for you to use MPI? Well, you can make descriptions longer than the 512 character input limit, by splitting them up into sections that are in different properties, and substituting them into your main @desc. This also makes it easier to update only one part of the description, such as what you are wearing, by changing only the property that has your clothes described. You can also make multiple line descriptions, by making a list with lsedit, or another list editor, and using the MPI command to display a list in your @desc. For those of you who want to get fancy, you can make your description depend on what you are carrying. For example, you can make your description mention that you are wearing sunglasses, only if you are actually carrying them. The possibilities are endless.
Because the commands are read and interpreted by the game itself, they run quickly, producing less lag for the game than the MUF description programs like @6800. Also, you can port your descriptions for objects between fb5.0 MUCKs, without having to worry if the other muck has the right MUF programs, or uses the same list styles. You can also get much fancier with MPI than you can with @6800, since there are many more commands available to you.
Okay, okay, that's enough evangelizing.. Lets get onto the next section.
{command:arg1,arg2,arg3...}The open-brace { says that the text until the matching close-brace } is going to be an MPI command that the game should interpret. The first word inside the braces, before the colon, is the name of the MPI command that you want it to run. The rest, after the colon, are the arguments, seperated by commas. MPI commands often take two or three arguments, though some take many more, one, or none at all. In fact, a lot of MPI commands can each take multiple different numbers of arguments, using default values for any arguments that aren't given. If an MPI command takes no arguments, you can omit the colon. Here's some examples of MPI commands:
{prop:_clothes,me}This example runs the MPI command {prop} with the two arguments "_clothes", and "me".
{nl}This runs the MPI command named "nl" with no arguments.
If you want to pass a comma as part of an argument, you have to mark it to say that you really mean for the comma to get passed to the function, and that it isn't there to seperate arguments. To mark it this way, you put a backslash \ in front of it. The backslash means that the next character following it has no special meaning, and that it is to be copied literally. This makes a comma look like part of an argument, instead of like an argument seperator. This is called 'escaping' a character. You can also escape an open-brace { to keep it from trying to interpret the text after it as an MPI command. Also, you can escape backslashes. In fact, to include a backslash in text, you HAVE to escape it. Almost any character after a backslash will be copied literally.
The only exception is \r which is replaced by a carriage return character. A carriage return character tells the game to split the text into two lines at that place, when the text is displayed to the player.
{store:\{Here\\now\}\, she thought.,_when}This will run "store" with the two arguments "{Here\now}, she thought.", and "_when". The first backslash \ escapes the open-brace {, copying it into the argument literally. The next backslash escapes the backslash that follows it, making the backslash copy into the argument literally. The close-brace has to be escaped, also, or else the game would think that you are trying to run the "store" command with only the argument "{Here\now". The comma is escaped to say that it is part of the argument, and not an argument seperator. The NEXT comma, however, is not escaped. The game sees this and goes, "Aha! A second argument follows!" Then it gets to the last close brace }, and sees that it has gotten all the arguments. At this point, it calls "store" with the two arguments that you passed.
Note that several backslashes in a row will escape each other, alternating between escaping and escaped characters. What this means is that the game will take a look at "\\\{" and see an escaped backslash and an escaped open-brace. Literally: "\{". However, it will see "\\\\{" as two escaped backslashes and a NON-escaped open-brace. It would try parsing anything after the non-escaped open-brace as an MPI command.
MPI commands can have MPI commands nested within them, so they can take the output of other commands and use them as inputs. Example:
{count:{contents:here}}This would first run the MPI command {contents} with the argument "here". Then the {count} command would be run with the string returned from the {contents} command as its single argument. Commas and other characters inside strings returned from nested commands will all act like they have been escaped. If they didn't, they would cause unexpected problems, as your commands would find more arguments than they expect! Luckily, you won't have to worry about that problem.
@desc me=You see a pretty young girl with {prop:_haircolor) hair.When someone looks at you, with that description set, the game will run the {prop} command with the argument "_haircolor". The {prop} command will then look for a property named "_haircolor" on the object the command is on. It then replaces the call to itself, in the output text, with the string value of the property. If the "_haircolor" property was set to "golden", then the looking player will see "You see a pretty young girl with golden hair."
Unlike the various MUF description programs such as @6800 and $wf-desc, MPI commands can be inside of omessages, such as @ofail, @osucc, and @odrop. This lets you do things like make an @osuccess message properly reflect a varying @succ message.
@desc me=You see a young woman who is wearing {prop:_clothes}. @set me=_clothes:a blue blouse and a short green skirt
@desc me=You see a young woman who is wearing {exec:_clothes}. @set me=_clothes:{prop:_clothes/top} and {prop:_clothes/bottom} @set me=_clothes/top:a blue blouse @set me=_clothes/bottom:a short green skirt
{timesub:86400,0,_sunmoon}This example will show different property list lines, depending on the time of day. The period is 86400 seconds, which is one day. If the property list has 24 items in it, then a different line will be returned for each hour of the day.
The following are examples of the accepted ways to refer to objects.
object Referencing by name. #1234 Referencing by dbref. $regname Referencing by registered name. *playername Referencing by player name.When an MPI command returns a reference to an object, (we'll discuss some of these commands in the intermediate guide) it will refer to nonplayers by dbref, and to players by starred name. ("*playername")
To run MPI commands when a player logs in, you need to make a special property on the player, or on the room where the player resides. To do this, just simply do:
@set <object>=_connect/XXX:&<mpi goes here>The XXX can be anything. The properties will be evaluated in alphabetical order. The result of the mpi code is displayed to the connecting user. The ampersand (&) that starts the property value tells the server that it has MPI commands in that property that it should evaluate. As an example:
@set here=_connect/room_motd:&{list:_room_motd,here}This example will show the room's message of the day, that is stored in the _room_motd property list on the room, to the player logging in. There is a different set of properties, with names starting with _oconnect/, that also runs when a player connects, but the results of the MPI code will be shown to the other people in the room, and not the player. For example:
@set here=_oconnect/herald:&Hear ye, hear ye! {name:me} has connected!Will tell everyone in the room that someone just connected in the room, in a somewhat heraldic fashion. =)
When a player logs off from the muck, the properties under the _disconnect and _odisconnect propdirs are evaluated in a similar fashion. When a player leaves a room, the properties under the _depart and _odepart propdirs are evaluated. When a player enters a room, the properties under the _arrive and _oarrive propdirs are evaluated.
Here's some examples:
@set here=_odisconnect/elvis:&{name:me} has left the muck! @set here=_arrive/enter-details:&{list:_entry_details,here} @set here=_odepart/cabbie:&The cabbie watches {name:me} storm out.When something is heard in the room, properties in the ~listen and ~olisten propdirs are run, from all things in the room. The {&arg} variable holds the message that was heard. For example:
@set here=~listen/echo:&You hear an echo: {&arg}That will echo whatever it hears in that room, to the player who made the noise. You can also make listeners be restricted to only hearing certain patterns of words. To do this, you need to put in a matching pattern at the beginning of the property value. The syntax is:
@set <obj>=~listen/XXX:<pattern>=&<mpicode>For example:
@set here=~listen/aod:*Klaatu barada nicto*=&The sky rumbles at You! @set here=~olisten/aod:*Klaatu barada nicto*=&The sky rumbles at {name:me}!This example would have the skies rumbling at any player who said or posed the words "Klaatu barada nicto" in the room.
You can use MPI in locks, too, but only indirectly. The way you do it, is you lock to a property and the result you want, then you make that property contain the MPI code. For example, to have a room display its fail message when there are more than ten people in the room, do this:
@fail here=The room's rather crowded at the moment. @succ here=The room's not so crowded at the moment. @lock here=_crowdedroom?:no @set here=_crowdedroom?:{if:{gt:{count:{contents:here}},10},yes,no}In this example, the MPI code in the _crowdedroom? property will return "yes" if there are more than ten items in the room. Otherwise, it will return "no". The lock on the room evaluates that MPI code, and checks to see if it returned "no". If it did, then the success is shown to the player looking at the room. Otherwise, the @fail is shown to the looker.