Skip to content

Instantly share code, notes, and snippets.

@oprypin
Last active August 1, 2016 19:37
Show Gist options
  • Save oprypin/81897645d5cea9f92d70c0b3dfdbbdf1 to your computer and use it in GitHub Desktop.
Save oprypin/81897645d5cea9f92d70c0b3dfdbbdf1 to your computer and use it in GitHub Desktop.
Fully automatic solver of Two Digits http://store.steampowered.com/app/371330/
print("Starting...")
import sys
import collections
import itertools
import subprocess
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
print("Taking screenshot...")
screenshot = app.primaryScreen().grabWindow(app.desktop().winId()).toImage()
data = screenshot.constBits().asstring(screenshot.byteCount())
per_line = screenshot.bytesPerLine()
per_pixel = per_line // screenshot.width()
print("Forming matrix...")
matrix = set()
for y in range(screenshot.height()):
for x in range(screenshot.width()):
i = y*per_line + x*per_pixel
if all(b == 255 for b in data[i : i + per_pixel]):
matrix.add((x, y))
def fill(x, y):
matrix.remove((x, y))
todo = collections.deque([(x, y)])
count = 1
min_x = max_x = x
min_y = max_y = y
while todo:
x, y = todo.popleft()
min_x = min(x, min_x)
min_y = min(y, min_y)
max_x = max(x, max_x)
max_y = max(y, max_y)
for dx, dy in (-1, 0), (0, -1), (1, 0), (0, 1):
pt = (x + dx, y + dy)
if pt in matrix:
matrix.remove(pt)
todo.append(pt)
count += 1
return count, (min_x, min_y, max_x, max_y)
def search(min_x, min_y, max_x, max_y):
for y in range(min_y, max_y+1):
for x in range(min_x, max_x+1):
if (x, y) in matrix:
yield fill(x, y)
# Tuned for 1920x1080
BORDER = 7933
DIGITS = {
779: 0,
418: 1,
751: 2,
720: 3,
804: 4,
795: 5,
837: 6,
533: 7,
854: 8,
830: 9,
}
print("Recognizing numbers...")
numbers = []
centers = []
for count, rect in search(0, 0, screenshot.width()-1, screenshot.height()-1):
if count != BORDER:
continue
number = 0
for count, _ in search(*rect):
number = number*10 + DIGITS[count]
numbers.append(number)
centers.append(((rect[0]+rect[2])//2, (rect[1]+rect[3])//2))
print(numbers)
assert len(numbers) == 9
print("Finding groups...")
commands = []
for grouping in itertools.product(range(3), repeat=len(numbers)):
sums = collections.defaultdict(int)
for group, number in zip(grouping, numbers):
sums[group] += number
if sums[1] == sums[2] > 0:
for group, number, center in zip(grouping, numbers, centers):
commands.append("mousemove {} {}".format(*center))
if group:
print(" " * group, number)
for i in range(group):
commands.append("click 1")
commands.append("sleep 0.1")
commands.append("mousemove 0 0")
break
else:
assert False
print("Sending mouse inputs...")
subprocess.run(['xdotool', '-'], input='\n'.join(commands).encode())
print("Done")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment