gameboy_worlds.emulation.pokemon.test_metrics

  1from typing import Optional
  2
  3from gameboy_worlds.emulation.pokemon.parsers import PokemonRedStateParser, PokemonPrismStateParser
  4from gameboy_worlds.emulation.tracker import (
  5    RegionMatchTerminationOnlyMetric,
  6    TerminationMetric,
  7    RegionMatchTerminationMetric,
  8    RegionMatchSubGoal,
  9    AnyRegionMatchSubGoal,
 10)
 11from gameboy_worlds.emulation.pokemon.base_metrics import (
 12    PokemonExitBattleTruncationMetric,
 13)
 14import numpy as np
 15
 16
 17class PokemonCenterTerminateMetric(RegionMatchTerminationOnlyMetric):
 18    REQUIRED_PARSER = PokemonRedStateParser
 19
 20    _TERMINATION_NAMED_REGION = "screen_bottom_half"
 21    _TERMINATION_TARGET_NAME = "viridian_pokemon_center_entrance"
 22
 23
 24class OutsideViridianCenterSubgoal(AnyRegionMatchSubGoal):
 25    NAME = "outside_viridian_center"
 26    _NAMED_REGIONS = [
 27        "screen_middle",
 28        "screen_middle",
 29    ]
 30    _TARGET_NAMES = [
 31        "outside_viridian_center_from_left",
 32        "outside_viridian_center_from_right",
 33    ]
 34
 35
 36class MtMoonTerminateMetric(RegionMatchTerminationOnlyMetric):
 37    REQUIRED_PARSER = PokemonRedStateParser
 38
 39    _TERMINATION_NAMED_REGION = "screen_bottom_half"
 40    _TERMINATION_TARGET_NAME = "mt_moon_entrance"
 41
 42
 43class SpeakToBillCompleteTerminateMetric(RegionMatchTerminationOnlyMetric):
 44    REQUIRED_PARSER = PokemonRedStateParser
 45
 46    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
 47    _TERMINATION_TARGET_NAME = "talk_bill_complete"
 48
 49
 50class PickupPokeballTerminateMetric(RegionMatchTerminationOnlyMetric):
 51    REQUIRED_PARSER = PokemonRedStateParser
 52
 53    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
 54    _TERMINATION_TARGET_NAME = "pick_up_pokeball_starting"
 55
 56
 57class ReadTrainersTipsSignTerminateMetric(RegionMatchTerminationOnlyMetric):
 58    REQUIRED_PARSER = PokemonRedStateParser
 59
 60    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
 61    _TERMINATION_TARGET_NAME = "trainers_tips_sign"
 62
 63
 64class SpeakToCinnabarGymAideCompleteTerminateMetric(RegionMatchTerminationOnlyMetric):
 65    REQUIRED_PARSER = PokemonRedStateParser
 66
 67    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
 68    _TERMINATION_TARGET_NAME = "cinnabar_gym_aid_complete"
 69
 70
 71class SpeakToCinnabarMonkTerminateMetric(RegionMatchTerminationOnlyMetric):
 72    REQUIRED_PARSER = PokemonRedStateParser
 73
 74    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
 75    _TERMINATION_TARGET_NAME = "talk_cinnabar_monk"
 76
 77
 78class DefeatedBrockTerminateMetric(
 79    RegionMatchTerminationMetric, PokemonExitBattleTruncationMetric
 80):
 81    REQUIRED_PARSER = PokemonRedStateParser
 82
 83    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
 84    _TERMINATION_TARGET_NAME = "defeated_brock"
 85
 86
 87class DefeatedLassTerminateMetric(
 88    RegionMatchTerminationMetric, PokemonExitBattleTruncationMetric
 89):
 90    REQUIRED_PARSER = PokemonRedStateParser
 91
 92    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
 93    _TERMINATION_TARGET_NAME = "defeated_lass"
 94
 95
 96class CaughtPidgeyTerminateMetric(
 97    RegionMatchTerminationMetric, PokemonExitBattleTruncationMetric
 98):
 99    REQUIRED_PARSER = PokemonRedStateParser
