Asked — Edited

Creating A Simple Robot Brain

Building on Justin's thread on creating a brain. There are many ways to create artificial intelligence and this is just what I have come up with using the tools ARC has currently available.

I have designed my project to be Service/Agent based. When the Robot is powered up the connection script launches the init script.


ControlCommand("Script Manager", ScriptStart, "Init")

This initializes all variables and launches the Voice Service and the Auditory Service and unpauses the Speech Recognition plugin. The only Speech Recognition phrase I have entered here is the robot's name and the is UNAS (meaning First One) Stargate SG1 fans will have known that. And that script looks like this:


ControlCommand("Speech Recognition", PauseOn)
ControlCommand("Bing Speech Recognition", StartListening)

As you can see when the Robot hears his name "UNAS", it pauses the speech recognition module and starts Bing Speech listening.

Here is the Bing Speech Script


ControlCommand("Bing Speech Recognition", StopListening)
WaitFor($IsListening = 1)
ControlCommand("Speech Recognition", PauseOff)

As again you can see after the speech has been captured the script stops Bing speech listening and unPauses Speech Recognition.

The WaitFor($IsListening = 1) we will see later in other scripts for now we can just ignore that line.

Now to the fun part:

The Auditory Service's first line is waiting for the $BingSpeech variable to change and when it does that is when the magic happens.


:AuditoryService
#The Auditory service monitors the $BingSpeech variable for speech and then routes this speech to
#the proper Agent for processing.
#
#***************************************
WaitforChange($BingSpeech)
$HumanSaid = $BingSpeech
$BingSpeech = ""
$IsListening = 0
#***************************************
#Convert the first letter of the captured speech to lower case
$Trash = $HumanSaid
ControlCommand("Agents",ScriptStartWait,"ConvertToLowercase")
$HumanSaid = $Trash
#***************************************

When the $BingSpeech variable changes, its contents are saved in the $HumanSaid variable and the $BingSpeech variable is cleared. Here is where we see the $IsListening variable set to 0 letting the other scripts know that the robot is currently processing and not listening.

The next few lines converts the first letter of the spoken speech to lowercase, you will see why later.

Next the script goes thru a bunch of if statements.


#BlankCanBlank
if(Contains($HumanSaid," can ") & !Contains($HumanSaid,"What can "))
  ControlCommand("Agents",ScriptStartWait,"BlankCanBlank")
#CanBlankBlank
elseif(Contains($HumanSaid,"can ") & !Contains($HumanSaid,"What can ") & !Contains($HumanSaid," can "))
  ControlCommand("Agents",ScriptStartWait,"CanBlankBlank")
#BlankHaveBlank
elseif(Contains($HumanSaid,"have") & !Contains($HumanSaid,"Do "))
  ControlCommand("Agents",ScriptStartWait,"BlankHaveBlank")
#BlankIsInBlank
elseif(Contains($HumanSaid,"is in"))  
  ControlCommand("Agents",ScriptStartWait,"BlankIsInBlank")
#BlankIsThePluralOfBlank
elseif(Contains($HumanSaid,"is the plural of") & !Contains($HumanSaid,"what ")) 
  ControlCommand("Agents",ScriptStartWait,"BlankIsThePluralOfBlank")

I did not include the entire script just enough for a good example So the if statements look at the speech phrase for specific words in specific orders and calls the corresponding Agent. For example we will use the following speech phrase "dogs can run" The if statements will match this and call the CanBlankBlank Agent


:BlankCanBlank
  $IsListening = 0
  $Junction = "can"
  $SpeechLength = Length($HumanSaid)
  $JuncIndex = IndexOf($HumanSaid,$Junction)
  $FirstPart = SubString($HumanSaid,0,$JuncIndex-1)
  $LastPart = SubString($HumanSaid, $JuncIndex + Length($Junction) + 1,$SpeechLength - ($JuncIndex + Length($Junction))-1)
  $SearchPhrase = $FirstPart + "_:::_" + $LastPart
  $MemoryType = "BlankCanBlank"
  ControlCommand("Agents",ScriptStartWait,"WriteMemory")
  if($WriteMemoryCheck = 0)
    $SayWhat = "I knew that!"
  else 
    $SayWhat = "I now know that " + $FirstPart + " " + $Junction + " " + $LastPart
  endif
$IsListening = 1

The Agent Parses the captured speech takes what is before the word can and stores that in $FirstPart and what comes after the word can and stores that in the variable $LastPart Then loads the variable $SearchPhrase and $MemoryType then calls the Write Memory Agent.

This Agent opens the file and searches the file for the SearchPhrase. I will go into detail of the read and write memory Agents in the next exciting episode of Creating a Simple Brain.


ARC Pro

Upgrade to ARC Pro

Subscribe to ARC Pro, and your robot will become a canvas for your imagination, limited only by your creativity.

#1  

I've been using the one word speech recognition engine with ARC to start the Bing speech recognition engine ever since it became available to us. I can confirm that it is a wonderful way to have your robot start listening to you. For me it completely removed any false positive responses from my robot. I'm also sure that it's Cuts way down on unneeded process time from my robot. Bing is no longer always listening for something. It only starts when my speech recognition engine tells it to. It totally resembles Amazon's Alexa. Only difference is I set the wake up word. In my case it's "Robot".

This is a brilliant tutorial. Thanks for putting it together. It's a real fun read. Can't wait for your next excitement filled episode. Same Bat time! Same Bat Channel! eek lol

PRO
USA
#2  

Episode 2 - Read / write files:

At the end of episode 1, we had just stored in $SearchPhrase dogs_:::_run and in $MemoryType we stored BlankCanBlank and called the WriteMemory Agent


  $FileName = "c:\users\richard\unas\x" + $MemoryType + ".txt" 
  $ReadType = 1
  ControlCommand("Agents",ScriptStartWait,"ReadMemory")
  if($ReadResultsCount = 0) #Memory does not currently exist
      FileReadReset($FileName)
      :Loop1
      $Trash = FileReadLine($FileName)
      $EndFlag = FileReadEnd($FileName)
      if($EndFlag = 1)
          goto(WriteMemory)
         $WriteMemoryCheck = 1
         return
         else
         goto(Loop1)
      endif
      Return 
   endif
 $WriteMemoryCheck = 0   
