Files
Litcraft_Python_B/game_base_class.py
2022-10-19 08:58:58 +02:00

266 lines
10 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.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 = []
#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(i * avr_in_sec * 0.60, i * avr_in_sec))
return breaks
def check_breaks(self, start_time, breaks):
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
def fill_data_coordinates(self):
# 230 to 2110 = 1883 / 14 = 134.5
# 60 to 1130 = 1076 / 8 = 134.5
dim = 134.5
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 = 230
offset_down = 58
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
def is_direction_in_bounce_and_same_color(self, 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
def local_pos_check(self, 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
def local_pos_checks(self, 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
def get_click_point(self, 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 = 230
offset_down = 58
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)
def dig_point(self, point1, point2, dig_time):
pydirectinput.moveTo(point1, point2)
cv.waitKey(dig_time)
pydirectinput.mouseDown()
w = random.randint(50, 100)
cv.waitKey(w)
pydirectinput.mouseUp()
def move_to(self, 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