chess.py

Created by ilyas-r

Created on October 05, 2023

14.1 KB

Chess v0.6.
Python Game for Numworks, all models.
By Ilyas R. 2022.

Learn more about the game on: nsi.xyz/chess (FR)

Changelog

Chess v0.6 - 29/08/2022:
- Beta release


from kandinsky import *
from ion import *

# Chess 0.6-SNAPSHOT NumWorks, XX/XX/2022
# Par Ilyas R.
# https://nsi.xyz/chess

pawn = (3584, 4352, 12672, 65504, 32800, 32800, 16448, 8320, 8320, 8320, 8320, 8320, 8320, 8320, 16448, 98352, 131080,
        524284, 524290, 1048577, 2097151)
knight = (480, 1840, 3096, 6220, 12390, 8194, 24577, 16497, 49371, 33166, 33152, 32960, 32864, 98352, 65560, 196616,
          131080, 524284, 524290, 1048577, 2097151)
rook = (101936, 168232, 160200, 131080, 131080, 131056, 32800, 32800, 32800, 32800, 32800, 32800, 32800, 32800, 32800,
        131056, 131080, 524284, 524290, 1048577, 2097151)
bishop = (3584, 4352, 4352, 4352, 3584, 4352, 12672, 24768, 49248, 32928, 33056, 33312, 32800, 49248, 16448, 49248,
          98352, 524284, 524290, 1048577, 2097151)
queen = (1024, 2560, 4352, 130032, 137992, 263172, 524290, 524290, 524290, 524290, 524290, 524290, 262148, 262148,
         131080, 131056, 65552, 524284, 524290, 1048577, 2097151)
king = (917518, 593426, 561442, 545090, 544322, 536962, 524290, 524290, 262148, 262148, 131080, 65552, 65504, 32800,
        16448, 131056, 65552, 524284, 524290, 1048577, 2097151)

pos, initial_pos = [0, 3], []
last_key, pion_selected, move_pion = None, None, None
tour = 0
roque_done = False
pos_pions = [["rook_b", "knight_b", "bishop_b", "king_b", "queen_b", "bishop_b", "knight_b", "rook_b"],
             ["pawn_b", "pawn_b", "pawn_b", "pawn_b", "pawn_b", "pawn_b", "pawn_b", "pawn_b"],
             ["", "", "", "", "", "", "", ""],
             ["", "", "", "", "", "", "", ""],
             ["", "", "", "", "", "", "", ""],
             ["", "", "", "", "", "", "", ""],
             ["pawn_w", "pawn_w", "pawn_w", "pawn_w", "pawn_w", "pawn_w", "pawn_w", "pawn_w"],
             ["rook_w", "knight_w", "bishop_w", "queen_w", "king_w", "bishop_w", "knight_w", "rook_w"]]
t_b, t_w = 4800, 4800
k_w_m, k_b_m, t1_w_m, t1_b_m, t2_w_m, t2_b_m = False, False, False, False, False, False
eat_pion = False
p1, p2 = (4, 7), (0, 7)


def roque(sender_pos, target_pos):
    pion = get_pion_of_pos(sender_pos).split("_")
    if pion[0] != "king":
        return False
    diff = sender_pos[0] - target_pos[0]
    print(diff)
    if pion[1] == "w":
        if 2 <= abs(diff) <= 4 and not k_w_m and ((diff < 0 and not t2_w_m) or (diff > 0 and not
           t1_w_m)) and not_pion_between_target(sender_pos, target_pos, 1):
            print(diff, t1_w_m)
            pos_pions[7][2 if diff > 0 else 6], pos_pions[7][3 if diff > 0 else 5] = pos_pions[sender_pos[1]][sender_pos[0]], pos_pions[7][7*(diff < 0)]
            pos_pions[7][7*(diff < 0)], pos_pions[sender_pos[1]][sender_pos[0]] = "", ""
            return True
        return False
    if pion[1] == "b":
        if 2 <= abs(diff) <= 4 and not k_b_m and ((diff < 0 and not t2_b_m) or (diff > 0 and not
           t1_b_m)) and not_pion_between_target(sender_pos, target_pos, 1):
            print(diff, t1_b_m)
            pos_pions[0][1 if diff > 0 else 5], pos_pions[0][2 if diff > 0 else 4] = pos_pions[sender_pos[1]][sender_pos[0]], pos_pions[0][7*(diff < 0)]
            pos_pions[0][7*(diff < 0)], pos_pions[sender_pos[1]][sender_pos[0]] = "", ""
            return True
        return False


