M_TRIGGERS The M_TRIGGERS module is designed to work with the M_ACTIONS module, so inherit that as well. M_TRIGGERS is separate because it causes an object to parse everything it sees, which can be expensive in terms of CPU time, and is unecessary for objects that do not use it. M_TRIGGERS is implemented using a catch_tell() function. If you override this function, M_TRIGGERS will fail to work. The main interface is through 'add_pattern' and 'add_sub_pattern'. The simplest use is as follows: add_pattern("The door slides open.", "say Wow!"); This will cause the object to say "Wow!" whenever it sees the first phrase. The pattern can either be an exact match, or it can be a pattern for sscanf() with either 1 or 2 arguments. (Note for power users: sscanf can handle regexps, so patterns like: "%([a-zA-Z]*@[a-zA-Z]*) tells you: %s" are legal). For example: add_pattern("%s smiles.", "smile"); will cause your object to smile whenever anyone in the room smiles. The response can also be a function pointer, in which the arguments from sscanf are passed to the function pointer, allowing you to do different things depending on what the matched argument was: add_pattern("%s smiles.", (: "slap " + $1 :)); // we're in a bad mood Multiple patterns may be added, and each will be tried until one returns a valid command. *** add_sub_pattern *** add_sub_pattern() can be used to create more complex behaviors. First, some terminology. A 'pattern' is a string to match and an 'action'. In the above examples we omitted the fact that add_pattern can actually take two more arguments specifying 'rule's for the first and second parts which were matched by the pattern. What is a 'rule'? A 'rule' s a list of 'pattern's which are associated with a name. The to level patterns (which are added by add_pattern) are actually members of the rule named '0'. You can add a pattern which has a sub rule as follows: // specify first arg uses "smile_sub_rule" add_pattern("%s smiles.", (: my_smile_action :), "smile_sub_rule"); // specify second arg uses "say_rule" add_pattern("%s says %s.", (: handle_say :), 0, "say_rule"); Now, we saw above that the 'piece's that matches each part of the pattern passed as strings to the 'action'. That is actually the _default_ behavior, when no subrule exists. If a subrule exists and one of the patterns in that subrule matches the 'piece', the result of the subpattern's 'action' is substituted for the 'piece'. Patterns are added to subrules as follows: varargs void add_sub_pattern(rule, pattern, action, left, right); sub patterns can have their own sub rules ad infinitum. If all this is a bit confusing, here is a quick example: // no left subrule, right subrule is "kick_sub_rule" add_pattern("%s kicks %s.", (: $2 :), 0, "kick_sub_rule"); add_sub_pattern("kick_sub_rule", "you", "say Hey! stop that!"); // default add_sub_pattern("kick_sub_rule", 0, (: "say Yeah, " + $1 + " is a piece of junk." :) ); A zero 'pattern' matches anything. When the object sees: Foo kicks bar. It matches the first 'pattern', with the left side being "Foo" and the right side being "bar". We have no left subrules, so we leave that alone. Now we try to parse "bar" according to the right sub rules. "bar" does not match "you", so we go on to the next one. It DOES match 0, so we evaluate the function for this subrule, creating the string "say Yeah, bar is a piece of junk.". The top level 'action' is then called with the args ("Foo", "say Yeah, bar is a piece of junk.") returning the second string. That string is then interpreted as a command. When the object sees: Foo kicks you. It matches the first 'pattern', with the left side being "Foo" and the right side being "you". This time, the "you" 'pattern' matches. The action is simply a string so we return that to the level above. The top level function gets called with ("Foo", "say Hey! stop that!"), and again the second string is taken as a command. Note: What is passed between levels is completely arbitrary, since it is generated by a user function, and interpreted by a user function. The above example followed the convention that a string command is passed back up. The following example passes up a function pointer to be evaluated. (This is a much more involved example, a bit of lispish-ness may be noted here :) ) int starts_with(string str, string pref) { return str[0..strlen(pref)-1] == pref; } int ends_with(string str, string suff) { return str[