Object/Action Trickery

One game you can play with objects to make them more interesting is to attach actions to them. Actions let your objects do things and can even make your objects possess states. The methods below can be done with anyone who has Builder status. They do not rely on programs written by Muckers, so you can create these even in the dead of night when no one else is around. It is assumed that you know how to create objects and describe them. The prequel to this tutorial, Object Basics, should probably be understood before you continue.

Action basics

The simplest kind of action is one that, conceptually, does nothing. It simply prints a message on all players' screens. Let's say you have an object; let it be a Plush SuperSoaker for the sake of argument. You have lavishly described it (using @desc) and have set the four messages for picking it up (@succ and @osucc) and dropping it (@drop and @odrop). While these are not important as fas as the action is concerned, it is always good practice to set these five fields, and, if you have locked the object (with @lock) you should also set the failure text (with @fail and @ofail).

Now you are ready to create your action. You want to be able to shoot your Plush SuperSoaker. Since a Plush SuperSoaker would not actually shoot water, you just want a simple message printed to the screen every time you shoot it.

First, create your action, and attach it. Attaching an action defines where the action belongs; it is not the same as linking an object, which will be discussed shortly. The creation step attaches the action to its object at the same time. Type the following:

@action shoot=supersoaker
This costs one penny. If you now examine your SuperSoaker you will see that it has an action shoot attached to it.

Try it. Just type shoot while holding the SuperSoaker or while it is in the same room as you.

