Notepad+AIML (AIMLpad or Alice Program N) System Design

 

Introduction

 

While using the AliCE program written by Jacco Bikker which was developed (I think) from the AliceC version of the AIML engine, I became frustrated with its bad habit of locking up my Pocket PC.  Furthermore I didn’t like the way it wrote the conversation over the top of the input buttons.  So first I rewrote it take input from a textbox in a dialog and display the conversation scrolling down a multi-line textbox.  I was able to at least begin to hold a discussion with the machine.

 

I soon grew impatient to add to the list of responses.  But AliCE had no editor.  In fact, it did not even have a way of using AIML which is what I supposed it was based on.  So I added the learn function and became immersed in the world of AIML.  I discovered there are several versions with the latest standard being 1.01.  So I set about upgrading the database in AliCE to become compliant with the last published language documentation.

 

In the course of this research, I had the opportunity to load various AIML sets that were available from the www.alicebot.org website.  I had to get an emacs editor to read them because the Windows notepad would not correctly interpret the linefeeds.  Of course, I got AliceD to try the AIML out on my desktop.  I wanted to be able to edit the categories right at the Pocket PC.  So then I decided that I needed an ASCII text editor that could look at the AIML when I was using it “out in the wild”.  Thus the notepad paradigm was adopted.

 

I had to fix the AIML engine to run the test suite I found on the alicebot website.  I found that some of my test cases weren’t correct.  Finally I tracked it down to the spell checker that was replacing my words with ones that best matching in its dictionary.  The spell checking had to go.  Soon I was compliant down to only one main exception.  I didn’t have a Javascript parser in my program.  I did have a text editor which also served as the I/O for my chatbot.  I had replaced the targeting so I could see the results of the matching processes.  As I considered adding more exits to the standard <system> hook, I made my big plunge.  I would add my own script language in a pared-down version in place of the Javascript.  Because it is non-standard, I just called it the <script> tag. (After all, I’m betting that is how the Javascript tag was invented in the first place – since the system tag probably already existed.)

 

I have an old script language I created about twenty years ago.  It was designed to do interviews.  Originally I was using it to gather information for a free dating service.  I have taken out most of the fancy processing for interviews and added some options for manipulating the text editor and the AIML engine.  While it is still experimental, I believe it can be used to dynamically create new AIML categories during the chat.  I can get away with this because the editor is a stand-alone application with only the botmaster shaping the conversation.  Perhaps this tool can be used to build that friend of your very own, like training a pet.

 

                Design goals

 

All the control and data used by the chat engine must be accessible by the text editor.  It must be able to edit AIML from other sources like the Linux platforms.  Wherever possible, output should be also in XML format, but flat text files are ok due to the limited environment of the Pocket PC.  I mostly care about running on my Compaq iPaq, but the core AIML engine should be simple C code for portability.  It has to respond in a respectable timeframe, delays over ten seconds will be tolerated only in rare circumstances.  It has to be able to learn new AIML and output the same when the botmaster extends the database on-the-fly.

 

Sets and Gets need to organize their values.  A calculator is required to work on those values.  The values should be combined in a way to describe objects or situations using things like inheritance.  Information should be driven towards simple kernel sentences so more sophisticated models of understanding can be explored later.  A framework for building stories or knowledge domains instead of the simple list of named pairs must be established to facilitate playing logic games and simulating ethic problems that take conversation past the party talk stage.  A good conversationalist must be a good listener.  To do this the chatbot needs to have a way of organizing the facts it has “heard”.

 

Since AIML is orientated to backwards chaining (bottom up), the script language should complement that with some old fashion forward chaining procedural processing.  Parts of the conversation should be taken over when a predefined function is required like extracting the correct details for new AIML categories.  The essence of this should be displaying text prompts and soliciting text replies.  Even if it is an interruption, the scripts should be able to take control of the text editor to make script or AIML.  It should be able to return the text editor to the state it was in before the interruption – to continue the chat.

 

 

Brief Notepad+AIML User Manual

 

The startup directory contains a file called options.ini which has a list of default file locations.  These locations override the built-in ones where Notepad+AIML expects to find it supporting files.  Basically there are five default folders; DATA, BOT, LOGS, SUB and DB.  The BOT folder contains the bot predicates.  The LOG folder contains the targets, dumped AIML and gossip files by default.  The DATA folder is usually where the facts and scripts are stored.  The SUB folder holds the substitution definitions in several files.  And the DB folder keeps the AIML database or brain of the bot.

 

Two new folders have been added for grammar processing.  The folder called REF contains a list of words that are male name, female names, a stop list of “noise” words, an exception list of bad words.  Another folder called DICT contains the WordNet dictionary.  Since the latter is a large amount of data, it is usually found on the storage card for the Pocket PC version.  These additional folders are optional.

 

Basically Notepad+AIML won't run completely when the main supporting directories/files are not there.  You need this directory structure for the default configuration:

 

AIMLpad.exe                        (desktop version, Pocket PC version is called npp2.exe)

options.ini

bot\character.txt

bot\init.txt                              (this file will be created when bot quits normally – using the <system>exit</system> aiml)

bot\moods.txt

bot\vars.txt

data\                                       (this directory will be filled with user predicates - it can be empty at start)

db\index.txt

db\patterns.txt

db\templates.txt

logs\                                       (this directory will be filled with gossip and targets - it can be empty at start)

sub\gender.txt

sub\person.txt

sub\person2.txt

sub\personf.txt

sub\substitute.txt

 

ref\malename.txt                   (ref files are optional and are only used for filtering with the words script command)

ref\femalename.txt

ref\stoplist.txt

ref\badwords.txt

dict\                                        (this optional directory is for WordNet dictionary files – see note below)

 

This is the same default configuration for the Pocket PC except the program name is npp2.exe (I guess I should fix that name).

 

Note: To use the WordNet dictionary you include the 19 files from the WordNet application in the AIMLpad’s dict\ directory.  WordNet dictionary files can be acquired from the http://www.cogsci.princeton.edu/~wn/ website.  After a standard installation, the WordNet dictionary files are usually located at \Program Files\WordNet\1.7.1\dict.  For the Pocket PC,  copy the dictionary files to \Storage Card\Dict  (because they are over 31 meg in size - the location can be changed using options.ini).  For the desktop editor, copy the dictionary files into a dict folder within wherever you installed the AIMLpad.exe program.  

 

The program called NPP2 (AIMLpad.exe for the desktop version) can be called with a command line parameter of a file name because it acts just like Notepad.  It can also start a script automatically when a document is loaded depending upon parameters in the options.ini file.  Properly configured, a shortcut can be created to launch the program right into an AIML editing session running through a conversation with the chatbot.

 

The options.ini contains these labels, each on a single line, each representing a directory or text file location:

character, moods, bot, data, temp, index, patterns, templates, info, errors, targets, gossip, subs, person, person2, personf, gender, stoplist, malenames, femalenames, badwords, scripts, facts, dict, dumpaiml, unsorted

They can be followed by an = and then immediately the fully qualified file name of where the data file is located.

 

Also there is a label for a script to be automatically loaded called “pose” (so “pose=tree” automatically loads the tree.txt sample file).  The default script file to be loaded when the pose option is not available is pu.txt.

 

There is a label for the script commands to perform once the text window is activated called “startcmd” (so “startcmd=facts” starts the editor pasting the facts of the last saved chat into the start of the text document).

 

There is a Boolean flag label to turn on the chatbot mode called “startbot” (so “startbot=true” automatically starts up the chatbot).  There is a Boolean flag label to turn on the CONNECT startup pattern called “useconnect” (so “useconnect=true” automatically starts with the word CONNECT as the chatbot’s first input).  The chatbot does not have to be automatically started for the CONNECT startup option to be used.  The first time the bot is activated, when useconnect is true, the chat starts from the CONNECT category.

 

There is a Boolean flag to recognize the predicate named “name” and switch the client to the value of it automatically.  It is called autoname.  It makes a new case for a new client.  If the bot is stopped using the <system>exit</system> AIML, the case and client is saved for the next run of the editor.

 

Since the desktop AIMLpad can use MS Agent to produce speech, it has a option called Msagent.  When it is set to equal zero (MSagent=0), the agent software is not loaded.  If it is set to one, the agent is ready for speaking, but not activated – use the menu options to activate it.  If it is equal to 2, the agent is ready and activated – once the bot has something to say, it will speak it too.

 

Once in the text editor, the toolbar contains these buttons:

 

Cut, Copy, Paste, Command Window Wizard, Dialog Balloon

 

The first three are by common sense self explanatory – cut, copy, paste.

 

The popup command window looks like a wizard’s wand in the toolbar (looks like a rolled up plan for the desktop version).  It is where immediate script commands can be submitted outside chats, other script’s processing, etc.  When the window appears, it has the current subject name and case name displayed in its status line.  Right now the command window has one bug.  To submit the command from the keyboard, you must be on the last character of the line when you press enter.  Of course, you can use the ok button at the top of the window to submit the commands no matter where the cursor is positioned.

 

The dialog balloon button on the toolbar toggles the chatting to the bot on and off.  You can tell if you are in a conversation with the chatbot because the cursor will blink twice as fast.  Normally the cursor blinks about once a second. Like a heartbeat  When chatting, it looks like a cursor gone hyper.  In the desktop version, the balloon button on the toolbar stays depressed to indicate you are in a chat.

 

There are two main menus to the Pocket PC application.  The first one you’ll usually see is on the browse window.  The browse window is a standard file select list like Pocket Word or Excel present when they don’t have a document picked.  It has the New option and Tools option.  Under Tools is the About NP+AIML and three AIML utility functions:  Load AIML, Sort AIML, Dump AIML.

 

