From dce64e5d3ffd5aab089afc256daa2ef37a730f6a Mon Sep 17 00:00:00 2001 From: csd4ni3l Date: Sun, 16 Nov 2025 21:27:21 +0100 Subject: [PATCH] Add 10 million timestep model, improve README, add diffculty/mode selector, score, make model training have instant graphs and also multiple envs for faster training, better plotting, improve RL model by including multiple players, better reard system, use EnemyFormation instead of single Enemy-es --- README.md | 9 +- game/play.py | 118 ++++++++++------ game/sprites.py | 136 +++++++++++++++--- invader_agent.zip | Bin 0 -> 163023 bytes menus/main.py | 4 +- menus/mode_selector.py | 72 ++++++++++ menus/train_model.py | 209 ++++++++++++++++++---------- run.py | 2 +- utils/constants.py | 59 ++++++-- utils/rl.py | 308 ++++++++++++++++++++++++----------------- 10 files changed, 644 insertions(+), 273 deletions(-) create mode 100644 invader_agent.zip create mode 100644 menus/mode_selector.py diff --git a/README.md b/README.md index 732770e..4c24e96 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ Fleet Commander is like Space Invaders but you are the enemy instead of the play It uses AI (Reinforcement Learning) for the Player, and you, the Enemy has to defeat it. -You can train yourself, or use the default model which comes with the game. +I know the game is too easy and is too simple, but please understand that doing RL isnt the easiest thing ever. I also did this so late so yeah. + +You can train yourself, or use the default model(10 million timesteps) which comes with the game. # Install steps: @@ -18,4 +20,7 @@ You can train yourself, or use the default model which comes with the game. - `pip3 install -r requirements.txt` - `pip3 install torch --index-url https://download.pytorch.org/whl/cpu` - `pip3 install stable_baselines3` -- `python3 run.py` \ No newline at end of file +- `python3 run.py` + +# Disclaimer +AI assistance was used in this project, since i never did any RL work before. But every instance of AI code was heavily modified by me. \ No newline at end of file diff --git a/game/play.py b/game/play.py index 8601b32..f239526 100644 --- a/game/play.py +++ b/game/play.py @@ -1,16 +1,17 @@ import arcade, arcade.gui, random, time -from utils.constants import button_style, ENEMY_ROWS, ENEMY_COLS, PLAYER_ATTACK_SPEED +from utils.constants import button_style, ENEMY_ATTACK_SPEED, ENEMY_SPEED from utils.preload import button_texture, button_hovered_texture from stable_baselines3 import PPO -from game.sprites import Enemy, Player, Bullet +from game.sprites import EnemyFormation, Player, Bullet class Game(arcade.gui.UIView): - def __init__(self, pypresence_client): + def __init__(self, pypresence_client, settings): super().__init__() + self.settings = settings self.pypresence_client = pypresence_client self.pypresence_client.update(state="Invading Space") @@ -18,42 +19,53 @@ class Game(arcade.gui.UIView): self.spritelist = arcade.SpriteList() - self.player = Player(self.window.width / 2 + random.randint(int(-self.window.width / 3), int(self.window.width / 3)), 100) # not actually player - self.spritelist.append(self.player) - - self.last_player_shoot = time.perf_counter() # not actually player + self.players = [] + for _ in range(settings["player_count"]): + self.players.append(Player(self.window.width / 2 + random.randint(int(-self.window.width / 3), int(self.window.width / 3)), 100)) # not actually player + self.spritelist.append(self.players[-1]) self.model = PPO.load("invader_agent.zip") - self.enemies: list[Enemy] = [] + self.enemy_formation = EnemyFormation(self.window.width / 2 + random.randint(int(-self.window.width / 3), int(self.window.width / 3)), self.window.height * 0.9, self.spritelist, settings["enemy_rows"], settings["enemy_cols"]) self.player_bullets: list[Bullet] = [] self.enemy_bullets: list[Bullet] = [] - self.summon_enemies() + self.player_respawns = settings["player_respawns"] + self.enemy_respawns = settings["enemy_respawns"] + + self.score = 0 + + self.last_enemy_shoot = time.perf_counter() + + self.game_over = False def on_show_view(self): super().on_show_view() self.back_button = self.anchor.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text='<--', style=button_style, width=100, height=50), anchor_x="left", anchor_y="top", align_x=5, align_y=-5) self.back_button.on_click = lambda event: self.main_exit() + self.score_label = self.anchor.add(arcade.gui.UILabel("Score: 0", font_size=24), anchor_x="center", anchor_y="top") def main_exit(self): from menus.main import Main self.window.show_view(Main(self.pypresence_client)) - def summon_enemies(self): - enemy_start_x = self.window.width * 0.15 - enemy_start_y = self.window.height * 0.9 - - for row in range(ENEMY_ROWS): - for col in range(ENEMY_COLS): - enemy_sprite = Enemy(enemy_start_x + col * 100, enemy_start_y - row * 100) - self.spritelist.append(enemy_sprite) - self.enemies.append(enemy_sprite) - def on_update(self, delta_time): - for enemy in self.enemies: - enemy.update() + if self.game_over: + return + + if self.window.keyboard[arcade.key.LEFT] or self.window.keyboard[arcade.key.A]: + self.enemy_formation.move(self.window.width, self.window.height, "x", -ENEMY_SPEED) + if self.window.keyboard[arcade.key.RIGHT] or self.window.keyboard[arcade.key.D]: + self.enemy_formation.move(self.window.width, self.window.height, "x", ENEMY_SPEED) + if self.window.keyboard[arcade.key.DOWN] or self.window.keyboard[arcade.key.S]: + self.enemy_formation.move(self.window.width, self.window.height, "y", -ENEMY_SPEED) + if self.window.keyboard[arcade.key.UP] or self.window.keyboard[arcade.key.W]: + self.enemy_formation.move(self.window.width, self.window.height, "y", ENEMY_SPEED) + if self.enemy_formation.enemies and self.window.keyboard[arcade.key.SPACE] and time.perf_counter() - self.last_enemy_shoot >= ENEMY_ATTACK_SPEED: + self.last_enemy_shoot = time.perf_counter() + enemy = self.enemy_formation.get_lowest_enemy() + self.shoot(enemy.center_x, enemy.center_y, -1) bullets_to_remove = [] @@ -62,18 +74,21 @@ class Game(arcade.gui.UIView): bullet_hit = False if bullet.direction_y == 1: - for enemy in self.enemies: + for enemy in self.enemy_formation.enemies: if bullet.rect.intersection(enemy.rect): - self.spritelist.remove(enemy) - self.enemies.remove(enemy) - self.player.target = None + self.enemy_formation.remove_enemy(enemy) bullets_to_remove.append(bullet) bullet_hit = True break else: - if bullet.rect.intersection(self.player.rect): - bullets_to_remove.append(bullet) - bullet_hit = True + for player in self.players: + if bullet.rect.intersection(player.rect): + self.spritelist.remove(player) + self.players.remove(player) + bullets_to_remove.append(bullet) + bullet_hit = True + self.score += 75 + break if not bullet_hit and bullet.center_y > self.window.height or bullet.center_y < 0: bullets_to_remove.append(bullet) @@ -86,20 +101,40 @@ class Game(arcade.gui.UIView): elif bullet_to_remove in self.player_bullets: self.player_bullets.remove(bullet_to_remove) - self.player.update(self.model, self.enemies, self.enemy_bullets, self.window.width, self.window.height) # not actually player + for player in self.players: + player.update(self.model, self.enemy_formation, self.enemy_bullets, self.window.width, self.window.height, self.player_respawns / self.settings["player_respawns"], self.enemy_respawns / self.settings["enemy_respawns"]) # not actually player - if self.player.center_x > self.window.width: - self.player.center_x = self.window.width - elif self.player.center_x < 0: - self.player.center_x = 0 + if player.center_x > self.window.width: + player.center_x = self.window.width + elif player.center_x < 0: + player.center_x = 0 - if self.player.shoot: - self.player.shoot = False - self.shoot(self.player.center_x, self.player.center_y, 1) + if player.shoot: + player.shoot = False + self.shoot(player.center_x, player.center_y, 1) - if time.perf_counter() - self.last_player_shoot >= PLAYER_ATTACK_SPEED: - self.last_player_shoot = time.perf_counter() - self.shoot(self.player.center_x, self.player.center_y, 1) + if len(self.players) == 0: + if self.player_respawns > 0: + self.player_respawns -= 1 + for _ in range(self.settings["player_count"]): + self.players.append(Player(self.window.width / 2 + random.randint(int(-self.window.width / 3), int(self.window.width / 3)), 100)) # not actually player + self.spritelist.append(self.players[-1]) + self.score += 300 + else: + self.game_over = True + self.game_over_label = self.anchor.add(arcade.gui.UILabel("You (The enemies) won!", font_size=48), anchor_x="center", anchor_y="center") + + elif len(self.enemy_formation.enemies) == 0: + if self.enemy_respawns > 0: + self.enemy_respawns -= 1 + self.enemy_formation.create_formation(self.window.width / 2 + random.randint(int(-self.window.width / 3), int(self.window.width / 3)), self.window.height * 0.9) + else: + self.game_over = True + self.game_over_label = self.anchor.add(arcade.gui.UILabel("You lost! The Players win!", font_size=48), anchor_x="center", anchor_y="center") + + self.score += 5 * delta_time + + self.score_label.text = f"Score: {int(self.score)}" def shoot(self, x, y, direction_y): bullet = Bullet(x, y, direction_y) @@ -112,11 +147,6 @@ class Game(arcade.gui.UIView): bullets.append(bullet) - def on_key_press(self, symbol, modifiers): - if symbol == arcade.key.SPACE: - enemy = random.choice(self.enemies) - self.shoot(enemy.center_x, enemy.center_y, -1) - def on_draw(self): super().on_draw() diff --git a/game/sprites.py b/game/sprites.py index 2de03f9..b3accec 100644 --- a/game/sprites.py +++ b/game/sprites.py @@ -1,10 +1,8 @@ -import arcade, time +import arcade, time, random, numpy as np from stable_baselines3 import PPO -import numpy as np - -from utils.constants import PLAYER_SPEED, BULLET_SPEED, BULLET_RADIUS, PLAYER_ATTACK_SPEED, ENEMY_COLS, ENEMY_ROWS +from utils.constants import PLAYER_SPEED, BULLET_SPEED, BULLET_RADIUS, PLAYER_ATTACK_SPEED from utils.preload import player_texture, enemy_texture class Bullet(arcade.Sprite): @@ -16,9 +14,100 @@ class Bullet(arcade.Sprite): def update(self): self.center_y += self.direction_y * BULLET_SPEED -class Enemy(arcade.Sprite): - def __init__(self, x, y): - super().__init__(enemy_texture, center_x=x, center_y=y) +class EnemyFormation(): + def __init__(self, start_x, start_y, spritelist: arcade.SpriteList | None, rows, cols): + self.grid = [[] for _ in range(rows)] + self.start_x = start_x + self.start_y = start_y + self.rows = rows + self.cols = cols + self.spritelist = spritelist + + self.create_formation() + + def create_formation(self, start_x=None, start_y=None): + if start_x: + self.start_x = start_x + if start_y: + self.start_y = start_y + + del self.grid + self.grid = [[] for _ in range(self.rows)] + + for row in range(self.rows): + for col in range(self.cols): + enemy_sprite = arcade.Sprite(enemy_texture, center_x=self.start_x + col * 100, center_y=self.start_y - row * 100) + + if self.spritelist: + self.spritelist.append(enemy_sprite) + + self.grid[row].append(enemy_sprite) + + def remove_enemy(self, enemy): + if self.spritelist and enemy not in self.spritelist: + return + + for row in range(self.rows): + for col in range(self.cols): + if self.grid[row][col] == enemy: + self.grid[row][col] = None + if self.spritelist: + self.spritelist.remove(enemy) + return + + def get_lowest_enemy(self): + valid_cols = [] + + for col in range(self.cols): + row = self.rows - 1 + + while row >= 0 and self.grid[row][col] is None: + row -= 1 + + if row >= 0: + valid_cols.append((col, row)) + + if not valid_cols: + return None + + col, row = random.choice(valid_cols) + return self.grid[row][col] + + def move(self, width, height, direction_type, value): + if direction_type == "x": + wall_hit = False + for enemy in self.enemies: + self.start_x += value + enemy.center_x += value + + if enemy.center_x + enemy.width / 2 > width or enemy.center_x < enemy.width / 2: + wall_hit = True + + if wall_hit: + for enemy in self.enemies: + self.start_x -= value + enemy.center_x -= value + else: + wall_hit = False + for enemy in self.enemies: + self.start_x += value + enemy.center_y += value + + if enemy.center_y + enemy.height / 2 > height or enemy.center_y < enemy.height / 2: + wall_hit = True + + if wall_hit: + for enemy in self.enemies: + self.start_y -= value + enemy.center_y -= value + + @property + def center_x(self): + return self.start_x + (self.cols / 2) * 100 + + @property + def enemies(self): + return [col for row in self.grid for col in row if not col == None] class Player(arcade.Sprite): # Not actually the player def __init__(self, x, y): @@ -26,21 +115,19 @@ class Player(arcade.Sprite): # Not actually the player self.last_target_change = time.perf_counter() self.last_shoot = time.perf_counter() - self.target = None self.shoot = False - self.player_speed = 0 - def update(self, model: PPO, enemies, bullets, width, height): - if enemies: - nearest_enemy = min(enemies, key=lambda e: abs(e.center_x - self.center_x)) + def update(self, model: PPO, enemy_formation, bullets, width, height, player_respawns_norm, enemy_respawns_norm): + if enemy_formation.enemies: + nearest_enemy = min(enemy_formation.enemies, key=lambda e: abs(e.center_x - self.center_x)) enemy_x = (nearest_enemy.center_x - self.center_x) / width enemy_y = (nearest_enemy.center_y - self.center_y) / height else: enemy_x = 2 enemy_y = 2 - enemy_count = len(enemies) / float(max(1, ENEMY_ROWS * ENEMY_COLS)) + enemy_count = len(enemy_formation.enemies) / float(max(1, enemy_formation.rows * enemy_formation.cols)) player_x_norm = self.center_x / width curr_bullet = min(bullets, key=lambda b: abs(b.center_x - self.center_x) + abs(b.center_y - self.center_y)) if bullets else None @@ -51,18 +138,31 @@ class Player(arcade.Sprite): # Not actually the player curr_bx = 2.0 curr_by = 2.0 - lowest = max(enemies, key=lambda e: e.center_y) if enemies else None + lowest = max(enemy_formation.enemies, key=lambda e: e.center_y) if enemy_formation.enemies else None if lowest is not None: lowest_dy = (lowest.center_y - self.center_y) / float(height) else: lowest_dy = 2.0 enemy_dispersion = 0.0 - if enemies: - xs = np.array([e.center_x for e in enemies], dtype=np.float32) + if enemy_formation.enemies: + xs = np.array([e.center_x for e in enemy_formation.enemies], dtype=np.float32) enemy_dispersion = float(xs.std()) / float(width) - obs = np.array([player_x_norm, enemy_x, enemy_y, lowest_dy, curr_bx, curr_by, self.player_speed, enemy_count, enemy_dispersion], dtype=np.float32) + obs = np.array([ + player_x_norm, + enemy_x, + enemy_y, + lowest_dy, + curr_bx, + curr_by, + self.player_speed, + enemy_count, + enemy_dispersion, + time.perf_counter() - self.last_shoot >= PLAYER_ATTACK_SPEED, + player_respawns_norm, + enemy_respawns_norm + ], dtype=np.float32) action, _ = model.predict(obs, deterministic=True) self.prev_x = self.center_x @@ -71,6 +171,8 @@ class Player(arcade.Sprite): # Not actually the player elif action == 1: self.center_x += PLAYER_SPEED elif action == 2: + pass + elif action == 3: t = time.perf_counter() if t - self.last_shoot >= PLAYER_ATTACK_SPEED: self.last_shoot = t diff --git a/invader_agent.zip b/invader_agent.zip new file mode 100644 index 0000000000000000000000000000000000000000..49979f266d050812263ed20334e609831f87bb5e GIT binary patch literal 163023 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
PRhs8;j>>2G#!O_M{9;h( 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Ξ!$6S%b@D`12AUFJ~(Lbk=v}F%`s5gRYv=bA(> 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%0Ar)HODP^A+S!OK87G+$yd)z=t|@;9j> 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

