mastermind2.py

Created by cent20

Created on December 27, 2022

9.64 KB

legit en version beta


from kandinsky import draw_string as txt, fill_rect as rec
from ion import keydown
from random import choice

# Mastermind 0.0 NumWorks, 25.12.2022
# Par Ilyas RAHMOUN & Vincent ROBERT
# https://nsi.xyz/mastermind <3

DARK_C = (42,)*3
LIGHT_C = (142,)*3
BRIGHT_C = (242,)*3
GAME_C = (148, 113, 222)
VOID_C = (255,)*3

COLORS = ((255, 89, 94), (255, 202, 58), (25, 130, 196), (138, 201, 38), (255, 146, 76), (142,)*3, (66, 103, 172),
          (82, 166, 117))
CURSOR = COLOR = LVL = 0

SCOREBOARD = [["Score", 0], ["Max", 0], ["Legit", 0], [None, None]]

GAME_CONFIG = (["Colors", 8], ["Code", 4], ["Dupli", 1], ["Help", 0])
CONFIG_LIMITS = ((5, 8), (3, 6), [0, 1], (0, 1))
GAME = COMBIN = []


def gui(e=0):
    rec(0, 200, 320, 22, GAME_C)
    txt("Code by nsi.xyz/mastermind", 33, 202, BRIGHT_C, GAME_C)
    for i in range(len(GAME_CONFIG)):
        txt(GAME_CONFIG[i][0], 50 - 5*len(GAME_CONFIG[i][0]), 200//(len(GAME_CONFIG) + 1)*(i + 1) - 18, LIGHT_C)
        rec((101 - 18)//2, 200//(len(GAME_CONFIG) + 1)*(i + 1), 18, 18, LIGHT_C)
        txt(str(GAME_CONFIG[i][1]), (101 - 18)//2 + 4, 200//(len(GAME_CONFIG) + 1)*(i + 1), BRIGHT_C, LIGHT_C)
    arrow(255,165,0,LIGHT_C)
    arrow(260,165,1,LIGHT_C)
    arrow(260,165,2,LIGHT_C)
    arrow(260,165,3,LIGHT_C)
    txt("OK",257,165,LIGHT_C)
    if not e:
        plateau()
        config_displayer(0, 1)
    arrows_displayer(0, 1*(e != 0))


def plateau(code=GAME_CONFIG[1][1]):
    rec(101, 1, 118, 198, VOID_C)
    for i in range(10):
        for j in range(code):
            set_cell((j, i), BRIGHT_C)


def config_displayer(conf, state):
    c = GAME_C if state else LIGHT_C
    txt(GAME_CONFIG[conf][0], 50 - 5*len(GAME_CONFIG[conf][0]), 200//(len(GAME_CONFIG) + 1)*(conf + 1) - 18, c)
    rec((101 - 18) // 2, 200 // (len(GAME_CONFIG) + 1) * (conf + 1), 18, 18, c)
    txt(str(GAME_CONFIG[conf][1]), (101 - 18) // 2 + 4, 200 // (len(GAME_CONFIG) + 1) * (conf + 1), BRIGHT_C, c)


def config_updater(conf, incr, f=0):
    global GAME_CONFIG
    c = LIGHT_C if f else GAME_C
    GAME_CONFIG[conf][1] += incr
    txt(str(GAME_CONFIG[conf][1]), (101 - 18)//2 + 4, 200//(len(GAME_CONFIG) + 1)*(conf + 1), BRIGHT_C, c)
    arrows_displayer(conf)
    scoreboard_init()  #Branchement VR
    if conf == 1:
        plateau(GAME_CONFIG[conf][1])


def arrows_displayer(conf, leave=0):
    if leave:
        for i in range(len(GAME_CONFIG)):
            for j in range(2):
                rec((101 - 18)//2 + (25 if j else -17), 200//(len(GAME_CONFIG) + 1)*(i + 1) + 3, 10, 10, VOID_C)
    else:
        if GAME_CONFIG[conf][1] > CONFIG_LIMITS[conf][0]:
            txt("<", (101 - 18)//2 - 17, 200//(len(GAME_CONFIG) + 1)*(conf + 1), GAME_C)
        else:
            txt("<", (101 - 18)//2 - 17, 200//(len(GAME_CONFIG) + 1)*(conf + 1), VOID_C)
        if GAME_CONFIG[conf][1] < CONFIG_LIMITS[conf][1]:
            txt(">", (101 - 18)//2 + 25, 200//(len(GAME_CONFIG) + 1)*(conf + 1), GAME_C)
        else:
            txt(">", (101 - 18)//2 + 25, 200//(len(GAME_CONFIG) + 1)*(conf + 1), VOID_C)


def arrow(x, y, d=0, c=GAME_C):
    for i in range(6):
        rec(x + (23 + i) * (d == 3) - (5 + i) * (d == 0) + (3 + i) * (d % 3 != 0),
            y + (3 + i) * (d % 3 == 0) - (7 + i) * (d == 1) + (22 + i) * (d == 2), 1, 2, c)
        rec(x + (23 + i) * (d == 3) - (5 + i) * (d == 0) + (13 - i) * (d % 3 != 0),
            y + (13 - i) * (d % 3 == 0) - (7 + i) * (d == 1) + (22 + i) * (d == 2), 1, 2, c)


def config_manager(conf, i):
    config_displayer(conf, 0)
    arrows_displayer(conf, 1)
    conf += i
    config_displayer(conf, 1)
    arrows_displayer(conf)


def config_dupli_manager(conf):
    if GAME_CONFIG[1][1] > GAME_CONFIG[0][1]:
        GAME_CONFIG[2][1] = 1
        CONFIG_LIMITS[2][0] = 1
        config_updater(2, 0, 1*(conf != 2))
    else:
        CONFIG_LIMITS[2][0] = 0


def menu():
    global GAME
    config = 0
    last_key = None
    while not (keydown(4) or keydown(52)):
        if keydown(1) and config > 0 and last_key != 1:
            config_manager(config, -1)
            config -= 1
            last_key = 1
        if keydown(2) and config < len(GAME_CONFIG) - 1 and last_key != 2:
            config_manager(config, 1)
            config += 1
            last_key = 2
        if keydown(0) and GAME_CONFIG[config][1] > CONFIG_LIMITS[config][0] and last_key != 0:
            config_updater(config, -1)
            last_key = 0
        if keydown(3) and GAME_CONFIG[config][1] < CONFIG_LIMITS[config][1] and last_key != 3:
            config_updater(config, 1)
            last_key = 3
        config_dupli_manager(config)
        if not (keydown(0) or keydown(1) or keydown(2) or keydown(3)):
            last_key = None
    gui(1)
    GAME = [["" for _ in range(GAME_CONFIG[1][1])] for _ in range(10)]
    indicators_manager(1)


def d_p(p_x=0, p_y=0):
    return (320 - (GAME_CONFIG[1][1]*20 - 2))//2 + 20*p_x, 181 - 20*p_y


def set_cell(pos, color):
    rec(d_p(pos[0])[0], d_p(p_y=pos[1])[1], 18, 18, color)


def indicators_manager(static=0, dyn_del=0, dyn_place=0):
    if static:
        arrow(d_p(-1)[0] + 16, d_p(p_y=LVL)[1], 0)
        arrow(d_p(GAME_CONFIG[1][1])[0] - 16, d_p(p_y=LVL)[1], 3)
        arrow(d_p(CURSOR)[0] + 1, d_p(p_y=LVL)[1] + 17, 1, BRIGHT_C)
        arrow(d_p(CURSOR)[0] + 1, d_p(p_y=LVL + 1)[1] + 17, 1)
    if dyn_del:
        for i in range(GAME_CONFIG[1][1]):
            arrow(d_p(i)[0] + 1, d_p(p_y=LVL + 1)[1] + 17, 1, BRIGHT_C)
    if dyn_place:
        arrow(d_p(CURSOR)[0] + 1, d_p(p_y=LVL + 1)[1] + 17, 1)


def generate_combination():
    suit = []
    while not suit or (len(set(suit)) != len(suit) and GAME_CONFIG[2][1] != 1):
        suit = [choice([i for i in range(GAME_CONFIG[0][1])]) for _ in range(GAME_CONFIG[1][1])]
    return suit


def check_line(line, secret):
    good = sum([line[i] == secret[i] for i in range(len(line))])
    bad = sum([line[i] in secret for i in range(len(line))])-good
    return bad, good

def check_manager(lvl):
    bad, good = check_line(GAME[lvl], COMBIN)
    txt(str(bad), d_p(-1)[0] + 4, d_p(p_y=lvl)[1], "red", VOID_C)
    txt(str(good), d_p(GAME_CONFIG[1][1])[0] + 4, d_p(p_y=lvl)[1], "green", VOID_C)
    scoreboard_manager(bad, good) # VR

def debug():
    txt("".join(str(i) for i in COMBIN), 250, 180, (0, 0, 0))


def scoreboard_init():
    factorielle = lambda n: n * factorielle(n-1) if n != 0 else 1
    if GAME_CONFIG[2][1]==0: # arrangement si pas de dupli
        combi =  int(factorielle(GAME_CONFIG[0][1]) / factorielle(GAME_CONFIG[0][1]-GAME_CONFIG[1][1]))
    else:
        combi = GAME_CONFIG[0][1] ** GAME_CONFIG[1][1]
    SCOREBOARD[0][1] = 100000
    SCOREBOARD[1][1] = SCOREBOARD[2][1] = combi
    scoreboard()


def scoreboard(): # Il y a des truc à sortir d'ici
    # Données dans GAME_CONFIG[i][1]
    # GAME_CONFIG = (["Colors", 8], ["Code", 4], ["Dupli", 1], ["Help", 0])
    # SCOREBOARD = [["Score", 0], ["Max", 0], ["Legit", 0], [None, None]]    
    rec(220,0,100,150,(255,255,255))
    for i in range(3): # TODO désactiver legit si aide = 0 
        txt(SCOREBOARD[i][0], 269 - 5*len(SCOREBOARD[i][0]), 200//(len(SCOREBOARD) + 1)*(i + 1) - 18, DARK_C)
        txt("         ",220, 200//(len(SCOREBOARD) + 1) * (i + 1)) # Nettoie les lignes
        txt(str(SCOREBOARD[i][1]), 269 - 5*len(str(SCOREBOARD[i][1])), 200//(len(SCOREBOARD) + 1) * (i + 1), LIGHT_C)


def scoreboard_manager(b,g):
    global LVL
    SCOREBOARD[0][1] = int(SCOREBOARD[0][1] * (0.80+0.2*g/GAME_CONFIG[1][1]+0.1*b/GAME_CONFIG[1][1]))
    if g == GAME_CONFIG[1][1]:  #WIN
        rec(230,152,70,42,GAME_C)
        txt("WIN", 250, 162, BRIGHT_C, GAME_C)
    elif LVL == 9: #10 à vérifier !
        rec(230,152,70,42,GAME_C)
        txt("LOOSE", 242, 162, BRIGHT_C, GAME_C)
    scoreboard()

def legit_eval():
    global LVL    
    ok = 0
    for _ in range(1000):
        test = generate_combination()
        for i in range(LVL+1):
            #print(test,GAME[i],check_line(test),check_line(GAME[i] ))
            if check_line(GAME[i], COMBIN) != check_line(GAME[i], test):
                break
            if i==LVL:
                ok +=1
    result = max(0.1, round(ok/10,1))
    SCOREBOARD[2][1] = str(result)+"%"
    txt(str(ok),240,0)
    check_manager(LVL)
            
        


def mastermind():
    global CURSOR, COLOR, LVL, GAME, COMBIN
    last_key = None
    gui()
    scoreboard_init()
    menu()
    COMBIN = generate_combination() # VR
    while not keydown(5):
        if keydown(0) and last_key != 0:
            indicators_manager(dyn_del=1)
            CURSOR -= 1
            CURSOR = CURSOR % GAME_CONFIG[1][1]
            indicators_manager(dyn_place=1)
            last_key = 0
        if keydown(3) and last_key != 3:
            indicators_manager(dyn_del=1)
            CURSOR += 1
            CURSOR = CURSOR % GAME_CONFIG[1][1]
            indicators_manager(dyn_place=1)
            last_key = 3
        if keydown(1) and last_key != 1:
            COLOR = (GAME[LVL - 1][CURSOR] - 1) % GAME_CONFIG[0][1] if GAME[LVL][CURSOR] == "" and LVL != 0 else COLOR
            COLOR += 1
            GAME[LVL][CURSOR] = COLOR % GAME_CONFIG[0][1]
            set_cell((CURSOR, LVL), COLORS[COLOR % GAME_CONFIG[0][1]])
            last_key = 1
        if keydown(2) and last_key != 2:
            COLOR = (GAME[LVL - 1][CURSOR] + 1) % GAME_CONFIG[0][1] if GAME[LVL][CURSOR] == "" and LVL != 0 else COLOR
            COLOR -= 1
            GAME[LVL][CURSOR] = COLOR % GAME_CONFIG[0][1]
            set_cell((CURSOR, LVL), COLORS[COLOR % GAME_CONFIG[0][1]])
            last_key = 2
        if (keydown(4) or keydown(52)) and "" not in GAME[LVL]:
            legit_eval()
            LVL += 1
            indicators_manager(1)
        if not (keydown(0) or keydown(1) or keydown(2) or keydown(3)):
            last_key = None


mastermind()