Load AIML opens a modal dialog that gets the parameters for learning AIML, that is, loading the XML into the text flat file AIML database.  You can load a single XML file or you can specify a file that contains a list of AIML files (sorry no wildcards are used to specify files in the Pocket PC version – desktop version can use the * wildcard when identifying files).  You also have the option of merging the AIML into the existing database instead of reloading it.  The AIML goes through some cleanup.  It is quickly checked for matching tags.  The patterns are separated and stored into the patterns.txt file.  The templates are stored in the templates.txt file after they are compressed.  The patterns are then sorted by only their first character into an order of  _ followed by the alphabet, then followed by any other characters which includes the *.  Since GraphMaster technology is not used, this first character sort reduces the search time during pattern matching.

 

But that isn’t good enough for the AIML standard you say.  Well if you want to take the time, you can use the Sort AIML menu option.  I only put the basics of a sort routine in for this feature, so the complete sorting is somewhat slow.  You can estimate about an hour for each 10,000 patterns you have to sort (this is not true of the desktop version where maybe it might possibly take a whole minute).  The process will stop if it is taking a long time, but it can be restarted to finish the job.  If it does stop, the AIML database is still useable, its just not perfectly matching until the complete sort is done.  It took two restarts to sort the standard AIML that contains over 20,000 categories.  I did this so you wouldn’t wait forever wondering if your Pocket PC ever locked up.  At the very most, it should stop sorting after about one hour whether it is finished or not.  On my one gigahertz desktop machine, the load using the learn menu option took eight seconds and the sort took one minute and fifteen seconds for the current Alice AIML set of over 40,000 categories.

 

The Dump AIML menu option writes out formatted XML that is in the sort order of the patterns.  So you can load this dump back into the database without have to do the complete sort (which would only be one pass anyway since all the sort has to do is prove the categories are in the right order.)  The dump only writes to a predefined default file (unless overridden by the options.ini parameter dumpaiml) called “<app folder>/logs/aiml.txt”.  All AIML files learned and categories dynamically added are combined in the one AIML file dumped.  In the dump dialog on the desktop version you can pick which files that were loaded into the database to output to the dumped file.  You can therefore pick only the newly created categories and/or the merged categories created from the “Remove Duplicate Categories” menu option to put into the dumped file.

 

The other menu to the application is available while you are editing a text document.  It has the Edit option and the Tools option.

 

The Edit option lets you do lots of text editing functions like Undo, Cut, Copy, Paste, Clear, Select All, Find…, Replace…, Go To…  These are all self explanatory.

 

The Tools menu option in the editor mode in the Pocket PC version has Save As… and three more submenus for script and AIML functions: Knowledge, Process, Context.  The desktop has four submenus for script and AIML functions:  AIML, Knowledgebase, Process, Context.

 

The Knowledge submenu option handles the object orientated facts database.  It offers four more menu options: Subjects…, Cases…, Facts…, Tree....  The latter gives a tree view of all the facts and script processing data.  The hierarchy looks something like:

 

                                ~~events~~                                                                           // the events subject area

                                                User                                                                        // situation tags for bot’s client named User (there are none)

                                ~~stack~~                                                                             // the script processing stack is empty

                                New Cases                                                                            // default subject called New Cases

                                                ~~global~~                                                            // global share facts for New Cases subject

                                                User                                                                        // client’s case called User

                                                                name=user                                             // a fact called name with value “user”

                                                                that=Hello User!                                   // the “that” of the last chat

                                                                topic=                                                     // the blank topic of the last chat

 

The Subjects… sub-submenu option lets you add or delete subject areas.  The ~~events~~ and ~~stack~~ subject areas are special and you should not delete them.  In the Subjects modal dialog you can also set the current subject area to one in the already-defined list.  The desktop version lets you get and put subject data to text files.  It also has a small button labeled “@” which takes you to the cases dialog for the selected subject area.

 

The Cases… sub-submenu lets you add or delete cases within the current subject area.  When a case is made, a corresponding case in the ~~events~ subject area is created.  If a case is dropped, the one in ~~events~~ is automatically dropped too.  This sub-submenu’s dialog also lets you set the currently active case.  When the chatbot sets or gets predicates, they are from the currently active case.  The desktop version lets you load and save case data to text files.  It also has a small button labeled “@” which takes you to the facts dialog for the selected case.

 

The Facts… sub-submenu option lets you add or delete facts within the current case.  It also lets you do things like set the confidence factor and source of the fact, but this version of Notepad+AIML doesn’t use that information.  The facts dialog lets you edit the multi-value list assigned to the predicate.  Also note that the facts dialog can be opened from the knowledge base tree by tapping upon the facts name.  Facts are the variables(predicates) and their values available to the bot’s <get> tag.  The desktop version also lets you declare a fact to the ~~global~~ case in the subject area.

 

Another submenu of the Tools menu option in the editor is Process.  This contains two sub-submenu options Scripts… and Frame…

 

The Scripts… sub-submenu shows a tree of all the scripts loaded into the script processor.  It looks something like this:

 

                                Sample Script

                                                Sample Frame Id 1

                                                Sample Frame Id 2

                                                Sample Frame Id 3

 

You can tap on the frame references to open the frame dialog.

 

The Frame… sub-submenu opens the script frame dialog.  Here you can edit the commands within the frame that was loaded for the script.  Then you can use the popup script command window to type the modified script into the text editor to permanently save (using the SaveAs.. submenu option) the changes you make using the frame dialog.

 

The last submenu of the Tools menu option in the editor is Context.  This contains three sub-submenu options Dialog, Targets, Command…

 

The Dialog sub-submenu option is the same as the dialog balloon on the toolbar.  It toggles on and off the chatbot conversation.  If the bot is chatting, this sub-submenu option will be checked.

 

The Targets sub-submenu option turns on or off the targeting logging of the chat.  If targeting is turned on this option will be checked.

 

The Command… sub-submenu option is the same as the wizard button on the toolbar.  You can call the command processor window anytime a script is waiting at the user input or the chatbot is waiting for user input or the notepad text is ready for editing.. 

 

The desktop version has more options on the tools menu.

 

You can remove duplicate categories by merging them together.  You can rebuild the index in case you edited the patterns.txt file.

 

You can search the loaded AIML database for categories.  The resulting list shows the matching order of the categories found.  You can search on patterns starting with a given phrase or containing a given phrase.  You can search for templates containing a given phrase.  You can search for patterns using the standard matching function with a given input.  You can even include a THAT parameter for the match.  The results also show which file contained the category when it was loaded into the AIML database.  You can double click on the pattern in the list to open an edit dialog for the category.

 

You can list or edit the targets.  The target list is sorted by patterns matched with inputs indented under them.  You can right click on a pattern to get statistics for it.  You can double click on an input to edit the target related to it.  The target editor is very similar to the one included with Alice Program D.  The only addition is some buttons to add the edited category directly into the AIML database or into an AIML text file.  The “Add” button put the category into the AIML database. The “Save” button immediately writes the category to the text editor’s current text.  The “Save As…” button will add the category to the end of a specified AIML text file.  The “Replace In…” button will remove the existing pattern before adding the changes to the end of the AIML text file.  The “Discard” and “Drop All”  buttons directly effect the target log file (not an extracted database like the AliceD version does.)

 

Also the desktop has a Tools-Context submenu option to set the targets logging file or the gossip log file locations.  It has a Tools-Context submenu option to activate the MS Agent for text-to-speech output of the bot’s responses.

 

The desktop has a tools option for quickly building categories from a dialog text file.  The dialog text is in the same format as the editor records dialog.  It is a line for the client’s input followed by the bot’s response followed by a blank line.  The first line is used when making quick categories for the pattern.  The remaining lines until a blank lines become the template.  The quick categories are written to the text area of the AIML+Notepad.

 

Using the same dialog text format, the desktop version offers a load dialog into targets menu option.  It reads the first lines of the dialog exchanges and sends them directly to the bot.  The bot has targeting turned on at the time.  All the bot responses are not displayed until after the dialog text file has been read.  The bot is then returned to normal operation.  Note: this option does mess with the that’s and inputs and topic history of the bot.

 

Eventually the desktop version will have a Classify Dialog Text menu option that will be similar to version B’s technique used to make quick targets using statistics.  Currently the option just lists some candidate patterns with wildcards matching inputs that might be defined more specifically.

 

 

Overview of script language structure

 

Scripts

 

A script consists of a set of frames.  The frames are arranged in a linear sequence of command statements.  They will execute that way if no branches are made.  Unless an interview is in process (not available in Notepad+AIML version 1.01), script processing will end at the completion of the statements in the called frame.  (btw, during an interview the engine processes each frame in the script in sequence.)

 

Each frame usually consists of a prompt and the matching patterns for the possible replies and/or a list of interpretive commands.  In fact, it will be easier to think of each prompt as a command and each particular reply as a command.

 

<FRAME> := { <FRAME ID> } <COMMANDS>

<COMMANDS> := <COMMAND>

                                := <COMMANDS>, <COMMAND>

<COMMAND>    := <PROMPT>

                                := <ASSIGNMENT>

                                := <SITUATION>

                                := <BRANCH>

                                := <PREDEFINED>

 

A question is displayed by simply stating the prompt inside quotation marks.  The current values for concepts can be displayed by trailing them after the quoted prompt string.  The key to identifying a prompt command is that it is the only command that starts with a quotation mark.

 

<PROMPT>          := “ <CHARACTER STRING> “

                                := <PROMPT> <CONCEPT>

                                := <PROMPT> “ <CHARACTER STRING> “

 

The reply for a prompt is usually a single concept, or, in other words, the assignment command without the = value part.  Concepts are variables that can be assigned values by the assignment command.  They are stored as predicates or facts of a case which is where the chatbot sets and gets its dynamic values.  They are user defined flags of relative value, which is to say the current value of a concept is the case’s contributor’s attitude towards the concept.  They can also be used as qualities a case might have, such as “brown hair”.     Concepts can also acquire values through the calculator or from predefined script commands.  The last entered input is stored internally when any input assignment command is made by specifying a single concept, but can be overridden by an assignment to the system predicate named $LAST. 

 

<ASSIGNMENT>                := <CONCEPT> = <EXPRESSION>

                                                := <CONCEPT>

                                                := <FACT>

<EXPRESSION>                   := <*any expression processed by the calculator>