$7_eS2GS4#msu?2h6?IXW3$%>)5;QD6^z+ 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

A;j|gm$ffI)T^HI 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 SsMHft=^>(V&E1X5ng0N^+07dO literal 0 HcmV?d00001 diff --git a/menus/main.py b/menus/main.py index 4342026..129d385 100644 --- a/menus/main.py +++ b/menus/main.py @@ -62,8 +62,8 @@ class Main(arcade.gui.UIView): self.settings_button.on_click = lambda event: self.settings() def play(self): - from game.play import Game - self.window.show_view(Game(self.pypresence_client)) + from menus.mode_selector import ModeSelector + self.window.show_view(ModeSelector(self.pypresence_client)) def settings(self): from menus.settings import Settings diff --git a/menus/mode_selector.py b/menus/mode_selector.py new file mode 100644 index 0000000..def34fb --- /dev/null +++ b/menus/mode_selector.py @@ -0,0 +1,72 @@ +import arcade, arcade.gui + +from utils.preload import button_texture, button_hovered_texture +from utils.constants import dropdown_style, button_style, DIFFICULTY_LEVELS, DIFFICULTY_SETTINGS + +class ModeSelector(arcade.gui.UIView): + def __init__(self, pypresence_client): + super().__init__() + + self.pypresence_client = pypresence_client + self.pypresence_client.update(state="Selecting Mode") + + self.anchor = self.add_widget(arcade.gui.UIAnchorLayout(size_hint=(1, 1))) + self.box = self.anchor.add(arcade.gui.UIBoxLayout(size_hint=(0.75, 0.75), space_between=10), anchor_x="center", anchor_y="center") + + self.settings = DIFFICULTY_LEVELS["Easy"] + self.setting_sliders = {} + self.setting_labels = {} + + def on_show_view(self): + super().on_show_view() + + self.back_button = self.anchor.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text='<--', style=button_style, width=100, height=50), anchor_x="left", anchor_y="top", align_x=5, align_y=-5) + self.back_button.on_click = lambda event: self.main_exit() + + self.box.add(arcade.gui.UILabel("Settings", font_size=32)) + + self.box.add(arcade.gui.UISpace(height=self.window.height / 80)) + + self.difficulty_selector = self.box.add(arcade.gui.UIDropdown(default="Easy", options=list(DIFFICULTY_LEVELS.keys()), active_style=dropdown_style, primary_style=dropdown_style, dropdown_style=dropdown_style, width=self.window.width / 2, height=self.window.height / 20)) + self.difficulty_selector.on_change = lambda event: self.set_difficulty_values(event.new_value) + + self.box.add(arcade.gui.UISpace(height=self.window.height / 80)) + + for key, data in DIFFICULTY_SETTINGS.items(): + default, name, min_value, max_value = DIFFICULTY_LEVELS["Easy"][key], *data + + label = self.box.add(arcade.gui.UILabel(text=f"{name}: {default}", font_size=14)) + + slider = self.box.add(arcade.gui.UISlider(value=default, min_value=min_value, max_value=max_value, step=1, width=self.window.width / 2, height=self.window.height / 25)) + slider._render_steps = lambda surface: None + slider.on_event = lambda event: None # disable slider for difficulties + slider.on_click = lambda event: None # disable slider for difficulties + slider.on_change = lambda e, key=key: self.change_value(key, e.new_value) + + self.setting_sliders[key] = slider + self.setting_labels[key] = label + + self.play_button = self.box.add(arcade.gui.UITextureButton(text="Play", width=self.window.width / 2, height=self.window.height / 15, texture=button_texture, texture_hovered=button_hovered_texture, style=button_style)) + self.play_button.on_click = lambda event: self.start_game() + + def set_difficulty_values(self, difficulty): + for key, value in DIFFICULTY_LEVELS[difficulty].items(): + self.settings[key] = value + self.setting_labels[key].text = f"{DIFFICULTY_SETTINGS[key][0]}: {value}" + self.setting_sliders[key].value = value + + for slider in self.setting_sliders.values(): + if difficulty != "Custom": + slider.on_event = lambda event: None + slider.on_click = lambda event: None + else: + slider.on_event = lambda event, slider=slider: arcade.gui.UISlider.on_event(slider, event) + slider.on_click = lambda event, slider=slider: arcade.gui.UISlider.on_click(slider, event) + + def change_value(self, key, value): + self.settings[key] = int(value) + self.setting_labels[key].text = f"{DIFFICULTY_SETTINGS[key][0]}: {int(value)}" + + def start_game(self): + from game.play import Game + self.window.show_view(Game(self.pypresence_client, self.settings)) \ No newline at end of file diff --git a/menus/train_model.py b/menus/train_model.py index f8921bd..b6fc6f6 100644 --- a/menus/train_model.py +++ b/menus/train_model.py @@ -1,20 +1,26 @@ -import arcade, arcade.gui, threading, io, os, time +import arcade, arcade.gui, threading, os, queue, time, shutil + +import matplotlib.pyplot as plt +import pandas as pd from utils.constants import button_style, MODEL_SETTINGS, monitor_log_dir from utils.preload import button_texture, button_hovered_texture +from utils.rl import SpaceInvadersEnv -import matplotlib.pyplot as plt -import numpy as np -import pandas as pd - -from io import BytesIO from PIL import Image +from io import BytesIO from stable_baselines3 import PPO from stable_baselines3.common.monitor import Monitor from stable_baselines3.common.logger import configure +from stable_baselines3.common.vec_env import DummyVecEnv -from utils.rl import SpaceInvadersEnv +def make_env(rank: int, seed: int = 0): + def _init(): + env = SpaceInvadersEnv() + env = Monitor(env, filename=os.path.join(monitor_log_dir, f"monitor_{rank}.csv")) + return env + return _init class TrainModel(arcade.gui.UIView): def __init__(self, pypresence_client): @@ -24,22 +30,25 @@ class TrainModel(arcade.gui.UIView): self.pypresence_client.update(state="Model Training") self.anchor = self.add_widget(arcade.gui.UIAnchorLayout(size_hint=(1, 1))) - self.box = self.anchor.add(arcade.gui.UIBoxLayout(space_between=10)) + self.box = self.anchor.add(arcade.gui.UIBoxLayout(space_between=5)) self.settings = { - setting: data[0] # default value + setting: data[0] for setting, data in MODEL_SETTINGS.items() } + self.labels = {} self.training = False - self.training_text = "" + self.training_text = "Starting training..." + + self.result_queue = queue.Queue() + self.training_thread = None self.last_progress_update = time.perf_counter() def on_show_view(self): super().on_show_view() - self.show_menu() def main_exit(self): @@ -50,128 +59,188 @@ class TrainModel(arcade.gui.UIView): self.back_button = self.anchor.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text='<--', style=button_style, width=100, height=50), anchor_x="left", anchor_y="top", align_x=5, align_y=-5) self.back_button.on_click = lambda event: self.main_exit() - self.box.add(arcade.gui.UILabel("Settings", font_size=36)) + self.box.add(arcade.gui.UILabel("Settings", font_size=32)) for setting, data in MODEL_SETTINGS.items(): default, min_value, max_value, step = data - label = self.box.add(arcade.gui.UILabel(text=f"{setting.replace('_', ' ').capitalize()}: {default}", font_size=18)) + is_int = setting == "n_envs" or (abs(step - 1) < 1e-6 and abs(min_value - round(min_value)) < 1e-6) + + val_text = str(int(default)) if is_int else str(default) + label = self.box.add(arcade.gui.UILabel(text=f"{setting.replace('_', ' ').capitalize()}: {val_text}", font_size=14)) slider = self.box.add(arcade.gui.UISlider(value=default, min_value=min_value, max_value=max_value, step=step, width=self.window.width / 2, height=self.window.height / 25)) slider._render_steps = lambda surface: None - slider.on_change = lambda e, key=setting: self.change_value(key, e.new_value) + slider.on_change = lambda e, key=setting, is_int_slider=is_int: self.change_value(key, e.new_value, is_int_slider) self.labels[setting] = label train_button = self.box.add(arcade.gui.UITextureButton(width=self.window.width / 2, height=self.window.height / 10, text="Train", style=button_style, texture=button_texture, texture_hovered=button_hovered_texture)) train_button.on_click = lambda e: self.start_training() - def change_value(self, key, value): - self.labels[key].text = f"{key.replace('_', ' ').capitalize()}: {self.round_near_int(value)}" - self.settings[key] = self.round_near_int(value) + def change_value(self, key, value, is_int=False): + if is_int: + val = int(round(value)) + self.settings[key] = val + self.labels[key].text = f"{key.replace('_', ' ').capitalize()}: {val}" + else: + val = self.round_near_int(value) + self.settings[key] = val + self.labels[key].text = f"{key.replace('_', ' ').capitalize()}: {val}" def start_training(self): self.box.clear() - self.training = True - - self.training_label = self.box.add(arcade.gui.UILabel("No Output yet.", font_size=16, multiline=True, width=self.window.width / 2, height=self.window.height / 2)) + self.training_text = "Starting training..." + self.training_label = self.box.add(arcade.gui.UILabel("Starting training...", font_size=16, multiline=True, width=self.window.width / 2, height=self.window.height / 2)) self.plot_image_widget = self.box.add(arcade.gui.UIImage(texture=arcade.Texture.create_empty("empty", (1, 1)))) self.plot_image_widget.visible = False - threading.Thread(target=self.train, daemon=True).start() + self.training_thread = threading.Thread(target=self.train, daemon=True) + self.training_thread.start() def on_update(self, delta_time): - if self.training and os.path.exists(os.path.join("training_logs", "progress.csv")) and time.perf_counter() - self.last_progress_update >= 0.5: - self.last_progress_update = time.perf_counter() + try: + result = self.result_queue.get_nowait() - try: - progress_df = pd.read_csv(os.path.join("training_logs", "progress.csv")) - except pd.errors.EmptyDataError: - return + if result["type"] == "text": + self.training_text = result["message"] - progress_text = "" + elif result["type"] == "plot": + self.plot_image_widget.texture = result["image"] + self.plot_image_widget.width = result["image"].width + self.plot_image_widget.height = result["image"].height + self.plot_image_widget.trigger_render() + self.plot_image_widget.visible = True - for key, value in progress_df.items(): - progress_text += f"{key}: {round(value.iloc[-1], 6)}\n" + elif result["type"] == "finished": + self.training = False + self.training_text = "Training finished." - self.training_text = progress_text + except queue.Empty: + if self.training and os.path.exists(os.path.join("training_logs", "progress.csv")) and all([os.path.exists(os.path.join(monitor_log_dir, f"monitor_{i}.csv.monitor.csv")) for i in range(int(self.settings["n_envs"]))]) and time.perf_counter() - self.last_progress_update >= 1: + self.last_progress_update = time.perf_counter() + self.plot_results() if hasattr(self, "training_label"): self.training_label.text = self.training_text def round_near_int(self, x, tol=1e-4): nearest = round(x) + if abs(x - nearest) < tol: return nearest + return x def train(self): - os.makedirs(monitor_log_dir, exist_ok=True) - env = Monitor(SpaceInvadersEnv(), filename=os.path.join(monitor_log_dir, "monitor.csv")) + if os.path.exists(monitor_log_dir): + shutil.rmtree(monitor_log_dir) + os.makedirs(monitor_log_dir) + + n_envs = int(self.settings["n_envs"]) + env = DummyVecEnv([make_env(i) for i in range(n_envs)]) + + n_steps = int(self.settings["n_steps"]) + batch_size = int(self.settings["batch_size"]) + + total_steps_per_rollout = n_steps * max(1, n_envs) + if total_steps_per_rollout % batch_size != 0: + batch_size = max(64, total_steps_per_rollout // max(1, total_steps_per_rollout // batch_size)) + print(f"Warning: Adjusting batch size to {batch_size} for {n_envs} envs.") model = PPO( - "MlpPolicy", - env, - n_steps=self.settings["n_steps"], - batch_size=self.settings["batch_size"], - n_epochs=self.settings["n_epochs"], - learning_rate=self.settings["learning_rate"], + "MlpPolicy", + env, + n_steps=n_steps, + batch_size=batch_size, + n_epochs=int(self.settings["n_epochs"]), + learning_rate=float(self.settings["learning_rate"]), verbose=1, device="cpu", - gamma=self.settings["gamma"], - ent_coef=self.settings["ent_coef"], - clip_range=self.settings["clip_range"], + gamma=float(self.settings["gamma"]), + ent_coef=float(self.settings["ent_coef"]), + clip_range=float(self.settings["clip_range"]), ) - new_logger = configure( - folder=monitor_log_dir, format_strings=["csv"] - ) - + new_logger = configure(folder=monitor_log_dir, format_strings=["csv"]) model.set_logger(new_logger) - model.learn(self.settings["learning_steps"]) - model.save("invader_agent") + try: + self.training = True + model.learn(int(self.settings["learning_steps"])) + model.save("invader_agent") + except Exception as e: + print(f"Error during training: {e}") + self.result_queue.put({"type": "text", "message": f"Error:\n{e}"}) + finally: + try: + env.close() + except Exception: + pass + self.result_queue.put({"type": "finished"}) - self.training = False + def plot_results(self): + try: + reward_df = pd.read_csv(os.path.join(monitor_log_dir, "progress.csv")) + except pd.errors.EmptyDataError: + return - self.plot_results(os.path.join(monitor_log_dir, "monitor.csv"), os.path.join(monitor_log_dir, "progress.csv")) + all_monitor_files = [os.path.join(monitor_log_dir, f) for f in os.listdir(monitor_log_dir) if f.startswith("monitor_") and f.endswith(".csv")] + try: + df_list = [pd.read_csv(f, skiprows=1) for f in all_monitor_files] + except pd.errors.EmptyDataError: + return - def plot_results(self, log_path, loss_log_path): - df = pd.read_csv(log_path, skiprows=1) + monitor_df = pd.concat(df_list).sort_values(by='t') + monitor_df['total_timesteps'] = monitor_df['l'].cumsum() + + loss_log_path = os.path.join(monitor_log_dir, "progress.csv") + loss_df = None + if os.path.exists(loss_log_path): + try: + loss_df = pd.read_csv(loss_log_path) + except Exception: + loss_df = None fig, axes = plt.subplots(2, 1, figsize=(6, 8), dpi=100) - loss_df = pd.read_csv(loss_log_path) - - axes[0].plot(np.cumsum(df['l']), df['r'], label='Reward') + if monitor_df is not None and 'total_timesteps' in monitor_df.columns and 'r' in monitor_df.columns: + axes[0].plot(monitor_df['total_timesteps'], monitor_df['r'].rolling(window=10).mean(), label='Episodic Reward (Rolling 10)') + elif reward_df is not None and 'time/total_timesteps' in reward_df.columns and 'rollout/ep_rew_mean' in reward_df.columns: + axes[0].plot(reward_df['time/total_timesteps'], reward_df['rollout/ep_rew_mean'], label='Ep reward mean') + else: + axes[0].text(0.5, 0.5, "No reward data available", horizontalalignment='center', verticalalignment='center') + axes[0].set_title('PPO Training: Episodic Reward') axes[0].set_xlabel('Total Timesteps') axes[0].set_ylabel('Reward') axes[0].grid(True) - axes[1].plot(loss_df['time/total_timesteps'], loss_df['train/policy_gradient_loss'], label='Policy Gradient Loss') - axes[1].plot(loss_df['time/total_timesteps'], loss_df['train/value_loss'], label='Value Loss') - axes[1].plot(loss_df['time/total_timesteps'], loss_df['train/explained_variance'], label='Explained Variance') - axes[1].set_title('PPO Training: Loss Functions') + axes[1].set_title('PPO Training: Loss & Variance') axes[1].set_xlabel('Total Timesteps') - axes[1].set_ylabel('Loss Value') - axes[1].legend() + axes[1].set_ylabel('Value') axes[1].grid(True) - + + if loss_df is not None and 'time/total_timesteps' in loss_df.columns and 'train/policy_gradient_loss' in loss_df.columns and 'train/value_loss' in loss_df.columns and 'train/explained_variance' in loss_df.columns: + tcol = 'time/total_timesteps' + axes[1].plot(loss_df[tcol], loss_df['train/policy_gradient_loss'], label='Policy Loss') + axes[1].plot(loss_df[tcol], loss_df['train/value_loss'], label='Value Loss') + axes[1].plot(loss_df[tcol], loss_df['train/explained_variance'], label='Explained Variance') + + axes[1].legend() + else: + axes[1].text(0.5, 0.5, "No loss/variance data available", horizontalalignment='center', verticalalignment='center') + plt.tight_layout() buffer = BytesIO() - plt.savefig(buffer, format='png') + plt.savefig(buffer, format='png', bbox_inches='tight') buffer.seek(0) plt.close(fig) - plot_texture = arcade.Texture(Image.open(buffer)) + pil_img = Image.open(buffer).convert("RGBA") - self.plot_image_widget.texture = plot_texture - self.plot_image_widget.size_hint = (None, None) - self.plot_image_widget.width = plot_texture.width - self.plot_image_widget.height = plot_texture.height + plot_texture = arcade.Texture(pil_img) - self.plot_image_widget.visible = True - self.training_text = "Training finished. Plot displayed." \ No newline at end of file + self.result_queue.put({"type": "plot", "image": plot_texture}) diff --git a/run.py b/run.py index 4e4d4ff..76da604 100644 --- a/run.py +++ b/run.py @@ -29,7 +29,7 @@ timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") log_filename = f"debug_{timestamp}.log" logging.basicConfig(filename=f'{os.path.join(log_dir, log_filename)}', format='%(asctime)s %(name)s %(levelname)s: %(message)s', level=logging.DEBUG) -for logger_name_to_disable in ['arcade']: +for logger_name_to_disable in ['arcade', "matplotlib", "matplotlib.fontmanager", "PIL"]: logging.getLogger(logger_name_to_disable).propagate = False logging.getLogger(logger_name_to_disable).disabled = True diff --git a/utils/constants.py b/utils/constants.py index 68beb95..e226ba1 100644 --- a/utils/constants.py +++ b/utils/constants.py @@ -3,25 +3,68 @@ from arcade.types import Color from arcade.gui.widgets.buttons import UITextureButtonStyle, UIFlatButtonStyle from arcade.gui.widgets.slider import UISliderStyle -ENEMY_ROWS = 3 -ENEMY_COLS = 13 +ENEMY_SPEED = 5 +ENEMY_ATTACK_SPEED = 0.75 PLAYER_SPEED = 5 # not actually player PLAYER_ATTACK_SPEED = 0.75 -BULLET_SPEED = 3 -BULLET_RADIUS = 10 +BULLET_SPEED = 5 +BULLET_RADIUS = 15 # default, min, max, step MODEL_SETTINGS = { - "n_steps": [2048, 256, 8192, 256], - "batch_size": [64, 16, 512, 16], + "n_steps": [1024, 256, 8192, 256], + "batch_size": [128, 16, 512, 16], "n_epochs": [10, 1, 50, 1], "learning_rate": [3e-4, 1e-5, 1e-2, 1e-5], "gamma": [0.99, 0.8, 0.9999, 0.001], - "ent_coef": [0.01, 0.0, 0.1, 0.001], + "ent_coef": [0.015, 0.0, 0.1, 0.001], "clip_range": [0.2, 0.1, 0.4, 0.01], - "learning_steps": [500_000, 50_000, 25_000_000, 50_000] + "learning_steps": [1_000_000, 50_000, 25_000_000, 50_000], + "n_envs": (12, 1, 128, 1) +} + +DIFFICULTY_SETTINGS = { + "enemy_rows": ["Enemy Rows", 1, 6], + "enemy_cols": ["Enemy Columns", 1, 7], + "enemy_respawns": ["Enemy Respawns", 1, 5], + "player_count": ["Player Count", 1, 10], + "player_respawns": ["Player Respawns", 1, 5] +} + +DIFFICULTY_LEVELS = { + "Easy": { + "enemy_rows": 3, + "enemy_cols": 4, + "enemy_respawns": 5, + "player_count": 2, + "player_respawns": 2 + }, + "Medium": { + "enemy_rows": 3, + "enemy_cols": 5, + "enemy_respawns": 4, + "player_count": 4, + "player_respawns": 3 + }, + "Hard": { + "enemy_rows": 4, + "enemy_cols": 6, + "enemy_respawns": 3, + "player_count": 6, + "player_respawns": 4 + }, + "Extra Hard": { + "enemy_rows": 6, + "enemy_cols": 7, + "enemy_respawns": 2, + "player_count": 8, + "player_respawns": 5 + }, + "Custom": { + + } } menu_background_color = (30, 30, 47) diff --git a/utils/rl.py b/utils/rl.py index d282ebf..6b42cc0 100644 --- a/utils/rl.py +++ b/utils/rl.py @@ -1,78 +1,87 @@ import gymnasium as gym import numpy as np import arcade -import time import random -from game.sprites import Enemy, Player, Bullet -from utils.constants import PLAYER_SPEED, BULLET_SPEED, PLAYER_ATTACK_SPEED, ENEMY_ROWS, ENEMY_COLS +from game.sprites import EnemyFormation, Player, Bullet +from utils.constants import PLAYER_SPEED, BULLET_SPEED, ENEMY_SPEED, DIFFICULTY_LEVELS class SpaceInvadersEnv(gym.Env): - def __init__(self, width=800, height=600): + def __init__(self, width=800, height=600, difficulty="Hard"): self.width = width self.height = height - self.action_space = gym.spaces.Discrete(3) - self.observation_space = gym.spaces.Box(low=-2.0, high=2.0, shape=(9,), dtype=np.float32) + self.action_space = gym.spaces.Discrete(4) + self.observation_space = gym.spaces.Box(low=-2.0, high=2.0, shape=(12,), dtype=np.float32) + + if difficulty not in DIFFICULTY_LEVELS: + raise ValueError(f"Unknown difficulty: {difficulty}. Available: {list(DIFFICULTY_LEVELS.keys())}") + + self.difficulty_settings = DIFFICULTY_LEVELS[difficulty] - self.enemies = [] self.bullets = [] - self.dir_history = [] - self.last_shot = 0.0 self.player = None - self.prev_x = 0.0 + self.enemy_formation = None self.player_speed = 0.0 - self.prev_bx = 2.0 - self.steps_since_direction_change = 0 - self.last_direction = 0 - self.max_steps = 1000 + self.max_steps = 2000 self.current_step = 0 + self.enemies_killed = 0 + self.enemy_move_speed = ENEMY_SPEED + self.player_respawns = self.difficulty_settings["player_respawns"] + self.enemy_respawns = self.difficulty_settings["enemy_respawns"] + self.player_respawns_remaining = 0 + self.enemy_respawns_remaining = 0 + self.player_alive = True + + self.player_attack_cooldown_steps = 5 + self.current_cooldown = 0 def reset(self, seed=None, options=None): if seed is not None: np.random.seed(seed) random.seed(seed) - self.enemies = [] self.bullets = [] - self.dir_history = [] self.player = Player(self.width / 2 + random.randint(int(-self.width / 3), int(self.width / 3)), 100) - self.prev_x = self.player.center_x self.player_speed = 0.0 - self.prev_bx = 2.0 - self.steps_since_direction_change = 0 - self.last_direction = 0 self.current_step = 0 - + self.enemies_killed = 0 + self.player_respawns_remaining = self.player_respawns + self.enemy_respawns_remaining = self.enemy_respawns + self.player_alive = True + self.current_cooldown = 0 + start_x = self.width * 0.15 start_y = self.height * 0.9 - for r in range(ENEMY_ROWS): - for c in range(ENEMY_COLS): - e = Enemy(start_x + c * 100, start_y - r * 100) - self.enemies.append(e) + self.enemy_formation = EnemyFormation(start_x, start_y, None, + self.difficulty_settings["enemy_rows"], + self.difficulty_settings["enemy_cols"]) - self.last_shot = time.perf_counter() return self._obs(), {} def _nearest_enemy(self): - if not self.enemies: + if not self.enemy_formation.enemies: return None - return min(self.enemies, key=lambda e: abs(e.center_x - self.player.center_x)) + + return min(self.enemy_formation.enemies, key=lambda e: abs(e.center_x - self.player.center_x)) def _lowest_enemy(self): - if not self.enemies: + if not self.enemy_formation.enemies: return None - return max(self.enemies, key=lambda e: e.center_y) + + return min(self.enemy_formation.enemies, key=lambda e: e.center_y) def _nearest_enemy_bullet(self): enemy_bullets = [b for b in self.bullets if b.direction_y == -1] + if not enemy_bullets: return None + return min(enemy_bullets, key=lambda b: abs(b.center_x - self.player.center_x) + abs(b.center_y - self.player.center_y)) def _obs(self): - if self.enemies: + if self.enemy_formation.enemies and self.player_alive: nearest = self._nearest_enemy() enemy_x = (nearest.center_x - self.player.center_x) / float(self.width) enemy_y = (nearest.center_y - self.player.center_y) / float(self.height) @@ -81,31 +90,60 @@ class SpaceInvadersEnv(gym.Env): enemy_y = 2.0 lowest = self._lowest_enemy() - - if lowest is not None: + if lowest is not None and self.player_alive: lowest_dy = (lowest.center_y - self.player.center_y) / float(self.height) else: lowest_dy = 2.0 nb = self._nearest_enemy_bullet() - if nb is not None: + if nb is not None and self.player_alive: bx = (nb.center_x - self.player.center_x) / float(self.width) by = (nb.center_y - self.player.center_y) / float(self.height) else: bx = 2.0 by = 2.0 - enemy_count = len(self.enemies) / float(max(1, ENEMY_ROWS * ENEMY_COLS)) - player_x_norm = self.player.center_x / float(self.width) - enemy_dispersion = 0.0 + enemy_count = len(self.enemy_formation.enemies) / float(max(1, self.difficulty_settings["enemy_rows"] * self.difficulty_settings["enemy_cols"])) + player_x_norm = self.player.center_x / float(self.width) if self.player_alive else 0.5 - if self.enemies: - xs = np.array([e.center_x for e in self.enemies], dtype=np.float32) + enemy_dispersion = 0.0 + if self.enemy_formation.enemies: + xs = np.array([e.center_x for e in self.enemy_formation.enemies], dtype=np.float32) enemy_dispersion = float(xs.std()) / float(self.width) - obs = np.array([player_x_norm, enemy_x, enemy_y, lowest_dy, bx, by, self.player_speed, enemy_count, enemy_dispersion], dtype=np.float32) + can_shoot = 1.0 if (self.player_alive and self.current_cooldown <= 0) else 0.0 + + player_respawns_norm = self.player_respawns_remaining / float(max(1, self.player_respawns)) + enemy_respawns_norm = self.enemy_respawns_remaining / float(max(1, self.enemy_respawns)) + + obs = np.array([ + player_x_norm, + enemy_x, + enemy_y, + lowest_dy, + bx, + by, + self.player_speed, + enemy_count, + enemy_dispersion, + can_shoot, + player_respawns_norm, + enemy_respawns_norm + ], dtype=np.float32) + return obs + def _respawn_player(self): + self.player = Player(self.width / 2 + random.randint(int(-self.width / 3), int(self.width / 3)), 100) + self.player_alive = True + self.bullets = [b for b in self.bullets if b.direction_y == 1] + self.current_cooldown = 0 + + def _respawn_enemies(self): + self.enemy_formation.start_x = self.width * 0.15 + self.enemy_formation.start_y = self.height * 0.9 + self.enemy_formation.create_formation() + def step(self, action): reward = 0.0 terminated = False @@ -115,113 +153,125 @@ class SpaceInvadersEnv(gym.Env): if self.current_step >= self.max_steps: truncated = True - nearest = self._nearest_enemy() - if nearest is not None: - enemy_x = (nearest.center_x - self.player.center_x) / float(self.width) - else: - enemy_x = 2.0 + if self.current_cooldown > 0: + self.current_cooldown -= 1 - prev_x = self.player.center_x - current_action_dir = 0 + if self.player_alive: + prev_x = self.player.center_x - if action == 0: - self.player.center_x -= PLAYER_SPEED - current_action_dir = -1 - elif action == 1: - self.player.center_x += PLAYER_SPEED - current_action_dir = 1 - elif action == 2: - t = time.perf_counter() - if t - self.last_shot >= PLAYER_ATTACK_SPEED: - self.last_shot = t - - b = Bullet(self.player.center_x, self.player.center_y, 1) + if action == 0: + self.player.center_x -= PLAYER_SPEED + elif action == 1: + self.player.center_x += PLAYER_SPEED + elif action == 2: + pass + elif action == 3: + if self.current_cooldown <= 0: + self.current_cooldown = self.player_attack_cooldown_steps + reward += 0.01 + b = Bullet(self.player.center_x, self.player.center_y, 1) + self.bullets.append(b) + else: + reward -= 0.05 - self.bullets.append(b) - - if enemy_x != 2.0 and abs(enemy_x) < 0.04: + if self.enemy_formation.enemies: + nearest = self._nearest_enemy() + alignment = abs(nearest.center_x - self.player.center_x) / self.width + if alignment < 0.025: reward += 0.3 - elif enemy_x != 2.0 and abs(enemy_x) < 0.1: - reward += 0.1 - if self.player.center_x > self.width: - self.player.center_x = self.width - elif self.player.center_x < 0: - self.player.center_x = 0 + self.player.center_x = np.clip(self.player.center_x, 0, self.width) + self.player_speed = (self.player.center_x - prev_x) / max(1e-6, PLAYER_SPEED) - self.player_speed = (self.player.center_x - prev_x) / max(1e-6, PLAYER_SPEED) + if self.enemy_formation.enemies and self.player_alive: + if self.enemy_formation.center_x < self.player.center_x: + self.enemy_formation.move(self.width, self.height, "x", self.enemy_move_speed) + elif self.enemy_formation.center_x > self.player.center_x: + self.enemy_formation.move(self.width, self.height, "x", -self.enemy_move_speed) + + if random.random() < 0.02: + if random.random() < 0.5: + self.enemy_formation.move(self.width, self.height, "y", -self.enemy_move_speed) + else: + self.enemy_formation.move(self.width, self.height, "y", self.enemy_move_speed) - if current_action_dir != 0: - if self.last_direction != 0 and current_action_dir != self.last_direction: - if self.steps_since_direction_change < 3: - reward -= 0.1 + bullets_to_remove = [] - self.steps_since_direction_change = 0 - else: - self.steps_since_direction_change += 1 - self.last_direction = current_action_dir - - if enemy_x != 2.0: - if abs(enemy_x) < 0.03: - reward += 0.1 - elif abs(enemy_x) < 0.08: - reward += 0.05 - - for b in list(self.bullets): + for b in self.bullets: b.center_y += b.direction_y * BULLET_SPEED + if b.center_y > self.height or b.center_y < 0: - try: - self.bullets.remove(b) - except ValueError: - pass - - for b in list(self.bullets): + bullets_to_remove.append(b) + continue + if b.direction_y == 1: - for e in list(self.enemies): + for e in self.enemy_formation.enemies: if arcade.check_for_collision(b, e): - try: - self.enemies.remove(e) - except ValueError: - pass - try: - self.bullets.remove(b) - except ValueError: - pass - reward += 1.0 + self.enemy_formation.remove_enemy(e) + bullets_to_remove.append(b) + reward += 10.0 + self.enemies_killed += 1 break - - for b in list(self.bullets): - if b.direction_y == -1: + + elif b.direction_y == -1 and self.player_alive: if arcade.check_for_collision(b, self.player): - try: - self.bullets.remove(b) - except ValueError: - pass - reward -= 5.0 + bullets_to_remove.append(b) + reward -= 10.0 + self.player_alive = False + + if self.player_respawns_remaining > 0: + self.player_respawns_remaining -= 1 + self._respawn_player() + reward += 2.0 + else: + terminated = True + + for b in bullets_to_remove: + if b in self.bullets: + self.bullets.remove(b) + + if self.player_alive: + lowest_enemy = self._lowest_enemy() + if lowest_enemy and lowest_enemy.center_y <= self.player.center_y: + reward -= 10.0 + self.player_alive = False + + if self.player_respawns_remaining > 0: + self.player_respawns_remaining -= 1 + self._respawn_player() + else: terminated = True - if not self.enemies: - reward += 10.0 - terminated = True + if not self.enemy_formation.enemies: + reward += 50.0 + + if self.enemy_respawns_remaining > 0: + self.enemy_respawns_remaining -= 1 + self._respawn_enemies() + reward += 20.0 + else: + reward += 100.0 + terminated = True - if self.enemies and random.random() < 0.05: - e = random.choice(self.enemies) - b = Bullet(e.center_x, e.center_y, -1) - self.bullets.append(b) + shooting_prob = 0.05 + (0.05 * (1.0 - len(self.enemy_formation.enemies) / (self.difficulty_settings["enemy_rows"] * self.difficulty_settings["enemy_cols"]))) + if self.enemy_formation.enemies and random.random() < shooting_prob: + enemy = self.enemy_formation.get_lowest_enemy() + if enemy: + b = Bullet(enemy.center_x, enemy.center_y, -1) + self.bullets.append(b) - curr_bullet = self._nearest_enemy_bullet() - if curr_bullet is not None: - curr_bx = (curr_bullet.center_x - self.player.center_x) / float(self.width) - else: - curr_bx = 2.0 + if self.player_alive: + edge_threshold = self.width * 0.15 + if self.player.center_x < edge_threshold or self.player.center_x > self.width - edge_threshold: + reward -= 0.03 - if self.prev_bx != 2.0 and curr_bx != 2.0: - if abs(curr_bx) > abs(self.prev_bx): - reward += 0.02 - - reward -= 0.01 + reward -= 0.005 obs = self._obs() - self.prev_bx = curr_bx - - return obs, float(reward), bool(terminated), bool(truncated), {} \ No newline at end of file + + return obs, float(reward), bool(terminated), bool(truncated), { + "enemies_killed": self.enemies_killed, + "step": self.current_step, + "player_respawns_remaining": self.player_respawns_remaining, + "enemy_respawns_remaining": self.enemy_respawns_remaining + } \ No newline at end of file