def get_pos_of_pion(pion):
    pos_of_pions = []
    for i in range(8):
        for j in range(8):
            if pion != "all":
                if pos_pions[i][j] == pion:
                    pos_of_pions.append((j, i))
            else:
                if pos_pions[i][j] != "":
                    pos_of_pions.append((j, i))
    return pos_of_pions


def get_pion_of_pos(p):
    return pos_pions[p[1]][p[0]]


def switch_pos_pions(sender_pos, target_pos, eat=0, rock=0):
    global tour, eat_pion
    if not rock:
        if not eat:
            pos_pions[sender_pos[1]][sender_pos[0]], pos_pions[target_pos[1]][target_pos[0]] = pos_pions[target_pos[1]][
                    target_pos[0]], pos_pions[sender_pos[1]][sender_pos[0]]
        else:
            pos_pions[target_pos[1]][target_pos[0]] = pos_pions[sender_pos[1]][sender_pos[0]]
            pos_pions[sender_pos[1]][sender_pos[0]] = ""
            eat_pion = False
    tour += 1
    menu()


def default_pions():
    for i in range(8):
        for j in range(8):
            if pos_pions[i][j] != "":
                draw_pion(eval(pos_pions[i][j].split("_")[0]), d_p(j, i, 3)[0], d_p(j, i, 3)[1], get_font([j, i]),
                          get_pion_color([j, i]))


def draw_pion(t, x, y, back=(0,) * 3, font=(170, 170, 170)):
    for i in range(21):
        for j in range(21):
            fill_rect(x + j, y + i, 1, 1, (t[i] >> (20 - j)) & 1 and font or back)


def debug(i_pos, target_pos):
    draw_string("i_p:" + str(i_pos), 221, 90, "black")
    draw_string("t_p:" + str(target_pos), 221, 110, "black")


def gui():
    fill_rect(0, 0, 320, 222, (49, 46, 43))
    plateau()
    draw_string("CHESS", 244, 3, "white", (49, 46, 43))
    draw_string("Blacks:16", 225, 40, "black", (49, 46, 43))
    draw_string("XXXsec", 225, 64, "black", (49, 46, 43))
    draw_string("Round:", 225, 100, "white", (49, 46, 43))
    fill_rect(290, 100, 20, 20, (170, 170, 170) if tour % 2 == 0 else "black")
    draw_string("XXXsec", 225, 140, (170, 170, 170), (49, 46, 43))
    draw_string("Whites:16", 225, 164, (170, 170, 170), (49, 46, 43))
    draw_string("nsi.xyz", 235, 201, "white", (49, 46, 43))
    default_pions()


def menu():
    fill_rect(290, 100, 20, 20, (170, 170, 170) if tour % 2 == 0 else "black")


def plateau():
    for i in range(8):
        for j in range(8):
            fill_rect(3 + j * 27, 3 + i * 27, 27, 27, get_font([j, i]))


def d_p(p_x=0, p_y=0, pion=0):
    return [(3 + 27 * p_x) + pion, (3 + 27 * p_y) + pion]


def get_font(p):
    return ((119, 149, 86) if p[0] % 2 == 0 else (235, 236, 208)) if p[1] % 2 != 0 else (235, 236, 208) \
        if p[0] % 2 == 0 else (119, 149, 86)


def get_pion_color(p):
    return (170, 170, 170) if get_pion_of_pos(p).split("_")[1] == "w" else (0,) * 3