<CONCEPT>                         := $ <CONCEPT NAME>

                                                := % <TEMPORARY CONCEPT NAME>

<FACT>                                := <OBJECT> _ <ATTRIBUTE> _ <VALUE>

   

 

 $LAST is considered the reply for a conditional situation.  Replies will be searched for the presence of key words or key phrases.  When a match is found between an case’s predicates and a set of parameters for which the reply is conditioned, a subset of commands specified by the conditions will be processed.  Situations always start with a left parenthesis mark and are optional tags for the conditional statement.  Conditionals always contain a left square bracket mark for their first character which is the start of the parameter(s) and they signal the end of the provisional command statements with a question mark.

 

<SITUATION>                     := ( <SITUATION TAG> ) <CONDITIONS> <COMMANDS> ?

                                                := <CONDITIONS> <COMMANDS> ?

<CONDITIONS>  := [ <PARAMETERS> ] <CONFIDENCE>

                                                := [ <PARAMETERS> ]

                                                := <CONDITIONS> [ <PARAMETERS>] <CONFIDENCE>

                                                := <CONDITIONS> [ <PARAMETERS>]

<PARAMETERS>               := <PARAMETER>

                                                := <PARAMETERS> , <PARAMETER>

<PARAMETER>                  := <PHRASE>

                                                := <FACT>

                                                := <NULL>

                                                := <UNIVERSAL>

                                                := <EQUATION>

                                                := <IDENTIFIER>

<PHRASE>                           := “ <CHARACTER STRING> “

<NULL>                 :=

<UNIVERSAL>                    := *

<EQUATION>                      := <EXPRESSION> <RELATIONAL OPERATOR> <EXPRESSION>

<IDENTIFIER>                     := <FRAME ID> ( <SITUATION TAG> )

 

 

Note: The confidence factor on conditions is not used in this version of Notepad+AIML.

 

The cataloguing of each possible reply allows not only the branching to a specific situation and thus skipping all the possible commands listed in between, but also informs later situations which ones have or have not previously occurred.  Whenever a frame is processed, it can flag all or part of its situations as TRUE or FALSE.  At the time of unification in a condition statement’s parameter(s),  the referenced frame may be processed to determine the status of its situation.  These dynamic calls may be nested to resolve the pattern matching of the condition.  The processing stack and events labeled by the situation tags are available for inspection as specially named predicates in the local processing stack - more about this later.

 

One of the parameters called <EQUATION> allows relational tests to be made on concepts.  A <FACT> may be considered a shorthand way of writing an equals equation.  If equations or facts are true, the conditional statements are processed.

 

Two other parameters are given, <NULL> and <UNIVERSAL>.  The latter stands for all the possible keywords and key phrases that can occur in any specific spot in the input’s syntax.  <UNIVERSAL> is necessary when the conditions are positional dependent.  If two sets of parameters are necessary for the proper conditions, then that says some parameter out of the first set must be satisfied and after that physically following it in the input some parameter out of the second set must be satisfied.  The second must follow immediately after the first unless a <UNIVERSAL> is placed between them.  In which case, the second parameter can follow anywhere after the first.  A <NULL> is always satisfied and can be used for unanticipated answers.  The <NULL> is not actually coded, instead a situation tag is put on any of the other commands without the conditional clauses present to make a default.

 

When a script procedure identifier is given as a command, it is the same as a subroutine call to the frame.  At the end of the frame, execution is returned to the command following the identifier.  Any branch with a @ following the identifier will not be stacked (thus effectively making it a goto.)  The starting colon identifies the branch.

 

<BRANCH>                          := : <IDENTIFIER>

                := : <IDENTIFIER>@

 

So far the script has been composed mostly of some special characters and free form text.  Parts of the text were given meaning through the definition of concepts.  Now we add a group of keywords, each followed by a preset format of parameters.  These predefined command statements are all third normal form syntax, that is, in the format: <keyword> <parameters>.  There are fifty four of them.  Nineteen of them deal with the storage of facts.  Four of them are the script functions.  Six control the processing of commands within the frames.  Sixteen are functions of the text editor.  Eight are centered around the AIML engine plus one more which is a convenient way for the bot to use the calculator.  With five of those commands just for reporting status and not real processing, over half of the predefined commands are solely dedicated to the goal of editing AIML.  The second largest group is dedicated to organizing the bot’s values acquired through chatting.

 

 

<PREDEFINED>   := break                                  * does the pop stack function

                                                := quit                                     * does the terminate function

                                                := <etc. see the following list for details>

 

 

Subjects, Cases, Facts

 

Knowledge can be represented by a network of associations or by classifications in an hierarchy or by an unstructured grab bag of values such as the Alice bots have been doing since their beginning (or by a mixture of all these ways, etc.)  Some have tried to add databases.  Often they are more for the patterns and templates which is where I’ve heard said the real knowledge resides.  Perhaps there are facts stored in the text of the templates.  But storytelling and adaptive conversation needs more than static canned responses to be real.

 

The first step towards supplementing the reference materials in the templates, is to give structure to facts acquired through conversations.  Organizing those facts should seem natural.  Hence the key areas of subjects.  A library is organized by subject.  A conversation sometimes has a subject or you might call it a topic.  If you are talking on a topic, you should be able to record the details according to subjects.  That is the trick – determine what the subject is under the current topic of discussion.  This tool is an attempt to tackle that problem.

 

Quite naturally each user or client of the bot has their own collection of predicates.  I called this a case.  You might say the chatbot is a case worker.  So when the <set name=”name”> tag is fired, a case is made in the current subject under discussion.  By default, the initial subject area where cases are created is called “New Cases”.  This subject cannot be discarded so cases always have an umbrella under which to exist.

 

It is possible to have a case with the same name exist under two different subjects.  This should be one of the areas to explore.  Right now the editor doesn’t link the cases together as though they represented a single client. Perhaps it should.  It does however share the events recorded by processing the script situation tags in a case under the subject of ~~events~~.  This events case shares the same name as the current subject’s case.  So it would make sense that other subjects take advantage of the same technique of sharing case names to represent a single client discussing on various topics.

 

Subjects can accumulate shared facts that all cases within that subject can use.  All an individual case has to do is declare a predicate or fact and it goes into a ~~global~~ case.  This automatic inheritance aides in collecting information that eventually could be turned into AIML knowledge.   There is another way a case can inherit values, that is, by using the $General system predicate.

 

Although scripts process all cases and subjects, each case can have its own set of script frames.  And since the ~~global~~ is just a special case for the subject, its set of script frames can be considered the whole subject’s methods.  This script is stored in a special predicate called $Method.  In fact, any predicate in a case could contain script and use the “submit” predefined command to process it.  $Method’s are special though in that they participate in the search when a branch or call is issued.  Taken to its logical conclusion, the $Method of the last $General named case (because a case may have a $General system predicate that inherits another case which could inherit another case, etc.) would be the last place searched for a called frame identifier.  Script files are universal.  $Methods are local or shared by the subject area.  $Methods can be inherited from other cases.

 

So subjects and cases are like classes and objects.  But facts are more like text than like fields or properties or attributes.  Mostly facts and a named value pair are interchangeable terms.  Some effort has been made to adjust to the nature of the world.  So while it may be correct to say I have a brother and name only one, it would be an understatement to say I have a sister without naming both of them.  So facts have been allowed to have multiple values in this system.  This is experimental.  Being so, it takes some command statements or the calculator to utilize the additional values.

 

Facts also can have a confidence factor between 1 and 100%.  Conditional can have a confidence factor too.  Neither of these have been implemented in this version of Notepad+AIML.

 

Events

 

Scripts track their processing creating events as commands execute.  Actually only one aspect of the language, that is, the situation tags create the events in this program.  The ~~events~~ subject area holds the predicates with the names of the situations.  The names are in the format “frame id(situation tag)”.  The values of the predicates in ~~events~~ are either TRUE or FALSE since situations are usually placed on conditional statements.

 

You can get rid of a situation by using the remove command.  All the situations can be removed with the *() identifier used instead of the exact event predicate’s name.

 

Since there is only one event subject, cases in several subjects share their events history (as long as they have the same name.)

 

Stack

 

Because the notepad process needs to collect input for predicates during the processing of a script, an external store for saving the script processor’s state was required.  The ~~stack~~ subject area exposes this information.  Call are pushed on the stack by creating a new case in the ~~stack~~ subject.  These temporary cases have the naming form of ~~cmd??~~ where the ?? is replaced with a sequential number.  Inside the ~~cmd~~ case are predicates containing the statements in the frame, the position where processing is occurring in these statements, the current case, etc.  Also in this stack case are the local/temporary predicates (those starting with %.)  When the frame finishes processing, the stack case is dropped and the temporary predicates disappear.  One other predicate named ~~STKRETURN~~ identifies the calling frame’s stack case so after the drop, the rest of the script can continue processing.

 

Note: an input causes a script call to the notepad.  When the input is acquired, notepad calls the script return subroutine that drops the stack case and continues the script processing.

 

Intrinsic commands

 

 

Procedures: frames

 

{ <frame id> }

 

Braces surround a procedure name called the frame id.  This makes it easy to spot in the text of the script,  A comma is not required to follow the frame’s tag unlike what usually occurs after all the other command statements.

 

If a list of commands does not have a frame id, they can’t be called by the branch statement.  This might happen from the pop-up command modal dialog or from the AIML <syste> or <script> tags.  In fact, frame ids are only significant in a script file or the $Method predicates.  If you do put a frame id in the AIML, you might be disappointed as the occurrence of the brace signals the end of the list of command statements.  I didn’t include the publish predefined command in this version which dynamically adds frames to the script database.  To get around that deficiency you can write the script to the text file, save the text, and pose that back into the scripts database.

 

Comments

 remarks,

' <remark>

 

An apostrophe starts a comment.  Watch out because a comma ends it.  Comments cannot be appended to the end of other statements – they are only a completely contained statement.

 

Display

displays,

" <display string> " <predicate name>...

 

