gameboy_worlds.emulation.harvest_moon.parsers

Harvest Moon GBC game state parser implementations. Uses visual screen regions to parse game state, following the same design principles as the Pokemon parsers.

CORE DESIGN PRINCIPLE: Never branch the parser subclasses for a given variant. The inheritance tree for a parser after the game variant parser should always be a tree with only one child per layer. This is to ensure that we don't double effort, any capability added to a parser will always be valid for that game variant. If this principle is followed, any state tracker can always use the STRONGEST (lowest level) parser for a given variant without concern for missing functionality.

   1"""
   2Harvest Moon GBC game state parser implementations.
   3Uses visual screen regions to parse game state, following the same design principles as the Pokemon parsers.
   4
   5CORE DESIGN PRINCIPLE: Never branch the parser subclasses for a given variant. The inheritance tree for a parser after the game variant parser should always be a tree with only one child per layer.
   6This is to ensure that we don't double effort, any capability added to a parser will always be valid for that game variant.
   7If this principle is followed, any state tracker can always use the STRONGEST (lowest level) parser for a given variant without concern for missing functionality.
   8"""
   9
  10from gameboy_worlds.emulation.parser import NamedScreenRegion
  11from gameboy_worlds.utils import (
  12    log_warn,
  13    log_info,
  14    log_error,
  15    load_parameters,
  16    verify_parameters,
  17)
  18from gameboy_worlds.emulation.parser import StateParser, _get_proper_regions
  19
  20from typing import Set, List, Type, Dict, Optional, Tuple
  21import os
  22from abc import ABC, abstractmethod
  23from enum import Enum
  24
  25from pyboy import PyBoy
  26
  27import json
  28import numpy as np
  29from bidict import bidict
  30
  31
  32class AgentState(Enum):
  33    """
  34    0. FREE_ROAM: The agent is freely roaming the game world.
  35    1. IN_DIALOGUE: The agent is currently in a dialogue state.
  36    2. IN_MENU: The agent has a menu open.
  37    """
  38
  39    FREE_ROAM = 0
  40    IN_DIALOGUE = 1
  41    IN_MENU = 2
  42    IN_STORAGE_LIST = 3
  43
  44
  45class HarvestMoonStateParser(StateParser, ABC):
  46    """
  47    Base class for Harvest Moon GBC game state parsers. Uses visual screen regions to parse game state.
  48    Defines common named screen regions and methods for determining game states such as being in dialogue.
  49
  50    Can be used to determine the exact AgentState.
  51    """
  52
  53    COMMON_REGIONS = []
  54    """ List of common single-target named screen regions for Harvest Moon games. """
  55
  56    COMMON_MULTI_TARGET_REGIONS = [
  57        ("screen", 0, 0, 150, 140),
  58        ("screen_middle", 65, 55, 20, 20),
  59        ("dialogue_box_top", 58, 10, 40, 10),
  60    ]
  61    """ List of common multi-target named screen regions for Harvest Moon games.
  62
  63    - dialogue_bottom_right: Bottom-right corner of the dialogue box (x=153, y=135, 10x10px).
  64      Capture while dialogue is visible in dev_play: `c dialogue_bottom_right,<type_name>`
  65    - screen_bottom: Bottom strip of the screen (x=0, y=100, 160x40px).
  66      Useful for detecting locations and events. Capture in dev_play: `c screen_bottom,<target_name>`
  67    """
  68
  69    COMMON_MULTI_TARGETS = {
  70        "screen_bottom": [
  71            "cow_barn_entrance",
  72            "chicken_coop_entrance",
  73        ],
  74    }
  75    """ Common multi-targets for the common multi-target named screen regions.
  76    - screen_bottom: Location/event captures for the bottom strip of the screen.
  77    """
  78
  79    def __init__(
  80        self,
  81        variant: str,
  82        pyboy: PyBoy,
  83        parameters: dict,
  84        additional_named_screen_region_details: List[
  85            Tuple[str, int, int, int, int]
  86        ] = [],
  87        additional_multi_target_named_screen_region_details: List[
  88            Tuple[str, int, int, int, int]
  89        ] = [],
  90        override_multi_targets: Dict[str, List[str]] = {},
  91    ):
  92        """
  93        Initializes the HarvestMoonStateParser.
  94        Args:
  95            pyboy (PyBoy): The PyBoy emulator instance.
  96            parameters (dict): Configuration parameters for the emulator.
  97            additional_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional named screen regions to include.
  98            additional_multi_target_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional multi-target named screen regions to include.
  99            override_multi_targets (Dict[str, List[str]]): Dictionary mapping region names to lists of additional target names for multi-target regions.
 100        """
 101        verify_parameters(parameters)
 102        regions = _get_proper_regions(
 103            override_regions=additional_named_screen_region_details,
 104            base_regions=self.COMMON_REGIONS,
 105        )
 106        self.variant = variant
 107        if f"{variant}_rom_data_path" not in parameters:
 108            log_error(
 109                f"ROM data path not found for variant: {variant}. Add {variant}_rom_data_path to the config files. See configs/pokemon_red_vars.yaml for an example",
 110                parameters,
 111            )
 112        self.rom_data_path = parameters[f"{variant}_rom_data_path"]
 113        """ Path to the ROM data directory for the specific Harvest Moon variant."""
 114        captures_dir = self.rom_data_path + "/captures/"
 115        named_screen_regions = []
 116        for region_name, x, y, w, h in regions:
 117            region = NamedScreenRegion(
 118                region_name,
 119                x,
 120                y,
 121                w,
 122                h,
 123                parameters=parameters,
 124                target_path=os.path.join(captures_dir, region_name),
 125            )
 126            named_screen_regions.append(region)
 127        multi_target_regions = _get_proper_regions(
 128            override_regions=additional_multi_target_named_screen_region_details,
 129            base_regions=self.COMMON_MULTI_TARGET_REGIONS,
 130        )
 131        multi_target_region_names = [region[0] for region in multi_target_regions]
 132        multi_targets = self.COMMON_MULTI_TARGETS.copy()
 133        for key in override_multi_targets:
 134            if key in multi_targets:
 135                multi_targets[key].extend(override_multi_targets[key])
 136            else:
 137                multi_targets[key] = override_multi_targets[key]
 138        multi_target_provided_region_names = list(multi_targets.keys())
 139        if not set(multi_target_provided_region_names).issubset(
 140            set(multi_target_region_names)
 141        ):
 142            log_error(
 143                f"Multi-target regions provided in multi_targets do not match the defined multi-target regions. Provided: {multi_target_provided_region_names}, Defined: {multi_target_region_names}",
 144                parameters,
 145            )
 146        for region_name, x, y, w, h in multi_target_regions:
 147            region_target_paths = {}
 148            subdir = captures_dir + f"/{region_name}/"
 149            for target_name in multi_targets.get(region_name, []):
 150                region_target_paths[target_name] = os.path.join(subdir, target_name)
 151            region = NamedScreenRegion(
 152                region_name,
 153                x,
 154                y,
 155                w,
 156                h,
 157                parameters=parameters,
 158                multi_target_paths=region_target_paths,
 159            )
 160            named_screen_regions.append(region)
 161        super().__init__(pyboy, parameters, named_screen_regions)    
 162
 163    def get_agent_state(self, current_screen: np.ndarray) -> AgentState:
 164        if self.is_in_dialogue(current_screen):
 165            return AgentState.IN_DIALOGUE
 166        return AgentState.FREE_ROAM
 167
 168
 169class BaseHarvestMoonStateParser(HarvestMoonStateParser, ABC):
 170    """
 171    Game state parser for all Harvest Moon GBC-based games.
 172    """
 173
 174    REGIONS = [
 175    ]
 176    """ Additional named screen regions specific to Harvest Moon GBC games.
 177    """
 178
 179    MULTI_TARGET_REGIONS = [
 180    ]
 181    """ Additional multi-target named screen regions specific to Harvest Moon GBC games. 
 182    """
 183
 184    def __init__(
 185        self,
 186        pyboy: PyBoy,
 187        variant: str,
 188        parameters: dict,
 189        override_regions: List[Tuple[str, int, int, int, int]] = [],
 190        override_multi_target_regions: List[Tuple[str, int, int, int, int]] = [],
 191        override_multi_targets: Dict[str, List[str]] = {},
 192    ):
 193        self.REGIONS = _get_proper_regions(
 194            override_regions=override_regions, base_regions=self.REGIONS
 195        )
 196        self.MULTI_TARGET_REGIONS = _get_proper_regions(
 197            override_regions=override_multi_target_regions,
 198            base_regions=self.MULTI_TARGET_REGIONS,
 199        )
 200        super().__init__(
 201            variant=variant,
 202            pyboy=pyboy,
 203            parameters=parameters,
 204            additional_named_screen_region_details=self.REGIONS,
 205            additional_multi_target_named_screen_region_details=self.MULTI_TARGET_REGIONS,
 206            override_multi_targets=override_multi_targets,
 207        )
 208    
 209    def __repr__(self):
 210        return f"<HarvestMoonParser(variant={self.variant})>"
 211
 212class HarvestMoon1Parser(BaseHarvestMoonStateParser):
 213
 214    DIALOGUE_TYPES = [
 215        "home_dialogue",
 216        "shop_dialogue",
 217        "church_dialogue",
 218        "harvest_spirits_dialogue",
 219        "read_signs_dialogue",
 220        "evening_dialogue",
 221        "barn_dialogue",
 222        "winter_read_signs_dialogue",
 223        "winter_evening_dialogue",
 224    ]
 225    def __init__(self, pyboy, parameters):
 226        override_regions = [
 227            ("menu_top_right", 153, 0, 5, 5),
 228            ("storage_list_top_right", 153, 0, 6, 6),
 229        ]
 230        
 231        override_multi_target_regions = [
 232            ("dialogue_bottom_right", 153, 135, 10, 10),
 233            ("screen", 0, 0, 160, 143),
 234            ("screen_middle", 65, 63, 30, 30),
 235            ("screen_bottom", 0, 100, 160, 40),
 236            ("dialogue_box_top", 60, 11, 40, 8),
 237            ("dialogue_box_top_mid", 68, 11, 22, 8),
 238            ("dialogue_box_top_short", 71, 11, 15, 8),
 239            ("dialogue_box_bottom", 0, 105, 160, 35),
 240            ("item_bed", 0, 40, 40, 40),
 241            ("item_watercan_above", 56, 85, 15, 35),
 242            ("item_watercan_right", 55, 80, 30, 20),
 243            ("item_watercan_below", 56, 70, 15, 30),
 244            ("item_cowbell_above", 39, 49, 15, 35),
 245            ("item_cowbell_below", 39, 70, 15, 30),
 246            ("item_sickle_above", 88, 85, 15, 35),
 247            ("item_sickle_left", 70, 80, 30, 20),
 248            ("item_sickle_below", 88, 70, 15, 30),
 249            ("item_hoe_above", 102, 85, 15, 35),
 250            ("item_hoe_below", 102, 70, 15, 30),
 251            ("item_hammer_above", 120, 85, 15, 35),
 252            ("item_hammer_below", 120, 70, 15, 30),
 253            ("item_grass_seed_above", 56, 55, 15, 35),
 254            ("item_grass_seed_right", 55, 70, 30, 20),
 255            ("item_grass_seed_below", 56, 70, 15, 30),
 256            ("item_storage_list", 0, 40, 20, 30),
 257            ("item_spirit_left", 70, 50, 30, 30),
 258            ("item_spirit_below", 70, 50, 30, 30),
 259            ("item_spirit_above", 70, 50, 15, 50),
 260            ("item_safe_below", 40, 30, 15, 40),
 261            ("item_lost_bird_left", 70, 65, 30, 25),
 262            ("item_lost_bird_right", 60, 65, 30, 25),
 263            ("item_lost_bird_below", 70, 50, 20, 35),
 264            ("item_blue_hair_girl_left", 80, 20, 30, 30),
 265            ("item_blue_hair_girl_right", 95, 20, 30, 30),
 266            ("item_blue_hair_girl_below", 95, 20, 20, 40),
 267            ("item_golden_hair_girl_above", 32, 40, 15, 40),
 268            ("item_golden_hair_girl_right", 30, 55, 35, 25),
 269            ("item_golden_hair_girl_below", 32, 55, 15, 35),
 270            ("item_pink_hair_girl_left", 32, 68, 33, 22),
 271            ("item_pink_hair_girl_right", 48, 68, 30, 22),
 272            ("item_pink_hair_girl_above", 48, 68, 15, 38),
 273            ("item_blue_hair_girl_wg_left", 80, 25, 30, 20),  
 274            ("item_blue_hair_girl_wg_right", 97, 25, 30, 21),
 275            ("item_blue_hair_girl_wg_below", 97, 25, 13, 35), 
 276            ("item_pink_hair_girl_wg_left",  32, 68, 33, 22), 
 277            ("item_pink_hair_girl_wg_right", 48, 68, 30, 22), 
 278            ("item_pink_hair_girl_wg_above", 48, 68, 15, 38), 
 279            ("item_red_hair_girl_wg_left", 80, 68, 30, 22),
 280            ("item_red_hair_girl_wg_right", 97, 68, 30, 22),
 281            ("item_red_hair_girl_wg_above", 97, 68, 13, 40),
 282            ("item_chicken_stall_block1", 5, 40, 25, 20),
 283            ("item_next_to_chicken_stall_block1", 5, 55, 25, 25),
 284            ("item_chicken_silo_left", 100, 40, 30, 30),
 285            ("item_chicken_silo_below1", 120, 50, 15, 35),
 286            ("item_chicken_silo_below2", 135, 50, 15, 35),
 287            ("item_cow_feeding_stall", 55, 25, 30, 45),
 288            ("item_cow_feeding_stall_right", 55, 25, 45, 45),
 289            ("item_egg_left", 89, 75, 31, 25),
 290            ("item_egg_above", 105, 78, 15, 37),
 291            ("item_egg_right", 110, 75, 22, 25),
 292            ("item_hatching_box", 120, 70, 35, 30), 
 293            ("turnip_center", 70, 90, 20, 20),
 294            ("turnip_top", 70, 70, 20, 35),
 295            ("item_turnip_field", 55, 65, 47, 54),
 296            ("item_turnip_field_water", 40, 58, 47, 47),
 297            ("item_potato_field", 55, 40, 47, 54),
 298            ("item_rock_left", 0, 65, 45, 20),
 299            ("item_rightmost_rock_above", 55, 60, 33, 40),
 300            ("item_weed_above", 15, 65, 30, 50),
 301            ("item_top_left_weed", 25, 60, 25, 25),
 302            ("item_grassland_right", 50, 60, 35, 30),
 303            ("item_center_grassline", 40, 70, 95, 20),
 304            ("item_broken_fence_field", 63, 55, 30, 30),
 305            ("item_fence_field", 0, 40, 30, 60),
 306            ("center_sign", 55, 65, 50, 15),
 307            ("screen_top_half", 0, 0, 160, 65),
 308            ("screen_bottom_half", 0, 75, 160, 65),
 309            ("left_border_frame", 0, 0, 5, 140),
 310        ]
 311        
 312        override_multi_targets = {
 313            "dialogue_bottom_right":[
 314                "home_dialogue",
 315                "shop_dialogue",
 316                "church_dialogue",
 317                "harvest_spirits_dialogue",
 318                "read_signs_dialogue",
 319                "evening_dialogue",
 320                "barn_dialogue",
 321                "winter_read_signs_dialogue",
 322                "winter_evening_dialogue",
 323            ],
 324            "screen_middle":[
 325                "outside_cow_barn_left",
 326                "outside_cow_barn_right",
 327                "outside_cow_barn_up",
 328                "outside_chicken_coop_left",
 329                "outside_chicken_coop_right",
 330                "outside_chicken_coop_up",
 331                "outside_storage_left",
 332                "outside_storage_right",
 333                "outside_storage_up",
 334            ],
 335            "screen_bottom": [
 336                "cow_barn_entrance",
 337                "chicken_coop_entrance",
 338                "storage_shed_entrance",
 339            ],
 340            "dialogue_box_bottom":[
 341                "found_rainy_money",
 342                "select_material",
 343                "select_home_expansion",
 344                "select_chicken",
 345                "select_selling_chicken",
 346                "select_cow",
 347                "bought_named_cow",
 348                "select_cow_brush",
 349                "select_saddlebag",
 350                "select_milker",
 351                "choose_yes_for_sleep",
 352                "fed_spirit",
 353                "helped_spirit_earthquake",
 354                "select_rice_ball",
 355                "select_croissant",
 356                "select_cake",
 357                "select_grape_juice",
 358                "found_bird_for_friend",
 359                "speaking_to_blue_hair_girl",
 360                "speaking_to_golden_hair_girl",
 361                "speaking_to_pink_hair_girl",
 362                "speaking_to_blue_hair_girl_wg",
 363                "speaking_to_pink_hair_girl_wg",
 364                "speaking_to_red_hair_girl_wg",
 365                "option_to_pray",
 366                "praying",
 367            ],
 368            "item_bed":[
 369                "sleep_in_bed",
 370            ],
 371            "item_storage_list":[
 372                "next_to_storage_list",
 373            ],
 374            "item_watercan_above":[
 375                "pickup_watercan_down",
 376            ],
 377            "item_watercan_right":[
 378                "pickup_watercan_left",
 379            ],
 380            "item_cowbell_above":[
 381                "next_to_cowbell_down",
 382            ],
 383            "item_cowbell_below":[
 384                "next_to_cowbell_up",
 385            ],
 386            "item_watercan_below":[
 387                "pickup_watercan_up",
 388            ],
 389            "item_sickle_above":[
 390                "pickup_sickle_down",
 391            ],
 392            "item_sickle_left":[
 393                "pickup_sickle_right",
 394            ],
 395            "item_sickle_below":[
 396                "pickup_sickle_up",
 397            ],
 398            "item_hoe_above":[
 399                "pickup_hoe_down",
 400            ],
 401            "item_hoe_below":[
 402                "pickup_hoe_up",
 403            ],
 404            "item_hammer_above":[
 405                "pickup_hammer_down",
 406            ],
 407            "item_hammer_below":[
 408                "pickup_hammer_up",
 409            ],
 410            "item_grass_seed_above":[
 411                "pickup_grass_seed_down",
 412            ],
 413            "item_grass_seed_right":[
 414                "pickup_grass_seed_left",
 415            ],
 416            "item_grass_seed_below":[
 417                "pickup_grass_seed_up",
 418            ],
 419            "item_spirit_left":[
 420                "feed_spirit_right",
 421                "help_spirit_earthquake_right",
 422            ],
 423            "item_spirit_above":[
 424                "feed_spirit_down",
 425                "help_spirit_earthquake_down",
 426            ],
 427            "item_spirit_below":[
 428                "feed_spirit_up",
 429                "help_spirit_earthquake_up",
 430            ],
 431            "item_safe_below":[
 432                "next_to_safe_up",
 433                "next_to_safe_left",
 434            ],
 435            "item_lost_bird_left":[
 436                "find_lost_bird_right",
 437            ],
 438            "item_lost_bird_right":[
 439                "find_lost_bird_left",
 440            ], 
 441            "item_lost_bird_below":[
 442                "find_lost_bird_up",
 443            ],
 444            "item_blue_hair_girl_left":[
 445                "next_to_blue_hair_girl_right",
 446            ],
 447            "item_blue_hair_girl_right":[
 448                "next_to_blue_hair_girl_left",
 449            ],
 450            "item_blue_hair_girl_below":[
 451                "next_to_blue_hair_girl_up",
 452            ],
 453            "item_golden_hair_girl_above":[
 454                "next_to_golden_hair_girl_down",
 455            ],
 456            "item_golden_hair_girl_right":[
 457                "next_to_golden_hair_girl_left",
 458            ],
 459            "item_golden_hair_girl_below":[
 460                "next_to_golden_hair_girl_up",
 461            ],
 462            "item_pink_hair_girl_left":[
 463                "next_to_pink_hair_girl_right",
 464            ],
 465            "item_pink_hair_girl_right":[
 466                "next_to_pink_hair_girl_left",
 467            ],
 468            "item_pink_hair_girl_above":[
 469                "next_to_pink_hair_girl_down",
 470            ],
 471            "item_blue_hair_girl_wg_left": [
 472                "next_to_blue_hair_girl_wg_right",
 473            ],
 474            "item_blue_hair_girl_wg_right": [
 475                "next_to_blue_hair_girl_wg_left",
 476            ],
 477            "item_blue_hair_girl_wg_below": [
 478                "next_to_blue_hair_girl_wg_up",
 479            ],
 480            "item_pink_hair_girl_wg_left": [
 481                "next_to_pink_hair_girl_wg_right",
 482            ],
 483            "item_pink_hair_girl_wg_right": [
 484                "next_to_pink_hair_girl_wg_left",
 485            ],
 486            "item_pink_hair_girl_wg_above": [
 487                "next_to_pink_hair_girl_wg_down",
 488            ],
 489            "item_red_hair_girl_wg_left": [
 490                "next_to_red_hair_girl_wg_right",
 491            ],
 492            "item_red_hair_girl_wg_right": [
 493                "next_to_red_hair_girl_wg_left",
 494            ],
 495            "item_red_hair_girl_wg_above": [
 496                "next_to_red_hair_girl_wg_down",
 497            ],
 498            "item_chicken_stall_block1":[
 499                "filled_chicken_stall_block1",
 500            ],
 501            "item_next_to_chicken_stall_block1":[
 502                "next_to_chicken_stall_block1",
 503            ],
 504            "item_chicken_silo_left":[
 505                "next_to_chicken_silo_right",
 506                "got_fodder_from_chicken_silo_right",
 507            ],
 508            "item_chicken_silo_below1":[
 509                "next_to_chicken_silo_up1",
 510                "got_fodder_from_chicken_silo_up1",
 511            ],
 512            "item_chicken_silo_below2":[
 513                "next_to_chicken_silo_up2",
 514                "got_fodder_from_chicken_silo_up2",
 515            ],
 516            "item_cow_feeding_stall": [
 517                "cow_feeding_stall_filled",
 518            ],
 519            "item_cow_feeding_stall_right": [
 520                "next_to_cow_feeding_stall_left",
 521            ],
 522            "item_egg_left": [
 523                "next_to_egg_right",
 524            ],
 525            "item_egg_above": [
 526                "next_to_egg_down",
 527            ],
 528            "item_egg_right": [
 529                "next_to_egg_left",
 530            ],
 531            "item_hatching_box": [
 532                "dropped_egg_into_hatching_box",
 533            ],
 534            "dialogue_box_top":[
 535                "pick_up_watercan",
 536                "pick_up_grass_seed",
 537            ],
 538            "dialogue_box_top_mid":[
 539                "pick_up_sickle",
 540                "pick_up_hammer",
 541                "pick_up_cowbell",
 542            ],
 543            "dialogue_box_top_short":[
 544                "pick_up_hoe",
 545            ],
 546            "turnip_center":[
 547                "finish_watering_1",
 548                "finish_watering_2",
 549            ],
 550            "turnip_top":[
 551                "ready_to_water_1",
 552                "ready_to_water_2",
 553            ],
 554            "item_turnip_field": [
 555                "next_to_center_turnip_down_1",
 556                "next_to_center_turnip_down_2",
 557                "center_turnip_harvested_1",
 558                "center_turnip_harvested_2",
 559            ],
 560            "item_turnip_field_water":[
 561                "next_to_center_turnip_left_1",
 562                "next_to_center_turnip_left_2",
 563                "center_turnip_watered_1",
 564                "center_turnip_watered_2",
 565            ],
 566            "item_potato_field": [
 567                "next_to_center_potato_up_1",
 568                "next_to_center_potato_up_2",
 569                "next_to_center_potato_below_up_1",
 570                "next_to_center_potato_below_up_2",
 571                "center_potato_watered_1",
 572                "center_potato_watered_2",
 573                "center_potato_harvested_1",
 574                "center_potato_harvested_2",
 575            ],
 576            "item_rock_left": [
 577                "next_to_rock_right",
 578                "rock_cleared",
 579            ],
 580            "item_rightmost_rock_above": [
 581                "next_to_rightmost_rock_down",
 582                "rightmost_rock_cleared",
 583            ],
 584            "item_weed_above": [
 585                "next_to_lowest_weed_down",
 586                "lowest_weed_removed",
 587                "lowest_weed_cut",
 588            ],
 589            "item_top_left_weed": [
 590                "next_to_top_left_weed_up",
 591                "top_left_weed_removed",
 592                "top_left_weed_cut",
 593            ],
 594            "item_grassland_right": [
 595                "next_to_grassland_left",
 596            ],
 597            "item_center_grassline": [
 598                "center_grass_harvested_1",
 599                "center_grass_harvested_2",
 600            ],
 601            "item_broken_fence_field": [
 602                "picked_up_broken_fence_up",
 603                "picked_up_broken_fence_down",
 604                "picked_up_broken_fence_left",
 605                "picked_up_broken_fence_right",
 606            ],
 607            "item_fence_field": [
 608                "restored_fence",
 609            ],
 610            "center_sign":[
 611                "outside_carpenter",
 612                "outside_animal_shop",
 613                "outside_tool_shop",
 614                "outside_restaurant",
 615                "outside_juice_bar",
 616                "outside_church",
 617            ],
 618            "screen_bottom_half":[
 619                "bought_material",
 620                "home_expansion_estimate",
 621                "bought_chicken",
 622                "sold_chicken",
 623                "bought_cow_brush",
 624                "bought_saddlebag",
 625                "bought_milker",
 626                "option_to_buy_rice_ball",
 627                "bought_rice_ball",
 628                "option_to_buy_croissant",
 629                "bought_croissant",
 630                "option_to_buy_cake",
 631                "bought_cake",
 632                "option_to_buy_grape_juice",
 633                "bought_grape_juice",
 634            ],
 635            "screen_top_half":[
 636                "in_carpenter",
 637                "in_animal_shop",
 638                "in_tool_shop",
 639                "in_restaurant",
 640                "in_juice_bar",
 641                "in_church",
 642            ],
 643            "left_border_frame":[
 644                "open_storage_list",
 645            ],
 646        }
 647
 648        super().__init__(
 649            pyboy,
 650            variant="harvest_moon_1",
 651            parameters=parameters,
 652            override_regions=override_regions,
 653            override_multi_target_regions=override_multi_target_regions,
 654            override_multi_targets=override_multi_targets,
 655        )
 656
 657    def dialogue_box_open(self, current_screen: np.ndarray) -> bool:
 658        """
 659        Determines if a dialogue box is currently open by checking the dialogue bottom right region.
 660        Args:
 661            current_screen (np.ndarray): The current screen frame from the emulator.
 662        Returns:
 663            bool: True if a dialogue box is open, False otherwise.
 664        """
 665        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
 666        return self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
 667            self.DIALOGUE_TYPES, captured
 668        )
 669
 670    def dialogue_box_empty(self, current_screen: np.ndarray) -> bool:
 671        box = self.capture_named_region(
 672            current_frame=current_screen, name="dialogue_box_bottom"
 673        )
 674        perc_lt_255 = np.mean(box < 255)
 675        if perc_lt_255 < 0.082:  # Empirical threshold
 676            return True
 677        return False
 678    
 679    def is_in_menu(self, current_screen: np.ndarray) -> bool:
 680        return self.named_region_matches_target(current_screen, "menu_top_right")
 681
 682    def is_in_storage_list(self, current_screen: np.ndarray) -> bool:
 683        return self.named_region_matches_target(current_screen, "storage_list_top_right")
 684
 685    def is_in_dialogue(self, current_screen: np.ndarray) -> bool:
 686        """
 687        Returns True if the dialogue_bottom_right region matches any of the saved dialogue type targets.
 688        """
 689        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
 690        return self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
 691            self.DIALOGUE_TYPES, captured
 692        )
 693
 694    def get_agent_state(self, current_screen: np.ndarray) -> AgentState:
 695        """
 696        Determines the current agent state based on the screen.
 697
 698        Args:
 699            current_screen (np.ndarray): The current screen frame from the emulator.
 700
 701        Returns:
 702            AgentState: The current agent state.
 703        """
 704        if self.is_in_menu(current_screen):
 705            return AgentState.IN_MENU
 706        if self.is_in_storage_list(current_screen):
 707            return AgentState.IN_STORAGE_LIST
 708        if self.is_in_dialogue(current_screen):
 709            return AgentState.IN_DIALOGUE
 710        return AgentState.FREE_ROAM
 711        
 712class HarvestMoon2Parser(BaseHarvestMoonStateParser):
 713    DIALOGUE_TYPES = [
 714        "home_dialogue",
 715        "carpenter_dialogue",
 716        "hospital_dialogue",
 717        "tool_shop_dialogue",
 718        "animal_shop_dialogue",
 719        "restaurant_dialogue",
 720        "library_dialogue",
 721        "flower_shop_dialogue",
 722        "church_dialogue",
 723        "read_signs_dialogue",
 724        "barn_dialogue",
 725    ]
 726
 727    def __init__(self, pyboy, parameters):
 728        override_regions = [
 729            ("menu_top_right", 153, 8, 6, 6),
 730            ("storage_list_top_right", 153, 0, 6, 6),
 731        ]
 732        override_multi_target_regions = [
 733            ("dialogue_bottom_right", 153, 135, 10, 10),
 734            ("screen_middle", 50, 25, 40, 43),
 735            ("outside_barns", 40, 15, 50, 53),
 736            ("screen_bottom", 0, 95, 160, 40),
 737            ("dialogue_box_top", 60, 11, 40, 8),
 738            ("dialogue_box_bottom", 0, 105, 160, 35),
 739            ("hospital_location", 65, 0, 55, 70),
 740            ("tool_shop_location", 65, 0, 55, 70),
 741            ("carpenter_location", 35, 0, 55, 70),
 742            ("animal_shop_location", 65, 0, 55, 70),
 743            ("library_location", 35, 0, 55, 70),
 744            ("flower_shop_location", 30, 0, 105, 70),
 745            ("restaurant_location", 40, 0, 70, 70),
 746            ("item_clock_below", 95, 25, 15, 45),
 747            ("item_bed", 0, 40, 40, 40),
 748            ("item_diary", 45, 40, 20, 40),
 749            ("item_storage_list", 0, 40, 20, 30),
 750            ("item_village_sign_above", 70, 85, 20, 35),
 751            ("item_village_sign_left", 55, 70, 30, 25),
 752            ("item_village_sign_right", 75, 70, 30, 25),
 753            ("item_farm_sign_above", 70, 85, 20, 35),
 754            ("item_farm_sign_left", 55, 70, 30, 25),
 755            ("item_farm_sign_right", 75, 70, 30, 25),
 756            ("item_secret_garden_sign_above", 74, 50, 15, 45),
 757            ("item_secret_garden_sign_right", 58, 50, 27, 25),
 758            ("item_secret_garden_sign_left", 72, 50, 30, 25),
 759            ("item_crop_field_sign_above", 71, 55, 24, 40),
 760            ("item_notice_board_above", 70, 85, 20, 35),
 761            ("item_notice_board_left", 55, 70, 30, 25),
 762            ("item_notice_board_right", 75, 70, 30, 25),
 763            ("turnip_center", 70, 90, 20, 20),
 764            ("turnip_top", 70, 70, 20, 35),
 765            ("item_eggplant_field", 55, 25, 50, 45),
 766            ("item_carrot_field", 55, 25, 50, 45),
 767            ("item_next_to_shipping_box", 0, 20, 30, 50),
 768            ("item_shipping_box_field", 0, 20, 45, 25),
 769            ("item_start_line", 0, 20, 30, 50),
 770            ("item_distance_markers", 65, 40, 30, 30),
 771            ("item_potato_field", 32, 40, 50, 45),
 772            ("item_asparagus_field", 70, 40, 50, 45),
 773            ("item_corn_field", 55, 40, 48, 47),
 774            ("item_cabbage_field", 55, 40, 48, 47),
 775            ("item_center_corn_above", 58, 50, 45, 50),
 776            ("item_leftmost_weed_right", 10, 50, 35, 23),
 777            ("item_leftmost_weed_above", 10, 50, 20, 43),
 778            ("item_berry_left", 70, 39, 32, 31),
 779            ("item_berry_above", 68, 38, 18, 48),
 780            ("item_chicken_stall_block1", 5, 20, 35, 20),
 781            ("item_next_to_chicken_stall_block1", 5, 35, 35, 30),
 782            ("item_chicken_silo_left1", 100, 30, 30, 30),
 783            ("item_chicken_silo_left2", 100, 40, 30, 30),
 784            ("item_chicken_silo_below", 115, 38, 15, 35),
 785            ("item_next_to_hatching_box", 113, 60, 37, 40),
 786            ("item_hatching_box", 129, 66, 16, 30),
 787            ("npc_blue_hair_girl_left", 66, 39, 29, 21),
 788            ("npc_blue_hair_girl_below", 72, 28, 16, 39),
 789            ("npc_blue_hair_girl_right", 56, 39, 29, 21),
 790            ("npc_purple_hair_girl_left", 98, 39, 30, 21),
 791            ("npc_purple_hair_girl_below", 114, 31, 16, 39),
 792            ("npc_blonde_girl_right", 31, 48, 29, 21),
 793            ("npc_blonde_girl_above", 31, 48, 14, 47),
 794            ("center_sign", 55, 65, 50, 15),
 795            ("screen_top_half", 0, 0, 160, 65),
 796            ("screen_bottom_half", 0, 75, 160, 65),
 797            ("left_border_frame", 0, 0, 5, 140),
 798            ("top_left_label", 0, 0, 160, 15),
 799            ("equipment_region_1", 45, 15, 26, 17),
 800            ("equipment_region_2", 72, 15, 26, 17),
 801            ("equipment_region_3", 95, 15, 26, 17),
 802            ("equipment_region_4", 119, 15, 26, 17),
 803        ]
 804        override_multi_targets = {
 805            "dialogue_bottom_right": [
 806                "home_dialogue",
 807                "carpenter_dialogue",
 808                "hospital_dialogue",
 809                "tool_shop_dialogue",
 810                "animal_shop_dialogue",
 811                "restaurant_dialogue",
 812                "library_dialogue",
 813                "flower_shop_dialogue",
 814                "church_dialogue",
 815                "read_signs_dialogue",
 816                "barn_dialogue",
 817            ],
 818            "dialogue_box_bottom": [
 819                "found_lucky_money",
 820                "option_to_diary_sleep",
 821                "reading_secret_garden_sign",
 822                "reading_crop_field_sign",
 823                "computers_article_selected",
 824                "reading_computers_article",
 825                "boulders_article_selected",
 826                "reading_boulders_article",
 827                "crops_article_selected",
 828                "reading_crops_article",
 829                "select_cow",
 830                "bought_named_cow",
 831                "select_chicken",
 832                "select_selling_chicken",
 833                "select_selling_cow",
 834                "select_hothouse",
 835                "select_bridge",
 836                "select_milker",
 837                "speaking_to_blue_hair_girl",
 838                "speaking_to_purple_hair_girl",
 839                "speaking_to_blonde_girl",
 840            ],
 841            "item_clock_below": [
 842                "next_to_clock_up",
 843            ],
 844            "flower_shop_location": [
 845                "outside_flower_shop_up",
 846                "outside_flower_shop_left",
 847                "outside_flower_shop_right",
 848            ],
 849            "item_bed": [
 850                "sleep_in_bed",
 851            ],
 852            "item_diary": [
 853                "next_to_diary",
 854            ],
 855            "item_secret_garden_sign_above": [
 856                "next_to_secret_garden_sign_down",
 857            ],
 858            "item_secret_garden_sign_right": [
 859                "next_to_secret_garden_sign_left",
 860            ],
 861            "item_secret_garden_sign_left": [
 862                "next_to_secret_garden_sign_right",
 863            ],
 864            "item_crop_field_sign_above": [
 865                "next_to_crop_field_sign_down",
 866            ],
 867            "item_start_line": [
 868                "at_the_start_line",
 869            ],
 870            "item_next_to_shipping_box": [
 871                "next_to_shipping_box_up",
 872            ],
 873            "item_shipping_box_field": [
 874                "drop_eggplant_into_shipping_box",
 875            ],
 876            "item_distance_markers": [
 877                "crossed_500m_line",
 878                "crossed_1000m_line",
 879            ],
 880            "item_eggplant_field": [
 881                "next_to_center_eggplant_up_1",
 882                "next_to_center_eggplant_up_2",
 883                "center_eggplant_harvested_1",
 884                "center_eggplant_harvested_2",
 885            ],
 886            "item_carrot_field": [
 887                "next_to_center_carrot_up_1",
 888                "next_to_center_carrot_up_2",
 889                "center_carrot_harvested_1",
 890                "center_carrot_harvested_2",
 891            ],
 892            "item_cabbage_field": [
 893                "at_cabbage_center_1",
 894                "at_cabbage_center_2",
 895                "cabbage_field_watered_1",
 896                "cabbage_field_watered_2",
 897            ],
 898            "item_potato_field": [
 899                "next_to_center_potato_up_1",
 900                "next_to_center_potato_up_2",
 901                "center_potato_watered_1",
 902                "center_potato_watered_2",
 903            ],
 904            "item_asparagus_field": [
 905                "next_to_center_asparagus_right_1",
 906                "next_to_center_asparagus_right_2",
 907                "center_asparagus_watered_1",
 908                "center_asparagus_watered_2",
 909            ],
 910            "item_corn_field": [
 911                "at_corn_center_1",
 912                "at_corn_center_2",
 913                "corn_field_watered_1",
 914                "corn_field_watered_2",
 915            ],
 916            "item_center_corn_above": [
 917                "next_to_center_corn_down_1",
 918                "next_to_center_corn_down_2",
 919                "center_corn_cut_1",
 920                "center_corn_cut_2",
 921            ],
 922            "restaurant_location": [
 923                "outside_restaurant_up",
 924                "outside_restaurant_left",
 925                "outside_restaurant_right",
 926            ],
 927            "hospital_location": [
 928                "outside_hospital_up",
 929                "outside_hospital_left",
 930                "outside_hospital_right",
 931            ],
 932            "tool_shop_location": [
 933                "outside_tool_shop_up",
 934                "outside_tool_shop_left",
 935                "outside_tool_shop_right",
 936            ],
 937            "carpenter_location": [
 938                "outside_carpenter_up",
 939                "outside_carpenter_left",
 940                "outside_carpenter_right",
 941            ],
 942            "animal_shop_location": [
 943                "outside_animal_shop_up",
 944                "outside_animal_shop_left",
 945                "outside_animal_shop_right",
 946            ],
 947            "library_location": [
 948                "outside_library_up",
 949                "outside_library_left",
 950                "outside_library_right",
 951            ],
 952            "screen_top_half": [
 953                "in_hospital",
 954                "in_tool_shop",
 955                "in_carpenter",
 956                "in_animal_shop",
 957                "in_library",
 958                "in_flower_shop",
 959                "in_restaurant",
 960                "shop_for_construction_estimates",
 961            ],
 962            "screen_bottom_half": [
 963                "bought_potato_seeds",
 964                "bought_asparagus_seeds",
 965                "select_potato_seeds",
 966                "select_potato_seeds_portion",
 967                "select_asparagus_seeds",
 968                "select_asparagus_seeds_portion",
 969                "bought_lunch_set",
 970                "select_lunch_set",
 971                "option_to_buy_lunch_set",
 972                "bought_beverage_set",
 973                "select_beverage_set",
 974                "option_to_buy_beverage_set",
 975                "bought_todays_special",
 976                "select_todays_special",
 977                "option_to_buy_todays_special",
 978                "bought_chicken",
 979                "sold_cow",
 980                "sold_chicken",
 981                "hothouse_estimate",
 982                "bridge_estimate",
 983                "bought_milker",
 984            ],
 985            "outside_barns":[
 986                "outside_cow_barn_left",
 987                "outside_cow_barn_right",
 988                "outside_cow_barn_up",
 989                "outside_chicken_coop_left",
 990                "outside_chicken_coop_right",
 991                "outside_chicken_coop_up",
 992            ],
 993            "top_left_label": [
 994                "ready_to_pick_sickle",
 995                "ready_to_pick_hammer",
 996                "ready_to_pick_fishing_rod",
 997                "ready_to_pick_net",
 998                "ready_to_pick_rosemary_seeds",
 999            ],
1000            "equipment_region_1": [
1001                "sprinkler_selected_1",
1002                "sickle_equipped_1",
1003            ],
1004            "equipment_region_2": [
1005                "ax_selected_2",
1006                "net_equipped",
1007                "rosemary_seeds_equipped",
1008            ],
1009            "equipment_region_3": [
1010                "hoe_selected_3",
1011                "net_equipped_3",
1012            ],
1013            "equipment_region_4":[
1014                "empty_hands_selected",
1015                "sickle_equipped",
1016                "hammer_equipped",
1017                "fishing_rod_equipped",
1018            ],
1019            "item_leftmost_weed_right": [
1020                "next_to_leftmost_weed_left",
1021                "leftmost_weed_removed_left",
1022            ],
1023            "item_leftmost_weed_above": [
1024                "next_to_leftmost_weed_down",
1025                "leftmost_weed_removed_down",
1026            ],
1027            "item_berry_left": [
1028                "next_to_berry_right",
1029                "berry_picked_right",
1030            ],
1031            "item_berry_above": [
1032                "next_to_berry_down_1",
1033                "next_to_berry_down_2",
1034                "berry_picked_above_1",
1035                "berry_picked_above_2",
1036            ],
1037            "item_chicken_stall_block1": [
1038                "filled_chicken_stall_block1",
1039            ],
1040            "item_next_to_chicken_stall_block1": [
1041                "next_to_chicken_stall_block1",
1042            ],
1043            "item_chicken_silo_left1": [
1044                "next_to_chicken_silo_right1",
1045                "got_fodder_from_chicken_silo_right1",
1046            ],
1047            "item_chicken_silo_left2": [
1048                "next_to_chicken_silo_right2",
1049                "got_fodder_from_chicken_silo_right2",
1050            ],
1051            "item_chicken_silo_below": [
1052                "next_to_chicken_silo_up",
1053                "got_fodder_from_chicken_silo_up",
1054            ],
1055            "item_next_to_hatching_box": [
1056                "next_to_hatching_box",
1057            ],
1058            "item_hatching_box": [
1059                "dropped_egg_into_hatching_box",
1060            ],
1061            "npc_blue_hair_girl_left": [
1062                "next_to_blue_hair_girl_right",
1063            ],
1064            "npc_blue_hair_girl_below": [
1065                "next_to_blue_hair_girl_up",
1066            ],
1067            "npc_blue_hair_girl_right": [
1068                "next_to_blue_hair_girl_left",
1069            ],
1070            "npc_purple_hair_girl_left": [
1071                "next_to_purple_hair_girl_right",
1072            ],
1073            "npc_purple_hair_girl_below": [
1074                "next_to_purple_hair_girl_up",
1075            ],
1076            "npc_blonde_girl_right": [
1077                "next_to_blonde_girl_left",
1078            ],
1079            "npc_blonde_girl_above": [
1080                "next_to_blonde_girl_down",
1081            ],
1082        }
1083        super().__init__(
1084            pyboy,
1085            variant="harvest_moon_2",
1086            parameters=parameters,
1087            override_regions=override_regions,
1088            override_multi_target_regions=override_multi_target_regions,
1089            override_multi_targets=override_multi_targets,
1090        )
1091
1092    def dialogue_box_open(self, current_screen: np.ndarray) -> bool:
1093        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
1094        return self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
1095            self.DIALOGUE_TYPES, captured
1096        )
1097        
1098    def dialogue_box_empty(self, current_screen: np.ndarray) -> bool:
1099        box = self.capture_named_region(
1100            current_frame=current_screen, name="dialogue_box_bottom"
1101        )
1102        perc_lt_255 = np.mean(box < 255)
1103        if perc_lt_255 < 0.082:  # Empirical threshold
1104            return True
1105        return False
1106
1107    def is_in_menu(self, current_screen: np.ndarray) -> bool:
1108        return self.named_region_matches_target(current_screen, "menu_top_right")
1109
1110    def is_in_storage_list(self, current_screen: np.ndarray) -> bool:
1111        return self.named_region_matches_target(current_screen, "storage_list_top_right")
1112
1113    def is_in_dialogue(self, current_screen: np.ndarray) -> bool:
1114        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
1115        return self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
1116            self.DIALOGUE_TYPES, captured
1117        )
1118
1119    def get_agent_state(self, current_screen: np.ndarray) -> AgentState:
1120        if self.is_in_menu(current_screen):
1121            return AgentState.IN_MENU
1122        if self.is_in_storage_list(current_screen):
1123            return AgentState.IN_STORAGE_LIST
1124        if self.is_in_dialogue(current_screen):
1125            return AgentState.IN_DIALOGUE
1126        return AgentState.FREE_ROAM
1127
1128
1129class HarvestMoon3Parser(BaseHarvestMoonStateParser):
1130    DIALOGUE_TYPES = [
1131        "normal_dialogue",
1132        "mainland_dialogue",
1133    ]
1134
1135    def __init__(self, pyboy, parameters):
1136        override_regions = [
1137            ("menu_top_right", 153, 0, 6, 6),
1138        ]
1139        override_multi_target_regions = [
1140            ("dialogue_bottom_right", 153, 135, 10, 10),
1141            ("screen_bottom", 0, 95, 160, 40),
1142            ("dialogue_box_bottom", 0, 98, 160, 45),
1143            ("item_secret_garden_sign_above", 60, 55, 20, 40),
1144            ("item_secret_garden_sign_right", 50, 55, 35, 25),
1145            ("item_turnip_seeds_above", 30, 55, 17, 41),
1146            ("item_turnip_seeds_below", 30, 40, 17, 39),
1147            ("item_potato_seeds_above", 63, 55, 17, 41),
1148            ("item_potato_seeds_below", 63, 40, 17, 39),
1149            ("screen_top_half", 0, 0, 160, 65),
1150            ("screen_bottom_half", 0, 75, 160, 65),
1151            ("item_storage_sign_below", 70, 40, 20, 40),
1152            ("item_storage_sign_left", 70, 55, 35, 25),
1153            ("item_storage_sign_right", 55, 55, 30, 25),
1154            ("item_morning_market_sign_left", 128, 55, 31, 27),
1155            ("npc_kirk_above", 65, 55, 25, 40),
1156            ("npc_kirk_mainland_right", 55, 45, 30, 25),
1157            ("npc_kirk_mainland_below", 70, 40, 15, 40),
1158            ("npc_joe_left", 125, 55, 34, 25),
1159            ("npc_lukia_right", 38, 55, 34, 25),
1160            ("dialogue_box_upper_border", 0, 96, 160, 8),
1161            ("npc_lucus_above", 70, 55, 19, 40),
1162            ("npc_lucus_left", 70, 55, 34, 25),
1163            ("npc_lucus_right", 55, 55, 34, 25),
1164            ("npc_lyla_right", 54, 55, 34, 25),
1165            ("item_meal_set_empty_1", 80, 40, 30, 15),
1166            ("item_meal_set_empty_2", 80, 80, 30, 15),
1167            ("item_coffee_above", 72, 55, 15, 39),
1168            ("item_coffee_below", 72, 40, 13, 30),
1169            ("entrance", 40, 65, 80, 80),
1170            ("top_entrance", 45, 0, 70, 40),
1171            ("outside_chicken_coop", 45, 40, 45, 35),
1172            ("outside_hot_spring", 45, 40, 45, 35),
1173            ("item_tea_above", 70, 55, 17, 41),
1174            ("item_tea_below", 70, 40, 17, 39),
1175            ("item_asparagus_seeds_above", 72, 55, 17, 41),
1176            ("item_asparagus_seeds_below", 72, 40, 17, 39),
1177            ("item_right_cow_stall_block", 115, 25, 45, 25),
1178            ("item_right_cow_stall_block_below", 115, 25, 45, 50),
1179            ("item_right_cow_stall_block_left", 95, 35, 55, 35),
1180            ("item_cow_stall_block_2", 112, 35, 38, 35),
1181            ("item_ferry_sign_above", 70, 60, 16, 45),
1182            ("item_ferry_sign_left", 70, 60, 30, 28),
1183            ("item_fireplace_below", 105, 40, 15, 40),
1184            ("item_rock_left", 95, 55, 30, 25),
1185            ("item_target_potato_below", 56, 32, 48, 47),
1186            ("item_center_spotato_above", 56, 60, 47, 50),
1187            ("item_center_watermelon_above", 30, 25, 49, 54),
1188            ("npc_kate_left", 50, 58, 28, 19),
1189            ("npc_kate_right", 63, 55, 33, 23),
1190            ("npc_kate_below", 63, 39, 16, 40),
1191            ("item_weed_left", 70, 0, 50, 45),
1192            ("item_cherry_left", 95, 50, 30, 38),
1193            ("item_fodder_set_below", 113, 40, 14, 40),
1194            ("item_horse_medicine_below", 97, 40, 14, 40),
1195            ("item_chicken_silo_left1", 96, 50, 30, 30),
1196            ("item_chicken_silo_left2", 96, 65, 30, 30),
1197            ("item_chicken_silo_above", 110, 50, 20, 40),
1198            ("item_topmost_chicken_stall_block", 115, 36, 35, 29),
1199            ("item_next_to_topmost_chicken_stall_block", 97, 36, 53, 29),
1200            ("item_fodder_set", 97, 40, 30, 5),
1201            ("item_horse_medicine", 97, 40, 30, 5),
1202            ("item_next_to_hatching_box", 7, 62, 36, 38),
1203            ("item_hatching_box", 7, 62, 23, 38),
1204            ("item_stairs", 40, 0, 95, 80),
1205            ("item_flower_vase_empty_1", 0, 80, 50, 15),
1206            ("item_flower_vase_empty_2", 0, 40, 50, 5),
1207            ("item_flower_vase_above", 32, 56, 16, 40),
1208            ("item_flower_vase_below", 32, 40, 16, 40),
1209            ("item_horse_saddle_empty_1", 78, 80, 80, 15),
1210            ("item_horse_saddle_empty_2", 78, 40, 80, 15),
1211            ("item_horse_saddle_above", 72, 55, 24, 41),
1212            ("item_horse_saddle_below", 78, 40, 17, 39),
1213            ("item_center_eggplant_above", 52, 15, 51, 64),
1214            ("item_center_eggplant_left", 70, 32, 48, 48),
1215            ("menu_box", 106, 0, 53, 122),
1216            ("player_top_left", 0, 0, 35, 40),
1217            ("item_berry_above", 0, 50, 35, 45),
1218            ("sell_animal_section_1", 62, 80, 83, 16),
1219            ("sell_animal_section_2", 62, 40, 83, 16),
1220            ("item_sell_chicken_below", 80, 40, 15, 40),
1221            ("item_sell_chicken_above", 78, 56, 17, 39),
1222            ("item_center_turnip_below", 56, 32, 48, 47),
1223            ("item_bookshelf_below", 125, 32, 25, 48),
1224        ]
1225        override_multi_targets = {
1226            "dialogue_bottom_right": [
1227                "normal_dialogue",
1228                "mainland_dialogue",
1229            ],
1230            "dialogue_box_bottom": [
1231                "reading_secret_garden_sign",
1232                "reading_storage_sign",
1233                "reading_morning_market_sign",
1234                "reading_ferry_sign",
1235                "found_secret_savings",
1236                "select_tea",
1237                "select_asparagus_seeds",
1238                "select_coffee",
1239                "select_turnip_seeds",
1240                "select_turnip_seeds_portion",
1241                "select_potato_seeds",
1242                "select_potato_seeds_portion",
1243                "bought_turnip_seeds",
1244                "bought_potato_seeds",
1245                "select_meal_set",
1246                "speaking_to_kate",
1247                "farm_label",
1248                "village_label",
1249                "grassland_label",
1250                "forest_label",
1251                "cliff_label",
1252                "mountain_label",
1253                "shopping_mall_label",
1254                "farmers_union_label",
1255                "aquarium_label",
1256                "theatre_label",
1257                "selected_fodder_set",
1258                "selected_horse_medicine",
1259                "bought_from_farmers_union",
1260                "bought_from_flower_shop",
1261                "animal_sold",
1262                "finish_animal_ch2",
1263            ],
1264            "item_rock_left": [
1265                "next_to_rock_right",
1266                "rock_cleared",
1267            ],
1268            "item_target_potato_below": [
1269                "next_to_target_potato_up",
1270                "target_potato_harvested",
1271            ],
1272            "item_center_spotato_above": [
1273                "next_to_spotato_down",
1274                "center_spotato_watered",
1275            ],
1276            "item_center_watermelon_above": [
1277                "next_to_center_watermelon_down",
1278                "center_watermelon_watered",
1279            ],
1280            "npc_kate_left": [
1281                "next_to_kate_right",
1282            ],
1283            "npc_kate_right": [
1284                "next_to_kate_left",
1285            ],
1286            "npc_kate_below": [
1287                "next_to_kate_up",
1288            ],
1289            "item_weed_left": [
1290                "next_to_weed_right",
1291                "weed_removed",
1292            ],
1293            "item_cherry_left": [
1294                "next_to_cherry_right",
1295                "cherry_picked",
1296            ],
1297            "item_chicken_silo_left1": [
1298                "next_to_chicken_silo_right1",
1299                "got_fodder_from_chicken_silo_right1",
1300            ],
1301            "item_chicken_silo_left2": [
1302                "next_to_chicken_silo_right2",
1303                "got_fodder_from_chicken_silo_right2",
1304            ],
1305            "item_chicken_silo_above": [
1306                "next_to_chicken_silo_down",
1307                "got_fodder_from_chicken_silo_down",
1308            ],
1309            "item_topmost_chicken_stall_block": [
1310                "filled_topmost_chicken_stall_block",
1311            ],
1312            "item_next_to_topmost_chicken_stall_block": [
1313                "next_to_topmost_chicken_stall_block",
1314            ],
1315            "item_next_to_hatching_box": [
1316                "next_to_hatching_box",
1317            ],
1318            "item_hatching_box": [
1319                "dropped_egg_into_hatching_box",
1320            ],
1321            "item_stairs": [
1322                "next_to_stairs_1",
1323                "next_to_stairs_2",
1324                "next_to_stairs_3",
1325            ],
1326            "item_fodder_set_below": [
1327                "next_to_fodder_set_up",
1328            ],
1329            "item_horse_medicine_below": [
1330                "next_to_horse_medicine_up",
1331            ],
1332            "item_fodder_set": [
1333                "picked_fodder_set",
1334            ],
1335            "item_horse_medicine": [
1336                "picked_horse_medicine",
1337            ],
1338            "item_storage_sign_below": [
1339                "next_to_storage_sign_up",
1340            ],
1341            "item_storage_sign_left": [
1342                "next_to_storage_sign_right",
1343            ],
1344            "item_storage_sign_right": [
1345                "next_to_storage_sign_left",
1346            ],
1347            "item_morning_market_sign_left": [
1348                "next_to_morning_market_sign_right",
1349            ],
1350            "npc_kirk_above": [
1351                "next_to_kirk_down",
1352            ],
1353            "npc_kirk_mainland_right": [
1354                "next_to_kirk_mainland_left",
1355            ],
1356            "npc_kirk_mainland_below": [
1357                "next_to_kirk_mainland_up",
1358            ],
1359            "npc_joe_left": [
1360                "next_to_joe_right",
1361            ],
1362            "dialogue_box_upper_border": [
1363                "speaking_to_kirk_village",
1364                "speaking_to_joe",
1365                "speaking_to_lukia",
1366                "speaking_to_lucus",
1367                "speaking_to_lyla",
1368            ],
1369            "item_secret_garden_sign_above": [
1370                "next_to_secret_garden_sign_down",
1371            ],
1372            "item_secret_garden_sign_right": [
1373                "next_to_secret_garden_sign_left",
1374            ],
1375            "item_turnip_seeds_above": [
1376                "next_to_turnip_seeds_down",
1377            ],
1378            "item_turnip_seeds_below": [
1379                "next_to_turnip_seeds_up",
1380            ],
1381            "item_potato_seeds_above": [
1382                "next_to_potato_seeds_down",
1383            ],
1384            "item_potato_seeds_below": [
1385                "next_to_potato_seeds_up",
1386            ],
1387            "npc_lukia_right": [
1388                "next_to_lukia_left",
1389            ],
1390            "npc_lucus_above": [
1391                "next_to_lucus_down",
1392            ],
1393            "npc_lucus_left": [
1394                "next_to_lucus_right",
1395            ],
1396            "npc_lucus_right": [
1397                "next_to_lucus_left",
1398            ],
1399            "npc_lyla_right": [
1400                "next_to_lyla_left",
1401            ],
1402            "outside_chicken_coop": [
1403                "outside_chicken_coop_left",
1404                "outside_chicken_coop_right",
1405                "outside_chicken_coop_up",
1406            ],
1407            "item_flower_vase_empty_1": [
1408                "bought_flower_vase_1",
1409            ],
1410            "item_flower_vase_empty_2": [
1411                "bought_flower_vase_2",
1412            ],
1413            "item_flower_vase_above": [
1414                "next_to_vase_down",
1415            ],
1416            "item_flower_vase_below": [
1417                "next_to_vase_up",
1418            ],
1419            "item_center_eggplant_above": [
1420                "next_to_eggplant_down",
1421                "center_eggplant_harvested_down",
1422            ],
1423            "item_center_eggplant_left": [
1424                "next_to_eggplant_right",
1425                "center_eggplant_harvested_right",
1426            ],
1427            "menu_box": [
1428                "choose_may",
1429            ],
1430            "player_top_left": [
1431                "display_player_status",
1432            ],
1433            "item_berry_above": [
1434                "next_to_berry_down",
1435                "berry_picked_above",
1436            ],
1437            "sell_animal_section_1": [
1438                "selling_animal_1",
1439            ],
1440            "sell_animal_section_2": [
1441                "selling_animal_2",
1442            ],
1443            "item_sell_chicken_below": [
1444                "next_to_sell_chicken_up",
1445            ],
1446            "item_sell_chicken_above": [
1447                "next_to_sell_chicken_down",
1448            ],
1449            "item_center_turnip_below": [
1450                "next_to_center_turnip_up",
1451                "center_turnip_harvested",
1452            ],
1453            "item_bookshelf_below": [
1454                "next_to_bookshelf_up",
1455            ],
1456            "item_horse_saddle_empty_1": [
1457                "bought_horse_saddle_1",
1458            ],
1459            "item_horse_saddle_empty_2": [
1460                "bought_horse_saddle_2",
1461            ],
1462            "item_horse_saddle_above": [
1463                "next_to_horse_saddle_down",
1464            ],
1465            "item_horse_saddle_below": [
1466                "next_to_horse_saddle_up",
1467            ],
1468            "item_meal_set_empty_1": [
1469                "bought_meal_set_1",
1470            ],
1471            "item_meal_set_empty_2": [
1472                "bought_meal_set_2",
1473            ],
1474            "item_coffee_above": [
1475                "next_to_coffee_down",
1476            ],
1477            "item_coffee_below": [
1478                "next_to_coffee_up",
1479            ],
1480            "top_entrance": [
1481                "village_entrance",
1482            ],
1483            "entrance": [
1484                "village_ferry_entrance",
1485                "farm_entrance",
1486                "grassland_entrance",
1487                "forest_entrance",
1488                "cliff_entrance",
1489                "mountain_entrance",
1490                "shopping_mall_entrance",
1491                "farmers_union_entrance",
1492                "aquarium_entrance",
1493                "theatre_entrance",
1494                "hot_spring_entrance",
1495                "shopping_mall_second_floor",
1496            ],
1497            "item_tea_above": [
1498                "next_to_tea_down",
1499            ],
1500            "item_tea_below": [
1501                "next_to_tea_up",
1502            ],
1503            "item_asparagus_seeds_above": [
1504                "next_to_asparagus_seeds_down",
1505            ],
1506            "item_asparagus_seeds_below": [
1507                "next_to_asparagus_seeds_up",
1508            ],
1509            "item_right_cow_stall_block": [
1510                "filled_right_cow_stall_block",
1511            ],
1512            "item_right_cow_stall_block_below": [
1513                "next_to_right_cow_stall_block_up",
1514            ],
1515            "item_right_cow_stall_block_left": [
1516                "next_to_right_cow_stall_block_right",
1517            ],
1518            "item_cow_stall_block_2": [
1519                "filled_cow_stall_block_right",
1520            ],
1521            "item_ferry_sign_above": [
1522                "next_to_ferry_sign_down",
1523            ],
1524            "item_ferry_sign_left": [
1525                "next_to_ferry_sign_right",
1526            ],
1527            "item_fireplace_below": [
1528                "next_to_fireplace_up",
1529            ],
1530            "outside_hot_spring": [
1531                "outside_hot_spring_left",
1532                "outside_hot_spring_right",
1533                "outside_hot_spring_up",
1534            ],
1535        }
1536        super().__init__(
1537            pyboy,
1538            variant="harvest_moon_3",
1539            parameters=parameters,
1540            override_regions=override_regions,
1541            override_multi_target_regions=override_multi_target_regions,
1542            override_multi_targets=override_multi_targets,
1543        )
1544
1545    def dialogue_box_open(self, current_screen: np.ndarray) -> bool:
1546        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
1547        if self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
1548            self.DIALOGUE_TYPES, captured
1549        ):
1550            return True
1551        return False
1552    
1553    def dialogue_box_empty(self, current_screen: np.ndarray) -> bool:
1554        box = self.capture_named_region(
1555            current_frame=current_screen, name="dialogue_box_bottom"
1556        )
1557        perc_lt_255 = np.mean(box < 255)
1558        if perc_lt_255 < 0.082:  # Empirical threshold
1559            return True
1560        return False
1561
1562    def is_in_menu(self, current_screen: np.ndarray) -> bool:
1563        return self.named_region_matches_target(current_screen, "menu_top_right")
1564    
1565    def is_in_dialogue(self, current_screen: np.ndarray) -> bool:
1566        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
1567        if self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
1568            self.DIALOGUE_TYPES, captured
1569        ):
1570            return True
1571        return False
1572
1573    def get_agent_state(self, current_screen: np.ndarray) -> AgentState:
1574        if self.is_in_menu(current_screen):
1575            return AgentState.IN_MENU
1576        if self.is_in_dialogue(current_screen):
1577            return AgentState.IN_DIALOGUE
1578        return AgentState.FREE_ROAM
class AgentState(enum.Enum):
33class AgentState(Enum):
34    """
35    0. FREE_ROAM: The agent is freely roaming the game world.
36    1. IN_DIALOGUE: The agent is currently in a dialogue state.
37    2. IN_MENU: The agent has a menu open.
38    """
39
40    FREE_ROAM = 0
41    IN_DIALOGUE = 1
42    IN_MENU = 2
43    IN_STORAGE_LIST = 3
  1. FREE_ROAM: The agent is freely roaming the game world.
  2. IN_DIALOGUE: The agent is currently in a dialogue state.
  3. IN_MENU: The agent has a menu open.