def legit_move(sender_pos, target_pos):
    pion = get_pion_of_pos(sender_pos).split("_")
    if pion[0] == "pawn":
        if pion[1] == "b":
            dist = 2 if sender_pos[1] == 1 else 1
            if 0 < target_pos[1] - sender_pos[1] <= dist and sender_pos[0] == target_pos[0]:
                return True
            return False
        else:
            dist = -2 if sender_pos[1] == 6 else -1
            if dist <= target_pos[1] - sender_pos[1] < 0 and sender_pos[0] == target_pos[0]:
                return True
            return False
    if pion[0] == "rook":
        if sender_pos[0] == target_pos[0] or sender_pos[1] == target_pos[1]:
            return True
        return False
    if pion[0] == "knight":
        diff_x, diff_y = abs(sender_pos[0] - target_pos[0]), abs(sender_pos[1] - target_pos[1])
        if (diff_x == 1 and diff_y == 2) or (diff_x == 2 and diff_y == 1):
            return True
        return False
    if pion[0] == "bishop":
        if abs(target_pos[0] - sender_pos[0]) == abs(target_pos[1] - sender_pos[1]):
            return True
        return False
    if pion[0] == "queen":
        if (abs(target_pos[0] - sender_pos[0]) == abs(target_pos[1] - sender_pos[1])) or (sender_pos[0] == target_pos[
           0] or sender_pos[1] == target_pos[1]):
            return True
        return False
    if pion[0] == "king":
        if abs(sender_pos[0] - target_pos[0]) < 2 and abs(sender_pos[1] - target_pos[1]) < 2:
            return True
        return False


def not_pion_between_target(sender_pos, target_pos, rock=0):
    global eat_pion
    all_pos_between_target = []
    pion = get_pion_of_pos(sender_pos).split("_")
    if get_pion_of_pos(target_pos) != "" and pion[1] == get_pion_of_pos(target_pos).split("_")[1] and not rock:
        return False
    for i in range(target_pos[1], sender_pos[1]) if target_pos[1] + 1 - sender_pos[1] < 0 else range(
            sender_pos[1] + -1 * (target_pos[1] + 1 - sender_pos[1] == 0), target_pos[1] + 1):
        for j in range(target_pos[0], sender_pos[0]) if target_pos[0] + 1 - sender_pos[0] < 0 else range(
                sender_pos[0] + -1 * (target_pos[0] + 1 - sender_pos[0] == 0), target_pos[0] + 1):
            if not rock:
                if legit_move(sender_pos, [j, i]) and list(sender_pos) != [j, i] and list(target_pos) != [j, i]:
                    if pion[0] == "queen" or pion[0] == "king":
                        if abs(target_pos[0] - sender_pos[0]) == abs(target_pos[1] - sender_pos[1]):
                            if abs(j - sender_pos[0]) == abs(i - sender_pos[1]):
                                all_pos_between_target.append([j, i])
                        if sender_pos[0] == target_pos[0] or sender_pos[1] == target_pos[1]:
                            all_pos_between_target.append([j, i])
                    else:
                        all_pos_between_target.append([j, i])
            else:
                if list(sender_pos) != [j, i] and list(target_pos) != [j, i]:
                    all_pos_between_target.append([j, i])
    print(all_pos_between_target)
    for i in range(len(all_pos_between_target)):
        if get_pion_of_pos(all_pos_between_target[i]) != "":
            return False
    if get_pion_of_pos(target_pos) != "" and pion[1] != get_pion_of_pos(target_pos).split("_")[1]:
        eat_pion = 1
    return True


def king_is_vulnerable():
    all_moves = []
    for k in range(len(get_pos_of_pion("all"))):
        print(k)
        for i in range(8):
            for j in range(8):
                if legit_move(get_pos_of_pion("all")[k], [j, i]) and not_pion_between_target(get_pos_of_pion("all")[
                     k], [j, i]) and list(get_pos_of_pion("all")[k]) != [j, i]:
                    all_moves.append([j, i])
    king_w_pos = list(get_pos_of_pion("king_w")[0])
    king_b_pos = list(get_pos_of_pion("king_b")[0])
    print(all_moves, king_w_pos, king_b_pos)
    if king_w_pos in all_moves or king_b_pos in all_moves:
        return True
    return False


def all_conditions_to_move(i_p, t_p):
    global k_w_m, k_b_m, t1_w_m, t1_b_m, t2_w_m, t2_b_m, roque_done
    if not_pion_between_target(i_p, t_p) and i_p != t_p and legit_move(i_p, t_p):
        print(i_p)
        if i_p == [0, 0]:
            t1_b_m = True
        if i_p == [3, 0]:
            k_b_m = True
        if i_p == [7, 0]:
            t2_b_m = True
        if i_p == [0, 7]:
            print('b')
            t1_w_m = True
        if i_p == [4, 7]:
            k_w_m = True
        if i_p == [7, 7]:
            t2_w_m = True
        return True
    if roque(tuple(i_p), tuple(t_p)):
        roque_done = True
        return True
    print(roque(tuple(i_p), tuple(t_p)))
    print(i_p, t_p)
    return False