Quotes surround literals.  If a statement starts with a literal, it writes that to the text file at the current position of the text cursor.  Quotes can be embedded within a literal by doubling them.  Simply, a literal for a statement adds to the text file.

 

The literal can be followed by a predicate name to display its value.  One or more literals and predicates can follow the initial literal in the display statement.  Be careful since comma don’t separate the predicates and literals.  A comma ends the statement.

 

In this version only predicate names are allowed in the display statement – calculator expressions are not available.  It is not uncommon to see temporary predicates which have been calculated and formatted before they are used in the display statement.

 

Assignment

 

The AIML engine and the script language share the facts database.  This part of the program is written so that other full scale database engines could be plugged in later as an upgrade.  I guessing that future versions of Notepad+AIML will use the GPL version of a PICK like DB instead of the basics coded here.

 

A predicate alone as a command statement will take its value from the standard input device which in this case is the notepad text editor.    Since predicates always start with a dollar sign mark (or a percent sign in the case of temporary predicates) and assignments always start with a predicate, this command is identified by the starting dollar sign (or percent sign.)

 

A special kind of object has been added to store a new kind of predicate, that is, predicates that are local to only the frame (could be several frames if branches are used -  locals are made with each invocation (subroutine call) of the frame.)  These predicates are prefixed with a % instead of the normal $.  Predicates are searched first for the $ ones, then the % ones, then the inherited ones and finally if the ~~global~~ case in the subject exists, it is searched. 

 

The following are some system predicates that can’t be used in calculations, but can be assigned a value or can assign their value to another predicate.

system predicates

                <last input value>                                $LAST

                <current stack object>                        $STACK

                <current situation tag>                       $SITUATION

                <current frame id>                                $FRAME

                <current object>                                   $CASE

                <current class>                                     $SUBJECT

$PATH           

$CURSOR    

$DBSIZE       

 

Standard Input

 

Besides getting the text typed in the notepad into a predicate in the facts database, the script language needs to use the information for making choices.  To provide this feature, automatically the system predicate $LAST gets the inputted data too.  But it is possible to give $LAST a value programmically too.  This input is not to be confused with the chatbot’s input.  $INPUT is the way to get that data.

 

The idea here is to consume the characters in $LAST in a consistent and convenient manner.  Otherwise we could assign the matching predicate ourselves each time before a conditional statement.  $LAST is the lazy way of approaching the input parsing problem.

 

Calculated values (and calculator)

assignments,

$% <predicate name> with optional = <expression>

 

Using a vary slow but adaptable calculation algorithm, expressions are first transposed internally into RPN and then rolled out to compute the final value.  All calculations are double floating point arithmetic.  There is no typing, so numbers are assumed to be in the proper format.  There is no exception handling either.  A divide-by-zero may stop the whole application.

 

There are numerous functions each beginning with @.  In the program code, it is easy to add another calculator function.  Just put it in the RPN list and hook the c function to the rollout switch to process it.  So there are string manipulation functions and formatting functions as well as the basic SIN, COS, POW, etc. math functions.

 

The calculations all flow through a buffer of standard size which is currently set to 12K.  So string concatenation cannot grow larger than that limit.  This is set by a #define in the c code, so it can easily be changed if necessary.

 

Multi-valued predicates can access their parts by using a subscript on the predicate’s name.  Again there is no bounds checking, so this feature abused will stop the application.

The following are the functions already defined in the calculator:

 

@ABS()

@INT()

@FLOOR()

@CEIL()

@SQRT()

@POW()

@LOG()

@EXP()

@COS()

@SIN()

@ATAN()

@MOD()

@LEN()

@RND()

@TRIM()

@UPPER()

@LOWER()

@PROPER()

@NUM(<text>,<decimal places>)                                                   Formats number with commas to given decimal places

@DEC(<text>,<decimal places>)                                                     Formats number to given decimal places

@PAD(<text>,<length>)                                                                   Adds spaces to end of text until given length

@JUSTIFY(<text>,<length>)                                                           Adds spaces to beginning until given length

@ZEROFILL(<text>,<length>)                                                        Adds zeroes to beginning until given length

@LEFT(<text>,<count>)                                                                   Returns left most part of text

@RIGHT(<text>,<count>)                                                               Returns right most part of text

@SUBSTR(<text>,<start>,<count> )                                               Returns part of text starting at given position

@FIND(<text>,<search text>)                                                         Returns location of search text, a zero means not found

@FIELD(<text>,<item>,<delimiter char>)                                      Returns the item in text list delimited by character

@CHANGE(<in text>,<char>,<to char>)                                        Changes all occurrences given character

@REPLACE(<in text>,<old text>,<new text>)                               Replaces first occurrence

@DATEDIFF(<date1>,<date2>)                                                      Returns the number of seconds different (d1 – d2)

@XMLTAG(<text>)                                                                         Returns the next XML tag in text

@XMLATTR(<text>, <name>)                                                       Returns the value of the named attribute in tag

@XMLDATA(<text>)                                                                       Returns data part of XML tag

 

Fixed values

 

These predefined values can be used in the calculator:  $KM, $RM, $VM, $SM, $TM are familiar to those knowing PICK since they are standard delimiters for the file data.

 

$KM                           Key mark, i.e., CHR$(255)

$RM                           Record mark, i.e., CHR$(254)

$FM                            Field mark, i.e., CHR$(253)

$VM                           Value mark, i.e., CHR$(252)

$SM                            Sub-value mark, i.e., CHR$(251)

$TM                            Text mark, i.e., CHR$(250)

$UL                             Underline

$LF                             Linefeed

$CM                           Comma

$SP                              Space

$DM                           Data mark, i.e., |

$QM                           Quote mark, i.e. “

$DATE          

$TIME           

$NOW

$RANDOM  

 

 

Kernel facts

                OAV       <noun>_<predicate>_<object>.                        values of OAV can be a list of values (or <object>s)

                OA          <noun>_<predicate>_                                        “null” value assumed                                         

OV          <predicate name> = <value>                              attribute “is” assumed

 

Accessing the fact is by the O or OA phrases. $noun gets a predicate’s value while $noun_verb_ gets the predicate’s value too.  This allows manipulating various aspects of the subject of the fact without destroying all the details of the subject.  In effect, the OA dimension is just a special form for naming the predicate.  The parser doesn’t strictly enforce the proper use of underline characters, so be careful to preserve this feature when writing scripts.   These facts are “kernel” sentences.

 

Multi-values

Multi-valued predicates are manipulated by predefined commands.  You can push a value into a predicate, queue a value into the head of a predicate, pop a value off the tail of the predicate.  Also a predicate can have a dimension like the functions that indicates what item in the list of multiple values the particular assignment or reference refers to.  For example, to use the third multi-value in the list of values for predicate $SCORES, the statement would look like:  $PERCENT= @INT(100 *  $SCORES(3) / $TOTAL COUNT).   Multi-values can be thought of as annotations to the predicate.  The predicate’s main value is required before multi-values can be added.  For example, say $list = “This is some words”.  When the words command executes, the predicate has four multi-values where $list(1) is “This” and $list(2) is “is” and $list(3) is “some” and $list(4) is “words”.  And while you can pop all the multi-values off a predicate, you can’t get rid of the main value of the predicate that way.

 

Special predicates

 

The history of processing leaves annotations for the tags activated.  For example, FRAME(TAG) will search the current object for the current script’s <frame>(<tag>), then any inherited object’s $Methods, then the system’s scripts database for each script loaded system-wide (using the script command).  Several modules of scripts can be loaded at a time within the system processor engine.  We also can have $Method for each object which contains a script module.  This history entry is given a value of TRUE or FALSE and stored as a fact in the object’s corresponding events case.  History facts are special in the respect that their name always ends with a ) character because of the notation for situation tags. 

 

 

Conditional situation

 

The specification of pattern matching to the $LAST system predicate was conceived from the early notation I used for defining syntax.  It seemed natural to put brackets around groups of possible elements that could be found in an input.  Sometimes notations used the vertical bar (|) to separate the choices within a group, but I chose the more readable comma mark.  So a yes or no answer might be checked for in the input with [“yes”,”no”].

conditions

[ <conditional> ]

 

                [fact to match]                      e.g. [type_is a_tree]

                [history to fulfill]                  e.g. [TYPE(tree)]

                [“phrase to match”, ”or phrase”]

                [!fact][“phrase”]

                [*][“end phrase”]                 wildcard and end phrase

                []                                             null (matches to an empty input in $LAST)

                [object existence]                 e.g. [type]              where ‘type’ is the name of a predicate - object in OA or OAV

                [relational equation]            e.g. [$type = “tree”]

 

, separates the ‘or’ conditions within the [...]

[...][...] multiple sets are ‘and’ together

[] is a null set and always matches to nothing

[*] is wild card match that consumes input characters up to the point where the next clause matches (or to end-of-line)

! is the not flag

 

The conditional statements are blocked by the clauses and a trailing question mark (?),  e.g.,  [test true] resulting command?

 

 

Complex expressions

 

It dawned on me that having one conditional statement immediately following the parameter of another automatically makes an “and” logical connection.  So a group of bracketed options following another group makes a more complex matching pattern.

 

The conditional paterrns don’t have to consume input characters.  They can be equatiojns or facts to test.  They can be situations that have been created while processing the script.  Using the ‘or’ between brackets and with several groups you can make any kind of complex logical expression.

 

 

$LAST matching, Null and Universal

 

The groups within brackets consume characters from the input.  They are processed starting from the left to the right effecting the input in the same way.  This is very similar to the patterns in AIML except for allowing groups of phrases to be matched instead of writing multiple patterns for all the combinations.  While there is no “_” wildcard, there is a “*” one.  Unlike the AIML, no saving of what the wildcard consumes is performed in script language.  Also note that the whole input does not have to be consumed for the conditional parameters to be satisfied.

 

 

Facts and equations

 