Return
:WriteMemory
        FileReadClose($FileName)
        FileWriteLine($FileName,$SearchPhrase)
       $WriteMemoryCheck = 1
  Return

First I set the file name. I put the x in the string to get around the problem of the backslash. As you remember we stored BlankCanBlank in $MemoryType so this will be our actual file name, plus the x of course (xBlankCanBlank.txt). In The ReadMemory Agent I have created, I believe at this time there is 4 read types

1 = compare complete memory line with $SearchPhrase

2 = Compare first part with $SearchPhrase and return first match

3 = Compare First Part with search phrase and return all that match

4 = Compare last part with search phrase and return all that match

Results are returned in an array $ReadResultsArray[x]

So we set the ReadType to 1, because we want to compare with the entire memory line. We will go deeper into the ReadMemory Agent shortly for now all we need to know is that the read memory agent sets the variable $ReadResultsCount = 0 if no entry is found. I then reset the file read to the beginning of the file and loop thru every line until I reach the end of the file. I then Write the line dogs_:::_run to the file Set the $WriteMemoryCheck flag to 1 and return to the calling script.


 ControlCommand("Agents",ScriptStartWait,"WriteMemory")
  if($WriteMemoryCheck = 0)
    $SayWhat = "I knew that!"
  else 
    $SayWhat = "I now know that " + $FirstPart + " " + $Junction + " " + $LastPart
  endif
$IsListening = 1

The if statement checks the WriteMemory flag to see if a new memory was written and if so, stores I knew that in the variable $SayWhat In eposode 1 one of the services that init started was the Voice Service.


$SayWhat = ""
$VoiceServiceStatus = 1
$IsTalking = 0
:VoiceService
#The Voice service monitors the $SayWhat variable for change and if it is not equal
#to null, will set the IsTalking flag and say what is stored in that vaiable.
#After speaking the phrase, it will reset the IsTalking flag and
#Set the $SayWhat variable to null and again wait for change.
waitForChange($SayWhat)
if($VoiceServiceStatus & 1)
 :Talking
  if($IsTalking = 0)
    $IsTalking = 1  #set the Robot is talking flag
      if($SayWhat != "")
        sayWait($SayWhat)
      endif
  :Done
  $SayWhat = ""
  $IsTalking = 0 #Clear the Robot is talking flag
  endif
endif
Goto(VoiceService)

A simple few lines of code but vary powerful as all I need to do to have the robot speek is put the words I want spoken into the $SayWhat variable and done. Another thing I should mention about this routing is the $IsTalking variable. If I have a few lines of speech I want the robot to speak this code whould not work.


$SayWhat = "Good morning Mister Phelps"
$SayWhat = "Your mission, if you decide to except it"
SayWhat = "Is to ......."

you would get the first line and that would be it. The rest would go unspoken because the script did not wait until each line was done before sending the next. But this code works perfect.


$SayWhat = "Good morning Mister Phelps"
WaitUntil($IsTalking = 0)
$SayWhat = "Your mission, if you decide to except it"
WaitUntil($IsTalking = 0)
SayWhat = "Is to ......."

Now lets go back to that ReadMemory Agent This script is a little bigger.


#**************************************************************
DefineArray($ReadResultsArray,1)
$Delimit = "_:::_"
$FilePath = "C:\users\richard\unas\x" + $Memorytype + ".txt"
FileReadReset($FilePath) #Reset read to start of file
if($ReadType = 1)
  goto(ReadType1)
elseif($ReadType = 2)
  goto(ReadType2)
elseif($ReadType = 3)
  goto(ReadType3)
elseif($ReadType = 4)
  goto(ReadType4)
endif
Return 
#*******************************************************
:ReadType1
$ReadResultsCount = 0
:Loop1
 Goto(ReadLine)
  if(Length($Trash) > 0)
   ControlCommand("Agents",ScriptStartWait,"ConvertToLowercase")
   if($RMFirstPart + "_:::_" + $RMLastPart = $SearchPhrase)
    AppendArray($ReadResultsArray,$SearchPhrase)
    FileReadClose($FilePath)
    $ReadResultsCount = 1
    $EOF = 0
    Return 
  else 
  goto(Loop1)
  endif 
endif 
fileReadClose($FilePath)
$EOF = 1
Return
#*******************************************************
#***********************************************
:ReadLine
$Trash = FileReadLine($FilePath)
if(Length($Trash) = 0)
  $EOF = 1
return 
endif
$SentenceLength = Length($Trash)
$RMFirstPartIndex = IndexOf($Trash,$Delimit)
$RMFirstPart = SubString($Trash,0,$RMFirstPartIndex)
$RMLastPartIndex = $RMFirstPartIndex + Length($Delimit)
$RMLastPartLength = $SentenceLength - $RMLastPartIndex
$RMLastPart = SubString($Trash,$RMLastPartIndex,$RMLastPartLength)
return 
#***********************************************
:CheckEOF
$EOF = 0
if(FileReadEnd($FilePath)  = 1) #Test for end of file
  FileReadClose($FilePath)
  $EOF = 1
 else
  $EOF = 0
endif
Print($EOF)
Return 
#************************************************

For this example I am only going to go thru the read type 1. If you recall the read memory agent was called for the write memory agent to check if a specific memory exists. The first thing I do is define the delimiter sence this never changes I might move this to the init script but and save me one line of code here and there. My thinking was mabe later I might want to use different delimiters, for what I dont know. back to the script. Set my delimiter, set my file path and reset the file to the begining. Now using an if statement goto the proper read routine in this case read type 1 Read a line from the file and because the if statement is case sensitive on its compare, I convert the first letter of the memory to lowercase (if its not already). I then build the entire memory just as it is stored in the file. In the actual read memory routine, it breaks it apart. This is so I can support multiple read types. Now that we have built our memory just as it is stored in the file, I compare it to the $SearchPhrase we are looking for. If the compairison fails, read the next line until we reach the end of the file. If the compare finds a match, we set the ReadResultsCount flag and return to the calling routine (WriteMemory). If we do not find a match $readResultsCount remains 0 and we again return to the calling routine. This covers the basic routines we need for our brain. So in the next episode we will expand on what we have so far. For those of you that are coping the code for study or use, here is the full ReadMemory Agent code. Remember this is a work in progress and not might change but will change in the future. But my plan is to update this thread when I make changes. So stay tuned !


