# Module `pyboy.api`

Tools to help interfacing with the Game Boy hardware

Expand source code

    #
    # License: See LICENSE.md file
    # GitHub: https://github.com/Baekalfen/PyBoy
    #
    """
    Tools to help interfacing with the Game Boy hardware
    """

    from . import constants
    from .gameshark import GameShark
    from .screen import Screen
    from .sprite import Sprite
    from .tile import Tile
    from .tilemap import TileMap

    # __pdoc__ = {
    #     "constants": False,
    #     "manager": False,
    # }
    __all__ = [
        "constants",
        "GameShark",
        "Screen",
        "Sprite",
        "Tile",
        "TileMap",
    ]

## Sub-modules

`pyboy.api.constants`

  Memory constants used internally to calculate tile and tile map addresses.

`pyboy.api.gameshark`
`pyboy.api.memory_scanner`
`pyboy.api.screen`

  This class gives access to the frame buffer and other screen parameters of PyBoy.

`pyboy.api.sound`

  This class gives access to the sound buffer of PyBoy.

`pyboy.api.sprite`

  This class presents an interface to the sprites held in the OAM data on the Game Boy.

`pyboy.api.tile`

  The Game Boy uses tiles as the building block for all graphics on the screen. This base-class is used both for `Sprite` and …

`pyboy.api.tilemap`

  The Game Boy has two tile maps, which defines what is rendered on the screen.

## Classes

`class GameShark (memory)`
  Expand source code

      class GameShark:
          def __init__(self, memory):
              self.memory = memory
              self.cheats = {}
              self.enabled = False

          def _convert_cheat(self, gameshark_code):
              """
              A GameShark code for these consoles is written in the format ttvvaaaa. tt specifies the type, which is usually 01.
              vv specifies the hexadecimal value the code will write into the game's memory. aaaa specifies the memory address
              that will be modified, with the low byte first (e.g. address C056 is written as 56C0).
              Example 011556C0 would output:
              type = 01
              value = 0x15
              address = 0x56C0

              For more details:
              https://doc.kodewerx.org/hacking_gb.html

              There seems to be conflicting information about the presence of other types than 01.
              """
              # Check if the input cheat code has the correct length (8 characters)
              if len(gameshark_code) != 8:
                  raise ValueError("Invalid cheat code length. Cheat code must be 8 characters long.")

              # Extract components from the cheat code
              _type = int(gameshark_code[:2], 16)
              value = int(gameshark_code[2:4], 16)  # Convert hexadecimal value to an integer
              unconverted_address = gameshark_code[4:]  # Ex:   1ED1
              lower = unconverted_address[:2]  # Ex:  1E
              upper = unconverted_address[2:]  # Ex:  D1
              address_converted = upper + lower  # Ex: 0xD11E   # Converting to Ram Readable address
              address = int(address_converted, 16)

              if not 0x8000 <= address:
                  raise ValueError("Invalid GameShark code provided. Address not in the RAM range")

              return (_type, value, address)

          def _get_value(self, _type, address):
              if _type == 0x01:
                  # 8-bit RAM write
                  # Writes the byte xx to the address zzyy.
                  return self.memory[address]
              # elif (_type & 0xF0) == 0x80:
              #     # 8-bit RAM write (with bank change)
              #     # Changes the RAM bank to b, then writes the byte xx to the address zzyy.
              #     bank = _type & 0xF
              #     pass
              # elif (_type & 0xF0) == 0x90:
              #     # 8-bit RAM write (with WRAM bank change)
              #     # Changes the WRAM bank to b and then writes the byte xx to the address zzyy. GBC only.
              #     bank = _type & 0xF
              #     pass
              else:
                  raise ValueError("Invalid GameShark type", _type)

          def _set_value(self, _type, value, address):
              if _type == 0x01:
                  # 8-bit RAM write
                  # Writes the byte xx to the address zzyy.
                  self.memory[address] = value
              # elif (_type & 0xF0) == 0x80:
              #     # 8-bit RAM write (with bank change)
              #     # Changes the RAM bank to b, then writes the byte xx to the address zzyy.
              #     bank = _type & 0xF
              #     pass
              # elif (_type & 0xF0) == 0x90:
              #     # 8-bit RAM write (with WRAM bank change)
              #     # Changes the WRAM bank to b and then writes the byte xx to the address zzyy. GBC only.
              #     bank = _type & 0xF
              #     pass
              else:
                  raise ValueError("Invalid GameShark type", _type)

          def add(self, code):
              """
              Add a GameShark cheat to the emulator.

              Example:
              ```python
              >>> pyboy.gameshark.add("01FF16D0")
              ```

              Args:
                  code (str): GameShark code to add
              """
              self.enabled = True
              _type, value, address = self._convert_cheat(code)
              if code not in self.cheats:
                  self.cheats[code] = (self._get_value(_type, address), (_type, value, address))
              else:
                  raise PyBoyInvalidInputException("GameShark code already applied!")

          def remove(self, code, restore_value=True):
              """
              Remove a GameShark cheat from the emulator.

              Example:
              ```python
              >>> pyboy.gameshark.add("01FF16D0")
              >>> pyboy.gameshark.remove("01FF16D0")
              ```

              Args:
                  code (str): GameShark code to remove
                  restore_value (bool): True to restore original value at address, otherwise don't restore
              """

              if code not in self.cheats:
                  raise ValueError("GameShark code cannot be removed. Hasn't been applied.")

              original_value, (_type, _, address) = self.cheats.pop(code)
              if restore_value:
                  self._set_value(_type, original_value, address)

              if len(self.cheats) == 0:
                  self.enabled = False

          def clear_all(self, restore_value=True):
              """
              Remove all GameShark cheats from the emulator.

              Example:
              ```python
              >>> pyboy.gameshark.clear_all()
              ```

              Args:
                  restore_value (bool): Restore the original values of the memory addresses that were modified by the cheats.
              """
              # NOTE: Create a list so we don't remove from the iterator we are going through
              for code in list(self.cheats.keys()):
                  self.remove(code, restore_value)

          def tick(self):
              if not self.enabled:
                  return 0
              # https://gbdev.io/pandocs/Shark_Cheats.html
              # "As far as it is understood, patching is implemented by hooking the original VBlank interrupt handler, and
              # re-writing RAM values each frame."
              for _, (_, (_type, value, address)) in self.cheats.items():
                  self._set_value(_type, value, address)

  ### Methods

  `def add(self, code)`

    Add a GameShark cheat to the emulator.

    Example:

        >>> pyboy.gameshark.add("01FF16D0")

    ## Args

    `code` :`str`
      GameShark code to add
    Expand source code

        def add(self, code):
            """
            Add a GameShark cheat to the emulator.

            Example:
            ```python
            >>> pyboy.gameshark.add("01FF16D0")
            ```

            Args:
                code (str): GameShark code to add
            """
            self.enabled = True
            _type, value, address = self._convert_cheat(code)
            if code not in self.cheats:
                self.cheats[code] = (self._get_value(_type, address), (_type, value, address))
            else:
                raise PyBoyInvalidInputException("GameShark code already applied!")

  `def remove(self, code, restore_value=True)`

    Remove a GameShark cheat from the emulator.

    Example:

        >>> pyboy.gameshark.add("01FF16D0")
        >>> pyboy.gameshark.remove("01FF16D0")

    ## Args

    `code` :`str`
      GameShark code to remove
    `restore_value` :`bool`
      True to restore original value at address, otherwise don't restore
    Expand source code

        def remove(self, code, restore_value=True):
            """
            Remove a GameShark cheat from the emulator.

            Example:
            ```python
            >>> pyboy.gameshark.add("01FF16D0")
            >>> pyboy.gameshark.remove("01FF16D0")
            ```

            Args:
                code (str): GameShark code to remove
                restore_value (bool): True to restore original value at address, otherwise don't restore
            """

            if code not in self.cheats:
                raise ValueError("GameShark code cannot be removed. Hasn't been applied.")

            original_value, (_type, _, address) = self.cheats.pop(code)
            if restore_value:
                self._set_value(_type, original_value, address)

            if len(self.cheats) == 0:
                self.enabled = False

  `def clear_all(self, restore_value=True)`

    Remove all GameShark cheats from the emulator.

    Example:

        >>> pyboy.gameshark.clear_all()

    ## Args

    `restore_value` :`bool`
      Restore the original values of the memory addresses that were modified by the cheats.
    Expand source code

        def clear_all(self, restore_value=True):
            """
            Remove all GameShark cheats from the emulator.

            Example:
            ```python
            >>> pyboy.gameshark.clear_all()
            ```

            Args:
                restore_value (bool): Restore the original values of the memory addresses that were modified by the cheats.
            """
            # NOTE: Create a list so we don't remove from the iterator we are going through
            for code in list(self.cheats.keys()):
                self.remove(code, restore_value)

  `def tick(self)`
    Expand source code

        def tick(self):
            if not self.enabled:
                return 0
            # https://gbdev.io/pandocs/Shark_Cheats.html
            # "As far as it is understood, patching is implemented by hooking the original VBlank interrupt handler, and
            # re-writing RAM values each frame."
            for _, (_, (_type, value, address)) in self.cheats.items():
                self._set_value(_type, value, address)