FREE_ROAM = <AgentState.FREE_ROAM: 0>
IN_DIALOGUE = <AgentState.IN_DIALOGUE: 1>
IN_MENU = <AgentState.IN_MENU: 2>
IN_STORAGE_LIST = <AgentState.IN_STORAGE_LIST: 3>
class HarvestMoonStateParser(gameboy_worlds.emulation.parser.StateParser, abc.ABC):
 46class HarvestMoonStateParser(StateParser, ABC):
 47    """
 48    Base class for Harvest Moon GBC game state parsers. Uses visual screen regions to parse game state.
 49    Defines common named screen regions and methods for determining game states such as being in dialogue.
 50
 51    Can be used to determine the exact AgentState.
 52    """
 53
 54    COMMON_REGIONS = []
 55    """ List of common single-target named screen regions for Harvest Moon games. """
 56
 57    COMMON_MULTI_TARGET_REGIONS = [
 58        ("screen", 0, 0, 150, 140),
 59        ("screen_middle", 65, 55, 20, 20),
 60        ("dialogue_box_top", 58, 10, 40, 10),
 61    ]
 62    """ List of common multi-target named screen regions for Harvest Moon games.
 63
 64    - dialogue_bottom_right: Bottom-right corner of the dialogue box (x=153, y=135, 10x10px).
 65      Capture while dialogue is visible in dev_play: `c dialogue_bottom_right,<type_name>`
 66    - screen_bottom: Bottom strip of the screen (x=0, y=100, 160x40px).
 67      Useful for detecting locations and events. Capture in dev_play: `c screen_bottom,<target_name>`
 68    """
 69
 70    COMMON_MULTI_TARGETS = {
 71        "screen_bottom": [
 72            "cow_barn_entrance",
 73            "chicken_coop_entrance",
 74        ],
 75    }
 76    """ Common multi-targets for the common multi-target named screen regions.
 77    - screen_bottom: Location/event captures for the bottom strip of the screen.
 78    """
 79
 80    def __init__(
 81        self,
 82        variant: str,
 83        pyboy: PyBoy,
 84        parameters: dict,
 85        additional_named_screen_region_details: List[
 86            Tuple[str, int, int, int, int]
 87        ] = [],
 88        additional_multi_target_named_screen_region_details: List[
 89            Tuple[str, int, int, int, int]
 90        ] = [],
 91        override_multi_targets: Dict[str, List[str]] = {},
 92    ):
 93        """
 94        Initializes the HarvestMoonStateParser.
 95        Args:
 96            pyboy (PyBoy): The PyBoy emulator instance.
 97            parameters (dict): Configuration parameters for the emulator.
 98            additional_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional named screen regions to include.
 99            additional_multi_target_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional multi-target named screen regions to include.
100            override_multi_targets (Dict[str, List[str]]): Dictionary mapping region names to lists of additional target names for multi-target regions.
101        """
102        verify_parameters(parameters)
103        regions = _get_proper_regions(
104            override_regions=additional_named_screen_region_details,
105            base_regions=self.COMMON_REGIONS,
106        )
107        self.variant = variant
108        if f"{variant}_rom_data_path" not in parameters:
109            log_error(
110                f"ROM data path not found for variant: {variant}. Add {variant}_rom_data_path to the config files. See configs/pokemon_red_vars.yaml for an example",
111                parameters,
112            )
113        self.rom_data_path = parameters[f"{variant}_rom_data_path"]
114        """ Path to the ROM data directory for the specific Harvest Moon variant."""
115        captures_dir = self.rom_data_path + "/captures/"
116        named_screen_regions = []
117        for region_name, x, y, w, h in regions:
118            region = NamedScreenRegion(
119                region_name,
120                x,
121                y,
122                w,
123                h,
124                parameters=parameters,
125                target_path=os.path.join(captures_dir, region_name),
126            )
127            named_screen_regions.append(region)
128        multi_target_regions = _get_proper_regions(
129            override_regions=additional_multi_target_named_screen_region_details,
130            base_regions=self.COMMON_MULTI_TARGET_REGIONS,
131        )
132        multi_target_region_names = [region[0] for region in multi_target_regions]
133        multi_targets = self.COMMON_MULTI_TARGETS.copy()
134        for key in override_multi_targets:
135            if key in multi_targets:
136                multi_targets[key].extend(override_multi_targets[key])
137            else:
138                multi_targets[key] = override_multi_targets[key]
139        multi_target_provided_region_names = list(multi_targets.keys())
140        if not set(multi_target_provided_region_names).issubset(
141            set(multi_target_region_names)
142        ):
143            log_error(
144                f"Multi-target regions provided in multi_targets do not match the defined multi-target regions. Provided: {multi_target_provided_region_names}, Defined: {multi_target_region_names}",
145                parameters,
146            )
147        for region_name, x, y, w, h in multi_target_regions:
148            region_target_paths = {}
149            subdir = captures_dir + f"/{region_name}/"
150            for target_name in multi_targets.get(region_name, []):
151                region_target_paths[target_name] = os.path.join(subdir, target_name)
152            region = NamedScreenRegion(
153                region_name,
154                x,
155                y,
156                w,
157                h,
158                parameters=parameters,
159                multi_target_paths=region_target_paths,
160            )
161            named_screen_regions.append(region)
162        super().__init__(pyboy, parameters, named_screen_regions)    
163
164    def get_agent_state(self, current_screen: np.ndarray) -> AgentState:
165        if self.is_in_dialogue(current_screen):
166            return AgentState.IN_DIALOGUE
167        return AgentState.FREE_ROAM