100
101    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
102    _TERMINATION_TARGET_NAME = "caught_pidgey"
103
104
105class CaughtPikachuTerminateMetric(
106    RegionMatchTerminationMetric, PokemonExitBattleTruncationMetric
107):
108    REQUIRED_PARSER = PokemonRedStateParser
109
110    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
111    _TERMINATION_TARGET_NAME = "caught_pikachu"
112
113
114class BoughtPotionAtPewterPokemartTerminateMetric(RegionMatchTerminationOnlyMetric):
115    REQUIRED_PARSER = PokemonRedStateParser
116
117    _TERMINATION_NAMED_REGION = "screen_bottom_half"
118    _TERMINATION_TARGET_NAME = "bought_potion_at_pewter_pokemart"
119
120
121class UsedPotionOnCharmanderTerminateMetric(RegionMatchTerminationOnlyMetric):
122    REQUIRED_PARSER = PokemonRedStateParser
123
124    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
125    _TERMINATION_TARGET_NAME = "used_potion_on_charmander"
126
127
128class OpenMapTerminateMetric(TerminationMetric):
129    REQUIRED_PARSER = PokemonRedStateParser
130
131    def determine_terminated(
132        self, current_frame: np.ndarray, recent_frames: Optional[np.ndarray]
133    ) -> bool:
134        all_frames = [current_frame]
135        if recent_frames is not None:
136            all_frames = recent_frames
137        for frame in all_frames:
138            self.state_parser: PokemonRedStateParser
139            in_map = self.state_parser.named_region_matches_target(
140                frame, "map_bottom_right"
141            )
142            if in_map:
143                return True
144        return False
145
146
147# ---------------------------------------------------------------------------
148# Pokemon Prism metrics
149# ---------------------------------------------------------------------------
150
151# Pokemon Prism is Crystal-engine based. Naljo badges share the same memory
152# layout as Johto badges in Crystal: byte at 0xD57C, one bit per badge.
153# Bit 0 = Magma Badge (Gym 1 – Brimstone City, Leader Tansy, Fire type).
154_PRISM_BADGE_ADDR = 0xD57C
155
156
157class PokemonPrismFirstBadgeTerminateMetric(
158    TerminationMetric, PokemonExitBattleTruncationMetric
159):
160    """Terminates when the player has obtained the first Naljo badge (Magma Badge)."""
161
162    REQUIRED_PARSER = PokemonPrismStateParser
163
164    def determine_terminated(
165        self, current_frame: np.ndarray, recent_frames: Optional[np.ndarray]
166    ) -> bool:
167        badge_byte = self.state_parser.read_m(_PRISM_BADGE_ADDR)
168        # Bit 0 set means the first badge has been awarded
169        return bool(badge_byte & 0x01)
class PokemonCenterTerminateMetric(gameboy_worlds.emulation.tracker.RegionMatchTerminationOnlyMetric):
18class PokemonCenterTerminateMetric(RegionMatchTerminationOnlyMetric):
19    REQUIRED_PARSER = PokemonRedStateParser
20
21    _TERMINATION_NAMED_REGION = "screen_bottom_half"
22    _TERMINATION_TARGET_NAME = "viridian_pokemon_center_entrance"

RegionMatchTerminationMetric with no truncation. No truncation.

The StateParser which implements the minimum required functionality for this MetricGroup to work.

class OutsideViridianCenterSubgoal(gameboy_worlds.emulation.tracker.AnyRegionMatchSubGoal):
25class OutsideViridianCenterSubgoal(AnyRegionMatchSubGoal):
26    NAME = "outside_viridian_center"
27    _NAMED_REGIONS = [
28        "screen_middle",
29        "screen_middle",
30    ]
31    _TARGET_NAMES = [
32        "outside_viridian_center_from_left",
33        "outside_viridian_center_from_right",
34    ]

A subgoal that is completed if any of a list of specific regions matches their targets.

NAME = 'outside_viridian_center'

Name of the subgoal.

class MtMoonTerminateMetric(gameboy_worlds.emulation.tracker.RegionMatchTerminationOnlyMetric):
37class MtMoonTerminateMetric(RegionMatchTerminationOnlyMetric):
38    REQUIRED_PARSER = PokemonRedStateParser
39
40    _TERMINATION_NAMED_REGION = "screen_bottom_half"
41    _TERMINATION_TARGET_NAME = "mt_moon_entrance"

RegionMatchTerminationMetric with no truncation. No truncation.

The StateParser which implements the minimum required functionality for this MetricGroup to work.

class SpeakToBillCompleteTerminateMetric(gameboy_worlds.emulation.tracker.RegionMatchTerminationOnlyMetric):
44class SpeakToBillCompleteTerminateMetric(RegionMatchTerminationOnlyMetric):
45    REQUIRED_PARSER = PokemonRedStateParser
46
47    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
48    _TERMINATION_TARGET_NAME = "talk_bill_complete"

