#!/usr/bin/env python3
# ANSI Mastermind © 2026 Annie RJ Brion

import os
import random
import re
import sys
import time

# GlobalError is not actually used
GlobalError = 0


def a(*ansi_code: int) -> str:
    return "\x1b[" + ";".join([str(item) for item in ansi_code]) + "m"


def strip_ansi(s: str) -> str:
    ansi_escape = re.compile(r"(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]")
    return ansi_escape.sub("", s)


def indent(amount: int) -> str:
    return " " * amount


def dash(amount: int) -> str:
    return "─" * amount


def dash2(amount: int) -> str:
    return "═" * amount


def erase_line(line: int) -> None:
    abs_pos(1, line, "\x1b[2K", False)


def abs_pos(x: int, y: int, text: str, end: bool) -> None:
    if end:
        print(f"\x1b[{y};{x}H{a(0)}{text}", end="")
    else:
        print(f"\x1b[{y};{x}H{a(0)}{text}")


def get_code(pegs: int, unique: str, digits: int) -> list:
    global GlobalError

    new_code: list[int] = []
    to_range: int = digits + 1
    new_digit: int = 0

    # Generate code of pegs length
    for x in range(pegs):
        if unique == "U":
            # Unique number in range chosen
            unq: bool = False
            while not unq:
                new_digit = random.randrange(1, to_range)
                try:
                    if new_code.index(new_digit) > len(new_code):
                        unq = False
                except Exception as exceptErr:
                    # GlobalError is not actually used
                    GlobalError = exceptErr
                    unq = True
        else:
            # Any number in range chosen
            new_digit = random.randrange(1, to_range)

        new_code.append(new_digit)

    return new_code


def hidden(code: list, char: str, pdu: bool) -> None:
    if pdu:
        temp: int = 5
    else:
        temp = 3
    print(
            f"\x1b[1A{indent(24)}{a(37)}╔{a(37)}{dash2((4 * len(code))+1)}"
            f"╦{dash2(temp+2)}╗{a(39)}",
            end="",
            )
    print(f"\n{indent(17)}{a(31)}Code{a(39)} : {a(37)}║ {a(93)}", end="")
    for x in code:
        print(f"{a(100, 31, 1)} {char} {a(22, 39, 49)} ", end="")

    print(
            f"{a(37)}║ {a(92, 1, 4)}C{a(24, 22)} "
            f"{a(31, 1, 4)}W{a(24, 22, 39)} ",
            end="",
            )

    if pdu:
        print(f"{a(37, 1, 4)}I{a(24, 22, 39)} ", end="")
        temp: int = 5
    else:
        temp = 3

    print(f"{a(37)}║\n{indent(24)}", end="")

    print(
            f"{a(37)}╠{a(37)}{dash2((4 * len(code))+1)}"
            f"╬{dash2(temp+2)}╣{a(39)}",
            end="",
            )


def unhidden(code: list, type: str) -> None:
    if type.upper() == "W":
        print("\n")
        print("\x1b[1F\x1b[0K", end="")
    elif type.upper() == "L":
        print("")
        print(f"\n{indent(24)}{a(100, 34)} You{a(31, 1)} LOSE {a(22, 39, 49)}")

    print(f"\n{indent(17)}{a(31)}Code{a(39)} : {a(93)}", end="")
    for x in code:
        print(f"{a(100, 31, 1, 5)} {x} {a(25, 22, 39, 49)}", end="")


def show_guess(g: list, guess_count: int) -> None:
    print(
            f"\x1b[1F{indent(18)}{a(36)}{
            guess_count:03d}{a(39)} : {a(37)}║ {a(93)}",
            end="",
            )

    for x in g:
        print(f" {a(93, 1)}{x}{a(22, 39)}  ", end="")


def validate(guess: str, pegs: int, digits: int, unique: str) -> bool:
    input_g: str = guess.lower()

    # Check for Hint or Quit
    if input_g == "h" or input_g == "q" or input_g == "i":
        return True

    # Have the correct number if digits been guessed
    elif len(guess) == pegs:
        g1: list[str] = [char for char in guess]
        # Make sure ALL digits are numeric
        for x in g1:
            try:
                x1: int = int(x)
            except Exception as exceptErr:
                error2(
                        f"??? Guess digit {
                        x} not a number ???", 3, 0, exceptErr,
                        )
                return False

            # Check each guess digit is in range
            if int(x1) < 1 or int(x1) > digits:
                error2(f"??? digit {str(x)} out of range (1 to "
                       f"{str(digits)}) ???", 3, 0, 0, )
                return False

        # Is guess code unique
        if len(set(input_g)) != len(input_g) and unique == "U":
            error2(f"??? {guess} is not Unique ???", 2, 0, 0)
            return False

        return True
    elif len(guess) != pegs:
        error2(f"??? Your guess needs {pegs} digits ???", 3, 0, 0)
        return False

    error2("??? Invalid ???", 2, 0, 0)
    return False


