8.2. Basic Triggers

The simplest kind of trigger specifies only a pattern and an action. Below these parameters are described in detail.

What exactly is pattern? It is a regular expression. In short, a regular expression is a way to specify text patterns that are looked for in the lines that the server sends. If you know Perl, you certainly know what is a regular expression. If not, it is advised that you look for some more information on it, there are plenty of tutorials on the Internet. For those who know them, you can use the full power of Perl's regular expressions in triggers, because Perl is used for the matching.

What about the action? It can be anything that could be entered in the command line. It can be a simple command, that is sent to the MUD. Or you can send several commands at separating them with %; as described in Section 3.2, “Interacting with the MUD”. Finally, you can execute some Perl code when a trigger matches, and this allows you to do virtually anything you want.

Below is an example of a very simple trigger. To create this trigger, inform the Pattern and Action parameters shown below. Leave the other parameters in their default values.

Example 8.1. A very simple trigger
  • Pattern: has attacked you!

  • Action: wield sword

Whenever a line that contains the phrase "has attacked you!" is received, the command "wield sword" will be automatically be sent. Note that in this case the received line will probably be something like "An orc has attacked you!", but the trigger matches because that line contains the pattern. This is a feature of regular expressions. If you want to match the entire line and not only part of it, you must use the ^ and $ anchors in the beginning and end, respectively.

By default, case is considered when matching: if the server sent a line saying "Has Attacked" then there would be no match. To make case be ignored when matching, check the Ignore case when matching option.

It is also possible for the action to be executed to depend on what was received from the server. This is better explained by an example:

Example 8.2. A trigger which captures part of the received line and uses it in the action
  • Pattern: ^(.*) has attacked you!$

  • Action: cast missile $1

There are two new things in the pattern. The first one is that is surrounded by ^ and $ which means that the entire line must match, as described previously. The other new thing (and the one that concerns us at this moment) is the (.*) part. In regular expressions, the dot means to match any character. The asterisk means zero or more of the previous element. So the combination .* means zero or more of any characters. Essentially, it matches anything. The brackets () around any part of a regular expression captures part of the string to be used afterwards. So the whole regular expression means: look for a line that contains something followed by has attacked you!. What comes before has attacked you! is stored for later use.

This stored string is then used in the action by means of the $1 construct. This special placeholder is substituted by what was captured in the matched string. So if the line Orc has attacked you! is received, cast missile Orc is send. If Smaug has attacked you! is received, then cast missile Smaug is sent to the World, and so on.

It is possible to have more than one captured string in the pattern. In this case, $1 is replaced by what was captured in the first group, $2 by the second group, and so on.

Sending commands to the World is useful, but the real power is the fact that you can also run Perl commands in response to triggers. Just enter them as you would in the command box: prefixed by /. If the action is simple you can enter the statements there directly, if not, you can define a function in your script file and call it from the trigger.

Let us rewrite Example 8.2, “A trigger which captures part of the received line and uses it in the action” to use Perl in the action:

Example 8.3. A trigger with an action in Perl
  • Pattern: ^(.*) has attacked you!$

  • Action: /$world->send("cast missile $_[1]")

This time, when a line consisting of some arbitrary text followed by "has attacked you!" is received, the $world->send will be called to send some text to the World.

You may have noticed that here $_[1] was used instead of $1 in the action to represent the first captured bracketed group. The reason for this is complex, and if you do not want to worry about the inner workings, just use the following rule: in commands sent to the mud, use $1, $2, etc., and in actions that are Perl commands, use $_[1], $_[2] and so on.

Here are the details for the different syntaxes. Feel free to skip the next two paragraphs:

When a trigger matches, KildClient substitutes $1 (and the other placeholders) by the captured expressions from the received line. However, $_[1] (and the other similar tokens) are not replaced by KildClient. If the action is just a string sent to the mud, they would not be replaced, so the only possibility to use the captured groups is with the $1 syntax. But Perl commands can access the captured groups in another way: the strings are stored in the @_ array. The first position, $_[0] contains the whole matched line. Subsequent positions contain each matched grouped expression, so $_[1] is the first bracketed substring, $_[2] is the second, and so on. This way, when a Perl command is executed the values are replaced by the Perl interpreter itself.

It is also possible to use $1 in commands to be passed to the Perl interpreter. Most of the time it will work, but in some specific circumstances you may get unexpected results. So it's preferable to let Perl do the substitution when commands are to be run by the Perl interpreter.

If you call a sub-routine as the trigger action, the matched arguments are not automatically passed, so you need to pass them manually. Since they are in the array @_, just pass that whole array as the argument to the sub-routine. Inside the sub-routine, they will be available as the sub-routine's arguments, which incidentally means that they will be accessed in the exact same way: with $_[1], $_[2] and so on. Alternatively, you can only pass the parameters that you need instead of the whole array.

Here's an example of a trigger that calls a sub-routine:

Example 8.4. A trigger that calls a sub-routine
  • Pattern: ^(.*) has attacked you!$

  • Action: /myGreatAttackSequence(@_)

Naturally, you need to define the myGreatAttackSequence sub-routine in your script file. It will be called as the result of the trigger. The @_ array, containing the whole matched line and the matched bracketed expressions is passed to the sub-routine as argument, and its contents will be available to the sub-routine as its parameters.