gameboy_worlds.emulation.deja_vu.parsers

DejaVu I & II: The Casebooks of Ace Harding game state parser implementations.

Deja Vu is a detective mystery game focused on investigation and puzzle-solving.

This parser provides visual-based state detection for:

  1. FREE_ROAM: Walking around investigation areas and locations
  2. IN_DIALOGUE: Interacting with NPCs, getting clues, and story progression
  3. IN_MENU: Accessing case notes, evidence view, location map, or other menus

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"""
  2DejaVu I & II: The Casebooks of Ace Harding game state parser implementations.
  3
  4Deja Vu is a detective mystery game focused on investigation and puzzle-solving.
  5
  6This parser provides visual-based state detection for:
  71. FREE_ROAM: Walking around investigation areas and locations
  82. IN_DIALOGUE: Interacting with NPCs, getting clues, and story progression
  93. IN_MENU: Accessing case notes, evidence view, location map, or other menus
 10
 11CORE 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.
 12This is to ensure that we don't double effort, any capability added to a parser will always be valid for that game variant.
 13If this principle is followed, any state tracker can always use the STRONGEST (lowest level) parser for a given variant without concern for missing functionality.
 14"""
 15
 16from gameboy_worlds.emulation.parser import NamedScreenRegion
 17from gameboy_worlds.utils import (
 18    log_warn,
 19    log_info,
 20    log_error,
 21    load_parameters,
 22    verify_parameters,
 23)
 24from gameboy_worlds.emulation.parser import StateParser
 25
 26from typing import Set, List, Type, Dict, Optional, Tuple
 27import os
 28from abc import ABC, abstractmethod
 29from enum import Enum
 30
 31from pyboy import PyBoy
 32
 33import numpy as np
 34from bidict import bidict
 35
 36
 37class AgentState(Enum):
 38    """
 39    0. FREE_ROAM: The agent is freely roaming the game world.
 40    1. IN_DIALOGUE: The agent is currently in a dialogue state. (e.g. receiving clues, action feedback)
 41    2. IN_MENU: The agent is currently in a menu state. (e.g. looking at items)
 42    """
 43
 44    FREE_ROAM = 0
 45    IN_DIALOGUE = 1
 46    IN_MENU = 2
 47
 48
 49def _get_proper_regions(
 50    override_regions: List[Tuple[str, int, int, int, int]],
 51    base_regions: List[Tuple[str, int, int, int, int]],
 52) -> List[Tuple[str, int, int, int, int]]:
 53    """Merges base regions with override regions, giving precedence to override regions."""
 54    if len(override_regions) == 0:
 55        return base_regions
 56    proper_regions = override_regions.copy()
 57    override_names = [region[0] for region in override_regions]
 58    for region in base_regions:
 59        if region[0] not in override_names:
 60            proper_regions.append(region)
 61    return proper_regions
 62
 63
 64class DejaVuStateParser(StateParser, ABC):
 65    """
 66    Base class for DejaVu game state parsers. Uses visual screen regions to parse game state.
 67    Defines common named screen regions and methods for determining game states such as being in battle, menu, or dialogue.
 68
 69    Can be used to determine the exact AgentState
 70    """
 71
 72    COMMON_REGIONS = [
 73        ("dialogue_top_left_hook", 0, 73, 10, 6),
 74        ("menu_bottom_line", 0, 143, 160, 1),
 75        ("selected_outfit_button", 120, 17, 14, 15),
 76        # map locations
 77        ("pointed_at_11_on_map", 120, 80, 8, 8),
 78        ("pointed_at_13_on_map", 136, 80, 8, 8),
 79        ("pointed_at_21_on_map", 120, 72, 8, 8),
 80        ("pointed_at_24_on_map", 144, 72, 8, 8),
 81        ("pointed_at_25_on_map", 152, 72, 8, 8),
 82        ("pointed_at_35_on_map", 152, 64, 8, 8),
 83        ("pointed_at_41_on_map", 120, 56, 8, 8),
 84        ("pointed_at_45_on_map", 152, 56, 8, 8),
 85        ("pointed_at_52_on_map", 128, 48, 8, 8),
 86        ("pointed_at_54_on_map", 144, 48, 8, 8),
 87        # action in menu
 88        ("selected_watch_action_in_menu", 8, 33, 16, 5),
 89        ("selected_use_action_in_menu", 24, 33, 16, 5),
 90        ("selected_take_action_in_menu", 40, 33, 16, 5),
 91        ("selected_open_action_in_menu", 64, 33, 16, 5),
 92        ("selected_close_action_in_menu", 80, 33, 16, 5),
 93        ("selected_talk_action_in_menu", 104, 33, 16, 5),
 94        ("selected_hit_action_in_menu", 120, 33, 16, 5),
 95        ("selected_throw_action_in_menu", 136, 33, 16, 5),
 96        # action in normal
 97        ("selected_watch_action_in_normal", 8, 121, 16, 5),
 98        ("selected_use_action_in_normal", 24, 121, 16, 5),
 99        ("selected_take_action_in_normal", 40, 121, 16, 5),
100        ("selected_open_action_in_normal", 64, 121, 16, 5),
101        ("selected_close_action_in_normal", 80, 121, 16, 5),
102        ("selected_talk_action_in_normal", 104, 121, 16, 5),
103        ("selected_hit_action_in_normal", 120, 121, 16, 5),
104        ("selected_throw_action_in_normal", 136, 121, 16, 5),
105    ]
106    """ 
107    List of common named screen regions for Deja Vu game.
108    
109    Deja Vu uses a primarily text/menu-driven interface. These regions help identify:
110    - dialogue_top_left_hook: A hook that appears in the top left after certain events, can be used to determine if certain game mechanics are available.
111    - menu_bottom_line: A line that appears at the bottom of the screen when any menu is open, can be used to prevent agent interaction with the UI frame of the emulator.
112    - selected_outfit_button: The area where the "Selected Outfit" button appears when the outfit menu is open, can be used to determine if the outfit menu is open.
113    - pointed_at_{ij}_on_map: The agent is currently pointing at location (i,j) on the map. (the map is divided into a 5x5 grid of locations, with (1,1) being the bottom left and (5,5) being the top right)
114    - selected_{action}_action_in_menu: The specified action is currently selected in the action bar while a menu is open.
115    - selected_{action}_action_in_normal: The specified action is currently selected in the action bar while no menu is open.
116    """
117
118    COMMON_MULTI_TARGET_REGIONS = [
119        ("dialogue_box_area", 0, 74, 160, 55),
120        ("menu_box_area", 0, 70, 160, 70),
121        # ("action_bar_in_normal", 0, 114, 160, 14),
122        # ("action_bar_in_menu", 0, 26, 160, 14),
123        ("no_action", 0, 114, 160, 14),
124        ("menu_title_area", 23, 56, 96, 17),
125        ("game_screen_area", 0, 0, 112, 112),
126        # ("map_area", 120, 48, 40, 40),
127    ]
128    """
129    List of common multi-target named screen regions for Deja Vu games.
130
131    Deja Vu has certain regions that can contain multiple important visual cues.
132    - dialogue_box_area: The area where dialogue text appears. Can contain multiple targets such as clues
133    - menu_box_area: The area where menu options appear. Can contain multiple targets such as items or actions.
134    - no_action: The area where no action is currently selected in the action bar.
135    - menu_title_area: The area where the menu title appears.
136    - game_screen_area: The entire game screen area.
137    (- map_area: The area where the map appears when the map is open.)
138    """
139
140    COMMON_MULTI_TARGETS = {
141        "dialogue_box_area": [
142            "_",
143            "nothing_usual",
144            "opened_door",
145            "closed_door",
146        ],
147        "no_action": [
148            "_",
149            "no_action_selected",
150        ],
151        "menu_title_area": [
152            "_",
153            "address_menu",
154            "goods_menu",
155        ],
156        "game_screen_area": [
157            "_",
158            "socko_on_screen",
159        ],
160        # "map_area": [
161        #     "a_default_target",
162        #     "pointed_at_1_3",
163        #     "pointed_at_2_1",
164        # ],
165    }
166    """
167    Common multi-targets for Deja Vu game regions.
168    - dialogue_box_area:
169        - nothing_usual: Point at useless area.
170        - opened_door: Open the door in front of you.
171    - no_action:
172        - no_action_selected: No action is currently selected in the action bar.
173    - menu_title_area:
174        - address_menu: The address menu is currently open.
175        - goods_menu: The goods menu is currently open.
176    - game_screen_area:
177        - socko_on_screen: The character "SOCKO" is currently visible on the screen.
178    """
179
180    def __init__(
181        self,
182        variant: str,
183        pyboy: PyBoy,
184        parameters: dict,
185        additional_named_screen_region_details: List[Tuple[str, int, int, int, int]] = [],
186        additional_multi_target_named_screen_region_details: List[Tuple[str, int, int, int, int]] = [],
187        override_multi_targets: Dict[str, List[str]] = {},
188    ):
189        """
190        Initializes the DejaVuStateParser.
191        Args:
192            variant (str): The variant of the Deja Vu game.
193            pyboy (PyBoy): The PyBoy emulator instance.
194            parameters (dict): Configuration parameters for the emulator.
195            additional_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional named screen regions to include.
196            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.
197            override_multi_targets (Dict[str, List[str]]): Dictionary mapping region names to lists of target names for multi-target regions.
198        """
199        verify_parameters(parameters)
200        regions = _get_proper_regions(
201            override_regions=additional_named_screen_region_details,
202            base_regions=self.COMMON_REGIONS,
203        )
204        self.variant = variant
205        if f"{variant}_rom_data_path" not in parameters:
206            log_error(
207                f"ROM data path not found for variant: {variant}. Add {variant}_rom_data_path to the config files. See configs/deja_vu_vars.yaml for an example",
208                parameters,
209            )
210        self.rom_data_path = parameters[f"{variant}_rom_data_path"]
211        """ Path to the ROM data directory for the specific Deja Vu variant."""
212        captures_dir = self.rom_data_path + "/captures/"
213        named_screen_regions = []
214        for region_name, x, y, w, h in regions:
215            region = NamedScreenRegion(
216                region_name,
217                x,
218                y,
219                w,
220                h,
221                parameters=parameters,
222                target_path=os.path.join(captures_dir, region_name),
223            )
224            named_screen_regions.append(region)
225        multi_target_regions = _get_proper_regions(
226            override_regions=additional_multi_target_named_screen_region_details,
227            base_regions=self.COMMON_MULTI_TARGET_REGIONS,
228        )
229        multi_target_region_names = [region[0] for region in multi_target_regions]
230        multi_targets = self.COMMON_MULTI_TARGETS.copy()
231        for key in override_multi_targets:
232            if key in multi_targets:
233                multi_targets[key].extend(override_multi_targets[key])
234            else:
235                multi_targets[key] = override_multi_targets[key]
236        multi_target_provided_region_names = list(multi_targets.keys())
237        if not set(multi_target_provided_region_names).issubset(
238            set(multi_target_region_names)
239        ):
240            log_error(
241                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}",
242                parameters,
243            )
244        for region_name, x, y, w, h in multi_target_regions:
245            region_target_paths = {}
246            subdir = captures_dir + f"/{region_name}/"
247            for target_name in multi_targets.get(region_name, []):
248                region_target_paths[target_name] = os.path.join(subdir, target_name)
249            region = NamedScreenRegion(
250                region_name,
251                x,
252                y,
253                w,
254                h,
255                parameters=parameters,
256                multi_target_paths=region_target_paths,
257            )
258            named_screen_regions.append(region)
259        super().__init__(pyboy, parameters, named_screen_regions)
260
261    def is_in_menu(self, current_screen: np.ndarray) -> bool:
262        """
263        Determines if any form of menu is currently open (Case Notes, Evidence, Location, etc).
264
265        Args:
266            current_screen (np.ndarray): The current screen frame from the emulator.
267            trust_previous (bool): If True, trusts that checks for other states have been done.
268
269        Returns:
270            bool: True if a menu is open, False otherwise.
271        """
272        return self.named_region_matches_target(current_screen, "menu_bottom_line")
273
274    def is_in_dialogue(self, current_screen: np.ndarray) -> bool:
275        """
276        Determines if the player is currently in a dialogue state.
277        Includes talking to NPCs, receiving clues, story narration, etc.
278
279        Args:
280            current_screen (np.ndarray): The current screen frame from the emulator.
281            trust_previous (bool): If True, trusts that checks for menu state have been done.
282
283        Returns:
284            bool: True if in dialogue, False otherwise.
285        """
286        if self.is_in_menu(current_screen):
287            return False
288        return self.named_region_matches_target(
289            current_screen, "dialogue_top_left_hook"
290        )
291
292    def get_agent_state(self, current_screen: np.ndarray) -> AgentState:
293        """
294        Determines the current agent state based on the screen.
295
296        Uses trust_previous to optimize checks.
297
298        Args:
299            current_screen (np.ndarray): The current screen frame from the emulator.
300
301        Returns:
302            AgentState: The current agent state (FREE_ROAM, IN_DIALOGUE, or IN_MENU).
303        """
304        if self.is_in_menu(current_screen):
305            return AgentState.IN_MENU
306        elif self.is_in_dialogue(current_screen):
307            return AgentState.IN_DIALOGUE
308        else:
309            return AgentState.FREE_ROAM
310
311
312class DejaVu1StateParser(DejaVuStateParser):
313    """Game state parser for Deja Vu I: The Casebooks of Ace Harding."""
314
315    def __init__(self, pyboy, parameters):
316        override_regions = [
317            ("selected_coat_item", 0, 79, 160, 8),
318            ("selected_wallet_item", 0, 120, 160, 8),
319            ("selected_coin_item", 0, 95, 160, 8),
320            ("using_coin_item", 0, 95, 160, 8),
321            ("using_key3_item", 0, 88, 160, 8),
322            ("using_key2_item", 0, 128, 160, 8),
323            ("selected_westend_address", 0, 88, 160, 8),
324            ("using_bullet_item", 0, 88, 160, 8),
325            ("using_note3_item", 0, 88, 160, 8),
326            ("using_key4_item", 0, 128, 160, 8),
327        ]
328        override_multi_target_regions = []
329        override_multi_targets = {
330            "dialogue_box_area": [
331                "took_coat",
332                "took_gun",
333                "opened_pocket",
334                "opened_wallet",
335                "closed_pocket",
336                "closed_wallet",
337                "checked_coat",
338                "checked_gun",
339                "opened_spigot",
340                "hit_bottle",
341                "entered_cellar",
342                "entered_connecting_room",
343                "made_bet",
344                "entered_empty_room",
345                "unlocked_front_door",
346                "met_mugger",
347                "hit_mugger",
348                "unlocked_car_door",
349                "opened_dashbrd",
350                "closed_dashbrd",
351                "checked_note2",
352                "checked_map",
353                "checked_snapshot",
354                "in_front_of_newsstand",
355                "entered_taxi",
356                "talked_to_taxi_driver",
357                "went_to_westend",
358                "paid_taxi",
359                "outside_apartment",
360                "entered_sherman",
361                "stood_in_front_office",
362                "entered_westend",
363                "opened_elevator_door",
364                "entered_elevator",
365                "closed_elevator_door",
366                "checked_photo",
367                "opened_desk",
368                "unlocked_office_door",
369                "opened_westend_door",
370                "opened_sherman_door",
371                "made_medicine",
372                "taken_medicine",
373                "opened_diary",
374                "checked_dead_man",
375                "opened_cabinet",
376                "exited_grimy_office",
377                "opened_wall_safe",
378                "opened_car_trunk",
379            ],
380            "menu_title_area": [
381                "coat_pocket_menu",
382                "wallet_menu",
383            ],
384            "game_screen_area": [
385                "opened_cellar_door",
386                "shot_door",
387                "shot_lock",
388            ],
389            "no_action": [
390                "in_cellar",
391                "in_empty_restaurant",
392                "on_peoria_st",
393                "in_sherman_lobby",
394                "in_westend_lobby",
395                "in_grimy_office",
396            ],
397        }
398
399        super().__init__(
400            variant="deja_vu_1",
401            pyboy=pyboy,
402            parameters=parameters,
403            additional_named_screen_region_details=override_regions,
404            additional_multi_target_named_screen_region_details=override_multi_target_regions,
405            override_multi_targets=override_multi_targets,
406        )
407
408    def __repr__(self):
409        return f"<DejaVuParser(variant={self.variant})>"
410
411
412class DejaVu2StateParser(DejaVuStateParser):
413    """Game state parser for Deja Vu II: The Casebooks of Ace Harding."""
414
415    def __init__(self, pyboy, parameters):
416        override_regions = [
417            ("selected_gum_item", 0, 79, 160, 8),
418            ("selected_pants_item", 0, 112, 160, 8),
419            ("selected_trench_coat_item", 0, 88, 160, 8),
420            ("selected_wallet1_item", 0, 96, 160, 8),
421            ("selected_newsclip1_item", 0, 79, 160, 8),
422            ("selected_license1_item", 0, 79, 160, 8),
423            ("using_cash_item", 0, 79, 160, 8),
424            ("using_key1_item", 0, 104, 160, 8),
425            ("using_key2_item", 0, 79, 160, 8),
426            ("using_knife_item", 0, 128, 160, 8),
427            ("using_key4_item", 0, 104, 160, 8),
428            ("using_flashlight_item", 0, 88, 160, 8),
429            ("using_nametag2_item", 0, 88, 160, 8),
430        ]
431        override_multi_target_regions = []
432        override_multi_targets = {
433            "dialogue_box_area": [
434                "opened_trench_coat_pocket",
435                "taken_gum",
436                "opened_pants_pocket",
437                "taken_pants",
438                "closed_pants_pocket",
439                "put_on_trench_coat",
440                "put_on_pants",
441                "opened_wallet1",
442                "taken_newsclip1",
443                "taken_license1",
444                "closed_wallet1",
445                "opened_cold_tap",
446                "closed_cold_tap",
447                "checked_newsclip1",
448                "taken_ring1",
449                "opened_room_door",
450                "closed_room_door",
451                "entered_hallway",
452                "selected_2_chips",
453                "bought_2_chips",
454                "returned_cashier",
455                "selected_50_chips",
456                "cashed_out",
457                "opened_lobby_door",
458                "exited_casino",
459                "talked_in_train_station",
460                "visited_counter",
461                "taken_pamphlet",
462                "timetable",
463                "entered_platform",
464                "entered_train",
465                "bought_ticket",
466                "checked_girl",
467                "checked_sign",
468                "chatted_seller",
469                "bought_newspaper",
470                "taken_newsclip4",
471                "entered_chicago_taxi",
472                "chatted_taxi_driver",
473                "unlocked_middle_door",
474                "entered_middle_room",
475                "loaded_gun",
476                "opened_lock",
477                "hit_board",
478                "opened_telephone",
479                "opened_box",
480                "opened_pocket_knife",
481                "opened_door_by_knife",
482                "put_on_flashlight",
483                "entered_joe_place",
484                "opened_joe_place_door",
485                "opened_slot_lock",
486                "turned_off_flashlight",
487                "got_location_from_card",
488                "opened_bag_with_knife",
489                "asked_about_nametage2",
490            ],
491            "menu_title_area": [
492                "trench_coat_pocket_menu", 
493                "wallet1_menu",
494                "vacuum_menu",
495            ],
496            "game_screen_area": [
497                "on_track6",
498            ],
499            "no_action": [
500                "in_lobby",
501            ],
502        }
503
504        super().__init__(
505            variant="deja_vu_2",
506            pyboy=pyboy,
507            parameters=parameters,
508            additional_named_screen_region_details=override_regions,
509            additional_multi_target_named_screen_region_details=override_multi_target_regions,
510            override_multi_targets=override_multi_targets,
511        )
512
513    def __repr__(self):
514        return f"<DejaVuParser(variant={self.variant})>"
class AgentState(enum.Enum):
38class AgentState(Enum):
39    """
40    0. FREE_ROAM: The agent is freely roaming the game world.
41    1. IN_DIALOGUE: The agent is currently in a dialogue state. (e.g. receiving clues, action feedback)
42    2. IN_MENU: The agent is currently in a menu state. (e.g. looking at items)
43    """
44
45    FREE_ROAM = 0
46    IN_DIALOGUE = 1
47    IN_MENU = 2
  1. FREE_ROAM: The agent is freely roaming the game world.
  2. IN_DIALOGUE: The agent is currently in a dialogue state. (e.g. receiving clues, action feedback)
  3. IN_MENU: The agent is currently in a menu state. (e.g. looking at items)