def test_1(code: list, guess: list, pegs: int) -> int:
    count: int = 0
    # Find number of correct digits in the right place
    for x in range(0, pegs):
        if code[x] == guess[x]:
            count += 1
    return count


def test_2(code: list, guess: list) -> int:
    count: int = 0
    # Remove number of correct digits in the right place
    for index in range(0, len(code)):
        if code[index] == guess[index]:
            code[index] = 0
            guess[index] = -1

    # Find number of correct digits in the wrong place
    for index in range(0, len(code)):
        if guess[index] == -1:
            continue
        elif guess[index] in code:
            count += 1
            if guess[index] >= 0:
                code[code.index(guess[index])] = 0

    return count


def calc_guesses(pegs: int, digits: int) -> int:
    # Calculate the suggested number of guesses
    goes: int = 0
    if unique == "D":
        goes = (5 * difficulty) + (digits * (pegs) - 1)
        if 9 == digits == pegs:
            goes += digits * 4
    else:
        if digits != pegs:
            goes = (5 * difficulty) + (digits * (pegs - 3))
        else:
            goes = 5 * difficulty
            if 9 == digits == pegs:
                goes += 18
    return goes


def error(text: str, delay: int, pos: int, errorNumber) -> None:
    global GlobalError

    # GlobalError is not actually used
    GlobalError = errorNumber

    if pos != 0:
        abs_pos(25, pos, f"{a(41, 97, 1)} {text} {a(22, 39, 49)}\n", False)
    else:
        print(f"\x1b[1F{indent(25)}{a(41, 97, 1)} {text} {a(22, 39, 49)}\n")

    time.sleep(delay)
    return


def error2(text: str, delay: int, pos: int, errorNumber) -> None:
    global GlobalError

    # GlobalError is not actually used
    GlobalError = errorNumber

    print("\x1b[1F\x1b[2K")
    error(text, delay, pos, GlobalError)
    print("\x1b[2F\x1b[2K\x1b[2F")


def error3(text: str, delay: int, pos: int, errorNumber) -> None:
    global GlobalError

    # GlobalError is not actually used
    GlobalError = errorNumber

    erase_line(pos)
    error(text, delay, pos, GlobalError)
    erase_line(pos)


def display_info(text: str, delay: int, pos: int) -> None:
    erase_line(pos)
    print(f"\x1b[1F{indent(25)}{a(103, 34, 1)} {text} {a(22, 39, 49)}\n")
    time.sleep(delay)
    erase_line(pos)


def clear_screen() -> None:
    if sys.platform.lower().startswith("lin"):
        os.system("clear")
    elif sys.platform.lower().startswith("win"):
        os.system("cls")
    elif sys.platform.lower().startswith("dar"):
        os.system("printf '\\33c\\e[3J'")
    else:
        print("\x1b[2J\x1b[=3h\x1b[?25h\x1b[=7l", end="")


