Repository: Baekalfen/PyBoy
File: pyboy/plugins/base_plugin.py (Python)

Code before:
        self.game_area_wrap_around = game_area_wrap_around
        width = self.game_area_section[2] - self.game_area_section[0]
        height = self.game_area_section[3] - self.game_area_section[1]
        self._cached_game_area_tiles_raw = array("B", [0xFF] * (width*height*4))

        self.saved_state = io.BytesIO()

        if cythonmode:
            self._cached_game_area_tiles = memoryview(self._cached_game_area_tiles_raw).cast("I", shape=(width, height))
        else:
            v = memoryview(self._cached_game_area_tiles_raw).cast("I")
            self._cached_game_area_tiles = [v[i:i + height] for i in range(0, height * width, height)]

    def enabled(self):
        return self.pyboy_argv.get("game_wrapper") and self.pyboy.cartridge_title() == self.cartridge_title

    def post_tick(self):
        raise NotImplementedError("post_tick not implemented in game wrapper")

    def _set_timer_div(self, timer_div, randomize_div):
        if timer_div is not None:
            self.pyboy.mb.timer.DIV = timer_div & 0xFF
        elif randomize_div:
            self.pyboy.mb.timer.DIV = random.getrandbits(8)

    def start_game(self, timer_div=None, randomize_div=False):
        """
        Call this function right after initializing PyBoy. This will navigate through menus to start the game at the
        first playable state.

        A value can be passed to set the timer's DIV register. Some games depend on it for randomization.

        The state of the emulator is saved, and using `reset_game`, you can get back to this point of the game
        instantly.

        Args:
            timer_div (int): Replace timer's DIV register with this value
            randomize_div (bool): Whether to randomize the DIV register or not
        """

        if not self.pyboy.frame_count == 0:
            logger.warning("Calling start_game from an already running game. This might not work.")

        self._set_timer_div(timer_div, randomize_div)

    def reset_game(self, timer_div=None, randomize_div=False):
        """
        After calling `start_game`, you can call this method at any time to reset the game.

        Args:
            timer_div (int): Replace timer's DIV register with this value

Review comment (bug):
I don't find it that elegant to have two variables when they do almost the same thing. It's much more common in Python to have a variable be None and do the default behavior, and do something else when defined.

With two variables, you also need to consider what will happen if both are set. Right now, it's undefined behavior.

Code after:
        self.game_area_wrap_around = game_area_wrap_around
        width = self.game_area_section[2] - self.game_area_section[0]
        height = self.game_area_section[3] - self.game_area_section[1]
        self._cached_game_area_tiles_raw = array("B", [0xFF] * (width*height*4))

        self.saved_state = io.BytesIO()

        if cythonmode:
            self._cached_game_area_tiles = memoryview(self._cached_game_area_tiles_raw).cast("I", shape=(width, height))
        else:
            v = memoryview(self._cached_game_area_tiles_raw).cast("I")
            self._cached_game_area_tiles = [v[i:i + height] for i in range(0, height * width, height)]

    def enabled(self):
        return self.pyboy_argv.get("game_wrapper") and self.pyboy.cartridge_title() == self.cartridge_title

    def post_tick(self):
        raise NotImplementedError("post_tick not implemented in game wrapper")

    def _set_timer_div(self, timer_div):
        if timer_div is None:
            self.mb.timer.DIV = random.getrandbits(8)
        else:
            self.mb.timer.DIV = timer_div & 0xFF

    def start_game(self, timer_div=None):
        """
        Call this function right after initializing PyBoy. This will navigate through menus to start the game at the
        first playable state.

        A value can be passed to set the timer's DIV register. Some games depend on it for randomization.

        The state of the emulator is saved, and using `reset_game`, you can get back to this point of the game
        instantly.

        Args:
            timer_div (int): Replace timer's DIV register with this value. Use `None` to randomize.
        """

        if not self.pyboy.frame_count == 0:
            logger.warning("Calling start_game from an already running game. This might not work.")

        self._set_timer_div(timer_div)

    def reset_game(self, timer_div=None):
        """
        After calling `start_game`, you can call this method at any time to reset the game.

        Args:
            timer_div (int): Replace timer's DIV register with this value. Use `None` to randomize.
        """