Base class for Harvest Moon GBC game state parsers. Uses visual screen regions to parse game state. Defines common named screen regions and methods for determining game states such as being in dialogue.

Can be used to determine the exact AgentState.

HarvestMoonStateParser( variant: str, pyboy: pyboy.pyboy.PyBoy, parameters: dict, additional_named_screen_region_details: List[Tuple[str, int, int, int, int]] = [], additional_multi_target_named_screen_region_details: List[Tuple[str, int, int, int, int]] = [], override_multi_targets: Dict[str, List[str]] = {})
 80    def __init__(
 81        self,
 82        variant: str,
 83        pyboy: PyBoy,
 84        parameters: dict,
 85        additional_named_screen_region_details: List[
 86            Tuple[str, int, int, int, int]
 87        ] = [],
 88        additional_multi_target_named_screen_region_details: List[
 89            Tuple[str, int, int, int, int]
 90        ] = [],
 91        override_multi_targets: Dict[str, List[str]] = {},
 92    ):
 93        """
 94        Initializes the HarvestMoonStateParser.
 95        Args:
 96            pyboy (PyBoy): The PyBoy emulator instance.
 97            parameters (dict): Configuration parameters for the emulator.
 98            additional_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional named screen regions to include.
 99            additional_multi_target_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional multi-target named screen regions to include.
100            override_multi_targets (Dict[str, List[str]]): Dictionary mapping region names to lists of additional target names for multi-target regions.
101        """
102        verify_parameters(parameters)
103        regions = _get_proper_regions(
104            override_regions=additional_named_screen_region_details,
105            base_regions=self.COMMON_REGIONS,
106        )
107        self.variant = variant
108        if f"{variant}_rom_data_path" not in parameters:
109            log_error(
110                f"ROM data path not found for variant: {variant}. Add {variant}_rom_data_path to the config files. See configs/pokemon_red_vars.yaml for an example",
111                parameters,
112            )
113        self.rom_data_path = parameters[f"{variant}_rom_data_path"]
114        """ Path to the ROM data directory for the specific Harvest Moon variant."""
115        captures_dir = self.rom_data_path + "/captures/"
116        named_screen_regions = []
117        for region_name, x, y, w, h in regions:
118            region = NamedScreenRegion(
119                region_name,
120                x,
121                y,
122                w,
123                h,
124                parameters=parameters,
125                target_path=os.path.join(captures_dir, region_name),
126            )
127            named_screen_regions.append(region)
128        multi_target_regions = _get_proper_regions(
129            override_regions=additional_multi_target_named_screen_region_details,
130            base_regions=self.COMMON_MULTI_TARGET_REGIONS,
131        )
132        multi_target_region_names = [region[0] for region in multi_target_regions]
133        multi_targets = self.COMMON_MULTI_TARGETS.copy()
134        for key in override_multi_targets:
135            if key in multi_targets:
136                multi_targets[key].extend(override_multi_targets[key])
137            else:
138                multi_targets[key] = override_multi_targets[key]
139        multi_target_provided_region_names = list(multi_targets.keys())
140        if not set(multi_target_provided_region_names).issubset(
141            set(multi_target_region_names)
142        ):
143            log_error(
144                f"Multi-target regions provided in multi_targets do not match the defined multi-target regions. Provided: {multi_target_provided_region_names}, Defined: {multi_target_region_names}",
145                parameters,
146            )
147        for region_name, x, y, w, h in multi_target_regions:
148            region_target_paths = {}
149            subdir = captures_dir + f"/{region_name}/"
150            for target_name in multi_targets.get(region_name, []):
151                region_target_paths[target_name] = os.path.join(subdir, target_name)
152            region = NamedScreenRegion(
153                region_name,
154                x,
155                y,
156                w,
157                h,
158                parameters=parameters,
159                multi_target_paths=region_target_paths,
160            )
161            named_screen_regions.append(region)
162        super().__init__(pyboy, parameters, named_screen_regions)    