FREE_ROAM = <AgentState.FREE_ROAM: 0>
IN_DIALOGUE = <AgentState.IN_DIALOGUE: 1>
IN_MENU = <AgentState.IN_MENU: 2>
class DejaVuStateParser(gameboy_worlds.emulation.parser.StateParser, abc.ABC):
 65class DejaVuStateParser(StateParser, ABC):
 66    """
 67    Base class for DejaVu game state parsers. Uses visual screen regions to parse game state.
 68    Defines common named screen regions and methods for determining game states such as being in battle, menu, or dialogue.
 69
 70    Can be used to determine the exact AgentState
 71    """
 72
 73    COMMON_REGIONS = [
 74        ("dialogue_top_left_hook", 0, 73, 10, 6),
 75        ("menu_bottom_line", 0, 143, 160, 1),
 76        ("selected_outfit_button", 120, 17, 14, 15),
 77        # map locations
 78        ("pointed_at_11_on_map", 120, 80, 8, 8),
 79        ("pointed_at_13_on_map", 136, 80, 8, 8),
 80        ("pointed_at_21_on_map", 120, 72, 8, 8),
 81        ("pointed_at_24_on_map", 144, 72, 8, 8),
 82        ("pointed_at_25_on_map", 152, 72, 8, 8),
 83        ("pointed_at_35_on_map", 152, 64, 8, 8),
 84        ("pointed_at_41_on_map", 120, 56, 8, 8),
 85        ("pointed_at_45_on_map", 152, 56, 8, 8),
 86        ("pointed_at_52_on_map", 128, 48, 8, 8),
 87        ("pointed_at_54_on_map", 144, 48, 8, 8),
 88        # action in menu
 89        ("selected_watch_action_in_menu", 8, 33, 16, 5),
 90        ("selected_use_action_in_menu", 24, 33, 16, 5),
 91        ("selected_take_action_in_menu", 40, 33, 16, 5),
 92        ("selected_open_action_in_menu", 64, 33, 16, 5),
 93        ("selected_close_action_in_menu", 80, 33, 16, 5),
 94        ("selected_talk_action_in_menu", 104, 33, 16, 5),
 95        ("selected_hit_action_in_menu", 120, 33, 16, 5),
 96        ("selected_throw_action_in_menu", 136, 33, 16, 5),
 97        # action in normal
 98        ("selected_watch_action_in_normal", 8, 121, 16, 5),
 99        ("selected_use_action_in_normal", 24, 121, 16, 5),
100        ("selected_take_action_in_normal", 40, 121, 16, 5),
101        ("selected_open_action_in_normal", 64, 121, 16, 5),
102        ("selected_close_action_in_normal", 80, 121, 16, 5),
103        ("selected_talk_action_in_normal", 104, 121, 16, 5),
104        ("selected_hit_action_in_normal", 120, 121, 16, 5),
105        ("selected_throw_action_in_normal", 136, 121, 16, 5),
106    ]
107    """ 
108    List of common named screen regions for Deja Vu game.
109    
110    Deja Vu uses a primarily text/menu-driven interface. These regions help identify:
111    - dialogue_top_left_hook: A hook that appears in the top left after certain events, can be used to determine if certain game mechanics are available.
112    - menu_bottom_line: A line that appears at the bottom of the screen when any menu is open, can be used to prevent agent interaction with the UI frame of the emulator.
113    - selected_outfit_button: The area where the "Selected Outfit" button appears when the outfit menu is open, can be used to determine if the outfit menu is open.
114    - pointed_at_{ij}_on_map: The agent is currently pointing at location (i,j) on the map. (the map is divided into a 5x5 grid of locations, with (1,1) being the bottom left and (5,5) being the top right)
115    - selected_{action}_action_in_menu: The specified action is currently selected in the action bar while a menu is open.
116    - selected_{action}_action_in_normal: The specified action is currently selected in the action bar while no menu is open.
117    """
118
119    COMMON_MULTI_TARGET_REGIONS = [
120        ("dialogue_box_area", 0, 74, 160, 55),
121        ("menu_box_area", 0, 70, 160, 70),
122        # ("action_bar_in_normal", 0, 114, 160, 14),
123        # ("action_bar_in_menu", 0, 26, 160, 14),
124        ("no_action", 0, 114, 160, 14),
125        ("menu_title_area", 23, 56, 96, 17),
126        ("game_screen_area", 0, 0, 112, 112),
127        # ("map_area", 120, 48, 40, 40),
128    ]
129    """
130    List of common multi-target named screen regions for Deja Vu games.
131
132    Deja Vu has certain regions that can contain multiple important visual cues.
133    - dialogue_box_area: The area where dialogue text appears. Can contain multiple targets such as clues
134    - menu_box_area: The area where menu options appear. Can contain multiple targets such as items or actions.
135    - no_action: The area where no action is currently selected in the action bar.
136    - menu_title_area: The area where the menu title appears.
137    - game_screen_area: The entire game screen area.
138    (- map_area: The area where the map appears when the map is open.)
139    """
140
141    COMMON_MULTI_TARGETS = {
142        "dialogue_box_area": [
143            "_",
144            "nothing_usual",
145            "opened_door",
146            "closed_door",
147        ],
148        "no_action": [
149            "_",
150            "no_action_selected",
151        ],
152        "menu_title_area": [
153            "_",
154            "address_menu",
155            "goods_menu",
156        ],
157        "game_screen_area": [
158            "_",
159            "socko_on_screen",
160        ],
161        # "map_area": [
162        #     "a_default_target",
163        #     "pointed_at_1_3",
164        #     "pointed_at_2_1",
165        # ],
166    }
167    """
168    Common multi-targets for Deja Vu game regions.
169    - dialogue_box_area:
170        - nothing_usual: Point at useless area.
171        - opened_door: Open the door in front of you.
172    - no_action:
173        - no_action_selected: No action is currently selected in the action bar.
174    - menu_title_area:
175        - address_menu: The address menu is currently open.
176        - goods_menu: The goods menu is currently open.
177    - game_screen_area:
178        - socko_on_screen: The character "SOCKO" is currently visible on the screen.
179    """
180
181    def __init__(
182        self,
183        variant: str,
184        pyboy: PyBoy,
185        parameters: dict,
186        additional_named_screen_region_details: List[Tuple[str, int, int, int, int]] = [],
187        additional_multi_target_named_screen_region_details: List[Tuple[str, int, int, int, int]] = [],
188        override_multi_targets: Dict[str, List[str]] = {},
189    ):
190        """
191        Initializes the DejaVuStateParser.
192        Args:
193            variant (str): The variant of the Deja Vu game.
194            pyboy (PyBoy): The PyBoy emulator instance.
195            parameters (dict): Configuration parameters for the emulator.
196            additional_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional named screen regions to include.
197            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.
198            override_multi_targets (Dict[str, List[str]]): Dictionary mapping region names to lists of target names for multi-target regions.
199        """
200        verify_parameters(parameters)
201        regions = _get_proper_regions(
202            override_regions=additional_named_screen_region_details,
203            base_regions=self.COMMON_REGIONS,
204        )
205        self.variant = variant
206        if f"{variant}_rom_data_path" not in parameters:
207            log_error(
208                f"ROM data path not found for variant: {variant}. Add {variant}_rom_data_path to the config files. See configs/deja_vu_vars.yaml for an example",
209                parameters,
210            )
211        self.rom_data_path = parameters[f"{variant}_rom_data_path"]
212        """ Path to the ROM data directory for the specific Deja Vu variant."""
213        captures_dir = self.rom_data_path + "/captures/"
214        named_screen_regions = []
215        for region_name, x, y, w, h in regions:
216            region = NamedScreenRegion(
217                region_name,
218                x,
219                y,
220                w,
221                h,
222                parameters=parameters,
223                target_path=os.path.join(captures_dir, region_name),
224            )
225            named_screen_regions.append(region)
226        multi_target_regions = _get_proper_regions(
227            override_regions=additional_multi_target_named_screen_region_details,
228            base_regions=self.COMMON_MULTI_TARGET_REGIONS,
229        )
230        multi_target_region_names = [region[0] for region in multi_target_regions]
231        multi_targets = self.COMMON_MULTI_TARGETS.copy()
232        for key in override_multi_targets:
233            if key in multi_targets:
234                multi_targets[key].extend(override_multi_targets[key])
235            else:
236                multi_targets[key] = override_multi_targets[key]
237        multi_target_provided_region_names = list(multi_targets.keys())
238        if not set(multi_target_provided_region_names).issubset(
239            set(multi_target_region_names)
240        ):
241            log_error(
242                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}",
243                parameters,
244            )
245        for region_name, x, y, w, h in multi_target_regions:
246            region_target_paths = {}
247            subdir = captures_dir + f"/{region_name}/"
248            for target_name in multi_targets.get(region_name, []):
249                region_target_paths[target_name] = os.path.join(subdir, target_name)
250            region = NamedScreenRegion(
251                region_name,
252                x,
253                y,
254                w,
255                h,
256                parameters=parameters,
257                multi_target_paths=region_target_paths,
258            )
259            named_screen_regions.append(region)
260        super().__init__(pyboy, parameters, named_screen_regions)
261
262    def is_in_menu(self, current_screen: np.ndarray) -> bool:
263        """
264        Determines if any form of menu is currently open (Case Notes, Evidence, Location, etc).
265
266        Args:
267            current_screen (np.ndarray): The current screen frame from the emulator.
268            trust_previous (bool): If True, trusts that checks for other states have been done.
269
270        Returns:
271            bool: True if a menu is open, False otherwise.
272        """
273        return self.named_region_matches_target(current_screen, "menu_bottom_line")
274
275    def is_in_dialogue(self, current_screen: np.ndarray) -> bool:
276        """
277        Determines if the player is currently in a dialogue state.
278        Includes talking to NPCs, receiving clues, story narration, etc.
279
280        Args:
281            current_screen (np.ndarray): The current screen frame from the emulator.
282            trust_previous (bool): If True, trusts that checks for menu state have been done.
283
284        Returns:
285            bool: True if in dialogue, False otherwise.
286        """
287        if self.is_in_menu(current_screen):
288            return False
289        return self.named_region_matches_target(
290            current_screen, "dialogue_top_left_hook"
291        )
292
293    def get_agent_state(self, current_screen: np.ndarray) -> AgentState:
294        """
295        Determines the current agent state based on the screen.
296
297        Uses trust_previous to optimize checks.
298
299        Args:
300            current_screen (np.ndarray): The current screen frame from the emulator.
301
302        Returns:
303            AgentState: The current agent state (FREE_ROAM, IN_DIALOGUE, or IN_MENU).
304        """
305        if self.is_in_menu(current_screen):
306            return AgentState.IN_MENU
307        elif self.is_in_dialogue(current_screen):
308            return AgentState.IN_DIALOGUE
309        else:
310            return AgentState.FREE_ROAM

