labytest.py

Created by andreanx

Created on September 26, 2020

6.2 KB


def col3_2_rgb(c, bits, bgr):
  return c[2*bgr]//2**(8 - bits[0]) + c[1]//2**(8 - bits[1])*2**bits[0] + c[2*(not bgr)]//2**(8-bits[2])*2**(bits[0] + bits[1])
def kc16_draw_line(x1, y1, x2, y2, c):
  draw_line(int(x1), int(y1), int(x2), int(y2), col3_2_rgb(c, [5, 6, 5], 1))

def get_infos():
  global kc16_draw_line
  fnop = lambda : None
  screen_w, screen_h, color_bits, poly_set_pixel, poly_draw_line, poly_fill_rect, poly_clean_screen, need_clean, need_line, need_rect = 0, 222, [5, 6, 5], fnop, fnop, fnop, fnop, 0, 1, 1
  try:
    if chr(256)==chr(0): # KhiCAS Python compat.
      need_line = 0
      need_clean = 1
      screen_w = 320
      def poly_set_pixel(x, y, c):
        set_pixel(x, y, col3_2_rgb(c, [5,6,5], 0))
      poly_draw_line = kc16_draw_line
  except:
    pass
  if not screen_w:
    kc16_draw_line = None
    try: # KhiCAS Micropython
      import graphic
      def poly_draw_line(x1, y1, x2, y2, c):
        graphic.draw_line(int(x1), int(y1), int(x2), int(y2), col3_2_rgb(c, color_bits, 1))
      def poly_fill_rect(x1, y1, x2, y2, c):
        graphic.draw_filled_rectangle(int(x1), int(y1), int(x2), int(y2), c)
      screen_w, poly_set_pixel, need_clean, need_line, need_rect = 320, graphic.set_pixel, 1, 0, 0
    except:
      pass
  if not screen_w:
    try: # NumWorks
      import kandinsky
      screen_w, poly_set_pixel, need_rect = 320, kandinsky.set_pixel, 0
      def poly_fill_rect(x, y, w, h, c):
        kandinsky.fill_rect(int(x), int(y), int(w), int(h), c)
    except:
      pass
  if need_line:
    def poly_draw_line(x1, y1, x2, y2, c):
      m, a1, b1, a2, b2 = 0, int(x1), int(y1), int(x2), int(y2)
      if (x2 - x1) ** 2 < (y2 - y1) ** 2:
        m, a1, a2, b1, b2 = 1, b1, b2, a1, a2
      if min(a1, a2) != a1: a1, b1, a2, b2 = a2, b2, a1, b1
      for k in range(a2 - a1 + 1):
        a, b = a1 + k, int(b1 + (b2 - b1) * k / ((a2 - a1) or 1))
        poly_set_pixel((a, b)[m], (b, a)[m], c)
  if need_rect:
    def poly_fill_rect(x, y, w, h, c):
      for k in range(h):
        poly_draw_line(x, y + k, x + w - 1, y + k, c)
  if need_clean:
    def poly_clean_screen():
      poly_fill_rect(0, 0, screen_w, screen_h, [255, 255, 255])
  return screen_w, screen_h, poly_set_pixel, poly_draw_line, poly_fill_rect, poly_clean_screen, fnop

from math import sin, cos, asin, pi

def ri(a,b):
  global s
  s = (s * 214013 + 2531011) % 4294967296
  r = (s // 65536) & 0x7fff
  return r % (b-a) + a

def mon_secret(v, b, n):
  return v & ~(b * 2**n)

def mon_xor(a, b):
  return a + b - (a & b)

def fix_angle(a):
  return a * 2 * asin(1) / pi

def ufl(r):
  global rl
  i, s = r // 3, 10 * (r % 3)
  rep = rl[i]//2**s & 1023
  if rep != r:
    rep = ufl(rep)
    rl[i] = mon_secret(rl[i], 1023, s)
    s = rep * 2**s
    rl[i] = mon_xor(rl[i], s)
  return rep

def ufm(r1, r2):
  global rl
  i, r1 = r1 // 3, 10 * (r1 % 3)
  r2 *= 2**r1
  rl[i] = mon_secret(rl[i], 1023, r1)
  rl[i] = mon_xor(rl[i], r2)

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 a_gauche(a):
  global state
  state[7] += a
  state[5] += 5 + cout(a)
  state[2] -= a

def a_droite(a):
  state[7] += 2 * a
  a_gauche(-a)

def avancer(l):
  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
    wx = laby_w - 2 - min(ix, ix - drx)
    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)
    poly_draw_line(state[3] * zx, state[4] * zy, state[0] * zx, state[1] * zy, colors[4])

laby_w, laby_h = 20, 12
s = 0xdeadbeef

rl = [(3*i + 2)*1048576 + (3*i + 1)*1024 + 3*i for i in range((laby_w*laby_h + 2) // 3)]
wl = [(2**(laby_w + 1) - 1) // (1 + (k < laby_h)) for k in range(2*laby_h - 1)]
cl = laby_w * laby_h
while cl > 1 - (laby_w * laby_h)//100*10:
  y = ri(0, 2*laby_h - 1)
  x = ri(0, laby_w - (y < laby_h))
  if wl[y] & 2**x:
    if y < laby_h:
      r1 = y*laby_w + x
      r2 = r1 + 1
    else:
      r1 = (y - laby_h)*laby_w + x
      r2 = r1 + laby_w
    rl1, rl2 = ufl(r1), ufl(r2)
    if rl1 != rl2 or cl <= 1:
      ufm(rl1, rl2)
      cl -= 1
      wl[y] = mon_secret(wl[y], 1, x)
for r in range(laby_w * laby_h):
  ufl(r)

screen_w, screen_h, poly_set_pixel, poly_draw_line, poly_fill_rect, poly_clean_screen, poly_show_screen = get_infos()
ds = 4
zint = 1 + (screen_w > 2*laby_w*ds)
ds += zint - 1
zx, zy = (screen_w - zint) / laby_w, (screen_h - zint) / laby_h
get_infos, poly_set_pixel, rl, ufl, ufm = None, None, None, None, None
colors = ([0, 95, 0], [0, 0, 63], [0, 127, 0], [0, 0, 79], [255, 0, 0])

def aller_selon(f):
  global state
  state = [0, .5, 0, 0, .5, 0, 0, 0]
  poly_clean_screen()
  for i in range(2):
    poly_fill_rect(0, i * laby_h * zy, laby_w * zx, zint, colors[1])
    poly_fill_rect(i * laby_w * zx, (not i) * zy, zint, (laby_h - 1) * zy, colors[0])
  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:
          poly_fill_rect(x * zx, y * zy, zint, zy, colors[2])
        else:
          poly_fill_rect(x * zx, (y - laby_h + 1) * zy, zx, zint, colors[3])
  f()
  poly_show_screen()
  state[5] += sin(fix_angle(state[7])) - state[6] // 2
  print('Consommation : ' + str(state[5]))
  if state[0] >= laby_w:
    print('Bravo, tu es sorti-e.')
    print('Pour jouer et gagner,')
    print('envoie ton script a')
    print('info@tiplanet.org.')
  return state[5]

def chemin():
  avancer(1.5)
  a_droite(1.5707963267948966)
  avancer(1)