├── .gitignore ├── bombly ├── __init__.py ├── modules │ ├── __init__.py │ ├── needy │ │ ├── __init__.py │ │ └── knob.py │ ├── passwords.py │ ├── simon_says.py │ ├── keypads.py │ ├── the_button.py │ ├── wire_sequences.py │ ├── wires.py │ ├── morse_code.py │ ├── complicated_wires.py │ ├── memory.py │ ├── mazes.py │ └── whos_on_first.py └── bomb.py ├── images ├── h.png ├── c_left.png ├── column1.png ├── column2.png ├── column3.png ├── column4.png ├── column5.png ├── column6.png ├── kitty.png ├── lambda.png ├── oomlow.png ├── star1.png ├── tennis.png ├── tornado.png ├── copyright.png ├── lightning.png ├── question.png └── alpha_tango.png ├── dfly-loader-wsr.py ├── README.md ├── bombly.py └── ' /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /bombly/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /bombly/modules/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /bombly/modules/needy/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /images/h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/h.png -------------------------------------------------------------------------------- /images/c_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/c_left.png -------------------------------------------------------------------------------- /images/column1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/column1.png -------------------------------------------------------------------------------- /images/column2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/column2.png -------------------------------------------------------------------------------- /images/column3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/column3.png -------------------------------------------------------------------------------- /images/column4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/column4.png -------------------------------------------------------------------------------- /images/column5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/column5.png -------------------------------------------------------------------------------- /images/column6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/column6.png -------------------------------------------------------------------------------- /images/kitty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/kitty.png -------------------------------------------------------------------------------- /images/lambda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/lambda.png -------------------------------------------------------------------------------- /images/oomlow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/oomlow.png -------------------------------------------------------------------------------- /images/star1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/star1.png -------------------------------------------------------------------------------- /images/tennis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/tennis.png -------------------------------------------------------------------------------- /images/tornado.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/tornado.png -------------------------------------------------------------------------------- /images/copyright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/copyright.png -------------------------------------------------------------------------------- /images/lightning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/lightning.png -------------------------------------------------------------------------------- /images/question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/question.png -------------------------------------------------------------------------------- /images/alpha_tango.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctfhacker/bombly/HEAD/images/alpha_tango.png -------------------------------------------------------------------------------- /bombly/modules/needy/knob.py: -------------------------------------------------------------------------------- 1 | def knob(extras): 2 | words = str(extras['words']) 3 | print words 4 | words = ''.join([word for word in words.split() if word in ('one', 'zero')]) 5 | print words 6 | leds = words.replace('one', '1').replace('zero', '0').replace(' ', '') 7 | print leds 8 | if leds == '111011' or leds == '011010': 9 | return 'Up' 10 | if leds == '111001' or leds == '010010': 11 | return 'Down' 12 | if leds == '100010' or leds == '000010': 13 | return 'Left' 14 | if leds == '111111' or leds == '111100': 15 | return 'Right' 16 | -------------------------------------------------------------------------------- /bombly/modules/passwords.py: -------------------------------------------------------------------------------- 1 | # Password 2 | curr_password = [] 3 | 4 | 5 | def solve_password(extras): 6 | global curr_password 7 | letters = str(extras['letters']) 8 | letters = [letter[0].lower() for letter in letters.split()] 9 | curr_password.append(letters) 10 | print curr_password 11 | 12 | passwords = ['about', 13 | 'after', 'again', 'below', 'could', 'every', 'first', 'found', 'great', 14 | 'house', 'large', 'learn', 'never', 'other', 'place', 'plant', 'point', 15 | 'right', 'small', 'sound', 'spell', 'still', 'study', 'their', 'there', 16 | 'these', 'thing', 'think', 'three', 'water', 'where', 'which', 'world', 17 | 'would', 'write'] 18 | 19 | possibles = [] 20 | if len(curr_password) == 2: 21 | for password in passwords: 22 | if password[0] in curr_password[0] and password[2] in curr_password[1]: 23 | possibles.append(password) 24 | 25 | print possibles 26 | 27 | return possibles 28 | 29 | 30 | def reset(): 31 | global curr_password 32 | curr_password = [] 33 | print curr_password 34 | -------------------------------------------------------------------------------- /bombly/modules/simon_says.py: -------------------------------------------------------------------------------- 1 | def simon(extras, vowel): 2 | print str(extras['words']) 3 | # if vowel == 'vowel': 4 | # engine.speak("Serial contain vowel?") 5 | # return 6 | 7 | words = str(extras['words']) 8 | print words 9 | words = words.replace('read', 'red').replace('blew', 'blue') 10 | words = [word for word in words.split() if word in ('blue', 'yellow', 'red', 'green')] 11 | 12 | new_words = [] 13 | print "Your words: {}".format(words) 14 | if vowel in ('true', 'yes'): 15 | colors = {'red': 'blue', 16 | 'blue': 'red', 17 | 'green': 'yellow', 18 | 'yellow': 'green'} 19 | for word in words: 20 | new_words.append(colors[word]) 21 | else: 22 | colors = {'red': 'blue', 23 | 'blue': 'yellow', 24 | 'green': 'green', 25 | 'yellow': 'red'} 26 | for word in words: 27 | new_words.append(colors[word]) 28 | 29 | new_words = ' '.join(new_words) 30 | print "My words: {}".format(new_words) 31 | 32 | return new_words 33 | -------------------------------------------------------------------------------- /bombly/modules/keypads.py: -------------------------------------------------------------------------------- 1 | def keypad(extras): 2 | symbols = str(extras['symbols']) 3 | 4 | groups = [ 5 | ['tennis', 'apple', 'a', 'l', 'lightning', 'spider', 'h', 'house', 'c', 'charlie'], 6 | ['e', 'echo', 'tennis', 'c', 'charlie', 'o', 'oscar', 'starr', 'star', 'h', 'house', 'question'], 7 | ['copyright', 'but', 'butt', 'o', 'oscar', 'k', 'r', 'romeo', 'l', 'starr', 'star'], 8 | ['six', 'paragraph', 'b', 'bravo', 'spider', 'k', 'question', 'smile'], 9 | ['goblet', 'smile', 'b', 'bravo', 'c', 'charlie', 'paragraph', 'three', 'star'], 10 | ['six', 'e', 'echo', 'equals', 'smash', 'goblet', 'in', 'omega'] 11 | ] 12 | 13 | print symbols 14 | symbols = symbols.replace('butt', 'but') 15 | curr_symbols = symbols.replace('.', '').lower().split() 16 | print curr_symbols 17 | 18 | answer = '' 19 | for group in groups: 20 | for symbol in curr_symbols: 21 | if symbol not in group: 22 | break 23 | else: 24 | for symbol in group: 25 | if symbol in curr_symbols: 26 | answer += symbol + ' ' 27 | 28 | return answer 29 | -------------------------------------------------------------------------------- /bombly/modules/the_button.py: -------------------------------------------------------------------------------- 1 | def button(extras, batteries, car, freak): 2 | """ 3 | spoken = 'need' 4 | print "Batteries: {}".format(batteries) 5 | print "Freak: {}".format(freak) 6 | print "Car: {}".format(car) 7 | if batteries == 99: 8 | spoken += ' batteries' 9 | if freak == 'freak': 10 | spoken += ' freak' 11 | if car == 'car': 12 | spoken += ' car identifier' 13 | if spoken != 'need': 14 | return spoken 15 | return 16 | """ 17 | 18 | words = str(extras['words']) 19 | print words 20 | words = words.replace('read', 'red').replace('blew', 'blue') 21 | print words 22 | if 'blue' in words and 'abort' in words: 23 | return 'Press and hold' 24 | elif 'detonate' in words and batteries > 1: 25 | return 'Press and release' 26 | elif 'white' in words and car in ('true', 'yes'): 27 | return 'Press and hold' 28 | elif batteries > 2 and freak in ('true', 'yes'): 29 | return 'Press and release' 30 | elif 'yellow' in words: 31 | return 'Press and hold' 32 | elif 'red' in words and 'hold' in words: 33 | return 'Press and release' 34 | else: 35 | return 'Press and hold' 36 | 37 | 38 | def button_color(extras): 39 | words = str(extras['words']) 40 | print words 41 | words = words.replace('read', 'red').replace('blew', 'blue') 42 | print words 43 | if 'blue' in words: 44 | return 'four' 45 | elif 'yellow' in words: 46 | return 'five' 47 | else: 48 | return 'one' 49 | -------------------------------------------------------------------------------- /bombly/modules/wire_sequences.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | counts = defaultdict(int) 4 | sequences = {} 5 | sequences['red'] = [ 6 | ('c'), 7 | ('b'), 8 | ('a'), 9 | ('a', 'c'), 10 | ('b'), 11 | ('a', 'c'), 12 | ('a', 'b', 'c'), 13 | ('a', 'b'), 14 | ('b') 15 | ] 16 | sequences['blue'] = [ 17 | ('b'), 18 | ('a', 'c'), 19 | ('b'), 20 | ('a'), 21 | ('b'), 22 | ('b','c'), 23 | ('c'), 24 | ('a', 'c'), 25 | ('a') 26 | ] 27 | sequences['black'] = [ 28 | ('a', 'b', 'c'), 29 | ('a', 'c'), 30 | ('b'), 31 | ('a', 'c'), 32 | ('b'), 33 | ('b', 'c'), 34 | ('a', 'b'), 35 | ('c'), 36 | ('c') 37 | ] 38 | 39 | 40 | def wire_sequence(extras): 41 | global sequences 42 | words = str(extras['words']) 43 | print words 44 | words = words.replace('read', 'red').replace('blew', 'blue') 45 | print words 46 | words = [word for word in words.split() if word in ('red', 'blue', 'black', 'apple', 'bravo', 'charlie')] 47 | print words 48 | words = [words[x:x+2] for x in xrange(0, len(words), 2)] 49 | print words 50 | answer = [] 51 | for index, item in enumerate(words): 52 | print index, item 53 | color, letter = item 54 | print "Color: {}".format(color) 55 | print "Letter: {}".format(letter) 56 | print "Count: {}".format(counts[color]) 57 | print sequences[color] 58 | print counts[color] 59 | print sequences[color][counts[color]] 60 | print sequences[color][counts[color]] 61 | if letter[0] in sequences[color][counts[color]]: 62 | answer.append(str(index+1)) 63 | 64 | counts[color] += 1 65 | 66 | if not answer: 67 | return 'cut nothing' 68 | else: 69 | return ', '.join(answer) 70 | 71 | 72 | def reset(): 73 | global counts 74 | counts = defaultdict(int) 75 | -------------------------------------------------------------------------------- /bombly/modules/wires.py: -------------------------------------------------------------------------------- 1 | def wires(extras, sanitize_colors, odd_serial): 2 | """ 3 | spoken = 'need' 4 | if serial == 'serial': 5 | spoken += ' last digit of serial' 6 | if spoken != 'need': 7 | engine.speak(spoken) 8 | return 9 | """ 10 | 11 | wire = str(extras['wires']) 12 | wire = sanitize_colors(wire) 13 | wire = wire.split() 14 | 15 | if len(wire) == 3: 16 | if 'red' not in wire: 17 | return 'cut second wire' 18 | elif wire[-1] == 'white': 19 | return 'cut last wire' 20 | elif wire.count('blue') > 1: 21 | return 'cut last blue wire' 22 | else: 23 | return 'cut last wire' 24 | 25 | elif len(wire) == 4: 26 | if wire.count('red') > 1 and odd_serial(): 27 | return 'cut last red wire' 28 | elif wire[-1] == 'yellow' and wire.count('red') == 0: 29 | return 'cut first wire' 30 | elif wire.count('blue') == 1: 31 | return 'cut first wire' 32 | elif wire.count('yellow') > 1: 33 | return 'cut last wire' 34 | else: 35 | return 'cut second wire' 36 | 37 | elif len(wire) == 5: 38 | if wire[-1] == 'black' and odd_serial(): 39 | return 'cut fourth wire' 40 | elif wire.count('red') and wire.count('yellow') > 1: 41 | return 'cut first wire' 42 | elif wire.count('black') == 0: 43 | return 'cut second wire' 44 | else: 45 | return 'cut first wire' 46 | 47 | elif len(wire) == 6: 48 | if wire.count('yellow') == 0 and odd_serial(): 49 | return 'cut third wire' 50 | elif wire.count('yellow') == 1 and wire.count('white') > 1: 51 | return 'cut fourth wire' 52 | elif wire.count('red') == 0: 53 | return 'cut last wire' 54 | else: 55 | return 'cut fourth wire' 56 | -------------------------------------------------------------------------------- /bombly/modules/morse_code.py: -------------------------------------------------------------------------------- 1 | # Morse 2 | morse_letters = [] 3 | 4 | 5 | def morse_code(extras): 6 | global morse_letters 7 | words = str(extras['words']) 8 | 9 | words = ''.join([word for word in words.split() if word in ('one', 'zero')]) 10 | print words 11 | code = words.replace('one', '-').replace('zero', '.') 12 | print code 13 | 14 | morse = { 15 | 'a': '.-', 16 | 'b': '-...', 17 | 'c': '-.-.', 18 | 'e': '.', 19 | 'f': '..-.', 20 | 'g': '--.', 21 | 'h': '....', 22 | 'i': '..', 23 | 'k': '-.-', 24 | 'l': '.-..', 25 | 'm': '--', 26 | 'n': '-.', 27 | 'o': '---', 28 | 'r': '.-.', 29 | 's': '...', 30 | 't': '-', 31 | 'v': '...-', 32 | 'x': '-..-', 33 | } 34 | 35 | codes = {} 36 | for key, val in morse.iteritems(): 37 | if code == val: 38 | morse_letters.append(key) 39 | 40 | codes[val] = key 41 | 42 | print "Current morse letters: {}".format(morse_letters) 43 | if len(morse_letters) < 2: 44 | return 45 | 46 | words = { 47 | 'shell': '5 0 5', 48 | 'halls': '5 1 5', 49 | 'slick': '5 2 2', 50 | 'trick': '5 3 2', 51 | 'boxes': '5 3 5', 52 | 'leaks': '5 4 2', 53 | 'strobe': '5 4 5', 54 | 'bistro': '5 5 2', 55 | 'flick': '5 5 5', 56 | 'bombs': '5 6 5', 57 | 'break': '5 7 2', 58 | 'brick': '5 7 5', 59 | 'steak': '5 8 2', 60 | 'sting': '5 9 2', 61 | 'vector': '5 9 5', 62 | 'beats': '6 0 0', 63 | } 64 | 65 | code = ''.join(morse_letters) 66 | 67 | combos = {} 68 | for word in words: 69 | curr_combo = [] 70 | for num in xrange(len(word)): 71 | curr_word = ''.join((word+word)[num:num+3]) 72 | combos[curr_word] = word 73 | 74 | print code 75 | print combos.keys() 76 | if code in combos: 77 | return words[combos[code]] 78 | 79 | possibles = [] 80 | for key, val in combos.iteritems(): 81 | curr_word = ''.join([morse[letter] for letter in key]) 82 | if code.startswith(curr_word): 83 | # print val, key, code, words[val] 84 | print words[val] 85 | 86 | 87 | def reset(): 88 | global morse_letters 89 | morse_letters = [] 90 | -------------------------------------------------------------------------------- /bombly/modules/complicated_wires.py: -------------------------------------------------------------------------------- 1 | def complicated_wires(extras, batteries, serial, parallel): 2 | """ 3 | spoken = 'need' 4 | if batteries == 99: 5 | spoken += ' batteries' 6 | if parallel == 'parallel': 7 | spoken += ' parallel port' 8 | if serial == 'serial': 9 | spoken += ' last digit of serial' 10 | if spoken != 'need': 11 | engine.speak(spoken) 12 | return 13 | """ 14 | 15 | meaning = { 16 | int('0000', 2): 'cut', 17 | int('0001', 2): 'dont cut', 18 | int('0010', 2): 'cut', 19 | int('0011', 2): 'cut' if batteries > 1 else 'dont cut', 20 | int('0100', 2): 'cut' if serial in (0, 2, 4, 6, 8) else 'dont cut', 21 | int('0101', 2): 'cut' if parallel in ('true', 'yes') else 'dont cut', 22 | int('0110', 2): 'dont cut', 23 | int('0111', 2): 'cut' if parallel in ('true', 'yes') else 'dont cut', 24 | int('1000', 2): 'cut' if serial in (0, 2, 4, 6, 8) else 'dont cut', 25 | int('1001', 2): 'cut' if batteries > 1 else 'dont cut', 26 | int('1010', 2): 'cut', 27 | int('1011', 2): 'cut' if batteries > 1 else 'dont cut', 28 | int('1100', 2): 'cut' if serial in (0, 2, 4, 6, 8) else 'dont cut', 29 | int('1101', 2): 'cut' if serial in (0, 2, 4, 6, 8) else 'dont cut', 30 | int('1110', 2): 'cut' if parallel in ('true', 'yes') else 'dont cut', 31 | int('1111', 2): 'dont cut' 32 | } 33 | 34 | for key, val in meaning.iteritems(): 35 | print key, val 36 | 37 | bad_words = [('read', 'red'), ('blew', 'blue'), ('start', 'star'), 38 | ('white', 'light')] 39 | wire = str(extras['wires']) 40 | print wire 41 | wires = [wire for wire in wire.split('next')] 42 | print wires 43 | print 'parallel', parallel 44 | print 'serial', serial 45 | print 'batteries', batteries 46 | final_wires = [] 47 | answer = 'cut nothing' 48 | for index, wire in enumerate(wires): 49 | for bad, good in bad_words: 50 | wire = wire.replace(bad, good) 51 | 52 | wire = [item for item in wire.split() if item in ('red', 'blue', 'light', 53 | 'star', 'blank')] 54 | 55 | print wire 56 | total = 0 57 | for letter, value in [('red', 8), ('blue', 4), ('star', 2), ('light', 1)]: 58 | if letter in wire: 59 | total += value 60 | 61 | print wire, total 62 | 63 | if meaning[total] == 'cut': 64 | if answer == 'cut nothing': 65 | answer = 'cut ' 66 | answer += str(index+1) + ', ' 67 | 68 | return answer 69 | -------------------------------------------------------------------------------- /bombly/modules/memory.py: -------------------------------------------------------------------------------- 1 | # Memory 2 | values = [] 3 | positions = [] 4 | curr_stage = 1 5 | 6 | 7 | def memory(extras): 8 | global values 9 | global positions 10 | global curr_stage 11 | words = str(extras['words']) 12 | print words 13 | words = [word for word in words.split() if word in ('one', 'two', 'three', 'four')] 14 | print words 15 | if len(words) != 5: 16 | return 'Try memory again' 17 | 18 | display = words[0] 19 | stage = words[1:] 20 | 21 | print "Current Stage: {}".format(curr_stage) 22 | print "Values: {}".format(values) 23 | print "Positions: {}".format(values) 24 | if curr_stage == 1: 25 | if display == 'one': 26 | answer = stage[1] 27 | if display == 'two': 28 | answer = stage[1] 29 | if display == 'three': 30 | answer = stage[2] 31 | if display == 'four': 32 | answer = stage[3] 33 | position = stage.index(answer) 34 | 35 | if curr_stage == 2: 36 | if display == 'one': 37 | answer = 'four' 38 | if display == 'two': 39 | answer = stage[positions[0]] 40 | if display == 'three': 41 | answer = stage[0] 42 | if display == 'four': 43 | answer = stage[positions[0]] 44 | position = stage.index(answer) 45 | 46 | if curr_stage == 3: 47 | if display == 'one': 48 | answer = values[1] 49 | position = 'one' 50 | if display == 'two': 51 | answer = values[0] 52 | position = 'two' 53 | if display == 'three': 54 | answer = stage[2] 55 | position = stage.index(answer) 56 | if display == 'four': 57 | answer = 'four' 58 | position = stage.index(answer) 59 | 60 | if curr_stage == 4: 61 | if display == 'one': 62 | answer = stage[positions[0]] 63 | position = stage.index(answer) 64 | if display == 'two': 65 | answer = stage[0] 66 | position = stage.index(answer) 67 | if display == 'three': 68 | answer = stage[positions[1]] 69 | position = stage.index(answer) 70 | if display == 'four': 71 | answer = stage[positions[1]] 72 | position = stage.index(answer) 73 | 74 | if curr_stage == 5: 75 | if display == 'one': 76 | answer = values[0] 77 | if display == 'two': 78 | answer = values[1] 79 | if display == 'three': 80 | answer = values[3] 81 | if display == 'four': 82 | answer = values[2] 83 | position = stage.index(answer) 84 | 85 | values.append(answer) 86 | positions.append(position) 87 | curr_stage += 1 88 | print "Answer: {}".format(answer) 89 | if curr_stage > 5: 90 | values = [] 91 | positions = [] 92 | curr_stage = 1 93 | 94 | return answer 95 | 96 | 97 | def reset(): 98 | global positions 99 | global curr_stage 100 | global values 101 | positions = [] 102 | values = [] 103 | curr_stage = 1 104 | -------------------------------------------------------------------------------- /bombly/bomb.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | # Battery characteristics 4 | batteries = 99 5 | freak = 'freak' 6 | car = 'car' 7 | parallel = 'parallel' 8 | serial = 'serial' 9 | vowel = 'vowel' 10 | 11 | 12 | def odd_serial(): 13 | return serial in (1, 3, 5, 7, 9) 14 | 15 | 16 | def even_serial(): 17 | return serial in (0, 2, 4, 6, 8) 18 | 19 | 20 | def set_car(extras): 21 | global car 22 | car = str(extras['car']) 23 | 24 | 25 | def set_batteries(extras): 26 | global batteries 27 | batteries = int(str(extras['batteries'])) 28 | 29 | 30 | def set_freak(extras): 31 | global freak 32 | freak = str(extras['word']) 33 | 34 | 35 | def set_parallel(extras): 36 | global parallel 37 | parallel = str(extras['word']) 38 | 39 | 40 | def set_serial(extras): 41 | global serial 42 | serial = extras['word'] 43 | 44 | 45 | def set_vowel(extras): 46 | global vowel 47 | vowel = str(extras['word']) 48 | 49 | 50 | def status(): 51 | global batteries 52 | global freak 53 | global car 54 | global parallel 55 | global serial 56 | global vowel 57 | 58 | from bombly.modules import morse_code, whos_on_first, memory, wire_sequences 59 | 60 | # Battery characteristics 61 | print 'batteries', batteries 62 | print 'frk', freak 63 | print 'car', car 64 | print 'parallel', parallel 65 | print 'serial', serial 66 | print 'vowel', vowel 67 | 68 | # Wire sequence 69 | print 'wire sequence', wire_sequences.counts 70 | 71 | # Memory 72 | print 'values', memory.values 73 | print 'position', memory.positions 74 | print 'curr_stage', memory.curr_stage 75 | 76 | # Morse 77 | print 'morse_letters', morse_code.morse_letters 78 | 79 | # On First Words 80 | print 'on first words', whos_on_first.on_first_words 81 | 82 | 83 | def done(): 84 | lines = [ 85 | "I AM YOUR BOMB DEFUSING OVERLORD", 86 | "BOOM SHAKALAKA", 87 | ] 88 | 89 | global batteries 90 | global freak 91 | global car 92 | global parallel 93 | global serial 94 | global vowel 95 | 96 | # Battery characteristics 97 | batteries = 99 98 | freak = 'freak' 99 | car = 'car' 100 | parallel = 'parallel' 101 | serial = 'serial' 102 | vowel = 'false' 103 | 104 | reset() 105 | 106 | return random.sample(lines, 1) 107 | 108 | 109 | def exploded(): 110 | lines = [ 111 | "YOU STUPID FUCK", 112 | "NOT MY FAULT!", 113 | "PLANNED..", 114 | "CRAP, BOMB EXPLODED", 115 | "HOW CAN YOU TELL ME THAT?", 116 | "IT'S ALL YOUR FAULT", 117 | ] 118 | return random.sample(lines, 1) 119 | 120 | 121 | def reset(): 122 | global batteries 123 | global freak 124 | global car 125 | global parallel 126 | global serial 127 | global vowel 128 | 129 | # Battery characteristics 130 | batteries = 99 131 | freak = 'freak' 132 | car = 'car' 133 | parallel = 'parallel' 134 | serial = 'serial' 135 | vowel = 'vowel' 136 | 137 | from bombly.modules import morse_code, whos_on_first, memory, wire_sequences, passwords 138 | 139 | wire_sequences.reset() 140 | memory.reset() 141 | morse_code.reset() 142 | whos_on_first.reset() 143 | passwords.reset() 144 | -------------------------------------------------------------------------------- /dfly-loader-wsr.py: -------------------------------------------------------------------------------- 1 | # 2 | # This file is a command-module for Dragonfly. 3 | # (c) Copyright 2008 by Christo Butcher 4 | # Licensed under the LGPL, see 5 | # 6 | 7 | """ 8 | Command-module loader for WSR 9 | ============================= 10 | 11 | This script can be used to look Dragonfly command-modules 12 | for use with Window Speech Recognition. It scans the 13 | directory it's in and loads any ``*.py`` it finds. 14 | 15 | """ 16 | 17 | 18 | import time 19 | import os.path 20 | import logging 21 | import pythoncom 22 | 23 | from dragonfly.engines.backend_sapi5.engine import Sapi5InProcEngine 24 | 25 | 26 | #--------------------------------------------------------------------------- 27 | # Set up basic logging. 28 | 29 | logging.basicConfig(level=logging.DEBUG) 30 | logging.getLogger("compound.parse").setLevel(logging.INFO) 31 | 32 | 33 | #--------------------------------------------------------------------------- 34 | # Command module class; wraps a single command-module. 35 | 36 | class CommandModule(object): 37 | 38 | _log = logging.getLogger("module") 39 | 40 | def __init__(self, path): 41 | self._path = os.path.abspath(path) 42 | self._namespace = None 43 | self._loaded = False 44 | 45 | def __str__(self): 46 | return "%s(%r)" % (self.__class__.__name__, 47 | os.path.basename(self._path)) 48 | 49 | def load(self): 50 | self._log.info("%s: Loading module: '%s'" % (self, self._path)) 51 | 52 | # Prepare namespace in which to execute the 53 | namespace = {} 54 | namespace["__file__"] = self._path 55 | 56 | # Attempt to execute the module; handle any exceptions. 57 | try: 58 | execfile(self._path, namespace) 59 | except Exception, e: 60 | self._log.error("%s: Error loading module: %s" % (self, e)) 61 | self._loaded = False 62 | return 63 | 64 | self._loaded = True 65 | self._namespace = namespace 66 | 67 | def unload(self): 68 | self._log.info("%s: Unloading module: '%s'" % (self, self._path)) 69 | 70 | def check_freshness(self): 71 | pass 72 | 73 | 74 | #--------------------------------------------------------------------------- 75 | # Command module directory class. 76 | 77 | class CommandModuleDirectory(object): 78 | 79 | _log = logging.getLogger("directory") 80 | 81 | def __init__(self, path, excludes=None): 82 | self._path = os.path.abspath(path) 83 | self._excludes = excludes 84 | self._modules = {} 85 | 86 | def load(self): 87 | valid_paths = self._get_valid_paths() 88 | 89 | # Remove any deleted modules. 90 | for path, module in self._modules.items(): 91 | if path not in valid_paths: 92 | del self._modules[path] 93 | module.unload() 94 | 95 | # Add any new modules. 96 | for path in valid_paths: 97 | if path not in self._modules: 98 | module = CommandModule(path) 99 | module.load() 100 | self._modules[path] = module 101 | else: 102 | module = self._modules[path] 103 | module.check_freshness() 104 | 105 | def _get_valid_paths(self): 106 | self._log.info("Looking for command modules here: %s" % (self._path,)) 107 | valid_paths = [] 108 | for filename in os.listdir(self._path): 109 | path = os.path.abspath(os.path.join(self._path, filename)) 110 | if not os.path.isfile(path): 111 | continue 112 | if not os.path.splitext(path)[1] == ".py": 113 | continue 114 | if path in self._excludes: 115 | continue 116 | valid_paths.append(path) 117 | self._log.info("Valid paths: %s" % (", ".join(valid_paths),)) 118 | return valid_paths 119 | 120 | 121 | #--------------------------------------------------------------------------- 122 | # Main event driving loop. 123 | 124 | def main(): 125 | logging.basicConfig(level=logging.INFO) 126 | 127 | try: 128 | path = os.path.dirname(__file__) 129 | except NameError: 130 | # The "__file__" name is not always available, for example 131 | # when this module is run from PythonWin. In this case we 132 | # simply use the current working directory. 133 | path = os.getcwd() 134 | __file__ = os.path.join(path, "dfly-loader-wsr.py") 135 | 136 | engine = Sapi5InProcEngine() 137 | engine.connect() 138 | 139 | directory = CommandModuleDirectory(path, excludes=[__file__]) 140 | directory.load() 141 | 142 | engine.speak('beginning loop!') 143 | while 1: 144 | pythoncom.PumpWaitingMessages() 145 | time.sleep(.1) 146 | 147 | if __name__ == "__main__": 148 | main() 149 | -------------------------------------------------------------------------------- /bombly/modules/mazes.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | from Queue import Queue 3 | 4 | mazes = { 5 | (('1','2'), ('6','3')): """ 6 | x x x|x x x 7 | - - - 8 | x|x x|x x x 9 | - - - 10 | x|x x|x x x 11 | - - 12 | x|x x x|x x 13 | - - - - 14 | x x x|x x|x 15 | - - 16 | x x|x x|x x 17 | """, 18 | (('5','2'), ('2','4')): """ 19 | x x x|x x x 20 | - - - 21 | x x|x x|x x 22 | - - - 23 | x|x x|x x x 24 | - - 25 | x x|x x|x|x 26 | - - 27 | x|x|x|x x|x 28 | - 29 | x|x x|x x x 30 | """, 31 | (('4','4'), ('6','4')): """ 32 | x x x|x|x x 33 | - 34 | x|x|x|x x|x 35 | - - - 36 | x x|x|x x|x 37 | 38 | x|x|x|x|x|x 39 | 40 | x|x x|x|x|x 41 | - - 42 | x x x x|x x 43 | """, 44 | (('1','1'), ('1','4')): """ 45 | x x|x x x x 46 | - - - 47 | x|x|x x x x 48 | - - 49 | x|x x|x x|x 50 | - - - 51 | x|x x x x x 52 | - - - - 53 | x x x x x|x 54 | - - - 55 | x x x|x x|x 56 | """, 57 | (('5','3'), ('4','6')): """ 58 | x x x x x x 59 | - - - - 60 | x x x x x|x 61 | - - - - 62 | x x|x x|x x 63 | - - 64 | x|x x x|x|x 65 | - - - 66 | x|x x x x|x 67 | - - - 68 | x|x x x x x 69 | """, 70 | (('5','1'), ('3','5')): """ 71 | x|x x|x x x 72 | - 73 | x|x|x|x x|x 74 | - 75 | x x|x|x|x x 76 | - - - 77 | x x|x x|x|x 78 | - 79 | x x|x|x|x x 80 | - - - 81 | x x x x|x x 82 | """, 83 | (('2','1'), ('2','6')): """ 84 | x x x x|x x 85 | - - 86 | x|x x|x x|x 87 | - - - 88 | x x|x x|x x 89 | - - - - 90 | x x|x x x|x 91 | - - 92 | x|x|x x x|x 93 | - - - 94 | x x x x x x 95 | """, 96 | (('4','1'), ('3','4')): """ 97 | x|x x x|x x 98 | - 99 | x x x|x x|x 100 | - - - - 101 | x|x x x x|x 102 | - - 103 | x|x x|x x x 104 | - - - - 105 | x|x|x x x x 106 | - - - - 107 | x x x x x x 108 | """, 109 | (('3','2'), ('1','5')): """ 110 | x|x x x x x 111 | - - 112 | x|x|x x|x|x 113 | - 114 | x x x|x x|x 115 | - - - 116 | x|x|x x|x x 117 | - - 118 | x|x|x|x x|x 119 | - 120 | x x|x x|x x 121 | """, 122 | } 123 | 124 | 125 | def get_maze_dict(maze): 126 | maze_dict = defaultdict(list) 127 | maze = maze[1:] 128 | maze = maze.split('\n') 129 | 130 | # Ensure all lines have enough spacing to fill the maze 131 | maze = [row.ljust(12, ' ') for row in maze] 132 | 133 | for row_index, line in enumerate(maze): 134 | for col_index, item in enumerate(line): 135 | if item == 'x': 136 | col = col_index/2+1 137 | row = row_index/2+1 138 | try: 139 | if maze[row_index+1][col_index] == ' ': 140 | maze_dict[(col, row)].append(('D', (col, row+1))) 141 | except: 142 | pass 143 | try: 144 | if maze[row_index-1][col_index] == ' ': 145 | maze_dict[(col, row)].append(('U', (col, row-1))) 146 | except: 147 | pass 148 | try: 149 | if maze[row_index][col_index+1] == ' ': 150 | maze_dict[(col, row)].append(('R', (col+1, row))) 151 | except: 152 | pass 153 | try: 154 | if maze[row_index][col_index-1] == ' ': 155 | maze_dict[(col, row)].append(('L', (col-1, row))) 156 | except: 157 | pass 158 | 159 | return maze_dict 160 | 161 | 162 | def traverse_maze(maze_dict, start, finish): 163 | path = Queue() 164 | path.put([('x', start)]) 165 | loop = {'D': 'U', 'U': 'D', 'L':'R', 'R':'L', 'x':''} 166 | while not path.empty(): 167 | curr_path = path.get() 168 | temp_path = curr_path[:] 169 | new_paths = maze_dict[temp_path[-1][1]] 170 | # Check that we are not looping back and forth 171 | new_paths = [place for place in new_paths if place[0] != loop[curr_path[-1][0]]] 172 | for new_path in new_paths: 173 | if finish == new_path[1]: 174 | answer = '' 175 | for pair in (temp_path + [new_path])[1:]: 176 | answer += pair[0] 177 | 178 | return answer 179 | else: 180 | path.put(temp_path + [new_path]) 181 | return None 182 | 183 | 184 | def get_maze(indicator): 185 | for indicators, maze in mazes.iteritems(): 186 | if indicator in indicators: 187 | return maze 188 | 189 | return '' 190 | 191 | 192 | def solve_maze(extras): 193 | maze = str(extras['maze']) 194 | maze = ' '.join([x for x in maze.split() if x in ['one', 'two','three', 'four', 'five', 'six', 'seven', 'eight', 'nine']]) 195 | print maze 196 | for word, num in [('one', '1'), ('two', '2'), ('three', '3'), ('four', '4'), ('five', '5'), ('six', '6'), ('seven', '7'), ('eight', '8'), ('nine', '9')]: 197 | maze = maze.replace(word, num) 198 | 199 | maze = maze.replace(' ', '') 200 | # If users input , or spaces, we ignore them 201 | indicator = tuple(maze[0:2]) 202 | start = tuple([int(x) for x in maze[2:4]]) 203 | finish = tuple([int(x) for x in maze[4:6]]) 204 | 205 | if len(indicator) != 2 or len(start) != 2 or len(finish) != 2: 206 | return ['Try Maze Again',] 207 | 208 | maze = get_maze(indicator) 209 | print maze 210 | maze_dict = get_maze_dict(maze) 211 | letters = {'L': 'left', 'R': 'right', 'D':'down', 'U':'up'} 212 | path = [] 213 | for letter in traverse_maze(maze_dict, start, finish): 214 | path.append(letters[letter]) 215 | 216 | answer = [] 217 | for path in [path[x:x+3] for x in range(0, len(path), 3)]: 218 | answer.append(path) 219 | 220 | return answer 221 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bombly - Keep Talking and Nobody Explodes Robot 2 | 3 | ## Product 4 | 5 | [![Hardcore Bomb Video](http://img.youtube.com/vi/ydQEb6zyAuE/0.jpg)](http://www.youtube.com/watch?v=ydQEb6zyAuE) 6 | 7 | ### THIS IS BETA.. USE AT YOUR OWN RISK 8 | 9 | This is a "expert" robot written in Python to assist in playing Keep Talking and Nobody Explodes. 10 | 11 | In its traditional form, the bomb defuse talks with an expert who holds the [Bomb Manual](http://www.bombmanual.com). Based on the information given by the defuser, the expert scrambles through the manual give information back to the defuser to correctly secure the bomb. 12 | 13 | This is just a problem waiting to be solved with Python. Below is my attempt to solve this problem. 14 | 15 | WARNING: This does ruin the fun of the game. You have been warned! 16 | 17 | ## Installation 18 | 19 | ### Windows only 20 | 21 | Install dragonfly 22 | 23 | ``` 24 | git clone https://github.com/t4ngo/dragonfly 25 | cd dragonfly 26 | python setup.py install 27 | ``` 28 | 29 | Start the bot 30 | 31 | ``` 32 | python dfly-loader-wsr.py 33 | ``` 34 | 35 | I believe dragonfly should work with Dragon NaturallySpeaking, however, I did not use it. 36 | 37 | ## Commands available 38 | 39 | The general idea is to speak a `command` then a series of words about that command. 40 | 41 | ### Bomb variables 42 | 43 | ``` 44 | batteries <#> - Number of batteries on bomb 45 | serial <#> - Last digit of serial 46 | vowel - Vowel in serial number 47 | car - CAR indicator on bomb 48 | freak - FRK indicator on bomb 49 | parallel - Parallel port on bomb 50 | ``` 51 | 52 | ### Metabomb 53 | 54 | ``` 55 | bomb reset - Reset global bomb variables 56 | bomb status - Print current values of global attributes 57 | ``` 58 | 59 | ### Simple Wires 60 | 61 | ``` 62 | simple wires - Where wires is in (red, blue, yellow, black, white) 63 | ``` 64 | 65 | Example: 66 | 67 | ``` 68 | simple wires red red blue blue yellow black 69 | ``` 70 | 71 | ### Complex Wires 72 | 73 | ``` 74 | complex wires - Where wires is in (light, red, blue, star, blank, next) 75 | ``` 76 | 77 | Seperate each wire from left to right with `next`. `blank` is the reserved word for no attributes 78 | 79 | Example: 80 | 81 | ``` 82 | 4 Wires: 83 | Red 84 | Blue with Star 85 | Red/Blue with Light/Star 86 | No attributes 87 | ``` 88 | 89 | ``` 90 | complex wires red next blue star next light red blue star next blank 91 | ``` 92 | 93 | ### Maze 94 | 95 | ``` 96 | maze - Where coords are 3 pairs of numbers for indicator, start, stop 97 | ``` 98 | Note: Coords start at upper left (1, 1) and go horizontally then vertically. 99 | 100 | 101 | Example maze and command: 102 | 103 | ``` 104 | X O X X 105 | X X X X 106 | S X X X 107 | X X X F 108 | 109 | Indicator - (2, 1) 110 | Start - (1, 3) 111 | Finish - (4, 4) 112 | ``` 113 | 114 | ``` 115 | maze 2 1 1 3 4 4 116 | ``` 117 | 118 | ### Simon 119 | 120 | ``` 121 | simon - Where colors are in (red, blue, yellow, green) 122 | ``` 123 | 124 | Example: 125 | 126 | ``` 127 | simon red blue blue red 128 | ``` 129 | 130 | ### Wire sequence 131 | 132 | Say each wire in increasing order. 133 | 134 | ``` 135 | wire sequence - where color in (red, blue, black) and destination in (apple, bravo, charlie) 136 | ``` 137 | 138 | Example: 139 | 140 | ``` 141 | 1 -blue-- A 142 | 143 | 2 -red--- B 144 | 145 | 3 -black- C 146 | ``` 147 | 148 | ``` 149 | wire sequence blue apple red bravo black charlie 150 | ``` 151 | 152 | If two wire sequences in the same bomb, be sure to reset the wire sequence state between sequences. 153 | 154 | ``` 155 | wire sequence reset 156 | ``` 157 | 158 | ### Button 159 | 160 | Step 1: 161 | ``` 162 | button 163 | ``` 164 | 165 | If press and hold: 166 | 167 | ``` 168 | button color 169 | ``` 170 | 171 | ### Memory 172 | 173 | ``` 174 | memory 175 | ``` 176 | 177 | Example: 178 | 179 | ``` 180 | 4 181 | 2 3 4 1 182 | ``` 183 | 184 | ``` 185 | memory 4 2 3 4 1 186 | ``` 187 | 188 | If two memory modules in the same bomb, be sure to reset the memory state: 189 | 190 | ``` 191 | memory reset 192 | ``` 193 | 194 | ### Morse 195 | 196 | ``` 197 | morse <0/1 for one letter> - Where 0 is short and 1 is long 198 | ``` 199 | 200 | Rules for morse: 201 | * Give the morse module one morse letter at a time. 202 | * Be sure the letters are in succession of each other. 203 | * Only three letters are necessary. 204 | 205 | Example: 206 | 207 | ``` 208 | -... ... -.-. 209 | ``` 210 | 211 | ``` 212 | morse 1 0 0 0 213 | morse 0 0 0 214 | morse 1 0 1 0 215 | ``` 216 | 217 | If two morse modules in the same bomb, be sure to reset the morse state: 218 | 219 | ``` 220 | morse reset 221 | ``` 222 | 223 | ### Symbols 224 | 225 | ``` 226 | symbols 227 | ``` 228 | 229 | ![column1](https://raw.githubusercontent.com/thebarbershopper/bombly/master/images/column1.png) 230 | 231 | ``` 232 | tennis, a, l, lightning, kitty, h, c 233 | ``` 234 | 235 | ![column2](https://raw.githubusercontent.com/thebarbershopper/bombly/master/images/column2.png) 236 | 237 | ``` 238 | e, tennis, c, o, star, h, question 239 | ``` 240 | 241 | ![column3](https://raw.githubusercontent.com/thebarbershopper/bombly/master/images/column3.png) 242 | 243 | ``` 244 | copyright, butt, o, k, r, l, star 245 | ``` 246 | 247 | ![column4](https://raw.githubusercontent.com/thebarbershopper/bombly/master/images/column4.png) 248 | 249 | ``` 250 | six, paragraph, b, kitty, k, question, smile 251 | ``` 252 | 253 | ![column5](https://raw.githubusercontent.com/thebarbershopper/bombly/master/images/column5.png) 254 | 255 | ``` 256 | goblet, smile, b, c, paragraph, three, star 257 | ``` 258 | 259 | ![column6](https://raw.githubusercontent.com/thebarbershopper/bombly/master/images/column6.png) 260 | 261 | ``` 262 | six, e, equals, smash, goblet, n, omega 263 | ``` 264 | 265 | ### Who's on First 266 | 267 | Now for the fun module. This is still a work in progress (check out the code for all of the cases) 268 | 269 | ``` 270 | words one - Step 1 of Who's on First, lookup position 271 | ``` 272 | 273 | ``` 274 | words two - Step 2 of Who's on First, start giving words from lookup table 275 | ``` 276 | 277 | Below is the table of what spoken words coorelate to the words necessary to complete the challenge. 278 | 279 | ``` 280 | ' ' - literally blank 281 | blank - blank 282 | c - c letter 283 | c - see letter 284 | cee - c c 285 | display - display 286 | done - don 287 | done - done 288 | done - done 289 | first - first 290 | hold - hold 291 | hold - hold 292 | hold on - hold on two 293 | lead - lead 294 | lead - mead 295 | led - L. E. D. 296 | left - left 297 | like - like 298 | middle - middle 299 | next - next 300 | no - no 301 | nothing - nothing 302 | okay - OK 303 | okay - okay 304 | press - press 305 | read - read 306 | ready - ready 307 | red - red short 308 | reed - read too 309 | right - right 310 | right - write 311 | says - says 312 | see - c s 313 | sure - sure 314 | their - e i r 315 | there - e r e 316 | they are - they are words 317 | they're - they are marked 318 | they're - they mark 319 | u - you letter 320 | uh huh - five letters 321 | uh uh - four letters 322 | uhhh - three h 323 | ur - you are letters 324 | wait - wait 325 | what - what no mark 326 | what? - what mark 327 | yes - yes 328 | yes - yes 329 | you - you word 330 | you are - you are words 331 | you are - your words 332 | you're - you are mark 333 | you're - your mark 334 | your - you're word 335 | your - your word 336 | ``` 337 | 338 | ### Needy knobs 339 | 340 | ``` 341 | knobs <0/1 of LEDs> - LEDs of bottom left 3 then upper right 3 342 | ``` 343 | 344 | Example: 345 | 346 | ``` 347 | Up 348 | 349 | < . > 350 | 351 | v 352 | 353 | 0 1 0 1 0 1 354 | 1 1 1 0 0 1 355 | ``` 356 | 357 | ``` 358 | knobs 1 1 1 1 0 1 359 | ``` 360 | 361 | ### Password 362 | 363 | Not implemented...yet. 364 | -------------------------------------------------------------------------------- /bombly/modules/whos_on_first.py: -------------------------------------------------------------------------------- 1 | # On first words 2 | on_first_words = [] 3 | curr_wordlist = [] 4 | 5 | 6 | def whos_on_first(extras): 7 | global curr_wordlist 8 | words = str(extras['words']) 9 | 10 | combos = { 11 | ('you', 'are', 'words'): 'you are', 12 | ('your', 'words'): 'you are', 13 | ('done',): 'done', 14 | ('don',): 'done', 15 | ('you', 'are', 'letters'): 'ur', 16 | ('uniform', 'romeo'): 'ur', 17 | ('sure',): 'sure', 18 | ('shore',): 'sure', 19 | ('you', 'word'): 'you', 20 | ('you', 'were'): 'you', 21 | ('you', 'were', 'to'): 'you', 22 | ('you', 'work'): 'you', 23 | ('hold',): 'hold', 24 | ('you', 'letter'): 'u', 25 | ('uniform'): 'u', 26 | ('yes',): 'yes', 27 | ('first',): 'first', 28 | ('display',): 'display', 29 | ('okay',): 'okay', 30 | ('OK',): 'okay', 31 | ('says',): 'says', 32 | ('nothing',): 'nothing', 33 | ('literally', 'blank'): ' ', 34 | ('literally', 'nothing'): ' ', 35 | ('blank',): 'blank', 36 | ('no',): 'no', 37 | ('L. E. D.'): 'led', 38 | ('lead',): 'lead', 39 | ('mead',): 'lead', 40 | ('read',): 'read', 41 | ('red', 'short'): 'red', 42 | ('read', 'too'): 'reed', 43 | ('hold', 'on', 'two'): 'hold on', 44 | ("you're", 'word'): 'your', 45 | ("your", 'word'): 'your', 46 | ('your', 'mark'): "you're", 47 | ('your', 'contraction'): "you're", 48 | ('your', 'apostrophe'): "you're", 49 | ('you', 'are', 'marked'): "you're", 50 | ('you', 'are', 'mark'): "you're", 51 | ('you', 'are', 'contraction'): "you're", 52 | ('you', 'are', 'apostrophe'): "you're", 53 | ("Sierra", "echo", "echo"): "see", 54 | ('they', 'are', 'words'): "they are", 55 | ("echo", "india", "romeo"): "their", 56 | ("echo", "romeo", "echo"): "there", 57 | ('they', 'are', 'marked'): "they're", 58 | ('they', 'are', 'contraction'): "they're", 59 | ('they', 'are', 'apostrophe'): "they're", 60 | ('they', 'mark'): "they're", 61 | ('their', 'mark'): "they're", 62 | ('there', 'mark'): "they're", 63 | ('Sierra', 'echo', 'echo'): "see", 64 | ('charlie',): "c", 65 | ('see', 'letter'): "c", 66 | ('charlie', 'echo', 'echo'): "cee", 67 | ('ready',): 'ready', 68 | ('yes',): 'yes', 69 | ('what', 'no', 'mark'): 'what', 70 | ('what', 'know', 'mark'): 'what', 71 | ('three', 'H.'): 'uhhh', 72 | ('left',): 'left', 73 | ('right',): 'right', 74 | ('write',): 'right', 75 | ('middle',): 'middle', 76 | ('metal',): 'middle', 77 | ('wait',): 'wait', 78 | ('press',): 'press', 79 | ('five', 'letters'): 'uh huh', 80 | ('hotel', 'uniform', 'hotel'): 'uh huh', 81 | ('four', 'letters'): 'uh uh', 82 | ('uniform', 'hotel'): 'uh uh', 83 | ('what', 'mark'): 'what?', 84 | ('done',): 'done', 85 | ('next',): 'next', 86 | ('hold',): 'hold', 87 | ('sure',): 'sure', 88 | ('like',): 'like', 89 | ('mike',): 'like', 90 | ('might',): 'like', 91 | ('white',): 'like', 92 | ('light',): 'like', 93 | } 94 | 95 | positions = { 96 | 'yes': 3, 97 | 'first': 2, 98 | 'display': 6, 99 | 'okay': 2, 100 | 'says': 6, 101 | 'nothing': 3, 102 | ' ': 5, 103 | 'blank': 4, 104 | 'no': 6, 105 | 'led': 3, 106 | 'lead': 6, 107 | 'read': 4, 108 | 'red': 4, 109 | 'reed': 5, 110 | 'leed': 5, 111 | 'hold on': 6, 112 | 'you': 4, 113 | 'you are': 6, 114 | 'your': 4, 115 | "you're": 4, 116 | 'ur': 1, 117 | 'there': 6, 118 | "they're": 5, 119 | 'their': 4, 120 | 'they are': 3, 121 | 'see': 6, 122 | 'c': 2, 123 | 'cee': 6 124 | } 125 | 126 | table = { 127 | "ready": ["yes", "okay", "what", "middle", "left", "press", "right", "blank", "ready"], 128 | "first": ["left", "okay", "yes", "middle", "no", "right", "nothing", "uhhh", "wait", "ready", "blank", "what", "press", "first"], 129 | "no": ["blank", "uhhh", "wait", "first", "what", "ready", "right", "yes", "nothing", "left", "press", "okay", "no", "middle"], 130 | "blank": ["wait", "right", "okay", "middle", "blank"], 131 | "nothing": ["uhhh", "right", "okay", "middle", "yes", "blank", "no", "press", "left", "what", "wait", "first", "nothing", "ready"], 132 | "yes": ["okay", "right", "uhhh", "middle", "first", "what", "press", "ready", "nothing", "yes"], 133 | "what": ["uhhh", "what"], 134 | "uhhh": ["ready", "nothing", "left", "what", "okay", "yes", "right", "no", "press", "blank", "uhhh"], 135 | "left": ["right", "left"], 136 | "right": ["yes", "nothing", "ready", "press", "no", "wait", "what", "right"], 137 | "middle": ["blank", "ready", "okay", "what", "nothing", "press", "no", "wait", "left", "middle"], 138 | "okay": ["middle", "no", "first", "yes", "uhhh", "nothing", "wait", "okay"], 139 | "wait": ["uhhh", "no", "blank", "okay", "yes", "left", "first", "press", "what", "wait"], 140 | "press": ["right", "middle", "yes", "ready", "press"], 141 | "you": ["sure", "you are", "your", "you're", "next", "uh huh", "ur", "hold", "what?", "you"], 142 | "you are": ["your", "next", "like", "uh huh", "what?", "done", "uh uh", "hold", "you", "u", "you're", "sure", "ur", "you are"], 143 | "your": ["uh uh", "you are", "uh huh", "your"], 144 | "you're": ["you", "you're"], 145 | "ur": ["done", "u", "ur"], 146 | "u": ["uh huh", "sure", "next", "what?", "you're", "ur", "uh uh", "done", "u"], 147 | "uh huh": ["uh huh"], 148 | "uh uh": ["ur", "u", "you are", "you", "done", "hold", "uh uh", "next", "sure", "like", "your", "sure", "hold", "what?"], 149 | "what?": ["you", "hold", "you're", "your", "u", "done", "uh uh", "like", "you are", "uh huh", "ur", "next", "what?"], 150 | "done": ["sure", "uh huh", "next", "what?", "your", "ur", "you're", "hold", "like", "you", "u", "you are", "uh uh", "done"], 151 | "next": ["what?", "uh huh", "uh uh", "your", "hold", "sure", "next"], 152 | "hold": ["you are", "u", "done", "uh uh", "you", "ur", "sure", "what?", "you're", "next", "hold"], 153 | "sure": ["you are", "done", "like", "you're", "you", "hold", "uh huh", "ur", "sure"], 154 | "like": ["you're", "next", "u", "ur", "hold", "uh uh", "what?", "uh huh", "you", "like"], 155 | } 156 | 157 | responses = { 158 | "you are": ("you" "are", "words"), 159 | "done": ("done",), 160 | "ur": ("you", "are", "letters"), 161 | "sure": ("sure",), 162 | "you": ("you", "word"), 163 | "hold": ("hold",), 164 | "u": ("you", "letter"), 165 | "yes": ("yes",), 166 | "first": ("first",), 167 | "display": ("display",), 168 | "okay": ("okay",), 169 | "says": ("says",), 170 | "nothing": ("nothing",), 171 | " ": ("literally", "blank"), 172 | "blank": ("blank",), 173 | "no": ("no",), 174 | "led": ("L.", "E.", "D."), 175 | "lead": ("lead",), 176 | "read": ("read",), 177 | "red": ("red", "short"), 178 | "reed": ("read", "too"), 179 | "hold on": ("hold", "on", "two"), 180 | "your": ("your", "word"), 181 | "you're": ("you", "are", "mark"), 182 | "see": ("Sierra", "echo", "echo"), 183 | "they are": ("they", "are", "words"), 184 | "their": ("E.", "I.", "R."), 185 | "there": ("E.", "R.", "E."), 186 | "they're": ("they", "are", "marked"), 187 | "c": ("charlie"), 188 | "cee": ("charlie", "echo", "echo"), 189 | "ready": ("ready",), 190 | "yes": ("yes",), 191 | "what": ("what", "no", "mark"), 192 | "uhhh": ("three", "H."), 193 | "left": ("left",), 194 | "right": ("right",), 195 | "right": ("write",), 196 | "middle": ("middle",), 197 | "wait": ("wait",), 198 | "press": ("press",), 199 | "uh huh": ("five", "letters"), 200 | "uh uh": ("four", "letters"), 201 | "what?": ("what", "question"), 202 | "done": ("done",), 203 | "next": ("next",), 204 | "hold": ("hold",), 205 | "sure": ("sure",), 206 | "like": ("like",), 207 | } 208 | print "Voice receive: ", words 209 | 210 | for combo, select in reversed(sorted(combos.iteritems(), key=lambda x: len(x[0]))): 211 | for word in combo: 212 | if word not in words.split(): 213 | break 214 | else: 215 | print 'Words', words 216 | print "Found word: {}".format(select) 217 | if 'one' in words.split(): 218 | curr_wordlist = [] 219 | return positions[select] 220 | 221 | if 'two' in words.split(): 222 | print 'select', select 223 | wordlist = table[select] 224 | answer = [] 225 | new_length = min(4, len(wordlist)) 226 | curr_wordlist = [] 227 | print wordlist 228 | 229 | # Cache next set of words in case we need to ask for more 230 | # words 231 | for word in wordlist[new_length:]: 232 | print 'word:', word 233 | curr_wordlist.append(' '.join(responses[word])) 234 | 235 | for word in wordlist[:new_length]: 236 | answer.append(' '.join(responses[word])) 237 | 238 | return ', '.join(answer) 239 | break 240 | 241 | 242 | def more(): 243 | global curr_wordlist 244 | speak = ', '.join(curr_wordlist[:4]) 245 | new_length = min(4, len(curr_wordlist)) 246 | curr_wordlist = curr_wordlist[new_length:] 247 | return speak 248 | 249 | 250 | def remove(): 251 | global on_first_words 252 | on_first_words = on_first_words[:-1] 253 | 254 | 255 | def reset(): 256 | global on_first_words 257 | on_first_words = [] 258 | -------------------------------------------------------------------------------- /bombly.py: -------------------------------------------------------------------------------- 1 | from dragonfly import * 2 | from dragonfly.engines.backend_sapi5.engine import Sapi5InProcEngine 3 | 4 | 5 | engine = Sapi5InProcEngine() 6 | engine.connect() 7 | 8 | 9 | def easy_answer(answer): 10 | count = 0 11 | curr_letter = answer[0] 12 | curr_answer = '' 13 | 14 | for index, letter in enumerate(answer): 15 | left = start[index:] 16 | if letter != curr_letter: 17 | curr_answer += curr_letter + str(count) + ' ' 18 | curr_letter = letter 19 | count = 1 20 | else: 21 | count += 1 22 | 23 | curr_answer += curr_letter + str(count) 24 | 25 | return curr_answer 26 | 27 | 28 | def sanitize_colors(words): 29 | print "Sanitizing: {}".format(words) 30 | words = words.replace('read', 'red').replace('blew', 'blue') 31 | words = ' '.join([word for word in words.split() if word in ('yellow', 'red', 'black', 'blue', 'white')]) 32 | print "Sanitized: {}".format(words) 33 | return words 34 | 35 | class SampleRule(CompoundRule): 36 | spec = "simple wires " # Spoken form of command. 37 | extras = [Dictation("wires")] 38 | def _process_recognition(self, node, extras): # Callback when command is spoken. 39 | wire = str(extras['wires']) 40 | 41 | class BombResetRule(CompoundRule): 42 | spec = "bomb reset" 43 | 44 | def _process_recognition(self, node, extras): # Callback when command is spoken. 45 | from bombly.bomb import reset 46 | reset() 47 | 48 | 49 | class BombStatusRule(CompoundRule): 50 | spec = "bomb status" 51 | 52 | def _process_recognition(self, node, extras): # Callback when command is spoken. 53 | from bombly.bomb import status 54 | status() 55 | 56 | 57 | class BombCarRule(CompoundRule): 58 | spec = "car " 59 | extras = [IntegerRef('car', 0, 10)] 60 | 61 | def _process_recognition(self, node, extras): # Callback when command is spoken. 62 | from bombly.bomb import set_car 63 | set_car(extras) 64 | 65 | 66 | class BombBatteriesRule(CompoundRule): 67 | spec = "batteries " 68 | extras = [IntegerRef('batteries', 0, 10)] 69 | 70 | def _process_recognition(self, node, extras): # Callback when command is spoken. 71 | from bombly.bomb import set_batteries 72 | set_batteries(extras) 73 | 74 | 75 | class BombFreakRule(CompoundRule): 76 | spec = "freak " 77 | extras = [Dictation('word')] 78 | 79 | def _process_recognition(self, node, extras): # Callback when command is spoken. 80 | from bombly.bomb import set_freak 81 | set_freak(extras) 82 | 83 | 84 | class BombParallelRule(CompoundRule): 85 | spec = "parallel " 86 | extras = [ 87 | Dictation('word'), 88 | ] 89 | 90 | def _process_recognition(self, node, extras): # Callback when command is spoken. 91 | from bombly.bomb import set_parallel 92 | set_parallel(extras) 93 | 94 | 95 | class BombSerialRule(CompoundRule): 96 | spec = "serial " 97 | extras = [ 98 | IntegerRef('word', 0, 10), 99 | ] 100 | 101 | def _process_recognition(self, node, extras): # Callback when command is spoken. 102 | from bombly.bomb import set_serial 103 | set_serial(extras) 104 | 105 | 106 | class BombVowelRule(CompoundRule): 107 | spec = "set vowel " 108 | extras = [ 109 | Dictation('word') 110 | ] 111 | 112 | def _process_recognition(self, node, extras): # Callback when command is spoken. 113 | from bombly.bomb import set_vowel 114 | set_vowel(extras) 115 | 116 | 117 | # Voice command rule combining spoken form and recognition processing. 118 | class SimpleWiresRule(CompoundRule): 119 | spec = "simple wires " # Spoken form of command. 120 | extras = [Dictation("wires")] 121 | def _process_recognition(self, node, extras): # Callback when command is spoken. 122 | from bombly.modules.wires import wires 123 | from bombly.bomb import odd_serial 124 | engine.speak(wires(extras, sanitize_colors, odd_serial)) 125 | 126 | class ComplexWiresRule(CompoundRule): 127 | spec = "complex wires " # Spoken form of command. 128 | extras = [Dictation("wires")] 129 | 130 | def _process_recognition(self, node, extras): # Callback when command is spoken. 131 | from bombly.modules.complicated_wires import complicated_wires 132 | from bombly.bomb import batteries, serial, parallel 133 | engine.speak(complicated_wires(extras, batteries, serial, parallel)) 134 | 135 | 136 | class MazeRule(CompoundRule): 137 | spec = "maze " # Spoken form of command. 138 | extras = [Dictation("maze")] 139 | def _process_recognition(self, node, extras): # Callback when command is spoken. 140 | from bombly.modules.mazes import solve_maze 141 | answer = solve_maze(extras) 142 | for item in answer: 143 | engine.speak(item) 144 | 145 | class SimonRule(CompoundRule): 146 | spec = "simon " # Spoken form of command. 147 | extras = [Dictation("words")] 148 | def _process_recognition(self, node, extras): # Callback when command is spoken. 149 | from bombly.modules.simon_says import simon 150 | from bombly.bomb import vowel 151 | engine.speak(simon(extras, vowel)) 152 | 153 | 154 | class WireSequenceRule(CompoundRule): 155 | spec = "wire sequence " # Spoken form of command. 156 | extras = [Dictation("words")] 157 | def _process_recognition(self, node, extras): # Callback when command is spoken. 158 | from bombly.modules.wire_sequences import wire_sequence 159 | engine.speak(wire_sequence(extras)) 160 | 161 | class WireSequenceResetRule(CompoundRule): 162 | spec = "wire sequence reset" # Spoken form of command. 163 | def _process_recognition(self, node, extras): # Callback when command is spoken. 164 | from bombly.modules.wire_sequences import reset 165 | reset() 166 | 167 | class ButtonRule(CompoundRule): 168 | spec = "button " # Spoken form of command. 169 | extras = [Dictation("words")] 170 | def _process_recognition(self, node, extras): # Callback when command is spoken. 171 | from bombly.modules.the_button import button 172 | from bombly.bomb import batteries, car, freak 173 | engine.speak(button(extras, batteries, car, freak)) 174 | 175 | class ButtonColorRule(CompoundRule): 176 | spec = "button color " # Spoken form of command. 177 | extras = [Dictation("words")] 178 | def _process_recognition(self, node, extras): # Callback when command is spoken. 179 | from bombly.modules.the_button import button_color 180 | engine.speak(button_color(extras)) 181 | 182 | class KnobsRule(CompoundRule): 183 | spec = "knobs " # Spoken form of command. 184 | extras = [Dictation("words")] 185 | def _process_recognition(self, node, extras): # Callback when command is spoken. 186 | from bombly.modules.needy.knob import knob 187 | engine.speak(knob(extras)) 188 | 189 | 190 | class MemoryRule(CompoundRule): 191 | spec = "memory " # Spoken form of command. 192 | extras = [Dictation("words")] 193 | def _process_recognition(self, node, extras): # Callback when command is spoken. 194 | from bombly.modules.memory import memory 195 | engine.speak(memory(extras)) 196 | 197 | 198 | class MemoryResetRule(CompoundRule): 199 | spec = "memory reset" # Spoken form of command. 200 | def _process_recognition(self, node, extras): # Callback when command is spoken. 201 | from bombly.modules.memory import reset 202 | reset() 203 | 204 | class MorseRule(CompoundRule): 205 | spec = "morse " # Spoken form of command. 206 | extras = [Dictation("words")] 207 | def _process_recognition(self, node, extras): # Callback when command is spoken. 208 | from bombly.modules.morse_code import morse_code 209 | engine.speak(morse_code(extras)) 210 | 211 | 212 | class MorseResetRule(CompoundRule): 213 | spec = "morse reset" # Spoken form of command. 214 | def _process_recognition(self, node, extras): # Callback when command is spoken. 215 | from bombly.modules.morse_code import reset 216 | reset() 217 | 218 | 219 | class WordsResetRule(CompoundRule): 220 | spec = "words reset" # Spoken form of command. 221 | def _process_recognition(self, node, extras): # Callback when command is spoken. 222 | from bombly.modules.whos_on_first import reset 223 | reset() 224 | 225 | 226 | class WordsRemoveRule(CompoundRule): 227 | spec = "words remove" # Spoken form of command. 228 | def _process_recognition(self, node, extras): # Callback when command is spoken. 229 | from bombly.modules.whos_on_first import remove 230 | remove() 231 | 232 | 233 | class SymbolsRule(CompoundRule): 234 | spec = "symbols " # Spoken form of command. 235 | extras = [Dictation("symbols")] 236 | def _process_recognition(self, node, extras): # Callback when command is spoken. 237 | from bombly.modules.keypads import keypad 238 | engine.speak(keypad(extras)) 239 | 240 | 241 | class WordsRule(CompoundRule): 242 | spec = "words " # Spoken form of command. 243 | extras = [Dictation("words")] 244 | def _process_recognition(self, node, extras): # Callback when command is spoken. 245 | from bombly.modules.whos_on_first import whos_on_first 246 | engine.speak(whos_on_first(extras)) 247 | 248 | 249 | class WordsMoreRule(CompoundRule): 250 | spec = "words more" # Spoken form of command. 251 | def _process_recognition(self, node, extras): # Callback when command is spoken. 252 | from bombly.modules.whos_on_first import more 253 | engine.speak(more()) 254 | 255 | 256 | class PasswordResetRule(CompoundRule): 257 | spec = "password reset" # Spoken form of command. 258 | def _process_recognition(self, node, extras): # Callback when command is spoken. 259 | from bombly.modules.passwords import reset 260 | reset() 261 | 262 | 263 | class PasswordRule(CompoundRule): 264 | spec = "password " # Spoken form of command. 265 | extras = [Dictation("letters")] 266 | def _process_recognition(self, node, extras): # Callback when command is spoken. 267 | from bombly.modules.passwords import solve_password 268 | for word in solve_password(extras): 269 | engine.speak(word) 270 | 271 | 272 | class BombDoneRule(CompoundRule): 273 | spec = "bomb done" # Spoken form of command. 274 | def _process_recognition(self, node, extras): # Callback when command is spoken. 275 | from bombly.bomb import done 276 | engine.speak(done()) 277 | 278 | 279 | class BombExplodedRule(CompoundRule): 280 | spec = "bomb exploded" # Spoken form of command. 281 | def _process_recognition(self, node, extras): # Callback when command is spoken. 282 | from bombly.bomb import exploded 283 | engine.speak(exploded()) 284 | 285 | 286 | # Create a grammar which contains and loads the command rule. 287 | grammar = Grammar("Keep Talking") # Create a grammar to contain the command rule. 288 | grammar.add_rule(BombBatteriesRule()) # Add the command rule to the grammar. 289 | grammar.add_rule(BombVowelRule()) # Add the command rule to the grammar. 290 | grammar.add_rule(BombParallelRule()) # Add the command rule to the grammar. 291 | grammar.add_rule(BombSerialRule()) # Add the command rule to the grammar. 292 | grammar.add_rule(BombFreakRule()) # Add the command rule to the grammar. 293 | grammar.add_rule(BombCarRule()) # Add the command rule to the grammar. 294 | grammar.add_rule(BombResetRule()) # Add the command rule to the grammar. 295 | grammar.add_rule(BombStatusRule()) # Add the command rule to the grammar. 296 | grammar.add_rule(SimpleWiresRule()) # Add the command rule to the grammar. 297 | grammar.add_rule(ComplexWiresRule()) # Add the command rule to the grammar. 298 | grammar.add_rule(MazeRule()) # Add the command rule to the grammar. 299 | grammar.add_rule(SimonRule()) # Add the command rule to the grammar. 300 | grammar.add_rule(WireSequenceRule()) # Add the command rule to the grammar. 301 | grammar.add_rule(WireSequenceResetRule()) # Add the command rule to the grammar. 302 | grammar.add_rule(ButtonRule()) # Add the command rule to the grammar. 303 | grammar.add_rule(ButtonColorRule()) # Add the command rule to the grammar. 304 | grammar.add_rule(KnobsRule()) # Add the command rule to the grammar. 305 | grammar.add_rule(MemoryRule()) # Add the command rule to the grammar. 306 | grammar.add_rule(MemoryResetRule()) # Add the command rule to the grammar. 307 | grammar.add_rule(MorseRule()) # Add the command rule to the grammar. 308 | grammar.add_rule(MorseResetRule()) # Add the command rule to the grammar. 309 | grammar.add_rule(SymbolsRule()) # Add the command rule to the grammar. 310 | grammar.add_rule(WordsRule()) # Add the command rule to the grammar. 311 | grammar.add_rule(WordsResetRule()) # Add the command rule to the grammar. 312 | grammar.add_rule(WordsRemoveRule()) # Add the command rule to the grammar. 313 | grammar.add_rule(WordsMoreRule()) # Add the command rule to the grammar. 314 | grammar.add_rule(PasswordResetRule()) # Add the command rule to the grammar. 315 | grammar.add_rule(PasswordRule()) # Add the command rule to the grammar. 316 | grammar.add_rule(BombDoneRule()) 317 | grammar.add_rule(BombExplodedRule()) 318 | grammar.load() 319 | -------------------------------------------------------------------------------- /': -------------------------------------------------------------------------------- 1 | from dragonfly import * 2 | from dragonfly.engines.backend_sapi5.engine import Sapi5InProcEngine 3 | 4 | from collections import defaultdict 5 | import sys 6 | 7 | ################################################################################ 8 | # Global variables 9 | ################################################################################ 10 | engine = Sapi5InProcEngine() 11 | engine.connect() 12 | 13 | # Battery characteristics 14 | batteries = 99 15 | freak = 'freak' 16 | car = 'car' 17 | parallel = 'parallel' 18 | serial = 'serial' 19 | vowel = 'vowel' 20 | 21 | # Maxes 22 | mazes = { 23 | (('1','2'), ('6','3')): """ 24 | x x x|x x x 25 | - - - 26 | x|x x|x x x 27 | - - - 28 | x|x x|x x x 29 | - - 30 | x|x x x|x x 31 | - - - - 32 | x x x|x x|x 33 | - - 34 | x x|x x|x x 35 | """, 36 | (('5','2'), ('2','4')): """ 37 | x x x|x x x 38 | - - - 39 | x x|x x|x x 40 | - - - 41 | x|x x|x x x 42 | - - 43 | x x|x x|x|x 44 | - - 45 | x|x|x|x x|x 46 | - 47 | x|x x|x x x 48 | """, 49 | (('4','4'), ('6','4')): """ 50 | x x x|x|x x 51 | - 52 | x|x|x|x x|x 53 | - - - 54 | x x|x|x x|x 55 | 56 | x|x|x|x|x|x 57 | 58 | x|x x|x|x|x 59 | - - 60 | x x x x|x x 61 | """, 62 | (('1','1'), ('1','4')): """ 63 | x x|x x x x 64 | - - - 65 | x|x|x x x x 66 | - - 67 | x|x x|x x|x 68 | - - - 69 | x|x x x x x 70 | - - - - 71 | x x x x x|x 72 | - - - 73 | x x x|x x|x 74 | """, 75 | (('5','3'), ('4','6')): """ 76 | x x x x x x 77 | - - - - 78 | x x x x x|x 79 | - - - - 80 | x x|x x|x x 81 | - - 82 | x|x x x|x|x 83 | - - - 84 | x|x x x x|x 85 | - - - 86 | x|x x x x x 87 | """, 88 | (('5','1'), ('3','5')): """ 89 | x|x x|x x x 90 | - 91 | x|x|x|x x|x 92 | - 93 | x x|x|x|x x 94 | - - - 95 | x x|x x|x|x 96 | - 97 | x x|x|x|x x 98 | - - - 99 | x x x x|x x 100 | """, 101 | (('2','1'), ('2','6')): """ 102 | x x x x|x x 103 | - - 104 | x|x x|x x|x 105 | - - - 106 | x x|x x|x x 107 | - - - - 108 | x x|x x x|x 109 | - - 110 | x|x|x x x|x 111 | - - - 112 | x x x x x x 113 | """, 114 | (('4','1'), ('3','4')): """ 115 | x|x x x|x x 116 | - 117 | x x x|x x|x 118 | - - - - 119 | x|x x x x|x 120 | - - 121 | x|x x|x x x 122 | - - - - 123 | x|x|x x x x 124 | - - - - 125 | x x x x x x 126 | """, 127 | (('3','2'), ('1','5')): """ 128 | x|x x x x x 129 | - - 130 | x|x|x x|x x 131 | - 132 | x x x|x x|x 133 | - - - 134 | x|x|x x|x x 135 | - - 136 | x|x|x|x x|x 137 | - 138 | x x|x x|x x 139 | """, 140 | } 141 | 142 | # Wire sequence 143 | counts = defaultdict(int) 144 | sequences = {} 145 | sequences['red'] = [ 146 | ('c'), 147 | ('b'), 148 | ('a'), 149 | ('a', 'c'), 150 | ('b'), 151 | ('a', 'c'), 152 | ('a', 'b', 'c'), 153 | ('a', 'b'), 154 | ('b') 155 | ] 156 | sequences['blue'] = [ 157 | ('b'), 158 | ('a', 'c'), 159 | ('b'), 160 | ('a'), 161 | ('b'), 162 | ('b','c'), 163 | ('c'), 164 | ('a', 'c'), 165 | ('a') 166 | ] 167 | sequences['black'] = [ 168 | ('a', 'b', 'c'), 169 | ('a', 'c'), 170 | ('b'), 171 | ('a', 'c'), 172 | ('b'), 173 | ('b', 'c'), 174 | ('a', 'b'), 175 | ('c'), 176 | ('c') 177 | ] 178 | 179 | # Memory 180 | values = [] 181 | positions = [] 182 | curr_stage = 1 183 | 184 | # Morse 185 | morse_letters = [] 186 | 187 | # On first words 188 | on_first_words = [] 189 | curr_wordlist = [] 190 | 191 | # Password 192 | curr_password = [] 193 | 194 | def get_maze_dict(maze): 195 | maze_dict = defaultdict(list) 196 | maze = maze[1:] 197 | maze = maze.split('\n') 198 | 199 | for row_index, line in enumerate(maze): 200 | for col_index, item in enumerate(line): 201 | if item == 'x': 202 | col = col_index/2+1 203 | row = row_index/2+1 204 | try: 205 | if maze[row_index+1][col_index] == ' ': 206 | maze_dict[(col, row)].append(('D', (col, row+1))) 207 | except: 208 | pass 209 | try: 210 | if maze[row_index-1][col_index] == ' ': 211 | maze_dict[(col, row)].append(('U', (col, row-1))) 212 | except: 213 | pass 214 | try: 215 | if maze[row_index][col_index+1] == ' ': 216 | maze_dict[(col, row)].append(('R', (col+1, row))) 217 | except: 218 | pass 219 | try: 220 | if maze[row_index][col_index-1] == ' ': 221 | maze_dict[(col, row)].append(('L', (col-1, row))) 222 | except: 223 | pass 224 | 225 | return maze_dict 226 | 227 | def easy_answer(answer): 228 | count = 0 229 | curr_letter = answer[0] 230 | curr_answer = '' 231 | 232 | for index, letter in enumerate(answer): 233 | left = start[index:] 234 | if letter != curr_letter: 235 | curr_answer += curr_letter + str(count) + ' ' 236 | curr_letter = letter 237 | count = 1 238 | else: 239 | count += 1 240 | 241 | curr_answer += curr_letter + str(count) 242 | 243 | return curr_answer 244 | 245 | 246 | def traverse_maze(maze_dict, start, finish): 247 | path = [[('x', start)]] 248 | while True: 249 | for curr_path in path: 250 | temp_path = curr_path[:] 251 | new_paths = maze_dict[temp_path[-1][1]] 252 | for new_path in new_paths: 253 | if finish == new_path[1]: 254 | answer = '' 255 | for pair in (temp_path + [new_path])[1:]: 256 | answer += pair[0] 257 | 258 | return answer 259 | else: 260 | path.append(temp_path + [new_path]) 261 | 262 | def get_maze(indicator): 263 | for indicators,maze in mazes.iteritems(): 264 | if indicator in indicators: 265 | return maze 266 | 267 | return '' 268 | 269 | def odd_serial(): 270 | return serial in ('one', 'three', 'five', 'seven', 'nine') 271 | 272 | def even_serial(): 273 | return serial in ('zero', 'two', 'four', 'six', 'eight') 274 | 275 | def sanitize_colors(words): 276 | print "Sanitizing: {}".format(words) 277 | words = words.replace('read', 'red').replace('blew', 'blue') 278 | words = ' '.join([word for word in words.split() if word in ('yellow', 'red', 'black', 'blue', 'white')]) 279 | print "Sanitized: {}".format(words) 280 | return words 281 | 282 | class SampleRule(CompoundRule): 283 | spec = "simple wires " # Spoken form of command. 284 | extras = [Dictation("wires")] 285 | def _process_recognition(self, node, extras): # Callback when command is spoken. 286 | wire = str(extras['wires']) 287 | 288 | class BombResetRule(CompoundRule): 289 | spec = "bomb reset" 290 | 291 | def _process_recognition(self, node, extras): # Callback when command is spoken. 292 | global batteries 293 | global freak 294 | global car 295 | global paralle 296 | global serial 297 | global vowel 298 | global counts 299 | global values 300 | global positions 301 | global curr_stage 302 | global morse_letters 303 | global on_first_words 304 | 305 | # Battery characteristics 306 | batteries = 99 307 | freak = 'freak' 308 | car = 'car' 309 | parallel = 'parallel' 310 | serial = 'serial' 311 | vowel = 'vowel' 312 | 313 | # Wire sequence 314 | counts = defaultdict(int) 315 | 316 | # Memory 317 | values = [] 318 | positions = [] 319 | curr_stage = 1 320 | 321 | # Morse 322 | morse_letters = [] 323 | 324 | # On First Words 325 | on_first_words = [] 326 | 327 | # Password 328 | curr_password = [] 329 | 330 | class BombStatusRule(CompoundRule): 331 | spec = "bomb status" 332 | 333 | def _process_recognition(self, node, extras): # Callback when command is spoken. 334 | global batteries 335 | global freak 336 | global car 337 | global paralle 338 | global serial 339 | global vowel 340 | global counts 341 | global values 342 | global positions 343 | global curr_stage 344 | global morse_letters 345 | global on_first_words 346 | 347 | # Battery characteristics 348 | print 'batteries', batteries 349 | print 'frk', freak 350 | print 'car', car 351 | print 'parallel', parallel 352 | print 'serial', serial 353 | print 'vowel', vowel 354 | 355 | # Wire sequence 356 | print 'wire sequence', counts 357 | 358 | # Memory 359 | print 'values', values 360 | print 'position', positions 361 | print 'curr_stage', curr_stage 362 | 363 | # Morse 364 | print 'morse_letters', morse_letters 365 | 366 | # On First Words 367 | print 'on first words', on_first_words 368 | 369 | class BombCarRule(CompoundRule): 370 | spec = "car " 371 | extras = [IntegerRef('car', 0, 10)] 372 | 373 | def _process_recognition(self, node, extras): # Callback when command is spoken. 374 | global car 375 | car = str(extras['car']) 376 | 377 | class BombBatteriesRule(CompoundRule): 378 | spec = "batteries " 379 | extras = [IntegerRef('batteries', 0, 10)] 380 | 381 | def _process_recognition(self, node, extras): # Callback when command is spoken. 382 | global batteries 383 | batteries = int(str(extras['batteries'])) 384 | 385 | class BombFreakRule(CompoundRule): 386 | spec = "freak " 387 | extras = [Dictation('word')] 388 | 389 | def _process_recognition(self, node, extras): # Callback when command is spoken. 390 | global freak 391 | freak = str(extras['word']) 392 | 393 | class BombParallelRule(CompoundRule): 394 | spec = "parallel " 395 | extras = [ 396 | Dictation('word'), 397 | ] 398 | 399 | def _process_recognition(self, node, extras): # Callback when command is spoken. 400 | global parallel 401 | parallel = str(extras['word']) 402 | 403 | class BombSerialRule(CompoundRule): 404 | spec = "serial " 405 | extras = [ 406 | Dictation('word'), 407 | ] 408 | 409 | def _process_recognition(self, node, extras): # Callback when command is spoken. 410 | global serial 411 | serial = str(extras['word']) 412 | 413 | class BombVowelRule(CompoundRule): 414 | spec = "vowel " 415 | extras = [ 416 | Dictation('word') 417 | ] 418 | 419 | def _process_recognition(self, node, extras): # Callback when command is spoken. 420 | global vowel 421 | vowel = str(extras['word']) 422 | 423 | # Voice command rule combining spoken form and recognition processing. 424 | class SimpleWiresRule(CompoundRule): 425 | spec = "simple wires " # Spoken form of command. 426 | extras = [Dictation("wires")] 427 | def _process_recognition(self, node, extras): # Callback when command is spoken. 428 | spoken = 'need' 429 | if serial == 'serial': 430 | spoken += ' last digit of serial' 431 | if spoken != 'need': 432 | engine.speak(spoken) 433 | return 434 | 435 | wire = str(extras['wires']) 436 | wire = sanitize_colors(wire) 437 | wire = wire.split() 438 | 439 | if len(wire) == 3: 440 | if 'red' not in wire: 441 | engine.speak('cut second wire') 442 | elif wire[-1] == 'white': 443 | engine.speak('cut last wire') 444 | elif wire.count('blue') > 1: 445 | engine.speak('cut last blue wire') 446 | else: 447 | engine.speak('cut last wire') 448 | 449 | elif len(wire) == 4: 450 | if wire.count('red') > 1 and odd_serial(): 451 | engine.speak('cut last red wire') 452 | elif wire[-1] == 'yellow' and wire.count('red') == 0: 453 | engine.speak('cut first wire') 454 | elif wire.count('blue') == 1: 455 | engine.speak('cut first wire') 456 | elif wire.count('yellow') > 1: 457 | engine.speak('cut last wire') 458 | else: 459 | engine.speak('cut second wire') 460 | 461 | elif len(wire) == 5: 462 | if wire[-1] == 'black' and odd_serial(): 463 | engine.speak('cut fourth wire') 464 | elif wire.count('red') and wire.count('yellow') > 1: 465 | engine.speak('cut first wire') 466 | elif wire.count('black') == 0: 467 | engine.speak('cut second wire') 468 | else: 469 | engine.speak('cut first wire') 470 | 471 | elif len(wire) == 6: 472 | if wire.count('yellow') == 0 and odd_serial(): 473 | engine.speak('cut third wire') 474 | elif wire.count('yellow') == 1 and wire.count('white') > 1: 475 | engine.speak('cut fourth wire') 476 | elif wire.count('red') == 0: 477 | engine.speak('cut last wire') 478 | else: 479 | engine.speak('cut fourth wire') 480 | 481 | class ComplexWiresRule(CompoundRule): 482 | spec = "complex wires " # Spoken form of command. 483 | extras = [Dictation("wires")] 484 | 485 | 486 | def _process_recognition(self, node, extras): # Callback when command is spoken. 487 | global batteries 488 | global serial 489 | global parallel 490 | spoken = 'need' 491 | if batteries == 99: 492 | spoken += ' batteries' 493 | if parallel == 'parallel': 494 | spoken += ' parallel port' 495 | if serial == 'serial': 496 | spoken += ' last digit of serial' 497 | if spoken != 'need': 498 | engine.speak(spoken) 499 | return 500 | 501 | meaning = { 502 | int('0000', 2): 'cut', 503 | int('0001', 2): 'dont cut', 504 | int('0010', 2): 'cut', 505 | int('0011', 2): 'cut' if batteries > 1 else 'dont cut', 506 | int('0100', 2): 'cut' if serial in ('zero', 'two', 'four', 'six', 'eight') else 'dont cut', 507 | int('0101', 2): 'cut' if parallel in ('true', 'yes') else 'dont cut', 508 | int('0110', 2): 'dont cut', 509 | int('0111', 2): 'cut' if parallel in ('true', 'yes') else 'dont cut', 510 | int('1000', 2): 'cut' if serial in ('zero', 'two', 'four', 'six', 'eight') else 'dont cut', 511 | int('1001', 2): 'cut' if batteries > 1 else 'dont cut', 512 | int('1010', 2): 'cut', 513 | int('1011', 2): 'cut' if batteries > 1 else 'dont cut', 514 | int('1100', 2): 'cut' if serial in ('zero', 'two', 'four', 'six', 'eight') else 'dont cut', 515 | int('1101', 2): 'cut' if serial in ('zero', 'two', 'four', 'six', 'eight') else 'dont cut', 516 | int('1110', 2): 'cut' if parallel in ('true', 'yes') else 'dont cut', 517 | int('1111', 2): 'dont cut' 518 | } 519 | 520 | bad_words = [('read', 'red'), ('blew', 'blue'), ('start', 'star'), 521 | ('white', 'light')] 522 | wire = str(extras['wires']) 523 | print wire 524 | wires = [wire for wire in wire.split('next')] 525 | print wires 526 | print 'parallel', parallel 527 | print 'serial', serial 528 | print 'batteries', batteries 529 | final_wires = [] 530 | answer = 'cut nothing' 531 | for index, wire in enumerate(wires): 532 | for bad, good in bad_words: 533 | wire = wire.replace(bad, good) 534 | 535 | wire = [item for item in wire.split() if item in ('red', 'blue', 'light', 536 | 'star', 'blank')] 537 | 538 | print wire 539 | total = 0 540 | for letter, value in [('red', 8), ('blue', 4), ('star', 2), ('light', 1)]: 541 | if letter in wire: 542 | total += value 543 | 544 | print wire, total 545 | 546 | if meaning[total] == 'cut': 547 | if answer == 'cut nothing': 548 | answer = 'cut ' 549 | answer += str(index+1) + ', ' 550 | 551 | engine.speak(answer) 552 | 553 | class MazeRule(CompoundRule): 554 | spec = "maze " # Spoken form of command. 555 | extras = [Dictation("maze")] 556 | def _process_recognition(self, node, extras): # Callback when command is spoken. 557 | maze = str(extras['maze']) 558 | maze = ' '.join([x for x in maze.split() if x in ['one', 'two','three', 'four', 'five', 'six', 'seven', 'eight', 'nine']]) 559 | print maze 560 | for word, num in [('one', '1'), ('two', '2'), ('three', '3'), ('four', '4'), ('five', '5'), ('six', '6'), ('seven', '7'), ('eight', '8'), ('nine', '9')]: 561 | maze = maze.replace(word, num) 562 | 563 | maze = maze.replace(' ', '') 564 | # If users input , or spaces, we ignore them 565 | indicator = tuple(maze[0:2]) 566 | start = tuple([int(x) for x in maze[2:4]]) 567 | finish = tuple([int(x) for x in maze[4:6]]) 568 | 569 | if len(indicator) != 2 or len(start) != 2 or len(finish) != 2: 570 | engine.speak("Try maze again") 571 | return 572 | 573 | maze = get_maze(indicator) 574 | print maze 575 | maze_dict = get_maze_dict(maze) 576 | letters = {'L': 'left', 'R': 'right', 'D':'down', 'U':'up'} 577 | path = [] 578 | for letter in traverse_maze(maze_dict, start, finish): 579 | path.append(letters[letter]) 580 | 581 | for path in [path[x:x+3] for x in range(0, len(path), 3)]: 582 | engine.speak(path) 583 | 584 | class SimonRule(CompoundRule): 585 | spec = "simon " # Spoken form of command. 586 | extras = [Dictation("words")] 587 | def _process_recognition(self, node, extras): # Callback when command is spoken. 588 | print str(extras['words']) 589 | if vowel == 'vowel': 590 | engine.speak("Serial contain vowel?") 591 | return 592 | 593 | words = str(extras['words']) 594 | print words 595 | words = words.replace('read', 'red').replace('blew', 'blue') 596 | words = [word for word in words.split() if word in ('blue', 'yellow', 'red', 'green')] 597 | 598 | new_words = [] 599 | print "Your words: {}".format(words) 600 | if vowel in ('true', 'yes'): 601 | colors = {'red': 'blue', 602 | 'blue': 'red', 603 | 'green': 'yellow', 604 | 'yellow': 'green'} 605 | for word in words: 606 | new_words.append(colors[word]) 607 | else: 608 | colors = {'red': 'blue', 609 | 'blue': 'yellow', 610 | 'green': 'green', 611 | 'yellow': 'red'} 612 | for word in words: 613 | new_words.append(colors[word]) 614 | 615 | new_words = ' '.join(new_words) 616 | print "My words: {}".format(new_words) 617 | engine.speak(new_words) 618 | 619 | class WireSequenceRule(CompoundRule): 620 | spec = "wire sequence " # Spoken form of command. 621 | extras = [Dictation("words")] 622 | def _process_recognition(self, node, extras): # Callback when command is spoken. 623 | global sequences 624 | words = str(extras['words']) 625 | print words 626 | words = words.replace('read', 'red').replace('blew', 'blue') 627 | print words 628 | words = [word for word in words.split() if word in ('red', 'blue', 'black', 'apple', 'bravo', 'charlie')] 629 | print words 630 | words = [words[x:x+2] for x in xrange(0, len(words), 2)] 631 | print words 632 | answer = [] 633 | for index, item in enumerate(words): 634 | print index, item 635 | color, letter = item 636 | print "Color: {}".format(color) 637 | print "Letter: {}".format(letter) 638 | print "Count: {}".format(counts[color]) 639 | print sequences[color] 640 | print counts[color] 641 | print sequences[color][counts[color]] 642 | print sequences[color][counts[color]] 643 | if letter[0] in sequences[color][counts[color]]: 644 | answer.append(str(index+1)) 645 | 646 | counts[color] += 1 647 | 648 | if not answer: 649 | engine.speak('cut nothing') 650 | else: 651 | engine.speak(', '.join(answer)) 652 | 653 | class WireSequenceResetRule(CompoundRule): 654 | spec = "wire sequence reset" # Spoken form of command. 655 | def _process_recognition(self, node, extras): # Callback when command is spoken. 656 | global counts 657 | counts = defaultdict(int) 658 | 659 | class ButtonRule(CompoundRule): 660 | spec = "button " # Spoken form of command. 661 | extras = [Dictation("words")] 662 | def _process_recognition(self, node, extras): # Callback when command is spoken. 663 | spoken = 'need' 664 | print "Batteries: {}".format(batteries) 665 | print "Freak: {}".format(freak) 666 | print "Car: {}".format(car) 667 | if batteries == 99: 668 | spoken += ' batteries' 669 | if freak == 'freak': 670 | spoken += ' freak' 671 | if car == 'car': 672 | spoken += ' car identifier' 673 | if spoken != 'need': 674 | engine.speak(spoken) 675 | return 676 | 677 | words = str(extras['words']) 678 | print words 679 | words = words.replace('read', 'red').replace('blew', 'blue') 680 | print words 681 | if 'blue' in words and 'abort' in words: 682 | engine.speak('Press and hold') 683 | elif 'detonate' in words and batteries > 1: 684 | engine.speak('Press and release') 685 | elif 'white' in words and car in ('true', 'yes'): 686 | engine.speak('Press and hold') 687 | elif batteries > 2 and freak in ('true', 'yes'): 688 | engine.speak('Press and release') 689 | elif 'yellow' in words: 690 | engine.speak('Press and hold') 691 | elif 'red' in words and 'hold' in words: 692 | engine.speak('Press and release') 693 | else: 694 | engine.speak('Press and hold') 695 | 696 | class ButtonColorRule(CompoundRule): 697 | spec = "button color " # Spoken form of command. 698 | extras = [Dictation("words")] 699 | def _process_recognition(self, node, extras): # Callback when command is spoken. 700 | words = str(extras['words']) 701 | print words 702 | words = words.replace('read', 'red').replace('blew', 'blue') 703 | print words 704 | if 'blue' in words: 705 | engine.speak('four') 706 | elif 'yellow' in words: 707 | engine.speak('five') 708 | else: 709 | engine.speak('one') 710 | 711 | class KnobsRule(CompoundRule): 712 | spec = "knobs " # Spoken form of command. 713 | extras = [Dictation("words")] 714 | def _process_recognition(self, node, extras): # Callback when command is spoken. 715 | words = str(extras['words']) 716 | print words 717 | words = ''.join([word for word in words.split() if word in ('one', 'zero')]) 718 | print words 719 | leds = words.replace('one', '1').replace('zero', '0').replace(' ', '') 720 | print leds 721 | if leds == '111011' or leds == '011010': 722 | engine.speak('Up') 723 | if leds == '111001' or leds == '010010': 724 | engine.speak('Down') 725 | if leds == '100010' or leds == '000010': 726 | engine.speak('Left') 727 | if leds == '111111' or leds == '111100': 728 | engine.speak('Right') 729 | 730 | 731 | class MemoryRule(CompoundRule): 732 | spec = "memory " # Spoken form of command. 733 | extras = [Dictation("words")] 734 | def _process_recognition(self, node, extras): # Callback when command is spoken. 735 | global values 736 | global positions 737 | global curr_stage 738 | words = str(extras['words']) 739 | print words 740 | words = [word for word in words.split() if word in ('one', 'two', 'three', 'four')] 741 | print words 742 | if len(words) != 5: 743 | engine.speak("Try memory again.") 744 | return 745 | 746 | display = words[0] 747 | stage = words[1:] 748 | 749 | print "Current Stage: {}".format(curr_stage) 750 | print "Values: {}".format(values) 751 | print "Positions: {}".format(values) 752 | if curr_stage == 1: 753 | if display == 'one': 754 | answer = stage[1] 755 | if display == 'two': 756 | answer = stage[1] 757 | if display == 'three': 758 | answer = stage[2] 759 | if display == 'four': 760 | answer = stage[3] 761 | position = stage.index(answer) 762 | 763 | if curr_stage == 2: 764 | if display == 'one': 765 | answer = 'four' 766 | if display == 'two': 767 | answer = stage[positions[0]] 768 | if display == 'three': 769 | answer = stage[0] 770 | if display == 'four': 771 | answer = stage[positions[0]] 772 | position = stage.index(answer) 773 | 774 | if curr_stage == 3: 775 | if display == 'one': 776 | answer = values[1] 777 | position = 'one' 778 | if display == 'two': 779 | answer = values[0] 780 | position = 'two' 781 | if display == 'three': 782 | answer = stage[2] 783 | position = stage.index(answer) 784 | if display == 'four': 785 | answer = 'four' 786 | position = stage.index(answer) 787 | 788 | if curr_stage == 4: 789 | if display == 'one': 790 | answer = stage[positions[0]] 791 | position = stage.index(answer) 792 | if display == 'two': 793 | answer = stage[0] 794 | position = stage.index(answer) 795 | if display == 'three': 796 | answer = stage[positions[1]] 797 | position = stage.index(answer) 798 | if display == 'four': 799 | answer = stage[positions[1]] 800 | position = stage.index(answer) 801 | 802 | if curr_stage == 5: 803 | if display == 'one': 804 | answer = values[0] 805 | if display == 'two': 806 | answer = values[1] 807 | if display == 'three': 808 | answer = values[3] 809 | if display == 'four': 810 | answer = values[2] 811 | position = stage.index(answer) 812 | 813 | values.append(answer) 814 | positions.append(position) 815 | curr_stage += 1 816 | print "Answer: {}".format(answer) 817 | engine.speak(answer) 818 | if curr_stage > 5: 819 | values = [] 820 | positions = [] 821 | curr_stage = 1 822 | 823 | 824 | class MemoryResetRule(CompoundRule): 825 | spec = "memory reset" # Spoken form of command. 826 | def _process_recognition(self, node, extras): # Callback when command is spoken. 827 | global positions 828 | global curr_stage 829 | global values 830 | positions = [] 831 | values = [] 832 | curr_stage = 1 833 | 834 | class MorseRule(CompoundRule): 835 | spec = "morse " # Spoken form of command. 836 | extras = [Dictation("words")] 837 | def _process_recognition(self, node, extras): # Callback when command is spoken. 838 | global morse_letters 839 | words = str(extras['words']) 840 | 841 | words = ''.join([word for word in words.split() if word in ('one', 'zero')]) 842 | print words 843 | code = words.replace('one', '-').replace('zero', '.') 844 | print code 845 | 846 | morse = { 847 | 'a': '.-', 848 | 'b': '-...', 849 | 'c': '-.-.', 850 | 'e': '.', 851 | 'f': '..-.', 852 | 'g': '--.', 853 | 'h': '....', 854 | 'i': '..', 855 | 'k': '-.-', 856 | 'l': '.-..', 857 | 'm': '--', 858 | 'n': '-.', 859 | 'o': '---', 860 | 'r': '.-.', 861 | 's': '...', 862 | 't': '-', 863 | 'v': '...-', 864 | 'x': '-..-', 865 | } 866 | 867 | codes = {} 868 | for key, val in morse.iteritems(): 869 | if code == val: 870 | morse_letters.append(key) 871 | 872 | codes[val] = key 873 | 874 | print "Current morse letters: {}".format(morse_letters) 875 | if len(morse_letters) < 2: 876 | return 877 | 878 | words = { 879 | 'shell': '5 0 5', 880 | 'halls': '5 1 5', 881 | 'slick': '5 2 2', 882 | 'trick': '5 3 2', 883 | 'boxes': '5 3 5', 884 | 'leaks': '5 4 2', 885 | 'strobe': '5 4 5', 886 | 'bistro': '5 5 2', 887 | 'flick': '5 5 5', 888 | 'bombs': '5 6 5', 889 | 'break': '5 7 2', 890 | 'brick': '5 7 5', 891 | 'steak': '5 8 2', 892 | 'sting': '5 9 2', 893 | 'vector': '5 9 5', 894 | 'beats': '6 0 0', 895 | } 896 | 897 | code = ''.join(morse_letters) 898 | 899 | combos = {} 900 | for word in words: 901 | curr_combo = [] 902 | for num in xrange(len(word)): 903 | curr_word = ''.join((word+word)[num:num+3]) 904 | combos[curr_word] = word 905 | 906 | print code 907 | print combos.keys() 908 | if code in combos: 909 | engine.speak(words[combos[code]]) 910 | 911 | possibles = [] 912 | for key, val in combos.iteritems(): 913 | curr_word = ''.join([morse[letter] for letter in key]) 914 | if code.startswith(curr_word): 915 | # print val, key, code, words[val] 916 | print words[val] 917 | 918 | class MorseResetRule(CompoundRule): 919 | spec = "morse reset" # Spoken form of command. 920 | def _process_recognition(self, node, extras): # Callback when command is spoken. 921 | global morse_letters 922 | morse_letters = [] 923 | 924 | class WordsResetRule(CompoundRule): 925 | spec = "words reset" # Spoken form of command. 926 | def _process_recognition(self, node, extras): # Callback when command is spoken. 927 | global on_first_words 928 | on_first_words = [] 929 | 930 | class WordsRemoveRule(CompoundRule): 931 | spec = "words remove" # Spoken form of command. 932 | def _process_recognition(self, node, extras): # Callback when command is spoken. 933 | global on_first_words 934 | on_first_words = on_first_words[:-1] 935 | 936 | class SymbolsRule(CompoundRule): 937 | spec = "symbols " # Spoken form of command. 938 | extras = [Dictation("symbols")] 939 | def _process_recognition(self, node, extras): # Callback when command is spoken. 940 | symbols = str(extras['symbols']) 941 | 942 | groups = [ 943 | ['tennis', 'a', 'l', 'lightning', 'cat', 'h', 'c'], 944 | ['e', 'tennis', 'c', 'o', 'star', 'h', 'question'], 945 | ['copyright', 'but', 'o', 'k', 'r', 'l', 'star'], 946 | ['six', 'paragraph', 'b', 'cat', 'k', 'question', 'smile'], 947 | ['goblet', 'smile', 'b', 'c', 'paragraph', 'three', 'star'], 948 | ['six', 'e', 'equals', 'smash', 'goblet', 'in', 'omega'] 949 | ] 950 | 951 | print symbols 952 | symbols = symbols.replace('butt', 'but') 953 | curr_symbols = symbols.replace('.', '').lower().split() 954 | print curr_symbols 955 | 956 | answer = '' 957 | for group in groups: 958 | for symbol in curr_symbols: 959 | if symbol not in group: 960 | break 961 | else: 962 | for symbol in group: 963 | if symbol in curr_symbols: 964 | answer += symbol + ' ' 965 | 966 | engine.speak(answer) 967 | 968 | class WordsRule(CompoundRule): 969 | spec = "words " # Spoken form of command. 970 | extras = [Dictation("words")] 971 | def _process_recognition(self, node, extras): # Callback when command is spoken. 972 | global curr_wordlist 973 | words = str(extras['words']) 974 | 975 | combos = { 976 | ('you', 'are', 'words'): 'you are', 977 | ('your', 'words'): 'you are', 978 | ('done',): 'done', 979 | ('don',): 'done', 980 | ('you', 'are', 'letters'): 'ur', 981 | ('sure',): 'sure', 982 | ('shore',): 'sure', 983 | ('you', 'word'): 'you', 984 | ('you', 'were'): 'you', 985 | ('you', 'were', 'to'): 'you', 986 | ('you', 'work'): 'you', 987 | ('hold',): 'hold', 988 | ('you', 'letter'): 'u', 989 | ('yes',): 'yes', 990 | ('first',): 'first', 991 | ('display',): 'display', 992 | ('okay',): 'okay', 993 | ('OK',): 'okay', 994 | ('says',): 'says', 995 | ('nothing',): 'nothing', 996 | ('literally', 'blank'): ' ', 997 | ('blank',): 'blank', 998 | ('no',): 'no', 999 | ('L.', 'E.', 'D.'): 'led', 1000 | ('lead',): 'lead', 1001 | ('mead',): 'lead', 1002 | ('read',): 'read', 1003 | ('red', 'short'): 'red', 1004 | ('read', 'too'): 'reed', 1005 | ('hold', 'on', 'two'): 'hold on', 1006 | ("you're", 'word'): 'your', 1007 | ("your", 'word'): 'your', 1008 | ('your', 'mark'): "you're", 1009 | ('you', 'are', 'marked'): "you're", 1010 | ('you', 'are', 'mark'): "you're", 1011 | ('C.', 'S.'): "see", 1012 | ('they', 'are', 'words'): "they are", 1013 | ('E.', 'I.', 'R.'): "their", 1014 | ('E.', 'R.', 'E.'): "there", 1015 | ('they', 'are', 'marked'): "they're", 1016 | ('they', 'mark'): "they're", 1017 | ('their', 'mark'): "they're", 1018 | ('there', 'mark'): "they're", 1019 | ('S.', 'E.', 'E.'): "see", 1020 | ('C.', 'letter'): "c", 1021 | ('see', 'letter'): "c", 1022 | ('C.', 'E.', 'E.'): "cee", 1023 | ('CC',): "cee", 1024 | ('ready',): 'ready', 1025 | ('yes',): 'yes', 1026 | ('what', 'no', 'mark'): 'what', 1027 | ('what', 'know', 'mark'): 'what', 1028 | ('three', 'H.'): 'uhhh', 1029 | ('left',): 'left', 1030 | ('right',): 'right', 1031 | ('write',): 'right', 1032 | ('middle',): 'middle', 1033 | ('metal',): 'middle', 1034 | ('wait',): 'wait', 1035 | ('press',): 'press', 1036 | ('five', 'letters'): 'uh huh', 1037 | ('four', 'letters'): 'uh uh', 1038 | ('what', 'mark'): 'what?', 1039 | ('done',): 'done', 1040 | ('next',): 'next', 1041 | ('hold',): 'hold', 1042 | ('sure',): 'sure', 1043 | ('like',): 'like', 1044 | ('mike',): 'like', 1045 | ('might',): 'like', 1046 | ('white',): 'like', 1047 | ('light',): 'like', 1048 | } 1049 | 1050 | positions = { 1051 | 'yes': 3, 1052 | 'first': 2, 1053 | 'display': 6, 1054 | 'okay': 2, 1055 | 'says': 6, 1056 | 'nothing': 3, 1057 | ' ': 5, 1058 | 'blank': 4, 1059 | 'no': 6, 1060 | 'led': 3, 1061 | 'lead': 6, 1062 | 'read': 4, 1063 | 'red': 4, 1064 | 'reed': 5, 1065 | 'leed': 5, 1066 | 'hold on': 6, 1067 | 'you': 4, 1068 | 'you are': 6, 1069 | 'your': 4, 1070 | "you're": 4, 1071 | 'ur': 1, 1072 | 'there': 6, 1073 | "they're": 5, 1074 | 'their': 4, 1075 | 'they are': 3, 1076 | 'see': 6, 1077 | 'c': 2, 1078 | 'cee': 6 1079 | } 1080 | 1081 | table = { 1082 | "ready": ["yes", "okay", "what", "middle", "left", "press", "right", "blank", "ready"], 1083 | "first": ["left", "okay", "yes", "middle", "no", "right", "nothing", "uhhh", "wait", "ready", "blank", "what", "press", "first"], 1084 | "no": ["blank", "uhhh", "wait", "first", "what", "ready", "right", "yes", "nothing", "left", "press", "okay", "no", "middle"], 1085 | "blank": ["wait", "right", "okay", "middle", "blank"], 1086 | "nothing": ["uhhh", "right", "okay", "middle", "yes", "blank", "no", "press", "left", "what", "wait", "first", "nothing", "ready"], 1087 | "yes": ["okay", "right", "uhhh", "middle", "first", "what", "press", "ready", "nothing", "yes"], 1088 | "what": ["uhhh", "what"], 1089 | "uhhh": ["ready", "nothing", "left", "what", "okay", "yes", "right", "no", "press", "blank", "uhhh"], 1090 | "left": ["right", "left"], 1091 | "right": ["yes", "nothing", "ready", "press", "no", "wait", "what", "right"], 1092 | "middle": ["blank", "ready", "okay", "what", "nothing", "press", "no", "wait", "left", "middle"], 1093 | "okay": ["middle", "no", "first", "yes", "uhhh", "nothing", "wait", "okay"], 1094 | "wait": ["uhhh", "no", "blank", "okay", "yes", "left", "first", "press", "what", "wait"], 1095 | "press": ["right", "middle", "yes", "ready", "press"], 1096 | "you": ["sure", "you are", "your", "you're", "next", "uh huh", "ur", "hold", "what?", "you"], 1097 | "you are": ["your", "next", "like", "uh huh", "what?", "done", "uh uh", "hold", "you", "u", "you're", "sure", "ur", "you are"], 1098 | "your": ["uh uh", "you are", "uh huh", "your"], 1099 | "you're": ["you", "you're"], 1100 | "ur": ["done", "u", "ur"], 1101 | "u": ["uh huh", "sure", "next", "what?", "you're", "ur", "uh uh", "done", "u"], 1102 | "uh huh": ["uh huh"], 1103 | "uh uh": ["ur", "u", "you are", "you", "done", "hold", "uh uh", "next", "sure", "like", "your", "sure", "hold", "what?"], 1104 | "what?": ["you", "hold", "you're", "your", "u", "done", "uh uh", "like", "you are", "uh huh", "ur", "next", "what?"], 1105 | "done": ["sure", "uh huh", "next", "what?", "your", "ur", "you're", "hold", "like", "you", "u", "you are", "uh uh", "done"], 1106 | "next": ["what?", "uh huh", "uh uh", "your", "hold", "sure", "next"], 1107 | "hold": ["you are", "u", "done", "uh uh", "you", "ur", "sure", "what?", "you're", "next", "hold"], 1108 | "sure": ["you are", "done", "like", "you're", "you", "hold", "uh huh", "ur", "sure"], 1109 | "like": ["you're", "next", "u", "ur", "hold", "uh uh", "what?", "uh huh", "you", "like"], 1110 | } 1111 | 1112 | responses = { 1113 | "you are": ("you" "are", "words"), 1114 | "done": ("done",), 1115 | "ur": ("you", "are", "letters"), 1116 | "sure": ("sure",), 1117 | "you": ("you", "word"), 1118 | "hold": ("hold",), 1119 | "u": ("you", "letter"), 1120 | "yes": ("yes",), 1121 | "first": ("first",), 1122 | "display": ("display",), 1123 | "okay": ("okay",), 1124 | "says": ("says",), 1125 | "nothing": ("nothing",), 1126 | " ": ("literally", "blank"), 1127 | "blank": ("blank",), 1128 | "no": ("no",), 1129 | "led": ("L.", "E.", "D."), 1130 | "lead": ("lead",), 1131 | "read": ("read",), 1132 | "red": ("red", "short"), 1133 | "reed": ("read", "too"), 1134 | "hold on": ("hold", "on", "two"), 1135 | "your": ("your", "word"), 1136 | "you're": ("you", "are", "mark"), 1137 | "see": ("C.", "S."), 1138 | "they are": ("they", "are", "words"), 1139 | "their": ("E.", "I.", "R."), 1140 | "there": ("E.", "R.", "E."), 1141 | "they're": ("they", "are", "marked"), 1142 | "see": ("s e e"), 1143 | "c": ("see", "letter"), 1144 | "cee": ("C.", "C."), 1145 | "cee": ("CC",), 1146 | "ready": ("ready",), 1147 | "yes": ("yes",), 1148 | "what": ("what", "no", "mark"), 1149 | "uhhh": ("three", "H."), 1150 | "left": ("left",), 1151 | "right": ("right",), 1152 | "right": ("write",), 1153 | "middle": ("middle",), 1154 | "wait": ("wait",), 1155 | "press": ("press",), 1156 | "uh huh": ("five", "letters"), 1157 | "uh uh": ("four", "letters"), 1158 | "what?": ("what", "mark"), 1159 | "done": ("done",), 1160 | "next": ("next",), 1161 | "hold": ("hold",), 1162 | "sure": ("sure",), 1163 | "like": ("like",), 1164 | } 1165 | print "Voice receive: ", words 1166 | 1167 | for combo, select in reversed(sorted(combos.iteritems(), key=lambda x: len(x[0]))): 1168 | for word in combo: 1169 | if word not in words.split(): 1170 | break 1171 | else: 1172 | print 'Words', words 1173 | print "Found word: {}".format(select) 1174 | if 'one' in words: 1175 | curr_wordlist = [] 1176 | engine.speak(positions[select]) 1177 | 1178 | if 'two' in words: 1179 | print 'select', select 1180 | wordlist = table[select] 1181 | answer = [] 1182 | new_length = min(4, len(wordlist)) 1183 | curr_wordlist = [] 1184 | print wordlist 1185 | # Cache next set of words in case we need to ask for more 1186 | # words 1187 | for word in wordlist[new_length:]: 1188 | print 'word:', word 1189 | curr_wordlist.append(' '.join(responses[word])) 1190 | 1191 | for word in wordlist[:new_length]: 1192 | answer.append(' '.join(responses[word])) 1193 | 1194 | engine.speak(', '.join(answer)) 1195 | break 1196 | 1197 | class WordsMoreRule(CompoundRule): 1198 | spec = "words more" # Spoken form of command. 1199 | def _process_recognition(self, node, extras): # Callback when command is spoken. 1200 | global curr_wordlist 1201 | speak = ', '.join(curr_wordlist[:4]) 1202 | new_length = min(4, len(curr_wordlist)) 1203 | curr_wordlist = curr_wordlist[new_length:] 1204 | engine.speak(speak) 1205 | 1206 | class PasswordResetRule(CompoundRule): 1207 | spec = "password reset" # Spoken form of command. 1208 | def _process_recognition(self, node, extras): # Callback when command is spoken. 1209 | global curr_password 1210 | curr_password = [] 1211 | print curr_password 1212 | 1213 | class PasswordRule(CompoundRule): 1214 | spec = "password " # Spoken form of command. 1215 | extras = [Dictation("letters")] 1216 | def _process_recognition(self, node, extras): # Callback when command is spoken. 1217 | global curr_password 1218 | letters = str(extras['letters']) 1219 | letters = [letter[0].lower() for letter in letters.split()] 1220 | curr_password.append(letters) 1221 | print curr_password 1222 | 1223 | passwords = ['about', 1224 | 'after', 'again', 'below', 'could', 'every', 'first', 'found', 'great', 1225 | 'house', 'large', 'learn', 'never', 'other', 'place', 'plant', 'point', 1226 | 'right', 'small', 'sound', 'spell', 'still', 'study', 'their', 'there', 1227 | 'these', 'thing', 'think', 'three', 'water', 'where', 'which', 'world', 1228 | 'would', 'write'] 1229 | 1230 | possibles = [] 1231 | if len(curr_password) == 2: 1232 | for password in passwords: 1233 | if password[0] in curr_password[0] and password[2] in curr_password[1]: 1234 | possibles.append(password) 1235 | 1236 | print possibles 1237 | 1238 | for word in possibles: 1239 | engine.speak(word) 1240 | 1241 | class BombDoneRule(CompoundRule): 1242 | spec = "bomb done" # Spoken form of command. 1243 | def _process_recognition(self, node, extras): # Callback when command is spoken. 1244 | engine.speak("I AM YOUR BOMB DEFUSING OVERLORD") 1245 | 1246 | global batteries 1247 | global freak 1248 | global car 1249 | global parallel 1250 | global serial 1251 | global vowel 1252 | global counts 1253 | global values 1254 | global positions 1255 | global curr_stage 1256 | global morse_letters 1257 | global on_first_words 1258 | global curr_wordlist 1259 | 1260 | # Battery characteristics 1261 | batteries = 99 1262 | freak = 'freak' 1263 | car = 'car' 1264 | parallel = 'parallel' 1265 | serial = 'serial' 1266 | vowel = 'vowel' 1267 | 1268 | # Wire sequence 1269 | counts = defaultdict(int) 1270 | 1271 | # Memory 1272 | values = [] 1273 | positions = [] 1274 | curr_stage = 1 1275 | 1276 | # Morse 1277 | morse_letters = [] 1278 | 1279 | # On First Words 1280 | on_first_words = [] 1281 | 1282 | # Who's on First 1283 | curr_wordlist = [] 1284 | 1285 | # Create a grammar which contains and loads the command rule. 1286 | grammar = Grammar("Keep Talking") # Create a grammar to contain the command rule. 1287 | grammar.add_rule(BombBatteriesRule()) # Add the command rule to the grammar. 1288 | grammar.add_rule(BombVowelRule()) # Add the command rule to the grammar. 1289 | grammar.add_rule(BombParallelRule()) # Add the command rule to the grammar. 1290 | grammar.add_rule(BombSerialRule()) # Add the command rule to the grammar. 1291 | grammar.add_rule(BombFreakRule()) # Add the command rule to the grammar. 1292 | grammar.add_rule(BombCarRule()) # Add the command rule to the grammar. 1293 | grammar.add_rule(BombResetRule()) # Add the command rule to the grammar. 1294 | grammar.add_rule(BombStatusRule()) # Add the command rule to the grammar. 1295 | grammar.add_rule(SimpleWiresRule()) # Add the command rule to the grammar. 1296 | grammar.add_rule(ComplexWiresRule()) # Add the command rule to the grammar. 1297 | grammar.add_rule(MazeRule()) # Add the command rule to the grammar. 1298 | grammar.add_rule(SimonRule()) # Add the command rule to the grammar. 1299 | grammar.add_rule(WireSequenceRule()) # Add the command rule to the grammar. 1300 | grammar.add_rule(WireSequenceResetRule()) # Add the command rule to the grammar. 1301 | grammar.add_rule(ButtonRule()) # Add the command rule to the grammar. 1302 | grammar.add_rule(ButtonColorRule()) # Add the command rule to the grammar. 1303 | grammar.add_rule(KnobsRule()) # Add the command rule to the grammar. 1304 | grammar.add_rule(MemoryRule()) # Add the command rule to the grammar. 1305 | grammar.add_rule(MemoryResetRule()) # Add the command rule to the grammar. 1306 | grammar.add_rule(MorseRule()) # Add the command rule to the grammar. 1307 | grammar.add_rule(MorseResetRule()) # Add the command rule to the grammar. 1308 | grammar.add_rule(SymbolsRule()) # Add the command rule to the grammar. 1309 | grammar.add_rule(WordsRule()) # Add the command rule to the grammar. 1310 | grammar.add_rule(WordsResetRule()) # Add the command rule to the grammar. 1311 | grammar.add_rule(WordsRemoveRule()) # Add the command rule to the grammar. 1312 | grammar.add_rule(WordsMoreRule()) # Add the command rule to the grammar. 1313 | grammar.add_rule(PasswordResetRule()) # Add the command rule to the grammar. 1314 | grammar.add_rule(PasswordRule()) # Add the command rule to the grammar. 1315 | grammar.add_rule(BombDoneRule()) 1316 | grammar.load() 1317 | --------------------------------------------------------------------------------