From 0da7388d86b56f790d6c367018ef6cd455e108b8 Mon Sep 17 00:00:00 2001 From: Lars Reining Date: Fri, 6 Jun 2025 15:04:06 +0200 Subject: [PATCH 01/11] Add igloo mod ice_inactive --- hackatari/games/frostbite.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hackatari/games/frostbite.py b/hackatari/games/frostbite.py index bfa86d6..b35684d 100644 --- a/hackatari/games/frostbite.py +++ b/hackatari/games/frostbite.py @@ -125,6 +125,17 @@ def igloo7(self): """ self.env.set_ram(77, 7) + def ice_inactive(self): + """ + Sets the ice floes to inactive. This means while the player can still + walk on them, they will not give points or contribute to the igloo + building progress. + """ + self.env.set_ram(43, 152) + self.env.set_ram(44, 152) + self.env.set_ram(45, 152) + self.env.set_ram(46, 152) + def _set_active_modifications(self, active_modifs): """ Specifies which modifications are active. @@ -153,6 +164,7 @@ def _fill_modif_lists(self): "no_birds": self.no_birds, "few_enemies": self.few_enemies, "many_enemies": self.many_enemies, + "ice_inactive": self.ice_inactive, } reset_modifs_mapping = { "full_igloo": self.full_igloo, From 24c155c3c9b6321b9d0f8843164208080e70f3a6 Mon Sep 17 00:00:00 2001 From: Lars Reining Date: Fri, 13 Jun 2025 10:26:56 +0200 Subject: [PATCH 02/11] Print warning if modif not found --- hackatari/core.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hackatari/core.py b/hackatari/core.py index 108c242..2a53a3f 100644 --- a/hackatari/core.py +++ b/hackatari/core.py @@ -83,6 +83,13 @@ def __init__( f"hackatari.games.{self.game_name.lower()}") step_modifs, reset_modifs, post_detection_modifs = modif_module.modif_funcs( self, modifs) + active_modifs = set(step_modifs + reset_modifs + post_detection_modifs) + if len(active_modifs) != len(modifs): + print( + colored( + f"Warning: Some modifications not found in {self.game_name}, requested: {modifs}, found: {active_modifs}" + ) + ) self.step_modifs.extend(step_modifs) self.reset_modifs.extend(reset_modifs) self.post_detection_modifs.extend(post_detection_modifs) From d1dcefc34c0e76301fb3432abfe0a3301b6edb63 Mon Sep 17 00:00:00 2001 From: lreining Date: Mon, 14 Jul 2025 09:17:45 +0000 Subject: [PATCH 03/11] Add modifications to Freeway --- hackatari/games/freeway.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/hackatari/games/freeway.py b/hackatari/games/freeway.py index 871dff1..6331538 100644 --- a/hackatari/games/freeway.py +++ b/hackatari/games/freeway.py @@ -61,6 +61,17 @@ def stop_all_cars(self): for new_pos_down in range(113, 118): self.env.set_ram(new_pos_down, 55) + def disable_cars(self): + """ + Disables all cars by stopping them and setting their positions to out of frame. + """ + for car in range(33, 43): + self.env.set_ram(car, 100) + for new_pos_down in range(108, 113): + self.env.set_ram(new_pos_down, 3) + for new_pos_down in range(113, 118): + self.env.set_ram(new_pos_down, 3) + def all_black_cars(self): """ Colors all cars black. @@ -95,6 +106,13 @@ def all_blue_cars(self): """ for car in range(77, 87): self.env.set_ram(car, 145) + + def all_pink_cars(self): + """ + Colors all cars pink. + """ + for car in range(77, 87): + self.env.set_ram(car, 90) # My modifications @@ -176,6 +194,7 @@ def _fill_modif_lists(self): "all_white_cars": self.all_white_cars, "all_red_cars": self.all_red_cars, "all_green_cars": self.all_green_cars, + "all_pink_cars": self.all_pink_cars, "all_blue_cars": self.all_blue_cars, "invisible_mode": self.invisible_mode, "strobo_mode": self.strobo_mode, @@ -184,6 +203,7 @@ def _fill_modif_lists(self): "speed_mode": self.speed_mode, "reverse_car_speed_bottom": self.reverse_car_speed_bottom, "reverse_car_speed_top": self.reverse_car_speed_top, + "disable_cars": self.disable_cars, } step_modifs = [modif_mapping[name] From 3e212b3221ad23552325d7777291dd17060078e1 Mon Sep 17 00:00:00 2001 From: Hannah Willkomm Date: Tue, 15 Jul 2025 11:31:33 +0200 Subject: [PATCH 04/11] add modification for varying car speeds for freeway --- hackatari/games/freeway.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/hackatari/games/freeway.py b/hackatari/games/freeway.py index 6331538..77244e5 100644 --- a/hackatari/games/freeway.py +++ b/hackatari/games/freeway.py @@ -16,6 +16,11 @@ def __init__(self, env): """ self.env = env self.active_modifications = set() + self.order_cars = list(range(10)) + + + def reset(self): + self.order_cars = [random.randint(0, 10) for _ in range(10)] def stop_random_car(self): """ @@ -50,6 +55,12 @@ def reverse_car_speed_top(self): val = self.env.get_ram()[1] % (i+1) self.env.set_ram(42-i, val) + def vary_car_speeds(self): + for i,j in enumerate(range(33, 43)): + car = self.order_cars[i] + val = self.env.get_ram()[1] % (car+1) + self.env.set_ram(j, val) + def stop_all_cars(self): """ Stops all cars and repositions some to predefined positions. @@ -160,7 +171,7 @@ def speed_mode(self): """ Each car drives with speed 2 (default) """ - speed = 2 # default + speed = 2 # default ram = self.env.get_ram() for car_x in range(108, 113): x_value = ram[car_x] @@ -204,11 +215,12 @@ def _fill_modif_lists(self): "reverse_car_speed_bottom": self.reverse_car_speed_bottom, "reverse_car_speed_top": self.reverse_car_speed_top, "disable_cars": self.disable_cars, + "vary_car_speeds": self.vary_car_speeds, } step_modifs = [modif_mapping[name] for name in self.active_modifications if name in modif_mapping] - reset_modifs = [] + reset_modifs = [self.reset] post_detection_modifs = [] return step_modifs, reset_modifs, post_detection_modifs From 19d860bc46bb90238af1fea164889f14120e240b Mon Sep 17 00:00:00 2001 From: lreining Date: Wed, 16 Jul 2025 10:15:56 +0000 Subject: [PATCH 05/11] Buf fixes --- hackatari/core.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/hackatari/core.py b/hackatari/core.py index 2a53a3f..3f1bf1b 100644 --- a/hackatari/core.py +++ b/hackatari/core.py @@ -76,7 +76,7 @@ def __init__( self.ale = self.env.unwrapped.ale # Initialize modifications and environment settings self.step_modifs, self.reset_modifs, self.post_detection_modifs = [], [], [] - + self.lives = self.ale.lives() # Load modification functions dynamically try: modif_module = importlib.import_module( @@ -84,7 +84,7 @@ def __init__( step_modifs, reset_modifs, post_detection_modifs = modif_module.modif_funcs( self, modifs) active_modifs = set(step_modifs + reset_modifs + post_detection_modifs) - if len(active_modifs) != len(modifs): + if len(active_modifs) < len(modifs): print( colored( f"Warning: Some modifications not found in {self.game_name}, requested: {modifs}, found: {active_modifs}" @@ -193,6 +193,12 @@ def step(self, *args, **kwargs): func() obs, reward, terminated, truncated, info = self._env.step( *args, **kwargs) + + lives = self.ale.lives() + if 0 < lives < self.lives: + for func in self.reset_modifs: + func() + self.lives = lives for func in self.step_modifs: func() total_reward += float(reward) From d90d840b1f1374b011c6a5fbfb695fcad182fa18 Mon Sep 17 00:00:00 2001 From: Hannah Willkomm Date: Fri, 1 Aug 2025 16:27:40 +0200 Subject: [PATCH 06/11] add strobo mode for breakout --- hackatari/games/breakout.py | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/hackatari/games/breakout.py b/hackatari/games/breakout.py index d25214b..4a7fd88 100644 --- a/hackatari/games/breakout.py +++ b/hackatari/games/breakout.py @@ -90,25 +90,33 @@ def color_player_and_ball_blue(self): def color_player_and_ball_green(self): self.env.set_ram(62, self.colors[4]) - def color_all_blocks_black(self): + def strobo_mode_player_and_ball(self): + color = random.randint(0, 255) + self.env.set_ram(62, color) + + def color_blocks(self, color): for i in range(64, 70): - self.env.set_ram(i, self.colors[0]) + self.env.set_ram(i, color) + + def color_all_blocks_black(self): + self.color_blocks(self.colors[0]) def color_all_blocks_white(self): - for i in range(64, 70): - self.env.set_ram(i, self.colors[1]) + self.color_blocks(self.colors[1]) def color_all_blocks_red(self): - for i in range(64, 70): - self.env.set_ram(i, self.colors[2]) + self.color_blocks(self.colors[2]) def color_all_blocks_blue(self): - for i in range(64, 70): - self.env.set_ram(i, self.colors[3]) + self.color_blocks(self.colors[3]) def color_all_blocks_green(self): + self.color_blocks(self.colors[4]) + + def strobo_mode_blocks(self): for i in range(64, 70): - self.env.set_ram(i, self.colors[4]) + color = random.randint(0, 255) + self.env.set_ram(i, color) def _set_active_modifications(self, active_modifs): """ @@ -139,6 +147,9 @@ def _fill_modif_lists(self): "color_all_blocks_red": self.color_all_blocks_red, "color_all_blocks_blue": self.color_all_blocks_blue, "color_all_blocks_green": self.color_all_blocks_green, + "strobo_mode_blocks": self.strobo_mode_blocks, + "strobo_mode_player_and_ball": self.strobo_mode_player_and_ball, + } step_modifs = [modif_mapping[name] From 2de3e5626fa3054bddb5bbe3465168346c510a70 Mon Sep 17 00:00:00 2001 From: Hannah Willkomm Date: Tue, 5 Aug 2025 11:53:15 +0200 Subject: [PATCH 07/11] add evaluation modifs for pong --- hackatari/games/pong.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/hackatari/games/pong.py b/hackatari/games/pong.py index d3fa1d3..05a5c9b 100644 --- a/hackatari/games/pong.py +++ b/hackatari/games/pong.py @@ -1,3 +1,4 @@ +import numpy as np from ocatari.ram.game_objects import NoObject @@ -17,7 +18,29 @@ def __init__(self, env): self.strength = 6 self.timer = 0 self.last_enemy_y_pos = 127 + self.last_player_y_pos = 127 self.ball_previous_x_pos = 130 + self.ball_previous_y_pos = 60 + + def parallel_enemy(self): + ram = self.env.get_ram() + player_pos = ram[60] + self.env.set_ram(21, player_pos) + + def parallel_enemy_after_hit(self): + ram = self.env.get_ram() + if 0 < ram[11] < 5: + self.env.set_ram(21, 127) + self.env.set_ram(49, 130) + if self.ball_previous_x_pos < ram[49]: + player_pos = ram[60] + self.env.set_ram(21, player_pos) + + def random_perturbation_enemy(self): + ram = self.env.get_ram() + enemy_pos = ram[21] + perturbation = np.random.randint(-5, 6) + self.env.set_ram(21, min(max(0,perturbation+enemy_pos),250)) def lazy_enemy(self): """ @@ -35,6 +58,7 @@ def lazy_enemy(self): self.ball_previous_x_pos = ram[49] self.last_enemy_y_pos = tmp + def hidden_enemy(self): """ Enemy does not move after returning the shot. @@ -105,6 +129,9 @@ def _fill_modif_lists(self): "down_drift": self.down_drift, "left_drift": self.left_drift, "right_drift": self.right_drift, + "parallel_enemy_complete": self.parallel_enemy, + "parallel_enemy": self.parallel_enemy_after_hit, + "random_perturbation_enemy": self.random_perturbation_enemy, } step_modifs = [modif_mapping[name] From 91de174d7c0299245fd47bcaca604700fd1ef746 Mon Sep 17 00:00:00 2001 From: Hannah Willkomm Date: Tue, 5 Aug 2025 12:34:50 +0200 Subject: [PATCH 08/11] add strobo mode breakout without black --- hackatari/games/breakout.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hackatari/games/breakout.py b/hackatari/games/breakout.py index 4a7fd88..defd3ac 100644 --- a/hackatari/games/breakout.py +++ b/hackatari/games/breakout.py @@ -17,6 +17,7 @@ def __init__(self, env): self.strength = 2 self.timer = 0 self.colors = [0, 12, 48, 113, 200] + self.colors_bricks = [134, 198, 22, 38, 54, 70] self.player_and_ball_color = 0 # Black, White, Red, Blue, Green self.all_blocks_color = 0 # Black, White, Red, Blue, Green self.row_colors = [None] * 6 @@ -94,6 +95,9 @@ def strobo_mode_player_and_ball(self): color = random.randint(0, 255) self.env.set_ram(62, color) + def strobo_mode_player_and_ball_no_black(self): + color = random.randint(1, 255) + self.env.set_ram(62, color) def color_blocks(self, color): for i in range(64, 70): self.env.set_ram(i, color) @@ -118,6 +122,10 @@ def strobo_mode_blocks(self): color = random.randint(0, 255) self.env.set_ram(i, color) + def strobo_mode_blocks_no_black(self): + for i in range(64, 70): + color = random.randint(1, 255) + self.env.set_ram(i, color) def _set_active_modifications(self, active_modifs): """ Specifies which modifications are active. @@ -149,6 +157,8 @@ def _fill_modif_lists(self): "color_all_blocks_green": self.color_all_blocks_green, "strobo_mode_blocks": self.strobo_mode_blocks, "strobo_mode_player_and_ball": self.strobo_mode_player_and_ball, + "strobo_mode_blocks_no_black": self.strobo_mode_blocks_no_black, + "strobo_mode_player_and_ball_no_black": self.strobo_mode_player_and_ball_no_black, } From 5f803ad0fc4ea48e8ed56ec2abbc1dc866664080 Mon Sep 17 00:00:00 2001 From: Hannah Willkomm Date: Fri, 8 Aug 2025 12:02:09 +0200 Subject: [PATCH 09/11] new modif for sampling colors in breakout --- hackatari/games/breakout.py | 38 +++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/hackatari/games/breakout.py b/hackatari/games/breakout.py index defd3ac..d5aba5d 100644 --- a/hackatari/games/breakout.py +++ b/hackatari/games/breakout.py @@ -1,5 +1,7 @@ import random +import numpy as np + class GameModifications: """ @@ -21,6 +23,7 @@ def __init__(self, env): self.player_and_ball_color = 0 # Black, White, Red, Blue, Green self.all_blocks_color = 0 # Black, White, Red, Blue, Green self.row_colors = [None] * 6 + self.already_reset = False def right_drift(self): """ @@ -98,6 +101,7 @@ def strobo_mode_player_and_ball(self): def strobo_mode_player_and_ball_no_black(self): color = random.randint(1, 255) self.env.set_ram(62, color) + def color_blocks(self, color): for i in range(64, 70): self.env.set_ram(i, color) @@ -126,6 +130,28 @@ def strobo_mode_blocks_no_black(self): for i in range(64, 70): color = random.randint(1, 255) self.env.set_ram(i, color) + + def sample_new_player_and_ball_color(self): + if not self.already_reset: + color = random.choice(self.colors_bricks) + self.player_and_ball_color = color + self.already_reset = True + self.env.set_ram(62, self.player_and_ball_color) + + def sample_new_brick_colors(self): + if not self.already_reset: + colors = self.colors_bricks.copy() + np.random.shuffle(colors) + for idx, i in enumerate(range(64, 70)): + self.row_colors[idx] = colors[idx] + self.already_reset = True + + for idx, i in enumerate(range(64, 70)): + self.env.set_ram(i, self.row_colors[idx]) + + def reset(self): + self.already_reset = False + def _set_active_modifications(self, active_modifs): """ Specifies which modifications are active. @@ -159,12 +185,16 @@ def _fill_modif_lists(self): "strobo_mode_player_and_ball": self.strobo_mode_player_and_ball, "strobo_mode_blocks_no_black": self.strobo_mode_blocks_no_black, "strobo_mode_player_and_ball_no_black": self.strobo_mode_player_and_ball_no_black, - + "sample_new_player_and_ball_color": self.sample_new_player_and_ball_color, + "sample_new_brick_colors": self.sample_new_brick_colors, } + step_modifs = [ + modif_mapping[name] + for name in self.active_modifications + if name in modif_mapping + ] + reset_modifs = [self.reset] - step_modifs = [modif_mapping[name] - for name in self.active_modifications if name in modif_mapping] - reset_modifs = [] post_detection_modifs = [] return step_modifs, reset_modifs, post_detection_modifs From 1aa997d3f5dbd4a2de1dafeba1f5c7e6f158f6ed Mon Sep 17 00:00:00 2001 From: lreining Date: Fri, 19 Sep 2025 09:25:59 +0200 Subject: [PATCH 10/11] Add documentation for new modifications --- modification_list.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/modification_list.md b/modification_list.md index 4344413..610f3a3 100644 --- a/modification_list.md +++ b/modification_list.md @@ -70,6 +70,10 @@ The modes are: | inverse_gravity | Set drift dirtection upwards | | color_player_and_ball_black | Set color of player and ball (also works with white, red, blue and green) | | color_all_blocks_black | Set color of all blocks (also works with white, red, blue and green) | +| strobo_mode_player_and_ball | Player and ball change color randomly every step (also available with the random colors not including black). | +| strobo_mode_blocks | All blocks change color randomly every step (also available with the random colors not including black). | +| sample_new_player_and_ball_color | Sample a new color for the player and ball for every game. | +| sample_new_block_color | Sample a new color for the blocks for every game. | ## Carnival: | Command | Effect | @@ -122,7 +126,10 @@ The modes are: | stop_random_car | Stops a random car with a biased probability for a certain time. | | stop_all_cars | Stops all cars on the side of the board. | | align_all_cars | Align all cars so they move in a line. | -| all_black_cars | All cars are black. (also works with white, red, blue and green)| +| all_black_cars | All cars are black. (also works with white, red, blue, pink and green)| +| disable_cars | Hide and disable all cars. | +| vary_car_speeds | Randomly interchange car speeds. | + ## Frostbite: @@ -135,6 +142,8 @@ The modes are: | no_birds | Removes all birds (and fishes?) | | few_enemies | Increase enemies slightly | | many_enemies | Increase enemies to a maximum| +| ice_inactive | Ice floes will not give points or contribute to the igloo. | + building progress. ## Kangaroo: @@ -170,6 +179,9 @@ The modes are: | lazy_enemy | Enemy does not move after returning the shot. | | up_drift | Makes the ball drift upwards. (Also works with down, left and right) | | hidden_enemy | Makes the enemy invisible for the player (does not work in dqn_default since it is a object detection modification) +| random_perturbation_enemy | Add random perturbations to enemy movement. | +| parallel_enemy | In the period where the ball is moving towards the player, the enemy moves in parallel with the player. | +| parallel_ememy_complete | The enemy always moves in parallel with the player. | ## Seaquest From 072b27247ddc567591f3172beedffdef83b257e6 Mon Sep 17 00:00:00 2001 From: lreining Date: Thu, 25 Sep 2025 14:53:41 +0000 Subject: [PATCH 11/11] Fix bug introduced through merge --- hackatari/core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hackatari/core.py b/hackatari/core.py index 55d662a..8457cd0 100644 --- a/hackatari/core.py +++ b/hackatari/core.py @@ -95,8 +95,8 @@ def __init__( self.inpainting_modifs.extend(inpainting_modifs) self.place_above_modifs.extend(place_above_modifs) except: - step_modifs, reset_modifs, post_detection_modifs = modif_module.modif_funcs( - self, modifs) + step_modifs, reset_modifs, post_detection_modifs = modif_module.modif_funcs(self, modifs) + active_modifs = [m.__name__ for m in step_modifs + reset_modifs + post_detection_modifs] if len(active_modifs) < len(modifs): print( colored(