RegionMatchTerminationMetric with no truncation. No truncation.

The StateParser which implements the minimum required functionality for this MetricGroup to work.

class PickupPokeballTerminateMetric(gameboy_worlds.emulation.tracker.RegionMatchTerminationOnlyMetric):
51class PickupPokeballTerminateMetric(RegionMatchTerminationOnlyMetric):
52    REQUIRED_PARSER = PokemonRedStateParser
53
54    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
55    _TERMINATION_TARGET_NAME = "pick_up_pokeball_starting"

RegionMatchTerminationMetric with no truncation. No truncation.

The StateParser which implements the minimum required functionality for this MetricGroup to work.

class ReadTrainersTipsSignTerminateMetric(gameboy_worlds.emulation.tracker.RegionMatchTerminationOnlyMetric):
58class ReadTrainersTipsSignTerminateMetric(RegionMatchTerminationOnlyMetric):
59    REQUIRED_PARSER = PokemonRedStateParser
60
61    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
62    _TERMINATION_TARGET_NAME = "trainers_tips_sign"

RegionMatchTerminationMetric with no truncation. No truncation.

The StateParser which implements the minimum required functionality for this MetricGroup to work.

class SpeakToCinnabarGymAideCompleteTerminateMetric(gameboy_worlds.emulation.tracker.RegionMatchTerminationOnlyMetric):
65class SpeakToCinnabarGymAideCompleteTerminateMetric(RegionMatchTerminationOnlyMetric):
66    REQUIRED_PARSER = PokemonRedStateParser
67
68    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
69    _TERMINATION_TARGET_NAME = "cinnabar_gym_aid_complete"

RegionMatchTerminationMetric with no truncation. No truncation.

The StateParser which implements the minimum required functionality for this MetricGroup to work.

class SpeakToCinnabarMonkTerminateMetric(gameboy_worlds.emulation.tracker.RegionMatchTerminationOnlyMetric):
72class SpeakToCinnabarMonkTerminateMetric(RegionMatchTerminationOnlyMetric):
73    REQUIRED_PARSER = PokemonRedStateParser
74
75    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
76    _TERMINATION_TARGET_NAME = "talk_cinnabar_monk"

RegionMatchTerminationMetric with no truncation. No truncation.

The StateParser which implements the minimum required functionality for this MetricGroup to work.

79class DefeatedBrockTerminateMetric(
80    RegionMatchTerminationMetric, PokemonExitBattleTruncationMetric
81):
82    REQUIRED_PARSER = PokemonRedStateParser
83
84    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
85    _TERMINATION_TARGET_NAME = "defeated_brock"

Terminates the episode if a specific region matches a target. Can be used to terminate episodes when specific dialogue boxes appear, etc.

The StateParser which implements the minimum required functionality for this MetricGroup to work.

88class DefeatedLassTerminateMetric(
89    RegionMatchTerminationMetric, PokemonExitBattleTruncationMetric
90):
91    REQUIRED_PARSER = PokemonRedStateParser
92
93    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
94    _TERMINATION_TARGET_NAME = "defeated_lass"

Terminates the episode if a specific region matches a target. Can be used to terminate episodes when specific dialogue boxes appear, etc.

The StateParser which implements the minimum required functionality for this MetricGroup to work.

 97class CaughtPidgeyTerminateMetric(
 98    RegionMatchTerminationMetric, PokemonExitBattleTruncationMetric
 99):
100    REQUIRED_PARSER = PokemonRedStateParser
101
102    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
103    _TERMINATION_TARGET_NAME = "caught_pidgey"

Terminates the episode if a specific region matches a target. Can be used to terminate episodes when specific dialogue boxes appear, etc.

The StateParser which implements the minimum required functionality for this MetricGroup to work.

106class CaughtPikachuTerminateMetric(
107    RegionMatchTerminationMetric, PokemonExitBattleTruncationMetric
108):
109    REQUIRED_PARSER = PokemonRedStateParser
110
111    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
112    _TERMINATION_TARGET_NAME = "caught_pikachu"

Terminates the episode if a specific region matches a target. Can be used to terminate episodes when specific dialogue boxes appear, etc.

The StateParser which implements the minimum required functionality for this MetricGroup to work.

