# -------------------------------------------- # See http://www.tropo.com for more info # -------------------------------------------- def make_test_versions_of_phone_functions(): """Make this code work as a normal Python script -- good for debugging.""" global ask, say, answer, hangup def ask(thing, other): print thing class Dummy: pass answer = Dummy() answer.name = "choice" answer.value = raw_input() return answer def say(thing): print thing def answer(): print "Answer" def hangup(): print "Hangup" # Patch the code unless we're running on the phone try: import os if 'nathan' in os.getcwd(): make_test_versions_of_phone_functions() except: pass import urllib2 import urllib import re class StartOverException(Exception): pass class GameOverException(Exception): def __init__(self, humanWon): Exception.__init__(self) self.humanWon = humanWon def get_question_at_path(path): """Returns (question to ask, map from word to URL). Or raises a GameOverException.""" host = 'http://y.20q.net' page = urllib2.urlopen(host + path).read() if "You won!" in page: raise GameOverException(humanWon=True) if "You were thinking of" in page: raise GameOverException(humanWon=False) try: question = re.findall('Q.*?;(.*?)
', page)[0] links = re.findall('href="(.*?)"', page) return question, dict(zip(['yes', 'no', "skip", 'irrelevant', 'sometimes', 'maybe', 'probably', 'doubtful', 'usually', 'depends', 'rarely', 'partly',], links)) except: question = re.findall('Q.*?;(.*?)
', page)[0] links = re.findall('href="(.*?)"', page) path_map = dict(zip(['right', 'wrong', 'close'], links)) path_map['yes'] = path_map['right'] path_map['no'] = path_map['wrong'] return question, path_map def instructions(): say("Think of something and I will try to guess it. I will ask you questions, and you can say: yes, no, irrelevant, sometimes, maybe, probably, doubtful, usually, depends, rarely, or partly. Try to give the best answer if you want me to guess correctly. If you don't know, say skip. To repeat the question, say repeat. To start the game over, say start over. To hear this again, say instructions at any time.") def get_answer(question, responses): """ Ask the caller 'question', and wait for one of the strings in the 'responses' list to be heard. Returns the string that was heard, or raises a StartOverException if the caller said 'start over'. (The caller can also say 'repeat' or 'instructions' which will cause something to be said back to them, but they will still then have to say something from the 'responses' list.) """ responses = responses + ['repeat', 'instructions', 'start_over'] question = re.sub("<.*?>", "", question) while True: result = ask(question, dict(bargein=False, repeat=3, choices=','.join(responses))) if result.name != 'choice': say("I can't understand your crazy moon language. Goodbye and good riddance!") hangup() raise Exception("Couldn't understand the user.") # Handle their query, or get a response say(result.value) if result.value == 'instructions': instructions() say("Let's continue.") elif result.value == 'repeat': pass # loop elif result.value == 'start_over': if 'really' == get_answer("If you really want to start over, say really, or say no to keep playing.", ["really", "no"]): raise StartOverException() else: return result.value def play(): """Play a game. Return True if they want to play again, or False if not.""" firstfetch = urllib2.urlopen('http://y.20q.net/anon-en').read() posturl = 'http://y.20q.net' + re.findall('action="(.*?)"', firstfetch)[0] postreq = urllib2.Request(posturl, urllib.urlencode(dict(age='28'))) page = urllib2.urlopen(postreq).read() words = ["animal", "vegetable", "mineral", "something_else"] path_map = dict(zip(words, re.findall('href="(.*?)"', page))) answer = get_answer("Are you thinking of an animal, vegetable, mineral, or something else?", words) chosen_path = path_map[answer] question, path_map = get_question_at_path(chosen_path) while True: answer = get_answer(question, path_map.keys()) try: chosen_path = path_map[answer] question, path_map = get_question_at_path(chosen_path) except GameOverException, e: if e.humanWon: say("You won! Good for you!") else: say("I won! Good for me!") return ('play_again' == get_answer("Say play again to play again, or say goodbye.", ["play_again", "goodbye"])) answer() say("Hello there. Welcome to 20 questions version oh point 2 by Michael Gunlock.") if 'yes' == get_answer("Is this your first time calling?", ["yes", "no"]): say("Michael taught me to play 20 questions with you. Here is how to play:") instructions() say("Let's begin.") else: say("Welcome back. Let's play.") while True: try: if not play(): break except StartOverException, e: pass say("Starting a new game") say("nice playing with you!") hangup()