Base class for DejaVu 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 battle, menu, or dialogue.

Can be used to determine the exact AgentState

DejaVuStateParser( 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]] = {})
181    def __init__(
182        self,
183        variant: str,
184        pyboy: PyBoy,
185        parameters: dict,
186        additional_named_screen_region_details: List[Tuple[str, int, int, int, int]] = [],
187        additional_multi_target_named_screen_region_details: List[Tuple[str, int, int, int, int]] = [],
188        override_multi_targets: Dict[str, List[str]] = {},
189    ):
190        """
191        Initializes the DejaVuStateParser.
192        Args:
193            variant (str): The variant of the Deja Vu game.
194            pyboy (PyBoy): The PyBoy emulator instance.
195            parameters (dict): Configuration parameters for the emulator.
196            additional_named_screen_region_details (List[Tuple[str, int, int, int, int]]): Parameters associated with additional named screen regions to include.
197            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.
198            override_multi_targets (Dict[str, List[str]]): Dictionary mapping region names to lists of target names for multi-target regions.
199        """
200        verify_parameters(parameters)
201        regions = _get_proper_regions(
202            override_regions=additional_named_screen_region_details,
203            base_regions=self.COMMON_REGIONS,
204        )
205        self.variant = variant
206        if f"{variant}_rom_data_path" not in parameters:
207            log_error(
208                f"ROM data path not found for variant: {variant}. Add {variant}_rom_data_path to the config files. See configs/deja_vu_vars.yaml for an example",
209                parameters,
210            )
211        self.rom_data_path = parameters[f"{variant}_rom_data_path"]
212        """ Path to the ROM data directory for the specific Deja Vu variant."""
213        captures_dir = self.rom_data_path + "/captures/"
214        named_screen_regions = []
215        for region_name, x, y, w, h in regions:
216            region = NamedScreenRegion(
217                region_name,
218                x,
219                y,
220                w,
221                h,
222                parameters=parameters,
223                target_path=os.path.join(captures_dir, region_name),
224            )
225            named_screen_regions.append(region)
226        multi_target_regions = _get_proper_regions(
227            override_regions=additional_multi_target_named_screen_region_details,
228            base_regions=self.COMMON_MULTI_TARGET_REGIONS,
229        )
230        multi_target_region_names = [region[0] for region in multi_target_regions]
231        multi_targets = self.COMMON_MULTI_TARGETS.copy()
232        for key in override_multi_targets:
233            if key in multi_targets:
234                multi_targets[key].extend(override_multi_targets[key])
235            else:
236                multi_targets[key] = override_multi_targets[key]
237        multi_target_provided_region_names = list(multi_targets.keys())
238        if not set(multi_target_provided_region_names).issubset(
239            set(multi_target_region_names)
240        ):
241            log_error(
242                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}",
243                parameters,
244            )
245        for region_name, x, y, w, h in multi_target_regions:
246            region_target_paths = {}
247            subdir = captures_dir + f"/{region_name}/"
248            for target_name in multi_targets.get(region_name, []):
249                region_target_paths[target_name] = os.path.join(subdir, target_name)
250            region = NamedScreenRegion(
251                region_name,
252                x,
253                y,
254                w,
255                h,
256                parameters=parameters,
257                multi_target_paths=region_target_paths,
258            )
259            named_screen_regions.append(region)
260        super().__init__(pyboy, parameters, named_screen_regions)

