class Gameplayer: def __init__(self): self.window_name = 'Gemgem' self.board = np.zeros((8, 8)) self.static_templates = { 1: 'graphics/gem1_background.png', 2: 'graphics/gem2_background.png', 3: 'graphics/gem3_background.png', 4: 'graphics/gem4_background.png', 5: 'graphics/gem5_background.png', 6: 'graphics/gem6_background.png', 7: 'graphics/gem7_background.png', } self.tile_width = 64 self.vision = Vision(self.static_templates, self.window_name) self.control = Controller() def read_board(self): coords = self.vision.match_templates() for key in coords.keys(): coords[key][0] //= self.tile_width coords[key][1] //= self.tile_width self.board[coords[key][0], coords[key][1]] = key def find_match(self): """Finds a pair of coordinates that can generate a match""" def has_match(interval): """checks if there is a match in a given 6 or 4 subinterval""" vals, counts = np.unique(interval, return_counts=True) curr_tile = vals[counts.argmax()] mask = interval == curr_tile if len(interval.shape) > 1: if np.sum(counts > 2) == 0: return False if counts.max() > 2 and (0 in np.sum(mask, axis=0)): return False return mask, curr_tile if counts.max() == 3: return mask, curr_tile vertically = False # firstly check horizontally, then vertically for board in (self.board, np.flipud(self.board).T): # check for six-matches, like so: # @@* # #$@ for h in range(2, 9): for w in range(3, 9): six = board[h - 2:h, w - 3:w] if not has_match(six): continue mask, val = has_match(six) y0 = np.sum(mask, axis=1).argmax() y1 = np.sum(mask, axis=1).argmin() if y0 == y1: y0, y1 = 0, 1 x = w - (2 - mask[y0].argmin()) - 1 y0 = h - y0 - 1 y1 = h - y1 - 1 coords = np.array([(x, y0), (x, y1)]) if vertically: coords = np.array([(y0, 7 - x), (y1, 7 - x)]) return coords # check for four-matches, like so: # @@*@ for y in range(8): for w in range(4, 9): four = board[y, w - 4:w] if not has_match(four): continue mask, val = has_match(four) x0 = mask.argmin() print(x0) x1 = x0 if x0 == 1: x1 -= 1 else: x1 += 1 print(x0, x1) print(w) x0 = w - (3 - x0) - 1 x1 = w - (3 - x1) - 1 coords = np.array([(x0, y), (x1, y)]) if vertically: coords = np.array([(y, 7 - x0), (y, 7 - x1)]) return coords vertically = True def make_move(self, game_pos_tpl): """calculates the coordinates of matching positions on the screen and clicks on them""" top = self.vision.find_window()['top'] left = self.vision.find_window()['left'] win = np.array([[left, top], [left, top]]) pos1, pos2 = game_pos_tpl * self.tile_width + self.tile_width // 2 + win self.control.move_mouse(pos1[0], pos1[1]) self.control.left_mouse_click() sleep(1) self.control.move_mouse(pos2[0], pos2[1]) self.control.left_mouse_click() def board_is_relevant(self): """check if past and present screenshots are equal""" if np.allclose(self.vision.take_screenshot(), self.vision.frame): return True return False def play(self, n_steps): for i in range(n_steps): print('========= CURRENT BOARD =========:') print(self.board) if not self.board_is_relevant(): self.vision.refresh_frame() self.read_board() coords = self.find_match() print('FOUND A MATCH:') print(coords) self.make_move(coords) sleep(1)