hashir-Ali's picture
Upload folder using huggingface_hub
f386f57 verified
import pygame
import numpy as np
import Main2
import importlib
import time
importlib.reload(Main2)
class RocketLandingGameRunner:
def __init__(self, width=800, height=600, render=False):
"""Initialize the game runner with screen dimensions and rendering option."""
self.width = width
self.height = height
self.step_duration = 0.1 # Time step for each action
self.frame_time = 1.0 / 60 # Frame time for rendering (60 FPS)
self.white = (255, 255, 255)
self.render_enabled = render
self.game = Main2.RocketLandingGame(self.render_enabled) # Initialize the RocketLandingGame instance
# Define state and action spaces
self.state_space = {
'x': (0, self.width), # Position x
'y': (0, self.height), # Position y
'velocity_x': (-50, 50), # Velocity bounds (adjust as needed)
'velocity_y': (-50, 50),
'angle': (-180, 180) # Angle in degrees
}
self.action_space = [0, 1, 2, 3] # 0: Nothing, 1: Thrust, 2: Rotate left, 3: Rotate right
def reset(self):
"""Reset the game to initial state and return initial state."""
self.game.rocket = Main2.Rocket()
self.game.game_over = False
self.game.win = False
self.game.running = True
self.game.action_log = []
return self._get_state()
def _get_state(self):
"""Return the current state as a numpy array without exponent format."""
state = np.array([
self.game.rocket.x,
self.game.rocket.y,
self.game.rocket.velocity_x,
self.game.rocket.velocity_y,
self.game.rocket.angle
], dtype=np.float32)
return np.round(state, 1)
def step(self, action):
"""Take an action, update the game, and return (next_state, reward, done, info)."""
# Map action to game inputs
thrusting = (action == 1)
rotate_left = (action == 2)
rotate_right = (action == 3)
# Log the action
if action == 1:
self.game.add_to_action_log("Thrust activated.")
elif action == 2:
self.game.add_to_action_log("Rotation left.")
elif action == 3:
self.game.add_to_action_log("Rotation right.")
else:
self.game.add_to_action_log("Doing nothing.")
# Update game state for one step
reward, game_over, win = self.game.game_step(thrusting, rotate_left, rotate_right, time_step=self.step_duration)
# Get next state
next_state = self._get_state()
# Determine done flag
done=game_over
# Info dictionary for additional data
info = {'win': win, 'action_log': self.game.action_log[-1]}
# Render if enabled
if self.render_enabled:
self._render()
return next_state, reward, done
def _render(self):
"""Render the game state."""
self.game.screen.fill(self.white)
self.game.draw_terrain()
self.game.rocket.draw(self.game.screen)
self.game.draw_info()
if self.game.game_over:
if self.game.win:
win_text = pygame.font.SysFont('Arial', 40).render(
"You Landed Safely!", True, (0, 128, 0)
)
self.game.screen.blit(
win_text, (self.width // 2 - win_text.get_width() // 2, self.height // 2 - 100)
)
else:
crash_text = pygame.font.SysFont('Arial', 40).render(
"Crash! Try Again.", True, (255, 0, 0)
)
self.game.screen.blit(
crash_text, (self.width // 2 - crash_text.get_width() // 2, self.height // 2 - 100)
)
self.game.draw_restart_button()
if self.render_enabled:
pygame.display.update()
self.game.clock.tick(30)
pygame.event.pump()
def run(self, agent=None):
if agent is None:
# Original human-controlled game loop
while self.game.running:
step_start_time = time.time()
thrusting = False
rotate_left = False
rotate_right = False
reset_game = False
action_logged = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.game.running = False
if event.type == pygame.MOUSEBUTTONDOWN and self.game.game_over:
mouse_pos = pygame.mouse.get_pos()
if self.game.draw_restart_button().collidepoint(mouse_pos):
reset_game = True
self.game.add_to_action_log("Game reset by user.")
action_logged = True
if not self.game.game_over and not reset_game:
keys = pygame.key.get_pressed()
if keys[pygame.K_w] and not action_logged:
thrusting = True
self.game.add_to_action_log("Thrust activated.")
action_logged = True
elif keys[pygame.K_a] and not action_logged:
rotate_left = True
self.game.add_to_action_log("Rotation left.")
action_logged = True
elif keys[pygame.K_d] and not action_logged:
rotate_right = True
self.game.add_to_action_log("Rotation right.")
action_logged = True
elif keys[pygame.K_r] and not action_logged:
reset_game = True
self.game.add_to_action_log("Game reset by 'R' key.")
action_logged = True
if not action_logged:
self.game.add_to_action_log("Doing nothing.")
if reset_game:
self.reset()
while time.time() - step_start_time < self.step_duration:
if not reset_game and not self.game.game_over:
reward, game_over, win = self.game.game_step(
thrusting, rotate_left, rotate_right, time_step=self.frame_time
)
print(reward)
else:
reward, game_over, win = 0, self.game.game_over, self.game.win
if self.render_enabled:
self._render()
print("\nAction Log:")
for entry in self.game.action_log:
print(entry)
pygame.quit()
else:
# RL agent-controlled loop
state = self.reset()
total_reward = 0
np.set_printoptions(suppress=True)
while self.game.running:
# if self.render_enabled:
state_input = np.expand_dims(state, axis=0) # make it shape (1,5)
action_values = agent(state_input) # get q_values
action = np.argmax(action_values.numpy()[0]) # pick best action
# action = np.random.choice(self.action_space)
next_state, reward, done = self.step(action)
total_reward += reward
# agent.update(state, action, reward, next_state, done) # Update agent's policy
state = next_state
if done:
break
start_time = time.time()
button_rect = self.game.draw_restart_button()
# Keep checking for mouse events during the 5-second window
while time.time() - start_time < 5:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pos = event.pos
if button_rect.collidepoint(mouse_pos):
# If the restart button is clicked, restart the game
game_runner2 = RocketLandingGameRunner(width=800, height=600, render=True)
game_runner2.run(agent)
return # Exit to avoid pygame.quit() being called twice
elif event.type == pygame.QUIT:
pygame.quit()
return
pygame.display.update() # Make sure the display is updated
# If no click within 5 seconds, quit the game
pygame.quit()
def get_action_log(self):
"""Return the current action log."""
return self.game.action_log