Sometimes information isn’t always an “is a” relationship that is implied by the assignment with an equals sign.  Facts are an attempt to use kernel statements, that is, very simple sentences consisting of an object with an attribute anda a value.  Another way of saying that sentence structure is subject – verb – object.  Because text is the notepad editor’s medium, an underscore character is used to separate the three parts (we can’t underline the whole verb or attribute phase.)

 

Checking in conditional parameters is just proving the given fact is true.

 

A predicate “is a” value can be represented as an equals equation.  This is checked the same way as facts for being true.  Equation are more flexible.  They can use <, >, <=, >=, <> relationships to prove true.

 

Situations

situations,

( <situation tag> )

 

Conditional statements can be preceded by a situation tag which is a label within parentheses.  Situation tags are stored in the ~~events~~ subject area in the case of the same name as currently being used in the current subject area.  If the conditions are met, the situation tag is given a value of TRUE, otherwise it is FALSE.

 

A situation tag can be tested in the conditional parameters, that is, it is specified between the brackets.  If the value is already in the ~~events~~, the parameter uses it for evaluation.  If it is not, a call is made to the appropriate frame so that it can be determined.  There is the possibility that the frame will exit before the situation is encountered.  When this happens, the script language will go into an endless loop.  Thu it is good coding practice to put breaks and exits after all the situation tags in each frame.

 

If you paid close attention, you might think this is a primitive version of Prolog.  We have goals pointing to conditions.  This wasn’t intentional.

 

 

Branches

branches,

: <frame id> or : <frame id> @

 

A call to a procedure is just the frame id preceded by a colon ( : ). The default is to do a subroutine like call, but it can be changed into a branch (or go to) by suffixing the frame id with the @ character.   Calls create a new case in the stack subject area for storing the temporary predicates.  Branches use the same stack case.

 

Predefined

 

The syntax of the command definitions is as follows:

 

·         If the command ends with … then the last syntactical element can be repeated any number of times.

·         Syntactical elements that start with an * indicate that the contents represented by the element are updated.

·         Syntactical elements that contain a / choose one of the named elements such as ON/OFF.

·         Syntactical elements surrounded by | are optional elements such as |v| is an optional v character.

·         The plus sign in front of the command name indicates the routine has been tested and appears to be working.

 

The following definitions are organized by categories of commands for better referencing.  The categories are Control, Scripts, Subjects, Cases, Facts, Editor, AIML Engine.

 

 

Control

+ break

stops current frame from continuing as though it finished normally (skip to end of frame)

+ restart

loops back to beginning of frame and starts again

looks for "}" of frame id so it doesn't work for the command statement and the command typed in at the command line

+ exit

stops the current frame from continuing with a flag set to stop any further processing of script

+ quit

stops the program

+ submit <predicate name>

immediately executes the predicate as though it was a called frame (without the frame id)

does not allow restarts in script because of the missing frame id

+ show <on/off>

turns the display flag on or off.  Predetermine commands will ignore their output when show is off.  This is especially significant for the kill command since it will not ask for confirmation if show is off. It effects these commands: subjects, cases, facts, db, frame, frames, scripts, kill, calc

+ calc <expression>

immediately display an answer from the expression sent to the calculator

 

Scripts

+ pose <file name>

loads text file with line length < 1024

text lines are CR,LF delimited

+ rescind <script>

deallocates the storage used by storing the script file and removes the object from the script class

+ frame <frame id>

lists all the command statements in the given frame

+ scripts |v| |c|

lists all available frames in the order by which they will be processed during an interview, etc.

 

the optional v parameter causes the list to include the frame statements

the optional c parameter causes the list to only include the currently processing script

 

A typical result displayed by the scripts command might look like this;

 

* Script: PTEST,

 {Quote Test}, {MATH TEST}, {BRANCH TEST}, {IF TEST}, {CHECK TEST},

 {LIT TEST}, {ASSIGN TEST}

 

Subjects

 

*** special subjects ***

 

New Cases

 

+ consider <subject>

switches focus to a class of objects

+ discard

deallocates all objects (memory) from current class and then deletes class, i.e., subject

returns to “New Cases” class afterwards

+ get <file name>

loads all objects in current class from a text file

+ put <file name>

saves all objects in current class into a text file

can be a way of renaming a class

+ subjects |v| |x|

display a list of class titles and cases

 

the optional v parameter causes the list to include the facts in each case

 

the optional x parameter causes the list to be in XML format

 

Cases

 

*** special cases ***

 

~~global~~

~~cmd???~~

 

+ make <object name>

allocates dynamic memory for object

+ drop

deallocates current object and its memory

current object becomes ~~global~~

if ~~global~~ was dropped, it is recreated

+ load <file name>

creates an object if one does not already exist, otherwise becomes the current object

reads a text file to create all the predicates for the single object

+ save <file name>

stores all the predicates of the current object into a text file

can be used to rename an object

+ cases |v| |x| |f| |l| |s|

lists all the classes (racks) and the objects (cards) they contain

optional v is verbose includes all details down to facts

optional x is in XML format

optional f is in file format (same as save statement)

optional l is local predicates filter

optional s is situation tags filter

 

 

Facts

 

*** special predicates throughout system ***

 

%~~STKRETURN~~

%~~STKPOSITION~~

%~~STKCMDS~~

%~~STKFRAME~~

%~~STKSITUATION~~

$General

$Method

 

$BotDB Index

$BotDB Pattern

$BotDB Template

 

+ evaluate <*predicate name>

replaces predicate with the result of sending the value(s) to the calculator

currently only works on first value of the predicate

+ queue <*predicate name> <predicate name>...

the first specified predicate becomes a list with the following predicates appended on the tail end (FIFO)

+ push <*predicate name> <predicate name>...

the first specified predicate becomes a list with the following predicates added to the front end of the list (LIFO)

+ pop <*predicate name> <predicate name>...

the first specified predicate loses first entry in its list and the second predicate becomes that entry, and so on for all the following predicates

? insert <count> <*predicate name> <predicate name>

puts second specified predicate into first specified predicate's multi-value list at specified count from beginning of list

? extract <count> <*predicate name> <*predicate name>

removes specified entry (count item) from the first predicate's multi-value list and puts it in second predicate

+ declare <predicate name>

moves the predicate to the ~~global~~ object

a predicate can be retrieved from the ~~global~~ object by just using its name in the assignment statement when the current object does not already contain the predicate, ~~global~~ is automatically inherited (after the $General inheritance has failed)

+ remove <*predicate name>...

delete predicate(s) only in current case

to remove all situation tags for a particular frame, add “()” to the end of the frame id, e.g., remove $GENUS()

to remove all the assigned values use the wildcard *, e.g., remove *

to remove all the script history for an case use the wildcard *(), e.g. remove *()

+ facts |x| |l| |s|

lists all the predicates and their values for the current object

x is to display in XML format

l is to display local or temporary predicate only, i.e., starts with %

s is to display situation tags only, i.e., tags end in )

 

Editor

+ nl

displays a new line, that is, carriage return and line feed

+ clear

erases all the text in the editor, that is, clears the display

+ home

moves the cursor to the first position in the file

+ eop

moves the cursor to the end of the text file (end of page)

+ position <pos>

moves the cursor to the given character position from the start of the text file

+ pin

saves the cursor position for later use by the select command

+ select <pos>

turns selection on from current position to given character position from start of text file.  If <pos> is not given, then the selected text is from the last pin position to the current cursor location

+ cut

cuts the selected text onto the clipboard

+ copy

copies the selected text onto the clipboard

+ paste

insert text from clipboard into current cursor location

+ erase

deletes the selected text

+ read <*predicate name>

copies the current text selection into the data of the given predicate

+ find <string>

selects the next text matching the find string.  The match is case sensitive.

 

Note: If the cursor is at home, the find currently doesn’t work!  Any other position in the file works fine.

+ open <filename>

opens the given text file for editing.  The filename must be fully qualified from the root of the Pocket PC file system.

+ saveas <filename>

saves the text to the given fully qualified file name.  If a file name is not given, a file explorer is presented similar to the saveas menu option.

+ kill <filename>

deletes the given fully qualified file name.  If the “show on” display flag is set (which is the default), a confirmation dialog is displayed.

 

AIML engine

 

*** special AIML text database predicates ***

 

BotDB Index                                         The sequential item number from the beginning of the patterns

BotDB Pattern                                      The pattern from the AIML text database without the template’s address

BotDB Template                                   The uncompressed template from the AIML text database

 

+ bot <input>

sends the input which may be a predicate’s data to chatter bot as a request and gets $REPLY as response

+ match <input>

sends the input which may be a predicate’s data to AIML engine matching routine and gets the $BotDB Pattern, $BotDB Template and $BotDB Index predicates for the category that matches

+ search <pattern>

searches the AIML internal database for the given pattern.  The pattern is in the BotDB Pattern format which looks like the data of the pattern tag followed by the optional <that> and the data in the that tag followed by an optional <topic> with the attribute in the topic tag.  Only compares the length of the given pattern so this may be used for a partial match to get a starting index in the database.  Returns $BotDB Pattern, $BotDB Template and BotDB Index predicates

+ ignore <pattern>

marks the exactly matching pattern as temporarily not part of the categories to be considered by the AIML engine

+ recall <pattern>

restores the exactly matching pattern back into the categories to be considered by the AIML engine

+ db <item number> <pattern file name> <template file name>

displays the specified pattern as a XML category entry.  Also creates BotDB Index, BotDB Pattern and BotDB Templates predicates.  If item number is negative or the “show off” display flag is set, only the predicates are created. Pattern file name and template file name are optional.  The item number may be from the data in a predicate.

+ use <index file name> <pattern file name> <template file name> <bot vars file name>

all the files names are optional.  If none are given, then the AIML database returns back to its default as at was at the start of the program.  If only one file name is given, then it is assumed to be the folder for the there AIML database files using their standard names of index.txt, patterns.txt and templates.txt. if two file names are given, then the bot predicates come from the indicated file as well as the AIML database changing to the given folder.  If three files are given, then each AIML file is changed as outlined in the above syntax.  If all four files are given, then the four files indicated in the syntax above are changed to the new settings.  This command effectively can change the bot’s brain like switching to a different bot.

