Created
September 17, 2017 06:31
-
-
Save wangqr/bc7ad3733c8b9bafb68006b820f254dd to your computer and use it in GitHub Desktop.
A python bot for game com.balysv.loop (Infinite loop)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env python3 | |
# -*- coding: utf-8 -*- | |
import cv2 | |
import numpy as np | |
import subprocess | |
import sys | |
adb = 'Fill your adb path here' | |
def get_screenshot(): | |
return cv2.imdecode(np.fromstring(subprocess.run( | |
[adb, 'exec-out', 'screencap', '-p'], | |
stdout=subprocess.PIPE).stdout, dtype='uint8'), cv2.IMREAD_GRAYSCALE) | |
def get_bounding_box_sym(arr): | |
r, c = arr.nonzero() | |
r, c = min(np.min(r), arr.shape[0]-2 - np.max(r) - 1), min(np.min(c), arr.shape[1] - np.max(c) - 1) | |
return r, c, arr.shape[0]-2 - r, arr.shape[1] - c | |
def parse_block(arr, r, c, bs): | |
t = 't' if arr[r + 4, c + bs // 2] else '' | |
b = 'b' if arr[r + bs - 4, c + bs // 2] else '' | |
l = 'l' if arr[r + bs // 2, c + 4] else '' | |
r = 'r' if arr[r + bs // 2, c + bs - 4] else '' | |
return t + b + l + r | |
def get_edge(edges, r, c): | |
t = 't' if edges[r, c, 0] == 1 else '' | |
b = 'b' if edges[r + 1, c, 0] == 1 else '' | |
l = 'l' if edges[r, c, 1] == 1 else '' | |
r = 'r' if edges[r, c + 1, 1] == 1 else '' | |
return t + b + l + r | |
def test_edge(edges, r, c, s): | |
return 't' in s and edges[r, c, 0] == -1 or 't' not in s and edges[r, c, 0] == 1 \ | |
or 'b' in s and edges[r + 1, c, 0] == -1 or 'b' not in s and edges[r + 1, c, 0] == 1 \ | |
or 'l' in s and edges[r, c, 1] == -1 or 'l' not in s and edges[r, c, 1] == 1 \ | |
or 'r' in s and edges[r, c + 1, 1] == -1 or 'r' not in s and edges[r, c + 1, 1] == 1 | |
def rot(s): | |
t = 't' if 'l' in s else '' | |
b = 'b' if 'r' in s else '' | |
l = 'l' if 'b' in s else '' | |
r = 'r' if 't' in s else '' | |
return t + b + l + r | |
def do_block(state, edges, r, c, q): | |
if r < 0 or r >= len(state) or c < 0 or c >= len(state[0]) or \ | |
edges[r, c, 0] and edges[r, c, 1] and edges[r + 1, c, 0] and edges[r, c + 1, 1]: | |
return | |
cur_state = state[r][c] | |
if len(cur_state) == 0: | |
edges[r:r + 2, c, 0] = -1 | |
edges[r, c:c + 2, 1] = -1 | |
elif len(cur_state) == 4: | |
edges[r:r + 2, c, 0] = 1 | |
edges[r, c:c + 2, 1] = 1 | |
elif len(cur_state) == 1: | |
if edges[r, c, 0] == -1 and edges[r, c, 1] == -1 and edges[r + 1, c, 0] == -1: | |
edges[r, c + 1, 1] = 1 | |
elif edges[r, c, 0] == -1 and edges[r, c, 1] == -1 and edges[r, c + 1, 1] == -1: | |
edges[r + 1, c, 0] = 1 | |
elif edges[r, c, 0] == -1 and edges[r + 1, c, 0] == -1 and edges[r, c + 1, 1] == -1: | |
edges[r, c, 1] = 1 | |
elif edges[r, c, 1] == -1 and edges[r + 1, c, 0] == -1 and edges[r, c + 1, 1] == -1: | |
edges[r, c, 0] = 1 | |
elif edges[r, c, 0] == 1: | |
edges[r, c, 1] = edges[r + 1, c, 0] = edges[r, c + 1, 1] = -1 | |
elif edges[r, c, 1] == 1: | |
edges[r, c, 0] = edges[r + 1, c, 0] = edges[r, c + 1, 1] = -1 | |
elif edges[r + 1, c, 0] == 1: | |
edges[r, c, 0] = edges[r, c, 1] = edges[r, c + 1, 1] = -1 | |
elif edges[r, c + 1, 1] == 1: | |
edges[r, c, 0] = edges[r, c, 1] = edges[r + 1, c, 0] = -1 | |
else: | |
return | |
elif len(cur_state) == 3: | |
if edges[r, c, 0] == 1 and edges[r, c, 1] == 1 and edges[r + 1, c, 0] == 1: | |
edges[r, c + 1, 1] = -1 | |
elif edges[r, c, 0] == 1 and edges[r, c, 1] == 1 and edges[r, c + 1, 1] == 1: | |
edges[r + 1, c, 0] = -1 | |
elif edges[r, c, 0] == 1 and edges[r + 1, c, 0] == 1 and edges[r, c + 1, 1] == 1: | |
edges[r, c, 1] = -1 | |
elif edges[r, c, 1] == 1 and edges[r + 1, c, 0] == 1 and edges[r, c + 1, 1] == 1: | |
edges[r, c, 0] = -1 | |
elif edges[r, c, 0] == -1: | |
edges[r, c, 1] = edges[r + 1, c, 0] = edges[r, c + 1, 1] = 1 | |
elif edges[r, c, 1] == -1: | |
edges[r, c, 0] = edges[r + 1, c, 0] = edges[r, c + 1, 1] = 1 | |
elif edges[r + 1, c, 0] == -1: | |
edges[r, c, 0] = edges[r, c, 1] = edges[r, c + 1, 1] = 1 | |
elif edges[r, c + 1, 1] == -1: | |
edges[r, c, 0] = edges[r, c, 1] = edges[r + 1, c, 0] = 1 | |
else: | |
return | |
elif cur_state in ['lr', 'tb']: | |
if edges[r, c, 0] == 1 or edges[r + 1, c, 0] == 1 or edges[r, c, 1] == -1 or edges[r, c + 1, 1] == -1: | |
edges[r, c, 1] = edges[r, c + 1, 1] = -1 | |
edges[r, c, 0] = edges[r + 1, c, 0] = 1 | |
elif edges[r, c, 0] == -1 or edges[r + 1, c, 0] == -1 or edges[r, c, 1] == 1 or edges[r, c + 1, 1] == 1: | |
edges[r, c, 1] = edges[r, c + 1, 1] = 1 | |
edges[r, c, 0] = edges[r + 1, c, 0] = -1 | |
else: | |
return | |
else: | |
flag = False | |
if edges[r, c, 0] and edges[r + 1, c, 0] == 0: | |
edges[r + 1, c, 0] = -edges[r, c, 0] | |
elif edges[r + 1, c, 0] and edges[r, c, 0] == 0: | |
edges[r, c, 0] = -edges[r + 1, c, 0] | |
else: | |
flag = True | |
if edges[r, c, 1] and edges[r, c + 1, 1] == 0: | |
edges[r, c + 1, 1] = -edges[r, c, 1] | |
elif edges[r, c + 1, 1] and edges[r, c, 1] == 0: | |
edges[r, c, 1] = -edges[r, c + 1, 1] | |
elif flag: | |
return | |
q.extend([(r - 1, c), (r, c - 1), (r, c + 1), (r + 1, c)]) | |
def find_final_solution(state, edges_orig, rs, cs): | |
p = (edges_orig[:, :-1, 0] == 0).nonzero() | |
if p[0].size: | |
p = p[0][0], p[1][0], 0 | |
q = [(p[0], p[1]), (p[0] - 1, p[1])] | |
else: | |
p = (edges_orig[:-1, :, 1] == 0).nonzero() | |
if p[0].size: | |
p = p[0][0], p[1][0], 1 | |
q = [(p[0], p[1]), (p[0], p[1] - 1)] | |
else: | |
for i in range(rs): | |
for j in range(cs): | |
source = state[i][j] | |
target = get_edge(edges_orig, i, j) | |
if len(source) != len(target) \ | |
or source in ['tb', 'lr'] and target not in ['tb', 'lr'] \ | |
or target in ['tb', 'lr'] and source not in ['tb', 'lr']: | |
return None | |
return edges_orig | |
edges = edges_orig.copy() | |
edges[p] = 1 | |
while q: | |
i, j = q.pop(0) | |
do_block(state, edges, i, j, q) | |
t = find_final_solution(state, edges, rs, cs) | |
if t is not None: | |
return t | |
edges = edges_orig.copy() | |
edges[p] = -1 | |
while q: | |
i, j = q.pop(0) | |
do_block(state, edges, i, j, q) | |
return find_final_solution(state, edges, rs, cs) | |
def tap(r, c): | |
return subprocess.Popen( | |
[adb, 'shell', 'input', 'tap', | |
str(c), str(r)]) | |
def main(): | |
p = get_screenshot() | |
p = ((p < 165) * 255).astype('uint8') | |
r1, c1, r2, c2 = get_bounding_box_sym(p) | |
print(r1, c1, r2, c2) | |
if c1 == 76: | |
bs = (c2 - c1) // 8 | |
print('Column number: 8') | |
elif c1 in [78, 92, 127]: | |
bs = (c2 - c1) // 7 | |
print('Column number: 7') | |
elif c1 in [108, 126, 156, 186, 192]: | |
bs = (c2 - c1) // 6 | |
print('Column number: 6') | |
elif c1 in [180, 195, 220, 245]: | |
bs = (c2 - c1) // 5 | |
print('Column number: 5') | |
elif c1 in [252, 284, 304]: | |
bs = (c2 - c1) // 4 | |
print('Column number: 4') | |
elif c1 == 0: | |
raise PermissionError | |
else: | |
print('If you get here, most likely your screen is not 1080x1920. In this case, please modify above code.') | |
bs = (c2 - c1) // int(input('Column number: ')) | |
cs = (c2 - c1) // bs | |
rem = (r2 - r1) % bs | |
if rem > 8: | |
print('rem', rem) | |
rem = (bs - rem + 1) // 2 | |
r1 -= rem | |
r2 += rem | |
rs = (r2 - r1) // bs | |
print(bs, rs, cs) | |
state = [[None] * cs for _ in range(rs)] | |
edges = np.zeros((rs + 1, cs + 1, 2), dtype='int8') # (top, left) | |
edges[[0, rs], :-1, 0] = -1 | |
edges[:-1, [0, cs], 1] = -1 | |
q = [(r, c) for r in [0, rs - 1] for c in range(cs)] + [(r, c) for c in [0, cs - 1] for r in range(1, rs - 1)] | |
dbg = np.tile(np.expand_dims(p, -1), [1, 1, 3]) | |
dbg = cv2.resize(dbg, (837, 1488), cv2.INTER_LANCZOS4) | |
for i in range(rs): | |
for j in range(cs): | |
r = r1 + bs * i | |
c = c1 + bs * j | |
state[i][j] = parse_block(p, r, c, bs) | |
cv2.putText(dbg, state[i][j], (c*1488//1920, r*1488//1920), cv2.FONT_HERSHEY_TRIPLEX, 1, (238,190,77)) | |
if len(state[i][j]) in [0, 4]: | |
q.append((i, j)) | |
while q: | |
i, j = q.pop(0) | |
do_block(state, edges, i, j, q) | |
for i in range(rs + 1): | |
for j in range(cs + 1): | |
r = r1 + bs * i | |
c = c1 + bs * j | |
if j != cs: | |
s = edges[i, j, 0] | |
dbg[r*1488//1920, c*1488//1920:(c + bs)*1488//1920, :] = [25,83,217] if s == -1 else [48,172,119] if s == 1 else [142,47,126] | |
if i != rs: | |
s = edges[i, j, 1] | |
dbg[r*1488//1920:(r + bs)*1488//1920, c*1488//1920, :] = [25,83,217] if s == -1 else [48,172,119] if s == 1 else [142,47,126] | |
cv2.imshow('test', dbg) | |
cv2.waitKey(1) | |
edges = find_final_solution(state, edges, rs, cs) | |
joins = [] | |
for i in range(rs): | |
for j in range(cs): | |
if len(state[i][j]) in [0, 4]: | |
continue | |
source = state[i][j] | |
target = get_edge(edges, i, j) | |
r = r1 + bs * i + bs // 2 | |
c = c1 + bs * j + bs // 2 | |
if len(source) != len(target): | |
while test_edge(edges, i, j, source): | |
source = rot(source) | |
tap(r, c) | |
else: | |
while source != target: | |
source = rot(source) | |
joins.append(tap(r, c)) | |
[(x.wait(), cv2.waitKey(1)) for x in joins] | |
[(x.wait(), cv2.waitKey(1)) for x in [tap(90, 90), tap(90, 90)]] | |
if __name__ == '__main__': | |
while True: | |
try: | |
main() | |
except PermissionError: | |
print('Stuck?') | |
[(x.wait(), cv2.waitKey(1)) for x in [tap(90, 90), tap(90, 90)]] | |
except ValueError: | |
print('ValueError') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment