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._get_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 123was 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