Initializes the HarvestMoonStateParser.

Arguments:
  • pyboy (PyBoy): The PyBoy emulator instance.
  • parameters (dict): Configuration parameters for the emulator.
  • additional_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional named screen regions to include.
  • additional_multi_target_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional multi-target named screen regions to include.
  • override_multi_targets (Dict[str, List[str]]): Dictionary mapping region names to lists of additional target names for multi-target regions.
COMMON_REGIONS = []

List of common single-target named screen regions for Harvest Moon games.

COMMON_MULTI_TARGET_REGIONS = [('screen', 0, 0, 150, 140), ('screen_middle', 65, 55, 20, 20), ('dialogue_box_top', 58, 10, 40, 10)]

List of common multi-target named screen regions for Harvest Moon games.

  • dialogue_bottom_right: Bottom-right corner of the dialogue box (x=153, y=135, 10x10px). Capture while dialogue is visible in dev_play: c dialogue_bottom_right,<type_name>
  • screen_bottom: Bottom strip of the screen (x=0, y=100, 160x40px). Useful for detecting locations and events. Capture in dev_play: c screen_bottom,<target_name>
COMMON_MULTI_TARGETS = {'screen_bottom': ['cow_barn_entrance', 'chicken_coop_entrance']}

Common multi-targets for the common multi-target named screen regions.

  • screen_bottom: Location/event captures for the bottom strip of the screen.
variant
rom_data_path

Path to the ROM data directory for the specific Harvest Moon variant.

def get_agent_state( self, current_screen: numpy.ndarray) -> AgentState:
164    def get_agent_state(self, current_screen: np.ndarray) -> AgentState:
165        if self.is_in_dialogue(current_screen):
166            return AgentState.IN_DIALOGUE
167        return AgentState.FREE_ROAM
class BaseHarvestMoonStateParser(HarvestMoonStateParser, abc.ABC):
170class BaseHarvestMoonStateParser(HarvestMoonStateParser, ABC):
171    """
172    Game state parser for all Harvest Moon GBC-based games.
173    """
174
175    REGIONS = [
176    ]
177    """ Additional named screen regions specific to Harvest Moon GBC games.
178    """
179
180    MULTI_TARGET_REGIONS = [
181    ]
182    """ Additional multi-target named screen regions specific to Harvest Moon GBC games. 
183    """
184
185    def __init__(
186        self,
187        pyboy: PyBoy,
188        variant: str,
189        parameters: dict,
190        override_regions: List[Tuple[str, int, int, int, int]] = [],
191        override_multi_target_regions: List[Tuple[str, int, int, int, int]] = [],
192        override_multi_targets: Dict[str, List[str]] = {},
193    ):
194        self.REGIONS = _get_proper_regions(
195            override_regions=override_regions, base_regions=self.REGIONS
196        )
197        self.MULTI_TARGET_REGIONS = _get_proper_regions(
198            override_regions=override_multi_target_regions,
199            base_regions=self.MULTI_TARGET_REGIONS,
200        )
201        super().__init__(
202            variant=variant,
203            pyboy=pyboy,
204            parameters=parameters,
205            additional_named_screen_region_details=self.REGIONS,
206            additional_multi_target_named_screen_region_details=self.MULTI_TARGET_REGIONS,
207            override_multi_targets=override_multi_targets,
208        )
209    
210    def __repr__(self):
211        return f"<HarvestMoonParser(variant={self.variant})>"

Game state parser for all Harvest Moon GBC-based games.

BaseHarvestMoonStateParser( pyboy: pyboy.pyboy.PyBoy, variant: str, parameters: dict, override_regions: List[Tuple[str, int, int, int, int]] = [], override_multi_target_regions: List[Tuple[str, int, int, int, int]] = [], override_multi_targets: Dict[str, List[str]] = {})
185    def __init__(
186        self,
187        pyboy: PyBoy,
188        variant: str,
189        parameters: dict,
190        override_regions: List[Tuple[str, int, int, int, int]] = [],
191        override_multi_target_regions: List[Tuple[str, int, int, int, int]] = [],
192        override_multi_targets: Dict[str, List[str]] = {},
193    ):
194        self.REGIONS = _get_proper_regions(
195            override_regions=override_regions, base_regions=self.REGIONS
196        )
197        self.MULTI_TARGET_REGIONS = _get_proper_regions(
198            override_regions=override_multi_target_regions,
199            base_regions=self.MULTI_TARGET_REGIONS,
200        )
201        super().__init__(
202            variant=variant,
203            pyboy=pyboy,
204            parameters=parameters,
205            additional_named_screen_region_details=self.REGIONS,
206            additional_multi_target_named_screen_region_details=self.MULTI_TARGET_REGIONS,
207            override_multi_targets=override_multi_targets,
208        )

Initializes the HarvestMoonStateParser.

Arguments:
  • pyboy (PyBoy): The PyBoy emulator instance.
  • parameters (dict): Configuration parameters for the emulator.
  • additional_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional named screen regions to include.
  • additional_multi_target_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional multi-target named screen regions to include.
  • override_multi_targets (Dict[str, List[str]]): Dictionary mapping region names to lists of additional target names for multi-target regions.
REGIONS = []

Additional named screen regions specific to Harvest Moon GBC games.

MULTI_TARGET_REGIONS = []

Additional multi-target named screen regions specific to Harvest Moon GBC games.

class HarvestMoon1Parser(BaseHarvestMoonStateParser):
213class HarvestMoon1Parser(BaseHarvestMoonStateParser):
214
215    DIALOGUE_TYPES = [
216        "home_dialogue",
217        "shop_dialogue",
218        "church_dialogue",
219        "harvest_spirits_dialogue",
220        "read_signs_dialogue",
221        "evening_dialogue",
222        "barn_dialogue",
223        "winter_read_signs_dialogue",
224        "winter_evening_dialogue",
225    ]
226    def __init__(self, pyboy, parameters):
227        override_regions = [
228            ("menu_top_right", 153, 0, 5, 5),
229            ("storage_list_top_right", 153, 0, 6, 6),
230        ]
231        
232        override_multi_target_regions = [
233            ("dialogue_bottom_right", 153, 135, 10, 10),
234            ("screen", 0, 0, 160, 143),
235            ("screen_middle", 65, 63, 30, 30),
236            ("screen_bottom", 0, 100, 160, 40),
237            ("dialogue_box_top", 60, 11, 40, 8),
238            ("dialogue_box_top_mid", 68, 11, 22, 8),
239            ("dialogue_box_top_short", 71, 11, 15, 8),
240            ("dialogue_box_bottom", 0, 105, 160, 35),
241            ("item_bed", 0, 40, 40, 40),
242            ("item_watercan_above", 56, 85, 15, 35),
243            ("item_watercan_right", 55, 80, 30, 20),
244            ("item_watercan_below", 56, 70, 15, 30),
245            ("item_cowbell_above", 39, 49, 15, 35),
246            ("item_cowbell_below", 39, 70, 15, 30),
247            ("item_sickle_above", 88, 85, 15, 35),
248            ("item_sickle_left", 70, 80, 30, 20),
249            ("item_sickle_below", 88, 70, 15, 30),
250            ("item_hoe_above", 102, 85, 15, 35),
251            ("item_hoe_below", 102, 70, 15, 30),
252            ("item_hammer_above", 120, 85, 15, 35),
253            ("item_hammer_below", 120, 70, 15, 30),
254            ("item_grass_seed_above", 56, 55, 15, 35),
255            ("item_grass_seed_right", 55, 70, 30, 20),
256            ("item_grass_seed_below", 56, 70, 15, 30),
257            ("item_storage_list", 0, 40, 20, 30),
258            ("item_spirit_left", 70, 50, 30, 30),
259            ("item_spirit_below", 70, 50, 30, 30),
260            ("item_spirit_above", 70, 50, 15, 50),
261            ("item_safe_below", 40, 30, 15, 40),
262            ("item_lost_bird_left", 70, 65, 30, 25),
263            ("item_lost_bird_right", 60, 65, 30, 25),
264            ("item_lost_bird_below", 70, 50, 20, 35),
265            ("item_blue_hair_girl_left", 80, 20, 30, 30),
266            ("item_blue_hair_girl_right", 95, 20, 30, 30),
267            ("item_blue_hair_girl_below", 95, 20, 20, 40),
268            ("item_golden_hair_girl_above", 32, 40, 15, 40),
269            ("item_golden_hair_girl_right", 30, 55, 35, 25),
270            ("item_golden_hair_girl_below", 32, 55, 15, 35),
271            ("item_pink_hair_girl_left", 32, 68, 33, 22),
272            ("item_pink_hair_girl_right", 48, 68, 30, 22),
273            ("item_pink_hair_girl_above", 48, 68, 15, 38),
274            ("item_blue_hair_girl_wg_left", 80, 25, 30, 20),  
275            ("item_blue_hair_girl_wg_right", 97, 25, 30, 21),
276            ("item_blue_hair_girl_wg_below", 97, 25, 13, 35), 
277            ("item_pink_hair_girl_wg_left",  32, 68, 33, 22), 
278            ("item_pink_hair_girl_wg_right", 48, 68, 30, 22), 
279            ("item_pink_hair_girl_wg_above", 48, 68, 15, 38), 
280            ("item_red_hair_girl_wg_left", 80, 68, 30, 22),
281            ("item_red_hair_girl_wg_right", 97, 68, 30, 22),
282            ("item_red_hair_girl_wg_above", 97, 68, 13, 40),
283            ("item_chicken_stall_block1", 5, 40, 25, 20),
284            ("item_next_to_chicken_stall_block1", 5, 55, 25, 25),
285            ("item_chicken_silo_left", 100, 40, 30, 30),
286            ("item_chicken_silo_below1", 120, 50, 15, 35),
287            ("item_chicken_silo_below2", 135, 50, 15, 35),
288            ("item_cow_feeding_stall", 55, 25, 30, 45),
289            ("item_cow_feeding_stall_right", 55, 25, 45, 45),
290            ("item_egg_left", 89, 75, 31, 25),
291            ("item_egg_above", 105, 78, 15, 37),
292            ("item_egg_right", 110, 75, 22, 25),
293            ("item_hatching_box", 120, 70, 35, 30), 
294            ("turnip_center", 70, 90, 20, 20),
295            ("turnip_top", 70, 70, 20, 35),
296            ("item_turnip_field", 55, 65, 47, 54),
297            ("item_turnip_field_water", 40, 58, 47, 47),
298            ("item_potato_field", 55, 40, 47, 54),
299            ("item_rock_left", 0, 65, 45, 20),
300            ("item_rightmost_rock_above", 55, 60, 33, 40),
301            ("item_weed_above", 15, 65, 30, 50),
302            ("item_top_left_weed", 25, 60, 25, 25),
303            ("item_grassland_right", 50, 60, 35, 30),
304            ("item_center_grassline", 40, 70, 95, 20),
305            ("item_broken_fence_field", 63, 55, 30, 30),
306            ("item_fence_field", 0, 40, 30, 60),
307            ("center_sign", 55, 65, 50, 15),
308            ("screen_top_half", 0, 0, 160, 65),
309            ("screen_bottom_half", 0, 75, 160, 65),
310            ("left_border_frame", 0, 0, 5, 140),
311        ]
312        
313        override_multi_targets = {
314            "dialogue_bottom_right":[
315                "home_dialogue",
316                "shop_dialogue",
317                "church_dialogue",
318                "harvest_spirits_dialogue",
319                "read_signs_dialogue",
320                "evening_dialogue",
321                "barn_dialogue",
322                "winter_read_signs_dialogue",
323                "winter_evening_dialogue",
324            ],
325            "screen_middle":[
326                "outside_cow_barn_left",
327                "outside_cow_barn_right",
328                "outside_cow_barn_up",
329                "outside_chicken_coop_left",
330                "outside_chicken_coop_right",
331                "outside_chicken_coop_up",
332                "outside_storage_left",
333                "outside_storage_right",
334                "outside_storage_up",
335            ],
336            "screen_bottom": [
337                "cow_barn_entrance",
338                "chicken_coop_entrance",
339                "storage_shed_entrance",
340            ],
341            "dialogue_box_bottom":[
342                "found_rainy_money",
343                "select_material",
344                "select_home_expansion",
345                "select_chicken",
346                "select_selling_chicken",
347                "select_cow",
348                "bought_named_cow",
349                "select_cow_brush",
350                "select_saddlebag",
351                "select_milker",
352                "choose_yes_for_sleep",
353                "fed_spirit",
354                "helped_spirit_earthquake",
355                "select_rice_ball",
356                "select_croissant",
357                "select_cake",
358                "select_grape_juice",
359                "found_bird_for_friend",
360                "speaking_to_blue_hair_girl",
361                "speaking_to_golden_hair_girl",
362                "speaking_to_pink_hair_girl",
363                "speaking_to_blue_hair_girl_wg",
364                "speaking_to_pink_hair_girl_wg",
365                "speaking_to_red_hair_girl_wg",
366                "option_to_pray",
367                "praying",
368            ],
369            "item_bed":[
370                "sleep_in_bed",
371            ],
372            "item_storage_list":[
373                "next_to_storage_list",
374            ],
375            "item_watercan_above":[
376                "pickup_watercan_down",
377            ],
378            "item_watercan_right":[
379                "pickup_watercan_left",
380            ],
381            "item_cowbell_above":[
382                "next_to_cowbell_down",
383            ],
384            "item_cowbell_below":[
385                "next_to_cowbell_up",
386            ],
387            "item_watercan_below":[
388                "pickup_watercan_up",
389            ],
390            "item_sickle_above":[
391                "pickup_sickle_down",
392            ],
393            "item_sickle_left":[
394                "pickup_sickle_right",
395            ],
396            "item_sickle_below":[
397                "pickup_sickle_up",
398            ],
399            "item_hoe_above":[
400                "pickup_hoe_down",
401            ],
402            "item_hoe_below":[
403                "pickup_hoe_up",
404            ],
405            "item_hammer_above":[
406                "pickup_hammer_down",
407            ],
408            "item_hammer_below":[
409                "pickup_hammer_up",
410            ],
411            "item_grass_seed_above":[
412                "pickup_grass_seed_down",
413            ],
414            "item_grass_seed_right":[
415                "pickup_grass_seed_left",
416            ],
417            "item_grass_seed_below":[
418                "pickup_grass_seed_up",
419            ],
420            "item_spirit_left":[
421                "feed_spirit_right",
422                "help_spirit_earthquake_right",
423            ],
424            "item_spirit_above":[
425                "feed_spirit_down",
426                "help_spirit_earthquake_down",
427            ],
428            "item_spirit_below":[
429                "feed_spirit_up",
430                "help_spirit_earthquake_up",
431            ],
432            "item_safe_below":[
433                "next_to_safe_up",
434                "next_to_safe_left",
435            ],
436            "item_lost_bird_left":[
437                "find_lost_bird_right",
438            ],
439            "item_lost_bird_right":[
440                "find_lost_bird_left",
441            ], 
442            "item_lost_bird_below":[
443                "find_lost_bird_up",
444            ],
445            "item_blue_hair_girl_left":[
446                "next_to_blue_hair_girl_right",
447            ],
448            "item_blue_hair_girl_right":[
449                "next_to_blue_hair_girl_left",
450            ],
451            "item_blue_hair_girl_below":[
452                "next_to_blue_hair_girl_up",
453            ],
454            "item_golden_hair_girl_above":[
455                "next_to_golden_hair_girl_down",
456            ],
457            "item_golden_hair_girl_right":[
458                "next_to_golden_hair_girl_left",
459            ],
460            "item_golden_hair_girl_below":[
461                "next_to_golden_hair_girl_up",
462            ],
463            "item_pink_hair_girl_left":[
464                "next_to_pink_hair_girl_right",
465            ],
466            "item_pink_hair_girl_right":[
467                "next_to_pink_hair_girl_left",
468            ],
469            "item_pink_hair_girl_above":[
470                "next_to_pink_hair_girl_down",
471            ],
472            "item_blue_hair_girl_wg_left": [
473                "next_to_blue_hair_girl_wg_right",
474            ],
475            "item_blue_hair_girl_wg_right": [
476                "next_to_blue_hair_girl_wg_left",
477            ],
478            "item_blue_hair_girl_wg_below": [
479                "next_to_blue_hair_girl_wg_up",
480            ],
481            "item_pink_hair_girl_wg_left": [
482                "next_to_pink_hair_girl_wg_right",
483            ],
484            "item_pink_hair_girl_wg_right": [
485                "next_to_pink_hair_girl_wg_left",
486            ],
487            "item_pink_hair_girl_wg_above": [
488                "next_to_pink_hair_girl_wg_down",
489            ],
490            "item_red_hair_girl_wg_left": [
491                "next_to_red_hair_girl_wg_right",
492            ],
493            "item_red_hair_girl_wg_right": [
494                "next_to_red_hair_girl_wg_left",
495            ],
496            "item_red_hair_girl_wg_above": [
497                "next_to_red_hair_girl_wg_down",
498            ],
499            "item_chicken_stall_block1":[
500                "filled_chicken_stall_block1",
501            ],
502            "item_next_to_chicken_stall_block1":[
503                "next_to_chicken_stall_block1",
504            ],
505            "item_chicken_silo_left":[
506                "next_to_chicken_silo_right",
507                "got_fodder_from_chicken_silo_right",
508            ],
509            "item_chicken_silo_below1":[
510                "next_to_chicken_silo_up1",
511                "got_fodder_from_chicken_silo_up1",
512            ],
513            "item_chicken_silo_below2":[
514                "next_to_chicken_silo_up2",
515                "got_fodder_from_chicken_silo_up2",
516            ],
517            "item_cow_feeding_stall": [
518                "cow_feeding_stall_filled",
519            ],
520            "item_cow_feeding_stall_right": [
521                "next_to_cow_feeding_stall_left",
522            ],
523            "item_egg_left": [
524                "next_to_egg_right",
525            ],
526            "item_egg_above": [
527                "next_to_egg_down",
528            ],
529            "item_egg_right": [
530                "next_to_egg_left",
531            ],
532            "item_hatching_box": [
533                "dropped_egg_into_hatching_box",
534            ],
535            "dialogue_box_top":[
536                "pick_up_watercan",
537                "pick_up_grass_seed",
538            ],
539            "dialogue_box_top_mid":[
540                "pick_up_sickle",
541                "pick_up_hammer",
542                "pick_up_cowbell",
543            ],
544            "dialogue_box_top_short":[
545                "pick_up_hoe",
546            ],
547            "turnip_center":[
548                "finish_watering_1",
549                "finish_watering_2",
550            ],
551            "turnip_top":[
552                "ready_to_water_1",
553                "ready_to_water_2",
554            ],
555            "item_turnip_field": [
556                "next_to_center_turnip_down_1",
557                "next_to_center_turnip_down_2",
558                "center_turnip_harvested_1",
559                "center_turnip_harvested_2",
560            ],
561            "item_turnip_field_water":[
562                "next_to_center_turnip_left_1",
563                "next_to_center_turnip_left_2",
564                "center_turnip_watered_1",
565                "center_turnip_watered_2",
566            ],
567            "item_potato_field": [
568                "next_to_center_potato_up_1",
569                "next_to_center_potato_up_2",
570                "next_to_center_potato_below_up_1",
571                "next_to_center_potato_below_up_2",
572                "center_potato_watered_1",
573                "center_potato_watered_2",
574                "center_potato_harvested_1",
575                "center_potato_harvested_2",
576            ],
577            "item_rock_left": [
578                "next_to_rock_right",
579                "rock_cleared",
580            ],
581            "item_rightmost_rock_above": [
582                "next_to_rightmost_rock_down",
583                "rightmost_rock_cleared",
584            ],
585            "item_weed_above": [
586                "next_to_lowest_weed_down",
587                "lowest_weed_removed",
588                "lowest_weed_cut",
589            ],
590            "item_top_left_weed": [
591                "next_to_top_left_weed_up",
592                "top_left_weed_removed",
593                "top_left_weed_cut",
594            ],
595            "item_grassland_right": [
596                "next_to_grassland_left",
597            ],
598            "item_center_grassline": [
599                "center_grass_harvested_1",
600                "center_grass_harvested_2",
601            ],
602            "item_broken_fence_field": [
603                "picked_up_broken_fence_up",
604                "picked_up_broken_fence_down",
605                "picked_up_broken_fence_left",
606                "picked_up_broken_fence_right",
607            ],
608            "item_fence_field": [
609                "restored_fence",
610            ],
611            "center_sign":[
612                "outside_carpenter",
613                "outside_animal_shop",
614                "outside_tool_shop",
615                "outside_restaurant",
616                "outside_juice_bar",
617                "outside_church",
618            ],
619            "screen_bottom_half":[
620                "bought_material",
621                "home_expansion_estimate",
622                "bought_chicken",
623                "sold_chicken",
624                "bought_cow_brush",
625                "bought_saddlebag",
626                "bought_milker",
627                "option_to_buy_rice_ball",
628                "bought_rice_ball",
629                "option_to_buy_croissant",
630                "bought_croissant",
631                "option_to_buy_cake",
632                "bought_cake",
633                "option_to_buy_grape_juice",
634                "bought_grape_juice",
635            ],
636            "screen_top_half":[
637                "in_carpenter",
638                "in_animal_shop",
639                "in_tool_shop",
640                "in_restaurant",
641                "in_juice_bar",
642                "in_church",
643            ],
644            "left_border_frame":[
645                "open_storage_list",
646            ],
647        }
648
649        super().__init__(
650            pyboy,
651            variant="harvest_moon_1",
652            parameters=parameters,
653            override_regions=override_regions,
654            override_multi_target_regions=override_multi_target_regions,
655            override_multi_targets=override_multi_targets,
656        )
657
658    def dialogue_box_open(self, current_screen: np.ndarray) -> bool:
659        """
660        Determines if a dialogue box is currently open by checking the dialogue bottom right region.
661        Args:
662            current_screen (np.ndarray): The current screen frame from the emulator.
663        Returns:
664            bool: True if a dialogue box is open, False otherwise.
665        """
666        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
667        return self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
668            self.DIALOGUE_TYPES, captured
669        )
670
671    def dialogue_box_empty(self, current_screen: np.ndarray) -> bool:
672        box = self.capture_named_region(
673            current_frame=current_screen, name="dialogue_box_bottom"
674        )
675        perc_lt_255 = np.mean(box < 255)
676        if perc_lt_255 < 0.082:  # Empirical threshold
677            return True
678        return False
679    
680    def is_in_menu(self, current_screen: np.ndarray) -> bool:
681        return self.named_region_matches_target(current_screen, "menu_top_right")
682
683    def is_in_storage_list(self, current_screen: np.ndarray) -> bool:
684        return self.named_region_matches_target(current_screen, "storage_list_top_right")
685
686    def is_in_dialogue(self, current_screen: np.ndarray) -> bool:
687        """
688        Returns True if the dialogue_bottom_right region matches any of the saved dialogue type targets.
689        """
690        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
691        return self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
692            self.DIALOGUE_TYPES, captured
693        )
694
695    def get_agent_state(self, current_screen: np.ndarray) -> AgentState:
696        """
697        Determines the current agent state based on the screen.
698
699        Args:
700            current_screen (np.ndarray): The current screen frame from the emulator.
701
702        Returns:
703            AgentState: The current agent state.
704        """
705        if self.is_in_menu(current_screen):
706            return AgentState.IN_MENU
707        if self.is_in_storage_list(current_screen):
708            return AgentState.IN_STORAGE_LIST
709        if self.is_in_dialogue(current_screen):
710            return AgentState.IN_DIALOGUE
711        return AgentState.FREE_ROAM

