How to build a “Bulls and Cows” capsule in Bixby?


What is “Bulls and Cows”?

Bulls and Cows is an old code-breaking mind or paper and pencil game for two or more players, predating the commercially marketed board game ” Mastermind ”. It is a game that may date back a century or more which uses numbers or words. The game is generally played with four digits but can also be played with any number of digits. The numerical version of the game is played with 4 digits, but can also be played with 3 or any other number of digits.

On a sheet of paper, the players each write a 4-digit secret number. The digits must be all different. Then, in turn, the players try to guess their opponent’s number who gives the number of matches. If the matching digits are in their right positions, they are “bulls”, if, in different positions, they are “cows”. Example:

  • Secret number: 4271
  • Opponent’s try: 1234
  • Answer: 1 bull and 2 cows. (The bull is “2”, the cows are “4” and “1”.)

The first one to reveal the secret number wins the game. As the first player has a logical advantage, the game can be balanced over multiple games by alternating the right to go first, or over a single game by granting the second player an equal number of guesses, possibly resulting in a tie. The game may also be played by two teams of 2–3 players, with the team members discussing their strategy before selecting a move.

For this capsule, I have changed a few things like for starters, the player can choose between three easy modes, medium and expert. In easy mode, the secret word is going to have three digits and the user will have six tries, for medium mode, the secret word is going to have four digits and the user will have eight tries and for expert mode, the secret word is going to have three digits and two alphabets and the user will have ten tries.

Basic components of Samsung Bixby:

 

Modelling concepts in Samsung Bixby:

The first step in building a capsule is to model your concepts. A concept is simply an object – it may represent user input (like ‘Guess’ in our capsule) or output (like ‘GameStructure’ in our capsule). A concept can be a primitive e.g. a string, integer etc., or a structured concept which contains primitive concepts.

Input Concepts:

  • Mode: easy, medium or expert
  • Guess: user guess
  • GameStructure: previous result as the current input

Output Concepts:

  • HomeStructure: home screen for the user to start the game or see instructions
  • GameMode: mode selected by the user
  • Instructions: how to play the game
  • GameStructure: response of the current guess
  • SecretWord: Contains secret word digit-wise.

Let’s look at how we model some of the concepts in Bixby. Here is a snippet of the Mode concept:

enum (Mode){
  description ()
  symbol (Easy)
  symbol (Medium)
  symbol (Expert)
  features { transient }
}

Our Mode concept is modelled as an enumeration; e.g. a fixed list of possible values that represent all of the modes.

The main output concept is GameStructure. It is modelled like this:

structure (GameStructure) {
  property (code) {
    type (Code)
    min (Optional) max (One)
  }	
  property (mode){
    type (Mode)
    min (Optional) max (One)
  }
  property (guess){
    type (Guess)
    min (Optional) max (One)
  }
  property (msg){
    type (ResponseMessage)
    min (Optional) max (One)
  }
  property (index){
   	 type (Index)
    min (Optional) max (One)
  }
  property (flag){
    type (Flag)
    min (Optional) max (One)
  }
  property (limit){
    type (Limit)
    min (Optional) max (One)
  }
  property (responses){
    type (History)
    min (Optional) max (Many)
  }
  property (digits){
    type (SecretWord)
    min (Optional) max (Many)
  }
  property (validInput){
    type (ValidInput)
    min (Optional) max (One)
  }
  property (exists){
    type (Exists)
    min (Optional) max (One)
  }
}

The GameStructure concept in a structure e.g. it contains other concepts. GameStructure is composed of secret code, user guess, game mode, index, response and few flag concept for different validation. Note the notation around cardinality: min and max. Min can be required or optional and max one or many.

As you can see, SecretWord has cardinality max as Many, this is because the array of secret word digits will be passed in this structure where each digit is of type Digit which is a primitive of type text. So the max(Many) cardinalities allow us to get an array of objects as a response.

Here is the SecretWord structure:

structure (SecretWord) {
  property (digit) {
    type (Digits)
    min (Optional) max (One)
  }
}

The HomeStructure is a structure containing image and response:

structure (HomeStructure) {
  property (image){
    type (OptionImage)
    min (Optional) max (One)
  }
  property (type){
    type (ResponseMessage)
    min (Optional) max (One)
  }
}

