"Speedwalking" is the act of moving from one location in the MUD to another location, quickly. zMUD provides a great deal of control over speedwalking in order to work with the hundreds of different MUDs that you can play. Because of the flexibility, speedwalking can sometimes be confusing, especially when you start writing scripts to try and control it. This article describes the speedwalking features in zMUD in details, both with and without using the Automapper.
NOTE: This article describes how speedwalking works in zMUD versions 7.04 and later. Earlier versions of zMUD worked differently and had many bugs and problems.
Without the Automapper, there are two ways to speedwalk:
When you are using the Automapper module, there are several other ways to speedwalk:
zMUD supports three different "modes" used by the Automapper for speedwalking:
As you can see, each speedwalk mode is unique and different. Selecting the correct speedwalk mode for your MUD or playing style is very important. If your mapper is correctly configured, you can use any method of speedwalking with any of the three modes. However, if your mapper is not properly configured, you might have trouble using Safe or Slow Walk modes since they depend upon receiving information from the MUD.
zMUD allows you to assign scripts to each room on the map, along with a global "onroomenter" alias that is executed whenever you enter a room. How and when these scripts are executed depends greatly on the speedwalk MODE. Understanding how each mode works in detail is the key to understanding how your room scripts will or won't work. Scripts will be discussed in detail in the different sections on each speedwalk mode.
In the mapper, rooms are connected via exits. Each exit has a direction associated with it (such as north, east, up, etc), as well as a customized exit command. Each exit also has an exit "type", such as "door". Each exit type has a script associated with it that can send custom commands to the MUD when traversing the exit. For example, the "door" exits have a script to open the door before you go through the exit. The "locked door" exits have a script to unlock the door and open the door before entering. The scripts for these two default exit types can be changed in the normal zMUD Map Properties. Using the zMapper program (available separately), you can add your own exit types and define your own scripts for each exit type. That customization is beyond the scope of this article.
Just remember that when going through an exit, a set of commands might be sent, and the customized exit command might be sent instead of the direction that you moved. For example, if you try to move through a north exit, but the exit has a customized command of "enter", then the word "enter" will be sent to the MUD instead of your "north" command. This feature allows you to use the keypad to move through exits, but still sends the correct exit commands to the MUD.
In the following sections we will examine each speedwalking mode in more detail. We will use examples based upon the following map:
(This map is available for download from http://www.zuggsoft.com/files/tutorial.mdb. Download this file to your zMUD directory. Then, to use this map, press <ESC> from the main zMUD character selection screen to open a blank MUD window, then click the Map button in the toolbar to open the mapper, then select the File/Open menu command in the mapper and load the tutorial.mdb map database.) |
Here you can see several rooms (A, B, C, etc) connected together via exits. Between room E and F there is a door called "gate". From room F to G there is an exit with a customized exit command. The north exit from room F is set to the command "enter" and the south exit from room G is set to the command "exit.
If you set the current map position (the blue marker) to room A, then typing "east" or "e" or pressing the Keypad 6 key will all move you to room B. If you set the current map position to room E and then type "east", you will see the command "open east" sent to the MUD, and will then see your "east" command sent to the MUD. The "open east" command came from the Door Exit script. You can customize the Door Exit script in the Map properties. The default value is "open %1". %1 is filled in with the direction you moved ("east" in this example). If you changed the Door script to "open %2" then %2 would be replaced with the name of the door, and "open gate" would have been sent to the MUD instead of "open east".
If you set the current map position to room F and then type "north" or "n" or press the Keypad 8 key, you will see the command "enter" sent to the MUD. Your "north" command was translated into the specific exit command for the north exit. Once you are in room G, if you type "south", then the command "exit" will be sent to the MUD. Of course, if you actually typed "enter" or "exit" instead of "n" and "s", then your command would also work as expected. The direction translation feature allows you to use the keypad to move between rooms with special exits like this.
If you set the current map position to room A, and then double-click on room D, you will see the commands "east", "north", "east" sent to the MUD. zMUD computes the shortest path between the current room (the blue dot) and the room you double-click on, and then uses that path to "speedwalk" to the destination.
If you are in room D and double-click on room G, you will see the commands "south", "open east", "east", "enter" sent to the MUD. Notice that the Door Script is sent, and that the custom direction command from room F to room G is sent.
Let's try speedwalking using normal Paths. Set your map position to room D and then type ".sen" on the command line. If the mapper is closed, the commands "south", "east", "north" would be sent to the MUD as expected. But if the mapper window is open, then the commands "south", "open east", "east", "enter" will be sent to the MUD instead, just as if you had double-clicked room G.
So you can see that no matter what method you use to walk (using the keypad, double-clicking a room, or using the .path commands), the mapper will attempt to send the correct commands to the MUD based upon your map structure and customizations.
Next, let's look at each speedwalk mode specifically to understand how each really works in order to customize speedwalking via scripts.
Set your map speedwalk mode to FAST using the button on the toolbar, then set your current map position (blue dot) to room A on the map.
Now, when you double-click room G on the map, here is a diagram of what happens:
Sent TO MUD | e | n | e | s | open east | e | enter | |||||||||||||
Received FROM MUD | B | C | D | E | F | G | ||||||||||||||
Map Position | A | B | C | D | E | F | G |
Time goes from left to right on the timeline diagram above. So, the Map starts out in position "A" (Room A). Next, the command "e" is sent TO the MUD. Next, the map position is updated to room B and then "n" is sent to the MUD, and so on. Only after all of the commands have been sent to the MUD and the map position has been updated to room G does the MUD start sending back the room descriptions for room B, then room C, and so on.
(Important Note: If you are using the Tutorial.MDB file to follow along, keep in mind that when you are not CONNECTED to a live MUD, the mapper will try to display it's own room descriptions as you move around the map if you have the Room Output map preference enabled. The text displayed by the mapper when offline sometimes doesn't exactly match the timing shown in the timeline for "real" MUD input. So, while you can develop and test your scripts when offline, keep in mind that timing differences between the offline mapper and the live MUD might make small differences in how your script is executed).
The above diagram shows a "clean" example. In real life, the MUD starts sending the room description for room B as soon as it receives the first "e" command. However, because zMUD is "busy" processing your speedwalk, the text from the MUD isn't actually displayed until after the "enter" command is sent at the end. Then all of the text received from the MUD is displayed.
It is VERY IMPORTANT to understand when zMUD is busy and when zMUD can process incoming MUD text. Normally, zMUD will wait until a command, or trigger, or alias, is finished before displaying new text from the MUD. However, certain zMUD scripting commands work in the background and allow processing of new text while they are executing. The commands that run in the background are the #WAIT command, and the various looping commands such as #LOOP, #WHILE, etc. These are described in more detail in the article Timers, Delays, and the Wait Command. To prevent zMUD from running these commands in the background, you can enclose them in a #PRIORITY command. The #PRIORITY command will keep zMUD "busy" during the execution to prevent new text from being processed from the MUD.
For example, if you added a Room Script to room C that included the command "#WAIT 5000", then text from the MUD can be processed during that time, and the room descriptions for room B and room C would be displayed immediately after the "n" command was sent and room C was set to the current map position.
You should only use scripting commands such as #WAIT or other looping commands within mapper scripts (such as room scripts) if you FULLY UNDERSTAND how that effects the speedwalking timeline. We will come back to this important topic later in this article when we discuss room scripts in more detail.
Set your map speedwalk mode to SAFE using the button on the toolbar, then set you current map position (blue dot) to room A on the map.
Now, when you double-click room G on the map, here is a diagram of what happens:
Sent TO MUD | e | n | e | s | open east | e | enter | |||||||||||||
Received FROM MUD | B | C | D | E | F | G | ||||||||||||||
Map Position | A | B | C | D | E | F | G |
Unlike FAST mode, the Map Position only updates when the room name and description for a room has been received from the MUD and the MUD prompt is then received. This helps keep the mapper in synch in case something unexpected happens on the MUD.
For example, let's imagine that there is a aggressive monster in room C that attacks you when you enter (as soon as the MUD receives the first "north" command). Some MUDs will clear your input buffer when you get attacked, and so the extra commands that were sent (e,s,open east, etc) will be ignored. On other MUDs, it will still accept your commands, but prevent you from moving during combat. So, when it gets the "east" command, it might say something like "You can't escape!" to indicate that you can't move to room D yet because you are in combat.
So, in this combat example, compare FAST mode with SAFE mode. In FAST mode, after the "north" command is sent to enter the room causing the immediate attack, the mapper "thinks" you are in room C, and that seems fine. But remember what I said about zMUD being "busy". zMUD won't see the text about you being attacked until it is done sending the speedwalk commands. The text describing the combat would normally appear just after the room description of Room C has been displayed. And you can see from the timeline in the Fast Mode section that when the room description of Room C is displayed, the mapper already has your current position set to room G. So, zMUD thinks you are in Room G, but you are really still in Room C on the MUD, fighting the monster. This is bad.
Safe mode is different...it is "safer". Look at the timeline for the Safe Walk example and look at where the room description of Room C is displayed. When this room description is displayed and the MUD prompt is received, the mapper position is updated to Room C. The room description of room D is never received because you are busy fighting a monster in Room C. So, the mapper position matches your actual MUD position.
We'll talk about how you resume your walking after combat a bit later in this article. But this example should show you the major difference between Fast mode and Safe mode and why you might prefer to use Safe mode when walking through a potentially dangerous area on your MUD.
Sometimes even Safe mode isn't safe enough. Remember that in Safe mode, zMUD still sent ALL of the movement commands to the MUD right at the beginning. While SOME MUDs will ignore these extra directions if you get into combat, other MUDs might not. On other MUDs, you might continue moving with a monster following right behind you! The monster might even continue attacking you while you are sending movement commands, which might cause you to die! That is where Slow Mode comes in. Here is the timeline for the same example using Slow Walk mode:
Sent TO MUD | e | n | e | s | open east | e | enter | |||||||||||||
Received FROM MUD | B | C | D | E | F | G | ||||||||||||||
Map Position | A | B | C | D | E | F | G |
In this timeline we see that zMUD only sends a single command, and then waits for the room name and description and then the MUD prompt before updating the current map position and moving to the next room. Once a step is confirmed, then the next direction command is sent to the MUD.
So imagine our combat scenario in this example. The combat text is displayed right after the description of room C. When the mapper sees the description of room C, it confirms the step, and when it receives the MUD prompt, it updates the map location to room C and then sends the next direction command to the MUD ("e" in this case). But the room description for room D is never displayed because you are in combat. While you are in combat, the slow walk "timer" will expire and cancel the rest of your speedwalk, allowing you to fight.
But even in this example, zMUD has already sent the "east" command to the MUD to try and move from room C to room D. How do you prevent this if you don't want the monster chasing you? That is where scripting comes in and is the next topic of discussion.
Before we get to scripting, take another look at these three examples and make sure you fully understand them. Slow walk mode is "slow" because it waits for the description of each room before sending the next direction command to the MUD. Fast and Safe mode send all of the directions at once, which is much faster.
Some MUDs do not like you to speedwalk and will restrict how quickly you can send exit commands. Slow walk mode is perfect for those MUDs since it sents the commands more slowly and doesn't "spam" the MUD with lots of text all at once. Even when using slow walk mode you might find yourself trying to move faster than the MUD will allow. In those cases, simply use the Send Delay preference to add more delay time between speedwalking steps. The Send Delay is used in all three speedwalk modes and simply adds a delay time after each direction command is sent to the MUD.
Back to our previous example...how do we prevent the next direction in the speedwalk being sent to the MUD when we get into combat? The answer is using the #PAUSE command. There are several scripting commands that can control speedwalking in zMUD. The commonly used speedwalk control commands are : #PAUSE, #STOP, #STEP, #OK. Here is the definition of each command:
Here are some mapper functions that can be used:
zMUD uses the #OK command extensively to confirm each step of a Slow and Safe walk. An internal trigger based upon the room name or the first line of a room description is generated to execute the #OK command. So, when the description of Room B is received, this internal trigger executes the #OK command, which confirms the step. It then waits for your MUD prompt and executes #STEP when it is received if speedwalking is still active.
In Slow Walk mode, the Room Script and the "onroomenter" alias is executed just after the map position has been updated by #OK, but before the #STEP is executed by the next MUD prompt. So, if you the following trigger in the Room Script:
#TRIGGER {attacks you} {#PAUSE}
this will pause the current speedwalk if this text is received before the next MUD prompt and prevent the automatic step when the MUD prompt is received.
To resume speedwalking when combat is over, use the #STEP command. For example, the trigger:
#TRIGGER {is dead!} {loot corpse;#STEP}
would automatically loot the corpse and then resume the speedwalking once the monster was dead.
If you ALWAYS wanted to pause in a room before automatically taking the next step, you can set the "Pause during speedwalk" option for the room. That prevents the #OK command from being executed for the room and prevents the #STEP from being executed at the MUD prompt. This allows you to use a room script to check for certain conditions before continuing. For example, you might have a room script like:
#TRIGGER {the door is open} {#STEP}
which would only continue the speedwalking only if the door was already open. Or, perhaps you are at a boat landing and you need to wait for a boat before continuing the speedwalk. In that case, you might use a Room Script like:
#TRIGGER {the boat arrives} {enter boat;#STEP}
Of course, this would resume your speedwalk as soon as you stepped onto the boat. What you'd probably want to do instead is something like:
#TRIGGER {the boat arrives} {enter boat}
#CONDITION {the boat has reached its destination} {exit boat;#STEP}
With the Pause option set for the room, this would wait until the boat arrives and automatically board the boat. Then using a second trigger state it would wait until the boat reaches its destination and automatically exit the boat and resume your speedwalking path.
Sometimes when you set the "Pause during speedwalk" flag, you only want to block movement in a certain direction. You can test the next direction in the speedwalk queue using the %nextdir function. So, perhaps you only want to wait for the boat if the next direction is "east" but want to continue the speedwalk if the next direction is "north" along the coast of the water. In that case, you could add a trigger like this to the Room Script:
#IF (%nextdir = "n") {#STEP}
which will automatically resume the speedwalk if you are walking north instead of trying to cross the river. If you used a script like this:
#IF (%nextdir = "n") {#OK}
then the next step in the speedwalk will only be sent automatically when the next MUD prompt is received.
As you can see, #PAUSE and #STEP are the most common map script commands that you will use in a room script. As mentioned, the #OK command is used internally by zMUD to confirm a speedwalk step using the room name or room description. If you have a room without a description or a room who's name or description changes, you might need to set up your own #OK trigger to continue the speedwalk. You might set up a Room Script like:
#TRIGGER {Exits:} {#OK}
to confirm the step whenever the exits to the room are displayed. This kind of technique can be useful in speedwalk through mazes. This will cause zMUD to send the #STEP command when the next MUD prompt is displayed. It's ok to send multiple #OK commands. Even if zMUD executes #OK when it received the room name, and your own trigger executed #OK when the Exit line was received, only a single #STEP command will be issued when the next MUD prompt is received.
If your MUD does not have a prompt, you might need to set up your own #STEP trigger. For example, if the MUD displays a blank line after the room name and description, you can use that to take the next step if an #OK command has been executed. Just something like:
#TRIGGER {^$} {#IF (%walkconfirm) {#STEP}}
to match a blank line would work fine. The #STEP command will only send the next step to the MUD if the speedwalk was confirmed by the #OK command (%walkconfirm returns True if the #OK command has fired for that step in the speedwalk).
Slow Walk Mode is the easiest mode to write scripts for because the mapper position and the MUD room position are always in synch. Since you always know what room you are in, it's easy to execute commands.
But in Safe and Fast mode, scripting can be trickier, and depends a lot on the specific timing of the MUD and when scripts are executed in zMUD. There are two different types of Room Scripts that you can define in zMUD. The normal room script is executed just after the current position is updated on the map. The other type of Room Script is called the Walk Script for the room and is executed just after the direction is sent to the MUD that would cause you to walk into the room. A global "onroomwalk" alias is also executed after each direction is sent to the MUD (before any Send Line delay).
To illustrate the differences between normal room scripts and Walk scripts, let's take a more detailed look at the Safe Walk timeline:
Active Walk Script | A | B | C | D | E | F | G | |||||||||||||||||||||||||
Sent TO MUD | e | n | e | s | open east | e | enter | |||||||||||||||||||||||||
Received FROM MUD | B | C | D | E | F | G | ||||||||||||||||||||||||||
Map Position | A | B | C | D | E | F | G | |||||||||||||||||||||||||
Active Room Script | A | B | C | D | E | F | G |
You can see that Room Scripts and Walk Scripts are executed at completely different times! When Walk Scripts are executed in Safe Walk mode, no text is being received from the MUD. So, it doesn't make any sense to put any sort of Trigger command in a Walk Script. So, why would you ever use a Walk Script instead of a Room Script?
Let's imagine that room B is a store and you always want to automatically display the stuff being sold in the store when you enter the room. In this case you might put a command like "list" into the Walk Script for room B (assuming "list" is the command on the MUD to display the store contents). So now, after the "east" command is sent to move from room A to room B, the Walk Script for room B would then send the "list" command to the MUD. So later, after the room description of room B is display, the contents of the store in room B will also be displayed.
Keep in mind that the automatic #OK trigger fires on either the room name or first line of room description. The Room Script is executed just after the #OK command executes. So, everything after the first line of room description can be tested by triggers in the Room Script.
Let's say you want to pause the speedwalking if the store is selling a particular item. Well, the display of the store contents is happening right after the room description for room B is received FROM the MUD. During that time, the normal Room Script for room B is active. So, you might do something like:
#TRIGGER {Cool sword} {#PAUSE}
to pause the speedwalk if the store is selling a "Cool sword". Do you see the problem?
If you really understand how speedwalking works, you will see that it's already too late. In SAFE mode, all of your speedwalk directions have already been sent to the MUD by the time the Room Script for Room B executes. So, you'll still run right past the store without stopping. If you don't understand why this doesn't work, go back and re-read the previous sections. It's very important to understand how this timing works.
So, how do you solve this problem? The preferred method to solve this problem is to turn on the "Pause during speedwalking" option in the Room B store. This will force zMUD to stop sending directions after Room B until the movement is confirmed. The "Pause during speedwalking" option ALSO PREVENTS the automatic #OK trigger from being generated for the room. The Room Script is executed just after the speedwalking is paused. So in this case, the entire room description is available for testing via triggers in the room script.
With the Pause option set, zMUD will send the "east" command to move from room A to B and will then execute the Walk Script for room B and send the "list" command to the MUD. Then it will update the map position and execute the Room Script. Our previous "Cool sword" trigger will be executed and will #PAUSE, but we are already paused! This is where we use #OK ourselves to confirm the room to keep walking. So, in the room script you can add:
#TRIGGER {The store is selling the following items:} {#OK}
This will confirm the previous speedwalk step and will get ready to send the #STEP command at the next MUD prompt to continue the speedwalk. But now our "Cool Sword" trigger will #PAUSE again if the sword is listed in the stuff for sale at the store. With the speedwalk pauses, the #STEP command issued by the MUD prompt won't be executed.
One potential timing issue can further complicate your script in Safe mode when using the "Pause during speedwalk" option. Imagine for a moment that instead of setting Room B as a "Pause during speedwalk" room, you set the Pause flag for room C. Now, when you speedwalk, zMUD will send the "east" command to move to Room B, then it will send the "north" command to move to room C. It will then execute the Walk Script for room C, will Pause the speedwalking, then execute the Room Script for room C. Then it waits for all of the MUD input to be processed. So, any triggers in your Room Script are able to trigger on the entire room description of room C. But in addition, these triggers are also active when the room description for the previous room B is displayed. Any output from when the speedwalk started until it was paused will be seen by your Room Script. So, be sure not to accidentally trigger on text from a past room. You can use a multi-state trigger to help with this situation, like this:
#TRIGGER {Room C Name} {}
#CONDITION {contents of room C} {do something}
which will ensure that the name of Room C is received before you process any text in the room description.
By know you should have the hang of this. In Fast Mode, again your Walk Scripts are executed just after the direction to move into the room is sent to the MUD. Your Room Scripts are executed just after the current map position is updated. So, the script timeline for Fast mode looks like this:
Active Walk Script | A | B | C | D | E | F | G | |||||||||||||||||||||||||
Sent TO MUD | e | n | e | s | open east | e | enter | |||||||||||||||||||||||||
Received FROM MUD | B | C | D | E | F | G | ||||||||||||||||||||||||||
Map Position | A | B | C | D | E | F | G | |||||||||||||||||||||||||
Active Room Script | A | B | C | D | E | F | G |
So you can see that the problem with Fast Walk mode is that none of your scripts are able to respond to anything displayed by the MUD since the MUD output is processed well after all of the speedwalk scripts have been executed.
However, the "Pause during speedwalk" flag still works in Fast mode. So, like in the Safe Walk example, setting the "Pause during speedwalk" flag for Room B would ensure that the room description of room B was displayed and could be processed. Again, the "Pause during speedwalk" flag causes the speedwalk to be halted immediately, and any output from the MUD is processed before continuing.
Now you see why it is much better to use the "Pause during speedwalk" flag rather than relying upon a #PAUSE command in a room script. By the time the script is executed, it might be too late to pause. You might think you could simulate the "Pause during speedwalk" by putting the #PAUSE command in your Walk Script, but this will not prevent the automatic #OK trigger from being generated, unless you have turned off the Automatic Room Matching option in the map preferences globally.
In addition to being able to detect the Room name, description, and exits, it's very important for the mapper to be able to detect your MUD prompt. A regular expression trigger is created using the pattern given in the Prompt Trigger field in the MUD Prompt configuration preferences in the mapper properties. Set this value to trigger on your MUD prompt.
If your MUD does not have a prompt, you can turn off the use of the MUD prompt in the preferences. When you do this, the next step in the speedwalk will be sent when the #OK command is executed, rather than waiting for a MUD prompt. This will allow the mapper to follow your movement around the MUD, but might prevent you from controlling the speedwalking with scripts since the next direction in the queue might be sent before you have a chance to stop it.
The mapper has been designed so that most of the time it works in the way you would expect it to. However, you can see some of the complexities involved in timing things so that they happen at just the right moment. Older versions of zMUD were not sophisticated enough to handle the timing properly, which made scripting the speedwalking a nightmare. In the new versions, the information from this article should help you understand how the mapper is working and how your scripts can influence it.