+ getbot <*thats> <*inputs> <*topic>

dumps the history in the AIML engine into the given predicates.

+ setbot <thats> <inputs> <topic>

set the history, the thats and inputs and topic, of the AIML engine from the data in the given predicates

+ normalize <*var>

normalize the contents of given predicate the same as the bot’s input is normalized.  Picks the last sentence so will match as <that>’s do.

+ category <pattern> <template>

given the format as in the BotDB Pattern and BotDB Template predicates extracted with the DB command, a new category is immediately added to the AIML text database and can be used in the next chat input.  Note that when the category is added, it is sorted in according to the standard AIML matching rules for GraphMaster technology.  If the database is large, this may take a few seconds.

 

Example:  category “xyzzy” “That’s a secret.”

 

Also note that pattern and template may be from the data in a predicate.  To assist in writing directly in AIML, &lt; and &gt; are converted in pattern and template data to < and >.

+ write <pattern> <template> <file name>

given the format as in the BotDB Pattern and BotDB Template predicates extracted with the DB command, a new category is immediately added to the AIML text file.  Note that the category is added to the end of the file just before </aiml>.  If the file does not exist, it is created.  The folder in which the file is created must exist before using the write command.

 

Example:  write “xyzzy” “That’s a secret.” “c:\bots\foo.aiml”

 

Also note that pattern and template and file name may be from the data in a predicate. To assist in writing directly in AIML, &lt; and &gt; are converted in pattern and template data to < and >.

+ rewrite <old pattern> <newpattern> <template> <file name>

this is just like the write script command except if a category matching the old pattern exists in the AIML text file, it is removed before the new category is added.

 

Example:  write “xyzzy” “xyzzy” “That’s a new secret.” “c:\bots\foo.aiml”

 

Also note that old pattern and new pattern and template and file name may be from the data in a predicate. To assist in writing directly in AIML, &lt; and &gt; are converted in patterns and template data to < and >.

 

+ sentences <*var>

the sentences in the predicate are split out into the multi-value fields associated with the predicate.  So the $var(0) is the original value and $var(1) to $var(n) are the sentences contained in it.  You can use the @MVCNT(“$var”) - 1 expression to determine how many sentences are found.  This lets you pick a single sentence out of the many possible responses to a bot input for feedback in self-chatting.

 

+ words <-parameters> <*var>

the words in the predicate are split out into the multi-value fields associated with the predicate.  So the $var(0) is the original value and $var(1) to $var(n) are the words contained in it.  You can use the @MVCNT(“$var”) - 1 expression to determine how many words are found. The –parameters is optional.  It is determined by the – prefix.  If used, it must be enclosed in quotes or be a predicate.   It filters the words to parts of speech.   It can be  a dash followed by any number of these letters: “n” for the nouns, “v” for the verbs, “a” for the adjectives, “r” for the adverbs, “f” for female names, “m” for male names, “s” for words in the stop list, “b” for words in the bad words list, and “x” to exclude words indicated by parameters instead of including them.  “!”  and “=” are special options for repeated executions of the word command.  “^” means all words found are merged into existing multi-value list and duplicates are ignored. “!”  is for removing words found from an existing multi-value list, for example “-s!” removes words on the stop list from words already in the multi-value list by a previous execution. All words found and placed in the multi-value list are changed to lowercase.

 

Example: words $phrase                      splits the phrase into words

                words “-v” $phrase             finds those words in the phrase which can be a verb

                words “-xnvr” $phrase        finds words that can only be a verb or unknown part of speech (specify stop list and names to eliminate more)

                words “-a^” $phrase            finds words that can be an adjective and add them if they are not already in the list of words found

                words “-b!” $phrase            remove bad words from those already in the list of words found

+ senses <-parameter> <*var>

the word in the predicate has its senses (meanings) iterated into the multi-value fields associated with the predicate.  So the $var(0) is the original value and $var(1) to $var(n) are the word senses pertaining to it.  You can use the @MVCNT(“$var”) - 1 expression to determine how many senses are found.  This lets you pick a single meaning out of the many possible senses a word can denote.  The –parameter is optional.  It is determined by the – prefix.  If used, it must be enclosed in quotes or be a predicate.   It filters the senses to a part of speech.   It can be “-n” for the noun senses, “-v” for the verb senses, “-a” for the adjective senses, or “-r” for the adverb senses.

+ synonyms <-parameter> <*var>

the sense or word in the predicate has its synonyms iterated into the multi-value fields associated with the predicate.  So the $var(0) is the original value and $var(1) to $var(n) are the synonyms relating to it.  You can use the @MVCNT(“$var”) - 1 expression to determine how many synonyms are found.  This lets you pick alternate words for a sense, that is, different words with the same specific meaning.  You can use a word instead of the sense as the value of the predicate.   Then all possible synonyms of the word are put into the multi-values.  The optional –parameter only applies when using a word because senses already are too specific to require filtering.  The -parameter is identified by its – prefix. If used, it must be enclosed in quotes or be a predicate.  It can be “-n” for the noun synonyms, “-v” for the verb synonyms, “-a” for the adjective synonyms, or “-r” for the adverb synonyms. All synonyms found are changed to lowercase.

+ define <-parameter> <word>

the WordNet dictionary definition of the word is displayed in the notepad edit text.  The –parameter is optional.  It is identified by the – prefix.  If used, it selects different reports available through the WordNet library.  The following is a list of possible reports to display for the definition of the given word (searchstr):

 

-syns (n | v | a | r )

Display synonyms and immediate hypernyms of synsets containing searchstr . Synsets are ordered by estimated frequency of use. For adjectives, if searchstr is in a head synset, the cluster's satellite synsets are displayed in place of hypernyms. If searchstr is in a satellite synset, its head synset is also displayed.

-simsv

Display verb synonyms and immediate hypernyms of synsets containing searchstr . Synsets are grouped by similarity of meaning.

-ants (n | v | a | r )

Display synsets containing antonyms of searchstr . For adjectives, if searchstr is in a head synset, searchstr has a direct antonym. The head synset for the direct antonym is displayed along with the direct antonym's satellite synsets. If searchstr is in a satellite synset, searchstr has an indirect antonym via the head synset, which is displayed.

-faml (n | v | a | r )

Display familiarity and polysemy information for searchstr .

-hype (n | v )

Recursively display hypernym (superordinate) tree for searchstr (searchstr IS A KIND OF _____ relation).

-hypo (n | v )

Display immediate hyponyms (subordinates) for searchstr (_____ IS A KIND OF searchstr relation).

-tree (n | v )

Display hyponym (subordinate) tree for searchstr . This is a recursive search that finds the hyponyms of each hyponym.

-coor (n | v )

Display the coordinates (sisters) of searchstr . This search prints the immediate hypernym for each synset that contains searchstr and the hypernym's immediate hyponyms.

-subsn

Display substance meronyms of searchstr (HAS SUBSTANCE relation).

-partn

Display part meronyms of searchstr (HAS PART relation).

-membn

Display member meronyms of searchstr (HAS MEMBER relation).

-meron

Display all meronyms of searchstr (HAS PART, HAS MEMBER, HAS SUBSTANCE relations).

-hmern

Display meronyms for searchstr tree. This is a recursive search that prints all the meronyms of searchstr and all of its hypernyms.

-sprtn

Display part of holonyms of searchstr (PART OF relation).

-smemn

Display member of holonyms of searchstr (MEMBER OF relation).

-ssubn

Display substance of holonyms of searchstr (SUBSTANCE OF relation).

-holon

Display all holonyms of searchstr (PART OF, MEMBER OF, SUBSTANCE OF relations).

-hholn

Display holonyms for searchstr tree. This is a recursive search that prints all the holonyms of searchstr and all of each holonym's holonyms.

-entav

Display entailment relations of searchstr .

-framv

Display applicable verb sentence frames for searchstr .

-causv

Display cause to relations of searchstr .

-pert (a | r )

Display pertainyms of searchstr .

-attr (n | a )

Display adjective values for noun attribute, or noun attributes of adjective values.

-grep (n | v | a | r )

List compound words containing searchstr as a substring.

 

For further explanation of WordNet and how it captures the English language, visit http://www.cogsci.princeton.edu/~wn/

WordNet was developed at Princeton University's Cognitive Science Laboratory under the direction of George Miller, James S. McDonnell Distinguished University Professor of Psychology, Emeritus.

+ url <http: address>

retrieves the data from the internet for the specified url.  Only retrieves the page data and not any embedded images or addition script like cascading style sheets. The results are put into predicates named URLdata1 through URLdata9 or whatever number it takes to download the page’s bits.  The URLdata predicates are sized at the basic buffer size for all variables which currently is set to 10,240 bytes.


Sample scripts

 

Tree expert

{tree}

make tree,

clear,

"Welcome to a simple script example.",nl,nl,

"  Answer the following questions about the conifer tree you have in mind.",nl,nl,

:GENUS@

 

{GENUS}

(bald)    [FAMILY(bald)]

          $genus = BALD CYPRESS?,

(yew)     [FAMILY(yew)]

          $genus = YEW?,

(arbor)   [FAMILY(cypress)]

          [SPRAY SHAPE(flat)]

          $genus = ARBOR VITEA (THUJA)?,

(pine)    [FAMILY(pine)]

          [BUNDLE(yes)]

          $genus = PINE?,

(fir)     [FAMILY(pine)]

          [BUNDLE(no)]

          [SILVERY BAND(yes)]

          [NEEDLE SCAR(depressed)]

          $genus = FIR?,

(hemlock) [FAMILY(pine)]

          [BUNDLE(no)]

          [SILVERY BAND(yes)]

          [NEEDLE SCAR(raised)]

          $genus = HEMLOCK?,

(larch)   [FAMILY(pine)]

          [BUNDLE(no)]

          [SILVERY BAND(no)]

          [CROSS SECTION(triangular)]

          $genus = LARCH?,

