, , , , , , , , , , , , ,

Peters, my morbidly objectionable Dutch lodger, has won every game of cards against me. He now owns the deeds to my house, the yellow car on the driveway and even the clothes on my back (if the fat fool could squeeze into them, that is).

But not anymore! I have updated SaltwashAR – my Python Augmented Reality application – so that Sporty Robot can help me win at Bruce Forsyth’s Play Your Cards Right.

How on God’s sweet earth did the robot help you? I hear you ask. Simple – I used PyBrain Reinforcement Learning, as detailed in my post Co-pilot for Donkey Kong (Mark II).

Sporty Robot learns – by trial and error – how best to advise me on winning the game. Let’s take a gander:

On the first card, Sporty Robot asks me “What card do you have?”.

I respond “2”.

Next, Sporty instructs me to play “Higher” and then asks me “Did you win the turn?”.

As the next card is a 7 – which is indeed higher than a 2 – I tell Sporty “Yes”.

Sporty Robot learns that “Higher” on a 2 is a good thing.

And so on the game goes, Sporty instructing me on each card “Higher” or “Lower”. Only on the last turn do I become unstuck when Sporty instructs me to go “Higher” on a 10 – the next card is a 9 so I tell him “No” I did not win the turn.

On every shot of Play Your Cards Right, Sporty reinforces his learning to know which cards are a surefire, and which are dicey.

Brilliant! With the robot fully trained, I will be able to win back all my belongings from Peters. Including my antique collection of staplers.

And if you are wondering who the hell Bruce Forsyth is, say Nice to see him, to see him nice.



Here’s the Game Interaction class for the new Play Your Cards Right feature of SaltwashAR:

class GameInteraction(object):
    def __init__(self, text_to_speech, speech_to_text):
        self.is_speaking = False
        self.text_to_speech = text_to_speech
        self.speech_to_text = speech_to_text
    # 13 states
    CARD = {
        '2': [0.0],
        '3': [1.0],
        '4': [2.0],
        '5': [3.0],
        '6': [4.0],
        '7': [5.0],
        '8': [6.0],
        '9': [7.0],
        '10': [8.0],
        'jack': [9.0],
        'queen': [10.0],
        'king': [11.0],
        'ace': [12.0]
    # 2 actions
    COMMAND = {
        0.0: "lower",
        1.0: "higher"
    # 2 rewards
    RESULT = {
        'no': -1.0,
        'yes': 1.0
    def get_card(self):
        # ask user for card
        self._text_to_speech("What card do you have?")
        # wait for user's response
        response = ""
        while response not in self.CARD:
            response = self._speech_to_text()
        return self.CARD[response]
    def give_command(self, action):
        # get command
        command_key = float(action)
        command = ""
        if command_key in self.COMMAND:
            command = self.COMMAND[command_key]
        # give command to user
    def get_result(self):
        # ask user for result
        self._text_to_speech("Did you win the turn?")
        # wait for user's response
        response = ""
        while response not in self.RESULT:
            response = self._speech_to_text()
        return self.RESULT[response]
    def _text_to_speech(self, text):
        self.is_speaking = True
        self.is_speaking = False

    def _speech_to_text(self):
        text = self.speech_to_text.convert()
        if not text: return ""

        return text.lower()

The class is initialized with Text To Speech and Speech To Text capabilities, so that we can have a conversation with the robot.

Each card in the pack has a state. We may need to implement multiple word matches to each state, as Google Speech Recognition thought I said “sex” when I actually said “six”.

The robot will give us either a “higher” or “lower” command for each card during the game.

The result of each turn of the card will either be “yes” or “no”, depending on whether we won or lost. As you can see, losing will yield a negative number of -1.0, which will make the robot less likely to give the same command the next time round for that particular card. Winning, and we yield a positive number of 1.0, which will reinforce the robot’s command for that card.

If you’d like to help develop features for SaltwashAR, check out the SaltwashAR Wiki.