#********************************************************************
# 1 = compare complete memory line with $SearchPhrase
# 2 = Compare first part with $SearchPhrase and return first match
# 3 = Compare First Part with search phrase and return all that match
# 4 = Compare last part with search phrase and return all that match
# Results are returned in an array $ReadResultsArray[x]
#******************************************************************** 
DefineArray($ReadResultsArray,1)
$Delimit = "_:::_"
$FilePath = "C:\users\richard\unas\x" + $Memorytype + ".txt"
FileReadReset($FilePath) #Reset read to start of file
if($ReadType = 1)
  goto(ReadType1)
elseif($ReadType = 2)
  goto(ReadType2)
elseif($ReadType = 3)
  goto(ReadType3)
elseif($ReadType = 4)
  goto(ReadType4)
endif
Return 
#*******************************************************
:ReadType1
$ReadResultsCount = 0
:Loop1
 Goto(ReadLine)
  if(Length($Trash) > 0)
   ControlCommand("Agents",ScriptStartWait,"ConvertToLowercase")
  if($RMFirstPart + "_:::_" + $RMLastPart = $SearchPhrase)
    AppendArray($ReadResultsArray,$SearchPhrase)
    FileReadClose($FilePath)
    $ReadResultsCount = 1
    $EOF = 0
    Return 
  else 
  goto(Loop1)
  endif 
endif 
fileReadClose($FilePath)
$EOF = 1
Return
#*******************************************************
:ReadType2
:Loop2
goto(CheckEOF)
if($EOF = 0)
  goto(ReadLine)
  if($RMFirstPart = $SearchPhrase)
    AppendArray($ReadResultsArray,$RMLastPart)
    FileReadClose($FilePath)
    $ReadResultsCount = 1
    return 
  else 
    goto(Loop2)
  endif 
endif 
FileReadClose($FilePath)
$ReadResultsCount = 0
return 
#********************************************************
:ReadType3
$LoopCount = 1
:Loop3
 goto(ReadLine)
  if(Length($Trash) > 0)
    ControlCommand("Agents",ScriptStartWait,"ConvertToLowercase")
  if($RMFirstPart = $SearchPhrase)
    AppendArray($ReadResultsArray,$RMLastPart)
    $LoopCount = $LoopCount + 1
    goto(Loop3)
  else 
    goto(Loop3)
  endif
  endif
FileReadClose($FilePath) 
$ReadResultsCount = $LoopCount - 1
return 
#**********************************************************
:ReadType4
$LoopCount = 0
:Loop4
goto(CheckEOF)
if(FileReadEnd($FilePath) = 0)
  goto(ReadLine)
    if($RMLastPart = $SearchPhrase)
    AppendArray($ReadResultsArray,$RMFirstPart)
    $LoopCount = $LoopCount + 1
    goto(Loop4)
  else 
    goto(Loop4)
  endif 
endif 
FileReadClose($FilePath)
$ReadResultsCount = $LoopCount
return 
:ReadLine
$Trash = FileReadLine($FilePath)
if(Length($Trash) = 0)
  $EOF = 1
return 
endif
$SentenceLength = Length($Trash)
$RMFirstPartIndex = IndexOf($Trash,$Delimit)
$RMFirstPart = SubString($Trash,0,$RMFirstPartIndex)
$RMLastPartIndex = $RMFirstPartIndex + Length($Delimit)
$RMLastPartLength = $SentenceLength - $RMLastPartIndex
$RMLastPart = SubString($Trash,$RMLastPartIndex,$RMLastPartLength)
return 
#***********************************************
:CheckEOF
$EOF = 0
if(FileReadEnd($FilePath)  = 1) #Test for end of file
  FileReadClose($FilePath)
  $EOF = 1
 else
  $EOF = 0
endif
Return 
#************************************************

Here is also the Convert the first letter to lowercase routine.


:LowerCase
$LCStringLength = Length($Trash)
$LCFirstLetter = SubString($Trash,0,1)
$LCFirstLetterValue = GetByteAt($Trash,0)
if($LCFirstLetterValue < 97)
  $LCFirstLetterValue = $LCFirstLetterValue + 32
  $LCStringLength = Length($Trash)
  $NewString = GetAsByte($LCFirstLetterValue) + SubString($Trash,1,$LCStringLength-1)
  $Trash = $NewString
endif 
return 

Canada
#3  

@rz90208, Wow, thanks for committing so much time doing this.

I'm lost, but my programming skill is in comparison to a 1st grader. :) Examples like this help me a lot. My favourite way to learn.

#4  

@rz90208,

Thanks so much for putting this together. Very impressive, and will be a big help to a lot of users.

Alan

PRO
USA
#5  

You are welcome, I enjoyed put it together. I will continue to post as the simple brain evolves.

PRO
USA
#6  

Episode 3 - Creating our Memory Agents and Memory Files.

Now that we have our Voice Service, Auditory Service and our Read and write Agents, we can make a few memory agent templates to make the creation of the agents much easier. Lets start out with the getting the robot to understand "dogs can run" If you recall from episode 1 the robot or brain was able to understand "dogs can run"


:BlankCanBlank
  $IsListening = 0
  $Junction = "can"
  $SpeechLength = Length($HumanSaid)
  $JuncIndex = IndexOf($HumanSaid,$Junction)
  $FirstPart = SubString($HumanSaid,0,$JuncIndex-1)
  $LastPart = SubString($HumanSaid, $JuncIndex + Length($Junction) + 1,$SpeechLength - ($JuncIndex + Length($Junction))-1)
  $SearchPhrase = $FirstPart + "_:::_" + $LastPart
  $MemoryType = "BlankCanBlank"
  ControlCommand("Agents",ScriptStartWait,"WriteMemory")
  if($WriteMemoryCheck = 0)
    $SayWhat = "I knew that!"
  else 
    $SayWhat = "I now know that " + $FirstPart + " " + $Junction + " " + $LastPart
  endif
$IsListening = 1