class BoughtPotionAtPewterPokemartTerminateMetric(gameboy_worlds.emulation.tracker.RegionMatchTerminationOnlyMetric):
115class BoughtPotionAtPewterPokemartTerminateMetric(RegionMatchTerminationOnlyMetric):
116    REQUIRED_PARSER = PokemonRedStateParser
117
118    _TERMINATION_NAMED_REGION = "screen_bottom_half"
119    _TERMINATION_TARGET_NAME = "bought_potion_at_pewter_pokemart"

RegionMatchTerminationMetric with no truncation. No truncation.

The StateParser which implements the minimum required functionality for this MetricGroup to work.

class UsedPotionOnCharmanderTerminateMetric(gameboy_worlds.emulation.tracker.RegionMatchTerminationOnlyMetric):
122class UsedPotionOnCharmanderTerminateMetric(RegionMatchTerminationOnlyMetric):
123    REQUIRED_PARSER = PokemonRedStateParser
124
125    _TERMINATION_NAMED_REGION = "dialogue_box_middle"
126    _TERMINATION_TARGET_NAME = "used_potion_on_charmander"

RegionMatchTerminationMetric with no truncation. No truncation.

The StateParser which implements the minimum required functionality for this MetricGroup to work.

class OpenMapTerminateMetric(gameboy_worlds.emulation.tracker.TerminationMetric):
129class OpenMapTerminateMetric(TerminationMetric):
130    REQUIRED_PARSER = PokemonRedStateParser
131
132    def determine_terminated(
133        self, current_frame: np.ndarray, recent_frames: Optional[np.ndarray]
134    ) -> bool:
135        all_frames = [current_frame]
136        if recent_frames is not None:
137            all_frames = recent_frames
138        for frame in all_frames:
139            self.state_parser: PokemonRedStateParser
140            in_map = self.state_parser.named_region_matches_target(
141                frame, "map_bottom_right"
142            )
143            if in_map:
144                return True
145        return False

Tracks whether the environment was terminated or truncated.

Reports:

  • terminated: Whether the environment was terminated.
  • truncated: Whether the environment was truncated.

Final Reports:

  • episode_end_reason: List of reasons for episode endings: "terminated", "truncated", or None (None will occur only if there is a bug that leads to a premature reset).

The StateParser which implements the minimum required functionality for this MetricGroup to work.

def determine_terminated( self, current_frame: numpy.ndarray, recent_frames: Optional[numpy.ndarray]) -> bool:
132    def determine_terminated(
133        self, current_frame: np.ndarray, recent_frames: Optional[np.ndarray]
134    ) -> bool:
135        all_frames = [current_frame]
136        if recent_frames is not None:
137            all_frames = recent_frames
138        for frame in all_frames:
139            self.state_parser: PokemonRedStateParser
140            in_map = self.state_parser.named_region_matches_target(
141                frame, "map_bottom_right"
142            )
143            if in_map:
144                return True
145        return False

Determines whether the environment was terminated.

Parameters
  • current_frame: The current frame rendered by the emulator.
  • recent_frames: The stack of frames that were rendered during the last action. Shape is [n_frames, height, width, channels]. Can be None if rendering is disabled.
Returns

True if the environment was terminated, False otherwise.

158class PokemonPrismFirstBadgeTerminateMetric(
159    TerminationMetric, PokemonExitBattleTruncationMetric
160):
161    """Terminates when the player has obtained the first Naljo badge (Magma Badge)."""
162
163    REQUIRED_PARSER = PokemonPrismStateParser
164
165    def determine_terminated(
166        self, current_frame: np.ndarray, recent_frames: Optional[np.ndarray]
167    ) -> bool:
168        badge_byte = self.state_parser.read_m(_PRISM_BADGE_ADDR)
169        # Bit 0 set means the first badge has been awarded
170        return bool(badge_byte & 0x01)

Terminates when the player has obtained the first Naljo badge (Magma Badge).

The StateParser which implements the minimum required functionality for this MetricGroup to work.

def determine_terminated( self, current_frame: numpy.ndarray, recent_frames: Optional[numpy.ndarray]) -> bool:
165    def determine_terminated(
166        self, current_frame: np.ndarray, recent_frames: Optional[np.ndarray]
167    ) -> bool:
168        badge_byte = self.state_parser.read_m(_PRISM_BADGE_ADDR)
169        # Bit 0 set means the first badge has been awarded
170        return bool(badge_byte & 0x01)

Determines whether the environment was terminated.

Parameters
  • current_frame: The current frame rendered by the emulator.
  • recent_frames: The stack of frames that were rendered during the last action. Shape is [n_frames, height, width, channels]. Can be None if rendering is disabled.
Returns

True if the environment was terminated, False otherwise.