Initializes the DejaVuStateParser.

Arguments:
  • variant (str): The variant of the Deja Vu game.
  • 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 target names for multi-target regions.
COMMON_REGIONS = [('dialogue_top_left_hook', 0, 73, 10, 6), ('menu_bottom_line', 0, 143, 160, 1), ('selected_outfit_button', 120, 17, 14, 15), ('pointed_at_11_on_map', 120, 80, 8, 8), ('pointed_at_13_on_map', 136, 80, 8, 8), ('pointed_at_21_on_map', 120, 72, 8, 8), ('pointed_at_24_on_map', 144, 72, 8, 8), ('pointed_at_25_on_map', 152, 72, 8, 8), ('pointed_at_35_on_map', 152, 64, 8, 8), ('pointed_at_41_on_map', 120, 56, 8, 8), ('pointed_at_45_on_map', 152, 56, 8, 8), ('pointed_at_52_on_map', 128, 48, 8, 8), ('pointed_at_54_on_map', 144, 48, 8, 8), ('selected_watch_action_in_menu', 8, 33, 16, 5), ('selected_use_action_in_menu', 24, 33, 16, 5), ('selected_take_action_in_menu', 40, 33, 16, 5), ('selected_open_action_in_menu', 64, 33, 16, 5), ('selected_close_action_in_menu', 80, 33, 16, 5), ('selected_talk_action_in_menu', 104, 33, 16, 5), ('selected_hit_action_in_menu', 120, 33, 16, 5), ('selected_throw_action_in_menu', 136, 33, 16, 5), ('selected_watch_action_in_normal', 8, 121, 16, 5), ('selected_use_action_in_normal', 24, 121, 16, 5), ('selected_take_action_in_normal', 40, 121, 16, 5), ('selected_open_action_in_normal', 64, 121, 16, 5), ('selected_close_action_in_normal', 80, 121, 16, 5), ('selected_talk_action_in_normal', 104, 121, 16, 5), ('selected_hit_action_in_normal', 120, 121, 16, 5), ('selected_throw_action_in_normal', 136, 121, 16, 5)]

