-
Notifications
You must be signed in to change notification settings - Fork 2
/
nopixel4_lockpick_solver.py
106 lines (86 loc) · 3.4 KB
/
nopixel4_lockpick_solver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import numpy as np # Math
import cv2 # Computer vision
import pyautogui # Button pressing
import mss # Screen grabbing
import time # Sleep
from helpers import rotate_image, colour_to_name
# Config
SLICE_WIDTH = 10
SPOKES = 12
RINGS = 5
RING_OFFSET = 50
DEBUG = False
CAPTURE_ZONE = {"top": 236, "left": 3017, "width": 580,
"height": 580} # Inner zone around game
def find_layers(img):
img_width = img.shape[1]
img_height = img.shape[0]
rings = [["" for _ in range(SPOKES)] for _ in range(RINGS)]
circles = [["" for _ in range(SPOKES)] for _ in range(RINGS)]
for i in range(SPOKES):
rotated = rotate_image(img, 360/SPOKES*i)
slice = rotated[0:img_height//2, img_width//2 -
SLICE_WIDTH:img_width//2+SLICE_WIDTH]
if DEBUG:
annotated = cv2.copyMakeBorder(
slice.copy(), 0, 0, 0, 300, cv2.BORDER_CONSTANT, value=[0, 0, 0])
for j in range(RINGS):
ring = slice[225-RING_OFFSET*j:250-RING_OFFSET*j, 0:250]
circle_pixel = ring[24, 10]
if DEBUG:
cv2.circle(annotated, (10, annotated.shape[0]-(RING_OFFSET*j)-40), 2,
(0, 255, 0), -1)
cv2.putText(annotated, colour_to_name(circle_pixel), (50, annotated.shape[0]-(RING_OFFSET*j)-35),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (int(circle_pixel[0]), int(circle_pixel[1]), int(circle_pixel[2])), 1, cv2.LINE_AA)
circles[j][i] = colour_to_name(circle_pixel)
line_pixel = ring[10, 10]
if DEBUG:
cv2.circle(annotated, (10, annotated.shape[0]-(RING_OFFSET*j)-55), 2,
(0, 255, 0), -1)
cv2.putText(annotated, colour_to_name(line_pixel), (50, annotated.shape[0]-(RING_OFFSET*j)-50),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (int(line_pixel[0]), int(line_pixel[1]), int(line_pixel[2])), 1, cv2.LINE_AA)
rings[j][i] = colour_to_name(line_pixel)
if DEBUG:
cv2.imshow('Annotated', annotated)
cv2.waitKey(0)
return rings, circles
def verify_solution(ring, circles):
solved = True
for i in range(len(ring)):
if ring[i] != "unknown" and ring[i] != circles[i]:
solved = False
return False
return solved
def solve_layer(ring, circles):
if verify_solution(ring, circles):
return 0
for i in range(SPOKES):
# slide the ring to the right
ring = ring[1:] + ring[:1]
if verify_solution(ring, circles):
return i+1
return 12
def optimize_rotations(rotations):
if rotations > 6:
return rotations - 12
return rotations
if __name__ == "__main__":
print("running in 2 seconds")
time.sleep(1)
print("running in 1 seconds")
time.sleep(1)
print("running")
while True:
with mss.mss() as sct:
img = np.array(sct.grab(CAPTURE_ZONE))
rings, circles = find_layers(img)
for i in range(len(rings)):
rotations = optimize_rotations(solve_layer(rings[i], circles[i]))
if rotations > 0:
pyautogui.press('right', presses=rotations)
elif rotations < 0:
pyautogui.press('left', presses=abs(rotations))
pyautogui.press('enter')
print("done")
print("trying again in 3 seconds")
time.sleep(3)