def instructions() -> None:
    print("\x1b[?1049h", end="")
    title()

    line_length = 50

    line = 3
    abs_pos(
            int((line_length - 14) / 2) + 1,
            line,
            f"{a(100, 37)} Instructions {a(39, 49)}",
            False,
            )

    line += 1
    abs_pos(2, line, dash(line_length), True)

    line += 1
    abs_pos(5, line, "The computer creates a code (a number between", False)

    line += 1
    abs_pos(5, line, "3 and 9 digits) and your task is to workout", False)

    line += 1
    abs_pos(5, line, "what the code is, using the clues given for", False)

    line += 1
    abs_pos(5, line, "each guess. If available, you may be allowed", False)

    line += 1
    abs_pos(5, line, "1 or more hints, but you will get a penalty", False)

    line += 1
    abs_pos(5, line, "for using them", False)

    line += 1
    abs_pos(2, line, dash(line_length), True)

    line += 1
    abs_pos(
            4,
            line,
            f"{a(100, 31, 1)} # {a(22, 39, 49)} - Code digits must be unique",
            False,
            )

    line += 1
    abs_pos(
            4,
            line,
            f"{a(100, 31, 1)} * {a(22, 39, 49)} "
            "- Code digits can be duplicates",
            False,
            )

    line += 1
    abs_pos(
            5,
            line,
            f"{a(92, 4, 1)}C{a(22, 24, 39)}  "
            "- Correct digit(s), Correct place",
            False,
            )

    line += 1
    abs_pos(
            5,
            line,
            f"{a(31, 4, 1)}W{a(22, 24, 39)}  "
            "- Correct digit(s), Wrong place",
            False,
            )

    line += 1
    abs_pos(
            5,
            line,
            f"{a(37, 4, 1)}I{a(22, 24, 39)}  "
            "- Incorrect digit(s)",
            False,
            )

    line += 1
    abs_pos(5, line, f"{a(93)}1{a(39)}  "
            "- Your guess", True)

    line += 1
    abs_pos(4, line, f"<{a(33)}1{a(39)}> "
            "- Hint digit", False)

    input(f"\n\n Press Enter for next page : {a(93)}")

    clear_screen()
    title()

    line = 3
    abs_pos(
            int((line_length - 14) / 2) + 1,
            line,
            f"{a(100, 37)} Instructions {a(39, 49)}",
            False,
            )

    line += 1
    abs_pos(2, line, dash(line_length), True)

    line += 1
    abs_pos(
            5,
            line,
            f"{a(1)}H{a(22)}  "
            "- Give a Hint, will use 2 or more guesses",
            False,
            )

    line += 1
    abs_pos(5, line, f"{a(1)}Q{a(22)}  "
            "- Quit and reveal the answer", False)

    line += 1
    abs_pos(5, line, f"{a(1)}I{a(22)}  "
            "- Show these instructions", False)

    line += 1
    abs_pos(2, line, dash(line_length), True)

    input(f"\n\n Press Enter to {a(92)}Continue{a(39)} : {a(93)}")
    print("\x1b[?1049l", end="")


def show_history():
    instructions()
    game_header()
    print("\n")
    count: int = 1
    abs_pos(1, 10, " ", False)
    if len(history) > 0:
        for x in history:
            if x[0:5] == "Hint:":
                hint_value = int(x[-1])
                count += hint_penalty[pegs]
                print("\x1b[2A")
                print(
                        f"{indent(17)}{a(33)}Hint{a(39)} : {a(37)}║ "
                        f"<{a(33)}{hint_value:01d}{a(39)}> "
                        f"{a(41, 93)} Penalty:{a(1)}{hint_penalty[pegs]} "
                        f"{a(22, 39, 49)} {a(37)}║ ░ ░ ░ {a(37)}║"
                        )
                print("")
            else:
                x1 = list(map(int, x))
                show_guess(x1, count)
                t2 = 0
                c1 = code[:]
                t1 = test_1(c1, x1, pegs)
                print(f"║ {a(92, 1)}{t1:01d}{a(39, 22)} ", end="")
                c1 = code[:]
                t2 = test_2(c1, x1)
                print(f"{a(31, 1)}{t2:01d}{a(22, 39)} ", end="")
                if pdu and t1 != pegs:
                    t3 = pegs - t1 - t2
                    print(f"{a(37, 1)}{t3:01d}{a(22, 39)} ", end="")

                count += 1
                print("║\n")

    print("\x1b[3A")


def game_header():
    title()

    if unique == "D":
        level_color: str = f"{a(37)}"  # White
    else:
        level_color = f"{a(36)}"  # Cyan

    line = 3
    abs_pos(
            5,
            line,
            f" Type {a(100,97)} i {a(0)} "
            "in your guess for the instructions",
            True,
            )

    line += 2
    abs_pos(7, line, "  " * (pegs - 3), True)  # Center text

    print(
            f"{a(100, 97)} Level:{level_color}{difficulty:02d}{a(97)} "
            f"Pegs:{a(35)}{pegs} {a(97)}Digits:{a(35)}{digits} {a(97)}"
            f"Guesses:{a(35)}{guesses_left:03d} \n",
            end="",
            )

    if pdu:
        print(
                f"{a(39, 49)}        {a(44, 37)} {a(97)}Penalty :"
                f"{a(36)}{hint_penalty[pegs]} {a(39, 49)}\n"
                )
        hidden(code, "*", pdu)
    else:
        print(f"{a(39, 49)}\n")
        hidden(code, "#", pdu)