List of common named screen regions for Deja Vu game.

Deja Vu uses a primarily text/menu-driven interface. These regions help identify:

  • dialogue_top_left_hook: A hook that appears in the top left after certain events, can be used to determine if certain game mechanics are available.
  • menu_bottom_line: A line that appears at the bottom of the screen when any menu is open, can be used to prevent agent interaction with the UI frame of the emulator.
  • selected_outfit_button: The area where the "Selected Outfit" button appears when the outfit menu is open, can be used to determine if the outfit menu is open.
  • pointed_at_{ij}_on_map: The agent is currently pointing at location (i,j) on the map. (the map is divided into a 5x5 grid of locations, with (1,1) being the bottom left and (5,5) being the top right)
  • selected_{action}_action_in_menu: The specified action is currently selected in the action bar while a menu is open.
  • selected_{action}_action_in_normal: The specified action is currently selected in the action bar while no menu is open.
COMMON_MULTI_TARGET_REGIONS = [('dialogue_box_area', 0, 74, 160, 55), ('menu_box_area', 0, 70, 160, 70), ('no_action', 0, 114, 160, 14), ('menu_title_area', 23, 56, 96, 17), ('game_screen_area', 0, 0, 112, 112)]

List of common multi-target named screen regions for Deja Vu games.

Deja Vu has certain regions that can contain multiple important visual cues.

  • dialogue_box_area: The area where dialogue text appears. Can contain multiple targets such as clues
  • menu_box_area: The area where menu options appear. Can contain multiple targets such as items or actions.
  • no_action: The area where no action is currently selected in the action bar.
  • menu_title_area: The area where the menu title appears.
  • game_screen_area: The entire game screen area. (- map_area: The area where the map appears when the map is open.)