`class Screen (mb)`

  As part of the emulation, we generate a screen buffer in 32-bit RGBA format. This class has several helper methods to make it possible to read this buffer out.

  If you're making an AI or bot, it's highly recommended to not use this class for detecting objects on the screen. It's much more efficient to use `PyBoy.tilemap_background`, `PyBoy.tilemap_window`, and `PyBoy.get_sprite()` instead.

  Expand source code

      class Screen:
          """
          As part of the emulation, we generate a screen buffer in 32-bit RGBA format. This class has several helper methods
          to make it possible to read this buffer out.

          If you're making an AI or bot, it's highly recommended to _not_ use this class for detecting objects on the screen.
          It's much more efficient to use `pyboy.PyBoy.tilemap_background`, `pyboy.PyBoy.tilemap_window`, and `pyboy.PyBoy.get_sprite` instead.
          """

          def __init__(self, mb):
              self.mb = mb

              self.raw_buffer = self.mb.lcd.renderer._screenbuffer
              """
              Provides a raw, unfiltered `bytes` object with the data from the screen. Check
              `Screen.raw_buffer_format` to see which dataformat is used. **The returned type and dataformat are
              subject to change.** The screen buffer is row-major.

              Use this, only if you need to bypass the overhead of `Screen.image` or `Screen.ndarray`.

              Example:
              ```python
              >>> import numpy as np
              >>> rows, cols = pyboy.screen.raw_buffer_dims
              >>> ndarray = np.frombuffer(
              ...     pyboy.screen.raw_buffer,
              ...     dtype=np.uint8,
              ... ).reshape(rows, cols, 4) # Just an example, use pyboy.screen.ndarray instead

              ```

              Returns
              -------
              memoryview:
                  92160 bytes memoryview of screen data.
              """
              self.raw_buffer_dims = self.mb.lcd.renderer.buffer_dims
              """
              Returns the dimensions of the raw screen buffer. The screen buffer is row-major.

              Example:
              ```python
              >>> pyboy.screen.raw_buffer_dims
              (144, 160)

              ```

              Returns
              -------
              tuple:
                  A two-tuple of the buffer dimensions. E.g. (144, 160).
              """
              self.raw_buffer_format = self.mb.lcd.renderer.color_format
              """
              Returns the color format of the raw screen buffer. **This format is subject to change.**

              Example:
              ```python
              >>> from PIL import Image
              >>> pyboy.screen.raw_buffer_format
              'RGBA'
              >>> image = Image.frombuffer(
              ...    pyboy.screen.raw_buffer_format,
              ...    pyboy.screen.raw_buffer_dims[::-1],
              ...    pyboy.screen.raw_buffer,
              ... ) # Just an example, use pyboy.screen.image instead
              >>> image.save('frame.png')

              ```

              Returns
              -------
              str:
                  Color format of the raw screen buffer. E.g. 'RGBA'.
              """
              self.image = None
              """
              Reference to a PIL Image from the screen buffer. **Remember to copy, resize or convert this object** if you
              intend to store it. The backing buffer will update, but it will be the same `PIL.Image` object.

              Convenient for screen captures, but might be a bottleneck, if you use it to train a neural network. In which
              case, read up on the `pyboy.api` features, [Pan Docs](https://gbdev.io/pandocs/) on tiles/sprites,
              and join our Discord channel for more help.

              Example:
              ```python
              >>> image = pyboy.screen.image
              >>> type(image)
              <class 'PIL.Image.Image'>
              >>> image.save('frame.png')

              ```

              Returns
              -------
              PIL.Image:
                  RGB image of (160, 144) pixels
              """
              if not Image:
                  logger.warning('Cannot generate screen image. Missing dependency "Pillow".')
                  self.image = utils.PillowImportError()
              else:
                  self._set_image()

              self.ndarray = np.frombuffer(
                  self.mb.lcd.renderer._screenbuffer_raw,
                  dtype=np.uint8,
              ).reshape(ROWS, COLS, 4)
              """
              References the screen data in NumPy format. **Remember to copy this object** if you intend to store it.
              The backing buffer will update, but it will be the same `ndarray` object.

              The format is given by `pyboy.api.screen.Screen.raw_buffer_format`. The screen buffer is row-major.

              Example:
              ```python
              >>> pyboy.screen.ndarray.shape
              (144, 160, 4)
              >>> # Display "P" on screen from the PyBoy bootrom
              >>> pyboy.screen.ndarray[66:80,64:72,0]
              array([[255, 255, 255, 255, 255, 255, 255, 255],
                     [255,   0,   0,   0,   0,   0, 255, 255],
                     [255,   0,   0,   0,   0,   0,   0, 255],
                     [255,   0,   0, 255, 255,   0,   0, 255],
                     [255,   0,   0, 255, 255,   0,   0, 255],
                     [255,   0,   0, 255, 255,   0,   0, 255],
                     [255,   0,   0,   0,   0,   0,   0, 255],
                     [255,   0,   0,   0,   0,   0, 255, 255],
                     [255,   0,   0, 255, 255, 255, 255, 255],
                     [255,   0,   0, 255, 255, 255, 255, 255],
                     [255,   0,   0, 255, 255, 255, 255, 255],
                     [255,   0,   0, 255, 255, 255, 255, 255],
                     [255,   0,   0, 255, 255, 255, 255, 255],
                     [255, 255, 255, 255, 255, 255, 255, 255]], dtype=uint8)

              ```

              Returns
              -------
              numpy.ndarray:
                  Screendata in `ndarray` of bytes with shape (144, 160, 4)
              """

          def _set_image(self):
              self.image = Image.frombuffer(
                  self.mb.lcd.renderer.color_format,
                  self.mb.lcd.renderer.buffer_dims[::-1],
                  self.mb.lcd.renderer._screenbuffer_raw,
              )

          @property
          def tilemap_position_list(self):
              """
              This function provides the screen (SCX, SCY) and window (WX, WY) position for each horizontal line in the
              screen buffer. These parameters are often used for visual effects, and some games will reset the registers at
              the end of each call to `pyboy.PyBoy.tick()`.

              See `Screen.get_tilemap_position` for more information.

              Example:
              ```python
              >>> pyboy.tick(25)
              True
              >>> swoosh = pyboy.screen.tilemap_position_list[66:77]
              >>> print(*swoosh, sep=newline) # Just to pretty-print it
              [0, 0, -7, 0]
              [1, 0, -7, 0]
              [2, 0, -7, 0]
              [2, 0, -7, 0]
              [2, 0, -7, 0]
              [3, 0, -7, 0]
              [3, 0, -7, 0]
              [2, 0, -7, 0]
              [1, 0, -7, 0]
              [1, 0, -7, 0]
              [0, 0, -7, 0]

              ```

              Returns
              -------
              list:
                  Nested list of SCX, SCY, WX and WY for each scanline (144x4). Returns (0, 0, 0, 0) when LCD is off.
              """

              if self.mb.lcd._LCDC.lcd_enable:
                  return [[line[0], line[1], line[2] - 7, line[3]] for line in self.mb.lcd._scanlineparameters]
              else:
                  return [[0, 0, 0, 0] for line in range(144)]

          def get_tilemap_position(self):
              """
              These coordinates define the offset in the tile map from where the top-left corner of the screen is place. Note
              that the tile map defines 256x256 pixels, but the screen can only show 160x144 pixels. When the offset is closer
              to the right or bottom edge than 160x144 pixels, the screen will wrap around and render from the opposite site
              of the tile map.

              For more details, see "7.4 Viewport" in the [report](https://github.com/Baekalfen/PyBoy/raw/master/extras/PyBoy.pdf),
              or the Pan Docs under [LCD Position and Scrolling](https://gbdev.io/pandocs/Scrolling.html).

              Example:
              ```python
              >>> pyboy.screen.get_tilemap_position()
              ((0, 0), (-7, 0))

              ```

              Returns
              -------
              tuple:
                  Returns the tuple of registers ((SCX, SCY), (WX - 7, WY))
              """
              return (self.mb.lcd.getviewport(), self.mb.lcd.getwindowpos())

  ### Instance variables

  `var tilemap_position_list`

    This function provides the screen (SCX, SCY) and window (WX, WY) position for each horizontal line in the screen buffer. These parameters are often used for visual effects, and some games will reset the registers at the end of each call to `PyBoy.tick()`.

    See `Screen.get_tilemap_position()` for more information.

    Example:

        >>> pyboy.tick(25)
        True
        >>> swoosh = pyboy.screen.tilemap_position_list[66:77]
        >>> print(*swoosh, sep=newline) # Just to pretty-print it
        [0, 0, -7, 0]
        [1, 0, -7, 0]
        [2, 0, -7, 0]
        [2, 0, -7, 0]
        [2, 0, -7, 0]
        [3, 0, -7, 0]
        [3, 0, -7, 0]
        [2, 0, -7, 0]
        [1, 0, -7, 0]
        [1, 0, -7, 0]
        [0, 0, -7, 0]

    ## Returns

    `list:`
      Nested list of SCX, SCY, WX and WY for each scanline (144x4). Returns (0, 0, 0, 0) when LCD is off.
    Expand source code

        @property
        def tilemap_position_list(self):
            """
            This function provides the screen (SCX, SCY) and window (WX, WY) position for each horizontal line in the
            screen buffer. These parameters are often used for visual effects, and some games will reset the registers at
            the end of each call to `pyboy.PyBoy.tick()`.

            See `Screen.get_tilemap_position` for more information.

            Example:
            ```python
            >>> pyboy.tick(25)
            True
            >>> swoosh = pyboy.screen.tilemap_position_list[66:77]
            >>> print(*swoosh, sep=newline) # Just to pretty-print it
            [0, 0, -7, 0]
            [1, 0, -7, 0]
            [2, 0, -7, 0]
            [2, 0, -7, 0]
            [2, 0, -7, 0]
            [3, 0, -7, 0]
            [3, 0, -7, 0]
            [2, 0, -7, 0]
            [1, 0, -7, 0]
            [1, 0, -7, 0]
            [0, 0, -7, 0]

            ```

            Returns
            -------
            list:
                Nested list of SCX, SCY, WX and WY for each scanline (144x4). Returns (0, 0, 0, 0) when LCD is off.
            """

            if self.mb.lcd._LCDC.lcd_enable:
                return [[line[0], line[1], line[2] - 7, line[3]] for line in self.mb.lcd._scanlineparameters]
            else:
                return [[0, 0, 0, 0] for line in range(144)]

  `var raw_buffer`

    Provides a raw, unfiltered `bytes` object with the data from the screen. Check `Screen.raw_buffer_format` to see which dataformat is used. The returned type and dataformat are subject to change. The screen buffer is row-major.

    Use this, only if you need to bypass the overhead of `Screen.image` or `Screen.ndarray`.

    Example:

        >>> import numpy as np
        >>> rows, cols = pyboy.screen.raw_buffer_dims
        >>> ndarray = np.frombuffer(
        ...     pyboy.screen.raw_buffer,
        ...     dtype=np.uint8,
        ... ).reshape(rows, cols, 4) # Just an example, use pyboy.screen.ndarray instead

    ## Returns

    `memoryview:`
      92160 bytes memoryview of screen data.
  `var raw_buffer_dims`

    Returns the dimensions of the raw screen buffer. The screen buffer is row-major.

    Example:

        >>> pyboy.screen.raw_buffer_dims
        (144, 160)

    ## Returns

    `tuple:`
      A two-tuple of the buffer dimensions. E.g. (144, 160).
  `var raw_buffer_format`

    Returns the color format of the raw screen buffer. This format is subject to change.

    Example:

        >>> from PIL import Image
        >>> pyboy.screen.raw_buffer_format
        'RGBA'
        >>> image = Image.frombuffer(
        ...    pyboy.screen.raw_buffer_format,
        ...    pyboy.screen.raw_buffer_dims[::-1],
        ...    pyboy.screen.raw_buffer,
        ... ) # Just an example, use pyboy.screen.image instead
        >>> image.save('frame.png')

    ## Returns

    `str:`
      Color format of the raw screen buffer. E.g. 'RGBA'.
  `var image`

    Reference to a PIL Image from the screen buffer. Remember to copy, resize or convert this object if you intend to store it. The backing buffer will update, but it will be the same `PIL.Image` object.

    Convenient for screen captures, but might be a bottleneck, if you use it to train a neural network. In which case, read up on the `pyboy.api` features, Pan Docs on tiles/sprites, and join our Discord channel for more help.

    Example:

        >>> image = pyboy.screen.image
        >>> type(image)
        <class 'PIL.Image.Image'>
        >>> image.save('frame.png')

    ## Returns

    `PIL.Image:`
      RGB image of (160, 144) pixels
  `var ndarray`

    References the screen data in NumPy format. Remember to copy this object if you intend to store it. The backing buffer will update, but it will be the same `ndarray` object.

    The format is given by `Screen.raw_buffer_format`. The screen buffer is row-major.

    Example:

        >>> pyboy.screen.ndarray.shape
        (144, 160, 4)
        >>> # Display "P" on screen from the PyBoy bootrom
        >>> pyboy.screen.ndarray[66:80,64:72,0]
        array([[255, 255, 255, 255, 255, 255, 255, 255],
               [255,   0,   0,   0,   0,   0, 255, 255],
               [255,   0,   0,   0,   0,   0,   0, 255],
               [255,   0,   0, 255, 255,   0,   0, 255],
               [255,   0,   0, 255, 255,   0,   0, 255],
               [255,   0,   0, 255, 255,   0,   0, 255],
               [255,   0,   0,   0,   0,   0,   0, 255],
               [255,   0,   0,   0,   0,   0, 255, 255],
               [255,   0,   0, 255, 255, 255, 255, 255],
               [255,   0,   0, 255, 255, 255, 255, 255],
               [255,   0,   0, 255, 255, 255, 255, 255],
               [255,   0,   0, 255, 255, 255, 255, 255],
               [255,   0,   0, 255, 255, 255, 255, 255],
               [255, 255, 255, 255, 255, 255, 255, 255]], dtype=uint8)

    ## Returns

    `numpy.ndarray:`
      Screendata in `ndarray` of bytes with shape (144, 160, 4)

  ### Methods

  `def get_tilemap_position(self)`

    These coordinates define the offset in the tile map from where the top-left corner of the screen is place. Note that the tile map defines 256x256 pixels, but the screen can only show 160x144 pixels. When the offset is closer to the right or bottom edge than 160x144 pixels, the screen will wrap around and render from the opposite site of the tile map.

    For more details, see "7.4 Viewport" in the report, or the Pan Docs under LCD Position and Scrolling.

    Example:

        >>> pyboy.screen.get_tilemap_position()
        ((0, 0), (-7, 0))

    ## Returns

    `tuple:`
      Returns the tuple of registers ((SCX, SCY), (WX - 7, WY))
    Expand source code

        def get_tilemap_position(self):
            """
            These coordinates define the offset in the tile map from where the top-left corner of the screen is place. Note
            that the tile map defines 256x256 pixels, but the screen can only show 160x144 pixels. When the offset is closer
            to the right or bottom edge than 160x144 pixels, the screen will wrap around and render from the opposite site
            of the tile map.

            For more details, see "7.4 Viewport" in the [report](https://github.com/Baekalfen/PyBoy/raw/master/extras/PyBoy.pdf),
            or the Pan Docs under [LCD Position and Scrolling](https://gbdev.io/pandocs/Scrolling.html).

            Example:
            ```python
            >>> pyboy.screen.get_tilemap_position()
            ((0, 0), (-7, 0))

            ```

            Returns
            -------
            tuple:
                Returns the tuple of registers ((SCX, SCY), (WX - 7, WY))
            """
            return (self.mb.lcd.getviewport(), self.mb.lcd.getwindowpos())