Game state parser for all Harvest Moon GBC-based games.

HarvestMoon1Parser(pyboy, parameters)
226    def __init__(self, pyboy, parameters):
227        override_regions = [
228            ("menu_top_right", 153, 0, 5, 5),
229            ("storage_list_top_right", 153, 0, 6, 6),
230        ]
231        
232        override_multi_target_regions = [
233            ("dialogue_bottom_right", 153, 135, 10, 10),
234            ("screen", 0, 0, 160, 143),
235            ("screen_middle", 65, 63, 30, 30),
236            ("screen_bottom", 0, 100, 160, 40),
237            ("dialogue_box_top", 60, 11, 40, 8),
238            ("dialogue_box_top_mid", 68, 11, 22, 8),
239            ("dialogue_box_top_short", 71, 11, 15, 8),
240            ("dialogue_box_bottom", 0, 105, 160, 35),
241            ("item_bed", 0, 40, 40, 40),
242            ("item_watercan_above", 56, 85, 15, 35),
243            ("item_watercan_right", 55, 80, 30, 20),
244            ("item_watercan_below", 56, 70, 15, 30),
245            ("item_cowbell_above", 39, 49, 15, 35),
246            ("item_cowbell_below", 39, 70, 15, 30),
247            ("item_sickle_above", 88, 85, 15, 35),
248            ("item_sickle_left", 70, 80, 30, 20),
249            ("item_sickle_below", 88, 70, 15, 30),
250            ("item_hoe_above", 102, 85, 15, 35),
251            ("item_hoe_below", 102, 70, 15, 30),
252            ("item_hammer_above", 120, 85, 15, 35),
253            ("item_hammer_below", 120, 70, 15, 30),
254            ("item_grass_seed_above", 56, 55, 15, 35),
255            ("item_grass_seed_right", 55, 70, 30, 20),
256            ("item_grass_seed_below", 56, 70, 15, 30),
257            ("item_storage_list", 0, 40, 20, 30),
258            ("item_spirit_left", 70, 50, 30, 30),
259            ("item_spirit_below", 70, 50, 30, 30),
260            ("item_spirit_above", 70, 50, 15, 50),
261            ("item_safe_below", 40, 30, 15, 40),
262            ("item_lost_bird_left", 70, 65, 30, 25),
263            ("item_lost_bird_right", 60, 65, 30, 25),
264            ("item_lost_bird_below", 70, 50, 20, 35),
265            ("item_blue_hair_girl_left", 80, 20, 30, 30),
266            ("item_blue_hair_girl_right", 95, 20, 30, 30),
267            ("item_blue_hair_girl_below", 95, 20, 20, 40),
268            ("item_golden_hair_girl_above", 32, 40, 15, 40),
269            ("item_golden_hair_girl_right", 30, 55, 35, 25),
270            ("item_golden_hair_girl_below", 32, 55, 15, 35),
271            ("item_pink_hair_girl_left", 32, 68, 33, 22),
272            ("item_pink_hair_girl_right", 48, 68, 30, 22),
273            ("item_pink_hair_girl_above", 48, 68, 15, 38),
274            ("item_blue_hair_girl_wg_left", 80, 25, 30, 20),  
275            ("item_blue_hair_girl_wg_right", 97, 25, 30, 21),
276            ("item_blue_hair_girl_wg_below", 97, 25, 13, 35), 
277            ("item_pink_hair_girl_wg_left",  32, 68, 33, 22), 
278            ("item_pink_hair_girl_wg_right", 48, 68, 30, 22), 
279            ("item_pink_hair_girl_wg_above", 48, 68, 15, 38), 
280            ("item_red_hair_girl_wg_left", 80, 68, 30, 22),
281            ("item_red_hair_girl_wg_right", 97, 68, 30, 22),
282            ("item_red_hair_girl_wg_above", 97, 68, 13, 40),
283            ("item_chicken_stall_block1", 5, 40, 25, 20),
284            ("item_next_to_chicken_stall_block1", 5, 55, 25, 25),
285            ("item_chicken_silo_left", 100, 40, 30, 30),
286            ("item_chicken_silo_below1", 120, 50, 15, 35),
287            ("item_chicken_silo_below2", 135, 50, 15, 35),
288            ("item_cow_feeding_stall", 55, 25, 30, 45),
289            ("item_cow_feeding_stall_right", 55, 25, 45, 45),
290            ("item_egg_left", 89, 75, 31, 25),
291            ("item_egg_above", 105, 78, 15, 37),
292            ("item_egg_right", 110, 75, 22, 25),
293            ("item_hatching_box", 120, 70, 35, 30), 
294            ("turnip_center", 70, 90, 20, 20),
295            ("turnip_top", 70, 70, 20, 35),
296            ("item_turnip_field", 55, 65, 47, 54),
297            ("item_turnip_field_water", 40, 58, 47, 47),
298            ("item_potato_field", 55, 40, 47, 54),
299            ("item_rock_left", 0, 65, 45, 20),
300            ("item_rightmost_rock_above", 55, 60, 33, 40),
301            ("item_weed_above", 15, 65, 30, 50),
302            ("item_top_left_weed", 25, 60, 25, 25),
303            ("item_grassland_right", 50, 60, 35, 30),
304            ("item_center_grassline", 40, 70, 95, 20),
305            ("item_broken_fence_field", 63, 55, 30, 30),
306            ("item_fence_field", 0, 40, 30, 60),
307            ("center_sign", 55, 65, 50, 15),
308            ("screen_top_half", 0, 0, 160, 65),
309            ("screen_bottom_half", 0, 75, 160, 65),
310            ("left_border_frame", 0, 0, 5, 140),
311        ]
312        
313        override_multi_targets = {
314            "dialogue_bottom_right":[
315                "home_dialogue",
316                "shop_dialogue",
317                "church_dialogue",
318                "harvest_spirits_dialogue",
319                "read_signs_dialogue",
320                "evening_dialogue",
321                "barn_dialogue",
322                "winter_read_signs_dialogue",
323                "winter_evening_dialogue",
324            ],
325            "screen_middle":[
326                "outside_cow_barn_left",
327                "outside_cow_barn_right",
328                "outside_cow_barn_up",
329                "outside_chicken_coop_left",
330                "outside_chicken_coop_right",
331                "outside_chicken_coop_up",
332                "outside_storage_left",
333                "outside_storage_right",
334                "outside_storage_up",
335            ],
336            "screen_bottom": [
337                "cow_barn_entrance",
338                "chicken_coop_entrance",
339                "storage_shed_entrance",
340            ],
341            "dialogue_box_bottom":[
342                "found_rainy_money",
343                "select_material",
344                "select_home_expansion",
345                "select_chicken",
346                "select_selling_chicken",
347                "select_cow",
348                "bought_named_cow",
349                "select_cow_brush",
350                "select_saddlebag",
351                "select_milker",
352                "choose_yes_for_sleep",
353                "fed_spirit",
354                "helped_spirit_earthquake",
355                "select_rice_ball",
356                "select_croissant",
357                "select_cake",
358                "select_grape_juice",
359                "found_bird_for_friend",
360                "speaking_to_blue_hair_girl",
361                "speaking_to_golden_hair_girl",
362                "speaking_to_pink_hair_girl",
363                "speaking_to_blue_hair_girl_wg",
364                "speaking_to_pink_hair_girl_wg",
365                "speaking_to_red_hair_girl_wg",
366                "option_to_pray",
367                "praying",
368            ],
369            "item_bed":[
370                "sleep_in_bed",
371            ],
372            "item_storage_list":[
373                "next_to_storage_list",
374            ],
375            "item_watercan_above":[
376                "pickup_watercan_down",
377            ],
378            "item_watercan_right":[
379                "pickup_watercan_left",
380            ],
381            "item_cowbell_above":[
382                "next_to_cowbell_down",
383            ],
384            "item_cowbell_below":[
385                "next_to_cowbell_up",
386            ],
387            "item_watercan_below":[
388                "pickup_watercan_up",
389            ],
390            "item_sickle_above":[
391                "pickup_sickle_down",
392            ],
393            "item_sickle_left":[
394                "pickup_sickle_right",
395            ],
396            "item_sickle_below":[
397                "pickup_sickle_up",
398            ],
399            "item_hoe_above":[
400                "pickup_hoe_down",
401            ],
402            "item_hoe_below":[
403                "pickup_hoe_up",
404            ],
405            "item_hammer_above":[
406                "pickup_hammer_down",
407            ],
408            "item_hammer_below":[
409                "pickup_hammer_up",
410            ],
411            "item_grass_seed_above":[
412                "pickup_grass_seed_down",
413            ],
414            "item_grass_seed_right":[
415                "pickup_grass_seed_left",
416            ],
417            "item_grass_seed_below":[
418                "pickup_grass_seed_up",
419            ],
420            "item_spirit_left":[
421                "feed_spirit_right",
422                "help_spirit_earthquake_right",
423            ],
424            "item_spirit_above":[
425                "feed_spirit_down",
426                "help_spirit_earthquake_down",
427            ],
428            "item_spirit_below":[
429                "feed_spirit_up",
430                "help_spirit_earthquake_up",
431            ],
432            "item_safe_below":[
433                "next_to_safe_up",
434                "next_to_safe_left",
435            ],
436            "item_lost_bird_left":[
437                "find_lost_bird_right",
438            ],
439            "item_lost_bird_right":[
440                "find_lost_bird_left",
441            ], 
442            "item_lost_bird_below":[
443                "find_lost_bird_up",
444            ],
445            "item_blue_hair_girl_left":[
446                "next_to_blue_hair_girl_right",
447            ],
448            "item_blue_hair_girl_right":[
449                "next_to_blue_hair_girl_left",
450            ],
451            "item_blue_hair_girl_below":[
452                "next_to_blue_hair_girl_up",
453            ],
454            "item_golden_hair_girl_above":[
455                "next_to_golden_hair_girl_down",
456            ],
457            "item_golden_hair_girl_right":[
458                "next_to_golden_hair_girl_left",
459            ],
460            "item_golden_hair_girl_below":[
461                "next_to_golden_hair_girl_up",
462            ],
463            "item_pink_hair_girl_left":[
464                "next_to_pink_hair_girl_right",
465            ],
466            "item_pink_hair_girl_right":[
467                "next_to_pink_hair_girl_left",
468            ],
469            "item_pink_hair_girl_above":[
470                "next_to_pink_hair_girl_down",
471            ],
472            "item_blue_hair_girl_wg_left": [
473                "next_to_blue_hair_girl_wg_right",
474            ],
475            "item_blue_hair_girl_wg_right": [
476                "next_to_blue_hair_girl_wg_left",
477            ],
478            "item_blue_hair_girl_wg_below": [
479                "next_to_blue_hair_girl_wg_up",
480            ],
481            "item_pink_hair_girl_wg_left": [
482                "next_to_pink_hair_girl_wg_right",
483            ],
484            "item_pink_hair_girl_wg_right": [
485                "next_to_pink_hair_girl_wg_left",
486            ],
487            "item_pink_hair_girl_wg_above": [
488                "next_to_pink_hair_girl_wg_down",
489            ],
490            "item_red_hair_girl_wg_left": [
491                "next_to_red_hair_girl_wg_right",
492            ],
493            "item_red_hair_girl_wg_right": [
494                "next_to_red_hair_girl_wg_left",
495            ],
496            "item_red_hair_girl_wg_above": [
497                "next_to_red_hair_girl_wg_down",
498            ],
499            "item_chicken_stall_block1":[
500                "filled_chicken_stall_block1",
501            ],
502            "item_next_to_chicken_stall_block1":[
503                "next_to_chicken_stall_block1",
504            ],
505            "item_chicken_silo_left":[
506                "next_to_chicken_silo_right",
507                "got_fodder_from_chicken_silo_right",
508            ],
509            "item_chicken_silo_below1":[
510                "next_to_chicken_silo_up1",
511                "got_fodder_from_chicken_silo_up1",
512            ],
513            "item_chicken_silo_below2":[
514                "next_to_chicken_silo_up2",
515                "got_fodder_from_chicken_silo_up2",
516            ],
517            "item_cow_feeding_stall": [
518                "cow_feeding_stall_filled",
519            ],
520            "item_cow_feeding_stall_right": [
521                "next_to_cow_feeding_stall_left",
522            ],
523            "item_egg_left": [
524                "next_to_egg_right",
525            ],
526            "item_egg_above": [
527                "next_to_egg_down",
528            ],
529            "item_egg_right": [
530                "next_to_egg_left",
531            ],
532            "item_hatching_box": [
533                "dropped_egg_into_hatching_box",
534            ],
535            "dialogue_box_top":[
536                "pick_up_watercan",
537                "pick_up_grass_seed",
538            ],
539            "dialogue_box_top_mid":[
540                "pick_up_sickle",
541                "pick_up_hammer",
542                "pick_up_cowbell",
543            ],
544            "dialogue_box_top_short":[
545                "pick_up_hoe",
546            ],
547            "turnip_center":[
548                "finish_watering_1",
549                "finish_watering_2",
550            ],
551            "turnip_top":[
552                "ready_to_water_1",
553                "ready_to_water_2",
554            ],
555            "item_turnip_field": [
556                "next_to_center_turnip_down_1",
557                "next_to_center_turnip_down_2",
558                "center_turnip_harvested_1",
559                "center_turnip_harvested_2",
560            ],
561            "item_turnip_field_water":[
562                "next_to_center_turnip_left_1",
563                "next_to_center_turnip_left_2",
564                "center_turnip_watered_1",
565                "center_turnip_watered_2",
566            ],
567            "item_potato_field": [
568                "next_to_center_potato_up_1",
569                "next_to_center_potato_up_2",
570                "next_to_center_potato_below_up_1",
571                "next_to_center_potato_below_up_2",
572                "center_potato_watered_1",
573                "center_potato_watered_2",
574                "center_potato_harvested_1",
575                "center_potato_harvested_2",
576            ],
577            "item_rock_left": [
578                "next_to_rock_right",
579                "rock_cleared",
580            ],
581            "item_rightmost_rock_above": [
582                "next_to_rightmost_rock_down",
583                "rightmost_rock_cleared",
584            ],
585            "item_weed_above": [
586                "next_to_lowest_weed_down",
587                "lowest_weed_removed",
588                "lowest_weed_cut",
589            ],
590            "item_top_left_weed": [
591                "next_to_top_left_weed_up",
592                "top_left_weed_removed",
593                "top_left_weed_cut",
594            ],
595            "item_grassland_right": [
596                "next_to_grassland_left",
597            ],
598            "item_center_grassline": [
599                "center_grass_harvested_1",
600                "center_grass_harvested_2",
601            ],
602            "item_broken_fence_field": [
603                "picked_up_broken_fence_up",
604                "picked_up_broken_fence_down",
605                "picked_up_broken_fence_left",
606                "picked_up_broken_fence_right",
607            ],
608            "item_fence_field": [
609                "restored_fence",
610            ],
611            "center_sign":[
612                "outside_carpenter",
613                "outside_animal_shop",
614                "outside_tool_shop",
615                "outside_restaurant",
616                "outside_juice_bar",
617                "outside_church",
618            ],
619            "screen_bottom_half":[
620                "bought_material",
621                "home_expansion_estimate",
622                "bought_chicken",
623                "sold_chicken",
624                "bought_cow_brush",
625                "bought_saddlebag",
626                "bought_milker",
627                "option_to_buy_rice_ball",
628                "bought_rice_ball",
629                "option_to_buy_croissant",
630                "bought_croissant",
631                "option_to_buy_cake",
632                "bought_cake",
633                "option_to_buy_grape_juice",
634                "bought_grape_juice",
635            ],
636            "screen_top_half":[
637                "in_carpenter",
638                "in_animal_shop",
639                "in_tool_shop",
640                "in_restaurant",
641                "in_juice_bar",
642                "in_church",
643            ],
644            "left_border_frame":[
645                "open_storage_list",
646            ],
647        }
648
649        super().__init__(
650            pyboy,
651            variant="harvest_moon_1",
652            parameters=parameters,
653            override_regions=override_regions,
654            override_multi_target_regions=override_multi_target_regions,
655            override_multi_targets=override_multi_targets,
656        )

Initializes the HarvestMoonStateParser.

Arguments:
  • pyboy (PyBoy): The PyBoy emulator instance.
  • parameters (dict): Configuration parameters for the emulator.
  • additional_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional named screen regions to include.
  • additional_multi_target_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional multi-target named screen regions to include.
  • override_multi_targets (Dict[str, List[str]]): Dictionary mapping region names to lists of additional target names for multi-target regions.
DIALOGUE_TYPES = ['home_dialogue', 'shop_dialogue', 'church_dialogue', 'harvest_spirits_dialogue', 'read_signs_dialogue', 'evening_dialogue', 'barn_dialogue', 'winter_read_signs_dialogue', 'winter_evening_dialogue']
def dialogue_box_open(self, current_screen: numpy.ndarray) -> bool:
658    def dialogue_box_open(self, current_screen: np.ndarray) -> bool:
659        """
660        Determines if a dialogue box is currently open by checking the dialogue bottom right region.
661        Args:
662            current_screen (np.ndarray): The current screen frame from the emulator.
663        Returns:
664            bool: True if a dialogue box is open, False otherwise.
665        """
666        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
667        return self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
668            self.DIALOGUE_TYPES, captured
669        )

Determines if a dialogue box is currently open by checking the dialogue bottom right region.

Arguments:
  • current_screen (np.ndarray): The current screen frame from the emulator.
Returns:

bool: True if a dialogue box is open, False otherwise.

def dialogue_box_empty(self, current_screen: numpy.ndarray) -> bool:
671    def dialogue_box_empty(self, current_screen: np.ndarray) -> bool:
672        box = self.capture_named_region(
673            current_frame=current_screen, name="dialogue_box_bottom"
674        )
675        perc_lt_255 = np.mean(box < 255)
676        if perc_lt_255 < 0.082:  # Empirical threshold
677            return True
678        return False
def is_in_menu(self, current_screen: numpy.ndarray) -> bool:
680    def is_in_menu(self, current_screen: np.ndarray) -> bool:
681        return self.named_region_matches_target(current_screen, "menu_top_right")
def is_in_storage_list(self, current_screen: numpy.ndarray) -> bool:
683    def is_in_storage_list(self, current_screen: np.ndarray) -> bool:
684        return self.named_region_matches_target(current_screen, "storage_list_top_right")
def is_in_dialogue(self, current_screen: numpy.ndarray) -> bool:
686    def is_in_dialogue(self, current_screen: np.ndarray) -> bool:
687        """
688        Returns True if the dialogue_bottom_right region matches any of the saved dialogue type targets.
689        """
690        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
691        return self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
692            self.DIALOGUE_TYPES, captured
693        )

Returns True if the dialogue_bottom_right region matches any of the saved dialogue type targets.

def get_agent_state( self, current_screen: numpy.ndarray) -> AgentState:
695    def get_agent_state(self, current_screen: np.ndarray) -> AgentState:
696        """
697        Determines the current agent state based on the screen.
698
699        Args:
700            current_screen (np.ndarray): The current screen frame from the emulator.
701
702        Returns:
703            AgentState: The current agent state.
704        """
705        if self.is_in_menu(current_screen):
706            return AgentState.IN_MENU
707        if self.is_in_storage_list(current_screen):
708            return AgentState.IN_STORAGE_LIST
709        if self.is_in_dialogue(current_screen):
710            return AgentState.IN_DIALOGUE
711        return AgentState.FREE_ROAM

Determines the current agent state based on the screen.

Arguments:
  • current_screen (np.ndarray): The current screen frame from the emulator.
Returns:

AgentState: The current agent state.

