import cv2 import numpy as np import pyautogui import pygetwindow as gw import pytesseract import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim import random import time import ctypes import ctypes from ctypes import wintypes pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe" PROCESS_VM_READ = 0x0010 PROCESS_QUERY_INFORMATION = 0x0400 def read_memory(process_id, address): # Uzyskaj uchwyt do procesu z odpowiednimi uprawnieniami process_handle = ctypes.windll.kernel32.OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, False, process_id) if not process_handle: raise Exception("Nie można otworzyć procesu: {}".format(process_id)) # Przygotuj buffor, do którego zostanie wczytana wartość value = ctypes.c_int() bytes_read = wintypes.SIZE() # Przeczytaj pamięć ctypes.windll.kernel32.ReadProcessMemory(process_handle, ctypes.c_void_p(address), ctypes.byref(value), ctypes.sizeof(value), ctypes.byref(bytes_read)) # Zamknij uchwyt do procesu ctypes.windll.kernel32.CloseHandle(process_handle) return value.value class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(1, 10, kernel_size=5) self.conv2 = nn.Conv2d(10, 20, kernel_size=5) self.conv2_drop = nn.Dropout2d() self.fc1 = nn.Linear(6480, 50) self.fc2 = nn.Linear(50, 5) # 5 akcji: w, a, s, d, space def forward(self, x): x = F.relu(F.max_pool2d(self.conv1(x), 2)) x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2)) x = x.view(-1, 6480) x = F.relu(self.fc1(x)) x = self.fc2(x) return F.log_softmax(x, dim=1) def get_game_image(game_window): screenshot = pyautogui.screenshot(region=(game_window.left, game_window.top, game_window.width, game_window.height)) screenshot = np.array(screenshot) screenshot = cv2.cvtColor(screenshot, cv2.COLOR_BGR2GRAY) return cv2.resize(screenshot, (84, 84)) def get_score_region(screenshot): # Assuming the score is located at the top right corner of the screen # We can try to give some padding to make sure we are only capturing the score score_height = 40 score_width = 150 top_padding = 10 right_padding = 10 y = top_padding x = screenshot.shape[1] - score_width - right_padding score_region = screenshot[y:y + score_height, x:x + score_width] return score_region def get_score(screenshot): score_region = get_score_region(screenshot) if score_region.size == 0: print("Score region is empty!") return 0 # We already have a grayscale image so we don't need to convert it again thresholded = cv2.threshold(score_region, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] score_text = pytesseract.image_to_string(thresholded, config='--psm 6') score_digits = ''.join(filter(str.isdigit, score_text)) return int(score_digits) if score_digits else 0 def perform_action(action_index, game_window): actions = ["w", "a", "s", "d", "space"] action = actions[action_index] print(f"Performing action: {action}") if action == "space": x = random.randint(game_window.left, game_window.left + game_window.width) y = random.randint(game_window.top, game_window.top + game_window.height) pyautogui.moveTo(x, y) #pyautogui.click() pyautogui.keyDown(action) time.sleep (0.1) pyautogui.keyUp(action) else: pyautogui.keyDown(action) time.sleep (0.1) pyautogui.keyUp(action) return action # Przykładowe użycie - ZMIEN process_id NA WŁAŚCIWY PROCES ORAZ address NA WŁAŚCIWY ADRES process_id = 2616 # ID procesu gry hp_address = 0x0437E9DC # Adres pamięci HP score_address = 0x040351A4 # Adres pamięci HP def train(model, device, game_window, optimizer, previous_score, previous_hp): model.train() current_score = previous_score current_hp = previous_hp for i in range(10000): # liczba epok treningowych time.sleep(0.1) image = get_game_image(game_window) image_tensor = ( torch.from_numpy(image).float().unsqueeze(0).unsqueeze(0).to(device) ) optimizer.zero_grad() output = model(image_tensor) new_hp = read_memory(process_id, hp_address) new_score = read_memory(process_id, score_address) if new_hp <= 6: time.sleep(2) pyautogui.keyDown("space") time.sleep (0.05) pyautogui.keyUp("space") acti 1).item() acti game_window) #new_image = get_game_image(game_window) print(f"Previous HP: {previous_hp}, Current HP: {new_hp}") print(f"Previous Score: {previous_score}, Current Score: {new_score}") # Oblicz nagrodę i stratę # 100 130 = -30 hp_diff = new_hp - previous_hp score_diff = new_score - previous_score; reward = 0; if new_hp <= 6: reward-=15; else: if hp_diff >= 0: reward+=1; else: reward-=5; if score_diff > 0: reward +=10; #reward = hp_diff + score_diff; print(f"HP Diff: {hp_diff}, Score Diff: {score_diff}, Reward: {reward}") loss = -torch.tensor([reward], dtype=torch.float,device = device) * output[0][action_index] #loss = -reward * output[0][action_index] loss.backward() optimizer.step() previous_hp = new_hp previous_score = new_score print(f"Loss: {loss.item()}") def main(): device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = Net().to(device) optimizer = optim.Adam(model.parameters(), lr=0.001) game_window = gw.getWindowsWithTitle("Yet Another Zombie Defense 2")[0] game_window.activate() process_id = game_window._hWnd initial_image = get_game_image(game_window) #initial_score = get_score(initial_image) train(model, device, game_window, optimizer, 0, 150) if __name__ == "__main__": main()