[Previous](ch11.html) [Index](index.html) [Next](ch13.html)

---

#12 - Interfaces

####Table of Contents

* [12.1 Introduction to interfaces](#12.1)
* [12.2 WAITTRIG](#12.2)
* [12.3 ADDTRIG](#12.3)
* [12.4 ADDALIAS, ADDMACRO, ADDTIMER and ADDHOOK](#12.4)
* [12.5 DELTRIG, DELALIAS, DELMACRO, DELTIMER and DELHOOK](#12.5)
* [12.6 Interfaces for profiles](#12.6)
* [12.7 Interfaces and main loops](#12.7)
* [12.8 Interface notifications](#12.8)
* [12.9 Retrieving notifications](#12.9)
* [12.10 Advanced notifications](#12.10)
* [12.11 Skipping notifications](#12.11)
* [12.12 DELIFACE](#12.12)
* [12.13 Starting a new script with SETTRIG](#12.13)
* [12.14 Future plans](#12.14)

---

##<a name="12.1">12.1 Introduction to interfaces</a>

Axmud interacts with the world using *triggers*, *aliases*, *macros*, *timers* and *hooks*. These are collectively called *interfaces*.

Interfaces have a *stimulus* and a *response*. In other words, when something happens (the stimulus), Axmud takes some form of action (the response).

* A **trigger** waits for the world to send a line matching a particular pattern
* An **alias** waits for you to type a world command that matches a particular pattern
* A **macro** waits for you to press a key (or a combination of keys)
* A **timer** waits for a certain period of time
* A **hook** waits for some kind of event to happen

The [Axmud Guide](../guide/index.html) discusses interfaces in detail. In this Section we'll discuss how scripts can interact with their own interfaces.

##<a name="12.2">12.2 WAITTRIG</a>

In [Section 4](ch04.html) we introduced the WAITTRIG statement, which creates a temporary trigger. The trigger waits for the world to send a line matching a certain pattern, in this case a line containing the word **opens**.

        WAITTRIG "opens"

When the trigger notices a matching line, it takes some kind of action. We say that the trigger *fires*. Until then, the Axbasic script is paused. (In the previous Section we discussed pauses and mentioned that Axbasic scripts with pauses must be run as a task.)

When the temporary trigger created by WAITTRIG fires, it deletes itself and the script resumes execution. (When the script stops running, Axmud will automatically delete any triggers it created.)

In [Section 4](ch04.html) we also discussed using a timeout. In this example, if the trigger doesn't fire within 60 seconds, the Axbasic script resumes running (and the trigger is deleted, never having fired).

        WAITTRIG "opens", 60

By the way, there is no WAITALIAS statement, and there are no WAITMACRO, WAITTIMER or WAITHOOK statements. There are better ways of handling those types of interface.

##<a name="12.3">12.3 ADDTRIG</a>

ADDTRIG also creates a trigger, but the script doesn't wait around for a response; it just creates the trigger and then executes the next statement. As a result, the trigger doesn't interact with the script directly.

ADDTRIG expects three arguments - a stimulus, a response and (optionally) a trigger name. If you don't specify a name, Axmud will choose a name for you.

This example creates a trigger that waits for a line containing the word **treasure**, and then sends the world command **get treasure** in response.

        ADDTRIG "treasure", "get treasure"

An ADDTRIG statement behaves just like the client command **;addtrigger**, except for one important detail - when the Axbasic script stops running, the trigger is deleted automatically.

Of course, if you *don't* want the trigger to be deleted automatically, you can create a permanent trigger. If you were typing a client command, you would type:

        ;addtrigger -s treasure -p <get treasure>

But in an Axbasic script, you would use a CLIENT statement:

        CLIENT "addtrigger -s treasure -p <get treasure>"

If you're not sure how to compose a client command in the correct format, you can consult the [Axmud Guide](../guide/index.html) or just type

        ;help addtrigger

(Note that **;addtrigger** is expecting a response that contains no spaces. Because our **get treasure** response contains spaces, we need to enclose it within diamond brackets.)

##<a name="12.4">12.4 ADDALIAS, ADDMACRO, ADDTIMER and ADDHOOK</a>

ADDALIAS, ADDMACRO and so on behave in the same was as ADDTRIG, and use the same three arguments - a stimulus, a response and an optional name.

        ADDALIAS "^gt$", "get treasure"
        ADDMACRO "f1", "kill orc"
        ADDTIMER 60, "score"
        ADDHOOK "lose_focus", "sleep"

In each case, the interface is deleted automatically when the script stops running.

##<a name="12.5">12.5 DELTRIG, DELALIAS, DELMACRO, DELTIMER and DELHOOK</a>

The opposite of ADDTRIG is DELTRIG.

To delete a trigger, you need to know its name. If you don't know the name, then you need to modify your script to specify one.

        ADDTRIG "treasure", "get treasure", "mytrigger"
        SLEEP 60
        DELTRIG "mytrigger"

DELALIAS, DELMACRO, DELTIMER and DELHOOK behave in exactly the same way. In fact, these five statements are the equivalent of the client commands **;deletetrigger**, **;deletealias** and so on.

All five statements can be used to delete an interface that was created by a different script, or which you have created yourself. This is behaviour is, in general, not a good idea.

By the way, if you try to delete a trigger that doesn't exist, you'll see a system error message (but the Axbasic script will keep running).

##<a name="12.6">12.6 Interfaces for profiles</a>

Axmud interfaces are available, by default, whenever you connect to a particular world. That is to say, if you're connected to *Discworld* and you run the following script, the trigger it creates will not be available when you connect to *Cryosphere.*

        ADDTRIG "treasure", "get treasure"
        END

However, it's possible to tie interfaces to a particular character, so that they're only available when you're playing that character. You could also tie your interfaces to a particular guild  or a particular race, so that they're only available when you're playing a character of that guild or race. (This is explained in detail in the [Axmud Guide](../guide/index.html).)

By default, a trigger created with ADDTRIG is tied to the current world profile. It's available whenever you connect to that world, regardless of which character you're playing.

If you want to create triggers tied to a particular character profile, you can use the PROFILE statement.

        PROFILE "gandalf"

After a PROFILE statement, ADDTRIG statements will create triggers tied to that profile. This behaviour continues until you use a different PROFILE statement.

If you want to go back to creating triggers with the current world, just use PROFILE on its own.

        ! This trigger is available to characters who
        ! are members of the thief guild
        PROFILE "thief"
        ADDTRIG "orc", "backstab orc"

        ! This trigger is available to all characters
        PROFILE
        ADDTRIG "troll", "escape"

The PROFILE statement also affects DELTRIG. Ordinarily, DELTRIG deletes the trigger that's tied to the current world profile. If you have specified a different profile using a PROFILE statement, the trigger tied to that profile is deleted instead.

ADDALIAS, ADDMACRO and so on, as well as DELALIAS, DELMACRO and so on, are all affected by a PROFILE statement in exactly the same way. (WAITTRIG isn't affected at all.)

By the way, the **Showprofile$ ()** function returns the name of the profile currently used by the statements ADDTRIG, DELTRIG (and so on).

        PRINT Showprofile$ ()

##<a name="12.7">12.7 Interfaces and main loops</a>

So far, the interfaces we've created don't really interact with script in any meaningful way.

In some respects, BASIC is a poor choice of language for interacting with interfaces. In many scripting languages, a script does nothing until one of its subroutines or functions is actually called.

That's not possible in Axbasic, at least not *directly*. If you need your scripts to interact with interfaces, you should design them with a *main loop*, as discussed in the previous Section.

This is roughly how it works:

* The Axbasic script must be run as a task
* Several times a second, Axmud calls the task
* On each call, the main loop runs once
* The main loop code checks all the interfaces created by the script
    * If an interface has fired, the code calls a subroutine or a function
    * If no interface has fired recently, nothing happens

Of course, dedicated scripting languages like Lua (or Perl, for that matter) handle this kind of thing much more efficiently. For most purposes, though, Axbasic is *good enough*.

##<a name="12.8">12.8 Interface notifications</a>

Let's create a complete script that creates a trigger and uses a main loop to check it continuously.

The trigger is created with a SETTRIG statement.

        SETTRIG "treasure"

We use a SETTRIG statement because, when the trigger fires, Axmud sends an *interface notification* to the script. The notification contains information about the fired trigger.

When the script receives an interface notification, nothing happens immediately; the notification is just stored. If the same trigger fires ten times, then ten separate notifications are stored in the order they're received.

When your script is ready, it can retrieve the first notification and take action. That notification can then be discarded. The script can continue retrieving and discarding notifications until there are none left.

##<a name="12.9">12.9 Retrieving notifications</a>

The **Ifacecount ()** function returns the number of interface notifications the script has received (and not yet discarded).

        LET count = Ifacecount ()

If more than one notification has been received, we deal with them one at a time. The **Ifacename$ ()** function gets the name of the trigger that generated the first notification.

        LET name$ = Ifacename$ ()

When you use SETTRIG, Axbasic chooses a suitable trigger name. You can't specify one for yourself.

If your script uses only one SETTRIG statement, then you don't need to know the trigger name that was chosen. Any notification that's received must originate from that single trigger.

However, if your script contains multiple SETTRIG statements, you'll need to keep track of them. The **Iface$ ()** function returns the name of the trigger created by the most recent SETTRIG statement.

Ordinarily, every SETTRIG statement should be followed by an **Iface$ ()** function.

        ! Create a trigger and store its name
        SETTRIG "treasure"
        LET treasure_trigger$ = Iface$ ()

If you know which trigger fired, you can take whatever action is required, for example:

        IF Ifacename$ () = treasure_trigger$ THEN CALL GetStuff

Once that's done, we can discard the notification using a NEXTIFACE statement.

Here is the complete script. Once per main loop, the earliest remaining notification (if any) is retrieved, a subroutine is called, and the notification is then discarded.

        OPTION NEEDTASK

        ! Create a trigger and store its name
        SETTRIG "treasure"
        LET treasure_trigger$ = Iface$ ()

        ! Main loop
        WHILE 1

            ! Retrieve the first notification...
            IF Ifacecount () > 1 THEN
                IF Ifacename$ () = treasure_trigger$ THEN
                    CALL GetStuff
                END IF
            END IF

            ! ...and discard it, ready for the next main loop
            NEXTIFACE

        LOOP

        END

        ! This subroutine is called if the treasure trigger fires
        SUB GetStuff
            SEND "get treasure"
            SEND "put treasure in sack"
        END SUB

Actually, if no notifications have been received, **Ifacename$ ()** returns an empty string. Therefore we could simplify the main loop by removing the **Ifacecount ()** line entirely.

        WHILE 1
            IF Ifacename$ () = treasure_trigger$ THEN
                CALL GetStuff
            END IF
            NEXTIFACE
        LOOP

##<a name="12.10">12.10 Advanced notifications</a>

An interface notification tells us the name of the trigger that fired, but also a lot more besides. There are several functions for retrieving the additional information, if you need it.

The **Ifacetext$ ()** function returns the line that caused the trigger to fire.

        LET line$ = Ifacetext$ ()

The **Ifacetime ()** function returns the time at which the trigger fired. The time is expressed as the number of seconds since the current session started.

The **Timestamp ()** function also returns a time expressed in this way, so we can work out how long ago the trigger fired by subtracting one from the other.

        LET interval = Timestamp () - Ifacetime ()

Axmud gives each active trigger a unique number. This probably isn't very useful, but nevertheless you can retrieve the number using the **Ifacenum ()** function, if you want to.

        LET number = Ifacenum ()

The **Ifacetype ()** function returns the type of interface that fired, in other words the string **"trigger"**.

Triggers test a pattern against a line of text. The **Ifacestrings ()** function returns the number of matching substrings. (See the regular expression tutorial in the [Axmud Guide](../guide/index.html) if you don't know what that means.)

The contents of those substrings can be retrieved using the **Ifaceshift$ ()** and **Ifacepop$ ()** functions. Both of those functions *remove* the matching substring from the notification, so you can use them several times until there are no more substrings left. **Ifaceshift$ ()** removes the first matching substring, and **Ifacepop$ ()** removes the last matching substring.

##<a name="12.11">12.11 Skipping notifications</a>

By default, these functions work on the *earliest* notification received. Usually, you'll retrieve the information you want, and then discard the notification, ready for the next one.

However, if you want to retrieve information from a different notification, you can use a SKIPIFACE statement.

Functions like **Ifacename$ ()** work on the *current* notification, which is usually the earliest remaining one. A SKIPIFACE statement changes the current notification to the next one in the list.

        ! Get the name of the trigger that generated
        ! the earliest notification
        LET first$ = Ifacename$ ()

        ! Get the name of the trigger that generated
        ! the notification after that
        SKIPIFACE
        LET second$ = Ifacename$ ()

If only one notification remains, then SKIPIFACE will have no effect. If there are ten remaining notifications and you've already used SKIPIFACE nine times, then the next SKIPIFACE statements moves back to the beginning of the list.

The **Ifacepos ()** function returns the number of the current notification. By default, it returns 1, representing the earliest remaining notification. If you've used SKIPIFACE once, it would return 2, representing the second notification on the list. (If no notifications have been received, or if they have all been discarded, it returns 0.)

##<a name="12.12">12.12 DELIFACE</a>

An *active interface* is one that's currently available. We've discussed how triggers, aliases and so on can be tied to a particular character profile. Those interfaces are only active when you're playing the right character.

A DELIFACE statement can be used to delete an active interface. As mentioned above, you shouldn't normally use Axbasic scripts to delete interfaces created by something else:

          DELIFACE "status_task_trigger_11"

You shouldn't use DELIFACE to delete triggers created with an ADDTRIG statement, either; use DELTRIG to do that. (The reason for this is a bit complicated, but we can summarise by saying that an active interface might not have the name you were expecting it to have.)

However, DELIFACE *is* the recommended way to delete a trigger created with a SETTRIG or a WAITTRIG statement.

If you want to be clever, you can delete the trigger that generated the current interface notification using a line like this:

          DELIFACE Ifacename$ ()

##<a name="12.13">12.13 Starting a new script with SETTRIG</a>

SETTRIG creates a trigger. When the trigger fires, the Axbasic script receives a notification, which can be retrieved when the script is ready.

However, SETTRIG has a second purpose: it can be used to run a different Axbasic script. If this is what you want, specify both the trigger stimulus and the name of the other Axbasic script:

        SETTRIG "You are dead", "prayer_script"

The new script is not run as a task. The original Axbasic script does not receive an interface notification.

##<a name="12.14">12.14 Future plans</a>

At the time of writing, there are no SETALIAS, SETMACRO, SETTIMER or SETHOOK statements.

---

[Previous](ch11.html) [Index](index.html) [Next](ch13.html)