class HarvestMoon2Parser(BaseHarvestMoonStateParser):
 713class HarvestMoon2Parser(BaseHarvestMoonStateParser):
 714    DIALOGUE_TYPES = [
 715        "home_dialogue",
 716        "carpenter_dialogue",
 717        "hospital_dialogue",
 718        "tool_shop_dialogue",
 719        "animal_shop_dialogue",
 720        "restaurant_dialogue",
 721        "library_dialogue",
 722        "flower_shop_dialogue",
 723        "church_dialogue",
 724        "read_signs_dialogue",
 725        "barn_dialogue",
 726    ]
 727
 728    def __init__(self, pyboy, parameters):
 729        override_regions = [
 730            ("menu_top_right", 153, 8, 6, 6),
 731            ("storage_list_top_right", 153, 0, 6, 6),
 732        ]
 733        override_multi_target_regions = [
 734            ("dialogue_bottom_right", 153, 135, 10, 10),
 735            ("screen_middle", 50, 25, 40, 43),
 736            ("outside_barns", 40, 15, 50, 53),
 737            ("screen_bottom", 0, 95, 160, 40),
 738            ("dialogue_box_top", 60, 11, 40, 8),
 739            ("dialogue_box_bottom", 0, 105, 160, 35),
 740            ("hospital_location", 65, 0, 55, 70),
 741            ("tool_shop_location", 65, 0, 55, 70),
 742            ("carpenter_location", 35, 0, 55, 70),
 743            ("animal_shop_location", 65, 0, 55, 70),
 744            ("library_location", 35, 0, 55, 70),
 745            ("flower_shop_location", 30, 0, 105, 70),
 746            ("restaurant_location", 40, 0, 70, 70),
 747            ("item_clock_below", 95, 25, 15, 45),
 748            ("item_bed", 0, 40, 40, 40),
 749            ("item_diary", 45, 40, 20, 40),
 750            ("item_storage_list", 0, 40, 20, 30),
 751            ("item_village_sign_above", 70, 85, 20, 35),
 752            ("item_village_sign_left", 55, 70, 30, 25),
 753            ("item_village_sign_right", 75, 70, 30, 25),
 754            ("item_farm_sign_above", 70, 85, 20, 35),
 755            ("item_farm_sign_left", 55, 70, 30, 25),
 756            ("item_farm_sign_right", 75, 70, 30, 25),
 757            ("item_secret_garden_sign_above", 74, 50, 15, 45),
 758            ("item_secret_garden_sign_right", 58, 50, 27, 25),
 759            ("item_secret_garden_sign_left", 72, 50, 30, 25),
 760            ("item_crop_field_sign_above", 71, 55, 24, 40),
 761            ("item_notice_board_above", 70, 85, 20, 35),
 762            ("item_notice_board_left", 55, 70, 30, 25),
 763            ("item_notice_board_right", 75, 70, 30, 25),
 764            ("turnip_center", 70, 90, 20, 20),
 765            ("turnip_top", 70, 70, 20, 35),
 766            ("item_eggplant_field", 55, 25, 50, 45),
 767            ("item_carrot_field", 55, 25, 50, 45),
 768            ("item_next_to_shipping_box", 0, 20, 30, 50),
 769            ("item_shipping_box_field", 0, 20, 45, 25),
 770            ("item_start_line", 0, 20, 30, 50),
 771            ("item_distance_markers", 65, 40, 30, 30),
 772            ("item_potato_field", 32, 40, 50, 45),
 773            ("item_asparagus_field", 70, 40, 50, 45),
 774            ("item_corn_field", 55, 40, 48, 47),
 775            ("item_cabbage_field", 55, 40, 48, 47),
 776            ("item_center_corn_above", 58, 50, 45, 50),
 777            ("item_leftmost_weed_right", 10, 50, 35, 23),
 778            ("item_leftmost_weed_above", 10, 50, 20, 43),
 779            ("item_berry_left", 70, 39, 32, 31),
 780            ("item_berry_above", 68, 38, 18, 48),
 781            ("item_chicken_stall_block1", 5, 20, 35, 20),
 782            ("item_next_to_chicken_stall_block1", 5, 35, 35, 30),
 783            ("item_chicken_silo_left1", 100, 30, 30, 30),
 784            ("item_chicken_silo_left2", 100, 40, 30, 30),
 785            ("item_chicken_silo_below", 115, 38, 15, 35),
 786            ("item_next_to_hatching_box", 113, 60, 37, 40),
 787            ("item_hatching_box", 129, 66, 16, 30),
 788            ("npc_blue_hair_girl_left", 66, 39, 29, 21),
 789            ("npc_blue_hair_girl_below", 72, 28, 16, 39),
 790            ("npc_blue_hair_girl_right", 56, 39, 29, 21),
 791            ("npc_purple_hair_girl_left", 98, 39, 30, 21),
 792            ("npc_purple_hair_girl_below", 114, 31, 16, 39),
 793            ("npc_blonde_girl_right", 31, 48, 29, 21),
 794            ("npc_blonde_girl_above", 31, 48, 14, 47),
 795            ("center_sign", 55, 65, 50, 15),
 796            ("screen_top_half", 0, 0, 160, 65),
 797            ("screen_bottom_half", 0, 75, 160, 65),
 798            ("left_border_frame", 0, 0, 5, 140),
 799            ("top_left_label", 0, 0, 160, 15),
 800            ("equipment_region_1", 45, 15, 26, 17),
 801            ("equipment_region_2", 72, 15, 26, 17),
 802            ("equipment_region_3", 95, 15, 26, 17),
 803            ("equipment_region_4", 119, 15, 26, 17),
 804        ]
 805        override_multi_targets = {
 806            "dialogue_bottom_right": [
 807                "home_dialogue",
 808                "carpenter_dialogue",
 809                "hospital_dialogue",
 810                "tool_shop_dialogue",
 811                "animal_shop_dialogue",
 812                "restaurant_dialogue",
 813                "library_dialogue",
 814                "flower_shop_dialogue",
 815                "church_dialogue",
 816                "read_signs_dialogue",
 817                "barn_dialogue",
 818            ],
 819            "dialogue_box_bottom": [
 820                "found_lucky_money",
 821                "option_to_diary_sleep",
 822                "reading_secret_garden_sign",
 823                "reading_crop_field_sign",
 824                "computers_article_selected",
 825                "reading_computers_article",
 826                "boulders_article_selected",
 827                "reading_boulders_article",
 828                "crops_article_selected",
 829                "reading_crops_article",
 830                "select_cow",
 831                "bought_named_cow",
 832                "select_chicken",
 833                "select_selling_chicken",
 834                "select_selling_cow",
 835                "select_hothouse",
 836                "select_bridge",
 837                "select_milker",
 838                "speaking_to_blue_hair_girl",
 839                "speaking_to_purple_hair_girl",
 840                "speaking_to_blonde_girl",
 841            ],
 842            "item_clock_below": [
 843                "next_to_clock_up",
 844            ],
 845            "flower_shop_location": [
 846                "outside_flower_shop_up",
 847                "outside_flower_shop_left",
 848                "outside_flower_shop_right",
 849            ],
 850            "item_bed": [
 851                "sleep_in_bed",
 852            ],
 853            "item_diary": [
 854                "next_to_diary",
 855            ],
 856            "item_secret_garden_sign_above": [
 857                "next_to_secret_garden_sign_down",
 858            ],
 859            "item_secret_garden_sign_right": [
 860                "next_to_secret_garden_sign_left",
 861            ],
 862            "item_secret_garden_sign_left": [
 863                "next_to_secret_garden_sign_right",
 864            ],
 865            "item_crop_field_sign_above": [
 866                "next_to_crop_field_sign_down",
 867            ],
 868            "item_start_line": [
 869                "at_the_start_line",
 870            ],
 871            "item_next_to_shipping_box": [
 872                "next_to_shipping_box_up",
 873            ],
 874            "item_shipping_box_field": [
 875                "drop_eggplant_into_shipping_box",
 876            ],
 877            "item_distance_markers": [
 878                "crossed_500m_line",
 879                "crossed_1000m_line",
 880            ],
 881            "item_eggplant_field": [
 882                "next_to_center_eggplant_up_1",
 883                "next_to_center_eggplant_up_2",
 884                "center_eggplant_harvested_1",
 885                "center_eggplant_harvested_2",
 886            ],
 887            "item_carrot_field": [
 888                "next_to_center_carrot_up_1",
 889                "next_to_center_carrot_up_2",
 890                "center_carrot_harvested_1",
 891                "center_carrot_harvested_2",
 892            ],
 893            "item_cabbage_field": [
 894                "at_cabbage_center_1",
 895                "at_cabbage_center_2",
 896                "cabbage_field_watered_1",
 897                "cabbage_field_watered_2",
 898            ],
 899            "item_potato_field": [
 900                "next_to_center_potato_up_1",
 901                "next_to_center_potato_up_2",
 902                "center_potato_watered_1",
 903                "center_potato_watered_2",
 904            ],
 905            "item_asparagus_field": [
 906                "next_to_center_asparagus_right_1",
 907                "next_to_center_asparagus_right_2",
 908                "center_asparagus_watered_1",
 909                "center_asparagus_watered_2",
 910            ],
 911            "item_corn_field": [
 912                "at_corn_center_1",
 913                "at_corn_center_2",
 914                "corn_field_watered_1",
 915                "corn_field_watered_2",
 916            ],
 917            "item_center_corn_above": [
 918                "next_to_center_corn_down_1",
 919                "next_to_center_corn_down_2",
 920                "center_corn_cut_1",
 921                "center_corn_cut_2",
 922            ],
 923            "restaurant_location": [
 924                "outside_restaurant_up",
 925                "outside_restaurant_left",
 926                "outside_restaurant_right",
 927            ],
 928            "hospital_location": [
 929                "outside_hospital_up",
 930                "outside_hospital_left",
 931                "outside_hospital_right",
 932            ],
 933            "tool_shop_location": [
 934                "outside_tool_shop_up",
 935                "outside_tool_shop_left",
 936                "outside_tool_shop_right",
 937            ],
 938            "carpenter_location": [
 939                "outside_carpenter_up",
 940                "outside_carpenter_left",
 941                "outside_carpenter_right",
 942            ],
 943            "animal_shop_location": [
 944                "outside_animal_shop_up",
 945                "outside_animal_shop_left",
 946                "outside_animal_shop_right",
 947            ],
 948            "library_location": [
 949                "outside_library_up",
 950                "outside_library_left",
 951                "outside_library_right",
 952            ],
 953            "screen_top_half": [
 954                "in_hospital",
 955                "in_tool_shop",
 956                "in_carpenter",
 957                "in_animal_shop",
 958                "in_library",
 959                "in_flower_shop",
 960                "in_restaurant",
 961                "shop_for_construction_estimates",
 962            ],
 963            "screen_bottom_half": [
 964                "bought_potato_seeds",
 965                "bought_asparagus_seeds",
 966                "select_potato_seeds",
 967                "select_potato_seeds_portion",
 968                "select_asparagus_seeds",
 969                "select_asparagus_seeds_portion",
 970                "bought_lunch_set",
 971                "select_lunch_set",
 972                "option_to_buy_lunch_set",
 973                "bought_beverage_set",
 974                "select_beverage_set",
 975                "option_to_buy_beverage_set",
 976                "bought_todays_special",
 977                "select_todays_special",
 978                "option_to_buy_todays_special",
 979                "bought_chicken",
 980                "sold_cow",
 981                "sold_chicken",
 982                "hothouse_estimate",
 983                "bridge_estimate",
 984                "bought_milker",
 985            ],
 986            "outside_barns":[
 987                "outside_cow_barn_left",
 988                "outside_cow_barn_right",
 989                "outside_cow_barn_up",
 990                "outside_chicken_coop_left",
 991                "outside_chicken_coop_right",
 992                "outside_chicken_coop_up",
 993            ],
 994            "top_left_label": [
 995                "ready_to_pick_sickle",
 996                "ready_to_pick_hammer",
 997                "ready_to_pick_fishing_rod",
 998                "ready_to_pick_net",
 999                "ready_to_pick_rosemary_seeds",
1000            ],
1001            "equipment_region_1": [
1002                "sprinkler_selected_1",
1003                "sickle_equipped_1",
1004            ],
1005            "equipment_region_2": [
1006                "ax_selected_2",
1007                "net_equipped",
1008                "rosemary_seeds_equipped",
1009            ],
1010            "equipment_region_3": [
1011                "hoe_selected_3",
1012                "net_equipped_3",
1013            ],
1014            "equipment_region_4":[
1015                "empty_hands_selected",
1016                "sickle_equipped",
1017                "hammer_equipped",
1018                "fishing_rod_equipped",
1019            ],
1020            "item_leftmost_weed_right": [
1021                "next_to_leftmost_weed_left",
1022                "leftmost_weed_removed_left",
1023            ],
1024            "item_leftmost_weed_above": [
1025                "next_to_leftmost_weed_down",
1026                "leftmost_weed_removed_down",
1027            ],
1028            "item_berry_left": [
1029                "next_to_berry_right",
1030                "berry_picked_right",
1031            ],
1032            "item_berry_above": [
1033                "next_to_berry_down_1",
1034                "next_to_berry_down_2",
1035                "berry_picked_above_1",
1036                "berry_picked_above_2",
1037            ],
1038            "item_chicken_stall_block1": [
1039                "filled_chicken_stall_block1",
1040            ],
1041            "item_next_to_chicken_stall_block1": [
1042                "next_to_chicken_stall_block1",
1043            ],
1044            "item_chicken_silo_left1": [
1045                "next_to_chicken_silo_right1",
1046                "got_fodder_from_chicken_silo_right1",
1047            ],
1048            "item_chicken_silo_left2": [
1049                "next_to_chicken_silo_right2",
1050                "got_fodder_from_chicken_silo_right2",
1051            ],
1052            "item_chicken_silo_below": [
1053                "next_to_chicken_silo_up",
1054                "got_fodder_from_chicken_silo_up",
1055            ],
1056            "item_next_to_hatching_box": [
1057                "next_to_hatching_box",
1058            ],
1059            "item_hatching_box": [
1060                "dropped_egg_into_hatching_box",
1061            ],
1062            "npc_blue_hair_girl_left": [
1063                "next_to_blue_hair_girl_right",
1064            ],
1065            "npc_blue_hair_girl_below": [
1066                "next_to_blue_hair_girl_up",
1067            ],
1068            "npc_blue_hair_girl_right": [
1069                "next_to_blue_hair_girl_left",
1070            ],
1071            "npc_purple_hair_girl_left": [
1072                "next_to_purple_hair_girl_right",
1073            ],
1074            "npc_purple_hair_girl_below": [
1075                "next_to_purple_hair_girl_up",
1076            ],
1077            "npc_blonde_girl_right": [
1078                "next_to_blonde_girl_left",
1079            ],
1080            "npc_blonde_girl_above": [
1081                "next_to_blonde_girl_down",
1082            ],
1083        }
1084        super().__init__(
1085            pyboy,
1086            variant="harvest_moon_2",
1087            parameters=parameters,
1088            override_regions=override_regions,
1089            override_multi_target_regions=override_multi_target_regions,
1090            override_multi_targets=override_multi_targets,
1091        )
1092
1093    def dialogue_box_open(self, current_screen: np.ndarray) -> bool:
1094        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
1095        return self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
1096            self.DIALOGUE_TYPES, captured
1097        )
1098        
1099    def dialogue_box_empty(self, current_screen: np.ndarray) -> bool:
1100        box = self.capture_named_region(
1101            current_frame=current_screen, name="dialogue_box_bottom"
1102        )
1103        perc_lt_255 = np.mean(box < 255)
1104        if perc_lt_255 < 0.082:  # Empirical threshold
1105            return True
1106        return False
1107
1108    def is_in_menu(self, current_screen: np.ndarray) -> bool:
1109        return self.named_region_matches_target(current_screen, "menu_top_right")
1110
1111    def is_in_storage_list(self, current_screen: np.ndarray) -> bool:
1112        return self.named_region_matches_target(current_screen, "storage_list_top_right")
1113
1114    def is_in_dialogue(self, current_screen: np.ndarray) -> bool:
1115        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
1116        return self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
1117            self.DIALOGUE_TYPES, captured
1118        )
1119
1120    def get_agent_state(self, current_screen: np.ndarray) -> AgentState:
1121        if self.is_in_menu(current_screen):
1122            return AgentState.IN_MENU
1123        if self.is_in_storage_list(current_screen):
1124            return AgentState.IN_STORAGE_LIST
1125        if self.is_in_dialogue(current_screen):
1126            return AgentState.IN_DIALOGUE
1127        return AgentState.FREE_ROAM

Game state parser for all Harvest Moon GBC-based games.