def get_old_pos(key):
    return [pos[0] + (-1 if key == 3 else +1 if key != 1 and key != 2 else 0), pos[1] +
            (-1 if key == 2 else +1 if key != 0 and key != 3 else 0)]


def update_pos_pion(old_p, p, rock=0):
    if not rock:
        fill_rect(d_p(old_p[0])[0], d_p(0, old_p[1])[1], 27, 27, get_font(old_p))
        fill_rect(d_p(p[0])[0], d_p(0, p[1])[1], 27, 27, (186, 202, 43))
        fill_rect(d_p(p[0])[0] + 3, d_p(0, p[1])[1] + 3, 21, 21, get_font(p))
        draw_pion(eval(get_pion_of_pos(p).split("_")[0]), d_p(p[0], 0, 3)[0], d_p(0, p[1], 3)[1],
                  get_font(p), get_pion_color(p))
    else:
        default_pions()


def move_cursor(key, select_mode=0, leave_select_mode=0):
    global pion_selected, initial_pos, roque_done
    if leave_select_mode:
        if all_conditions_to_move(initial_pos, pos):
            print("1", pos_pions)
            switch_pos_pions(initial_pos, pos, 1 * eat_pion, 1 * roque_done)
            print("2", pos_pions)
            update_pos_pion(initial_pos, pos, 1 * roque_done)
            roque_done = 0
            print("3", pos_pions)
    else:
        if select_mode:
            fill_rect(d_p(pos[0])[0], d_p(0, pos[1])[1], 27, 27, (206, 222, 63))
            draw_pion(eval(get_pion_of_pos(pos).split("_")[0]), d_p(pos[0], 0, 3)[0], d_p(0, pos[1], 3)[1],
                      (206, 222, 63), get_pion_color(pos))
            initial_pos = [pos[0], pos[1]]
            pion_selected = True
        if not select_mode and not pion_selected:
            old_pos = get_old_pos(key)
            fill_rect(d_p(old_pos[0])[0], d_p(0, old_pos[1])[1], 27, 27, get_font(old_pos))
            if get_pion_of_pos(old_pos) != "":
                draw_pion(eval(get_pion_of_pos(old_pos).split("_")[0]), d_p(old_pos[0], 0, 3)[0],
                          d_p(0, old_pos[1], 3)[1], get_font(old_pos), get_pion_color(old_pos))
        if not select_mode:
            fill_rect(d_p(pos[0])[0], d_p(0, pos[1])[1], 27, 27, (186, 202, 43))
            fill_rect(d_p(pos[0])[0] + 3, d_p(0, pos[1])[1] + 3, 21, 21, get_font(pos))
            if get_pion_of_pos(pos) != "":
                draw_pion(eval(get_pion_of_pos(pos).split("_")[0]), d_p(pos[0], 0, 3)[0], d_p(0, pos[1], 3)[1],
                          get_font(pos), get_pion_color(pos))
            debug(initial_pos, pos)
            pion_selected = False


def legit_turn(t):
    team_pion = get_pion_of_pos(pos).split("_")[1]
    if (team_pion == "w" and t % 2 == 0) or (team_pion == "b" and t % 2 != 0):
        return True
    return False


def chess():
    gui()
    global pos, last_key, move_pion
    while not keydown(5):
        if keydown(3) and pos[0] < 7 and last_key != 3:
            pos[0] += 1
            move_cursor(3)
            last_key = 3
        if keydown(0) and pos[0] > 0 and last_key != 0:
            pos[0] -= 1
            move_cursor(0)
            last_key = 0
        if keydown(1) and pos[1] > 0 and last_key != 1:
            pos[1] -= 1
            move_cursor(1)
            last_key = 1
        if keydown(2) and pos[1] < 7 and last_key != 2:
            pos[1] += 1
            move_cursor(2)
            last_key = 2
        if keydown(52) and last_key != 52:
            if not move_pion and get_pion_of_pos(pos) != "" and legit_turn(tour):
                move_cursor(42, 1)
                move_pion = True
            elif move_pion:
                move_cursor(42, 0, 1)
                move_pion = False
            last_key = 52
        if not (keydown(0) or keydown(1) or keydown(2) or keydown(3) or keydown(52)):
            last_key = None


chess()
print(roque(p1, p2))