279 lines
11 KiB
Python
279 lines
11 KiB
Python
import pydirectinput
|
|
import random
|
|
import cv2 as cv
|
|
import numpy as np
|
|
from window_capture import WindowCapture
|
|
from vision import Vision
|
|
from config_file import UserConfigs
|
|
from time import time
|
|
|
|
GREEN = 1
|
|
YELLOW = 2
|
|
RED = 3
|
|
BLUE = 4
|
|
PURPLE = 5
|
|
RAINBOW = 6
|
|
BIGBOMB = 7
|
|
BOMB = 8
|
|
ARROW_DOWN = 9
|
|
ARROW_RIGHT = 10
|
|
ROCK_1 = 11
|
|
ROCK_2 = 12
|
|
ROCK_3 = 13
|
|
BURGER = 14
|
|
PAB1 = 15
|
|
GOLDBAR = 16
|
|
MAGINENT = 21
|
|
CHEMTRANT = 22
|
|
TENESENT = 23
|
|
CIBUTRANT = 24
|
|
ARTISENT = 25
|
|
|
|
|
|
class GameBase:
|
|
|
|
def __init__(self, overlay):
|
|
self.overlay = overlay
|
|
|
|
self.data_value_grid = np.zeros((8, 14), dtype=int)
|
|
self.data_coordinates = np.zeros((8, 14), dtype=object)
|
|
self.observation = np.zeros((8, 14), dtype=int)
|
|
self.data_score_map = np.zeros((8, 14), dtype=int)
|
|
|
|
self.explosives = [RAINBOW, ARROW_RIGHT, ARROW_DOWN, BIGBOMB, BOMB]
|
|
self.colors = [GREEN, YELLOW, RED, BLUE, MAGINENT, CHEMTRANT, TENESENT, CIBUTRANT, ARTISENT]
|
|
|
|
self.next_level = cv.imread("control_elements/next_level.jpg", cv.IMREAD_COLOR)
|
|
self.next_level_x = cv.imread("control_elements/next_level_x.jpg", cv.IMREAD_COLOR)
|
|
self.reset_board = cv.imread("control_elements/reset_button.jpg", cv.IMREAD_COLOR)
|
|
self.reset_confirm = cv.imread("control_elements/reset_confirm.jpg", cv.IMREAD_COLOR)
|
|
self.ok_button = cv.imread("control_elements/ok_button.jpg", cv.IMREAD_COLOR)
|
|
|
|
self.reset_counter = 0
|
|
|
|
self.stop_time = overlay.global_timeout_use.get()
|
|
self.breaks = overlay.hourly_breaks_use.get()
|
|
self.break_time = overlay.break_duration_use.get()
|
|
|
|
# initialize the user-class
|
|
self.config = UserConfigs()
|
|
# initialize the StunWindowCapture class
|
|
self.capture_window = WindowCapture(None, None, self.config)
|
|
# initialize the StunVision class
|
|
self.vision_stun = Vision()
|
|
|
|
def execute_main_loop(self):
|
|
start_time = time()
|
|
breaks = self.init_breaks()
|
|
while True:
|
|
self.check_breaks(start_time, breaks)
|
|
if self.overlay.run_mode == 'paused':
|
|
cv.waitKey(1)
|
|
continue
|
|
elif self.overlay.run_mode == 'stopped':
|
|
break
|
|
elif self.overlay.run_mode == 'finished':
|
|
break
|
|
self.assess_playfield_and_make_move()
|
|
cv.waitKey(500)
|
|
|
|
def init_breaks(self):
|
|
breaks = []
|
|
if int(self.breaks) == 0:
|
|
return breaks
|
|
#breaks.append(7)
|
|
for i in range(1, int(self.breaks) + 1, 1):
|
|
avr_in_sec = int(self.stop_time) * 60 * 60 / int(self.breaks)
|
|
breaks.append(random.randint(int(i * avr_in_sec * 0.60), int(i * avr_in_sec)))
|
|
return breaks
|
|
|
|
def check_breaks(self, start_time, breaks):
|
|
if int(self.stop_time) == 0:
|
|
return
|
|
if (time() - start_time) > float(self.stop_time) * 60 * 60:
|
|
self.overlay.run_mode = 'stopped'
|
|
for break_ in breaks:
|
|
elapsed = int(time() - start_time)
|
|
if elapsed > break_:
|
|
pause = random.randint(1, 3)
|
|
self.overlay.update_status_label("Break: " + str(pause) + "m")
|
|
cv.waitKey(pause * 60 * 1000)
|
|
breaks.remove(break_)
|
|
self.overlay.update_status_label("running")
|
|
|
|
def assess_playfield_and_make_move(self):
|
|
pass
|
|
|
|
#screenshot = screenshot[190:1230, 260:2090]
|
|
#[58: 1134, 230: 2113]
|
|
def fill_data_coordinates(self):
|
|
# 260 to 2090 = 1883 / 14 = 130
|
|
# 190 to 1230 = 1076 / 8 = 130
|
|
dim = 130
|
|
for e in range(0, 8, 1):
|
|
for i in range(0, 14, 1):
|
|
self.data_coordinates[e][i] = [i * dim, e * dim, dim, dim]
|
|
|
|
def check_for_button_and_execute(self, screen, needle, offset_left=0, offset_down=0):
|
|
rectangles = self.vision_stun.find(screen, needle, 0.70, 1)
|
|
if len(rectangles) == 0:
|
|
return False
|
|
point = self.vision_stun.get_click_points(rectangles)[0]
|
|
self.dig_point(point[0] + offset_left, point[1] + offset_down, 500)
|
|
return True
|
|
|
|
def check_for_next_level(self, screen, needle):
|
|
offset_left = 260
|
|
offset_down = 190
|
|
rectangles = self.vision_stun.find(screen, needle, 0.70, 1)
|
|
if len(rectangles) == 0:
|
|
return False
|
|
if self.detonate_explosive_when_stuck(self.observation):
|
|
return True
|
|
point = self.vision_stun.get_click_points(rectangles)[0]
|
|
self.dig_point(point[0] + offset_left, point[1] + offset_down, 500)
|
|
return True
|
|
|
|
def detonate_explosive_when_stuck(self, state):
|
|
for e in range(0, 8, 1):
|
|
for i in range(0, 14, 1):
|
|
for explosive in self.explosives:
|
|
if self.local_pos_check(state, e, i, 0, 0, explosive):
|
|
src_pt = self.get_click_point(self.data_coordinates[e, i])
|
|
if self.local_pos_checks(state, e, i, 1, 0, self.colors):
|
|
dest_pt = self.get_click_point(self.data_coordinates[e + 1, i])
|
|
self.move_tile(src_pt, dest_pt)
|
|
return True
|
|
elif self.local_pos_checks(state, e, i, 0, 1, self.colors):
|
|
dest_pt = self.get_click_point(self.data_coordinates[e, i + 1])
|
|
self.move_tile(src_pt, dest_pt)
|
|
return True
|
|
elif self.local_pos_checks(state, e, i, -1, 0, self.colors):
|
|
dest_pt = self.get_click_point(self.data_coordinates[e - 1, i])
|
|
self.move_tile(src_pt, dest_pt)
|
|
return True
|
|
elif self.local_pos_checks(state, e, i, 0, -1, self.colors):
|
|
dest_pt = self.get_click_point(self.data_coordinates[e, i - 1])
|
|
self.move_tile(src_pt, dest_pt)
|
|
return True
|
|
else:
|
|
continue
|
|
return False
|
|
|
|
def check_explosives(self, state, e, i):
|
|
for explosive in self.explosives:
|
|
if self.local_pos_check(state, e, i, 0, 0, explosive):
|
|
dest_pt = self.get_click_point(self.data_coordinates[e, i])
|
|
if self.local_pos_checks(state, e, i, 1, 0, self.explosives):
|
|
src_pt = self.get_click_point(self.data_coordinates[e + 1, i])
|
|
self.move_tile(src_pt, dest_pt)
|
|
elif self.local_pos_checks(state, e, i, 0, 1, self.explosives):
|
|
src_pt = self.get_click_point(self.data_coordinates[e, i + 1])
|
|
self.move_tile(src_pt, dest_pt)
|
|
elif self.local_pos_checks(state, e, i, -1, 0, self.explosives):
|
|
src_pt = self.get_click_point(self.data_coordinates[e - 1, i])
|
|
self.move_tile(src_pt, dest_pt)
|
|
elif self.local_pos_checks(state, e, i, 0, -1, self.explosives):
|
|
src_pt = self.get_click_point(self.data_coordinates[e, i - 1])
|
|
self.move_tile(src_pt, dest_pt)
|
|
else:
|
|
continue
|
|
return True
|
|
else:
|
|
continue
|
|
return False
|
|
|
|
@staticmethod
|
|
def is_direction_in_bounce_and_same_color(state, loc, color):
|
|
x, y = loc
|
|
if x <= 7 and x >= 0 and y <= 13 and y >= 0:
|
|
if state[x, y] == color:
|
|
return 1
|
|
return 0
|
|
|
|
@staticmethod
|
|
def local_pos_check(state, e, i, e_check, i_check, needle):
|
|
if e + e_check >= 0 and e + e_check <= 7 and i + i_check >= 0 and i + i_check <= 13:
|
|
if state[e + e_check, i + i_check] == needle:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
@staticmethod
|
|
def local_pos_checks(state, e, i, e_check, i_check, needles):
|
|
if e + e_check >= 0 and e + e_check <= 7 and i + i_check >= 0 and i + i_check <= 13:
|
|
for needle in needles:
|
|
if state[e + e_check, i + i_check] == needle:
|
|
return True
|
|
else:
|
|
continue
|
|
return False
|
|
|
|
@staticmethod
|
|
def get_click_point(rectangle):
|
|
# Loop over all the rectangles
|
|
x, y, w, h = rectangle
|
|
# Determine the center position
|
|
center_x = x + int(w / 2)
|
|
center_y = y + int(h / 2)
|
|
# Save the points
|
|
return int(center_x), int(center_y)
|
|
|
|
def move_tile(self, point_source, point_dest):
|
|
offset_left = 260
|
|
offset_down = 190
|
|
pydirectinput.moveTo(point_source[0] + offset_left, point_source[1] + offset_down)
|
|
# pydirectinput.moveTo(0,0)
|
|
pydirectinput.mouseDown()
|
|
w = random.randint(25, 50)
|
|
cv.waitKey(100 + w)
|
|
pydirectinput.moveTo(point_dest[0] + offset_left, point_dest[1] + offset_down)
|
|
pydirectinput.mouseUp()
|
|
cv.waitKey(400 + w)
|
|
|
|
def check_for_button_and_click_it(self, button_url):
|
|
screenshot = self.capture_window.get_screenshot()
|
|
# gray = cv.cvtColor(screenshot, cv.COLOR_BGR2GRAY)
|
|
# thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
|
|
# gray_needle = cv.cvtColor(cv.imread(button_url, cv.IMREAD_UNCHANGED), cv.COLOR_BGR2GRAY)
|
|
# thresh_needle = cv.threshold(gray_needle, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
|
|
needle = cv.imread(button_url, cv.IMREAD_UNCHANGED)
|
|
# rectangles = self.vision_stun.find(thresh, thresh_needle, 0.4, 1)
|
|
rectangles = self.vision_stun.find(screenshot, needle, 0.7, 1)
|
|
|
|
if len(rectangles) == 1:
|
|
pointis = self.vision_stun.get_click_points(rectangles)
|
|
for pointi in pointis:
|
|
self.dig_point(pointi[0], pointi[1], 150)
|
|
|
|
@staticmethod
|
|
def dig_point(point1, point2, dig_time):
|
|
pydirectinput.moveTo(point1, point2)
|
|
cv.waitKey(dig_time)
|
|
pydirectinput.mouseDown()
|
|
w = random.randint(50, 100)
|
|
cv.waitKey(w)
|
|
pydirectinput.mouseUp()
|
|
|
|
@staticmethod
|
|
def move_to(x, y):
|
|
point_src = (1113, 598)
|
|
pydirectinput.moveTo(point_src[0], point_src[1])
|
|
pydirectinput.mouseDown()
|
|
w = random.randint(1, 100)
|
|
cv.waitKey(150 + w)
|
|
pydirectinput.moveTo(x, y)
|
|
pydirectinput.mouseUp()
|
|
cv.waitKey(500 + w)
|
|
|
|
def point_in_rect(self, point):
|
|
for e in range(0, 8, 1):
|
|
for i in range(0, 14, 1):
|
|
x1, y1, w, h = self.data_coordinates[e][i]
|
|
x2, y2 = x1 + w, y1 + h
|
|
x, y = point
|
|
if x1 < x and x < x2:
|
|
if y1 < y and y < y2:
|
|
return e, i
|
|
return None, None
|