This code works for object detection, how can I also make it like cloning behaviour, so it simulates actions randomely and trys to upgrade each time? behaviour cloning without reward system or anything complex or manual code

import torch
import cv2
import numpy as np
import pygetwindow as gw
import os
import ctypes
import time
import mss

# Step 2: Print the current working directory
print("Current working directory:", os.getcwd())

# Step 3: Load YOLOv5 Model
class YOLOv5:
    def __init__(self, model_path=None, device='cuda'):
        if model_path is None:
            # Load a pretrained model
            self.model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)
        else:
            # Load a custom model using the provided model_path
            self.model = torch.hub.load('ultralytics/yolov5', 'custom', path=model_path)

        self.model = self.model.to(device).eval()

        # Define the class names in the correct order
        self.class_names = ["health", "energy", "use", "local_player", "enemy_player", "playerHUD", "medkit", "melee", "gun", "grenades", "equipment", "fire", "ladder", "barrel", "acid", "pickup"]

        # Dictionary to track detected classes
        self.detected_classes = {class_name: False for class_name in self.class_names}

        # Dictionary to map classes to colors
        self.class_colors = {
            "health": (255, 0, 0),
            "energy": (0, 255, 0),
            "use": (0, 0, 255),
            "local_player": (0, 255, 0),
            "enemy_player": (255, 0, 0),
            "playerHUD": (255, 255, 0),
            "medkit": (0, 255, 255),
            "melee": (255, 0, 255),
            "gun": (128, 0, 128),
            "grenades": (128, 128, 0),
            "equipment": (0, 128, 128),
            "fire": (128, 128, 128),
            "ladder": (0, 0, 0),
            "barrel": (255, 255, 255),
            "acid": (0, 0, 128),
            "pickup": (0, 128, 0)
        }

    # Map class names to their corresponding indices
    def get_class_index(self, class_name):
        return self.class_names.index(class_name)

# Step 4: Handling Game State Verification
def is_game_open():
    # Use pygetwindow to get the game window
    game_window = gw.getWindowsWithTitle('Superfighters Deluxe')
    return bool(game_window)

# Step 5: Calculate frames per second
def calculate_fps(start_time, frames):
    current_time = time.time()
    elapsed_time = current_time - start_time
    fps = frames / elapsed_time
    return fps

# Step 6: Main Real-Time Detection Loop
def main():
    # Step 6.1: Adjust the path to your custom-trained YOLOv5 model
    model_path = r"C:\Windows\System32\yolov5\models\last.pt"

    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

    # Step 6.2: Load YOLOv5 model
    model = YOLOv5(model_path, device=device)

    # Step 6.3: Variables for calculating frames per second
    start_time = time.time()
    frames = 0

    # Step 6.4: Set the target frame rate
    target_fps = 60  # Increase target FPS for smoother detection
    target_frame_time = 1 / target_fps
    frame_skip = 2  # Adjust the frame skip value as needed

    # Step 6.5: Create a window with a fixed size
    cv2.namedWindow("YOLOv5 on Superfighters Deluxe", cv2.WINDOW_NORMAL)
    cv2.resizeWindow("YOLOv5 on Superfighters Deluxe", 800, 600)

    with mss.mss() as sct:
        while True:
            iteration_start_time = time.time()

            game_window = gw.getWindowsWithTitle('Superfighters Deluxe')
            if game_window:
                game_window = game_window[0]
                ctypes.windll.user32.ShowWindow(game_window._hWnd, 9)  # SW_RESTORE
                ctypes.windll.user32.SetForegroundWindow(game_window._hWnd)

            monitor = {"top": game_window.top, "left": game_window.left, "width": game_window.width, "height": game_window.height}
            frame = np.array(sct.grab(monitor))

            # Resize the frame to a smaller size
            resized_frame = cv2.resize(frame, (800, 600))  # Adjust dimensions as needed

            # Real-Time Detection Loop on the resized frame
            results = model.model(resized_frame)
            labels, cord = results.xyxy[0][:, -1], results.xyxy[0][:, :-1]

            for i, detection in enumerate(cord):
                x, y, w, h = detection[:4]
                x1, y1, x2, y2 = int(x), int(y), int(w), int(h)

                label_index = int(labels[i])
                label_name = model.class_names[label_index]
                color = model.class_colors.get(label_name, (0, 0, 0))  # Default to black if class color is not defined

                cv2.rectangle(resized_frame, (x1, y1), (x2, y2), color, 2)
                cv2.putText(resized_frame, label_name, (x1, y1), cv2.FONT_HERSHEY_SIMPLEX, 0.9, color, 2)

            # Show the resized frame (comment this line if not needed)
            cv2.imshow("YOLOv5 on Superfighters Deluxe", resized_frame)

            frames += 1

            if time.time() - start_time > 3:
                fps = calculate_fps(start_time, frames)
                print(f"Frames per second: {fps:.2f}")
                start_time = time.time()
                frames = 0

            iteration_time = time.time() - iteration_start_time

            remaining_time = max(0, target_frame_time - iteration_time)
            delay_time = remaining_time + 0.001
            time.sleep(delay_time)

            key = cv2.waitKey(1)

            if key == ord("q"):
                cv2.destroyAllWindows()
                break

if __name__ == "__main__":
    main()


And here are the simulating actions

def simulate_action(action):
    if action == 0:
        # Randomly choose between Jump / ClimbLadder and Move to the Left or Move to the Right
        if np.random.rand() < 0.5:
            pydirectinput.keyDown('up')  
            pydirectinput.keyDown('left')
            logger.info("Simulating action: Jump / ClimbLadder and Move to the Left")
        else:
            pydirectinput.keyDown('up')
            pydirectinput.keyDown('right')
            logger.info("Simulating action: Jump / ClimbLadder and Move to the Right")
    elif action == 1:
        pydirectinput.keyDown('down')  # Crouch / SlideDownLadder
        logger.info("Simulating action: Crouch / SlideDownLadder")
    elif action == 2:
        # Move to the left
        pydirectinput.keyDown('left')
        logger.info("Simulating action: Move to the left")
    elif action == 3:
        # Move to the right
        pydirectinput.keyDown('right')
        logger.info("Simulating action: Move to the right")

    time.sleep(0.1)

    keys_to_release = ['up', 'down', 'left', 'right', 'd', 'a', 's', 'shift']
    keys_to_release.extend(map(str, range(1, 6)))
    keys_to_release.extend(['left', 'right', 'down', 'f'])

    for key in keys_to_release:
        pydirectinput.keyUp(key)