commandblockguy

Xuanwu path finder

Oct 20th, 2020
975
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. from laby import *
  2. from math import atan2, sqrt, pi
  3. import numpy as np
  4.  
  5. def try_advance(pos, dist):
  6.   state = list(pos)
  7.   dx, dy = cos(state[2]), sin(state[2])
  8.   while(dist > 0):
  9.     x, y = state[0] + dx/4, state[1] + dy/4
  10.     ix, iy = int(x) - (x < 0), int(y) - (y < 0)
  11.     drx, dry = ix - int(state[0]), iy - int(state[1])
  12.     vw = lambda y, x: wl[y] & 2**x
  13.     hw = lambda y, x: wl[y + laby_h] & 2**x
  14.     wx = laby_w - 2 - min(ix, ix - drx)
  15.     tx = drx and (ix < 0 or ix >= laby_w or vw(iy - dry, laby_w - 2 - min(ix, ix - drx)))
  16.     ty = dry and (iy < 0 or iy >= laby_h or hw(min(iy, iy - dry), laby_w - 1 - (ix - drx)))
  17.     t = dx <= 0 or int(x) < laby_w - 1 or int(y) < laby_h - 1
  18.     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))):
  19.       return False
  20.     dist -= .25
  21.     state[0:1] = (x, y)
  22.   return True
  23.  
  24. def get_positions(pos_list, target_pos):
  25.     result = []
  26.     count = 0
  27.     for pos in pos_list:
  28.         count += 1
  29.         if count % 1000 == 0: print(count)
  30.         for da10 in range(-99, 100):
  31.             da = da10 / 10.
  32.             new_angle = pos[2] + da
  33.             rot_pos = (pos[0], pos[1], new_angle)
  34.             for dist10 in range(-3, 3):
  35.                 dx = target_pos[0] - pos[0]
  36.                 dy = target_pos[1] - pos[1]
  37.                 dist = sqrt(dx**2 + dy**2)
  38.                 dist += dist10 / 2.
  39.                 dist = round(dist * 2) / 2
  40.                 new_pos = (pos[0] + dist * cos(new_angle), pos[1] + dist * sin(new_angle), new_angle, da, dist, pos[5] + [pos[0:5]])
  41.                 if abs(new_pos[0] - target_pos[0]) < .75 and abs(new_pos[1] - target_pos[1]) < .75:
  42.                     if try_advance(rot_pos, dist):
  43.                         result.append(new_pos)
  44.                     else:
  45.                         break
  46.     return result
  47.  
  48. manual_positions = [
  49.     (2.5, 1.5),
  50.     (4, 7.5),
  51.     (8.75, 8.75),
  52.     (9.5, 5),
  53.     (14.75, 3.6),
  54.     (16.2, 8.5),
  55.     (17.2, 9),
  56.     (16, 10.9),
  57.     (40, 11.9)
  58. ]
  59.  
  60. colors = [
  61.     (0, 0x64, 0),
  62.     (0xbc, 0x8f, 0x8f),
  63.     (0xff, 0, 0),
  64.     (0xff, 0xd7, 0),
  65.     (0, 0xff, 0),
  66.     (0, 0xff, 0xff),
  67.     (0xa0, 0x20, 0xf0),
  68.     (0x1e, 0x90, 0xff),
  69.     (0xff, 0x14, 0x93)
  70. ]
  71.  
  72. def pos_list(pos):
  73.     return pos[5][1:] + [pos[0:5]]
  74.  
  75. import cv2, numpy as np
  76. screen_w, screen_h = 640, 480
  77. w_scale, h_scale = 640 / 20, 480 / 12
  78. img = np.full((screen_h, screen_w, 3), 255, np.uint8)
  79.  
  80. positions = [(0., 0.5, 0., 0., 0., [])]
  81. for index, new_pos in enumerate(manual_positions):
  82.     print(index, ':', len(positions))
  83.     positions = get_positions(positions, new_pos)
  84.     for pos in positions:
  85.         for p in pos_list(pos):
  86.             try:
  87.                 img[int(p[1] * h_scale)][int(p[0] * w_scale)] = colors[index]
  88.             except: pass
  89.  
  90. print(len(manual_positions), ':', len(positions))
  91.  
  92. def sign_score(pos, signs):
  93.     total = 0
  94.     for i, x in enumerate(pos_list(pos)):
  95.         total += x[4]
  96.         total += x[3] * signs[i]
  97.     return 72 + sin(total), total
  98.  
  99. def score(pos):
  100.     min_score = 73
  101.     for i in np.ndindex((2, 2, 2, 2, 2, 2, 2, 2, 2)):
  102.         signs = np.subtract(np.multiply(i, 2.0), 1.0)
  103.         s, total = sign_score(pos, signs)
  104.         if s < min_score:
  105.             min_score = s
  106.             min_signs = signs
  107.             min_total = total
  108.     return min_score, min_signs, min_total % (pi*2) - 3*pi/2
  109.  
  110. def get_orders(pos, s):
  111.     score, signs, total = s
  112.     return ([(x[3], x[4], sign) for x, sign in zip(pos_list(pos), signs)], score, total)
  113.  
  114. with open('out.txt', 'w') as f:
  115.     orders = []
  116.     for i, pos in enumerate(positions):
  117.         if i % 1000 == 0: print(i)
  118.         orders.append(get_orders(pos, score(pos)))
  119.     print('sorting...')
  120.     orders.sort(key= lambda x: x[1])
  121.     f.write(str(orders))
  122.  
  123. cv2.imshow('Xuanwu', img)
  124. cv2.waitKey(0)
RAW Paste Data