[docs]defset_secret_code(self)->Optional[str]:valid_guess=ValidCombination(number_of_dots=self.game_state.number_of_dots,number_of_colors=self.game_state.number_of_colors,)whileTrue:secret=getpass("Enter the secret code: ")ifsecret=="?":hint=f""" Enter a {self.game_state.number_of_dots}-digit number with digit ranging from 1 to {self.game_state.number_of_colors}. For example, a 6-digit 4-color code can be 123412, or 1,2,3,4,1,2 Or, you can enter a command: (?) for help (d) to discard the game """print(hint)continueifsecret=="d":print("Game discarded.")return"d"try:valid_guess.validate_value(secret)except(TypeValidationError,InputConversionError)ase:print(e)print("To get more help, enter '?'")exceptRangeError:print(f"Guess must consist of {self.game_state.number_of_dots} integers in range [1, {self.game_state.number_of_colors}]")print("To get more help, enter '?'")else:# Confirm passwordconfirm=getpass("Confirm the secret code: ")ifconfirm!=secret:print("Code does not match. Try again.")continueself.SECRET_CODE=valid_guess.validate_value(secret)return
[docs]defget_feedback(self,guess:tuple)->tuple:ifnothasattr(self,"SECRET_CODE"):raiseNotImplementedError("Secret code not set yet.")returngenerate_feedback(guess,self.SECRET_CODE,self.game_state.number_of_colors)
[docs]classHumanCodeCracker(CodeCracker):_WIN_MESSAGE="Congratulations! You won in {step} steps!"_LOSE_MESSAGE="Sorry, you lost. The secret code was {step}."
[docs]defobtain_guess(self)->Union[tuple,str]:valid_guess=ValidCombination(number_of_dots=self.game_state.number_of_dots,number_of_colors=self.game_state.number_of_colors,)whileTrue:guess=input("Enter your guess: ")ifguess=="?":hint=f""" Enter a {self.game_state.number_of_dots}-digit number with digit ranging from 1 to {self.game_state.number_of_colors}. For example, a 6-digit 4-color code can be 123412, or 1,2,3,4,1,2 Or, you can enter a command: (?) for help (d) to discard the game (q) to save and quit (u) to undo (r) to redo """print(hint)continueifguess=="d":print("Game discarded.")return"d"ifguess=="q":# quitprint("Game saved.")return"q"ifguess=="u":# undoreturn"u"ifguess=="r":# redoreturn"r"try:returnvalid_guess.validate_value(guess)except(TypeValidationError,InputConversionError)ase:print(e)print("To get more help, enter '?'")exceptRangeError:print(f"Guess must consist of {self.game_state.number_of_dots} integers in range [1, {self.game_state.number_of_colors}]")print("To get more help, enter '?'")