Going thru this script line by line we first see that we set the IsListening flag = 0 so the robot will not listen while it is processing the current speech. Next to set what I call the Junction. This is the word or phrase that separates the subject from the object, in this case the word "can". We then Find the total spoken speech length and store this in the variable $SpeechLength. Next we need to know where in the speech string the junction is located. So for this we use the IndexOf function. Instead of using the variable $Junction I could have used "can", but then the script would not be as easily changed later when we want to reuse it for another Memory Agent. Now to get the first part.To do this we use the SubString function. The $HumanSaid is the source string to search, the zero is where to start and the JuncIndex -1 is the number of characters. The reason for the -1 is because we do not want the space between the first part and the word can. To get the last part we start at the junction index instead of 0. But this will give us the word "can" also, so we move our start point ahead the length of the junction, and don't forget the space. Now to calculate the remaining characters. To do this we just take how many characters were in the entire string, subtract all the characters up to the junction, plus the length of the junction, oh and again don't forget the space and what is left is our total remaining characters. The script now calls the WriteMemory Agent that we went over before. Now to change this script into a BlankHaveBlank script, all we need to do is: Change the first line of the script from :BlankCanBlank to BlankHaveBlank, change out $Junction assignment from "can" to "have", change our $MemoryType from "BlankCanBlank" to "BlankHaveBlank".

And now we have a new Agent.

I think I failed to mention that at this point I am manually creating the text files initially. After that the scripts read and write to them. So in your file path create a file for each memory type: xBlankHaveBlank, xBlankHaveBlank. You dont have to create a file for CanBlankBlank or DoBlankHaveBlank because they will search the other files for the answer.

I am currently working on possibly adding a ! to the memory for an entry such as dog can not fly - dos_:::_!fly. This way if an entry was not present the robot could say "I don't know" instead of "no".

Well that's all for this post.

Please fell free to post comments, questions or recommendations that might improve the project.

PRO
USA
#7  

List of Agents I currently have completed.

BlankLikeBlank HowManyBlankDoBlankHave DoBlankHaveBlank BlankLikeBlank CanBlankBlank BlankIsPluralOfBlank BlankIsInBlank IsBlankBlank BlankIsBlank BlankHaveBlank BlankCanBlank

If anyone would like me to post the code just let me know.

Canada
#8  

I would certainly like you to post the code!

PRO
USA
#9  

@Holy1 Let me know your email and I will send you everything I have completed so far.

#10  

I'd be interested as well @rz90208. My email is weyoun7ster at gmail dot com

#11  

I to would like a copy of your code. Email: edited

PRO
USA
#12  

I’m very intrigued by this. Be great if you could do a video demonstrating this in cation. Would love to have a copy of this code as well.

Canada
#13  

@rz90208 my email is mr_r51@hotmail.com. Thank you. Very fascinating.

PRO
USA
#14  

@fxrtst Currently my InMoov is awaiting parts so I am working the software side of the project but I will post a video when he is operational again.

@Everyone I din't realize so many were following this thread. I considered just posting my project but I have many things going on and have over 200+ scripts written and wont get then all tied together until UNAS is complete and up and running.

So here goes: (Please remember this is a work in progress)

First decide on a directory to store your memory files. I use c:\users\UserName\RobotName
Now create empty text files with the following names: xBlankCanBlank xBlankHaveBlank xBlankHaveBlankBlank xBlankIsBlank xBlankIsInBlank xBlankIsPluralOfBlank xBlankLikeBlank (I will add more as I write them but these are the basic ones) To teach your bot you can talk to it or edit these files directly. Then you will need 2 Script Managers one named Agents and one named Services. In the Agents Script Manger are: WriteMemory


#********************************************************************
# Routine requires: $MemoryType, $SearchPhrase, $Junction, $ReadType
# ReadType 
# 1 = Find all entries that match first part of $SearchPhrase up to $Junction
# 2 = Find entry that matchs $SearchPhrase
# 3 = Compare First Part with search phrase and return all that match
# 4 = Compare last part with search phrase and return all that match
# Results are returned in an array $ReadResultsArray[x]
#********************************************************************* 
#Testing settings 
#$Junction = "can"
#$memoryType = "BlankIsInBlank"
#$SearchPhrase = "Wisconsin"
#$ReadType = 2
#End Testing settings
#**************************************************************
DefineArray($ReadResultsArray,1)
$Delimit = "_:::_"
$FilePath = "C:\users\richard\unas\x" + $Memorytype + ".txt"
FileReadReset($FilePath) #Reset read to start of file
if($ReadType = 1)
  goto(ReadType1)
elseif($ReadType = 2)
  goto(ReadType2)
elseif($ReadType = 3)
  goto(ReadType3)
elseif($ReadType = 4)
  goto(ReadType4)
endif
Return 
#*******************************************************
:ReadType1
$ReadResultsCount = 0
:Loop1
 Goto(ReadLine)
  if(Length($Trash) > 0)
   ControlCommand("Agents",ScriptStartWait,"ConvertToLowercase")
     if($RMFirstPart + "_:::_" + $RMLastPart = $SearchPhrase)
    AppendArray($ReadResultsArray,$SearchPhrase)
    FileReadClose($FilePath)
    $ReadResultsCount = 1
    $EOF = 0
    Return 
  else 
  goto(Loop1)
  endif 
endif 
fileReadClose($FilePath)
$EOF = 1
Return
#*******************************************************
:ReadType2
:Loop2
goto(CheckEOF)
if($EOF = 0)
  goto(ReadLine)
  if($RMFirstPart = $SearchPhrase)
    AppendArray($ReadResultsArray,$RMLastPart)
    FileReadClose($FilePath)
    $ReadResultsCount = 1
    return 
  else 
    goto(Loop2)
  endif 
endif 
FileReadClose($FilePath)
$ReadResultsCount = 0
return 
#********************************************************
:ReadType3
$LoopCount = 1
:Loop3
 goto(ReadLine)
 Print(Length($RMFirstPart))
 Print(Length($SearchPhrase))
 Print(Length($Trash))
 if(Length($Trash) > 0)
    ControlCommand("Agents",ScriptStartWait,"ConvertToLowercase")
    Print($RMFirstPart)
  if($RMFirstPart = $SearchPhrase)
    AppendArray($ReadResultsArray,$RMLastPart)
    $LoopCount = $LoopCount + 1
    goto(Loop3)
  else 
    goto(Loop3)
  endif
  Print($LoopCount)
  endif