def title() -> None:
    clear_screen()
    abs_pos(3, 1, f"{a(44, 30, 1)} ANSI Master Mind {a(23, 39, 49, 22)}", True)
    abs_pos(24, 1, f"{a(46, 30, 1)} v1.14 {a(39, 49, 22)}", True)
    abs_pos(34, 1, f"{a(105, 30, 3, 1)} by Annie RJ Brion {a(23, 39, 49, 22)}",
            False)


if __name__ == "__main__":
    unique_default: str = "U"
    pegs_default: int = 5
    digits_default: int = 5
    guesses_default: int = 0
    changed: bool = False

    title()

    inst: str = ""
    # Instructions? (Y/N)
    while inst != "y" and inst != "n":
        inst = (
                input(
                    f"\n Instructions? ({a(35)}Y {a(39)}or {a(35)}N{a(39)}) "
                    f"[{a(36)}n{a(39)}] : {a(93)}"
                    ).lower()
                or "n"
                )
        if inst != "y" and inst != "n":
            error2("??? Y or N ???", 2, 0, 0)

    if inst == "y":
        instructions()

    # Play loop ==============================
    while True:
        # Options ----------

        title()

        line = 3

        abs_pos(25, line, f"{a(100, 97)} Options {a(39, 49)}", False)

        # Start here :) ===================================================
        win: bool = False
        pegs: int = 3
        guesses = [5, 12, 15, 20, 25, 30, 40]
        hint_num = [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3]
        hint_penalty = [0, 0, 0, 2, 2, 3, 3, 4, 4, 5]
        code = []
        history = []
        hint = []
        guess_count: int = 1
        unique: str = ""

        # Show all options up front
        abs_pos(
                2,
                5,
                f"{a(35, 1)}U{a(22, 39)}nique digits or Allow "
                f"{a(35, 1)}D{a(22, 39)}uplicates ({a(35)}U {a(39)}or "
                f"{a(35)}D{a(39)}) [{a(36)}{unique_default}{a(39)}] : {a(93)}",
                False,
                )

        abs_pos(
                2,
                7,
                f"Number of digits within the code ({a(35)}3 - 9{a(39)}) "
                f"[{a(36)}{pegs_default}{a(39)}] : {a(93)}",
                False,
                )

        abs_pos(
                2,
                9,
                f"How many different numbers per digit "
                f"({a(35)}? - ?{a(39)}) [{a(36)}?{a(39)}]"
                f": {a(93)}",
                False,
                )

        if guesses_default != 0:
            default: str = f"{guesses_default:03d}"
        else:
            default = "???"

        abs_pos(
                2,
                11,
                f"Number of guesses ({a(35)}0 {a(90)}Reset {a(39)}or "
                f"{a(35)}1 - 300{a(39)}) {a(39)}[{a(36)}{default}{a(39)}]"
                f": {a(93)}",
                False,
                )

        line: int = 13
        abs_pos(2, line, dash(52), True)

        line += 1
        hash = f"[{a(36)}#{a(39)}]"
        abs_pos(
                2,
                line,
                f"{hash} = Default value if you press Enter with no value",
                False,
                )

        line += 1
        abs_pos(2, line, dash(52), False)

        line += 1
        abs_pos(
                2,
                line,
                f"{a(1)}Note{a(22)}: Enter {a(35, 1)}0{a(22, 39)} for Option "
                f"{a(93)}4{a(39)} to {a(90)}reset{a(39)} its default",
                False,
                )

        line += 1
        abs_pos(
                8,
                line,
                f"value, changing options {a(93)}1{a(39)}, {a(93)}2{a(39)} "
                f"or {a(93)}3{a(39)} will also",
                False,
                )

        line += 1
        abs_pos(8, line, "recalculate its value", False)

        line += 1
        abs_pos(2, line, dash(52), False)

        # Unique or Dups?
        while True:
            abs_pos(2, 5, "", True)
            input_text: str = (
                    f"{a(35, 1)}U{a(22, 39)}nique digits or Allow {a(35, 1)}"
                    f"D{a(22, 39)}uplicates ({a(35)}U {a(39)}or {a(35)}"
                    f"D{a(39)})"
                    f"[{a(36)}{unique_default}{a(39)}] : {a(93)}"
                    )

            unique = input(input_text).upper() or unique_default

            if unique == "U" or unique == "D":
                pos = len(strip_ansi(input_text)) + 2
                abs_pos(pos, 5, f"{a(93)}{unique}", True)
                break
            else:
                error3("??? U or D ???", 2, 5, 0)

        if unique_default != unique:
            changed = True

        unique_default = unique
        pegs = 0

        # Number of pegs?
        # while pegs < 3 or pegs > 9:
        while True:
            abs_pos(2, 7, "", True)
            input_text = (
                    f"Number of digits within the code "
                    f"({a(35)}3 - 9{a(39)}) [{a(36)}{pegs_default}{a(39)}]"
                    f": {a(93)}"
                    )

            p = input(input_text) or pegs_default

            try:
                pegs = int(p)
            except Exception as exceptErr:
                error3("??? Enter a number ???", 2, 7, exceptErr)
                continue

            if 3 <= pegs <= 9:
                pos = len(strip_ansi(input_text)) + 2
                abs_pos(pos, 7, f"{a(93)}{str(pegs)}", True)
                break
            else:
                error3("??? 3 to 9 ???", 2, 7, 0)

        if pegs_default != pegs:
            changed = True

        pegs_default = pegs

        to_range: int = 9

        if unique == "U":
            from_range: int = pegs
        else:
            from_range = 3

        hints: int = hint_num[pegs]

        if unique == "U" and pegs == 9:
            digits = 9
            abs_pos(56, 9, str(digits), True)
        else:
            digits = 0

            # Number of digits?
            while True:
                abs_pos(2, 9, "", True)

                input_text = (
                        f"How many different numbers per digit "
                        f"({a(35)}{from_range} - {to_range}{a(39)}) "
                        f"[{a(36)}{digits_default}{a(39)}] : {a(93)}"
                        )

                d = input(input_text) or digits_default

                try:
                    digits: int = int(d)
                except Exception as exceptErr:
                    error3("??? Enter a number ???", 2, 9, exceptErr)
                    continue

                if from_range <= digits <= to_range:
                    abs_pos(
                            len(strip_ansi(input_text)) + 2,
                            9,
                            f"{a(93)}{str(digits)}",
                            True,
                            )  # 56
                    break
                else:
                    error3(f"??? {from_range} to {to_range} ???", 2, 9, 0)

            print("")

        if digits_default != digits:
            changed = True

        digits_default = digits

        # Calculate difficulty and number of guesses, 13 levels
        difficulty: int = (pegs - 2) + (digits - 3)

        # Has Pegs, Digits or Unique/Dups changed?
        if changed:
            changed = False
            guesses_default = 0

        if guesses_default == 0:
            input_g = calc_guesses(pegs, digits)
        else:
            input_g = guesses_default

        guesses_left: int = 0

        # Number of guesses?
        while True:
            abs_pos(2, 11, "", True)
            input_text = (
                    f"Number of guesses ({a(35)}0 {a(90)}Reset "
                    f"{a(39)}or {a(35)}1 - 300{a(39)}) {a(39)}"
                    f"[{a(36)}{input_g:03d}{a(39)}] : {a(93)}"
                    )

            input_l = input(input_text) or input_g

            try:
                guesses_left = int(input_l)
            except Exception as exceptErr:
                error3("??? Enter a number ???", 2, 11, exceptErr)
                continue

            if input_l == "0":
                guesses_default = calc_guesses(pegs, digits)
                imput_g = guesses_default
                display_info(f"Default reset to {input_g:03d}", 2, 11)
            else:
                if 1 <= guesses_left <= 300:
                    break
                else:
                    error3("??? 1 to 300 ???", 2, 11, 0)

        if guesses_default != guesses_left:
            guesses_default = guesses_left

        if unique == "U" and pegs == digits:
            hints = -1

        if unique == "D" or pegs != digits:
            pdu = True
        else:
            pdu = False

        code = get_code(pegs, unique, digits)
        hint = code[:]  # Copy code to hint

        game_header()

        correct: int = 0

        # Main game loop ==============================
        while guesses_left > 0 and not win:
            aa: str = ""
            bb: str = ""
            if guesses_left == 1:
                aa = a(5)  # Blink On
                bb = a(25)  # Blink Off
            input_g = []
            guess: str = ""
            valid: bool = False
            while not valid:
                input_g = []
                if pdu:
                    guess = input(
                            f"\n  {a(33)}Hints{a(39)} {a(36, 1)}{hints:02d}"
                            f"{a(22, 39)},"
                            f"Guess {a(36)}{aa}{guess_count:03d}{bb}{a(39)}"
                            f": {a(37)}║ {a(93)}"
                            )
                else:
                    guess = input(
                            f"\n{indent(12)}Guess {a(36)}{aa}{guess_count:03d}"
                            f"{bb}{a(39)} : {a(37)}║ {a(93)}"
                            )

                input_g = [char for char in guess]

                valid = validate(guess, pegs, digits, unique)

            if guess.lower() == "q":
                win = True
                print("\x1b[1F\x1b[2K\x1b[1F")  # Erase line on screen
                if guess_count != 1:
                    print("")
                if pdu:
                    temp: int = 5
                else:
                    temp = 3
                print(
                        f"\x1b[1A{indent(24)}{a(37)}"
                        f"╚{dash2((4 * len(code))+1)}"
                        f"╩{dash2(temp+2)}╝{a(39)}",
                        end="",
                        )
                print(
                        f"\n\n{indent(24)}{a(100, 34)} You {a(91, 1)}"
                        f"QUIT {a(22, 39, 49)}"
                        )
                unhidden(code, "Q")
            elif (
                    guess.lower() == "h"
                    and pdu
                    and guesses_left > hint_penalty[pegs]
                    and hints > 0
                    ):
                hint_code = random.randrange(0, len(hint))
                hint_num = hint[hint_code]
                history.insert(guess_count, f"Hint:{str(hint_num)}")
                hints -= 1
                guesses_left -= hint_penalty[pegs]
                guess_count += hint_penalty[pegs]
                print(
                        f"\x1b[1F{indent(17)}{a(33)}Hint{a(39)} : {a(37)}"
                        f"║ {a(93)}<{a(33)}{hint_num:01d}{a(39)}> {a(41, 93)} "
                        f"HP :{a(1)}{hint_penalty[pegs]} {a(22, 39, 49)} "
                        f"{indent((pegs - 3) * 4)}{a(37)}║ ░ ░ ░ {a(37)}║",
                        end="",
                        )
            else:
                if guess.lower() != "h":
                    if guess.lower() == "i":
                        show_history()
                    else:
                        history.insert(guess_count, guess)
                        input_g = list(map(int, input_g))

                        show_guess(input_g, guess_count)
                        guess_count += 1
                        t2 = 0
                        t1 = test_1(code, input_g, pegs)
                        print(
                                f"{a(37)}║ {a(92, 1)}{
                                t1:01d}{a(39, 22)} ",
                                end="",
                                )

                        if t1 == pegs:
                            win = True
                            if guesses_left == 2:
                                s = ""
                            else:
                                s = "es"
                            print(f"{a(31, 1)}0{a(22, 39)} ", end="")
                            if pdu:
                                print(f"{a(37, 1)}0{a(22, 39)} ", end="")
                            if pdu:
                                temp: int = 5
                            else:
                                temp = 3
                            print(f"{a(37)}║\n")
                            print(
                                    f"\x1b[1A{indent(24)}{a(37)}"
                                    f"╚{dash2((4 * len(code))+1)}"
                                    f"╩{dash2(temp+2)}╝{a(39)}",
                                    end="",
                                    )
                            print(
                                    f"\n\n{indent(24)}{a(100, 34)} "
                                    f"You {a(32, 1, 5)}"
                                    f"WIN {a(25, 22, 39, 49)}",
                                    end="",
                                    )
                            unhidden(code, "W")
                        else:
                            win = False
                            c = code.copy()
                            t2: int = test_2(c, input_g)
                            print(f"{a(31, 1)}{t2:01d}{a(22, 39)} ", end="")
                            if pdu and t1 != pegs:
                                t3: int = pegs - t1 - t2
                                print(
                                        f"{a(37, 1)}{t3:01d}{
                                        a(22, 39)} ",
                                        end="",
                                        )
                            print(f"{a(37)}║", end="")

                    guesses_left -= 1
                else:
                    if hints == -1:
                        error("No hints available", 2, 0, 0)
                    elif hints == 0:
                        error("No more hints left", 2, 0, 0)
                    else:
                        error("Not enough guesses left", 2, 0, 0)

                    print("\x1b[1F\x1b[0K\x1b[1F\x1b[2K\x1b[2F")

        if not win:
            unhidden(code, "L")

        print("")

        another: str = ""
        # Play again? (Y/N)
        while another != "y" and another != "n":
            another = (
                    input(
                        f"\n Play again ({a(35)}Y {a(39)}or "
                        f"{a(35)}N{a(39)}) [{a(36)}y{a(39)}] : {a(93)}"
                        ).lower()
                    or "y"
                    )
            if another != "y" and another != "n":
                error2("??? Y or N ???", 2, 0, 0)

        if another == "n":
            quit()