(spruce)  [FAMILY(pine)]

          [BUNDLE(no)]

          [SILVERY BAND(no)]

          [CROSS SECTION(four)]

          $genus = SPRUCE?,

(douglas) [FAMILY(pine)]

          [BUNDLE(no)]

          [SILVERY BAND(no)]

          [CROSS SECTION(flat)]

          $genus = DOUGLAS FIR?,

(sequoia) [FAMILY(sequoia)]

          $genus = SEQUOIA (REDWOODS)?,

(juniper) [FAMILY(cypress)]

          [SPRAY SHAPE(round)]

          [RANDOM NEEDLES(yes),$scatter = "YES"]

          $genus = JUNIPER?,

(cedar)   [FAMILY(cypress)]

          [SPRAY SHAPE(round)]

          [$scatter = "NO"]

          $genus = WHITE CEDAR?,

"Q.E.D., the botanical genus of the tree is " $genus ".",nl,

exit

 

{FAMILY}

(yew)     [CLASS(gymnosperm)]

          [LEAF SHAPE(needlelike)]

          [EVEN PATTERN(yes)]

          [SILVERY BAND(no)]

          [DECURRENT(yes)]

          [NEEDLE LENGTH VARIES(no)]

          $family = YEW?,

(sequoia) [CLASS(gymnosperm)]

          [LEAF SHAPE(needlelike)]

          [EVEN PATTERN(yes)]

          [SPRAY SHAPE(flat)]

          [DECURRENT(yes)]

          [NEEDLE LENGTH VARIES(yes)]

          $family = SEQUOIA?,

(cypress) [CLASS(gymnosperm)]

          [LEAF SHAPE(scalelike)]

          $family = CYPRESS?,

(pine1)   [CLASS(gymnosperm)]

          [LEAF SHAPE(needlelike)]

          [EVEN PATTERN(no)]?,

(pine2)   [CLASS(gymnosperm)]

          [LEAF SHAPE(needlelike)]

          [EVEN PATTERN(yes)]

          [SILVERY BAND(yes)]

          [NEEDLE LENGTH VARIES(no)]?,

(pine)    [FAMILY(pine1),FAMILY(pine2)]

          $family = PINE?,

(bald)    [CLASS(gymnosperm)]

          [LEAF SHAPE(needlelike)]

          [EVEN PATTERN(yes)]

          [SILVERY BAND(no)]

          [DECURRENT(no)]

          [NEEDLE LENGTH VARIES(no)]

          $family = BALD CYPRESS?,

"Therefore, the family of the plant is " $family ".",nl

 

{CLASS}

(angiosperm) [TYPE(tree)]

             [BROAD AND FLAT(yes)]

             $class = ANGIOSPERM?,

(gymnosperm) [TYPE(tree)]

             [BROAD AND FLAT(no)]

             $class = GYMNOSPERM?,

remove CLASS(angiosperm),

"Therefore, the class of the tree is " $class ".",nl

 

{TYPE}

(tree)  [STEM(woody)]

        [POSITION(upright)]

        [ONE MAIN TRUNK(yes)]

        $type = TREE?,

(herb)  [STEM(green)]

        $type = HERB?,

(shrub) [STEM(woody)]

        [POSITION(upright)]

        [ONE MAIN TRUNK(no)]

        $type = SHRUB?,

(vine)  [STEM(woody)]

        [POSITION(creeping)]

        $type = VINE?,

"Therefore, the type of the plant is " $type ".",nl

 

{STEM}

pin,"Is the stem of the plant woody or green?",

$stem,erase,

(woody) ["W","Woody","w","woody","WOODY"]

        $stem = WOODY?,

(green) ["G","Green","g","green","GREEN"]

        $stem = GREEN?,

"The stem of the plant is " $stem ".",nl

 

{POSITION}

pin,"Is the position of the stem upright or creeping?",

$position,erase,

(upright)  ["U","Upright","u","upright","UPRIGHT"]

           $position = UPRIGHT?,

(creeping) ["C","Creeping","c","creeping","CREEPING"]

           $position = CREEPING?,

"The position of the stem is " $position ".",nl

 

{ONE MAIN TRUNK}

pin,"Does the plant have one main trunk?",

$trunk,erase,

(yes) ["Y","Yes","y","yes","YES"]

      "The plant has one main trunk.",nl,

      $trunk = YES?,

(no)  ["N","No","n","no","NO"]

      "The plant does not have one main trunk.",nl,

      $trunk = NO?

 

{BROAD AND FLAT}

pin,"Is the shape of the leaves broad and flat?",

$flat,erase,

(yes) ["Y","Yes","y","yes","YES"]

      "The shape of the leaves is broad and flat.",nl,

      $flat = YES?,

(no)  ["N","No","n","no","NO"]

      "The shape of the leaves is not broad and flat.",nl,

      $flat = NO?

 

{LEAF SHAPE}

pin,"Is the leaf shape needlelike or scalelike?",

$shape,erase,

(needlelike) ["N","Needle","n","needle","NEEDLE"]

             $shape = NEEDLELIKE?,

(scalelike)  ["S","Scale","s","scale","SCALE"]

             $shape = SCALELIKE?,

"The leaf shape is " $shape ".",nl

 

{EVEN PATTERN}

pin,"Do the needles grow in two lines along the sides of the branch?",

$pattern,erase,

(yes) ["Y","Yes","y","yes","YES"]

      "The needles line up along two sides of the branch.",nl,

      $pattern = YES?,

(no)  ["N","No","n","no","NO"]

      "The needles do not line up along two sides of the branch.",nl,

      $pattern = NO?

 

{SILVERY BAND}

pin,"Is there a silver band under each needle?",

$band,erase,

(yes) ["Y","Yes","y","yes","YES"]

      "There is a silver band under each needle.",nl,

      $band = YES?,

(no)  ["N","No","n","no","NO"]

      "There is not a silver band under each needle.",nl,

      $band = NO?

 

{DECURRENT}

pin,"Do the stems of the needles grow down along the twig?",

$decurrent,erase,

(yes) ["Y","Yes","y","yes","YES"]

      "The stem of the needle grow down along the twig.",nl,

      $decurrent = YES?,

(no)  ["N","No","n","no","NO"]

      "The stem of the needle does not grow down along the twig.",nl,

      $decurrent = NO?

 

{SPRAY SHAPE}

pin,"Is the shape of the leaf spray round or flat?",

$spray,erase,

(round) ["R","Round","r","round","ROUND"]

        $spray = ROUND?,

(flat)  ["F","Flat","f","flat","FLAT"]

        $spray = FLAT?,

"The shape of the leaf spray is " $spray ".",nl

 

{RANDOM NEEDLES}

pin,"Are there at least a few needle scattered along the branch?",

$scatter,erase,

(yes) ["Y","Yes","y","yes","YES"]

      "There are a few needles scattered along the branch.",nl,

      $scatter = YES?,

(no)  ["N","No","n","no","NO"]

      "There are not a few needles scattered along the branch.",nl,

       $scatter = NO?,

 

{BUNDLE}

pin,"Are the needles grouped together in groups of two to five?",

$bundle,erase,

(yes) ["Y","Yes","y","yes","YES"]

      "The needles are grouped together in bundles of two to five.",nl,

      $bundle = YES?,

(no)  ["N","No","n","no","NO"]

      "The needles are not grouped together in bundles of two to five.",nl,

      $bundle = NO?

 

{NEEDLE SCAR}

pin,"Pull a needle off the twig. Is the scar it makes raised or depressed?",

$scar,erase,

(raised)    ["R","Raised","r","raised","RAISED"]

            $scar = RAISED?,

(depressed) ["D","Depressed","d","depressed","DEPRESSED"]

            $scar = DEPRESSED?,

"The scar left when the needle is removed is " $scar ".",nl

 

{CROSS SECTION}

pin,"Pull off a needle. Is its cross section flat, triangular, or four sided?",

$cross,erase,

(flat)       ["F","Flat","f","flat","FLAT"]

             $cross = FLAT?,

(triangular) ["T","Triangular","t","triangular","TRIANGULAR"]

             $cross = TRIANGULAR?,

(four)       ["4","Four","four","FOUR"]

             $cross = FOUR SIDED?,

"The cross section of the needle is " $cross ".",nl

 

{NEEDLE LENGTH VARIES}

pin,"Does the length of the needles vary by more than half an inch?",

$vary,erase,

(yes) ["Y","Yes","y","yes","YES"]

      "The length of the needles vary more than half an inch.",nl,

      $vary = YES?,

(no)  ["N","No","n","no","NO"]

      "The length of the needles does not vary more than half an inch.",nl,

      $vary = NO?

 

 

State machine

 

{rose}

make rose,

clear,

"                              No Rose Arose",nl,nl,

"You are the owner of a new house and you have proudly planted a new ",

"garden, including an expensive rosebush. Having carefully followed the ",

"directions which came with the plant, you anticipate the flowering of ",

"Yellow Blend Peach roses. The weather has been rainy. The leaves emerge ",

"but, to your dismay, they are discolored; the flowers which form do not ",

"open completely before fading and there are many rose leaves on ground.",nl,

nl,nl,

:SECTION A,nl,nl,

"Thank you for trying No Rose Arose.",nl,nl

 

{SECTION A}

"SECTION A: Initial Section",nl,nl,

"At this time you would...",nl,

"(Choose ONLY ONE EACH TIME you are directed to in this section):",nl,nl,

"1. Buy a spray or special rose food and treat as directed",nl,

"2. Examine the plant (i.e. the setting, ground, leaves, and flowers)",nl,

"3. Seek help from a professional gardener",nl,

"4. Consult your local librarian",nl,

"5. Return the plant to the store",nl,

:SECTION A ASK

 

{SECTION A ASK}

nl,

"Your Choice? ",$choiceA,

(section b) ["1","B","b"] :SECTION B@?,

(section d) ["2","E","e"] :SECTION D@?,

(section e) ["3","S","s"] :SECTION E@?,

(section c) ["4","C","c"] :SECTION C@?,