FileReadClose($FilePath) 
$ReadResultsCount = $LoopCount - 1
return 
#**********************************************************
:ReadType4
$LoopCount = 0
:Loop4
goto(CheckEOF)
if(FileReadEnd($FilePath) = 0)
  goto(ReadLine)
    if($RMLastPart = $SearchPhrase)
    AppendArray($ReadResultsArray,$RMFirstPart)
    $LoopCount = $LoopCount + 1
    goto(Loop4)
  else 
    goto(Loop4)
  endif 
endif 
FileReadClose($FilePath)
$ReadResultsCount = $LoopCount
return 
:ReadLine
$Trash = FileReadLine($FilePath)
if(Length($Trash) = 0)
  $EOF = 1
return 
endif
$SentenceLength = Length($Trash)
$RMFirstPartIndex = IndexOf($Trash,$Delimit)
$RMFirstPart = SubString($Trash,0,$RMFirstPartIndex)
$RMLastPartIndex = $RMFirstPartIndex + Length($Delimit)
$RMLastPartLength = $SentenceLength - $RMLastPartIndex
$RMLastPart = SubString($Trash,$RMLastPartIndex,$RMLastPartLength)
return 

#***********************************************
:CheckEOF
$EOF = 0
if(FileReadEnd($FilePath)  = 1) #Test for end of file
  FileReadClose($FilePath)
  $EOF = 1
 else
  $EOF = 0
endif
Print($EOF)
Return 
#************************************************

WriteMemory


#$MemoryType = "BlankIsInBlank"
  $FileName = "c:\users\richard\unas\x" + $MemoryType + ".txt" 
  #Check if Memory currently exists
 #$WriteMemoryCheck = 1 # Set memory check flag
 
 $ReadType = 1
  ControlCommand("Agents",ScriptStartWait,"ReadMemory")
  Print($ReadResultsCount)
  
  if($ReadResultsCount = 0) #Memory does not currently exist
      FileReadReset($FileName)
      :Loop1
      $Trash = FileReadLine($FileName)
      $EndFlag = FileReadEnd($FileName)
      if($EndFlag = 1)
       Goto(WriteMemory)
       $WriteMemoryCheck = 1
       return
      else
      goto(Loop1)
      endif
         Return
       endif
 $WriteMemoryCheck = 0   
Return
   $SayWhat = "Should not be here"
  :WriteMemory  
        FileReadClose($FileName)
        FileWriteLine($FileName,$SearchPhrase)
       # FileWrite($FileName,"_:::_")
       # FileWriteLine($FileName,$SecondPart)
       # FileReadClose($FileName)
       $WriteMemoryCheck = 1
   Return 

ConvertToLowercase


:LowerCase
$LCStringLength = Length($Trash)
$LCFirstLetter = SubString($Trash,0,1)
$LCFirstLetterValue = GetByteAt($Trash,0)
if($LCFirstLetterValue < 97)
  $LCFirstLetterValue = $LCFirstLetterValue + 32
  $LCStringLength = Length($Trash)
  $NewString = GetAsByte($LCFirstLetterValue) + SubString($Trash,1,$LCStringLength-1)
  $Trash = $NewString
endif 
return 

BlankCanBlank


:BlankCanBlank
  $IsListening = 0
  $Junction = "can"
  $SpeechLength = Length($HumanSaid)
  $JuncIndex = IndexOf($HumanSaid,$Junction)
  $FirstPart = SubString($HumanSaid,0,$JuncIndex-1)
  $LastPart = SubString($HumanSaid, $JuncIndex + Length($Junction) + 1,$SpeechLength - ($JuncIndex + Length($Junction))-1)
  $SearchPhrase = $FirstPart + "_:::_" + $LastPart
  $MemoryType = "BlankCanBlank"
  ControlCommand("Agents",ScriptStartWait,"WriteMemory")
  if($WriteMemoryCheck = 0)
    $SayWhat = "I knew that!"
  else 
    $SayWhat = "I now know that " + $FirstPart + " " + $Junction + " " + $LastPart
  endif
$IsListening = 1

BlankHaveBlank


:BlankHaveBlank
  $IsListening = 0
  $Junction = "have"
  $SpeechLength = Length($HumanSaid)
  $JuncIndex = IndexOf($HumanSaid,$Junction)
  $FirstPart = SubString($HumanSaid,0,$JuncIndex-1)
  $LastPart = SubString($HumanSaid, $JuncIndex + Length($Junction) + 1,$SpeechLength - ($JuncIndex + Length($Junction))-1)
  $SearchPhrase = $FirstPart + "_:::_" + $LastPart
  $MemoryType = "BlankHaveBlank"
  ControlCommand("Agents",ScriptStartWait,"WriteMemory")
  Print($WriteMemoryCheck)
  if($WriteMemoryCheck = 0)
    $SayWhat = "I knew that!"
  else 
    $SayWhat = "I now know that " + $FirstPart + " have " + $LastPart
  endif
$IsListening = 1

BlankHaveBlankBlank


:BlankHaveBlankBlank
  $IsListening = 0
  $Junction = "have"
  $SpeechLength = Length($HumanSaid)
  $JuncIndex = IndexOf($HumanSaid,$Junction)
  $FirstPart = SubString($HumanSaid,0,$JuncIndex-1)
  $SecondPart1 = SubString($HumanSaid,$JuncIndex + 5,Length($HumanSaid) - ($JuncIndex +5))
  $SecondPart = SubString($SecondPart1,0,IndexOf($SecondPart1," "))
  $LastPart = SubString($SecondPart1,IndexOf($SecondPart1," ")+ 1,Length($SecondPart1) - (IndexOf($SecondPart1, " ") + 1))
  $SearchPhrase = $FirstPart + "_:::_" + $SecondPart + " " + $LastPart
  $MemoryType = "BlankHaveBlankBlank"
  ControlCommand("Agents",ScriptStartWait,"WriteMemory")
  if($WriteMemoryCheck = 0)
    $SayWhat = "I knew that!"
  else 
    $SayWhat = "I now know that " + $FirstPart + " have " + $SecondPart + " " + $LastPart
  endif
