from math import sin, cos, pi, asin from tkinter import * laby_w, laby_h = 20, 12 wl = [676499, 819210, 704161, 828804, 911396, 1010837, 772540, 600182, 526017, 803480, 756064, 701196, 1756736, 1376344, 1158834, 1315990, 1102792, 1323847, 1497194, 1810708, 1327018, 1094903, 1349813] zint = 2 zx, zy = 50, 50 screen_w, screen_h = laby_w * zx + zint, laby_h * zy + zint master = Tk() master.resizable(0, 0) index = 0 path = [(0.0, 0.5)] def escape(event): global master master.quit() def add(event): global path, index if len(path) < 24: index += 1 path.append((0.0, 0.5)) aller_selon(path) def remove(event): global path, index if len(path) > 1: path = path[:-1] if index > len(path) - 1: index = len(path) - 1 aller_selon(path) def next(event): global path, index if index < len(path) - 1: index += 1 aller_selon(path) def previous(event): global path, index if index > 0: index -= 1 aller_selon(path) def left(event, step): global path, index path[index] = (round(path[index][0] + step, 2), path[index][1]) aller_selon(path) def right(event, step): global path, index path[index] = (round(path[index][0] - step, 2), path[index][1]) aller_selon(path) def up(event): global path, index path[index] = (path[index][0], round(path[index][1] + 0.1, 1)) aller_selon(path) def down(event): global path, index if path[index][1] > 0: path[index] = (path[index][0], round(path[index][1] - 0.1, 1)) aller_selon(path) def print_code(event): global path print('') print('path = %s' % path) print('') print('def chemin():') for i in range(len(path)): print(' a_gauche(%s)' % path[i][0]) print(' avancer(%s)' % path[i][1]) print('') master.bind('', escape) master.bind('', add) master.bind('', remove) master.bind('', previous) master.bind('', next) master.bind('', lambda e: left(e, 0.1)) master.bind('', lambda e: right(e, 0.1)) master.bind('', lambda e: left(e, 0.01)) master.bind('', lambda e: right(e, 0.01)) master.bind('', up) master.bind('', down) master.bind('p', print_code) master.bind('P', print_code) canvas = Canvas(master, width = screen_w, height = screen_h + 68, bg = 'white') canvas.pack() def clean_screen(): global canvas canvas.delete('all') def draw_rect(x, y, w, h, color): global canvas x += 1 y += 1 canvas.create_rectangle(x, y, x + w, y + h, fill = color, outline = '') def draw_line(x1, y1, x2, y2, color): global canvas canvas.create_line(x1 + 1, y1 + 1, x2 + 1, y2 + 1, fill = color, width = 2.0) def draw_help(): global canvas help = 'change angle: [Shift+]Left/Right, change length: Up/Down, add/remove element: Enter/BackSpace, previous/next element: Ctrl+Left/Right, print code: P, exit: Esc' canvas.create_text(4, screen_h + 36, anchor = NW, text = help, fill = 'black') def draw_path(): global canvas, path for i in range(len(path)): if i == index: color = 'red' else: color = 'blue' if i < 12: y = 0 else: y = 16 canvas.create_text(4 + (i % 12) * 80, screen_h + 4 + y, anchor = NW, text = '(%5.2f, %3.1f)' % path[i], fill = color) def draw_score(score): global canvas canvas.create_text(4, screen_h + 52, anchor = NW, text = f'score: {score}, state[7]: {state[7]}, state[6]: {state[6]}', fill = 'black') def fix_angle(a): return a * 2 * asin(1) / pi def cout(x): n, c = 5, 1 x = round(abs(x) * 10**n) if x: c = max(n + 1 - len(str(x)), 0) while n and not (x % 10): x = x // 10 n -= 1 c += not n return 1 + len(str(x)) + c def tourner(a): global state state[7] += a state[5] += 5 + cout(a) state[2] -= a def avancer(l, color): global state t = fix_angle(state[2]) dx, dy = cos(t), sin(t) state[7] += l state[5] += 8 + cout(l) while(l > 0): state[3:5] = state[0:2] x, y = state[0] + dx/4, state[1] + dy/4 ix, iy = int(x) - (x < 0), int(y) - (y < 0) drx, dry = ix - int(state[3]), iy - int(state[4]) vw = lambda y, x: wl[y] & 2**x hw = lambda y, x: wl[y + laby_h] & 2**x tx = drx and (ix < 0 or ix >= laby_w or vw(iy - dry, laby_w - 2 - min(ix, ix - drx))) ty = dry and (iy < 0 or iy >= laby_h or hw(min(iy, iy - dry), laby_w - 1 - (ix - drx))) t = dx <= 0 or int(x) < laby_w - 1 or int(y) < laby_h - 1 if t and tx or ty or (drx and dry and (t and tx or ty)) or (drx and dry and (t and vw(iy, laby_w - 2 - min(ix, ix - drx)) or hw(min(iy, iy - dry), laby_w - 1 - ix))): state[5] += 15 return l -= .25 state[6] += (state[6] < 200) state[0:2] = (x, y) draw_line(state[3] * zx, state[4] * zy, state[0] * zx, state[1] * zy, color) def aller_selon(path): global state state = [0, .5, 0, 0, .5, 0, 0, 0] clean_screen() for i in range(2): draw_rect(0, i * laby_h * zy, laby_w * zx + zint, zint, 'black') draw_rect(i * laby_w * zx, (not i) * zy, zint, (laby_h - 1) * zy, 'black') for y in range(2 * laby_h - 1): for z in range(laby_w - (y < laby_h)): if wl[y] & 2**z: x = laby_w - 1 - z if y < laby_h: draw_rect(x * zx, y * zy, zint, zy + zint, 'black') else: pass draw_rect(x * zx, (y - laby_h + 1) * zy, zx + zint, zint, 'black') for i in range(len(path)): tourner(path[i][0]) if i == index: color = 'red' else: color = 'blue' avancer(path[i][1], color) state[5] += sin(fix_angle(state[7])) - state[6] // 2 draw_help() draw_path() draw_score(state[5]) aller_selon(path) master.mainloop()