Color Guide:
Red indicates a command (or commands) you enter into the MUCK.
Navy indicates text returned by the MUCK, usually a result of a command you typed.


Actions and MPI: A Sketchpad

In this tutorial I'll show you how to add functionality to objects (make them do things) by combining action objects with MPI. I'll also show a practical application of the random character selection function from the earlier tutorial.

To illustrate these things, we'll build a sketchpad. We want people to be able to 'draw' something on the sketchpad, and the sketchpad's description should show not only what was last drawn, but also who made the drawing.

If you read the tutorial Dynamic Descriptions and MPI, you know you can alter an object's description based on properties stored on the object. Similarly, you can include properties stored on the object in the object's description. We're going to use those ideas here. Let's say we have an object called 'sketchpad' and we want it to have a description like this:

When someone looks at the sketchpad, we want X to be replaced by whatever was last drawn on the sketchpad, and Y to be replaced by the name of the artist. Both X and Y can be properties on the sketchpad: _drawof and _drawby. You can use the Prop function to return the values in the properties, so the sketchpad's description can be pretty simple:

This is fine, but it's possible for the _drawof and/or _drawby properties to not be set, which would leave ugly blanks where the subject and artist name should be, so let's adjust the MPI to cover this situation:

All we did is add a conditional statement that includes the middle sentence only if an artist name is present; in other words, if the _drawby property has been set. Remember that if no statement for a false condition is provided to an If function and the function condition evaluates to false, a null string is returned. This simplifies the MPI. In the above case, if no artist is present, we want a null string (no middle sentence) to be returned.

So here's a sketchpad and its complete description:

That's it for the sketchpad itself. Pretty simple. Now we need to set up a way for characters to use it. As the owner of the object, you could simply say @set sketchpad=_drawof:a butterfly, but other characters can't do that, and you wouldn't '@set' a real sketchpad, would you? What we want is something where a character could do draw a butterfly. We'll use an 'action' to do this.

What's an 'action'? An action is an object associated with a parent object that when triggered by its name initiates a move from the parent object to another location. Room exits are the most common use of actions. Just like other objects, when an action is used, its message properties are triggered as applicable. For example, when you use an exit to move to another location, you'll see the exit's _/sc message, if there is one. Like all message properties, any MPI in the message property is executed.

We're not interested in the teleport effect of actions. What we're interested in is the fact that using an action triggers a message which can include MPI. What we're going to do is create an action associated with our sketchpad, turn off the movement stuff, and embed some MPI in the success message that will set artist and subject properties on our sketchpad.

Create an action called 'draw' on your sketchpad with the following commands:

The @link command turns off the action's teleport capabilities by setting its destination to a little MUF program that essentially does nothing. This prevents others from setting a destination, and makes sure message properties will work correctly when the action is used.

Setting the _/sc message property is the most important part of the draw action, because the MPI in this message will save the _drawof and _drawby properties. We need to accomplish three things with the _/sc message:

The second component has a hidden tricky part: What if the user didn't type anything after 'draw'? What do we set _drawof to? Whoops. We'll need to account for that possibility, and the way we'll do it is to use a random character in the room as the subject.

Let's set up the situation in english:

Now let's start building the MPI. We'll fill in the conditional first:

The 'argument' is whatever the user typed after the name of the action. If the user typed 'draw a butterfly', 'a butterfly' is the argument. The action will pass this argument to any dependent MPI. MPI has a pre-defined variable {&arg} that always holds the value of this argument, even if it is just an empty string (no argument). For our If statement, we need to know if an argument exists. If it does, we'll store it in _drawof, if it doesn't, we'll get a random character name instead. MPI gives us an easy way to do this test. An empty string is considered 'false', so we can write the following: So if the user typed 'draw a butterfly', {&arg} will be 'a butterfly' which is not an empty string and is considered a 'true' condition, so the If statement will opt to store what the user provided as a subject. If the user simply typed 'draw', {&arg} will be '' which is considered 'false', and the If statement opts to store a random name instead.

The next step is to store what the user sketched on the sketchpad. Once you learn how to do this, the remainder of the sketchpad project is easy.

Storing the subject requires grabbing the value of the argument and saving it on the sketchpad's _drawof property. Use the Store function, which looks like this: {store:value,property,object}. For the value to store, plug in {&arg}. For property, plug in _drawof. The object we're storing it on is our sketchpad. We could use the dbref of the sketchpad, but there is an easier solution. Just as an exit is located within a room, our draw action is located within the sketchpad. MPI has a location function, {loc:object}, which returns the dbref of the container. Why remember some silly dbref when MPI will look it up for you? Using the pre-defined value 'this' to represent our triggering action, we'll plug in {loc:this} for the object of our store function, the sketchpad itself. Our MPI now looks like:

Let's go ahead and complete the rest of the MPI for the draw action's _/sc message:

In the case where a subject wasn't provided, we simply plugged in the handy random character function from the earlier tutorial for the value of the Store function. For the name of the artist we used the MPI function Name and the pre-defined value 'me' which contains the user of the action. In the message returned to the user, we retrieved what was drawn from the sketchpad's _drawof property and incorporated it into the message.

We're almost done. MPI functions are designed to return values and can be 'noisy'-- in other words, they like to say things which have an annoying tendency to end up in your messages. Store is such a function, for it repeats back the value it stored. To make these functions shut up, we'll enclose most of our MPI in the Null function, which always returns a null string, effectively gagging any functions inside.

Here's the completed _/sc message for your sketchpad's draw function, and an _/osc message to go with it:

That's it! If you understand the techniques mentioned here, you can build the majority of toys commonly seen in mucks.