$IsListening = 1

BlankIsBlank


:BlankIsBlank
  $IsListening = 0
  $Junction = "is"
 # if(SubString($HumanSaid,0,4) = "the " | SubString($HumanSaid,0,4) = "The ")
 #   $Trash = SubString($HumanSaid,4,Length($HumanSaid) - 4)
 #   $HumanSaid = $Trash
 # endif 
  $SpeechLength = Length($HumanSaid)
  $JuncIndex = IndexOf($HumanSaid,$Junction)
  $FirstPart = SubString($HumanSaid,0,$JuncIndex-1)
  $LastPart = SubString($HumanSaid, $JuncIndex + Length($Junction) + 1,$SpeechLength - ($JuncIndex + Length($Junction))-1)
  $SearchPhrase = $FirstPart + "_:::_" + $LastPart
  $MemoryType = "BlankIsBlank"
  Print($SearchPhrase)
  ControlCommand("Agents",ScriptStartWait,"WriteMemory")
  Print($WriteMemoryCheck)
  if($WriteMemoryCheck = 0)
    $SayWhat = "I knew that!"
  else 
    $SayWhat = "I now know that " + $FirstPart + " is " + $LastPart
  endif
$IsListening = 1

BlankIsInBlank


:BlankIsInBlank
  $IsListening = 0
  $Junction = "is in"
  $SpeechLength = Length($HumanSaid)
  $JuncIndex = IndexOf($HumanSaid,$Junction)
  $FirstPart = SubString($HumanSaid,0,$JuncIndex-1)
  $LastPart = SubString($HumanSaid, $JuncIndex + Length($Junction) + 1,$SpeechLength - ($JuncIndex + Length($Junction))-1)
  $SearchPhrase = $FirstPart + "_:::_" + $LastPart
  $MemoryType = "BlankIsInBlank"
  Print($SearchPhrase)
  ControlCommand("Agents",ScriptStartWait,"WriteMemory")
  Print($WriteMemoryCheck)
  if($WriteMemoryCheck = 0)
    $SayWhat = "I knew that!"
  else 
    $SayWhat = "I now know that " + $FirstPart + " is in " + $LastPart
  endif
  $IsListening = 1

BlankIsPluralOfBlank


:BlankIsThePluralOfBlank
  $IsListening = 0
  $Junction = "is the plural of"
  $SpeechLength = Length($HumanSaid)
  $JuncIndex = IndexOf($HumanSaid,$Junction)
  $FirstPart = SubString($HumanSaid,0,$JuncIndex-1)
  $LastPart = SubString($HumanSaid, $JuncIndex + Length($Junction) + 1,$SpeechLength - ($JuncIndex + Length($Junction))-1)
  $SearchPhrase = $FirstPart + "_:::_" + $LastPart
  $MemoryType = "BlankIsThePluralOfBlank"
  Print($SearchPhrase)
  ControlCommand("Agents",ScriptStartWait,"WriteMemory")
  Print($WriteMemoryCheck)
  if($WriteMemoryCheck = 0)
    $SayWhat = "I knew that!"
  else 
    $SayWhat = "I now know that " + $FirstPart + " is the plural of " + $LastPart
  endif
$IsListening = 1

BlankLikeBlank


:BlankLikeBlank
  $IsListening = 0
  $Junction = "like"
  $SpeechLength = Length($HumanSaid)
  $JuncIndex = IndexOf($HumanSaid,$Junction)
  $FirstPart = SubString($HumanSaid,0,$JuncIndex-1)
  $LastPart = SubString($HumanSaid, $JuncIndex + Length($Junction) + 1,$SpeechLength - ($JuncIndex + Length($Junction))-1)
  $SearchPhrase = $FirstPart + "_:::_" + $LastPart
  $MemoryType = "BlankLikeBlank"
  Print($SearchPhrase)
  ControlCommand("Agents",ScriptStartWait,"WriteMemory")
  Print($WriteMemoryCheck)
  if($WriteMemoryCheck = 0)
    $SayWhat = "Yes, that is a true statement."
  else 
    $SayWhat = "I now know that " + $FirstPart + " " + $Junction + " " + $LastPart
  endif
$IsListening = 1

CanBlankBlank


:CanBlankBlank

  $IsListening = 0
  $Junction = " "
  $SpeechLength = Length($HumanSaid)
  $HumanSaid2 = SubString($HumanSaid,4,$SpeechLength -4)
  $JuncIndex = IndexOf($HumanSaid2,$Junction)
  $FirstPart = SubString($HumanSaid2,0,$JuncIndex)
  $LastPart = SubString($HumanSaid2, $JuncIndex + Length($Junction),Length($HumanSaid2) - (Length($Junction)+Length($FirstPart)))
  $SearchPhrase = $FirstPart + "_:::_" + $LastPart
  $MemoryType = "BlankCanBlank"
  $ReadType = 1
  $WriteFileCheck = 0
  ControlCommand("Agents",ScriptStartWait,"ReadMemory")
  if($ReadResultsCount = 0)
    $SayWhat = "As far as I know, " + $FirstPart + "can not " + $LastPart
  elseif($ReadResultsCount = 1)
    $SayWhat = "Yes, I believe " + $FirstPart + " can " + $LastPart
  endif 
$IsListening = 1

CountBackwards


 $IsListening = 0
 if(Contains($HumanSaid, "count backwards starting at ") = true) #28
   $CountBackFrom = SubString($HumanSaid,28,Length($HumanSaid) - 28)
   elseif(Contains($HumanSaid, "count backwards starting from ") = true) #30
  $CountBackFrom = SubString($HumanSaid,30,Length($HumanSaid) - 30)
  elseif(Contains($HumanSaid, "count backwards from ") = true) #21
  $CountBackFrom = SubString($HumanSaid,21,Length($HumanSaid) - 21)
 endif
 :CountBackLoop
 if($CountBackFrom >= 0)
 $SayWhat = $CountBackFrom
 Waitfor($IsTalking = 0)
 $CountBackFrom = $CountBackFrom -1
 goto(CountBackLoop)
 endif
 $IsListening = 1
 

DoBlankHaveBlank



