#Higher Lower game

import random
import math

#Number Checking Function goes here

def integer_check(question, low=None, high=None):

    situation = ""

    if low is not None and high is not None:
        situation = "both"
    elif low is not None and high is None:
        situation = "low only"

    while True:

        try:
            response = int(input(question))

            if situation == "both":
                if response < low or response > high:
                    print("Please enter a number between {} and {}".format(low, high))
                    continue

            elif situation == "low only":
                if response < low:
                    print("Please enter a number that is more than (or equal to) {}".format(low))
                    continue

            return response

        except ValueError:
            print("Please enter an integer. You still have {} guesses left.".format(guesses_left))
            continue

def game_instructions():
    statement_generator("How to play", "*")
    print("The goal of the Higher Lower game is to guess")
    print("the secret number generated by the computer.")
    print("First you will be asked to enter your ")
    print("low number and then you will be asked to enter your high number")
    print("the secret number will be generated between the two numbers.")
    print("The two numbers are the maximum and minimum range for the secret number you can guess.")
    print("The maximum amount of guesses you are allowed to have depends on the numbers you are guessing between.")
    print("When you try to guess the secret number")
    print("you will be told if you guessed lower or higher than the secret number.")
    print("Good Luck and hopefully you guess the secret number.")
    print("")
    return""

#Played before function, output depends on what the user answers
#If the user answers yes, program continues ask user how many
#Rounds they want to play or if they want to play continuous mode
#If user answers no, game information will display
#If user answers anything other than yes/no, <error> please answer yes/no will appear
def played_before(question):
    valid = False
    while not valid:
        response = input(question).lower()
#If user response is either 'yes' or 'y' the response will be outputed as yes.
        if response == "yes" or response == "y":
            response = "yes"
            return response
#If user response is either 'no' or 'n' the response will be outputed as no.
        elif response == "no" or response == "n":
            response = "no"
            return response
#If user response is anything other than yes or no,user will be asked to answer yes or no.
        else:
            print("<error> please answer yes/no")


#Statement generator
#Decorates the statements in the Lucky Unicorn game
def statement_generator(statement, decoration):

    sides = decoration * 3

    statement = "{} {} {}".format(sides, statement, sides)
    top_bottom = decoration * len(statement)

    print(top_bottom)
    print(statement)
    print(top_bottom)

    return ""

#Main Routine

#Welcomes User to the Higher Lower Game
#Statement is decorated
statement_generator("Welcome to the Higher Lower Game", "*")

#Calls ask user if they have played before funtion and game information function
#Played before statement is decorated
#If the user answers yes, program continues to ask the user how much they want to play with
#If user answers no, game information will display
#If user answers anything other than yes/no, <error> please answer yes/no will appear
print()
statement_generator("Played before", "?")
show_played_before = played_before("Have you played this game before (yes/no)?")
print()

if show_played_before == "no":
    print()
    game_instructions()

game_loop = ""
while game_loop == "":

    statement_generator("Lets get Guessing", "*")

    lowest = integer_check("What is your Low Number: ")
    highest = integer_check("What is your High Number: ", lowest + 1)

    rounds = integer_check("How many rounds do you want to play?", 1)
    game_summary = []

    number_range = highest - lowest + 1
    max_raw = math.log2(number_range)
    max_upped = math.ceil(max_raw)
    max_guesses = max_upped + 1
    print("You will have {} guesses as the maximum amount of guesses you have".format(max_guesses))

    guesses_allowed = max_guesses

    rounds_played = 0
    number_won = 0

    if game_loop == "xxx":
        break

    while rounds_played < rounds:

        if rounds_played >= 1:
            game_loop = input("Press <Enter> if you wish to continue the game, if you wish to quit type 'xxx'.")

        secret = random.randint(lowest, highest)

        print(secret)

        guess = ""
        already_guessed = []
        guesses_left = guesses_allowed

        round_start = statement_generator("Round {} of {}".format(rounds_played + 1, rounds), "*")

        while guess != secret and guesses_left >= 1:

            guess = integer_check("What is your Guess: ", lowest, highest)

            #Check that the guess is not a duplicate
            if guess in already_guessed:
                print("You have already guessed that number! Please try again. "
                      "You *still* have {} guesses left".format(guesses_left))
                continue

            guesses_left -= 1
            already_guessed.append(guess)

            if guesses_left >= 1:

                if guess < secret:
                    statement_generator("Too Low", "!")
                    print("Too low, try a higher number. Guesses left {}.".format(guesses_left))

                elif guess > secret:
                    statement_generator("Too High", "!")
                    print("Too high, try a lower number. Guesses left {}.".format(guesses_left))

            else:
                if guess < secret:
                    statement_generator("Too Low", "!")
                    print("Too low!")
                elif guess > secret:
                    statement_generator("Too High", "!")
                    print("Too high!")

        if guess == secret:
            if guesses_left == guesses_allowed - 1:
                statement_generator("Amazing. You have got it", "*")
                number_won += 1
            else:
                statement_generator("Well Done. You have got it", "*")
                number_won += 1

        else:
            print("Sorry. You have lost you have run out of guesses.")
            print("The secret number was {}".format(secret))

        rounds_played += 1
