Skip to content

Instantly share code, notes, and snippets.

@wangqr
Created September 17, 2017 06:31
Show Gist options
  • Save wangqr/bc7ad3733c8b9bafb68006b820f254dd to your computer and use it in GitHub Desktop.
Save wangqr/bc7ad3733c8b9bafb68006b820f254dd to your computer and use it in GitHub Desktop.
A python bot for game com.balysv.loop (Infinite loop)
#! /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