The ResponseMessage consist of the type of action that the user wants to call on click upon eg. StartAction or HowToPlay actions. StartAction starts the game directly without instructions this is useful when the user is familiar to the game. But, if the user doesn’t know how to play the game then HowToPlay action can be called. We will see the implementation of HomeStructure structure in the view to have a further understanding.

The Instructions structure is the output for HowToPlay actions. The user can get information about the game like rules, scoring, video link, etc. through this structure.

structure (Instructions) {
  property (message){
    type (InstructionMessage)
    min (Optional) max (One)
  }
  property (scoring){
    type (ScoringCriteria)
    min (Optional) max (One)
  }
  property (example){
    type (Examples)
    min (Optional) max (One)
  }
  property (link){
    type (VideoLink)
    min (Optional) max (One)
  }
}

Actions and Endpoints in Samsung Bixby:

We are now finished modelling our concepts – we have the necessary entities for our solution. Notice that no traditional code has been written. We have simply used a simple Bixby Language or bxb to describe our concepts.

We use the action to tell Bixby what to do. Actions are verbs that do something with the input concept and populate an output concept.

Here is the model for our HomeAction action:

action (HomeAction) {
  type(Search)
  output (HomeStructure)
}

This action doesn’t require any input as the purpose of this action is just to start the capsule which gives the user the option to choose between Start game and Instructions. The output for this action is HomeStructure structure which consists of the data returned from the code.

Here is the model for our StartAction action:

action (StartAction) {
  type(Search)
  collect{
    input (mode){
      type (GameMode)
      min (Required) max (One)
       default-init{
        intent{
          goal: GetMode
        }
      }
    }
  }
  output (GameStructure)
}

This capsule starts the actual game and initialize the GameStructure concept which is passed further to the GetGuess action as input. StartAction take GameMode as an input and if the mode is not provided then by default GetMode action will be called and this is because of the default-init block in the GameMode input block.

Here is the model for our GameMode action:

action (GetMode) {
  type(Search)
  collect{
    input (image){
      type (ModeImage)
      min (Required) max (One)
      default-init{
        intent{
          goal: ModeImage
          value: ModeImage{
            url: viv.core.Url("images/Modes/Easy.png")
          }
          value: ModeImage{
             url: viv.core.Url("images/Modes/Medium.png")
          }
          value: ModeImage{
             url: viv.core.Url("images/Modes/Expert.png")
          }
        }
      }
    }
  }
  output (GameMode)
}

This action gives the user the selection screen for modes. User needs to select from Easy, Medium and Hard mode, the selection screen is prompted because in default-init we are passing three values in ModeImage concept but as we can see the cardinality for ModeImage is max(One). So, Bixby is prompting us to select any one option.

Here is the action for HowToPlay action:

action (HowToPlay) {
  type(Search)
  output (Instructions)
}

This action gets the data from the code and passes it to the Instruction structure which is later passed to the view for user view.

Here is the action for GetGusess action:

action (GetGuess) {
  type (Search)
  collect {
    input (guess) {
      type (Guess)
      min (Required) max (One)
    }
    input (structure){
      type (GameStructure)
      min (Optional) max (One)
    }
  }
  output (GameStructure)
}

This is the main action which is responsible to get guess from the user and display the updated results. It takes two inputs user to guess and previous GameStructure.

We modelled an action above but have no behaviour. To create behaviour, we jump into writing code. But before we write code, we create an Endpoint which ties the actions with our codes.

Here are the Bulls And Cows endpoints:

endpoints {
  action-endpoints {
    action-endpoint (GetMode) {
      accepted-inputs (image)
      local-endpoint (GetMode.js)
    }
    action-endpoint (StartAction) {
      accepted-inputs (mode)
      local-endpoint (StartAction.js)
    }
    action-endpoint (GetGuess) {
      accepted-inputs (guess, structure)
      local-endpoint (GetGuess.js)
    }
    action-endpoint (GetModeImage) {
      accepted-inputs (mode)
      local-endpoint (GetModeImage.js)
    }
    action-endpoint (HowToPlay){
      accepted-inputs ()
      local-endpoint (HowToPlay.js)
    }
    action-endpoint (HomeAction){
      accepted-inputs ()
      local-endpoint (HomeAction.js)
    }
  }
}

In our endpoint, we are tying together the GetGuess action with our local Node.js code: GetGuess.js and defining the inputs as our Guess and GameStruture concepts. Similarly, for all the actions, there is local Node.js code. The code is not included here but is available at the GitHub link at the end of the article.

Modelling UI And speech output in Samsung Bixby:

Now that we have our output e.g. the GameStructure concept filled in, we need to give our user an answer – both via speech and in the UI. Our output is defined in a dialogue. Our GameStructure dialogue looks like this:

dialog (Result) {
     match: GameStructure(this)
     if(this.validInput == false && exists(this.validInput)){
          if(this.mode == 'Easy'){
               template (Oops, I need three numbers)
          }
          else-if(this.mode == 'Medium'){
               template (Oops, I need four numbers)
          }
          else-if(this.mode == 'Expert'){
                template (Oops, I need three numbers and two alphabets.)
          }
     }
     if(this.exists == true && exists(this.exists)){ 
          template (You already tried that one.)
     }
     if (this.index == 0 && exists(this.index)){
          template (){
               speech ("Guess the number")
          }
     }
    else{
         template ("[#{value(this.msg)}]")
     }
}

What this dialogue does is first, match the GameStructure concept output from GetGuess e.g. when GameStructure is called and returns data, this dialogue will be used.

The template tag defines the visual output at the top of the UI, the header if you will, in our case the simple “You already tried that one.” The speech tag defines what is spoken. On a voice-only device like the upcoming Samsung Galaxy Home, this would be the only output. Bixby will always speak (TTS) the text contained in the speech attribute of a dialogue.

A capsule will run with just a Dialog, but the UI will be very “programmer like.” We need to add a markup to format the GameStructure data.

To format the GameStructure data we create a view. There are several different ways to do so. We will choose one of the very simplest by using a layout view.

We will show the departure and arrival stations and then details about the individual trips.

The full code for the layout is available on GitHub. An excerpt is below:

for-each (this.responses){
     as (res){
          index-var (i)
          section{
               content{
                    hbox{
                         content{
                              vbox{
                                   halign (Center)
                                   valign (Baseline)
                                   content{
                                        text{ 
                                             style(Detail_L)
                                             value("#{i+1}")
                                        }
                                    }
                                }
                               vbox{
                                    halign (Center)
                                    valign (Baseline)
                                    content{
                                         text{
                                               style(Detail_L)
                                               value("[#{value(res.guess)}]")
                                          }
                                     }
                                }
                               vbox{
                                     halign (Center)
                                     valign (Baseline)
                                     content{
                                          text{
                                               style(Detail_L)
                                               value("[#{value(res.msg)}]")
                                          }
                                      }
                                }
                           }
                     }
                }
           }
      }
 }

Vocabulary and Training for Samsung Bixby:

When the user is asked about the mode, they may not use the proper names of mode like for expert other synonym is hard or if you want to call any mode by any different name, you can add that name into vocab. What we need is a list of synonyms and equivalent phrases. To do so, Bixby supports the concept of vocabulary. A snippet of our Mode vocabulary is below:

vocab (Mode) {
     "Easy" { "easy" }
     "Medium" { "medium" }
     "Expert" { "expert" "hard" }
}

Looking at the “Expert” line, we have defined “hard” and “expert” as synonyms. A user can use any of these and Bixby will resolve the input to the canonical “Expert”.

The last thing we need to do is define the actual Natural Language input. Bixby calls this training. Training has a UI (there is a markup text format available). A training entry sample is below:

In this example, we have defined “12345” as Guess part of the input and GetGuess as a goal which means GetGuess action will be called. This is our first view into some of the Bixby “magic” – the flowchart below the natural language input shows how this sentence would be processed.

What we are seeing is essentially a plan for the NLU and program flow. This is the vaunted Bixby auto program generation. The closest technical analogy I can think of is a relational database explain plan.

Let’s put this all together and ask “Start Bulls and Cows” to Bixby. The following debug output is for the GetGuess UI:

Like during Natural Language training we get a flowchart of the program flow – in this case, the full execution. There is a lot of information available on this screen and each box is clickable for information on a particular step. Here we have clicked on the first box and we can see the NLU process and data.

This type of detailed debugging information about the NLU and your program workings is unique to Bixby. It is one of its market differentiators.

Stories are a powerful feature which lets you create use cases, setup assertions and run the tests. You can then modify configurations and rerun a test – all within the same UI. This is another market differentiator for Bixby.

Conclusion:

I hope you have enjoyed Bulls and Cows capsule on Bixby. I see a bright future for this platform and encourage everyone to try it out.

Samsung will be adding Bixby to the 500 million devices it ships yearly over the next few years. There is going to be a lot of Bixby out there!