BSAgent Engine BotScript Introductory Tutorial - Solifugus/bsagent GitHub Wiki
The Overall Flow
Basically when a users enters a statement, the statement is passed into the BSAgent Engine which, interpreting according to its currently loaded botscript, takes decides upon a reaction and performs whatever actions sequences the chosen reaction holds. Only a concurrently valid reaction may be chosen, based on any conditions it may have. Actions may include things like remembering something, recalling something, or replying with something (for example). All of this must be coded into the botscript.
In processing a statement, the BSAgent Engine runs through its loaded botscript in order, from top to bottom. Commands prior to any "Upon Hearing" directive, are executed unconditionally. Actions after one "Upon hearing" directive but before the next, may only happen if the user's statement matches the pattern specified by the "Upon hearing" directive. And furthermore, the action commands after a "Condition" directive are only validly chosable if the condition specified with it is concurrently true.
Directives
Directives structure a script by separating where commands are and are not valid. Directives are as follows:
Upon Hearing:text pattern
Commands before the first "Upon Hearing" directive are executed with every user statement, in order. Commands and "Consider If" directives are valid only when the "Upon Hearing" directive's specified pattern matches the user's statement, and only up to the next "Upon hearing" directive (or end of file).
Consider If:condition
Commands after a "Consider If" directive should only be valid if the directive's specified condition is true. And among valid ones, only one may be chosen per user statement.
Patterns
Patterns may be employed to identify or generate text in various places. Everywhere except the "Upon Hearing" directive, a pattern should be in quotes. Also, variable components of a pattern may be specified by enclosing the variable name in square brackets. Either a quote or a square bracket may be escaped with a backslash, if you need to use them as part of the pattern itself.
Upon matching a pattern (any kind of read operation), if a variable name used has already been assigned then it is populated as such in the pattern. Otherwise, the variable acts as a wildcard in the pattern match operation. That is, all matches are retrieved and the variable name is assigned accordingly. For example, Upon Hearing: my favorite food is [food]
will assign "cake" if the user statement is "My favorite food is cake.". However, the Recall "[user] has [food]"
command would seek any user's who's favorite food is "cake" because we've already assigned the variable [cake]
but not [person]
. So the recall command would assign [person]
with every matching value in memory... those who have cake, in this case..
In a write operation, such as the pattern given to the "Say "pattern"" command, assigned variables are transformed to the values they hold (could be a comma separated list of recalled values). If a variable is not assigned then the variable name itself is left. Also, any conjugations defined are transformed. For example, if the variable [person]
is assigned "bob", "fred", and "sally" but [food]
is not assigned any value then the Say "I know that [person] has [food]."
will transform to generate "I know that bob, fred, sally has food.". To smooth this out, you may specify to use "and" or "or" where there might be multiple values, such as Say "I know that [and:person] has [food]."
Commands
Available Commands are listed below. For timings, a command may be suffixed with a timing specification such as " in 10 minutes" or "at 5:00pm".
Mostly Useful Early in Script:
- Synonyms word:other, words, with, same, meaning
- Group word:list, of, other, words
- Conjugate "word1" To "word2"
- Always Recall variable
Mostly Useful As a Reaction:
- Say "pattern"
- Remember "pattern"
- Recall "pattern"
- Forget "pattern"
- Expect "pattern" As "pattern"
- Interpret As "pattern"
- Request "RESTful call"
Conditions
Conditions are specified logic. The logic may comprise of pattern count comparisons plus And, Or, Not, and parenthesis. For example: Consider If: "[user]'s favorite food is [food]" > 3 Or "[user] likes all food"
will evaluate as true if the the variable "[user]" is currently assigned "Bob" and the following is currently remembered into memory:
Bob's favorite food is cake
Bob's favorite food is icecream
Bob's favorite food is apples
Bob likes all food
The first part of the condition is false because there are only 3 matches and it's asking for more than three matches. However, the second part is true because there is at least one match to "[user] likes all food". If no numerical operator is specified then zero matches is false and anything more is true.
More Complete Example
The following is very brief but complete, in a sense:
-- Synonyms specify that various words may be interpreted the same
Synonyms yes:yep, yeah, sure
Synonyms no:nah, nope
Synonyms hello:hi, howdy
-- Conjugations are terms to change when replying to the user..
Conjugate "me" To "you"
Conjugate "you" To "me"
Conjugate "my" To "your"
Conjugate "your To "my"
-- Variables to keep in working memory between statements
Always Recall it
-- On the opening of a new session with a user
Upon Hearing:~new session
Say "Hello."
Remember "said hello to user"
-- This is a way to program responses to "Hello"
Upon Hearing:hello
Consider If: "user name is [name]" = 0
Say "What is your name?"
Expect "[name]" As "My name is [name]."
Consider If: "user name is [user]" > 0
Say "So what can I do for you, [name]?"
-- This illustrates some logic that works with the above.. Upon Hearing:my name is [name] Consider If:"user name is [already] > 0 Say "I thought your name was [already]? I will assume you have multiple names." Remember "user name is [name]" Consider If:"user name is [known]" = 0 Say "I will remember you, [name]." Remember "user name is [name]"
-- This illustrates how to forget something and to assume the user said something else ("Hello", in this case) Upon Hearing "my name is not [name]" Forget "user name is [name]" Interpret As "Hello"