#### Number guessing "can she guess" - make Alexa guess your number import logging from ask_sdk.standard import StandardSkillBuilder #from ask_sdk_core.skill_builder import SkillBuilder from ask_sdk_core.utils import is_request_type, is_intent_name from ask_sdk_core.handler_input import HandlerInput from ask_sdk_model import Response from ask_sdk_model.ui import SimpleCard import time # for delayed responses - probably don't work #import urllib #import urllib.request SKILL_NAME = 'guess the number' #sb = StandardSkillBuilder(table_name="number_guessing_game", auto_create_table=True) sb = StandardSkillBuilder() logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) ############################# Game Logic ################################# class Game: def __init__(self,min0,max0): self.min = min0 self.max = max0 self.min0 = min0 # safe originals for reset self.max0 = max0 self.lastguess = self.min-1 #first guess will assume num is higher self.guesscount = 0 # counts guesses, also indicates game state self.terminated = False # state variable # dispatch vector of three functions defined below: self.dispatch = [self.correct, self.higher, self.lower] #init def reset(self): self.min,self.max = self.min0,self.max0 self.lastguess = self.min-1 self.guesscount = 0 self.terminated = False #reset def makeguess(self): self.guesscount += 1 self.lastguess = (self.min+self.max)//2 return self.lastguess # makeguess # functions that respond, depending on higher or lower or correct def higher(self): # called if response is number should be higher self.min = self.lastguess + 1 # must set before makeguess guess = self.makeguess() return "Is your number "+str(guess)+"? Or is it higher or lower" #higher def lower(self): self.max = self.lastguess - 1 guess = self.makeguess() return "Is your number "+str(guess)+"? Or is it higher or lower" #lower def correct(self): self.terminated = True return "I guessed your number in "+str(self.guesscount)+" attempts because professor Liang taught me how to do binary search." #correct # make next guess based on response: # human_answer is 0 for equals, 1 for higher, 2 for lower, used to # index vector of options (better than if-else) def nextguess(self,human_answer): response = "" # response string that will be returned #if self.min>self.max or (self.min==self.max and human_answer!=0): if self.guesscount>6: self.terminated = True return "You cheated! Skynet was informed of this incident. Terminators are on their way. Kiss your ass goodbye!" if self.guesscount>5: response += "I hope you're not misleading me, I can tell if you're lying. " response += self.dispatch[human_answer]() # call a function return response # nextguess # class Game GG = Game(1,100) # global instance of guessing game ### ##############################Alexa Handlers################################## ### These decorators generate class code. @sb.request_handler(can_handle_func=is_request_type("LaunchRequest")) def launch_request_handler(handler_input): GG.reset() # just in case speech_text = "Think of a number between "+str(GG.min)+" and "+str(GG.max)+" and I will try to guess what it is. Ready to begin?" reprompt = "Ready to begin?" handler_input.response_builder.speak(speech_text).ask(reprompt) return handler_input.response_builder.response @sb.request_handler(can_handle_func=is_intent_name("AMAZON.HelpIntent")) def help_intent_handler(handler_input): """Handler for Help Intent.""" # type: (HandlerInput) -> Response speech_text = "You can say correct, higher, or lower." reprompt = "What's your answer?" handler_input.response_builder.speak(speech_text).ask(reprompt) return handler_input.response_builder.response @sb.request_handler( can_handle_func=lambda input: is_intent_name("AMAZON.CancelIntent")(input) or is_intent_name("AMAZON.StopIntent")(input)) def cancel_and_stop_intent_handler(handler_input): speech_text = "Loser. Goodbye." handler_input.response_builder.speak(speech_text).set_should_end_session(True) return handler_input.response_builder.response @sb.request_handler(can_handle_func=is_request_type("SessionEndedRequest")) def session_ended_request_handler(handler_input): """Handler for Session End.""" # type: (HandlerInput) -> Response logger.info( "Session ended with reason: {}".format( handler_input.request_envelope.request.reason)) return handler_input.response_builder.response #### main intent handlers @sb.request_handler(can_handle_func=lambda x:(is_intent_name("AMAZON.YesIntent")(x) and GG.guesscount==0)) def yes_handler(handler_input): speech = GG.nextguess(1) # initially call higher function handler_input.response_builder.speak(speech).ask(speech).set_should_end_session(False) return handler_input.response_builder.response """ The above decorator generates code equivalent to: class YesHandler(AbstractRequestHandler): def can_handle(self,x): return (is_intent_name("AMAZON.YesIntent")(x) and GG.guesscount==0) def handle(self,handler_input): speech = GG.nextguess(1) # initially call higher function handler_input.response_builder.speak(speech).ask(speech).set_should_end_session(False) return handler_input.response_builder.response """ @sb.request_handler(can_handle_func=is_intent_name("AMAZON.NoIntent")) def no_handler(handler_input): speech = "I won't take no for an answer!" handler_input.response_builder.speak(speech).ask(speech).set_should_end_session(False) return handler_input.response_builder.response @sb.request_handler(can_handle_func=lambda input: is_intent_name("HigherIntent")(input) and GG.guesscount>0) def higher_handler(handler_input): res = GG.nextguess(1) handler_input.response_builder.speak(res).ask(res).set_should_end_session(GG.terminated) return handler_input.response_builder.response @sb.request_handler(can_handle_func=lambda input: is_intent_name("LowerIntent")(input) and GG.guesscount>0) def lower_handler(handler_input): res = GG.nextguess(2) handler_input.response_builder.speak(res).ask(res).set_should_end_session(GG.terminated) return handler_input.response_builder.response @sb.request_handler(can_handle_func=lambda x: GG.guesscount>0 and (is_intent_name("CorrectIntent")(x) or is_intent_name("AMAZON.YesIntent")(x))) def correct_handler(handler_input): res = GG.nextguess(0) handler_input.response_builder.speak(res).set_should_end_session(True) return handler_input.response_builder.response @sb.request_handler(can_handle_func=lambda input: is_intent_name("AMAZON.FallbackIntent")(input)) def fallback_handler(handler_input): """AMAZON.FallbackIntent is only available in en-US locale. This handler will not be triggered except in that locale, so it is safe to deploy on any locale. """ # type: (HandlerInput) -> Response #attr = handler_input.attributes_manager.session_attributes speech_text = "You can say correct, higher, or lower" handler_input.response_builder.speak(speech_text).ask("What's your response") return handler_input.response_builder.response @sb.exception_handler(can_handle_func=lambda i, e: True) def all_exception_handler(handler_input, exception): """Catch all exception handler, log exception and respond with custom message. """ # type: (HandlerInput, Exception) -> Response logger.error(exception, exc_info=True) speech = "I can't understand. Please say it again!!" handler_input.response_builder.speak(speech).ask(speech) return handler_input.response_builder.response @sb.global_response_interceptor() def log_response(handler_input, response): """Response logger.""" # type: (HandlerInput, Response) -> None logger.info("Response: {}".format(response)) handler = sb.lambda_handler()