(return)      ["5","R","r"] "Your money is not refundable.",nl,

         "The store clerk points out that your plant needs some treatment",restart?

 

{SECTION B}

nl,

"SECTION B: Management",nl,nl,

"In order to treat the plant, you would now buy and use... (Choose ONLY ONE):",

nl,nl,

"6.  Special rose food for weekly feeding",nl,

"7.  A fungicide for weekly spraying",nl,

"8.  Systemic insecticide for biweekly spraying",nl,

"9.  A spray insecticide for biweekly spraying",nl,

"10. An aqueous root feeder for weekly feeding",nl,nl,nl,

"Your Choice? ",$choiceB,

(food)      ["6"] "  No improvement. Plant dies.",nl,exit?,

(fungicide) ["7"] "  The plant improves.",nl,exit?,

(systemic)  ["8"] "  No improvement. Plant dies.",nl,exit?,

(spray)     ["9"] "  Plant dies. You also kill a nearby hummingbird colony",

                  nl,"and numerous honey bees, and you feel a little ",

                  "sick yourself from inhaling the spray.",nl,exit?,

(feeder)    ["10"] "  Most of the loose earth is washed out, exposing the",

                   nl,"plant's roots. Plant dies.",nl,exit?

 

{SECTION C}

clear,

"SECTION C: Consultation",nl,nl,

"The librarian directs you to 300 references on plants, listed in the",nl,

"card catalog. You would (Select AS MANY AS you WISH):",nl,nl,

"11. Work through the references logically, beginning with plant",nl,

"    'structure' and going on to 'cultivation', 'disease', etc.",nl,

"12. Check out a book entitled Dieases of the Rose, and try to match",nl,

"    the appearence of your plant to what you find pictured in the book",nl,

"13. Look up 'all-purpose' plant medicine",nl,

"14. Try to locate the problem under 'insects', 'fungi', 'nutrition', etc.",nl,

$mvlistc = "Multiple choiceCA answers in mvlistc's MVList",

:SECTION C ASK

 

{SECTION C ASK}

nl,

"Your Choice? ",$choiceCA,

(reference) ["11","W","w"] "Three weeks later you are still on the first topic and the plant has died.",

                       push $mvlistc $choiceCA,

                       exit?,

(check)     ["12","C","c"] "The best match is something called 'black spot diease', which is described",nl,

                       "as a common fungus infection.",

                       push $mvlistc $choiceCA,

                       restart?,

(lookup)    ["13","L","l"] "You cannot find any such listings.",

                       push $mvlistc $choiceCA,

                       restart?,

(try)       ["14","T","t"] "There is a bewildering number of plant diseases, several of which could cause sick

 

leaves.",

                       push $mvlistc $choiceCA,

                       restart?,

clear,

"At this time you would... (Choose ONLY ONE):",nl,nl,

"15. Buy a spray or rose food and treat as directed, if you have not ",nl,

"    already done so",nl,

"16. Examine the plant, if you have not already done so",nl,

"17. Seek help from a professional gardener, if you have not already",nl,

"    done so",nl,

"18. Return the plant to the store, if you have not already done so",nl,nl,

"Your Choice? ",$choiceCB,nl,

(section b) ["15","B"] :SECTION B@?,

(section d) ["16","E"] :SECTION D@?,

(section e) ["17","S"] :SECTION E@?,

(return)    ["18","R"] "Your money is not refundable.",nl,

         "The store clerk points out that your plant needs some treatment ",

         nl,"but it is too late now.",nl,exit?

 

{SECTION D}

clear,

"SECTION D: Data Gathering",nl,nl,

"At this time, you would like to check the...",nl,

"(Select AS MANY AS you consider HELPFUL):",nl,nl,

"19. Bladder habits of the neighbor's dog",nl,

"20. Weather bureau for recent statistics",nl,

"21. Water supply to roots",nl,

"22. Soil's pH",nl,

"23. Food supply to roots",nl,

"24. Leaves for color",nl,

"25. Leaves for insects",nl,

"26. Flowers",nl,

"27. Stems",nl,

$mvlistd = "Multiple choiceDA answers in mvlistd's MVList",

:SECTION D ASK

 

{SECTION D ASK}

nl,

"Your Choice? ",$choiceDA,

(bladder) ["19"] "Dog usually uses large trees.",push $mvlistd $choiceDA,restart?,

(weather) ["20"] "Lots of rain, T. 72-84 degrees F. Adequate sunshine",push $mvlistd $choiceDA,restart?,

(water)     ["21"] "Good.",push $mvlistd $choiceDA,restart?,

(soil)        ["22"] "Close to neutral pH.",push $mvlistd $choiceDA,restart?,

(food)       ["23"] "The uprooted plant dies.",push $mvlistd $choiceDA,nl,exit?,

(color)      ["24"] "Dark spots on leaves.",push $mvlistd $choiceDA,restart?,

(insects)  ["25"] "None seen on one occassion; later a few aphids are present.",push $mvlistd $choiceDA,restart?,

(flowers)  ["26"] "Small buds seem normal, but they do not open.",push $mvlistd $choiceDA,restart?,

(stems)    ["27"] "Seem normal.",push $mvlistd $choiceDA,restart?,

clear,

"At this time you would... (Choose ONLY ONE):",nl,nl,

"28. Buy a spray or rose food and treat as directed, if you have not ",nl,

"    already done so",nl,

"29. Seek help from a professional gardener, if you have not already done so",nl,

"30. Consult your local library, if you have not already done so",nl,

"31. Return the plant to the store, if you have not already done so",nl,nl,

"Your Choice? ",$choiceDB,nl,

(section b) ["28","B"] :SECTION B@?,

(section d) ["29","E"] :SECTION E@?,

(section c) ["30","S"] :SECTION C@?,

(return)    ["31","R"] "Your money is not refundable.",nl,

         "The store clerk points out that your plant needs some treatment",nl,

         "but it is too late now.",nl,

         exit?

 

{SECTION E}

clear,

"SECTION E: Consultation",nl,nl,

"The professional gardener is very reluctant to come out just to look at",nl,

"a single plant. He suggests you consult your local library. If you wish,",nl,

"he is willing to come in about two weeks.",nl,nl,

"You would now... (Choose ONLY ONE):",nl

"32. Buy a spray or rose food and treat as directed, if you have not ",nl,

"    already done so",nl,

"33. Examine the plant, if you have not already done so",nl,

"34. Follow the gardener's advice to consult your local library, if you",nl,

"    have not already done so",nl,

"35. Return the plant to the store, if you have not already done so",nl,

"36. Wait for the professinal gardener to handle the problem",nl,nl,

"Your Choice? ",$choiceE,nl,

(section b) ["32","B"] :SECTION B@?,

(section d) ["33","E"] :SECTION D@?,

(section c) ["34","F"] :SECTION C@?,

(return)    ["35","R"] "Your money is not refundable.",nl,

         "The store clerk points out that your plant needs some treatment",nl,

         "but it is too late now.",nl,

         exit?,

(wait)      ["36","W"] "When he finally shows up three weeks later, your plant is dead.",nl,exit?

 

 

 

AIML editor utilities

 

 A simple auto-chat example…

 

{chat}

"How many exchanges?",

$cnt,

"Start with input?",

$ask,nl,

:sayit

 

{sayit}

bot $ask,

"" $REPLY,nl,

$ask = $REPLY,

sentences $ask,

$mv = @MVCNT("ask"),

[$mv > 1] %x = @RND($mv - 1), %x = @INT(%x) + 1, $ask = $ask(%x)?

$cnt = $cnt - 1,

[$cnt > 0] restart?

Nl

 

 

A more complex two bot chat sample…

 

{chat}

"How many exchanges?",

$cnt,

"Start with input?",

$ask,nl,

bot $ask,

setbot $Thats Alice $Inputs Alice $Topic Alice,

"" $REPLY,nl,

$ask = $REPLY,

sentences $ask,

%mv = @MVCNT("ask"),

[%mv > 1] %x = @RND(%mv - 1), %x = @INT(%x) + 1, $ask = $ask(%x)?

use anna,

bot $ask,

setbot $Thats Anna $Inputs Anna $Topic Anna,

"" $REPLY,nl,

$ask = $REPLY,

sentences $ask,

%mv = @MVCNT("ask"),

[%mv > 1] %x = @RND(%mv - 1), %x = @INT(%x) + 1, $ask = $ask(%x)?

use alice,

getbot $Thats Alice $Inputs Alice $Topic Alice,

:sayit

 

{sayit}

bot $ask,

setbot $Thats Alice $Inputs Alice $Topic Alice,

"" $REPLY,nl,

$ask = $REPLY,

sentences $ask,

%mv = @MVCNT("ask"),

[%mv > 1] %x = @RND(%mv - 1), %x = @INT(%x) + 1, $ask = $ask(%x)?

use anna,

getbot $Thats Anna $Inputs Anna $Topic Anna,

bot $ask,

setbot $Thats Anna $Inputs Anna $Topic Anna,

"" $REPLY,nl,

$ask = $REPLY,

sentences $ask,

%mv = @MVCNT("ask"),

[%mv > 1] %x = @RND(%mv - 1), %x = @INT(%x) + 1, $ask = $ask(%x)?

use alice,

getbot $Thats Alice $Inputs Alice $Topic Alice,

$cnt = $cnt - 1,

[$cnt > 1] restart?

remove $Thats Alice $Inputs Alice $Topic Alice,

remove $Thats Anna $Inputs Anna $Topic Anna,

remove $cnt $ask,

nl

 

 

An AIML template for making categories…

 

{Category}

“<category>”,nl,

”<pattern>TESTTING6</pattern>”,nl,

“<that>this is optional and can be removed</that>”,nl,

”<template>”,nl,

“<random>”,nl,

“<li>put a reply here</li>”,nl,

“<li>another reply</li>”,nl,

“<li>and some other response</li>”,nl,

“<li>etc.</li>”,nl,

“<li></li>”,nl,

”<li></li>”,nl,

“</random>”,nl,

”</template>”,nl,

”</category>”,nl