COMMON_MULTI_TARGETS = {'dialogue_box_area': ['_', 'nothing_usual', 'opened_door', 'closed_door'], 'no_action': ['_', 'no_action_selected'], 'menu_title_area': ['_', 'address_menu', 'goods_menu'], 'game_screen_area': ['_', 'socko_on_screen']}

Common multi-targets for Deja Vu game regions.

  • dialogue_box_area:
    • nothing_usual: Point at useless area.
    • opened_door: Open the door in front of you.
  • no_action:
    • no_action_selected: No action is currently selected in the action bar.
  • menu_title_area:
    • address_menu: The address menu is currently open.
    • goods_menu: The goods menu is currently open.
  • game_screen_area:
    • socko_on_screen: The character "SOCKO" is currently visible on the screen.
variant
rom_data_path

Path to the ROM data directory for the specific Deja Vu variant.

def is_in_menu(self, current_screen: numpy.ndarray) -> bool:
262    def is_in_menu(self, current_screen: np.ndarray) -> bool:
263        """
264        Determines if any form of menu is currently open (Case Notes, Evidence, Location, etc).
265
266        Args:
267            current_screen (np.ndarray): The current screen frame from the emulator.
268            trust_previous (bool): If True, trusts that checks for other states have been done.
269
270        Returns:
271            bool: True if a menu is open, False otherwise.
272        """
273        return self.named_region_matches_target(current_screen, "menu_bottom_line")

Determines if any form of menu is currently open (Case Notes, Evidence, Location, etc).

Arguments:
  • current_screen (np.ndarray): The current screen frame from the emulator.
  • trust_previous (bool): If True, trusts that checks for other states have been done.
Returns:

bool: True if a menu is open, False otherwise.

def is_in_dialogue(self, current_screen: numpy.ndarray) -> bool:
275    def is_in_dialogue(self, current_screen: np.ndarray) -> bool:
276        """
277        Determines if the player is currently in a dialogue state.
278        Includes talking to NPCs, receiving clues, story narration, etc.
279
280        Args:
281            current_screen (np.ndarray): The current screen frame from the emulator.
282            trust_previous (bool): If True, trusts that checks for menu state have been done.
283
284        Returns:
285            bool: True if in dialogue, False otherwise.
286        """
287        if self.is_in_menu(current_screen):
288            return False
289        return self.named_region_matches_target(
290            current_screen, "dialogue_top_left_hook"
291        )

Determines if the player is currently in a dialogue state. Includes talking to NPCs, receiving clues, story narration, etc.

Arguments:
  • current_screen (np.ndarray): The current screen frame from the emulator.
  • trust_previous (bool): If True, trusts that checks for menu state have been done.
Returns:

bool: True if in dialogue, False otherwise.

def get_agent_state( self, current_screen: numpy.ndarray) -> AgentState:
293    def get_agent_state(self, current_screen: np.ndarray) -> AgentState:
294        """
295        Determines the current agent state based on the screen.
296
297        Uses trust_previous to optimize checks.
298
299        Args:
300            current_screen (np.ndarray): The current screen frame from the emulator.
301
302        Returns:
303            AgentState: The current agent state (FREE_ROAM, IN_DIALOGUE, or IN_MENU).
304        """
305        if self.is_in_menu(current_screen):
306            return AgentState.IN_MENU
307        elif self.is_in_dialogue(current_screen):
308            return AgentState.IN_DIALOGUE
309        else:
310            return AgentState.FREE_ROAM