HarvestMoon2Parser(pyboy, parameters)
 728    def __init__(self, pyboy, parameters):
 729        override_regions = [
 730            ("menu_top_right", 153, 8, 6, 6),
 731            ("storage_list_top_right", 153, 0, 6, 6),
 732        ]
 733        override_multi_target_regions = [
 734            ("dialogue_bottom_right", 153, 135, 10, 10),
 735            ("screen_middle", 50, 25, 40, 43),
 736            ("outside_barns", 40, 15, 50, 53),
 737            ("screen_bottom", 0, 95, 160, 40),
 738            ("dialogue_box_top", 60, 11, 40, 8),
 739            ("dialogue_box_bottom", 0, 105, 160, 35),
 740            ("hospital_location", 65, 0, 55, 70),
 741            ("tool_shop_location", 65, 0, 55, 70),
 742            ("carpenter_location", 35, 0, 55, 70),
 743            ("animal_shop_location", 65, 0, 55, 70),
 744            ("library_location", 35, 0, 55, 70),
 745            ("flower_shop_location", 30, 0, 105, 70),
 746            ("restaurant_location", 40, 0, 70, 70),
 747            ("item_clock_below", 95, 25, 15, 45),
 748            ("item_bed", 0, 40, 40, 40),
 749            ("item_diary", 45, 40, 20, 40),
 750            ("item_storage_list", 0, 40, 20, 30),
 751            ("item_village_sign_above", 70, 85, 20, 35),
 752            ("item_village_sign_left", 55, 70, 30, 25),
 753            ("item_village_sign_right", 75, 70, 30, 25),
 754            ("item_farm_sign_above", 70, 85, 20, 35),
 755            ("item_farm_sign_left", 55, 70, 30, 25),
 756            ("item_farm_sign_right", 75, 70, 30, 25),
 757            ("item_secret_garden_sign_above", 74, 50, 15, 45),
 758            ("item_secret_garden_sign_right", 58, 50, 27, 25),
 759            ("item_secret_garden_sign_left", 72, 50, 30, 25),
 760            ("item_crop_field_sign_above", 71, 55, 24, 40),
 761            ("item_notice_board_above", 70, 85, 20, 35),
 762            ("item_notice_board_left", 55, 70, 30, 25),
 763            ("item_notice_board_right", 75, 70, 30, 25),
 764            ("turnip_center", 70, 90, 20, 20),
 765            ("turnip_top", 70, 70, 20, 35),
 766            ("item_eggplant_field", 55, 25, 50, 45),
 767            ("item_carrot_field", 55, 25, 50, 45),
 768            ("item_next_to_shipping_box", 0, 20, 30, 50),
 769            ("item_shipping_box_field", 0, 20, 45, 25),
 770            ("item_start_line", 0, 20, 30, 50),
 771            ("item_distance_markers", 65, 40, 30, 30),
 772            ("item_potato_field", 32, 40, 50, 45),
 773            ("item_asparagus_field", 70, 40, 50, 45),
 774            ("item_corn_field", 55, 40, 48, 47),
 775            ("item_cabbage_field", 55, 40, 48, 47),
 776            ("item_center_corn_above", 58, 50, 45, 50),
 777            ("item_leftmost_weed_right", 10, 50, 35, 23),
 778            ("item_leftmost_weed_above", 10, 50, 20, 43),
 779            ("item_berry_left", 70, 39, 32, 31),
 780            ("item_berry_above", 68, 38, 18, 48),
 781            ("item_chicken_stall_block1", 5, 20, 35, 20),
 782            ("item_next_to_chicken_stall_block1", 5, 35, 35, 30),
 783            ("item_chicken_silo_left1", 100, 30, 30, 30),
 784            ("item_chicken_silo_left2", 100, 40, 30, 30),
 785            ("item_chicken_silo_below", 115, 38, 15, 35),
 786            ("item_next_to_hatching_box", 113, 60, 37, 40),
 787            ("item_hatching_box", 129, 66, 16, 30),
 788            ("npc_blue_hair_girl_left", 66, 39, 29, 21),
 789            ("npc_blue_hair_girl_below", 72, 28, 16, 39),
 790            ("npc_blue_hair_girl_right", 56, 39, 29, 21),
 791            ("npc_purple_hair_girl_left", 98, 39, 30, 21),
 792            ("npc_purple_hair_girl_below", 114, 31, 16, 39),
 793            ("npc_blonde_girl_right", 31, 48, 29, 21),
 794            ("npc_blonde_girl_above", 31, 48, 14, 47),
 795            ("center_sign", 55, 65, 50, 15),
 796            ("screen_top_half", 0, 0, 160, 65),
 797            ("screen_bottom_half", 0, 75, 160, 65),
 798            ("left_border_frame", 0, 0, 5, 140),
 799            ("top_left_label", 0, 0, 160, 15),
 800            ("equipment_region_1", 45, 15, 26, 17),
 801            ("equipment_region_2", 72, 15, 26, 17),
 802            ("equipment_region_3", 95, 15, 26, 17),
 803            ("equipment_region_4", 119, 15, 26, 17),
 804        ]
 805        override_multi_targets = {
 806            "dialogue_bottom_right": [
 807                "home_dialogue",
 808                "carpenter_dialogue",
 809                "hospital_dialogue",
 810                "tool_shop_dialogue",
 811                "animal_shop_dialogue",
 812                "restaurant_dialogue",
 813                "library_dialogue",
 814                "flower_shop_dialogue",
 815                "church_dialogue",
 816                "read_signs_dialogue",
 817                "barn_dialogue",
 818            ],
 819            "dialogue_box_bottom": [
 820                "found_lucky_money",
 821                "option_to_diary_sleep",
 822                "reading_secret_garden_sign",
 823                "reading_crop_field_sign",
 824                "computers_article_selected",
 825                "reading_computers_article",
 826                "boulders_article_selected",
 827                "reading_boulders_article",
 828                "crops_article_selected",
 829                "reading_crops_article",
 830                "select_cow",
 831                "bought_named_cow",
 832                "select_chicken",
 833                "select_selling_chicken",
 834                "select_selling_cow",
 835                "select_hothouse",
 836                "select_bridge",
 837                "select_milker",
 838                "speaking_to_blue_hair_girl",
 839                "speaking_to_purple_hair_girl",
 840                "speaking_to_blonde_girl",
 841            ],
 842            "item_clock_below": [
 843                "next_to_clock_up",
 844            ],
 845            "flower_shop_location": [
 846                "outside_flower_shop_up",
 847                "outside_flower_shop_left",
 848                "outside_flower_shop_right",
 849            ],
 850            "item_bed": [
 851                "sleep_in_bed",
 852            ],
 853            "item_diary": [
 854                "next_to_diary",
 855            ],
 856            "item_secret_garden_sign_above": [
 857                "next_to_secret_garden_sign_down",
 858            ],
 859            "item_secret_garden_sign_right": [
 860                "next_to_secret_garden_sign_left",
 861            ],
 862            "item_secret_garden_sign_left": [
 863                "next_to_secret_garden_sign_right",
 864            ],
 865            "item_crop_field_sign_above": [
 866                "next_to_crop_field_sign_down",
 867            ],
 868            "item_start_line": [
 869                "at_the_start_line",
 870            ],
 871            "item_next_to_shipping_box": [
 872                "next_to_shipping_box_up",
 873            ],
 874            "item_shipping_box_field": [
 875                "drop_eggplant_into_shipping_box",
 876            ],
 877            "item_distance_markers": [
 878                "crossed_500m_line",
 879                "crossed_1000m_line",
 880            ],
 881            "item_eggplant_field": [
 882                "next_to_center_eggplant_up_1",
 883                "next_to_center_eggplant_up_2",
 884                "center_eggplant_harvested_1",
 885                "center_eggplant_harvested_2",
 886            ],
 887            "item_carrot_field": [
 888                "next_to_center_carrot_up_1",
 889                "next_to_center_carrot_up_2",
 890                "center_carrot_harvested_1",
 891                "center_carrot_harvested_2",
 892            ],
 893            "item_cabbage_field": [
 894                "at_cabbage_center_1",
 895                "at_cabbage_center_2",
 896                "cabbage_field_watered_1",
 897                "cabbage_field_watered_2",
 898            ],
 899            "item_potato_field": [
 900                "next_to_center_potato_up_1",
 901                "next_to_center_potato_up_2",
 902                "center_potato_watered_1",
 903                "center_potato_watered_2",
 904            ],
 905            "item_asparagus_field": [
 906                "next_to_center_asparagus_right_1",
 907                "next_to_center_asparagus_right_2",
 908                "center_asparagus_watered_1",
 909                "center_asparagus_watered_2",
 910            ],
 911            "item_corn_field": [
 912                "at_corn_center_1",
 913                "at_corn_center_2",
 914                "corn_field_watered_1",
 915                "corn_field_watered_2",
 916            ],
 917            "item_center_corn_above": [
 918                "next_to_center_corn_down_1",
 919                "next_to_center_corn_down_2",
 920                "center_corn_cut_1",
 921                "center_corn_cut_2",
 922            ],
 923            "restaurant_location": [
 924                "outside_restaurant_up",
 925                "outside_restaurant_left",
 926                "outside_restaurant_right",
 927            ],
 928            "hospital_location": [
 929                "outside_hospital_up",
 930                "outside_hospital_left",
 931                "outside_hospital_right",
 932            ],
 933            "tool_shop_location": [
 934                "outside_tool_shop_up",
 935                "outside_tool_shop_left",
 936                "outside_tool_shop_right",
 937            ],
 938            "carpenter_location": [
 939                "outside_carpenter_up",
 940                "outside_carpenter_left",
 941                "outside_carpenter_right",
 942            ],
 943            "animal_shop_location": [
 944                "outside_animal_shop_up",
 945                "outside_animal_shop_left",
 946                "outside_animal_shop_right",
 947            ],
 948            "library_location": [
 949                "outside_library_up",
 950                "outside_library_left",
 951                "outside_library_right",
 952            ],
 953            "screen_top_half": [
 954                "in_hospital",
 955                "in_tool_shop",
 956                "in_carpenter",
 957                "in_animal_shop",
 958                "in_library",
 959                "in_flower_shop",
 960                "in_restaurant",
 961                "shop_for_construction_estimates",
 962            ],
 963            "screen_bottom_half": [
 964                "bought_potato_seeds",
 965                "bought_asparagus_seeds",
 966                "select_potato_seeds",
 967                "select_potato_seeds_portion",
 968                "select_asparagus_seeds",
 969                "select_asparagus_seeds_portion",
 970                "bought_lunch_set",
 971                "select_lunch_set",
 972                "option_to_buy_lunch_set",
 973                "bought_beverage_set",
 974                "select_beverage_set",
 975                "option_to_buy_beverage_set",
 976                "bought_todays_special",
 977                "select_todays_special",
 978                "option_to_buy_todays_special",
 979                "bought_chicken",
 980                "sold_cow",
 981                "sold_chicken",
 982                "hothouse_estimate",
 983                "bridge_estimate",
 984                "bought_milker",
 985            ],
 986            "outside_barns":[
 987                "outside_cow_barn_left",
 988                "outside_cow_barn_right",
 989                "outside_cow_barn_up",
 990                "outside_chicken_coop_left",
 991                "outside_chicken_coop_right",
 992                "outside_chicken_coop_up",
 993            ],
 994            "top_left_label": [
 995                "ready_to_pick_sickle",
 996                "ready_to_pick_hammer",
 997                "ready_to_pick_fishing_rod",
 998                "ready_to_pick_net",
 999                "ready_to_pick_rosemary_seeds",
1000            ],
1001            "equipment_region_1": [
1002                "sprinkler_selected_1",
1003                "sickle_equipped_1",
1004            ],
1005            "equipment_region_2": [
1006                "ax_selected_2",
1007                "net_equipped",
1008                "rosemary_seeds_equipped",
1009            ],
1010            "equipment_region_3": [
1011                "hoe_selected_3",
1012                "net_equipped_3",
1013            ],
1014            "equipment_region_4":[
1015                "empty_hands_selected",
1016                "sickle_equipped",
1017                "hammer_equipped",
1018                "fishing_rod_equipped",
1019            ],
1020            "item_leftmost_weed_right": [
1021                "next_to_leftmost_weed_left",
1022                "leftmost_weed_removed_left",
1023            ],
1024            "item_leftmost_weed_above": [
1025                "next_to_leftmost_weed_down",
1026                "leftmost_weed_removed_down",
1027            ],
1028            "item_berry_left": [
1029                "next_to_berry_right",
1030                "berry_picked_right",
1031            ],
1032            "item_berry_above": [
1033                "next_to_berry_down_1",
1034                "next_to_berry_down_2",
1035                "berry_picked_above_1",
1036                "berry_picked_above_2",
1037            ],
1038            "item_chicken_stall_block1": [
1039                "filled_chicken_stall_block1",
1040            ],
1041            "item_next_to_chicken_stall_block1": [
1042                "next_to_chicken_stall_block1",
1043            ],
1044            "item_chicken_silo_left1": [
1045                "next_to_chicken_silo_right1",
1046                "got_fodder_from_chicken_silo_right1",
1047            ],
1048            "item_chicken_silo_left2": [
1049                "next_to_chicken_silo_right2",
1050                "got_fodder_from_chicken_silo_right2",
1051            ],
1052            "item_chicken_silo_below": [
1053                "next_to_chicken_silo_up",
1054                "got_fodder_from_chicken_silo_up",
1055            ],
1056            "item_next_to_hatching_box": [
1057                "next_to_hatching_box",
1058            ],
1059            "item_hatching_box": [
1060                "dropped_egg_into_hatching_box",
1061            ],
1062            "npc_blue_hair_girl_left": [
1063                "next_to_blue_hair_girl_right",
1064            ],
1065            "npc_blue_hair_girl_below": [
1066                "next_to_blue_hair_girl_up",
1067            ],
1068            "npc_blue_hair_girl_right": [
1069                "next_to_blue_hair_girl_left",
1070            ],
1071            "npc_purple_hair_girl_left": [
1072                "next_to_purple_hair_girl_right",
1073            ],
1074            "npc_purple_hair_girl_below": [
1075                "next_to_purple_hair_girl_up",
1076            ],
1077            "npc_blonde_girl_right": [
1078                "next_to_blonde_girl_left",
1079            ],
1080            "npc_blonde_girl_above": [
1081                "next_to_blonde_girl_down",
1082            ],
1083        }
1084        super().__init__(
1085            pyboy,
1086            variant="harvest_moon_2",
1087            parameters=parameters,
1088            override_regions=override_regions,
1089            override_multi_target_regions=override_multi_target_regions,
1090            override_multi_targets=override_multi_targets,
1091        )

Initializes the HarvestMoonStateParser.

Arguments:
  • pyboy (PyBoy): The PyBoy emulator instance.
  • parameters (dict): Configuration parameters for the emulator.
  • additional_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional named screen regions to include.
  • additional_multi_target_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional multi-target named screen regions to include.
  • override_multi_targets (Dict[str, List[str]]): Dictionary mapping region names to lists of additional target names for multi-target regions.
DIALOGUE_TYPES = ['home_dialogue', 'carpenter_dialogue', 'hospital_dialogue', 'tool_shop_dialogue', 'animal_shop_dialogue', 'restaurant_dialogue', 'library_dialogue', 'flower_shop_dialogue', 'church_dialogue', 'read_signs_dialogue', 'barn_dialogue']
def dialogue_box_open(self, current_screen: numpy.ndarray) -> bool:
1093    def dialogue_box_open(self, current_screen: np.ndarray) -> bool:
1094        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
1095        return self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
1096            self.DIALOGUE_TYPES, captured
1097        )
def dialogue_box_empty(self, current_screen: numpy.ndarray) -> bool:
1099    def dialogue_box_empty(self, current_screen: np.ndarray) -> bool:
1100        box = self.capture_named_region(
1101            current_frame=current_screen, name="dialogue_box_bottom"
1102        )
1103        perc_lt_255 = np.mean(box < 255)
1104        if perc_lt_255 < 0.082:  # Empirical threshold
1105            return True
1106        return False
def is_in_menu(self, current_screen: numpy.ndarray) -> bool:
1108    def is_in_menu(self, current_screen: np.ndarray) -> bool:
1109        return self.named_region_matches_target(current_screen, "menu_top_right")
def is_in_storage_list(self, current_screen: numpy.ndarray) -> bool:
1111    def is_in_storage_list(self, current_screen: np.ndarray) -> bool:
1112        return self.named_region_matches_target(current_screen, "storage_list_top_right")
def is_in_dialogue(self, current_screen: numpy.ndarray) -> bool:
1114    def is_in_dialogue(self, current_screen: np.ndarray) -> bool:
1115        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
1116        return self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
1117            self.DIALOGUE_TYPES, captured
1118        )
def get_agent_state( self, current_screen: numpy.ndarray) -> AgentState:
1120    def get_agent_state(self, current_screen: np.ndarray) -> AgentState:
1121        if self.is_in_menu(current_screen):
1122            return AgentState.IN_MENU
1123        if self.is_in_storage_list(current_screen):
1124            return AgentState.IN_STORAGE_LIST
1125        if self.is_in_dialogue(current_screen):
1126            return AgentState.IN_DIALOGUE
1127        return AgentState.FREE_ROAM
class HarvestMoon3Parser(BaseHarvestMoonStateParser):
1130class HarvestMoon3Parser(BaseHarvestMoonStateParser):
1131    DIALOGUE_TYPES = [
1132        "normal_dialogue",
1133        "mainland_dialogue",
1134    ]
1135
1136    def __init__(self, pyboy, parameters):
1137        override_regions = [
1138            ("menu_top_right", 153, 0, 6, 6),
1139        ]
1140        override_multi_target_regions = [
1141            ("dialogue_bottom_right", 153, 135, 10, 10),
1142            ("screen_bottom", 0, 95, 160, 40),
1143            ("dialogue_box_bottom", 0, 98, 160, 45),
1144            ("item_secret_garden_sign_above", 60, 55, 20, 40),
1145            ("item_secret_garden_sign_right", 50, 55, 35, 25),
1146            ("item_turnip_seeds_above", 30, 55, 17, 41),
1147            ("item_turnip_seeds_below", 30, 40, 17, 39),
1148            ("item_potato_seeds_above", 63, 55, 17, 41),
1149            ("item_potato_seeds_below", 63, 40, 17, 39),
1150            ("screen_top_half", 0, 0, 160, 65),
1151            ("screen_bottom_half", 0, 75, 160, 65),
1152            ("item_storage_sign_below", 70, 40, 20, 40),
1153            ("item_storage_sign_left", 70, 55, 35, 25),
1154            ("item_storage_sign_right", 55, 55, 30, 25),
1155            ("item_morning_market_sign_left", 128, 55, 31, 27),
1156            ("npc_kirk_above", 65, 55, 25, 40),
1157            ("npc_kirk_mainland_right", 55, 45, 30, 25),
1158            ("npc_kirk_mainland_below", 70, 40, 15, 40),
1159            ("npc_joe_left", 125, 55, 34, 25),
1160            ("npc_lukia_right", 38, 55, 34, 25),
1161            ("dialogue_box_upper_border", 0, 96, 160, 8),
1162            ("npc_lucus_above", 70, 55, 19, 40),
1163            ("npc_lucus_left", 70, 55, 34, 25),
1164            ("npc_lucus_right", 55, 55, 34, 25),
1165            ("npc_lyla_right", 54, 55, 34, 25),
1166            ("item_meal_set_empty_1", 80, 40, 30, 15),
1167            ("item_meal_set_empty_2", 80, 80, 30, 15),
1168            ("item_coffee_above", 72, 55, 15, 39),
1169            ("item_coffee_below", 72, 40, 13, 30),
1170            ("entrance", 40, 65, 80, 80),
1171            ("top_entrance", 45, 0, 70, 40),
1172            ("outside_chicken_coop", 45, 40, 45, 35),
1173            ("outside_hot_spring", 45, 40, 45, 35),
1174            ("item_tea_above", 70, 55, 17, 41),
1175            ("item_tea_below", 70, 40, 17, 39),
1176            ("item_asparagus_seeds_above", 72, 55, 17, 41),
1177            ("item_asparagus_seeds_below", 72, 40, 17, 39),
1178            ("item_right_cow_stall_block", 115, 25, 45, 25),
1179            ("item_right_cow_stall_block_below", 115, 25, 45, 50),
1180            ("item_right_cow_stall_block_left", 95, 35, 55, 35),
1181            ("item_cow_stall_block_2", 112, 35, 38, 35),
1182            ("item_ferry_sign_above", 70, 60, 16, 45),
1183            ("item_ferry_sign_left", 70, 60, 30, 28),
1184            ("item_fireplace_below", 105, 40, 15, 40),
1185            ("item_rock_left", 95, 55, 30, 25),
1186            ("item_target_potato_below", 56, 32, 48, 47),
1187            ("item_center_spotato_above", 56, 60, 47, 50),
1188            ("item_center_watermelon_above", 30, 25, 49, 54),
1189            ("npc_kate_left", 50, 58, 28, 19),
1190            ("npc_kate_right", 63, 55, 33, 23),
1191            ("npc_kate_below", 63, 39, 16, 40),
1192            ("item_weed_left", 70, 0, 50, 45),
1193            ("item_cherry_left", 95, 50, 30, 38),
1194            ("item_fodder_set_below", 113, 40, 14, 40),
1195            ("item_horse_medicine_below", 97, 40, 14, 40),
1196            ("item_chicken_silo_left1", 96, 50, 30, 30),
1197            ("item_chicken_silo_left2", 96, 65, 30, 30),
1198            ("item_chicken_silo_above", 110, 50, 20, 40),
1199            ("item_topmost_chicken_stall_block", 115, 36, 35, 29),
1200            ("item_next_to_topmost_chicken_stall_block", 97, 36, 53, 29),
1201            ("item_fodder_set", 97, 40, 30, 5),
1202            ("item_horse_medicine", 97, 40, 30, 5),
1203            ("item_next_to_hatching_box", 7, 62, 36, 38),
1204            ("item_hatching_box", 7, 62, 23, 38),
1205            ("item_stairs", 40, 0, 95, 80),
1206            ("item_flower_vase_empty_1", 0, 80, 50, 15),
1207            ("item_flower_vase_empty_2", 0, 40, 50, 5),
1208            ("item_flower_vase_above", 32, 56, 16, 40),
1209            ("item_flower_vase_below", 32, 40, 16, 40),
1210            ("item_horse_saddle_empty_1", 78, 80, 80, 15),
1211            ("item_horse_saddle_empty_2", 78, 40, 80, 15),
1212            ("item_horse_saddle_above", 72, 55, 24, 41),
1213            ("item_horse_saddle_below", 78, 40, 17, 39),
1214            ("item_center_eggplant_above", 52, 15, 51, 64),
1215            ("item_center_eggplant_left", 70, 32, 48, 48),
1216            ("menu_box", 106, 0, 53, 122),
1217            ("player_top_left", 0, 0, 35, 40),
1218            ("item_berry_above", 0, 50, 35, 45),
1219            ("sell_animal_section_1", 62, 80, 83, 16),
1220            ("sell_animal_section_2", 62, 40, 83, 16),
1221            ("item_sell_chicken_below", 80, 40, 15, 40),
1222            ("item_sell_chicken_above", 78, 56, 17, 39),
1223            ("item_center_turnip_below", 56, 32, 48, 47),
1224            ("item_bookshelf_below", 125, 32, 25, 48),
1225        ]
1226        override_multi_targets = {
1227            "dialogue_bottom_right": [
1228                "normal_dialogue",
1229                "mainland_dialogue",
1230            ],
1231            "dialogue_box_bottom": [
1232                "reading_secret_garden_sign",
1233                "reading_storage_sign",
1234                "reading_morning_market_sign",
1235                "reading_ferry_sign",
1236                "found_secret_savings",
1237                "select_tea",
1238                "select_asparagus_seeds",
1239                "select_coffee",
1240                "select_turnip_seeds",
1241                "select_turnip_seeds_portion",
1242                "select_potato_seeds",
1243                "select_potato_seeds_portion",
1244                "bought_turnip_seeds",
1245                "bought_potato_seeds",
1246                "select_meal_set",
1247                "speaking_to_kate",
1248                "farm_label",
1249                "village_label",
1250                "grassland_label",
1251                "forest_label",
1252                "cliff_label",
1253                "mountain_label",
1254                "shopping_mall_label",
1255                "farmers_union_label",
1256                "aquarium_label",
1257                "theatre_label",
1258                "selected_fodder_set",
1259                "selected_horse_medicine",
1260                "bought_from_farmers_union",
1261                "bought_from_flower_shop",
1262                "animal_sold",
1263                "finish_animal_ch2",
1264            ],
1265            "item_rock_left": [
1266                "next_to_rock_right",
1267                "rock_cleared",
1268            ],
1269            "item_target_potato_below": [
1270                "next_to_target_potato_up",
1271                "target_potato_harvested",
1272            ],
1273            "item_center_spotato_above": [
1274                "next_to_spotato_down",
1275                "center_spotato_watered",
1276            ],
1277            "item_center_watermelon_above": [
1278                "next_to_center_watermelon_down",
1279                "center_watermelon_watered",
1280            ],
1281            "npc_kate_left": [
1282                "next_to_kate_right",
1283            ],
1284            "npc_kate_right": [
1285                "next_to_kate_left",
1286            ],
1287            "npc_kate_below": [
1288                "next_to_kate_up",
1289            ],
1290            "item_weed_left": [
1291                "next_to_weed_right",
1292                "weed_removed",
1293            ],
1294            "item_cherry_left": [
1295                "next_to_cherry_right",
1296                "cherry_picked",
1297            ],
1298            "item_chicken_silo_left1": [
1299                "next_to_chicken_silo_right1",
1300                "got_fodder_from_chicken_silo_right1",
1301            ],
1302            "item_chicken_silo_left2": [
1303                "next_to_chicken_silo_right2",
1304                "got_fodder_from_chicken_silo_right2",
1305            ],
1306            "item_chicken_silo_above": [
1307                "next_to_chicken_silo_down",
1308                "got_fodder_from_chicken_silo_down",
1309            ],
1310            "item_topmost_chicken_stall_block": [
1311                "filled_topmost_chicken_stall_block",
1312            ],
1313            "item_next_to_topmost_chicken_stall_block": [
1314                "next_to_topmost_chicken_stall_block",
1315            ],
1316            "item_next_to_hatching_box": [
1317                "next_to_hatching_box",
1318            ],
1319            "item_hatching_box": [
1320                "dropped_egg_into_hatching_box",
1321            ],
1322            "item_stairs": [
1323                "next_to_stairs_1",
1324                "next_to_stairs_2",
1325                "next_to_stairs_3",
1326            ],
1327            "item_fodder_set_below": [
1328                "next_to_fodder_set_up",
1329            ],
1330            "item_horse_medicine_below": [
1331                "next_to_horse_medicine_up",
1332            ],
1333            "item_fodder_set": [
1334                "picked_fodder_set",
1335            ],
1336            "item_horse_medicine": [
1337                "picked_horse_medicine",
1338            ],
1339            "item_storage_sign_below": [
1340                "next_to_storage_sign_up",
1341            ],
1342            "item_storage_sign_left": [
1343                "next_to_storage_sign_right",
1344            ],
1345            "item_storage_sign_right": [
1346                "next_to_storage_sign_left",
1347            ],
1348            "item_morning_market_sign_left": [
1349                "next_to_morning_market_sign_right",
1350            ],
1351            "npc_kirk_above": [
1352                "next_to_kirk_down",
1353            ],
1354            "npc_kirk_mainland_right": [
1355                "next_to_kirk_mainland_left",
1356            ],
1357            "npc_kirk_mainland_below": [
1358                "next_to_kirk_mainland_up",
1359            ],
1360            "npc_joe_left": [
1361                "next_to_joe_right",
1362            ],
1363            "dialogue_box_upper_border": [
1364                "speaking_to_kirk_village",
1365                "speaking_to_joe",
1366                "speaking_to_lukia",
1367                "speaking_to_lucus",
1368                "speaking_to_lyla",
1369            ],
1370            "item_secret_garden_sign_above": [
1371                "next_to_secret_garden_sign_down",
1372            ],
1373            "item_secret_garden_sign_right": [
1374                "next_to_secret_garden_sign_left",
1375            ],
1376            "item_turnip_seeds_above": [
1377                "next_to_turnip_seeds_down",
1378            ],
1379            "item_turnip_seeds_below": [
1380                "next_to_turnip_seeds_up",
1381            ],
1382            "item_potato_seeds_above": [
1383                "next_to_potato_seeds_down",
1384            ],
1385            "item_potato_seeds_below": [
1386                "next_to_potato_seeds_up",
1387            ],
1388            "npc_lukia_right": [
1389                "next_to_lukia_left",
1390            ],
1391            "npc_lucus_above": [
1392                "next_to_lucus_down",
1393            ],
1394            "npc_lucus_left": [
1395                "next_to_lucus_right",
1396            ],
1397            "npc_lucus_right": [
1398                "next_to_lucus_left",
1399            ],
1400            "npc_lyla_right": [
1401                "next_to_lyla_left",
1402            ],
1403            "outside_chicken_coop": [
1404                "outside_chicken_coop_left",
1405                "outside_chicken_coop_right",
1406                "outside_chicken_coop_up",
1407            ],
1408            "item_flower_vase_empty_1": [
1409                "bought_flower_vase_1",
1410            ],
1411            "item_flower_vase_empty_2": [
1412                "bought_flower_vase_2",
1413            ],
1414            "item_flower_vase_above": [
1415                "next_to_vase_down",
1416            ],
1417            "item_flower_vase_below": [
1418                "next_to_vase_up",
1419            ],
1420            "item_center_eggplant_above": [
1421                "next_to_eggplant_down",
1422                "center_eggplant_harvested_down",
1423            ],
1424            "item_center_eggplant_left": [
1425                "next_to_eggplant_right",
1426                "center_eggplant_harvested_right",
1427            ],
1428            "menu_box": [
1429                "choose_may",
1430            ],
1431            "player_top_left": [
1432                "display_player_status",
1433            ],
1434            "item_berry_above": [
1435                "next_to_berry_down",
1436                "berry_picked_above",
1437            ],
1438            "sell_animal_section_1": [
1439                "selling_animal_1",
1440            ],
1441            "sell_animal_section_2": [
1442                "selling_animal_2",
1443            ],
1444            "item_sell_chicken_below": [
1445                "next_to_sell_chicken_up",
1446            ],
1447            "item_sell_chicken_above": [
1448                "next_to_sell_chicken_down",
1449            ],
1450            "item_center_turnip_below": [
1451                "next_to_center_turnip_up",
1452                "center_turnip_harvested",
1453            ],
1454            "item_bookshelf_below": [
1455                "next_to_bookshelf_up",
1456            ],
1457            "item_horse_saddle_empty_1": [
1458                "bought_horse_saddle_1",
1459            ],
1460            "item_horse_saddle_empty_2": [
1461                "bought_horse_saddle_2",
1462            ],
1463            "item_horse_saddle_above": [
1464                "next_to_horse_saddle_down",
1465            ],
1466            "item_horse_saddle_below": [
1467                "next_to_horse_saddle_up",
1468            ],
1469            "item_meal_set_empty_1": [
1470                "bought_meal_set_1",
1471            ],
1472            "item_meal_set_empty_2": [
1473                "bought_meal_set_2",
1474            ],
1475            "item_coffee_above": [
1476                "next_to_coffee_down",
1477            ],
1478            "item_coffee_below": [
1479                "next_to_coffee_up",
1480            ],
1481            "top_entrance": [
1482                "village_entrance",
1483            ],
1484            "entrance": [
1485                "village_ferry_entrance",
1486                "farm_entrance",
1487                "grassland_entrance",
1488                "forest_entrance",
1489                "cliff_entrance",
1490                "mountain_entrance",
1491                "shopping_mall_entrance",
1492                "farmers_union_entrance",
1493                "aquarium_entrance",
1494                "theatre_entrance",
1495                "hot_spring_entrance",
1496                "shopping_mall_second_floor",
1497            ],
1498            "item_tea_above": [
1499                "next_to_tea_down",
1500            ],
1501            "item_tea_below": [
1502                "next_to_tea_up",
1503            ],
1504            "item_asparagus_seeds_above": [
1505                "next_to_asparagus_seeds_down",
1506            ],
1507            "item_asparagus_seeds_below": [
1508                "next_to_asparagus_seeds_up",
1509            ],
1510            "item_right_cow_stall_block": [
1511                "filled_right_cow_stall_block",
1512            ],
1513            "item_right_cow_stall_block_below": [
1514                "next_to_right_cow_stall_block_up",
1515            ],
1516            "item_right_cow_stall_block_left": [
1517                "next_to_right_cow_stall_block_right",
1518            ],
1519            "item_cow_stall_block_2": [
1520                "filled_cow_stall_block_right",
1521            ],
1522            "item_ferry_sign_above": [
1523                "next_to_ferry_sign_down",
1524            ],
1525            "item_ferry_sign_left": [
1526                "next_to_ferry_sign_right",
1527            ],
1528            "item_fireplace_below": [
1529                "next_to_fireplace_up",
1530            ],
1531            "outside_hot_spring": [
1532                "outside_hot_spring_left",
1533                "outside_hot_spring_right",
1534                "outside_hot_spring_up",
1535            ],
1536        }
1537        super().__init__(
1538            pyboy,
1539            variant="harvest_moon_3",
1540            parameters=parameters,
1541            override_regions=override_regions,
1542            override_multi_target_regions=override_multi_target_regions,
1543            override_multi_targets=override_multi_targets,
1544        )
1545
1546    def dialogue_box_open(self, current_screen: np.ndarray) -> bool:
1547        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
1548        if self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
1549            self.DIALOGUE_TYPES, captured
1550        ):
1551            return True
1552        return False
1553    
1554    def dialogue_box_empty(self, current_screen: np.ndarray) -> bool:
1555        box = self.capture_named_region(
1556            current_frame=current_screen, name="dialogue_box_bottom"
1557        )
1558        perc_lt_255 = np.mean(box < 255)
1559        if perc_lt_255 < 0.082:  # Empirical threshold
1560            return True
1561        return False
1562
1563    def is_in_menu(self, current_screen: np.ndarray) -> bool:
1564        return self.named_region_matches_target(current_screen, "menu_top_right")
1565    
1566    def is_in_dialogue(self, current_screen: np.ndarray) -> bool:
1567        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
1568        if self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
1569            self.DIALOGUE_TYPES, captured
1570        ):
1571            return True
1572        return False
1573
1574    def get_agent_state(self, current_screen: np.ndarray) -> AgentState:
1575        if self.is_in_menu(current_screen):
1576            return AgentState.IN_MENU
1577        if self.is_in_dialogue(current_screen):
1578            return AgentState.IN_DIALOGUE
1579        return AgentState.FREE_ROAM

