Skip to main content

Script structure

At the previous step, we’ve created a chatbot.yaml configuration file and a main.sc script for the bot.

Now, let’s work with the structure of the script. We will create intents for navigating states, and will also use the functions that we’ve created previously.

Start

The script starts from the Start state. The bot sends a welcome message and asks the user to choose who will start the game first.

state: Start || modal = true
q!: $regex</start>
intent!: /LetsPlay
script:
$session = {}
$client = {}
$temp = {}
$response = {}
a: Let's play "Cities" Game. Who will start first: bot or user?

state: User
intent: /user
a: Name the city
script:
$session.keys = Object.keys($Cities);
$session.prevBotCity = 0;
go!: /LetsPlayCitiesGame

state: Computer
intent: /computer
script:
$session.keys = Object.keys($Cities);
var city = $Cities[chooseRandCityKey($session.keys)].value.name
$reactions.answer(city)
$session.prevBotCity = city

go!: /LetsPlayCitiesGame

state: LocalCatchAll
event: noMatch
a: I don't understand you. Please try again.

Under the script tag, initialize all session variables to zero. We use them to save user’s and bot’s replies.

Let’s create a Letsplay intent, so we can get to the Rules state from any other state when the user sends a message Let's play.

To view the intents settings, go to the NLU > Intents tab on the control panel. Create an intent and specify phrases in the Training phrases field: let's play, play, I want to play.

Intent Letsplay

Let’s set modal flag to true in the Start state. It is used when you need the user to provide some information for the game to go on. In our case, the game cannot go on until the user chooses who starts the game first.

tip
Learn more about the process of configuring intents

The state includes three nested states: Computer, User and LocalCatchAll.

User

The transition to the User state is triggered by the /user intent. Then the message Name the city is displayed.

state: User
intent: /user
a: Name the city
script:
$session.keys = Object.keys($Cities);
$session.prevBotCity = 0;
go!: /LetsPlayCitiesGame

Create a /user intent and specify phrases in the Training phrases field: user, me, not you, I.

Intent user

tip
To make the bot better understand the users, add more phrases to the Training Phrases field. The more phrases there are, the more likely it is that the bot will correctly detect the user’s intention.

In the script tag, assign an array of id from the city/cities-en.csv list to the $session.keys variable.

$session.keys = Object.keys($Cities);

Clear the $session.prevBotCity variable in which we store the city named by the bot. Then move to LetsPlayCitiesGame state using go! tag.

Computer

The bot moves to the Computer state when the /computer intent is triggered.

state: Computer
intent: /computer
script:
$session.keys = Object.keys($Cities);
var city = $Cities[chooseRandCityKey($session.keys)].value.name
$reactions.answer(city)
$session.prevBotCity = city
go!: /LetsPlayCitiesGame

Create a /computer intent and specify phrases in the Training phrases field: computer, you, not me.

Intent computer

In the script tag, assign an array of id from the city/cities-en.csv list to the $session.keys variable.

Write a randomly selected city into the city variable using the chooseRandCityKey() function. Let’s use the built-in function $reactions.answer() to display the city from city as the bot’s response.

Save the city named by the bot to the $session.prevBotCity variable. Then move to LetsPlayCitiesGame state.

LocalCatchAll

If modal=true, the system will process the request in the context of that state, i.e. the request can only be switched to one of its nested states.

If the nested states have no matching answer and the local LocalCatchAll state is missing, the system returns an error. The error log tells you that no state to switch to was found in the script.

So, let’s create a LocalCatchAll state. The bot switches to this state if it receives a message that differs from all the considered options in the states.

state: LocalCatchAll
event: noMatch
a: I don't understand you. Please try again.

LetsPlayCitiesGame

The LetsPlayCitiesGame state consists of two nested states: CityPattern and NoMatch.

 state: LetsPlayCitiesGame
state: CityPattern
q: * $City *
script:
if (isAFullNameOfCity()) {
if (checkLetter($parseTree._City.name, $session.prevBotCity) == true
|| $session.prevBotCity == 0) {
var removeCity = findByName($parseTree._City.name, $session.keys, $Cities)

if (checkCity($parseTree, $session.keys, $Cities) == true) {
$session.keys.splice(removeCity, 1)
var key = responseCity($parseTree, $session.keys, $Cities)
if (key == 0) {
$reactions.answer("I give up")
} else {
$reactions.answer($Cities[key].value.name)
$session.prevBotCity = $Cities[key].value.name
removeCity = findByName($Cities[key].value.name, $session.keys, $Cities)
$session.keys.splice(removeCity, 1)
}
} else $reactions.answer("You can't name the same city twice. Try again.")
}
} else $reactions.answer("Please use only full cities name")

state: noMatch
event: noMatch
a: I don't know this city. Try again.

CityPattern

The transition to the CityPattern state is based on the * $City * pattern specified in the q tag.

The script tag implements the game logic:

  • In the first condition, we check that the user has entered the full name of the city. If false, the following message is displayed:
Please use only full cities name
  • If true, we check whether the first letter of the city entered by the user matches the last letter of the city entered by the bot, or the $session.prevBotCity variable equals to 0.
  • If true, save the entered city in the removeCity.
  • Then we check whether the city has been named earlier. If so, the following message is displayed:
You can't name the same city twice. Try again.
  • Otherwise, remove the entered city from the list. Assign the result of responseCity() function to the key variable.
  • If the key variable equals to 0, then the bot has run out of city names starting with the last or the second to last letter. The bot displays the message I give up.
  • Otherwise, we display the city generated by the bot and remove it from the city list.

NoMatch

If the user makes a mistake when entering a city or names a non-existent city, the noMatch event is triggered. The bot displays a message:

I don't know this city. Try again.

EndGame

The EndGame state is used to process the end of the game in case the user chooses to finish the game.

state: EndGame
intent!: /endThisGame
a: That's a pity! If you change your mind, just text me "Let's play"

Create an /endThisGame intent that will process the transition to the EndGame state from any other state. There can be two cases when the users want to finish the game: they don’t want to play anymore or they give up to continue the city names chain. So, specify phrases in the Training phrases field: stop, give up, tired, finish.

Intent endThisGame

Next, move on to testing the script.