:DoBlankHaveBlank


  $IsListening = 0
  $Junction = "have"

  $SpeechLength = Length($HumanSaid)
  $JuncIndex = IndexOf($HumanSaid, $Junction)
  $FirstPart = SubString($HumanSaid, 3, $JuncIndex - 3)
  $LastPart = SubString($HumanSaid, $JuncIndex + (Length($Junction) + 1), $SpeechLength - ($JuncIndex + Length($Junction)+1))
  $SearchPhrase = SubString($FirstPart, 0,Length($FirstPart)-1) + "_:::_" + $LastPart
  $MemoryType = "BlankHaveBlank"
  $ReadType = 1
  $WriteFileCheck = 0
  ControlCommand("Agents",ScriptStartWait,"ReadMemory")
  Print($ReadResultsCount)
  if($ReadResultsCount = 0)
    $SayWhat = "I far as I know, " + $FirstPart + "do not have " + $LastPart
  elseif($ReadResultsCount = 1)
    $SayWhat = "Yes, I believe " + $FirstPart + " do have " + $LastPart
  endif 
$IsListening = 1
 

HowManyBlankDoBlankHave


:HowManyBlankDoBlankHave
$HumanSaid = "how many legs do dogs have"
  $Foundit = 0
  $IsListening = 0
  $Junction = "do"

  $SpeechLength = Length($HumanSaid)
  $JuncIndex = IndexOf($HumanSaid, $Junction)
  $LastPart = SubString($HumanSaid, 9, $JuncIndex - 10)
  $FirstPart = SubString($HumanSaid, $JuncIndex + (Length($Junction) + 1), $SpeechLength - ($JuncIndex + Length($Junction)+1)-5)
  $SearchPhrase = $FirstPart
  Print(Length($SearchPhrase))
 
  $MemoryType = "BlankHaveBlank"
  $ReadType = 3
  $WriteMemoryCheck = 0
  ControlCommand("Agents",ScriptStartWait,"ReadMemory")
  
  $Counter5 = $ReadResultsCount
  repeatuntil( $Counter5 = 0 ) 
    if(Contains($ReadResultsArray[$Counter5]," ") & GetByte(SubString($ReadResultsArray[$Counter5],0,1)) > 47 & GetByte(SubString($ReadResultsArray[$Counter5],0,1)) < 58)
      $SayWhat = "To my knowledge, " + $FirstPart + " have " + $ReadResultsArray[$Counter5]
      $Foundit = 1
    endif
    $Counter5--
  endrepeatuntil 
  if($Foundit = 0)
    $SayWhat = "I am not sure how many " + $LastPart + " a " + $FirstPart + " has"
  endif 
 $IsListening = 1

IsBlankBlank


:IsBlankBlank
  $IsListening = 0
  $Junction = " "
  $SpeechLength = Length($HumanSaid)
  $HumanSaid2 = SubString($HumanSaid,3,$SpeechLength -3)
  $JuncIndex = IndexOf($HumanSaid2,$Junction)
  $FirstPart = SubString($HumanSaid2,0,$JuncIndex)
  $SecondPart = SubString($HumanSaid2, $JuncIndex + Length($Junction),Length($HumanSaid2) - (Length($Junction)+Length($FirstPart)))
  if($FirstPart = "the")
    $LastPart = SubString($SecondPart,IndexOf($SecondPart,$Junction)+ 1,Length($SecondPart) - (IndexOf($SecondPart,$Junction)+1))
    $SecondPart = SubString($HumanSaid2,IndexOf($HumanSaid2,$Junction)+1, IndexOf($SecondPart,$Junction))
  else 
    $SecondPart =""
    $LastPart = SubString($HumanSaid2,IndexOf($HumanSaid2,$Junction)+1,Length($HumanSaid) - (IndexOf($HumanSaid2,$Junction)+4))
  endif 
  $SearchPhrase = $FirstPart + $SecondPart + "_:::_" + $LastPart
  $MemoryType = "BlankIsBlank"
  $ReadType = 1
  $WriteFileCheck = 0
  ControlCommand("Agents",ScriptStartWait,"ReadMemory")
   if($ReadResultsCount = 0)
    $SayWhat = "As far as I know, " + $FirstPart + " " + $SecondPart + " is not " + $LastPart
  elseif($ReadResultsCount = 1)
    $SayWhat = "Yes, I believe " + $FirstPart + " " +$SecondPart + " is " + $LastPart
  endif 
$IsListening = 1

WhatCanBlankDo


:WhatCanBlankDo


  $IsListening = 0
  $Junction = "can"

  $SpeechLength = Length($HumanSaid)
  $JuncIndex = IndexOf($HumanSaid, $Junction)
  $FirstPart = SubString($HumanSaid, 3, $JuncIndex - 3)
 # $LastPart = SubString($HumanSaid, $JuncIndex + (Length($Junction) + 1), $SpeechLength - ($JuncIndex + Length($Junction)+1))
  $SearchPhrase = $FirstPart
  $MemoryType = "WhatCanBlankDo"
  $ReadType = 3
  $WriteFileCheck = 0
  ControlCommand("Agents",ScriptStartWait,"ReadMemory")
  if($ReadResultsCount = 0)
    $SayWhat = "I do not know what " + $FirstPart + "can do"
  elseif($ReadResultsCount > 0)
    repeatwhile($ReadResultsCount > 0)
     $SayWhat = $FirstPart + " " + $ReadResultsArray[$ReadResultsCount]
     waitfor($IsTalking = 0)
     $ReadResultsCount = $ReadResultsCount - 1
    endrepeatwhile 
  endif 
$IsListening = 1
endif 

Now for the Services Script Manager AuditoryService


:AuditoryService
#The Auditory service monitors the $BingSpeech variable for speech and then routes this speech to
#the proper Agent for processing.
#
#***************************************
WaitforChange($BingSpeech)
#$BingSpeech = "Do dogs have feathers"
 $HumanSaid = $BingSpeech
