added first draft litris

This commit is contained in:
2023-07-23 14:28:12 +02:00
parent 6012a51538
commit 27f7638557

164
litris.py
View File

@@ -1,58 +1,10 @@
'''
playfield:
box = 63*63 + 4
20x20 boxes
2d array filled or not
shape class
methods:
shift direction
is row full
actions:
mini frame to detect a new spawned piece in the middle of the board
direction decision
identify shape
find posititon to store on y axis and move n fields
drop piece down
extras:
pre run calc with next piece and bypass calc
'''
import cv2 as cv import cv2 as cv
import keyboard
import numpy as np import numpy as np
from utils import mse
from game_base_class import GameBase from game_base_class import GameBase
import random
from pynput.keyboard import Key, Controller from pynput.keyboard import Key, Controller
from field import Field from field import Field
from tetromino import Tetromino from tetromino import Tetromino
from optimizer import Optimizer from optimizer import Optimizer
import time
O_FULL = [[0, 1, 1, 0], [0, 1, 1, 0]]
D_FULL = [[0, 1, 1, 0], [0, 0, 1, 0]]
L_FULL = [[0, 0, 1, 0], [1, 1, 1, 0]]
J_FULL = [[1, 1, 1, 0], [0, 0, 1, 0]]
I_FULL = [[1, 1, 1, 1], [0, 0, 0, 0]]
C_FULL = [[0, 0, 0, 0], [0, 0, 1, 0]]
B_FULL = [[0, 0, 0, 0], [0, 1, 1, 0]]
A_FULL = [[0, 1, 1, 1], [0, 0, 0, 0]]
S_FULL = [[0, 0, 1, 1], [0, 1, 1, 0]]
Z_FULL = [[0, 1, 1, 0], [0, 0, 1, 1]]
T_FULL = [[0, 1, 1, 1], [0, 0, 1, 0]]
class Litris(GameBase): class Litris(GameBase):
@@ -62,7 +14,7 @@ class Litris(GameBase):
self.keyboard = Controller() self.keyboard = Controller()
self.data_coordinates = np.zeros((20, 20), dtype=object) self.data_coordinates = np.zeros((20, 20), dtype=object)
self.stone_coordinates = np.zeros((2, 4), dtype=object)
self.observation = np.zeros((20, 20), dtype=int) self.observation = np.zeros((20, 20), dtype=int)
self.colors = [1, 2, 3, 4, 5, 6, 7, 8, 9] self.colors = [1, 2, 3, 4, 5, 6, 7, 8, 9]
@@ -103,30 +55,11 @@ class Litris(GameBase):
for e in range(0, 20, 1): for e in range(0, 20, 1):
for i in range(0, 20, 1): for i in range(0, 20, 1):
self.data_coordinates[e][i] = [(i * dim) + (i * i_spacing), (e * dim) + (e * e_spacing), dim, dim] self.data_coordinates[e][i] = [(i * dim) + (i * i_spacing), (e * dim) + (e * e_spacing), dim, dim]
for e in range(0, 2, 1):
for i in range(0, 4, 1):
self.stone_coordinates[e][i] = [(i * dim) + (i * i_spacing), (e * dim) + (e * e_spacing), dim, dim]
def assess_playfield_and_make_move(self): def assess_playfield_and_make_move(self):
#if self.check_for_button_and_execute(self.capture_window.get_screenshot(), self.sd_reset_board):
# cv.waitKey(2000)
#current_stone = self.new_stone_detection_and_identification()
#new_observation, new_screenshot = self.get_current_board_state()
#col = self.find_place_for_stone(current_stone, new_observation)
#self.move_stone(col)
#field = Field()
#current_tetromino = Tetromino.create("O")
#next_tetromino = None
#time.sleep(2)
#stone_list = ["L","S","Z","J"]
#ier = 0
#current_letter = self.new_stone_detection_and_identification()
current_letter = self.stone_id() current_letter = self.stone_id()
print("current_letter: ", current_letter)
current_tetromino = Tetromino.create(current_letter) current_tetromino = Tetromino.create(current_letter)
opt = Optimizer.get_optimal_drop(self.field, current_tetromino) opt = Optimizer.get_optimal_drop(self.field, current_tetromino)
rotation = opt['tetromino_rotation'] rotation = opt['tetromino_rotation']
@@ -145,10 +78,6 @@ class Litris(GameBase):
self.move_stone(column - offset_col, rotation) self.move_stone(column - offset_col, rotation)
print(self.field) print(self.field)
#time.sleep(0.2)
#self.observation = new_observation
#return new_observation
def get_current_board_state(self): def get_current_board_state(self):
# get an updated image of the game # get an updated image of the game
screenshot = self.capture_window.get_screenshot() screenshot = self.capture_window.get_screenshot()
@@ -214,78 +143,6 @@ class Litris(GameBase):
fail_counter = fail_counter + 1 fail_counter = fail_counter + 1
cv.waitKey(50) cv.waitKey(50)
def new_stone_detection_and_identification(self):
stone_coords = np.zeros((2, 4), dtype=object)
fail_counter = 0
while True:
screenshot = self.capture_window.get_screenshot()
#screenshot = cv.imread("litris/main_playfield.jpg")
# 1148 1412 580 845
screenshot = screenshot[643:782, 1148:1412]
#cv.imshow("screenshot", screenshot)
#cv.waitKey(150)
# gray_needle = cv.cvtColor(self.needles[needle_key], cv.COLOR_BGR2GRAY)
# thresh_needle = cv.threshold(gray_needle, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
rectangles = self.vision_stun.find(screenshot, self.needles[1], 0.85, 8)
if len(rectangles) == 0:
if self.overlay.run_mode == 'stopped' or self.overlay.run_mode == 'paused':
return
if fail_counter >= 5:
self.keyboard.press(Key.down)
self.keyboard.release(Key.down)
print("direction pressed: drop down")
cv.waitKey(100)
fail_counter = fail_counter + 1
cv.waitKey(50)
continue
points = self.vision_stun.get_click_points(rectangles)
for point in points:
x, y = self.point_in_smal_rect(point)
if x is not None and y is not None:
stone_coords[x][y] = 1
# self.change_value(x, y, int(needle_key))
# print(field.data_value_grid)
#cv.circle(screenshot, points[0], 7, (0, 255, 0), -1)
#output_image = self.vision_stun.draw_rectangles(screenshot, rectangles)
#cv.imshow("output_image", output_image)
#cv.waitKey(150)
current_letter = self.get_letter_for_stone(stone_coords)
if current_letter is None:
print("letter id failed for: ", stone_coords)
cv.waitKey(50)
continue
return current_letter
def get_letter_for_stone(self, stone):
if np.array_equal(stone, O_FULL):
return "O"
elif np.array_equal(stone, D_FULL):
return "D"
elif np.array_equal(stone, L_FULL):
return "L"
elif np.array_equal(stone, J_FULL):
return "J"
elif np.array_equal(stone, I_FULL):
return "I"
elif np.array_equal(stone, C_FULL):
return "C"
elif np.array_equal(stone, B_FULL):
return "B"
elif np.array_equal(stone, A_FULL):
return "A"
elif np.array_equal(stone, S_FULL):
return "S"
elif np.array_equal(stone, Z_FULL):
return "Z"
elif np.array_equal(stone, T_FULL):
return "T"
else:
return None
def move_stone(self, col_movement, rotation): def move_stone(self, col_movement, rotation):
if col_movement is None: if col_movement is None:
return return
@@ -293,7 +150,7 @@ class Litris(GameBase):
self.keyboard.press(Key.down) self.keyboard.press(Key.down)
self.keyboard.release(Key.down) self.keyboard.release(Key.down)
print("direction pressed: down") print("direction pressed: down")
cv.waitKey(250) cv.waitKey(120)
if rotation == 1: if rotation == 1:
self.keyboard.press('e') self.keyboard.press('e')
@@ -321,13 +178,13 @@ class Litris(GameBase):
self.keyboard.press(Key.left) self.keyboard.press(Key.left)
self.keyboard.release(Key.left) self.keyboard.release(Key.left)
print("move left 3 pressed") print("move left 3 pressed")
cv.waitKey(100) cv.waitKey(40)
else: else:
for i in range(0, col_movement, 1): for i in range(0, col_movement, 1):
self.keyboard.press(Key.right) self.keyboard.press(Key.right)
self.keyboard.release(Key.right) self.keyboard.release(Key.right)
print("move right 3 pressed") print("move right 3 pressed")
cv.waitKey(100) cv.waitKey(40)
def point_in_rect(self, point): def point_in_rect(self, point):
for e in range(0, 20, 1): for e in range(0, 20, 1):
@@ -338,15 +195,4 @@ class Litris(GameBase):
if x1 < x and x < x2: if x1 < x and x < x2:
if y1 < y and y < y2: if y1 < y and y < y2:
return e, i return e, i
return None, None
def point_in_smal_rect(self, point):
for e in range(0, 2, 1):
for i in range(0, 4, 1):
x1, y1, w, h = self.stone_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 return None, None