Determines the current agent state based on the screen.

Uses trust_previous to optimize checks.

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

AgentState: The current agent state (FREE_ROAM, IN_DIALOGUE, or IN_MENU).

class DejaVu1StateParser(DejaVuStateParser):
313class DejaVu1StateParser(DejaVuStateParser):
314    """Game state parser for Deja Vu I: The Casebooks of Ace Harding."""
315
316    def __init__(self, pyboy, parameters):
317        override_regions = [
318            ("selected_coat_item", 0, 79, 160, 8),
319            ("selected_wallet_item", 0, 120, 160, 8),
320            ("selected_coin_item", 0, 95, 160, 8),
321            ("using_coin_item", 0, 95, 160, 8),
322            ("using_key3_item", 0, 88, 160, 8),
323            ("using_key2_item", 0, 128, 160, 8),
324            ("selected_westend_address", 0, 88, 160, 8),
325            ("using_bullet_item", 0, 88, 160, 8),
326            ("using_note3_item", 0, 88, 160, 8),
327            ("using_key4_item", 0, 128, 160, 8),
328        ]
329        override_multi_target_regions = []
330        override_multi_targets = {
331            "dialogue_box_area": [
332                "took_coat",
333                "took_gun",
334                "opened_pocket",
335                "opened_wallet",
336                "closed_pocket",
337                "closed_wallet",
338                "checked_coat",
339                "checked_gun",
340                "opened_spigot",
341                "hit_bottle",
342                "entered_cellar",
343                "entered_connecting_room",
344                "made_bet",
345                "entered_empty_room",
346                "unlocked_front_door",
347                "met_mugger",
348                "hit_mugger",
349                "unlocked_car_door",
350                "opened_dashbrd",
351                "closed_dashbrd",
352                "checked_note2",
353                "checked_map",
354                "checked_snapshot",
355                "in_front_of_newsstand",
356                "entered_taxi",
357                "talked_to_taxi_driver",
358                "went_to_westend",
359                "paid_taxi",
360                "outside_apartment",
361                "entered_sherman",
362                "stood_in_front_office",
363                "entered_westend",
364                "opened_elevator_door",
365                "entered_elevator",
366                "closed_elevator_door",
367                "checked_photo",
368                "opened_desk",
369                "unlocked_office_door",
370                "opened_westend_door",
371                "opened_sherman_door",
372                "made_medicine",
373                "taken_medicine",
374                "opened_diary",
375                "checked_dead_man",
376                "opened_cabinet",
377                "exited_grimy_office",
378                "opened_wall_safe",
379                "opened_car_trunk",
380            ],
381            "menu_title_area": [
382                "coat_pocket_menu",
383                "wallet_menu",
384            ],
385            "game_screen_area": [
386                "opened_cellar_door",
387                "shot_door",
388                "shot_lock",
389            ],
390            "no_action": [
391                "in_cellar",
392                "in_empty_restaurant",
393                "on_peoria_st",
394                "in_sherman_lobby",
395                "in_westend_lobby",
396                "in_grimy_office",
397            ],
398        }
399
400        super().__init__(
401            variant="deja_vu_1",
402            pyboy=pyboy,
403            parameters=parameters,
404            additional_named_screen_region_details=override_regions,
405            additional_multi_target_named_screen_region_details=override_multi_target_regions,
406            override_multi_targets=override_multi_targets,
407        )
408
409    def __repr__(self):
410        return f"<DejaVuParser(variant={self.variant})>"

Game state parser for Deja Vu I: The Casebooks of Ace Harding.

DejaVu1StateParser(pyboy, parameters)
316    def __init__(self, pyboy, parameters):
317        override_regions = [
318            ("selected_coat_item", 0, 79, 160, 8),
319            ("selected_wallet_item", 0, 120, 160, 8),
320            ("selected_coin_item", 0, 95, 160, 8),
321            ("using_coin_item", 0, 95, 160, 8),
322            ("using_key3_item", 0, 88, 160, 8),
323            ("using_key2_item", 0, 128, 160, 8),
324            ("selected_westend_address", 0, 88, 160, 8),
325            ("using_bullet_item", 0, 88, 160, 8),
326            ("using_note3_item", 0, 88, 160, 8),
327            ("using_key4_item", 0, 128, 160, 8),
328        ]
329        override_multi_target_regions = []
330        override_multi_targets = {
331            "dialogue_box_area": [
332                "took_coat",
333                "took_gun",
334                "opened_pocket",
335                "opened_wallet",
336                "closed_pocket",
337                "closed_wallet",
338                "checked_coat",
339                "checked_gun",
340                "opened_spigot",
341                "hit_bottle",
342                "entered_cellar",
343                "entered_connecting_room",
344                "made_bet",
345                "entered_empty_room",
346                "unlocked_front_door",
347                "met_mugger",
348                "hit_mugger",
349                "unlocked_car_door",
350                "opened_dashbrd",
351                "closed_dashbrd",
352                "checked_note2",
353                "checked_map",
354                "checked_snapshot",
355                "in_front_of_newsstand",
356                "entered_taxi",
357                "talked_to_taxi_driver",
358                "went_to_westend",
359                "paid_taxi",
360                "outside_apartment",
361                "entered_sherman",
362                "stood_in_front_office",
363                "entered_westend",
364                "opened_elevator_door",
365                "entered_elevator",
366                "closed_elevator_door",
367                "checked_photo",
368                "opened_desk",
369                "unlocked_office_door",
370                "opened_westend_door",
371                "opened_sherman_door",
372                "made_medicine",
373                "taken_medicine",
374                "opened_diary",
375                "checked_dead_man",
376                "opened_cabinet",
377                "exited_grimy_office",
378                "opened_wall_safe",
379                "opened_car_trunk",
380            ],
381            "menu_title_area": [
382                "coat_pocket_menu",
383                "wallet_menu",
384            ],
385            "game_screen_area": [
386                "opened_cellar_door",
387                "shot_door",
388                "shot_lock",
389            ],
390            "no_action": [
391                "in_cellar",
392                "in_empty_restaurant",
393                "on_peoria_st",
394                "in_sherman_lobby",
395                "in_westend_lobby",
396                "in_grimy_office",
397            ],
398        }
399
400        super().__init__(
401            variant="deja_vu_1",
402            pyboy=pyboy,
403            parameters=parameters,
404            additional_named_screen_region_details=override_regions,
405            additional_multi_target_named_screen_region_details=override_multi_target_regions,
406            override_multi_targets=override_multi_targets,
407        )

Initializes the DejaVuStateParser.

Arguments:
  • variant (str): The variant of the Deja Vu game.
  • 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 target names for multi-target regions.