# $CapturedSpeech = $BingSpeech
#$ToBotLibre = $BingSpeech
$BingSpeech = ""
#***************************************
#Convert the first letter of the captured speech to lower case
$Trash = $HumanSaid
ControlCommand("Agents",ScriptStartWait,"ConvertToLowercase")
$HumanSaid = $Trash
#***************************************
#YesNoQuestions
#Goto(GetFirstWord)
#if($FirstWord = "might" | $FirstWord = "should" | $FirstWord = "could" | $FirstWord = "may" | $FirstWord = "did" | $FirstWord = "do" |$firstWord = "are" |$FirstWord = "can" | $FirstWord = "will" | $FirstWord = "does" | $FirstWord = "is" | $FirstWord = "shall" | $FirstWord = "have" | $FirstWord = "has")
#  ControlCommand("Agents",ScriptStartWait,"YesNoQuestion")
#BlankCanBlank
if(Contains($HumanSaid," can ") & !Contains($HumanSaid,"What can "))
  ControlCommand("Agents",ScriptStartWait,"BlankCanBlank")
#CanBlankBlank
elseif(Contains($HumanSaid,"can ") & !Contains($HumanSaid,"What can ") & !Contains($HumanSaid," can "))
  ControlCommand("Agents",ScriptStartWait,"CanBlankBlank")
#BlankHaveBlank
elseif(Contains($HumanSaid,"have") & !Contains($HumanSaid,"Do "))
  ControlCommand("Agents",ScriptStartWait,"BlankHaveBlank")
#BlankIsInBlank
elseif(Contains($HumanSaid,"is in"))  
  ControlCommand("Agents",ScriptStartWait,"BlankIsInBlank")
#BlankIsThePluralOfBlank
elseif(Contains($HumanSaid,"is the plural of")) 
  ControlCommand("Agents",ScriptStartWait,"BlankIsThePluralOfBlank")
#BlankIsBlank 
elseif(Contains($HumanSaid," is ")) 
  ControlCommand("Agents",ScriptStartWait,"BlankIsBlank")
#DoBlankHaveBlank
elseif(Contains($HumanSaid,"do ") & Contains($HumanSaid, " have ") & !Contains($HumanSaid, "how many"))
  ControlCommand("Agents",ScriptStartWait,"DoBlankHaveBlank")
elseif(Contains($HumanSaid,"do ") & Contains($HumanSaid, " have ") & Contains($HumanSaid, "how many"))
  ControlCommand("Agents",ScriptStartWait,"HowManyBlankDoBlankHave")
#BlankLikeBlank
elseif(Contains($HumanSaid," like ")& !Contains($HumanSaid, "Do "))
  ControlCommand("Agents",ScriptStartWait,"BlankLikeBlank")
#DoBlankLikeBlank
elseif(Contains($HumanSaid, "do ") & Contains($HumanSaid, "like "))
  ControlCommand("Agents",ScriptStartWait,"DoBlankLikeBlank")
elseif(Contains($HumanSaid,"count backwards"))
ControlCommand("Agents",ScriptStartWait,"CountBackwards") 
else
ControlCommand("AimlBot",SetPhrase,$HumanSaid)
$SayWhat = $BotResponse  
endif
goto(AuditoryService)

VoiceService


$SayWhat = ""
$VoiceServiceStatus = 1
$IsTalking = 0
:VoiceService
#The Voice service monitors the $SayWhat variable for change and if it is not equal
#to null, will set the IsTalking flag and say what is stored in that vaiable.
#After speaking the phrase, it will reset the IsTalking flag and
#Set the $SayWhat variable to null and again wait for change.


waitForChange($SayWhat)
if($VoiceServiceStatus & 1)
  :Talking
  if($IsTalking = 0)
 
    $IsTalking = 1  #set the Robot is talking flag
      if($SayWhat != "")
  

        sayWait($SayWhat)
       

      endif
  :Done
  $SayWhat = ""
  $IsTalking = 0 #Clear the Robot is talking flag
  
  endif
endif
Goto(VoiceService)


You can look back in the post for the code for VoiceRecognition and Bing. This should get your simple brain up and going. I originally had all the Agents waiting for change to the $HumanSaid variable so when it did change all agents would evaluate the speech at the same time but only the one pass the if statement and process the speech. Well that didn't workout. I am not sure if it is a bug or just bad programming but as soon as I started one script another unrelated script would start. Anyway have fun I will continue to post as more get written.

PRO
USA
#15  

Once you have the services and agents created start the VoiceService and the Auditory Service and you can test by opening one of the Agents such as the CanBlankBlank and at the top of the script add a test line of


$HumanSaid = "can cats purr"

and run the script

the bot shoult repond with "As far as I know cats cannot purr"

Now to teach it that cats can purr, open the Agent BlankCanBlank and add the test line


$HumanSaid = "cats can purr"

Now run this script. The bot should respond "I now know that cats can purr"

Now go back to the CanBlankBlank Agent and run it again. The bot should now respond with "Yes, I believe cats can purr"

This same thing can be done by just speaking the same words.

Don't forget to remove or comment out the test line after you are done testing.

PRO
USA
#16  

Just an added tidbit, The backslash has always been an issue when working with strings. I believe I have come up with a work around. Using the GetAsByte() command, I loop thru the string removing the backslashes one at a time. You could replace them with another character but I just skip over them.


:CleanItUpLoop
if(Contains($BotResponse,GetAsByte(92)))
  $FirstPart = SubString($BotResponse,0,IndexOf($BotResponse,GetAsByte(92)))
  $SecondPart = SubString($BotResponse,IndexOf($BotResponse,GetAsByte(92)) + 1,Length($BotResponse) - (IndexOf($BotResponse,GetAsByte(92))+1))  
  $BotResponse = $FirstPart + $SecondPart
Goto(CleanItUpLoop)
endif

#17   — Edited

I'm trying to set this up and am having some problems. I think the ReadMemory script is mislabeled as there are two WriteMemory scripts. I believe the first one is the read one.  When I try the can cats purr example I get an error in line 74 of ReadMemory - variable not defined $RMFirstPart Also when I try cats can purr I get   12: if($WriteMemoryCheck = 0)> Error on line 12: Variable not defined: $WriteMemoryCheckI appreciate any help.

PRO
USA
#18  

How ironic, I lost most of my scripts when I upgraded to ARC, I am now coming back to this thread to get my code so I can start converting it to JavaScript. And my tutorial is a real good memory refresher Thank you DJ for saving all the old posts when you went to the new site. Never thought I would be using it as a backup. Wish I would have posted a lot more of my code or posted the entire project.

RichardZ