It didn't work, did it? The reason for this is that the action was not linked. The action will not succeed because the Muck doesn't know what to do with it. It's very much like having an exit from a room that doesn't lead anywhere. (In fact, it *is* like having an exit from a room that doesn't leave anywhere; actions and exits are the same type of object. We will return to this point later.)

What you need is to link the action to something that does absolutely nothing. This will satisfy the Muck that the action is linked, and still ensure that shoot will do nothing but print a message to the screen. There is just such a linking destination, called dummy-for-exits. when you link to it you'll have to refer to it by its database reference (dbref) of #56. This number isn't special; it is just the object number that this simple program is stored under. Linking an action or exit costs another penny.

Link the action with the following command:

@link shoot=#56
If you try to shoot now, the action will succeed. But nothing at all is printed! That's because you haven't set the success messages. Set some appropriate messages with @succ and @osucc:
@succ shoot=You pull the plush trigger and plush water comes streaming out everywhere!
and similarly with @osucc. Now your Plush SuperSoaker is ready to shoot! Don't forget to set the object's @desc or @succ field to suggest that the Plush SuperSoaker can shoot when tou look at it or pick it up respectively.

Action not-so-basics

You have a simple action, and there is a lot you can do with a simple action if you are creative enough in your descriptions. You can even go ahead and create more actions on the SuperSoaker - perhaps it has an explode option. But there are a few ways you can improve the SuperSoaker. You may have noticed that before you linked the shoot action, trying to perform the action failed. Instead of linking and setting the @succ messages (for a success), you could leave the action unlinked and set the @fail messages instead (for failure), saving yourself a whole penny in the process. From the point of view of another player, the two are indistinguishable. However, you probably shouldn't do this, since it allows other players to "steal" your action by linking it themselves. Spend the extra penny and do it right.

Doing this is fine if there is only ever going to be one result of an action, but say you don't want anybody else to use your Plush SuperSoaker. You have to lock it so that only you can use the shoot action. Use the @lock command for this:

@lock shoot=me
By doing this, only you can succeed in the shoot action (you get the SUCC message) whereas everyone else fails (and gets the FAIL message). Anybody can still pick up the water pistol though. To stop that from happening, lock the *object*, not the action, to you.

More room for improvement can be seen if you do the following: drop the supersoaker, then shoot while it is on the ground. True to form, the shooting still happens. It would be more realistic to make shooting only possible while you are holding the gun. This requires a different lock on the action:

@lock shoot=supersoaker
This will succeed only if you have the supersoaker in your possession. By locking both the Plush SuperSoaker and its action, you have made a safe weapon that only you can pick up or fire.

For a Real Muck Example of this, try the stuffed sheepdog called Minimax in Ariel's Room (#5160). He has two actions, cuddlenhug and shake. They only work if you are holding him.

Another Real Muck Example that shows a lock is the crystal chandelier in the Palace (#5153). It can be turned on and off by anyone holding a trident. Specifically, if something you are holding has the property _trident:yes, the lock succeeds. Try setting the property on your own home-made trident or any other thing you own, or even yourself. Don't forget to clear the property afterwards. Tridents are dangerous things!

Toggles

A toggle is something which has two states. Performing some action will make the object switch between the states. This sort of thing is easy to do with actions and objects.

Let's say that you would like a window in your room. Furthermore, you would like to be able to open it and close it (but only open it when it is closed and close it when it is opened) and have its present state reflected in the listing of the room's contents when you do a look. Graphically, you'd like:

              +--------+     close      +--------+
              |        | -------------> |        |
              | opened |                | closed |
              |        | <------------- |        |
              +--------+      open      +--------+ 
where opened and closed are states and open and close are actions to change the state. (Technically this is not a true toggle since the actions are different, but if we named them the same then there would be no perceivable difference between this and a true toggle. The version presented here is more general and more useful.)

The trick with creating this object is that every state is a separate object. You actually have two windows, identical in most respects except that one has the description opened and the other is closed. You then create two actions, one per object, and link the actions to the opposite object. You cannot close an already-closed window because there is no close action on the closed window.

This works because linking an action to an object does a fairly strange-sounding thing: The object that the action is linked to is brought to the same place as the object that owns the action, then, the object that owns the action is sent to its home room.

In our case - say the window was already closed - we apply the open action, the opened window is brought into the room, and the closed window is sent to its home, which is probably the Player Start room unless you changed it.

The actual steps for creating this window would be:

@create opened window
@create closed window
@action open=closed window
@link open=opened window
@action close=opened window
@link close=opened window
Now drop the closed window into the room and open it. The opened window is miraculously teleported from its previous location (you were holding it) to the room and the closed window is nowhere to be seen. If you remember the dbref of the closed window (say it was #2496), you can verify that it has gone home by locating it:
where #2496
The Muck will report that the closed window is in the Player Start Room.

Once you have the basic toggle working, you can do a few things to embellish it. You will have to add descriptions for the two windows, somehow hinting that you can open and close it. You should add SUCC and OSUCC messages to the two actions, and if you have locked them at all, FAIL and OFAIL messages too. It is always nice to add dummy actions (such as an open action on the already-opened window), because people are sure to try opening it twice just to see what happens. Such actions would be simple do-nothing actions as have already been described. Another thing you should be aware of is that there is always an "anti-window" at the Player Start which is in the opposite state to the one in your room. It's not good manners to clutter up this room, so don't be surprised if a Wizard hands you your anti-window at some time. What would be better is to create a "Warehouse" room which only you can access, and set all these objects to have their home there. For example, say your warehouse is room #5172 (this is Ariel's Warehouse's dbref). Set the home of each window with:

@link closed window=#5172
and likewise for the opened window.

For a Real Muck Example of this, try the soft inviting bed in Ariel's Room (#5160). Its two states are "unoccupied" and "occupied" and you can switch between them by the actions bounce and arise. Only one player can occupy the bed at any time, which you can verify by bouncing twice on it. Unfortunately, a small problem that shows up with the bed is that if player A bounces on the bed, player B can arise from it, on A's behalf, as it were. The analogy with the window example is one person opening it and another closing it. Making a bed that is more realistic (only the bouncer may change its state by arising) would require a program, which is beyond the abilities of a Builder. You can alleviate this a bit by careful wording of the actions, and only telling the bouncer how to arise when she first bounces on it.

Extensions

One extension of the concept is not any more difficult at all. You can create a chain of several states and link them any way you like. Let's say you want your Plush SuperSoaker to have three shots before it runs out and needs to be recharged. Diagrammatically, the SuperSoaker's states map like this:
            +-------+                       +-------+
  <-------- |       | --------------------> |       |
    shoot   | empty |        reload         |   3   |
   (fails)  |       |                       |       |
            +-------+                       +-------+
                ^                               |
                | shoot                   shoot |
                |                               v
            +-------+                       +-------+
            |       |                       |       |
            |   1   | <-------------------- |   2   |
            |       |         shoot         |       |
            +-------+                       +-------+
The process is exactly the same as before, except that you now have four Plush SuperSoakers and five actions. Naturally, this starts to cost money; the window would cost 24 pennies, whereas this device would cost 50! Building macros in your Muck client program to set the mundane information (SUCC, OFAIL, DESC, actions, etc.) is quite worthwhile for such objects, if your client will do macros. You would probably also want to make the reload action locked to a room or Plush Water source in a real life situation.

For a Real Muck Example, play with the hat stand in the Palace (#5153). It has five states and you can place or remove a hat up to a maximum of four. The hat stand's description changes very slightly at each state.

Summoning objects

You now have a way of changing an object's state, by sending one object away and bringing another to fill its place. But what if you only want to bring an object to a place?

To name an example, let's look at the Secluded Beach (#5120), specifically the ramp into the water that leads to Atlantica. This exit is locked so that female characters can only enter if they are carrying seashells. Now, it's unreasonable to expect every female character to carry seashells, so we need a way of giving them seashells just before they use the exit, then reuse the shells for some other player's use. (You can actually bypass the shell-getting if it annoys you. There's a topless exit which goes the same place and doesn't have a seashell lock.)

A very small variation on the toggle presented above will suffice. (In fact there are two subtly different ways of summoning an object.) If the seashells aren't on the beach, the player can do a search in the room and the single pair of seashells, wherever they are, whoever is carrying them, will be teleported to the beach. There they can be picked up and worn while the player enters Atlantica. Since she will have probably forgotten about them afterwards, it doesn't matter too much if they disappear without warning once she is in Atlantica.

The search action is part of the room. That is, it was created with the command:

@action search=here
The action was then linked to the seashells as normal:
@link search=seashells
What happens when a player searches is that, as before, the linked-to object (seashells) is brought to the room. But because a room can't be sent home like an object, that's all that happens.

As long as only one player wants to use the seashells at once, this method works well.

There is one side-effect of this which you will notice if you list the room's exits. This action is listed among the exits! Remember that an action and an exit are the same thing, so the exits command is just listing all action/exits belonging to the room. You can suppress the printing of an action in the exits listing by setting its HAVEN flag. Do this:

@set search=haven
Another variation on summoning an object works a little better if you are using one object as the summoner. This method does not require the summoning to be fixed to a room.

The trick is to create a normal toggle situation as described earlier, but to set the summoning action's STICKY flag. When the action is performed, the usual happens: the linked-to object is brought to the room, but if the action is sticky, the action's source object is not sent home. To set an action's STICKY flag, do this:

@set action=sticky

Vanquishing objects

You have a way of bringing an object into a room, now you'd like the object to go away again. How do you do it?

There are three ways. If you can force a player to pick up the object, you can simply make it sticky, so that when the player drops it, it will go back to its home position. To set an object to be STICKY, type:

@set object=sticky
(Note that sticky actions and sticky objects behave quite differently.) A simple Real Muck Example is the cute sea slug in the Princess' Hall (#5156). You can pick it up and take it anywhere. When you drop it it slithers back to its home in the hall.

Another way, which doesn't require a player to pick up the object, is to make yet another variation on the toggle. Recall that a toggle will send an object home while teleporting another one here. What would happen if the object you are teleporting here is already here? The net effect would be to send the first object home, and nothing more.

To do this, you'll need an object that isn't going to be moved from this room. It doesn't actually have to be related to the object you want to send home. You can't use the room itself for this purpose. Form an action that will send the object home. Attach it to the object:

@action vanquish=object
Then link the action to some immovable object:
@link vanquish=anchor
Set the SUCC and OSUCC messages, as always, and then try it out with a simple vanquish. The object has gone to its home. This technique will only work if neither object nor anchor can be picked up or moved. Otherwise unexpected things happen.

As always you should set the object's home to a private warehouse-type building (and you need only have one warehouse, where all your toggle objects are kept).

The safest way of all, with few restrictions, is to turn the sending into a summoning. As far as you are concerned, the object is being sent to your warehouse room. But imagine the situation from someone standing in the warehouse. The action is summoning the object to that person's location.

So, make an action, in your warehouse, and link it to the object you want to move. It won't be in the warehouse at the time, so you will have to refer to it by its dbref. This is exactly how you summoned an object in the previous section. Now, go back to the room where the object is, and create the dismissal action, attaching it to the object. The trick is to link this action to the summoning action you made in your warehouse. As explained in Other Links below, linking to an action causes the actions to chain, so that the second action is performed. The object is summoned to the warehouse by this action and, as far as you are concerned, it has disappeared from your location just as it should. This method uses one more dbref than the second method, so to conserve this limited resource you should only use it where necessary. Also note that summoning and vanquishing an object, while related, need not be done together at all. For a Real Muck Example, look at the chest of drawers in the Princess' Hall (#5156). When you open it, some miscellaneous odds and ends pour out. You can pick them up then drop them (the first method shown here) or you can put them back in the drawer (the second method). The @succ message for both is the same, somewhat hiding the true implementation.

Multiple actions

With the simple action examples given at the start of this section, you could have zero, one or two results from an action. If you didn't lock an action you would have the same result for everybody (SUCC), and if you did lock it you could have two based upon some property or object (SUCC or FAIL). Even with two results, you are partly limited in what you can do, because a failed action will not perform its link.

There is a way to make as many different actions as you like and have them do as many things as you like. You can see how it works by noting two things about actions. First, you can have multiple actions with the same name on the same object. Second, if there is an ambiguity, the Muck will favour a success over a failure.

The main caveat is that if there are two possible successes or two possible failures, you have no way of knowing which action will trigger. So you have to be very careful designing your lock functions such that exactly one can ever be true at once.

Imagine you want to create a Change Room, but you want to segregate the males from the females so that they end up in different rooms without them having to choose themselves. In fact, to be really careful (and to emphasise the point), you will need three rooms: one for people with sex:male and no sex:female (the men); one for people with sex:female and no sex:male (the women); and one for everyone else. The last room is needed because some players (notably guest players) might not have a gender, and because it is possible to be carrying an object with a sex opposite to your own, so that you may actually pass both a sex:male and a sex:female lock. The division given above is the safest way to do it and will work for everybody.

You'll need three rooms. You will have to refer to the rooms via their dbrefs, but we'll stick to names here as it makes it clearer. You will also need three exits. Link one to each of the three rooms, and give them exactly the same name. You will have to refer to the exits by their dbrefs too since they are ambiguous.

The task is now to choose proper lock functions. In this case, they would be:

@lock #female exit=sex:female & !sex:male
@lock #male exit=sex:male & !sex:female
@lock #questionable exit=(sex:female & sex:male) | (!sex:female & !sex:male)
You can try out all possibilities to convince yourself that only one exit will ever be unlocked at once.

Using this technique, you can create as many actions as you like and let them perform any link you want. For a Real Muck Example, look at the blue dress in Ariel's Room (#5160). It has four locks: one that triggers when you are not holding the dress; one that triggers if you are holding the dress and wearing something else (such as Ariel's seashells); one that triggers if you are holding the dress, not wearing anything else, male and not female, and one that triggers if you are holding the dress, not wearing anything else, and female or not male. These cover all eventualities.

Random actions

Using the technique of naming several actions the same, you have been able to get as many results as you like from one action. But remember that you had to make sure that the actions formed a disjoint covering set: only one action can ever succeed at once.

What happens when you have two actions with the same name, and both of them can theoretically succeed? The Muck picks one at random. This is a simple way to make two or more actions happen nondeterministically.

Going back to the Plush SuperSoaker example, say you'd like to make it so that when you shoot it, there is a 50% chance that it backfires and drenches you instead. (We are talking about the non-counting SuperSoaker from the first section. This is only for the sake of illustration. The same technique can be used where any action can be used.) Your first step is to create another shoot action to go with the one you already have:

@action shoot=supersoaker
This time you are going to have to work with the action's dbref rather than its name. Remember the number the Muck returns. You will use it when you link the action to dummy-for-exits:
@link shoot backfire=#56
Don't forget to describe the action too in its SUCC and OSUCC messages. (Remember, while you might think that backfiring is a "failure" of sorts, the Muck must see it as a successful action. Recall that the Muck doesn't care what text goes with an action.) Once you've done this, try your new version of shoot. Half the time it will backfire, or whatever you set the message to say, and half the time it will work "normally".

There is nothing about this that limits the actions to two. It is just as easy (though somewhat time-consuming) to have ten different actions, all with the same name.

If you want to have the actions' frequencies anything other than equal, you will have to use a little more trickery. You can create a three-to-one frequency ratio by making three "normal" shoots and one backfire one. By setting the messages the same for the first three the player doing the shooting will not know which one is being triggered. Doing this becomes inefficient (and chews up dbrefs, of which there are a finite number), so if you want to create unusually-weighted random actions, investigate other techniques, such as RUFUS, available on FDCMuck. A word of advice: use random actions sparingly. Players don't usually like having room exits or important actions that only work some of the time. Try to keep random actions to trivial or humorous situations.

Other links

So far, all our actions have been linked to tangible objects. But actions may be linked to other Muck objects too. They may be linked to rooms, players, programs or other actions. Each of these performs a certain job.

If an action is linked to a program, the program is run. This is only of real use if you have some Mucker-written program that you are able to run. You have already done this by linking do-nothing actions to dummy-for-exits (#56). The program does nothing, but it is a program nonetheless.

If an action is linked to another action, it chains the actions. The first action will cause the second action to trigger. In itself this isn't very useful (unless you are being sneaky with locks or something). Linking to actions really comes into its own when you make multiple links. See the following section.

Actions that link to rooms simply transport you to the room. The room must be set LINK_OK for you to be able to make the link.

With this, you can create an action that allows you to go to a room at any time, even if you cannot jump there. To set it up, navigate to the room you want to be able to teleport to. When you are there, create an action and attach it to yourself:

@action goroom=me
Then link the action to the room.
@link goroom=here
Now, wherever you are in the Muck, you can move to this room by simply typing goroom. This has the advantage over home in that you can create your own OSUCC message to be displayed to the other people in the room, and that it can take you to any room, not just your home. It also has the advantage of not sending the objects you carry to their homes. If you are carrying a toggle item with several states, none of which actually has its home as you, this is an important advantage.

Linking to a room is normally how an exit from a room is made. In fact, since actions and exits are the same, goroom is in every respect a portable exit that you carry around with you, the other end of which always leads to the room you linked it to.

An action that is linked to a person teleports you to the room that the person is in. The same considerations apply as when linking an action to a room, and the person must be JUMP_OK at the time you activate the action.

Multiple linking

With the linking we have done so far, you are able to have a single action perform a single task - swap an object with another, summon or vanquish an object, go to another room, run a program. In fact, an action may be linked to many other objects simultaneously. This is how you can have a single action perform many tasks in one move.

Let's begin with a simple example of what multiple linking can do. In the room West of House (#5121) there is a mailbox. You want to be able to open the mailbox, to reveal a leaflet. Up to now, you could swap the mailbox with an open mailbox containing a leaflet, or you could have the open and close actions bring and dismiss a leaflet without changing the status of the mailbox at all. What you really want is this:

                                        +----------+
                                        |          |
                                +-----> | open box |
          +----------+  open    |       |          |
          |  closed  | ---------+       +----------+
          |          |          |             |
          |  mailbox | <----------------------+ close
          +----------+          |             |
                                |       +----------+
                                |       |          |
                                +-----> | leaflet  |
                                        |          |
                                        +----------+
The open action brings the open box and the leaflet here and sends the closed mailbox home. Assuming you already have the objects and have set their home to be your warehouse room, you would do this by:
@action open=#closed mailbox
@link open=#open box;#leaflet
Note that you separate the multiple link destinations with a semicolon. The close action is a little more difficult to achieve. You must swap the open box with the closed box, then send the leaflet home. This can be done by creating two actions, one being the close that players use, and the other being something that no player should ever type. Let's create the latter action first, and have it swap the two mailboxes:
@action close_2=#open box
@link close_2=#closed mailbox
This action, which we called close_2 in the hope that no one would ever type that, is just a simple toggle link, just as you've seen before. The cunning part comes when you create the proper close action:
@action close=#leaflet
@link close=#closed mailbox;close_2
The first half of the link sends the leaflet home while bringing the closed mailbox here. The second half chains the close_2 action, which sends the open box home while bringing the closed mailbox here. Of course, the closed mailbox is already here, so you have in effect swapped two objects for one.

What has been presented here is the "optimised" linkage. You could just as easily link the open action to two other actions, one of which opens the mailbox (swaps the closed mailbox with the open box) and one of which brings the leaflet here (using the summoning by action-connected-to-a-room method). It may help to do it this way on more complex examples.

Multiple linking works with the full range of linkable objects that normal linking does. You can link to any number of objects, actions and programs, but you can only link to one program, room or player. This is because you can only be teleported to one room at once, for obvious reasons, and for efficiency and stack balance reasons in the case of linking to programs.

Using multiple links, you can not only create any combination of summoning and vanquishing objects, you can also run a string of programs, move an object somewhere automatically as you exit a room, or make sure you are carrying a certain object before you enter a room. The possibilities are immense.