class DejaVu2StateParser(DejaVuStateParser):
413class DejaVu2StateParser(DejaVuStateParser):
414    """Game state parser for Deja Vu II: The Casebooks of Ace Harding."""
415
416    def __init__(self, pyboy, parameters):
417        override_regions = [
418            ("selected_gum_item", 0, 79, 160, 8),
419            ("selected_pants_item", 0, 112, 160, 8),
420            ("selected_trench_coat_item", 0, 88, 160, 8),
421            ("selected_wallet1_item", 0, 96, 160, 8),
422            ("selected_newsclip1_item", 0, 79, 160, 8),
423            ("selected_license1_item", 0, 79, 160, 8),
424            ("using_cash_item", 0, 79, 160, 8),
425            ("using_key1_item", 0, 104, 160, 8),
426            ("using_key2_item", 0, 79, 160, 8),
427            ("using_knife_item", 0, 128, 160, 8),
428            ("using_key4_item", 0, 104, 160, 8),
429            ("using_flashlight_item", 0, 88, 160, 8),
430            ("using_nametag2_item", 0, 88, 160, 8),
431        ]
432        override_multi_target_regions = []
433        override_multi_targets = {
434            "dialogue_box_area": [
435                "opened_trench_coat_pocket",
436                "taken_gum",
437                "opened_pants_pocket",
438                "taken_pants",
439                "closed_pants_pocket",
440                "put_on_trench_coat",
441                "put_on_pants",
442                "opened_wallet1",
443                "taken_newsclip1",
444                "taken_license1",
445                "closed_wallet1",
446                "opened_cold_tap",
447                "closed_cold_tap",
448                "checked_newsclip1",
449                "taken_ring1",
450                "opened_room_door",
451                "closed_room_door",
452                "entered_hallway",
453                "selected_2_chips",
454                "bought_2_chips",
455                "returned_cashier",
456                "selected_50_chips",
457                "cashed_out",
458                "opened_lobby_door",
459                "exited_casino",
460                "talked_in_train_station",
461                "visited_counter",
462                "taken_pamphlet",
463                "timetable",
464                "entered_platform",
465                "entered_train",
466                "bought_ticket",
467                "checked_girl",
468                "checked_sign",
469                "chatted_seller",
470                "bought_newspaper",
471                "taken_newsclip4",
472                "entered_chicago_taxi",
473                "chatted_taxi_driver",
474                "unlocked_middle_door",
475                "entered_middle_room",
476                "loaded_gun",
477                "opened_lock",
478                "hit_board",
479                "opened_telephone",
480                "opened_box",
481                "opened_pocket_knife",
482                "opened_door_by_knife",
483                "put_on_flashlight",
484                "entered_joe_place",
485                "opened_joe_place_door",
486                "opened_slot_lock",
487                "turned_off_flashlight",
488                "got_location_from_card",
489                "opened_bag_with_knife",
490                "asked_about_nametage2",
491            ],
492            "menu_title_area": [
493                "trench_coat_pocket_menu", 
494                "wallet1_menu",
495                "vacuum_menu",
496            ],
497            "game_screen_area": [
498                "on_track6",
499            ],
500            "no_action": [
501                "in_lobby",
502            ],
503        }
504
505        super().__init__(
506            variant="deja_vu_2",
507            pyboy=pyboy,
508            parameters=parameters,
509            additional_named_screen_region_details=override_regions,
510            additional_multi_target_named_screen_region_details=override_multi_target_regions,
511            override_multi_targets=override_multi_targets,
512        )
513
514    def __repr__(self):
515        return f"<DejaVuParser(variant={self.variant})>"

Game state parser for Deja Vu II: The Casebooks of Ace Harding.

DejaVu2StateParser(pyboy, parameters)
416    def __init__(self, pyboy, parameters):
417        override_regions = [
418            ("selected_gum_item", 0, 79, 160, 8),
419            ("selected_pants_item", 0, 112, 160, 8),
420            ("selected_trench_coat_item", 0, 88, 160, 8),
421            ("selected_wallet1_item", 0, 96, 160, 8),
422            ("selected_newsclip1_item", 0, 79, 160, 8),
423            ("selected_license1_item", 0, 79, 160, 8),
424            ("using_cash_item", 0, 79, 160, 8),
425            ("using_key1_item", 0, 104, 160, 8),
426            ("using_key2_item", 0, 79, 160, 8),
427            ("using_knife_item", 0, 128, 160, 8),
428            ("using_key4_item", 0, 104, 160, 8),
429            ("using_flashlight_item", 0, 88, 160, 8),
430            ("using_nametag2_item", 0, 88, 160, 8),
431        ]
432        override_multi_target_regions = []
433        override_multi_targets = {
434            "dialogue_box_area": [
435                "opened_trench_coat_pocket",
436                "taken_gum",
437                "opened_pants_pocket",
438                "taken_pants",
439                "closed_pants_pocket",
440                "put_on_trench_coat",
441                "put_on_pants",
442                "opened_wallet1",
443                "taken_newsclip1",
444                "taken_license1",
445                "closed_wallet1",
446                "opened_cold_tap",
447                "closed_cold_tap",
448                "checked_newsclip1",
449                "taken_ring1",
450                "opened_room_door",
451                "closed_room_door",
452                "entered_hallway",
453                "selected_2_chips",
454                "bought_2_chips",
455                "returned_cashier",
456                "selected_50_chips",
457                "cashed_out",
458                "opened_lobby_door",
459                "exited_casino",
460                "talked_in_train_station",
461                "visited_counter",
462                "taken_pamphlet",
463                "timetable",
464                "entered_platform",
465                "entered_train",
466                "bought_ticket",
467                "checked_girl",
468                "checked_sign",
469                "chatted_seller",
470                "bought_newspaper",
471                "taken_newsclip4",
472                "entered_chicago_taxi",
473                "chatted_taxi_driver",
474                "unlocked_middle_door",
475                "entered_middle_room",
476                "loaded_gun",
477                "opened_lock",
478                "hit_board",
479                "opened_telephone",
480                "opened_box",
481                "opened_pocket_knife",
482                "opened_door_by_knife",
483                "put_on_flashlight",
484                "entered_joe_place",
485                "opened_joe_place_door",
486                "opened_slot_lock",
487                "turned_off_flashlight",
488                "got_location_from_card",
489                "opened_bag_with_knife",
490                "asked_about_nametage2",
491            ],
492            "menu_title_area": [
493                "trench_coat_pocket_menu", 
494                "wallet1_menu",
495                "vacuum_menu",
496            ],
497            "game_screen_area": [
498                "on_track6",
499            ],
500            "no_action": [
501                "in_lobby",
502            ],
503        }
504
505        super().__init__(
506            variant="deja_vu_2",
507            pyboy=pyboy,
508            parameters=parameters,
509            additional_named_screen_region_details=override_regions,
510            additional_multi_target_named_screen_region_details=override_multi_target_regions,
511            override_multi_targets=override_multi_targets,
512        )

Initializes the DejaVuStateParser.

Arguments:
  • variant (str): The variant of the Deja Vu game.
  • 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 target names for multi-target regions.