`class Sprite (mb, sprite_index)`

  This class presents an interface to the sprites held in the OAM data on the Game Boy.

  The purpose is to make it easier to interpret events on the screen, in order to program a bot, or train an AI.

  Sprites are used on the Game Boy for enemy and player characters, as only sprites can have transparency, and can move at pixel-precision on the screen. The other method of graphics – tile maps – can only be placed in a grid-size of 8x8 pixels precision, and can have no transparency.

  Sprites on the Game Boy are tightly associated with tiles. The sprites can be seen as "upgraded" tiles, as the image data still refers back to one (or two) tiles. The tile that a sprite will show, can change between each call to `PyBoy.tick()`, so make sure to verify the `Sprite.tile_identifier` hasn't changed.

  By knowing the tile identifiers of players, enemies, power-ups and so on, you'll be able to search for them using `pyboy.sprite_by_tile_identifier` and feed it to your bot or AI.

  Expand source code

      class Sprite:
          def __init__(self, mb, sprite_index):
              """
              This class presents an interface to the sprites held in the OAM data on the Game Boy.

              The purpose is to make it easier to interpret events on the screen, in order to program a bot, or train an AI.

              Sprites are used on the Game Boy for enemy and player characters, as only sprites can have transparency, and can
              move at pixel-precision on the screen. The other method of graphics -- tile maps -- can only be placed in a
              grid-size of 8x8 pixels precision, and can have no transparency.

              Sprites on the Game Boy are tightly associated with tiles. The sprites can be seen as "upgraded" tiles, as the
              image data still refers back to one (or two) tiles. The tile that a sprite will show, can change between each
              call to `pyboy.PyBoy.tick`, so make sure to verify the `Sprite.tile_identifier` hasn't changed.

              By knowing the tile identifiers of players, enemies, power-ups and so on, you'll be able to search for them
              using `pyboy.sprite_by_tile_identifier` and feed it to your bot or AI.
              """
              if not (0 <= sprite_index < SPRITES):
                  raise PyBoyOutOfBoundsException(f"Sprite index of {sprite_index} is out of range (0-{SPRITES})")
              self.mb = mb
              self._offset = sprite_index * 4

              self._sprite_index = sprite_index
              """
              The index of the sprite itself. Beware, that this only represents the index or a "slot" in OAM memory.
              Many games will change the image data of the sprite in the "slot" several times per second.

              Returns
              -------
              int:
                  unsigned tile index
              """

              # Documentation states the y coordinate needs to be subtracted by 16
              self.y = self.mb.getitem(OAM_OFFSET + self._offset + 0) - 16
              """
              The Y-coordinate on the screen to show the Sprite. The (x,y) coordinate points to the top-left corner of the sprite.

              Returns
              -------
              int:
                  Y-coordinate
              """

              # Documentation states the x coordinate needs to be subtracted by 8
              self.x = self.mb.getitem(OAM_OFFSET + self._offset + 1) - 8
              """
              The X-coordinate on the screen to show the Sprite. The (x,y) coordinate points to the top-left corner of the sprite.

              Returns
              -------
              int:
                  X-coordinate
              """

              # Sprites can only use unsigned tile indexes in the lower tile data.
              self.tile_identifier = self.mb.getitem(OAM_OFFSET + self._offset + 2)
              """
              The identifier of the tile the sprite uses. To get a better representation, see the method
              `pyboy.api.sprite.Sprite.tiles`.

              For double-height sprites, this will only give the identifier of the first tile. The second tile will
              always be the one immediately following the first (`tile_identifier + 1`).

              Returns
              -------
              int:
                  unsigned tile index
              """

              attr = self.mb.getitem(OAM_OFFSET + self._offset + 3)
              self.attr_obj_bg_priority = _bit(attr, 7)
              """
              To better understand this values, look in the [Pan Docs: VRAM Sprite Attribute Table
              (OAM)](https://gbdev.io/pandocs/OAM.html).

              Returns
              -------
              bool:
                  The state of the bit in the attributes lookup.
              """

              self.attr_y_flip = _bit(attr, 6)
              """
              To better understand this values, look in the [Pan Docs: VRAM Sprite Attribute Table
              (OAM)](https://gbdev.io/pandocs/OAM.html).

              Returns
              -------
              bool:
                  The state of the bit in the attributes lookup.
              """

              self.attr_x_flip = _bit(attr, 5)
              """
              To better understand this values, look in the [Pan Docs: VRAM Sprite Attribute Table
              (OAM)](https://gbdev.io/pandocs/OAM.html).

              Returns
              -------
              bool:
                  The state of the bit in the attributes lookup.
              """

              self.attr_palette_number = 0
              """
              To better understand this values, look in the [Pan Docs: VRAM Sprite Attribute Table
              (OAM)](https://gbdev.io/pandocs/OAM.html).

              Returns
              -------
              int:
                  The state of the bit(s) in the attributes lookup.
              """

              self.attr_cgb_bank_number = 0
              """
              To better understand this values, look in the [Pan Docs: VRAM Sprite Attribute Table
              (OAM)](https://gbdev.io/pandocs/OAM.html).

              Returns
              -------
              bool:
                  The state of the bit in the attributes lookup.
              """

              if self.mb.cgb:
                  self.attr_palette_number = attr & 0b111
                  self.attr_cgb_bank_number = _bit(attr, 3)
              else:
                  self.attr_palette_number = _bit(attr, 4)

              LCDC = LCDCRegister(self.mb.getitem(LCDC_OFFSET))
              sprite_height = 16 if LCDC.sprite_height else 8
              self.shape = (8, sprite_height)
              """
              Sprites can be set to be 8x8 or 8x16 pixels (16 pixels tall). This is defined globally for the rendering
              hardware, so it's either all sprites using 8x16 pixels, or all sprites using 8x8 pixels.

              Returns
              -------
              (int, int):
                  The width and height of the sprite.
              """

              self.tiles = [Tile(self.mb, self.tile_identifier)]
              """
              The Game Boy support sprites of single-height (8x8 pixels) and double-height (8x16 pixels).

              In the single-height format, one tile is used. For double-height sprites, the Game Boy will also use the tile
              immediately following the identifier given, and render it below the first.

              More information can be found in the [Pan Docs: VRAM Sprite Attribute Table
              (OAM)](https://gbdev.io/pandocs/OAM.html)

              Returns
              -------
              list:
                  A list of `pyboy.api.tile.Tile` object(s) representing the graphics data for the sprite
              """
              if sprite_height == 16:
                  self.tiles += [Tile(self.mb, self.tile_identifier + 1)]

              self.on_screen = -sprite_height < self.y < 144 and -8 < self.x < 160
              """
              To disable sprites from being rendered on screen, developers will place the sprite outside the area of the
              screen. This is often a good way to determine if the sprite is inactive.

              This check doesn't take transparency into account, and will only check the sprite's bounding-box of 8x8 or 8x16
              pixels.

              Returns
              -------
              bool:
                  True if the sprite has at least one pixel on screen.
              """

          def __eq__(self, other):
              return self._offset == other._offset

          def __repr__(self):
              tiles = ", ".join([str(t) for t in self.tiles])
              return f"Sprite [{self._sprite_index}]: Position: ({self.x}, {self.y}), Shape: {self.shape}, Tiles: ({tiles}), On screen: {self.on_screen}"

  ### Instance variables

  `var y`

    The Y-coordinate on the screen to show the Sprite. The (x,y) coordinate points to the top-left corner of the sprite.

    ## Returns

    `int:`
      Y-coordinate
  `var x`

    The X-coordinate on the screen to show the Sprite. The (x,y) coordinate points to the top-left corner of the sprite.

    ## Returns

    `int:`
      X-coordinate
  `var tile_identifier`

    The identifier of the tile the sprite uses. To get a better representation, see the method `Sprite.tiles`.

    For double-height sprites, this will only give the identifier of the first tile. The second tile will always be the one immediately following the first (`tile_identifier + 1`).

    ## Returns

    `int:`
      unsigned tile index
  `var attr_obj_bg_priority`

    To better understand this values, look in the Pan Docs: VRAM Sprite Attribute Table (OAM).

    ## Returns

    `bool:`
      The state of the bit in the attributes lookup.
  `var attr_y_flip`

    To better understand this values, look in the Pan Docs: VRAM Sprite Attribute Table (OAM).

    ## Returns

    `bool:`
      The state of the bit in the attributes lookup.
  `var attr_x_flip`

    To better understand this values, look in the Pan Docs: VRAM Sprite Attribute Table (OAM).

    ## Returns

    `bool:`
      The state of the bit in the attributes lookup.
  `var attr_palette_number`

    To better understand this values, look in the Pan Docs: VRAM Sprite Attribute Table (OAM).

    ## Returns

    `int:`
      The state of the bit(s) in the attributes lookup.
  `var attr_cgb_bank_number`

    To better understand this values, look in the Pan Docs: VRAM Sprite Attribute Table (OAM).

    ## Returns

    `bool:`
      The state of the bit in the attributes lookup.
  `var shape`

    Sprites can be set to be 8x8 or 8x16 pixels (16 pixels tall). This is defined globally for the rendering hardware, so it's either all sprites using 8x16 pixels, or all sprites using 8x8 pixels.

    ## Returns

    (int, int): The width and height of the sprite.

  `var tiles`

    The Game Boy support sprites of single-height (8x8 pixels) and double-height (8x16 pixels).

    In the single-height format, one tile is used. For double-height sprites, the Game Boy will also use the tile immediately following the identifier given, and render it below the first.

    More information can be found in the Pan Docs: VRAM Sprite Attribute Table (OAM)

    ## Returns

    `list:`
      A list of `Tile` object(s) representing the graphics data for the sprite
  `var on_screen`

    To disable sprites from being rendered on screen, developers will place the sprite outside the area of the screen. This is often a good way to determine if the sprite is inactive.

    This check doesn't take transparency into account, and will only check the sprite's bounding-box of 8x8 or 8x16 pixels.

    ## Returns

    `bool:`
      True if the sprite has at least one pixel on screen.