Game state parser for all Harvest Moon GBC-based games.

HarvestMoon3Parser(pyboy, parameters)
1136    def __init__(self, pyboy, parameters):
1137        override_regions = [
1138            ("menu_top_right", 153, 0, 6, 6),
1139        ]
1140        override_multi_target_regions = [
1141            ("dialogue_bottom_right", 153, 135, 10, 10),
1142            ("screen_bottom", 0, 95, 160, 40),
1143            ("dialogue_box_bottom", 0, 98, 160, 45),
1144            ("item_secret_garden_sign_above", 60, 55, 20, 40),
1145            ("item_secret_garden_sign_right", 50, 55, 35, 25),
1146            ("item_turnip_seeds_above", 30, 55, 17, 41),
1147            ("item_turnip_seeds_below", 30, 40, 17, 39),
1148            ("item_potato_seeds_above", 63, 55, 17, 41),
1149            ("item_potato_seeds_below", 63, 40, 17, 39),
1150            ("screen_top_half", 0, 0, 160, 65),
1151            ("screen_bottom_half", 0, 75, 160, 65),
1152            ("item_storage_sign_below", 70, 40, 20, 40),
1153            ("item_storage_sign_left", 70, 55, 35, 25),
1154            ("item_storage_sign_right", 55, 55, 30, 25),
1155            ("item_morning_market_sign_left", 128, 55, 31, 27),
1156            ("npc_kirk_above", 65, 55, 25, 40),
1157            ("npc_kirk_mainland_right", 55, 45, 30, 25),
1158            ("npc_kirk_mainland_below", 70, 40, 15, 40),
1159            ("npc_joe_left", 125, 55, 34, 25),
1160            ("npc_lukia_right", 38, 55, 34, 25),
1161            ("dialogue_box_upper_border", 0, 96, 160, 8),
1162            ("npc_lucus_above", 70, 55, 19, 40),
1163            ("npc_lucus_left", 70, 55, 34, 25),
1164            ("npc_lucus_right", 55, 55, 34, 25),
1165            ("npc_lyla_right", 54, 55, 34, 25),
1166            ("item_meal_set_empty_1", 80, 40, 30, 15),
1167            ("item_meal_set_empty_2", 80, 80, 30, 15),
1168            ("item_coffee_above", 72, 55, 15, 39),
1169            ("item_coffee_below", 72, 40, 13, 30),
1170            ("entrance", 40, 65, 80, 80),
1171            ("top_entrance", 45, 0, 70, 40),
1172            ("outside_chicken_coop", 45, 40, 45, 35),
1173            ("outside_hot_spring", 45, 40, 45, 35),
1174            ("item_tea_above", 70, 55, 17, 41),
1175            ("item_tea_below", 70, 40, 17, 39),
1176            ("item_asparagus_seeds_above", 72, 55, 17, 41),
1177            ("item_asparagus_seeds_below", 72, 40, 17, 39),
1178            ("item_right_cow_stall_block", 115, 25, 45, 25),
1179            ("item_right_cow_stall_block_below", 115, 25, 45, 50),
1180            ("item_right_cow_stall_block_left", 95, 35, 55, 35),
1181            ("item_cow_stall_block_2", 112, 35, 38, 35),
1182            ("item_ferry_sign_above", 70, 60, 16, 45),
1183            ("item_ferry_sign_left", 70, 60, 30, 28),
1184            ("item_fireplace_below", 105, 40, 15, 40),
1185            ("item_rock_left", 95, 55, 30, 25),
1186            ("item_target_potato_below", 56, 32, 48, 47),
1187            ("item_center_spotato_above", 56, 60, 47, 50),
1188            ("item_center_watermelon_above", 30, 25, 49, 54),
1189            ("npc_kate_left", 50, 58, 28, 19),
1190            ("npc_kate_right", 63, 55, 33, 23),
1191            ("npc_kate_below", 63, 39, 16, 40),
1192            ("item_weed_left", 70, 0, 50, 45),
1193            ("item_cherry_left", 95, 50, 30, 38),
1194            ("item_fodder_set_below", 113, 40, 14, 40),
1195            ("item_horse_medicine_below", 97, 40, 14, 40),
1196            ("item_chicken_silo_left1", 96, 50, 30, 30),
1197            ("item_chicken_silo_left2", 96, 65, 30, 30),
1198            ("item_chicken_silo_above", 110, 50, 20, 40),
1199            ("item_topmost_chicken_stall_block", 115, 36, 35, 29),
1200            ("item_next_to_topmost_chicken_stall_block", 97, 36, 53, 29),
1201            ("item_fodder_set", 97, 40, 30, 5),
1202            ("item_horse_medicine", 97, 40, 30, 5),
1203            ("item_next_to_hatching_box", 7, 62, 36, 38),
1204            ("item_hatching_box", 7, 62, 23, 38),
1205            ("item_stairs", 40, 0, 95, 80),
1206            ("item_flower_vase_empty_1", 0, 80, 50, 15),
1207            ("item_flower_vase_empty_2", 0, 40, 50, 5),
1208            ("item_flower_vase_above", 32, 56, 16, 40),
1209            ("item_flower_vase_below", 32, 40, 16, 40),
1210            ("item_horse_saddle_empty_1", 78, 80, 80, 15),
1211            ("item_horse_saddle_empty_2", 78, 40, 80, 15),
1212            ("item_horse_saddle_above", 72, 55, 24, 41),
1213            ("item_horse_saddle_below", 78, 40, 17, 39),
1214            ("item_center_eggplant_above", 52, 15, 51, 64),
1215            ("item_center_eggplant_left", 70, 32, 48, 48),
1216            ("menu_box", 106, 0, 53, 122),
1217            ("player_top_left", 0, 0, 35, 40),
1218            ("item_berry_above", 0, 50, 35, 45),
1219            ("sell_animal_section_1", 62, 80, 83, 16),
1220            ("sell_animal_section_2", 62, 40, 83, 16),
1221            ("item_sell_chicken_below", 80, 40, 15, 40),
1222            ("item_sell_chicken_above", 78, 56, 17, 39),
1223            ("item_center_turnip_below", 56, 32, 48, 47),
1224            ("item_bookshelf_below", 125, 32, 25, 48),
1225        ]
1226        override_multi_targets = {
1227            "dialogue_bottom_right": [
1228                "normal_dialogue",
1229                "mainland_dialogue",
1230            ],
1231            "dialogue_box_bottom": [
1232                "reading_secret_garden_sign",
1233                "reading_storage_sign",
1234                "reading_morning_market_sign",
1235                "reading_ferry_sign",
1236                "found_secret_savings",
1237                "select_tea",
1238                "select_asparagus_seeds",
1239                "select_coffee",
1240                "select_turnip_seeds",
1241                "select_turnip_seeds_portion",
1242                "select_potato_seeds",
1243                "select_potato_seeds_portion",
1244                "bought_turnip_seeds",
1245                "bought_potato_seeds",
1246                "select_meal_set",
1247                "speaking_to_kate",
1248                "farm_label",
1249                "village_label",
1250                "grassland_label",
1251                "forest_label",
1252                "cliff_label",
1253                "mountain_label",
1254                "shopping_mall_label",
1255                "farmers_union_label",
1256                "aquarium_label",
1257                "theatre_label",
1258                "selected_fodder_set",
1259                "selected_horse_medicine",
1260                "bought_from_farmers_union",
1261                "bought_from_flower_shop",
1262                "animal_sold",
1263                "finish_animal_ch2",
1264            ],
1265            "item_rock_left": [
1266                "next_to_rock_right",
1267                "rock_cleared",
1268            ],
1269            "item_target_potato_below": [
1270                "next_to_target_potato_up",
1271                "target_potato_harvested",
1272            ],
1273            "item_center_spotato_above": [
1274                "next_to_spotato_down",
1275                "center_spotato_watered",
1276            ],
1277            "item_center_watermelon_above": [
1278                "next_to_center_watermelon_down",
1279                "center_watermelon_watered",
1280            ],
1281            "npc_kate_left": [
1282                "next_to_kate_right",
1283            ],
1284            "npc_kate_right": [
1285                "next_to_kate_left",
1286            ],
1287            "npc_kate_below": [
1288                "next_to_kate_up",
1289            ],
1290            "item_weed_left": [
1291                "next_to_weed_right",
1292                "weed_removed",
1293            ],
1294            "item_cherry_left": [
1295                "next_to_cherry_right",
1296                "cherry_picked",
1297            ],
1298            "item_chicken_silo_left1": [
1299                "next_to_chicken_silo_right1",
1300                "got_fodder_from_chicken_silo_right1",
1301            ],
1302            "item_chicken_silo_left2": [
1303                "next_to_chicken_silo_right2",
1304                "got_fodder_from_chicken_silo_right2",
1305            ],
1306            "item_chicken_silo_above": [
1307                "next_to_chicken_silo_down",
1308                "got_fodder_from_chicken_silo_down",
1309            ],
1310            "item_topmost_chicken_stall_block": [
1311                "filled_topmost_chicken_stall_block",
1312            ],
1313            "item_next_to_topmost_chicken_stall_block": [
1314                "next_to_topmost_chicken_stall_block",
1315            ],
1316            "item_next_to_hatching_box": [
1317                "next_to_hatching_box",
1318            ],
1319            "item_hatching_box": [
1320                "dropped_egg_into_hatching_box",
1321            ],
1322            "item_stairs": [
1323                "next_to_stairs_1",
1324                "next_to_stairs_2",
1325                "next_to_stairs_3",
1326            ],
1327            "item_fodder_set_below": [
1328                "next_to_fodder_set_up",
1329            ],
1330            "item_horse_medicine_below": [
1331                "next_to_horse_medicine_up",
1332            ],
1333            "item_fodder_set": [
1334                "picked_fodder_set",
1335            ],
1336            "item_horse_medicine": [
1337                "picked_horse_medicine",
1338            ],
1339            "item_storage_sign_below": [
1340                "next_to_storage_sign_up",
1341            ],
1342            "item_storage_sign_left": [
1343                "next_to_storage_sign_right",
1344            ],
1345            "item_storage_sign_right": [
1346                "next_to_storage_sign_left",
1347            ],
1348            "item_morning_market_sign_left": [
1349                "next_to_morning_market_sign_right",
1350            ],
1351            "npc_kirk_above": [
1352                "next_to_kirk_down",
1353            ],
1354            "npc_kirk_mainland_right": [
1355                "next_to_kirk_mainland_left",
1356            ],
1357            "npc_kirk_mainland_below": [
1358                "next_to_kirk_mainland_up",
1359            ],
1360            "npc_joe_left": [
1361                "next_to_joe_right",
1362            ],
1363            "dialogue_box_upper_border": [
1364                "speaking_to_kirk_village",
1365                "speaking_to_joe",
1366                "speaking_to_lukia",
1367                "speaking_to_lucus",
1368                "speaking_to_lyla",
1369            ],
1370            "item_secret_garden_sign_above": [
1371                "next_to_secret_garden_sign_down",
1372            ],
1373            "item_secret_garden_sign_right": [
1374                "next_to_secret_garden_sign_left",
1375            ],
1376            "item_turnip_seeds_above": [
1377                "next_to_turnip_seeds_down",
1378            ],
1379            "item_turnip_seeds_below": [
1380                "next_to_turnip_seeds_up",
1381            ],
1382            "item_potato_seeds_above": [
1383                "next_to_potato_seeds_down",
1384            ],
1385            "item_potato_seeds_below": [
1386                "next_to_potato_seeds_up",
1387            ],
1388            "npc_lukia_right": [
1389                "next_to_lukia_left",
1390            ],
1391            "npc_lucus_above": [
1392                "next_to_lucus_down",
1393            ],
1394            "npc_lucus_left": [
1395                "next_to_lucus_right",
1396            ],
1397            "npc_lucus_right": [
1398                "next_to_lucus_left",
1399            ],
1400            "npc_lyla_right": [
1401                "next_to_lyla_left",
1402            ],
1403            "outside_chicken_coop": [
1404                "outside_chicken_coop_left",
1405                "outside_chicken_coop_right",
1406                "outside_chicken_coop_up",
1407            ],
1408            "item_flower_vase_empty_1": [
1409                "bought_flower_vase_1",
1410            ],
1411            "item_flower_vase_empty_2": [
1412                "bought_flower_vase_2",
1413            ],
1414            "item_flower_vase_above": [
1415                "next_to_vase_down",
1416            ],
1417            "item_flower_vase_below": [
1418                "next_to_vase_up",
1419            ],
1420            "item_center_eggplant_above": [
1421                "next_to_eggplant_down",
1422                "center_eggplant_harvested_down",
1423            ],
1424            "item_center_eggplant_left": [
1425                "next_to_eggplant_right",
1426                "center_eggplant_harvested_right",
1427            ],
1428            "menu_box": [
1429                "choose_may",
1430            ],
1431            "player_top_left": [
1432                "display_player_status",
1433            ],
1434            "item_berry_above": [
1435                "next_to_berry_down",
1436                "berry_picked_above",
1437            ],
1438            "sell_animal_section_1": [
1439                "selling_animal_1",
1440            ],
1441            "sell_animal_section_2": [
1442                "selling_animal_2",
1443            ],
1444            "item_sell_chicken_below": [
1445                "next_to_sell_chicken_up",
1446            ],
1447            "item_sell_chicken_above": [
1448                "next_to_sell_chicken_down",
1449            ],
1450            "item_center_turnip_below": [
1451                "next_to_center_turnip_up",
1452                "center_turnip_harvested",
1453            ],
1454            "item_bookshelf_below": [
1455                "next_to_bookshelf_up",
1456            ],
1457            "item_horse_saddle_empty_1": [
1458                "bought_horse_saddle_1",
1459            ],
1460            "item_horse_saddle_empty_2": [
1461                "bought_horse_saddle_2",
1462            ],
1463            "item_horse_saddle_above": [
1464                "next_to_horse_saddle_down",
1465            ],
1466            "item_horse_saddle_below": [
1467                "next_to_horse_saddle_up",
1468            ],
1469            "item_meal_set_empty_1": [
1470                "bought_meal_set_1",
1471            ],
1472            "item_meal_set_empty_2": [
1473                "bought_meal_set_2",
1474            ],
1475            "item_coffee_above": [
1476                "next_to_coffee_down",
1477            ],
1478            "item_coffee_below": [
1479                "next_to_coffee_up",
1480            ],
1481            "top_entrance": [
1482                "village_entrance",
1483            ],
1484            "entrance": [
1485                "village_ferry_entrance",
1486                "farm_entrance",
1487                "grassland_entrance",
1488                "forest_entrance",
1489                "cliff_entrance",
1490                "mountain_entrance",
1491                "shopping_mall_entrance",
1492                "farmers_union_entrance",
1493                "aquarium_entrance",
1494                "theatre_entrance",
1495                "hot_spring_entrance",
1496                "shopping_mall_second_floor",
1497            ],
1498            "item_tea_above": [
1499                "next_to_tea_down",
1500            ],
1501            "item_tea_below": [
1502                "next_to_tea_up",
1503            ],
1504            "item_asparagus_seeds_above": [
1505                "next_to_asparagus_seeds_down",
1506            ],
1507            "item_asparagus_seeds_below": [
1508                "next_to_asparagus_seeds_up",
1509            ],
1510            "item_right_cow_stall_block": [
1511                "filled_right_cow_stall_block",
1512            ],
1513            "item_right_cow_stall_block_below": [
1514                "next_to_right_cow_stall_block_up",
1515            ],
1516            "item_right_cow_stall_block_left": [
1517                "next_to_right_cow_stall_block_right",
1518            ],
1519            "item_cow_stall_block_2": [
1520                "filled_cow_stall_block_right",
1521            ],
1522            "item_ferry_sign_above": [
1523                "next_to_ferry_sign_down",
1524            ],
1525            "item_ferry_sign_left": [
1526                "next_to_ferry_sign_right",
1527            ],
1528            "item_fireplace_below": [
1529                "next_to_fireplace_up",
1530            ],
1531            "outside_hot_spring": [
1532                "outside_hot_spring_left",
1533                "outside_hot_spring_right",
1534                "outside_hot_spring_up",
1535            ],
1536        }
1537        super().__init__(
1538            pyboy,
1539            variant="harvest_moon_3",
1540            parameters=parameters,
1541            override_regions=override_regions,
1542            override_multi_target_regions=override_multi_target_regions,
1543            override_multi_targets=override_multi_targets,
1544        )

Initializes the HarvestMoonStateParser.

Arguments:
  • pyboy (PyBoy): The PyBoy emulator instance.
  • parameters (dict): Configuration parameters for the emulator.
  • additional_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional named screen regions to include.
  • additional_multi_target_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional multi-target named screen regions to include.
  • override_multi_targets (Dict[str, List[str]]): Dictionary mapping region names to lists of additional target names for multi-target regions.
DIALOGUE_TYPES = ['normal_dialogue', 'mainland_dialogue']
def dialogue_box_open(self, current_screen: numpy.ndarray) -> bool:
1546    def dialogue_box_open(self, current_screen: np.ndarray) -> bool:
1547        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
1548        if self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
1549            self.DIALOGUE_TYPES, captured
1550        ):
1551            return True
1552        return False
def dialogue_box_empty(self, current_screen: numpy.ndarray) -> bool:
1554    def dialogue_box_empty(self, current_screen: np.ndarray) -> bool:
1555        box = self.capture_named_region(
1556            current_frame=current_screen, name="dialogue_box_bottom"
1557        )
1558        perc_lt_255 = np.mean(box < 255)
1559        if perc_lt_255 < 0.082:  # Empirical threshold
1560            return True
1561        return False
def is_in_menu(self, current_screen: numpy.ndarray) -> bool:
1563    def is_in_menu(self, current_screen: np.ndarray) -> bool:
1564        return self.named_region_matches_target(current_screen, "menu_top_right")
def is_in_dialogue(self, current_screen: numpy.ndarray) -> bool:
1566    def is_in_dialogue(self, current_screen: np.ndarray) -> bool:
1567        captured = self.capture_named_region(current_screen, "dialogue_bottom_right")
1568        if self.named_screen_regions["dialogue_bottom_right"].matches_any_multi_target(
1569            self.DIALOGUE_TYPES, captured
1570        ):
1571            return True
1572        return False
def get_agent_state( self, current_screen: numpy.ndarray) -> AgentState:
1574    def get_agent_state(self, current_screen: np.ndarray) -> AgentState:
1575        if self.is_in_menu(current_screen):
1576            return AgentState.IN_MENU
1577        if self.is_in_dialogue(current_screen):
1578            return AgentState.IN_DIALOGUE
1579        return AgentState.FREE_ROAM