Skip to content
Draft
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 57 additions & 1 deletion pyboy/plugins/game_wrapper_pokemon_gen1.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,23 @@

logger = pyboy.logging.get_logger(__name__)

# Set of addresses for information on pokemon
# Based on the following link: https://datacrystal.tcrf.net/wiki/Pok%C3%A9mon_Red_and_Blue/RAM_map
ADDR_TITLE_SCREEN = 0x1FC3
ADDR_NUMBER_OF_POKEMON = 0xD163 # In party

#Item related values
ADDR_TOTAL_ITEMS = 0xD53A
ADDR_BADGES = 0xD356 # Currently requires conversion (each bit is an independent switch and represents a badge)

# Game Time
ADDR_HOURS = 0xDA40
ADDR_MINUTES = 0xDA42
ADDR_SECONDS = 0xDA44

# Battle mode
ADDR_BATTLE = 0xD057


class GameWrapperPokemonGen1(PyBoyGameWrapper):
"""
Expand All @@ -28,6 +45,24 @@ class GameWrapperPokemonGen1(PyBoyGameWrapper):
def __init__(self, *args, **kwargs):
super().__init__(*args, game_area_section=(0, 0, 20, 18), game_area_follow_scxy=True, **kwargs)
self.sprite_offset = 0
if self.pyboy.memory[ADDR_TITLE_SCREEN] == 0:
pass
else:
self.number_of_pokemon = self.pyboy.memory[ADDR_NUMBER_OF_POKEMON]
self.total_items = self.pyboy.memory[ADDR_TOTAL_ITEMS]
# Extract the time in game:
_hours = self.pyboy.memory[ADDR_HOURS]
_minutes = self.pyboy.memory[ADDR_MINUTES]
_seconds = self.pyboy.memory[ADDR_SECONDS]
self.game_time = f'{_hours}:{_minutes}:{_seconds}'

# Check whether the player is in battle mode or out of battle
if self.pyboy.memory[ADDR_BATTLE] == 1:
self.battle_state = 'In Battle'
else:
self.battle_state = 'Overworld'

self.badges = self.pyboy.memory[ADDR_BADGES] #Research how this works.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is all duplicate code. Better just define some default value (0) for all of them. The data of the game wrapper classes are not valid before calling pyboy.tick() anyway.


def enabled(self):
return (self.pyboy.cartridge_title == "POKEMON RED") or (self.pyboy.cartridge_title == "POKEMON BLUE")
Expand All @@ -36,6 +71,22 @@ def post_tick(self):
self._tile_cache_invalid = True
self._sprite_cache_invalid = True

self.number_of_pokemon = self.pyboy.memory[ADDR_NUMBER_OF_POKEMON]
self.total_items = self.pyboy.memory[ADDR_TOTAL_ITEMS]
# Extract the time in game:
_hours = self.pyboy.memory[ADDR_HOURS]
_minutes = self.pyboy.memory[ADDR_MINUTES]

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see from datacrystal which you link to, that hours and minutes are two bytes. You'll need to check how this works.

_seconds = self.pyboy.memory[ADDR_SECONDS]
self.game_time = f'{_hours}:{_minutes}:{_seconds}'

# Check whether the player is in battle mode or out of battle
if self.pyboy.memory[ADDR_BATTLE] == 1:
self.battle_state = 'In Battle'
else:
self.battle_state = 'Overworld'
Comment on lines +67 to +70

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you test this? I think there's some distinction between trainer battle and wild pokémon.


self.badges = self.pyboy.memory[ADDR_BADGES] #Research how this works.

scanline_parameters = self.pyboy.screen.tilemap_position_list
# WX = scanline_parameters[0][2]
WY = scanline_parameters[0][3]
Expand Down Expand Up @@ -78,4 +129,9 @@ def game_area_collision(self):
return game_area

def __repr__(self):
return "Pokemon Gen 1:\n" + super().__repr__()
return ("Pokemon Gen 1:\n"
+ f"Pokemon in Party: {self.number_of_pokemon}\n"
+ f"Battle State: {self.battle_state}\n"
+ f"Game Time: {self.game_time}\n"
+ f"Total items: {self.total_items}\n"
+ super().__repr__())