`class Tile (mb, identifier)`

  The Game Boy uses tiles as the building block for all graphics on the screen. This base-class is used for `PyBoy.get_tile()`, `Sprite` and `TileMap`, when refering to graphics.

  This class is not meant to be instantiated by developers reading this documentation, but it will be created internally and returned by `Sprite.tiles` and `TileMap.tile()`.

  The data of this class is static, apart from the image data, which is loaded from the Game Boy's memory when needed. Beware that the graphics for the tile can change between each call to `PyBoy.tick()`.

  Expand source code

      class Tile:
          def __init__(self, mb, identifier):
              """
              The Game Boy uses tiles as the building block for all graphics on the screen. This base-class is used for
              `pyboy.PyBoy.get_tile`, `pyboy.api.sprite.Sprite` and `pyboy.api.tilemap.TileMap`, when refering to graphics.

              This class is not meant to be instantiated by developers reading this documentation, but it will be created
              internally and returned by `pyboy.api.sprite.Sprite.tiles` and
              `pyboy.api.tilemap.TileMap.tile`.

              The data of this class is static, apart from the image data, which is loaded from the Game Boy's memory when
              needed. Beware that the graphics for the tile can change between each call to `pyboy.PyBoy.tick`.
              """
              self.mb = mb

              if self.mb.cgb:
                  if not (0 <= identifier < TILES_CGB):
                      raise PyBoyOutOfBoundsException("Identifier out of range")
              else:
                  if not (0 <= identifier < TILES):
                      raise PyBoyOutOfBoundsException("Identifier out of range")

              self.data_address = LOW_TILEDATA + (16 * (identifier % TILES))
              """
              The tile data is defined in a specific area of the Game Boy. This function returns the address of the tile data
              corresponding to the tile identifier. It is advised to use `pyboy.api.tile.Tile.image` or one of the
              other `image`-functions if you want to view the tile.

              You can read how the data is read in the
              [Pan Docs: VRAM Tile Data](https://gbdev.io/pandocs/Tile_Data.html).

              Returns
              -------
              int:
                  address in VRAM where tile data starts
              """

              if identifier < TILES:
                  self.vram_bank = 0
              else:
                  self.vram_bank = 1

              self.tile_identifier = identifier
              """
              The Game Boy has a slightly complicated indexing system for tiles. This identifier unifies the otherwise
              complicated indexing system on the Game Boy into a single range of 0-383 (both included) or 0-767 for Game Boy
              Color.

              Returns
              -------
              int:
                  Unique identifier for the tile
              """

              self.shape = (8, 8)
              """
              Tiles are always 8x8 pixels.

              Returns
              -------
              (int, int):
                  The width and height of the tile.
              """

              self.raw_buffer_format = self.mb.lcd.renderer.color_format
              """
              Returns the color format of the raw screen buffer.

              Returns
              -------
              str:
                  Color format of the raw screen buffer. E.g. 'RGBA'.
              """

          def image(self):
              """
              Use this function to get an `PIL.Image` object of the tile. The image is 8x8 pixels. The format or "mode" might change at any time.

              Be aware, that the graphics for this tile can change between each call to `pyboy.PyBoy.tick`.

              Example:
              ```python
              >>> tile = pyboy.get_tile(1)
              >>> tile.image().save('tile_1.png')

              ```

              Returns
              -------
              PIL.Image :
                  Image of tile in 8x8 pixels and RGBA colors.
              """
              if Image is None:
                  logger.error(f'{__name__}: Missing dependency "Pillow".')
                  utils.PillowImportError()._raise_import_error()

              if utils.cython_compiled:
                  return Image.fromarray(self._image_data().base, mode=self.raw_buffer_format)
              else:
                  return Image.frombytes(self.raw_buffer_format, (8, 8), self._image_data())

          def ndarray(self):
              """
              Use this function to get an `numpy.ndarray` object of the tile. The array has a shape of (8, 8, 4)
              and each value is of `numpy.uint8`. The values corresponds to an image of 8x8 pixels with each sub-color
              in a separate cell. The format is given by `pyboy.api.tile.Tile.raw_buffer_format`.

              Be aware, that the graphics for this tile can change between each call to `pyboy.PyBoy.tick`.

              Example:
              ```python
              >>> tile1 = pyboy.get_tile(1)
              >>> tile1.ndarray()[:,:,0] # Upper part of "P"
              array([[255, 255, 255, 255, 255, 255, 255, 255],
                     [255, 255, 255, 255, 255, 255, 255, 255],
                     [255, 255, 255, 255, 255, 255, 255, 255],
                     [255,   0,   0,   0,   0,   0, 255, 255],
                     [255,   0,   0,   0,   0,   0,   0, 255],
                     [255,   0,   0, 255, 255,   0,   0, 255],
                     [255,   0,   0, 255, 255,   0,   0, 255],
                     [255,   0,   0, 255, 255,   0,   0, 255]], dtype=uint8)
              >>> tile2 = pyboy.get_tile(2)
              >>> tile2.ndarray()[:,:,0] # Lower part of "P"
              array([[255,   0,   0,   0,   0,   0,   0, 255],
                     [255,   0,   0,   0,   0,   0, 255, 255],
                     [255,   0,   0, 255, 255, 255, 255, 255],
                     [255,   0,   0, 255, 255, 255, 255, 255],
                     [255,   0,   0, 255, 255, 255, 255, 255],
                     [255,   0,   0, 255, 255, 255, 255, 255],
                     [255,   0,   0, 255, 255, 255, 255, 255],
                     [255, 255, 255, 255, 255, 255, 255, 255]], dtype=uint8)

              ```

              Returns
              -------
              numpy.ndarray :
                  Array of shape (8, 8, 4) with data type of `numpy.uint8`.
              """
              # The data is laid out as (X, red, green, blue), where X is currently always zero, but this is not guarenteed
              # across versions of PyBoy.
              return np.asarray(self._image_data()).view(dtype=np.uint8).reshape(8, 8, 4)

          def _image_data(self):
              """
              Use this function to get the raw tile data. The data is a `memoryview` corresponding to 8x8 pixels in RGBA
              colors.

              Be aware, that the graphics for this tile can change between each call to `pyboy.PyBoy.tick`.

              Returns
              -------
              memoryview :
                  Image data of tile in 8x8 pixels and RGB colors.
              """
              self.data = np.zeros((8, 8), dtype=np.uint32)
              for k in range(0, 16, 2):  # 2 bytes for each line
                  if self.vram_bank == 0:
                      byte1 = self.mb.lcd.VRAM0[self.data_address + k - VRAM_OFFSET]
                      byte2 = self.mb.lcd.VRAM0[self.data_address + k + 1 - VRAM_OFFSET]
                  else:
                      byte1 = self.mb.lcd.VRAM1[self.data_address + k - VRAM_OFFSET]
                      byte2 = self.mb.lcd.VRAM1[self.data_address + k + 1 - VRAM_OFFSET]

                  colorcode = self.mb.lcd.renderer.colorcode(byte1, byte2)
                  for x in range(8):
                      self.data[k // 2][x] = self.mb.lcd.BGP.getcolor((colorcode >> x * 8) & 0xFF)
              return self.data

          def __eq__(self, other):
              return self.data_address == other.data_address and self.vram_bank == other.vram_bank

          def __repr__(self):
              return f"Tile: {self.tile_identifier}"

  ### Instance variables

  `var data_address`

    The tile data is defined in a specific area of the Game Boy. This function returns the address of the tile data corresponding to the tile identifier. It is advised to use `Tile.image()` or one of the other `image`-functions if you want to view the tile.

    You can read how the data is read in the Pan Docs: VRAM Tile Data.

    ## Returns

    `int:`
      address in VRAM where tile data starts
  `var tile_identifier`

    The Game Boy has a slightly complicated indexing system for tiles. This identifier unifies the otherwise complicated indexing system on the Game Boy into a single range of 0-383 (both included) or 0-767 for Game Boy Color.

    ## Returns

    `int:`
      Unique identifier for the tile
  `var shape`

    Tiles are always 8x8 pixels.

    ## Returns

    (int, int): The width and height of the tile.

  `var raw_buffer_format`

    Returns the color format of the raw screen buffer.

    ## Returns

    `str:`
      Color format of the raw screen buffer. E.g. 'RGBA'.

  ### Methods

  `def image(self)`

    Use this function to get an `PIL.Image` object of the tile. The image is 8x8 pixels. The format or "mode" might change at any time.

    Be aware, that the graphics for this tile can change between each call to `PyBoy.tick()`.

    Example:

        >>> tile = pyboy.get_tile(1)
        >>> tile.image().save('tile_1.png')

    ## Returns

    `PIL.Image :`
      Image of tile in 8x8 pixels and RGBA colors.
    Expand source code

        def image(self):
            """
            Use this function to get an `PIL.Image` object of the tile. The image is 8x8 pixels. The format or "mode" might change at any time.

            Be aware, that the graphics for this tile can change between each call to `pyboy.PyBoy.tick`.

            Example:
            ```python
            >>> tile = pyboy.get_tile(1)
            >>> tile.image().save('tile_1.png')

            ```

            Returns
            -------
            PIL.Image :
                Image of tile in 8x8 pixels and RGBA colors.
            """
            if Image is None:
                logger.error(f'{__name__}: Missing dependency "Pillow".')
                utils.PillowImportError()._raise_import_error()

            if utils.cython_compiled:
                return Image.fromarray(self._image_data().base, mode=self.raw_buffer_format)
            else:
                return Image.frombytes(self.raw_buffer_format, (8, 8), self._image_data())

  `def ndarray(self)`

    Use this function to get an `numpy.ndarray` object of the tile. The array has a shape of (8, 8, 4) and each value is of `numpy.uint8`. The values corresponds to an image of 8x8 pixels with each sub-color in a separate cell. The format is given by `Tile.raw_buffer_format`.

    Be aware, that the graphics for this tile can change between each call to `PyBoy.tick()`.

    Example:

        >>> tile1 = pyboy.get_tile(1)
        >>> tile1.ndarray()[:,:,0] # Upper part of "P"
        array([[255, 255, 255, 255, 255, 255, 255, 255],
               [255, 255, 255, 255, 255, 255, 255, 255],
               [255, 255, 255, 255, 255, 255, 255, 255],
               [255,   0,   0,   0,   0,   0, 255, 255],
               [255,   0,   0,   0,   0,   0,   0, 255],
               [255,   0,   0, 255, 255,   0,   0, 255],
               [255,   0,   0, 255, 255,   0,   0, 255],
               [255,   0,   0, 255, 255,   0,   0, 255]], dtype=uint8)
        >>> tile2 = pyboy.get_tile(2)
        >>> tile2.ndarray()[:,:,0] # Lower part of "P"
        array([[255,   0,   0,   0,   0,   0,   0, 255],
               [255,   0,   0,   0,   0,   0, 255, 255],
               [255,   0,   0, 255, 255, 255, 255, 255],
               [255,   0,   0, 255, 255, 255, 255, 255],
               [255,   0,   0, 255, 255, 255, 255, 255],
               [255,   0,   0, 255, 255, 255, 255, 255],
               [255,   0,   0, 255, 255, 255, 255, 255],
               [255, 255, 255, 255, 255, 255, 255, 255]], dtype=uint8)

    ## Returns

    `numpy.ndarray :`
      Array of shape (8, 8, 4) with data type of `numpy.uint8`.
    Expand source code

        def ndarray(self):
            """
            Use this function to get an `numpy.ndarray` object of the tile. The array has a shape of (8, 8, 4)
            and each value is of `numpy.uint8`. The values corresponds to an image of 8x8 pixels with each sub-color
            in a separate cell. The format is given by `pyboy.api.tile.Tile.raw_buffer_format`.

            Be aware, that the graphics for this tile can change between each call to `pyboy.PyBoy.tick`.

            Example:
            ```python
            >>> tile1 = pyboy.get_tile(1)
            >>> tile1.ndarray()[:,:,0] # Upper part of "P"
            array([[255, 255, 255, 255, 255, 255, 255, 255],
                   [255, 255, 255, 255, 255, 255, 255, 255],
                   [255, 255, 255, 255, 255, 255, 255, 255],
                   [255,   0,   0,   0,   0,   0, 255, 255],
                   [255,   0,   0,   0,   0,   0,   0, 255],
                   [255,   0,   0, 255, 255,   0,   0, 255],
                   [255,   0,   0, 255, 255,   0,   0, 255],
                   [255,   0,   0, 255, 255,   0,   0, 255]], dtype=uint8)
            >>> tile2 = pyboy.get_tile(2)
            >>> tile2.ndarray()[:,:,0] # Lower part of "P"
            array([[255,   0,   0,   0,   0,   0,   0, 255],
                   [255,   0,   0,   0,   0,   0, 255, 255],
                   [255,   0,   0, 255, 255, 255, 255, 255],
                   [255,   0,   0, 255, 255, 255, 255, 255],
                   [255,   0,   0, 255, 255, 255, 255, 255],
                   [255,   0,   0, 255, 255, 255, 255, 255],
                   [255,   0,   0, 255, 255, 255, 255, 255],
                   [255, 255, 255, 255, 255, 255, 255, 255]], dtype=uint8)

            ```

            Returns
            -------
            numpy.ndarray :
                Array of shape (8, 8, 4) with data type of `numpy.uint8`.
            """
            # The data is laid out as (X, red, green, blue), where X is currently always zero, but this is not guarenteed
            # across versions of PyBoy.
            return np.asarray(self._image_data()).view(dtype=np.uint8).reshape(8, 8, 4)

`class TileMap (pyboy, mb, select)`

  The Game Boy has two tile maps, which defines what is rendered on the screen. These are also referred to as "background" and "window".

  Use `pyboy.tilemap_background` and `pyboy.tilemap_window` to instantiate this object.

  This object defines `__getitem__`, which means it can be accessed with the square brackets to get a tile identifier at a given coordinate.

  Example:

      >>> pyboy.tilemap_window[8,8]
      1
      >>> pyboy.tilemap_window[7:12,8]
      [0, 1, 0, 1, 0]
      >>> pyboy.tilemap_window[7:12,8:11]
      [[0, 1, 0, 1, 0], [0, 2, 3, 4, 5], [0, 0, 6, 0, 0]]

  Each element in the matrix, is the tile identifier of the tile to be shown on screen for each position. If you need the entire 32x32 tile map, you can use the shortcut: `tilemap[:,:]`.

  Expand source code

      class TileMap:
          def __init__(self, pyboy, mb, select):
              """
              The Game Boy has two tile maps, which defines what is rendered on the screen. These are also referred to as
              "background" and "window".

              Use `pyboy.tilemap_background` and
              `pyboy.tilemap_window` to instantiate this object.

              This object defines `__getitem__`, which means it can be accessed with the square brackets to get a tile
              identifier at a given coordinate.

              Example:
              ```
              >>> pyboy.tilemap_window[8,8]
              1
              >>> pyboy.tilemap_window[7:12,8]
              [0, 1, 0, 1, 0]
              >>> pyboy.tilemap_window[7:12,8:11]
              [[0, 1, 0, 1, 0], [0, 2, 3, 4, 5], [0, 0, 6, 0, 0]]

              ```

              Each element in the matrix, is the tile identifier of the tile to be shown on screen for each position. If you
              need the entire 32x32 tile map, you can use the shortcut: `tilemap[:,:]`.
              """
              self.pyboy = pyboy
              self.mb = mb
              self._select = select
              self._use_tile_objects = False
              self.frame_count_update = 0
              self.__refresh_lcdc()

              self.shape = (32, 32)
              """
              Tile maps are always 32x32 tiles.

              Returns
              -------
              (int, int):
                  The width and height of the tile map.
              """

          def _refresh_lcdc(self):
              if self.frame_count_update == self.pyboy.frame_count:
                  return 0
              self.__refresh_lcdc()

          def __refresh_lcdc(self):
              """
              The tile data and view that is showed on the background and window respectively can change dynamically. If you
              believe it has changed, you can use this method to update the tilemap from the LCDC register.
              """
              LCDC = LCDCRegister(self.mb.getitem(LCDC_OFFSET))
              if self._select == "WINDOW":
                  self.map_offset = HIGH_TILEMAP if LCDC.windowmap_select else LOW_TILEMAP
                  self.signed_tile_data = not bool(LCDC.tiledata_select)
              elif self._select == "BACKGROUND":
                  self.map_offset = HIGH_TILEMAP if LCDC.backgroundmap_select else LOW_TILEMAP
                  self.signed_tile_data = not bool(LCDC.tiledata_select)
              else:
                  raise KeyError(f"Invalid tilemap selected: {self._select}")

          def search_for_identifiers(self, identifiers):
              """
              Provided a list of tile identifiers, this function will find all occurrences of these in the tilemap and return
              the coordinates where each identifier is found.

              Example:
              ```
              >>> pyboy.tilemap_window.search_for_identifiers([5,3])
              [[[9, 11]], [[9, 9], [9, 12]]]

              ```

              Meaning, that tile identifier `43` is found at the positions: (0,0), (2,4), and (8,7), while tile identifier
              `123`was not found anywhere.

              Args:
                  identifiers (list): List of tile identifiers (int)

              Returns
              -------
              list:
                  list of matches for every tile identifier in the input
              """
              # TODO: Crude implementation
              tilemap_identifiers = np.asarray(self[:, :], dtype=np.uint32)
              matches = []
              for i in identifiers:
                  matches.append([[int(y) for y in x] for x in np.argwhere(tilemap_identifiers == i)])
              return matches

          def _tile_address(self, column, row):
              """
              Returns the memory address in the tilemap for the tile at the given coordinate. The address contains the index
              of tile which will be shown at this position. This should not be confused with the actual tile data of
              `pyboy.api.tile.Tile.data_address`.

              This can be used as an global identifier for the specific location in a tile map.

              Be aware, that the tile index referenced at the memory address might change between calls to
              `pyboy.PyBoy.tick`. And the tile data for the same tile index might also change to display something else
              on the screen.

              The index might also be a signed number. Depending on if it is signed or not, will change where the tile data
              is read from. Use `pyboy.api.tilemap.TileMap.signed_tile_index` to test if the indexes are signed for
              this tile view. You can read how the indexes work in the
              [Pan Docs: VRAM Tile Data](https://gbdev.io/pandocs/Tile_Data.html).

              Args:
                  column (int): Column in this tile map.
                  row (int): Row in this tile map.

              Returns
              -------
              int:
                  Address in the tile map to read a tile index.
              """
              if not 0 <= column < 32:
                  raise IndexError("column is out of bounds. Value of 0 to 31 is allowed")
              if not 0 <= row < 32:
                  raise IndexError("row is out of bounds. Value of 0 to 31 is allowed")
              return self.map_offset + 32 * row + column

          def tile(self, column, row):
              """
              Provides a `pyboy.api.tile.Tile`-object which allows for easy interpretation of the tile data. The
              object is agnostic to where it was found in the tilemap. I.e. equal `pyboy.api.tile.Tile`-objects might
              be returned from two different coordinates in the tile map if they are shown different places on the screen.

              Args:
                  column (int): Column in this tile map.
                  row (int): Row in this tile map.

              Returns
              -------
              `pyboy.api.tile.Tile`:
                  Tile object corresponding to the tile index at the given coordinate in the
                  tile map.
              """
              return Tile(self.mb, self.tile_identifier(column, row))

          def tile_identifier(self, column, row):
              """
              Returns an identifier (integer) of the tile at the given coordinate in the tile map. The identifier can be used
              to quickly recognize what is on the screen through this tile view.

              This identifier unifies the otherwise complicated indexing system on the Game Boy into a single range of
              0-383 (both included).

              You can read how the indexes work in the
              [Pan Docs: VRAM Tile Data](https://gbdev.io/pandocs/Tile_Data.html).

              Args:
                  column (int): Column in this tile map.
                  row (int): Row in this tile map.

              Returns
              -------
              int:
                  Tile identifier.
              """
              self._refresh_lcdc()
              tile = self.mb.getitem(self._tile_address(column, row))
              if self.signed_tile_data:
                  return ((tile ^ 0x80) - 128) + LOW_TILEDATA_NTILES
              else:
                  return tile

          def __repr__(self):
              self._refresh_lcdc()
              adjust = 4
              _use_tile_objects = self._use_tile_objects
              self.use_tile_objects(False)

              return_data = (
                  f"Tile Map Address: {self.map_offset:#0{6}x}, "
                  + f"Signed Tile Data: {'Yes' if self.signed_tile_data else 'No'}\n"
                  + " " * 5
                  + "".join([f"{i: <4}" for i in range(32)])
                  + "\n"
                  + "_" * (adjust * 32 + 2)
                  + "\n"
                  + "\n".join(
                      [
                          f"{i: <3}| " + "".join([str(tile).ljust(adjust) for tile in line])
                          for i, line in enumerate(self[:, :])
                      ]
                  )
              )
              self.use_tile_objects(_use_tile_objects)
              return return_data

          def use_tile_objects(self, switch):
              """
              Used to change which object is returned when using the ``__getitem__`` method (i.e. `tilemap[0,0]`).

              Args:
                  switch (bool): If True, accesses will return `pyboy.api.tile.Tile`-object. If False, accesses will
                      return an `int`.
              """
              self._use_tile_objects = switch

          def _fix_slice(self, addr):
              if addr.step is None:
                  step = 1
              else:
                  step = addr.step

              if addr.start is None:
                  start = 0
              else:
                  start = addr.start

              if addr.stop is None:
                  stop = 32
              else:
                  stop = addr.stop

              if step < 0:
                  raise ValueError("Reversed ranges are unsupported")
              elif start > stop:
                  raise ValueError("Invalid range")
              return start, stop, step

          def __getitem__(self, xy):
              if isinstance(xy, (int, slice)):
                  x = xy
                  y = slice(None)
              else:
                  x, y = xy

              x_slice = isinstance(x, slice)
              y_slice = isinstance(y, slice)
              if x_slice:
                  x = self._fix_slice(x)
              else:
                  assert isinstance(x, int)

              if y_slice:
                  y = self._fix_slice(y)
              else:
                  assert isinstance(y, int)

              if self._use_tile_objects:
                  tile_fun = self.tile
              else:
                  tile_fun = lambda x, y: self.tile_identifier(x, y)

              if x_slice and y_slice:
                  return [[tile_fun(_x, _y) for _x in range(*x)] for _y in range(*y)]
              elif x_slice:
                  return [tile_fun(_x, y) for _x in range(*x)]
              elif y_slice:
                  return [tile_fun(x, _y) for _y in range(*y)]
              else:
                  return tile_fun(x, y)

  ### Instance variables

  `var shape`

    Tile maps are always 32x32 tiles.

    ## Returns

    (int, int): The width and height of the tile map.

  ### Methods

  `def search_for_identifiers(self, identifiers)`

    Provided a list of tile identifiers, this function will find all occurrences of these in the tilemap and return the coordinates where each identifier is found.

    Example:

        >>> pyboy.tilemap_window.search_for_identifiers([5,3])
        [[[9, 11]], [[9, 9], [9, 12]]]

    Meaning, that tile identifier `43` is found at the positions: (0,0), (2,4), and (8,7), while tile identifier `123`was not found anywhere.

    ## Args

    `identifiers` :`list`
      List of tile identifiers (int)

    ## Returns

    `list:`
      list of matches for every tile identifier in the input
    Expand source code

        def search_for_identifiers(self, identifiers):
            """
            Provided a list of tile identifiers, this function will find all occurrences of these in the tilemap and return
            the coordinates where each identifier is found.

            Example:
            ```
            >>> pyboy.tilemap_window.search_for_identifiers([5,3])
            [[[9, 11]], [[9, 9], [9, 12]]]

            ```

            Meaning, that tile identifier `43` is found at the positions: (0,0), (2,4), and (8,7), while tile identifier
            `123`was not found anywhere.

            Args:
                identifiers (list): List of tile identifiers (int)

            Returns
            -------
            list:
                list of matches for every tile identifier in the input
            """
            # TODO: Crude implementation
            tilemap_identifiers = np.asarray(self[:, :], dtype=np.uint32)
            matches = []
            for i in identifiers:
                matches.append([[int(y) for y in x] for x in np.argwhere(tilemap_identifiers == i)])
            return matches

  `def tile(self, column, row)`

    Provides a `Tile`-object which allows for easy interpretation of the tile data. The object is agnostic to where it was found in the tilemap. I.e. equal `Tile`-objects might be returned from two different coordinates in the tile map if they are shown different places on the screen.

    ## Args

    `column` :`int`
      Column in this tile map.
    `row` :`int`
      Row in this tile map.

    ## Returns

    `Tile`: Tile object corresponding to the tile index at the given coordinate in the tile map.

    Expand source code

        def tile(self, column, row):
            """
            Provides a `pyboy.api.tile.Tile`-object which allows for easy interpretation of the tile data. The
            object is agnostic to where it was found in the tilemap. I.e. equal `pyboy.api.tile.Tile`-objects might
            be returned from two different coordinates in the tile map if they are shown different places on the screen.

            Args:
                column (int): Column in this tile map.
                row (int): Row in this tile map.

            Returns
            -------
            `pyboy.api.tile.Tile`:
                Tile object corresponding to the tile index at the given coordinate in the
                tile map.
            """
            return Tile(self.mb, self.tile_identifier(column, row))

  `def tile_identifier(self, column, row)`

    Returns an identifier (integer) of the tile at the given coordinate in the tile map. The identifier can be used to quickly recognize what is on the screen through this tile view.

    This identifier unifies the otherwise complicated indexing system on the Game Boy into a single range of 0-383 (both included).

    You can read how the indexes work in the Pan Docs: VRAM Tile Data.

    ## Args

    `column` :`int`
      Column in this tile map.
    `row` :`int`
      Row in this tile map.

    ## Returns

    `int:`
      Tile identifier.
    Expand source code

        def tile_identifier(self, column, row):
            """
            Returns an identifier (integer) of the tile at the given coordinate in the tile map. The identifier can be used
            to quickly recognize what is on the screen through this tile view.

            This identifier unifies the otherwise complicated indexing system on the Game Boy into a single range of
            0-383 (both included).

            You can read how the indexes work in the
            [Pan Docs: VRAM Tile Data](https://gbdev.io/pandocs/Tile_Data.html).

            Args:
                column (int): Column in this tile map.
                row (int): Row in this tile map.

            Returns
            -------
            int:
                Tile identifier.
            """
            self._refresh_lcdc()
            tile = self.mb.getitem(self._tile_address(column, row))
            if self.signed_tile_data:
                return ((tile ^ 0x80) - 128) + LOW_TILEDATA_NTILES
            else:
                return tile

  `def use_tile_objects(self, switch)`

    Used to change which object is returned when using the `__getitem__` method (i.e. `pyboy.api.tilemap[0,0]`).

    ## Args

    `switch` :`bool`
      If True, accesses will return `Tile`-object. If False, accesses will return an `int`.
    Expand source code

        def use_tile_objects(self, switch):
            """
            Used to change which object is returned when using the ``__getitem__`` method (i.e. `tilemap[0,0]`).

            Args:
                switch (bool): If True, accesses will return `pyboy.api.tile.Tile`-object. If False, accesses will
                    return an `int`.
            """
            self._use_tile_objects = switch